#!perl -wc
package ActinicDiscounts;
require 5.002;
push (@INC, "cgi-bin");
use strict;
require ac000001;
use Time::Local;
$ActinicDiscounts::prog_name = 'ActinicDiscounts.pm';
$ActinicDiscounts::prog_name = $ActinicDiscounts::prog_name;
$ActinicDiscounts::prog_ver = '$Revision: 44 $ ';
$ActinicDiscounts::prog_ver = substr($ActinicDiscounts::prog_ver, 11);
$ActinicDiscounts::prog_ver =~ s/ \$//;
sub CalculateProductAdjustment
{
my ($phashCartItems) = @_;
my @arrAdjustments;
my $nTotalAdjustments = 0;
my ($pItem, $pCartItem, $nGroupID);
my $bGotOneDiscount = $::FALSE;
my %hUsedGroups;
my %hCartTotals;
foreach $nGroupID (keys %{$phashCartItems})
{
my @Array = sort
{
$$b[$::eDCartLineTotal] / $$b[$::eDCartLineQuantity] <=>
$$a[$::eDCartLineTotal] / $$a[$::eDCartLineQuantity]
} (@{$$phashCartItems{$nGroupID}});
$$phashCartItems{$nGroupID} = \@Array;
map {$hCartTotals{$$_[$::eDCartLineIndex]} = $$_[$::eDCartLineTotal]} (@{$$phashCartItems{$nGroupID}});
}
foreach $pItem (@{$$::g_pDiscountBlob{PRODUCT_LEVEL}})
{
$nGroupID = $$pItem{'GROUPID'};
if (!defined $$phashCartItems{$nGroupID})
{
next;
}
if (!IsDateValid(\$pItem) ||
!IsCustomerValid(\$pItem) ||
!IsCouponValid(\$pItem))
{
next;
}
if ($$::g_pDiscountBlob{'PRODUCT_GROUPS'}->{$nGroupID}->[0] &&
$hUsedGroups{$nGroupID})
{
next;
}
my @arrThisAdjustments = CalculateProductRewards($phashCartItems, $nGroupID, $pItem);
if ((scalar @arrThisAdjustments) != 0)
{
push @arrAdjustments, @arrThisAdjustments;
$hUsedGroups{$nGroupID} = 1;
if ($$::g_pDiscountBlob{'ONE_PRODUCT_DISCOUNT'})
{
last;
}
}
}
my %hTotals;
foreach $pItem (@arrAdjustments)
{
my $nNewTotal = $$pItem[$::eAdjIdxAmount] + $hTotals{$$pItem[$::eAdjIdxCartIndex]};
if (0 < $nNewTotal + $hCartTotals{$$pItem[$::eAdjIdxCartIndex]})
{
$hTotals{$$pItem[$::eAdjIdxCartIndex]} = $nNewTotal;
next;
}
else
{
$$pItem[$::eAdjIdxAmount] = -($hCartTotals{$$pItem[$::eAdjIdxCartIndex]} + $hTotals{$$pItem[$::eAdjIdxCartIndex]});
$hTotals{$$pItem[$::eAdjIdxCartIndex]} += $$pItem[$::eAdjIdxAmount];
}
}
return($::SUCCESS, '', \@arrAdjustments);
}
sub GetRewardString
{
my $pDiscount = shift;
my $nReward = $$pDiscount{'REWARD_TYPE'};
my $nBasis = $$pDiscount{'BASIS'};
my $sMsg;
if ($nReward == $::eRewardMoneyOff)
{
my $sPrice = (ActinicOrder::FormatPrice($$pDiscount{'REWARDS'}->{'MONEY_OFF'}, $::TRUE, $::g_pCatalogBlob))[2];
$sMsg = ACTINIC::GetPhrase(-1, 2391, $sPrice, GetGroupLink($$pDiscount{'GROUPID'}));
}
elsif ($nReward == $::eRewardPercentageOff)
{
if ($$pDiscount{'REWARDS'}->{'PERCENTAGE_OFF'} eq '100.00%')
{
$sMsg = ACTINIC::GetPhrase(-1, 2392, GetGroupLink($$pDiscount{'GROUPID'}));
}
else
{
$sMsg = ACTINIC::GetPhrase(-1, 2391, StripTrailingZero($$pDiscount{'REWARDS'}->{'PERCENTAGE_OFF'}), GetGroupLink($$pDiscount{'GROUPID'}));
}
}
elsif ($nReward == $::eRewardPercentageOffCheapest)
{
if ($$pDiscount{'REWARDS'}->{'PERCENTAGE_OFF'} eq '100.00%')
{
$sMsg = ACTINIC::GetPhrase(-1, 2394, GetGroupLink($$pDiscount{'GROUPID'}));
}
else
{
$sMsg = ACTINIC::GetPhrase(-1, 2393, StripTrailingZero($$pDiscount{'REWARDS'}->{'PERCENTAGE_OFF'}), GetGroupLink($$pDiscount{'GROUPID'}));
}
}
elsif ($nReward == $::eRewardFixedPrice)
{
my $sPrice = (ActinicOrder::FormatPrice($$pDiscount{'REWARDS'}->{'MONEY_OFF'}, $::TRUE, $::g_pCatalogBlob))[2];
$sMsg = ACTINIC::GetPhrase(-1, 2395, GetGroupLink($$pDiscount{'GROUPID'}), $sPrice);
}
elsif ($nReward == $::eRewardMoneyOffExtraProduct)
{
my $sPrice = (ActinicOrder::FormatPrice($$pDiscount{'REWARDS'}->{'MONEY_OFF'}, $::TRUE, $::g_pCatalogBlob))[2];
$sMsg = ACTINIC::GetPhrase(-1, 2397, $sPrice, GetRewardProductLink($pDiscount));
}
elsif ($nReward == $::eRewardPercentageOffExtraProduct)
{
if ($$pDiscount{'REWARDS'}->{'PERCENTAGE_OFF'} eq '100.00%')
{
$sMsg = ACTINIC::GetPhrase(-1, 2392, GetRewardProductLink($pDiscount));
}
else
{
$sMsg = ACTINIC::GetPhrase(-1, 2397, StripTrailingZero($$pDiscount{'REWARDS'}->{'PERCENTAGE_OFF'}), GetRewardProductLink($pDiscount));
}
}
return $sMsg;
}
sub StripTrailingZero
{
my $sIn = shift;
$sIn =~ s/(.+\.+[^\.0]*)0*(%*)$/$1$2/;
$sIn =~ s/\.(%*)$/$1/;
return $sIn;
}
sub GetRewardProductLink
{
my $pDiscount = shift;
my $sLink;
if ($$pDiscount{'REWARDS'}->{'USE_GROUP'})
{
$sLink = GetGroupLink($$pDiscount{'REWARDS'}->{'PRODUCT_GROUP'});
}
else
{
my ($nStatus, $sMessage, $pProduct) = Cart::GetProduct($$pDiscount{'REWARDS'}->{'PRODUCT_REF'});
if ($nStatus != $::SUCCESS)
{
return "";
}
my @Response = ACTINIC::ProcessEscapableText($$pProduct{'NAME'});
$sLink = sprintf("%s", $$pDiscount{'REWARDS'}->{'PRODUCT_REF'}, $Response[1]);
}
return $sLink;
}
sub GetGroupLink
{
my $nGroupID = shift;
my $sLink;
my $sShop = ($::g_InputHash{SHOP} ? '&SHOP=' . ACTINIC::EncodeText2($::g_InputHash{SHOP}, $::FALSE) : '');
if ($$::g_pDiscountBlob{'PRODUCT_GROUPS'}->{$nGroupID}->[2] ne '')
{
my ($nStatus, $sMessage, $pProduct) = Cart::GetProduct($$::g_pDiscountBlob{'PRODUCT_GROUPS'}->{$nGroupID}->[2]);
if ($nStatus != $::SUCCESS)
{
return "";
}
my @Response = ACTINIC::ProcessEscapableText($$pProduct{'NAME'});
$sLink = sprintf("%s",
$$::g_pDiscountBlob{'PRODUCT_GROUPS'}->{$nGroupID}->[2],
$sShop,
$Response[1]);
}
else
{
$sLink = sprintf("%s",
$nGroupID,
$sShop,
$$::g_pDiscountBlob{'PRODUCT_GROUPS'}->{$nGroupID}->[1]);
}
return ($sLink);
}
sub AddProductDiscountInfo
{
my $sMessage = shift;
if ($$::g_pSetupBlob{'SHOW_PRODUCT_DISCOUNT_INFO'})
{
$ACTINIC::B2B->AppendXML("DiscountInfo", $sMessage . "\n");
}
}
sub AddOrderDiscountInfo
{
my $sMessage = shift;
if ($$::g_pSetupBlob{'SHOW_DISCOUNT_INFO'})
{
$ACTINIC::B2B->AppendXML("DiscountInfo", $sMessage . "\n");
}
}
sub CalculateProductRewards
{
my $pItemList = shift;
my $nGroupID = shift;
my $pDiscount = shift;
my @arrAdjustments;
my $nReward = $$pDiscount{'REWARD_TYPE'};
my $nBasis = $$pDiscount{'BASIS'};
my $bPaymentMessageDisplayed = $::FALSE;
my $bInactive = $::FALSE;
my $nDiscountTotal;
my %SavedItemList;
foreach my $nGroup (keys %{$pItemList})
{
my @Array;
map
{
my @Array2;
map {push @Array2, $_} (@{$_});
push @Array, \@Array2;
} (@{$$pItemList{$nGroup}});
$SavedItemList{$nGroup} = \@Array;
}
while ($::TRUE)
{
my ($nRemained, @CartItems) = GetNextTriggeringIndex($$pItemList{$nGroupID}, $$pDiscount{'BASIS'}, $$pDiscount{'REWARDS'}->{'TRIGGER'});
if ($$pDiscount{RESTRICTED_TO_PAYMENT} &&
(scalar @CartItems) != 0)
{
if (IsPaymentValid(\$pDiscount))
{
if (!$bPaymentMessageDisplayed)
{
if (!($nReward == $::eRewardMoneyOffExtraProduct ||
$nReward == $::eRewardPercentageOffExtraProduct))
{
my $sMessage = ACTINIC::GetPhrase(-1, 2362, $$pDiscount{'DESCRIPTION'}, GetPaymentMethodList(\$pDiscount));
AddProductDiscountInfo($sMessage);
$bPaymentMessageDisplayed = $::TRUE;
}
}
}
else
{
$bInactive = $::TRUE;
}
}
if ((scalar @CartItems) == 0)
{
if ($nRemained > 0 &&
!$bInactive)
{
my $sReward = GetRewardString($pDiscount);
my $sTrigger;
if ($$pDiscount{'BASIS'} != $::eBasisQuantity)
{
my $sPrice = (ActinicOrder::FormatPrice($nRemained, $::TRUE, $::g_pCatalogBlob))[2];
if ($nReward == $::eRewardMoneyOffExtraProduct ||
$nReward == $::eRewardPercentageOffExtraProduct)
{
$sTrigger = ACTINIC::GetPhrase(-1, 2398, $sPrice, GetGroupLink($$pDiscount{'GROUPID'}));
}
else
{
$sTrigger = ACTINIC::GetPhrase(-1, 2415, $sPrice);
}
}
else
{
if ($nReward == $::eRewardMoneyOffExtraProduct ||
$nReward == $::eRewardPercentageOffExtraProduct)
{
$sTrigger = ACTINIC::GetPhrase(-1, 2416,
$nRemained,
GetGroupLink($$pDiscount{'GROUPID'}),
$nRemained == 1 ? ACTINIC::GetPhrase(-1, 2403) : ACTINIC::GetPhrase(-1, 2404));
}
else
{
$sTrigger = ACTINIC::GetPhrase(-1, 2414, $nRemained);
}
}
my $sMessage = $sReward . $sTrigger;
AddProductDiscountInfo($sMessage);
}
last;
}
if ($nReward == $::eRewardMoneyOffExtraProduct ||
$nReward == $::eRewardPercentageOffExtraProduct)
{
my (@TempItems) = GetExtraProduct($pItemList, $pDiscount);
if ((scalar @TempItems) == 0)
{
my $sReward = GetRewardString($pDiscount);
my $sTrigger = ACTINIC::GetPhrase(-1, 2399, ACTINIC::GetPhrase(-1, $$pDiscount{'REWARDS'}->{'USE_GROUP'} ? 2412 : 2411));
my $sMessage = $sReward . $sTrigger;
AddProductDiscountInfo($sMessage);
last;
}
if ($$pDiscount{RESTRICTED_TO_PAYMENT} &&
IsPaymentValid(\$pDiscount))
{
if (!$bPaymentMessageDisplayed)
{
my $sMessage = ACTINIC::GetPhrase(-1, 2362, $$pDiscount{'DESCRIPTION'}, GetPaymentMethodList(\$pDiscount));
AddProductDiscountInfo($sMessage);
$bPaymentMessageDisplayed = $::TRUE;
}
}
push @CartItems, $TempItems[0];
}
if ($nReward == $::eRewardPercentageOff)
{
@CartItems = GetAllAvailableGroupItems($$pItemList{$nGroupID}, $$pDiscount{'BASIS'});
}
my $pLine;
my $nUsed;
my $nTaxExclusiveItemTotal;
my $nUsedValue;
foreach $pLine (@CartItems)
{
$nUsed += ($nBasis == $::eBasisQuantity) ? $$pLine[1] : $$pLine[2];
$nUsedValue += ($nBasis == $::eBasisQuantity) ? $$pLine[3]->[$::eDCartLineItemCost] * $$pLine[1] : $$pLine[2];
$nTaxExclusiveItemTotal += $$pLine[3]->[$::eDCartLineItemCost] * $$pLine[1];
}
my $nIndex;
my $nAdjTotal;
foreach $pLine (@CartItems)
{
my $nAdjustment = 0;
my $nContribution = 0;
unless ((($nBasis == $::eBasisQuantity) &&
($$pLine[3]->[$::eDCartLineItemCost] * $$pLine[1] == 0)) ||
(($nBasis != $::eBasisQuantity) &&
($$pLine[2] == 0)))
{
$nContribution = 1 / $nUsedValue * (($nBasis == $::eBasisQuantity) ? $$pLine[3]->[$::eDCartLineItemCost] * $$pLine[1] : $$pLine[2]);
}
if ($nReward == $::eRewardMoneyOff)
{
if ((scalar @CartItems) == $nIndex + 1)
{
$nAdjustment = -$$pDiscount{'REWARDS'}->{'MONEY_OFF'} - $nAdjTotal;
}
else
{
$nAdjustment = ActinicOrder::RoundTax(-($$pDiscount{'REWARDS'}->{'MONEY_OFF'} * $nContribution), $ActinicOrder::SCIENTIFIC_NORMAL);
}
}
elsif ($nReward == $::eRewardPercentageOff)
{
if ($$pDiscount{'BASIS'} == $::eBasisQuantity)
{
$nAdjustment = ActinicOrder::RoundTax(-($$pLine[1] * $$pLine[3]->[$::eDCartLineItemCost] / 100 * $$pDiscount{'REWARDS'}->{'PERCENTAGE_OFF'}), $ActinicOrder::SCIENTIFIC_NORMAL);
}
else
{
$nAdjustment = ActinicOrder::RoundTax(-($$pLine[2] / 100 * $$pDiscount{'REWARDS'}->{'PERCENTAGE_OFF'}), $ActinicOrder::SCIENTIFIC_NORMAL);
}
}
elsif ($nReward == $::eRewardPercentageOffCheapest)
{
if ((scalar @CartItems) == $nIndex + 1)
{
$nAdjustment = ActinicOrder::RoundTax(-($$pLine[3]->[$::eDCartLineItemCost] / 100 * $$pDiscount{'REWARDS'}->{'PERCENTAGE_OFF'}), $ActinicOrder::SCIENTIFIC_NORMAL);
}
}
elsif ($nReward == $::eRewardFixedPrice)
{
my $nDiscount = $$pDiscount{'REWARDS'}->{'MONEY_OFF'} - $nTaxExclusiveItemTotal;
if ((scalar @CartItems) == $nIndex + 1)
{
$nAdjustment = $nDiscount - $nAdjTotal;
}
else
{
$nAdjustment = ActinicOrder::RoundTax(($nDiscount * $nContribution), $ActinicOrder::SCIENTIFIC_NORMAL);
}
}
elsif ($nReward == $::eRewardMoneyOffExtraProduct)
{
if ((scalar @CartItems) == $nIndex + 1)
{
$nAdjustment = -$$pDiscount{'REWARDS'}->{'MONEY_OFF'};
}
}
elsif ($nReward == $::eRewardPercentageOffExtraProduct)
{
if ((scalar @CartItems) == $nIndex + 1)
{
$nAdjustment = ActinicOrder::RoundTax(-($$pLine[3]->[$::eDCartLineItemCost] / 100 * $$pDiscount{'REWARDS'}->{'PERCENTAGE_OFF'}), $ActinicOrder::SCIENTIFIC_NORMAL);
}
}
my $nUsedValue = ($nBasis == $::eBasisQuantity) ? $$pLine[3]->[$::eDCartLineItemCost] * $$pLine[1] : $$pLine[2];
$nAdjTotal += $nAdjustment;
$nDiscountTotal += $nAdjustment;
if (((scalar @CartItems) == $nIndex + 1) &&
(($nReward == $::eRewardPercentageOffExtraProduct) ||
($nReward == $::eRewardMoneyOffExtraProduct)))
{
$$pLine[3]->[$::eDcartLineQuantityUsed]++;
$$pLine[3]->[$::eDcartLineValueUsed] += $$pLine[2];
$nUsedValue = $$pLine[3]->[$::eDCartLineItemCost];
}
else
{
$$pLine[3]->[$::eDcartLineQuantityUsed] += $$pLine[1];
$$pLine[3]->[$::eDcartLineValueUsed] += $$pLine[2];
}
if (($nAdjTotal < 0) &&
($nUsedValue < abs($nAdjustment)))
{
$nAdjTotal -= $nAdjustment;
$nDiscountTotal -= $nAdjustment;
$nAdjustment = - $nUsedValue;
$nAdjTotal += $nAdjustment;
$nDiscountTotal += $nAdjustment;
}
if (($nAdjustment != 0) &&
!$bInactive)
{
my @arrAdjustment =
($$pLine[3]->[$::eDcartLineProductRef],
$$pDiscount{'DESCRIPTION'},
$nAdjustment,
$::eAdjTaxProRata );
$arrAdjustment[$::eAdjIdxCouponCode] = $$pDiscount{'COUPON_CODE'};
$arrAdjustment[$::eAdjIdxCartIndex] = $$pLine[0];
$arrAdjustment[$::eAdjIdxDiscountID] = $$pDiscount{'ID'};
$arrAdjustment[$::eAdjIdxRewardType] = $nReward;
if ((scalar @arrAdjustments) != 0 &&
$arrAdjustments[$#arrAdjustments][$::eAdjIdxCartIndex] == $$pLine[0] &&
$arrAdjustments[$#arrAdjustments][$::eAdjIdxDiscountID] == $$pDiscount{'ID'})
{
$arrAdjustments[$#arrAdjustments][2] += $nAdjustment;
}
else
{
push @arrAdjustments, \@arrAdjustment;
}
}
$nIndex++;
}
if ($$pDiscount{'ONE_PER_ORDER'})
{
last;
}
}
if ($bInactive)
{
if ($bInactive &&
($nDiscountTotal != 0))
{
my $sPrice = (ActinicOrder::FormatPrice(abs($nDiscountTotal), $::TRUE, $::g_pCatalogBlob))[2];
my $sMessage = ACTINIC::GetPhrase(-1, 2363, $sPrice, "adjustment", GetPaymentMethodList(\$pDiscount));
AddProductDiscountInfo($sMessage);
}
foreach my $nGroup (keys %SavedItemList)
{
my @Array;
map
{
my @Array2;
map {push @Array2, $_} (@{$_});
push @Array, \@Array2;
} (@{$SavedItemList{$nGroup}});
$$pItemList{$nGroup} = \@Array;
}
}
return @arrAdjustments;
}
sub GetExtraProduct
{
my $pItemList = shift;
my $pDiscount = shift;
if ($$pDiscount{'REWARDS'}->{'USE_GROUP'})
{
my ($nRemained, @Cart) = GetNextTriggeringIndex($$pItemList{$$pDiscount{'REWARDS'}->{'PRODUCT_GROUP'}}, $::eBasisQuantity, 1);
return(@Cart);
}
else
{
my ($nRemained, @Cart) = GetNextTriggeringIndex($$pItemList{-1}, $::eBasisProductReference, $$pDiscount{'REWARDS'}->{'PRODUCT_REF'});
return(@Cart);
}
}
sub GetAllAvailableGroupItems
{
my ($pItemList, $nBasis) = @_;
my $pItem;
my @Quantity;
foreach $pItem (@{$pItemList})
{
my $nUsableQty = $$pItem[$::eDCartLineQuantity] - $$pItem[$::eDcartLineQuantityUsed];
my $nUsableValue = $$pItem[$::eDCartLineTotal] - $$pItem[$::eDcartLineValueUsed];
my @Ret;
if ($nBasis == $::eBasisQuantity)
{
@Ret = ($$pItem[0], $nUsableQty, 0, $pItem);
}
else
{
@Ret = ($$pItem[0], 0, $nUsableValue, $pItem);
}
push @Quantity, \@Ret;
}
return (@Quantity);
}
sub GetNextTriggeringIndex
{
my ($pItemList, $nBasis, $nTrigger) = @_;
my $pItem;
my $nActual = 0;
my @Quantity;
foreach $pItem (@{$pItemList})
{
my $nUsableQty = $$pItem[$::eDCartLineQuantity] - $$pItem[$::eDcartLineQuantityUsed];
my $nUsableValue = $$pItem[$::eDCartLineTotal] - $$pItem[$::eDcartLineValueUsed];
if (($nBasis == $::eBasisQuantity) &&
($nUsableQty == 0)
||
($nBasis != $::eBasisQuantity) &&
($nUsableValue == 0))
{
next;
}
my $nTotalCost;
my $nCurrentIncrement;
my $nRatio;
if ($nBasis == $::eBasisTaxExlusiveValue)
{
$nCurrentIncrement = $nUsableValue;
$nRatio = 1;
}
elsif ($nBasis == $::eBasisValueIncludingDefaultTax)
{
$nRatio = ($$pItem[$::eDCartLineTotal] +
$$pItem[$::eDcartLineTax1Default] +
$$pItem[$::eDcartLineTax2Default]) == 0 ? 1 :
$$pItem[$::eDCartLineTotal] / ($$pItem[$::eDCartLineTotal] +
$$pItem[$::eDcartLineTax1Default] +
$$pItem[$::eDcartLineTax2Default]);
$nCurrentIncrement = $nUsableValue / $nRatio;
}
elsif ($nBasis == $::eBasisValueIncludingActualTax)
{
$nRatio = ($$pItem[$::eDCartLineTotal] +
$$pItem[$::eDcartLineTax1Actual] +
$$pItem[$::eDCartLineTax2Actual]) == 0 ? 1 :
$$pItem[$::eDCartLineTotal] / ($$pItem[$::eDCartLineTotal] +
$$pItem[$::eDcartLineTax1Actual] +
$$pItem[$::eDCartLineTax2Actual]);
$nCurrentIncrement = $nUsableValue / $nRatio;
}
elsif ($nBasis == $::eBasisQuantity)
{
$nCurrentIncrement = $nUsableQty;
}
elsif ($nBasis == $::eBasisProductReference)
{
if ($nTrigger eq $$pItem[$::eDcartLineProductRef] &&
$nUsableQty >= 1)
{
my @Ret = ($$pItem[0], 1, 0, $pItem);
push @Quantity, \@Ret;
return (0, @Quantity);
}
next;
}
$nActual += $nCurrentIncrement;
if ($nActual >= $nTrigger)
{
my $nUsedQty = 0;
my $nUsedValue = 0;
if ($nBasis == $::eBasisQuantity)
{
$nUsedQty = $nTrigger - ($nActual - $nCurrentIncrement);
}
else
{
$nUsedValue = ($nTrigger - ($nActual - $nCurrentIncrement)) * $nRatio;
}
my @Ret = ($$pItem[0], $nUsedQty, $nUsedValue, $pItem);
push @Quantity, \@Ret;
return (0, @Quantity);
}
my @Ret;
if ($nBasis == $::eBasisQuantity)
{
@Ret = ($$pItem[0], $nUsableQty, 0, $pItem);
}
else
{
@Ret = ($$pItem[0], 0, $nUsableValue, $pItem);
}
push @Quantity, \@Ret;
}
return ($nActual == 0 ? 0 : $nTrigger - $nActual, ());
}
sub CalculateOrderAdjustment
{
my ($parrOrderTotals) = @_;
my @arrAdjustments;
my $nTotalAdjustments = 0;
my ($pItem);
my $bGotOneDiscount = $::FALSE;
my $bGotOneSurcharge = $::FALSE;
foreach $pItem (@{$$::g_pDiscountBlob{ORDER_LEVEL}})
{
if (!IsDateValid(\$pItem) ||
!IsCustomerValid(\$pItem) ||
!IsCouponValid(\$pItem))
{
next;
}
if (($pItem->{'BASIS'} <= 2 && scalar(@$parrOrderTotals) == 2))
{
my $nTotal;
my $nAdjustable;
if (defined $pItem->{'BASIS'})
{
if ($pItem->{'BASIS'} == $::eBasisTaxExlusiveValue)
{
$nTotal = $parrOrderTotals->[1][0];
$nAdjustable = $nTotal;
}
elsif ($pItem->{'BASIS'} == $::eBasisValueIncludingDefaultTax)
{
$nTotal = $parrOrderTotals->[1][0] +
$parrOrderTotals->[1][3] +
$parrOrderTotals->[1][4];
$nAdjustable = $parrOrderTotals->[1][0];
}
elsif ($pItem->{'BASIS'} == $::eBasisValueIncludingActualTax)
{
if ($parrOrderTotals->[1][5])
{
$nTotal = $parrOrderTotals->[1][0] +
$parrOrderTotals->[1][1] +
$parrOrderTotals->[1][2];
$nAdjustable = $parrOrderTotals->[1][0];
}
}
}
my $nAdjustment = CalculateOrderRewards(\$pItem, $nTotal, $nAdjustable, $bGotOneDiscount, $bGotOneSurcharge);
if (($parrOrderTotals->[1][0] + $nTotalAdjustments + $nAdjustment) < 0)
{
$nAdjustment = - ($parrOrderTotals->[1][0] + $nTotalAdjustments);
}
$nTotalAdjustments += $nAdjustment;
my @arrAdjustment =
($pItem->{'DESCRIPTION'},
$nAdjustment,
$::eAdjTaxProRataAdjusted,
"",
$pItem->{'BASIS'},
$pItem->{'COUPON_CODE'});
if ($nAdjustment != 0)
{
if (((!$$::g_pDiscountBlob{ONE_ORDER_DISCOUNT} && $nAdjustment < 0) ||
($nAdjustment < 0 && !$bGotOneDiscount)) ||
((!$$::g_pDiscountBlob{ONE_ORDER_DISCOUNT_SURCHAGE} && $nAdjustment > 0) ||
($nAdjustment > 0 && !$bGotOneSurcharge)))
{
push @arrAdjustments, \@arrAdjustment;
}
if ($nAdjustment < 0)
{
$bGotOneDiscount = $::TRUE;
}
else
{
$bGotOneSurcharge = $::TRUE;
}
}
}
}
return($::SUCCESS, '', \@arrAdjustments);
}
sub CalculateOrderRewards
{
my ($phashDiscount, $nTotal, $nAdjustable, $bGotOneDiscount, $bGotOneSurcharge) = @_;
my $nCartValue;
my $nAdjustment = 0;
my $sAdjustment = 0;
my $nNextBand;
foreach $nCartValue (sort {$b <=> $a} keys %{$$phashDiscount->{'REWARDS'}})
{
if ($nCartValue <= $nTotal)
{
$sAdjustment = $$phashDiscount->{'REWARDS'}->{$nCartValue};
last;
}
$nNextBand = $nCartValue;
}
$nAdjustment = $sAdjustment;
if ($nAdjustment =~ /%$/)
{
$nAdjustment =~ s/%$//;
$nAdjustment = $nAdjustable * $nAdjustment / 100;
my $nRound = ($nAdjustment < 0) ? -0.5 : 0.5;
$nAdjustment = int($nAdjustment + $nRound);
}
my $bDiscount = ($nAdjustment < 0) || ($$phashDiscount->{'REWARDS'}->{$nNextBand} < 0) ? $::TRUE : $::FALSE;
if (($$::g_pDiscountBlob{ONE_ORDER_DISCOUNT} &&
$bDiscount &&
$bGotOneDiscount) ||
($$::g_pDiscountBlob{ONE_ORDER_DISCOUNT_SURCHAGE} &&
!$bDiscount &&
$bGotOneSurcharge))
{
return 0;
}
if (!$bDiscount &&
($nTotal == 0))
{
return 0;
}
if ($$phashDiscount->{RESTRICTED_TO_PAYMENT} &&
$nAdjustment != 0)
{
my $sMessage;
if (IsPaymentValid($phashDiscount))
{
$sMessage = ACTINIC::GetPhrase(-1, 2362, $$phashDiscount->{'DESCRIPTION'}, GetPaymentMethodList($phashDiscount));
}
else
{
my $sAdjustment = ($sAdjustment =~ /%$/) ? StripTrailingZero($sAdjustment) : (ActinicOrder::FormatPrice($sAdjustment, $::TRUE, $::g_pCatalogBlob))[2];
$sAdjustment =~ s/^-//;
my $sDiscount = ACTINIC::GetPhrase(-1, ($nAdjustment < 0 ? 2364 : 2365));
$sMessage = ACTINIC::GetPhrase(-1, 2363, $sAdjustment, $sDiscount, GetPaymentMethodList($phashDiscount));
$nAdjustment = 0;
}
AddOrderDiscountInfo($sMessage);
}
my $sNext = $$phashDiscount->{'REWARDS'}->{$nNextBand};
if ($nNextBand > $nCartValue &&
$sNext =~ /^-/)
{
$sNext =~ s/^-//;
my $sPrice = (ActinicOrder::FormatPrice($nNextBand, $::TRUE, $::g_pCatalogBlob))[2];
my $sOff = ($sNext =~ /%$/) ? StripTrailingZero($sNext) : (ActinicOrder::FormatPrice($sNext, $::TRUE, $::g_pCatalogBlob))[2];
my $sMessage = ACTINIC::GetPhrase(-1, 2366, $sOff, $sPrice);
AddOrderDiscountInfo($sMessage);
}
return $nAdjustment;
}
sub GetPaymentMethodList
{
my ($phashDiscount) = @_;
my $sRestriction;
my $sList;
foreach $sRestriction (keys %{$$phashDiscount->{'RESTRICTIONS'}})
{
if ($sRestriction =~ /P_(\d+)/)
{
$sList .= $$::g_pPaymentList{$1}{'PROMPT'} . ", ";
}
}
my $sOr = " " . ACTINIC::GetPhrase(-1, 2367);
$sList =~ s/, $//;
$sList =~ s/,([^,]*)$/$sOr$1/g;
return $sList;
}
sub IsDateValid
{
my ($phashDiscount) = @_;
my $nNow = time;
if ($$phashDiscount->{USE_FROM_DATE})
{
my @aFrom = split /\//, $$phashDiscount->{VALID_FROM};
my $nStart = timegm(0, 0, 0, $aFrom[2], $aFrom[1] - 1, $aFrom[0]);
if ($nNow < $nStart)
{
return $::FALSE;
}
}
if ($$phashDiscount->{USE_UNTIL_DATE})
{
my @aUntil = split /\//, $$phashDiscount->{VALID_UNTIL};
my $nExpiry = timegm(59, 59, 23, $aUntil[2], $aUntil[1] - 1, $aUntil[0]);
if ($nNow > $nExpiry)
{
return $::FALSE;
}
}
return ($::TRUE);
}
sub IsCustomerValid
{
my ($phashDiscount) = @_;
if (!$$phashDiscount->{RESTRICTED_TO_CUSTOMER})
{
return $::TRUE;
}
my $sDigest = $ACTINIC::B2B->Get('UserDigest');
my $nSchedule = ActinicOrder::GetScheduleID($sDigest);
my $sKey = "C_" . $nSchedule;
if ($$phashDiscount->{RESTRICTIONS}->{$sKey} == 1)
{
return $::TRUE;
}
return $::FALSE;
}
sub IsPaymentValid
{
my ($phashDiscount) = @_;
if (!$$phashDiscount->{RESTRICTED_TO_PAYMENT})
{
return $::TRUE;
}
my $nPaymentID = $::g_PaymentInfo{METHOD};
my $sKey = "P_" . $nPaymentID;
if ($$phashDiscount->{RESTRICTIONS}->{$sKey} == 1)
{
return $::TRUE;
}
return $::FALSE;
}
sub IsCouponValid
{
my ($phashDiscount) = @_;
if (!$$phashDiscount->{REQUIRES_COUPON})
{
return $::TRUE;
}
my $sCoupon = $::g_PaymentInfo{COUPONCODE};
if ($$phashDiscount->{COUPON_CODE} eq $sCoupon)
{
return $::TRUE;
}
return $::FALSE;
}
sub ValidateCoupon
{
my $sCoupon = shift;
my ($pItem);
my @Discounts = (@{$$::g_pDiscountBlob{ORDER_LEVEL}}, @{$$::g_pDiscountBlob{PRODUCT_LEVEL}});
foreach $pItem (@Discounts)
{
if (!$pItem->{REQUIRES_COUPON})
{
next;
}
if ($pItem->{COUPON_CODE} ne $sCoupon)
{
next;
}
if ($pItem->{USE_UNTIL_DATE})
{
my @aUntil = split /\//, $pItem->{VALID_UNTIL};
my $nNow = time;
my $nExpiry = timegm(59, 59, 23, $aUntil[2], $aUntil[1] - 1, $aUntil[0]);
if ($nNow > $nExpiry)
{
my $sExpiry = ACTINIC::FormatDate($aUntil[2], $aUntil[1], $aUntil[0], $::FALSE);
return ($::FAILURE, ACTINIC::GetPhrase(-1, 2358, $sExpiry), undef);
}
}
return ($::SUCCESS, undef, undef);
}
if (ACTINIC::GetPhrase(-1, 2355) eq $sCoupon)
{
return ($::SUCCESS, undef, undef);
}
return ($::FAILURE, ACTINIC::GetPhrase(-1, 2357, $sCoupon), undef);
}
1;