Bitrix-D7 23.9
 
Загрузка...
Поиск...
Не найдено
orderbuilder.php
1<?php
3
21use \Bitrix\Sale\Delivery;
27
28Loc::loadLanguageFile($_SERVER['DOCUMENT_ROOT'] . BX_ROOT . '/modules/sale/lib/helpers/admin/blocks/orderbasketshipment.php');
29
35abstract class OrderBuilder
36{
38 protected $delegate = null;
40 protected $basketBuilder = null;
41
43 protected $settingsContainer = null;
44
46 protected $order = null;
48 protected $formData = array();
50 protected $errorsContainer = null;
51
53 protected $isStartField;
54
56 protected $registry = null;
57
58 public function __construct(SettingsContainer $settings)
59 {
60 $this->settingsContainer = $settings;
61 $this->errorsContainer = new ErrorsContainer();
62 $this->errorsContainer->setAcceptableErrorCodes(
63 $this->settingsContainer->getItemValue('acceptableErrorCodes')
64 );
65
67 }
68
73 public function build($data)
74 {
75 $this->initFields($data)
76 ->delegate()
77 ->createOrder()
78 ->setDiscounts() //?
79 ->setFields()
80 ->buildTradeBindings()
81 ->setProperties()
82 ->setUser()
83 ->buildProfile()
84 ->buildBasket()
85 ->buildPayments()
86 ->buildShipments()
87 ->setRelatedProperties()
88 ->setDiscounts() //?
89 ->finalActions();
90
91 return $this;
92 }
93
95 {
96 $this->basketBuilder = $basketBuilder;
97 }
98
99 public function getRegistry()
100 {
101 return $this->registry;
102 }
103
104 protected function prepareFields(array $fields)
105 {
106 $fields["ID"] = (isset($fields["ID"]) ? (int)$fields["ID"] : 0);
107 return $fields;
108 }
109
110 public function initFields(array $data)
111 {
112 $data = $this->prepareFields($data);
113 $this->formData = $data;
114 return $this;
115 }
116
117 public function delegate()
118 {
119 $data = $this->formData;
120 $this->delegate = (int)$data['ID'] > 0 ? new OrderBuilderExist($this) : new OrderBuilderNew($this);
121
122 return $this;
123 }
124
125 public function createOrder()
126 {
127 $data = $this->formData;
128 if($this->order = $this->delegate->createOrder($data))
129 {
130 $this->isStartField = $this->order->isStartField();
131 }
132
133 return $this;
134 }
135
136 protected function getSettableShipmentFields()
137 {
138 $shipmentClassName = $this->registry->getShipmentClassName();
139 return array_merge(['PROPERTIES'], $shipmentClassName::getAvailableFields());
140 }
141
142 protected function getSettablePaymentFields()
143 {
144 $paymentClassName = $this->registry->getPaymentClassName();
145 return $paymentClassName::getAvailableFields();
146 }
147
148 protected function getSettableOrderFields()
149 {
150 return ['RESPONSIBLE_ID', 'USER_DESCRIPTION', 'ORDER_TOPIC', 'ACCOUNT_NUMBER'];
151 }
152
153 public function setFields()
154 {
155 $fields = $this->getSettableOrderFields();
156
157 foreach($fields as $field)
158 {
159 if(isset($this->formData[$field]))
160 {
161 $r = $this->order->setField($field, $this->formData[$field]);
162
163 if(!$r->isSuccess())
164 {
165 $this->getErrorsContainer()->addErrors($r->getErrors());
166 }
167 }
168 }
169
170 if(isset($this->formData["PERSON_TYPE_ID"]) && intval($this->formData["PERSON_TYPE_ID"]) > 0)
171 {
173 $r = $this->order->setPersonTypeId(intval($this->formData['PERSON_TYPE_ID']));
174 }
175 else
176 {
178 $r = $this->order->setPersonTypeId(
180 $this->order->getSiteId()
181 )
182 );
183 }
184
185 if(!$r->isSuccess())
186 {
187 $this->getErrorsContainer()->addErrors($r->getErrors());
188 }
189
190 return $this;
191 }
192
193 public function setProperties()
194 {
195 if (empty($this->formData["PROPERTIES"]))
196 {
197 return $this;
198 }
199
200 $propCollection = $this->order->getPropertyCollection();
201 $res = $propCollection->setValuesFromPost(
202 $this->formData,
203 $this->settingsContainer->getItemValue('propsFiles')
204 );
205
206 if (!$res->isSuccess())
207 {
208 $this->getErrorsContainer()->addErrors($res->getErrors());
209 }
210
211 return $this;
212 }
213
214 public function setRelatedProperties()
215 {
216 if (empty($this->formData["PROPERTIES"]))
217 {
218 return $this;
219 }
220
221 $propCollection = $this->order->getPropertyCollection();
222
224 foreach ($propCollection as $propertyValue)
225 {
226 if (!$propertyValue->getRelations())
227 {
228 continue;
229 }
230
231 $post = Internals\Input\File::getPostWithFiles($this->formData, $this->settingsContainer->getItemValue('propsFiles'));
232
233 $res = $propertyValue->setValueFromPost($post);
234 if (!$res->isSuccess())
235 {
236 $this->getErrorsContainer()->addErrors($res->getErrors());
237 }
238 }
239
240 return $this;
241 }
242
243 public function setUser()
244 {
245 $this->delegate->setUser();
246 return $this;
247 }
248
249 public function buildProfile()
250 {
251 if (empty($this->formData["PROPERTIES"]) || empty($this->formData["USER_ID"]))
252 {
253 return $this;
254 }
255
256 $profileId = $this->formData["USER_PROFILE"]["ID"] ?? 0;
257 $profileName = $this->formData["USER_PROFILE"]["NAME"] ?? '';
258
259 $errors = [];
260 \CSaleOrderUserProps::DoSaveUserProfile(
261 $this->getUserId(),
262 $profileId,
263 $profileName,
264 $this->order->getPersonTypeId(),
265 $this->formData["PROPERTIES"],
266 $errors
267 );
268
269 foreach ($errors as $error)
270 {
271 $this->errorsContainer->addError(new Main\Error($error['TEXT'], $error['CODE'], 'PROFILE'));
272 }
273
274 return $this;
275 }
276
277 public function setDiscounts()
278 {
279 if(isset($this->formData["DISCOUNTS"]) && is_array($this->formData["DISCOUNTS"]))
280 {
281 $this->order->getDiscount()->setApplyResult($this->formData["DISCOUNTS"]);
282
283 $r = $this->order->getDiscount()->calculate();
284
285 if($r->isSuccess())
286 {
287 $discountData = $r->getData();
288 $this->order->applyDiscount($discountData);
289 }
290 }
291
292 return $this;
293 }
294
295 public function buildBasket()
296 {
297 $this->delegate->buildBasket();
298 return $this;
299 }
300
301 protected function createEmptyShipment()
302 {
303 $shipments = $this->order->getShipmentCollection();
304 return $shipments->createItem();
305 }
306
307 protected function removeShipments()
308 {
309 if($this->getSettingsContainer()->getItemValue('deleteShipmentIfNotExists'))
310 {
311 $shipmentCollection = $this->order->getShipmentCollection();
312
313 $shipmentIds = [];
314 foreach($this->formData["SHIPMENT"] as $shipmentData)
315 {
316 if(!isset($shipmentData['ID']))
317 continue;
318
319 $shipment = $shipmentCollection->getItemById($shipmentData['ID']);
320
321 if ($shipment == null)
322 continue;
323
324 $shipmentIds[] = $shipment->getId();
325 }
326
327 foreach ($shipmentCollection as $shipment)
328 {
329 if($shipment->isSystem())
330 continue;
331
332 if(!in_array($shipment->getId(), $shipmentIds))
333 {
334 $r = $shipment->delete();
335 if (!$r->isSuccess())
336 {
337 $this->errorsContainer->addErrors($r->getErrors());
338 return false;
339 }
340 }
341 }
342 }
343 return true;
344 }
345
346 protected function prepareFieldsStatusId($isNew, $item, $defaultFields)
347 {
348 $statusId = '';
349
350 if($isNew)
351 {
352 $deliveryStatusClassName = $this->registry->getDeliveryStatusClassName();
353 $statusId = $deliveryStatusClassName::getInitialStatus();
354 }
355 elseif (isset($item['STATUS_ID']) && $item['STATUS_ID'] !== $defaultFields['STATUS_ID'])
356 {
357 $statusId = $item['STATUS_ID'];
358 }
359
360 return $statusId;
361 }
362
363 public function buildShipments()
364 {
365 $isEmptyShipmentData = empty($this->formData["SHIPMENT"]) || !is_array($this->formData["SHIPMENT"]);
366 if ($isEmptyShipmentData)
367 {
368 $this->formData["SHIPMENT"] = [];
369 }
370
371 if ($isEmptyShipmentData && !$this->getSettingsContainer()->getItemValue('createDefaultShipmentIfNeed'))
372 {
373 return $this;
374 }
375
376 if($isEmptyShipmentData && $this->getOrder()->isNew())
377 {
378 $this->createEmptyShipment();
379 return $this;
380 }
381
382 if(!$this->removeShipments())
383 {
384 throw new BuildingException();
385 }
386
387 global $USER;
388 $shipmentCollection = $this->order->getShipmentCollection();
389
390 foreach($this->formData["SHIPMENT"] as $item)
391 {
392 $shipmentId = intval($item['ID'] ?? 0);
393 $isNew = ($shipmentId <= 0);
394 $deliveryService = null;
395 $storeId = null;
396
397 if (!isset($item['DEDUCTED']) || $item['DEDUCTED'] !== 'Y')
398 {
399 $item['DEDUCTED'] = 'N';
400 }
401
402 $extraServices =
403 isset($item['EXTRA_SERVICES']) && is_array($item['EXTRA_SERVICES'])
404 ? $item['EXTRA_SERVICES']
405 : []
406 ;
407
408 $settableShipmentFields = $this->getSettableShipmentFields();
409 if (!empty($settableShipmentFields))
410 {
411 //for backward compatibility
412 $product = $item['PRODUCT'] ?? null;
413 $storeId = (int)($item['DELIVERY_STORE_ID'] ?? 0);
414 $item = array_intersect_key($item, array_flip($settableShipmentFields));
415 if ($product !== null)
416 {
417 $item['PRODUCT'] = $product;
418 }
419 unset($product);
420 }
421
422 if($isNew)
423 {
424 $shipment = $shipmentCollection->createItem();
425 }
426 else
427 {
428 $shipment = $shipmentCollection->getItemById($shipmentId);
429
430 if(!$shipment)
431 {
432 $this->errorsContainer->addError(new Error(Loc::getMessage("SALE_HLP_ORDERBUILDER_SHIPMENT_NOT_FOUND")." - ".$shipmentId));
433 continue;
434 }
435 }
436
437 $defaultFields = $shipment->getFieldValues();
438
440 $systemShipment = $shipmentCollection->getSystemShipment();
441 $systemShipmentItemCollection = $systemShipment->getShipmentItemCollection();
442 //We suggest that if products is null - ShipmentBasket not loaded yet, if array ShipmentBasket loaded, but empty.
443 $products = null;
444
445 if(
446 !isset($item['PRODUCT'])
447 && $shipment->getId() <= 0
448 )
449 {
450 $products = array();
451 $basket = $this->order->getBasket();
452
453 if($basket)
454 {
455 $basketItems = $basket->getBasketItems();
456 foreach($basketItems as $product)
457 {
458 $systemShipmentItem = $systemShipmentItemCollection->getItemByBasketCode($product->getBasketCode());
459
460 if($product->isBundleChild() || !$systemShipmentItem || $systemShipmentItem->getQuantity() <= 0)
461 continue;
462
463 $products[] = array(
464 'AMOUNT' => $systemShipmentItem->getQuantity(),
465 'BASKET_CODE' => $product->getBasketCode(),
466 );
467 }
468 }
469 }
470 elseif (isset($item['PRODUCT']) && is_array($item['PRODUCT']))
471 {
472 $products = $item['PRODUCT'];
473 }
474
475 if($item['DEDUCTED'] == 'Y' && $products !== null)
476 {
477 $basketResult = $this->buildShipmentBasket($shipment, $products);
478
479 if(!$basketResult->isSuccess())
480 {
481 $this->errorsContainer->addErrors($basketResult->getErrors());
482 }
483 }
484
485 $shipmentFields = array(
486 'COMPANY_ID' => (isset($item['COMPANY_ID']) && intval($item['COMPANY_ID']) > 0) ? intval($item['COMPANY_ID']) : 0,
487 'DEDUCTED' => $item['DEDUCTED'] ?? 'N',
488 'DELIVERY_DOC_NUM' => $item['DELIVERY_DOC_NUM'] ?? '',
489 'TRACKING_NUMBER' => $item['TRACKING_NUMBER'] ?? '',
490 'CURRENCY' => $this->order->getCurrency(),
491 'COMMENTS' => $item['COMMENTS'] ?? '',
492 );
493
494 if (!empty($item['IS_REALIZATION']))
495 {
496 $shipmentFields['IS_REALIZATION'] = $item['IS_REALIZATION'];
497 }
498
499 if (!empty($item['ACCOUNT_NUMBER']))
500 {
501 $shipmentFields['ACCOUNT_NUMBER'] = $item['ACCOUNT_NUMBER'];
502 }
503
504 if (!empty($item['XML_ID']))
505 {
506 $shipmentFields['XML_ID'] = $item['XML_ID'];
507 }
508
509 $statusId = $this->prepareFieldsStatusId($isNew, $item, $defaultFields);
510 if ($statusId !== '')
511 {
512 $shipmentFields['STATUS_ID'] = $statusId;
513 }
514
515 if (empty($item['COMPANY_ID']))
516 {
517 $shipmentFields['COMPANY_ID'] = $this->order->getField('COMPANY_ID');
518 }
519
520 if (empty($item['RESPONSIBLE_ID']))
521 {
522 $shipmentFields['RESPONSIBLE_ID'] = $this->order->getField('RESPONSIBLE_ID');
523 $shipmentFields['EMP_RESPONSIBLE_ID'] = $USER->GetID();
524 }
525
526 $deliveryId = 0;
527 if (isset($item['PROFILE_ID']) && (int)$item['PROFILE_ID'] > 0)
528 {
529 $deliveryId = (int)$item['PROFILE_ID'];
530 }
531 elseif (isset($item['DELIVERY_ID']))
532 {
533 $deliveryId = (int)$item['DELIVERY_ID'];
534 }
535 elseif ($shipment->getField('DELIVERY_ID'))
536 {
537 $deliveryId = $shipment->getField('DELIVERY_ID');
538 }
539
540 $shipmentFields['DELIVERY_ID'] = $deliveryId;
541
542 $dateFields = ['DELIVERY_DOC_DATE', 'DATE_DEDUCTED', 'DATE_MARKED', 'DATE_CANCELED', 'DATE_RESPONSIBLE_ID'];
543
544 foreach($dateFields as $fieldName)
545 {
546 if(isset($item[$fieldName]))
547 {
548 if (is_string($item[$fieldName]))
549 {
550 try
551 {
552 $shipmentFields[$fieldName] = new DateTime($item[$fieldName]);
553 }
554 catch (ObjectException $exception)
555 {
556 $this->errorsContainer->addError(new Error('Wrong field "'.$fieldName.'"'));
557 }
558 }
559 elseif ($item[$fieldName] instanceof Date)
560 {
561 $shipmentFields[$fieldName] = $item[$fieldName];
562 }
563 }
564 }
565
566 try
567 {
568 if($deliveryService = Delivery\Services\Manager::getObjectById($shipmentFields['DELIVERY_ID']))
569 {
570 if($deliveryService->isProfile())
571 {
572 $shipmentFields['DELIVERY_NAME'] = $deliveryService->getNameWithParent();
573 }
574 else
575 {
576 $shipmentFields['DELIVERY_NAME'] = $deliveryService->getName();
577 }
578 }
579 }
580 catch (ArgumentNullException $e)
581 {
582 $this->errorsContainer->addError(new Error(Loc::getMessage('SALE_HLP_ORDERBUILDER_DELIVERY_NOT_FOUND'), 'OB_DELIVERY_NOT_FOUND'));
583 return $this;
584 }
585
586 $responsibleId = $shipment->getField('RESPONSIBLE_ID');
587
588 if (($item['RESPONSIBLE_ID'] ?? null) !== $responsibleId || empty($responsibleId))
589 {
590 if (isset($item['RESPONSIBLE_ID']))
591 {
592 $shipmentFields['RESPONSIBLE_ID'] = $item['RESPONSIBLE_ID'];
593 }
594 else
595 {
596 $shipmentFields['RESPONSIBLE_ID'] = $this->order->getField('RESPONSIBLE_ID');
597 }
598
599 if (!empty($shipmentFields['RESPONSIBLE_ID']))
600 {
601 $shipmentFields['EMP_RESPONSIBLE_ID'] = $USER->getID();
602 }
603 }
604
605 if($extraServices)
606 {
607 $shipment->setExtraServices($extraServices);
608 }
609
610 $setFieldsResult = $shipment->setFields($shipmentFields);
611
612 if(!$setFieldsResult->isSuccess())
613 {
614 $this->errorsContainer->addErrors($setFieldsResult->getErrors());
615 }
616
617 // region Properties
618 if (isset($item['PROPERTIES']) && is_array($item['PROPERTIES']))
619 {
621 $propCollection = $shipment->getPropertyCollection();
622 $res = $propCollection->setValuesFromPost($item, []);
623
624 if (!$res->isSuccess())
625 {
626 foreach ($res->getErrors() as $error)
627 {
628 $this->getErrorsContainer()->addError(
629 new Main\Error($error->getMessage(), $error->getCode(), 'SHIPMENT_PROPERTIES')
630 );
631 }
632 }
633
635 foreach ($propCollection as $propValue)
636 {
637 if ($propValue->isUtil())
638 {
639 continue;
640 }
641
642 $property = $propValue->getProperty();
643 $relatedDeliveryIds = (isset($property['RELATION']) && is_array($property['RELATION']))
644 ? array_column(
645 array_filter(
646 $property['RELATION'],
647 function ($item)
648 {
649 return $item['ENTITY_TYPE'] === 'D';
650 }
651 ),
652 'ENTITY_ID'
653 )
654 : [];
655
656 if (
657 !empty($relatedDeliveryIds)
658 && !in_array($shipment->getField('DELIVERY_ID'), $relatedDeliveryIds)
659 )
660 {
661 continue;
662 }
663
664 $res = $propValue->verify();
665 if (!$res->isSuccess())
666 {
667 foreach ($res->getErrors() as $error)
668 {
669 $this->getErrorsContainer()->addError(
670 new Main\Error($error->getMessage(), $propValue->getPropertyId(), 'SHIPMENT_PROPERTIES')
671 );
672 }
673 }
674
675 $res = $propValue->checkRequiredValue($propValue->getPropertyId(), $propValue->getValue());
676 if (!$res->isSuccess())
677 {
678 foreach ($res->getErrors() as $error)
679 {
680 $this->getErrorsContainer()->addError(
681 new Main\Error($error->getMessage(), $propValue->getPropertyId(), 'SHIPMENT_PROPERTIES')
682 );
683 }
684 }
685 }
686 }
687 // endregion
688
689 if ($storeId)
690 {
691 $shipment->setStoreId($storeId);
692 }
693
694 if($item['DEDUCTED'] == 'N' && $products !== null)
695 {
696 $basketResult = $this->buildShipmentBasket($shipment, $products);
697
698 if(!$basketResult->isSuccess())
699 {
700 $this->errorsContainer->addErrors($basketResult->getErrors());
701 }
702 }
703
704 $isCustomPrice = false;
705 if (isset($item['CUSTOM_PRICE_DELIVERY']))
706 {
707 $isCustomPrice = $item['CUSTOM_PRICE_DELIVERY'] === 'Y';
708 }
709
710 $fields = array(
711 'CUSTOM_PRICE_DELIVERY' => $isCustomPrice ? 'Y' : 'N',
712 'PRICE_DELIVERY' => (float)str_replace(',', '.', $item['PRICE_DELIVERY'] ?? 0),
713 );
714
715 if (isset($item['ALLOW_DELIVERY']))
716 {
717 $fields['ALLOW_DELIVERY'] = $item['ALLOW_DELIVERY'] === 'Y' ? 'Y' : 'N';
718 }
719
720 if (isset($item['BASE_PRICE_DELIVERY']))
721 {
722 $fields['BASE_PRICE_DELIVERY'] = (float)str_replace(',', '.', $item['BASE_PRICE_DELIVERY']);
723 }
724
725 $shipment = $this->delegate->setShipmentPriceFields($shipment, $fields);
726
727 if($deliveryService && !empty($item['ADDITIONAL']))
728 {
729 $modifiedShipment = $deliveryService->processAdditionalInfoShipmentEdit($shipment, $item['ADDITIONAL']);
730
732 if ($modifiedShipment && get_class($modifiedShipment) == $registry->getShipmentClassName())
733 {
734 $shipment = $modifiedShipment;
735 }
736 }
737 }
738
739 return $this;
740 }
741
742 protected function removeShipmentItems(\Bitrix\Sale\Shipment $shipment, $products, $idsFromForm)
743 {
744 $result = new Result();
745
746 $shipmentItemCollection = $shipment->getShipmentItemCollection();
747
749 foreach ($shipmentItemCollection as $shipmentItem)
750 {
751 if (!array_key_exists($shipmentItem->getBasketCode(), $idsFromForm))
752 {
754 $r = $shipmentItem->delete();
755 if (!$r->isSuccess())
756 {
757 $result->addErrors($r->getErrors());
758 }
759 }
760
761 $shipmentItemStoreCollection = $shipmentItem->getShipmentItemStoreCollection();
762 if ($shipmentItemStoreCollection)
763 {
765 foreach ($shipmentItemStoreCollection as $shipmentItemStore)
766 {
767 $shipmentItemId = $shipmentItemStore->getId();
768 if (!isset($idsFromForm[$shipmentItem->getBasketCode()]['BARCODE_IDS'][$shipmentItemId]))
769 {
770 $delResult = $shipmentItemStore->delete();
771 if (!$delResult->isSuccess())
772 {
773 $result->addErrors($delResult->getErrors());
774 }
775 }
776 }
777 }
778 }
779
780 return $result;
781 }
782
795 public function buildShipmentBasket(&$shipment, $shipmentBasket)
796 {
798 $result = new Result();
799 $shippingItems = array();
800 $idsFromForm = array();
801 $basket = $this->order->getBasket();
802 $shipmentItemCollection = $shipment->getShipmentItemCollection();
803 $useStoreControl = Configuration::useStoreControl();
804
805 if(is_array($shipmentBasket))
806 {
807 // PREPARE DATA FOR SET_FIELDS
808 foreach ($shipmentBasket as $items)
809 {
810 $items['QUANTITY'] = floatval(str_replace(',', '.', $items['QUANTITY']));
811 $items['AMOUNT'] = floatval(str_replace(',', '.', $items['AMOUNT']));
812
813 $r = $this->prepareDataForSetFields($shipment, $items);
814 if($r->isSuccess())
815 {
816 $items = $r->getData()[0];
817 }
818 else
819 {
820 $result->addErrors($r->getErrors());
821 return $result;
822 }
823
824 if (isset($items['BASKET_ID']) && !BasketBuilder::isBasketItemNew($items['BASKET_ID']))
825 {
826 if (!$basketItem = $basket->getItemById($items['BASKET_ID']))
827 {
828 $result->addError( new Error(
829 Loc::getMessage('SALE_ORDER_SHIPMENT_BASKET_BASKET_ITEM_NOT_FOUND', array(
830 '#BASKET_ITEM_ID#' => $items['BASKET_ID'],
831 )),
832 'PROVIDER_UNRESERVED_SHIPMENT_ITEM_WRONG_BASKET_ITEM')
833 );
834 return $result;
835 }
837 $basketCode = $basketItem->getBasketCode();
838 }
839 else
840 {
841 $basketCode = $items['BASKET_CODE'];
842 if(!$basketItem = $basket->getItemByBasketCode($basketCode))
843 {
844 $result->addError( new Error(
845 Loc::getMessage('SALE_ORDER_SHIPMENT_BASKET_BASKET_ITEM_NOT_FOUND', array(
846 '#BASKET_ITEM_ID#' => $basketCode,
847 )),
848 'PROVIDER_UNRESERVED_SHIPMENT_ITEM_WRONG_BASKET_ITEM')
849 );
850 return $result;
851 }
852 }
853
854 $isSupportedMarkingCode = false;
855 if (isset($items['IS_SUPPORTED_MARKING_CODE']))
856 {
857 $isSupportedMarkingCode = $items['IS_SUPPORTED_MARKING_CODE'] === 'Y';
858 }
859
860 $tmp = [
861 'BASKET_CODE' => $basketCode,
862 'AMOUNT' => $items['AMOUNT'] ?? 0,
863 'ORDER_DELIVERY_BASKET_ID' => $items['ORDER_DELIVERY_BASKET_ID'] ?? 0,
864 'IS_SUPPORTED_MARKING_CODE' => $isSupportedMarkingCode ? 'Y' : 'N',
865 ];
866 if (array_key_exists('XML_ID', $items))
867 {
868 $tmp['XML_ID'] = $items['XML_ID'];
869 }
870 $idsFromForm[$basketCode] = array();
871
872 if (
873 isset($items['BARCODE_INFO'])
874 && $items['BARCODE_INFO']
875 && ($useStoreControl || $isSupportedMarkingCode)
876 )
877 {
878 foreach ($items['BARCODE_INFO'] as $item)
879 {
880 if (!$basketItem->isReservableItem())
881 {
882 $shippingItems[] = $tmp;
883 continue;
884 }
885
886 $barcodeQuantity = ($basketItem->isBarcodeMulti() || $basketItem->isSupportedMarkingCode()) ? 1 : $item['QUANTITY'];
887 $barcodeStoreId = $item['STORE_ID'];
888
889 $tmp['BARCODE'] = array(
890 'ORDER_DELIVERY_BASKET_ID' => $items['ORDER_DELIVERY_BASKET_ID'] ?? 0,
891 'STORE_ID' => $barcodeStoreId,
892 'QUANTITY' => $barcodeQuantity,
893 );
894
895 $tmp['BARCODE_INFO'] = [
896 $item['STORE_ID'] => [
897 'STORE_ID' => (int)$barcodeStoreId,
898 'QUANTITY' => (float)$barcodeQuantity,
899 ],
900 ];
901
902 $barcodeCount = 0;
903 if ($item['BARCODE'])
904 {
905 foreach ($item['BARCODE'] as $barcode)
906 {
907 $barcode['ID'] = (int)($barcode['ID'] ?? 0);
908
909 $tmp['BARCODE_INFO'][$barcodeStoreId]['BARCODE'] = [$barcode];
910
911 if (isset($barcode['MARKING_CODE']))
912 {
913 $barcode['MARKING_CODE'] = (string)$barcode['MARKING_CODE'];
914 }
915 else
916 {
917 $barcode['MARKING_CODE'] = '';
918 }
919
920 $idsFromForm[$basketCode]['BARCODE_IDS'][$barcode['ID']] = true;
921
922 if ($barcode['ID'] > 0)
923 {
924 $tmp['BARCODE']['ID'] = $barcode['ID'];
925 }
926 else
927 {
928 unset($tmp['BARCODE']['ID']);
929 }
930
931 $tmp['BARCODE']['BARCODE'] = (string)$barcode['VALUE'];
932 $tmp['BARCODE']['MARKING_CODE'] = $barcode['MARKING_CODE'];
933
934 $shippingItems[] = $tmp;
935 $barcodeCount++;
936 }
937 }
938 elseif (!$basketItem->isBarcodeMulti() && !$basketItem->isSupportedMarkingCode())
939 {
940 $shippingItems[] = $tmp;
941 continue;
942 }
943
944
945 if ($basketItem->isBarcodeMulti() || $basketItem->isSupportedMarkingCode())
946 {
947 while ($barcodeCount < $item['QUANTITY'])
948 {
949 unset($tmp['BARCODE']['ID']);
950 $tmp['BARCODE']['BARCODE'] = '';
951 $tmp['BARCODE']['MARKING_CODE'] = '';
952 $shippingItems[] = $tmp;
953 $barcodeCount++;
954 }
955 }
956 }
957 }
958 else
959 {
960 $shippingItems[] = $tmp;
961 }
962 }
963 }
964
965 // DELETE FROM COLLECTION
966 $r = $this->removeShipmentItems($shipment, $shipmentBasket, $idsFromForm);
967 if(!$r->isSuccess())
968 $result->addErrors($r->getErrors());
969
970 $isStartField = $shipmentItemCollection->isStartField();
971
972 // SET DATA
973 foreach ($shippingItems as $shippingItem)
974 {
975 if ((int)$shippingItem['ORDER_DELIVERY_BASKET_ID'] <= 0)
976 {
977 $basketCode = $shippingItem['BASKET_CODE'];
979 $basketItem = $this->order->getBasket()->getItemByBasketCode($basketCode);
980
982 $shipmentItem = $shipmentItemCollection->createItem($basketItem);
983
984 if ($shipmentItem === null)
985 {
986 $result->addError(
987 new Error(
988 Loc::getMessage('SALE_ORDER_SHIPMENT_BASKET_ERROR_ALREADY_SHIPPED')
989 )
990 );
991 return $result;
992 }
993
994 unset($shippingItem['BARCODE']['ORDER_DELIVERY_BASKET_ID']);
995 }
996 else
997 {
998 $shipmentItem = $shipmentItemCollection->getItemById($shippingItem['ORDER_DELIVERY_BASKET_ID']);
999
1000 if($shipmentItem)
1001 {
1002 $basketItem = $shipmentItem->getBasketItem();
1003 }
1004 else //It's a possible case when we are creating new shipment.
1005 {
1007 $systemShipment = $shipment->getCollection()->getSystemShipment();
1009 $systemShipmentItemCollection = $systemShipment->getShipmentItemCollection();
1010
1011 $shipmentItem = $systemShipmentItemCollection->getItemById($shippingItem['ORDER_DELIVERY_BASKET_ID']);
1012
1013 if($shipmentItem)
1014 {
1015 $basketItem = $shipmentItem->getBasketItem();
1016 $shipmentItem = $shipmentItemCollection->createItem($basketItem);
1017 $shipmentItem->setField('QUANTITY', $shipmentItem->getField('QUANTITY'));
1018 }
1019 else
1020 {
1021 $result->addError(
1022 new Error(
1023 Loc::getMessage('SALE_HLP_ORDERBUILDER_SHIPMENT_ITEM_ERROR',[
1024 '#ID#' => $shippingItem['ORDER_DELIVERY_BASKET_ID'],
1025 ])
1026 )
1027 );
1028
1029 continue;
1030 }
1031 }
1032 }
1033
1034 if ($shippingItem['AMOUNT'] <= 0)
1035 {
1036 $result->addError(
1037 new Error(
1038 Loc::getMessage('SALE_ORDER_SHIPMENT_BASKET_ERROR_QUANTITY', array('#BASKET_ITEM#' => $basketItem->getField('NAME'))),
1039 'BASKET_ITEM_'.$basketItem->getBasketCode()
1040 )
1041 );
1042 continue;
1043 }
1044
1045 $r = $this->modifyQuantityShipmentItem($shipmentItem, $shippingItem);
1046 if(!$r->isSuccess())
1047 $result->addErrors($r->getErrors());
1048
1049 if (array_key_exists('XML_ID', $shippingItem))
1050 {
1051 $setFieldResult = $shipmentItem->setField('XML_ID', $shippingItem['XML_ID']);
1052 if (!$setFieldResult->isSuccess())
1053 {
1054 $result->addErrors($setFieldResult->getErrors());
1055 }
1056 }
1057 }
1058
1059 if ($isStartField)
1060 {
1061 $hasMeaningfulFields = $shipmentItemCollection->hasMeaningfulField();
1062
1064 $r = $shipmentItemCollection->doFinalAction($hasMeaningfulFields);
1065 if (!$r->isSuccess())
1066 {
1067 $result->addErrors($r->getErrors());
1068 }
1069 }
1070
1071 return $result;
1072 }
1073
1074 protected function prepareDataForSetFields(\Bitrix\Sale\Shipment $shipment, $items)
1075 {
1076 $result = new Result();
1077 return $result->setData([$items]);
1078 }
1079
1080 protected function modifyQuantityShipmentItem(ShipmentItem $shipmentItem, array $params)
1081 {
1082 $result = new Result();
1083 if ($shipmentItem->getQuantity() < $params['AMOUNT'])
1084 {
1085 $this->order->setMathActionOnly(true);
1086 $setFieldResult = $shipmentItem->setField('QUANTITY', $params['AMOUNT']);
1087 $this->order->setMathActionOnly(false);
1088
1089 if (!$setFieldResult->isSuccess())
1090 {
1091 $result->addErrors($setFieldResult->getErrors());
1092 }
1093 }
1094
1095 $r = $this->setBarcodeShipmentItem($shipmentItem, $params);
1096
1097 if($r->isSuccess() == false)
1098 {
1099 $result->addErrors($r->getErrors());
1100 }
1101
1102 $setFieldResult = $shipmentItem->setField('QUANTITY', $params['AMOUNT']);
1103
1104 if (!$setFieldResult->isSuccess())
1105 {
1106 $result->addErrors($setFieldResult->getErrors());
1107 }
1108
1109 return $result;
1110 }
1111
1112 protected function setBarcodeShipmentItem(ShipmentItem $shipmentItem, array $params)
1113 {
1114 $result = new Result();
1115 $basketItem = $shipmentItem->getBasketItem();
1116
1117 $useStoreControl = Configuration::useStoreControl();
1118
1119 if (
1120 !empty($params['BARCODE'])
1121 && ($useStoreControl || $params['IS_SUPPORTED_MARKING_CODE'] === 'Y' )
1122 && $basketItem->isReservableItem()
1123 )
1124 {
1125 $barcode = $params['BARCODE'];
1126
1128 $shipmentItemStoreCollection = $shipmentItem->getShipmentItemStoreCollection();
1129 if ($shipmentItemStoreCollection)
1130 {
1131 if (!$basketItem->isBarcodeMulti() && !$basketItem->isSupportedMarkingCode())
1132 {
1134 $r = $shipmentItemStoreCollection->setBarcodeQuantityFromArray($params);
1135 if (!$r->isSuccess())
1136 {
1137 $result->addErrors($r->getErrors());
1138 }
1139 }
1140
1141 if (isset($barcode['ID']) && intval($barcode['ID']) > 0)
1142 {
1144 if ($shipmentItemStore = $shipmentItemStoreCollection->getItemById($barcode['ID']))
1145 {
1146 unset($barcode['ID']);
1147 $setFieldResult = $shipmentItemStore->setFields($barcode);
1148
1149 if (!$setFieldResult->isSuccess())
1150 {
1151 $result->addErrors($setFieldResult->getErrors());
1152 }
1153 }
1154 }
1155 else
1156 {
1157 $shipmentItemStore = $shipmentItemStoreCollection->createItem($basketItem);
1158 $setFieldResult = $shipmentItemStore->setFields($barcode);
1159 if (!$setFieldResult->isSuccess())
1160 {
1161 $result->addErrors($setFieldResult->getErrors());
1162 }
1163 }
1164 }
1165 }
1166
1167 return $result;
1168 }
1169
1170 protected function createEmptyPayment()
1171 {
1172 $innerPaySystem = PaySystem\Manager::getObjectById(PaySystem\Manager::getInnerPaySystemId());
1173
1174 $paymentCollection = $this->order->getPaymentCollection();
1175 $payment = $paymentCollection->createItem($innerPaySystem);
1176 $payment->setField('SUM', $this->order->getPrice());
1177
1178 return $payment;
1179 }
1180
1181 protected function removePayments()
1182 {
1183 if($this->getSettingsContainer()->getItemValue('deletePaymentIfNotExists'))
1184 {
1185 $paymentCollection = $this->order->getPaymentCollection();
1186
1187 $paymentIds = [];
1188 foreach($this->formData["PAYMENT"] as $paymentData)
1189 {
1190 if(!isset($paymentData['ID']))
1191 continue;
1192
1193 $payment = $paymentCollection->getItemById($paymentData['ID']);
1194
1195 if ($payment == null)
1196 continue;
1197
1198 $paymentIds[] = $payment->getId();
1199 }
1200
1201 foreach ($paymentCollection as $payment)
1202 {
1203 if(!in_array($payment->getId(), $paymentIds))
1204 {
1205 $r = $payment->delete();
1206 if (!$r->isSuccess())
1207 {
1208 $this->errorsContainer->addErrors($r->getErrors());
1209 return false;
1210 }
1211 }
1212 }
1213 }
1214 return true;
1215 }
1216
1220 protected function isEmptyPaymentData(): bool
1221 {
1222 return empty($this->formData["PAYMENT"]) || !is_array($this->formData["PAYMENT"]);
1223 }
1224
1228 protected function needCreateDefaultPayment(): bool
1229 {
1230 return $this->getSettingsContainer()->getItemValue('createDefaultPaymentIfNeed');
1231 }
1232
1233 public function buildPayments()
1234 {
1235 global $USER;
1236
1237 $isEmptyPaymentData = $this->isEmptyPaymentData();
1238 if ($isEmptyPaymentData)
1239 {
1240 $this->formData['PAYMENT'] = [];
1241 }
1242
1243 if ($isEmptyPaymentData && !$this->needCreateDefaultPayment())
1244 {
1245 return $this;
1246 }
1247
1248 if($isEmptyPaymentData && $this->getOrder()->isNew())
1249 {
1250 $this->createEmptyPayment();
1251 return $this;
1252 }
1253
1254 if(!$this->removePayments())
1255 {
1256 $this->errorsContainer->addError(new Error('Payments remove - error'));
1257 throw new BuildingException();
1258 }
1259
1260 $paymentCollection = $this->order->getPaymentCollection();
1261
1262 foreach($this->formData["PAYMENT"] as $paymentData)
1263 {
1264 $paymentId = (int)($paymentData['ID'] ?? 0);
1265 $isNew = ($paymentId <= 0);
1266 $hasError = false;
1267 $products = $paymentData['PRODUCT'] ?? [];
1268
1269 $settablePaymentFields = $this->getSettablePaymentFields();
1270
1271 if(count($settablePaymentFields)>0)//for backward compatibility
1272 $paymentData = array_intersect_key($paymentData, array_flip($settablePaymentFields));
1273
1275 if($isNew)
1276 {
1277 $paymentItem = $paymentCollection->createItem();
1278 if (isset($paymentData['CURRENCY']) && !empty($paymentData['CURRENCY']) && $paymentData['CURRENCY'] !== $this->order->getCurrency())
1279 {
1280 $paymentData["SUM"] = \CCurrencyRates::ConvertCurrency($paymentData["SUM"], $paymentData["CURRENCY"], $this->order->getCurrency());
1281 $paymentData['CURRENCY'] = $this->order->getCurrency();
1282 }
1283 }
1284 else
1285 {
1286 $paymentItem = $paymentCollection->getItemById($paymentId);
1287
1288 if(!$paymentItem)
1289 {
1290 $this->errorsContainer->addError(new Error(Loc::getMessage("SALE_HLP_ORDERBUILDER_PAYMENT_NOT_FOUND")." - ".$paymentId));
1291 continue;
1292 }
1293 }
1294
1295 $isReturn = (isset($paymentData['IS_RETURN']) && ($paymentData['IS_RETURN'] == 'Y' || $paymentData['IS_RETURN'] == 'P'));
1296 $psService = null;
1297
1298 if((int)$paymentData['PAY_SYSTEM_ID'] > 0)
1299 {
1300 $psService = PaySystem\Manager::getObjectById((int)$paymentData['PAY_SYSTEM_ID']);
1301
1302 $paymentData['PAY_SYSTEM_NAME'] = ($psService) ? $psService->getField('NAME') : '';
1303 }
1304
1305 if (isset($paymentData['COMPANY_ID']))
1306 {
1307 $paymentData['COMPANY_ID'] = (int)$paymentData['COMPANY_ID'];
1308 }
1309
1310 if (isset($paymentData['PAID']))
1311 {
1312 $paymentFields['PAID'] = ($paymentData['PAID'] === 'Y') ? 'Y' : 'N';
1313 unset($paymentData['PAID']);
1314 }
1315
1316 if ($isNew)
1317 {
1318 if(empty($paymentData['COMPANY_ID']))
1319 {
1320 $paymentData['COMPANY_ID'] = $this->order->getField('COMPANY_ID');
1321 }
1322
1323 if(empty($paymentData['RESPONSIBLE_ID']))
1324 {
1325 $paymentData['RESPONSIBLE_ID'] = $this->order->getField('RESPONSIBLE_ID');
1326 $paymentData['EMP_RESPONSIBLE_ID'] = $USER->GetID();
1327 }
1328 }
1329
1330 $dateFields = ['DATE_PAID', 'DATE_PAY_BEFORE', 'DATE_BILL', 'PAY_RETURN_DATE', 'PAY_VOUCHER_DATE'];
1331
1332 foreach($dateFields as $fieldName)
1333 {
1334 if(isset($paymentData[$fieldName]) && is_string($paymentData[$fieldName]))
1335 {
1336 try
1337 {
1338 $paymentData[$fieldName] = new Date($paymentData[$fieldName]);
1339 }
1340 catch (ObjectException $exception)
1341 {
1342 $this->errorsContainer->addError(new Error('Wrong field "'.$fieldName.'"'));
1343 $hasError = true;
1344 }
1345 }
1346 }
1347
1348 if($paymentItem->isPaid()
1349 && isset($paymentData['SUM'])
1350 && abs(floatval($paymentData['SUM']) - floatval($paymentItem->getSum())) > 0.001)
1351 {
1352 $this->errorsContainer->addError(new Error(Loc::getMessage("SALE_HLP_ORDERBUILDER_ERROR_PAYMENT_SUM")));
1353 $hasError = true;
1354 }
1355
1356 /*
1357 * We are editing an order. We have only one payment. So the payment fields are mostly in view mode.
1358 * If we have changed the price of the order then the sum of the payment must be changed automaticaly by payment api earlier.
1359 * But if the payment sum was received from the form we will erase the previous changes.
1360 */
1361 if(isset($paymentData['SUM']))
1362 {
1363 $paymentData['SUM'] = (float)str_replace(',', '.', $paymentData['SUM']);
1364 }
1365
1366 if(isset($paymentData['RESPONSIBLE_ID']))
1367 {
1368 $paymentData['RESPONSIBLE_ID'] = !empty($paymentData['RESPONSIBLE_ID']) ? $paymentData['RESPONSIBLE_ID'] : $USER->GetID();
1369
1370 if($paymentData['RESPONSIBLE_ID'] != $paymentItem->getField('RESPONSIBLE_ID'))
1371 {
1372 if(!$isNew)
1373 {
1374 $paymentData['EMP_RESPONSIBLE_ID'] = $USER->GetID();
1375 }
1376 }
1377 }
1378
1379 if(!$hasError)
1380 {
1381 if($paymentItem->isInner() && isset($paymentData['SUM']) && $paymentData['SUM'] === 0)
1382 {
1383 unset($paymentData['SUM']);
1384 }
1385
1386 $setResult = $paymentItem->setFields($paymentData);
1387
1388 if(!$setResult->isSuccess())
1389 {
1390 $this->errorsContainer->addErrors($setResult->getErrors());
1391 }
1392
1393 if ($products)
1394 {
1395 $this->buildPayableItems($paymentItem, $products);
1396 }
1397
1398 if($isReturn && $paymentData['IS_RETURN'])
1399 {
1400 $setResult = $paymentItem->setReturn($paymentData['IS_RETURN']);
1401
1402 if(!$setResult->isSuccess())
1403 {
1404 $this->errorsContainer->addErrors($setResult->getErrors());
1405 }
1406 }
1407
1408 if(!empty($paymentFields['PAID']))
1409 {
1410 $setResult = $paymentItem->setPaid($paymentFields['PAID']);
1411
1412 if(!$setResult->isSuccess())
1413 {
1414 $this->errorsContainer->addErrors($setResult->getErrors());
1415 }
1416 }
1417 }
1418 }
1419
1420 return $this;
1421 }
1422
1434 public function buildPayableItems(Payment $payment, array $payableItems): Result
1435 {
1436 $result = new Result();
1437
1438 $basket = $this->order->getBasket();
1439 $payableItemCollection = $payment->getPayableItemCollection();
1440
1441 foreach ($payableItems as $item)
1442 {
1443 $payableItem = null;
1444
1445 if (isset($item['BASKET_CODE']))
1446 {
1448 $basketItem = $basket->getItemByBasketCode($item['BASKET_CODE']);
1449 if ($basketItem)
1450 {
1451 $payableItem = $payableItemCollection->createItemByBasketItem($basketItem);
1452 }
1453 }
1454 elseif (isset($item['DELIVERY_ID']))
1455 {
1457 foreach ($this->order->getShipmentCollection()->getNotSystemItems() as $shipment)
1458 {
1459 if (
1460 $shipment->getId() === 0
1461 && (int)$item['DELIVERY_ID'] === $shipment->getDeliveryId()
1462 )
1463 {
1464 $payableItem = $payableItemCollection->createItemByShipment($shipment);
1465 }
1466 }
1467 }
1468
1469 if ($payableItem === null)
1470 {
1471 continue;
1472 }
1473
1474 $quantity = floatval(str_replace(',', '.', $item['QUANTITY']));
1475
1476 $payableItem->setField('QUANTITY', $quantity);
1477 }
1478
1479 return $result;
1480 }
1481
1482 public function buildTradeBindings()
1483 {
1484 if(!isset($this->formData["TRADE_BINDINGS"]))
1485 {
1486 return $this;
1487 }
1488
1489 if(!$this->removeTradeBindings())
1490 {
1491 return $this;
1492 }
1493
1494 if(isset($this->formData["TRADE_BINDINGS"]) && count($this->formData["TRADE_BINDINGS"])>0)
1495 {
1496 $tradeBindingCollection = $this->order->getTradeBindingCollection();
1497
1498 foreach($this->formData["TRADE_BINDINGS"] as $fields)
1499 {
1500 $tradingPlatformId = (int)($fields['TRADING_PLATFORM_ID'] ?? 0);
1501 if ($tradingPlatformId === 0)
1502 {
1503 continue;
1504 }
1505
1506 $r = $this->tradingPlatformExists($tradingPlatformId);
1507
1508 if($r->isSuccess())
1509 {
1510 $id = (int)($fields['ID'] ?? 0);
1511 $isNew = ($id <= 0);
1512
1513 if($isNew)
1514 {
1515 $binding = $tradeBindingCollection->createItem();
1516 }
1517 else
1518 {
1519 $binding = $tradeBindingCollection->getItemById($id);
1520
1521 if(!$binding)
1522 {
1523 $this->errorsContainer->addError(new Error('Can\'t find Trade Binding with id:"'.$id.'"', 'TRADE_BINDING_NOT_EXISTS'));
1524 continue;
1525 }
1526 }
1527
1528 $fields = array_intersect_key($fields, array_flip(TradeBindingEntity::getAvailableFields()));
1529
1530 $r = $binding->setFields($fields);
1531 }
1532
1533 if(!$r->isSuccess())
1534 $this->errorsContainer->addErrors($r->getErrors());
1535 }
1536 }
1537
1538 return $this;
1539 }
1540
1541 protected function tradingPlatformExists($id)
1542 {
1543 $r = new Result();
1544
1545 $platformFields = TradingPlatformTable::getById($id)->fetchAll();
1546
1547 if (!isset($platformFields[0]))
1548 {
1549 $r->addError(new Error('tradingPlatform is not exists'));
1550 }
1551
1552 return $r;
1553 }
1554
1555 protected function removeTradeBindings()
1556 {
1557 if($this->getSettingsContainer()->getItemValue('deleteTradeBindingIfNotExists'))
1558 {
1559 $tradeBindingCollection = $this->order->getTradeBindingCollection();
1560
1561 $internalIx = [];
1562 foreach($this->formData["TRADE_BINDINGS"] as $tradeBinding)
1563 {
1564 if(!isset($tradeBinding['ID']))
1565 continue;
1566
1567 $binding = $tradeBindingCollection->getItemById($tradeBinding['ID']);
1568
1569 if ($binding == null)
1570 continue;
1571
1572 $internalIx[] = $binding->getId();
1573 }
1574
1575 foreach ($tradeBindingCollection as $binding)
1576 {
1577 if(!in_array($binding->getId(), $internalIx))
1578 {
1579 $r = $binding->delete();
1580 if (!$r->isSuccess())
1581 {
1582 $this->errorsContainer->addErrors($r->getErrors());
1583 return false;
1584 }
1585 }
1586 }
1587 }
1588
1589 return true;
1590 }
1591
1592 public function finalActions()
1593 {
1594 if($this->isStartField)
1595 {
1596 $hasMeaningfulFields = $this->order->hasMeaningfulField();
1597 $r = $this->order->doFinalAction($hasMeaningfulFields);
1598
1599 if(!$r->isSuccess())
1600 {
1601 $this->errorsContainer->addErrors($r->getErrors());
1602 }
1603 }
1604
1605 return $this;
1606 }
1607
1608 public function getOrder()
1609 {
1610 return $this->order;
1611 }
1612
1613 public function getSettingsContainer()
1614 {
1616 }
1617
1618 public function getErrorsContainer()
1619 {
1621 }
1622
1623 public function getFormData($fieldName = '')
1624 {
1625 if($fieldName <> '')
1626 {
1627 $result = $this->formData[$fieldName] ?? null;
1628 }
1629 else
1630 {
1631 $result = $this->formData;
1632 }
1633
1634 return $result;
1635 }
1636
1637 public function getBasketBuilder()
1638 {
1639 return $this->basketBuilder;
1640 }
1641
1642 public static function getDefaultPersonType($siteId)
1643 {
1644 $personTypes = self::getBuyerTypesList($siteId);
1645 reset($personTypes);
1646 return key($personTypes);
1647 }
1648
1649 public static function getBuyerTypesList($siteId)
1650 {
1651 static $result = array();
1652
1653 if(!isset($result[$siteId]))
1654 {
1655 $result[$siteId] = array();
1656
1657 $res = \Bitrix\Sale\Internals\PersonTypeTable::getList(array(
1658 'order' => array('SORT' => 'ASC', 'NAME' => 'ASC'),
1659 'filter' => array('=ACTIVE' => 'Y', '=PERSON_TYPE_SITE.SITE_ID' => $siteId),
1660 ));
1661
1662 while ($personType = $res->fetch())
1663 {
1664 $result[$siteId][$personType["ID"]] = htmlspecialcharsbx($personType["NAME"])." [".$personType["ID"]."]";
1665 }
1666 }
1667
1668 return $result[$siteId];
1669 }
1670
1671 public function getUserId()
1672 {
1673 $userId = (int)($this->formData["USER_ID"] ?? 0);
1674 if($userId > 0)
1675 {
1676 return $userId;
1677 }
1678
1679 $userId = 0;
1680
1681 $settingValue = (int)$this->getSettingsContainer()->getItemValue('createUserIfNeed');
1682 if ($settingValue === \Bitrix\Sale\Helpers\Order\Builder\SettingsContainer::SET_ANONYMOUS_USER)
1683 {
1684 $userId = \CSaleUser::GetAnonymousUserID();
1685 }
1686 elseif ($settingValue === \Bitrix\Sale\Helpers\Order\Builder\SettingsContainer::ALLOW_NEW_USER_CREATION)
1687 {
1688 $userId = $this->createUserFromFormData();
1689 }
1690
1691 if ($userId > 0 && empty($this->formData["USER_ID"]))
1692 {
1693 $this->formData["USER_ID"] = $userId;
1694 }
1695
1696 return $userId;
1697 }
1698
1707 protected function createUserFromFormData()
1708 {
1709 $errors = [];
1710 $orderProps = $this->order->getPropertyCollection();
1711
1712 if ($email = $orderProps->getUserEmail())
1713 {
1714 $email = $email->getValue();
1715 }
1716
1717 if ($name = $orderProps->getPayerName())
1718 {
1719 $name = $name->getValue();
1720 }
1721
1722 if ($phone = $orderProps->getPhone())
1723 {
1724 $phone = $phone->getValue();
1725 }
1726
1727 if ($this->getSettingsContainer()->getItemValue('searchExistingUserOnCreating'))
1728 {
1729 $userId = $this->searchExistingUser($email, $phone);
1730 }
1731
1732 if (!isset($userId))
1733 {
1734 $userId = $this->searchExistingUser($email, $phone);
1735 }
1736
1737 if (!isset($userId))
1738 {
1739 $userId = \CSaleUser::DoAutoRegisterUser(
1740 $email,
1741 $name,
1742 $this->formData['SITE_ID'],
1743 $errors,
1744 [
1745 'PERSONAL_PHONE' => $phone,
1746 'PHONE_NUMBER' => $phone,
1747 ]
1748 );
1749
1750 if (!empty($errors))
1751 {
1752 foreach ($errors as $val)
1753 {
1754 $this->errorsContainer->addError(new Error($val['TEXT'], 0, 'USER'));
1755 }
1756 }
1757 else
1758 {
1759 // ToDo remove it? when to authorize buyer?
1760 global $USER;
1761 $USER->Authorize($userId);
1762 }
1763 }
1764
1765 return $userId;
1766 }
1767
1776 private function searchExistingUser($email, $phone): ?int
1777 {
1778 $existingUserId = null;
1779
1780 if (!empty($email))
1781 {
1782 $res = Main\UserTable::getRow([
1783 'filter' => [
1784 '=ACTIVE' => 'Y',
1785 '=EMAIL' => $email,
1786 ],
1787 'select' => ['ID'],
1788 ]);
1789 if (isset($res['ID']))
1790 {
1791 $existingUserId = (int)$res['ID'];
1792 }
1793 }
1794
1795 if (!$existingUserId && !empty($phone))
1796 {
1797 $normalizedPhone = NormalizePhone($phone);
1798 $normalizedPhoneForRegistration = Main\UserPhoneAuthTable::normalizePhoneNumber($phone);
1799
1800 if (!empty($normalizedPhone))
1801 {
1802 $res = Main\UserTable::getRow([
1803 'filter' => [
1804 'ACTIVE' => 'Y',
1805 [
1806 'LOGIC' => 'OR',
1807 '=PHONE_AUTH.PHONE_NUMBER' => $normalizedPhoneForRegistration,
1808 '=PERSONAL_PHONE' => $normalizedPhone,
1809 '=PERSONAL_MOBILE' => $normalizedPhone,
1810 ],
1811 ],
1812 'select' => ['ID'],
1813 ]);
1814 if (isset($res['ID']))
1815 {
1816 $existingUserId = (int)$res['ID'];
1817 }
1818 }
1819 }
1820
1821 return $existingUserId;
1822 }
1823}
static loadLanguageFile($file, $language=null, $normalize=true)
Definition loc.php:224
static getMessage($code, $replace=null, $language=null)
Definition loc.php:29
prepareFieldsStatusId($isNew, $item, $defaultFields)
setBasketBuilder(BasketBuilder $basketBuilder)
modifyQuantityShipmentItem(ShipmentItem $shipmentItem, array $params)
prepareDataForSetFields(\Bitrix\Sale\Shipment $shipment, $items)
static getInstance($type)
Definition registry.php:183