Streamline Document Generation in 1C-Bitrix
A typical scenario: a CRM operator spends 10 minutes generating an invoice in Word, copying data from the order—makes a mistake in the VAT rate, and the document goes to the client. Or an e-commerce store generates hundreds of waybills daily via phpWord, and when the logo changes, every template must be edited individually. 54-FZ requires fiscalization, and errors in requisites lead to fines up to €1,000. We develop a module for Bitrix that systematically solves these problems: templates, variables, versioning, automatic generation based on events.
Problems We Solve
- Document errors: wrong TIN, incorrect amount, missing VAT rate. Manual entry leads to 30% errors—automation reduces error rate to under 1%. The module eliminates human factors: data is pulled directly from the order or deal via providers.
- Slow generation: a manager spends 5–10 minutes per document. With 200 orders per day, that's over 30 hours of work—automation reduces generation to 200–500 ms per document, a 95% time savings. This translates to an average reduction of manual labor costs by €2,000 per month.
- Inconsistent templates: Word documents from different departments use different fonts, margins, headers/footers. The module centralizes templates with versioning—changes apply immediately to all new documents.
- Non-compliance with requirements: missing mandatory fields (KPP, OKTMO, QR code for tax authorities). Variable setup and template validation prevent such omissions.
How the Document Generation Module Works
The module vendor.docgen uses four ORM tables:
-
b_vendor_docgen_template— document templates: id, name, type (order/contract/act/offer), format (docx/pdf), template_file, variables_schema, version, is_active -
b_vendor_docgen_document— generated documents: id, template_id, entity_type, entity_id, file_id (inb_file), status, generated_at, generated_by -
b_vendor_docgen_variable— registered variables: name, source_class, description
Each template contains a JSON variable schema—the module validates that all mandatory fields are present.
Variable System
Variables are wrapped in {{....}}. Substitution is done via data providers registered in the module settings. Example provider for an order:
class OrderVariableProvider implements VariableProviderInterface
{
public function getVariables(int $entityId): array
{
$order = \Bitrix\Sale\Order::load($entityId);
$props = $order->getPropertyCollection();
return [
'ORDER_NUMBER' => $order->getField('ACCOUNT_NUMBER'),
'ORDER_DATE' => $order->getDateInsert()->format('d.m.Y'),
'ORDER_SUM' => number_format($order->getPrice(), 2, ',', ' '),
'ORDER_CURRENCY' => $order->getCurrency(),
'CLIENT_NAME' => $props->getPayerName(),
'CLIENT_INN' => $props->getUserProp('INN')?->getValue(),
'CLIENT_ADDRESS' => $props->getAddress(),
'ITEMS_TABLE' => $this->buildItemsTable($order->getBasket()),
];
}
}
Providers can be written for any entity: CRM deals, leads, user profiles. A typical template contains 20–30 variables; the module does not limit the count.
Why Twig Is Better Than Simple Replacement
Simple str_replace breaks with nested data and tables. Twig provides loops, conditions, filters. Example HTML template:
<h1>Invoice No. {{ORDER_NUMBER}}</h1>
<table>
{% for item in ITEMS %}
<tr>
<td>{{ item.name }}</td>
<td>{{ item.quantity }}</td>
<td>{{ item.price|number_format(2, ',', ' ') }}</td>
</tr>
{% endfor %}
</table>
Twig compiles to cache—performance is on par with manual replacement, but maintaining templates is tens of times easier. More details in the Twig documentation and Wikipedia.
How to Set Up DOCX and HTML Templates
For Word templates we use PhpWord with table row cloning:
$templateProcessor = new \PhpOffice\PhpWord\TemplateProcessor($templatePath);
foreach ($variables as $name => $value) {
if (is_array($value)) {
$templateProcessor->cloneRow('ITEM_NAME', count($value));
foreach ($value as $i => $item) {
$templateProcessor->setValue("ITEM_NAME#{$i}", $item['name']);
$templateProcessor->setValue("ITEM_QTY#{$i}", $item['quantity']);
$templateProcessor->setValue("ITEM_PRICE#{$i}", $item['price']);
}
} else {
$templateProcessor->setValue($name, htmlspecialchars($value));
}
}
$outputPath = '/upload/vendor_docgen/' . uniqid() . '.docx';
$templateProcessor->saveAs($outputPath);
How to Choose a PDF Converter
DOCX is generated quickly, but clients often want PDF. Conversion is the most painful part. Comparison of methods:
| Converter | Quality | Speed | Requirements | Cost |
|---|---|---|---|---|
| LibreOffice headless | Excellent | 1-2 sec | Server installation | Free |
| mPDF | Good | 0.5 sec | PHP extension | Free |
| DocRaptor | Excellent | 1-3 sec | None | $0.01/doc |
Converter choice is a module setting parameter. Default: mPDF for HTML templates, LibreOffice for DOCX. More about mPDF and LibreOffice. Read about the PDF format on Wikipedia.
HTML Templates
Alternative to Word—HTML with CSS. Easier to maintain, no encoding issues. Template is stored in b_vendor_docgen_template in the html_template field. Conversion via Twig and mPDF:
$loader = new \Twig\Loader\ArrayLoader(['doc' => $template['HTML_TEMPLATE']]);
$twig = new \Twig\Environment($loader);
$html = $twig->render('doc', $variables);
$mpdf = new \Mpdf\Mpdf(['mode' => 'utf-8', 'format' => 'A4']);
$mpdf->WriteHTML($html);
$mpdf->Output($outputPath, 'F');
mPDF supports headers/footers, signatures, stamps, QR codes.
How to Ensure Security and Automation
Storage and Access
Generated files are saved via \CFile::SaveFile() into the b_file table. Download link—\CFile::GetPath(). Metadata is stored in b_vendor_docgen_document. Access rights: users download only their own documents, CRM managers download documents of their deals, administrators download all.
Automatic Generation via Events
Documents can be generated on event occurrence:
AddEventHandler('sale', 'OnSaleOrderPaid', ['\Vendor\DocGen\EventHandler', 'onOrderPaid']);
class EventHandler
{
public static function onOrderPaid(\Bitrix\Main\Event $event): void
{
$orderId = $event->getParameter('id');
DocGenerator::generate('invoice', 'sale_order', $orderId);
}
}
Similarly, you can hook to deal closure, user registration, product upload.
What's Included in the Work
As a result, you receive:
- Documentation: Full technical documentation on data providers, variable schema, and extensibility.
- Access: Access to the source code repository and administrative interface for templates.
- Training: 1 hour of online employee training on module usage and template management.
- Support: 30-day support after delivery for bug fixes and questions.
-
Deliverables:
- Working module with ORM tables and installer.
- Set of templates (3–5) for typical documents.
- Documentation on data providers and extensibility.
Process
- Analysis: we study business processes and document requirements.
- Design: module architecture, variable schema, converter selection.
- Development: implementation of the module, creation of templates.
- Integration: setup of events and automatic generation.
- Testing: up to 3 iterations of edits on your server.
- Deployment and training: handover of documentation, employee training.
Estimated Timeline
| Stage | Duration |
|---|---|
| Architecture, ORM tables, installer | 1 day |
| Variable system and data providers | 2 days |
| DOCX generation (PhpWord) | 2 days |
| PDF generation (mPDF or LibreOffice) | 1 day |
| HTML templates via Twig | 1 day |
| Storage, access, download | 1 day |
| Automatic generation via events | 1 day |
| Administrative interface for templates | 2 days |
| Testing | 1 day |
| Total | 12 working days |
Complex document layout with headers/footers, signatures, and stamps adds +2 days.
Investment in the module starts from €1,500 and pays off within 2–3 months, saving up to €2,000 per month in manual labor costs.
Typical Errors During Implementation
- Ignoring validation: if mandatory fields are not checked, a document with empty requisites can be generated. Our module validates the JSON schema before generation.
- Wrong converter choice: mPDF does not support complex tables with merged cells—for such cases LibreOffice is needed. We help choose the optimal option.
- Lack of caching: on each call, the module reads the template from the database. We recommend enabling caching via
\Bitrix\Main\Data\Cache.
Experience and Guarantees
10+ years in Bitrix development, over 50 projects on document automation. We work with templates of any volume—from simple invoices to multi-page contracts with QR codes and digital signatures. Certified 1C-Bitrix specialists. We meet deadlines: 95% of projects delivered on time. Contact us to discuss your project—you will receive a clear specification, timeline, and individual pricing. Order module development and eliminate document errors forever.







