Skip to content

Instantly share code, notes, and snippets.

@dyrkow
Last active November 21, 2023 13:07
Show Gist options
  • Save dyrkow/40c105204eaea574166b424863569850 to your computer and use it in GitHub Desktop.
Save dyrkow/40c105204eaea574166b424863569850 to your computer and use it in GitHub Desktop.
enum PrintableDocumentType {
SELL = 'sell',
PAYBACK = 'payback',
OPEN_SHIFT = 'open_shift',
CLOSE_SHIFT = 'close_shift',
CASH_INCOME = 'cash_income',
CASH_OUTCOME = 'cash_outcome',
PRECHECK = 'precheck',
PACKING_LIST = 'packing_list',
}
export interface ICanBeFiscal {
get isFiscal(): boolean;
}
export abstract class PrintableDocument {
id: Identifier;
type: DocumentType;
date: Date; // Дата формирования документа
user: User; // Пользователь, который составил документ
organization: Organization;
}
export type ReceiptDocumentFiscalization = {
number: number; // Глобальный номер чека
shiftNumber: number; // Номер смены, в которой чек находится
shiftCheckNumber: number; // Порядковый номер чека в смене
qr: string;
url: string;
}
export abstract class ReceiptDocument extends PrintableDocument implements ICanBeFiscal {
positions: DocumentPosition[];
payments: DocumentPayment[];
tax: Tax;
customer: Customer;
fiscalization: ReceiptDocumentFiscalization;
isElectron: boolean;
get isFiscal(): boolean;
}
export class SellDocument extends ReceiptDocument {
type = DocumentType.SELL;
}
export class PaybackDocument extends ReceiptDocument {
type = DocumentType.PAYBACK;
public static createFromSell(): PaybackDocument;
}
export class PrecheckDocument extends ReceiptDocument {
type = DocumentType.PRECHECK;
}
export class PackingListDocument extends ReceiptDocument {
type = DocumentType.PACKING_LIST;
}
export type ReportFiscalization = {
number: number; // Глобальный номер чека
shiftNumber: number; // Номер смены
qr: string;
}
/**
Общий класс документ, отвечающего за отчетную информацию
**/
export abstract class ReportDocument extends PrintableDocument {
number: number; // Не фискальный номер документа (порядковый)
fiscalization: ReportFiscalization;
get isFiscal(): boolean;
}
export class OpenShiftDodument extends ReportDocument {
type = DocumentType.OPEN_SHIFT;
}
export class CloseShiftDocument extends ReportDocuent {
type = DocumentType.CLOSE_SHIFT;
}
/**
Документ для работы с наличными денежными средствами
**/
export abstract class CashDocument extends PrintableDocument {
reason: string; // Причина внесения или изьятия
value: Money;
}
export class CashIncomeDocument extends CashDocument {
type = DocumentType.CASH_INCOME;
// Имеет свои причины внесения
}
export class CashOutcomeDocument extends CashDocument {
type = DocumentType.CASH_OUTCOME;
// Имеет свои причины изьятия
}
/**
* Шаблон печатного документа - это набор секций, определяющих порядок и формат отображения информации на чеке
*
* Шаблоны используется для формировании команд на печать для принтере чеков. Наличие множества чеков
* для одного и того же документа дает возможность настраивать его под различное оборудование или любые другие условия.
*/
type PrintedDocumentTemplate = {
id: string;
/**
* Тип документа определяет к какому чеку относится данный шаблон
*/
type: DocumentType;
sections: {
/**
* Секция заголовка позволяет редактировать отображение
* информации в самом верху чека
*/
header: PrintedDocumentTemplateSection,
/**
* Секция позиции заказа позволяет редактировать отображение
* элемента заказа, его количества, цены и т.д.
*/
position: PrintedDocumentTemplateSection,
/**
* Секция отображает подыток чека, информацию о скидке и т.д.
*/
subtotal: PrintedDocumentTemplateSection,
/**
* Секция отображает общий итог чека
*/
total: PrintedDocumentTemplateSection,
/**
* Секция отобржает размер каждого налога, который указан
* в чеке
*/
tax: PrintedDocumentTemplateSection,
/**
* Секция отображет информацию о размере и форме оплаты по чеку
*/
payment: PrintedDocumentTemplateSection,
/**
* Секция предназначена для отображения дополнительной
* информации в самом низу чека
*/
footer: PrintedDocumentTemplateSection,
/**
* Секция отображает фискальную информацию по чеку
* Тут отображаентся ИНН кассира, ФД, ФП и т.д.
*/
fiscalization: PrintedDocumentTemplateSection,
}
}
/**
* Каждая секция в чеке состоит из набора строк чека
*/
type PrintedDocumentTemplateSection = PrintedDocumentTemplateLine[];
/**
* Строка секции определяет поочередность отображения
* полей чека. В одной строке может быть несколько полей.
*/
type PrintedDocumentTemplateLine = PrintedDocumentTemplateField[];
enum FieldType {
STATIC = 'static',
DYNAMIC = 'dynamic'
}
enum DisplayType {
TEXT = 'text', // Отображает значение как текстовую строку
QR = 'qr', // Отображает значение поля как QR код
BARCODE = 'barcode' // Отображает значение поля как штрихкод
}
/**
* Поле чека - это структурный блок, из которых формируется отображение данных в строке
*
* Поля могут быть статическими и динамическими
* Статические - это поля, которые не изменяются от чека к чеку
* Динамические - это поля, которые для каждого чека свои
*/
type PrintedDocumentTemplateField = {
type?: FieldType;
value: string; // статические - произвольная Строка
prefix?: string;
postfix?: string;
display?: DisplayType;
barcodeType?: 'ean13' | 'ean8' // Используется когда надо отобразить контент в виде barcode-да
};
// TODO: как бы с полями как-то удобнее, можно сделать нормальный редактор, можно много настроек добавить
// и это будет работать даже быстрее вроде, так как не надо искать подстроки какие-то
// Секция - набор строк данных сгруппированных по определенному смыслу
type DocumentSection {
sort: number; // определяем порядок секций
type: DocumentSectionType;
lines: DocumentLine[];
}
// Строка - это упорядоченный набор полей данных о документе
type DocumentLine {
sort: number;
fileds: DocumentField[];
}
// Поле - состоит из названия и значения определенного свойства документа
type DocumentField {
name: string;
value: string;
}
// Значние поля - это строка, которую можно привести в
// Uppercase, Lowercase, замаксировать значение, скрывать поле, если значение пустое
// ограничить ширину поля значения
// символ до поля, символ после поля - чтобы ставить двоеточие, или символ после значения
// Так же некоторым полям можно настроить формат чисел, дробных чисел, склько цифр после запятой и тд
// Но это значит, что у полей есть типы или категории, с различными наборами свойств
// Документы печатаются на чековой ленте
// Ленты бывают разной ширины:
// - 44мм
// - 57мм
// - 80мм
// На каждую ленту помещается определенное количество символов
// или определенное количество пикселей (изображения)
type DocumentTemplate = {
type: DocumentType; // Тип документа
header: PrintableLine[]; // Шапка документа
footer: PrintableLine[]; // Подвал подкумента
}
type ReceiptDocumentTemplate = DocumentTemplate && {
position: PrintableLine[]; // строчки отображения позиции чека
subtotal: PrintableLine[]; // Подытог
total: PrintableLine[]; // строчки отображения общей стоимости чека
tax: PrintableLine[]; // строчки по налогу чека
payment: PrintableLine[]; // строчки отображения оплаты
fiscalization: PrintableLine[]; // строчки отображения фискальной информации
customer: PrintableLine[]; // Отображение информации о клиенте заказа
delivery: PrintableLine[]; // Отображение информации о доставке
}
/**
%title% - заголовок
%document.name% - название чека (кассовый чек, пречек)
%document.value% - приход/возврат
%position.number%
%position.name%
%position.cost% - со скидкой
%position.price% - без скидки
%position.quantity% - количество
%position.measure% - символ единицы измерения
%position.amount% - сумма позиции
%currency% - символ валюты
%tax.name%
%tax.symbol%
%sign_calculation.method% - признак способа расчета
%sign_calculation.object% - признак предмета расчете
%payment.name% - название оплаты
%payment.amount% - размер оплаты
%cashier.name%
%cashier.inn%
%fiscaliztion.zn_kkt%
%organization.inn%
%fiscaliztion.rn_kkt%
%fiscaliztion.fn%
%fiscaliztion.fd%
%fiscaliztion.fpd%
%fiscaliztion.qr_code%
%fiscaliztion.ofd%
%datetime%
%total.amount% - сколько к оплате
%total.received% - сколько было получено наличных денег
%total.chang% - размер сдачи
*/
/**
* Нужно создать штуку, которая будет заполнять шаблон данными заменяя плейсхолдеры
движок плейсхолдеров
*
заполненный шаблоне по идее уже представляет из себя чек/команду на печать которую можно передавать устройству для печати.
/
interface ITemplateEngine<T> {
process(template: DocumentTemplate, document: Document): T;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment