Bitrix-D7 23.9
 
Загрузка...
Поиск...
Не найдено
basketcomponenthelper.php
1<?php
2namespace Bitrix\Sale;
3
7
8Main\Localization\Loc::loadMessages(__FILE__);
9
11{
12 static $cacheRatio = array();
13 static $cacheRatioData = array();
14
21 public static function getFUserBasketQuantity($fuserId, $siteId = null)
22 {
23 if ($fuserId === null)
24 {
25 return 0;
26 }
27 if ($siteId === null)
28 {
29 $siteId = SITE_ID;
30 }
31
32 $quantity = null;
33 if (!empty($_SESSION['SALE_USER_BASKET_QUANTITY'][$siteId]) && is_array($_SESSION['SALE_USER_BASKET_QUANTITY'][$siteId])
34 && array_key_exists($fuserId, $_SESSION['SALE_USER_BASKET_QUANTITY'][$siteId]))
35 {
36 $quantity = $_SESSION['SALE_USER_BASKET_QUANTITY'][$siteId][$fuserId];
37 }
38
39 if ($quantity === null)
40 {
41 static::updateFUserBasketQuantity($fuserId, $siteId);
42 $quantity = $_SESSION['SALE_USER_BASKET_QUANTITY'][$siteId][$fuserId];
43 }
44
45 return $quantity;
46 }
47
54 public static function getFUserBasketPrice($fuserId, $siteId = null)
55 {
56 if ($fuserId === null)
57 {
58 return 0;
59 }
60 if ($siteId === null)
61 {
62 $siteId = SITE_ID;
63 }
64
65 $price = null;
66 if (!empty($_SESSION['SALE_USER_BASKET_PRICE'][$siteId]) && is_array($_SESSION['SALE_USER_BASKET_PRICE'][$siteId])
67 && array_key_exists($fuserId, $_SESSION['SALE_USER_BASKET_PRICE'][$siteId]))
68 {
69 $price = $_SESSION['SALE_USER_BASKET_PRICE'][$siteId][$fuserId];
70 }
71
72 if ($price === null)
73 {
74 static::updateFUserBasketPrice($fuserId, $siteId);
75 $price = $_SESSION['SALE_USER_BASKET_PRICE'][$siteId][$fuserId];
76 }
77
78 return $price;
79 }
80
87 protected static function setFUserBasketQuantity($fUserId, $quantity, $siteId = null)
88 {
89 if ($siteId === null)
90 {
91 $siteId = SITE_ID;
92 }
93
94 $_SESSION['SALE_USER_BASKET_QUANTITY'][$siteId][$fUserId] = $quantity;
95 }
96
101 public static function clearFUserBasketQuantity($fUserId, $siteId = null)
102 {
103 if ($siteId === null)
104 {
105 $siteId = SITE_ID;
106 }
107
108 unset($_SESSION['SALE_USER_BASKET_QUANTITY'][$siteId][$fUserId]);
109 }
110
117 protected static function setFUserBasketPrice($fUserId, $price, $siteId = null)
118 {
119 if ($siteId === null)
120 {
121 $siteId = SITE_ID;
122 }
123
124 $_SESSION['SALE_USER_BASKET_PRICE'][$siteId][$fUserId] = $price;
125 }
126
131 public static function clearFUserBasketPrice($fUserId, $siteId = null)
132 {
133 if ($siteId === null)
134 {
135 $siteId = SITE_ID;
136 }
137
138 unset($_SESSION['SALE_USER_BASKET_PRICE'][$siteId][$fUserId]);
139 }
140
148 public static function updateFUserBasketPrice($fuserId, $siteId = null, $basketList = null)
149 {
150 if ($siteId === null)
151 {
152 $siteId = SITE_ID;
153 }
154
155 $price = 0;
156
157 if ($basketList === null)
158 {
159 $basketList = static::getFUserBasketList($fuserId, $siteId);
160 }
161
162 if (!empty($basketList) && is_array($basketList))
163 {
164 $orderData = static::calculatePrice($fuserId, $basketList);
165 $price = $orderData['ORDER_PRICE'];
166 }
167
168 static::setFUserBasketPrice($fuserId, $price, $siteId);
169 }
170
178 public static function updateFUserBasketQuantity($fuserId, $siteId = null, $basketList = null)
179 {
180 if ($siteId === null)
181 {
182 $siteId = SITE_ID;
183 }
184
185 $quantity = 0;
186
187 if ($basketList === null)
188 {
189 $basketList = static::getFUserBasketList($fuserId, $siteId);
190 }
191
192 if (!empty($basketList) && is_array($basketList))
193 {
194 $quantity = count($basketList);
195 }
196
197 static::setFUserBasketQuantity($fuserId, $quantity, $siteId);
198 }
199
206 public static function updateFUserBasket($fuserId, $siteId = null)
207 {
208 if ($siteId === null)
209 {
210 $siteId = SITE_ID;
211 }
212
213 $basketList = static::getFUserBasketList($fuserId, $siteId);
214
215 static::updateFUserBasketPrice($fuserId, $siteId, $basketList);
216 static::updateFUserBasketQuantity($fuserId, $siteId, $basketList);
217 }
218
225 protected static function getFUserBasketList($fuserId, $siteId = null)
226 {
227 if ($siteId === null)
228 {
229 $siteId = SITE_ID;
230 }
231
234 $basketClassName = $registry->getBasketClassName();
235
236 $basketList = array();
237 $res = $basketClassName::getList(array(
238 'filter' => array(
239 '=FUSER_ID' => $fuserId,
240 '=ORDER_ID' => null,
241 '=LID' => $siteId,
242 '=CAN_BUY' => 'Y',
243 '=DELAY' => 'N'
244 )
245 ));
246 while ($data = $res->fetch())
247 {
248 if (\CSaleBasketHelper::isSetItem($data))
249 continue;
250
251 if (!isset($data['BASE_PRICE']) || (float)$data['BASE_PRICE'] <= 0)
252 {
253 $data['BASE_PRICE'] = $data['PRICE'] + $data['DISCOUNT_PRICE'];
254 }
255
256 $basketList[] = $data;
257 }
258
259 return $basketList;
260 }
261
268 protected static function calculatePrice($fuserId, array $basketList)
269 {
270 $totalPrice = 0;
271 $totalWeight = 0;
272
273 foreach ($basketList as $basketData)
274 {
275 $totalPrice += $basketData["PRICE"] * $basketData["QUANTITY"];
276 $totalWeight += $basketData["WEIGHT"] * $basketData["QUANTITY"];
277 }
278
279 $orderData = array(
280 'SITE_ID' => SITE_ID,
281 'ORDER_PRICE' => $totalPrice,
282 'ORDER_WEIGHT' => $totalWeight,
283 'BASKET_ITEMS' => $basketList
284 );
285
288 $basketClassName = $registry->getBasketClassName();
289
290 $basket = $basketClassName::create(SITE_ID);
291 $basket->setFUserId($fuserId);
292 foreach ($basketList as $oldItem)
293 {
294 $item = $basket->createItem($oldItem['MODULE'], $oldItem['PRODUCT_ID']);
295 unset($oldItem['MODULE'], $oldItem['PRODUCT_ID']);
296 $item->initFields($oldItem);
297 }
298 $orderData['ORDER_PRICE'] = self::calculateBasketCost($basket);
299 unset($basket);
300
301 return $orderData;
302 }
303
304
310 public static function onSaleBasketItemEntitySaved(Main\Event $event)
311 {
312 $fuserId = Fuser::getId(true);
313 $basketItem = $event->getParameter('ENTITY');
314
315 $originalValues = $event->getParameter('VALUES');
316 if ((!$basketItem instanceof BasketItem))
317 {
318 return new Main\EventResult( Main\EventResult::SUCCESS, null, 'sale');
319 }
320
322 if ((!$basket = $basketItem->getCollection())
323 || ($basketItem->getFUserId() != $fuserId)
324 )
325 {
326 return new Main\EventResult( Main\EventResult::SUCCESS, null, 'sale');
327 }
328
329 if ($basketItem->isChanged())
330 {
331 $updateSessionData = false;
332
333 if (!$basket->getOrder())
334 {
335 if (!$updateSessionData && array_key_exists('QUANTITY', $originalValues))
336 {
337 $updateSessionData = true;
338 }
339
340 if (!$updateSessionData && (array_key_exists('PRICE', $originalValues) && PriceMaths::roundPrecision($originalValues['PRICE']) !== PriceMaths::roundPrecision($basketItem->getPrice())))
341 {
342 $updateSessionData = true;
343 }
344
345 if (!$updateSessionData && (array_key_exists('DISCOUNT_PRICE', $originalValues) && PriceMaths::roundPrecision($originalValues['DISCOUNT_PRICE']) !== PriceMaths::roundPrecision($basketItem->getDiscountPrice())))
346 {
347 $updateSessionData = true;
348 }
349 }
350
351 if (!$updateSessionData && (array_key_exists('ORDER_ID', $originalValues) && (intval($originalValues['ORDER_ID'])) == 0 && intval($basketItem->getField('ORDER_ID') > 0)))
352 {
353 $updateSessionData = true;
354 }
355
356 if (!$updateSessionData
357 && (array_key_exists('CAN_BUY', $originalValues) && ($originalValues['CAN_BUY'] !== $basketItem->getField('CAN_BUY'))))
358 {
359 $updateSessionData = true;
360 }
361
362 if (!$updateSessionData
363 && (array_key_exists('DELAY', $originalValues) && ($originalValues['DELAY'] !== $basketItem->getField('DELAY'))))
364 {
365 $updateSessionData = true;
366 }
367
368 if ($updateSessionData)
369 {
370 static::clearFUserBasketPrice($fuserId, SITE_ID);
371 static::clearFUserBasketQuantity($fuserId, SITE_ID);
372 }
373 }
374
375 return new Main\EventResult( Main\EventResult::SUCCESS, null, 'sale');
376 }
377
383 public static function onSaleBasketItemDeleted(Main\Event $event)
384 {
385 $fuserId = Fuser::getId(true);
386 $originalValues = $event->getParameter('VALUES');
387 if ($originalValues['FUSER_ID'] != $fuserId)
388 {
389 return new Main\EventResult( Main\EventResult::SUCCESS, null, 'sale');
390 }
391
392 static::clearFUserBasketPrice($fuserId, SITE_ID);
393 static::clearFUserBasketQuantity($fuserId, SITE_ID);
394
395 return new Main\EventResult( Main\EventResult::SUCCESS, null, 'sale');
396 }
397
405 public static function checkQuantityRatio(Basket $basket, BasketItem $item = null)
406 {
407 $result = new Result();
408
409 $basketItemRatioList = array();
410 $ratioList = array();
411 $ratioResult = static::getRatio($basket, $item);
412
413 if ($ratioResult->isSuccess())
414 {
415 $ratioData = $ratioResult->getData();
416
417 if (!empty($ratioData['RATIO_LIST']) && is_array($ratioData['RATIO_LIST']))
418 {
419 $ratioList = $ratioData['RATIO_LIST'];
420 }
421 }
422
424 foreach ($basket as $basketItem)
425 {
426 $basketItemCode = $basketItem->getBasketCode();
427
428 if ($item === null || $item->getBasketCode() === $basketItemCode)
429 {
430 $basketItemRatioList[$basketItemCode] = false;
431
432 if (isset($ratioList[$basketItemCode]))
433 {
434 $basketItemQuantity = $basketItem->getQuantity();
435 $basketItemRatio = (float)$ratioList[$basketItemCode];
436
437 $mod = roundEx(($basketItemQuantity / $basketItemRatio - round($basketItemQuantity / $basketItemRatio)), 6);
438
439 if ($mod == 0)
440 {
441 $basketItemRatioList[$basketItemCode] = true;
442 }
443 }
444 }
445 }
446
447 if (!empty($basketItemRatioList))
448 {
449 $result->addData(array('CHECK_RATIO_LIST' => $basketItemRatioList));
450 }
451
452 return $result;
453 }
454
464 public static function correctQuantityRatio(Basket $basket, BasketItem $item = null)
465 {
466 $result = new Result();
467 $changedItems = array();
468
469 $checkRatioList = array();
470 $checkRatioResult = static::checkQuantityRatio($basket, $item);
471
472 if ($checkRatioResult->isSuccess())
473 {
474 $checkRatioData = $checkRatioResult->getData();
475
476 if (!empty($checkRatioData['CHECK_RATIO_LIST']) && is_array($checkRatioData['CHECK_RATIO_LIST']))
477 {
478 $checkRatioList = $checkRatioData['CHECK_RATIO_LIST'];
479 }
480 }
481
482 $basketItemRatioList = array();
483 $ratioList = null;
484
486 foreach ($basket as $basketItem)
487 {
488 $basketItemCode = $basketItem->getBasketCode();
489
490 if ($item === null || $item->getBasketCode() === $basketItemCode)
491 {
492 $basketItemRatioList[$basketItemCode] = false;
493
494 if (isset($checkRatioList[$basketItemCode]) && $checkRatioList[$basketItemCode] === false)
495 {
496 if ($ratioList === null)
497 {
498 $ratioList = array();
499 $ratioResult = static::getRatio($basket, $item);
500
501 if ($ratioResult->isSuccess())
502 {
503 $ratioData = $ratioResult->getData();
504
505 if (!empty($ratioData['RATIO_LIST']) && is_array($ratioData['RATIO_LIST']))
506 {
507 $ratioList = $ratioData['RATIO_LIST'];
508 }
509 }
510 }
511
512 if (!isset($ratioList[$basketItemCode]))
513 {
514 $result->addError(new ResultError(Main\Localization\Loc::getMessage('SALE_BASKET_COMPONENT_HELPER_PRODUCT_RATIO_NOT_FOUND', array(
515 '#PRODUCT_NAME#' => $basketItem->getField('NAME')
516 )), 'SALE_BASKET_COMPONENT_HELPER_PRODUCT_RATIO_NOT_FOUND'));
517 continue;
518 }
519
520 $basketItemQuantity = $basketItem->getQuantity();
521 $basketItemRatio = (float)$ratioList[$basketItemCode];
522
523 $mod = roundEx(($basketItemQuantity / $basketItemRatio - round($basketItemQuantity / $basketItemRatio)), 6);
524
525 if ($mod != 0)
526 {
527 $changedItems[] = $basketItemCode;
528
529 $closestQuantity = round($basketItemQuantity / $basketItemRatio) * $basketItemRatio;
530 if ($closestQuantity < $basketItemRatio)
531 {
532 $closestQuantity = $basketItemRatio;
533 }
534
535 $r = $basketItem->setField('QUANTITY', $closestQuantity);
536 if (!$r->isSuccess())
537 {
538 $floorQuantity = floor(ceil($basketItemQuantity) / $basketItemRatio) * $basketItemRatio;
539 if ($floorQuantity < $basketItemRatio)
540 {
541 $floorQuantity = $basketItemRatio;
542 }
543
544 if ($floorQuantity != $closestQuantity)
545 {
546 $r = $basketItem->setField('QUANTITY', $floorQuantity);
547 }
548 }
549
550 if (!$r->isSuccess())
551 {
552 $result->addErrors($r->getErrors());
553
554 $r = $basketItem->setField('CAN_BUY', 'N');
555 if (!$r->isSuccess())
556 {
557 $result->addErrors($r->getErrors());
558 }
559 }
560 }
561 }
562 }
563 }
564
565 $result->addData(array('CHANGED_BASKET_ITEMS' => $changedItems));
566
567 return $result;
568 }
569
577 public static function getRatio(Basket $basket, BasketItem $item = null)
578 {
579 $result = new Result();
580 $ratioList = array();
581 if (Main\Loader::includeModule('catalog'))
582 {
583 $map = array();
584 $elementList = array();
585
587 foreach ($basket as $basketItem)
588 {
589 $code = $basketItem->getBasketCode();
590 if ($item !== null && $item->getBasketCode() != $code)
591 {
592 continue;
593 }
594
595 $hash = md5((strval($basketItem->getField("PRODUCT_PROVIDER_CLASS")) != '' ? $basketItem->getField("PRODUCT_PROVIDER_CLASS"): "")."|".(strval($basketItem->getField("MODULE")) != '' ? $basketItem->getField("MODULE"): "")."|".$basketItem->getField("PRODUCT_ID"));
596
597 if (array_key_exists($hash, static::$cacheRatio))
598 {
599 $ratioList[$code] = static::$cacheRatio[$hash];
600 }
601 else
602 {
603 $elementList[$basketItem->getField("PRODUCT_ID")] = $basketItem->getField("PRODUCT_ID");
604 }
605
606 if (!isset($map[$basketItem->getField("PRODUCT_ID")]))
607 {
608 $map[$basketItem->getField("PRODUCT_ID")] = array();
609 }
610
611 $map[$basketItem->getField("PRODUCT_ID")][] = $code;
612 }
613
614 if (!empty($elementList))
615 {
616 $res = Catalog\MeasureRatioTable::getList(array(
617 'select' => array('*'),
618 'filter' => array('@PRODUCT_ID' => $elementList, '=IS_DEFAULT' => 'Y')
619 ));
620 while ($ratioData = $res->fetch())
621 {
622 if (empty($map[$ratioData["PRODUCT_ID"]]))
623 continue;
624
625 foreach ($map[$ratioData["PRODUCT_ID"]] as $key)
626 {
627 $ratioList[$key] = $ratioData["RATIO"];
628
629 if (!$basketItem = $basket->getItemByBasketCode($key))
630 continue;
631
632 $hash = md5((strval($basketItem->getField("PRODUCT_PROVIDER_CLASS")) != '' ? $basketItem->getField("PRODUCT_PROVIDER_CLASS"): "")."|".(strval($basketItem->getField("MODULE")) != '' ? $basketItem->getField("MODULE"): "")."|".$basketItem->getField("PRODUCT_ID"));
633
634 static::$cacheRatio[$hash] = $ratioData["RATIO"];
635 static::$cacheRatioData[$hash] = $ratioData;
636 }
637 unset($key);
638 }
639 unset($ratioData, $dbRatio);
640 }
641 unset($elementList, $map);
642 }
643
644 if (!empty($ratioList))
645 $result->addData(array('RATIO_LIST' => $ratioList));
646
647 return $result;
648 }
649
655 protected static function calculateBasketCost(Basket $basket)
656 {
657 if ($basket->count() == 0)
658 return 0;
659
660 $oldApiStatus = Compatible\DiscountCompatibility::isUsed(); // TODO: remove this code after refactoring DiscountCompatibility
661 if ($oldApiStatus)
662 Compatible\DiscountCompatibility::stopUsageCompatible();
664 $basket->refreshData(array('PRICE', 'COUPONS'));
665 $discounts = Discount::buildFromBasket($basket, new Discount\Context\Fuser($basket->getFUserId(true)));
666 $discounts->calculate();
667 $discountResult = $discounts->getApplyResult();
669 if ($oldApiStatus)
670 Compatible\DiscountCompatibility::revertUsageCompatible();
671
672 if (empty($discountResult['PRICES']['BASKET']))
673 return 0;
674
675 $result = 0;
676 $discountResult = $discountResult['PRICES']['BASKET'];
678 foreach ($basket as $basketItem)
679 {
680 if (!$basketItem->canBuy())
681 continue;
682 $code = $basketItem->getBasketCode();
683 if (!empty($discountResult[$code]))
684 $result += $discountResult[$code]['PRICE'] * $basketItem->getQuantity();
685 unset($code);
686 }
687 unset($basketItem);
688 unset($discountResult);
689
690 return $result;
691 }
692
697 public static function getRatioCache()
698 {
699 return static::$cacheRatio;
700 }
701
706 public static function getRatioDataCache()
707 {
708 return static::$cacheRatioData;
709 }
710}
static getMessage($code, $replace=null, $language=null)
Definition loc.php:29
static setFUserBasketPrice($fUserId, $price, $siteId=null)
static updateFUserBasketPrice($fuserId, $siteId=null, $basketList=null)
static getFUserBasketQuantity($fuserId, $siteId=null)
static getFUserBasketPrice($fuserId, $siteId=null)
static updateFUserBasket($fuserId, $siteId=null)
static updateFUserBasketQuantity($fuserId, $siteId=null, $basketList=null)
static clearFUserBasketPrice($fUserId, $siteId=null)
static setFUserBasketQuantity($fUserId, $quantity, $siteId=null)
static onSaleBasketItemDeleted(Main\Event $event)
static clearFUserBasketQuantity($fUserId, $siteId=null)
static getId($skipCreate=false)
Definition fuser.php:33
static roundPrecision($value)
static getInstance($type)
Definition registry.php:183