PluginProbe
ووسلام – همگام سازی ووکامرس و باسلام / 1.10.21
ووسلام – همگام سازی ووکامرس و باسلام v1.10.21
1.10.21 1.10.19 1.10.20 1.10.18 1.10.17 1.10.15 1.10.14 1.10.13 1.10.12 1.10.10 1.10.9 1.10.8 1.10.7 1.10.6 1.10.5 1.10.4 1.10.3 1.10.2 1.10.1 1.10.0 1.9.2 1.9.1 1.9.0 1.8.8 1.8.5 All 54 releases
sync-basalam / includes / Admin / Product / Data / Services / PriceService.php

PriceService.php in ووسلام – همگام سازی ووکامرس و باسلام 1.10.21, at includes/Admin/Product/Data/Services/PriceService.php

195 lines 6.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace SyncBasalam\Admin\Product\Data\Services;
4
5 use SyncBasalam\Admin\Product\elements\SingleProduct\PriceChangeField;
6 use SyncBasalam\Admin\Settings\SettingsConfig;
7 use SyncBasalam\Logger\Logger;
8 use SyncBasalam\Services\Products\FetchCommission;
9 use SyncBasalam\Utilities\ProductMetaKey;
10 use SyncBasalam\Utilities\PriceAdjustment;
11
12 defined('ABSPATH') || exit;
13
14 class PriceService
15 {
16 public function calculateFinalPrice($product): ?int
17 {
18 $price = $this->getBasePrice($product);
19 if (!$price) return null;
20
21 return $this->applyPriceCalculations($price, $product);
22 }
23
24 private function getBasePrice($product)
25 {
26 $priceField = syncBasalamSettings()->getSettings(SettingsConfig::PRODUCT_PRICE_FIELD);
27 $regularPrice = $product->get_regular_price();
28 $salePrice = $product->get_sale_price();
29
30 if ($priceField === 'original_price' || $priceField === 'sale_strikethrough_price') {
31 return $regularPrice && is_numeric($regularPrice) ? floatval($regularPrice) : null;
32 }
33
34 if ($priceField === 'sale_price') {
35 if ($salePrice && is_numeric($salePrice)) return floatval($salePrice);
36 return $regularPrice && is_numeric($regularPrice) ? floatval($regularPrice) : null;
37 }
38
39 return null;
40 }
41
42 private function applyPriceCalculations(float $price, $product): ?int
43 {
44 $priceChangeValue = $this->getPriceChangeValue($product);
45 $roundMode = syncBasalamSettings()->getSettings(SettingsConfig::ROUND_PRICE);
46 $currency = get_woocommerce_currency();
47
48 $finalPrice = $this->convertToRial($price, $currency);
49 if (!$finalPrice) return null;
50
51
52 if ($priceChangeValue !== '' && $priceChangeValue !== '0') $finalPrice = $this->applyPriceChange($finalPrice, $priceChangeValue, $product);
53
54 if ($roundMode && $roundMode != 'none') $finalPrice = $this->applyRounding($finalPrice, $roundMode);
55
56 if ($finalPrice < 1000) return null;
57
58 return intval($finalPrice);
59 }
60
61 private function getPriceChangeValue($product): string
62 {
63 $productId = method_exists($product, 'get_id') ? intval($product->get_id()) : 0;
64
65 if ($productId > 0) {
66 $productValue = PriceAdjustment::normalize($this->getProductPriceChangeMeta($productId));
67
68 if ($productValue !== null) return $productValue;
69
70 if (method_exists($product, 'get_parent_id')) {
71 $parentId = intval($product->get_parent_id());
72 $parentValue = $parentId > 0
73 ? PriceAdjustment::normalize($this->getProductPriceChangeMeta($parentId))
74 : null;
75
76 if ($parentValue !== null) return $parentValue;
77 }
78 }
79
80 return (string) (PriceAdjustment::normalize(syncBasalamSettings()->getSettings(SettingsConfig::PRICE_CHANGE_VALUE)) ?? '0');
81 }
82
83 private function getProductPriceChangeMeta(int $productId): string
84 {
85 return (string) get_post_meta($productId, PriceChangeField::META_KEY, true);
86 }
87
88 private function convertToRial(float $price, string $currency)
89 {
90 if ($currency === 'IRT') return $price * 10;
91 if ($currency === 'IRHT') return $price * 10000;
92 if ($currency === 'IRHR') return $price * 1000;
93
94 return $price;
95 }
96
97 private function applyPriceChange(float $price, string $priceChangeValue, $product = null): float
98 {
99 if (PriceAdjustment::isCommission($priceChangeValue)) return $this->applyCommissionCalculation($price, $product);
100
101 $value = intval($priceChangeValue);
102
103 if (PriceAdjustment::isPercent($value)) return $price + ($price * ($value / 100));
104
105 return $price + ($value * 10);
106 }
107
108 private function applyCommissionCalculation(float $price, $product = null): float
109 {
110 $basalamProductId = $this->getBasalamProductId($product);
111 $categoryIds = [];
112
113 if ($basalamProductId !== null) {
114 $commissionPercent = FetchCommission::fetchProductCommission($basalamProductId);
115 } else {
116 $categoryIds = $this->getCategoryIds($product);
117 $commissionPercent = FetchCommission::fetchCategoryCommission($categoryIds);
118 }
119
120 $commissionPercent = floatval($commissionPercent);
121
122 if ($commissionPercent <= 0 || $commissionPercent >= 100) return $price;
123
124 $multiplier = 1 / (1 - ($commissionPercent / 100));
125 $maxMultiplier = 1 + (PriceAdjustment::MAX_PERCENT / 100);
126
127 if ($multiplier > $maxMultiplier) {
128 Logger::warning('کار�
129 زد دسته‌بندی باسلا�
130 خارج از بازه �
131 نطقی بود و افزایش قی�
132 ت به سقف �
133 جاز �
134 حدود شد.', [
135 'category_ids' => $categoryIds,
136 'commission_percent' => $commissionPercent,
137 'max_percent' => PriceAdjustment::MAX_PERCENT,
138 ]);
139
140 $multiplier = $maxMultiplier;
141 }
142
143 return $price * $multiplier;
144 }
145
146 /**
147 * Resolve the remote product id used by the product commission endpoint.
148 * Variations inherit the connection from their parent product.
149 */
150 private function getBasalamProductId($product): ?int
151 {
152 if (!is_object($product)) return null;
153
154 $postIds = [];
155
156 if (method_exists($product, 'get_parent_id')) {
157 $parentId = intval($product->get_parent_id());
158 if ($parentId > 0) {
159 $postIds[] = $parentId;
160 }
161 }
162
163 if (empty($postIds) && method_exists($product, 'get_id')) {
164 $productId = intval($product->get_id());
165 if ($productId > 0) $postIds[] = $productId;
166 }
167
168 $metaKey = ProductMetaKey::basalamProductId();
169 foreach (array_unique($postIds) as $postId) {
170 $basalamProductId = get_post_meta($postId, $metaKey, true);
171
172 if (is_numeric($basalamProductId) && intval($basalamProductId) > 0) {
173 return intval($basalamProductId);
174 }
175 }
176
177 return null;
178 }
179
180 private function applyRounding(float $price, $mode): float
181 {
182 if ($mode === 'up') return ceil($price / 10000) * 10000;
183
184 if ($mode === 'down') return floor($price / 10000) * 10000;
185
186 return $price;
187 }
188
189 private function getCategoryIds($product): array
190 {
191 $categoryService = new CategoryService();
192 return $categoryService->getCategoryIds($product);
193 }
194 }
195