Bitrix-D7 23.9
 
Загрузка...
Поиск...
Не найдено
orderedit.php
1<?php
3
16use Bitrix\Main\Page\Asset;
20use Bitrix\Main\Entity\EntityError;
26
27Loc::loadMessages(__FILE__);
28
29Loader::registerAutoLoadClasses('sale',
30 array(
31 '\Bitrix\Sale\Helpers\Admin\Blocks\OrderShipmentStatus' => 'lib/helpers/admin/blocks/ordershipmentstatus.php',
32 '\Bitrix\Sale\Helpers\Admin\Blocks\OrderFinanceInfo' => 'lib/helpers/admin/blocks/orderfinanceinfo.php',
33 '\Bitrix\Sale\Helpers\Admin\Blocks\OrderAdditional' => 'lib/helpers/admin/blocks/orderadditional.php',
34 '\Bitrix\Sale\Helpers\Admin\Blocks\OrderShipment' => 'lib/helpers/admin/blocks/ordershipment.php',
35 '\Bitrix\Sale\Helpers\Admin\Blocks\OrderPayment' => 'lib/helpers/admin/blocks/orderpayment.php',
36 '\Bitrix\Sale\Helpers\Admin\Blocks\OrderStatus' => 'lib/helpers/admin/blocks/orderstatus.php',
37 '\Bitrix\Sale\Helpers\Admin\Blocks\OrderBasket' => 'lib/helpers/admin/blocks/orderbasket.php',
38 '\Bitrix\Sale\Helpers\Admin\Blocks\OrderBuyer' => 'lib/helpers/admin/blocks/orderbuyer.php',
39 '\Bitrix\Sale\Helpers\Admin\Blocks\OrderInfo' => 'lib/helpers/admin/blocks/orderinfo.php',
40 '\Bitrix\Sale\Helpers\Admin\Blocks\OrderMarker' => 'lib/helpers/admin/blocks/ordermarker.php',
41
42 '\Bitrix\Sale\Helpers\Admin\OrderEditResult' => 'lib/helpers/admin/ordereditresult.php'
43));
44
51{
52 protected static $productsDetails = null;
53 public static $isTrustProductFormData = false;
54 public static $needUpdateNewProductPrice = false;
55 public static $isBuyerIdChanged = false;
56 public static $isRefreshData = false;
57
58 const BASKET_CODE_NEW = 'new';
59
69 public static function makeSelectHtml($name, array $data, $selected = "", $showNotUse = true, $attributes = array())
70 {
71 if(!is_array($data))
72 throw new ArgumentTypeException("data", "array");
73
74 if(!is_array($attributes))
75 throw new ArgumentTypeException("attributies", "array");
76
77 $result = '<select name="'.htmlspecialcharsbx($name).'"';
78
79 foreach($attributes as $attrName => $attrValue )
80 $result.=" ".$attrName."=\"".htmlspecialcharsbx($attrValue)."\"";
81
82 $result .= '>';
83
84 if($showNotUse)
85 $result .= '<option value="">'.GetMessage("SALE_ORDEREDIT_NOT_USE").'</option>';
86
87 foreach($data as $value => $title)
88 $result .= '<option value="'.htmlspecialcharsbx($value).'"'.($selected == $value ? " selected" : "").'>'.htmlspecialcharsbx(TruncateText($title, 40)).'</option>';
89
90 $result .= '</select>';
91
92 return $result;
93 }
94
104 public static function makeSelectHtmlWithRestricted($name, array $data, $selected = "", $showNotUse = true, $attributes = array())
105 {
106 if(!is_array($data))
107 throw new ArgumentTypeException("data", "array");
108
109 if(!is_array($attributes))
110 throw new ArgumentTypeException("attributies", "array");
111
112 $result = '<select name="'.htmlspecialcharsbx($name).'"';
113
114 foreach($attributes as $attrName => $attrValue )
115 $result .= " ".$attrName."=\"".htmlspecialcharsbx($attrValue)."\"";
116
117 $result .= '>';
118
119 $result .= self::makeSelectHtmlBodyWithRestricted($data, $selected, $showNotUse);
120 $result .= '</select>';
121
122 return $result;
123 }
124
131 public static function makeSelectHtmlBodyWithRestricted($data, $selected = '', $showNotUse = true)
132 {
133 $activePaySystems = '';
134
135 if($showNotUse)
136 $activePaySystems .= '<option value="">'.GetMessage("SALE_ORDEREDIT_NOT_USE").'</option>';
137
138 $restrictedPaySystems = '';
139 foreach($data as $item)
140 {
141 if (!isset($item['RESTRICTED']))
142 {
143 $activePaySystems .= '<option value="'.htmlspecialcharsbx($item['ID']).'"'.($selected == $item['ID'] ? " selected" : "").'>'.htmlspecialcharsbx(TruncateText($item['NAME'], 40)).'</option>';
144 }
145 else
146 {
147 $restrictedPaySystems .= '<option value="'.htmlspecialcharsbx($item['ID']).'"'.($selected == $item['ID'] ? " selected" : "").' class="bx-admin-service-restricted">'.htmlspecialcharsbx(TruncateText($item['NAME'], 40)).'</option>';
148 }
149 }
150
151 return $activePaySystems.$restrictedPaySystems;
152 }
153
159 public static function getScripts(Order $order, $formId)
160 {
161 Asset::getInstance()->addJs("/bitrix/js/sale/admin/order_edit.js");
162 Asset::getInstance()->addJs("/bitrix/js/sale/admin/order_ajaxer.js");
163 $currencyId = $order->getCurrency();
164 $currencies = array();
165
166 if(Loader::includeModule('currency'))
167 {
168 \CJSCore::Init(array('currency'));
169 $currencyFormat = \CCurrencyLang::getFormatDescription($currencyId);
170 $currencies = array(
171 array(
172 'CURRENCY' => $currencyId,
173 'FORMAT' => array(
174 'FORMAT_STRING' => $currencyFormat['FORMAT_STRING'],
175 'DEC_POINT' => $currencyFormat['DEC_POINT'],
176 'THOUSANDS_SEP' => $currencyFormat['THOUSANDS_SEP'],
177 'DECIMALS' => $currencyFormat['DECIMALS'],
178 'THOUSANDS_VARIANT' => $currencyFormat['THOUSANDS_VARIANT'],
179 'HIDE_ZERO' => "N" //$currencyFormat['HIDE_ZERO']
180 )
181 )
182 );
183 }
184
185 $connectedB24Portal = '';
186
187 if(Loader::includeModule('b24connector'))
188 {
189 $connectedB24Portal = \Bitrix\B24Connector\Connection::getDomain();
190 }
191
192 $curFormat = \CCurrencyLang::GetFormatDescription($currencyId);
193 $currencyLang = preg_replace("/(^|[^&])#/", '$1', $curFormat["FORMAT_STRING"]);
194 $langPhrases = array("SALE_ORDEREDIT_DISCOUNT_UNKNOWN", "SALE_ORDEREDIT_REFRESHING_DATA", "SALE_ORDEREDIT_FIX",
195 "SALE_ORDEREDIT_UNFIX", "SALE_ORDEREDIT_CLOSE", "SALE_ORDEREDIT_MESSAGE", "SALE_ORDEREDIT_CONFIRM",
196 "SALE_ORDEREDIT_CONFIRM_CONTINUE", "SALE_ORDEREDIT_CONFIRM_ABORT");
197
198 $result = '
199 <script type="text/javascript">
200 BX.ready(function(){
201 BX.Sale.Admin.OrderEditPage.orderId = "'.$order->getId().'";
202 BX.Sale.Admin.OrderEditPage.siteId = "'.\CUtil::JSEscape($order->getSiteId()).'";
203 BX.Sale.Admin.OrderEditPage.languageId = "'.LANGUAGE_ID.'";
204 BX.Sale.Admin.OrderEditPage.formId = "'.$formId.'_form";
205 BX.Sale.Admin.OrderEditPage.connectedB24Portal = "'.\CUtil::JSEscape($connectedB24Portal).'";
206 BX.Sale.Admin.OrderEditPage.adminTabControlId = "'.$formId.'";
207 '.(!empty($currencies) ? 'BX.Currency.setCurrencies('.\CUtil::PhpToJSObject($currencies, false, true, true).');' : '').
208 'BX.Sale.Admin.OrderEditPage.currency = "'.\CUtil::JSEscape($currencyId).'";
209 BX.Sale.Admin.OrderEditPage.currencyLang = "'.\CUtil::JSEscape($currencyLang).'";';
210
211 if($formId == "sale_order_create")
212 $result .= '
213 BX.Sale.Admin.OrderEditPage.registerFieldsUpdaters(BX.Sale.Admin.OrderPayment.prototype.getCreateOrderFieldsUpdaters());';
214
215 foreach($langPhrases as $phrase)
216 $result .= ' BX.message({'.$phrase.': "'.\CUtil::JSEscape(Loc::getMessage($phrase)).'"});';
217
218 $result .=
219 '});
220 </script>
221 ';
222
223 return $result;
224 }
225
231 public static function getUserName($userId, $siteId = "")
232 {
233 if(intval($userId) <= 0)
234 return Loc::getMessage("SALE_ORDEREDIT_NAME_NULL");
235
236 static $userNames = array();
237
238 if(!isset($userNames[$userId]))
239 {
240 $res = UserTable::getById($userId);
241
242 if($buyer = $res->fetch())
243 {
244 $userNames[$userId] = \CUser::FormatName(
245 \CSite::GetNameFormat(
246 null,
247 $siteId
248 ),
249 $buyer,
250 true,
251 false
252 );
253 }
254 }
255
256 return $userNames[$userId];
257 }
258
264 public static function getProblemBlockHtml($text, $orderId)
265 {
266 if($text == '')
267 $result = "";
268 else
269 $result = '
270 <div class="adm-bus-orderproblem" id="sale-adm-order-problem-block">
271 <div class="adm-bus-orderproblem-container">
272 <table>
273 <tr>
274 <td class="adm-bus-orderproblem-title">'.Loc::getMessage("SALE_ORDEREDIT_ORDER_PROBLEM").':</td>
275 <td class="adm-bus-orderproblem-text">'.$text.'</td>
276 </tr>
277 </table>
278 <span class="adm-bus-orderproblem-close" title="'.Loc::getMessage("SALE_ORDEREDIT_CLOSE").'" onclick="BX.Sale.Admin.OrderEditPage.onProblemCloseClick(\''.$orderId.'\',\'sale-adm-order-problem-block\');"></span>
279 </div>
280 </div>';
281
282 return $result;
283 }
284
291 public static function getFastNavigationHtml(array $items, $formId = '', $tabId = '')
292 {
293 if(empty($items))
294 return "";
295
296 $result = '
297 <div class="adm-bus-fastnav adm-detail-tabs-block-pin" id="sale-order-edit-block-fast-nav">
298 <div class="adm-bus-fastnav-container">
299 <table>
300 <tr>
301 <td class="adm-bus-fastnav-title">'.Loc::getMessage('SALE_ORDEREDIT_NAVIGATION').':</td>
302 <td>
303 <ul class="adm-bus-fastnav-navlist" id="adm-bus-fastnav-navlist">';
304
305 foreach($items as $anchor => $itemName)
306 {
307 if($formId <> '' && $tabId <> '')
308 {
309 $href = 'javascript:void(0);';
310 $onClick = ' onclick="BX.Sale.Admin.OrderEditPage.fastNavigation.onClickItem(\''.$formId.'\', \''.$tabId.'\', \''.$anchor.'\')"';
311 }
312 else
313 {
314 $href = '#'.$anchor;
315 $onClick = '';
316 }
317
318 if ($anchor == 'relprops')
319 $result .= '<li style="display:none;"><a href="'.$href.'" id="nav_'.$anchor.'"'.$onClick.'>'.$itemName.'</a></li>';
320 else
321 $result .= '<li><a href="'.$href.'" id="nav_'.$anchor.'"'.$onClick.'>'.$itemName.'</a></li>';
322 }
323
324 $result .= '
325 </ul>
326 </td>
327 </tr>
328 </table>
329 <div id="sale-order-edit-block-fast-nav-pin" onclick="BX.Sale.Admin.OrderEditPage.toggleFix(this.id, \'sale-order-edit-block-fast-nav\');" class="adm-detail-pin-btn-tabs" style="top: 9px;right: 0px;"></div>
330 </div>
331 </div>';
332
333 $orderEditOpts = \CUserOptions::GetOption("sale_admin", "sale_order_edit", array());
334 $isFixed = isset($orderEditOpts["fix_sale-order-edit-block-fast-nav"]) && $orderEditOpts["fix_sale-order-edit-block-fast-nav"] == "Y" ? true : false;
335
336 $result .= '
337 <script type="text/javascript">
338 BX.ready(function(){
339 BX.bind(window, "scroll", BX.Sale.Admin.OrderEditPage.fastNavigation.markItem);
340 setTimeout(function(){
341 BX.Sale.Admin.OrderEditPage.fastNavigation.markItem();'
342 .($isFixed ? 'BX.Sale.Admin.OrderEditPage.toggleFix("sale-order-edit-block-fast-nav-pin", "sale-order-edit-block-fast-nav");' : '').
343 '
344 },
345 1
346 );
347 });
348 </script>';
349
350 return $result;
351 }
352
359 protected static function createUserFromForm(Order &$order, array $formData)
360 {
361 $errors = array();
362 $orderProps = $order->getPropertyCollection();
363
364 if($email = $orderProps->getUserEmail())
365 $email = $email->getValue();
366
367 if($name = $orderProps->getPayerName())
368 $name = $name->getValue();
369
370 if($phone = $orderProps->getPhone())
371 $phone = $phone->getValue();
372
373 $userId = \CSaleUser::DoAutoRegisterUser(
374 $email,
375 $name,
376 $formData["SITE_ID"],
377 $errors,
378 [
379 'PERSONAL_PHONE' => $phone,
380 'PHONE_NUMBER' => $phone
381 ]
382 );
383
384 if (!empty($errors))
385 {
386 $errorMessage = "";
387
388 foreach($errors as $val)
389 $errorMessage .= $val["TEXT"];
390
391 throw new UserMessageException($errorMessage);
392 }
393
394 return $userId;
395 }
396
397 public static function getUserId($order, $formData, $createUserIfNeed, Result &$result)
398 {
399 if(intval($formData["USER_ID"]) > 0)
400 return intval($formData["USER_ID"]);
401
402 $userId = 0;
403
404 if($createUserIfNeed && (!isset($formData["USER_ID"]) || intval($formData["USER_ID"]) <= 0))
405 {
406 try
407 {
408 $userId = self::createUserFromForm($order, $formData);
409 }
410 catch(UserMessageException $e)
411 {
412 $result->addError( new EntityError($e->getMessage()));
413 }
414 }
415
416 return $userId;
417 }
418
429 public static function createOrderFromForm(array $formData, $creatorUserId, $createUserIfNeed, array $files, Result &$opResult)
430 {
431 if(!isset($formData["SITE_ID"]) || $formData["SITE_ID"] == '')
432 throw new ArgumentNullException('formData["SITE_ID"]');
433
434 $registry = Sale\Registry::getInstance(Sale\Registry::REGISTRY_TYPE_ORDER);
436 $orderClass = $registry->getOrderClassName();
437
438 global $APPLICATION, $USER;
439 $order = $orderClass::create($formData["SITE_ID"]);
440 $saleModulePermissions = $APPLICATION->GetGroupRight("sale");
441 $userCompanyId = null;
442
443 if($saleModulePermissions == "P")
444 {
445 $userCompanyList = Company\Manager::getUserCompanyList($USER->GetID());
446 if (!empty($userCompanyList) && is_array($userCompanyList))
447 {
448 $userCompanyId = reset($userCompanyList);
449 if (intval($userCompanyId) > 0 && empty($formData['ORDER']['COMPANY_ID']))
450 {
451 $formData['ORDER']['COMPANY_ID'] = $userCompanyId;
452 }
453 }
454 }
455
457 $res = self::fillSimpleFields($order, $formData, $creatorUserId);
458
459 if(!$res->isSuccess())
460 $opResult->addErrors($res->getErrors());
461
462 $res = self::fillOrderProperties($order, $formData, $files);
463 if(!$res->isSuccess())
464 $opResult->addErrors($res->getErrors());
465
466 //creates new user if need
467 $order->setFieldNoDemand(
468 "USER_ID",
469 self::getUserId($order, $formData, $createUserIfNeed, $opResult)
470 );
471
472 $fUserId = null;
473
474 if ($order->getUserId() > 0)
475 {
476 $fUserId = Fuser::getIdByUserId($order->getUserId());
477 }
478
479 $needDataUpdate = array();
480 $basketCodeMap = array();
481
482 //init basket
483 if(isset($formData["PRODUCT"]) && is_array($formData["PRODUCT"]) && !empty($formData["PRODUCT"]))
484 {
485 $isStartField = $order->isStartField();
486
487 $basketClass = $registry->getBasketClassName();
489 $basket = $basketClass::create($formData["SITE_ID"]);
490
491 $res = $order->setBasket($basket);
492
493 if(!$res->isSuccess())
494 $opResult->addErrors($res->getErrors());
495
496 $basket->setFUserId($fUserId);
497 \Bitrix\Sale\ProviderBase::setUsingTrustData(true);
498
499 $sort = 100;
500 $maxBasketCodeIdx = 0;
501
502 foreach($formData["PRODUCT"] as $basketCode => $productData)
503 {
504 $formData["PRODUCT"][$basketCode]["SORT"] = $sort;
505 $sort += 100;
506
507 /* Fix collision if price of new product is larger than exists have.
508 * After sorting new product pick basket code from existing products.
509 * See below.
510 */
511 if(self::isBasketItemNew($basketCode))
512 {
513 $basketInternalId = intval(mb_substr($basketCode, 1));
514
515 if($basketInternalId > $maxBasketCodeIdx)
516 $maxBasketCodeIdx = $basketInternalId;
517
518 if(self::$needUpdateNewProductPrice)
519 {
520 unset($formData["PRODUCT"][$basketCode]["PROVIDER_DATA"]);
521 unset($formData["PRODUCT"][$basketCode]["SET_ITEMS_DATA"]);
522 }
523 }
524 }
525
526 sortByColumn($formData["PRODUCT"], array("BASE_PRICE" => SORT_DESC, "PRICE" => SORT_DESC), '', null, true);
527
528 foreach($formData["PRODUCT"] as $basketCode => $productData)
529 {
530 if (($productData['IS_SET_ITEM'] ?? null) === 'Y')
531 {
532 continue;
533 }
534
535 if(!isset($productData["PROPS"]) || !is_array($productData["PROPS"]))
536 {
537 $productData["PROPS"] = array();
538 }
539
540 // Always search only by $basketCode so that can add duplicates
541 $item =
542 $basketCode != self::BASKET_CODE_NEW
543 ? $basket->getItemByBasketCode($basketCode)
544 : null
545 ;
546
547 if($item == null && $basketCode != self::BASKET_CODE_NEW)
548 {
549 $item = $basket->getItemByBasketCode($basketCode);
550 }
551
552 if($item && $item->isBundleChild())
553 {
554 $item = null;
555 }
556
557 if($item)
558 {
559 //Let's extract cached provider product data from field
560 if(!empty($productData["PROVIDER_DATA"]) && CheckSerializedData($productData["PROVIDER_DATA"]))
561 {
562 $providerData = unserialize($productData["PROVIDER_DATA"], ['allowed_classes' => false]);
563 self::setProviderTrustData($item, $order, $providerData);
564 }
565
566 if(!empty($productData["SET_ITEMS_DATA"]) && CheckSerializedData($productData["SET_ITEMS_DATA"]))
567 $productData["SET_ITEMS"] = unserialize($productData["SET_ITEMS_DATA"], ['allowed_classes' => false]);
568
569 $res = $item->setField("QUANTITY", $item->getField("QUANTITY")+$productData["QUANTITY"]);
570
571 if(!$res->isSuccess())
572 $opResult->addErrors($res->getErrors());
573 }
574 else
575 {
576 if($basketCode != self::BASKET_CODE_NEW)
577 $setBasketCode = $basketCode;
578 elseif(intval($maxBasketCodeIdx) > 0)
579 $setBasketCode = 'n'.strval($maxBasketCodeIdx+1); //Fix collision part 2.
580 else
581 $setBasketCode = null;
582
583 $productId = $productData["PRODUCT_ID"];
584 if (isset($productData["OFFER_ID"]) && !empty($productData["OFFER_ID"]))
585 {
586 $productId = $productData["OFFER_ID"];
587 }
588
589 $item = $basket->createItem($productData["MODULE"], $productId, $setBasketCode);
590
591 if ($basketCode != $productData["BASKET_CODE"])
592 $productData["BASKET_CODE"] = $item->getBasketCode();
593
594 if($basketCode == self::BASKET_CODE_NEW)
595 {
596 $opResult->setData(array("NEW_ITEM_BASKET_CODE" => $productData["BASKET_CODE"]));
597 $needDataUpdate[] = $item->getBasketCode();
598 }
599
600 if(!empty($productData['REPLACED']) && $productData['REPLACED'] == 'Y')
601 $needDataUpdate[] = $item->getBasketCode();
602
603 if($basketCode != $item->getBasketCode())
604 $basketCodeMap[$basketCode] = $item->getBasketCode();
605
606 if(isset($productData["PROPS"]) && !empty($productData["PROPS"]) && is_array($productData["PROPS"]))
607 {
609 $property = $item->getPropertyCollection();
610 $property->setProperty($productData["PROPS"]);
611 }
612 }
613 }
614
615 $productsData = $formData["PRODUCT"];
616
617 if(!empty($basketCodeMap))
618 {
619 foreach($basketCodeMap as $old => $new)
620 {
621 $productsData[$new] = $productsData[$old];
622 unset($productsData[$old]);
623 }
624 }
625
626 $res = self::fillBasketItems($basket, $productsData, $order, array_unique($needDataUpdate));
627
628 if(!$res->isSuccess())
629 {
630 $opResult->addErrors($res->getErrors());
631
632 if($res->isTerminal())
633 {
634 return null;
635 }
636 }
637
638 if ($isStartField)
639 {
640 $hasMeaningfulFields = $order->hasMeaningfulField();
641
643 $r = $order->doFinalAction($hasMeaningfulFields);
644 if (!$r->isSuccess())
645 {
646 $opResult->addErrors($r->getErrors());
647 }
648 }
649
650 if(isset($formData["DISCOUNTS"]) && is_array($formData["DISCOUNTS"]))
651 $order->getDiscount()->setApplyResult($formData["DISCOUNTS"]);
652 }
653 else
654 {
655 $opResult->addError(new EntityError(Loc::getMessage("SALE_ORDEREDIT_ERROR_NO_PRODUCTS")));
656 }
657
658 return $order;
659 }
660
661 public static function fillOrderProperties(OrderBase $order, $formData, $files = [])
662 {
663 $propCollection = $order->getPropertyCollection();
664 return $propCollection->setValuesFromPost($formData, $files);
665 }
666
667 public static function isBasketItemNew($basketCode)
668 {
669 return (mb_strpos($basketCode, 'n') === 0) && ($basketCode != self::BASKET_CODE_NEW);
670 }
671
672 public static function saveCoupons($userId, $formData)
673 {
674 if(intval($userId) <= 0)
675 return false;
676
677 // init discount coupons
679
681 throw new UserMessageException(implode(" \n", DiscountCouponsManager::getErrors()));
682
683 if(isset($formData["COUPONS"]) && $formData["COUPONS"] <> '')
684 {
685 $coupons = explode(",", $formData["COUPONS"]);
686
687 if(is_array($coupons) && count($coupons) > 0)
688 {
689 foreach($coupons as $coupon)
691 }
692 }
693
694 return true;
695 }
696
697 public static function saveProfileData($profileId, Order $order, array $formData)
698 {
699 $result = new Result();
700 $errors = array();
701 $name = "";
702
703 if($profileName = $order->getPropertyCollection()->getProfileName())
704 $name = $profileName->getValue();
705
706 $res = \CSaleOrderUserProps::DoSaveUserProfile(
707 $order->getUserId(),
708 $profileId,
709 $name,
710 $order->getPersonTypeId(),
711 $propCollection = $formData["PROPERTIES"],
712 $errors
713 );
714
715 if($res === false)
716 {
717 if(!empty($errors))
718 {
719 foreach($errors as $error)
720 $result->addError(new EntityError($error."<br>\n"));
721 }
722 else
723 {
724 $result->addError(new EntityError(Loc::getMessage("SALE_ORDEREDIT_PROFILE_ERROR_SAVE")));
725 }
726 }
727
728 return $result;
729 }
730
742 public static function editOrderByFormData(array $formData, Order $order, $userId, $createUserIfNeed, array $files, Result &$result)
743 {
745 $res = self::fillSimpleFields($order, $formData, $userId);
746
747 if(!$res->isSuccess())
748 $result->addErrors($res->getErrors());
749
750 $propCollection = $order->getPropertyCollection();
751 $res = $propCollection->setValuesFromPost($formData, $files);
752
753 if(!$res->isSuccess())
754 $result->addErrors($res->getErrors());
755
756 /*
757 $currentUserId = $order->getUserId();
758
759 if ($currentUserId && ((int)$currentUserId !== (int)$formData['USER_ID']))
760 {
761 $paymentCollection = $order->getPaymentCollection();
762/*
763 foreach ($paymentCollection as $payment)
764 {
765 if ($payment->isPaid())
766 {
767 $result->addError(new EntityError(
768 Loc::getMessage("SALE_ORDEREDIT_ERROR_CHANGE_USER_WITH_PAID_PAYMENTS")
769 , 'SALE_ORDEREDIT_ERROR_CHANGE_USER_WITH_PAID_PAYMENTS'));
770 return null;
771 }
772 }
773 }
774 */
775
776 $order->setFieldNoDemand(
777 "USER_ID",
778 self::getUserId($order, $formData, $createUserIfNeed, $result)
779 );
780
781 if(isset($formData["DISCOUNTS"]) && is_array($formData["DISCOUNTS"]))
782 $order->getDiscount()->setApplyResult($formData["DISCOUNTS"]);
783
784 //init basket
785 $basket = $order->getBasket();
786 $itemsBasketCodes = array();
787 $maxBasketCodeIdx = 0;
788 $productAdded = false;
789
790 if(isset($formData["PRODUCT"]) && is_array($formData["PRODUCT"]) && !empty($formData["PRODUCT"]))
791 {
792 $sort = 100;
793
794 foreach($formData["PRODUCT"] as $basketCode => $productData)
795 {
796 $formData["PRODUCT"][$basketCode]["SORT"] = $sort;
797 $sort += 100;
798
799 /* Fix collision if price of new product is larger than added earlier have.
800 * After sorting new product pick basket code from existing products.
801 * See below.
802 */
803 if(self::isBasketItemNew($basketCode))
804 {
805 $basketInternalId = intval(mb_substr($basketCode, 1));
806
807 if($basketInternalId > $maxBasketCodeIdx)
808 $maxBasketCodeIdx = $basketInternalId;
809
810 $needDataUpdate[] = $basketCode;
811 unset($formData["PRODUCT"][$basketCode]["PROVIDER_DATA"]);
812 unset($formData["PRODUCT"][$basketCode]["SET_ITEMS_DATA"]);
813 }
814 }
815
816 sortByColumn($formData["PRODUCT"], array("BASE_PRICE" => SORT_DESC, "PRICE" => SORT_DESC), '', null, true);
817
818 //we choose sku wich already exist in basket, so we must kill one of them.
819 if(!empty($formData["ALREADY_IN_BASKET_CODE"]))
820 {
821 $item = $basket->getItemByBasketCode($formData["ALREADY_IN_BASKET_CODE"]);
822
823 if($item)
824 {
825 $res = $item->delete();
826
827 if (!$res->isSuccess())
828 {
829 $errMess = "";
830
831 foreach($res->getErrors() as $error)
832 $errMess .= $error->getMessage()."\n";
833
834 if($errMess == '')
835 $errMess = Loc::getMessage("SALE_ORDEREDIT_BASKET_ITEM_DEL_ERROR");
836
837 $result->addError(new Error($errMess));
838// return null;
839 }
840 }
841 }
842
843 foreach($formData["PRODUCT"] as $basketCode => $productData)
844 {
845 if (!isset($productData["PROPS"]))
846 {
847 $productData["PROPS"] = array();
848 }
849
850 // Always search only by $basketCode so that can add duplicates
851 $item =
852 $basketCode != self::BASKET_CODE_NEW
853 ? $basket->getItemByBasketCode($basketCode)
854 : null
855 ;
856
857 if ($item == null)
858 {
860 }
861
862 if($item && $item->isBundleChild())
863 {
864 continue;
865 }
866
867 if(!$item)
868 {
869 continue;
870 }
871
872 $itemsBasketCodes[] = $item->getBasketCode();
873 }
874 }
875
877 $basketItems = $basket->getBasketItems();
878
879 foreach($basketItems as $item)
880 {
881 if(!in_array($item->getBasketCode(), $itemsBasketCodes))
882 {
883 $res = $item->delete();
884
885 if (!$res->isSuccess())
886 {
887 $errMess = "";
888
889 foreach($res->getErrors() as $error)
890 $errMess .= $error->getMessage()."\n";
891
892 if($errMess == '')
893 $errMess = Loc::getMessage("SALE_ORDEREDIT_BASKET_ITEM_DEL_ERROR");
894
895 $result->addError(new Error($errMess));
896// return null;
897 }
898 }
899 }
900
901 \Bitrix\Sale\ProviderBase::setUsingTrustData(true);
902 $isStartField = $order->isStartField();
903 $needDataUpdate = array();
904 $basketCodeMap = array();
905
906 if(isset($formData["PRODUCT"]) && is_array($formData["PRODUCT"]) && !empty($formData["PRODUCT"]))
907 {
908 foreach($formData["PRODUCT"] as $basketCode => $productData)
909 {
910 $providerData = array();
911
912 if($productData["IS_SET_ITEM"] == "Y")
913 {
914 continue;
915 }
916
917 if(!isset($productData["PROPS"]) || !is_array($productData["PROPS"]))
918 {
919 $productData["PROPS"] = array();
920 }
921
922 // Always search only by $basketCode so that can add duplicates
923 $item =
924 $basketCode != self::BASKET_CODE_NEW
925 ? $basket->getItemByBasketCode($basketCode)
926 : null
927 ;
928
929 //sku was changed
930 if($item == null && $basketCode != self::BASKET_CODE_NEW)
931 {
932 if($item = $basket->getItemByBasketCode($basketCode))
933 {
934 $res = $item->delete();
935
936 if(!$res->isSuccess())
937 {
938 $result->addErrors($res->getErrors());
939// return null;
940 }
941
942 $item = null;
943 }
944 }
945
946 if($item && $item->isBundleChild())
947 $item = null;
948
949 if(!$item)
950 {
951 if($basketCode != self::BASKET_CODE_NEW)
952 $setBasketCode = $basketCode;
953 elseif(intval($maxBasketCodeIdx) > 0)
954 $setBasketCode = 'n'.strval($maxBasketCodeIdx+1); //Fix collision part 2.
955 else
956 $setBasketCode = null;
957
958 $item = $basket->createItem(
959 $productData["MODULE"],
960 $productData["OFFER_ID"],
961 $setBasketCode
962 );
963
964 if ($basketCode != $productData["BASKET_CODE"])
965 $productData["BASKET_CODE"] = $item->getBasketCode();
966
967 if($basketCode == self::BASKET_CODE_NEW)
968 {
969 $result->setData(array("NEW_ITEM_BASKET_CODE" => $productData["BASKET_CODE"]));
970 $needDataUpdate[] = $item->getBasketCode();
971 }
972
973 if(!empty($productData['REPLACED']) && $productData['REPLACED'] == 'Y')
974 $needDataUpdate[] = $item->getBasketCode();
975
976 if(!$productAdded)
977 $productAdded = true;
978 }
979 else
980 {
981 if ($basketCode != $productData["BASKET_CODE"])
982 $productData["BASKET_CODE"] = $item->getBasketCode();
983
984 if(isset($productData["OFFER_ID"]) || intval($productData["OFFER_ID"]) >= 0)
985 $productData["PRODUCT_ID"] = $productData["OFFER_ID"];
986
987 $itemFields = array_intersect_key($productData, array_flip($item::getAvailableFields()));
988
989 if(isset($itemFields["MEASURE_CODE"]) && $itemFields["MEASURE_CODE"] <> '')
990 {
991 $measures = OrderBasket::getCatalogMeasures();
992
993 if(isset($measures[$itemFields["MEASURE_CODE"]]) && $measures[$itemFields["MEASURE_CODE"]] <> '')
994 $itemFields["MEASURE_NAME"] = $measures[$itemFields["MEASURE_CODE"]];
995 }
996
997 if(!empty($productData["PROVIDER_DATA"]) && !self::$needUpdateNewProductPrice && CheckSerializedData($productData["PROVIDER_DATA"]))
998 {
999 $providerData = unserialize($productData["PROVIDER_DATA"], ['allowed_classes' => false]);
1000 }
1001
1002 if(is_array($providerData) && !empty($providerData))
1003 self::setProviderTrustData($item, $order, $providerData);
1004
1005 if(!empty($productData["SET_ITEMS_DATA"]) && CheckSerializedData($productData["SET_ITEMS_DATA"]))
1006 $productData["SET_ITEMS"] = unserialize($productData["SET_ITEMS_DATA"], ['allowed_classes' => false]);
1007
1009 $res = self::setBasketItemFields($item, $itemFields);
1010
1011 if (!$res->isSuccess())
1012 {
1013 $result->addErrors($res->getErrors());
1014// return null;
1015 }
1016 elseif($res->hasWarnings())
1017 {
1018 foreach($res->getWarningMessages() as $warning)
1019 {
1020 $result->addError(new Error($warning));
1021 }
1022 }
1023 }
1024
1025 /*
1026 * Could be deleted and than added one more time product.
1027 * Or just added product.
1028 */
1029 if($basketCode != $item->getBasketCode())
1030 $basketCodeMap[$basketCode] = $item->getBasketCode();
1031
1032 if(!empty($productData["PROPS"]) && is_array($productData["PROPS"]))
1033 {
1035 $property = $item->getPropertyCollection();
1036 $property->setProperty($productData["PROPS"]);
1037 }
1038 }
1039
1040 $productsData = $formData["PRODUCT"];
1041
1042 if(!empty($basketCodeMap))
1043 {
1044 foreach($basketCodeMap as $old => $new)
1045 {
1046 $productsData[$new] = $productsData[$old];
1047 unset($productsData[$old]);
1048 }
1049 }
1050
1051 $res = self::fillBasketItems($basket, $productsData, $order, array_unique($needDataUpdate));
1052
1053 if(!$res->isSuccess())
1054 {
1055 $result->addErrors($res->getErrors());
1056
1057 if($res->isTerminal())
1058 {
1059 return null;
1060 }
1061 }
1062
1063 if ($isStartField)
1064 {
1065 $hasMeaningfulFields = $order->hasMeaningfulField();
1066
1068 $r = $order->doFinalAction($hasMeaningfulFields);
1069 if (!$r->isSuccess())
1070 {
1071 $result->addErrors($r->getErrors());
1072 }
1073 }
1074
1075 if(isset($formData["DISCOUNTS"]) && is_array($formData["DISCOUNTS"]))
1076 $order->getDiscount()->setApplyResult($formData["DISCOUNTS"]);
1077 }
1078 else
1079 {
1080 $result->addError(new EntityError(Loc::getMessage("SALE_ORDEREDIT_ERROR_NO_PRODUCTS")));
1081 }
1082
1083 return $order;
1084 }
1085
1093 public static function fillSimpleFields(Order $order, array $formData, $userId = 0)
1094 {
1095 $result = new \Bitrix\Sale\Result();
1096 if(isset($formData["ORDER"]["RESPONSIBLE_ID"]))
1097 {
1098 if (intval($formData["ORDER"]["RESPONSIBLE_ID"]) != intval($order->getField('RESPONSIBLE_ID')))
1099 {
1101 $r = $order->setField("RESPONSIBLE_ID", $formData["ORDER"]["RESPONSIBLE_ID"]);
1102 if (!$r->isSuccess())
1103 {
1104 $result->addErrors($r->getErrors());
1105 }
1106 }
1107 }
1108
1109 if(!empty($formData["ORDER"]) && array_key_exists('COMPANY_ID', $formData["ORDER"]))
1110 {
1112 $r = $order->setField("COMPANY_ID", (isset($formData["ORDER"]['COMPANY_ID']) && $formData["ORDER"]['COMPANY_ID'] > 0) ? $formData["ORDER"]['COMPANY_ID'] : 0);
1113 if (!$r->isSuccess())
1114 {
1115 $result->addErrors($r->getErrors());
1116 }
1117 }
1118
1119 if(isset($formData["PERSON_TYPE_ID"]) && intval($formData["PERSON_TYPE_ID"]) > 0)
1120 {
1122 $r = $order->setPersonTypeId(intval($formData['PERSON_TYPE_ID']));
1123 }
1124 else
1125 {
1127 $r = $order->setPersonTypeId(
1128 Blocks\OrderBuyer::getDefaultPersonType(
1129 $order->getSiteId()
1130 )
1131 );
1132 }
1133
1134 if (!$r->isSuccess())
1135 {
1136 $result->addErrors($r->getErrors());
1137 }
1138
1139 if(isset($formData["ORDER"]["COMMENTS"]))
1140 {
1142 $r = $order->setField("COMMENTS", $formData["ORDER"]["COMMENTS"]);
1143 if (!$r->isSuccess())
1144 {
1145 $result->addErrors($r->getErrors());
1146 }
1147 }
1148
1149 if(isset($formData["USER_DESCRIPTION"]))
1150 {
1152 $r = $order->setField("USER_DESCRIPTION", $formData["USER_DESCRIPTION"]);
1153 if (!$r->isSuccess())
1154 {
1155 $result->addErrors($r->getErrors());
1156 }
1157 }
1158
1159 if(isset($formData["RESPONSIBLE_ID"]))
1160 {
1162 $r = $order->setField("RESPONSIBLE_ID", $formData["RESPONSIBLE_ID"]);
1163 if (!$r->isSuccess())
1164 {
1165 $result->addErrors($r->getErrors());
1166 }
1167 }
1168
1169 if(isset($formData["STATUS_ID"]) && $formData["STATUS_ID"] <> '')
1170 {
1171 $statusesList = \Bitrix\Sale\OrderStatus::getAllowedUserStatuses(
1172 $userId,
1174 );
1175
1176 if(array_key_exists($formData["STATUS_ID"], $statusesList))
1177 {
1179 $r = $order->setField("STATUS_ID", $formData["STATUS_ID"]);
1180 if (!$r->isSuccess())
1181 {
1182 $result->addErrors($r->getErrors());
1183 }
1184 }
1185 }
1186
1187 return $result;
1188 }
1189
1190 public static function fillBasketItems(Basket &$basket, array $productsFormData, Order $order, array $needDataUpdate = array())
1191 {
1192 $basketItems = $basket->getBasketItems();
1193 $result = new OrderEditResult();
1194 $catalogProductsIds = array();
1195 $trustData = array();
1196
1197 // Preparing fields need by provider
1199 foreach($basketItems as $item)
1200 {
1201 $basketCode = $item->getBasketCode();
1202
1203 if(empty($productsFormData[$basketCode]))
1204 continue;
1205
1206 $productData = $productsFormData[$basketCode];
1207 $isDataNeedUpdate = in_array($basketCode, $needDataUpdate);
1208
1209 if(isset($productData["PRODUCT_PROVIDER_CLASS"]) && $productData["PRODUCT_PROVIDER_CLASS"] <> '')
1210 {
1211 $item->setField("PRODUCT_PROVIDER_CLASS", trim($productData["PRODUCT_PROVIDER_CLASS"]));
1212 }
1213
1214 /*
1215 * Let's extract cached provider product data from field
1216 * in case activity is through ajax.
1217 */
1218 if(self::$isTrustProductFormData && !$isDataNeedUpdate)
1219 {
1220 if(!empty($productData["PROVIDER_DATA"]) && CheckSerializedData($productData["PROVIDER_DATA"]))
1221 $trustData[$basketCode] = unserialize($productData["PROVIDER_DATA"], ['allowed_classes' => false]);
1222
1223 // if quantity changed we must get fresh data from provider
1224 if(!empty($trustData[$basketCode]) && $trustData[$basketCode]["QUANTITY"] == $productData["QUANTITY"])
1225 {
1226 if(!empty($productData["SET_ITEMS_DATA"]) && CheckSerializedData($productData["SET_ITEMS_DATA"]))
1227 $productData["SET_ITEMS"] = unserialize($productData["SET_ITEMS_DATA"], ['allowed_classes' => false]);
1228
1229 if(is_array($trustData[$basketCode]) && !empty($trustData[$basketCode]))
1230 self::setProviderTrustData($item, $order, $trustData[$basketCode]);
1231 }
1232 else
1233 {
1234 unset($trustData[$basketCode]);
1235 }
1236 }
1237
1238 if (isset($productData['NAME']))
1239 {
1240 $item->setField('NAME', $productData['NAME']);
1241 }
1242 $res = $item->setField("QUANTITY", $productData["QUANTITY"]);
1243
1244 if(!$res->isSuccess())
1245 {
1246 $result->addErrors($res->getErrors());
1247 $justAdded = isset($productsFormData[$basketCode]['JUST_ADDED']) && $productsFormData[$basketCode]['JUST_ADDED'] == 'Y';
1248
1249 if($justAdded)
1250 {
1251 foreach($res->getErrors() as $error)
1252 {
1253 if($error->getCode() == 'SALE_BASKET_ITEM_WRONG_AVAILABLE_QUANTITY')
1254 {
1255 $result->setIsTerminal(true);
1256 return $result;
1257 }
1258 }
1259 }
1260 }
1261
1262 if(isset($productData["MODULE"]) && $productData["MODULE"] == "catalog")
1263 {
1264 $catalogProductsIds[] = $item->getField('PRODUCT_ID');
1265 }
1266 elseif(empty($productData["PRODUCT_PROVIDER_CLASS"]))
1267 {
1268 $availableFields = BasketItemBase::getAvailableFields();
1269 $availableFields = array_fill_keys($availableFields, true);
1270 $fillFields = array_intersect_key($productData, $availableFields);
1271 if (!empty($fillFields))
1272 {
1273 $r = $item->setFields($fillFields);
1274 }
1275 }
1276 }
1277
1278 $catalogData = array();
1279
1280 if(!empty($catalogProductsIds))
1281 $catalogData = OrderBasket::getProductsData($catalogProductsIds, $order->getSiteId(), array(), $order->getUserId());
1282
1283 $providerData = array();
1284
1285 if(!self::$isTrustProductFormData || !empty($needDataUpdate) || self::$needUpdateNewProductPrice)
1286 {
1287 $params = array("AVAILABLE_QUANTITY");
1288
1289 if($order->getId() <= 0)
1290 $params[] = "PRICE";
1291
1292 $providerData = Provider::getProductData($basket, $params);
1293
1294 /*
1295 foreach($basketItems as $item)
1296 {
1297 $basketCode = $item->getBasketCode();
1298
1299 if($order->getId() <= 0 && !empty($providerData[$basketCode]) && empty($providerData[$basketCode]['QUANTITY']))
1300 {
1301 $result->addError(
1302 new Error(
1303 Loc::getMessage(
1304 "SALE_ORDEREDIT_PRODUCT_QUANTITY_IS_EMPTY",
1305 array(
1306 "#NAME#" => $item->getField('NAME')
1307 )
1308 ),
1309 'SALE_ORDEREDIT_PRODUCT_QUANTITY_IS_EMPTY'
1310 )
1311 );
1312 }
1313 }
1314 */
1315
1316 }
1317
1318 /*
1319 if (!$result->isSuccess())
1320 {
1321 return $result;
1322 }
1323 */
1324
1325 $data = array();
1326
1327 foreach($basketItems as $item)
1328 {
1329 $basketCode = $item->getBasketCode();
1330 $productData = $productsFormData[$basketCode];
1331 if (!$productData)
1332 {
1333 continue;
1334 }
1335
1336 $isDataNeedUpdate = in_array($basketCode, $needDataUpdate);
1337 $data[$basketCode] = $item->getFieldValues();
1338
1339 if(!empty($providerData[$basketCode]))
1340 {
1341 if (static::$isRefreshData === true)
1342 {
1343 unset($providerData[$basketCode]['QUANTITY']);
1344 }
1345
1346 $data[$basketCode] = $providerData[$basketCode];
1347 }
1348 elseif(!empty($trustData[$basketCode]))
1349 {
1350 $data[$basketCode] = $trustData[$basketCode];
1351 }
1352 else
1353 {
1354 $data = Provider::getProductData($basket, array("PRICE", "AVAILABLE_QUANTITY"), $item);
1355
1356 if(is_array($data[$basketCode]) && !empty($data[$basketCode]))
1357 self::setProviderTrustData($item, $order, $data[$basketCode]);
1358 }
1359
1360 /* Get actual info from provider
1361 * cases:
1362 * 1) add new product to basket;
1363 * 2) saving operation;
1364 * 3) changing quantity;
1365 * 4) changing buyerId
1366 */
1367 if($order->getId() <= 0 && (empty($data[$basketCode]) || !self::$isTrustProductFormData || $isDataNeedUpdate))
1368 {
1369 if(empty($providerData[$basketCode]) && $productData["PRODUCT_PROVIDER_CLASS"] <> '')
1370 {
1371 $name = "";
1372
1373 if(!empty($productData["NAME"]))
1374 $name = $productData["NAME"];
1375
1376 if(!empty($productData["PRODUCT_ID"]))
1377 $name .= " (".$productData['PRODUCT_ID'].")";
1378
1379 $result->addError(
1380 new Error(
1382 "SALE_ORDEREDIT_PRODUCT_IS_NOT_AVAILABLE",
1383 array(
1384 "#NAME_ID#" => $name
1385 )
1386 )
1387 )
1388 );
1389
1390// return $result;
1391 }
1392 }
1393
1394 $product = array();
1395
1396 if(isset($data[$basketCode]) && !empty($data[$basketCode]))
1397 {
1398 $product = $data[$basketCode];
1399
1400 if(isset($productData['PRICE']) && isset($productData['CUSTOM_PRICE']) && $productData['CUSTOM_PRICE'] == 'Y')
1401 $product['PRICE'] = $productData['PRICE'];
1402 elseif(isset($product['BASE_PRICE']))
1403 $product['PRICE'] = $product['BASE_PRICE'] - $product['DISCOUNT_PRICE'];
1404 }
1405
1406 if($item->getField("MODULE") == "catalog")
1407 {
1408 if(!empty($catalogData[$item->getProductId()]))
1409 {
1410 $product = array_merge($product, $catalogData[$item->getProductId()]);
1411 unset($productData["CURRENCY"]);
1412 }
1413 }
1414
1415 if(!self::$isTrustProductFormData || $isDataNeedUpdate)
1416 {
1417 $product = array_merge($productData, $product);
1418 }
1419 else
1420 {
1421 $needUpdateItemPrice = self::$needUpdateNewProductPrice && self::isBasketItemNew($basketCode);
1422 $isPriceCustom = isset($productData['CUSTOM_PRICE']) && $productData['CUSTOM_PRICE'] == 'Y';
1423
1424 if(($order->getId() <= 0 && !$isPriceCustom) || $needUpdateItemPrice)
1425 unset($productData['PRICE'], $productData['PRICE_BASE'], $productData['BASE_PRICE']);
1426
1427 $product = array_merge($product, $productData);
1428 }
1429
1430 if(isset($product["OFFER_ID"]) && intval($product["OFFER_ID"]) > 0)
1431 $product["PRODUCT_ID"] = $product["OFFER_ID"];
1432
1433 $product = array_intersect_key($product, array_flip($item::getAvailableFields()));
1434
1435 if(isset($product["MEASURE_CODE"]) && $product["MEASURE_CODE"] <> '')
1436 {
1437 $measures = OrderBasket::getCatalogMeasures();
1438
1439 if(isset($measures[$product["MEASURE_CODE"]]) && $measures[$product["MEASURE_CODE"]] <> '')
1440 $product["MEASURE_NAME"] = $measures[$product["MEASURE_CODE"]];
1441 }
1442
1443 if(!isset($product["CURRENCY"]) || $product["CURRENCY"] == '')
1444 $product["CURRENCY"] = $order->getCurrency();
1445
1446 if (($productData['IS_SET_PARENT'] ?? null) === 'Y')
1447 {
1448 $product['TYPE'] = BasketItem::TYPE_SET;
1449 }
1450
1452 $productData["OFFER_ID"],
1453 $order->getUserId(),
1454 $order->getSiteId(),
1455 array_merge($product, $productData)
1456 );
1457
1458 if (!empty($item->getProvider()))
1459 {
1460 unset($product['PRODUCT_PROVIDER_CLASS']);
1461 }
1462
1463 $res = self::setBasketItemFields($item, $product);
1464
1465 if(!$res->isSuccess())
1466 {
1467 foreach($res->getErrors() as $newError)
1468 {
1469 foreach($result->getErrors() as $existError)
1470 if($newError->getMessage() == $existError->getMessage())
1471 continue 2;
1472
1473 $result->addError($newError);
1474 }
1475 }
1476 }
1477
1478 return $result;
1479 }
1480
1496 public static function fillBasketItem(BasketItem &$item, array $productData, Order $order, Basket $basket, $needDataUpdate = false)
1497 {
1498 $result = new Result();
1499 $basketCode = $item->getBasketCode();
1500
1501 if(isset($productData["PRODUCT_PROVIDER_CLASS"]) && $productData["PRODUCT_PROVIDER_CLASS"] <> '')
1502 $item->setField("PRODUCT_PROVIDER_CLASS", trim($productData["PRODUCT_PROVIDER_CLASS"]));
1503
1504 $data = array();
1505
1506 /*
1507 * Let's extract cached provider product data from field
1508 * in case activity is through ajax.
1509 */
1510 if(self::$isTrustProductFormData && !$needDataUpdate)
1511 {
1512 if(!empty($productData["PROVIDER_DATA"]) && CheckSerializedData($productData["PROVIDER_DATA"]))
1513 $data[$basketCode] = unserialize($productData["PROVIDER_DATA"], ['allowed_classes' => false]);
1514
1515 // if quantity changed we must get fresh data from provider
1516 if(!empty($data[$basketCode]) && $data[$basketCode] == $productData["QUANTITY"])
1517 {
1518 if(!empty($productData["SET_ITEMS_DATA"]) && CheckSerializedData($productData["SET_ITEMS_DATA"]))
1519 $productData["SET_ITEMS"] = unserialize($productData["SET_ITEMS_DATA"], ['allowed_classes' => false]);
1520
1521 if(is_array($data[$basketCode]) && !empty($data[$basketCode]))
1522 self::setProviderTrustData($item, $order, $data[$basketCode]);
1523 }
1524 else
1525 {
1526 unset($data[$basketCode]);
1527 }
1528 }
1529
1530 $item->setField("NAME", $productData["NAME"]);
1531 $res = $item->setField("QUANTITY", $productData["QUANTITY"]);
1532
1533 if(!$res->isSuccess())
1534 {
1535 $result->addErrors($res->getErrors());
1536 return $result;
1537 }
1538
1539 $product = array();
1540
1541 /* Get actual info from provider
1542 * cases:
1543 * 1) add new product to basket;
1544 * 2) saving operation;
1545 * 3) changing quantity;
1546 */
1547 if(empty($data[$basketCode]) || !self::$isTrustProductFormData || $needDataUpdate)
1548 {
1549 $data = Provider::getProductData($basket, array("PRICE", "AVAILABLE_QUANTITY"), $item);
1550
1551 if(empty($data[$basketCode]) && $productData["PRODUCT_PROVIDER_CLASS"] <> '')
1552 {
1553 $name = "";
1554
1555 if(!empty($productData["NAME"]))
1556 $name = $productData["NAME"];
1557
1558 if(!empty($productData["PRODUCT_ID"]))
1559 $name .= " (".$productData['PRODUCT_ID'].")";
1560
1561 $result->addError(
1562 new Error(
1564 "SALE_ORDEREDIT_PRODUCT_IS_NOT_AVAILABLE",
1565 array(
1566 "#NAME_ID#" => $name
1567 )
1568 )
1569 )
1570 );
1571
1572 return $result;
1573 }
1574
1575 if(is_array($data[$basketCode]) && !empty($data[$basketCode]))
1576 self::setProviderTrustData($item, $order, $data[$basketCode]);
1577 }
1578
1579 if(isset($data[$basketCode]) && !empty($data[$basketCode]))
1580 {
1581 $product = $data[$basketCode];
1582
1583 if(isset($productData['PRICE']) && isset($productData['CUSTOM_PRICE']) && $productData['CUSTOM_PRICE'] == 'Y')
1584 $product['PRICE'] = $productData['PRICE'];
1585 elseif(isset($product['BASE_PRICE']))
1586 $product['PRICE'] = $product['BASE_PRICE'] - $product['DISCOUNT_PRICE'];
1587 }
1588
1589 if(!self::$isTrustProductFormData)
1590 {
1591 if(isset($productData["MODULE"]) && $productData["MODULE"] == "catalog")
1592 {
1593 $data = OrderBasket::getProductDetails(
1594 $item->getProductId(),
1595 $productData["QUANTITY"],
1596 $order->getUserId(),
1597 $order->getSiteId()
1598 );
1599
1600 $product = array_merge($product, $data);
1601 }
1602
1603 unset($productData["CURRENCY"]);
1604 }
1605
1606 $product = array_merge($product, $productData);
1607
1608 if(isset($product["OFFER_ID"]) || intval($product["OFFER_ID"]) >= 0)
1609 $product["PRODUCT_ID"] = $product["OFFER_ID"];
1610
1611 $product = array_intersect_key($product, array_flip($item::getAvailableFields()));
1612
1613 if(isset($product["MEASURE_CODE"]) && $product["MEASURE_CODE"] <> '')
1614 {
1615 $measures = OrderBasket::getCatalogMeasures();
1616
1617 if(isset($measures[$product["MEASURE_CODE"]]) && $measures[$product["MEASURE_CODE"]] <> '')
1618 $product["MEASURE_NAME"] = $measures[$product["MEASURE_CODE"]];
1619 }
1620
1621 if(!isset($product["CURRENCY"]) || $product["CURRENCY"] == '')
1622 $product["CURRENCY"] = $order->getCurrency();
1623
1624 if($productData["IS_SET_PARENT"] == "Y")
1625 $product["TYPE"] = BasketItem::TYPE_SET;
1626
1628 $productData["OFFER_ID"],
1629 $order->getUserId(),
1630 $order->getSiteId(),
1631 array_merge($product, $productData)
1632 );
1633
1634 $result = self::setBasketItemFields($item, $product);
1635 return $result;
1636 }
1637
1638 public static function setProviderTrustData(BasketItem $item, Order $order, array $data)
1639 {
1640 if(empty($data))
1641 return false;
1642
1643 Provider::setTrustData($order->getSiteId(), $item->getField('MODULE'), $item->getProductId(), $data);
1644
1645 if ($item->isBundleParent())
1646 {
1647 if ($bundle = $item->getBundleCollection())
1648 {
1650 foreach ($bundle as $bundleItem)
1651 {
1652 $bundleItemData = $bundleItem->getFields()->getValues();
1653 Provider::setTrustData($order->getSiteId(), 'sale', $bundleItem->getProductId(), $bundleItemData);
1654 }
1655 }
1656 }
1657
1658 return true;
1659 }
1660
1661 public static function setBasketItemFields(BasketItem &$item, array $fields = array())
1662 {
1663 return $item->setFields($fields);
1664 }
1665
1666 public static function getSiteName(&$siteId)
1667 {
1668 $siteName = "";
1669
1670 if($siteId == '')
1671 {
1672 $res = \CSite::GetList("id", "asc", array("ACTIVE" => "Y", "DEF" => "Y"));
1673
1674 if($site = $res->Fetch())
1675 {
1676 $siteId = $site["ID"];
1677 $siteName = $site["NAME"]." (".$siteId.")";
1678 }
1679 }
1680 else
1681 {
1682 $res = \CSite::GetByID($siteId);
1683
1684 if($site = $res->Fetch())
1685 $siteName = $site["NAME"]." (".$siteId.")";
1686 }
1687
1688 return $siteName;
1689 }
1690
1691 public static function restoreFieldsNames(array $data, $path = "")
1692 {
1693 $result = array();
1694
1695 foreach($data as $fieldName => $fieldValue)
1696 {
1697 $fullName = ($path == "" ? $fieldName : $path."[".$fieldName."]");
1698
1699 if(is_array($fieldValue))
1700 $result = array_merge($result, self::restoreFieldsNames($fieldValue, $fullName));
1701 else
1702 $result[$fullName] = $fieldValue;
1703 }
1704
1705 return $result;
1706 }
1707
1713 public static function initCouponsData($newUserId, $orderId = 0, $oldUserId = 0)
1714 {
1715 $newUserId = (int)$newUserId;
1716 $orderId = (int)$orderId;
1717
1718 $params = array('userId' => $newUserId);
1719
1720 if ($oldUserId !== null)
1721 {
1722 $oldUserId = (int)$oldUserId;
1723 if ($oldUserId != $newUserId)
1724 $params["oldUserId"] = $oldUserId;
1725 }
1726
1727 if ($orderId > 0)
1728 {
1729 $params['orderId'] = $orderId;
1730
1733 $params
1734 );
1735 }
1736 else
1737 {
1740 $params
1741 );
1742 }
1743 }
1744
1745 public static function getCouponsData()
1746 {
1747 return DiscountCouponsManager::get(true, array(), true, false);
1748 }
1749
1758 public static function getDiscountsApplyResult(Order $order, $needRecalculate = false)
1759 {
1760 static $calcResults = null;
1761
1762 if ($order instanceof Sale\Archive\Order)
1763 {
1765 return $order->getDiscountData();
1766 }
1767
1768 if ($calcResults === null || $needRecalculate)
1769 {
1770 $discounts = $order->getDiscount();
1771
1772 if ($needRecalculate)
1773 {
1775 $r = $discounts->calculate();
1776
1777 if ($r->isSuccess())
1778 {
1779 $discountData = $r->getData();
1780 $order->applyDiscount($discountData);
1781 }
1782 }
1783
1784 $calcResults = $discounts->getApplyResult(true);
1785 unset($discounts);
1786 }
1787
1788 return $calcResults === null ? array() : $calcResults;
1789 }
1790
1791 public static function getOrderedDiscounts(Order $order, $needRecalculate = true)
1792 {
1793 $discounts = self::getDiscountsApplyResult($order, $needRecalculate);
1794 $discounts["ORDER"] = array();
1795
1796 if(isset($discounts["DISCOUNT_LIST"]) && is_array($discounts["DISCOUNT_LIST"]))
1797 $discounts["ORDER"]["DISCOUNT_LIST"] = array_keys($discounts["DISCOUNT_LIST"]);
1798
1799 return $discounts;
1800 }
1801
1802 public static function getCouponList(Order $order = null, $needRecalculate = true)
1803 {
1804 $result = array();
1805 $discounts = array();
1806
1807 if ($order instanceof Sale\Archive\Order)
1808 {
1809 $discounts = $order->getDiscountData();
1810 return $discounts['COUPON_LIST'];
1811 }
1812
1813 $couponsList = self::getCouponsData();
1814
1815 if($order)
1816 $discounts = self::getDiscountsApplyResult($order, $needRecalculate);
1817
1818 if (!empty($couponsList))
1819 {
1820 foreach ($couponsList as &$oneCoupon)
1821 {
1822 if ($oneCoupon['STATUS'] == DiscountCouponsManager::STATUS_NOT_FOUND || $oneCoupon['STATUS'] == DiscountCouponsManager::STATUS_FREEZE)
1823 $oneCoupon['JS_STATUS'] = 'BAD';
1824 elseif ($oneCoupon['STATUS'] == DiscountCouponsManager::STATUS_NOT_APPLYED || $oneCoupon['STATUS'] == DiscountCouponsManager::STATUS_ENTERED)
1825 $oneCoupon['JS_STATUS'] = 'ENTERED';
1826 else
1827 $oneCoupon['JS_STATUS'] = 'APPLYED';
1828
1829 $oneCoupon['JS_CHECK_CODE'] = '';
1830
1831 if (isset($oneCoupon['CHECK_CODE_TEXT']))
1832 {
1833 $oneCoupon['JS_CHECK_CODE'] = (
1834 is_array($oneCoupon['CHECK_CODE_TEXT'])
1835 ? implode(', ', $oneCoupon['CHECK_CODE_TEXT'])
1836 : $oneCoupon['CHECK_CODE_TEXT']
1837 );
1838 }
1839
1840 if(!empty($discounts) && isset($discounts["COUPON_LIST"]) && is_array($discounts["COUPON_LIST"]))
1841 {
1842 foreach($discounts["COUPON_LIST"] as $coupon => $couponParams)
1843 {
1844 $couponsList[$coupon]["APPLY"] = $couponParams["APPLY"];
1845 $couponsList[$coupon]["DISCOUNT_SIZE"] = "";
1846
1847 if(isset($couponParams["ORDER_DISCOUNT_ID"]) && $couponParams["ORDER_DISCOUNT_ID"] <> '')
1848 {
1849 $couponsList[$coupon]["ORDER_DISCOUNT_ID"] = $couponParams["ORDER_DISCOUNT_ID"];
1850
1851 if(isset($discounts["DISCOUNT_LIST"][$couponParams["ORDER_DISCOUNT_ID"]]))
1852 {
1853 $couponDiscountParams = $discounts["DISCOUNT_LIST"][$couponParams["ORDER_DISCOUNT_ID"]];
1854
1855 if(isset($couponDiscountParams["ACTIONS_DESCR"]) && is_array($couponDiscountParams["ACTIONS_DESCR"]))
1856 foreach($couponDiscountParams["ACTIONS_DESCR"] as $key => $val)
1857 $couponsList[$coupon]["DISCOUNT_SIZE"] .= $val;
1858 }
1859 }
1860 }
1861 }
1862 }
1863
1864 $result = array_values($couponsList);
1865 }
1866
1867 return $result;
1868 }
1869
1870 public static function getTotalPrices(Order $order, OrderBasket $orderBasket, $needRecalculate = true)
1871 {
1872 $result = array(
1873 'PRICE_TOTAL' => $order->getPrice(),
1874 'TAX_VALUE' => $order->getTaxValue(),
1875 'PRICE_DELIVERY_DISCOUNTED' => $order->getDeliveryPrice(),
1876 'SUM_PAID' => $order->getSumPaid(),
1877 'ORDER_DISCOUNT_VALUE' => $order->getField('DISCOUNT_VALUE')
1878 );
1879
1880 $result["SUM_UNPAID"] = $result["PRICE_TOTAL"] - $result["SUM_PAID"];
1881
1882 if(!$result["PRICE_DELIVERY_DISCOUNTED"])
1883 $result["PRICE_DELIVERY_DISCOUNTED"] = 0;
1884
1885 if(!$result["TAX_VALUE"])
1886 $result["TAX_VALUE"] = 0;
1887
1888 $orderDiscount = $order->getDiscount();
1889
1890 if($orderDiscount)
1891 $discountsList = self::getDiscountsApplyResult($order, $needRecalculate);
1892 else
1893 $discountsList = array();
1894
1895 if(isset($discountsList["PRICES"]["DELIVERY"]["DISCOUNT"]))
1896 $result['DELIVERY_DISCOUNT'] = $discountsList["PRICES"]["DELIVERY"]["DISCOUNT"];
1897 else
1898 $result['DELIVERY_DISCOUNT'] = 0;
1899
1900 $result['PRICE_DELIVERY'] = $result['PRICE_DELIVERY_DISCOUNTED'] + $result['DELIVERY_DISCOUNT'];
1901 $basketData = $orderBasket->getPrices($discountsList);
1902 $result["PRICE_BASKET_DISCOUNTED"] = $basketData["BASKET_PRICE"];
1903 $result["PRICE_BASKET"] = $basketData["BASKET_PRICE_BASE"];
1904
1905 return $result;
1906 }
1907
1915 public static function setProductDetails($productId, $userId, $siteId, array $params)
1916 {
1917 if($productId == '')
1918 return;
1919
1920 if($userId == '')
1921 $userId = "0";
1922
1923 if($siteId == '')
1924 throw new ArgumentNullException("siteId");
1925
1926 self::$productsDetails[$productId."_".$userId."_".$siteId] = $params;
1927 }
1928
1929 public static function getProductDetails($productId, $userId, $siteId)
1930 {
1931 if($productId == '')
1932 {
1933 throw new ArgumentNullException("productId");
1934 }
1935
1936 if($userId == '')
1937 $userId = "0";
1938
1939 if($siteId == '')
1940 throw new ArgumentNullException("siteId");
1941
1942 if(isset(self::$productsDetails[$productId."_".$userId."_".$siteId]))
1943 $result = self::$productsDetails[$productId."_".$userId."_".$siteId];
1944 else
1945 $result = false;
1946
1947 return $result;
1948 }
1949
1954 public static function getCompanyList()
1955 {
1956 $dbRes = Company\Manager::getList(
1957 array(
1958 'select' => array('ID', 'NAME'),
1959 'filter' => array('ACTIVE' => 'Y')
1960 )
1961 );
1962 $result = array();
1963 while ($company = $dbRes->fetch())
1964 $result[$company["ID"]] = $company["NAME"]." [".$company["ID"]."]";
1965
1966 return $result;
1967 }
1968
1969 public static function getLockingMessage($orderId)
1970 {
1971 $intLockUserID = 0;
1972 $strLockTime = '';
1973
1974 $registry = Sale\Registry::getInstance(Sale\Registry::REGISTRY_TYPE_ORDER);
1976 $orderClass = $registry->getOrderClassName();
1977
1978 $r = $orderClass::getLockedStatus($orderId);
1979
1980 if ($r->isSuccess())
1981 {
1982 $lockResult = $r->getData();
1983
1984 if (array_key_exists('LOCKED_BY', $lockResult) && intval($lockResult['LOCKED_BY']) > 0)
1985 $intLockUserID = intval($lockResult['LOCKED_BY']);
1986
1987 if (array_key_exists('DATE_LOCK', $lockResult) && $lockResult['DATE_LOCK'] instanceof \Bitrix\Main\Type\DateTime)
1988 $strLockTime = $lockResult['DATE_LOCK']->toString();
1989 }
1990
1991 $strLockUserInfo = $intLockUserID;
1992
1993 $userIterator = \Bitrix\Main\UserTable::getList(array(
1994 'select' => array('ID', 'LOGIN', 'NAME', 'LAST_NAME', 'SECOND_NAME', 'EMAIL'),
1995 'filter' => array('=ID' => $intLockUserID)
1996 ));
1997
1998 if ($arOneUser = $userIterator->fetch())
1999 {
2000 $strNameFormat = \CSite::GetNameFormat(true);
2001 $strLockUser = \CUser::FormatName($strNameFormat, $arOneUser);
2002 $strLockUserInfo = '<a href="/bitrix/admin/user_edit.php?lang='.LANGUAGE_ID.'&ID='.$intLockUserID.'">'.$strLockUser.'</a>';
2003 }
2004
2005 return Loc::getMessage(
2006 'SALE_ORDEREDIT_LOCKED',
2007 array(
2008 '#ID#' => $strLockUserInfo,
2009 '#DATE#' => $strLockTime,
2010 )
2011 );
2012 }
2013}
static loadMessages($file)
Definition loc.php:64
static getMessage($code, $replace=null, $language=null)
Definition loc.php:29
addError(Error $error)
Definition result.php:50
addErrors(array $errors)
Definition result.php:98
setData(array $data)
Definition result.php:113
static get($extMode=true, $filter=[], $show=false, $final=false)
static init($mode=self::MODE_CLIENT, $params=[], $clearStorage=false)
static getIdByUserId($userId)
Definition fuser.php:151
static restoreFieldsNames(array $data, $path="")
static initCouponsData($newUserId, $orderId=0, $oldUserId=0)
static getProductDetails($productId, $userId, $siteId)
static getCouponList(Order $order=null, $needRecalculate=true)
static createUserFromForm(Order &$order, array $formData)
static isBasketItemNew($basketCode)
static fillOrderProperties(OrderBase $order, $formData, $files=[])
static getUserId($order, $formData, $createUserIfNeed, Result &$result)
static getTotalPrices(Order $order, OrderBasket $orderBasket, $needRecalculate=true)
static saveProfileData($profileId, Order $order, array $formData)
static fillBasketItem(BasketItem &$item, array $productData, Order $order, Basket $basket, $needDataUpdate=false)
static saveCoupons($userId, $formData)
static getScripts(Order $order, $formId)
static makeSelectHtmlWithRestricted($name, array $data, $selected="", $showNotUse=true, $attributes=array())
static setBasketItemFields(BasketItem &$item, array $fields=array())
static setProductDetails($productId, $userId, $siteId, array $params)
static makeSelectHtml($name, array $data, $selected="", $showNotUse=true, $attributes=array())
Definition orderedit.php:69
static getFastNavigationHtml(array $items, $formId='', $tabId='')
static makeSelectHtmlBodyWithRestricted($data, $selected='', $showNotUse=true)
static getOrderedDiscounts(Order $order, $needRecalculate=true)
static getUserName($userId, $siteId="")
static getProblemBlockHtml($text, $orderId)
static getProductData(BasketItemCollection $basketCollection, array $select=array(), BasketItem $refreshItem=null)
static setTrustData($siteId, $module, $productId, array $fields)
if(!function_exists(__NAMESPACE__.'\\___1034172934'))
Definition license.php:1