Razor - це синтаксис розмітки, заснований на технології ASP.NET. В Syrve Razor вбудовується в код xml, який надсилається на принтери.
Схема друку Razor-шаблонів: Data → Razor template → View XML (наша розмітка для друку) → Друк.
У кожного чека своя модель даних. Моделі даних постачаються разом із дистрибутивом Syrve. Усі моделі та шаблони чеків зберігаються у папці \Resources\Cheques\RazorTemplates у котрій знаходиться:
Розберемо на прикладі чека для закінчення приготування.
У файлі TemplateModels.xml є модель CookingCompleteCheque:
<Model Name="CookingCompleteCheque" Comment=“Чек про закінчення приготування страви" TemplateRootModel="true" CommentEn="Cooking complete ticket"> <Include PropertiesGroupId="CommonChequeProperties" /> <Property Name="CookingPlace" Type="RestaurantSection" Nullness="NotNull" Comment=“Місце приготування, для котрого друкується чек" CommentEn="Production place ticket" /> <Property Name="Order" Type="KitchenOrder" Nullness="NotNull" Comment=“Замовлення" CommentEn="Order" /> <Property Name="Item" Type="KitchenOrderItem" Nullness="NotNull" Comment=“Елемент замовлення, для котрого друкується чек" CommentEn="Order item ticket" /> <Property Name="CompoundItemSecondaryComponent" Type="KitchenOrderProductItem" Nullness="CanBeNull" Comment=“Права половинка розділеної піци, для котрої друкується чек"CommentEn="Right half of divided pizza for which ticket is printed" /></Model>
У тезі <Model> є атрибут TemplateRootModel = "true". Він показує, що в елементі <Model> описується модель чека.
У шаблоні чека CookingCompleteCheque.cshtml вкажемо, яку модель використовуємо:
@inherits TemplateBase<ICookingCompleteCheque>
У шаблон можна під'єднати поля і групи полів чека. У прикладі нижче підключена група полів CommonChequeProperties. Описи полів і груп можна знайти в TemplateModels.xml.
include PropertiesGroupId="CommonChequeProperties" />
Властивості Order і Item є об'єктами Syrve POS класів KitchenOrder і KitchenOrderItem, які описані в TemplateModels.xml.
Властивість CookingPlace є об'єктом класу RestaurantSection. Цей тип серверний, тому його опис можна знайти у файлі RmsEntityWrappers.xml.
<Model Name="RestaurantSection" Comment=“Відділення"> <Property Name="Name" Type="string" Nullness="NotNull" Comment=“Назва відділення" /> <Property Name="PrintProductItemCommentInCheque" Type="bool" Comment=“Чи потрібно друкувати коментар до елемента замовлення (страви) в чеку" /> <Property Name="PrintBarcodeInServiceCheque" Type="bool" Comment="Чи потрібно друкувати штрих-код до елемента замовлення (страви) в сервісному чеку" /> <Property Name="DisplayGuests" Type="bool" Comment=“Чи потрібно показувати гостей у даному відділенні" /> <Property Name="PrintSummaryServiceCheque" Type="bool" Comment=“Друкується у відділенні зведений сервісний чек (true) або сервісний чек відділення (false)" /></Model>
Razor-звіти використовують єдину модель даних. Описи об'єктів і шаблони звітів знаходяться в папці \Resources\Reports\Templates у котрій знаходяться наступні файли:
Модель даних Razor-звітів:
Поле моделі[NotNull/CanBeNull] Тип даних Назва поля | Значення |
[NotNull] string Name | Назва звіту |
[CanBeNull] ICashRegister CashRegister | Поточний фіскальний реєстратор |
[CanBeNull] ICafeSession CafeSession | Поточна касова зміна |
DateTime CurrentTime | Поточні дата і час |
[CanBeNull] IUser CurrentUser | Поточний користувач |
[NotNull] IGroup Group | Поточна група |
[NotNull] ICafeSetup CafeSetup | Налаштування точки продажів |
[NotNull] string CurrentTerminal | Назва поточного терміналу |
bool IsOnlyBodyMarkupRequired | Чи потрібна тільки розмітка тіла звіту (для версій 4.0+) |
bool? IsXReportFinal | Чи є X-звіт остаточним для касової зміни (Z-звітом):
|
[CanBeNull] ISettings ReportSettings | Налаштування/параметри звіту |
[NotNull] IEntitiesProvider Entities | Провайдер, що дає доступ до сутностей Syrve POS |
[NotNull] IEventsProvider Events | Провайдер, що дає доступ до подій Syrve POS |
[NotNull] ITransactionsProvider Transactions | Провайдер, що дає доступ до транзакцій Syrve POS |
[NotNull] IOlapReportsProvider OlapReports | Провайдер, що дає доступ до OLAP-звітів сервера |
У моделі звіту поле Entities дає можливість отримати списки різних сутностей Syrve POS (замовлення, операції, типи оплати тощо).
// Отримати всі замовлення, які не видалені та не пов'язані з бронюваннями/банкетами, та котрі не були закриті за касову зміну IEnumerable<IOrder> GetAllNotDeletedNotBoundToNonStartedReservesOrdersBySession([NotNull] ICafeSession session);// Отримати всі не видалені відділення зі столами за групоюIEnumerable<IRestaurantSection> GetAllNotDeletedSectionsWithAnyTablesByGroup([NotNull] IGroup group);// Отримати всі типи оплатIEnumerable<IPaymentType> GetAllPaymentTypes();// Отримати всі системи оплатIEnumerable<IPaymentSystem> GetAllPaymentSystems();// Отримати всі не видалені замовлення доставкиIEnumerable<IDelivery> GetAllNotDeletedDeliveries();// Отримати всі проблемні операціїIEnumerable<ICommonGroup> GetProblemOperationsEvents(bool allTerminalsEvents, DateTime dateBegin, DateTime dateEnd);
У моделі звіту поле Events дає можливість отримати списки різних подій Syrve POS.
// Отримати всі події продажів за касову зміну IEnumerable<IItemSaleEvent> GetItemSaleEventsBySession([NotNull] ICafeSession session);// Отримати всі події внесень та вилучень за касову змінуIEnumerable<IPayInOutEvent> GetPayInOutEventsBySession([NotNull] ICafeSession session);
У моделі звіту поле Transactions дає можливість отримати списки різних транзакцій Syrve POS.
// Отримати всі транзакції оплати замовленьIEnumerable<IOrderPaymentTransaction> GetOrderPaymentTransactions();// Отримати всі транзакції оплати замовлень за касову змінуIEnumerable<IOrderPaymentTransaction> GetOrderPaymentTransactionsBySession([NotNull] ICafeSession session);// Отримати всі фіскальні транзакції внесень та вилучень за касову змінуIEnumerable<IPayInOutFiscalTransaction> GetPayInOutFiscalTransactionsBySession([NotNull] ICafeSession session);// Отримати всі транзакції оплати замовлень з інформацією про закриття замовленняIEnumerable<IOrderPaymentTransaction> GetOrderPaymentTransactionsByOrderCloseInfo([NotNull] IOrderCloseInfo orderCloseInfo);
У моделі звіту поле OlapReports дає можливість отримати дані з серверного OLAP-звіту і вбудувати їх. У цього поля доступні методи:
// Отримати OLAP-звіт відповідно до налаштуваньIOlapReport BuildReport([NotNull] OlapReportSettings reportSettings);// Отримати декілька OLAP-звітів відповідно до списку налаштуваньList<IOlapReport> BuildReports([NotNull] IEnumerable<OlapReportSettings> reportsSettings);
Деякі параметри впливають на дані та розмітку звіту. За допомогою поля ReportSettings у моделі можна отримувати доступи до параметрів в Syrve Office і Syrve POS.
Щоб отримати значення параметра, потрібно знати його ім'я і тип даних. Від типу даних (перерахування, логічна величина, період, рядок, число) залежить те, як значення буде отримано.
Як отримати значення:
var settings = Model.ReportSettings;// Отримати значення перерахування за назвою параметра і порівняти його з одним із значеньif (settings.GetEnum("GroupDishes") == "GroupByDishes") // Згрупувати за стравами
var settings = Model.ReportSettings;// Отримати логічне значення за параметромif (settings.GetBool("ShowOneDishPrice")) // Показати ціну за одиницю страви
var settings = Model.ReportSettings;// Отримати дату початку періодуvar periodBegin = settings.GetPeriodBegin("ReportInterval");// Отримати дату закінчення періодуvar periodEnd = settings.GetPeriodEnd("ReportInterval");
var settings = Model.ReportSettings;// Отримати рядковий параметр “str”var myStr = (string)settings.GetValue("str");
var settings = Model.ReportSettings;// Отримати числовий параметр "number" (де Format - це дробове число або сума)var myNumber = (decimal)settings.GetValue("number");// Отримати числовий параметр "number" (де Format - ціле число)myNumber = (int)settings.GetValue("number");
Додавання і редагування параметрів користувацького звіту описано в статті Звіти Syrve POS.
У чеках і звітах часто використовуються однакові блоки коду: округлення грошових одиниць, форматування дат, ваги, отримання всіх елементів замовлення, суми ПДВ, суми передоплат замовлення тощо. Для уникнення помилок і повторень блоки коду були винесені в окремі методи. Деякі методи можна використовувати тільки для чеків або звітів, а деякі - для того й іншого.
Сигнатура | Опис | Застосування |
string FormatAmount(decimal amount) | Форматування кількості. Ціле значення виводиться без дробової частини, дробове - з точністю до трьох знаків. | Чеки, звіти |
string FormatFoodValueItem(decimal foodValueItem) | Форматування харчової цінності. Ціле значення виводиться без дробової частини, дробове - з точністю до одного знака. | Чеки |
string FormatMoney(decimal money) | Форматування ціни з дробовою частиною. Без роздільників. Довжина дробової частини залежить від (зазначеної в Back Office) валюти. | Чеки |
string FormatPrice(decimal price) | Аналог FormatMoney. | Звіти |
string FormatAmountAndPrice(decimal amount, decimal price) | Форматування кількості та ціни у вигляді АхВ, де А - FormatAmount, В - FormatMoneyMin. | Звіти |
string FormatMoneyMin(decimal money) | Форматування ціни. Ціле значення виводиться без дробової частини, дробове - відповідно до довжини дробової частини поточної (зазначеної в Back Office) валюти. Без роздільників. | Чеки |
string FormatMoneyInWords(decimal money) | Перетворює число і повертає його в рядковій (друкованій) формі. Вказується також повна назва грошових одиниць у правильному відмінюванні. | Чеки |
string FormatPercent(decimal value) | Форматування процентної величини. Ціле значення виводиться без дробової частини, дробове - з точністю до двох знаків. Наприкінці додається символ "%". | Чеки, звіти |
string FormatAveragePercent(decimal percent) | Форматування процентної величини з точністю до одного знака. У кінці додається символ "%". | Звіти |
string FormatAverage(decimal value) | Форматування числа. Ціле значення виводиться без дробової частини, дробове - з точністю до двох знаків. | Звіти |
string FormatTime(DateTime time) | Форматування часу. Виводяться годинник і хвилини в 24-х годинному форматі (HH:mm). | Чеки, звіти |
string FormatLongTime(DateTime time) | Форматування часу. Виводяться годинник, хвилини та секунди у 24-х годинному форматі (HH:mm:ss). | Чеки |
string FormatLongDateTime(DateTime dateTime) | Форматування дати та часу. Виводиться день, місяць, рік, години та хвилини (dd.MM.yyyy HH:mm) | Чеки, звіти |
string FormatFullDateTime(DateTime dateTime) | Форматування дати та часу. Виводяться день, місяць прописом, години та хвилини (d MMM HH:mm). | Чеки |
string FormatDate(DateTime dateTime) | Форматування дати. Виводяться день, місяць і рік (dd.MM.yyyy). | Чеки, звіти |
string FormatDateTimeCustom(DateTime dateTime, string format) | Користувацьке форматування дати/часу. Формат виконується за маскою, що задається другим аргументом функції. | Чеки |
string FormatTimeSpan(TimeSpan timeSpan, bool displaySeconds) | Форматування величини часового інтервалу. Залежно від значення другого параметра секунди відображаються (true) або ні (false) (HH:mm:ss/HH:mm). Якщо секунди не показуються, то вони округлюються до хвилини в більший бік, якщо >=30, інакше в менший бік. | Чеки, звіти |
decimal CalculatePercent(decimal fullValue, decimal partValue) | Обчислює частку partValue по відношенню fullValue у відсотках з точністю до двох знаків. Якщо fullValue дорівнює нулю, то величина відсотка дорівнює нулю. | Чеки |
decimal CalculateDiscountPercent(decimal fullSum, decimal discountSum) | Аналог CalculatePercent | Звіти |
decimal RoundMoney(this decimal value) | Округлення грошових сум відповідно до довжини дробової частини поточної валюти. | Чеки, звіти |
decimal RoundWeight(this decimal value) | Округлення ваги до третього знака після коми. | Чеки, звіти |
decimal GetCost([NotNull] this IChequeTaskSalechequeTaskSale) | Отримати суму для позиції чека. Спрощена формула: ціна * к-ть = сума | Чеки |
decimal GetCost([NotNull] this IOrderEntry orderEntry) | Отримати суму для позиції замовлення. Спрощена формула: ціна * к-ть = сума | Чеки, звіти |
IEnumerable<IOrderEntry> GetAllEntries([NotNull] this IOrder order) | Отримати список усіх позицій замовлення. | Звіти |
IEnumerable<IOrderEntry> ExpandAllEntries([NotNull] this IOrderItem orderItem) | Отримати список усіх дочірніх позицій для елемента замовлення. Сам елемент теж включено в колекцію. | Звіти |
IEnumerable<IOrderEntry> GetChildren([NotNull] this IOrderItem orderItem) | Отримати список усіх дочірніх позицій для елемента замовлення. Сам елемент не включений до колекції. | Звіти |
IEnumerable<IOrderEntry> GetIncludedEntries([NotNull] this IOrder order) | Отримати список усіх невидалених позицій замовлення. | Чеки, звіти |
IEnumerable<IOrderEntry> ExpandIncludedEntries([NotNull] this IOrderItem orderItem) | Отримати список усіх невидалених дочірніх позицій для елемента замовлення. Сам елемент теж включено в колекцію. Якщо сам елемент видалено, то повертається порожня колекція. | Чеки, звіти |
IEnumerable<IOrderEntry> GetNotDeletedChildren([NotNull] this IOrderItem orderItem) | Отримати список усіх невидалених дочірніх позицій для елемента замовлення. Сам елемент не включений до колекції. Якщо сам елемент видалено, то повертається порожня колекція. | Чеки, звіти |
decimal GetVatSumExcludedFromPriceForOrderEntry([NotNull] this IOrderEntry orderEntry, [NotNull] IEnumerable<IDiscountItem> discountItems) | Отримати суму ПДВ, не включеного у вартість, для позиції замовлення. Якщо ПДВ включено у вартість, сума = 0. Потрібно передати в метод список знижок замовлення. | Чеки, звіти |
decimal GetVatSumIncludedInPriceForOrderEntry([NotNull] this IOrderEntry orderEntry, [NotNull] IEnumerable<IDiscountItem> discountItems) | Отримати суму ПДВ, включеного у вартість, для позиції замовлення. Якщо ПДВ не включено у вартість, сума = 0. У метод потрібно передати список знижок замовлення. | Чеки |
decimal GetDiscountSumFor([NotNull] this IDiscountItemdiscountItem, [NotNull] IOrderEntry orderEntry) | Отримати суму знижки для зазначеної знижки та позиції замовлення. | Чеки |
decimal GetDiscountSum([NotNull] this IDiscountItem discountItem) | Отримати суму знижки за всіма невидаленими позиціями замовлення для зазначеної знижки. | Чеки, звіти |
bool IsDiscount([NotNull] this IDiscountItem discountItem) | Чи є зазначена знижка знижкою (а не надбавкою). | Чеки, звіти |
decimal GetFullSum([NotNull] this IOrder order) | Отримати повну суму замовлення без урахування знижок/надбавок, ПДВ, не включеного у вартість. | Чеки, звіти |
decimal GetResultSum([NotNull] this IOrder order) | Отримати суму замовлення з урахуванням знижок/надбавок, ПДВ, не включеного у вартість. | Звіти |
decimal GetResultSumWithoutExcludedVat([NotNull]this IOrder order) | Отримати суму замовлення з урахуванням знижок/надбавок, без урахування ПДВ, не включеного у вартість. | Звіти |
decimal GetCategorizedDiscountsSum([NotNull] this IOrder order) | Отримати суму категоріальних знижок для замовлення. | Чеки |
decimal GetNonCategorizedDiscountsSum([NotNull] this IOrder order) | Отримати суму некатегоріальних знижок для замовлення. | Чеки |
decimal GetVatSumExcludedFromPrice([NotNull] this IOrder order) | Отримати суму ПДВ, не включеного у вартість, для замовлення. Якщо ПДВ включено у вартість, сума = 0. | Чеки, звіти |
decimal GetPrepaySum([NotNull] this IOrder order) | Отримати суму всіх передоплат для замовлення. | Чеки |
decimal GetChangeSum([NotNull] this IOrder order, decimal resultSum) | Отримати суму здачі для замовлення. У метод потрібно передати кінцеву суму. | Чеки |
string GetNameOrEmpty([CanBeNull] this IUser user) | Повертає ім'я користувача, якщо user не порожній, в іншому випадку повертає порожній рядок | Чеки |
string StringView([NotNull] this IAddress address) | Повертає рядкове подання адреси. | Чеки |
string GetKitchenOrDefaultName([NotNull] this IProduct product) | Повертає кухонну назву продукту, якщо вона не порожня, в іншому разі повертає звичайну назву. | Чеки |
bool IsAmountIndependentOfParentAmount([NotNull] this IModifierEntry modifier) | Чи є кількість зазначеного модифікатора незалежною від кількості страви. | Чеки |
IEnumerable<HashSet<IProductItem>> GetNotDeletedProductItemsByMix([NotNull] this IGuest guest) | Повертає список згрупованих за міксом елементів замовлення (страв). У метод потрібно передати гостя. | Чеки |
DateTime GetPeriodBegin([NotNull] this ISettings settings, [NotNull] string name = "ReportInterval") | Повертає "Початок періоду" параметра типу "Період" для налаштувань звіту. Передане значення name - це ім'я параметра в беку. За замовчуванням name = "ReportInterval". | Звіти |
DateTime GetPeriodEnd([NotNull] this ISettings settings, [NotNull] string name = "ReportInterval") | Повертає "Кінець періоду" параметра типу "Період" для налаштувань звіту. Передане значення name - це ім'я параметра в беку. За замовчуванням name = "ReportInterval". | Звіти |
bool GetBool([NotNull] this ISettings settings, [NotNull] string name) | Повертає значення логічної величини параметра типу "Логічна величина (так/ні)". Передане значення name - це ім'я параметра в беку. | Звіти |
string GetEnum([NotNull] this ISettings settings, [NotNull] string name) | Повертає значення перерахування параметра "Перерахування". Передане значення name - це ім'я параметра в беку. | Звіти |
IEnumerable<IUser> GetCounteragents([NotNull] this ISettings settings, [NotNull] string name) | Повертає список контрагентів параметра "Контрагенти". Передане значення name - це ім'я параметра в беку. | Звіти, 4.2+ |
Друк чека або звіту можна скасувати в шаблоні, викинувши OperationCanceledException з текстом винятку. У print-templates.log запишеться повідомлення Template running was canceled. Message: {0}, де {0} - текст винятку, який можна задати в шаблоні.
@inherits TemplateBase<IBillCheque> @{ var order = Model.Order; if (order.Number % 2 == 0) { throw new OperationCanceledException(“Другий чек замовлення не потрібно друкувати"); } }
@inherits TemplateBase<IServiceChequeBase> @helper ThrowException(string message) { throw new OperationCanceledException(message); } <doc bell="" formatter="split"> @if (Model is IServiceCheque) { if (Model.Order.Number % 2 == 0) { @ThrowException(“Не друкуємо сервісний чек для парного замовлення") } @Service((IServiceCheque)Model) } else if (Model is IBanquetServiceCheque) { @Banquet((IBanquetServiceCheque)Model) } else if (Model is IDeleteProductsServiceCheque) { @DeleteProducts((IDeleteProductsServiceCheque)Model) } else if (Model is IDeleteModifiersServiceCheque) { @DeleteModifiers((IDeleteModifiersServiceCheque)Model) } else if (Model is IProductsServeCheque) { @ProductsServe((IProductsServeCheque)Model) } else if (Model is IWholeCourseServeCheque) { @WholeCourseServe((IWholeCourseServeCheque)Model) } else { throw new NotSupportedException(string.Format("Invalid model type '{0}'", Model.GetType())); }</doc>
У Галереї шаблонів можна вибрати та відредагувати чек із уже готових прикладів. Збережіть налаштування шаблону, завантажте його у свій ресторан і починайте користуватися.
Галерея шаблонів знаходиться в Адміністрування → Шаблони чеків.
Якщо потрібно щось змінити, зробіть це у вкладці Текст шаблону. Якщо шаблон буде не основним, зніміть галочку з параметра Основний. Збережіть зміни.