Документация

Печатные бланки: теги и подстановки

Суммы прописью, числа для колонок, реквизиты компании в бланке и счёт на каждый склад — с готовыми кусками разметки.

На этой странице

Счёт, накладная и всё остальное, что магазин печатает по заказу, — это тоже шаблоны: обычная разметка страницы с подстановками из заказа. Правятся они в «Настройки» → «Печатные формы», каждая на своём языке, а кнопка «Посмотреть» показывает готовую бумагу на настоящем заказе — можно ввести номер того заказа, ради которого правка и затевалась.

Бланк пишется теми же тегами, что и тема, плюс несколько своих — денежных.

Деньги, числа и количество

{sum amount=$order.total}                Разом: 1 250,50 ₴
{in_words amount=$order.total}           Одна тисяча двісті п’ятдесят гривень 50 коп.
{number value=$item.price}               1250.50
{number value=$item.weight precision=3}  6.100
{qty value=$item.qty}                    1.5

{sum} берёт валюту самого заказа — писать её в каждом месте бланка не нужно. {number} печатает голое число ровно в сотых: его ставят в колонки, где валюта вынесена в шапку. {qty} печатает количество без хвостовых нулей, чтобы штучный товар не выглядел как «2.000».

Заказ — это снимок: суммы, цены и курс в нём остаются такими, какими были в день оформления. Бланк ничего не пересчитывает, он только печатает.

От какой компании счёт

{profile id=2}                  дальше весь бланк печатается от этой компании
{profile id=2 assign=seller}    реквизиты лягут в $seller, $shop не тронут

Компанию объявляет сам бланк, а не тот, кто нажал «Печать». Поэтому «Счёт от ФОП» и «Счёт от ТОВ» — два разных бланка: выбирать компанию при каждой печати не нужно, да и в письме со счётом выбирать некому. Номер профиля показывает подсказка под редактором, там же его можно вставить нажатием.

Профиль удалили, а бланк на него ссылается — напечатается продавец витрины заказа: пустая шапка счёта хуже неточной.

Что доступно в бланке

Переменная Что внутри
$doc сам документ: number, date, title
$shop продавец: name, legal_name, tax_number, vat_number, tax_system, address, phone, email, bank_name, iban, director, accountant, logo, stamp, signature
$order заказ: number, date, comment, items_total, services_total, discount_total, shipping_total, tax_total, total, paid_total, due, total_in_words, weight, storefront, status
$customer покупатель: name, company, tax_number, phone, email, address
$recipient другой получатель — или null, если посылку принимает сам покупатель
$items позиции заказа, перебираются {foreach}
$warehouses тот же заказ, разложенный по складам
$shipping, $payment доставка и оплата: id, code, name, адрес и точка получения, номер накладной, оплачено и когда

Позиция ($item внутри цикла) даёт n, name, sku, unit, qty, price, discount, total, tax_rate, tax, photo, weight, упаковку (pack.name, pack.packs, pack.rest), характеристики (features, feature), услуги (services) и склад отгрузки (warehouse, warehouse_id).

Полный перечень с человеческими подписями лежит прямо под редактором бланка — «Что можно подставить в бланк»: нажатие вставляет подстановку туда, где стоит курсор. А что пришло в этот конкретный документ, покажет {dump}.

Таблица позиций

<table>
    {foreach $items as $item}
        <tr>
            <td>{$item.n}</td>
            <td>{$item.name}{if $item.sku} ({$item.sku}){/if}</td>
            <td>{qty value=$item.qty} {$item.unit}</td>
            <td>{number value=$item.price}</td>
            <td>{number value=$item.total}</td>
        </tr>
    {/foreach}
</table>

<p>Всього до сплати: {sum amount=$order.total}</p>
<p>Прописом: {in_words amount=$order.total}</p>

Другой получатель — отдельным блоком

{if $recipient}
    <h3>Отримувач</h3>
    <p>{$recipient.name}, {$recipient.phone}</p>

    {* или всё, что магазин спросил у покупателя, — с подписями полей *}
    {foreach $recipient.fields as $f}
        <div>{$f.label}: {$f.value}</div>
    {/foreach}
{/if}

Получатель приходит своим набором, а не подмешивается в поля покупателя: посылку принимает человек, даже когда заказ оформляет компания. Нет другого получателя — переменная пуста, и блок не печатается.

Состав полей получателя владелец задаёт сам, поэтому кроме name и телефона в бланке есть перебираемый список fields — с подписью и значением каждого поля. Отметка «заказ забирает компания» лежит отдельно, в is_company, и в перебор не попадает.

Счёт на каждый склад

Магазину, у которого склады принадлежат разным юрлицам, нужен счёт от того, чей товар в строке. Заказ приходит в бланк разложенным по складам, а компанию для каждого объявляет {profile}:

{$fops = [1 => 2, 5 => 3, 6 => 4]}   {* номер склада → номер профиля *}

{foreach $warehouses as $w}
    {profile id=$fops[$w.id] assign=seller}

    <h2>{$seller.legal_name}</h2>
    <p>{$seller.address}, {$seller.iban}</p>

    {foreach $w.items as $item}
        <div>{$item.name} — {qty value=$item.qty} × {number value=$item.price}</div>
    {/foreach}

    <p>Разом: {sum amount=$w.total}</p>
{/foreach}

Готовую заготовку этого куска можно вставить из подсказки под редактором — останется вписать свои номера складов и профилей. Доставку и скидку на заказ магазин между складами не делит: как их разнести между юрлицами, решаете вы в самом бланке.

Бумага и печать

Бланк печатается браузером и сохраняется в PDF, поэтому вёрстка простая: таблицы, отступы, размеры в миллиметрах. Размер листа задаётся в стилях бланка:

<style>{literal}
    @page { size: A4 portrait; margin: 12mm; }
    body { font-family: Arial, "DejaVu Sans", sans-serif; font-size: 11px; }
{/literal}</style>

{literal} здесь обязателен: без него фигурные скобки CSS шаблонизатор примет за свои теги.

Если бланк сломался

Опечатка в разметке не роняет магазин: вместо документа откроется страница с объяснением, в какой форме ошибка. Кнопка «Вернуть заводской вид» возвращает бланк, который идёт с магазином, — ваши правки при этом заменяются, отменить это нельзя.

Тем же способом смотрят, что нового появилось в заводском бланке после обновления магазина: ваши правки обновление не трогает, поэтому свежий бланк виден только так.

Обновлено 24 августа 2026