Setting up inventory through 1C-Bitrix

Our company is engaged in the development, support and maintenance of Bitrix and Bitrix24 solutions of any complexity. From simple one-page sites to complex online stores, CRM systems with 1C and telephony integration. The experience of developers is confirmed by certificates from the vendor.
Our competencies:
Development stages
Latest works
  • image_website-b2b-advance_0.png
    B2B ADVANCE company website development
    1212
  • image_bitrix-bitrix-24-1c_fixper_448_0.png
    Website development for FIXPER company
    815
  • image_bitrix-bitrix-24-1c_development_of_an_online_appointment_booking_widget_for_a_medical_center_594_0.webp
    Development based on Bitrix, Bitrix24, 1C for the company Development of an Online Appointment Booking Widget for a Medical Center
    565
  • image_bitrix-bitrix-24-1c_mirsanbel_458_0.webp
    Development based on 1C Enterprise for MIRSANBEL
    747
  • image_crm_dolbimby_434_0.webp
    Website development on CRM Bitrix24 for DOLBIMBY
    657
  • image_crm_technotorgcomplex_453_0.webp
    Development based on Bitrix24 for the company TECHNOTORGKOMPLEKS
    980

Setting Up Inventory Count in 1C-Bitrix

Inventory breaks at the verification stage: system shows 50 units, physically there are 47. Someone manually adjusts inventory via b_catalog_product, bypassing document flow. After a week, discrepancies accumulate again, history disappears.

Inventory count document

Inventory in Bitrix is a document of type I in b_catalog_docs. Difference from receipt/shipment: document rows specify not delta, but actual quantity. The system itself calculates the difference against accounting balances and applies correction when conducting.

Fields of b_catalog_docs for inventory: DOC_TYPE = 'I', STORE_FROM and STORE_TO simultaneously point to one warehouse (inventory is tied to specific warehouse), STATUS.

Rows in b_catalog_docs_element: AMOUNT — physically counted quantity, AMOUNT_RESERVED — not used in inventory. When conducting, system reads current AMOUNT from b_catalog_store_product for this warehouse, calculates difference and applies it.

Creating an inventory document:

$result = \Bitrix\Catalog\StoreDocumentTable::add([
    'DOC_TYPE' => \Bitrix\Catalog\StoreDocumentTable::TYPE_STORE_ADJUSTMENT,
    'STATUS' => 'N',
    'STORE_TO' => 1,
    'TITLE' => 'Inventory ' . date('m.d.Y'),
    'DATE_DOCUMENT' => new \Bitrix\Main\Type\DateTime(),
]);

TYPE_STORE_ADJUSTMENT — constant for type I.

Collecting actual balances

The problem with inventory in Bitrix — no built-in mechanism for staged warehouse walk-through. Standard interface requires entering all items at once. For large warehouses this is inconvenient.

Solution — create document in N status and add rows as you count. While document is in draft, it doesn't affect balances. Rows are added via \Bitrix\Catalog\StoreDocumentElementTable::add(). Already added rows are updated via update() by ID.

To get list of all warehouse products with current accounting balances:

$storeItems = \Bitrix\Catalog\StoreProductTable::getList([
    'filter' => ['STORE_ID' => 1, '>AMOUNT' => 0],
    'select' => ['PRODUCT_ID', 'AMOUNT', 'QUANTITY_RESERVED'],
    'order' => ['PRODUCT_ID' => 'ASC'],
]);

This list serves as basis for printed form for counting. After physical count, actual quantities are entered in document rows.

Conducting and calculating discrepancies

When calling \Bitrix\Catalog\Document\DocManager::conductDocument($docId) for document type I, system for each row:

  1. Reads current accounting balance from b_catalog_store_product.
  2. Compares with actual (AMOUNT from document row).
  3. If actual less — creates shipment (decreases AMOUNT).
  4. If more — creates receipt (increases AMOUNT).
  5. Updates total QUANTITY in b_catalog_product.

Products not in document rows are not affected by inventory. This allows partial inventory — only certain category or warehouse zone.

Zero balances after inventory

If inventory count shows 0 units, row must still be added to document with AMOUNT = 0. Without this, product remains with previous accounting balance. Many forget this — especially when importing actual balances from Excel.

Automatic adding zero rows for all warehouse products:

// Get all warehouse products
$existing = \Bitrix\Catalog\StoreProductTable::getList([
    'filter' => ['STORE_ID' => $storeId, '>AMOUNT' => 0],
    'select' => ['PRODUCT_ID'],
])->fetchAll();

// Add zero rows for missing in document
foreach ($existing as $item) {
    if (!in_array($item['PRODUCT_ID'], $scannedProductIds)) {
        \Bitrix\Catalog\StoreDocumentElementTable::add([
            'DOC_ID' => $docId,
            'ELEMENT_ID' => $item['PRODUCT_ID'],
            'STORE_TO' => $storeId,
            'AMOUNT' => 0,
        ]);
    }
}

History of adjustments

After inventory is conducted, document in b_catalog_docs remains with STATUS = 'Y' and serves as historical record. For audit of discrepancies, it's convenient to query documents by period with difference between accounting and actual quantity — this would require JOIN with b_catalog_store_product at time of conducting, which standard Bitrix doesn't save. For complete audit, you need to add custom table of balance snapshots before conducting.