/** * Processing object before save data * * @return $this */ protected function _beforeSave() { if (!$this->getRuleId() && $this->_rule instanceof \Magento\SalesRule\Model\Rule) { $this->setRuleId($this->_rule->getId()); } return parent::_beforeSave(); }
/** * Update auto generated Specific Coupon if it's rule changed * * @param \Magento\SalesRule\Model\Rule $rule * @return $this */ public function updateSpecificCoupons(\Magento\SalesRule\Model\Rule $rule) { if (!$rule || !$rule->getId() || !$rule->hasDataChanges()) { return $this; } $updateArray = []; if ($rule->dataHasChangedFor('uses_per_coupon')) { $updateArray['usage_limit'] = $rule->getUsesPerCoupon(); } if ($rule->dataHasChangedFor('uses_per_customer')) { $updateArray['usage_per_customer'] = $rule->getUsesPerCustomer(); } $ruleNewDate = $this->dateTime->formatDate($rule->getToDate()); $ruleOldDate = $this->dateTime->formatDate($rule->getOrigData('to_date')); if ($ruleNewDate != $ruleOldDate) { $updateArray['expiration_date'] = $rule->getToDate(); } if (!empty($updateArray)) { $this->getConnection()->update($this->getTable('salesrule_coupon'), $updateArray, ['rule_id = ?' => $rule->getId(), 'generated_by_dotmailer is null']); } //update coupons generated by dotmailer. not to change expiration date $dotmailerUpdateArray = $updateArray; unset($dotmailerUpdateArray['expiration_date']); if (!empty($dotmailerUpdateArray)) { $this->getConnection()->update($this->getTable('salesrule_coupon'), $dotmailerUpdateArray, ['rule_id = ?' => $rule->getId(), 'generated_by_dotmailer is 1']); } return $this; }
/** * @param \Magento\SalesRule\Model\Rule $rule * @param \Magento\Sales\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(); } if ($cartRules[$rule->getId()] > 0) { $store = $quote->getStore(); if ($ruleTotals['items_count'] <= 1) { $quoteAmount = $store->convertPrice($cartRules[$rule->getId()]); $baseDiscountAmount = min($baseItemPrice * $qty, $cartRules[$rule->getId()]); } else { $discountRate = $baseItemPrice * $qty / $ruleTotals['base_items_price']; $maximumItemDiscount = $rule->getDiscountAmount() * $discountRate; $quoteAmount = $store->convertPrice($maximumItemDiscount); $baseDiscountAmount = min($baseItemPrice * $qty, $maximumItemDiscount); $this->validator->decrementRuleItemTotalsCount($rule->getId()); } $baseDiscountAmount = $store->roundPrice($baseDiscountAmount); $cartRules[$rule->getId()] -= $baseDiscountAmount; $discountData->setAmount($store->roundPrice(min($itemPrice * $qty, $quoteAmount))); $discountData->setBaseAmount($baseDiscountAmount); $discountData->setOriginalAmount(min($itemOriginalPrice * $qty, $quoteAmount)); $discountData->setBaseOriginalAmount($store->roundPrice($baseItemOriginalPrice)); } $address->setCartFixedRules($cartRules); return $discountData; }
/** * Add rule to filter * * @param Rule|int $rule * @return $this */ public function addRuleToFilter($rule) { if ($rule instanceof Rule) { $ruleId = $rule->getId(); } else { $ruleId = (int) $rule; } $this->addFieldToFilter('rule_id', $ruleId); return $this; }
/** * Add rule discount description label to address object * * @param Address $address * @param \Magento\SalesRule\Model\Rule $rule * @return $this */ public function addDiscountDescription($address, $rule) { $description = $address->getDiscountDescriptionArray(); $ruleLabel = $rule->getStoreLabel($address->getQuote()->getStore()); $label = ''; if ($ruleLabel) { $label = $ruleLabel; } else { if (strlen($address->getCouponCode())) { $label = $address->getCouponCode(); } } if (strlen($label)) { $description[$rule->getId()] = $label; } $address->setDiscountDescriptionArray($description); return $this; }
/** * Set rule instance * * @param \Magento\SalesRule\Model\Rule $rule * @return $this */ public function setRule(\Magento\SalesRule\Model\Rule $rule) { $this->setRuleId($rule->getId()); return $this; }
/** * Check if rule can be applied for specific address/quote/customer * * @param \Magento\SalesRule\Model\Rule $rule * @param \Magento\Quote\Model\Quote\Address $address * @return bool * @SuppressWarnings(PHPMD.CyclomaticComplexity) * @SuppressWarnings(PHPMD.NPathComplexity) */ public function canProcessRule($rule, $address) { if ($rule->hasIsValidForAddress($address) && !$address->isObjectNew()) { return $rule->getIsValidForAddress($address); } /** * check per coupon usage limit */ if ($rule->getCouponType() != \Magento\SalesRule\Model\Rule::COUPON_TYPE_NO_COUPON) { $couponCode = $address->getQuote()->getCouponCode(); if (strlen($couponCode)) { /** @var \Magento\SalesRule\Model\Coupon $coupon */ $coupon = $this->couponFactory->create(); $coupon->load($couponCode, 'code'); if ($coupon->getId()) { // check entire usage limit if ($coupon->getUsageLimit() && $coupon->getTimesUsed() >= $coupon->getUsageLimit()) { $rule->setIsValidForAddress($address, false); return false; } // check per customer usage limit $customerId = $address->getQuote()->getCustomerId(); if ($customerId && $coupon->getUsagePerCustomer()) { $couponUsage = $this->objectFactory->create(); $this->usageFactory->create()->loadByCustomerCoupon($couponUsage, $customerId, $coupon->getId()); if ($couponUsage->getCouponId() && $couponUsage->getTimesUsed() >= $coupon->getUsagePerCustomer()) { $rule->setIsValidForAddress($address, false); return false; } } } } } /** * check per rule usage limit */ $ruleId = $rule->getId(); if ($ruleId && $rule->getUsesPerCustomer()) { $customerId = $address->getQuote()->getCustomerId(); /** @var \Magento\SalesRule\Model\Rule\Customer $ruleCustomer */ $ruleCustomer = $this->customerFactory->create(); $ruleCustomer->loadByCustomerRule($customerId, $ruleId); if ($ruleCustomer->getId()) { if ($ruleCustomer->getTimesUsed() >= $rule->getUsesPerCustomer()) { $rule->setIsValidForAddress($address, false); return false; } } } $rule->afterLoad(); /** * quote does not meet rule's conditions */ if (!$rule->validate($address)) { $rule->setIsValidForAddress($address, false); return false; } /** * passed all validations, remember to be valid */ $rule->setIsValidForAddress($address, true); return true; }
/** * Update auto generated Specific Coupon if it's rule changed * * @param \Magento\SalesRule\Model\Rule $rule * @return $this */ public function updateSpecificCoupons(\Magento\SalesRule\Model\Rule $rule) { if (!$rule || !$rule->getId() || !$rule->hasDataChanges()) { return $this; } $updateArray = []; if ($rule->dataHasChangedFor('uses_per_coupon')) { $updateArray['usage_limit'] = $rule->getUsesPerCoupon(); } if ($rule->dataHasChangedFor('uses_per_customer')) { $updateArray['usage_per_customer'] = $rule->getUsesPerCustomer(); } $ruleNewDate = new \DateTime($rule->getToDate()); $ruleOldDate = new \DateTime($rule->getOrigData('to_date')); if ($ruleNewDate != $ruleOldDate) { $updateArray['expiration_date'] = $rule->getToDate(); } if (!empty($updateArray)) { $this->getConnection()->update($this->getTable('salesrule_coupon'), $updateArray, ['rule_id = ?' => $rule->getId()]); } return $this; }
/** * Save product attributes currently used in conditions and actions of rule * * @param \Magento\SalesRule\Model\Rule $rule * @param mixed $attributes * @return $this */ public function setActualProductAttributes($rule, $attributes) { $connection = $this->getConnection(); $connection->delete($this->getTable('salesrule_product_attribute'), ['rule_id=?' => $rule->getId()]); //Getting attribute IDs for attribute codes $attributeIds = []; $select = $this->getConnection()->select()->from(['a' => $this->getTable('eav_attribute')], ['a.attribute_id'])->where('a.attribute_code IN (?)', [$attributes]); $attributesFound = $this->getConnection()->fetchAll($select); if ($attributesFound) { foreach ($attributesFound as $attribute) { $attributeIds[] = $attribute['attribute_id']; } $data = []; foreach ($rule->getCustomerGroupIds() as $customerGroupId) { foreach ($rule->getWebsiteIds() as $websiteId) { foreach ($attributeIds as $attribute) { $data[] = ['rule_id' => $rule->getId(), 'website_id' => $websiteId, 'customer_group_id' => $customerGroupId, 'attribute_id' => $attribute]; } } } $connection->insertMultiple($this->getTable('salesrule_product_attribute'), $data); } return $this; }
/** * {@inheritdoc} */ public function getId() { $pluginInfo = $this->pluginList->getNext($this->subjectType, 'getId'); if (!$pluginInfo) { return parent::getId(); } else { return $this->___callPlugins('getId', func_get_args(), $pluginInfo); } }
/** * Save product attributes currently used in conditions and actions of rule * * @param \Magento\SalesRule\Model\Rule $rule * @param mixed $attributes * @return $this */ public function setActualProductAttributes($rule, $attributes) { $write = $this->_getWriteAdapter(); $write->delete($this->getTable('salesrule_product_attribute'), array('rule_id=?' => $rule->getId())); //Getting attribute IDs for attribute codes $attributeIds = array(); $select = $this->_getReadAdapter()->select()->from(array('a' => $this->getTable('eav_attribute')), array('a.attribute_id'))->where('a.attribute_code IN (?)', array($attributes)); $attributesFound = $this->_getReadAdapter()->fetchAll($select); if ($attributesFound) { foreach ($attributesFound as $attribute) { $attributeIds[] = $attribute['attribute_id']; } $data = array(); foreach ($rule->getCustomerGroupIds() as $customerGroupId) { foreach ($rule->getWebsiteIds() as $websiteId) { foreach ($attributeIds as $attribute) { $data[] = array('rule_id' => $rule->getId(), 'website_id' => $websiteId, 'customer_group_id' => $customerGroupId, 'attribute_id' => $attribute); } } } $write->insertMultiple($this->getTable('salesrule_product_attribute'), $data); } return $this; }