7
7
namespace Magento \SalesRule \Model ;
8
8
9
9
use Magento \Framework \App \ObjectManager ;
10
+ use Magento \Quote \Model \Quote ;
10
11
use Magento \Quote \Model \Quote \Address ;
11
12
use Magento \Quote \Model \Quote \Item \AbstractItem ;
12
13
use Magento \SalesRule \Helper \CartFixedDiscount ;
@@ -319,7 +320,7 @@ public function processShippingAmount(Address $address)
319
320
$ quote = $ address ->getQuote ();
320
321
$ appliedRuleIds = [];
321
322
foreach ($ this ->_getRules ($ address ) as $ rule ) {
322
- /* @var \Magento\SalesRule\Model\ Rule $rule */
323
+ /* @var Rule $rule */
323
324
if (!$ rule ->getApplyToShipping () || !$ this ->validatorUtility ->canProcessRule ($ rule , $ address )) {
324
325
continue ;
325
326
}
@@ -328,28 +329,28 @@ public function processShippingAmount(Address $address)
328
329
$ baseDiscountAmount = 0 ;
329
330
$ rulePercent = min (100 , $ rule ->getDiscountAmount ());
330
331
switch ($ rule ->getSimpleAction ()) {
331
- case \ Magento \ SalesRule \ Model \ Rule::TO_PERCENT_ACTION :
332
+ case Rule::TO_PERCENT_ACTION :
332
333
$ rulePercent = max (0 , 100 - $ rule ->getDiscountAmount ());
333
334
// break is intentionally omitted
334
335
// no break
335
- case \ Magento \ SalesRule \ Model \ Rule::BY_PERCENT_ACTION :
336
+ case Rule::BY_PERCENT_ACTION :
336
337
$ discountAmount = ($ shippingAmount - $ address ->getShippingDiscountAmount ()) * $ rulePercent / 100 ;
337
338
$ baseDiscountAmount = ($ baseShippingAmount -
338
339
$ address ->getBaseShippingDiscountAmount ()) * $ rulePercent / 100 ;
339
340
$ discountPercent = min (100 , $ address ->getShippingDiscountPercent () + $ rulePercent );
340
341
$ address ->setShippingDiscountPercent ($ discountPercent );
341
342
break ;
342
- case \ Magento \ SalesRule \ Model \ Rule::TO_FIXED_ACTION :
343
+ case Rule::TO_FIXED_ACTION :
343
344
$ quoteAmount = $ this ->priceCurrency ->convert ($ rule ->getDiscountAmount (), $ quote ->getStore ());
344
345
$ discountAmount = $ shippingAmount - $ quoteAmount ;
345
346
$ baseDiscountAmount = $ baseShippingAmount - $ rule ->getDiscountAmount ();
346
347
break ;
347
- case \ Magento \ SalesRule \ Model \ Rule::BY_FIXED_ACTION :
348
+ case Rule::BY_FIXED_ACTION :
348
349
$ quoteAmount = $ this ->priceCurrency ->convert ($ rule ->getDiscountAmount (), $ quote ->getStore ());
349
350
$ discountAmount = $ quoteAmount ;
350
351
$ baseDiscountAmount = $ rule ->getDiscountAmount ();
351
352
break ;
352
- case \ Magento \ SalesRule \ Model \ Rule::CART_FIXED_ACTION :
353
+ case Rule::CART_FIXED_ACTION :
353
354
$ cartRules = $ address ->getCartFixedRules ();
354
355
$ quoteAmount = $ this ->priceCurrency ->convert ($ rule ->getDiscountAmount (), $ quote ->getStore ());
355
356
$ isAppliedToShipping = (int ) $ rule ->getApplyToShipping ();
@@ -385,6 +386,12 @@ public function processShippingAmount(Address $address)
385
386
}
386
387
$ address ->setCartFixedRules ($ cartRules );
387
388
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 ;
388
395
}
389
396
390
397
$ discountAmount = min ($ address ->getShippingDiscountAmount () + $ discountAmount , $ shippingAmount );
@@ -426,9 +433,9 @@ public function initTotals($items, Address $address)
426
433
return $ this ;
427
434
}
428
435
429
- /** @var \Magento\SalesRule\Model\ Rule $rule */
436
+ /** @var Rule $rule */
430
437
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 ()
432
439
&& $ this ->validatorUtility ->canProcessRule ($ rule , $ address )
433
440
) {
434
441
$ ruleTotalItemsPrice = 0 ;
@@ -481,6 +488,40 @@ private function isValidItemForRule(AbstractItem $item, Rule $rule)
481
488
return true ;
482
489
}
483
490
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
+
484
525
/**
485
526
* Return item price
486
527
*
@@ -564,7 +605,7 @@ public function prepareDescription($address, $separator = ', ')
564
605
public function sortItemsByPriority ($ items , Address $ address = null )
565
606
{
566
607
$ itemsSorted = [];
567
- /** @var $rule \Magento\SalesRule\Model\ Rule */
608
+ /** @var $rule Rule */
568
609
foreach ($ this ->_getRules ($ address ) as $ rule ) {
569
610
foreach ($ items as $ itemKey => $ itemValue ) {
570
611
if ($ rule ->getActions ()->validate ($ itemValue )) {
0 commit comments