Skip to content

Commit c63b388

Browse files
🔃 [Magento Community Engineering] Community Contributions - 2.3-develop expedited
Accepted Community Pull Requests: - #23387: #23386: Copy Service does not work properly for Entities which extends Data Object and implements ExtensibleDataInterface. (by @swnsma) - #20579: #12817: [Forwardport] Coupon code with canceled order. (by @p-bystritsky) Fixed GitHub Issues: - #23386: Copy Service does not works properly for Entities which extends Data Object and implements ExtensibleDataInterface (reported by @swnsma) has been fixed in #23387 by @swnsma in 2.3-develop branch Related commits: 1. 9852b08 2. d70edfc 3. 661874a 4. 731a4fc - #12817: Coupon code with canceled order (reported by @AleksLi) has been fixed in #20579 by @p-bystritsky in 2.3-develop branch Related commits: 1. 757856f 2. 378f03c 3. f02b0fa 4. 53abf95 5. 8f41977 6. 6f3362f
2 parents d200ae8 + 95e4a00 commit c63b388

File tree

16 files changed

+822
-402
lines changed

16 files changed

+822
-402
lines changed
Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
declare(strict_types=1);
7+
8+
namespace Magento\SalesRule\Model\Coupon;
9+
10+
use Magento\Sales\Model\Order;
11+
use Magento\SalesRule\Model\Coupon;
12+
use Magento\SalesRule\Model\ResourceModel\Coupon\Usage;
13+
use Magento\SalesRule\Model\Rule\CustomerFactory;
14+
use Magento\SalesRule\Model\RuleFactory;
15+
16+
/**
17+
* Updates the coupon usages.
18+
*/
19+
class UpdateCouponUsages
20+
{
21+
/**
22+
* @var RuleFactory
23+
*/
24+
private $ruleFactory;
25+
26+
/**
27+
* @var RuleFactory
28+
*/
29+
private $ruleCustomerFactory;
30+
31+
/**
32+
* @var Coupon
33+
*/
34+
private $coupon;
35+
36+
/**
37+
* @var Usage
38+
*/
39+
private $couponUsage;
40+
41+
/**
42+
* @param RuleFactory $ruleFactory
43+
* @param CustomerFactory $ruleCustomerFactory
44+
* @param Coupon $coupon
45+
* @param Usage $couponUsage
46+
*/
47+
public function __construct(
48+
RuleFactory $ruleFactory,
49+
CustomerFactory $ruleCustomerFactory,
50+
Coupon $coupon,
51+
Usage $couponUsage
52+
) {
53+
$this->ruleFactory = $ruleFactory;
54+
$this->ruleCustomerFactory = $ruleCustomerFactory;
55+
$this->coupon = $coupon;
56+
$this->couponUsage = $couponUsage;
57+
}
58+
59+
/**
60+
* Executes the current command.
61+
*
62+
* @param Order $subject
63+
* @param bool $increment
64+
* @return Order
65+
*/
66+
public function execute(Order $subject, bool $increment): Order
67+
{
68+
if (!$subject || !$subject->getAppliedRuleIds()) {
69+
return $subject;
70+
}
71+
// lookup rule ids
72+
$ruleIds = explode(',', $subject->getAppliedRuleIds());
73+
$ruleIds = array_unique($ruleIds);
74+
$customerId = (int)$subject->getCustomerId();
75+
// use each rule (and apply to customer, if applicable)
76+
foreach ($ruleIds as $ruleId) {
77+
if (!$ruleId) {
78+
continue;
79+
}
80+
$this->updateRuleUsages($increment, (int)$ruleId, $customerId);
81+
}
82+
$this->updateCouponUsages($subject, $increment, $customerId);
83+
84+
return $subject;
85+
}
86+
87+
/**
88+
* Update the number of rule usages.
89+
*
90+
* @param bool $increment
91+
* @param int $ruleId
92+
* @param int $customerId
93+
*/
94+
private function updateRuleUsages(bool $increment, int $ruleId, int $customerId)
95+
{
96+
/** @var \Magento\SalesRule\Model\Rule $rule */
97+
$rule = $this->ruleFactory->create();
98+
$rule->load($ruleId);
99+
if ($rule->getId()) {
100+
$rule->loadCouponCode();
101+
if ($increment || $rule->getTimesUsed() > 0) {
102+
$rule->setTimesUsed($rule->getTimesUsed() + ($increment ? 1 : -1));
103+
$rule->save();
104+
}
105+
if ($customerId) {
106+
$this->updateCustomerRuleUsages($increment, $ruleId, $customerId);
107+
}
108+
}
109+
}
110+
111+
/**
112+
* Update the number of rule usages per customer.
113+
*
114+
* @param bool $increment
115+
* @param int $ruleId
116+
* @param int $customerId
117+
*/
118+
private function updateCustomerRuleUsages(bool $increment, int $ruleId, int $customerId): void
119+
{
120+
/** @var \Magento\SalesRule\Model\Rule\Customer $ruleCustomer */
121+
$ruleCustomer = $this->ruleCustomerFactory->create();
122+
$ruleCustomer->loadByCustomerRule($customerId, $ruleId);
123+
if ($ruleCustomer->getId()) {
124+
if ($increment || $ruleCustomer->getTimesUsed() > 0) {
125+
$ruleCustomer->setTimesUsed($ruleCustomer->getTimesUsed() + ($increment ? 1 : -1));
126+
}
127+
} elseif ($increment) {
128+
$ruleCustomer->setCustomerId($customerId)->setRuleId($ruleId)->setTimesUsed(1);
129+
}
130+
$ruleCustomer->save();
131+
}
132+
133+
/**
134+
* Update the number of coupon usages.
135+
*
136+
* @param Order $subject
137+
* @param bool $increment
138+
* @param int $customerId
139+
*/
140+
private function updateCouponUsages(Order $subject, bool $increment, int $customerId): void
141+
{
142+
$this->coupon->load($subject->getCouponCode(), 'code');
143+
if ($this->coupon->getId()) {
144+
if ($increment || $this->coupon->getTimesUsed() > 0) {
145+
$this->coupon->setTimesUsed($this->coupon->getTimesUsed() + ($increment ? 1 : -1));
146+
$this->coupon->save();
147+
}
148+
if ($customerId) {
149+
$this->couponUsage->updateCustomerCouponTimesUsed($customerId, $this->coupon->getId(), $increment);
150+
}
151+
}
152+
}
153+
}

app/code/Magento/SalesRule/Model/ResourceModel/Coupon/Usage.php

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,10 @@ protected function _construct()
2727
*
2828
* @param int $customerId
2929
* @param mixed $couponId
30+
* @param bool $increment
3031
* @return void
3132
*/
32-
public function updateCustomerCouponTimesUsed($customerId, $couponId)
33+
public function updateCustomerCouponTimesUsed($customerId, $couponId, $increment = true): void
3334
{
3435
$connection = $this->getConnection();
3536
$select = $connection->select();
@@ -44,13 +45,13 @@ public function updateCustomerCouponTimesUsed($customerId, $couponId)
4445

4546
$timesUsed = $connection->fetchOne($select, [':coupon_id' => $couponId, ':customer_id' => $customerId]);
4647

47-
if ($timesUsed > 0) {
48+
if ($timesUsed !== false) {
4849
$this->getConnection()->update(
4950
$this->getMainTable(),
50-
['times_used' => $timesUsed + 1],
51+
['times_used' => $timesUsed + ($increment ? 1 : -1)],
5152
['coupon_id = ?' => $couponId, 'customer_id = ?' => $customerId]
5253
);
53-
} else {
54+
} elseif ($increment) {
5455
$this->getConnection()->insert(
5556
$this->getMainTable(),
5657
['coupon_id' => $couponId, 'customer_id' => $customerId, 'times_used' => 1]

app/code/Magento/SalesRule/Observer/SalesOrderAfterPlaceObserver.php

Lines changed: 0 additions & 110 deletions
This file was deleted.
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
declare(strict_types=1);
7+
8+
namespace Magento\SalesRule\Plugin;
9+
10+
use Magento\Sales\Model\Order;
11+
use Magento\SalesRule\Model\Coupon\UpdateCouponUsages;
12+
13+
/**
14+
* Decrements number of coupon usages after cancelling order.
15+
*/
16+
class CouponUsagesDecrement
17+
{
18+
/**
19+
* @var UpdateCouponUsages
20+
*/
21+
private $updateCouponUsages;
22+
23+
/**
24+
* @param UpdateCouponUsages $updateCouponUsages
25+
*/
26+
public function __construct(
27+
UpdateCouponUsages $updateCouponUsages
28+
) {
29+
$this->updateCouponUsages = $updateCouponUsages;
30+
}
31+
32+
/**
33+
* Decrements number of coupon usages after cancelling order.
34+
*
35+
* @param Order $subject
36+
* @param callable $proceed
37+
* @return Order
38+
*/
39+
public function aroundCancel(Order $subject, callable $proceed): Order
40+
{
41+
$canCancel = $subject->canCancel();
42+
$returnValue = $proceed();
43+
if ($canCancel) {
44+
$returnValue = $this->updateCouponUsages->execute($returnValue, false);
45+
}
46+
47+
return $returnValue;
48+
}
49+
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
declare(strict_types=1);
7+
8+
namespace Magento\SalesRule\Plugin;
9+
10+
use Magento\Sales\Model\Order;
11+
use Magento\SalesRule\Model\Coupon\UpdateCouponUsages;
12+
13+
/**
14+
* Increments number of coupon usages after placing order.
15+
*/
16+
class CouponUsagesIncrement
17+
{
18+
/**
19+
* @var UpdateCouponUsages
20+
*/
21+
private $updateCouponUsages;
22+
23+
/**
24+
* @param UpdateCouponUsages $updateCouponUsages
25+
*/
26+
public function __construct(
27+
UpdateCouponUsages $updateCouponUsages
28+
) {
29+
$this->updateCouponUsages = $updateCouponUsages;
30+
}
31+
32+
/**
33+
* Increments number of coupon usages after placing order.
34+
*
35+
* @param Order $subject
36+
* @param Order $result
37+
* @return Order
38+
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
39+
*/
40+
public function afterPlace(Order $subject, Order $result): Order
41+
{
42+
$this->updateCouponUsages->execute($subject, true);
43+
44+
return $subject;
45+
}
46+
}

0 commit comments

Comments
 (0)