Отчёты: DSL и JavaScript¶
Типовой отчёт в Каяле — это форма (ReportForm в *.form), логика на C# (BaseService) и макет .tcr. Для новых отчётов логику можно описать декларативно в той же форме или скриптом рядом с ней. И то и другое выполняется на сервере (запросы и CreateReport). Клиентский ScriptAction / DeclareScript для генерации отчёта не подходит.
Сложные отчёты (ABC, прайс с динамическими колонками, свод касса+банк) по-прежнему пишутся на C#.
Порядок использования¶
- C#
ReportBuilder— укоротить существующий сервис без смены языка. - JavaScript рядом с формой или
System.ExecuteScript. - XML
<Report>внутриReportForm, кнопка вызывает сервисReportEngine.
1. C# helper¶
var rb = new ReportBuilder(this);
var groups = ReportBuilder.GroupsFromLines(linesList, lines,
new ReportGroupMap("Склады", "Склад"),
new ReportGroupMap("Товары", "Товар", showGoodGroups, groupsCount));
var criteria = CreateRestQuery("Остатки товаров").Sum("Количество").Sum("Сумма").OnDate(date);
foreach (var field in ReportGroups.FieldNames(groups))
criteria.Select(field);
rb.WhereInDict(criteria, "Товар", "Товары", goods);
var layout = rb.Create("ОстаткиТоваров.tcr").Header().Set("ДатаНа", date).Table();
Деньги: ReportBuilder.Div, Pct, Neg — не делить decimal через JS number.
2. JavaScript¶
Файл Остатки товаров.js в work folder (имя = имя формы) или блок:
<ReportForm Name="Остатки товаров" DefaultServiceName="ReportEngine">
...
<ReportScript File="Остатки товаров.js" Method="Run" />
</ReportForm>
Скрипт:
/// <reference path="../Scripts/kayala-report.d.ts" />
function Run(p) {
report.build({
template: "ОстаткиТоваров.tcr",
query: {
source: "Остатки товаров",
mode: "rest",
onDate: p.Date,
sums: ["Количество", "Сумма"],
groups: {
from: p.Lines,
order: p.LinesList,
map: {
"Склады": { field: "Склад" },
"Товары": { field: "Товар", hierarchy: p.ShowGoodGroups, levels: p.GroupsCount }
}
},
filters: [
{ field: "Товар", dict: "Товары", values: p.Goods },
{ field: "Склад", dict: "Склады", values: p.Subdivs }
]
},
header: { ДатаНа: p.Date },
columns: {
Кол: "Количество",
Цена: "div(Сумма, Количество)",
Сум: "Сумма"
}
});
}
Глобалы: p (параметры формы), report.build, div / pct / neg / names. Формулы колонок — строка div(Сумма, Количество) или функция function (row) { return div(row.num("Сумма"), row.num("Количество")); }. Не писать row.num("Сумма") / row.num("Количество").
Режимы запроса:
mode |
Хост |
|---|---|
rest |
CreateRestQuery + OnDate |
turnover |
CreateTwoDatesRestQuery + OnDates, итоги +| / -| |
query |
QueryCriteria + период from/to |
Песочница: форма «Выполнить скрипт» вызывает System.ExecuteScript (ScriptCode, опционально ScriptMethod).
3. XML DSL¶
<ReportForm Name="Остатки товаров" DefaultServiceName="ReportEngine">
<Button Label="#Common/Generate" IsDefault="true">
<Event EventType="Click">
<ServiceAction MethodName="Run" />
</Event>
</Button>
<!-- UI: Date, Lines, Goods, ... -->
<Report Template="ОстаткиТоваров.tcr" Source="Остатки товаров" Mode="Rest" OnDate="[Date]">
<Sum Field="Количество" />
<Sum Field="Сумма" />
<Groups From="[Lines]" OrderFrom="[LinesList]">
<Map Value="Склады" Field="Склад" />
<Map Value="Товары" Field="Товар" Hierarchy="[ShowGoodGroups]" Levels="[GroupsCount]" />
</Groups>
<Filter Param="Goods" Field="Товар" Dictionary="Товары" />
<Filter Param="Subdivs" Field="Склад" Dictionary="Склады" />
<HeaderParam Name="ДатаНа" From="Date" />
<HeaderParam Name="Товары" NamesOf="Goods" Dictionary="Товары" />
<Column Name="Кол" Field="Количество" />
<Column Name="Цена" Expr="div(Сумма, Количество)" />
<Column Name="Сум" Field="Сумма" />
<Footer FromTotals="true" />
</Report>
</ReportForm>
ReportEngine.Run копирует все параметры формы (AcceptFormParams) и подставляет FormName. Автоотчёты тоже передают FormName.
Expr колонки: имя поля, div(a,b), pct(a,b), neg(a), вложенные вызовы.
VS Code¶
В корне work folder (Base):
jsconfig.json—checkJs,target ES5Scripts/kayala-report.d.ts— автодополнениеreport.build,p.Date
В скрипте отчёта:
/// <reference path="../Scripts/kayala-report.d.ts" />
Отладка: console.log / report.writeToConsole, форма «Выполнить скрипт», превью запроса. Breakpoint DAP для NiL.JS не подключён.
Что не входит в DSL/JS v1¶
Нулевые остатки, бегущий остаток по документам, динамические колонки прайса, ABC, pivot по складам — C# (при желании с ReportBuilder для групп и фильтров).