123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155 |
- <?php
- /**
- * Copyright © Magento, Inc. All rights reserved.
- * See COPYING.txt for license details.
- */
- namespace Magento\SalesRule\Model\Rule\Action\Discount;
- use Magento\Framework\Pricing\PriceCurrencyInterface;
- use Magento\SalesRule\Model\DeltaPriceRound;
- use Magento\SalesRule\Model\Validator;
- /**
- * Calculates discount for cart item if fixed discount applied on whole cart.
- */
- class CartFixed extends AbstractDiscount
- {
- /**
- * Store information about addresses which cart fixed rule applied for
- *
- * @var int[]
- */
- protected $_cartFixedRuleUsedForAddress = [];
- /**
- * @var DeltaPriceRound
- */
- private $deltaPriceRound;
- /**
- * @var string
- */
- private static $discountType = 'CartFixed';
- /**
- * @param Validator $validator
- * @param DataFactory $discountDataFactory
- * @param PriceCurrencyInterface $priceCurrency
- * @param DeltaPriceRound $deltaPriceRound
- */
- public function __construct(
- Validator $validator,
- DataFactory $discountDataFactory,
- PriceCurrencyInterface $priceCurrency,
- DeltaPriceRound $deltaPriceRound
- ) {
- $this->deltaPriceRound = $deltaPriceRound;
- parent::__construct($validator, $discountDataFactory, $priceCurrency);
- }
- /**
- * Fixed discount for cart calculation
- *
- * @param \Magento\SalesRule\Model\Rule $rule
- * @param \Magento\Quote\Model\Quote\Item\AbstractItem $item
- * @param float $qty
- * @return \Magento\SalesRule\Model\Rule\Action\Discount\Data
- */
- public function calculate($rule, $item, $qty)
- {
- /** @var \Magento\SalesRule\Model\Rule\Action\Discount\Data $discountData */
- $discountData = $this->discountFactory->create();
- $ruleTotals = $this->validator->getRuleItemTotalsInfo($rule->getId());
- $quote = $item->getQuote();
- $address = $item->getAddress();
- $itemPrice = $this->validator->getItemPrice($item);
- $baseItemPrice = $this->validator->getItemBasePrice($item);
- $itemOriginalPrice = $this->validator->getItemOriginalPrice($item);
- $baseItemOriginalPrice = $this->validator->getItemBaseOriginalPrice($item);
- /**
- * prevent applying whole cart discount for every shipping order, but only for first order
- */
- if ($quote->getIsMultiShipping()) {
- $usedForAddressId = $this->getCartFixedRuleUsedForAddress($rule->getId());
- if ($usedForAddressId && $usedForAddressId != $address->getId()) {
- return $discountData;
- } else {
- $this->setCartFixedRuleUsedForAddress($rule->getId(), $address->getId());
- }
- }
- $cartRules = $address->getCartFixedRules();
- if (!isset($cartRules[$rule->getId()])) {
- $cartRules[$rule->getId()] = $rule->getDiscountAmount();
- }
- $availableDiscountAmount = (float)$cartRules[$rule->getId()];
- $discountType = self::$discountType . $rule->getId();
- if ($availableDiscountAmount > 0) {
- $store = $quote->getStore();
- if ($ruleTotals['items_count'] <= 1) {
- $quoteAmount = $this->priceCurrency->convert($availableDiscountAmount, $store);
- $baseDiscountAmount = min($baseItemPrice * $qty, $availableDiscountAmount);
- $this->deltaPriceRound->reset($discountType);
- } else {
- $ratio = $baseItemPrice * $qty / $ruleTotals['base_items_price'];
- $maximumItemDiscount = $this->deltaPriceRound->round(
- $rule->getDiscountAmount() * $ratio,
- $discountType
- );
- $quoteAmount = $this->priceCurrency->convert($maximumItemDiscount, $store);
- $baseDiscountAmount = min($baseItemPrice * $qty, $maximumItemDiscount);
- $this->validator->decrementRuleItemTotalsCount($rule->getId());
- }
- $baseDiscountAmount = $this->priceCurrency->round($baseDiscountAmount);
- $availableDiscountAmount -= $baseDiscountAmount;
- $cartRules[$rule->getId()] = $availableDiscountAmount;
- if ($availableDiscountAmount <= 0) {
- $this->deltaPriceRound->reset($discountType);
- }
- $discountData->setAmount($this->priceCurrency->round(min($itemPrice * $qty, $quoteAmount)));
- $discountData->setBaseAmount($baseDiscountAmount);
- $discountData->setOriginalAmount(min($itemOriginalPrice * $qty, $quoteAmount));
- $discountData->setBaseOriginalAmount($this->priceCurrency->round($baseItemOriginalPrice));
- }
- $address->setCartFixedRules($cartRules);
- return $discountData;
- }
- /**
- * Set information about usage cart fixed rule by quote address
- *
- * @param int $ruleId
- * @param int $itemId
- * @return void
- */
- protected function setCartFixedRuleUsedForAddress($ruleId, $itemId)
- {
- $this->_cartFixedRuleUsedForAddress[$ruleId] = $itemId;
- }
- /**
- * Retrieve information about usage cart fixed rule by quote address
- *
- * @param int $ruleId
- * @return int|null
- */
- protected function getCartFixedRuleUsedForAddress($ruleId)
- {
- if (isset($this->_cartFixedRuleUsedForAddress[$ruleId])) {
- return $this->_cartFixedRuleUsedForAddress[$ruleId];
- }
- return null;
- }
- }
|