Imagine: an online store with 200 orders per day. Each shipment requires an invoice, an act, and a tax invoice. Managers spend 10 to 20 minutes per order on manual data entry. Multiply by the number of orders, and you get up to 67 hours per month — almost two working weeks of one employee. Automatic generation of shipping documents in 1C-Bitrix reduces this time to seconds, eliminating input errors. For a typical store with 200 orders/day, automation saves approximately 350,000 rubles annually, reducing document processing time by 99%. Error rates drop by 95%. We are a team with over 8 years of experience in 1C-Bitrix development (CMS and Bitrix24). Over that time, we have implemented more than 120 projects, including integrations with 1C, CRM, and payment gateways. Configuring automated document creation is one of the frequent tasks we solve within 3-5 days. Get a consultation on your project — automation pays off in 2-3 weeks.
According to Bitrix documentation, the OnSaleStatusOrderChange event is triggered on every order status change.
Why Automate Shipping Document Generation?
Manual creation of documents during shipment is a source of errors and wasted time. The manager enters data from the order into Excel or 1C, makes mistakes in SKUs or prices, and redoes the work. This automation optimizes order management in Bitrix by eliminating the human factor: documents are generated according to set rules when the status changes. This is especially important for stores with a large flow of orders — from 50 per day and above. Errors in documents lead to returns and customer dissatisfaction.
Setting Up Automated Document Creation
The entry point is the OnSaleStatusOrderChange event of the sale module. It is triggered on every status change. Parameters: ORDER_ID, STATUS_ID (new status), OLD_STATUS_ID. The handler is registered in /bitrix/php_interface/init.php or in a module:
AddEventHandler('sale', 'OnSaleStatusOrderChange', 'generateShipmentDoc');
function generateShipmentDoc($orderId, $newStatus, $oldStatus) {
if ($newStatus !== 'S') return;
$order = \Bitrix\Sale\Order::load($orderId);
if (!$order) return;
generateInvoiceForOrder($order);
}
In the new Bitrix API (D7), the event is called OnSaleOrderSaved and passes the order object — it is recommended to use it instead of the deprecated one. It fires on every order save, so you need to additionally check the status change.
The Critical DEDUCTED Check
Not all shipments with an "Shipped" status have actual write-offs. It is critical to check the DEDUCTED='Y' flag, otherwise a document may be generated for a shipment that has not yet been processed by the warehouse. This is a common mistake — we fix it at the audit stage.
Shipment Structure in the Sale Module
A shipment in Bitrix is an object \Bitrix\Sale\Shipment. Each order can have multiple shipments. The b_sale_shipment table stores shipments with fields: ORDER_ID, DELIVERY_ID, STATUS_ID, PRICE_DELIVERY, CURRENCY, DEDUCTED (Y — goods written off from warehouse). Shipment items — b_sale_shipment_item: SHIPMENT_ID, BASKET_ID, QUANTITY, RESERVED_QUANTITY. When generating a shipping document, you must read from b_sale_shipment_item, not from b_sale_basket — with partial shipments, quantities may differ.
| Field | Description |
|---|---|
ORDER_ID |
Order identifier |
DELIVERY_ID |
Delivery service |
STATUS_ID |
Shipment status |
DEDUCTED |
Goods write-off flag |
PDF Invoice Generation
For PDF generation, we use the external mpdf library. Bitrix does not have a built-in PDF generator for documents, but there is a mechanism for print forms via the bitrix:sale.order.invoice component. Programmatic PDF creation via mpdf:
function generateInvoiceForOrder(\Bitrix\Sale\Order $order) {
$shipmentCollection = $order->getShipmentCollection();
$items = [];
foreach ($shipmentCollection as $shipment) {
if ($shipment->isSystem()) continue;
foreach ($shipment->getShipmentItemCollection() as $shipmentItem) {
$basketItem = $shipmentItem->getBasketItem();
$items[] = [
'name' => $basketItem->getField('NAME'),
'quantity' => $shipmentItem->getQuantity(),
'price' => $basketItem->getPrice(),
'sum' => $basketItem->getPrice() * $shipmentItem->getQuantity(),
];
}
}
ob_start();
include __DIR__ . '/templates/invoice.php';
$html = ob_get_clean();
$mpdf = new \Mpdf\Mpdf(['utf-8', 'A4']);
$mpdf->WriteHTML($html);
$pdfContent = $mpdf->Output('', 'S');
$fileId = \CFile::SaveFile([
'name' => 'invoice_' . $order->getId() . '.pdf',
'type' => 'application/pdf',
'content' => $pdfContent,
], 'sale/invoices');
saveInvoiceFile($order->getId(), $fileId);
}
Methods to Save Generated PDFs
Bitrix does not have a standard place for storing order files. Let's compare options:
| Storage Method | Advantages | Disadvantages |
|---|---|---|
| Order property of type "File" | Simple setup | May be lost during updates |
Custom table sale_order_documents |
Core independence, extensibility | Requires SQL migration |
| CRM deal infoblock | CRM integration | Depends on the crm module |
We recommend a custom table — it does not lose data during updates and does not require additional modules. This approach also facilitates Bitrix document export and sale event configuration.
Delivery of Documents to the Manager
After generation, the document is sent to the manager's email or to CRM. Via the OnSaleOrderSaved event, ORDER_ID is available — from it, the responsible manager is taken from b_sale_order (field RESPONSIBLE_ID) and an email is sent via \Bitrix\Main\Mail\Event::send() with a template of type SALE_NEW_ORDER or a custom one. An alternative is integration with the tasks module: when the status changes, a task is created for the manager with a link to the document. The task remains until completion, while an email may be lost.
What's Included in the Setup Work
- Audit of current order statuses and shipment schemes
- Development of a handler according to your logic (statuses, partial shipment)
- PDF document template with layout (name, prices, SKUs, signatures)
- Selection and configuration of file storage location (property, table, CRM)
- Setup of notifications (email, tasks) for managers
- Documentation of the solution and staff training
- Technical support after launch — 1-month guarantee
Implementation Stages
- Analysis — we study the order-shipment chain, identify entry points (statuses, user fields)
- Design — we choose the event, storage table, PDF generation method
- Implementation — we write code, test on a test order
- Testing — we run partial, full, and return shipments
- Deployment — we roll out to production, set up error logging
- Acceptance — we present the result, get feedback
Approximate Timelines
A typical project for one or two shipment statuses — from 3 to 5 business days. Complex schemes with multiple shipments, integration with 1C, and custom templates — up to 2 weeks. The cost is calculated individually after an audit of the current system. Contact us for a free project evaluation and we will offer optimization with no hidden extras.
Common Mistakes and How to Avoid Them
The most common mistake is the lack of checking the DEDUCTED flag. As a result, a document is generated for shipments without actual write-offs. We always check this flag before generation. Another common problem is reading data from b_sale_basket instead of b_sale_shipment_item during partial shipment. The quantity of goods in the cart may differ from the shipped quantity, so we use the b_sale_shipment_item table. It is also important to bind the document template to the shipment type; otherwise, different delivery services will get the same format. Logging all errors is a mandatory requirement for quick diagnostics. Under high load, a lock by order ID is necessary to avoid duplicate generation.
We use these practices in all projects — more than 120 implementations confirm their effectiveness. Order the setup of automatic generation of shipping documents — get a ready-made solution with documentation and support.







