PluginProbe
AliNext – WooCommerce Dropshipping Plugin for AliExpress / trunk
AliNext – WooCommerce Dropshipping Plugin for AliExpress vtrunk
ali2woo-lite / includes / classes / service / PriceFormulaService.php

PriceFormulaService.php in AliNext – WooCommerce Dropshipping Plugin for AliExpress trunk, at includes/classes/service/PriceFormulaService.php

378 lines 20.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 /**
4 * Description of PermanentAlert
5 *
6 * @author Ali2Woo Team
7 */
8
9 namespace AliNext_Lite;;
10
11 class PriceFormulaService
12 {
13 protected PriceFormulaRepository $PriceFormulaRepository;
14 protected PriceFormulaSettingsRepository $PriceFormulaSettingsRepository;
15
16 public const REGULAR_PRICE_AS_BASE = 'regular_price_as_base';
17 public const SALE_PRICE_AS_BASE = 'sale_price_as_base';
18 public const SALE_PRICE_AND_DISCOUNT = 'sale_price_and_discount';
19
20 public function __construct(
21 PriceFormulaRepository $PriceFormulaRepository, PriceFormulaSettingsRepository $PriceFormulaSettingsRepository
22 ) {
23 $this->PriceFormulaRepository = $PriceFormulaRepository;
24 $this->PriceFormulaSettingsRepository = $PriceFormulaSettingsRepository;
25 }
26
27 public function applyFormula(array $product, int $round = 2, string $applyFormulaTo = PriceFormula::TYPE_ALL): array
28 {
29 $pricing_rules_type = $this->PriceFormulaSettingsRepository->getPricingRulesType();
30 //todo: add this method to the test
31 $apply_price_rules_after_shipping_cost = $this->PriceFormulaSettingsRepository
32 ->getApplyPriceRulesAfterShippingCost();
33
34 $shipping_cost = 0;
35 //todo: add this method to the test
36 if ($this->PriceFormulaSettingsRepository->getAddShippingToPrice() && !empty($product[ImportedProductService::FIELD_COST])) {
37 $shipping_cost = round($product[ImportedProductService::FIELD_COST], $round);
38 }
39
40 if ($this->PriceFormulaSettingsRepository->getUseSeparateFormula()) {
41 $formula = $this->getFormulaByProduct($product, PriceFormula::TYPE_PRICE);
42 $formula_regular = $this->getFormulaByProduct($product, PriceFormula::TYPE_REGULAR_PRICE);
43 } else {
44 $price_type = $pricing_rules_type == self::REGULAR_PRICE_AS_BASE ?
45 PriceFormula::TYPE_REGULAR_PRICE :
46 PriceFormula::TYPE_PRICE;
47
48 $formula = $this->getFormulaByProduct($product, $price_type);
49 $formula_regular = $this->getFormulaByProduct($product, $price_type);
50 }
51
52 $product_price = $this->normalizeProductPrice($product);
53 if ($formula && $formula_regular && $product_price['price']) {
54 $use_compared_price_markup = $this->PriceFormulaSettingsRepository->getUseComparedPriceMarkup();
55 $price_cents = $this->PriceFormulaSettingsRepository->getPriceCents();
56 $price_compared_cents = $this->PriceFormulaSettingsRepository->getPriceComparedCents();
57 if ($applyFormulaTo === PriceFormula::TYPE_ALL || $applyFormulaTo === PriceFormula::TYPE_PRICE || !isset($product['calc_price'])) {
58 // calculate price
59 $price = $pricing_rules_type == self::REGULAR_PRICE_AS_BASE ?
60 $product_price['regular_price'] :
61 $product_price['price'];
62
63 if ($formula->sign == "=") {
64 $product['calc_price'] = round(floatval($formula->value) + $shipping_cost, $round);
65 } else if ($formula->sign == "*") {
66 if ($apply_price_rules_after_shipping_cost) {
67 $product['calc_price'] = round((floatval($price) + $shipping_cost) * floatval($formula->value), $round);
68 } else {
69 $product['calc_price'] = round(floatval($price) * floatval($formula->value) + $shipping_cost, $round);
70 }
71 } else if ($formula->sign == "+") {
72 $product['calc_price'] = round(floatval($price) + $shipping_cost + floatval($formula->value), $round);
73 }
74
75 if (!empty($product['calc_price']) && $price_cents > -1) {
76 $product['calc_price'] = round(floor($product['calc_price']) + ($price_cents / 100), 2);
77 }
78 }
79
80 if ($applyFormulaTo === PriceFormula::TYPE_ALL || $applyFormulaTo === PriceFormula::TYPE_REGULAR_PRICE || !isset($product['calc_regular_price'])) {
81 // calculate regular_price
82 if ($pricing_rules_type == PriceFormulaService::SALE_PRICE_AND_DISCOUNT) {
83 // use source discount
84 if (isset($product['discount']) && isset($product['calc_price'])) {
85 $product['calc_regular_price'] = round($product['calc_price'] * 100 / (100 - min(99.9, floatval($product['discount']))), $round);
86 }
87
88 if ($use_compared_price_markup) {
89 if ($formula_regular->compared_sign == "=") {
90 $product['calc_regular_price'] = round(floatval($formula_regular->compared_value) + $shipping_cost, $round);
91 } else if ($formula_regular->compared_sign == "*") {
92 if ($apply_price_rules_after_shipping_cost) {
93 $product['calc_regular_price'] = round((floatval($product_price['price']) + $shipping_cost) * floatval($formula_regular->compared_value), $round);
94 } else {
95 $product['calc_regular_price'] = round(floatval($product_price['price']) * floatval($formula_regular->compared_value) + $shipping_cost, $round);
96 }
97 } else if ($formula_regular->compared_sign == "+") {
98 $product['calc_regular_price'] = round(floatval($product_price['price']) + $shipping_cost + floatval($formula_regular->compared_value), $round);
99 }
100 }
101
102 } else {
103 $price = $pricing_rules_type == self::REGULAR_PRICE_AS_BASE ?
104 $product_price['regular_price'] :
105 $product_price['price'];
106
107 if ($use_compared_price_markup) {
108 if ($formula_regular->compared_sign == "=") {
109 $product['calc_regular_price'] = round(floatval($formula_regular->compared_value) + $shipping_cost, $round);
110 } else if ($formula_regular->compared_sign == "*") {
111 if ($apply_price_rules_after_shipping_cost) {
112 $product['calc_regular_price'] = round((floatval($price) + $shipping_cost) * floatval($formula_regular->compared_value), $round);
113 } else {
114 $product['calc_regular_price'] = round(floatval($price) * floatval($formula_regular->compared_value) + $shipping_cost, $round);
115 }
116 } else if ($formula_regular->compared_sign == "+") {
117 $product['calc_regular_price'] = round(floatval($price) + $shipping_cost + floatval($formula_regular->compared_value), $round);
118 }
119 } else {
120 if ($formula_regular->sign == "=") {
121 $product['calc_regular_price'] = round(floatval($formula_regular->value) + $shipping_cost, $round);
122 } else if ($formula_regular->sign == "*") {
123 if ($apply_price_rules_after_shipping_cost) {
124 $product['calc_regular_price'] = round((floatval($price) + $shipping_cost) * floatval($formula_regular->value), $round);
125 } else {
126 $product['calc_regular_price'] = round(floatval($price) * floatval($formula_regular->value) + $shipping_cost, $round);
127 }
128 } else if ($formula_regular->sign == "+") {
129 $product['calc_regular_price'] = round(floatval($price) + $shipping_cost + floatval($formula_regular->value), $round);
130 }
131 }
132 }
133
134 if (!empty($product['calc_regular_price']) && $price_compared_cents > -1) {
135 $product['calc_regular_price'] = round(floor($product['calc_regular_price']) + ($price_compared_cents / 100), 2);
136 }
137
138 if (!empty($product['calc_regular_price']) && !empty($product['calc_price']) && $product['calc_regular_price'] < $product['calc_price']) {
139 $product['calc_regular_price'] = $product['calc_price'];
140 }
141 }
142
143 if (isset($product['sku_products']['variations']) && $product['sku_products']['variations']) {
144 foreach ($product['sku_products']['variations'] as &$var) {
145 if ($this->PriceFormulaSettingsRepository->getUseSeparateFormula()) {
146 $formula = $this->getFormulaByProduct($var, PriceFormula::TYPE_PRICE);
147 $formula_regular = $this->getFormulaByProduct($var, PriceFormula::TYPE_REGULAR_PRICE);
148 } else {
149 $price_type = $pricing_rules_type == self::REGULAR_PRICE_AS_BASE ?
150 PriceFormula::TYPE_REGULAR_PRICE :
151 PriceFormula::TYPE_PRICE;
152
153 $formula = $this->getFormulaByProduct($var, $price_type);
154 $formula_regular = $this->getFormulaByProduct($var, $price_type);
155 }
156
157 if ($formula && $formula_regular) {
158 if ($applyFormulaTo === PriceFormula::TYPE_ALL || $applyFormulaTo === PriceFormula::TYPE_PRICE || !isset($var['calc_price'])) {
159 // calculate price
160 $price = $pricing_rules_type == self::REGULAR_PRICE_AS_BASE ?
161 $var['regular_price'] :
162 $var['price'];
163
164 if ($formula->sign == "=") {
165 $var['calc_price'] = round(floatval($formula->value) + $shipping_cost, $round);
166 } else if ($formula->sign == "*") {
167 if ($apply_price_rules_after_shipping_cost) {
168 $var['calc_price'] = round((floatval($price) + $shipping_cost) * floatval($formula->value), $round);
169 } else {
170 $var['calc_price'] = round(floatval($price) * floatval($formula->value) + $shipping_cost, $round);
171 }
172 } else if ($formula->sign == "+") {
173 $var['calc_price'] = round(floatval($price) + $shipping_cost + floatval($formula->value), $round);
174 }
175
176 if (!empty($var['calc_price']) && $price_cents > -1) {
177 $var['calc_price'] = round(floor($var['calc_price']) + ($price_cents / 100), 2);
178 }
179 }
180
181 if ($applyFormulaTo === PriceFormula::TYPE_ALL || $applyFormulaTo === PriceFormula::TYPE_REGULAR_PRICE || !isset($var['calc_regular_price'])) {
182 // calculate regular_price
183 if ($pricing_rules_type == PriceFormulaService::SALE_PRICE_AND_DISCOUNT) {
184 // use source discount
185 if (isset($var['discount']) && isset($var['calc_price'])) {
186 $var['calc_regular_price'] = round($var['calc_price'] * 100 / (100 - min(99.9, floatval($var['discount']))), $round);
187 }
188 if ($use_compared_price_markup) {
189 if ($formula_regular->compared_sign == "=") {
190 $var['calc_regular_price'] = round(floatval($formula_regular->compared_value) + $shipping_cost, $round);
191 } else if ($formula_regular->compared_sign == "*") {
192 if ($apply_price_rules_after_shipping_cost) {
193 $var['calc_regular_price'] = round((floatval($var['price']) + $shipping_cost) * floatval($formula_regular->compared_value), $round);
194 } else {
195 $var['calc_regular_price'] = round(floatval($var['price']) * floatval($formula_regular->compared_value) + $shipping_cost, $round);
196 }
197 } else if ($formula_regular->compared_sign == "+") {
198 $var['calc_regular_price'] = round(floatval($var['price']) + $shipping_cost + floatval($formula_regular->compared_value), $round);
199 }
200 }
201
202 } else {
203 $price = $pricing_rules_type == self::REGULAR_PRICE_AS_BASE ?
204 $var['regular_price'] :
205 $var['price'];
206
207 if ($use_compared_price_markup) {
208 if ($formula_regular->compared_sign == "=") {
209 $var['calc_regular_price'] = round(floatval($formula_regular->compared_value) + $shipping_cost, $round);
210 } else if ($formula_regular->compared_sign == "*") {
211 if ($apply_price_rules_after_shipping_cost) {
212 $var['calc_regular_price'] = round((floatval($price) + $shipping_cost) * floatval($formula_regular->compared_value), $round);
213 } else {
214 $var['calc_regular_price'] = round(floatval($price) * floatval($formula_regular->compared_value) + $shipping_cost, $round);
215 }
216 } else if ($formula_regular->compared_sign == "+") {
217 $var['calc_regular_price'] = round(floatval($price) + $shipping_cost + floatval($formula_regular->compared_value), $round);
218 }
219 } else {
220 if ($formula_regular->sign == "=") {
221 $var['calc_regular_price'] = round(floatval($formula_regular->value) + $shipping_cost, $round);
222 } else if ($formula_regular->sign == "*") {
223 if ($apply_price_rules_after_shipping_cost) {
224 $var['calc_regular_price'] = round((floatval($price) + $shipping_cost) * floatval($formula_regular->value), $round);
225 } else {
226 $var['calc_regular_price'] = round(floatval($price) * floatval($formula_regular->value) + $shipping_cost, $round);
227 }
228 } else if ($formula_regular->sign == "+") {
229 $var['calc_regular_price'] = round(floatval($price) + $shipping_cost + floatval($formula_regular->value), $round);
230 }
231 }
232 }
233
234 $regular_price_cents = $use_compared_price_markup ? $price_compared_cents : $price_cents;
235 if (!empty($var['calc_regular_price']) && $regular_price_cents > -1) {
236 $var['calc_regular_price'] = round(floor($var['calc_regular_price']) + ($regular_price_cents / 100), 2);
237 }
238
239 if (!empty($var['calc_regular_price']) && !empty($var['calc_price']) && $var['calc_regular_price'] < $var['calc_price']) {
240 $var['calc_regular_price'] = $var['calc_price'];
241 }
242 }
243 }
244 }
245 }
246 }
247
248 return $product;
249 }
250
251 public function getFormulaByProduct(array $product, string $base_price_type = PriceFormula::TYPE_PRICE): PriceFormula
252 {
253 $res_formula = false;
254 $use_extended_price_markup = $this->PriceFormulaSettingsRepository->getUseExtendedPriceMarkup();
255
256 if ($use_extended_price_markup) {
257 $base_price_type = in_array($base_price_type, [PriceFormula::TYPE_PRICE, PriceFormula::TYPE_REGULAR_PRICE]) ?
258 $base_price_type : PriceFormula::TYPE_PRICE;
259
260 $product_price = $this->normalizeProductPrice($product);
261 $product_price = $product_price[$base_price_type];
262 if ($product_price) {
263 $GetExtendedFormulasGroupedResult = $this->PriceFormulaRepository->getExtendedFormulasGrouped();
264
265 $CategoryPriceFormula = $this->getCategoryFormulaByProduct(
266 $product, $product_price, $GetExtendedFormulasGroupedResult->getCategoryRules()
267 );
268
269 if (!is_null($CategoryPriceFormula)) {
270 return $CategoryPriceFormula;
271 }
272
273 $formula_list = $GetExtendedFormulasGroupedResult->getGlobalRules();
274
275 foreach ($formula_list as $PriceFormula) {
276 $check = true;
277
278 if (!is_null($PriceFormula->getMinPrice()) && $PriceFormula->getMinPrice() > $product_price) {
279 $check = false;
280 }
281
282 if (!is_null($PriceFormula->getMaxPrice()) && $PriceFormula->getMaxPrice() < $product_price) {
283 $check = false;
284 }
285
286 if (!is_null($PriceFormula->getCategory()) &&
287 $PriceFormula->getCategory() != intval($product['category_id'])
288 ) {
289 $check = false;
290 }
291
292 if ($check) {
293 $res_formula = $PriceFormula;
294 break;
295 }
296 }
297 } else {
298 a2wl_error_log("can't find normalize product price for " . $product[ImportedProductService::FIELD_EXTERNAL_PRODUCT_ID]);
299 }
300 }
301
302 return $res_formula ?: $this->PriceFormulaRepository->getDefaultFormula();
303 }
304
305 public function getCategoryFormulaByProduct(
306 array $product, float $testedProductPrice, array $PriceFormulasWithCategories
307 ): ?PriceFormula {
308
309 if (empty($PriceFormulasWithCategories)) {
310 return null;
311 }
312
313 if (empty($product['categories'])) {
314 return null;
315 }
316
317 $res_formula = false;
318
319 $formula_list = $PriceFormulasWithCategories;
320 foreach ($formula_list as $PriceFormula) {
321 $check = true;
322
323 if (!is_null($PriceFormula->getMinPrice()) && $PriceFormula->getMinPrice() > $testedProductPrice) {
324 $check = false;
325 }
326
327 if (!is_null($PriceFormula->getMaxPrice()) && $PriceFormula->getMaxPrice() < $testedProductPrice) {
328 $check = false;
329 }
330
331 if (!is_null($PriceFormula->getCategoryIds())) {
332 $intersection = array_intersect(
333 $PriceFormula->getCategoryIds(),
334 $product['categories']
335 );
336
337 if (empty($intersection)) {
338 $check = false;
339 }
340 }
341
342 if ($check) {
343 $res_formula = $PriceFormula;
344 break;
345 }
346 }
347
348 return $res_formula ?: null;
349 }
350
351 public function normalizeProductPrice(array $product): array
352 {
353 $price = $regular_price = 0;
354 if (isset($product['price']) && floatval($product['price'])) {
355 $price = $regular_price = floatval($product['price']);
356 if (isset($product['regular_price']) && floatval($product['regular_price'])) {
357 $regular_price = floatval($product['regular_price']);
358 }
359 } else if (isset($product['price_min']) && floatval($product['price_min'])) {
360 $price = $regular_price = floatval($product['price_min']);
361 if (isset($product['regular_price_min']) && floatval($product['regular_price_min'])) {
362 $regular_price = floatval($product['regular_price_min']);
363 }
364 } else if (isset($product['price_max']) && floatval($product['price_max'])) {
365 $price = $regular_price = floatval($product['price_max']);
366 if (isset($product['regular_price_max']) && floatval($product['regular_price_max'])) {
367 $regular_price = floatval($product['regular_price_max']);
368 }
369 }
370
371 return [
372 'price' => $price,
373 'regular_price' => $regular_price,
374 ];
375 }
376
377 }
378