Bitrix-D7 23.9
 
Загрузка...
Поиск...
Не найдено
orderdiscountbase.php
1<?php
2namespace Bitrix\Sale;
3
6
7Loc::loadMessages(__FILE__);
8
9abstract class OrderDiscountBase
10{
11 const EVENT_ON_BUILD_DISCOUNT_PROVIDERS = 'onBuildDiscountProviders';
12
13 const ERROR_ID = 'BX_SALE_ORDER_DISCOUNT';
14
15 const PROVIDER_ACTION_PREPARE_DISCOUNT = 'prepareData';
16 const PROVIDER_ACTION_GET_URL = 'getEditUrl';
17 const PROVIDER_ACTION_APPLY_COUPON = 'calculateApplyCoupons';
20
21 const STORAGE_TYPE_DISCOUNT_ACTION_DATA = 'ACTION_DATA';
22 const STORAGE_TYPE_ORDER_CONFIG = 'ORDER_CONFIG';
23 const STORAGE_TYPE_ROUND_CONFIG = 'ROUND_CONFIG';
24 const STORAGE_TYPE_BASKET_ITEM = 'BASKET_ITEM';
25
26 protected static $init = false;
27 protected static $errors = array();
28 private static $discountProviders = array();
29 private static $managerConfig = array();
30
31 private static $discountCache = array();
32
38 public static function init()
39 {
40 if (self::$init)
41 return;
42
43 static::initDiscountProviders();
44 self::$init = true;
45 }
46
53 public static function setManagerConfig($config)
54 {
55 if (empty($config) || empty($config['SITE_ID']))
56 return false;
57 if (empty($config['CURRENCY']))
58 $config['CURRENCY'] = Internals\SiteCurrencyTable::getSiteCurrency($config['SITE_ID']);
59 if (!isset($config['USE_BASE_PRICE']) || ($config['USE_BASE_PRICE'] != 'Y' && $config['USE_BASE_PRICE'] != 'N'))
60 $config['USE_BASE_PRICE'] = ((string)Main\Config\Option::get('sale', 'get_discount_percent_from_base_price') == 'Y' ? 'Y' : 'N');
61 if (empty($config['BASKET_ITEM']))
62 $config['BASKET_ITEM'] = '$basketItem';
63 self::$managerConfig = $config;
64 return true;
65 }
66
72 public static function getManagerConfig()
73 {
74 return self::$managerConfig;
75 }
76
84 public static function saveDiscount(array $discount, $extResult = false)
85 {
86 static::init();
87 $result = new Result();
88
89 $extResult = ($extResult === true);
90
91 $process = true;
92
93 $internal = null;
94 $discountData = false;
95 $fields = false;
96 $emptyData = array(
97 'ID' => 0,
98 'DISCOUNT_ID' => 0,
99 'NAME' => '',
100 'ORDER_DISCOUNT_ID' => 0,
101 'ORDER_COUPON_ID' => 0,
102 'USE_COUPONS' => '',
103 'LAST_DISCOUNT' => '',
104 'MODULE_ID' => '',
105 'EDIT_PAGE_URL' => '',
106 'ACTIONS_DESCR' => array()
107 );
108 if ($extResult)
109 {
110 $emptyData['RAW_DATA'] = array();
111 $emptyData['PREPARED_DATA'] = array();
112 }
113 $resultData = $emptyData;
114
115 $config = static::getManagerConfig();
116
117 if (empty($config))
118 {
119 $process = false;
120 $result->addError(new Main\Entity\EntityError(
121 Loc::getMessage('SALE_ORDER_DISCOUNT_ERR_EMPTY_MANAGER_PARAMS'),
122 self::ERROR_ID
123 ));
124 }
125
126 if (empty($discount) || empty($discount['MODULE_ID']))
127 {
128 $process = false;
129 $result->addError(new Main\Entity\EntityError(
130 Loc::getMessage('SALE_ORDER_DISCOUNT_ERR_EMPTY_DISCOUNT'),
131 self::ERROR_ID
132 ));
133 }
134
135 if ($process)
136 {
137 if (!static::isNativeModule($discount['MODULE_ID']))
138 {
139 if (!static::checkDiscountProvider($discount['MODULE_ID']))
140 {
141 $process = false;
142 $result->addError(new Main\Entity\EntityError(
143 Loc::getMessage('SALE_ORDER_DISCOUNT_ERR_BAD_DISCOUNT_MODULE'),
144 self::ERROR_ID
145 ));
146 }
147 else
148 {
149 $discountData = static::executeDiscountProvider(
150 array('MODULE_ID' => $discount['MODULE_ID'], 'METHOD' => self::PROVIDER_ACTION_PREPARE_DISCOUNT),
151 array($discount, $config)
152 );
153 }
154 }
155 else
156 {
157 $discountData = static::prepareData($discount);
158 }
159 if (empty($discountData) || !is_array($discountData))
160 {
161 $process = false;
162 $result->addError(new Main\Entity\EntityError(
163 Loc::getMessage('SALE_ORDER_DISCOUNT_ERR_BAD_PREPARE_DISCOUNT'),
164 self::ERROR_ID
165 ));
166 }
167 }
168
169 if ($process)
170 {
171 $fields = static::normalizeDiscountFields($discountData);
172 if (empty($fields) || !is_array($fields))
173 {
174 $process = false;
175 $result->addError(new Main\Entity\EntityError(
176 Loc::getMessage('SALE_ORDER_DISCOUNT_ERR_BAD_PREPARE_DISCOUNT'),
177 self::ERROR_ID
178 ));
179 }
180 elseif ($fields['DISCOUNT_HASH'] === null)
181 {
182 $process = false;
183 $result->addError(new Main\Entity\EntityError(
184 Loc::getMessage('SALE_ORDER_DISCOUNT_ERR_BAD_DISCOUNT_HASH'),
185 self::ERROR_ID
186 ));
187 }
188 }
189
190 if ($process)
191 {
192 $existDiscount = static::searchDiscount($fields['DISCOUNT_HASH']);
193 if ($existDiscount === null)
194 {
196 $internalResult = static::addDiscount($fields, $discountData);
197 if ($internalResult->isSuccess())
198 {
199 $existDiscount = static::searchDiscount($fields['DISCOUNT_HASH']);
200 }
201 else
202 {
203 $process = false;
204 $result->addErrors($internalResult->getErrors());
205 }
206 unset($internalResult);
207 }
208 if ($existDiscount !== null)
209 {
210 $resultData = $existDiscount;
211 $result->setId($resultData['ID']);
212 }
213 }
214
215 if ($process)
216 {
217 $resultData['EDIT_PAGE_URL'] = $discountData['EDIT_PAGE_URL'];
218 if ($extResult)
219 {
220 $resultData['RAW_DATA'] = $discount;
221 $resultData['PREPARED_DATA'] = $discountData;
222 }
223 $result->setData($resultData);
224 }
225 unset($resultData, $process);
226
227 return $result;
228 }
229
236 public static function saveCoupon($coupon)
237 {
238 static::init();
239 $result = new Result();
240
241 $process = true;
242
243 $resultData = array(
244 'ID' => 0,
245 'ORDER_ID' => 0,
246 'ORDER_DISCOUNT_ID' => 0,
247 'COUPON' => '',
248 'TYPE' => 0,
249 'COUPON_ID' => 0,
250 'DATA' => array()
251 );
252
253 if (empty($coupon) || !is_array($coupon))
254 {
255 $process = false;
256 $result->addError(new Main\Entity\EntityError(
257 Loc::getMessage('SALE_ORDER_DISCOUNT_ERR_EMPTY_COUPON'),
258 self::ERROR_ID
259 ));
260 }
261 if ($process)
262 {
263 if (empty($coupon['ORDER_DISCOUNT_ID']) || (int)$coupon['ORDER_DISCOUNT_ID'] <= 0)
264 {
265 $process = false;
266 $result->addError(new Main\Entity\EntityError(
267 Loc::getMessage('SALE_ORDER_DISCOUNT_ERR_EMPTY_COUPON'),
268 self::ERROR_ID
269 ));
270 }
271 if (empty($coupon['COUPON']))
272 {
273 $process = false;
274 $result->addError(new Main\Entity\EntityError(
275 Loc::getMessage('SALE_ORDER_DISCOUNT_ERR_COUPON_CODE_ABSENT'),
276 self::ERROR_ID
277 ));
278 }
279 if (!isset($coupon['TYPE']))
280 {
281 $process = false;
282 $result->addError(new Main\Entity\EntityError(
284 'SALE_ORDER_DISCOUNT_ERR_COUPON_TYPE_ABSENT',
285 array('#COUPON#' => $coupon['COUPON'])
286 ),
287 self::ERROR_ID
288 ));
289 }
290 }
291
292 if ($process)
293 {
294 $validateResult = static::validateCoupon($coupon);
295 if (!$validateResult->isSuccess())
296 {
297 $process = false;
298 $result->addErrors($validateResult->getErrors());
299 }
300 unset($validateResult);
301 }
302
303 if ($process)
304 {
305 $iterator = static::getOrderCouponIterator(array(
306 'select' => array('*'),
307 'filter' => array('=COUPON' => $coupon['COUPON'], '=ORDER_ID' => $coupon['ORDER_ID'])
308 ));
309 if ($row = $iterator->fetch())
310 {
311 $resultData = $row;
312 }
313 else
314 {
315 $internalResult = static::addCoupon($coupon);
316 if ($internalResult->isSuccess())
317 {
318 $resultData = $internalResult->getData();
319 $resultData['ID'] = $internalResult->getId();
320 }
321 else
322 {
323 $process = false;
324 $result->addErrors($internalResult->getErrors());
325 }
326 unset($internalResult);
327 }
328 unset($row, $iterator);
329 }
330
331 if ($process)
332 {
333 $result->setId($resultData['ID']);
334 $result->setData($resultData);
335 }
336 unset($process, $resultData);
337
338 return $result;
339 }
340
350 public static function calculateApplyCoupons($module, $discount, $basket, $params)
351 {
352 static::init();
353
354 $module = (string)$module;
355 if (static::isNativeModule($module))
356 return false;
357
358 return static::executeDiscountProvider(
359 array('MODULE_ID' => $module, 'METHOD' => self::PROVIDER_ACTION_APPLY_COUPON),
360 array($discount, $basket, $params)
361 );
362 }
363
371 public static function roundPrice(array $basketItem, array $roundData = array())
372 {
373 static::init();
374
375 if (empty($basketItem))
376 return array();
377
378 $result = static::executeDiscountProvider(
379 array('MODULE_ID' => $basketItem['MODULE'], 'METHOD' => self::PROVIDER_ACTION_ROUND_ITEM_PRICE),
380 array($basketItem, $roundData)
381 );
382 if (empty($result))
383 return array();
384
385 if (!isset($result['PRICE']) || !isset($result['DISCOUNT_PRICE']))
386 return array();
387
388 if (!isset($result['ROUND_RULE']))
389 return array();
390
391 return $result;
392 }
393
402 public static function roundBasket(array $basket, array $roundData = array(), array $orderData = array())
403 {
404 static::init();
405
406 if (empty($basket))
407 return array();
408
409 $result = array();
410 $basketByModules = array();
411 $roundByModules = array();
412 foreach ($basket as $basketCode => $basketItem)
413 {
414 if (!isset($basketItem['MODULE']))
415 continue;
416 $module = $basketItem['MODULE'];
417 if (!isset($basketByModules[$module]))
418 {
419 $basketByModules[$module] = array();
420 $roundByModules[$module] = array();
421 }
422 $basketByModules[$module][$basketCode] = $basketItem;
423 $roundByModules[$module][$basketCode] = (isset($roundData[$basketCode]) ? $roundData[$basketCode] : array());
424 }
425 unset($basketCode, $basketItem);
426
427 foreach ($basketByModules as $module => $moduleItems)
428 {
429 $moduleResult = static::executeDiscountProvider(
430 array('MODULE_ID' => $module, 'METHOD' => self::PROVIDER_ACTION_ROUND_BASKET_PRICES),
431 array($moduleItems, $roundByModules[$module], $orderData)
432 );
433 if ($moduleResult === false)
434 {
435 $moduleResult = array();
436 foreach ($moduleItems as $basketCode => $basketItem)
437 {
438 $itemResult = static::roundPrice($basketItem, $roundByModules[$module][$basketCode]);
439 if (!empty($itemResult))
440 $moduleResult[$basketCode] = $itemResult;
441 }
442 }
443 if (empty($moduleResult))
444 continue;
445
446 foreach (array_keys($moduleResult) as $basketCode)
447 $result[$basketCode] = $moduleResult[$basketCode];
448 unset($moduleResult);
449 }
450 unset($moduleResult, $module, $moduleItems);
451
452 return $result;
453 }
454
461 public static function checkDiscountProvider($module)
462 {
463 static::init();
464 $module = (string)$module;
465 if (static::isNativeModule($module))
466 return true;
467 return ($module != '' && isset(self::$discountProviders[$module]));
468 }
469
476 public static function getEditUrl(array $discount)
477 {
478 $result = '';
479 if (!empty($discount['ID']))
480 $result = '/bitrix/admin/sale_discount_edit.php?lang='.LANGUAGE_ID.'&ID='.$discount['ID'];
481 return $result;
482 }
483
489 public static function clearCache()
490 {
491 $entity = get_called_class();
492 if (!isset(self::$discountCache[$entity]))
493 return;
494 unset(self::$discountCache[$entity]);
495 }
496
505 public static function loadResultFromDb($order, array $basketList = [], array $basketData = [])
506 {
507 static::init();
508 $result = new Result;
509
511 $discountClassName = static::getDiscountClassName();
512 $emptyApplyBlock = $discountClassName::getEmptyApplyBlock();
513
514 $order = (int)$order;
515 if ($order <= 0)
516 {
517 $result->addError(new Main\Entity\EntityError(
518 Loc::getMessage('SALE_ORDER_DISCOUNT_BAD_ORDER_ID'),
519 self::ERROR_ID
520 ));
521 return $result;
522 }
523 $resultData = [
524 'APPLY_BLOCKS' => [],
525 'DISCOUNT_LIST' => [],
526 'COUPON_LIST' => [],
527 'STORED_ACTION_DATA' => []
528 ];
529
530 $applyBlocks = [];
531
532 $orderDiscountIndex = [];
533 $orderDiscountLink = [];
534
535 $discountList = [];
536 $discountSort = [];
537 $couponList = [];
538
539 $resultData['COUPON_LIST'] = static::loadCouponsFromDb($order);
540 if (!empty($resultData['COUPON_LIST']))
541 {
542 foreach ($resultData['COUPON_LIST'] as $coupon)
543 $couponList[$coupon['ID']] = $coupon['COUPON'];
544 unset($coupon);
545 }
546
547 $ruleIterator = static::getResultIterator([
548 'filter' => ['=ORDER_ID' => $order],
549 'order' => ['ID' => 'ASC']
550 ]);
551 while ($rule = $ruleIterator->fetch())
552 {
553 $rule['ID'] = (int)$rule['ID'];
554 $rule['ORDER_DISCOUNT_ID'] = (int)$rule['ORDER_DISCOUNT_ID'];
555 $rule['ORDER_COUPON_ID'] = (int)$rule['COUPON_ID'];
556 $rule['ENTITY_ID'] = (int)$rule['ENTITY_ID'];
557
558 if ($rule['ORDER_COUPON_ID'] > 0)
559 {
560 if (!isset($couponList[$rule['COUPON_ID']]))
561 {
562 $result->addError(new Main\Entity\EntityError(
564 'SALE_ORDER_DISCOUNT_ERR_RULE_COUPON_NOT_FOUND',
565 array('#ID#' => $rule['ID'], '#COUPON_ID#' => $rule['COUPON_ID'])
566 )
567 ));
568 }
569 else
570 {
571 $rule['COUPON_ID'] = $couponList[$rule['ORDER_COUPON_ID']];
572 }
573 }
574 if (!isset($rule['RULE_DESCR_ID']))
575 $rule['RULE_DESCR_ID'] = 0;
576 $rule['RULE_DESCR_ID'] = (int)$rule['RULE_DESCR_ID'];
577
578 $rule['APPLY_BLOCK_COUNTER'] = (int)$rule['APPLY_BLOCK_COUNTER'];
579 $blockCounter = $rule['APPLY_BLOCK_COUNTER'];
580 if (!isset($applyBlocks[$blockCounter]))
581 $applyBlocks[$blockCounter] = $emptyApplyBlock;
582 if (!isset($orderDiscountIndex[$blockCounter]))
583 $orderDiscountIndex[$blockCounter] = 0;
584
585 if (!isset($discountList[$rule['ORDER_DISCOUNT_ID']]))
586 {
587 $discountList[$rule['ORDER_DISCOUNT_ID']] = $rule['ORDER_DISCOUNT_ID'];
588 $discountSort[] = $rule['ORDER_DISCOUNT_ID'];
589 }
590
591 if (static::isNativeModule($rule['MODULE_ID']))
592 {
593 $discountId = (int)$rule['ORDER_DISCOUNT_ID'];
594 if (!isset($orderDiscountLink[$discountId]))
595 {
596 $applyBlocks[$blockCounter]['ORDER'][$orderDiscountIndex[$blockCounter]] = static::formatSaleRuleResult($rule);
597 $orderDiscountLink[$discountId] = &$applyBlocks[$blockCounter]['ORDER'][$orderDiscountIndex[$blockCounter]];
598 $orderDiscountIndex[$blockCounter]++;
599 }
600
601 $ruleItem = static::formatSaleItemRuleResult($rule);
602
603 switch (static::getResultEntityFromInternal($rule['ENTITY_TYPE']))
604 {
605 case $discountClassName::ENTITY_BASKET_ITEM:
606 $index = static::transferEntityCodeFromInternal($rule, $basketList);
607 if ($index == '')
608 continue 2;
609
610 $ruleItem['BASKET_ID'] = static::transferEntityCodeFromInternal($rule, []);
611 static::fillRuleProductFields($ruleItem, $basketData, $index);
612 if (!isset($orderDiscountLink[$discountId]['RESULT']['BASKET']))
613 $orderDiscountLink[$discountId]['RESULT']['BASKET'] = [];
614 $orderDiscountLink[$discountId]['RESULT']['BASKET'][$index] = $ruleItem;
615 if ($ruleItem['ACTION_BLOCK_LIST'] === null)
616 $orderDiscountLink[$discountId]['ACTION_BLOCK_LIST'] = false;
617 break;
618 case $discountClassName::ENTITY_DELIVERY:
619 if (!isset($orderDiscountLink[$discountId]['RESULT']['DELIVERY']))
620 $orderDiscountLink[$discountId]['RESULT']['DELIVERY'] = [];
621 $ruleItem['DELIVERY_ID'] = static::transferEntityCodeFromInternal($rule, []);
622 $orderDiscountLink[$discountId]['RESULT']['DELIVERY'] = $ruleItem;
623 break;
624 }
625 unset($ruleItem, $discountId);
626 }
627 else
628 {
629 if (
630 $rule['ENTITY_ID'] <= 0
631 || static::getResultEntityFromInternal($rule['ENTITY_TYPE']) != $discountClassName::ENTITY_BASKET_ITEM
632 )
633 continue;
634
635 $index = static::transferEntityCodeFromInternal($rule, $basketList);
636 if ($index == '')
637 continue;
638
639 $ruleResult = static::formatBasketRuleResult($rule);
640 static::fillRuleProductFields($ruleResult, $basketData, $index);
641
642 if (!isset($applyBlocks[$blockCounter]['BASKET'][$index]))
643 $applyBlocks[$blockCounter]['BASKET'][$index] = [];
644 $applyBlocks[$blockCounter]['BASKET'][$index][] = $ruleResult;
645
646 unset($ruleResult);
647 }
648 }
649 unset($rule, $ruleIterator);
650 unset($couponList);
651 unset($orderDiscountLink, $orderDiscountIndex);
652
653 if (!empty($discountList))
654 {
655 $resultData['DISCOUNT_LIST'] = static::loadOrderDiscountFromDb($discountList, $discountSort);
656 if ($resultData['DISCOUNT_LIST'] === null)
657 $resultData['DISCOUNT_LIST'] = [];
658 }
659 unset($discountSort, $discountList);
660
661 $actionsData = static::loadOrderStoredDataFromDb(
662 $order,
663 self::STORAGE_TYPE_DISCOUNT_ACTION_DATA
664 );
665 if ($actionsData !== null)
666 $resultData['STORED_ACTION_DATA'] = $actionsData;
667 unset($actionsData);
668
669 $dataIterator = static::getRoundResultIterator([
670 'select' => ['*'],
671 'filter' => [
672 '=ORDER_ID' => $order,
673 '=ENTITY_TYPE' => static::getRoundEntityInternal($discountClassName::ENTITY_BASKET_ITEM)
674 ]
675 ]);
676 while ($data = $dataIterator->fetch())
677 {
678 $data['APPLY_BLOCK_COUNTER'] = (int)$data['APPLY_BLOCK_COUNTER'];
679 $blockCounter = $data['APPLY_BLOCK_COUNTER'];
680 if (!isset($applyBlocks[$blockCounter]))
681 $applyBlocks[$blockCounter] = $emptyApplyBlock;
682 $basketCode = static::transferEntityCodeFromInternal($data, $basketList);
683 if ($basketCode == '')
684 continue;
685
686 $applyBlocks[$blockCounter]['BASKET_ROUND'][$basketCode] = array(
687 'RULE_ID' => (int)$data['ID'],
688 'APPLY' => $data['APPLY'],
689 'ROUND_RULE' => $data['ROUND_RULE']
690 );
691 unset($basketCode, $blockCounter);
692 }
693 unset($data, $dataIterator);
694
695 if (!empty($applyBlocks))
696 ksort($applyBlocks);
697
698 $resultData['APPLY_BLOCKS'] = $applyBlocks;
699 unset($applyBlocks);
700
701 $result->setData($resultData);
702 unset($resultData);
703
704 unset($emptyApplyBlock, $discountClassName);
705
706 return $result;
707 }
708
716 protected static function loadOrderDiscountFromDb(array $discountIds, array $discountOrder)
717 {
718 if (empty($discountIds) || empty($discountOrder))
719 return null;
720
721 $result = [];
722 $list = [];
723 $iterator = static::getOrderDiscountIterator([
724 'select' => ['*'],
725 'filter' => ['@ID' => $discountIds]
726 ]);
727 while ($row = $iterator->fetch())
728 {
729 $row['ID'] = (int)$row['ID'];
730 $row['ORDER_DISCOUNT_ID'] = $row['ID'];
731 $row['MODULES'] = [];
732 $row['SIMPLE_ACTION'] = true;
733 if (static::isNativeModule($row['MODULE_ID']))
734 $row['SIMPLE_ACTION'] = self::isSimpleAction($row['APPLICATION']);
735 $list[$row['ID']] = $row;
736 }
737 unset($row, $iterator);
738
739 if (!empty($list))
740 {
741 foreach ($discountOrder as $id)
742 {
743 if (!isset($list[$id]))
744 continue;
745 $result[$id] = $list[$id];
746 }
747 unset($id);
748 }
749 unset($list);
750
751 if (!empty($result))
752 {
753 $resultIds = array_keys($result);
754 $discountModules = static::loadModulesFromDb($resultIds);
755 if ($discountModules !== null)
756 {
757 foreach ($discountModules as $id => $modules)
758 $result[$id]['MODULES'] = $modules;
759 unset($id, $modules);
760 }
761 unset($discountModules);
762
763 foreach ($resultIds as $id)
764 {
765 $discount = $result[$id];
766 if (static::isNativeModule($discount['MODULE_ID']))
767 {
768 $result[$id]['EDIT_PAGE_URL'] = static::getEditUrl(['ID' => $discount['DISCOUNT_ID']]);
769 }
770 else
771 {
772 $result[$id]['EDIT_PAGE_URL'] = (string)static::executeDiscountProvider(
773 ['MODULE_ID' => $discount['MODULE_ID'], 'METHOD' => self::PROVIDER_ACTION_GET_URL],
774 [
775 ['ID' => $discount['DISCOUNT_ID'], 'MODULE_ID' => $discount['MODULE_ID']]
776 ]
777 );
778 }
779 }
780 unset($discount, $id);
781 }
782
783 return (!empty($result) ? $result : null);
784 }
785
795 public static function loadStoredDataFromDb($order, $storageType, array $additionalFilter = array())
796 {
797 $result = null;
798
799 $order = (int)$order;
800 if ($order <= 0)
801 return $result;
802
803 $storageType = static::getStorageTypeInternal($storageType);
804 if ($storageType === null)
805 return $result;
806 $filter = [
807 '=ORDER_ID' => $order,
808 '=ENTITY_TYPE' => $storageType,
809 ];
810 if (!empty($additionalFilter))
811 $filter = $filter + $additionalFilter;
812
813 $list = [];
814 $iterator = static::getStoredDataIterator(array(
815 'select' => ['*'],
816 'filter' => $filter
817 ));
818 while ($row = $iterator->fetch())
819 {
820 if (empty($row['ENTITY_DATA']) || !is_array($row['ENTITY_DATA']))
821 continue;
822 $index = static::getEntityIndex($row);
823 $list[$index] = $row['ENTITY_DATA'];
824 }
825 unset($index, $row, $iterator);
826 if (!empty($list))
827 $result = $list;
828 unset($list);
829
830 return $result;
831 }
832
841 public static function loadOrderStoredDataFromDb($order, $storageType)
842 {
843 $result = null;
844
845 $data = static::loadStoredDataFromDb(
846 $order,
847 $storageType,
848 ['=ENTITY_ID' => $order]
849 );
850 if ($data === null)
851 return $result;
852 if (count($data) > 1)
853 return $result;
854 if (isset($data[$order]))
855 $result = $data[$order];
856 unset($data);
857
858 return $result;
859 }
860
870 public static function saveOrderStoredData($order, $storageType, array $data, array $options = array())
871 {
872 return static::saveStoredDataBlock(
873 $order,
874 $storageType,
875 [$order => [
876 'ENTITY_ID' => $order,
877 'ENTITY_VALUE' => $order,
878 'ENTITY_DATA' => $data
879 ]],
880 $options
881 );
882 }
883
894 public static function saveStoredDataBlock($order, $storageType, array $block, array $options = array())
895 {
896 $result = new Result;
897
898 $order = (int)$order;
899 if ($order <= 0)
900 {
901 $result->addError(new Main\Error(
902 Loc::getMessage('SALE_ORDER_DISCOUNT_ERR_BAD_ORDER_ID'),
903 self::ERROR_ID
904 ));
905 return $result;
906 }
907
908 $storageType = static::getStorageTypeInternal($storageType);
909 if ($storageType === null)
910 {
911 $result->addError(new Main\Error(
912 Loc::getMessage('SALE_ORDER_DISCOUNT_ERR_BAD_STORAGE_TYPE'),
913 self::ERROR_ID
914 ));
915 return $result;
916 }
917
918 $allowUpdate = (isset($options['ALLOW_UPDATE']) && $options['ALLOW_UPDATE'] === 'Y');
919 $deleteMissing = (isset($options['DELETE_MISSING']) && $options['DELETE_MISSING'] === 'Y');
920
921 $collection = [];
922 $deleteList = [];
923 $iterator = static::getStoredDataIterator([
924 'select' => ['*'],
925 'filter' => [
926 '=ORDER_ID' => $order,
927 '=ENTITY_TYPE' => $storageType,
928 ]
929 ]);
930 while ($row = $iterator->fetch())
931 {
932 $index = static::getEntityIndex($row);
933 $collection[$index] = $row;
934 $deleteList[$index] = $row['ID'];
935 }
936 unset($row, $iterator);
937
938 $existError = false;
939 foreach ($block as $index => $row)
940 {
941 if (isset($deleteList[$index]))
942 unset($deleteList[$index]);
943 if (!empty($collection[$index]) && !$allowUpdate)
944 {
945 $existError = true;
946 continue;
947 }
948 if (empty($collection[$index]))
949 {
950 $row['ORDER_ID'] = $order;
951 $row['ENTITY_TYPE'] = $storageType;
952 $resultInternal = static::addStoredDataInternal($row);
953 }
954 else
955 {
956 $resultInternal = static::updateStoredDataInternal(
957 $collection[$index]['ID'],
958 ['ENTITY_DATA' => $row['ENTITY_DATA']]
959 );
960 }
961 if (!$resultInternal->isSuccess())
962 $result->addErrors($resultInternal->getErrors());
963 }
964 unset($resultInternal, $index, $row);
965
966 if ($existError)
967 {
968 $result->addError(new Main\Error(
969 Loc::getMessage('SALE_ORDER_DISCOUNT_ERR_ORDER_STORED_DATA_ALREADY_EXISTS'),
970 self::ERROR_ID
971 ));
972 }
973 unset($existError);
974
975 if ($result->isSuccess())
976 {
977 if ($deleteMissing && !empty($deleteList))
978 static::deleteRowsByIndex(static::getStoredDataTableInternal(), 'ID', $deleteList);
979 }
980 unset($deleteList, $deleteMissing);
981
982 return $result;
983 }
984
985 public static function addResultBlock($order, array $block)
986 {
987 $result = new Result();
988
989 $order = (int)$order;
990 if ($order <= 0)
991 {
992 $result->addError(new Main\Error(
993 Loc::getMessage('SALE_ORDER_DISCOUNT_ERR_BAD_ORDER_ID'),
994 self::ERROR_ID
995 ));
996 return $result;
997 }
998
999 if (empty($block))
1000 return $result;
1001
1002 foreach ($block as $row)
1003 {
1004 $row['ORDER_ID'] = $order;
1005 $row['ENTITY_TYPE'] = static::getResultEntityInternal($row['ENTITY_TYPE']);
1006 if (!isset($row['APPLY_BLOCK_COUNTER']) || $row['APPLY_BLOCK_COUNTER'] < 0)
1007 {
1008 $result->addError(new Main\Entity\EntityError(
1009 Loc::getMessage('SALE_ORDER_DISCOUNT_ERR_BAD_APPLY_BLOCK_COUNTER')
1010 ));
1011 return $result;
1012 }
1013 $resultInternal = static::addResultRow($row);
1014 if (!$resultInternal->isSuccess())
1015 $result->addErrors($resultInternal->getErrors());
1016 }
1017 unset($resultInternal, $row);
1018
1019 return $result;
1020 }
1021
1022 public static function updateResultBlock($order, array $block)
1023 {
1024 $result = new Result();
1025
1026 $order = (int)$order;
1027 if ($order <= 0)
1028 {
1029 $result->addError(new Main\Error(
1030 Loc::getMessage('SALE_ORDER_DISCOUNT_ERR_BAD_ORDER_ID'),
1031 self::ERROR_ID
1032 ));
1033 return $result;
1034 }
1035
1036 $deleteList = array();
1037 $iterator = static::getResultIterator(array(
1038 'select' => array('ID'),
1039 'filter' => array('=ORDER_ID' => $order),
1040 'order' => array('ID' => 'ASC')
1041 ));
1042 while ($row = $iterator->fetch())
1043 {
1044 $row['ID'] = (int)$row['ID'];
1045 $deleteList[$row['ID']] = $row['ID'];
1046 }
1047 unset($row, $iterator);
1048
1049 if (!empty($block))
1050 {
1051 foreach ($block as $row)
1052 {
1053 $id = null;
1054 if (isset($row['RULE_ID']) && $row['RULE_ID'] > 0)
1055 $id = $row['RULE_ID'];
1056 unset($row['RULE_ID']);
1057 if ($id === null)
1058 {
1059 $result->addError(new Main\Error(
1060 Loc::getMessage('SALE_ORDER_DISCOUNT_ERR_RESULT_ROW_ID_IS_ABSENT'),
1061 self::ERROR_ID
1062 ));
1063 continue;
1064 }
1065 if (!isset($deleteList[$id]))
1066 {
1067 $result->addError(new Main\Error(
1068 Loc::getMessage('SALE_ORDER_DISCOUNT_ERR_BAD_RESULT_ROW_ID'),
1069 self::ERROR_ID
1070 ));
1071 continue;
1072 }
1073 unset($deleteList[$id]);
1074
1075 $resultInternal = static::updateResultRow($id, $row);
1076 if (!$resultInternal->isSuccess())
1077 $result->addErrors($resultInternal->getErrors());
1078 }
1079 unset($resultInternal, $row);
1080 }
1081
1082 if (!$result->isSuccess())
1083 return $result;
1084
1085 if (!empty($deleteList))
1086 {
1087 self::deleteRowsByIndex(static::getResultTableNameInternal(), 'ID', $deleteList);
1088 self::deleteRowsByIndex(static::getResultDescriptionTableNameInternal(), 'RULE_ID', $deleteList);
1089 }
1090
1091 return $result;
1092 }
1093
1094 public static function addRoundBlock($order, array $block)
1095 {
1096 $result = new Result();
1097
1098 $order = (int)$order;
1099 if ($order <= 0)
1100 {
1101 $result->addError(new Main\Error(
1102 Loc::getMessage('SALE_ORDER_DISCOUNT_ERR_BAD_ORDER_ID'),
1103 self::ERROR_ID
1104 ));
1105 return $result;
1106 }
1107
1108 if (empty($block))
1109 return $result;
1110
1111 foreach ($block as $row)
1112 {
1113 $row['ORDER_ID'] = $order;
1114 $row['ENTITY_TYPE'] = static::getRoundEntityInternal($row['ENTITY_TYPE']);
1115 $row['ORDER_ROUND'] = 'N';
1116 if (!isset($row['APPLY_BLOCK_COUNTER']) || $row['APPLY_BLOCK_COUNTER'] < 0)
1117 {
1118 $result->addError(new Main\Entity\EntityError(
1119 Loc::getMessage('SALE_ORDER_DISCOUNT_ERR_BAD_APPLY_BLOCK_COUNTER')
1120 ));
1121 return $result;
1122 }
1123 $resultInternal = static::addRoundResultInternal($row);
1124 if (!$resultInternal->isSuccess())
1125 $result->addErrors($resultInternal->getErrors());
1126 }
1127 unset($resultInternal, $row);
1128
1129 return $result;
1130 }
1131
1132 public static function updateRoundBlock($order, array $block)
1133 {
1134 $result = new Result();
1135
1136 $order = (int)$order;
1137 if ($order <= 0)
1138 {
1139 $result->addError(new Main\Error(
1140 Loc::getMessage('SALE_ORDER_DISCOUNT_ERR_BAD_ORDER_ID'),
1141 self::ERROR_ID
1142 ));
1143 return $result;
1144 }
1145
1146 $deleteList = array();
1147 $iterator = static::getRoundResultIterator([
1148 'select' => ['ID'],
1149 'filter' => ['=ORDER_ID' => $order]
1150 ]);
1151 while ($row = $iterator->fetch())
1152 {
1153 $row['ID'] = (int)$row['ID'];
1154 $deleteList[$row['ID']] = $row['ID'];
1155 }
1156 unset($row, $iterator);
1157
1158 if (!empty($block))
1159 {
1160 foreach ($block as $row)
1161 {
1162 $id = null;
1163 if (isset($row['RULE_ID']) && $row['RULE_ID'] > 0)
1164 $id = $row['RULE_ID'];
1165 if ($id === null)
1166 {
1167 $result->addError(new Main\Error(
1168 Loc::getMessage('SALE_ORDER_DISCOUNT_ERR_ROUND_ROW_ID_IS_ABSENT'),
1169 self::ERROR_ID
1170 ));
1171 continue;
1172 }
1173 if (!isset($deleteList[$id]))
1174 {
1175 $result->addError(new Main\Error(
1176 Loc::getMessage('SALE_ORDER_DISCOUNT_ERR_BAD_ROUND_ROW_ID'),
1177 self::ERROR_ID
1178 ));
1179 continue;
1180 }
1181 unset($deleteList[$id]);
1182
1183 unset($row['RULE_ID']);
1184 $resultInternal = static::updateRoundResultInternal($id, $row);
1185 if (!$resultInternal->isSuccess())
1186 $result->addErrors($resultInternal->getErrors());
1187 }
1188 unset($resultInternal, $row);
1189 }
1190
1191 if (!$result->isSuccess())
1192 return $result;
1193
1194 if (!empty($deleteList))
1195 self::deleteRowsByIndex(static::getRoundTableNameInternal(), 'ID', $deleteList);
1196
1197 return $result;
1198 }
1199
1206 public static function deleteByOrder($order) {}
1207
1215 public static function getRegistryType()
1216 {
1217 throw new Main\NotImplementedException();
1218 }
1219
1220 protected static function getDiscountClassName()
1221 {
1222 $registry = Registry::getInstance(static::getRegistryType());
1223 return $registry->getDiscountClassName();
1224 }
1225
1232 protected static function isNativeModule($module)
1233 {
1234 return ($module === 'sale');
1235 }
1236
1242 protected static function getDiscountProviderActions()
1243 {
1244 return array(
1245 self::PROVIDER_ACTION_PREPARE_DISCOUNT,
1246 self::PROVIDER_ACTION_GET_URL,
1247 self::PROVIDER_ACTION_APPLY_COUPON,
1248 self::PROVIDER_ACTION_ROUND_ITEM_PRICE,
1249 self::PROVIDER_ACTION_ROUND_BASKET_PRICES
1250 );
1251 }
1252
1258 protected static function initDiscountProviders()
1259 {
1260 self::$discountProviders = array();
1261 $event = new Main\Event('sale', self::EVENT_ON_BUILD_DISCOUNT_PROVIDERS, array());
1262 $event->send();
1263 $resultList = $event->getResults();
1264 if (empty($resultList) || !is_array($resultList))
1265 return;
1266 $actionList = static::getDiscountProviderActions();
1268 foreach ($resultList as $eventResult)
1269 {
1270 if ($eventResult->getType() != Main\EventResult::SUCCESS)
1271 continue;
1272 $module = (string)$eventResult->getModuleId();
1273 $provider = $eventResult->getParameters();
1274 if (empty($provider) || !is_array($provider))
1275 continue;
1276 if (!isset($provider[self::PROVIDER_ACTION_PREPARE_DISCOUNT]))
1277 continue;
1278 self::$discountProviders[$module] = array(
1279 'module' => $module
1280 );
1281 foreach ($actionList as $action)
1282 {
1283 if (isset($provider[$action]))
1284 self::$discountProviders[$module][$action] = $provider[$action];
1285 }
1286 }
1287 unset($provider, $module, $actionList, $eventResult, $resultList, $event);
1288 }
1289
1302 protected static function executeDiscountProvider(array $provider, array $data)
1303 {
1304 $module = $provider['MODULE_ID'];
1305 $method = $provider['METHOD'];
1306
1307 if (!isset(self::$discountProviders[$module]) || !isset(self::$discountProviders[$module][$method]))
1308 return false;
1309
1310 return call_user_func_array(
1311 self::$discountProviders[$module][$method],
1312 $data
1313 );
1314 }
1315
1322 protected static function prepareData($discount)
1323 {
1324 $fields = static::fillAbsentDiscountFields($discount);
1325 if ($fields === null)
1326 return false;
1327
1328 $discountId = (int)$fields['ID'];
1329 if (!isset($fields['NAME']) || (string)$fields['NAME'] == '')
1330 $fields['NAME'] = Loc::getMessage('SALE_ORDER_DISCOUNT_NAME_TEMPLATE', array('#ID#' => $fields['ID']));
1331 $fields['DISCOUNT_ID'] = $discountId;
1332 $fields['EDIT_PAGE_URL'] = static::getEditUrl(array('ID' => $discountId));
1333 unset($fields['ID']);
1334
1335 return $fields;
1336 }
1337
1344 protected static function fillAbsentDiscountFields(array $fields)
1345 {
1346 if (empty($fields) || empty($fields['ID']))
1347 return null;
1348
1349 $discountId = (int)$fields['ID'];
1350 if ($discountId <= 0)
1351 return null;
1352
1353 $requiredFields = static::checkRequiredOrderDiscountFields($fields);
1354 if (!empty($requiredFields))
1355 {
1356 if (in_array('ACTIONS_DESCR', $requiredFields))
1357 return null;
1358 $requiredFields[] = 'ID';
1359 $iterator = static::getDiscountIterator(array(
1360 'select' => $requiredFields,
1361 'filter' => array('=ID' => $discountId)
1362 ));
1363 $row = $iterator->fetch();
1364 unset($iterator);
1365 if (empty($row))
1366 return null;
1367 foreach ($row as $field => $value)
1368 {
1369 if (isset($fields[$field]))
1370 continue;
1371 $fields[$field] = $value;
1372 }
1373 unset($field, $value);
1374 }
1375 unset($requiredFields);
1376
1377 return $fields;
1378 }
1379
1386 protected static function normalizeDiscountFields(array $rawFields)
1387 {
1388 $result = static::normalizeOrderDiscountFieldsInternal($rawFields);
1389 if (!is_array($result))
1390 return null;
1391 $result['DISCOUNT_HASH'] = static::calculateOrderDiscountHashInternal($result);
1392 return $result;
1393 }
1394
1401 protected static function searchDiscount($hash)
1402 {
1403 $hash = (string)$hash;
1404 if ($hash === '')
1405 return null;
1406 $entity = get_called_class();
1407 if (!isset(self::$discountCache[$entity]))
1408 self::$discountCache[$entity] = array();
1409 if (!isset(self::$discountCache[$entity][$hash]))
1410 {
1411 $iterator = static::getOrderDiscountIterator(array(
1412 'select' => array('*'),
1413 'filter' => array('=DISCOUNT_HASH' => $hash)
1414 ));
1415 $row = $iterator->fetch();
1416 if (!empty($row))
1417 self::setCacheItem($entity, $row);
1418 unset($row, $iterator);
1419 }
1420
1421 return (isset(self::$discountCache[$entity][$hash]) ? self::$discountCache[$entity][$hash] : null);
1422 }
1423
1431 private static function setCacheItem($entity, array $fields)
1432 {
1433 $fields['ID'] = (int)$fields['ID'];
1434 $fields['NAME'] = (string)$fields['NAME'];
1435 $fields['ORDER_DISCOUNT_ID'] = $fields['ID'];
1436 self::$discountCache[$entity][$fields['DISCOUNT_HASH']] = $fields;
1437 }
1438
1445 protected static function validateCoupon(array $fields)
1446 {
1447 $result = new Result();
1448
1449 if (
1450 !static::isValidCouponTypeInternal($fields['TYPE'])
1451 )
1452 {
1453 $result->addError(new Main\Entity\EntityError(
1455 'SALE_ORDER_DISCOUNT_ERR_COUPON_TYPE_BAD',
1456 array('#COUPON#' => $fields['COUPON'])
1457 ),
1458 self::ERROR_ID
1459 ));
1460 }
1461
1462 if (empty($fields['COUPON_ID']) || (int)$fields['COUPON_ID'] <= 0)
1463 {
1464 $result->addError(new Main\Entity\EntityError(
1466 'SALE_ORDER_DISCOUNT_ERR_COUPON_ID_BAD',
1467 array('#COUPON#' => $fields['COUPON'])
1468 ),
1469 self::ERROR_ID
1470 ));
1471 }
1472
1473 return $result;
1474 }
1475
1482 protected static function addCoupon(array $fields)
1483 {
1484 $result = new Result();
1485
1486 if (array_key_exists('ID', $fields))
1487 unset($fields['ID']);
1488 $tabletResult = static::addOrderCouponInternal($fields);
1489 if ($tabletResult->isSuccess())
1490 {
1491 $fields['ID'] = $tabletResult->getId();
1492 $result->setId($fields['ID']);
1493 $result->setData($fields);
1494 }
1495 else
1496 {
1497 $result->addErrors($tabletResult->getErrors());
1498 }
1499 unset($tabletResult);
1500
1501 return $result;
1502 }
1503
1511 protected static function addDiscount(array $fields, array $rawFields)
1512 {
1513 $result = new Result;
1514
1515 $process = true;
1516 $orderDiscountId = null;
1517
1518 $tabletResult = static::addOrderDiscountInternal($fields);
1519 if ($tabletResult->isSuccess())
1520 {
1521 $orderDiscountId = (int)$tabletResult->getId();
1522 }
1523 else
1524 {
1525 $process = false;
1526 $result->addErrors($tabletResult->getErrors());
1527 }
1528 unset($tabletResult);
1529
1530 if ($process)
1531 {
1532 $moduleList = static::prepareDiscountModules($rawFields);
1533 if (!empty($moduleList))
1534 {
1535 $resultModule = static::saveOrderDiscountModulesInternal(
1536 $orderDiscountId,
1537 $moduleList
1538 );
1539 if (!$resultModule)
1540 {
1541 $process = false;
1542 $result->addError(new Main\Entity\EntityError(
1543 Loc::getMessage('SALE_ORDER_DISCOUNT_ERR_SAVE_DISCOUNT_MODULES'),
1544 self::ERROR_ID
1545 ));
1546 }
1547 unset($resultModule);
1548 }
1549 unset($moduleList);
1550 }
1551
1552 if ($process)
1553 $result->setId($orderDiscountId);
1554
1555 return $result;
1556 }
1557
1564 protected static function loadModulesFromDb(array $discountIds)
1565 {
1566 if (empty($discountIds))
1567 return null;
1568
1569 Main\Type\Collection::normalizeArrayValuesByInt($discountIds, true);
1570 if (empty($discountIds))
1571 return null;
1572
1573 $result = array();
1574 $iterator = static::getOrderDiscountModuleIterator(array(
1575 'select' => array('MODULE_ID', 'ORDER_DISCOUNT_ID'),
1576 'filter' => array('@ORDER_DISCOUNT_ID' => $discountIds)
1577 ));
1578 while ($row = $iterator->fetch())
1579 {
1580 $orderDiscountId = (int)$row['ORDER_DISCOUNT_ID'];
1581 if (!isset($result[$orderDiscountId]))
1582 $result[$orderDiscountId] = array();
1583 $result[$orderDiscountId][] = $row['MODULE_ID'];
1584 }
1585 unset($row, $iterator);
1586
1587 return (!empty($result) ? $result : null);
1588 }
1589
1590 protected static function prepareDiscountModules(array $discount)
1591 {
1592 $result = array();
1593 $needDiscountModules = array();
1594 if (!empty($discount['MODULES']))
1595 {
1596 $needDiscountModules = (
1597 !is_array($discount['MODULES'])
1598 ? array($discount['MODULES'])
1599 : $discount['MODULES']
1600 );
1601 }
1602 elseif (!empty($discount['HANDLERS']))
1603 {
1604 if (!empty($discount['HANDLERS']['MODULES']))
1605 {
1606 $needDiscountModules = (
1607 !is_array($discount['HANDLERS']['MODULES'])
1608 ? array($discount['HANDLERS']['MODULES'])
1609 : $discount['HANDLERS']['MODULES']
1610 );
1611 }
1612 }
1613 if (!empty($needDiscountModules))
1614 {
1615 foreach ($needDiscountModules as &$module)
1616 {
1617 $module = trim((string)$module);
1618 if (!empty($module))
1619 $result[$module] = $module;
1620 }
1621 unset($module);
1622 $result = array_values($result);
1623 }
1624 return $result;
1625 }
1626
1634 protected static function transferEntityCodeFromInternal(array $row, array $transferList)
1635 {
1636 $code = '';
1637 if (empty($row))
1638 return $code;
1639 $row['ENTITY_VALUE'] = (string)$row['ENTITY_VALUE'];
1640 if (!empty($transferList))
1641 {
1642 if ($row['ENTITY_ID'] > 0 && isset($transferList[$row['ENTITY_ID']]))
1643 $code = $transferList[$row['ENTITY_ID']];
1644 elseif ($row['ENTITY_VALUE'] !== '' && isset($transferList[$row['ENTITY_VALUE']]))
1645 $code = $transferList[$row['ENTITY_VALUE']];
1646 }
1647 else
1648 {
1649 $code = ($row['ENTITY_ID'] > 0 ? $row['ENTITY_ID'] : $row['ENTITY_VALUE']);
1650 }
1651 return $code;
1652 }
1653
1660 protected static function formatBasketRuleResult(array $rule)
1661 {
1662 $ruleResult = [
1663 'BASKET_ID' => $rule['ENTITY_ID'],
1664 'RULE_ID' => $rule['ID'],
1665 'ORDER_ID' => $rule['ORDER_ID'],
1666 'DISCOUNT_ID' => $rule['ORDER_DISCOUNT_ID'],
1667 'ORDER_COUPON_ID' => $rule['ORDER_COUPON_ID'],
1668 'COUPON_ID' => ($rule['ORDER_COUPON_ID'] > 0 ? $rule['COUPON_ID'] : ''),
1669 'RESULT' => ['APPLY' => $rule['APPLY']],
1670 'RULE_DESCR_ID' => $rule['RULE_DESCR_ID'],
1671 'ACTION_BLOCK_LIST' => (isset($rule['ACTION_BLOCK_LIST']) ? $rule['ACTION_BLOCK_LIST'] : null)
1672 ];
1673
1674 if (!empty($rule['RULE_DESCR']) && is_array($rule['RULE_DESCR']))
1675 {
1676 $ruleResult['RESULT']['DESCR_DATA'] = $rule['RULE_DESCR'];
1677 $ruleResult['RESULT']['DESCR'] = Discount\Formatter::formatList($rule['RULE_DESCR']);
1678 $ruleResult['DESCR_ID'] = $rule['RULE_DESCR_ID'];
1679 }
1680
1681 return $ruleResult;
1682 }
1683
1690 protected static function formatSaleRuleResult(array $rule)
1691 {
1692 return [
1693 'ORDER_ID' => $rule['ORDER_ID'],
1694 'DISCOUNT_ID' => $rule['ORDER_DISCOUNT_ID'],
1695 'ORDER_COUPON_ID' => $rule['ORDER_COUPON_ID'],
1696 'COUPON_ID' => ($rule['ORDER_COUPON_ID'] > 0 ? $rule['COUPON_ID'] : ''),
1697 'RESULT' => [],
1698 'ACTION_BLOCK_LIST' => true
1699 ];
1700 }
1701
1708 protected static function formatSaleItemRuleResult(array $rule)
1709 {
1710 $ruleItem = array(
1711 'RULE_ID' => $rule['ID'],
1712 'APPLY' => $rule['APPLY'],
1713 'RULE_DESCR_ID' => $rule['RULE_DESCR_ID'],
1714 'ACTION_BLOCK_LIST' => (
1715 !empty($rule['ACTION_BLOCK_LIST']) && is_array($rule['ACTION_BLOCK_LIST'])
1716 ? $rule['ACTION_BLOCK_LIST']
1717 : null
1718 )
1719 );
1720 if (!empty($rule['RULE_DESCR']) && is_array($rule['RULE_DESCR']))
1721 {
1722 $ruleItem['DESCR_DATA'] = $rule['RULE_DESCR'];
1723 $ruleItem['DESCR'] = Discount\Formatter::formatList($rule['RULE_DESCR']);
1724 $ruleItem['DESCR_ID'] = $rule['RULE_DESCR_ID'];
1725 }
1726
1727 return $ruleItem;
1728 }
1729
1738 protected static function fillRuleProductFields(array &$result, array $basketData, $index)
1739 {
1740 if (!empty($basketData[$index]))
1741 {
1742 $result['MODULE'] = $basketData[$index]['MODULE'];
1743 $result['PRODUCT_ID'] = $basketData[$index]['PRODUCT_ID'];
1744 }
1745 }
1746
1747 /* discounts */
1748
1755 protected static function getDiscountIterator(array $parameters)
1756 {
1757 return null;
1758 }
1759
1760 /* discounts end */
1761
1762 /* coupons */
1763
1770 protected static function isValidCouponTypeInternal($type)
1771 {
1772 return false;
1773 }
1774
1775 /* coupons end */
1776
1777 /* order discounts */
1778
1785 protected static function getOrderDiscountIterator(array $parameters)
1786 {
1787 return null;
1788 }
1789
1796 protected static function addOrderDiscountInternal(array $fields)
1797 {
1798 return null;
1799 }
1800
1807 protected static function checkRequiredOrderDiscountFields(array $fields)
1808 {
1809 return [];
1810 }
1811
1818 protected static function normalizeOrderDiscountFieldsInternal(array $rawFields)
1819 {
1820 return null;
1821 }
1822
1829 protected static function calculateOrderDiscountHashInternal(array $fields)
1830 {
1831 return null;
1832 }
1833
1834 /* order discounts end */
1835
1836 /* order coupons */
1843 public static function getOrderCouponIterator(array $parameters)
1844 {
1845 return null;
1846 }
1847
1854 protected static function addOrderCouponInternal(array $fields)
1855 {
1856 return null;
1857 }
1858
1865 protected static function loadCouponsFromDb($order)
1866 {
1867 $result = array();
1868
1869 $couponIterator = static::getOrderCouponIterator(array(
1870 'select' => array('*'),
1871 'filter' => array('=ORDER_ID' => $order),
1872 'order' => array('ID' => 'ASC')
1873 ));
1874 while ($coupon = $couponIterator->fetch())
1875 {
1876 $coupon['ID'] = (int)$coupon['ID'];
1877 $coupon['ORDER_ID'] = (int)$coupon['ORDER_ID'];
1878 $coupon['ORDER_DISCOUNT_ID'] = (int)$coupon['ORDER_DISCOUNT_ID'];
1879 $result[$coupon['COUPON']] = $coupon;
1880 }
1881 unset($coupon, $couponIterator);
1882
1883 return $result;
1884 }
1885
1886 /* order coupons end */
1887
1888 /* order discount modules */
1889
1894 protected static function getOrderDiscountModuleIterator(array $parameters)
1895 {
1896 return null;
1897 }
1898
1906 protected static function saveOrderDiscountModulesInternal($orderDiscountId, array $modules)
1907 {
1908 return false;
1909 }
1910
1911 /* order discount modules end */
1912
1913 /* discount results */
1914
1921 protected static function getResultEntityInternal($entity)
1922 {
1923 return null;
1924 }
1925
1932 protected static function getResultEntityFromInternal($entity)
1933 {
1934 return null;
1935 }
1936
1941 protected static function getResultIterator(array $parameters)
1942 {
1943 return null;
1944 }
1945
1950 protected static function getResultDescriptionIterator(array $parameters)
1951 {
1952 return null;
1953 }
1954
1961 protected static function addResultRow(array $fields)
1962 {
1963 if (array_key_exists('ID', $fields))
1964 unset($fields['ID']);
1965 $resultFields = static::checkResultTableWhiteList($fields);
1966 if (empty($resultFields))
1967 {
1968 $result = new Main\Entity\AddResult();
1969 $result->addError(new Main\Entity\EntityError(
1970 Loc::getMessage('SALE_ORDER_DISCOUNT_ERR_RESULT_ROW_IS_EMPTY')
1971 ));
1972 return $result;
1973 }
1974 $result = static::addResultInternal($resultFields);
1975 unset($resultFields);
1976 if (!$result->isSuccess())
1977 return $result;
1978
1979 $fields['RULE_ID'] = (int)$result->getId();
1980 $descriptionFields = static::checkResultDescriptionTableWhiteList($fields);
1981 if (empty($descriptionFields))
1982 {
1983 $result->addError(new Main\Entity\EntityError(
1984 Loc::getMessage('SALE_ORDER_DISCOUNT_ERR_RESULT_ROW_DESCRIPTION_IS_EMPTY')
1985 ));
1986 return $result;
1987 }
1988 $descriptionResult = static::addResultDescriptionInternal($descriptionFields);
1989 unset($descriptionFields);
1990 if (!$descriptionResult->isSuccess())
1991 $result->addErrors($descriptionResult->getErrors());
1992 unset($descriptionResult);
1993
1994 return $result;
1995 }
1996
2004 protected static function updateResultRow($id, array $fields)
2005 {
2006 $rowUpdate = ['APPLY' => $fields['APPLY']];
2007 if (isset($fields['ACTION_BLOCK_LIST']))
2008 $rowUpdate['ACTION_BLOCK_LIST'] = $fields['ACTION_BLOCK_LIST'];
2009 $result = static::updateResultInternal($id, $rowUpdate);
2010 unset($rowUpdate);
2011 if (!$result->isSuccess())
2012 return $result;
2013
2014 $descrId = null;
2015 if (isset($fields['DESCR_ID']) && $fields['DESCR_ID'] > 0)
2016 $descrId = $fields['DESCR_ID'];
2017 if ($descrId === null)
2018 {
2019 $iterator = static::getResultDescriptionIterator([
2020 'select' => ['ID'],
2021 'filter' => ['=RULE_ID' => $id]
2022 ]);
2023 $row = $iterator->fetch();
2024 if (!empty($row['ID']))
2025 $descrId = (int)$row['ID'];
2026 unset($row, $iterator);
2027 }
2028 if ($descrId === null)
2029 {
2030 $iterator = static::getResultIterator([
2031 'select' => ['MODULE_ID', 'ORDER_DISCOUNT_ID', 'ORDER_ID'],
2032 'filter' => ['=ID' => $id],
2033 'order' => []
2034 ]);
2035 $row = $iterator->fetch();
2036 unset($iterator);
2037 $row['RULE_ID'] = $id;
2038 $row['DESCR'] = $fields['DESCR'];
2039 $resultDescr = static::addResultDescriptionInternal($row);
2040 unset($row);
2041 }
2042 else
2043 {
2044 $resultDescr = static::updateResultDescriptionInternal(
2045 $fields['DESCR_ID'],
2046 array('DESCR' => $fields['DESCR'])
2047 );
2048 }
2049
2050 if (!$resultDescr->isSuccess())
2051 $result->addErrors($resultDescr->getErrors());
2052 unset($resultDescr);
2053
2054 return $result;
2055 }
2056
2062 protected static function getResultTableNameInternal()
2063 {
2064 return null;
2065 }
2066
2072 protected static function getResultDescriptionTableNameInternal()
2073 {
2074 return null;
2075 }
2076
2083 protected static function checkResultTableWhiteList(array $fields)
2084 {
2085 return null;
2086 }
2087
2094 protected static function checkResultDescriptionTableWhiteList(array $fields)
2095 {
2096 return null;
2097 }
2098
2105 protected static function addResultInternal(array $fields)
2106 {
2107 return null;
2108 }
2109
2116 protected static function addResultDescriptionInternal(array $fields)
2117 {
2118 return null;
2119 }
2120
2128 protected static function updateResultInternal($id, array $fields)
2129 {
2130 return null;
2131 }
2132
2140 protected static function updateResultDescriptionInternal($id, array $fields)
2141 {
2142 return null;
2143 }
2144
2145 /* discount results end */
2146
2147 /* round result */
2148
2155 protected static function getRoundEntityInternal($entity)
2156 {
2157 return null;
2158 }
2159
2166 protected static function getRoundEntityFromInternal($entity)
2167 {
2168 return null;
2169 }
2170
2175 protected static function getRoundResultIterator(array $parameters)
2176 {
2177 return null;
2178 }
2179
2186 protected static function addRoundResultInternal(array $fields)
2187 {
2188 return null;
2189 }
2190
2198 protected static function updateRoundResultInternal($id, array $fields)
2199 {
2200 return null;
2201 }
2202
2208 protected static function getRoundTableNameInternal()
2209 {
2210 return null;
2211 }
2212
2213 /* round result end */
2214
2215 /* data storage */
2216
2223 protected static function getStorageTypeInternal($storageType)
2224 {
2225 return null;
2226 }
2227
2232 protected static function getStoredDataIterator(array $parameters)
2233 {
2234 return null;
2235 }
2236
2243 protected static function addStoredDataInternal(array $fields)
2244 {
2245 return null;
2246 }
2247
2255 protected static function updateStoredDataInternal($id, array $fields)
2256 {
2257 return null;
2258 }
2259
2265 protected static function getStoredDataTableInternal()
2266 {
2267 return null;
2268 }
2269
2270 /* data storage end */
2271
2279 private static function isSimpleAction($action)
2280 {
2281 $result = true;
2282
2283 $action = (string)$action;
2284 if ($action == '')
2285 return $result;
2286
2287 $action = trim(mb_substr($action, 8));
2288 $action = mb_substr($action, 2);
2289 $key = mb_strpos($action, ')');
2290 if ($key === false)
2291 return $result;
2292 $orderName = '\\'.mb_substr($action, 0, $key);
2293
2294 preg_match_all("/".$orderName."(?:,|\‍))/".BX_UTF_PCRE_MODIFIER, $action, $list);
2295 if (isset($list[0]) && is_array($list[0]))
2296 $result = count($list[0]) <= 2;
2297
2298 return $result;
2299 }
2300
2309 private static function deleteRowsByIndex($tableName, $indexField, array $ids)
2310 {
2311 $tableName = (string)$tableName;
2312 if ($tableName === '')
2313 return;
2314 $indexField = (string)$indexField;
2315 if ($indexField === '')
2316 return;
2317
2318 if (empty($ids))
2319 return;
2320 Main\Type\Collection::normalizeArrayValuesByInt($ids, true);
2321 if (empty($ids))
2322 return;
2323
2324 $conn = Main\Application::getConnection();
2325 $helper = $conn->getSqlHelper();
2326
2327 $query = 'delete from '.$helper->quote($tableName).' where '.$helper->quote($indexField);
2328 foreach (array_chunk($ids, 500) as $page)
2329 {
2330 $conn->queryExecute($query.' in ('.implode(', ', $page).')');
2331 }
2332 unset($page, $query);
2333
2334 unset($helper, $conn);
2335 }
2336
2337 private static function getEntityIndex(array $row)
2338 {
2339 return (isset($row['ENTITY_ID']) ? $row['ENTITY_ID'] : $row['ENTITY_VALUE']);
2340 }
2341}
static loadMessages($file)
Definition loc.php:64
static getMessage($code, $replace=null, $language=null)
Definition loc.php:29
static addRoundResultInternal(array $fields)
static getOrderDiscountIterator(array $parameters)
static getResultIterator(array $parameters)
static roundBasket(array $basket, array $roundData=array(), array $orderData=array())
static getRoundResultIterator(array $parameters)
static updateRoundBlock($order, array $block)
static roundPrice(array $basketItem, array $roundData=array())
static loadOrderDiscountFromDb(array $discountIds, array $discountOrder)
static formatSaleRuleResult(array $rule)
static addResultInternal(array $fields)
static getOrderDiscountModuleIterator(array $parameters)
static updateResultInternal($id, array $fields)
static loadOrderStoredDataFromDb($order, $storageType)
static addResultDescriptionInternal(array $fields)
static loadModulesFromDb(array $discountIds)
static calculateApplyCoupons($module, $discount, $basket, $params)
static getDiscountIterator(array $parameters)
static addStoredDataInternal(array $fields)
static fillRuleProductFields(array &$result, array $basketData, $index)
static addOrderDiscountInternal(array $fields)
static checkResultTableWhiteList(array $fields)
static saveOrderStoredData($order, $storageType, array $data, array $options=array())
static getOrderCouponIterator(array $parameters)
static addResultBlock($order, array $block)
static checkRequiredOrderDiscountFields(array $fields)
static updateResultDescriptionInternal($id, array $fields)
static loadStoredDataFromDb($order, $storageType, array $additionalFilter=array())
static formatBasketRuleResult(array $rule)
static executeDiscountProvider(array $provider, array $data)
static calculateOrderDiscountHashInternal(array $fields)
static updateStoredDataInternal($id, array $fields)
static updateRoundResultInternal($id, array $fields)
static getStorageTypeInternal($storageType)
static checkResultDescriptionTableWhiteList(array $fields)
static validateCoupon(array $fields)
static getResultDescriptionIterator(array $parameters)
static updateResultRow($id, array $fields)
static updateResultBlock($order, array $block)
static prepareDiscountModules(array $discount)
static addDiscount(array $fields, array $rawFields)
static formatSaleItemRuleResult(array $rule)
static saveOrderDiscountModulesInternal($orderDiscountId, array $modules)
static saveStoredDataBlock($order, $storageType, array $block, array $options=array())
static addRoundBlock($order, array $block)
static fillAbsentDiscountFields(array $fields)
static addOrderCouponInternal(array $fields)
static getStoredDataIterator(array $parameters)
static transferEntityCodeFromInternal(array $row, array $transferList)
static getEditUrl(array $discount)
static normalizeOrderDiscountFieldsInternal(array $rawFields)
static normalizeDiscountFields(array $rawFields)
static getInstance($type)
Definition registry.php:183