Нормативно визначені макети
Деякі документи мають макет, встановлений нормативно: платіжна інструкція, касовий ордер, форма з визначеним переліком полів. Для них макет не є дизайнерським рішенням, тож форма друку має це відображати. Рушій пропонує два способи побудувати такий макет. Використовуйте перший. Другий існує для випадку, коли сама геометрія визначена нормативно.
create-print-form (у .claude/skills/ вашого репозиторію) містить повну таблицю атрибутів і діагностику. Ця
сторінка пояснює, коли нормативна форма відрізняється і який інструмент обрати.
Більшості нормативних форм достатньо рамки й ролей
Нормативний документ у еталонній конфігурації — це звичайна форма друку з трьома відмінними вибором:
Frame = PrintFrame.None. Ні фірмового бланка, ні рядка параметрів. Платника або компанію називає блок сторони, тож бланк повторював би її. Смуга нижнього колонтитула все одно малюється.- Чернетки.
Forbiddenдля документа, який взагалі не можна друкувати як чернетку, тож друк відхиляється.Markedдля того, який можна друкувати як чернетку, з позначкою. - Без таблиці, якщо документ її не має. Форма, що складається лише зі сторін, реквізитів і підсумків, просто
не має
[PrintTable]. Не додавайте колекцію-заглушку, щоб її заповнити.
Решта — той самий словник, що й у будь-якій формі друку: сторони, реквізити, Note, GrandTotal, Currency,
підписи і VatMode.
Робочий приклад: платіжна інструкція
Платіжна інструкція (PaymentInstructionPrintForm, «Платіжна інструкція») — це нормативний документ еталонної
конфігурації без таблиці. Її не надсилають банку на папері. Це те, що користувач передруковує в клієнт-банк.
Оплачені документи на ній не друкуються, і фірмового бланка в неї немає:
[PrintForm(Frame = PrintFrame.None, Drafts = DraftPrinting.Marked)]
[PrintTitle("PaymentInstructionPrintTitle")]
public sealed class PaymentInstructionPrintForm : DocumentPrintForm
{
[Caption("Payer")]
public required PrintParty Payer { get; set; }
// Null, коли платіж не називає контрагента (комісія банку): блок пропускається.
[Caption("Recipient")]
public PrintParty? Recipient { get; set; }
[PrintRole(PrintRole.Note)]
[Caption("PaymentPurpose")]
public string PaymentPurpose { get; set; } = string.Empty;
// Платіжний документ не робить жодного твердження про ПДВ: сума може містити ПДВ, тож без примітки «Без ПДВ» під сумою прописом.
public PrintVatMode VatMode { get; set; } = PrintVatMode.None;
[PrintRole(PrintRole.GrandTotal)]
public decimal Amount { get; set; }
[PrintRole(PrintRole.Currency)]
public string? CurrencyCode { get; set; }
public IReadOnlyList<PrintSignature> Signatures { get; set; } = [];
}
Кожен вибір має причину:
- Без фірмового бланка. Блок платника — це сама компанія, тож бланк друкував би компанію двічі.
- Без таблиці. Інструкція стосується одного платежу. Документи, які цей платіж погашає, на ній не перелічуються.
VatMode = None. Сума платежу може містити ПДВ, а може й не містити, і «Без ПДВ» було б твердженням, якого платіж не може зробити. ФормаNoneдрукує підсумок і суму прописом, і жодного твердження про ПДВ.Recipient, який може бутиnull. Комісія банку не називає контрагента. Нульова сторона прибирає свій блок, а не друкує порожній.
Касові ордери (прибутковий і видатковий, «ПКО» та «ВКО») мають ту саму будову з Frame = PrintFrame.None і
Drafts = DraftPrinting.Forbidden, бо касовий ордер не можна друкувати як чернетку. Компанія є першою
стороною. Ім'я головного бухгалтера береться з константи, а ім'я касира — з каси. Касовий ордер у стані
чернетки відхиляється в кожному форматі.
Запасний варіант: розділи та стилі
Деякі нормативні форми визначають не лише те, що означає поле, а й де воно стоїть на сторінці. Для них рушій зберігає геометричний словник:
| Область | Атрибут | Що робить |
|---|---|---|
| Клас, повторюваний | [PrintSection(key, Columns = n)] | Секція потоку: сітка з n стовпців «підпис і значення». PositionX, PositionY і PositionWidth прив'язують її до положення на сторінці. |
| Клас, повторюваний | [FixedSection(key, HeightMm = …)] | Зарезервований прямокутник в абсолютних міліметрових координатах, завжди прив'язаний. Його поля друкують по одному рядку «підпис і значення» в порядку оголошення. |
| Клас, повторюваний | [PrintStyle(key)] | Іменований стиль: Align, FontSize, Bold, Italic, Color, BackgroundColor і Borders. Секція чи стовпець користуються ним через StyleKey. |
| Властивість | [PrintSectionRef(key)] | Розміщує скалярну властивість у секції. Явна секція має перевагу над роллю. |
Три правила діють для всіх них:
- У секції немає власного заголовка. Давайте кожному полю відмінний підпис: «IBAN платника» і «IBAN одержувача», а не два «IBAN».
- Ролі, крім
AuditіStatus, всередині[FixedSection]ігноруються. - Використовуйте з ними
Frame = PrintFrame.None. Фірмовий бланк і рядок параметрів не є частиною нормативно визначеного макета.
Жодна форма KandraWms сьогодні не використовує запасний варіант. Рушій малює секції та фіксовані секції, а
його власні тести (SectionsOnlyPrintGeneratorTests і PrintRolesGeneratorTests у Kandra.Tests) є еталоном
синтаксису. Вважайте його неперевіреним у конфігурації, доки жодна форма у вашій конфігурації його не
використовує, і перевіряйте результат за нормативним зразком.
Який інструмент для якої потреби
| Потрібно | Використовуйте |
|---|---|
| Сторони, реквізити, підсумки, підписи | Ролі й типи, як у будь-якій формі друку |
| Без блоку компанії | Frame = PrintFrame.None |
| Абзац вільного тексту під таблицею | [PrintRole(PrintRole.Note)] |
| Твердження про ПДВ, якого не має бути | VatMode = PrintVatMode.None (платіжний документ) |
| Макет, у якому положення полів визначено нормативно | [PrintSection], [FixedSection] і [PrintStyle] |
Перевірка
- Відрендеріть форму й подивіться на сторінку. У рамці
Noneнемає блоку компанії над заголовком, а формаForbiddenне друкує нічого як чернетку. - Для форми
Forbiddenнадрукуйте чернетку й перевірте відповідь 409 зPrintDraftForbiddenException, а не PDF. - Для форми без таблиці експортуйте CSV. Якщо форма не має ні таблиці, ні застарілих секцій, CSV порожній, тож
оголосіть
[SupportedExportFormats(ExportFormat.Pdf)]на Dto документа. - Для форми з секціями перевірте положення кожного поля за нормативним макетом, а не лише те, що поле з'явилося.
Дивіться також
- Форми друку: ролі, рамки й політика чернеток.
- Форми друку документів: частина
OnPrintAsyncі режими ПДВ. - Фірмовий бланк і логотип: блок компанії, який додає форма з бланком, і рамка, яка його прибирає.