Bitrix-D7 23.9
 
Загрузка...
Поиск...
Не найдено
orderbasket.php
1<?php
2
4
17
18Loc::loadMessages(__FILE__);
19
20require_once __DIR__.'/../../../../general/admin_tool.php';
21
23{
24 protected static $jsInited = false;
25 protected static $arSkuProps = array();
26 protected static $offersCatalog = array();
27 protected static $iblockPropsParams = array();
28 protected static $iblockPropsParamsOrder = array();
29 protected static $productsOffersSkuParams = array();
30
31 public $settingsDialog = null;
32
34 protected $order = null;
35 protected $data = null;
36 protected $dataLight = null;
37 protected $jsObjName = "";
38 protected $idPrefix = "";
39 protected $visibleColumns = array();
40 protected $createProductBasement = true;
41 protected $mode;
42 protected $weightUnit;
43 protected $weightKoef;
44 protected $isShowXmlId;
45
46 protected static $iblockIncluded = null;
47 protected static $catalogIncluded = null;
48 protected static $highloadIncluded = null;
49
50 const VIEW_MODE = 0;
51 const EDIT_MODE = 1;
52
53 public function __construct(Order $order, $jsObjName = "", $idPrefix = "", $createProductBasement = true, $mode = self::EDIT_MODE)
54 {
55 $this->order = $order;
56 $this->idPrefix = $idPrefix;
57 if (!$this->visibleColumns)
58 $this->visibleColumns = $this->getVisibleColumns($idPrefix);
59 $this->createProductBasement = $createProductBasement;
60 $this->mode = $mode;
61 $this->weightUnit = htmlspecialcharsbx(Option::get('sale', 'weight_unit', "", $this->order->getSiteId()));
62 $this->weightKoef = floatval(Option::get('sale', 'weight_koef', 1, $this->order->getSiteId()));
63
64 if($this->weightKoef <= 0)
65 $this->weightKoef = 1;
66
67 $this->isShowXmlId = Option::get("sale", "show_order_product_xml_id", "N") == "Y";
68
69 if($jsObjName <> '' && $idPrefix <> '')
70 {
71 $this->jsObjName = $jsObjName;
72
73 $this->settingsDialog = new OrderBasketSettings(array(
74 "ID_PREFIX" => $this->idPrefix,
75 "SETTINGS_DLG_OBJECT_NAME" => $jsObjName.".settingsDialog",
76 "ALL_COLUMNS" => array_merge(
77 static::getDefaultVisibleColumns(),
78 getAdditionalColumns(),
79 array('NUMBER' => Loc::getMessage('SALE_ORDER_BASKET_SETTINGS_COL_NUMBER'))
80 ),
81 "VISIBLE_COLUMNS" => $this->visibleColumns
82 ));
83 }
84 }
85
86 public function setSettingsShowPropsVisible(bool $isVisible): void
87 {
88 $this->settingsDialog->setShowPropsVisible($isVisible);
89 }
90
97 public function getEdit($defTails = false)
98 {
99 $productAddBool = Option::get('sale', 'SALE_ADMIN_NEW_PRODUCT', 'N');
100 $siteId = htmlspecialcharsbx(
101 \CUtil::JSEscape(
102 $this->order->getSiteId()
103 ));
104
105 $result = '
106 <div class="adm-s-gray-title" style="padding-right: 2px;">
107 '.Loc::getMessage("SALE_ORDER_BASKET_COMPOSITION").'
108 <div class="adm-s-gray-title-btn-container">
109 <span
110 class="adm-btn adm-btn-green adm-btn-add"
111 onClick="'.$this->jsObjName.'.addProductSearch({lang: \''.LANGUAGE_ID.'\', siteId: \''.$siteId.'\', orderId: '.intval($this->order->getId()).'});"
112 >'.
113 Loc::getMessage("SALE_ORDER_BASKET_PRODUCT_ADD").
114 '</span>
115 </div>
116 <div class="clb"></div>
117 </div>';
118
119 $result .= '
120 <div class="adm-s-order-table-ddi">
121 <table class="adm-s-order-table-ddi-table" style="width: 100%;" id="'.$this->idPrefix.'sale_order_edit_product_table">
122 <thead style="text-align: left;">
123 <tr>
124 <td class="adm-s-order-table-context-menu-column">
125 <span class="adm-s-order-table-title-icon"
126 title="'.Loc::getMessage("SALE_ORDER_BASKET_SETTINGS_BUTTON_TITLE").'"
127 onclick="'.$this->jsObjName.'.onHeadMenu(this);"
128 >
129 </span>
130 </td> ';
131
132 foreach($this->visibleColumns as $name)
133 $result .= "<td>".htmlspecialcharsbx($name)."</td>";
134
135 $result .= '</tr>
136 </thead>';
137
138 if($defTails)
139 {
140 $result .='
141 <tbody style="border: 1px solid rgb(221, 221, 221);" id="'.$this->idPrefix.'sale-adm-order-basket-loading-row">
142 <tr>
143 <td colspan="'.(count($this->visibleColumns)+1).'" style="padding: 20px;">
144 <img src="/bitrix/images/sale/admin-loader.gif"/>
145 </td>
146 </tr>
147 </tbody>';
148 }
149
150 $result .='
151 <tbody style="border: 1px solid rgb(221, 221, 221);'.($defTails ? ' display:none;' : '').'" id="'.$this->idPrefix.'sale-adm-order-edit-basket-empty-row">
152 <tr>
153 <td colspan="'.(count($this->visibleColumns)+1).'" style="padding: 20px;">
154 '.Loc::getMessage("SALE_ORDER_BASKET_EMPTY_ROW").'.
155 </td>
156 </tr>
157 </tbody>';
158
159 $result .= '
160 </table>
161 </div>
162 <div class="adm-s-gray-title" style="padding-right: 2px;">
163 <div class="adm-s-gray-title-btn-container">
164 <!--<span
165 class="adm-btn adm-btn-green"
166 onClick="BX.Sale.Admin.OrderAjaxer.sendRequest(BX.Sale.Admin.OrderEditPage.ajaxRequests.refreshOrderData({operation: \'DATA_ACTUALIZE\'}));"
167 >'.Loc::getMessage('SALE_ORDER_BASKET_ACTUALIZE_DATA').'</span>&nbsp;-->';
168
169 if($productAddBool == "Y")
170 {
171 $result .= '<span
172 class="adm-btn adm-btn-green adm-btn-add"
173 onClick="'.$this->jsObjName.'.productEditDialog.show();"
174 >'.
175 Loc::getMessage("SALE_ORDER_BASKET_PRODUCT_NEW").
176 '</span>&nbsp;';
177 }
178
179 $result .= '<span
180 class="adm-btn adm-btn-green adm-btn-add"
181 onClick="'.$this->jsObjName.'.addProductSearch({lang: \''.LANGUAGE_ID.'\', siteId: \''.$siteId.'\', index: 1, orderId: '.intval($this->order->getId()).'});"
182 >'.
183 Loc::getMessage("SALE_ORDER_BASKET_PRODUCT_ADD").
184 '</span>
185 </div>
186 <div class="clb"></div>
187 </div>
188 <input type="hidden" name="BASKET[ID_PREFIX]" value="'.$this->idPrefix.'">
189 <div class="adm-s-result-container">';
190
191 $result .= $this->getCouponsHtml(self::EDIT_MODE, false);
192 $result .= $this->getTotalHtml(false);
193 $result .= '
194 </div>
195 <div class="clb"></div>';
196 return $result;
197 }
198
199 public static function getBasePrice(Order $order)
200 {
201 return $order->getPrice() - $order->getTaxValue() - $order->getDiscountPrice() - $order->getDeliveryPrice();
202 }
203
204 public function getTotalHtml($needRecalculate = true)
205 {
206 $currency = $this->order->getCurrency();
207 $basket = $this->order->getBasket();
208 $totalPrices = OrderEdit::getTotalPrices($this->order, $this, $needRecalculate);
209
210 $orderDiscount = '';
211 if ((float)$totalPrices['ORDER_DISCOUNT_VALUE'] > 0)
212 {
213 $orderDiscount = '<tr>
214 <td>'.Loc::getMessage("SALE_ORDER_DEPRECATED_DISCOUNT_VALUE").'</td>
215 <td id="'.$this->idPrefix.'sale_order_edit_basket_order_discount">'.
216 \CCurrencyLang::currencyFormat(floatval($totalPrices["ORDER_DISCOUNT_VALUE"]), $currency, true).
217 '</td>
218 </tr>';
219 }
220
221 if($basket)
222 $weight = $basket->getWeight();
223 else
224 $weight = 0;
225
226 return '
227 <div class="adm-s-result-container-itog">
228 <table class="adm-s-result-container-itog-table">
229 <tr>
230 <td>'.Loc::getMessage("SALE_ORDER_BASKET_PRICE").'</td>
231 <td id="'.$this->idPrefix.'sale_order_edit_basket_price_basket">'.
232 \CCurrencyLang::currencyFormat(floatval($totalPrices["PRICE_BASKET"]), $currency, true).
233 '</td>
234 </tr>
235 <tr>
236 <td>'.Loc::getMessage("SALE_ORDER_BASKET_PRICE_DISCOUNT").'</td>
237 <td id="'.$this->idPrefix.'sale_order_edit_basket_price_discount">'.
238 \CCurrencyLang::currencyFormat(floatval($totalPrices["PRICE_BASKET_DISCOUNTED"]), $currency, true).
239 '</td>
240 </tr>
241 <tr>
242 <td>'.Loc::getMessage("SALE_ORDER_BASKET_PRICE_DELIVERY").'</td>
243 <td id="'.$this->idPrefix.'sale_order_edit_basket_price_delivery">'.
244 \CCurrencyLang::currencyFormat(floatval($totalPrices["PRICE_DELIVERY"]), $currency, true).
245 '</td>
246 </tr>
247 <tr>
248 <td>'.Loc::getMessage("SALE_ORDER_BASKET_PRICE_DELIVERY_DISCOUNT").'</td>
249 <td id="'.$this->idPrefix.'sale_order_edit_basket_price_delivery_discount">'.
250 \CCurrencyLang::currencyFormat(floatval($totalPrices["PRICE_DELIVERY_DISCOUNTED"]), $currency, true).
251 '</td>
252 </tr>'.
253 $orderDiscount.'
254 <tr>
255 <td>'.Loc::getMessage("SALE_ORDER_BASKET_TAX").'</td>
256 <td id="'.$this->idPrefix.'sale_order_edit_basket_tax">'.
257 \CCurrencyLang::currencyFormat(floatval($totalPrices["TAX_VALUE"]), $currency, true).
258 '</td>
259 </tr>
260 <tr>
261 <td>'.Loc::getMessage("SALE_ORDER_BASKET_WEIGHT").'</td>
262 <td id="'.$this->idPrefix.'sale_order_edit_basket_weight">'.
263 roundEx(floatval($weight/$this->weightKoef), SALE_WEIGHT_PRECISION)." ".$this->weightUnit.
264 '</td>
265 </tr>
266 <tr>
267 <td>'.Loc::getMessage("SALE_ORDER_BASKET_PAID").'</td>
268 <td id="'.$this->idPrefix.'sale_order_edit_summ_paid">'.
269 \CCurrencyLang::currencyFormat(
270 floatval($totalPrices["SUM_PAID"]),
271 $currency,
272 true
273 ).
274 '</td>
275 </tr>
276 <tr class="adm-s-result-container-itog-table-result">
277 <td>'.Loc::getMessage("SALE_ORDER_BASKET_PRICE_TOTAL").'</td>
278 <td id="'.$this->idPrefix.'sale_order_edit_basket_price_total">'.
279 \CCurrencyLang::currencyFormat(
280 floatval($totalPrices["SUM_UNPAID"]),
281 $currency,
282 true
283 ).
284 '</td>
285 </tr>
286 </table>
287 </div>
288 ';
289
290 }
291
292 public function getCouponsHtml($mode, $needRecalculate = true)
293 {
294 $showBlock = true;
295
296 if($mode == self::VIEW_MODE)
297 {
298 $discounts = OrderEdit::getDiscountsApplyResult($this->order, $needRecalculate);
299 $showBlock = !empty($discounts["COUPON_LIST"]);
300 }
301
302 if($showBlock)
303 {
304 $couponMessage = '';
305 if ($this->order->getId() > 0 && !($this->order instanceof Sale\Archive\Order))
306 $couponMessage = '<br><div class="bx-adm-pc-section" style="font-size: smaller;">'.Loc::getMessage('SALE_ORDER_BASKET_COUPONS_NOTE').'</div>';
307
308 $result = '
309 <div class="adm-s-result-container-promo">
310 <div class="bx-adm-promocode-container">
311 <div class="bx-adm-pc-section">
312 <div class="bx-adm-pc-title">'.Loc::getMessage("SALE_ORDER_BASKET_PROMO").'</div>'.
313 ($mode == self::EDIT_MODE ?
314 '<div class="bx-adm-pc-inputs-container">
315 <input type="text" class="bx-adm-pc-inout-text" id="sale-admin-order-coupons">
316 <input type="submit" class="bx-adm-pc-input-submit" value='.Loc::getMessage("SALE_ORDER_BASKET_ADD").' onclick="BX.Sale.Admin.OrderBasketCoupons.onAddCoupons(); return false;">
317 </div>'.$couponMessage : '').
318 '</div>
319 <div class="bx-adm-pc-section">
320 <ul class="bx-adm-pc-sale-list" id="sale-admin-order-coupons-container">
321 </ul>
322 </div>
323 </div>
324 </div>';
325 unset($couponMessage);
326 }
327 else
328 {
329 $result = '';
330 }
331
332 return $result;
333 }
334
339 public function getView($index = 0)
340 {
341 $result = '
342 <div class="adm-s-order-table-ddi">
343 <table class="adm-s-order-table-ddi-table" style="width: 100%;" id="'.$this->idPrefix.'sale_order_view_product_table">
344 <thead style="text-align: left;">
345 <tr>';
346
347 foreach($this->visibleColumns as $colId => $name)
348 {
349 $result .= "<td>".htmlspecialcharsbx($name)."</td>";
350 }
351
352 $result .= '</tr>
353 </thead>
354 <tbody style="border: 1px solid rgb(221, 221, 221);" id="'.$this->idPrefix.'sale-adm-order-basket-loading-row">
355 <tr>
356 <td colspan="'.(count($this->visibleColumns)+1).'" style="padding: 20px;">
357 <img src="/bitrix/images/sale/admin-loader.gif"/>
358 </td>
359 </tr>
360 </tbody>
361 <tbody style="border: 1px solid rgb(221, 221, 221); display:none;" id="'.$this->idPrefix.'sale-adm-order-edit-basket-empty-row">
362 <tr>
363 <td colspan="'.(count($this->visibleColumns)+1).'" style="padding: 20px;">
364 '.Loc::getMessage("SALE_ORDER_BASKET_EMPTY_ROW").'.
365 </td>
366 </tr>
367 </tbody>
368 </table>
369 </div>
370 <div class="adm-s-result-container">';
371
372 $result .= $this->getCouponsHtml(self::VIEW_MODE, false);
373 $result .= $this->getTotalHtml(false);
374 $result .= '
375 </div>
376 <div class="clb"></div>';
377
378 return $result;
379 }
380
387 public function getScripts($defTails = false)
388 {
389 if(!static::$jsInited)
390 {
391 \Bitrix\Main\Page\Asset::getInstance()->addJs("/bitrix/js/sale/admin/order_basket.js");
392 static::$jsInited = true;
393 }
394
395 $langPhrases = array("SALE_ORDER_BASKET_TURN", "SALE_ORDER_BASKET_EXPAND", "SALE_ORDER_BASKET_UP_RATIO",
396 "SALE_ORDER_BASKET_PROD_EDIT", "SALE_ORDER_BASKET_DOWN_RATIO", "SALE_ORDER_BASKET_PROD_COUNT",
397 "SALE_ORDER_BASKET_NO_PICTURE", "SALE_ORDER_BASKET_PROD_CREATE", "SALE_ORDER_BASKET_ROW_SETTINGS",
398 "SALE_ORDER_BASKET_PROD_MENU_EDIT", "SALE_ORDER_BASKET_PROD_MENU_DELETE", "SALE_ORDER_BASKET_BASE_CATALOG_PRICE",
399 "SALE_ORDER_BASKET_PROD_EDIT_ITEM_SAVE", "SALE_ORDER_BASKET_KG", "SALE_ORDER_BASKET_COUPON",
400 "SALE_ORDER_BASKET_COUPON_STATUS", "SALE_ORDER_BASKET_COUPON_APPLY", "SALE_ORDER_BASKET_COUPON_DELETE",
401 "SALE_ORDER_BASKET_POSITION_EXISTS", "SALE_ORDER_BASKET_ADD_COUPON_ERROR", "SALE_ORDER_BASKET_NO_NAME",
402 "SALE_ORDER_BASKET_PRODUCT_UNAVAILABLE"
403 );
404 $result = '<script type="text/javascript">';
405
406 foreach($langPhrases as $phrase)
407 $result .= ' BX.message({'.$phrase.': "'.\CUtil::jsEscape(Loc::getMessage($phrase)).'"});';
408
409 if(!$defTails)
410 $data = static::prepareData();
411
412 $totalPrices = OrderEdit::getTotalPrices($this->order, $this, false);
413 $weight = $this->order->getBasket() ? $this->order->getBasket()->getWeight() : 0;
414
415 if($this->mode == self::EDIT_MODE)
416 {
417
418 $result .= '
419 BX.ready(function(){
420 var obParams = {
421 tableId: "'.$this->idPrefix.'sale_order_edit_product_table",
422 idPrefix: "'.$this->idPrefix.'",
423 visibleColumns: '.\CUtil::phpToJSObject($this->visibleColumns).',
424 objName: "'.$this->jsObjName.'",
425 createProductBasement: '.($this->createProductBasement ? 'true' : 'false').',
426 columnsCount: '.count($this->visibleColumns).',
427 createBasketBottom: true,
428 isShowXmlId: '.($this->isShowXmlId ? 'true' : 'false').',
429 discounts: '.\CUtil::phpToJSObject(OrderEdit::getOrderedDiscounts($this->order, false)).',
430 mode: "edit",
431 unRemovableFields: ["PRICE", "QUANTITY"],
432 formatQuantity: "'.Option::get('sale', 'format_quantity', 'AUTO').'",
433 weightUnit: "'.$this->weightUnit.'",
434 '.$this->getTotalBlockFieldsJs($totalPrices, array("WEIGHT" => $weight)).'
435 };';
436
437 if(!$defTails)
438 {
439 $result .= '
440 obParams.productsOrder = '.\CUtil::phpToJSObject($data["ITEMS_ORDER"] ?? []).';
441 obParams.products = '.\CUtil::phpToJSObject($data["ITEMS"] ?? []).';
442 obParams.iblocksSkuParams = '.\CUtil::phpToJSObject($data["IBLOCKS_SKU_PARAMS"] ?? []).';
443 obParams.iblocksSkuParamsOrder = '.\CUtil::phpToJSObject($data["IBLOCKS_SKU_PARAMS_ORDER"] ?? []).';';
444 }
445
446 $result .=
447 $this->jsObjName.'= new BX.Sale.Admin.OrderBasketEdit(obParams);
448 BX.Sale.Admin.OrderEditPage.registerFieldsUpdaters( '.$this->jsObjName.'.getFieldsUpdaters() );
449 BX.Sale.Admin.OrderBasketCoupons.statusCouponApplyed = '.DiscountCouponsManager::STATUS_APPLYED.';
450 BX.Sale.Admin.OrderBasketCoupons.mode = BX.Sale.Admin.OrderBasketCoupons.MODES_LIST.'.($this->order->getId() > 0 ? 'EDIT' : 'CREATE').';
451 BX.Sale.Admin.OrderBasketCoupons.setCoupons('.
452 \CUtil::phpToJSObject(
453 OrderEdit::getCouponList($this->order, false)
454 ).
455 ');
456 });';
457
458 $result .= $this->settingsDialog->getScripts();
459 }
460 else
461 {
463
464 $result .= '
465 BX.ready(function(){
466 var obParams = {
467 tableId: "'.$this->idPrefix.'sale_order_view_product_table",
468 idPrefix: "'.$this->idPrefix.'",
469 visibleColumns: '.\CUtil::phpToJSObject($this->visibleColumns).',
470 objName: "'.$this->jsObjName.'",
471 createProductBasement: '.($this->createProductBasement ? 'true' : 'false').',
472 columnsCount: '.count($this->visibleColumns).',
473 isShowXmlId: '.($this->isShowXmlId ? 'true' : 'false').',
474 discounts: '.\CUtil::phpToJSObject(OrderEdit::getOrderedDiscounts($this->order, false)).',
475 createBasketBottom: true,
476 mode: "view",
477 showProps: '.($showProps ? 'true' : 'false').',
478 formatQuantity: "'.Option::get('sale', 'format_quantity', 'AUTO').'",
479 weightUnit: "'.$this->weightUnit.'",
480 '.$this->getTotalBlockFieldsJs($totalPrices, array("WEIGHT" => $weight)).'
481 };';
482
483 if(!$defTails)
484 {
485 $result .= '
486 obParams.productsOrder = '.\CUtil::phpToJSObject($data["ITEMS_ORDER"]).';
487 obParams.products = '.\CUtil::phpToJSObject($data["ITEMS"]).';
488 obParams.iblocksSkuParams = '.\CUtil::phpToJSObject($data["IBLOCKS_SKU_PARAMS"]).';
489 obParams.iblocksSkuParamsOrder = '.\CUtil::phpToJSObject($data["IBLOCKS_SKU_PARAMS_ORDER"]).';';
490 }
491
492 $result .=
493 $this->jsObjName.'= new BX.Sale.Admin.OrderBasket(obParams);
494 BX.Sale.Admin.OrderEditPage.registerFieldsUpdaters( '.$this->jsObjName.'.getFieldsUpdaters() );
495 BX.Sale.Admin.OrderBasketCoupons.mode = BX.Sale.Admin.OrderBasketCoupons.MODES_LIST.VIEW;
496 BX.Sale.Admin.OrderBasketCoupons.setCoupons('.
497 \CUtil::phpToJSObject(
498 OrderEdit::getCouponList($this->order, false)
499 ).
500 ');
501 });';
502
503 $result .= $this->settingsDialog->getScripts();
504 }
505
506 $result .= '</script>';
507 return $result;
508 }
509
510 protected function getTotalBlockFieldsJs($totalPrices, $data)
511 {
512 return '
513 totalBlockFields: {
514 PRICE_BASKET: {
515 id: "'.$this->idPrefix.'sale_order_edit_basket_price_basket",
516 value: "'.Sale\PriceMaths::roundByFormatCurrency($totalPrices["PRICE_BASKET"], $this->order->getCurrency()).'",
517 type: "currency"
518 },
519 PRICE_BASKET_DISCOUNTED: {
520 id: "'.$this->idPrefix.'sale_order_edit_basket_price_discount",
521 value: "'.Sale\PriceMaths::roundByFormatCurrency($totalPrices["PRICE_BASKET_DISCOUNTED"], $this->order->getCurrency()).'",
522 type: "currency"
523 },
524 PRICE_DELIVERY: {
525 id: "'.$this->idPrefix.'sale_order_edit_basket_price_delivery",
526 value: "'.Sale\PriceMaths::roundByFormatCurrency($totalPrices["PRICE_DELIVERY"], $this->order->getCurrency()).'",
527 type: "currency"
528 },
529 PRICE_DELIVERY_DISCOUNTED: {
530 id: "'.$this->idPrefix.'sale_order_edit_basket_price_delivery_discount",
531 value: "'.Sale\PriceMaths::roundByFormatCurrency($totalPrices["PRICE_DELIVERY_DISCOUNTED"], $this->order->getCurrency()).'",
532 type: "currency"
533 },
534 TAX_VALUE: {
535 id: "'.$this->idPrefix.'sale_order_edit_basket_tax",
536 value: "'.Sale\PriceMaths::roundByFormatCurrency($totalPrices["TAX_VALUE"], $this->order->getCurrency()).'",
537 type: "currency"
538 },
539 WEIGHT: {
540 id: "'.$this->idPrefix.'sale_order_edit_basket_weight",
541 value: "'.roundEx(floatval($data["WEIGHT"]), SALE_WEIGHT_PRECISION).'",
542 type: "weight"
543 },
544 SUM_PAID: {
545 id: "'.$this->idPrefix.'sale_order_edit_summ_paid",
546 value: "'.Sale\PriceMaths::roundByFormatCurrency($totalPrices["SUM_PAID"], $this->order->getCurrency()).'",
547 //edit: true,
548 type: "currency"
549 },
550 SUM_UNPAID: {
551 id: "'.$this->idPrefix.'sale_order_edit_basket_price_total",
552 value: "'.Sale\PriceMaths::roundByFormatCurrency($totalPrices["SUM_UNPAID"], $this->order->getCurrency()).'",
553 type: "currency"
554 }
555 }';
556 }
557
563 protected function getOffersIds($productId, array $products)
564 {
565 $result = array();
566
567 foreach($products as $product)
568 {
569 if($product['PRODUCT_ID'] == $productId && intval($product['OFFER_ID']) > 0)
570 {
571 $result[] = $product['OFFER_ID'];
572 }
573 }
574
575 return $result;
576 }
577
578 public function getOffersSkuParams(array $productsParams, array $visibleColumns = array())
579 {
580 return static::getOffersSkuParamsMode($productsParams, $visibleColumns, $this->mode);
581 }
582
590 public static function getOffersSkuParamsMode(array $productsParams, array $visibleColumns = array(), $mode = 0)
591 {
592 if(!empty($productsParams["ITEMS"]) && is_array($productsParams["ITEMS"]))
593 {
594 if (self::$catalogIncluded === null)
595 self::$catalogIncluded = Main\Loader::includeModule('catalog');
596 if (!self::$catalogIncluded)
597 return $productsParams;
598
599 $iblockPropsUsed = array();
600 $productIds = array();
601 $existOffers = array();
602 $skuFilter = array('ID' => array());
603 $propFilter = array('ID' => array());
604 $ibs = array();
605
606 foreach($productsParams["ITEMS"] as $params)
607 {
608 if($params['MODULE'] != 'catalog')
609 continue;
610
611 $productIds[] = $params['PRODUCT_ID'];
612
613 if ($mode == self::VIEW_MODE)
614 {
615 if ((int)$params['OFFER_ID'] > 0)
616 {
617 $skuFilter['ID'][] = $params['OFFER_ID'];
618 }
619 }
620
621 if (!isset($ibs[$params["IBLOCK_ID"]]))
622 {
623 $props = static::getSkuProps(true, $params["IBLOCK_ID"]);
624 if (!empty($props))
625 {
626 foreach($props as $prop)
627 {
628 $propFilter['ID'][] = $prop['ID'];
629 }
630 }
631
632 $ibs[$params["IBLOCK_ID"]] = true;
633 }
634
635 if($params["PRODUCT_ID"] != $params["OFFER_ID"])
636 $existOffers[] = $params["OFFER_ID"];
637 }
638
639 $skuFilter['ID'] = array_unique($skuFilter['ID']);
640 $productIds = array_unique($productIds);
641 $propFilter['ID'] = array_unique($propFilter['ID']);
642
643 $allOffers = \CCatalogSKU::getOffersList(
644 $productIds,
645 0,
646 $skuFilter,
647 array('NAME', "ACTIVE", 'CATALOG_QUANTITY'),
648 $propFilter
649 );
650
651 $tmpPropsOff = array();
652
653 if(!empty($allOffers))
654 $tmpPropsOff = static::getPropsFromOffers2($allOffers, $existOffers);
655
656 unset($skuFilter, $propFilter, $existOffers, $productIds);
657
658 foreach($productsParams["ITEMS"] as &$params)
659 {
660 if($params['MODULE'] != 'catalog')
661 continue;
662
663 if (!isset(self::$productsOffersSkuParams[$params["PRODUCT_ID"]]))
664 {
665 if(isset($tmpPropsOff[$params["PRODUCT_ID"]]))
666 {
667 self::$productsOffersSkuParams[$params["PRODUCT_ID"]] = $tmpPropsOff[$params["PRODUCT_ID"]];
668
669 foreach($tmpPropsOff[$params["PRODUCT_ID"]] as $offerId => $propsList)
670 {
671 foreach($propsList as $propId => $propValue)
672 {
673 if(!isset($iblockPropsUsed[$propId]))
674 $iblockPropsUsed[$propId] = array();
675
676 if(is_array($propValue))
677 {
678 $iblockPropsUsed[$propId] = array_merge(
679 $iblockPropsUsed[$propId],
680 array_diff(
681 $propValue,
682 $iblockPropsUsed[$propId]
683 )
684 );
685 }
686 else
687 {
688 if(!in_array($propValue, $iblockPropsUsed[$propId]))
689 $iblockPropsUsed[$propId][] = $propValue;
690 }
691 }
692 }
693 }
694 }
695 }
696
697 unset($allOffers, $tmpPropsOff);
698 $possibleSkuParams = array();
699
700 foreach($productsParams["ITEMS"] as &$params)
701 {
702 if($params['MODULE'] != 'catalog')
703 continue;
704
705 $possibleSku = array();
706
707 if(intval($params["OFFERS_IBLOCK_ID"]) > 0 && !isset(self::$iblockPropsParams[$params["OFFERS_IBLOCK_ID"]]))
708 {
709 self::$iblockPropsParams[$params["OFFERS_IBLOCK_ID"]] = static::getPropsParams(
710 $params["OFFERS_IBLOCK_ID"],
711 array(),
712 $iblockPropsUsed
713 );
714 }
715
716 if (!empty(self::$productsOffersSkuParams[$params["PRODUCT_ID"]][$params["OFFER_ID"]]))
717 {
718 $params["SKU_PROPS"] = self::$productsOffersSkuParams[$params["PRODUCT_ID"]][$params["OFFER_ID"]];
719 }
720
721 if (
722 isset($params["SKU_PROPS"])
723 && is_array($params["SKU_PROPS"])
724 )
725 {
726 foreach ($params["SKU_PROPS"] as $id => $skuProps)
727 {
728 if(is_array($skuProps))
729 {
730 unset($params["SKU_PROPS"][$id]);
731 continue;
732 }
733
734 $params["SKU_PROPS"][$id] = array(
735 'ID' => $skuProps,
736 'NAME' => self::$iblockPropsParams[$params["OFFERS_IBLOCK_ID"]][$id]['NAME'],
737 'VALUE' => self::$iblockPropsParams[$params["OFFERS_IBLOCK_ID"]][$id]['VALUES'][$skuProps],
738 'CODE' => self::$iblockPropsParams[$params["OFFERS_IBLOCK_ID"]][$id]['CODE'],
739 'SORT' => self::$iblockPropsParams[$params["OFFERS_IBLOCK_ID"]][$id]['SORT']
740 );
741
742 $possibleSku[$id] = self::$iblockPropsParams[$params["OFFERS_IBLOCK_ID"]][$id]['VALUES'][$skuProps]['ID'];
743 }
744 }
745
746 if($mode == self::EDIT_MODE && $params['PRODUCT_ID'] != $params['OFFER_ID'])
747 {
748 if(is_array(self::$iblockPropsParams[$params["OFFERS_IBLOCK_ID"]]))
749 $skuOrder = array_keys(self::$iblockPropsParams[$params["OFFERS_IBLOCK_ID"]]);
750 else
751 $skuOrder = array_keys($possibleSku);
752
753 $possibleSkuParams[$params['OFFER_ID']] = array(
754 'PRODUCT_ID' => $params['PRODUCT_ID'],
755 'OFFER_ID' => $params['OFFER_ID'],
756 'SKU_PROPS' => $possibleSku,
757 'SKU_ORDER' => $skuOrder
758 );
759 }
760 }
761
762 unset($params, $iblockPropsUsed);
763
764 if($mode == self::EDIT_MODE && !empty($possibleSkuParams))
765 {
766 $possibleSkuProps = Sale\Helpers\Admin\SkuProps::getPossibleSkuPropsValues($possibleSkuParams);
767
768 if(!empty($possibleSkuProps))
769 {
770 foreach($productsParams["ITEMS"] as $key => $params)
771 {
772 if($params['MODULE'] != 'catalog')
773 continue;
774
775 $productsParams["ITEMS"][$key]["SKU_PROPS_POSSIBLE_VALUES"] = $possibleSkuProps[$params['OFFER_ID']] ?? [];
776 }
777
778 unset($possibleSkuParams);
779 }
780 }
781
782 $productsParams["IBLOCKS_SKU_PARAMS"] = self::$iblockPropsParams;
783
784 foreach(self::$iblockPropsParams as $iBlockId => $props)
785 self::$iblockPropsParamsOrder[$iBlockId] = array_keys($props);
786 }
787
788 $productsParams["IBLOCKS_SKU_PARAMS_ORDER"] = self::$iblockPropsParamsOrder;
789 return $productsParams;
790 }
791
803 public static function getProductDetails($productId, $quantity, $userId, $siteId, array $columns = array())
804 {
805 $stored = true;
806 $result = OrderEdit::getProductDetails($productId, $userId, $siteId);
807
808 if($result === false)
809 $stored = false;
810
811 if($result === false)
812 {
813 if (self::$catalogIncluded === null)
814 self::$catalogIncluded = Main\Loader::includeModule('catalog');
815 if (!self::$catalogIncluded)
816 return array();
817
818 $result = self::getProductDataToFillBasket($productId, $quantity, $userId, $siteId, implode(",",array_keys($columns)));
819
820 static $proxyProductData = array();
821
822 if (!empty($proxyProductData[$productId]) && is_array($proxyProductData[$productId]))
823 {
824 $productInfo = $proxyProductData[$productId];
825 }
826 else
827 {
828 $productInfo = \CCatalogSku::getProductInfo($productId);
829 $proxyProductData[$productId] = $productInfo;
830 }
831
832 if($productInfo != false)
833 {
834 $result["OFFERS_IBLOCK_ID"] = $productInfo["OFFER_IBLOCK_ID"];
835 $result["IBLOCK_ID"] = $productInfo["IBLOCK_ID"];
836 $result["PRODUCT_ID"] = $productInfo["ID"];
837 }
838 else
839 {
840 $result["OFFERS_IBLOCK_ID"] = 0;
841 $result["IBLOCK_ID"] = $result["PRODUCT_PROPS_VALUES"]["IBLOCK_ID"];
842 $result["PRODUCT_ID"] = $result["PRODUCT_PROPS_VALUES"]["ID"];
843 }
844 }
845
846 if(!$stored)
847 OrderEdit::setProductDetails($productId, $userId, $siteId, $result);
848
849 return $result;
850 }
851
860 public static function getProductsData(array $productsIds, $siteId, array $fields = array(), $userId = 0)
861 {
862 if(empty($productsIds))
863 return array();
864
865 $result = array();
866
867 foreach($productsIds as $id)
868 {
869 $details = OrderEdit::getProductDetails($id, $userId, $siteId);
870
871 if($details !== false)
872 $result[$id] = $details;
873 }
874
875 $noCachedProductIds = array_diff($productsIds, array_keys($result));
876
877 if(!empty($noCachedProductIds))
878 {
879 $noCachedData = \Bitrix\Sale\Helpers\Admin\Product::getData($noCachedProductIds, $siteId, array_keys($fields));
880
881 foreach($noCachedData as $productId => $productData)
882 {
883 $result[$productId] = $productData;
884 OrderEdit::setProductDetails($productId, $userId, $siteId, $result[$productId]);
885 }
886
887 $emptyData = array_diff($productsIds, array_keys($result));
888
889 foreach($emptyData as $productId)
890 $result[$productId] = array();
891 }
892
893 return $result;
894 }
895
896 protected static function getPropsParams($iblockId, array $visibleColumns = array(), array $iblockPropsUsed = array())
897 {
898 $arRes = array();
899 $bUseHLIblock = \Bitrix\Main\Loader::includeModule('highloadblock');
900 $filter = array(
901 '=IBLOCK_ID' => intval($iblockId),
902 '=ACTIVE' => 'Y'
903 );
904
905 if(!empty($iblockPropsUsed))
906 {
907 $filter['ID'] = array_keys($iblockPropsUsed);
908 }
909
910 if(!empty($visibleColumns))
911 {
912 $iBlockProps = array();
913 $iBlockPropsInt = array();
914
915 foreach ($visibleColumns as $id => $name)
916 {
917 if (mb_substr($id, 0, 9) == "PROPERTY_")
918 {
919 $iblockPropCode = mb_substr($id, 9);
920
921 if($iblockPropCode <> '')
922 {
923 $iBlockProps[] = $iblockPropCode;
924
925 if(intval($iblockPropCode) > 0)
926 $iBlockPropsInt[] = intval($iblockPropCode);
927 }
928 }
929 }
930
931 if(!empty($iBlockProps) || !empty($iBlockPropsInt))
932 {
933 $codes = array('LOGIC' => 'OR');
934
935 if(!empty($iBlockProps))
936 $codes['=CODE'] = $iBlockProps;
937
938 if(!empty($iBlockPropsInt))
939 $codes['=ID'] = $iBlockPropsInt;
940
941 $filter[] = $codes;
942 }
943 }
944
945 $rsProps = \Bitrix\Iblock\PropertyTable::getList(array(
946 'filter' => $filter,
947 'order' => array('SORT' => 'ASC', 'ID' => 'ASC'),
948 ));
949
950 while ($arProp = $rsProps->fetch())
951 {
952 if(!empty($iblockPropsUsed) && !array_key_exists($arProp['ID'], $iblockPropsUsed))
953 continue;
954
955 if (
956 $arProp['PROPERTY_TYPE'] == 'L'
957 || $arProp['PROPERTY_TYPE'] == 'E'
958 || ($arProp['PROPERTY_TYPE'] == 'S' && $arProp['USER_TYPE'] == 'directory')
959 )
960 {
961 if ($arProp['XML_ID'] == 'CML2_LINK')
962 continue;
963
964 $arValues = array();
965
966 if ($arProp['PROPERTY_TYPE'] == 'L')
967 {
968 $arValues = array();
969 $rsPropEnums = \CIBlockProperty::getPropertyEnum($arProp['ID']);
970 while ($arEnum = $rsPropEnums->fetch())
971 {
972 $arValues[$arEnum['VALUE']] = array(
973 'ID' => $arEnum['ID'],
974 'NAME' => $arEnum['VALUE'],
975 'PICT' => false
976 );
977 }
978 }
979 elseif ($arProp['PROPERTY_TYPE'] == 'E')
980 {
981 $eFilter = array('IBLOCK_ID' => $arProp['LINK_IBLOCK_ID'], 'ACTIVE' => 'Y');
982
983 if(!empty($iblockPropsUsed[$arProp['ID']]))
984 $eFilter['ID'] = $iblockPropsUsed[$arProp['ID']];
985 else
986 continue;
987
988 $rsPropEnums = \CIBlockElement::getList(
989 array('SORT' => 'ASC'),
990 $eFilter,
991 false,
992 false,
993 array('ID', 'NAME', 'PREVIEW_PICTURE', 'SORT')
994 );
995
996 while ($arEnum = $rsPropEnums->Fetch())
997 {
998 $arEnum['PREVIEW_PICTURE'] = \CFile::getFileArray($arEnum['PREVIEW_PICTURE']);
999
1000 if (!is_array($arEnum['PREVIEW_PICTURE']))
1001 {
1002 $arEnum['PREVIEW_PICTURE'] = false;
1003 }
1004
1005 if ($arEnum['PREVIEW_PICTURE'] !== false)
1006 {
1007 $productImg = \CFile::resizeImageGet($arEnum['PREVIEW_PICTURE'], array('width'=>80, 'height'=>80), BX_RESIZE_IMAGE_PROPORTIONAL, false, false);
1008 $arEnum['PREVIEW_PICTURE'] = $productImg['src'];
1009 }
1010
1011 $arValues[$arEnum['ID']] = array(
1012 'ID' => $arEnum['ID'],
1013 'NAME' => $arEnum['NAME'],
1014 'SORT' => $arEnum['SORT'],
1015 'PICT' => $arEnum['PREVIEW_PICTURE']
1016 );
1017 }
1018 }
1019 elseif ($arProp['PROPERTY_TYPE'] == 'S' && $arProp['USER_TYPE'] == 'directory')
1020 {
1021 if ($bUseHLIblock)
1022 {
1023 if(!is_array($arProp["USER_TYPE_SETTINGS"]))
1024 $arProp["USER_TYPE_SETTINGS"] = unserialize($arProp["USER_TYPE_SETTINGS"], ['allowed_classes' => false]);
1025
1026 $hlblock = HL\HighloadBlockTable::getList(array("filter" => array("TABLE_NAME" => $arProp["USER_TYPE_SETTINGS"]["TABLE_NAME"])))->fetch();
1027 if ($hlblock)
1028 {
1029 $entity = HL\HighloadBlockTable::compileEntity($hlblock);
1030 $entityDataClass = $entity->getDataClass();
1031 $rsData = $entityDataClass::getList();
1032
1033 while ($arData = $rsData->fetch())
1034 {
1035 $arValues[$arData['UF_XML_ID']] = array(
1036 'ID' => $arData['UF_XML_ID'],
1037 'NAME' => $arData['UF_NAME'],
1038 'SORT' => $arData['UF_SORT'],
1039 'FILE' => $arData['UF_FILE'],
1040 'PICT' => '',
1041 'XML_ID' => $arData['UF_XML_ID']
1042 );
1043 }
1044
1045 }
1046 }
1047 }
1048
1049 if (
1050 isset($iblockPropsUsed[$arProp['ID']])
1051 && is_array($iblockPropsUsed[$arProp['ID']])
1052 && !empty($arValues)
1053 && is_array($arValues)
1054 )
1055 {
1056 //if property value deleted or inactive
1057 $notFound = array_diff($iblockPropsUsed[$arProp['ID']], array_keys($arValues));
1058
1059 //if Empty values exist
1060 if((is_array($iblockPropsUsed[$arProp['ID']]) && in_array("-", $iblockPropsUsed[$arProp['ID']])) || (is_array($notFound) && !empty($notFound)))
1061 {
1062 $arValues["-"] = array(
1063 "ID" => "-",
1064 "NAME" => "-"
1065 );
1066 }
1067
1068 $arRes[$arProp['ID']] = array(
1069 'ID' => $arProp['ID'],
1070 'CODE' => $arProp['CODE'],
1071 'NAME' => $arProp['NAME'],
1072 'TYPE' => $arProp['PROPERTY_TYPE'],
1073 'ORDER' => array_keys($arValues),
1074 'VALUES' => $arValues,
1075 'SORT' => $arProp['SORT']
1076 );
1077 }
1078 }
1079
1080 if (
1081 $arProp['PROPERTY_TYPE'] == "S"
1082 && $arProp['USER_TYPE'] == 'directory'
1083 && isset($arRes[$arProp['ID']]['VALUES'])
1084 && is_array($arRes[$arProp['ID']]['VALUES'])
1085 )
1086 {
1087 foreach($arRes[$arProp['ID']]['VALUES'] as $id => $value)
1088 {
1089 if (isset($value["FILE"]))
1090 {
1091 $arTmpFile = \CFile::getFileArray($value["FILE"]);
1092 $tmpImg = \CFile::resizeImageGet(
1093 $arTmpFile,
1094 [
1095 'width' => 20,
1096 'height' => 20,
1097 ],
1098 BX_RESIZE_IMAGE_PROPORTIONAL,
1099 false,
1100 false
1101 );
1102 $arRes[$arProp['ID']]['VALUES'][$id]['PICT'] = $tmpImg['src'];
1103 }
1104 }
1105 }
1106 }
1107
1108 return $arRes;
1109 }
1110
1111 protected static function getPropsFromOffers2(array $items, array $existOffers)
1112 {
1113 $props = array();
1114 $notEmptyProps = array();
1115 $allProps = array();
1116
1117 foreach($items as $id => $item)
1118 {
1119 if(!isset($props[$id]))
1120 $props[$id] = array();
1121
1122 foreach($item as $offerId => $offer)
1123 {
1124 if(!isset($offer["PROPERTIES"]))
1125 continue;
1126
1127 if(!in_array($offerId, $existOffers) && $offer["ACTIVE"] != "Y")
1128 continue;
1129
1130 if(!isset($props[$id][$offerId]))
1131 $props[$id][$offerId] = array();
1132
1133 foreach($offer["PROPERTIES"] as $propCode => $propParams)
1134 {
1135 if($propParams["MULTIPLE"] == "Y")
1136 continue;
1137
1138 if($propParams["ACTIVE"] != "Y")
1139 continue;
1140
1141 if($propParams['PROPERTY_TYPE'] == 'L'
1142 || $propParams['PROPERTY_TYPE'] == 'E'
1143 || (
1144 $propParams['PROPERTY_TYPE'] == 'S'
1145 && $propParams['USER_TYPE'] == 'directory'
1146 )
1147 )
1148 {
1149 if(!in_array($propParams["ID"], $allProps))
1150 $allProps[] = $propParams["ID"];
1151
1152 if($propParams["~VALUE"] <> '')
1153 {
1154 $props[$id][$offerId][$propParams["ID"]] = $propParams["~VALUE"];
1155
1156 if(!in_array($propParams["ID"], $notEmptyProps))
1157 $notEmptyProps[] = $propParams["ID"];
1158 }
1159 else
1160 {
1161 $props[$id][$offerId][$propParams["ID"]] = "-";
1162 }
1163 }
1164 }
1165 }
1166 }
1167
1168 $emptyProps = array_diff($allProps, $notEmptyProps);
1169
1170 if(!empty($emptyProps))
1171 {
1172 foreach($emptyProps as $propId)
1173 {
1174 foreach($props as $prodId => $offers)
1175 {
1176 foreach($offers as $offerId => $offerProps)
1177 {
1178 unset($props[$prodId][$offerId][$propId]);
1179 }
1180 }
1181 }
1182 }
1183
1184 return $props;
1185 }
1186
1187 protected static function getSkuProps($flagAll, $iblockId)
1188 {
1189 if (!isset(static::$arSkuProps[$iblockId]))
1190 {
1191 $arCatalog = static::getOffersCatalog($iblockId);
1192 static::$arSkuProps[$iblockId] = $arCatalog? static::getPropsList($arCatalog["IBLOCK_ID"], $arCatalog['SKU_PROPERTY_ID']) : array();
1193 }
1194 return $flagAll? static::$arSkuProps[$iblockId] : static::filterProps(static::$arSkuProps[$iblockId]);
1195 }
1196
1197 protected static function getOffersCatalog($iblockId)
1198 {
1199 if (self::$catalogIncluded === null)
1200 self::$catalogIncluded = Main\Loader::includeModule('catalog');
1201 if (!self::$catalogIncluded)
1202 return array();
1203
1204 if (!isset(static::$offersCatalog[$iblockId]))
1205 static::$offersCatalog[$iblockId] = \CCatalogSKU::getInfoByProductIBlock($iblockId);
1206
1207 return static::$offersCatalog[$iblockId];
1208 }
1209
1210 protected static function getPropsList($iblockId, $skuPropertyId = 0)
1211 {
1212 if (self::$catalogIncluded === null)
1213 self::$catalogIncluded = Main\Loader::includeModule('catalog');
1214 if (!self::$catalogIncluded)
1215 return [];
1216
1217 $propertyIds = Catalog\Product\PropertyCatalogFeature::getOfferTreePropertyCodes($iblockId);
1218 if ($propertyIds === null)
1219 return [];
1220 $arResult = [];
1221 $filter = array(
1222 '@ID' => $propertyIds,
1223 '=IBLOCK_ID' => $iblockId,
1224 );
1225 if ($skuPropertyId > 0)
1226 $filter['!=ID'] = $skuPropertyId;
1227 $iterator = Iblock\PropertyTable::getList(array(
1228 'select' => array('*'),
1229 'filter' => $filter,
1230 'order' => array(
1231 'SORT' => 'ASC',
1232 'NAME' => 'ASC'
1233 )
1234 ));
1235 while ($row = $iterator->fetch())
1236 {
1237 $row['USER_TYPE'] = (string)$row['USER_TYPE'];
1238 $row['~NAME'] = $row['NAME'];
1239 $row['NAME'] = htmlspecialcharsEx($row['NAME']);
1240 $row['PROPERTY_USER_TYPE'] = ($row['USER_TYPE'] != '' ? \CIBlockProperty::getUserType($row['USER_TYPE']) : array());
1241 $arResult[] = $row;
1242 }
1243 unset($row, $iterator);
1244
1245 return $arResult;
1246 }
1247
1248 protected static function filterProps(&$props)
1249 {
1250 $result = array();
1251 if ($props)
1252 {
1253 foreach ($props AS $prop)
1254 {
1255 if ($prop['FILTRABLE'] == 'Y' && $prop['PROPERTY_TYPE'] != 'F')
1256 $result[] = $prop;
1257 }
1258 }
1259 return $result;
1260 }
1261
1263 {
1264 return $this->settingsDialog->getHtml();
1265 }
1266
1267 public static function loadVisibleColumns($idPrefix)
1268 {
1269 return \CUserOptions::GetOption($idPrefix."order_basket_table", "table_columns");
1270 }
1271
1272 protected static function getDefaultVisibleColumns()
1273 {
1274 return array(
1275 "IMAGE" => Loc::getMessage("SALE_ORDER_BASKET_SETTINGS_COL_IMAGE"),
1276 "NAME" => Loc::getMessage("SALE_ORDER_BASKET_SETTINGS_COL_NAME"),
1277 "QUANTITY" => Loc::getMessage("SALE_ORDER_BASKET_SETTINGS_COL_QUANTITY"),
1278 "AVAILABLE" => Loc::getMessage("SALE_ORDER_BASKET_SETTINGS_COL_AVAILABLE"),
1279 "PROPS" => Loc::getMessage("SALE_ORDER_BASKET_SETTINGS_COL_PROPS"),
1280 "PRICE" => Loc::getMessage("SALE_ORDER_BASKET_SETTINGS_COL_PRICE"),
1281 "SUM" => Loc::getMessage("SALE_ORDER_BASKET_SETTINGS_COL_SUM")
1282 );
1283 }
1284
1285 protected function getVisibleColumns($idPrefix)
1286 {
1287 if (self::$iblockIncluded === null)
1288 self::$iblockIncluded = Main\Loader::includeModule('iblock');
1289 if (!self::$iblockIncluded)
1290 return array();
1291
1292 $result = array();
1293 $arTmpColumns = array();
1294 $arColumnsOptions = static::loadVisibleColumns($idPrefix);
1295
1296 if (is_array($arColumnsOptions) && isset($arColumnsOptions["columns"]) && $arColumnsOptions["columns"] <> '')
1297 $arTmpColumns = explode(",", $arColumnsOptions["columns"]);
1298
1299 if(is_array($arTmpColumns) && !empty($arTmpColumns))
1300 {
1301 $iBlockProps = array();
1302 $iBlockPropsInt = array();
1303
1304 foreach ($arTmpColumns as $id => $columnCode)
1305 {
1306 if (mb_substr($columnCode, 0, 9) == "PROPERTY_")
1307 {
1308 $iblockPropCode = mb_substr($columnCode, 9);
1309
1310 if($iblockPropCode <> '')
1311 {
1312 $iBlockProps[] = $iblockPropCode;
1313
1314 if(intval($iblockPropCode) > 0)
1315 $iBlockPropsInt[] = intval($iblockPropCode);
1316
1317 $result[$columnCode] = "";
1318 }
1319 }
1320 else
1321 {
1322 $result[$columnCode] = Loc::getMessage("SALE_ORDER_BASKET_SETTINGS_COL_".$columnCode);
1323 }
1324 }
1325
1326 if(!empty($iBlockProps))
1327 {
1328 $dbRes = \Bitrix\Iblock\PropertyTable::getList(array(
1329 'filter' => array(
1330 'LOGIC' => 'OR',
1331 '=CODE' => $iBlockProps,
1332 '=ID' => $iBlockPropsInt
1333 ),
1334 'select' => array('ID', 'NAME', 'CODE')
1335 ));
1336
1337 while($arPropData = $dbRes->fetch())
1338 {
1339 if($arPropData['CODE'] <> '')
1340 $result["PROPERTY_".$arPropData['CODE']] = $arPropData["NAME"];
1341 else
1342 $result["PROPERTY_".$arPropData['ID']] = $arPropData["NAME"];
1343 }
1344 }
1345 }
1346 else
1347 {
1348 $result = static::getDefaultVisibleColumns();
1349 }
1350
1351 return $result;
1352 }
1353
1354 public static function getProductEditDialogHtml($currency, $objName)
1355 {
1356 return '
1357 <input id="FORM_BASKET_PRODUCT_ID" name="BASKET_PRODUCT_ID" value="" type="hidden">
1358 <input id="FORM_PROD_BASKET_CUSTOM_PRICE" name="BASKET_CUSTOM_PRICE" value="Y" type="hidden">
1359 <input id="FORM_PROD_BASKET_BASKET_CODE" name="FORM_PROD_BASKET_BASKET_CODE" value="" type="hidden">
1360 <table class="edit-table">
1361 <tr>
1362 <td width="40%">&nbsp;</td>
1363 <td align="left" width="60%">
1364 <div id="basketError" style="display:none;">
1365 <table class="message message-error" border="0" cellpadding="0" cellspacing="0" style="border:2px solid #FF0000;color:#FF0000">
1366 <tr>
1367 <td>
1368 <table class="content" border="0" cellpadding="0" cellspacing="0" style="margin:4px;">
1369 <tr>
1370 <td valign="top"><div class="icon-error"></div></td>
1371 <td>
1372 <span class="message-title" style="font-weight:bold;">'.Loc::getMessage("SALE_ORDER_BASKET_PROD_EDIT_ERROR").'</span><br>
1373 <div class="empty" style="height: 5px;"></div><div id="basketErrorText"></div>
1374 </td>
1375 </tr>
1376 </table>
1377 </td>
1378 </tr>
1379 </table>
1380 </div></td>
1381 </tr>
1382 <tr id="FORM_NEWPROD_CODE">
1383 <td class="adm-detail-content-cell-l" width="30%">'.Loc::getMessage("SALE_ORDER_BASKET_PROD_EDIT_ITEM_ID").':</td>
1384 <td width="70%"><input size="10" id="FORM_PROD_BASKET_OFFER_ID" name="FORM_PROD_BASKET_OFFER_ID" type="text" value="" tabindex="1"></td>
1385 </tr>
1386 <tr class="adm-detail-required-field">
1387 <td class="adm-detail-content-cell-l">'.Loc::getMessage("SALE_ORDER_BASKET_PROD_EDIT_ITEM_NAME").':</td>
1388 <td><input size="40" id="FORM_PROD_BASKET_NAME" name="FORM_PROD_BASKET_NAME" type="text" value="" tabindex="2" onkeyup="'.$objName.'.productEditDialog.disableButton();"></td>
1389 </tr>
1390 <tr>
1391 <td class="adm-detail-content-cell-l">'.Loc::getMessage("SALE_ORDER_BASKET_PROD_EDIT_ITEM_PATH").':</td>
1392 <td><input id="FORM_PROD_BASKET_DETAIL_PAGE_URL" name="FORM_PROD_BASKET_DETAIL_PAGE_URL" value="" size="40" type="text" tabindex="3"></td>
1393 </tr>
1394 <tr>
1395 <td class="adm-detail-content-cell-l">'.Loc::getMessage("SALE_ORDER_BASKET_PROD_EDIT_ITEM_CATALOG_XML").':</td>
1396 <td><input id="FORM_PROD_BASKET_CATALOG_XML_ID" name="FORM_PROD_BASKET_CATALOG_XML_ID" value="" size="40" type="text" tabindex="4"></td>
1397 </tr>
1398 <tr>
1399 <td class="adm-detail-content-cell-l">'.Loc::getMessage("SALE_ORDER_BASKET_PROD_EDIT_ITEM_PRODUCT_XML").':</td>
1400 <td><input id="FORM_PROD_BASKET_PRODUCT_XML_ID" name="FORM_PROD_BASKET_PRODUCT_XML_ID" value="" size="40" type="text" tabindex="5"></td>
1401 </tr>
1402 <tr>
1403 <td class="adm-detail-content-cell-l">'.Loc::getMessage("SALE_ORDER_BASKET_PROD_EDIT_ITEM_NOTES").':</td>
1404 <td><input name="FORM_PROD_BASKET_NOTES" id="FORM_PROD_BASKET_NOTES" size="40" maxlength="250" value="" type="text" tabindex="6"></td>
1405 </tr>
1406 <tr>
1407 <td class="adm-detail-content-cell-l" valign="top" width="40%">'.Loc::getMessage("SALE_ORDER_BASKET_PROD_EDIT_ITEM_PROPS").':</td>
1408 <td width="60%">
1409 <table id="BASKET_PROP_TABLE" class="internal" border="0" cellpadding="3" cellspacing="1" style="width: 521px; margin-top: 20px;">
1410 <tr class="heading" style="border-collapse:collapse;background-color:#E7EAF5;color:#525355;">
1411 <td align="center">'.Loc::getMessage("SALE_ORDER_BASKET_PROD_EDIT_ITEM_IP_NAME").'</td>
1412 <td align="center">'.Loc::getMessage("SALE_ORDER_BASKET_PROD_EDIT_ITEM_IP_VALUE").'</td>
1413 <td align="center">'.Loc::getMessage("SALE_ORDER_BASKET_PROD_EDIT_ITEM_IP_CODE").'</td>
1414 <td align="center">'.Loc::getMessage("SALE_ORDER_BASKET_PROD_EDIT_ITEM_IP_SORT").'</td>
1415 </tr>
1416 <tr id="FORM_PROD_BASKET_EMPTY_PROP_ROW">
1417 <td colspan="4" style="text-align: center;">
1418 '.Loc::getMessage("SALE_ORDER_BASKET_PROD_EDIT_EMPTY_PROP_ROW").'
1419 </td>
1420 </tr>
1421 </table>
1422 <div width="100%" style="text-align: right;">
1423 <input value="'.Loc::getMessage("SALE_ORDER_BASKET_PROD_EDIT_ITEM_PROPERTY_MORE").'" onclick="'.$objName.'.productEditDialog.addPropRow();" type="button" style="margin-top: 10px;">
1424 </div>
1425 </td>
1426 </tr>
1427 <tr class="adm-detail-required-field">
1428 <td class="adm-detail-content-cell-l">'.Loc::getMessage("SALE_ORDER_BASKET_PROD_EDIT_ITEM_QUANTITY").':</td>
1429 <td>
1430 <input name="FORM_PROD_BASKET_QUANTITY" id="FORM_PROD_BASKET_QUANTITY" size="10" maxlength="20" value="" type="text" tabindex="7" onkeyup="'.$objName.'.productEditDialog.disableButton();">&nbsp;
1432 'FORM_PROD_BASKET_MEASURE_CODE',
1433 self::getCatalogMeasures(),
1434 '',
1435 true,
1436 array(
1437 'id' => 'FORM_PROD_BASKET_MEASURE_CODE',
1438 'onchange' => $objName.'.productEditDialog.setMeasureText();'
1439 )
1440 ).'
1441 <input name="FORM_PROD_BASKET_MEASURE_TEXT" id="FORM_PROD_BASKET_MEASURE_TEXT" type="hidden" value="">
1442 </td>
1443 </tr>
1444 <tr class="adm-detail-required-field">
1445 <td class="adm-detail-content-cell-l">'.Loc::getMessage("SALE_ORDER_BASKET_PROD_EDIT_ITEM_PRICE").':</td>
1446 <td><input name="FORM_PROD_BASKET_PRICE" id="FORM_PROD_BASKET_PRICE" size="10" maxlength="20" value="" type="text" tabindex="8" onkeyup="'.$objName.'.productEditDialog.disableButton();"> ('.\CUtil::JSEscape($currency).')</td>
1447 </tr>
1448 <tr>
1449 <td class="adm-detail-content-cell-l">'.Loc::getMessage("SALE_ORDER_BASKET_PROD_EDIT_ITEM_WEIGHT").':</td>
1450 <td><input name="FORM_PROD_BASKET_WEIGHT" id="FORM_PROD_BASKET_WEIGHT" size="10" maxlength="20" value="" type="text" tabindex="9"> ('.Loc::getMessage("SALE_ORDER_BASKET_PROD_EDIT_ITEM_GRAMM").')</td>
1451 </tr>
1452 </table>';
1453 }
1454
1455 public static function getCatalogMeasures()
1456 {
1457 return \Bitrix\Sale\Helpers\Order\Builder\BasketBuilder::getCatalogMeasures();
1458 }
1459
1460 public static function getDefaultMeasures()
1461 {
1462 return \CCatalogMeasure::getDefaultMeasure(true, true);
1463 }
1464
1476 public static function getProductDataToFillBasket($productId, $quantity, $userId, $LID, $userColumns, $tmpId = "")
1477 {
1478 $isSetItem = $tmpId != "";
1479
1480 if (self::$catalogIncluded === null)
1481 self::$catalogIncluded = Main\Loader::includeModule('catalog');
1482 if (!self::$catalogIncluded)
1483 return array();
1484
1485 $arParams = array();
1486
1487 static $proxyIblockElement = array();
1488 static $proxyCatalogMeasure = array();
1489 static $proxyParent = array();
1490 static $proxyIblockProperty = array();
1491 static $proxyProductData = array();
1492 static $proxyCatalogProduct = array();
1493 static $proxyCatalogMeasureRatio = array();
1494
1495 $productId = (int)$productId;
1496 if ($productId <= 0)
1497 {
1498 return $arParams;
1499 }
1500
1501 if (!empty($proxyIblockElement[$productId]))
1502 {
1503 $iblockId = $proxyIblockElement[$productId];
1504 }
1505 else
1506 {
1507 $iblockId = (int)\CIBlockElement::getIBlockByID($productId);
1508
1509 if ($iblockId > 0)
1510 $proxyIblockElement[$productId] = $iblockId;
1511 }
1512
1513 if ($iblockId <= 0)
1514 {
1515 return $arParams;
1516 }
1517
1518 $arSku2Parent = array();
1519 $arElementId = array();
1520
1521 $arElementId[] = $productId;
1522
1523 $proxyParentKey = $productId."|".$iblockId;
1524
1525 if (!empty($proxyParent[$proxyParentKey]) && is_array($proxyParent[$proxyParentKey]))
1526 {
1527 $arParent = $proxyParent[$proxyParentKey];
1528 }
1529 else
1530 {
1531 $arParent = \CCatalogSku::getProductInfo($productId, $iblockId);
1532 $proxyParent[$proxyParentKey] = $arParent;
1533 }
1534
1535
1536 if ($arParent)
1537 {
1538 $arElementId[] = $arParent["ID"];
1539 $arSku2Parent[$productId] = $arParent["ID"];
1540 }
1541
1542 $arPropertyInfo = array();
1543 $userColumns = (string)$userColumns;
1544 $arUserColumns = ($userColumns != '') ? explode(",", $userColumns) : array();
1545 foreach ($arUserColumns as $key => $column)
1546 {
1547 $column = mb_strtoupper($column);
1548 if (strncmp($column, 'PROPERTY_', 9) != 0)
1549 {
1550 unset($arUserColumns[$key]);
1551 }
1552 else
1553 {
1554 $propertyCode = mb_substr($column, 9);
1555 if ($propertyCode == '')
1556 {
1557 unset($arUserColumns[$key]);
1558 continue;
1559 }
1560
1561 if (!empty($proxyIblockProperty[$propertyCode]) && is_array($proxyIblockProperty[$propertyCode]))
1562 {
1563 $arPropertyInfo[$column] = $proxyIblockProperty[$propertyCode];
1564 }
1565 else
1566 {
1567 $dbres = \CIBlockProperty::getList(array(), array("CODE" => $propertyCode));
1568 if ($arPropData = $dbres->getNext())
1569 {
1570 $arPropertyInfo[$column] = $arPropData;
1571 $proxyIblockProperty[$propertyCode] = $arPropData;
1572 }
1573 }
1574
1575 }
1576 }
1577
1578 $arSelect = array_merge(
1579 [
1580 "ID",
1581 "NAME",
1582 "IBLOCK_ID",
1583 "IBLOCK_SECTION_ID",
1584 "DETAIL_PICTURE",
1585 "PREVIEW_PICTURE",
1586 "XML_ID",
1587 "IBLOCK_EXTERNAL_ID",
1588 "DETAIL_PAGE_URL",
1589 ],
1590 $arUserColumns
1591 );
1592
1593 $proxyProductDataKey = md5(join('|', $arElementId)."_".join('|', $arSelect));
1594 if (!empty($proxyProductData[$proxyProductDataKey]) && is_array($proxyProductData[$proxyProductDataKey]))
1595 {
1596 $arProductData = $proxyProductData[$proxyProductDataKey];
1597 }
1598 else
1599 {
1600 $arProductData = getProductProps($arElementId, $arSelect);
1601 $proxyProductData[$proxyProductDataKey] = $arProductData;
1602 }
1603
1604 $defaultMeasure = \CCatalogMeasure::getDefaultMeasure(true, true);
1605
1606 if (!empty($arProductData))
1607 {
1608 $arElementInfo = array();
1609 foreach ($arProductData as $elemId => &$arElement)
1610 {
1611 foreach ($arElement as $key => $value)
1612 {
1613 if (strncmp($key, 'PROPERTY_', 9) == 0 && mb_substr($key, -6) == "_VALUE")
1614 {
1615 $columnCode = str_replace("_VALUE", "", $key);
1616 if (!isset($arPropertyInfo[$columnCode]))
1617 continue;
1618 $keyResult = 'PROPERTY_'.$arPropertyInfo[$columnCode]['CODE'].'_VALUE';
1619 $arElement[$key] = getIblockPropInfo($value, $arPropertyInfo[$columnCode], array("WIDTH" => 90, "HEIGHT" => 90));
1620 if ($keyResult != $key)
1621 $arElement[$keyResult] = $arElement[$key];
1622 unset($keyResult);
1623 }
1624 }
1625 }
1626 unset($arElement);
1627
1628 if (isset($arProductData[$productId]))
1629 $arElementInfo = $arProductData[$productId];
1630
1631 if (isset( $arSku2Parent[$productId]))
1632 $arParent = $arProductData[$arSku2Parent[$productId]];
1633
1634 if (!empty($arSku2Parent)) // if sku element doesn't have value of some property - we'll show parent element value instead
1635 {
1636 foreach ($arUserColumns as $field)
1637 {
1638 $fieldVal = $field."_VALUE";
1639 $parentId = $arSku2Parent[$productId];
1640
1641 if ((!isset($arElementInfo[$fieldVal]) || (isset($arElementInfo[$fieldVal]) && $arElementInfo[$fieldVal] == ''))
1642 && (isset($arProductData[$parentId][$fieldVal]) && !empty($arProductData[$parentId][$fieldVal]))) // can be array or string
1643 {
1644 $arElementInfo[$fieldVal] = $arProductData[$parentId][$fieldVal];
1645 }
1646 }
1647 if (mb_strpos($arElementInfo["~XML_ID"], '#') === false)
1648 {
1649 $arElementInfo["~XML_ID"] = $arParent['~XML_ID'].'#'.$arElementInfo["~XML_ID"];
1650 }
1651 }
1652
1653 $arElementInfo["MODULE"] = "catalog";
1654 $arElementInfo["PRODUCT_PROVIDER_CLASS"] = "CCatalogProductProvider";
1655
1656 $arElementInfo["PRODUCT_ID"] = $arElementInfo["ID"];
1657 if ($arElementInfo["IBLOCK_ID"] > 0)
1658 {
1659 $arElementInfo["EDIT_PAGE_URL"] = \CIBlock::GetAdminElementEditLink($arElementInfo["IBLOCK_ID"], $arElementInfo["PRODUCT_ID"], array(
1660 "find_section_section" => $arElementInfo["IBLOCK_SECTION_ID"],
1661 'WF' => 'Y',
1662 ));
1663 }
1664
1665 static $buyersGroups = array();
1666
1667 if(empty($buyersGroups[$userId]))
1668 $buyersGroups[$userId] = \CUser::getUserGroup($userId);
1669
1670 $arBuyerGroups = $buyersGroups[$userId];
1671
1672 // price
1673 Catalog\Product\Price\Calculation::pushConfig();
1674 Catalog\Product\Price\Calculation::setConfig(array(
1675 'CURRENCY' => Sale\Internals\SiteCurrencyTable::getSiteCurrency($LID),
1676 'PRECISION' => (int)Main\Config\Option::get('sale', 'value_precision'),
1677 'USE_DISCOUNTS' => !$isSetItem,
1678 'RESULT_WITH_VAT' => true
1679 ));
1680 $arPrice = \CCatalogProduct::getOptimalPrice($arElementInfo["ID"], 1, $arBuyerGroups, "N", array(), $LID);
1681 Catalog\Product\Price\Calculation::popConfig();
1682 $priceType = GetCatalogGroup($arPrice["PRICE"]["CATALOG_GROUP_ID"]);
1683
1684 $currentPrice = $arPrice['RESULT_PRICE']['DISCOUNT_PRICE'];
1685 $arElementInfo['PRICE'] = $currentPrice;
1686 $arElementInfo['CURRENCY'] = $arPrice['RESULT_PRICE']['CURRENCY'];
1687 $currentTotalPrice = $arPrice['RESULT_PRICE']['BASE_PRICE'];
1688
1689 if (!empty($proxyCatalogProduct[$productId]) && is_array($proxyCatalogProduct[$productId]))
1690 {
1691 $arProduct = $proxyCatalogProduct[$productId];
1692 }
1693 else
1694 {
1695 $rsProducts = Catalog\ProductTable::getList([
1696 'select' => ['ID', 'QUANTITY', 'WEIGHT', 'MEASURE', 'TYPE', 'BARCODE_MULTI', 'WIDTH', 'LENGTH', 'HEIGHT'],
1697 'filter' => ['=ID' => $productId]
1698 ]);
1699 if ($arProduct = $rsProducts->fetch())
1700 {
1701 $proxyCatalogProduct[$productId] = $arProduct;
1702 }
1703 unset($rsProducts);
1704 }
1705
1706 if (empty($arProduct) || !is_array($arProduct))
1707 {
1708 return array();
1709 }
1710
1711 $balance = floatval($arProduct["QUANTITY"]);
1712
1713 // sku props
1714 $arSkuData = array();
1715
1716 static $proxySkuProperty = array();
1717
1718 if (!empty($proxySkuProperty[$productId]) && is_array($proxySkuProperty[$productId]))
1719 {
1720 $arSkuProperty = $proxySkuProperty[$productId];
1721 }
1722 else
1723 {
1724 $arSkuProperty = \CSaleProduct::GetProductSkuProps($productId, '', true);
1725 $proxySkuProperty[$productId] = $arSkuProperty;
1726 }
1727
1728 if (!empty($arSkuProperty))
1729 {
1730 foreach ($arSkuProperty as &$val)
1731 {
1732 $arSkuData[] = array(
1733 'NAME' => htmlspecialcharsback($val['NAME']),
1734 'VALUE' => htmlspecialcharsback($val['VALUE']),
1735 'CODE' => htmlspecialcharsback($val['CODE'])
1736 );
1737 }
1738 unset($val);
1739 }
1740
1741 if($arElementInfo["~IBLOCK_EXTERNAL_ID"] <> '')
1742 {
1743 $arSkuData[] = array(
1744 "NAME" => "Catalog XML_ID",
1745 "CODE" => "CATALOG.XML_ID",
1746 "VALUE" => $arElementInfo['~IBLOCK_EXTERNAL_ID']
1747 );
1748 }
1749
1750 if($arElementInfo["~XML_ID"] <> '')
1751 {
1752 $arSkuData[] = array(
1753 "NAME" => "Product XML_ID",
1754 "CODE" => "PRODUCT.XML_ID",
1755 "VALUE" => $arElementInfo["~XML_ID"]
1756 );
1757 }
1758
1759 $arElementInfo["WEIGHT"] = $arProduct["WEIGHT"];
1760 $arElementInfo["WIDTH"] = $arProduct["WIDTH"];
1761 $arElementInfo["LENGTH"] = $arProduct["LENGTH"];
1762 $arElementInfo["HEIGHT"] = $arProduct["HEIGHT"];
1763
1764 // measure
1765 $arElementInfo["MEASURE_TEXT"] = "";
1766 $arElementInfo["MEASURE_CODE"] = 0;
1767
1768 if ((int)$arProduct["MEASURE"] > 0)
1769 {
1770
1771 if (!empty($proxyCatalogMeasure[$arProduct["MEASURE"]]) && is_array($proxyCatalogMeasure[$arProduct["MEASURE"]]))
1772 {
1773 $arMeasure = $proxyCatalogMeasure[$arProduct["MEASURE"]];
1774 }
1775 else
1776 {
1777 $dbMeasure = \CCatalogMeasure::GetList(array(), array("ID" => intval($arProduct["MEASURE"])), false, false, array("ID", "SYMBOL_RUS", "SYMBOL_INTL"));
1778 if ($arMeasure = $dbMeasure->Fetch())
1779 {
1780 $proxyCatalogMeasure[$arProduct["MEASURE"]] = $arMeasure;
1781 }
1782 }
1783
1784 if (!empty($arMeasure) && is_array($arMeasure))
1785 {
1786 $arElementInfo["MEASURE_TEXT"] = ($arMeasure["SYMBOL_RUS"] != '' ? $arMeasure["SYMBOL_RUS"] : $arMeasure["SYMBOL_INTL"]);
1787 $arElementInfo["MEASURE_CODE"] = $arMeasure["CODE"];
1788 }
1789 }
1790 if ($arElementInfo["MEASURE_TEXT"] == '')
1791 {
1792 $arElementInfo["MEASURE_TEXT"] = ($defaultMeasure["SYMBOL_RUS"] != '' ? $defaultMeasure["SYMBOL_RUS"] : $defaultMeasure["SYMBOL_INTL"]);
1793 }
1794
1795
1796 // ratio
1797 $arElementInfo["RATIO"] = 1;
1798
1799 if (!empty($proxyCatalogMeasureRatio[$productId]) && is_array($proxyCatalogMeasureRatio[$productId]))
1800 {
1801 $arRatio = $proxyCatalogMeasureRatio[$productId];
1802 }
1803 else
1804 {
1805 $dbratio = Catalog\MeasureRatioTable::getList(array(
1806 'select' => array('*'),
1807 'filter' => array('=PRODUCT_ID' => $productId, '=IS_DEFAULT' => 'Y')
1808 ));
1809 if ($arRatio = $dbratio->fetch())
1810 {
1811 $proxyCatalogMeasureRatio[$productId] = $arRatio;
1812 }
1813
1814 }
1815
1816 if (!empty($arRatio) && is_array($arRatio))
1817 $arElementInfo["RATIO"] = $arRatio["RATIO"];
1818
1819 // image
1820 $imgCode = '';
1821 $imgUrl = '';
1822 if ($arElementInfo["PREVIEW_PICTURE"] > 0)
1823 $imgCode = $arElementInfo["PREVIEW_PICTURE"];
1824 elseif ($arElementInfo["DETAIL_PICTURE"] > 0)
1825 $imgCode = $arElementInfo["DETAIL_PICTURE"];
1826
1827 if ($imgCode == "" && !empty($arParent) && is_array($arParent))
1828 {
1829 if ($arParent["PREVIEW_PICTURE"] > 0)
1830 $imgCode = $arParent["PREVIEW_PICTURE"];
1831 elseif ($arParent["DETAIL_PICTURE"] > 0)
1832 $imgCode = $arParent["DETAIL_PICTURE"];
1833 }
1834
1835 if ($imgCode > 0)
1836 {
1837 $arFile = \CFile::GetFileArray($imgCode);
1838 $arImgProduct = \CFile::ResizeImageGet($arFile, array('width'=>80, 'height'=>80), BX_RESIZE_IMAGE_PROPORTIONAL, false, false);
1839 if (is_array($arImgProduct))
1840 $imgUrl = $arImgProduct["src"];
1841 }
1842
1843 $arSetInfo = array();
1844 $arStores = array();
1845
1847 if ($productProvider = \CSaleBasket::GetProductProvider(array("MODULE" => $arElementInfo["MODULE"], "PRODUCT_PROVIDER_CLASS" => $arElementInfo["PRODUCT_PROVIDER_CLASS"])))
1848 {
1849 // get set items if it is set
1850 if ($arProduct["TYPE"] == \CCatalogProduct::TYPE_SET)
1851 {
1852 if (method_exists($productProvider, "GetSetItems"))
1853 {
1854 $arSets = $productProvider::GetSetItems($productId, \CSaleBasket::TYPE_SET);
1855
1856 if ($tmpId == "")
1857 $tmpId = randString(7);
1858
1859 if (!empty($arSets))
1860 {
1861 foreach ($arSets as $arSetData)
1862 {
1863 foreach ($arSetData["ITEMS"] as $setItem)
1864 {
1865 $arSetItemParams = self::getProductDataToFillBasket($setItem["PRODUCT_ID"], $setItem["QUANTITY"], $userId, $LID, $userColumns, $tmpId); // recursive call
1866
1867 // re-define some fields with set data values
1868 $arSetItemParams["PARENT_OFFER_ID"] = $productId;
1869 $arSetItemParams["OFFER_ID"] = $setItem["PRODUCT_ID"];
1870 $arSetItemParams["NAME"] = $setItem["NAME"];
1871 $arSetItemParams["MODULE"] = $setItem["MODULE"];
1872 $arSetItemParams["PRODUCT_PROVIDER_CLASS"] = $setItem["PRODUCT_PROVIDER_CLASS"];
1873 $arSetItemParams["QUANTITY"] = $setItem["QUANTITY"] * $quantity;
1874 $arSetItemParams["BARCODE_MULTI"] = $setItem["BARCODE_MULTI"];
1875 $arSetItemParams["PRODUCT_TYPE"] = $setItem["TYPE"];
1876 $arSetItemParams["WEIGHT"] = $setItem["WEIGHT"];
1877 $arSetItemParams["VAT_RATE"] = $setItem["VAT_RATE"];
1878 $arSetItemParams["SET_ITEMS"] = "";
1879 $arSetItemParams["OLD_PARENT_ID"] = $productId."_tmp".$tmpId;
1880 $arSetItemParams["IS_SET_ITEM"] = "Y";
1881 $arSetItemParams["IS_SET_PARENT"] = "N";
1882 $arSetItemParams["PROVIDER_DATA"] = serialize($setItem);
1883 $arSetInfo[] = $arSetItemParams;
1884 }
1885 }
1886 }
1887 }
1888 }
1889
1890 // get stores
1891 $storeCount = $productProvider::GetStoresCount(array("SITE_ID" => $LID)); // with exact SITE_ID or SITE_ID = NULL
1892
1893 if ($storeCount > 0)
1894 {
1895 if ($arProductStore = $productProvider::GetProductStores(array("PRODUCT_ID" => $productId, "SITE_ID" => $LID)))
1896 $arStores = $arProductStore;
1897 }
1898 }
1899
1900 $currentTotalPrice = (float)$currentTotalPrice;
1901 // params array
1902 $arParams["OFFER_ID"] = $productId;
1903 $arParams["NAME"] = $arElementInfo["~NAME"]; //'
1904 $arParams["EDIT_PAGE_URL"] = $arElementInfo["EDIT_PAGE_URL"];
1905 $arParams["DETAIL_PAGE_URL"] = htmlspecialcharsex($arElementInfo["~DETAIL_PAGE_URL"]);
1906 $arParams["PICTURE_URL"] = $imgUrl;
1907 $arParams["PRICE"] = floatval($arElementInfo["PRICE"]);
1908 $arParams["PRICE_BASE"] = $currentTotalPrice;
1909 $arParams["DIMENSIONS"] = serialize(array("WIDTH" => $arElementInfo["WIDTH"], "HEIGHT" => $arElementInfo["HEIGHT"], "LENGTH" => $arElementInfo["LENGTH"]));
1910 $arParams["QUANTITY"] = $quantity;
1911 $arParams["MODULE"] = $arElementInfo["MODULE"];
1912 $arParams["CURRENCY"] = $arElementInfo["CURRENCY"];
1913 $arParams["WEIGHT"] = $arElementInfo["WEIGHT"];
1914 $arParams["VAT_RATE"] = $arPrice["PRICE"]["VAT_RATE"];
1915 $arParams["PRICE_TYPE"] = $priceType["NAME_LANG"];
1916 $arParams["AVAILABLE"] = $balance;
1917 $arParams["NOTES"] = (!empty($priceType["NAME_LANG"]) ? $priceType["NAME_LANG"] : "");
1918 $arParams["CATALOG_XML_ID"] = $arElementInfo["~IBLOCK_EXTERNAL_ID"];
1919 $arParams["PRODUCT_XML_ID"] = $arElementInfo["~XML_ID"];
1920 $arParams["PRODUCT_PROVIDER_CLASS"] = $arElementInfo["PRODUCT_PROVIDER_CLASS"];
1921 $arParams["PROPS"] = $arSkuData;
1922 $arParams["MEASURE_TEXT"] = $arElementInfo["MEASURE_TEXT"];
1923 $arParams["MEASURE_CODE"] = $arElementInfo["MEASURE_CODE"];
1924 $arParams["MEASURE_RATIO"] = $arElementInfo["RATIO"];
1925 $arParams["BARCODE_MULTI"] = $arProduct["BARCODE_MULTI"];
1926
1927 $arParams["PRODUCT_TYPE"] = empty($arSetInfo) ? "" : \CSaleBasket::TYPE_SET;
1928 $arParams["OLD_PARENT_ID"] = empty($arSetInfo) ? "" : $productId."_tmp".$tmpId;
1929
1930 $arParams["SET_ITEMS"] = $arSetInfo;
1931 $arParams["IS_SET_ITEM"] = "N";
1932 $arParams["IS_SET_PARENT"] = empty($arSetInfo) ? "N" : "Y";
1933
1934 $arParams["STORES"] = empty($arSetInfo) ? $arStores : array();
1935 $arParams["PRODUCT_PROPS_VALUES"] = $arElementInfo; // along with other information also contains values of properties with correct keys (after getProductProps)
1936 }
1937
1938 return $arParams;
1939 }
1940
1941
1947 public function prepareData(array $inParams = array())
1948 {
1949 if($this->data === null)
1950 {
1951 $inParams['ADDED_PRODUCTS'] ??= null;
1952 $isArrayAddedProducts = is_array($inParams['ADDED_PRODUCTS']);
1953
1954 $result = array(
1955 "ITEMS" => array(),
1956 "WEIGHT" => 0
1957 );
1958
1959 $basket = $this->order->getBasket();
1960 $discounts = !empty($inParams["DISCOUNTS"]) ? $inParams["DISCOUNTS"] : OrderEdit::getDiscountsApplyResult($this->order, true);
1961
1962 if(!$basket)
1963 {
1964 $result["WEIGHT_FOR_HUMAN"] = roundEx(floatval(0), SALE_WEIGHT_PRECISION);
1965 $this->data = $result;
1966 return $result;
1967 }
1968
1969 $result["WEIGHT"] = $basket->getWeight();
1970 $result["WEIGHT_FOR_HUMAN"] = roundEx(floatval($result["WEIGHT"]/$this->weightKoef), SALE_WEIGHT_PRECISION);
1971 $items = $basket->getBasketItems();
1972
1973 if (self::$catalogIncluded === null)
1974 self::$catalogIncluded = Main\Loader::includeModule('catalog');
1975
1976 if(!empty($inParams["ADDED_PRODUCTS"]))
1977 $result["ADDED_PRODUCTS"] = array();
1978
1979 $catalogProductIds = array();
1980
1982 foreach($items as $item)
1983 if($item->getField('MODULE') == 'catalog')
1984 $catalogProductIds[] = $item->getProductId();
1985
1986 $catalogPreparedData = static::getProductsData($catalogProductIds, $this->order->getSiteId(), $this->visibleColumns, $this->order->getUserId());
1987 $providerData = Provider::getProductData($basket, array("PRICE"));
1988
1990 foreach($items as $item)
1991 {
1992 $params = array();
1993 $productId = $item->getProductId();
1994
1995 $params["BASKET_CODE"] = $basketCode = $item->getBasketCode();
1996 $params["QUANTITY"] = Sale\BasketItem::formatQuantity($item->getField('QUANTITY'));
1997 $params["NOTES"] = $item->getField("NOTES");
1998 $params["MODULE"] = $item->getField("MODULE");
1999 $params['TYPE'] = (int)$item->getField('TYPE');
2000
2001 if($params["MODULE"] == 'catalog')
2002 {
2003 if(!empty($catalogPreparedData[$productId]['OFFERS_IBLOCK_ID']))
2004 $params["OFFERS_IBLOCK_ID"] = $catalogPreparedData[$productId]['OFFERS_IBLOCK_ID'];
2005
2006 if(!empty($catalogPreparedData[$productId]['IBLOCK_ID']))
2007 $params["IBLOCK_ID"] = $catalogPreparedData[$productId]['IBLOCK_ID'];
2008
2009 if(!empty($catalogPreparedData[$productId]['PRODUCT_ID']))
2010 $params["PRODUCT_ID"] = $catalogPreparedData[$productId]['PRODUCT_ID'];
2011 }
2012
2013 if(!isset($params["OFFER_ID"]))
2014 $params["OFFER_ID"] = $productId;
2015
2016 if(isset($discounts["RESULT"]["BASKET"][$basketCode]) && is_array($discounts["RESULT"]["BASKET"][$basketCode]))
2017 foreach($discounts["RESULT"]["BASKET"][$basketCode] as $discount)
2018 $params["DISCOUNTS"][$discount["DISCOUNT_ID"]] = $discount;
2019
2020 if(isset($discounts["PRICES"]["BASKET"][$basketCode]))
2021 $params["PRICE"] = $discounts["PRICES"]["BASKET"][$basketCode]["PRICE"];
2022 else
2023 $params["PRICE"] = $item->getPrice();
2024
2025 //alias for backward compatibility.
2026 $params["PRICE_BASE"] = $params["BASE_PRICE"] = $item->getField("BASE_PRICE");
2027 $params["CUSTOM_PRICE"] = $item->isCustomPrice() ? "Y" : "N";
2028
2029 if (
2030 !$isArrayAddedProducts
2031 ||
2032 (
2033 !empty($inParams["ADDED_PRODUCTS"])
2034 && in_array($productId, $inParams["ADDED_PRODUCTS"])
2035 )
2036 )
2037 {
2038 $params = $params + self::getPropsForBasketItem($item, $catalogPreparedData);
2039
2040 if ($isArrayAddedProducts && in_array($productId, $inParams["ADDED_PRODUCTS"]))
2041 {
2042 $result["ADDED_PRODUCTS"][] = $basketCode;
2043 }
2044 }
2045
2046 //Let's cache provider product data into form field
2047 if(!Provider::isExistsTrustData($this->order->getSiteId(), 'sale', $item->getProductId()))
2048 {
2049 $basketItem = $basket->getItemByBasketCode($basketCode);
2050 if($basketItem)
2051 {
2052 if (!empty($providerData[$basketCode]))
2053 {
2054 \Bitrix\Sale\Helpers\Admin\OrderEdit::setProviderTrustData($item, $this->order, $providerData[$basketCode]);
2055 $params["PROVIDER_DATA"] = serialize($providerData[$basketCode]);
2056 }
2057 }
2058 }
2059 else
2060 {
2061 $providerData = Provider::getTrustData($this->order->getSiteId(), 'sale', $item->getProductId());
2062
2063 if(is_array($providerData) && !empty($providerData))
2064 {
2065 $params["PROVIDER_DATA"] = serialize($providerData);
2066 }
2067 }
2068
2069 if (!empty($params["SET_ITEMS"]) && is_array($params["SET_ITEMS"]))
2070 {
2071 $offerToIdx = array();
2072
2073 foreach($params["SET_ITEMS"] as $idx => $childFields)
2074 $offerToIdx[$childFields["OFFER_ID"]] = $idx;
2075
2076 $setItems = [];
2077
2078 if($children = $item->getBundleCollection())
2079 {
2081 foreach($children->getBasketItems() as $idx => $child)
2082 {
2083 $fields = $child->getFieldValues();
2084
2085 if(isset($offerToIdx[$fields['PRODUCT_ID']]))
2086 {
2087 $fields = $fields + $params["SET_ITEMS"][$offerToIdx[$fields['PRODUCT_ID']]];
2088 }
2089 else
2090 {
2091 $fields["OFFER_ID"] = $fields["PRODUCT_ID"];
2092 }
2093
2094 $fields["IS_ENABLED"] = ($fields['CAN_BUY'] === 'N') ? 'N' : 'Y';
2095
2096 $setItems[$idx] = $fields;
2097 }
2098
2099 $params["SET_ITEMS"] = $setItems;
2100 }
2101
2102 $params["SET_ITEMS_DATA"] = serialize($params["SET_ITEMS"]);
2103 }
2104 elseif($item->isBundleParent())
2105 {
2106 $params["SET_ITEMS"] = array();
2107
2108 if($children = $item->getBundleCollection())
2109 {
2111 foreach($children->getBasketItems() as $child)
2112 {
2113 $childFields = $child->getFieldValues();
2114 $childFields["OFFER_ID"] = $child->getProductId();
2115 $childFields["IS_SET_ITEM"] = "Y";
2116 $childFields["IS_SET_PARENT"] = "N";
2117 $childFields["IS_ENABLED"] = ($childFields['CAN_BUY'] === 'N') ? 'N' : 'Y';
2118 $params["SET_ITEMS"][] = $childFields;
2119 }
2120 }
2121
2122 if(!empty($params["SET_ITEMS"]))
2123 {
2124 $params["IS_SET_PARENT"] = "Y";
2125 }
2126 }
2127
2128 $params["IS_ENABLED"] = (($params['CAN_BUY'] ?? null) === 'N') ? 'N' : 'Y';
2129
2130 $result["ITEMS"][$basketCode] = $params;
2131 }
2132
2133 $result = array_merge(
2134 $result, $this->getPrices($discounts)
2135 );
2136
2137 $result["ITEMS_ORDER"] = array_keys($result["ITEMS"]);
2138
2139 if (empty($inParams["SKIP_SKU_INFO"]))
2140 {
2141 $result = $this->getOffersSkuParams($result, $this->visibleColumns);
2142 }
2143
2144 $this->data = $result;
2145 }
2146
2147 return $this->data;
2148 }
2149
2150 public function getPrices($discounts = null)
2151 {
2152 static $result = null;
2153
2154 if($result === null)
2155 {
2156 $basketPrice = 0;
2157 $basketPriceBase = 0;
2158 $basket = $this->order->getBasket();
2159
2160 if($basket)
2161 {
2162 if (!$discounts)
2163 $discounts = OrderEdit::getDiscountsApplyResult($this->order, true);
2164
2165 $basketPriceBase = $basket->getBasePrice();
2166 $basketPrice = $basket->getPrice();
2167 }
2168
2169 $result = array(
2170 "BASKET_PRICE_BASE" => $basketPriceBase,
2171 "BASKET_PRICE" => $basketPrice,
2172 );
2173
2174 $result["DISCOUNT_VALUE"] = $result["BASKET_PRICE_BASE"] - $result["BASKET_PRICE"];
2175 }
2176
2177 return $result;
2178 }
2179
2180 protected function getPropsForBasketItem($item, array $preparedData = array())
2181 {
2182 $params = array();
2183
2185 if (self::$catalogIncluded === null)
2186 self::$catalogIncluded = Main\Loader::includeModule('catalog');
2187
2188 $productId = $item->getProductId();
2189
2190 if($item->getField("MODULE") == "catalog")
2191 {
2192 if(!empty($preparedData[$item->getProductId()]))
2193 {
2194 $params = $preparedData[$item->getProductId()];
2195 }
2196 else
2197 {
2198 $res = static::getProductsData(array($productId), $this->order->getSiteId(), $this->visibleColumns, $this->order->getUserId());
2199 $params = $res[$productId];
2200 }
2201 }
2202
2203 if(intval($item->getField("MEASURE_CODE")) > 0)
2204 $params["MEASURE_CODE"] = intval($item->getField("MEASURE_CODE"));
2205 elseif(!isset($params["MEASURE_CODE"]))
2206 $params["MEASURE_CODE"] = 0;
2207
2208 if($item->getField("MEASURE_NAME") <> '')
2209 $params["MEASURE_TEXT"] = $item->getField("MEASURE_NAME");
2210 elseif(!isset($params["MEASURE_TEXT"]))
2211 $params["MEASURE_TEXT"] = "";
2212
2213 if(!isset($params["OFFER_ID"]))
2214 $params["OFFER_ID"] = $productId;
2215
2216 $params["PRODUCT_PROVIDER_CLASS"] = $item->getProvider();
2217 $id = $params["PRODUCT_ID"] ?? 0;
2218 $params = array_merge($params, $item->getFieldValues(), array("PRODUCT_ID" => $id));
2219
2220 //If product became bundle, but in saved order it is a simple product.
2221 if($item->getBasketCode() == intval($item->getBasketCode()) && !$item->isBundleParent() && !empty($params['SET_ITEMS']))
2222 {
2223 unset($params['SET_ITEMS'], $params['OLD_PARENT_ID']);
2224 $params['IS_SET_PARENT'] = 'N';
2225 }
2226
2227 $params["PROPS"] = array();
2228
2230 foreach($item->getPropertyCollection() as $property)
2231 {
2232 $propKey = 'PROPERTY_'.$property->getField("CODE").'_VALUE';
2233
2234 if(isset($params['PRODUCT_PROPS_VALUES'][$propKey]))
2235 {
2236 $params['PRODUCT_PROPS_VALUES'][$propKey] = $property->getField("VALUE");
2237 }
2238
2239 $params["PROPS"][] = array(
2240 "VALUE" => $property->getField("VALUE"),
2241 "NAME" => $property->getField("NAME"),
2242 "CODE" => $property->getField("CODE"),
2243 "SORT" => $property->getField("SORT"),
2244 "ID" => $property->getField("ID")
2245 );
2246 }
2247
2248 //Let's cache provider product data into form field
2249 if(Provider::isExistsTrustData($this->order->getSiteId(), 'sale', $item->getProductId()))
2250 {
2251 $providerData = Provider::getTrustData($this->order->getSiteId(), 'sale', $item->getProductId());
2252
2253 if(is_array($providerData) && !empty($providerData))
2254 $params["PROVIDER_DATA"] = serialize($providerData);
2255 }
2256
2257 if (!empty($params["SET_ITEMS"]) && is_array($params["SET_ITEMS"]))
2258 {
2259 $offerToIdx = array();
2260 $items = [];
2261
2262 foreach($params["SET_ITEMS"] as $idx => $childFields)
2263 $offerToIdx[$childFields["OFFER_ID"]] = $idx;
2264
2265 if($children = $item->getBundleCollection())
2266 {
2268 foreach($children->getBasketItems() as $idx => $child)
2269 {
2270 $fields = $child->getFieldValues();
2271
2272 if(isset($offerToIdx[$fields['PRODUCT_ID']]))
2273 {
2274 $items[$idx] = $fields + $params["SET_ITEMS"][$offerToIdx[$fields['PRODUCT_ID']]];
2275 }
2276 else //Child have been deleted from bundle after order been created
2277 {
2278 $res = static::getProductsData(array($fields["PRODUCT_ID"]), $this->order->getSiteId(), $this->visibleColumns, $this->order->getUserId());
2279
2280 if(!empty($res[$fields["PRODUCT_ID"]]))
2281 {
2282 $fields = array_merge($res[$fields["PRODUCT_ID"]], $fields);
2283 }
2284
2285 $fields["OFFER_ID"] = $fields["PRODUCT_ID"];
2286 $fields["IS_SET_ITEM"] = "Y";
2287 $fields["IS_SET_PARENT"] = "N";
2288 $fields["OLD_PARENT_ID"] = $params["OLD_PARENT_ID"];
2289 $items[$idx] = $fields;
2290 }
2291 }
2292
2293 sortByColumn($items, array("SORT" => SORT_DESC), '');
2294 $params["SET_ITEMS"] = $items;
2295 }
2296
2297 $params["SET_ITEMS_DATA"] = serialize($params["SET_ITEMS"]);
2298 }
2299
2300 return $params;
2301 }
2302}
static loadMessages($file)
Definition loc.php:64
static getMessage($code, $replace=null, $language=null)
Definition loc.php:29
static getPropsParams($iblockId, array $visibleColumns=array(), array $iblockPropsUsed=array())
getOffersIds($productId, array $products)
__construct(Order $order, $jsObjName="", $idPrefix="", $createProductBasement=true, $mode=self::EDIT_MODE)
getOffersSkuParams(array $productsParams, array $visibleColumns=array())
static getProductsData(array $productsIds, $siteId, array $fields=array(), $userId=0)
static getProductDetails($productId, $quantity, $userId, $siteId, array $columns=array())
getCouponsHtml($mode, $needRecalculate=true)
static getPropsList($iblockId, $skuPropertyId=0)
static getProductEditDialogHtml($currency, $objName)
static getPropsFromOffers2(array $items, array $existOffers)
static getOffersSkuParamsMode(array $productsParams, array $visibleColumns=array(), $mode=0)
static getProductDetails($productId, $userId, $siteId)
static getCouponList(Order $order=null, $needRecalculate=true)
static getTotalPrices(Order $order, OrderBasket $orderBasket, $needRecalculate=true)
static setProductDetails($productId, $userId, $siteId, array $params)
static makeSelectHtml($name, array $data, $selected="", $showNotUse=true, $attributes=array())
Definition orderedit.php:69
static getOrderedDiscounts(Order $order, $needRecalculate=true)
static getProductData(BasketItemCollection $basketCollection, array $select=array(), BasketItem $refreshItem=null)
static getTrustData($siteId, $module, $productId)
static isExistsTrustData($siteId, $module, $productId)
if(!function_exists(__NAMESPACE__.'\\___1034172934'))
Definition license.php:1