Шаблон чека

Шаблон имеет строго определённую, но расширяемую структуру.
Описание шаблона задаётся в формате JSON и содержит обязательные поля и переменные.

Базовая структура шаблона HTML-чека

{
  "width": 80,
  "margin_left": 0,
  "margin_right": 0,
  "img_id": 0,
  "show_storno_position": true,
  "strikeout_storno_position": true,
  "show_storno_payment": true,
  "strikeout_storno_payment": true,
  "variables": {
    "change": "(сдача)",
    "type_sale": "Продажа",
    "type_return": "Возврат",
    "tax_without_vat": "Без НДС"
  },
  "header": [...],
  "positions": [...],
  "position_totals": [...],
  "payments": [...],
  "payment_totals": [...],
  "footer": [...]
}

Глобальные поля шаблона

  • width — ширина ленты чека в миллиметрах
    (например, 80 для 80-мм термоленты, 58 — для 58-мм и т.п.).

  • margin_left — левое поле чека в миллиметрах.
    В HTML воспринимается как внутренний отступ (padding-left) всего блока чека.

  • margin_right — правое поле чека в миллиметрах.
    В HTML воспринимается как padding-right.
    Также левое и правое поля учитываются при расчёте ширины строки в символах для маркеров <SF>, <DF> и т.п.

  • img_id — идентификатор логотипа (изображения) в базе.
    Если img_id > 0, логотип загружается один раз и может выводиться в строках, где show_img = true.

  • show_storno_position (true / false) — показывать ли сторнированные позиции номенклатуры.

  • strikeout_storno_position (true / false) — зачёркивать ли сторнированные позиции.
    Работает только вместе с show_storno_position = true.

  • show_storno_payment (true / false) — показывать ли сторнированные оплаты.

  • strikeout_storno_payment (true / false) — зачёркивать ли сторнированные оплаты.
    Работает только вместе с show_storno_payment = true.

  • variables — текстовые константы, используемые в подстановках:

    • change — текст, добавляемый к типу оплаты для сдачи ((сдача) по умолчанию);
    • type_sale — текст для <doc.type> в документах продажи ("Продажа");
    • type_return — текст для <doc.type> в документах возврата ("Возврат");
    • tax_without_vat — текст для позиций без НДС ("Без НДС").

Базовые элементы шаблона

Каждый элемент массивов header, positions, position_totals,
payments, payment_totals, footer — объект примерно такого вида:

{
  "text": "Строка текста с переменными",
  "font": "Lucida Console, 10pt, style=bold",
  "interval": -30,
  "alignment": 1,
  "show_img": false,
  "img_width": 0,
  "img_height": 0,
  "barcode_height": 0,
  "barcode_module": 0,
  "barcode_show_text": false,
  "barcode_type": 0
}
Общие поля элемента
  • text — текст строки. Может содержать:

    • переменные <doc.*>, <pos.*>, <payment.*>;
    • спец-маркеры заполнения <SF>, <DF>, <UF>, <EF>, <PF>, <AF>;
    • обычный текст.
  • font — описание шрифта:

    • название шрифта, размер (Npt), стиль (style=bold, style=italic и т.п.);
    • в примерах используется моноширинный шрифт:
    "Lucida Console, 10pt"
    "Lucida Console, 10pt, style=bold"
    "Lucida Console, 8pt"

    Рекомендуется использовать моноширинный шрифт (как Lucida Console),
    так как маркеры <SF>/<DF>/… рассчитаны именно на одинаковую ширину символа.

  • interval — вертикальный «шаг» между строками. Может быть:

    • положительным — строки раздвигаются;
    • нулевым — стандартный интервал;
    • отрицательным (как в реальном шаблоне, -30) — строки визуально «поджимаются» ближе друг к другу.

    Подбор значения interval — чисто визуальная настройка.
    В твоём шаблоне для компактного чека везде стоит -30.

  • alignment — выравнивание:

    • 0 — по левому краю;
    • 1 — по центру;
    • 2 — по правому краю.

    В реальном шаблоне:

    • заголовки и итоги — alignment: 1 (по центру),
    • строки с товарами — alignment: 0 (слева),
    • суммы по позиции — alignment: 2 (справа).
  • show_img — если true, в этой строке будет выводиться глобальный логотип (img_id), а text игнорируется.

  • img_width, img_height — размеры логотипа в пикселях (используются при show_img = true).

  • barcode_height, barcode_module, barcode_show_text, barcode_type — настройки штрих-кода / QR-кода (см. отдельный раздел).

Перенос строк

Поведение по переносу текста:

  • Строки с товаром (где в text есть <pos.item.name>) — могут переноситься на следующую строку, если название длинное.

  • Все остальные строки (суммы, итоги, тип оплаты, служебные надписи) — выводятся как одна строка без переноса.
    Если текст слишком длинный, он будет визуально обрезан, поэтому такие строки лучше делать короткими.

Это заложено в логике HTML-рендера и не настраивается в шаблоне.
Поддержке достаточно знать: «переносится только название товара, всё остальное — компактные строки».


Спец-маркеры заполнения

Для красивого выравнивания по ширине строки используются маркеры:

  • <SF> — заполнение пробелами;
  • <DF> — символами -;
  • <UF> — символами _;
  • <EF> — символами =;
  • <PF> — символами +;
  • <AF> — символами *.

Принцип:

  1. В шаблоне ставится маркер, например:

    "Всего:<SF><pos.total.price2>"
  2. При формировании:

    • маркер <SF> удаляется из строки;
    • левая часть ("Всего:") и правая часть ("<pos.total.price2>") раздвигаются пробелами так, чтобы строка заняла «всю» доступную ширину в символах.
  3. Ширина строки в символах выбирается автоматически с учётом:

    • ширины ленты width (80 мм, 58 мм и т.д.);
    • полей margin_left, margin_right;
    • размера шрифта в font.

Для ориентира:

  • для ширины 80 мм и шрифта 10 pt получается примерно 30–35 символов в строку;
  • для меньшей ширины ленты — меньше символов.

В твоём шаблоне маркеры используются, например, так:

{
  "text": "Код:<SF><doc.code>",
  "font": "Lucida Console, 10pt",
  "interval": -30,
  "alignment": 1
}
{
  "text": "Всего:<SF><pos.total.price2>",
  "font": "Lucida Console, 10pt",
  "interval": -30,
  "alignment": 1
}

Изображения (логотип)

Логотип задаётся двумя уровнями:

  1. В корне шаблона:

    "img_id": 0

    Если img_id > 0 — будет загружена соответствующая картинка.

  2. В строке:

    {
     "text": "",
     "font": "",
     "interval": 30,
     "alignment": 1,
     "show_img": true,
     "img_width": 180,
     "img_height": 180
    }
    • show_img: true — выводится логотип по img_id;
    • img_width / img_height — размеры в пикселях.

В твоём текущем шаблоне show_img везде false, то есть логотип пока не выводится,
но структура уже готова и при необходимости можно включить.

Штрих-коды и QR-коды

Если у строки barcode_type > 0, текст превращается в штрих-код/QR-код:

  • из text сначала подставляются переменные <doc.*> / <pos.*> / <payment.*>;
  • по получившейся строке строится изображение кода.

Поля:

  • barcode_height — высота линейного штрих-кода (EAN/Code128) в пикселях;

  • barcode_module — «масштаб» кода:

    • для линейных кодов влияет на ширину и плотность;
    • для QR-кодов — на размер квадратиков и итоговый размер изображения.
  • barcode_show_text — печатать ли текст под линейным штрих-кодом (для QR не применяется).

  • barcode_type:

    • 0 — нет штрих-кода, строка обычная;
    • 1 — EAN13;
    • 2 — EAN8;
    • 3 — Code128;
    • 4 — QR-код.

В твоём реальном шаблоне в footer настроен Code128 по коду документа:

{
  "font": "Lucida Console, 10pt",
  "text": "<doc.code>",
  "barcode_height": 25,
  "barcode_module": 2,
  "barcode_show_text": false,
  "barcode_type": 3,
  "interval": 30,
  "alignment": 1
}

header — заголовок чека (пример из живого шаблона)

"header": [
  {
    "text": "",
    "font": "",
    "interval": 30,
    "alignment": 1,
    "show_img": false,
    "img_width": 180,
    "img_height": 180
  },
  {
    "text": "REGOS",
    "font": "Lucida Console, 20pt, style=bold",
    "interval": 10,
    "alignment": 1
  },
  {
    "text": "Код:<SF><doc.code>",
    "font": "Lucida Console, 10pt",
    "interval": -30,
    "alignment": 1
  },
  {
    "text": "<doc.date><SF><doc.time>",
    "font": "Lucida Console, 10pt",
    "interval": -30,
    "alignment": 1
  },
  {
    "text": "Тип:<SF><doc.type>",
    "font": "Lucida Console, 10pt",
    "interval": -30,
    "alignment": 1
  },
  {
    "text": "Касса:<SF>0000<doc.cash_id>",
    "font": "Lucida Console, 10pt",
    "interval": -30,
    "alignment": 1
  },
  {
    "text": "Смена:<SF><doc.session>",
    "font": "Lucida Console, 10pt",
    "interval": -30,
    "alignment": 1
  },
  {
    "text": "Кассир:<SF><doc.cashier_name>",
    "font": "Lucida Console, 10pt",
    "interval": -30,
    "alignment": 1
  },
  {
    "text": "Покупатель:<SF><doc.customer_full_name>",
    "font": "Lucida Console, 10pt",
    "interval": -30,
    "alignment": 1
  },
  {
    "text": "Карта покупателя:<SF><doc.card_barcode>",
    "font": "Lucida Console, 10pt",
    "interval": -30,
    "alignment": 1
  },
  {
    "text": "Номер тел. покупателя:<SF><doc.customer_main_phone>",
    "font": "Lucida Console, 10pt",
    "interval": -30,
    "alignment": 1
  },
  {
    "text": "<DF>",
    "font": "Lucida Console, 10pt",
    "interval": -30,
    "alignment": 1
  }
]

Основные переменные:

  • doc.code — код документа;
  • doc.date — дата;
  • doc.time — время;
  • doc.type — тип (Продажа / Возврат);
  • doc.cash_id — идентификатор кассы;
  • doc.session — код смены;
  • doc.cashier_name — кассир;
  • doc.customer_full_name — покупатель;
  • doc.card_barcode — карта покупателя;
  • doc.customer_main_phone — телефон покупателя.

Если данных по карте нет, строки с <doc.customer_full_name>, <doc.card_barcode>, <doc.customer_main_phone> не выводятся.

positions — список позиций (пример из живого шаблона)

"positions": [
  {
    "text": "<pos.n>. <pos.item.name>[<pos.item.unit>]",
    "font": "Lucida Console, 10pt",
    "interval": -30,
    "alignment": 0
  },
  {
    "text": "<pos.quantity> x <pos.price> = <pos.amount>",
    "font": "Lucida Console, 8pt",
    "interval": -30,
    "alignment": 2
  },
  {
    "text": "в т.ч. НДС <pos.vat_amount> ",
    "font": "Lucida Console, 8pt",
    "interval": -30,
    "alignment": 2
  }
]

Что выводится:

  • первая строка — номер, название и единица измерения;
  • вторая — количество × цена = сумма;
  • третья — сумма НДС по позиции.

Перенос строки возможен только в первой строке (где есть <pos.item.name>).

position_totals — итоги по позициям (пример из живого шаблона)

"position_totals": [
  {
    "text": "<DF>",
    "font": "Lucida Console, 10pt",
    "interval": -30,
    "alignment": 1
  },
  {
    "text": "Всего:<SF><pos.total.price2>",
    "font": "Lucida Console, 10pt",
    "interval": -30,
    "alignment": 1
  },
  {
    "text": "Скидки:<SF><pos.total.discount>",
    "font": "Lucida Console, 10pt",
    "interval": -30,
    "alignment": 1
  },
  {
    "text": "К оплате:<SF><pos.total.price>",
    "font": "Lucida Console, 10pt, style=bold",
    "interval": -30,
    "alignment": 1
  },
  {
    "text": "<DF>",
    "font": "Lucida Console, 10pt",
    "interval": -30,
    "alignment": 1
  }
]

Переменные:

  • pos.total.price2 — сумма без скидок;
  • pos.total.discount — размер скидки по чеку;
  • pos.total.price — сумма с учётом скидки.

Все строки выровнены по центру (alignment: 1), а суммы дотягиваются маркером <SF>.

payments — список оплат (пример из живого шаблона)

"payments": [
  {
    "text": "<payment.type_name><SF><payment.value>",
    "font": "Lucida Console, 10pt",
    "interval": -30,
    "alignment": 1
  }
]
  • payment.type_name — тип оплаты (Наличные, Банковская карта и т.д.).
    Для сдачи к названию автоматически добавляется variables.change, например:
    "Наличные (сдача)".

  • payment.value — сумма оплаты.

Сторнированные оплаты обрабатываются по флагам show_storno_payment / strikeout_storno_payment.

payment_totals — итоги по оплатам (пример из живого шаблона)

"payment_totals": [
  {
    "text": "<DF>",
    "font": "Lucida Console, 10pt",
    "interval": -30,
    "alignment": 1
  },
  {
    "text": "Оплачено:<SF><payment.total.payed_value>",
    "font": "Lucida Console, 10pt, style=bold",
    "interval": -30,
    "alignment": 1
  },
  {
    "text": "Сдача:<SF><payment.total.change_value>",
    "font": "Lucida Console, 10pt, style=bold",
    "interval": -30,
    "alignment": 1
  },
  {
    "text": "<DF>",
    "font": "Lucida Console, 10pt",
    "interval": -30,
    "alignment": 1
  }
]
  • payment.total.payed_value — общая сумма внесённых оплат;
  • payment.total.change_value — сумма сдачи (по модулю).
"footer": [
  {
    "font": "Lucida Console, 10pt",
    "text": "<doc.code>",
    "barcode_height": 25,
    "barcode_module": 2,
    "barcode_show_text": false,
    "barcode_type": 3,
    "interval": 30,
    "alignment": 1
  },
  {
    "text": "Спасибо за покупку",
    "font": "Lucida Console, 10pt, style=bold",
    "interval": -30,
    "alignment": 1
  }
]

В подвале:

  • штрих-код чека по doc.code (Code128, без подписи);
  • текст благодарности.

Доступны те же переменные, что и в header.