Skip to content

Commit

Permalink
[Totals] #43 #44 - Avoid issue when trigger_recollect is set to true …
Browse files Browse the repository at this point in the history
…and base the price range logic on the subtotal including tax instead of the grand total
  • Loading branch information
PierreLeMaguer committed Nov 10, 2020
1 parent 36e41f3 commit 81d6bf3
Show file tree
Hide file tree
Showing 9 changed files with 87 additions and 114 deletions.
6 changes: 4 additions & 2 deletions Helper/Cache.php
Expand Up @@ -39,9 +39,10 @@ class Cache extends AbstractHelper
const CACHE_DATA_TAG = "gift_rule_cache";
const CACHE_IDENTIFIER = "gift_rule_product_";

const DATA_NUMBER_OFFERED_PRODUCT = "number_offered_product";
const DATA_PRODUCT_ITEMS = "product_items";
const DATA_LABEL = "label";
const DATA_PRICE_RANGE = "price_range";
const DATA_MAXIMUM_NUMBER_PRODUCT = "maximum_number_product";

/**
* @var CacheInterface
Expand Down Expand Up @@ -135,7 +136,8 @@ public function saveCachedGiftRule($identifier, $rule, $giftRule)

$giftRuleData = [
self::DATA_LABEL => $rule->getStoreLabel(),
self::DATA_NUMBER_OFFERED_PRODUCT => $giftRule->getNumberOfferedProduct(),
self::DATA_PRICE_RANGE => $giftRule->getPriceRange(),
self::DATA_MAXIMUM_NUMBER_PRODUCT => $giftRule->getMaximumNumberProduct(),
self::DATA_PRODUCT_ITEMS => $items,
];

Expand Down
32 changes: 27 additions & 5 deletions Helper/GiftRule.php
Expand Up @@ -109,7 +109,7 @@ public function isValidGiftRule(Rule $rule, Quote $quote)
/** @var GiftRuleInterface $giftRule */
$giftRule = $this->giftRuleRepository->getById($rule->getRuleId());

if ($quote->getGrandTotal() < $giftRule->getPriceRange()) {
if ($quote->getShippingAddress()->getBaseSubtotalTotalInclTax() < $giftRule->getPriceRange()) {
$valid = false;
}
}
Expand Down Expand Up @@ -139,14 +139,36 @@ public function getAddUrl($giftRuleId, $giftRuleCode)
/**
* Get range of a gift rule for a quote.
*
* @param Quote $quote Quote
* @param GiftRuleInterface $giftRule Gift rule
* @param float $total Total
* @param float $priceRange Price range
*
* @return float
*/
public function getRange($quote, $giftRule)
public function getRange($total, $priceRange)
{
return floor($quote->getGrandTotal() / $giftRule->getPriceRange());
return floor($total / $priceRange);
}

/**
* Get number offered product for a quote.
*
* @param Quote $quote Quote
* @param float $maximumNumberProduct Maximum number product
* @param float $priceRange Price range
* @return int
*/
public function getNumberOfferedProduct($quote, $maximumNumberProduct, $priceRange)
{
$numberOfferedProduct = $maximumNumberProduct;
if (floatval($priceRange) > 0) {
$range = $this->getRange(
$quote->getShippingAddress()->getBaseSubtotalTotalInclTax(),
$priceRange
);
$numberOfferedProduct = $maximumNumberProduct * $range;
}

return (int) $numberOfferedProduct;
}

/**
Expand Down
2 changes: 0 additions & 2 deletions Model/GiftRule.php
Expand Up @@ -22,8 +22,6 @@
*
* @author Maxime Queneau <maxime.queneau@smile.fr>
* @copyright 2019 Smile
* @method int getNumberOfferedProduct()
* @method GiftRule setNumberOfferedProduct(int $number)
* @SuppressWarnings(PHPMD.CamelCasePropertyName)
*/
class GiftRule extends AbstractModel implements GiftRuleInterface, IdentityInterface
Expand Down
34 changes: 27 additions & 7 deletions Model/GiftRuleService.php
Expand Up @@ -25,6 +25,7 @@
use Smile\GiftSalesRule\Api\Data\GiftRuleDataInterfaceFactory;
use Smile\GiftSalesRule\Api\GiftRuleServiceInterface;
use Smile\GiftSalesRule\Helper\Cache as GiftRuleCacheHelper;
use Smile\GiftSalesRule\Helper\GiftRule as GiftRuleHelper;

/**
* Class GiftRuleService
Expand Down Expand Up @@ -54,6 +55,11 @@ class GiftRuleService implements GiftRuleServiceInterface
*/
protected $giftRuleCacheHelper;

/**
* @var GiftRuleHelper
*/
protected $giftRuleHelper;

/**
* @var GiftRuleDataInterfaceFactory
*/
Expand All @@ -67,19 +73,22 @@ class GiftRuleService implements GiftRuleServiceInterface
* @param CacheInterface $cache Cache
* @param GiftRuleCacheHelper $giftRuleCacheHelper Gift rule cache helper
* @param GiftRuleDataInterfaceFactory $giftRuleDataFactory Gift rule data factory
* @param GiftRuleHelper $giftRuleHelper Gift rule helper
*/
public function __construct(
CheckoutSession $checkoutSession,
Cart $cart,
CacheInterface $cache,
GiftRuleCacheHelper $giftRuleCacheHelper,
GiftRuleDataInterfaceFactory $giftRuleDataFactory
GiftRuleDataInterfaceFactory $giftRuleDataFactory,
GiftRuleHelper $giftRuleHelper
) {
$this->checkoutSession = $checkoutSession;
$this->cart = $cart;
$this->cache = $cache;
$this->giftRuleCacheHelper = $giftRuleCacheHelper;
$this->giftRuleDataFactory = $giftRuleDataFactory;
$this->giftRuleHelper = $giftRuleHelper;
}

/**
Expand Down Expand Up @@ -120,6 +129,12 @@ public function getAvailableGifts(Quote $quote)
$gifts[$giftRuleId] = $giftRuleCachedData;
$gifts[$giftRuleId][GiftRuleDataInterface::RULE_ID] = $giftRuleId;
$gifts[$giftRuleId][GiftRuleDataInterface::CODE] = $giftRuleCode;
$gifts[$giftRuleId][GiftRuleDataInterface::NUMBER_OFFERED_PRODUCT]
= $this->giftRuleHelper->getNumberOfferedProduct(
$quote,
$giftRuleCachedData[GiftRuleCacheHelper::DATA_MAXIMUM_NUMBER_PRODUCT],
$giftRuleCachedData[GiftRuleCacheHelper::DATA_PRICE_RANGE]
);
$gifts[$giftRuleId][GiftRuleDataInterface::REST_NUMBER]
= $gifts[$giftRuleId][GiftRuleDataInterface::NUMBER_OFFERED_PRODUCT];
$gifts[$giftRuleId][GiftRuleDataInterface::QUOTE_ITEMS] = [];
Expand Down Expand Up @@ -165,7 +180,7 @@ public function addGiftProducts(Quote $quote, array $products, string $identifie
throw new Exception(__('We found an invalid request for adding gift product.'));
}

if ($this->isAuthorizedGiftProduct($product['id'], $giftRuleData, $product['qty'])) {
if ($this->isAuthorizedGiftProduct($quote, $product['id'], $giftRuleData, $product['qty'])) {
$product['gift_rule'] = $giftRuleId;
$this->cart->addProduct($product['id'], $product);
} else {
Expand Down Expand Up @@ -204,7 +219,7 @@ public function replaceGiftProducts(Quote $quote, array $products, string $ident
if (!(isset($product['id']) && isset($product['qty']))) {
throw new Exception(__('We found an invalid request for adding gift product.'));
}
if ($this->isAuthorizedGiftProduct($product['id'], $giftRuleData, $product['qty'])) {
if ($this->isAuthorizedGiftProduct($quote, $product['id'], $giftRuleData, $product['qty'])) {
$quoteItem = false;

$productId = $product['id'];
Expand Down Expand Up @@ -239,19 +254,24 @@ public function replaceGiftProducts(Quote $quote, array $products, string $ident
}

/**
* Check if is authorized gift product
* Check if is authorized gift product.
*
* @param Quote $quote Quote
* @param int $productId Product id
* @param array $giftRuleData Gift rule data
* @param int $qty Qty
*
* @return bool
*/
protected function isAuthorizedGiftProduct($productId, $giftRuleData, $qty)
protected function isAuthorizedGiftProduct($quote, $productId, $giftRuleData, $qty)
{
$isAuthorizedGiftProduct = false;
if (array_key_exists($productId, $giftRuleData[GiftRuleCacheHelper::DATA_PRODUCT_ITEMS])
&& $qty <= $giftRuleData[GiftRuleCacheHelper::DATA_NUMBER_OFFERED_PRODUCT]) {
&& $qty <= $this->giftRuleHelper->getNumberOfferedProduct(
$quote,
$giftRuleData[GiftRuleCacheHelper::DATA_MAXIMUM_NUMBER_PRODUCT],
$giftRuleData[GiftRuleCacheHelper::DATA_PRICE_RANGE]
)
) {
$isAuthorizedGiftProduct = true;
}

Expand Down
7 changes: 5 additions & 2 deletions Model/Rule/Action/Discount/OfferProductPerPriceRange.php
Expand Up @@ -114,8 +114,11 @@ public function calculate($rule, $item, $qty)
/** @var GiftRule $giftRule */
$giftRule = $this->giftRuleRepository->getById($rule->getRuleId());

if ($quote->getGrandTotal() >= $giftRule->getPriceRange()) {
$range = $this->giftRuleHelper->getRange($quote, $giftRule);
if ($quote->getShippingAddress()->getBaseSubtotalTotalInclTax() >= $giftRule->getPriceRange()) {
$range = $this->giftRuleHelper->getRange(
$quote->getShippingAddress()->getBaseSubtotalTotalInclTax(),
$giftRule->getPriceRange()
);

// Save active gift rule in session.
$giftRuleSessionData = $this->checkoutSession->getGiftRules();
Expand Down
21 changes: 18 additions & 3 deletions Observer/CollectGiftRule.php
Expand Up @@ -23,6 +23,7 @@
use Magento\Quote\Model\Quote\Item\Option;
use Smile\GiftSalesRule\Helper\Cache as GiftRuleCacheHelper;
use Smile\GiftSalesRule\Helper\Config as GiftRuleConfigHelper;
use Smile\GiftSalesRule\Helper\GiftRule as GiftRuleHelper;
use Smile\GiftSalesRule\Api\GiftRuleServiceInterface;

/**
Expand Down Expand Up @@ -53,6 +54,11 @@ class CollectGiftRule implements ObserverInterface
*/
protected $giftRuleConfigHelper;

/**
* @var GiftRuleHelper
*/
protected $giftRuleHelper;

/**
* @var CartRepositoryInterface
*/
Expand All @@ -70,6 +76,7 @@ class CollectGiftRule implements ObserverInterface
* @param GiftRuleServiceInterface $giftRuleService Gift rule service
* @param GiftRuleCacheHelper $giftRuleCacheHelper Gift rule cache helper
* @param GiftRuleConfigHelper $giftRuleConfigHelper Gift rule config helper
* @param GiftRuleHelper $giftRuleHelper Gift rule helper
* @param CartRepositoryInterface $quoteRepository Quote repository
* @param Http $request Request
*/
Expand All @@ -78,13 +85,15 @@ public function __construct(
GiftRuleServiceInterface $giftRuleService,
GiftRuleCacheHelper $giftRuleCacheHelper,
GiftRuleConfigHelper $giftRuleConfigHelper,
GiftRuleHelper $giftRuleHelper,
\Magento\Quote\Api\CartRepositoryInterface $quoteRepository,
\Magento\Framework\App\Request\Http $request
) {
$this->checkoutSession = $checkoutSession;
$this->giftRuleService = $giftRuleService;
$this->giftRuleCacheHelper = $giftRuleCacheHelper;
$this->giftRuleConfigHelper = $giftRuleConfigHelper;
$this->giftRuleHelper = $giftRuleHelper;
$this->quoteRepository = $quoteRepository;
$this->request = $request;
}
Expand Down Expand Up @@ -148,6 +157,12 @@ public function execute(Observer $observer)
}
}

$numberOfferedProduct = $this->giftRuleHelper->getNumberOfferedProduct(
$quote,
$giftRuleData[GiftRuleCacheHelper::DATA_MAXIMUM_NUMBER_PRODUCT],
$giftRuleData[GiftRuleCacheHelper::DATA_PRICE_RANGE]
);

// If only 1 gift product available => add automatic gift product.
if ($this->giftRuleConfigHelper->isAutomaticAddEnabled() && count($giftItem) == 0 &&
count($giftRuleData[GiftRuleCacheHelper::DATA_PRODUCT_ITEMS]) == 1) {
Expand All @@ -156,7 +171,7 @@ public function execute(Observer $observer)
[
[
'id' => key($giftRuleData[GiftRuleCacheHelper::DATA_PRODUCT_ITEMS]),
'qty' => $giftRuleData[GiftRuleCacheHelper::DATA_NUMBER_OFFERED_PRODUCT],
'qty' => $numberOfferedProduct,
],
],
$giftRuleCode,
Expand All @@ -165,9 +180,9 @@ public function execute(Observer $observer)
$saveQuote = true;
}

if ($giftItemQty > $giftRuleData[GiftRuleCacheHelper::DATA_NUMBER_OFFERED_PRODUCT]) {
if ($giftItemQty > $numberOfferedProduct) {
// Delete gift item.
$qtyToDelete = $giftItemQty - $giftRuleData[GiftRuleCacheHelper::DATA_NUMBER_OFFERED_PRODUCT];
$qtyToDelete = $giftItemQty - $numberOfferedProduct;

foreach (array_reverse($giftItem) as $item) {
if ($item->getQty() > $qtyToDelete) {
Expand Down
84 changes: 0 additions & 84 deletions Observer/SetNumberOfferedProduct.php

This file was deleted.

12 changes: 6 additions & 6 deletions Plugin/Model/Rule/Metadata/ValueProviderPlugin.php
Expand Up @@ -86,17 +86,17 @@ public function afterGetMetadataValues(
];

$result['actions']['children']['maximum_number_product']['arguments']['data']['config'] = [
'value' => $extensionAttributes
? $extensionAttributes['gift_rule'][GiftRuleInterface::MAXIMUM_NUMBER_PRODUCT]
: '',
'value' => $extensionAttributes ?
$extensionAttributes['gift_rule'][GiftRuleInterface::MAXIMUM_NUMBER_PRODUCT] :
'',
'componentType' => Field::NAME,
'formElement' => Input::NAME,
];

$result['actions']['children']['price_range']['arguments']['data']['config'] = [
'value' => $extensionAttributes
? $extensionAttributes['gift_rule'][GiftRuleInterface::PRICE_RANGE]
: '',
'value' => $extensionAttributes ?
$extensionAttributes['gift_rule'][GiftRuleInterface::PRICE_RANGE] :
'',
'componentType' => Field::NAME,
'formElement' => Input::NAME,
];
Expand Down
3 changes: 0 additions & 3 deletions etc/events.xml
Expand Up @@ -26,9 +26,6 @@
<event name="sales_quote_collect_totals_after">
<observer name="smile_gift_salesrule_collect_totals_after" instance="Smile\GiftSalesRule\Observer\CollectGiftRule"/>
</event>
<event name="smile_gift_sales_rule_gift_rule_load_after">
<observer name="smile_gift_salesrule_set_number_offered_product_after_load" instance="Smile\GiftSalesRule\Observer\SetNumberOfferedProduct"/>
</event>
<event name="sales_rules_skip_actions_validation">
<observer name="smile_gift_salesrule_set_skip_actions_validation" instance="Smile\GiftSalesRule\Observer\ValidateGiftRuleActions"/>
</event>
Expand Down

0 comments on commit 81d6bf3

Please sign in to comment.