PluginProbe
FluentCart A New Era of eCommerce – Faster, Lighter, and Simpler / 1.3.25
FluentCart A New Era of eCommerce – Faster, Lighter, and Simpler v1.3.25
1.6.6 1.6.5 1.6.4 1.6.3 1.6.2 1.6.1 1.6.0 1.5.4 1.5.5 1.5.3 1.5.2 1.5.1 1.5.0 1.4.2 1.4.1 1.4.0 1.3.28 1.3.27 1.3.26 1.3.25 1.3.23 1.3.22 1.3.21 1.3.20 1.3.19 All 49 releases
fluent-cart / app / Services / Coupon / CouponServiceAdmin.php

CouponServiceAdmin.php in FluentCart A New Era of eCommerce – Faster, Lighter, and Simpler 1.3.25, at app/Services/Coupon/CouponServiceAdmin.php

209 lines 6.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace FluentCart\App\Services\Coupon;
4
5 use FluentCart\App\Models\Coupon;
6 use FluentCart\App\Models\Product;
7 use FluentCart\App\Services\Coupon\Concerns\CanCalculateLineTotal;
8 use FluentCart\App\Services\Coupon\Concerns\CanValidateCoupon;
9 use FluentCart\Framework\Support\Collection;
10 use WP_Error;
11
12 /*
13 * Class CouponService was removed as all coupon logic goes to DiscountService.php
14 * we had to bring it back and make it as CouponServiceAdmin
15 *
16 * @devnotes: for admin order this is used to apply/cancel/reapply coupons.
17 * we may refactore this later
18 */
19
20 class CouponServiceAdmin
21 {
22 use CanValidateCoupon, CanCalculateLineTotal;
23
24 protected ?Collection $previouslyAppliedCoupons;
25 protected array $previouslyAppliedCouponCodes = [];
26 protected ?Collection $applicableCoupons;
27 protected ?Collection $appliedCoupons;
28 protected array $applicableCouponCodes = [];
29 protected array $cancelableCouponCodes = [];
30 protected array $productIds = [];
31 protected ?Collection $products;
32 protected array $lineItems = [];
33 protected array $calculatedLineItems = [];
34 protected bool $usingCart = true;
35 protected ?Collection $couponErrors = null;
36
37
38 /**
39 * @param array $lineItems
40 * @param ?Collection $previouslyAppliedCoupons
41 * @param bool $usingCart
42 */
43 public function __construct(array $lineItems = [], ?Collection $previouslyAppliedCoupons = null, $applicableCouponCodes = [])
44 {
45 $this->appliedCoupons = $previouslyAppliedCoupons;
46 $this->couponErrors = new Collection();
47
48 //Set Data from the parameters
49 $this->lineItems = $lineItems;
50 $this->previouslyAppliedCoupons = $previouslyAppliedCoupons === null ? new Collection() : $previouslyAppliedCoupons->keyBy('code');
51
52 $this->previouslyAppliedCouponCodes = $this->previouslyAppliedCoupons->pluck('code')->toArray();
53 $this->applicableCouponCodes = array_merge($this->applicableCouponCodes, $applicableCouponCodes);
54 $this->init();
55 }
56
57 private function init()
58 {
59 $this->calculatedLineItems = $this->lineItems;
60 $this->productIds = (new Collection($this->lineItems))
61 ->pluck('post_id')
62 ->toArray();
63
64 $this->productIds = array_unique($this->productIds);
65 $this->products = Product::query()
66 ->select('ID')
67 ->whereIn('ID', $this->productIds)
68 ->with('categories')
69 ->get()
70 ->keyBy('ID');
71 }
72
73
74 public function initializeCoupons(array $couponCodes = [])
75 {
76 $originalOrder = array_unique($this->applicableCouponCodes);
77
78 //Remove the cancelable code from the applicable coupon codes;
79 $this->applicableCouponCodes = array_merge(
80 $this->previouslyAppliedCouponCodes,
81 $this->applicableCouponCodes,
82 $couponCodes
83 );
84
85 $this->applicableCouponCodes = array_unique($this->applicableCouponCodes);
86
87 $orderMap = array_flip($originalOrder); // ['d' => 0, 'b' => 1, 'a' => 2]
88
89 usort($this->applicableCouponCodes, function ($a, $b) use ($orderMap) {
90 $indexA = $orderMap[$a] ?? PHP_INT_MAX;
91 $indexB = $orderMap[$b] ?? PHP_INT_MAX;
92 return $indexA <=> $indexB;
93 });
94
95 //Remove from the collection list if it should be canceled.
96 foreach ($this->cancelableCouponCodes as $couponCode) {
97 $this->applicableCouponCodes = array_diff($this->applicableCouponCodes, [$couponCode]);
98 }
99
100 if (empty($this->applicableCouponCodes)) {
101 $this->applicableCoupons = new Collection();
102 } else {
103 $this->applicableCoupons = $this->populateCouponsFromModel($this->applicableCouponCodes);
104 }
105
106
107 $sortedCoupons = new Collection();
108 foreach ($this->applicableCouponCodes as $couponCode) {
109 if ($this->applicableCoupons->has($couponCode)) {
110 $sortedCoupons->put($couponCode, $this->applicableCoupons->get($couponCode));
111 }
112 }
113
114 $this->applicableCoupons = $sortedCoupons;
115
116 $this->appliedCoupons = $this->appliedCoupons ?? new Collection();
117 $this->appliedCoupons = $this->appliedCoupons->keyBy('code');
118 $appliedCoupons = $this->appliedCoupons;
119
120 $this->applicableCoupons = $this->applicableCoupons->map(function ($coupon) use ($appliedCoupons) {
121 if ($appliedCoupons->has($coupon->code)) {
122 $data = $appliedCoupons->get($coupon->code);
123 $data['id'] = $coupon->id;
124
125 return $this->populateCouponFromArray($data);
126 }
127
128 return $coupon;
129 });
130
131 $this->applicableCouponCodes = $this->applicableCoupons->keys()->toArray();
132
133 }
134
135 public function getCouponErrors(): ?Collection
136 {
137 return $this->couponErrors;
138 }
139
140 protected function populateCouponFromArray($data): Coupon
141 {
142 $coupon = new Coupon();
143 $coupon->fill($data);
144 $coupon->id = $data['id'];
145 return $coupon;
146 }
147
148 protected function populateCouponsFromModel($couponCodes = [], $model = Coupon::class)
149 {
150 return $model::query()
151 ->whereIn('code', $couponCodes) // Lowercase the array for comparison
152 ->orderBy('priority')//Order by is important here
153 ->get()
154 ->keyBy('code');
155 }
156
157 public function applyCoupon(string $couponCode): ?WP_Error
158 {
159 return $this->apply([$couponCode]);
160 }
161
162 protected function apply(array $couponCodes = []): ?WP_Error
163 {
164 $this->initializeCoupons($couponCodes);
165 $this->calculateLineItems();
166 return null;
167 }
168
169 public function getCalculatedLineItems(): array
170 {
171 return $this->calculatedLineItems;
172 }
173
174 public function cancelCoupon(string $couponCode)
175 {
176 $this->cancelableCouponCodes = array_merge(
177 $this->cancelableCouponCodes,
178 [$couponCode]
179 );
180
181 $this->initializeCoupons();
182 $this->calculateLineItems();
183 }
184
185 public function reapplyCoupons()
186 {
187 $this->initializeCoupons();
188 $this->calculateLineItems();
189 }
190
191 protected function ensureCouponExistInDiscountData(Coupon $coupon)
192 {
193 if (empty($this->discountData[$coupon->code])) {
194 $this->discountData[$coupon->code] = [
195 'id' => $coupon->id,
196 'title' => $coupon->title,
197 'amount' => 0,
198 'formatted_discount' => '',
199 'unit_amount' => 0,
200 'actual_quantity' => 0,
201 'discount' => 0,
202 'type' => $coupon->type,
203 'actual_amount' => $coupon->amount,
204 ];
205 }
206 }
207
208 }
209