Skip to content

Commit 6005a92

Browse files
committed
add case BuyXGetYAction
1 parent 679cd33 commit 6005a92

File tree

1 file changed

+50
-9
lines changed

1 file changed

+50
-9
lines changed

app/code/Magento/SalesRule/Model/Validator.php

Lines changed: 50 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
namespace Magento\SalesRule\Model;
88

99
use Magento\Framework\App\ObjectManager;
10+
use Magento\Quote\Model\Quote;
1011
use Magento\Quote\Model\Quote\Address;
1112
use Magento\Quote\Model\Quote\Item\AbstractItem;
1213
use Magento\SalesRule\Helper\CartFixedDiscount;
@@ -319,7 +320,7 @@ public function processShippingAmount(Address $address)
319320
$quote = $address->getQuote();
320321
$appliedRuleIds = [];
321322
foreach ($this->_getRules($address) as $rule) {
322-
/* @var \Magento\SalesRule\Model\Rule $rule */
323+
/* @var Rule $rule */
323324
if (!$rule->getApplyToShipping() || !$this->validatorUtility->canProcessRule($rule, $address)) {
324325
continue;
325326
}
@@ -328,28 +329,28 @@ public function processShippingAmount(Address $address)
328329
$baseDiscountAmount = 0;
329330
$rulePercent = min(100, $rule->getDiscountAmount());
330331
switch ($rule->getSimpleAction()) {
331-
case \Magento\SalesRule\Model\Rule::TO_PERCENT_ACTION:
332+
case Rule::TO_PERCENT_ACTION:
332333
$rulePercent = max(0, 100 - $rule->getDiscountAmount());
333334
// break is intentionally omitted
334335
// no break
335-
case \Magento\SalesRule\Model\Rule::BY_PERCENT_ACTION:
336+
case Rule::BY_PERCENT_ACTION:
336337
$discountAmount = ($shippingAmount - $address->getShippingDiscountAmount()) * $rulePercent / 100;
337338
$baseDiscountAmount = ($baseShippingAmount -
338339
$address->getBaseShippingDiscountAmount()) * $rulePercent / 100;
339340
$discountPercent = min(100, $address->getShippingDiscountPercent() + $rulePercent);
340341
$address->setShippingDiscountPercent($discountPercent);
341342
break;
342-
case \Magento\SalesRule\Model\Rule::TO_FIXED_ACTION:
343+
case Rule::TO_FIXED_ACTION:
343344
$quoteAmount = $this->priceCurrency->convert($rule->getDiscountAmount(), $quote->getStore());
344345
$discountAmount = $shippingAmount - $quoteAmount;
345346
$baseDiscountAmount = $baseShippingAmount - $rule->getDiscountAmount();
346347
break;
347-
case \Magento\SalesRule\Model\Rule::BY_FIXED_ACTION:
348+
case Rule::BY_FIXED_ACTION:
348349
$quoteAmount = $this->priceCurrency->convert($rule->getDiscountAmount(), $quote->getStore());
349350
$discountAmount = $quoteAmount;
350351
$baseDiscountAmount = $rule->getDiscountAmount();
351352
break;
352-
case \Magento\SalesRule\Model\Rule::CART_FIXED_ACTION:
353+
case Rule::CART_FIXED_ACTION:
353354
$cartRules = $address->getCartFixedRules();
354355
$quoteAmount = $this->priceCurrency->convert($rule->getDiscountAmount(), $quote->getStore());
355356
$isAppliedToShipping = (int) $rule->getApplyToShipping();
@@ -385,6 +386,12 @@ public function processShippingAmount(Address $address)
385386
}
386387
$address->setCartFixedRules($cartRules);
387388
break;
389+
case Rule::BUY_X_GET_Y_ACTION:
390+
$qty = $this->getDiscountQtyAllItemsBuyXGetYAction($quote, $rule);
391+
$quoteAmount = $address->getBaseShippingAmount() / $quote->getItemsQty() * $qty;
392+
$discountAmount = $this->priceCurrency->convert($quoteAmount, $quote->getStore());
393+
$baseDiscountAmount = $quoteAmount;
394+
break;
388395
}
389396

390397
$discountAmount = min($address->getShippingDiscountAmount() + $discountAmount, $shippingAmount);
@@ -426,9 +433,9 @@ public function initTotals($items, Address $address)
426433
return $this;
427434
}
428435

429-
/** @var \Magento\SalesRule\Model\Rule $rule */
436+
/** @var Rule $rule */
430437
foreach ($this->_getRules($address) as $rule) {
431-
if (\Magento\SalesRule\Model\Rule::CART_FIXED_ACTION == $rule->getSimpleAction()
438+
if (Rule::CART_FIXED_ACTION == $rule->getSimpleAction()
432439
&& $this->validatorUtility->canProcessRule($rule, $address)
433440
) {
434441
$ruleTotalItemsPrice = 0;
@@ -481,6 +488,40 @@ private function isValidItemForRule(AbstractItem $item, Rule $rule)
481488
return true;
482489
}
483490

491+
/**
492+
* Return discount Qty for all items at Buy_X_Get_Y_Action
493+
*
494+
* @param Quote $quote
495+
* @param Rule $rule
496+
* @return float
497+
*/
498+
private function getDiscountQtyAllItemsBuyXGetYAction($quote, $rule)
499+
{
500+
$discountAllQty = 0;
501+
foreach ($quote->getItems() as $item) {
502+
$qty = $item->getQty();
503+
504+
$x = $rule->getDiscountStep();
505+
$y = $rule->getDiscountAmount();
506+
if (!$x || $y > $x) {
507+
continue;
508+
}
509+
$buyAndDiscountQty = $x + $y;
510+
511+
$fullRuleQtyPeriod = floor($qty / $buyAndDiscountQty);
512+
$freeQty = $qty - $fullRuleQtyPeriod * $buyAndDiscountQty;
513+
514+
$discountQty = $fullRuleQtyPeriod * $y;
515+
if ($freeQty > $x) {
516+
$discountQty += $freeQty - $x;
517+
}
518+
519+
$discountAllQty += $discountQty;
520+
}
521+
522+
return $discountAllQty;
523+
}
524+
484525
/**
485526
* Return item price
486527
*
@@ -564,7 +605,7 @@ public function prepareDescription($address, $separator = ', ')
564605
public function sortItemsByPriority($items, Address $address = null)
565606
{
566607
$itemsSorted = [];
567-
/** @var $rule \Magento\SalesRule\Model\Rule */
608+
/** @var $rule Rule */
568609
foreach ($this->_getRules($address) as $rule) {
569610
foreach ($items as $itemKey => $itemValue) {
570611
if ($rule->getActions()->validate($itemValue)) {

0 commit comments

Comments
 (0)