1C-Bitrix 25.700.0
Загрузка...
Поиск...
Не найдено
product2product.php
См. документацию.
1<?php
2namespace Bitrix\Sale\Internals;
3
4use \Bitrix\Main;
5use \Bitrix\Main\Config;
6use \Bitrix\Sale;
7use Bitrix\Main\Localization\Loc;
8
9Loc::loadMessages(__FILE__);
10
27class Product2ProductTable extends Main\Entity\DataManager
28{
29 public static function getTableName()
30 {
31 return "b_sale_product2product";
32 }
33
34 public static function getMap()
35 {
36 return array(
37 'ID' => array(
38 'data_type' => 'integer',
39 'primary' => true,
40 'autocomplete' => true,
41 ),
42 'PRODUCT_ID' => array(
43 'data_type' => 'integer'
44 ),
45 'PARENT_PRODUCT_ID' => array(
46 'data_type' => 'integer'
47 ),
48 'CNT' => array(
49 'data_type' => 'integer'
50 )
51 );
52 }
53
63 public static function deleteOldProducts($liveTime = 10)
64 {
65 $liveTime = (int)$liveTime;
67
68 // Update existing
69 if ($connection->isTableExists('b_sale_order_product_stat'))
70 {
71 $helper = $connection->getSqlHelper();
72 $now = $helper->getCurrentDateTimeFunction();
73 $liveTo = $helper->addSecondsToDateTime($liveTime * 24 * 3600, 'ORDER_DATE');
74 $sqlDelete = "DELETE FROM b_sale_order_product_stat WHERE $now > $liveTo";
75 $connection->query($sqlDelete);
76 $connection->query('TRUNCATE TABLE b_sale_product2product');
77
78 $sqlUpdate = 'INSERT INTO b_sale_product2product(PRODUCT_ID, PARENT_PRODUCT_ID, CNT)
79 SELECT ops.PRODUCT_ID, ops.RELATED_PRODUCT_ID, SUM(ops.CNT)
80 FROM b_sale_order_product_stat ops
81 GROUP BY PRODUCT_ID, RELATED_PRODUCT_ID';
83 {
84 $sqlUpdate .= '
85 ORDER BY NULL'
86 ;
87 }
88 $connection->query($sqlUpdate);
89 unset($sqlUpdate);
90 }
91
92 // @deprecated update status, stayed for compatibility
93 $updateRemStatusSql = "UPDATE b_sale_order_processing SET PRODUCTS_REMOVED = 'Y'";
94 $connection->query($updateRemStatusSql);
95
96 return "\\Bitrix\\Sale\\Product2ProductTable::deleteOldProducts(".$liveTime.");";
97 }
98
106 public static function refreshProductStatistic($liveTime = 10)
107 {
108 $liveTime = (int)$liveTime;
110 $isMysql = $connection instanceof Main\DB\MysqlCommonConnection;
111
112 if (!$connection->isTableExists('b_sale_order_product_stat'))
113 {
114 return;
115 }
116
117 $sqlDelete = "TRUNCATE TABLE b_sale_order_product_stat";
118 $connection->queryExecute($sqlDelete);
119 $helper = $connection->getSqlHelper();
120 $dateLimit = "";
121 if ($liveTime > 0)
122 {
123 $liveTo = $helper->addSecondsToDateTime($liveTime * 24 * 3600, "b.DATE_INSERT");
124 $dateLimit = " AND NOW() < $liveTo";
125 }
126 $sqlUpdate = "
127 INSERT INTO b_sale_order_product_stat (PRODUCT_ID, RELATED_PRODUCT_ID, ORDER_DATE, CNT)
128 SELECT
129 b.PRODUCT_ID as PRODUCT_ID,
130 b1.PRODUCT_ID as RELATED_PRODUCT_ID,
131 " . $helper->getDatetimeToDateFunction('b.DATE_INSERT') . " as ORDER_DATE,
132 COUNT(b.PRODUCT_ID)
133 FROM b_sale_basket b, b_sale_basket b1
134 WHERE b.ORDER_ID = b1.ORDER_ID
135 AND b.ID <> b1.ID
136 $dateLimit
137 GROUP BY b.PRODUCT_ID, b1.PRODUCT_ID, ORDER_DATE"
138 ;
139 if ($isMysql)
140 {
141 $sqlUpdate .= "
142 ORDER BY NULL"
143 ;
144 }
145 $connection->queryExecute($sqlUpdate);
146
147 $sqlDelete = "TRUNCATE TABLE b_sale_product2product";
148 $connection->query($sqlDelete);
149 $sqlUpdate = "
150 INSERT INTO b_sale_product2product (PRODUCT_ID, PARENT_PRODUCT_ID, CNT)
151 SELECT ops.PRODUCT_ID, ops.RELATED_PRODUCT_ID, SUM(ops.CNT)
152 FROM b_sale_order_product_stat ops
153 GROUP BY PRODUCT_ID, RELATED_PRODUCT_ID"
154 ;
155 if ($isMysql)
156 {
157 $sqlUpdate .= "
158 ORDER BY NULL
159 ";
160 }
161
162 $connection->queryExecute($sqlUpdate);
163 }
164
172 public static function addProductsFromOrder($orderId = 0)
173 {
174 $orderId = (int)$orderId;
175
177 return;
178
180 $helper = $connection->getSqlHelper();
181
182 // Update existing
183 if ($connection->isTableExists('b_sale_order_product_stat'))
184 {
185 $sqlUpdate = $helper->prepareMergeSelect(
186 'b_sale_order_product_stat',
187 ['PRODUCT_ID', 'RELATED_PRODUCT_ID', 'ORDER_DATE'],
188 ['PRODUCT_ID', 'RELATED_PRODUCT_ID', 'ORDER_DATE'],
189 "SELECT
190 b.PRODUCT_ID,
191 b1.PRODUCT_ID,
192 " . $helper->getDatetimeToDateFunction('b.DATE_INSERT') . "
193 FROM b_sale_basket b, b_sale_basket b1
194 WHERE b.ORDER_ID = b1.ORDER_ID AND
195 b.ORDER_ID = " . $orderId . " AND
196 b.ID <> b1.ID",
197 ['CNT' => new \Bitrix\Main\DB\SqlExpression('b_sale_order_product_stat.CNT + 1')],
198 );
199 $connection->query($sqlUpdate);
200
201 $sqlUpdate = $helper->prepareCorrelatedUpdate(
202 'b_sale_product2product',
203 'p2p',
204 ['CNT' => 'p2p.CNT + 1'],
205 'b_sale_basket b, b_sale_basket b1',
206 "b.ORDER_ID = b1.ORDER_ID AND
207 b.ID <> b1.ID AND
208 b.ORDER_ID = " . $orderId . " AND
209 p2p.PRODUCT_ID = b.PRODUCT_ID AND
210 p2p.PARENT_PRODUCT_ID = b1.PRODUCT_ID"
211 );
212 $connection->query($sqlUpdate);
213 }
214
215 // Insert new
216 $sqlInsert = "INSERT INTO b_sale_product2product (PRODUCT_ID, PARENT_PRODUCT_ID, CNT)
217 SELECT b.PRODUCT_ID, b1.PRODUCT_ID, 1
218 FROM b_sale_basket b, b_sale_basket b1
219 WHERE b.ORDER_ID = b1.ORDER_ID AND
220 b.ORDER_ID = $orderId AND
221 b.ID <> b1.ID AND
222 NOT EXISTS (SELECT 1 FROM b_sale_product2product d WHERE d.PRODUCT_ID = b.PRODUCT_ID AND d.PARENT_PRODUCT_ID = b1.PRODUCT_ID)";
223
224 $connection->query($sqlInsert);
225
226 Sale\OrderProcessingTable::markProductsAdded($orderId);
227
228 if (defined("BX_COMP_MANAGED_CACHE"))
229 {
231 $app->getTaggedCache()->clearByTag('sale_product_buy');
232 }
233 }
234
241 public static function addProductsByAgent($limit = 100)
242 {
243 global $pPERIOD;
244
245 $limit = (int)$limit;
247 $type = $connection->getType();
248 $isTableExists = $connection->isTableExists('b_sale_order_product_stat');
249 if ($isTableExists)
250 {
251 $params = [
252 'filter' => [
253 '=PRODUCTS_ADDED' => 'N',
254 ],
255 'select' => [
256 'ORDER_ID',
257 ]
258 ];
259
260 if ($limit > 0)
261 {
262 $params['limit'] = $limit;
263 }
264
265 $orderIds = [];
266 $processingData = Sale\OrderProcessingTable::getList($params);
267 while ($processingOrder = $processingData->fetch())
268 {
269 $orderIds[] = (int)$processingOrder['ORDER_ID'];
270 }
271
272 if (!empty($orderIds))
273 {
274 $sqlOrderIds = implode(',', $orderIds);
275 Sale\OrderProcessingTable::markProductsAddedByList($orderIds);
276 $helper = $connection->getSqlHelper();
277
278 $sqlInsert = $helper->prepareMergeSelect(
279 'b_sale_order_product_stat',
280 ['PRODUCT_ID', 'RELATED_PRODUCT_ID', 'ORDER_DATE'],
281 ['CNT', 'PRODUCT_ID', 'RELATED_PRODUCT_ID', 'ORDER_DATE'],
282 "SELECT SUMM, PRODUCT_ID, PARENT_PRODUCT_ID, TODAY
283 FROM (
284 SELECT COUNT(1) as SUMM,
285 b.PRODUCT_ID as PRODUCT_ID,
286 b1.PRODUCT_ID as PARENT_PRODUCT_ID,
287 " . $helper->getCurrentDateFunction() . " as TODAY
288 FROM b_sale_basket b, b_sale_basket b1
289 WHERE
290 b1.ORDER_ID = b.ORDER_ID
291 AND b1.ID <> b.ID
292 AND b.ORDER_ID IN ($sqlOrderIds)
293 GROUP BY b.PRODUCT_ID, b1.PRODUCT_ID
294 " . ($type === 'mysql' ? 'ORDER BY NULL' : '') . "
295 ) cacl",
296 ['CNT' => new \Bitrix\Main\DB\SqlExpression('b_sale_order_product_stat.CNT + ?v', 'CNT')],
297 );
298 $connection->query($sqlInsert);
299
300 $sqlUpdate = $helper->prepareCorrelatedUpdate(
301 'b_sale_product2product',
302 'p2p',
303 ['CNT' => 'p2p.CNT + calc.CNT'],
304 "(
305 SELECT COUNT(1) as CNT,
306 b.PRODUCT_ID as PRODUCT_ID,
307 b1.PRODUCT_ID as PARENT_PRODUCT_ID
308 FROM b_sale_basket b, b_sale_basket b1
309 WHERE
310 b1.ORDER_ID = b.ORDER_ID
311 AND b1.ID <> b.ID
312 AND b.ORDER_ID IN ($sqlOrderIds)
313 GROUP BY b.PRODUCT_ID, b1.PRODUCT_ID
314 ) calc",
315 'p2p.PRODUCT_ID = calc.PRODUCT_ID AND p2p.PARENT_PRODUCT_ID = calc.PARENT_PRODUCT_ID'
316 );
317
318 $connection->query($sqlUpdate);
319
320 $sqlInsert = "
321 INSERT INTO b_sale_product2product (PRODUCT_ID, PARENT_PRODUCT_ID, CNT)
322 SELECT b.PRODUCT_ID, b1.PRODUCT_ID, 1
323 FROM b_sale_basket b, b_sale_basket b1
324 WHERE b.ORDER_ID = b1.ORDER_ID AND
325 b.ORDER_ID IN ($sqlOrderIds) AND
326 b.ID <> b1.ID AND
327 NOT EXISTS (SELECT 1 FROM b_sale_product2product d WHERE d.PRODUCT_ID = b.PRODUCT_ID AND d.PARENT_PRODUCT_ID = b1.PRODUCT_ID)";
328 $connection->query($sqlInsert);
329
330 if (defined("BX_COMP_MANAGED_CACHE"))
331 {
333 $app->getTaggedCache()->clearByTag('sale_product_buy');
334 }
335 }
336 }
337
338 $agentName = "\\Bitrix\\Sale\\Product2ProductTable::addProductsByAgent($limit);";
339 $agentData = \CAgent::GetList(
340 [],
341 [
342 'NAME' => $agentName,
343 'MODULE_ID' => 'sale',
344 ]
345 );
346 $agent = $agentData->Fetch();
347 unset($agentData);
348 $agentId = (int)($agent['ID'] ?? 0);
349
350 $processingData = Sale\OrderProcessingTable::getRow([
351 'filter' => [
352 '=PRODUCTS_ADDED' => 'N'
353 ],
354 ]);
355
356 if ($processingData)
357 {
358 if (
359 $isTableExists
360 && $agentId > 0
361 && (int)$agent['AGENT_INTERVAL'] > 60
362 )
363 {
364 \CAgent::Update($agentId, ['AGENT_INTERVAL' => 60]);
365 $pPERIOD = 60;
366 }
367 }
368 else
369 {
370 if (
371 $agentId > 0
372 && (int)$agent['AGENT_INTERVAL'] < 86400
373 )
374 {
375 \CAgent::Update($agentId, ['AGENT_INTERVAL' => 86400]);
376 $pPERIOD = 86400;
377 }
378 }
379
380 return $agentName;
381 }
382
388 public static function onSaleOrderAddEvent(Main\Event $event)
389 {
390 $order = $event->getParameter('ENTITY');
391 $isNew = $event->getParameter('IS_NEW');
392 if ((!$order instanceof Sale\Order))
393 {
394 return new Main\EventResult(
395 Main\EventResult::ERROR,
396 new Sale\ResultError(Main\Localization\Loc::getMessage('SALE_EVENT_PRODUCT2PRODUCT_WRONG_ORDER'), 'SALE_EVENT_PRODUCT2PRODUCT_ON_SALE_ORDER_ADD_WRONG_ORDER'),
397 'sale'
398 );
399 }
400
401 $basket = $order->getBasket();
402
403 if ($isNew && ($basket && count($basket) > 0))
404 {
405 static::onSaleOrderAdd($order->getId());
406 }
407
408 return new Main\EventResult( Main\EventResult::SUCCESS, null, 'sale');
409 }
410
417 {
418 $order = $event->getParameter('ENTITY');
419 $value = $event->getParameter('VALUE');
420 if ((!$order instanceof Sale\Order))
421 {
422 return new Main\EventResult(
423 Main\EventResult::ERROR,
424 new Sale\ResultError(Main\Localization\Loc::getMessage('SALE_EVENT_PRODUCT2PRODUCT_WRONG_ORDER'), 'SALE_EVENT_PRODUCT2PRODUCT_ON_SALE_ORDER_STATUS_WRONG_ORDER'),
425 'sale'
426 );
427 }
428
429 static::onSaleStatusOrderHandler($order->getId(), $value);
430
431 return new Main\EventResult( Main\EventResult::SUCCESS, null, 'sale');
432 }
433
440 {
441 $shipment = $event->getParameter('ENTITY');
442 if ((!$shipment instanceof Sale\Shipment))
443 {
444 return new Main\EventResult(
445 Main\EventResult::ERROR,
446 new Sale\ResultError(Main\Localization\Loc::getMessage('SALE_EVENT_PRODUCT2PRODUCT_WRONG_SHIPMENT'), 'SALE_EVENT_PRODUCT2PRODUCT_ON_SALE_DELIVERY_ORDER_WRONG_SHIPMENT'),
447 'sale'
448 );
449 }
450
451 if (!$shipmentCollection = $shipment->getCollection())
452 {
453 return new Main\EventResult(
454 Main\EventResult::ERROR,
455 new Sale\ResultError(Main\Localization\Loc::getMessage('SALE_EVENT_PRODUCT2PRODUCT_WRONG_SHIPMENTCOLLECTION'), 'SALE_EVENT_PRODUCT2PRODUCT_ON_SALE_DELIVERY_ORDER_WRONG_SHIPMENTCOLLECTION'),
456 'sale'
457 );
458
459 }
460
461 if (!$order = $shipmentCollection->getOrder())
462 {
463 return new Main\EventResult(
464 Main\EventResult::ERROR,
465 new Sale\ResultError(Main\Localization\Loc::getMessage('SALE_EVENT_PRODUCT2PRODUCT_WRONG_ORDER'), 'SALE_EVENT_PRODUCT2PRODUCT_ON_SALE_DELIVERY_ORDER_WRONG_ORDER'),
466 'sale'
467 );
468
469 }
470
471 static::onSaleDeliveryOrderHandler($order->getId(), $order->isAllowDelivery() ? 'Y' : 'N');
472
473 return new Main\EventResult( Main\EventResult::SUCCESS, null, 'sale');
474 }
475
482 {
483 $shipment = $event->getParameter('ENTITY');
484 if ((!$shipment instanceof Sale\Shipment))
485 {
486 return new Main\EventResult(
487 Main\EventResult::ERROR,
488 new Sale\ResultError(Main\Localization\Loc::getMessage('SALE_EVENT_PRODUCT2PRODUCT_WRONG_SHIPMENT'), 'SALE_EVENT_PRODUCT2PRODUCT_ON_SALE_DEDUCT_ORDER_WRONG_SHIPMENT'),
489 'sale'
490 );
491 }
492
493 if (!$shipmentCollection = $shipment->getCollection())
494 {
495 return new Main\EventResult(
496 Main\EventResult::ERROR,
497 new Sale\ResultError(Main\Localization\Loc::getMessage('SALE_EVENT_PRODUCT2PRODUCT_WRONG_SHIPMENTCOLLECTION'), 'SALE_EVENT_PRODUCT2PRODUCT_ON_SALE_DEDUCT_ORDER_WRONG_SHIPMENTCOLLECTION'),
498 'sale'
499 );
500
501 }
502
503 if (!$order = $shipmentCollection->getOrder())
504 {
505 return new Main\EventResult(
506 Main\EventResult::ERROR,
507 new Sale\ResultError(Main\Localization\Loc::getMessage('SALE_EVENT_PRODUCT2PRODUCT_WRONG_ORDER'), 'SALE_EVENT_PRODUCT2PRODUCT_ON_SALE_DEDUCT_ORDER_WRONG_ORDER'),
508 'sale'
509 );
510
511 }
512
513
514 static::onSaleDeductOrderHandler($order->getId(), $order->isShipped() ? 'Y' : 'N');
515
516 return new Main\EventResult( Main\EventResult::SUCCESS, null, 'sale');
517 }
518
525 {
526 $order = $event->getParameter('ENTITY');
527 if ((!$order instanceof Sale\Order))
528 {
529 return new Main\EventResult(
530 Main\EventResult::ERROR,
531 new Sale\ResultError(Main\Localization\Loc::getMessage('SALE_EVENT_PRODUCT2PRODUCT_WRONG_ORDER'), 'SALE_EVENT_PRODUCT2PRODUCT_ON_SALE_CANCELED_ORDER_WRONG_ORDER'),
532 'sale'
533 );
534 }
535
536 static::onSaleCancelOrderHandler($order->getId(), $order->isCanceled() ? 'Y' : 'N');
537
538 return new Main\EventResult( Main\EventResult::SUCCESS, null, 'sale');
539 }
540
547 {
548 $order = $event->getParameter('ENTITY');
549 if ((!$order instanceof Sale\Order))
550 {
551 return new Main\EventResult(
552 Main\EventResult::ERROR,
553 new Sale\ResultError(Main\Localization\Loc::getMessage('SALE_EVENT_PRODUCT2PRODUCT_WRONG_ORDER'), 'SALE_EVENT_PRODUCT2PRODUCT_ON_SALE_PAID_ORDER_WRONG_ORDER'),
554 'sale'
555 );
556 }
557
558 static::onSaleCancelOrderHandler($order->getId(), $order->isPaid() ? 'Y' : 'N');
559
560 return new Main\EventResult( Main\EventResult::SUCCESS, null, 'sale');
561 }
562
569 public static function onSaleOrderAdd($orderId)
570 {
571 $statusName = "N";
572 static::addOrderProcessing($orderId, $statusName);
573 }
574
583 {
584 static::addOrderProcessing($orderId, $status);
585 }
586
595 {
596 if ($status == 'Y')
597 {
598 $statusName = "F_DELIVERY";
599 static::addOrderProcessing($orderId, $statusName);
600 }
601 }
602
611 {
612 if ($status == 'Y')
613 {
614 $statusName = "F_OUT";
615 static::addOrderProcessing($orderId, $statusName);
616 }
617 }
618
627 {
628 if ($status == 'Y')
629 {
630 $statusName = "F_CANCELED";
631 static::addOrderProcessing($orderId, $statusName);
632 }
633 }
634
642 public static function onSalePayOrderHandler($orderId, $status)
643 {
644 if ($status == 'Y')
645 {
646 $statusName = "F_PAY";
647 static::addOrderProcessing($orderId, $statusName);
648 }
649 }
650
658 protected static function addOrderProcessing($orderId, $statusName)
659 {
660 $allowStatuses = Config\Option::get("sale", "p2p_status_list", "");
661 $allowCollecting = Config\Option::get("sale", "p2p_allow_collect_data");
662 if ($allowStatuses != '')
663 $allowStatuses = unserialize($allowStatuses, ['allowed_classes' => false]);
664 else
665 $allowStatuses = array();
666
667 if ($allowCollecting == "Y" && !empty($allowStatuses) && is_array($allowStatuses) && in_array($statusName, $allowStatuses))
668 {
669 $orderInformation = Sale\OrderProcessingTable::getList(
670 array(
671 "filter" => array("ORDER_ID" => (int)$orderId),
672 "limit" => 1
673 )
674 );
675 $result = $orderInformation->fetch();
676 if (!$result)
677 Sale\OrderProcessingTable::add(array("ORDER_ID" => (int)$orderId));
678 }
679 }
680}
$connection
Определения actionsdefinitions.php:38
$type
Определения options.php:106
static getInstance()
Определения application.php:98
static getConnection($name="")
Определения application.php:638
static get($moduleId, $name, $default="", $siteId=false)
Определения option.php:30
static hasAddedProducts($orderId=0)
Определения orderprocessing.php:62
static onSaleStatusOrderHandler($orderId, $status)
Определения product2product.php:582
static onSaleDeductOrderHandlerEvent(Main\Event $event)
Определения product2product.php:481
static addProductsByAgent($limit=100)
Определения product2product.php:241
static onSaleDeductOrderHandler($orderId, $status)
Определения product2product.php:610
static onSaleStatusOrderHandlerEvent(Main\Event $event)
Определения product2product.php:416
static onSaleOrderAdd($orderId)
Определения product2product.php:569
static onSaleCancelOrderHandlerEvent(Main\Event $event)
Определения product2product.php:524
static refreshProductStatistic($liveTime=10)
Определения product2product.php:106
static addOrderProcessing($orderId, $statusName)
Определения product2product.php:658
static deleteOldProducts($liveTime=10)
Определения product2product.php:63
static addProductsFromOrder($orderId=0)
Определения product2product.php:172
static onSaleOrderAddEvent(Main\Event $event)
Определения product2product.php:388
static onSaleDeliveryOrderHandler($orderId, $status)
Определения product2product.php:594
static onSaleDeliveryOrderHandlerEvent(Main\Event $event)
Определения product2product.php:439
static onSaleCancelOrderHandler($orderId, $status)
Определения product2product.php:626
static onSalePayOrderHandlerEvent(Main\Event $event)
Определения product2product.php:546
static onSalePayOrderHandler($orderId, $status)
Определения product2product.php:642
$orderId
Определения payment.php:5
</td ></tr ></table ></td ></tr >< tr >< td class="bx-popup-label bx-width30"><?=GetMessage("PAGE_NEW_TAGS")?> array( $site)
Определения file_new.php:804
$result
Определения get_property_values.php:14
$app
Определения proxy.php:8
$status
Определения session.php:10
Определения arrayresult.php:2
Определения buffer.php:3
$order
Определения payment.php:8
$event
Определения prolog_after.php:141
</p ></td >< td valign=top style='border-top:none;border-left:none;border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt;padding:0cm 2.0pt 0cm 2.0pt;height:9.0pt'>< p class=Normal align=center style='margin:0cm;margin-bottom:.0001pt;text-align:center;line-height:normal'>< a name=ТекстовоеПоле54 ></a ><?=($taxRate > count( $arTaxList) > 0) ? $taxRate."%"
Определения waybill.php:936
if($inWords) echo htmlspecialcharsbx(Number2Word_Rus(roundEx($totalVatSum $params['CURRENCY']
Определения template.php:799