1C-Bitrix 25.700.0
costpricecalculator.php
См. документацию.
1<?php
2namespace Bitrix\Catalog\Product\Store;
3
4use Bitrix\Catalog\ProductTable;
5use Bitrix\Catalog\StoreBatchTable;
6use Bitrix\Main\Config\Option;
7use Bitrix\Catalog\Config\State;
8use Bitrix\Main\Loader;
9use Bitrix\Main\Localization\Loc;
10use phpDocumentor\Reflection\Types\Boolean;
11
20{
21 public const METHOD_FIFO = 'fifo';
22 public const METHOD_AVERAGE = 'average';
23 private const OPTION_NAME = 'cost_price_calculation_method';
24
25 private static string $method;
26 private static bool $isUsedInventoryManagement;
27
28 protected ?array $productFields = null;
30
31 private BatchManager $batchManager;
32
36 public function __construct(BatchManager $batchManager)
37 {
38 $this->batchManager = $batchManager;
39
40 $this->isCurrencyModuleIncluded = Loader::includeModule('currency');
41 }
42
48 public static function getMethod(): string
49 {
50 self::$method ??= Option::get('catalog', self::OPTION_NAME);
51
52 return self::$method;
53 }
54
62 public static function setMethod(string $method): void
63 {
64 self::$method = ($method === self::METHOD_FIFO) ? self::METHOD_FIFO : self::METHOD_AVERAGE;
65
66 Option::set('catalog', self::OPTION_NAME, self::$method);
67 }
68
69 private static function isUsedInventoryManagement(): bool
70 {
71 static::$isUsedInventoryManagement ??= State::isUsedInventoryManagement();
72
73 return static::$isUsedInventoryManagement;
74 }
75
76 private function getCatalogPurchasingFields(): ?array
77 {
78 if ($this->productFields === null)
79 {
80 $this->productFields = ProductTable::getRow([
81 'filter' => ['=ID' => $this->batchManager->getProductId()],
82 'select' => ['PURCHASING_PRICE', 'PURCHASING_CURRENCY'],
83 'cache' => ['ttl' => 3600]
84 ]);
85
86 }
87
89 }
90
91 private function getCatalogPurchasingPrice(): float
92 {
93 return (float)($this->getCatalogPurchasingFields()['PURCHASING_PRICE'] ?? 0);
94 }
95
96 private function getCatalogPurchasingCurrency(): string
97 {
98 return (string)($this->getCatalogPurchasingFields()['PURCHASING_CURRENCY'] ?? '');
99 }
100
110 public function calculate(float $quantity, int $storeId, string $currency = null): float
111 {
112 if ($quantity <= 0 || !self::isUsedInventoryManagement())
113 {
114 $catalogPrice = $this->getCatalogPurchasingPrice();
115
116 if (
117 empty($currency)
118 || !$this->isCurrencyModuleIncluded
119 || $currency === $this->getCatalogPurchasingCurrency()
120 )
121 {
122 return $catalogPrice;
123 }
124
125 return \CCurrencyRates::convertCurrency($catalogPrice, $this->getCatalogPurchasingCurrency(), $currency);
126 }
127
128 if (self::getMethod() === self::METHOD_FIFO)
129 {
130 return $this->calculateFifo($quantity, $storeId, $currency);
131 }
132
133 return $this->calculateAverage($storeId, $currency);
134 }
135
136 private function calculateFifo(float $quantity, int $storeId, string $currency = null): float
137 {
138 $commonAmount = 0;
139 $commonSum = 0;
140 foreach ($this->batchManager->getAvailableStoreCollection($storeId) as $item)
141 {
142 $itemAvailableAmount = $item->getAvailableAmount();
143 $itemPurchasingPrice = $item->getPurchasingPrice();
144 if ($this->isCurrencyModuleIncluded && $currency && $item->getPurchasingCurrency() !== $currency)
145 {
146 $itemPurchasingPrice = \CCurrencyRates::convertCurrency(
147 $itemPurchasingPrice,
148 $item->getPurchasingCurrency(),
150 );
151 }
152
153 if ($itemAvailableAmount >= $quantity)
154 {
155 $commonAmount += $quantity;
156 $commonSum += ($itemPurchasingPrice * $quantity);
157
158 break;
159 }
160
161 $quantity -= $itemAvailableAmount;
162 $commonAmount += $itemAvailableAmount;
163 $commonSum += ($itemPurchasingPrice * $itemAvailableAmount);
164 }
165
166 if ($commonAmount === 0)
167 {
168 return $this->getCatalogPurchasingPrice();
169 }
170
171 return $this->roundCalculation($commonSum / $commonAmount);
172 }
173
174 private function calculateAverage(int $storeId, string $currency = null): float
175 {
176 $batchCollection = $this->batchManager->getAvailableStoreCollection($storeId);
177 $batch = $batchCollection->current();
178
179 if (!$batch)
180 {
181 $itemPurchasingPrice = $this->getCatalogPurchasingPrice();
182 $itemPurchasingCurrency = $this->getCatalogPurchasingCurrency();
183 }
184 else
185 {
186 $itemPurchasingPrice = $batch->getPurchasingPrice();
187 $itemPurchasingCurrency = $batch->getPurchasingCurrency();
188 }
189
190 if (
191 $itemPurchasingPrice > 0
192 && $this->isCurrencyModuleIncluded
193 && $currency
194 && $itemPurchasingCurrency !== $currency
195 )
196 {
197 $itemPurchasingPrice = \CCurrencyRates::convertCurrency(
198 $itemPurchasingPrice,
199 $itemPurchasingCurrency,
201 );
202 }
203
204 return $this->roundCalculation($itemPurchasingPrice);
205 }
206
207 private function roundCalculation(float $value): float
208 {
209 return round($value, $this->getRoundPrecision());
210 }
211
212 private function getRoundPrecision(): int
213 {
214 return (int)Option::get('sale', 'value_precision', 2);
215 }
216
217 public static function getMethodList(): array
218 {
219 return [
220 self::METHOD_AVERAGE => Loc::getMessage('COST_PRICE_CALCULATION_MODE_AVERAGE'),
221 self::METHOD_FIFO => Loc::getMessage('COST_PRICE_CALCULATION_MODE_FIFO'),
222 ];
223 }
224}
__construct(BatchManager $batchManager)
Определения costpricecalculator.php:36
calculate(float $quantity, int $storeId, string $currency=null)
Определения costpricecalculator.php:110
static getRow(array $parameters)
Определения datamanager.php:398
</td ></tr ></table ></td ></tr >< tr >< td class="bx-popup-label bx-width30"><?=GetMessage("PAGE_NEW_TAGS")?> array( $site)
Определения file_new.php:804
$currency
Определения template.php:266