27 public static function isUsed(): bool
29 return State::isUsedInventoryManagement();
34 return Option::get(
'catalog',
'once_inventory_management') ===
'Y';
39 Option::set(
'catalog',
'once_inventory_management',
'Y');
46 Option::set(
'catalog',
'once_inventory_management',
'N');
53 return !Catalog\Config\Feature::isInventoryManagementEnabled();
61 return Loader::includeModule(
'crm');
69 if (!self::isCrmExists())
74 return !\CCrmSaleHelper::isWithOrdersMode();
82 return Option::get(
'catalog',
'show_catalog_tab_with_offers') ===
'Y';
89 && !\CCrmSaleHelper::isWithOrdersMode()
90 && !self::isUsedOneC()
96 Option::set(
'catalog',
'default_quantity_trace',
'Y');
97 Option::set(
'catalog',
'default_can_buy_zero',
'Y');
98 Option::set(
'catalog',
'allow_negative_amount',
'Y');
99 Option::set(
'catalog',
'default_use_store_control',
'Y');
100 Option::set(
'catalog',
'enable_reservation',
'Y');
109 if (!self::checkEnablingConditions())
118 self::resetStoreBatch();
120 self::resetCrmReserve();
122 self::installRealizationDocumentTradingPlatform();
126 self::showEntityProductGridColumns();
133 $eventManager = EventManager::getInstance();
135 $eventManager->registerEventHandler(
'sale',
'onBeforeSaleShipmentSetField',
'crm',
'\Bitrix\Crm\Order\EventsHandler\Shipment',
'onBeforeSetField');
140 $eventManager = EventManager::getInstance();
142 $eventManager->unRegisterEventHandler(
'sale',
'onBeforeSaleShipmentSetField',
'crm',
'\Bitrix\Crm\Order\EventsHandler\Shipment',
'onBeforeSetField');
151 if (!self::checkEnablingConditions())
158 self::installRealizationDocumentTradingPlatform();
160 self::showEntityProductGridColumns();
167 if (!self::isCrmExists())
172 Option::set(
'catalog',
'default_use_store_control',
'N');
173 Option::set(
'catalog',
'default_quantity_trace',
'N');
175 if (self::shouldManageQuantityTrace())
183 self::deactivateRealizationDocumentTradingPlatform();
187 if (Loader::includeModule(
'pull'))
189 \CPullWatch::AddToStack(
190 'CATALOG_INVENTORY_MANAGEMENT_CHANGED',
192 'module_id' =>
'crm',
193 'command' =>
'onCatalogInventoryManagementDisabled',
204 $conn->queryExecute(
'truncate table b_catalog_store_product');
205 $conn->queryExecute(
'delete from b_catalog_store_barcode where ORDER_ID is null and STORE_ID > 0');
219 $mainTypes = implode(
229 update b_catalog_product
232 QUANTITY_RESERVED = 0,
238 TYPE in (" . $mainTypes .
")
244 if (!self::isCloud() && self::isSeparateSku())
247 update b_catalog_product
250 QUANTITY_RESERVED = 0,
262 update b_catalog_product
265 QUANTITY_RESERVED = 0,
278 if (!self::isCloud())
283 update b_catalog_product
299 update b_catalog_product
313 if (Loader::includeModule(
'sale'))
317 $conn->queryExecute(
"update b_sale_order_dlv_basket set RESERVED_QUANTITY = 0 where 1 = 1");
318 $conn->queryExecute(
"update b_sale_order_delivery set RESERVED='N' where 1 = 1");
320 $conn->queryExecute(
"truncate table b_sale_basket_reservation_history");
321 $conn->queryExecute(
"truncate table b_sale_basket_reservation");
325 private static function resetCrmReserve(): void
327 if (Loader::includeModule(
'crm'))
330 $conn->queryExecute(
"truncate table b_crm_product_row_reservation");
331 $conn->queryExecute(
"truncate table b_crm_product_reservation_map");
335 private static function resetStoreBatch(): void
346 private static function resetCrmRealizations(): void
348 if (Loader::includeModule(
'crm'))
350 $realizations = ShipmentRealizationTable::getList([
352 '=IS_REALIZATION' =>
'Y',
355 foreach ($realizations as $realization)
357 ShipmentRealizationTable::delete($realization[
'ID']);
358 ShipmentTable::deleteWithItems($realization[
'SHIPMENT_ID']);
368 private static function resetStoreDocuments(): void
370 global $USER_FIELD_MANAGER;
372 $fileIds = Catalog\StoreDocumentFileTable::getList([
'select' => [
'FILE_ID']])->fetchAll();
373 $fileIds = array_column($fileIds,
'FILE_ID');
375 foreach ($fileIds as $fileId)
377 \CFile::Delete($fileId);
380 $documents = Catalog\StoreDocumentTable::getList([
'select' => [
'ID',
'DOC_TYPE']])->fetchAll();
381 foreach ($documents as $document)
383 $typeTableClass = Catalog\Document\StoreDocumentTableManager::getTableClassByType($document[
'DOC_TYPE']);
386 $USER_FIELD_MANAGER->Delete($typeTableClass::getUfId(), $document[
'ID']);
392 $conn->queryExecute(
'truncate table b_catalog_store_docs');
393 $conn->queryExecute(
'truncate table b_catalog_docs_element');
394 $conn->queryExecute(
'truncate table b_catalog_docs_barcode');
395 $conn->queryExecute(
'truncate table b_catalog_store_document_file');
397 if (Loader::includeModule(
'crm'))
399 \Bitrix\Crm\Timeline\TimelineEntry::deleteByAssociatedEntityType(\CCrmOwnerType::StoreDocument);
401 $conn->queryExecute(
"truncate table b_crm_store_document_contractor");
412 self::resetStoreDocuments();
413 self::resetCrmRealizations();
418 $mainTypes = implode(
428 update b_catalog_product
435 TYPE in (" . $mainTypes .
")
442 update b_catalog_product
455 if (!self::isCloud())
460 update b_catalog_product
475 update b_catalog_product
497 $query = $connection->query(
"
498 select cp.ID, (cp.QUANTITY - (sum(csp.AMOUNT) - sum(csp.QUANTITY_RESERVED))) as QUANTITY_DIFFERENCE from b_catalog_product cp
499 inner join b_catalog_store_product csp on cp.ID = csp.PRODUCT_ID
500 inner join b_catalog_store cs on cs.ID = csp.STORE_ID
501 where cp.TYPE in {$productTypes} and (cs.ACTIVE = 'Y')
503 having QUANTITY_DIFFERENCE != 0
512 $query = $connection->query(
"
513 select cp.ID, cp.QUANTITY from b_catalog_product cp
514 left outer join b_catalog_store_product csp on cp.ID = csp.PRODUCT_ID
515 where cp.TYPE in {$productTypes} and csp.PRODUCT_ID is null and cp.QUANTITY != 0
532 $query = $connection->query(
"
533 select ID from b_catalog_product cp
534 where TYPE in {$productTypes} and (QUANTITY != 0 or QUANTITY_RESERVED != 0)
543 $query = $connection->query(
"
544 select ID from b_catalog_store_product csp
545 where AMOUNT != 0 or QUANTITY_RESERVED != 0
559 $iterator = Catalog\StoreDocumentTable::getList([
568 $row = $iterator->fetch();
576 return self::catalogIsEmpty() && self::storeIsEmpty();
579 private static function catalogIsEmpty(): bool
582 $str =
"SELECT ID FROM b_catalog_product WHERE QUANTITY > 0 or QUANTITY_RESERVED > 0 limit 1";
583 $r = $DB->query($str);
585 return !($r->fetch());
588 private static function storeIsEmpty(): bool
591 $str =
"SELECT ID FROM b_catalog_store_product WHERE AMOUNT > 0 limit 1";
592 $r = $DB->query($str);
594 return !($r->fetch());
597 private static function getPortalZone(): string
601 if (Loader::includeModule(
'bitrix24'))
603 if (method_exists(
'CBitrix24',
'getLicensePrefix'))
605 $licensePrefix = \CBitrix24::getLicensePrefix();
606 if ($licensePrefix !==
false)
608 $portalZone = (string)$licensePrefix;
612 elseif (Loader::includeModule(
'intranet'))
614 if (method_exists(
'CIntranetUtils',
'getPortalZone'))
616 $portalZone = \CIntranetUtils::getPortalZone();
623 private static function installRealizationDocumentTradingPlatform(): void
625 if (Loader::includeModule(
'crm'))
627 $platformCode = TradingPlatform\RealizationDocument::TRADING_PLATFORM_CODE;
628 $platform = TradingPlatform\RealizationDocument::getInstanceByCode($platformCode);
629 if (!$platform->isInstalled())
631 $platform->install();
636 private static function showEntityProductGridColumns(): void
638 if (!Loader::includeModule(
'crm'))
651 $allHeaderMap = ProductList::getHeaderDefaultMap();
652 $allHeaders = array_keys($allHeaderMap);
654 $gridId = ProductList::DEFAULT_GRID_ID;
656 $sqlHelper = $connection->getSqlHelper();
657 $queryResult = $connection->query(
658 "SELECT ID, VALUE FROM b_user_option WHERE CATEGORY = 'main.interface.grid' AND NAME = '{$sqlHelper->forSql($gridId)}'"
662 while ($gridSettings = $queryResult->fetch())
664 $optionID = (int)$gridSettings[
'ID'];
665 $value = $gridSettings[
'VALUE'];
671 $options = unserialize($value, [
'allowed_classes' =>
false]);
675 || !isset($options[
'views'])
676 || !is_array($options[
'views'])
683 foreach ($options[
'views'] as &$view)
685 if (!isset($view[
'columns']) || $view[
'columns'] ===
'')
690 $allUsedColumns = explode(
',', $view[
'columns']);
691 $currentHeadersInDefaultPosition = array_values(
692 array_intersect($allHeaders, array_merge($allUsedColumns, $headers))
694 $headers = array_values(array_intersect($allHeaders, $headers));
696 foreach ($headers as $header)
698 if (in_array($header, $allUsedColumns,
true))
703 $insertPosition = array_search($header, $currentHeadersInDefaultPosition,
true);
704 array_splice($allUsedColumns, $insertPosition, 0, $header);
710 $view[
'columns'] = implode(
',', $allUsedColumns);
717 $sqlValue = $sqlHelper->forSql(serialize($options));
718 $connection->queryExecute(
719 "UPDATE b_user_option SET VALUE = '{$sqlValue}' WHERE ID ='{$optionID}'"
730 if (Loader::includeModule(
'pull'))
732 \CPullWatch::AddToStack(
733 'CATALOG_INVENTORY_MANAGEMENT_CHANGED',
735 'module_id' =>
'crm',
736 'command' =>
'onCatalogInventoryManagementEnabled',
742 private static function deactivateRealizationDocumentTradingPlatform()
744 if (Loader::includeModule(
'crm'))
746 $platformCode = TradingPlatform\RealizationDocument::TRADING_PLATFORM_CODE;
747 $platform = TradingPlatform\RealizationDocument::getInstanceByCode($platformCode);
748 if ($platform->isInstalled())
750 $platform->unsetActive();
762 return Loader::includeModule(
'bitrix24');
static getConnection($name="")
static loadMessages($file)