1C-Bitrix 25.700.0
Загрузка...
Поиск...
Не найдено
orderbuilder.php
См. документацию.
1<?php
2namespace Bitrix\Sale\Helpers\Order\Builder;
3
4use Bitrix\Main;
5use Bitrix\Sale\Internals;
6use Bitrix\Sale\PropertyValue;
7use Bitrix\Sale\PropertyValueCollection;
8use Bitrix\Sale\BasketItem;
9use Bitrix\Sale\Shipment;
10use Bitrix\Main\ArgumentNullException;
11use Bitrix\Main\Error;
12use Bitrix\Main\Localization\Loc;
13use Bitrix\Main\ObjectException;
14use Bitrix\Sale\Order;
15use Bitrix\Sale\Helpers\Admin\Blocks\OrderBuyer;
16use Bitrix\Sale\Payment;
17use Bitrix\Sale\PaySystem;
18use Bitrix\Main\Type\Date;
19use Bitrix\Main\Type\DateTime;
20use Bitrix\Sale\Registry;
21use \Bitrix\Sale\Delivery;
22use Bitrix\Sale\Result;
23use Bitrix\Sale\Configuration;
24use Bitrix\Sale\ShipmentItem;
25use Bitrix\Sale\TradeBindingEntity;
26use Bitrix\Sale\TradingPlatformTable;
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
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 {
120 $this->delegate = (int)$data['ID'] > 0 ? new OrderBuilderExist($this) : new OrderBuilderNew($this);
121
122 return $this;
123 }
124
125 public function createOrder()
126 {
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 {
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(
179 OrderBuyer::getDefaultPersonType(
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 = [];
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 $shipmentCollection = $this->order->getShipmentCollection();
388
389 foreach($this->formData["SHIPMENT"] as $item)
390 {
391 $shipmentId = intval($item['ID'] ?? 0);
392 $isNew = ($shipmentId <= 0);
393 $deliveryService = null;
394 $storeId = null;
395
396 if (!isset($item['DEDUCTED']) || $item['DEDUCTED'] !== 'Y')
397 {
398 $item['DEDUCTED'] = 'N';
399 }
400
401 $extraServices =
402 isset($item['EXTRA_SERVICES']) && is_array($item['EXTRA_SERVICES'])
403 ? $item['EXTRA_SERVICES']
404 : []
405 ;
406
407 $settableShipmentFields = $this->getSettableShipmentFields();
408 if (!empty($settableShipmentFields))
409 {
410 //for backward compatibility
411 $product = $item['PRODUCT'] ?? null;
412 $storeId = (int)($item['DELIVERY_STORE_ID'] ?? 0);
413 $item = array_intersect_key($item, array_flip($settableShipmentFields));
414 if ($product !== null)
415 {
416 $item['PRODUCT'] = $product;
417 }
418 unset($product);
419 }
420
421 if($isNew)
422 {
423 $shipment = $shipmentCollection->createItem();
424 }
425 else
426 {
427 $shipment = $shipmentCollection->getItemById($shipmentId);
428
429 if(!$shipment)
430 {
431 $this->errorsContainer->addError(new Error(Loc::getMessage("SALE_HLP_ORDERBUILDER_SHIPMENT_NOT_FOUND")." - ".$shipmentId));
432 continue;
433 }
434 }
435
436 $defaultFields = $shipment->getFieldValues();
437
439 $systemShipment = $shipmentCollection->getSystemShipment();
440 $systemShipmentItemCollection = $systemShipment->getShipmentItemCollection();
441 //We suggest that if products is null - ShipmentBasket not loaded yet, if array ShipmentBasket loaded, but empty.
442 $products = null;
443
444 if(
445 !isset($item['PRODUCT'])
446 && $shipment->getId() <= 0
447 )
448 {
449 $products = array();
450 $basket = $this->order->getBasket();
451
452 if($basket)
453 {
454 $basketItems = $basket->getBasketItems();
455 foreach($basketItems as $product)
456 {
457 $systemShipmentItem = $systemShipmentItemCollection->getItemByBasketCode($product->getBasketCode());
458
459 if($product->isBundleChild() || !$systemShipmentItem || $systemShipmentItem->getQuantity() <= 0)
460 continue;
461
462 $products[] = array(
463 'AMOUNT' => $systemShipmentItem->getQuantity(),
464 'BASKET_CODE' => $product->getBasketCode(),
465 );
466 }
467 }
468 }
469 elseif (isset($item['PRODUCT']) && is_array($item['PRODUCT']))
470 {
471 $products = $item['PRODUCT'];
472 }
473
474 if($item['DEDUCTED'] == 'Y' && $products !== null)
475 {
476 $basketResult = $this->buildShipmentBasket($shipment, $products);
477
478 if(!$basketResult->isSuccess())
479 {
480 $this->errorsContainer->addErrors($basketResult->getErrors());
481 }
482 }
483
484 $shipmentFields = array(
485 'COMPANY_ID' => (isset($item['COMPANY_ID']) && intval($item['COMPANY_ID']) > 0) ? intval($item['COMPANY_ID']) : 0,
486 'DEDUCTED' => $item['DEDUCTED'] ?? 'N',
487 'DELIVERY_DOC_NUM' => $item['DELIVERY_DOC_NUM'] ?? '',
488 'TRACKING_NUMBER' => $item['TRACKING_NUMBER'] ?? '',
489 'CURRENCY' => $this->order->getCurrency(),
490 'COMMENTS' => $item['COMMENTS'] ?? '',
491 );
492
493 if (!empty($item['IS_REALIZATION']))
494 {
495 $shipmentFields['IS_REALIZATION'] = $item['IS_REALIZATION'];
496 }
497
498 if (!empty($item['ACCOUNT_NUMBER']))
499 {
500 $shipmentFields['ACCOUNT_NUMBER'] = $item['ACCOUNT_NUMBER'];
501 }
502
503 if (!empty($item['XML_ID']))
504 {
505 $shipmentFields['XML_ID'] = $item['XML_ID'];
506 }
507
508 $statusId = $this->prepareFieldsStatusId($isNew, $item, $defaultFields);
509 if ($statusId !== '')
510 {
511 $shipmentFields['STATUS_ID'] = $statusId;
512 }
513
514 if (empty($item['COMPANY_ID']))
515 {
516 $shipmentFields['COMPANY_ID'] = $this->order->getField('COMPANY_ID');
517 }
518
519 if (empty($item['RESPONSIBLE_ID']))
520 {
521 $shipmentFields['RESPONSIBLE_ID'] = $this->order->getField('RESPONSIBLE_ID');
522 $shipmentFields['EMP_RESPONSIBLE_ID'] = $this->getCurrentUserId();
523 }
524
525 $deliveryId = 0;
526 if (isset($item['PROFILE_ID']) && (int)$item['PROFILE_ID'] > 0)
527 {
528 $deliveryId = (int)$item['PROFILE_ID'];
529 }
530 elseif (isset($item['DELIVERY_ID']))
531 {
532 $deliveryId = (int)$item['DELIVERY_ID'];
533 }
534 elseif ($shipment->getField('DELIVERY_ID'))
535 {
536 $deliveryId = $shipment->getField('DELIVERY_ID');
537 }
538
539 $shipmentFields['DELIVERY_ID'] = $deliveryId;
540
541 $dateFields = ['DELIVERY_DOC_DATE', 'DATE_DEDUCTED', 'DATE_MARKED', 'DATE_CANCELED', 'DATE_RESPONSIBLE_ID'];
542
543 foreach($dateFields as $fieldName)
544 {
545 if(isset($item[$fieldName]))
546 {
547 if (is_string($item[$fieldName]))
548 {
549 try
550 {
551 $shipmentFields[$fieldName] = new DateTime($item[$fieldName]);
552 }
553 catch (ObjectException $exception)
554 {
555 $this->errorsContainer->addError(new Error('Wrong field "'.$fieldName.'"'));
556 }
557 }
558 elseif ($item[$fieldName] instanceof Date)
559 {
560 $shipmentFields[$fieldName] = $item[$fieldName];
561 }
562 }
563 }
564
565 try
566 {
567 if($deliveryService = Delivery\Services\Manager::getObjectById($shipmentFields['DELIVERY_ID']))
568 {
569 if($deliveryService->isProfile())
570 {
571 $shipmentFields['DELIVERY_NAME'] = $deliveryService->getNameWithParent();
572 }
573 else
574 {
575 $shipmentFields['DELIVERY_NAME'] = $deliveryService->getName();
576 }
577 }
578 }
579 catch (ArgumentNullException $e)
580 {
581 $this->errorsContainer->addError(new Error(Loc::getMessage('SALE_HLP_ORDERBUILDER_DELIVERY_NOT_FOUND'), 'OB_DELIVERY_NOT_FOUND'));
582 return $this;
583 }
584
585 $responsibleId = $shipment->getField('RESPONSIBLE_ID');
586
587 if (($item['RESPONSIBLE_ID'] ?? null) !== $responsibleId || empty($responsibleId))
588 {
589 if (isset($item['RESPONSIBLE_ID']))
590 {
591 $shipmentFields['RESPONSIBLE_ID'] = $item['RESPONSIBLE_ID'];
592 }
593 else
594 {
595 $shipmentFields['RESPONSIBLE_ID'] = $this->order->getField('RESPONSIBLE_ID');
596 }
597
598 if (!empty($shipmentFields['RESPONSIBLE_ID']))
599 {
600 $shipmentFields['EMP_RESPONSIBLE_ID'] = $this->getCurrentUserId();
601 }
602 }
603
604 if($extraServices)
605 {
606 $shipment->setExtraServices($extraServices);
607 }
608
609 $setFieldsResult = $shipment->setFields($shipmentFields);
610
611 if(!$setFieldsResult->isSuccess())
612 {
613 $this->errorsContainer->addErrors($setFieldsResult->getErrors());
614 }
615
616 // region Properties
617 if (isset($item['PROPERTIES']) && is_array($item['PROPERTIES']))
618 {
620 $propCollection = $shipment->getPropertyCollection();
621 $res = $propCollection->setValuesFromPost($item, []);
622
623 if (!$res->isSuccess())
624 {
625 foreach ($res->getErrors() as $error)
626 {
627 $this->getErrorsContainer()->addError(
628 new Main\Error($error->getMessage(), $error->getCode(), 'SHIPMENT_PROPERTIES')
629 );
630 }
631 }
632
634 foreach ($propCollection as $propValue)
635 {
636 if ($propValue->isUtil())
637 {
638 continue;
639 }
640
641 $property = $propValue->getProperty();
642 $relatedDeliveryIds = (isset($property['RELATION']) && is_array($property['RELATION']))
643 ? array_column(
644 array_filter(
645 $property['RELATION'],
646 function ($item)
647 {
648 return $item['ENTITY_TYPE'] === 'D';
649 }
650 ),
651 'ENTITY_ID'
652 )
653 : [];
654
655 if (
656 !empty($relatedDeliveryIds)
657 && !in_array($shipment->getField('DELIVERY_ID'), $relatedDeliveryIds)
658 )
659 {
660 continue;
661 }
662
663 $res = $propValue->verify();
664 if (!$res->isSuccess())
665 {
666 foreach ($res->getErrors() as $error)
667 {
668 $this->getErrorsContainer()->addError(
669 new Main\Error($error->getMessage(), $propValue->getPropertyId(), 'SHIPMENT_PROPERTIES')
670 );
671 }
672 }
673
674 $res = $propValue->checkRequiredValue($propValue->getPropertyId(), $propValue->getValue());
675 if (!$res->isSuccess())
676 {
677 foreach ($res->getErrors() as $error)
678 {
679 $this->getErrorsContainer()->addError(
680 new Main\Error($error->getMessage(), $propValue->getPropertyId(), 'SHIPMENT_PROPERTIES')
681 );
682 }
683 }
684 }
685 }
686 // endregion
687
688 if ($storeId)
689 {
690 $shipment->setStoreId($storeId);
691 }
692
693 if($item['DEDUCTED'] == 'N' && $products !== null)
694 {
695 $basketResult = $this->buildShipmentBasket($shipment, $products);
696
697 if(!$basketResult->isSuccess())
698 {
699 $this->errorsContainer->addErrors($basketResult->getErrors());
700 }
701 }
702
703 $isCustomPrice = false;
704 if (isset($item['CUSTOM_PRICE_DELIVERY']))
705 {
706 $isCustomPrice = $item['CUSTOM_PRICE_DELIVERY'] === 'Y';
707 }
708
709 $fields = array(
710 'CUSTOM_PRICE_DELIVERY' => $isCustomPrice ? 'Y' : 'N',
711 'PRICE_DELIVERY' => (float)str_replace(',', '.', $item['PRICE_DELIVERY'] ?? 0),
712 );
713
714 if (isset($item['ALLOW_DELIVERY']))
715 {
716 $fields['ALLOW_DELIVERY'] = $item['ALLOW_DELIVERY'] === 'Y' ? 'Y' : 'N';
717 }
718
719 if (isset($item['BASE_PRICE_DELIVERY']))
720 {
721 $fields['BASE_PRICE_DELIVERY'] = (float)str_replace(',', '.', $item['BASE_PRICE_DELIVERY']);
722 }
723
724 $shipment = $this->delegate->setShipmentPriceFields($shipment, $fields);
725
726 if($deliveryService && !empty($item['ADDITIONAL']))
727 {
728 $modifiedShipment = $deliveryService->processAdditionalInfoShipmentEdit($shipment, $item['ADDITIONAL']);
729
731 if ($modifiedShipment && get_class($modifiedShipment) == $registry->getShipmentClassName())
732 {
733 $shipment = $modifiedShipment;
734 }
735 }
736 }
737
738 return $this;
739 }
740
741 protected function removeShipmentItems(\Bitrix\Sale\Shipment $shipment, $products, $idsFromForm)
742 {
743 $result = new Result();
744
745 $shipmentItemCollection = $shipment->getShipmentItemCollection();
746
748 foreach ($shipmentItemCollection as $shipmentItem)
749 {
750 if (!array_key_exists($shipmentItem->getBasketCode(), $idsFromForm))
751 {
753 $r = $shipmentItem->delete();
754 if (!$r->isSuccess())
755 {
756 $result->addErrors($r->getErrors());
757 }
758 }
759
760 $shipmentItemStoreCollection = $shipmentItem->getShipmentItemStoreCollection();
761 if ($shipmentItemStoreCollection)
762 {
764 foreach ($shipmentItemStoreCollection as $shipmentItemStore)
765 {
766 $shipmentItemId = $shipmentItemStore->getId();
767 if (!isset($idsFromForm[$shipmentItem->getBasketCode()]['BARCODE_IDS'][$shipmentItemId]))
768 {
769 $delResult = $shipmentItemStore->delete();
770 if (!$delResult->isSuccess())
771 {
772 $result->addErrors($delResult->getErrors());
773 }
774 }
775 }
776 }
777 }
778
779 return $result;
780 }
781
794 public function buildShipmentBasket(&$shipment, $shipmentBasket)
795 {
797 $result = new Result();
798 $shippingItems = array();
799 $idsFromForm = array();
800 $basket = $this->order->getBasket();
801 $shipmentItemCollection = $shipment->getShipmentItemCollection();
803
804 if(is_array($shipmentBasket))
805 {
806 // PREPARE DATA FOR SET_FIELDS
807 foreach ($shipmentBasket as $items)
808 {
809 $items['QUANTITY'] = floatval(str_replace(',', '.', $items['QUANTITY']));
810 $items['AMOUNT'] = floatval(str_replace(',', '.', $items['AMOUNT']));
811
812 $r = $this->prepareDataForSetFields($shipment, $items);
813 if($r->isSuccess())
814 {
815 $items = $r->getData()[0];
816 }
817 else
818 {
819 $result->addErrors($r->getErrors());
820 return $result;
821 }
822
823 if (isset($items['BASKET_ID']) && !BasketBuilder::isBasketItemNew($items['BASKET_ID']))
824 {
825 if (!$basketItem = $basket->getItemById($items['BASKET_ID']))
826 {
827 $result->addError( new Error(
828 Loc::getMessage('SALE_ORDER_SHIPMENT_BASKET_BASKET_ITEM_NOT_FOUND', array(
829 '#BASKET_ITEM_ID#' => $items['BASKET_ID'],
830 )),
831 'PROVIDER_UNRESERVED_SHIPMENT_ITEM_WRONG_BASKET_ITEM')
832 );
833 return $result;
834 }
836 $basketCode = $basketItem->getBasketCode();
837 }
838 else
839 {
840 $basketCode = $items['BASKET_CODE'];
841 if(!$basketItem = $basket->getItemByBasketCode($basketCode))
842 {
843 $result->addError( new Error(
844 Loc::getMessage('SALE_ORDER_SHIPMENT_BASKET_BASKET_ITEM_NOT_FOUND', array(
845 '#BASKET_ITEM_ID#' => $basketCode,
846 )),
847 'PROVIDER_UNRESERVED_SHIPMENT_ITEM_WRONG_BASKET_ITEM')
848 );
849 return $result;
850 }
851 }
852
853 $isSupportedMarkingCode = false;
854 if (isset($items['IS_SUPPORTED_MARKING_CODE']))
855 {
856 $isSupportedMarkingCode = $items['IS_SUPPORTED_MARKING_CODE'] === 'Y';
857 }
858
859 $tmp = [
860 'BASKET_CODE' => $basketCode,
861 'AMOUNT' => $items['AMOUNT'] ?? 0,
862 'ORDER_DELIVERY_BASKET_ID' => $items['ORDER_DELIVERY_BASKET_ID'] ?? 0,
863 'IS_SUPPORTED_MARKING_CODE' => $isSupportedMarkingCode ? 'Y' : 'N',
864 ];
865 if (array_key_exists('XML_ID', $items))
866 {
867 $tmp['XML_ID'] = $items['XML_ID'];
868 }
869 $idsFromForm[$basketCode] = array();
870
871 if (
872 isset($items['BARCODE_INFO'])
873 && $items['BARCODE_INFO']
874 && ($useStoreControl || $isSupportedMarkingCode)
875 )
876 {
877 foreach ($items['BARCODE_INFO'] as $item)
878 {
879 if (!$basketItem->isReservableItem())
880 {
881 $shippingItems[] = $tmp;
882 continue;
883 }
884
885 $barcodeQuantity = ($basketItem->isBarcodeMulti() || $basketItem->isSupportedMarkingCode()) ? 1 : $item['QUANTITY'];
886 $barcodeStoreId = $item['STORE_ID'];
887
888 $tmp['BARCODE'] = array(
889 'ORDER_DELIVERY_BASKET_ID' => $items['ORDER_DELIVERY_BASKET_ID'] ?? 0,
890 'STORE_ID' => $barcodeStoreId,
891 'QUANTITY' => $barcodeQuantity,
892 );
893
894 $tmp['BARCODE_INFO'] = [
895 $item['STORE_ID'] => [
896 'STORE_ID' => (int)$barcodeStoreId,
897 'QUANTITY' => (float)$barcodeQuantity,
898 ],
899 ];
900
901 $barcodeCount = 0;
902 if ($item['BARCODE'])
903 {
904 foreach ($item['BARCODE'] as $barcode)
905 {
906 $barcode['ID'] = (int)($barcode['ID'] ?? 0);
907
908 $tmp['BARCODE_INFO'][$barcodeStoreId]['BARCODE'] = [$barcode];
909
910 if (isset($barcode['MARKING_CODE']))
911 {
912 $barcode['MARKING_CODE'] = (string)$barcode['MARKING_CODE'];
913 }
914 else
915 {
916 $barcode['MARKING_CODE'] = '';
917 }
918
919 $idsFromForm[$basketCode]['BARCODE_IDS'][$barcode['ID']] = true;
920
921 if ($barcode['ID'] > 0)
922 {
923 $tmp['BARCODE']['ID'] = $barcode['ID'];
924 }
925 else
926 {
927 unset($tmp['BARCODE']['ID']);
928 }
929
930 $tmp['BARCODE']['BARCODE'] = (string)$barcode['VALUE'];
931 $tmp['BARCODE']['MARKING_CODE'] = $barcode['MARKING_CODE'];
932
933 $shippingItems[] = $tmp;
934 $barcodeCount++;
935 }
936 }
937 elseif (!$basketItem->isBarcodeMulti() && !$basketItem->isSupportedMarkingCode())
938 {
939 $shippingItems[] = $tmp;
940 continue;
941 }
942
943
944 if ($basketItem->isBarcodeMulti() || $basketItem->isSupportedMarkingCode())
945 {
946 while ($barcodeCount < $item['QUANTITY'])
947 {
948 unset($tmp['BARCODE']['ID']);
949 $tmp['BARCODE']['BARCODE'] = '';
950 $tmp['BARCODE']['MARKING_CODE'] = '';
951 $shippingItems[] = $tmp;
952 $barcodeCount++;
953 }
954 }
955 }
956 }
957 else
958 {
959 $shippingItems[] = $tmp;
960 }
961 }
962 }
963
964 // DELETE FROM COLLECTION
965 $r = $this->removeShipmentItems($shipment, $shipmentBasket, $idsFromForm);
966 if(!$r->isSuccess())
967 $result->addErrors($r->getErrors());
968
969 $isStartField = $shipmentItemCollection->isStartField();
970
971 // SET DATA
972 foreach ($shippingItems as $shippingItem)
973 {
974 if ((int)$shippingItem['ORDER_DELIVERY_BASKET_ID'] <= 0)
975 {
976 $basketCode = $shippingItem['BASKET_CODE'];
978 $basketItem = $this->order->getBasket()->getItemByBasketCode($basketCode);
979
981 $shipmentItem = $shipmentItemCollection->createItem($basketItem);
982
983 if ($shipmentItem === null)
984 {
985 $result->addError(
986 new Error(
987 Loc::getMessage('SALE_ORDER_SHIPMENT_BASKET_ERROR_ALREADY_SHIPPED')
988 )
989 );
990 return $result;
991 }
992
993 unset($shippingItem['BARCODE']['ORDER_DELIVERY_BASKET_ID']);
994 }
995 else
996 {
997 $shipmentItem = $shipmentItemCollection->getItemById($shippingItem['ORDER_DELIVERY_BASKET_ID']);
998
999 if($shipmentItem)
1000 {
1001 $basketItem = $shipmentItem->getBasketItem();
1002 }
1003 else //It's a possible case when we are creating new shipment.
1004 {
1006 $systemShipment = $shipment->getCollection()->getSystemShipment();
1008 $systemShipmentItemCollection = $systemShipment->getShipmentItemCollection();
1009
1010 $shipmentItem = $systemShipmentItemCollection->getItemById($shippingItem['ORDER_DELIVERY_BASKET_ID']);
1011
1012 if($shipmentItem)
1013 {
1014 $basketItem = $shipmentItem->getBasketItem();
1015 $shipmentItem = $shipmentItemCollection->createItem($basketItem);
1016 $shipmentItem->setField('QUANTITY', $shipmentItem->getField('QUANTITY'));
1017 }
1018 else
1019 {
1020 $result->addError(
1021 new Error(
1022 Loc::getMessage('SALE_HLP_ORDERBUILDER_SHIPMENT_ITEM_ERROR',[
1023 '#ID#' => $shippingItem['ORDER_DELIVERY_BASKET_ID'],
1024 ])
1025 )
1026 );
1027
1028 continue;
1029 }
1030 }
1031 }
1032
1033 if ($shippingItem['AMOUNT'] <= 0)
1034 {
1035 $result->addError(
1036 new Error(
1037 Loc::getMessage('SALE_ORDER_SHIPMENT_BASKET_ERROR_QUANTITY', array('#BASKET_ITEM#' => $basketItem->getField('NAME'))),
1038 'BASKET_ITEM_'.$basketItem->getBasketCode()
1039 )
1040 );
1041 continue;
1042 }
1043
1044 $r = $this->modifyQuantityShipmentItem($shipmentItem, $shippingItem);
1045 if(!$r->isSuccess())
1046 $result->addErrors($r->getErrors());
1047
1048 if (array_key_exists('XML_ID', $shippingItem))
1049 {
1050 $setFieldResult = $shipmentItem->setField('XML_ID', $shippingItem['XML_ID']);
1051 if (!$setFieldResult->isSuccess())
1052 {
1053 $result->addErrors($setFieldResult->getErrors());
1054 }
1055 }
1056 }
1057
1058 if ($isStartField)
1059 {
1060 $hasMeaningfulFields = $shipmentItemCollection->hasMeaningfulField();
1061
1063 $r = $shipmentItemCollection->doFinalAction($hasMeaningfulFields);
1064 if (!$r->isSuccess())
1065 {
1066 $result->addErrors($r->getErrors());
1067 }
1068 }
1069
1070 return $result;
1071 }
1072
1073 protected function prepareDataForSetFields(\Bitrix\Sale\Shipment $shipment, $items)
1074 {
1075 $result = new Result();
1076 return $result->setData([$items]);
1077 }
1078
1079 protected function modifyQuantityShipmentItem(ShipmentItem $shipmentItem, array $params)
1080 {
1081 $result = new Result();
1082 if ($shipmentItem->getQuantity() < $params['AMOUNT'])
1083 {
1084 $this->order->setMathActionOnly(true);
1085 $setFieldResult = $shipmentItem->setField('QUANTITY', $params['AMOUNT']);
1086 $this->order->setMathActionOnly(false);
1087
1088 if (!$setFieldResult->isSuccess())
1089 {
1090 $result->addErrors($setFieldResult->getErrors());
1091 }
1092 }
1093
1094 $r = $this->setBarcodeShipmentItem($shipmentItem, $params);
1095
1096 if($r->isSuccess() == false)
1097 {
1098 $result->addErrors($r->getErrors());
1099 }
1100
1101 $setFieldResult = $shipmentItem->setField('QUANTITY', $params['AMOUNT']);
1102
1103 if (!$setFieldResult->isSuccess())
1104 {
1105 $result->addErrors($setFieldResult->getErrors());
1106 }
1107
1108 return $result;
1109 }
1110
1111 protected function setBarcodeShipmentItem(ShipmentItem $shipmentItem, array $params)
1112 {
1113 $result = new Result();
1114 $basketItem = $shipmentItem->getBasketItem();
1115
1117
1118 if (
1119 !empty($params['BARCODE'])
1120 && ($useStoreControl || $params['IS_SUPPORTED_MARKING_CODE'] === 'Y' )
1121 && $basketItem->isReservableItem()
1122 )
1123 {
1124 $barcode = $params['BARCODE'];
1125
1127 $shipmentItemStoreCollection = $shipmentItem->getShipmentItemStoreCollection();
1128 if ($shipmentItemStoreCollection)
1129 {
1130 if (!$basketItem->isBarcodeMulti() && !$basketItem->isSupportedMarkingCode())
1131 {
1133 $r = $shipmentItemStoreCollection->setBarcodeQuantityFromArray($params);
1134 if (!$r->isSuccess())
1135 {
1136 $result->addErrors($r->getErrors());
1137 }
1138 }
1139
1140 if (isset($barcode['ID']) && intval($barcode['ID']) > 0)
1141 {
1143 if ($shipmentItemStore = $shipmentItemStoreCollection->getItemById($barcode['ID']))
1144 {
1145 unset($barcode['ID']);
1146 $setFieldResult = $shipmentItemStore->setFields($barcode);
1147
1148 if (!$setFieldResult->isSuccess())
1149 {
1150 $result->addErrors($setFieldResult->getErrors());
1151 }
1152 }
1153 }
1154 else
1155 {
1156 $shipmentItemStore = $shipmentItemStoreCollection->createItem($basketItem);
1157 $setFieldResult = $shipmentItemStore->setFields($barcode);
1158 if (!$setFieldResult->isSuccess())
1159 {
1160 $result->addErrors($setFieldResult->getErrors());
1161 }
1162 }
1163 }
1164 }
1165
1166 return $result;
1167 }
1168
1169 protected function createEmptyPayment()
1170 {
1171 $innerPaySystem = PaySystem\Manager::getObjectById(PaySystem\Manager::getInnerPaySystemId());
1172
1173 $paymentCollection = $this->order->getPaymentCollection();
1174 $payment = $paymentCollection->createItem($innerPaySystem);
1175 $payment->setField('SUM', $this->order->getPrice());
1176
1177 return $payment;
1178 }
1179
1180 protected function removePayments()
1181 {
1182 if($this->getSettingsContainer()->getItemValue('deletePaymentIfNotExists'))
1183 {
1184 $paymentCollection = $this->order->getPaymentCollection();
1185
1186 $paymentIds = [];
1187 foreach($this->formData["PAYMENT"] as $paymentData)
1188 {
1189 if(!isset($paymentData['ID']))
1190 continue;
1191
1192 $payment = $paymentCollection->getItemById($paymentData['ID']);
1193
1194 if ($payment == null)
1195 continue;
1196
1197 $paymentIds[] = $payment->getId();
1198 }
1199
1200 foreach ($paymentCollection as $payment)
1201 {
1202 if(!in_array($payment->getId(), $paymentIds))
1203 {
1204 $r = $payment->delete();
1205 if (!$r->isSuccess())
1206 {
1207 $this->errorsContainer->addErrors($r->getErrors());
1208 return false;
1209 }
1210 }
1211 }
1212 }
1213 return true;
1214 }
1215
1219 protected function isEmptyPaymentData(): bool
1220 {
1221 return empty($this->formData["PAYMENT"]) || !is_array($this->formData["PAYMENT"]);
1222 }
1223
1227 protected function needCreateDefaultPayment(): bool
1228 {
1229 return $this->getSettingsContainer()->getItemValue('createDefaultPaymentIfNeed');
1230 }
1231
1232 public function buildPayments()
1233 {
1234 $isEmptyPaymentData = $this->isEmptyPaymentData();
1235 if ($isEmptyPaymentData)
1236 {
1237 $this->formData['PAYMENT'] = [];
1238 }
1239
1240 if ($isEmptyPaymentData && !$this->needCreateDefaultPayment())
1241 {
1242 return $this;
1243 }
1244
1245 if($isEmptyPaymentData && $this->getOrder()->isNew())
1246 {
1247 $this->createEmptyPayment();
1248 return $this;
1249 }
1250
1251 if(!$this->removePayments())
1252 {
1253 $this->errorsContainer->addError(new Error('Payments remove - error'));
1254 throw new BuildingException();
1255 }
1256
1257 $paymentCollection = $this->order->getPaymentCollection();
1258
1259 foreach($this->formData["PAYMENT"] as $paymentData)
1260 {
1261 $paymentId = (int)($paymentData['ID'] ?? 0);
1262 $isNew = ($paymentId <= 0);
1263 $hasError = false;
1264 $products = $paymentData['PRODUCT'] ?? [];
1265
1266 $settablePaymentFields = $this->getSettablePaymentFields();
1267
1268 if(count($settablePaymentFields)>0)//for backward compatibility
1269 $paymentData = array_intersect_key($paymentData, array_flip($settablePaymentFields));
1270
1272 if($isNew)
1273 {
1274 $paymentItem = $paymentCollection->createItem();
1275 if (isset($paymentData['CURRENCY']) && !empty($paymentData['CURRENCY']) && $paymentData['CURRENCY'] !== $this->order->getCurrency())
1276 {
1277 $paymentData["SUM"] = \CCurrencyRates::ConvertCurrency($paymentData["SUM"], $paymentData["CURRENCY"], $this->order->getCurrency());
1278 $paymentData['CURRENCY'] = $this->order->getCurrency();
1279 }
1280 }
1281 else
1282 {
1283 $paymentItem = $paymentCollection->getItemById($paymentId);
1284
1285 if(!$paymentItem)
1286 {
1287 $this->errorsContainer->addError(new Error(Loc::getMessage("SALE_HLP_ORDERBUILDER_PAYMENT_NOT_FOUND")." - ".$paymentId));
1288 continue;
1289 }
1290 }
1291
1292 $isReturn = (isset($paymentData['IS_RETURN']) && ($paymentData['IS_RETURN'] == 'Y' || $paymentData['IS_RETURN'] == 'P'));
1293 $psService = null;
1294
1295 if((int)$paymentData['PAY_SYSTEM_ID'] > 0)
1296 {
1297 $psService = PaySystem\Manager::getObjectById((int)$paymentData['PAY_SYSTEM_ID']);
1298
1299 $paymentData['PAY_SYSTEM_NAME'] = ($psService) ? $psService->getField('NAME') : '';
1300 }
1301
1302 if (isset($paymentData['COMPANY_ID']))
1303 {
1304 $paymentData['COMPANY_ID'] = (int)$paymentData['COMPANY_ID'];
1305 }
1306
1307 if (isset($paymentData['PAID']))
1308 {
1309 $paymentFields['PAID'] = ($paymentData['PAID'] === 'Y') ? 'Y' : 'N';
1310 unset($paymentData['PAID']);
1311 }
1312
1313 if ($isNew)
1314 {
1315 if(empty($paymentData['COMPANY_ID']))
1316 {
1317 $paymentData['COMPANY_ID'] = $this->order->getField('COMPANY_ID');
1318 }
1319
1320 if(empty($paymentData['RESPONSIBLE_ID']))
1321 {
1322 $paymentData['RESPONSIBLE_ID'] = $this->order->getField('RESPONSIBLE_ID');
1323 $paymentData['EMP_RESPONSIBLE_ID'] = $this->getCurrentUserId();
1324 }
1325 }
1326
1327 $dateFields = ['DATE_PAID', 'DATE_PAY_BEFORE', 'DATE_BILL', 'PAY_RETURN_DATE', 'PAY_VOUCHER_DATE'];
1328
1329 foreach($dateFields as $fieldName)
1330 {
1331 if(isset($paymentData[$fieldName]) && is_string($paymentData[$fieldName]))
1332 {
1333 try
1334 {
1335 $paymentData[$fieldName] = new Date($paymentData[$fieldName]);
1336 }
1337 catch (ObjectException $exception)
1338 {
1339 $this->errorsContainer->addError(new Error('Wrong field "'.$fieldName.'"'));
1340 $hasError = true;
1341 }
1342 }
1343 }
1344
1345 if($paymentItem->isPaid()
1346 && isset($paymentData['SUM'])
1347 && abs(floatval($paymentData['SUM']) - floatval($paymentItem->getSum())) > 0.001)
1348 {
1349 $this->errorsContainer->addError(new Error(Loc::getMessage("SALE_HLP_ORDERBUILDER_ERROR_PAYMENT_SUM")));
1350 $hasError = true;
1351 }
1352
1353 /*
1354 * We are editing an order. We have only one payment. So the payment fields are mostly in view mode.
1355 * If we have changed the price of the order then the sum of the payment must be changed automaticaly by payment api earlier.
1356 * But if the payment sum was received from the form we will erase the previous changes.
1357 */
1358 if(isset($paymentData['SUM']))
1359 {
1360 $paymentData['SUM'] = (float)str_replace(',', '.', $paymentData['SUM']);
1361 }
1362
1363 if(isset($paymentData['RESPONSIBLE_ID']))
1364 {
1365 $paymentData['RESPONSIBLE_ID'] = !empty($paymentData['RESPONSIBLE_ID']) ? $paymentData['RESPONSIBLE_ID'] : $this->getCurrentUserId();
1366
1367 if($paymentData['RESPONSIBLE_ID'] != $paymentItem->getField('RESPONSIBLE_ID'))
1368 {
1369 if(!$isNew)
1370 {
1371 $paymentData['EMP_RESPONSIBLE_ID'] = $this->getCurrentUserId();
1372 }
1373 }
1374 }
1375
1376 if(!$hasError)
1377 {
1378 if($paymentItem->isInner() && isset($paymentData['SUM']) && $paymentData['SUM'] === 0)
1379 {
1380 unset($paymentData['SUM']);
1381 }
1382
1383 $setResult = $paymentItem->setFields($paymentData);
1384
1385 if(!$setResult->isSuccess())
1386 {
1387 $this->errorsContainer->addErrors($setResult->getErrors());
1388 }
1389
1390 if ($products)
1391 {
1392 $this->buildPayableItems($paymentItem, $products);
1393 }
1394
1395 if($isReturn && $paymentData['IS_RETURN'])
1396 {
1397 $setResult = $paymentItem->setReturn($paymentData['IS_RETURN']);
1398
1399 if(!$setResult->isSuccess())
1400 {
1401 $this->errorsContainer->addErrors($setResult->getErrors());
1402 }
1403 }
1404
1405 if(!empty($paymentFields['PAID']))
1406 {
1407 $setResult = $paymentItem->setPaid($paymentFields['PAID']);
1408
1409 if(!$setResult->isSuccess())
1410 {
1411 $this->errorsContainer->addErrors($setResult->getErrors());
1412 }
1413 }
1414 }
1415 }
1416
1417 return $this;
1418 }
1419
1431 public function buildPayableItems(Payment $payment, array $payableItems): Result
1432 {
1433 $result = new Result();
1434
1435 $basket = $this->order->getBasket();
1436 $payableItemCollection = $payment->getPayableItemCollection();
1437
1438 foreach ($payableItems as $item)
1439 {
1440 $payableItem = null;
1441
1442 if (isset($item['BASKET_CODE']))
1443 {
1445 $basketItem = $basket->getItemByBasketCode($item['BASKET_CODE']);
1446 if ($basketItem)
1447 {
1448 $payableItem = $payableItemCollection->createItemByBasketItem($basketItem);
1449 }
1450 }
1451 elseif (isset($item['DELIVERY_ID']))
1452 {
1454 foreach ($this->order->getShipmentCollection()->getNotSystemItems() as $shipment)
1455 {
1456 if (
1457 $shipment->getId() === 0
1458 && (int)$item['DELIVERY_ID'] === $shipment->getDeliveryId()
1459 )
1460 {
1461 $payableItem = $payableItemCollection->createItemByShipment($shipment);
1462 }
1463 }
1464 }
1465
1466 if ($payableItem === null)
1467 {
1468 continue;
1469 }
1470
1471 $quantity = floatval(str_replace(',', '.', $item['QUANTITY']));
1472
1473 $payableItem->setField('QUANTITY', $quantity);
1474 }
1475
1476 return $result;
1477 }
1478
1479 public function buildTradeBindings()
1480 {
1481 if(!isset($this->formData["TRADE_BINDINGS"]))
1482 {
1483 return $this;
1484 }
1485
1486 if(!$this->removeTradeBindings())
1487 {
1488 return $this;
1489 }
1490
1491 if(isset($this->formData["TRADE_BINDINGS"]) && count($this->formData["TRADE_BINDINGS"])>0)
1492 {
1493 $tradeBindingCollection = $this->order->getTradeBindingCollection();
1494
1495 foreach($this->formData["TRADE_BINDINGS"] as $fields)
1496 {
1497 $tradingPlatformId = (int)($fields['TRADING_PLATFORM_ID'] ?? 0);
1498 if ($tradingPlatformId === 0)
1499 {
1500 continue;
1501 }
1502
1503 $r = $this->tradingPlatformExists($tradingPlatformId);
1504
1505 if($r->isSuccess())
1506 {
1507 $id = (int)($fields['ID'] ?? 0);
1508 $isNew = ($id <= 0);
1509
1510 if($isNew)
1511 {
1512 $binding = $tradeBindingCollection->createItem();
1513 }
1514 else
1515 {
1516 $binding = $tradeBindingCollection->getItemById($id);
1517
1518 if(!$binding)
1519 {
1520 $this->errorsContainer->addError(new Error('Can\'t find Trade Binding with id:"'.$id.'"', 'TRADE_BINDING_NOT_EXISTS'));
1521 continue;
1522 }
1523 }
1524
1525 $fields = array_intersect_key($fields, array_flip(TradeBindingEntity::getAvailableFields()));
1526
1527 $r = $binding->setFields($fields);
1528 }
1529
1530 if(!$r->isSuccess())
1531 $this->errorsContainer->addErrors($r->getErrors());
1532 }
1533 }
1534
1535 return $this;
1536 }
1537
1538 protected function tradingPlatformExists($id)
1539 {
1540 $r = new Result();
1541
1542 $platformFields = TradingPlatformTable::getById($id)->fetchAll();
1543
1544 if (!isset($platformFields[0]))
1545 {
1546 $r->addError(new Error('tradingPlatform is not exists'));
1547 }
1548
1549 return $r;
1550 }
1551
1552 protected function removeTradeBindings()
1553 {
1554 if($this->getSettingsContainer()->getItemValue('deleteTradeBindingIfNotExists'))
1555 {
1556 $tradeBindingCollection = $this->order->getTradeBindingCollection();
1557
1558 $internalIx = [];
1559 foreach($this->formData["TRADE_BINDINGS"] as $tradeBinding)
1560 {
1561 if(!isset($tradeBinding['ID']))
1562 continue;
1563
1564 $binding = $tradeBindingCollection->getItemById($tradeBinding['ID']);
1565
1566 if ($binding == null)
1567 continue;
1568
1569 $internalIx[] = $binding->getId();
1570 }
1571
1572 foreach ($tradeBindingCollection as $binding)
1573 {
1574 if(!in_array($binding->getId(), $internalIx))
1575 {
1576 $r = $binding->delete();
1577 if (!$r->isSuccess())
1578 {
1579 $this->errorsContainer->addErrors($r->getErrors());
1580 return false;
1581 }
1582 }
1583 }
1584 }
1585
1586 return true;
1587 }
1588
1589 public function finalActions()
1590 {
1591 if($this->isStartField)
1592 {
1593 $hasMeaningfulFields = $this->order->hasMeaningfulField();
1594 $r = $this->order->doFinalAction($hasMeaningfulFields);
1595
1596 if(!$r->isSuccess())
1597 {
1598 $this->errorsContainer->addErrors($r->getErrors());
1599 }
1600 }
1601
1602 return $this;
1603 }
1604
1605 public function getOrder()
1606 {
1607 return $this->order;
1608 }
1609
1610 public function getSettingsContainer()
1611 {
1613 }
1614
1615 public function getErrorsContainer()
1616 {
1618 }
1619
1620 public function getFormData($fieldName = '')
1621 {
1622 if($fieldName <> '')
1623 {
1624 $result = $this->formData[$fieldName] ?? null;
1625 }
1626 else
1627 {
1629 }
1630
1631 return $result;
1632 }
1633
1634 public function getBasketBuilder()
1635 {
1636 return $this->basketBuilder;
1637 }
1638
1639 public static function getDefaultPersonType($siteId)
1640 {
1641 $personTypes = self::getBuyerTypesList($siteId);
1642 reset($personTypes);
1643 return key($personTypes);
1644 }
1645
1646 public static function getBuyerTypesList($siteId)
1647 {
1648 static $result = array();
1649
1650 if(!isset($result[$siteId]))
1651 {
1652 $result[$siteId] = array();
1653
1654 $res = \Bitrix\Sale\Internals\PersonTypeTable::getList(array(
1655 'order' => array('SORT' => 'ASC', 'NAME' => 'ASC'),
1656 'filter' => array('=ACTIVE' => 'Y', '=PERSON_TYPE_SITE.SITE_ID' => $siteId),
1657 ));
1658
1659 while ($personType = $res->fetch())
1660 {
1661 $result[$siteId][$personType["ID"]] = htmlspecialcharsbx($personType["NAME"])." [".$personType["ID"]."]";
1662 }
1663 }
1664
1665 return $result[$siteId];
1666 }
1667
1668 public function getUserId()
1669 {
1670 $userId = (int)($this->formData["USER_ID"] ?? 0);
1671 if($userId > 0)
1672 {
1673 return $userId;
1674 }
1675
1676 $userId = 0;
1677
1678 $settingValue = (int)$this->getSettingsContainer()->getItemValue('createUserIfNeed');
1680 {
1682 }
1684 {
1686 }
1687
1688 if ($userId > 0 && empty($this->formData["USER_ID"]))
1689 {
1690 $this->formData["USER_ID"] = $userId;
1691 }
1692
1693 return $userId;
1694 }
1695
1704 protected function createUserFromFormData()
1705 {
1706 $errors = [];
1707 $orderProps = $this->order->getPropertyCollection();
1708
1709 if ($email = $orderProps->getUserEmail())
1710 {
1711 $email = $email->getValue();
1712 }
1713
1714 if ($name = $orderProps->getPayerName())
1715 {
1716 $name = $name->getValue();
1717 }
1718
1719 if ($phone = $orderProps->getPhone())
1720 {
1721 $phone = $phone->getValue();
1722 }
1723
1724 if ($this->getSettingsContainer()->getItemValue('searchExistingUserOnCreating'))
1725 {
1726 $userId = $this->searchExistingUser($email, $phone);
1727 }
1728
1729 if (!isset($userId))
1730 {
1731 $userId = $this->searchExistingUser($email, $phone);
1732 }
1733
1734 if (!isset($userId))
1735 {
1737 $email,
1738 $name,
1739 $this->formData['SITE_ID'],
1740 $errors,
1741 [
1742 'PERSONAL_PHONE' => $phone,
1743 'PHONE_NUMBER' => $phone,
1744 ]
1745 );
1746
1747 if (!empty($errors))
1748 {
1749 foreach ($errors as $val)
1750 {
1751 $this->errorsContainer->addError(new Error($val['TEXT'], 0, 'USER'));
1752 }
1753 }
1754 else
1755 {
1756 // ToDo remove it? when to authorize buyer?
1757 global $USER;
1758 $USER->Authorize($userId);
1759 }
1760 }
1761
1762 return $userId;
1763 }
1764
1773 private function searchExistingUser($email, $phone): ?int
1774 {
1775 $existingUserId = null;
1776
1777 if (!empty($email))
1778 {
1780 'filter' => [
1781 '=ACTIVE' => 'Y',
1782 '=EMAIL' => $email,
1783 ],
1784 'select' => ['ID'],
1785 ]);
1786 if (isset($res['ID']))
1787 {
1788 $existingUserId = (int)$res['ID'];
1789 }
1790 }
1791
1792 if (!$existingUserId && !empty($phone))
1793 {
1794 $normalizedPhone = NormalizePhone($phone);
1795 $normalizedPhoneForRegistration = Main\UserPhoneAuthTable::normalizePhoneNumber($phone);
1796
1797 if (!empty($normalizedPhone))
1798 {
1800 'filter' => [
1801 'ACTIVE' => 'Y',
1802 [
1803 'LOGIC' => 'OR',
1804 '=PHONE_AUTH.PHONE_NUMBER' => $normalizedPhoneForRegistration,
1805 '=PERSONAL_PHONE' => $normalizedPhone,
1806 '=PERSONAL_MOBILE' => $normalizedPhone,
1807 ],
1808 ],
1809 'select' => ['ID'],
1810 ]);
1811 if (isset($res['ID']))
1812 {
1813 $existingUserId = (int)$res['ID'];
1814 }
1815 }
1816 }
1817
1818 return $existingUserId;
1819 }
1820
1821 protected function getCurrentUserId(): ?int
1822 {
1823 global $USER;
1824 $currentUserId = null;
1825 if (isset($USER) && $USER instanceof \CUser)
1826 {
1827 $currentUserId = (int)$USER->GetID();
1828 if ($currentUserId <= 0)
1829 {
1830 $currentUserId = null;
1831 }
1832 }
1833
1834 return $currentUserId;
1835 }
1836}
const BX_ROOT
Определения bx_root.php:3
if(!is_object($USER)||! $USER->IsAuthorized()) $userId
Определения check_mail.php:18
Определения error.php:15
static getRow(array $parameters)
Определения datamanager.php:398
static normalizePhoneNumber($number, $defaultCountry='')
Определения userphoneauth.php:123
static useStoreControl()
Определения configuration.php:260
static isBasketItemNew($basketCode)
Определения basketbuilder.php:799
prepareFieldsStatusId($isNew, $item, $defaultFields)
Определения orderbuilder.php:346
__construct(SettingsContainer $settings)
Определения orderbuilder.php:58
setBasketBuilder(BasketBuilder $basketBuilder)
Определения orderbuilder.php:94
modifyQuantityShipmentItem(ShipmentItem $shipmentItem, array $params)
Определения orderbuilder.php:1079
prepareDataForSetFields(\Bitrix\Sale\Shipment $shipment, $items)
Определения orderbuilder.php:1073
static getDefaultPersonType($siteId)
Определения orderbuilder.php:1639
static getPostWithFiles(array $post, array $files)
Определения input.php:1345
static getObjectById($id)
Определения manager.php:719
static getInstance($type)
Определения registry.php:183
const REGISTRY_TYPE_ORDER
Определения registry.php:16
setField($name, $value)
Определения shipmentitem.php:444
static getAvailableFields()
Определения tradebindingentity.php:35
static ConvertCurrency($valSum, $curFrom, $curTo, $valDate="")
Определения currency_rate.php:393
static DoSaveUserProfile($userId, $profileId, $profileName, $personTypeId, $orderProps, &$arErrors)
Определения order_user_props.php:41
static DoAutoRegisterUser($autoEmail, $payerName, $siteId, &$arErrors, $arOtherFields=null)
Определения basket.php:3614
static GetAnonymousUserID()
Определения basket.php:3562
Определения user.php:6037
if(!is_array($prop["VALUES"])) $tmp
Определения component_props.php:203
$data['IS_AVAILABLE']
Определения .description.php:13
</td ></tr ></table ></td ></tr ><?endif?><? $propertyIndex=0;foreach( $arGlobalProperties as $propertyCode=> $propertyValue
Определения file_new.php:729
</td ></tr ></table ></td ></tr >< tr >< td class="bx-popup-label bx-width30"><?=GetMessage("PAGE_NEW_TAGS")?> array( $site)
Определения file_new.php:804
$res
Определения filter_act.php:7
$result
Определения get_property_values.php:14
$errors
Определения iblock_catalog_edit.php:74
$useStoreControl
Определения iblock_subelement_generator.php:49
$_SERVER["DOCUMENT_ROOT"]
Определения cron_frame.php:9
global $USER
Определения csv_new_run.php:40
$siteId
Определения ajax.php:8
NormalizePhone($number, $minLength=10)
Определения tools.php:4959
htmlspecialcharsbx($string, $flags=ENT_COMPAT, $doubleEncode=true)
Определения tools.php:2701
$name
Определения menu_edit.php:35
Определения tools.php:2
trait Error
Определения error.php:11
$payment
Определения payment.php:14
$paymentCollection
Определения payment.php:11
$email
Определения payment.php:49
$settings
Определения product_settings.php:43
if( $daysToExpire >=0 &&$daysToExpire< 60 elseif)( $daysToExpire< 0)
Определения prolog_main_admin.php:393
</p ></td >< td valign=top style='border-top:none;border-left:none;border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt;padding:0cm 2.0pt 0cm 2.0pt;height:9.0pt'>< p class=Normal align=center style='margin:0cm;margin-bottom:.0001pt;text-align:center;line-height:normal'>< a name=ТекстовоеПоле54 ></a ><?=($taxRate > count( $arTaxList) > 0) ? $taxRate."%"
Определения waybill.php:936
if($inWords) echo htmlspecialcharsbx(Number2Word_Rus(roundEx($totalVatSum $params['CURRENCY']
Определения template.php:799
$items
Определения template.php:224
$post
Определения template.php:8
$val
Определения options.php:1793
$error
Определения subscription_card_product.php:20
$fields
Определения yandex_run.php:501