Bitrix-D7 23.9
 
Загрузка...
Поиск...
Не найдено
storeamount.php
1<?php
2
4
13
22
23Loc::loadLanguageFile($_SERVER['DOCUMENT_ROOT'] . BX_ROOT . '/modules/catalog/install/components/bitrix/catalog.productcard.store.amount/class.php');
24
26{
27 protected $entityId;
28 protected $variationIds;
29
30 protected $storesCount;
31 protected $storeTotal;
32
33 protected $measures = [];
34 protected $defaultMeasure;
35
36 protected const GRID_NAME = 'productcard_store_amount';
37
38 public function __construct(int $entityId)
39 {
40 $this->entityId = $entityId;
41 }
42
43 public function getEntityId(): int
44 {
45 return $this->entityId;
46 }
47
48 public function getVariationIds(): array
49 {
50 if (!isset($this->variationIds))
51 {
52 $productId = $this->getEntityId();
53 $variations = \CCatalogSku::getOffersList($productId);
54 if (isset($variations[$productId]))
55 {
56 $this->variationIds = array_column($variations[$productId], 'ID');
57 }
58 else
59 {
60 $this->variationIds = [$productId];
61 }
62 }
63
65 }
66
67 public function getStoreAmountGridId(): string
68 {
69 return self::GRID_NAME . '_' . $this->getEntityId();
70 }
71
72 public function getStoresCount(): int
73 {
74 if (!isset($this->storesCount))
75 {
76 $filter = [
77 '=PRODUCT_ID' => $this->getVariationIds(),
78 [
79 'LOGIC' => 'OR',
80 '!=AMOUNT' => 0,
81 '!=QUANTITY_RESERVED' => 0,
82 ],
83 '=STORE.ACTIVE' => 'Y',
84 ];
85
86 $filter = array_merge(
87 $filter,
88 AccessController::getCurrent()->getEntityFilter(
89 ActionDictionary::ACTION_STORE_VIEW,
90 StoreProductTable::class
91 )
92 );
93
94 $this->storesCount = StoreProductTable::getList([
95 'select' => ['CNT'],
96 'filter' => $filter,
97 'runtime' => [
98 new \Bitrix\Main\Entity\ExpressionField('CNT', 'COUNT(DISTINCT(STORE_ID))')
99 ],
100 ])->fetch()['CNT'];
101 }
102
103 return $this->storesCount;
104 }
105
106 public function getProductStores(array $params = []): array
107 {
108 $stores = [];
109
110 $offset = $params['offset'] ?? 0;
111 $limit = $params['limit'] ?? null;
112
114 $filter = [
115 '=PRODUCT_ID' => $variationIds,
116 '=STORE.ACTIVE' => 'Y',
117 ];
118
119 $filter = array_merge(
120 $filter,
121 AccessController::getCurrent()->getEntityFilter(
122 ActionDictionary::ACTION_STORE_VIEW,
123 StoreProductTable::class
124 )
125 );
126
127 $storeProductData = StoreProductTable::getList([
128 'select' => ['SID_DISTINCT'],
129 'filter' => $filter,
130 'runtime' => [
131 new \Bitrix\Main\Entity\ExpressionField('SID_DISTINCT', 'DISTINCT(STORE_ID)'),
132 ],
133 ])->fetchAll();
134
135 $storeIds = array_column($storeProductData, 'SID_DISTINCT');
136 $storeIds = array_slice($storeIds, $offset, $limit);
137
138 $storeProductData = StoreProductTable::getList([
139 'select' => [
140 'STORE_ID',
141 'PRODUCT_ID',
142 'AMOUNT',
143 'QUANTITY_RESERVED'
144 ],
145 'filter' => [
146 '=STORE_ID' => $storeIds,
147 '=PRODUCT_ID' => $variationIds,
148 '=STORE.ACTIVE' => 'Y',
149 ],
150 ])->fetchAll();
151
152 $fetchedVariationIds = array_column($storeProductData, 'PRODUCT_ID');
153 $variationsData = $this->getVariationsData($fetchedVariationIds);
154
155 $variations = [];
156 foreach ($variationsData as $variationData)
157 {
158 $variations[$variationData['ID']] = $variationData;
159 }
160
161 $storeIds = [];
162 foreach ($storeProductData as $storeProduct)
163 {
164 $productData = $variations[$storeProduct['PRODUCT_ID']];
165
166 if ((float)$storeProduct['QUANTITY_RESERVED'] === 0.0 && (float)$storeProduct['AMOUNT'] === 0.0)
167 {
168 continue;
169 }
170
171 $storeId = (int)$storeProduct['STORE_ID'];
172 $amount = (float)$productData['PURCHASING_PRICE'] * (float)$storeProduct['AMOUNT'];
173
174 $measureId = $productData['MEASURE'] ?? (int)$this->getDefaultMeasure()['ID'];
175 $currency = $productData['PURCHASING_CURRENCY'];
176
177 if (!isset($stores[$storeId]))
178 {
179 $storeIds[] = $storeId;
180
181 $stores[$storeId] = [
182 'ID' => $storeId,
183 'QUANTITY' => [],
184 'AMOUNT' => [],
185 ];
186 }
187
188 // MEASURE EXIST CHECK
189 if (!isset($stores[$storeId]['QUANTITY'][$measureId]))
190 {
191 $stores[$storeId]['QUANTITY'][$measureId] = [
192 'QUANTITY_COMMON' => (float)$storeProduct['AMOUNT'],
193 'QUANTITY_RESERVED' => (float)$storeProduct['QUANTITY_RESERVED'],
194 'MEASURE_ID' => $measureId,
195 ];
196 }
197 else
198 {
199 $stores[$storeId]['QUANTITY'][$measureId]['QUANTITY_COMMON'] += (float)$storeProduct['AMOUNT'];
200 $stores[$storeId]['QUANTITY'][$measureId]['QUANTITY_RESERVED'] += (float)$storeProduct['QUANTITY_RESERVED'];
201 }
202
203 // CURRENCY EXIST CHECK
204 if (!isset($stores[$storeId]['AMOUNT'][$currency]))
205 {
206 $stores[$storeId]['AMOUNT'][$currency] = [
207 'AMOUNT' => $amount,
208 'CURRENCY' => $currency,
209 ];
210 }
211 else
212 {
213 $stores[$storeId]['AMOUNT'][$currency]['AMOUNT'] += $amount;
214 }
215 }
216
217 $storesInfo = $this->getStoresInfo($storeIds);
218
219 foreach ($storesInfo as $storeInfo)
220 {
221 if (isset($stores[(int)$storeInfo['ID']]))
222 {
223 $stores[(int)$storeInfo['ID']]['TITLE'] = $storeInfo['TITLE'];
224 }
225 }
226
227 return $stores;
228 }
229
235 protected function getStoresInfo(array $storeIds): array
236 {
237 if (count($storeIds) > 0)
238 {
239 return StoreTable::getList([
240 'select' => ['ID', 'TITLE'],
241 'filter' => [
242 '=ID' => $storeIds,
243 'ACTIVE' => 'Y',
244 ],
245 ])
246 ->fetchAll()
247 ;
248 }
249
250 return [];
251 }
252
253 protected function getVariationsData(array $variationIds): array
254 {
255 return ProductTable::getList([
256 'select' => [
257 'ID',
258 'PURCHASING_PRICE',
259 'PURCHASING_CURRENCY',
260 'MEASURE',
261 ],
262
263 'filter' => ['=ID' => $variationIds],
264 ])->fetchAll();
265 }
266
271 public function getTotalData(): array
272 {
273 $storeTotal = $this->getStoreTotal();
274
275 $quantity = '';
276 $quantityCommon = '';
277 $quantityReserved = '';
278
279 foreach ($storeTotal['QUANTITY'] as $storeQuantity)
280 {
281 $measureSymbol = htmlspecialcharsbx($this->getMeasure($storeQuantity['MEASURE_ID']));
282
283 $measureInfo =
284 "<span class='total-info'>
285 <span class='total-info-value'>{$storeQuantity['QUANTITY']}</span>
286 {$measureSymbol}
287 </span>";
288
289 $measureCommonInfo =
290 "<span class='total-info'>
291 <span class='total-info-value'>{$storeQuantity['QUANTITY_COMMON']}</span>
292 {$measureSymbol}
293 </span>";
294
295 $measureReservedInfo =
296 "<span class='total-info'>
297 <span class='total-info-value'>{$storeQuantity['QUANTITY_RESERVED']}</span>
298 {$measureSymbol}
299 </span>";
300
301 $quantity .= $measureInfo . '<br>';
302 $quantityCommon .= $measureCommonInfo . '<br>';
303 $quantityReserved .= $measureReservedInfo . '<br>';
304 }
305
306 $amount = '';
307
308 foreach ($storeTotal['AMOUNT'] as $storeAmount)
309 {
310 if (isset($storeAmount['CURRENCY']))
311 {
312 $amountValue =
313 "<span class='total-info-value'>"
314 . \CCurrencyLang::CurrencyFormat($storeAmount['AMOUNT'], $storeAmount['CURRENCY'], false)
315 . "</span>";
316
317 $amountBlock =
318 "<span class='total-info'>"
319 . \CCurrencyLang::getPriceControl(
320 $amountValue,
321 $storeAmount['CURRENCY']
322 )
323 . "</span>";
324
325 $amount .= $amountBlock.'<br>';
326 }
327
328 }
329
330 return [
331 "QUANTITY" => $quantity,
332 "QUANTITY_COMMON" => $quantityCommon,
333 "QUANTITY_RESERVED" => $quantityReserved,
334 "AMOUNT" => $amount,
335 ];
336 }
337
342 protected function getStoreTotal(): array
343 {
344 if (!isset($this->storeTotal))
345 {
346 $this->fillStoreTotal();
347 }
348
349 return $this->storeTotal;
350 }
351
355 protected function fillStoreTotal(): void
356 {
357 $storeTotalData = [
358 'QUANTITY' => [],
359 'AMOUNT' => [],
360 ];
361
362 if ($this->getStoresCount() > 0)
363 {
364 $variationsTotalData = $this->getVariationsTotalData($this->getVariationIds());
365 foreach ($variationsTotalData as $variationData)
366 {
367 $variationData['MEASURE_ID'] = $variationData['MEASURE_ID'] ?? (int)$this->getDefaultMeasure()['ID'];
368
369 if (!isset($storeTotalData['QUANTITY'][$variationData['MEASURE_ID']]))
370 {
371 $storeTotalData['QUANTITY'][$variationData['MEASURE_ID']] = [
372 'QUANTITY' => 0.0,
373 'QUANTITY_COMMON' => 0.0,
374 'QUANTITY_RESERVED' => 0.0,
375 'MEASURE_ID' => $variationData['MEASURE_ID'],
376 ];
377 }
378
379 $quantityValue = (float)$variationData['QUANTITY_COMMON'] - (float)$variationData['QUANTITY_RESERVED'];
380
381 $storeTotalData['QUANTITY'][$variationData['MEASURE_ID']]['QUANTITY'] += $quantityValue;
382 $storeTotalData['QUANTITY'][$variationData['MEASURE_ID']]['QUANTITY_COMMON'] += (float)$variationData['QUANTITY_COMMON'];
383 $storeTotalData['QUANTITY'][$variationData['MEASURE_ID']]['QUANTITY_RESERVED'] += (float)$variationData['QUANTITY_RESERVED'];
384
385 if (!isset($storeTotalData['AMOUNT'][$variationData['CURRENCY']]))
386 {
387 $storeTotalData['AMOUNT'][$variationData['CURRENCY']] = [
388 'AMOUNT' => 0.0,
389 'CURRENCY' => $variationData['CURRENCY'],
390 ];
391 }
392 $commonPrice = (float)$variationData['QUANTITY_COMMON'] * (float)$variationData['PRICE'];
393 $storeTotalData['AMOUNT'][$variationData['CURRENCY']]['AMOUNT'] += $commonPrice;
394 }
395 }
396
397 $this->storeTotal = $storeTotalData;
398 }
399
407 protected function getVariationsTotalData(array $variationIds): array
408 {
409 $products = [];
410
411 $filter = [
412 '=PRODUCT_ID' => $variationIds,
413 '=STORE.ACTIVE' => 'Y',
414 ];
415
416 $filter = array_merge(
417 $filter,
418 AccessController::getCurrent()->getEntityFilter(
419 ActionDictionary::ACTION_STORE_VIEW,
420 StoreProductTable::class
421 )
422 );
423
424 $commonProductData = StoreProductTable::getList([
425 'select' => [
426 'PRODUCT_ID',
427 'MEASURE_ID' => 'PRODUCT.MEASURE',
428 'PRICE' => 'PRODUCT.PURCHASING_PRICE',
429 'CURRENCY' => 'PRODUCT.PURCHASING_CURRENCY',
430 'QUANTITY_COMMON',
431 ],
432 'filter' => $filter,
433 'group' => ['PRODUCT_ID'],
434 'runtime' => [
435 new Entity\ExpressionField('QUANTITY_COMMON', 'SUM(AMOUNT)'),
436 ],
437 ])->fetchAll();
438
439 foreach ($commonProductData as $productData)
440 {
441 $products[$productData['PRODUCT_ID']] = $productData;
442 }
443
444 $productQuantityReservedData = StoreProductTable::getList([
445 'select' => [
446 'PRODUCT_ID',
447 'RESERVED_AMOUNT',
448 ],
449 'filter' => [
450 '=PRODUCT_ID' => $variationIds,
451 '=STORE.ACTIVE' => 'Y',
452 ],
453 'group' => ['PRODUCT_ID'],
454 'runtime' => [
455 new Entity\ExpressionField('RESERVED_AMOUNT', 'SUM(QUANTITY_RESERVED)'),
456 ],
457 ])->fetchAll();
458
459 foreach ($productQuantityReservedData as $productData)
460 {
461 $products[$productData['PRODUCT_ID']]['QUANTITY_RESERVED'] = $productData['RESERVED_AMOUNT'];
462 }
463
464 return $products;
465 }
466
473 public function getMeasure(?int $measureId): string
474 {
475 if ($measureId === null)
476 {
477 return $this->getDefaultMeasure()['SYMBOL'];
478 }
479
480 if (!isset($this->measures[$measureId]))
481 {
482 $measure = \CCatalogMeasure::getList([], ['=ID' => $measureId])->Fetch();
483
484 if ($measure)
485 {
486 $this->measures[$measureId] = $measure['SYMBOL'];
487 }
488 else
489 {
490 $this->measures[$measureId] = '';
491 }
492 }
493
494 return $this->measures[$measureId];
495 }
496
501 protected function getDefaultMeasure(): array
502 {
503 if (!isset($this->defaultMeasure))
504 {
505 $fetchedMeasure = \CCatalogMeasure::getList([], ['=IS_DEFAULT' => 'Y'])->Fetch();
506 if ($fetchedMeasure)
507 {
508 $this->defaultMeasure = $fetchedMeasure;
509 }
510 else
511 {
512 // default symbol not exist catch
513 $this->defaultMeasure = [
514 'ID' => 0,
515 'SYMBOL' => '',
516 ];
517 }
518 }
519
521 }
522
523 public function getStoreAmountSignedParameters(): string
524 {
528 );
529 }
530
531 protected function getStoreAmountComponentName(): string
532 {
533 return 'bitrix:catalog.productcard.store.amount';
534 }
535
536 protected function getStoreAmountParameters(): array
537 {
538 return [
539 'ENTITY_ID' => $this->getEntityId(),
540 ];
541 }
542}
getVariationsData(array $variationIds)
getVariationsTotalData(array $variationIds)
static signParameters($componentName, $parameters)
static loadLanguageFile($file, $language=null, $normalize=true)
Definition loc.php:224
static getList(array $parameters=array())