1C-Bitrix 25.700.0
Загрузка...
Поиск...
Не найдено
enabler.php
См. документацию.
1<?php
2
3namespace Bitrix\Catalog\Store\EnableWizard;
4
5use Bitrix\Catalog;
6use Bitrix\Main\EventManager;
7use Bitrix\Crm\Order\TradingPlatform;
8use Bitrix\Crm\Component\EntityDetails\ProductList;
9use Bitrix\Crm\Order\Internals\ShipmentRealizationTable;
10use Bitrix\Main\Localization\Loc;
11use Bitrix\Sale\Internals\ShipmentTable;
12use Bitrix\Catalog\ProductTable;
13use Bitrix\Main\Application;
14use Bitrix\Main\Error;
15use Bitrix\Main\Loader;
16use Bitrix\Main\Result;
17use Bitrix\Main\Config\Option;
18use Bitrix\Crm\Timeline\TimelineEntry;
19use Bitrix\Catalog\Access\AccessController;
20use Bitrix\Catalog\Access\ActionDictionary;
21
22abstract class Enabler
23{
24 public static function enable(array $options = []): Result
25 {
26 $result = new Result();
27
28 if (!self::hasAccess())
29 {
30 return $result->addError(
31 new Error(
32 Loc::getMessage('STORE_ENABLE_WIZARD_NO_PERMISSION_ENABLE'),
33 0,
34 [
35 'analyticsCode' => 'no_access',
36 ],
37 )
38 );
39 }
40
41 if (!self::canBeEnabled())
42 {
43 return $result->addError(
44 new Error(
45 Loc::getMessage('STORE_ENABLE_WIZARD_ENABLE_ERROR'),
46 0,
47 [
48 'analyticsCode' => 'conditions_not_met',
49 ],
50 )
51 );
52 }
53
54 self::enableOptions();
55 self::resetQuantities();
56 self::installRealizationDocumentTradingPlatform();
57 self::registerEventsHandlers();
58 self::showEntityProductGridColumns();
59
60 return $result;
61 }
62
63 public static function disable(): Result
64 {
65 $result = new Result();
66
67 if (!self::hasAccess())
68 {
69 return $result->addError(
70 new Error(
71 Loc::getMessage('STORE_ENABLE_WIZARD_NO_PERMISSION_DISABLE'),
72 0,
73 [
74 'analyticsCode' => 'no_access',
75 ],
76 )
77 );
78 }
79
80 if (!self::canBeDisabled())
81 {
82 return $result->addError(
83 new Error(
84 Loc::getMessage('STORE_ENABLE_WIZARD_DISABLE_ERROR'),
85 0,
86 [
87 'analyticsCode' => 'conditions_not_met',
88 ],
89 )
90 );
91 }
92
93 self::disableOptions();
94 self::resetQuantities();
95 self::deleteDocuments();
96 self::uninstallRealizationDocumentTradingPlatform();
97 self::unRegisterEventsHandlers();
98
99 return $result;
100 }
101
102 private static function canBeEnabled(): bool
103 {
104 return (
105 self::isCrmIncluded()
106 && !\CCrmSaleHelper::isWithOrdersMode()
107 );
108 }
109
110 private static function canBeDisabled(): bool
111 {
112 return self::isCrmIncluded();
113 }
114
115 private static function enableOptions(): void
116 {
117 Option::set('catalog', 'default_quantity_trace', 'Y');
118 Option::set('catalog', 'default_can_buy_zero', 'Y');
119 Option::set('catalog', 'allow_negative_amount', 'Y');
120 Option::set('catalog', 'default_use_store_control', 'Y');
121 Option::set('catalog', 'enable_reservation', 'Y');
122 }
123
124 private static function disableOptions(): void
125 {
126 Option::set('catalog', 'default_use_store_control', 'N');
127 Option::set('catalog', 'default_quantity_trace', 'N');
128 }
129
130 private static function resetQuantities(): void
131 {
133 {
134 return;
135 }
136
137 self::resetQuantity();
138 self::resetQuantityTrace();
139 self::resetSaleReserve();
140 self::resetCrmReserve();
141 }
142
143 private static function deleteDocuments(): void
144 {
146 {
147 return;
148 }
149
150 self::resetStoreBatch();
151 self::deleteStoreDocuments();
152 self::deleteRealizations();
153 }
154
155 private static function resetQuantity(): void
156 {
157 $conn = Application::getConnection();
158 $conn->queryExecute('truncate table b_catalog_store_product');
159 $conn->queryExecute('delete from b_catalog_store_barcode where ORDER_ID is null and STORE_ID > 0');
160 unset($conn);
161 }
162
163 private static function resetQuantityTrace(): void
164 {
165 self::resetQuantityTraceMainTypes();
166 self::resetQuantityTraceSku();
167 self::resetQuantityTraceEmptySku();
168 self::resetQuantityTraceSets();
169 }
170
171 private static function resetQuantityTraceMainTypes(): void
172 {
173 $mainTypes = implode(
174 ', ',
175 [
179 ]
180 );
181
182 Application::getConnection()->queryExecute("
183 update b_catalog_product
184 set
185 QUANTITY = 0,
186 QUANTITY_RESERVED = 0,
187 QUANTITY_TRACE = '" . ProductTable::STATUS_DEFAULT . "',
188 CAN_BUY_ZERO = '" . ProductTable::STATUS_DEFAULT . "',
189 NEGATIVE_AMOUNT_TRACE = '" . ProductTable::STATUS_DEFAULT . "',
190 AVAILABLE = '" . ProductTable::STATUS_YES . "'
191 where
192 TYPE in (" . $mainTypes . ")
193 ");
194 }
195
196 private static function resetQuantityTraceSku(): void
197 {
198 if (
199 !self::isCloud()
200 && Option::get('catalog', 'show_catalog_tab_with_offers') === 'Y'
201 )
202 {
203 Application::getConnection()->queryExecute("
204 update b_catalog_product
205 set
206 QUANTITY = 0,
207 QUANTITY_RESERVED = 0,
208 QUANTITY_TRACE = '" . ProductTable::STATUS_DEFAULT . "',
209 CAN_BUY_ZERO = '" . ProductTable::STATUS_DEFAULT . "',
210 NEGATIVE_AMOUNT_TRACE = '" . ProductTable::STATUS_DEFAULT . "',
211 AVAILABLE = '" . ProductTable::STATUS_YES . "'
212 where
213 TYPE = " . ProductTable::TYPE_SKU
214 );
215 }
216 else
217 {
218 Application::getConnection()->queryExecute("
219 update b_catalog_product
220 set
221 QUANTITY = 0,
222 QUANTITY_RESERVED = 0,
223 QUANTITY_TRACE = '" . ProductTable::STATUS_NO . "',
224 CAN_BUY_ZERO = '" . ProductTable::STATUS_YES . "',
225 NEGATIVE_AMOUNT_TRACE = '" . ProductTable::STATUS_YES . "',
226 AVAILABLE = '" . ProductTable::STATUS_YES . "'
227 where
228 TYPE = " . ProductTable::TYPE_SKU
229 );
230 }
231 }
232
233 private static function resetQuantityTraceEmptySku(): void
234 {
235 if (!self::isCloud())
236 {
237 return;
238 }
239 Application::getConnection()->queryExecute("
240 update b_catalog_product
241 set
242 QUANTITY = 0,
243 QUANTITY_TRACE = '" . ProductTable::STATUS_YES . "',
244 CAN_BUY_ZERO = '" . ProductTable::STATUS_NO . "',
245 NEGATIVE_AMOUNT_TRACE = '" . ProductTable::STATUS_NO . "',
246 AVAILABLE = '" . ProductTable::STATUS_NO . "',
247 TYPE = " . ProductTable::TYPE_PRODUCT . "
248 where
250 );
251 }
252
253 private static function resetQuantityTraceSets(): void
254 {
255 Application::getConnection()->queryExecute("
256 update b_catalog_product
257 set
258 QUANTITY = 0,
259 QUANTITY_TRACE = '" . ProductTable::STATUS_NO . "',
260 CAN_BUY_ZERO = '" . ProductTable::STATUS_YES . "',
261 NEGATIVE_AMOUNT_TRACE = '" . ProductTable::STATUS_YES . "',
262 AVAILABLE = '" . ProductTable::STATUS_YES . "'
263 where
264 TYPE = " . ProductTable::TYPE_SET
265 );
266 }
267
268 private static function resetStoreBatch(): void
269 {
270 Application::getConnection()->queryExecute('truncate table b_catalog_store_batch');
271 Application::getConnection()->queryExecute('truncate table b_catalog_store_batch_docs_element');
272 }
273
274 private static function resetSaleReserve(): void
275 {
276 if (Loader::includeModule('sale'))
277 {
278 $conn = Application::getConnection();
279
280 $conn->queryExecute("update b_sale_order_dlv_basket set RESERVED_QUANTITY = 0 where 1 = 1");
281 $conn->queryExecute("update b_sale_order_delivery set RESERVED='N' where 1 = 1");
282
283 $conn->queryExecute("truncate table b_sale_basket_reservation_history");
284 $conn->queryExecute("truncate table b_sale_basket_reservation");
285 }
286 }
287
288 private static function resetCrmReserve(): void
289 {
290 if (!self::isCrmIncluded())
291 {
292 return;
293 }
294
295 Application::getConnection()->queryExecute("truncate table b_crm_product_row_reservation");
296 Application::getConnection()->queryExecute("truncate table b_crm_product_reservation_map");
297 }
298
299 private static function deleteStoreDocuments(): void
300 {
301 global $USER_FIELD_MANAGER;
302
303 $fileIds = Catalog\StoreDocumentFileTable::getList(['select' => ['FILE_ID']])->fetchAll();
304 $fileIds = array_column($fileIds, 'FILE_ID');
305
306 foreach ($fileIds as $fileId)
307 {
308 \CFile::Delete($fileId);
309 }
310
311 $documents = Catalog\StoreDocumentTable::getList(['select' => ['ID', 'DOC_TYPE']])->fetchAll();
312 foreach ($documents as $document)
313 {
314 $typeTableClass = Catalog\Document\StoreDocumentTableManager::getTableClassByType($document['DOC_TYPE']);
315 if ($typeTableClass)
316 {
317 $USER_FIELD_MANAGER->Delete($typeTableClass::getUfId(), $document['ID']);
318 }
319 }
320
321 $conn = Application::getConnection();
322
323 $conn->queryExecute('truncate table b_catalog_store_docs');
324 $conn->queryExecute('truncate table b_catalog_docs_element');
325 $conn->queryExecute('truncate table b_catalog_docs_barcode');
326 $conn->queryExecute('truncate table b_catalog_store_document_file');
327
328 if (self::isCrmIncluded())
329 {
330 TimelineEntry::deleteByAssociatedEntityType(\CCrmOwnerType::StoreDocument);
331
332 $conn->queryExecute("truncate table b_crm_store_document_contractor");
333 }
334 }
335
336 private static function deleteRealizations(): void
337 {
338 if (!self::isCrmIncluded())
339 {
340 return;
341 }
342
343 $realizations = ShipmentRealizationTable::getList([
344 'filter' => [
345 '=IS_REALIZATION' => 'Y',
346 ],
347 ]);
348 foreach ($realizations as $realization)
349 {
350 ShipmentRealizationTable::delete($realization['ID']);
351 ShipmentTable::deleteWithItems($realization['SHIPMENT_ID']);
352 }
353 }
354
355 private static function installRealizationDocumentTradingPlatform(): void
356 {
357 if (!self::isCrmIncluded())
358 {
359 return;
360 }
361
362 $platformCode = TradingPlatform\RealizationDocument::TRADING_PLATFORM_CODE;
363 $platform = TradingPlatform\RealizationDocument::getInstanceByCode($platformCode);
364 if (!$platform->isInstalled())
365 {
366 $platform->install();
367 }
368 }
369
370 private static function uninstallRealizationDocumentTradingPlatform(): void
371 {
372 if (!self::isCrmIncluded())
373 {
374 return;
375 }
376
377 $platformCode = TradingPlatform\RealizationDocument::TRADING_PLATFORM_CODE;
378 $platform = TradingPlatform\RealizationDocument::getInstanceByCode($platformCode);
379 if ($platform->isInstalled())
380 {
381 $platform->unsetActive();
382 }
383 }
384
385 private static function registerEventsHandlers()
386 {
387 $eventManager = EventManager::getInstance();
388
389 $eventManager->registerEventHandler('sale', 'onBeforeSaleShipmentSetField', 'crm', '\Bitrix\Crm\Order\EventsHandler\Shipment', 'onBeforeSetField');
390 }
391
392 private static function unRegisterEventsHandlers()
393 {
394 $eventManager = EventManager::getInstance();
395
396 $eventManager->unRegisterEventHandler('sale', 'onBeforeSaleShipmentSetField', 'crm', '\Bitrix\Crm\Order\EventsHandler\Shipment', 'onBeforeSetField');
397 }
398
399 private static function showEntityProductGridColumns(): void
400 {
401 if (!self::isCrmIncluded())
402 {
403 return;
404 }
405
406 $headers = [
407 'STORE_INFO',
408 'STORE_AVAILABLE',
409 'RESERVE_INFO',
410 'ROW_RESERVED',
411 'DEDUCTED_INFO',
412 ];
413
414 $allHeaderMap = ProductList::getHeaderDefaultMap();
415 $allHeaders = array_keys($allHeaderMap);
416
417 $gridId = ProductList::DEFAULT_GRID_ID;
418 $connection = Application::getConnection();
419 $sqlHelper = $connection->getSqlHelper();
420 $queryResult = $connection->query(
421 "SELECT ID, VALUE FROM b_user_option WHERE CATEGORY = 'main.interface.grid' AND NAME = '{$sqlHelper->forSql($gridId)}'"
422 );
423
424 $resetCache = false;
425 while ($gridSettings = $queryResult->fetch())
426 {
427 $optionID = (int)$gridSettings['ID'];
428 $value = $gridSettings['VALUE'];
429 if (!$value)
430 {
431 continue;
432 }
433
434 $options = unserialize($value, ['allowed_classes' => false]);
435 if (
436 !is_array($options)
437 || empty($options)
438 || !isset($options['views'])
439 || !is_array($options['views'])
440 )
441 {
442 continue;
443 }
444
445 $changed = false;
446 foreach ($options['views'] as &$view)
447 {
448 if (!isset($view['columns']) || $view['columns'] === '')
449 {
450 continue;
451 }
452
453 $allUsedColumns = explode(',', $view['columns']);
454 $currentHeadersInDefaultPosition = array_values(
455 array_intersect($allHeaders, array_merge($allUsedColumns, $headers))
456 );
457 $headers = array_values(array_intersect($allHeaders, $headers));
458
459 foreach ($headers as $header)
460 {
461 if (in_array($header, $allUsedColumns, true))
462 {
463 continue;
464 }
465
466 $insertPosition = array_search($header, $currentHeadersInDefaultPosition, true);
467 array_splice($allUsedColumns, $insertPosition, 0, $header);
468 $changed = true;
469 }
470
471 if ($changed)
472 {
473 $view['columns'] = implode(',', $allUsedColumns);
474 }
475 }
476 unset($view);
477
478 if ($changed)
479 {
480 $sqlValue = $sqlHelper->forSql(serialize($options));
481 $connection->queryExecute(
482 "UPDATE b_user_option SET VALUE = '{$sqlValue}' WHERE ID ='{$optionID}'"
483 );
484 $resetCache = true;
485 }
486 }
487
488 if ($resetCache)
489 {
490 Application::getInstance()->getManagedCache()->cleanDir('user_option');
491 }
492 }
493
494 private static function isCloud(): bool
495 {
496 return Loader::includeModule('bitrix24');
497 }
498
499 private static function isCrmIncluded(): bool
500 {
501 return Loader::includeModule('crm');
502 }
503
504 private static function hasAccess(): bool
505 {
506 $accessController = AccessController::getCurrent();
507
508 return (
509 $accessController->check(ActionDictionary::ACTION_CATALOG_READ)
510 && $accessController->check(ActionDictionary::ACTION_CATALOG_SETTINGS_ACCESS)
511 );
512 }
513}
$connection
Определения actionsdefinitions.php:38
$accessController
Определения options.php:23
const STATUS_YES
Определения product.php:66
const TYPE_EMPTY_SKU
Определения product.php:75
const TYPE_SET
Определения product.php:71
const TYPE_SKU
Определения product.php:72
const TYPE_FREE_OFFER
Определения product.php:74
const STATUS_NO
Определения product.php:67
const TYPE_OFFER
Определения product.php:73
const STATUS_DEFAULT
Определения product.php:68
const TYPE_PRODUCT
Определения product.php:70
static enable(array $options=[])
Определения enabler.php:24
Определения error.php:15
$options
Определения commerceml2.php:49
</td ></tr ></table ></td ></tr >< tr >< td class="bx-popup-label bx-width30"><?=GetMessage("PAGE_NEW_TAGS")?> array( $site)
Определения file_new.php:804
global $USER_FIELD_MANAGER
Определения attempt.php:6
$result
Определения get_property_values.php:14
$platform
Определения settings.php:7
$value
Определения Param.php:39
$eventManager
Определения include.php:412