Magento 2 Documentation  2.3
Documentation for Magento 2 CMS v2.3 (December 2018)
Utility.php
Go to the documentation of this file.
1 <?php
8 
10 
16 class Utility
17 {
21  protected $_roundingDeltas = [];
22 
26  protected $_baseRoundingDeltas = [];
27 
31  protected $usageFactory;
32 
36  protected $couponFactory;
37 
41  protected $customerFactory;
42 
46  protected $objectFactory;
47 
51  protected $priceCurrency;
52 
60  public function __construct(
61  \Magento\SalesRule\Model\ResourceModel\Coupon\UsageFactory $usageFactory,
62  \Magento\SalesRule\Model\CouponFactory $couponFactory,
63  \Magento\SalesRule\Model\Rule\CustomerFactory $customerFactory,
64  \Magento\Framework\DataObjectFactory $objectFactory,
66  ) {
67  $this->couponFactory = $couponFactory;
68  $this->customerFactory = $customerFactory;
69  $this->usageFactory = $usageFactory;
70  $this->objectFactory = $objectFactory;
71  $this->priceCurrency = $priceCurrency;
72  }
73 
83  public function canProcessRule($rule, $address)
84  {
85  if ($rule->hasIsValidForAddress($address) && !$address->isObjectNew()) {
86  return $rule->getIsValidForAddress($address);
87  }
88 
93  $couponCode = $address->getQuote()->getCouponCode();
94  if (strlen($couponCode)) {
96  $coupon = $this->couponFactory->create();
97  $coupon->load($couponCode, 'code');
98  if ($coupon->getId()) {
99  // check entire usage limit
100  if ($coupon->getUsageLimit() && $coupon->getTimesUsed() >= $coupon->getUsageLimit()) {
101  $rule->setIsValidForAddress($address, false);
102  return false;
103  }
104  // check per customer usage limit
105  $customerId = $address->getQuote()->getCustomerId();
106  if ($customerId && $coupon->getUsagePerCustomer()) {
107  $couponUsage = $this->objectFactory->create();
108  $this->usageFactory->create()->loadByCustomerCoupon(
109  $couponUsage,
110  $customerId,
111  $coupon->getId()
112  );
113  if ($couponUsage->getCouponId() &&
114  $couponUsage->getTimesUsed() >= $coupon->getUsagePerCustomer()
115  ) {
116  $rule->setIsValidForAddress($address, false);
117  return false;
118  }
119  }
120  }
121  }
122  }
123 
127  $ruleId = $rule->getId();
128  if ($ruleId && $rule->getUsesPerCustomer()) {
129  $customerId = $address->getQuote()->getCustomerId();
131  $ruleCustomer = $this->customerFactory->create();
132  $ruleCustomer->loadByCustomerRule($customerId, $ruleId);
133  if ($ruleCustomer->getId()) {
134  if ($ruleCustomer->getTimesUsed() >= $rule->getUsesPerCustomer()) {
135  $rule->setIsValidForAddress($address, false);
136  return false;
137  }
138  }
139  }
140  $rule->afterLoad();
144  if (!$rule->validate($address)) {
145  $rule->setIsValidForAddress($address, false);
146  return false;
147  }
151  $rule->setIsValidForAddress($address, true);
152  return true;
153  }
154 
161  public function minFix(
162  \Magento\SalesRule\Model\Rule\Action\Discount\Data $discountData,
164  $qty
165  ) {
166  $itemPrice = $this->getItemPrice($item);
167  $baseItemPrice = $this->getItemBasePrice($item);
168 
169  $itemDiscountAmount = $item->getDiscountAmount();
170  $itemBaseDiscountAmount = $item->getBaseDiscountAmount();
171 
172  $discountAmount = min($itemDiscountAmount + $discountData->getAmount(), $itemPrice * $qty);
173  $baseDiscountAmount = min($itemBaseDiscountAmount + $discountData->getBaseAmount(), $baseItemPrice * $qty);
174 
175  $discountData->setAmount($discountAmount);
176  $discountData->setBaseAmount($baseDiscountAmount);
177  }
178 
186  public function deltaRoundingFix(
187  \Magento\SalesRule\Model\Rule\Action\Discount\Data $discountData,
189  ) {
190  $discountAmount = $discountData->getAmount();
191  $baseDiscountAmount = $discountData->getBaseAmount();
192  $rowTotalInclTax = $item->getRowTotalInclTax();
193  $baseRowTotalInclTax = $item->getBaseRowTotalInclTax();
194 
195  //TODO Seems \Magento\Quote\Model\Quote\Item\AbstractItem::getDiscountPercent() returns float value
196  //that can not be used as array index
197  $percentKey = $item->getDiscountPercent();
198  if ($percentKey) {
199  $delta = isset($this->_roundingDeltas[$percentKey]) ? $this->_roundingDeltas[$percentKey] : 0;
200  $baseDelta = isset($this->_baseRoundingDeltas[$percentKey]) ? $this->_baseRoundingDeltas[$percentKey] : 0;
201 
202  $discountAmount += $delta;
203  $baseDiscountAmount += $baseDelta;
204 
205  $this->_roundingDeltas[$percentKey] = $discountAmount - $this->priceCurrency->round($discountAmount);
206  $this->_baseRoundingDeltas[$percentKey] = $baseDiscountAmount
207  - $this->priceCurrency->round($baseDiscountAmount);
208  }
209 
214  if ($percentKey == 100) {
215  $discountDelta = $rowTotalInclTax - $discountAmount;
216  $baseDiscountDelta = $baseRowTotalInclTax - $baseDiscountAmount;
217 
218  if ($discountDelta < 0) {
219  $discountAmount += $discountDelta;
220  }
221 
222  if ($baseDiscountDelta < 0) {
223  $baseDiscountAmount += $baseDiscountDelta;
224  }
225  }
226 
227  $discountData->setAmount($this->priceCurrency->round($discountAmount));
228  $discountData->setBaseAmount($this->priceCurrency->round($baseDiscountAmount));
229 
230  return $this;
231  }
232 
239  public function getItemPrice($item)
240  {
241  $price = $item->getDiscountCalculationPrice();
242  $calcPrice = $item->getCalculationPrice();
243  return $price === null ? $calcPrice : $price;
244  }
245 
252  public function getItemBasePrice($item)
253  {
254  $price = $item->getDiscountCalculationPrice();
255  return $price !== null ? $item->getBaseDiscountCalculationPrice() : $item->getBaseCalculationPrice();
256  }
257 
265  public function getItemQty($item, $rule)
266  {
267  $qty = $item->getTotalQty();
268  $discountQty = $rule->getDiscountQty();
269  return $discountQty ? min($qty, $discountQty) : $qty;
270  }
271 
280  public function mergeIds($a1, $a2, $asString = true)
281  {
282  if (!is_array($a1)) {
283  $a1 = empty($a1) ? [] : explode(',', $a1);
284  }
285  if (!is_array($a2)) {
286  $a2 = empty($a2) ? [] : explode(',', $a2);
287  }
288  $a = array_unique(array_merge($a1, $a2));
289  if ($asString) {
290  $a = implode(',', $a);
291  }
292  return $a;
293  }
294 
298  public function resetRoundingDeltas()
299  {
300  $this->_roundingDeltas = [];
301  $this->_baseRoundingDeltas = [];
302  }
303 }
$coupon
__construct(\Magento\SalesRule\Model\ResourceModel\Coupon\UsageFactory $usageFactory, \Magento\SalesRule\Model\CouponFactory $couponFactory, \Magento\SalesRule\Model\Rule\CustomerFactory $customerFactory, \Magento\Framework\DataObjectFactory $objectFactory, PriceCurrencyInterface $priceCurrency)
Definition: Utility.php:60
$price
$address
Definition: customer.php:38
deltaRoundingFix(\Magento\SalesRule\Model\Rule\Action\Discount\Data $discountData, \Magento\Quote\Model\Quote\Item\AbstractItem $item)
Definition: Utility.php:186
mergeIds($a1, $a2, $asString=true)
Definition: Utility.php:280
minFix(\Magento\SalesRule\Model\Rule\Action\Discount\Data $discountData, \Magento\Quote\Model\Quote\Item\AbstractItem $item, $qty)
Definition: Utility.php:161