Files
cc-1c-skills/docs/skd-dsl-spec.md
T
Nick Shirokov 6e3632e5ff revert(skd-decompile): вернуть @normal shorthand-флаг
Раньше при наличии явного <viewMode>Normal</viewMode> decompile
переводил filter item в полноценный object form. Это раздувало JSON
без причины — @normal в shorthand функционально эквивалентен
"viewMode": "Normal" в object form, и compile уже его парсит.

Теперь: object form триггерится только реальными причинами
(userSettingPresentation, value-массив, dcscor:Field валуетайп);
явный Normal сохраняется как @normal в shorthand. Object form
по-прежнему может содержать "viewMode": "Normal" — это равнозначно.

Compile-side изменений не требуется. Spec обновлён.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-22 18:41:57 +03:00

1160 lines
49 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# JSON DSL для схемы компоновки данных (СКД)
Компактный JSON-формат для описания `DataCompositionSchema` (Template.xml).
Компилируется навыком `/skd-compile` в XML, валидируется `/skd-validate`.
---
## 1. Корневая структура
```json
{
"dataSources": [...],
"dataSets": [...],
"dataSetLinks": [...],
"calculatedFields": [...],
"totalFields": [...],
"parameters": [...],
"templates": [...],
"groupTemplates": [...],
"settingsVariants": [...]
}
```
**Умолчания:**
- `dataSources` опущен → авто-создаётся `{ "name": "ИсточникДанных1", "type": "Local" }`
- `source` в наборе опущен → первый dataSource
- `name` набора опущен → "НаборДанных1", "НаборДанных2"...
- `settingsVariants` опущен → один вариант "Основной" с детальной группировкой и `selection: ["Auto"]`
---
## 2. Источники данных (dataSources)
```json
"dataSources": [
{ "name": "ИсточникДанных1", "type": "Local" }
]
```
| Поле | Обязат. | Умолчание | XML-маппинг |
|------|---------|-----------|-------------|
| `name` | да | — | `<name>` |
| `type` | нет | `"Local"` | `<dataSourceType>` |
Значения `type`: `"Local"`, `"External"`.
---
## 3. Наборы данных (dataSets)
Тип определяется по ключу-дискриминатору:
| Ключ | Тип | xsi:type |
|------|-----|----------|
| `query` | Запрос | `DataSetQuery` |
| `objectName` | Объект | `DataSetObject` |
| `items` | Объединение | `DataSetUnion` |
### DataSetQuery (самый частый)
```json
{ "name": "Продажи", "query": "ВЫБРАТЬ ...", "fields": [...], "autoFillFields": false }
```
### DataSetObject
```json
{ "name": "ТаблицаПроверки", "objectName": "ТаблицаПроверки", "fields": [...] }
```
### DataSetUnion
```json
{
"name": "Объединение",
"items": [
{ "name": "Набор1", "query": "...", "fields": [...] },
{ "name": "Набор2", "query": "...", "fields": [...] }
],
"fields": [...]
}
```
| Поле | Обязат. | Описание |
|------|---------|----------|
| `name` | нет | Авто: "НаборДанных1"... |
| `source` | нет | Имя dataSource (авто: первый) |
| `query` | да* | Текст запроса (DataSetQuery). Поддерживает `@file` — см. ниже |
| `objectName` | да* | Имя объекта (DataSetObject) |
| `items` | да* | Вложенные наборы (DataSetUnion) |
| `fields` | нет | Массив полей |
| `autoFillFields` | нет | `false` — отключить автозаполнение (по умолчанию не выводится = true) |
### Ссылка на внешний файл запроса (@file)
Вместо inline-текста запроса можно указать путь к внешнему файлу с префиксом `@`:
```json
{ "query": "@queries/sales.sql" }
```
Порядок разрешения пути:
1. Абсолютный путь — используется как есть
2. Относительно директории JSON-файла определения
3. Относительно текущей рабочей директории (CWD)
4. Если файл не найден — ошибка компиляции
---
## 4. Поля — shorthand и объектная форма
### Shorthand-строка
```
"<dataPath>[: <type>] [@role...] [#restrict...]"
```
Примеры:
```json
"fields": [
"Наименование",
"Количество: decimal(15,2)",
"Организация: CatalogRef.Организации @dimension",
"Служебное: string #noFilter #noOrder",
"Счёт: CatalogRef.Хозрасчетный @account",
"Сумма: decimal(15,2) @balance",
"СуммаНач: decimal(15,2) @balance balanceGroupName=Сумма balanceType=OpeningBalance"
]
```
### Объектная форма
```json
{
"dataPath": "Сумма",
"field": "Сумма",
"title": "Сумма продаж",
"type": "decimal(15,2)",
"role": { "dimension": true },
"restrict": ["noFilter", "noGroup"],
"attrRestrict": ["noFilter"],
"appearance": { "Формат": "ЧДЦ=2" },
"presentationExpression": "Формат(Сумма, \"ЧДЦ=2\")",
"orderExpression": { "expression": "ЕстьNULL(Поле.Порядок, 10000)", "orderType": "Asc", "autoOrder": false },
"availableValues": [
{ "value": 1, "presentation": { "ru": "Доход", "en": "Income" } },
{ "value": 2, "presentation": { "ru": "Расход", "en": "Expense" } }
]
}
```
`availableValues` — список допустимых значений поля с (опциональной multilang) подписью. Типы значений автоопределяются (`bool`/`decimal`/`dateTime`/`string`); можно указать `valueType` явно. Аналогичное поле существует на `parameters` — см. раздел 6.
### Парсинг shorthand
1. Извлечь `@`-роли (regex `@(\w+)`), `#`-ограничения (`#(\w+)`), KV-пары роли (`(\w+)=(\S+)`)
2. Остаток до первого `:``dataPath``field` по умолчанию)
3. После `:` — тип
### Типы
| DSL | XML v8:Type | Квалификатор |
|-----|-------------|--------------|
| `string` | `xs:string` | Length=0, AllowedLength=Variable |
| `string(N)` | `xs:string` | Length=N, AllowedLength=Variable |
| `decimal(D,F)` | `xs:decimal` | Digits=D, FractionDigits=F, AllowedSign=Any |
| `decimal(D,F,nonneg)` | `xs:decimal` | Digits=D, FractionDigits=F, AllowedSign=Nonnegative |
| `boolean` | `xs:boolean` | — |
| `date` | `xs:dateTime` | DateFractions=Date |
| `dateTime` | `xs:dateTime` | DateFractions=DateTime |
| `CatalogRef.XXX` | `d5p1:CatalogRef.XXX` | inline xmlns:d5p1 |
| `DocumentRef.XXX` | `d5p1:DocumentRef.XXX` | inline xmlns:d5p1 |
| `EnumRef.XXX` | `d5p1:EnumRef.XXX` | inline xmlns:d5p1 |
| `ChartOfAccountsRef.XXX` | `d5p1:ChartOfAccountsRef.XXX` | inline xmlns:d5p1 |
| `StandardPeriod` | `v8:StandardPeriod` | — |
> **Ссылочные типы** (`CatalogRef.XXX`, `DocumentRef.XXX` и др.) эмитируются с inline namespace declaration: `<v8:Type xmlns:d5p1="http://v8.1c.ru/8.1/data/enterprise/current-config">d5p1:CatalogRef.XXX</v8:Type>`. Использование префикса `cfg:` вместо `d5p1:` с объявлением namespace приводит к ошибке XDTO. Сборка EPF со ссылочными типами требует базу с соответствующей конфигурацией (не пустую).
### Синонимы типов
Все имена типов регистронезависимые. Поддерживаются русские и альтернативные имена:
| Синоним | Канонический тип |
|---------|-----------------|
| `число`, `Число` | `decimal` |
| `строка`, `Строка` | `string` |
| `булево`, `Булево`, `bool` | `boolean` |
| `дата`, `Дата` | `date` |
| `датаВремя`, `ДатаВремя` | `dateTime` |
| `СтандартныйПериод` | `StandardPeriod` |
| `int`, `integer`, `number`, `num` | `decimal` |
| `СправочникСсылка.XXX` | `CatalogRef.XXX` |
| `ДокументСсылка.XXX` | `DocumentRef.XXX` |
| `ПеречислениеСсылка.XXX` | `EnumRef.XXX` |
| `ПланСчетовСсылка.XXX` | `ChartOfAccountsRef.XXX` |
| `ПланВидовХарактеристикСсылка.XXX` | `ChartOfCharacteristicTypesRef.XXX` |
Параметризованные: `число(15,2)``decimal(15,2)`, `строка(100)``string(100)`.
### Роли
Принимаются четыре формы:
```json
"role": "dimension" // одиночный флаг
"role": ["dimension", "required"] // массив флагов
"role": "balance balanceGroupName=Сумма balanceType=OpeningBalance" // shorthand
"role": { "balance": true, "balanceGroupName": "Сумма", "balanceType": "OpeningBalance" }
```
Shorthand-формат может быть встроен прямо в shorthand поля:
```
"Сумма: decimal(15,2) @balance balanceGroupName=Сумма balanceType=OpeningBalance"
```
**Парсинг shorthand**: `@(\w+)` → boolean флаги; `(\w+)=(\S+)` → строковые KV; остаток — `dataPath[: type]`.
**Поддерживаемые ключи**:
| Категория | Ключи |
|-----------|-------|
| `@`-флаги (boolean) | `@dimension`, `@account`, `@balance`, `@period`, `@required`, `@autoOrder`, `@ignoreNullValues` |
| Строковые KV | `balanceGroupName`, `balanceType` (`OpeningBalance`/`ClosingBalance`), `parentDimension`, `accountTypeExpression`, `expression`, `orderType` (`Asc`/`Desc`), `periodNumber`, `periodType` |
Whitelist'а нет — любой `<dcscom:KEY>` принимается; перечисленные — типичные. `@period` — sugar для `periodNumber=1` + `periodType=Main` (можно переопределить явно).
**XML-выход**: `<dcscom:KEY>true</dcscom:KEY>` для флагов; `<dcscom:KEY>VALUE</dcscom:KEY>` для KV.
> Устаревший ключ `balanceGroup` в object-форме принимается как alias для `balanceGroupName` (имя элемента в реальном XML — `balanceGroupName`).
### Ограничения
| DSL shorthand | Объектная форма | XML useRestriction |
|---------------|----------------|-----|
| `#noField` | `"noField"` | `<field>true</field>` |
| `#noFilter` / `#noCondition` | `"noFilter"` | `<condition>true</condition>` |
| `#noGroup` | `"noGroup"` | `<group>true</group>` |
| `#noOrder` | `"noOrder"` | `<order>true</order>` |
### Оформление (appearance)
```json
"appearance": {
"Формат": "ЧДЦ=2",
"ГоризонтальноеПоложение": "Center"
}
```
Маппинг на XML:
```xml
<appearance>
<dcscor:item xsi:type="dcsset:SettingsParameterValue">
<dcscor:parameter>Формат</dcscor:parameter>
<dcscor:value xsi:type="xs:string">ЧДЦ=2</dcscor:value>
</dcscor:item>
</appearance>
```
Значения `ГоризонтальноеПоложение``xsi:type="v8ui:HorizontalAlign"`.
---
## 5. Итоговые поля (totalFields)
### Shorthand
```
"<dataPath>: <Функция>"
"<dataPath>: <Функция>(<выражение>)"
```
Примеры:
```json
"totalFields": [
"Количество: Сумма",
"Цена: Максимум",
"Стоимость: Сумма(Кол * Цена)"
]
```
**Парсинг:** `"A: Func"``dataPath=A`, `expression=Func(A)`. `"A: Func(expr)"``dataPath=A`, `expression=Func(expr)`.
Функции (русские): `Сумма`, `Количество`, `Максимум`, `Минимум`, `Среднее`.
### Объектная форма
```json
{ "dataPath": "X", "expression": "Максимум(X)", "group": "Группа1" }
```
### Привязка к группировкам (group)
В объектной форме поле `group` может быть строкой или массивом строк. Каждая строка задаёт имя группировки, для которой вычисляется итог:
```json
"totalFields": [
{ "dataPath": "Кол", "expression": "Сумма(Кол)", "group": ["ГруппаПользователей", "ГруппаПользователей Иерархия", "ОбщийИтог"] }
]
```
XML-маппинг — по `<group>` на каждый элемент:
```xml
<totalField>
<dataPath>Кол</dataPath>
<expression>Сумма(Кол)</expression>
<group>ГруппаПользователей</group>
<group>ГруппаПользователей Иерархия</group>
<group>ОбщийИтог</group>
</totalField>
```
---
## 6. Параметры (parameters)
### Shorthand
```
"<name>: <type> [= <default>] [@autoDates] [@valueList] [@hidden]"
```
Примеры:
```json
"parameters": [
"Период: StandardPeriod = LastMonth @autoDates",
"Организация: CatalogRef.Организации",
"ДатаОтчета: date"
]
```
**Парсинг:** `"A: T = V"``name=A`, `type=T`, `value=V`. Значение `LastMonth` и другие варианты периодов → `v8:StandardPeriod` с `v8:variant`.
### @autoDates
Флаг `@autoDates` в shorthand параметра автоматически генерирует два дополнительных параметра:
- `ДатаНачала` (date, expression=`&<Имя>.ДатаНачала`, availableAsField=false)
- `ДатаОкончания` (date, expression=`&<Имя>.ДатаОкончания`, availableAsField=false)
Заменяет типовой бойлерплейт из 5 строк на 1:
```json
// Было:
"parameters": [
"Период: StandardPeriod = LastMonth",
{ "name": "ДатаНачала", "type": "date", "expression": "&Период.ДатаНачала", "availableAsField": false },
{ "name": "ДатаОкончания", "type": "date", "expression": "&Период.ДатаОкончания", "availableAsField": false }
]
// Стало:
"parameters": ["Период: StandardPeriod = LastMonth @autoDates"]
```
### @valueList
Флаг `@valueList` генерирует `<valueListAllowed>true</valueListAllowed>` — разрешает передавать список значений в параметр:
```json
"parameters": ["Организации: CatalogRef.Организации @valueList"]
```
### @hidden
Флаг `@hidden` — скрытый параметр. Автоматически ставит `availableAsField=false` и исключает параметр из автогенерируемых `dataParameters` при `"dataParameters": "auto"`:
```json
"parameters": [
{ "name": "Счет43", "type": "ChartOfAccountsRef.Хозрасчетный", "value": "...", "hidden": true },
"СкрытыйПараметр: string = test @hidden"
]
```
### Объектная форма
```json
{
"name": "ДатаНач",
"title": "Дата начала",
"type": "date",
"value": "0001-01-01T00:00:00",
"expression": "&Период.ДатаНачала",
"availableAsField": false,
"useRestriction": true,
"use": "Always"
}
```
| Поле | Описание |
|------|----------|
| `name` | Имя параметра |
| `title` | Заголовок (умолч. = name) |
| `type` | Тип (см. таблицу типов) |
| `value` | Значение по умолчанию |
| `expression` | Выражение для вычисления |
| `availableAsField` | `false` — скрыть из полей |
| `valueListAllowed` | `true` — разрешить список значений |
| `hidden` | `true` — скрытый параметр (авто `availableAsField=false`, исключение из `dataParameters: auto`) |
| `useRestriction` | `true` — скрыть от пользователя |
| `use` | `"Always"`, `"Auto"` |
| `denyIncompleteValues` | `true` — запретить произвольные значения (только из availableValues) |
| `availableValues` | Массив `[{value, presentation}]` — допустимые значения с представлениями |
### availableValues
Список допустимых значений параметра. Тип значения определяется автоматически (`Перечисление.*`, `Справочник.*` и др. → `dcscor:DesignTimeValue`):
```json
{
"name": "ПорядокОкругления",
"type": "EnumRef.Округления",
"value": "Перечисление.Округления.Окр1_00",
"use": "Always",
"denyIncompleteValues": true,
"availableValues": [
{"value": "Перечисление.Округления.Окр1_00", "presentation": "руб. коп"},
{"value": "Перечисление.Округления.Окр1", "presentation": "руб."},
{"value": "Перечисление.Округления.Окр1000", "presentation": "тыс. руб"}
]
}
```
### Значения параметров по типу
| Тип | value | XML |
|-----|-------|-----|
| `StandardPeriod` | `"LastMonth"`, `"ThisYear"` и др. | `<v8:variant xsi:type="v8:StandardPeriodVariant">LastMonth</v8:variant>` |
| `date` | `"0001-01-01T00:00:00"` | `xsi:type="xs:dateTime"` |
| `string` | `"текст"` | `xsi:type="xs:string"` |
| `boolean` | `true`/`false` | `xsi:type="xs:boolean"` |
Стандартные варианты периодов: `Custom`, `Today`, `ThisWeek`, `ThisMonth`, `ThisQuarter`, `ThisYear`, `LastMonth`, `LastQuarter`, `LastYear`.
---
## 7. Вычисляемые поля (calculatedFields)
### Shorthand
```
"<dataPath> = <expression>"
```
```json
"calculatedFields": [
"УИД = Строка(Ссылка.УникальныйИдентификатор())",
"Итого = Количество * Цена"
]
```
### Объектная форма
```json
{
"dataPath": "Итого",
"expression": "Количество * Цена",
"title": "Итого",
"type": "decimal(15,2)",
"restrict": ["noGroup"],
"appearance": { "Формат": "ЧДЦ=2" }
}
```
Ключ `field` — алиас для `dataPath` (используется если `dataPath` не указан).
---
## 8. Связи наборов (dataSetLinks)
Только объектная форма:
```json
"dataSetLinks": [
{
"source": "Периоды",
"dest": "Данные",
"sourceExpr": "Месяц",
"destExpr": "Месяц",
"parameter": "НачалоМесяца"
}
]
```
| Поле | XML |
|------|-----|
| `source` | `<sourceDataSet>` |
| `dest` | `<destinationDataSet>` |
| `sourceExpr` | `<sourceExpression>` |
| `destExpr` | `<destinationExpression>` |
| `parameter` | `<parameter>` (опц.) |
---
## 9. Варианты настроек (settingsVariants)
```json
"settingsVariants": [{
"name": "Основной",
"presentation": "Основной вариант",
"settings": {
"userFields": [...],
"selection": [...],
"filter": [...],
"order": [...],
"conditionalAppearance": [...],
"outputParameters": {...},
"dataParameters": [...],
"structure": [...]
}
}]
```
### selection
```json
"selection": [
"Наименование",
{ "field": "Количество", "title": "Кол-во" },
{ "field": "Контрагент", "viewMode": "Inaccessible" },
{ "field": "Скрытое", "use": false },
{ "auto": true, "use": false },
"Auto"
]
```
- Строка → `SelectedItemField`
- `"Auto"``SelectedItemAuto` (только на уровне группировок; на верхнем уровне settings игнорируется)
- Объект с `field` + опц. `title`/`viewMode`/`use``SelectedItemField`. `use: false` = поле выборки отключено (видно в UI, но не применяется)
- Объект `{ auto: true, use: false }` → отключённый `SelectedItemAuto`
- Объект с `folder`/`items``SelectedItemFolder` — группа полей с заголовком и `placement=Auto`:
```json
"selection": [
"Auto",
"Счет",
{"folder": "Поступление", "items": ["ПолеА", "ПолеБ", "ПолеВ"]},
{"folder": "Выбытие", "items": ["ВыбытиеРеализовано", "ВыбытиеПрочее"]}
]
```
### filter
#### Shorthand-строка
```json
"filter": [
"Организация = _ @off @user",
"Дата >= 2024-01-01T00:00:00",
"Статус filled",
"Количество > 0"
]
```
Формат: `"<Поле> <оператор> [<значение>] [@off] [@user] [@quickAccess] [@normal] [@inaccessible]"`.
- Значение `_` — пустое (placeholder, не выводится в XML)
- `@off``use=false`
- `@user``userSettingID=auto` (генерировать GUID)
- `@quickAccess``viewMode=QuickAccess`
- `@normal``viewMode=Normal` (явный — для bit-perfect, см. [viewMode](#viewmode-режим-доступности))
- `@inaccessible``viewMode=Inaccessible`
- Типы значений автоопределяются: `true`/`false` → boolean, `2024-01-01T00:00:00` → dateTime, числа → decimal, `Перечисление.*`/`Справочник.*`/`ПланСчетов.*`/`Документ.*` → DesignTimeValue, прочее → string
- OrGroup: `{"group": "Or", "items": ["условие1", "условие2"]}` — объединяет условия через ИЛИ
#### Объектная форма
```json
"filter": [
{ "field": "Организация", "op": "=", "use": false, "userSettingID": "auto" },
{ "field": "Дата", "op": ">=", "value": "0001-01-01T00:00:00", "valueType": "xs:dateTime" },
{ "field": "СуммаДт", "op": "=", "value": "СуммаКт", "valueType": "dcscor:Field" },
{ "field": "Статус", "op": "in", "value": [1, 3, 5] },
{ "field": "Контрагенты", "op": "in", "value": [], "userSettingID": "auto" },
{ "group": "Or", "items": [
{ "field": "Статус", "op": "=", "value": true, "valueType": "xs:boolean" },
{ "field": "Пометка", "op": "filled" }
], "userSettingID": "auto" }
]
```
| Поле | Описание |
|------|----------|
| `field` | Имя поля |
| `op` | Оператор (см. таблицу) |
| `value` | Правая часть (опц.). См. формы ниже |
| `valueType` | xsi:type для значения (опц.). `"dcscor:Field"` = field-to-field comparison (значение — имя другого поля) |
| `use` | Включён (`true` по умолчанию) |
| `presentation` | Текст подсказки |
| `viewMode` | `"Normal"`, `"QuickAccess"`, `"Inaccessible"` |
| `userSettingID` | `"auto"` → генерировать GUID |
| `userSettingPresentation` | Отображаемое имя настройки (LocalStringType) |
**Формы `value`:**
- Скаляр (`"X"`, `5`, `true`, `"2024-01-01T00:00:00"`) — single `<right>` (стандартный случай). Тип определяется автоматически: bool / число / дата / строка.
- Массив `[a, b, c]` — несколько `<right>` подряд (для `in`/`notIn` с конкретными значениями).
- Пустой массив `[]``<right xsi:type="v8:ValueListType">` placeholder (типичный паттерн для `in` с пользовательскими настройками — значения заполнит пользователь через UI).
Операторы:
| DSL | XML comparisonType |
|-----|--------------------|
| `=` | `Equal` |
| `<>` | `NotEqual` |
| `>` | `Greater` |
| `>=` | `GreaterOrEqual` |
| `<` | `Less` |
| `<=` | `LessOrEqual` |
| `in` | `InList` |
| `notIn` | `NotInList` |
| `inHierarchy` | `InHierarchy` |
| `contains` | `Contains` |
| `notContains` | `NotContains` |
| `beginsWith` | `BeginsWith` |
| `filled` | `Filled` |
| `notFilled` | `NotFilled` |
Группа условий: `{ "group": "And"|"Or"|"Not", "items": [...] }``FilterItemGroup` с `groupType`. Группа также принимает item-level поля `presentation`, `viewMode`, `userSettingID`, `userSettingPresentation` — для регистрации группы как пункта пользовательских настроек.
### order
```json
"order": [
"Количество desc",
"Наименование",
{ "field": "Контрагент", "direction": "desc", "viewMode": "Inaccessible" },
"Auto"
]
```
- `"Field"``OrderItemField`, `orderType=Asc`
- `"Field desc"``OrderItemField`, `orderType=Desc`
- `"Field asc"``OrderItemField`, `orderType=Asc`
- `"Auto"``OrderItemAuto` (только на уровне группировок; на верхнем уровне settings игнорируется)
- Объект `{ field, direction?, viewMode? }` — нужен, когда требуется задать `viewMode` (см. [viewMode](#viewmode-режим-доступности))
### conditionalAppearance
Условное оформление — массив правил, каждое задаёт набор полей (selection), условия (filter), параметры оформления (appearance) и мета-атрибуты.
```json
"conditionalAppearance": [
{
"selection": ["Сумма"],
"filter": ["Сумма > 1000"],
"appearance": { "ЦветТекста": "style:ПросроченныеДанныеЦвет" },
"presentation": "Выделять крупные суммы",
"viewMode": "Normal",
"userSettingID": "auto"
},
{
"filter": ["Статус notFilled"],
"appearance": { "Текст": "Не указано", "ЦветТекста": "web:Gray" },
"presentation": "Скрывать пустые статусы"
}
]
```
| Поле | Описание |
|------|----------|
| `selection` | Массив полей, к которым применяется. Пусто/опущено = все поля |
| `filter` | Условия (shorthand-строки или объекты, как в settings filter) |
| `appearance` | Объект `{ "Параметр": "Значение" }` |
| `presentation` | Описание правила |
| `use` | Включено (`true` по умолчанию) |
| `viewMode` | `"Normal"`, `"QuickAccess"`, `"Inaccessible"` |
| `userSettingID` | `"auto"` → генерировать GUID |
**Типы значений appearance** определяются автоматически:
- `style:XXX`, `web:XXX`, `win:XXX``v8ui:Color`
- `true`/`false``xs:boolean`
- Параметр `Формат`, `Текст` или `Заголовок``v8:LocalStringType`
- Прочее → `xs:string`
Поддержка `use=false` на уровне параметра:
```json
"appearance": {
"ЦветФона": { "value": "web:LightGray", "use": false }
}
```
### outputParameters
```json
"outputParameters": {
"Заголовок": "Мой отчёт",
"ВыводитьЗаголовок": "Output",
"МакетОформления": "ОформлениеОтчетовЧерноБелый"
}
```
Ключ → `dcscor:parameter`, значение → `dcscor:value`.
Типы значений определяются автоматически:
- `"Заголовок"``v8:LocalStringType`
- `"ВыводитьЗаголовок"`, `"ВыводитьПараметрыДанных"`, `"ВыводитьОтбор"``dcsset:DataCompositionTextOutputType`
- `"РасположениеПолейГруппировки"``dcsset:DataCompositionGroupFieldsPlacement`
- `"РасположениеРеквизитов"``dcsset:DataCompositionAttributesPlacement`
- `"ГоризонтальноеРасположениеОбщихИтогов"`, `"ВертикальноеРасположениеОбщихИтогов"``dcscor:DataCompositionTotalPlacement`
- Прочие → `xs:string`
### dataParameters
#### Автогенерация
```json
"dataParameters": "auto"
```
Генерирует записи `dataParameters` для всех не-hidden параметров с `userSettingID`. Скрытые параметры (`hidden: true` / `@hidden`) исключаются.
#### Shorthand-строка
```json
"dataParameters": [
"Период = LastMonth @user",
"Организация @off @user"
]
```
Формат: `"<Имя> [= <значение>] [@off] [@user] [@quickAccess] [@normal] [@inaccessible]"`.
- Значения-варианты периодов (`LastMonth`, `ThisYear` и др.) автоматически оборачиваются в `v8:StandardPeriod`
- `@off``use=false`, `@user``userSettingID=auto`
#### Объектная форма
```json
"dataParameters": [
{ "parameter": "Период", "value": { "variant": "LastMonth" }, "userSettingID": "auto" },
{ "parameter": "Организация", "use": false, "viewMode": "Normal", "userSettingID": "auto", "userSettingPresentation": "Организация отчёта" }
]
```
| Поле | Описание |
|------|----------|
| `parameter` | Имя параметра |
| `value` | Значение (объект `{ "variant": "LastMonth" }` для StandardPeriod, или скаляр) |
| `use` | Включён (`true` по умолчанию) |
| `viewMode` | `"Normal"`, `"QuickAccess"`, `"Inaccessible"` |
| `userSettingID` | `"auto"` → генерировать GUID |
| `userSettingPresentation` | Отображаемое имя настройки (LocalStringType) |
### structure
#### String shorthand (рекомендуется для типичных случаев)
```json
"structure": "Организация > details"
"structure": "Организация > Номенклатура > details"
"structure": "Период > Организация > Номенклатура > details"
```
`>` разделяет уровни вложенности. Каждый сегмент — группировка по указанному полю. `details` (или `детали`) — детальные записи (пустой `groupBy`). Для каждого уровня `selection` и `order` автоматически `["Auto"]`.
#### Массив объектов
```json
"structure": [
{
"type": "group",
"groupBy": ["Организация"],
"children": [
{ "type": "group" }
]
}
]
```
**Умолчания:** `selection` и `order` по умолчанию `["Auto"]` на каждом уровне (в группировках, строках/колонках таблиц, точках/сериях диаграмм). Указывать явно нужно только если требуется другой набор полей.
#### Группировка (group)
| Поле | Описание |
|------|----------|
| `type` | `"group"` |
| `name` | Имя группировки (опц.) |
| `groupBy` | Массив полей. Пусто/опущено = детальные записи |
| `groupType` | `"Items"` (умолч.), `"Hierarchy"`, `"HierarchyOnly"` |
| `selection` | Выборка (умолч. `["Auto"]`) |
| `filter` | Отборы (как в settings) |
| `order` | Сортировка (умолч. `["Auto"]`) |
| `outputParameters` | Параметры вывода (как в settings) |
| `conditionalAppearance` | Условное оформление группы (как в settings) |
| `viewMode` | `"Normal"`, `"QuickAccess"`, `"Inaccessible"` — режим доступности группы в пользовательских настройках |
| `itemsViewMode` | `"Normal"`, `"QuickAccess"`, `"Inaccessible"` — режим доступности подэлементов группы |
| `children` | Вложенные элементы структуры |
Пустой `groupBy` (или `[]`) = детальные записи (без `groupItems` в XML).
#### Таблица (table)
```json
{
"type": "table",
"name": "Таблица",
"rows": [
{ "groupBy": ["Номенклатура"], "selection": ["Auto"], "order": ["Auto"] }
],
"columns": [
{
"name": "Период",
"groupBy": ["Период"],
"filter": ["Сумма > 0"],
"selection": ["Auto"],
"order": ["Auto"],
"outputParameters": { "РасположениеИтогов": "None" },
"userSettingID": "auto",
"userSettingPresentation": { "ru": "Колонка с периодом" }
}
]
}
```
Каждая `column`/`row` принимает те же поля что и `group`: `name`, `groupBy`/`groupFields`, `filter`, `order`, `selection`, `outputParameters`, плюс user-settings — `viewMode`, `userSettingID`, `userSettingPresentation` (регистрация column/row как пункта «Изменить вариант»).
#### Диаграмма (chart)
```json
{
"type": "chart",
"points": { "groupBy": ["Организация"], "order": ["Auto"], "filter": [...] },
"series": { "groupBy": ["Месяц"], "order": ["Auto"] },
"selection": ["Сумма"]
}
```
`points` и `series` принимают те же поля что table column/row (включая `name` и user-settings).
### userFields (пользовательские вычисляемые поля)
Дополнительные поля, которые пользователь может задать в режиме «Изменить вариант» через UI. Хранятся в settings варианта. Два подтипа определяются по содержимому объекта:
**Expression-форма** — поле вычисляется выражением (опционально с разделением для детальных строк и для итогов):
```json
"userFields": [
{
"dataPath": "ПользовательскиеПоля.Поле1",
"title": { "ru": "Отработано дней", "en": "Days worked" },
"detail": {
"expression": "Выбор Когда Группа = ... Тогда ОтработаноДней Иначе 0 Конец",
"presentation": "Выбор Когда Группа = ... Тогда [Отработано дней] Иначе 0 Конец"
},
"total": {
"expression": "Сумма(Выбор Когда Группа = ... Тогда ОтработаноДней Иначе 0 Конец)",
"presentation": "Сумма(Выбор Когда Группа = ... Тогда [Отработано дней] Иначе 0 Конец)"
}
}
]
```
| Поле | Описание |
|------|----------|
| `dataPath` | Путь поля в формате `ПользовательскиеПоля.ПолеN` |
| `title` | Заголовок (строка или multilang dict) |
| `detail.expression` | Выражение для детальных записей |
| `detail.presentation` | Тот же expression с подстановкой `[Имя поля]` (для UI) |
| `total.expression` | Выражение для итоговой строки |
| `total.presentation` | Same для UI |
**Case-форма** — поле принимает разные значения в зависимости от условий:
```json
"userFields": [
{
"dataPath": "ПользовательскиеПоля.Поле1",
"title": { "ru": "Вид продаж" },
"cases": [
{
"filter": ["ХозОперация <> Перечисление.ХозяйственныеОперации.РеализацияВРозницу"],
"value": 2,
"presentation": { "ru": "Только оптовые продажи", "en": "Wholesale only" }
},
{
"filter": ["ХозОперация = Перечисление.ХозяйственныеОперации.РеализацияВРозницу"],
"value": 3,
"presentation": { "ru": "Только розничные продажи", "en": "Retail only" }
}
]
}
]
```
| Поле | Описание |
|------|----------|
| `cases[].filter` | Условие (как в settings filter) |
| `cases[].value` | Значение поля если условие выполнено (типы автоопределяются: bool/decimal/string) |
| `cases[].presentation` | Текст значения для UI (multilang) |
Тип элемента определяется автоматически: наличие `cases``UserFieldCase`, иначе → `UserFieldExpression`.
### viewMode (режим доступности)
`viewMode` управляет доступностью элемента в **пользовательских настройках** отчёта («Изменить вариант…» / «Настройки»). Возможные значения:
| Значение | Семантика |
|----------|-----------|
| `"Normal"` | Пользователь видит и может править (default) |
| `"Inaccessible"` | Скрыто от пользователя, не редактируется |
| `"QuickAccess"` | Вынесено в быстрые настройки (на форму отчёта) |
| `"Auto"` | Автоматический режим (наследование от контейнера) |
Применяется в трёх контекстах:
**1. Item-level** — на отдельном элементе блока (см. описание объектной формы соответствующего раздела):
```json
"filter": [{ "field": "X", "op": "=", "value": "Y", "viewMode": "Inaccessible" }],
"selection": [{ "field": "X", "viewMode": "Inaccessible" }],
"order": [{ "field": "X", "viewMode": "Inaccessible" }],
"conditionalAppearance": [{ "filter": [...], "appearance": {...}, "viewMode": "Inaccessible" }],
"dataParameters": [{ "parameter": "X", "viewMode": "QuickAccess" }]
```
Shorthand-флаги `@inaccessible`, `@quickAccess` доступны для `filter` и `dataParameters` строковых форм.
**2. Block-level** — на самом блоке (внутри `settings`). Управляет доступностью всей группы как пункта пользовательских настроек:
```json
"settings": {
"selectionViewMode": "Inaccessible",
"filterViewMode": "Inaccessible",
"orderViewMode": "Inaccessible",
"conditionalAppearanceViewMode": "Inaccessible",
"itemsViewMode": "Inaccessible",
"selection": [...],
"filter": [...]
}
```
`itemsViewMode` на settings — общий режим для всех подэлементов варианта (`<dcsset:itemsViewMode>` в XML).
**3. Structure item** — на элементе структуры (`group`):
```json
{ "type": "group", "groupBy": ["Организация"], "viewMode": "Inaccessible", "itemsViewMode": "Inaccessible" }
```
**4. Table axis / chart axis** — на самой `column`/`row`/`points`/`series`. Через те же поля `viewMode`, `userSettingID`, `userSettingPresentation` (см. раздел Таблица).
#### Стратегия сохранения
Платформа эмитит `viewMode` непоследовательно: в одних местах `<viewMode>Normal</viewMode>` присутствует явно (когда элемент — пункт пользовательских настроек), в других — нет. Для bit-perfect round-trip:
- `skd-decompile` сохраняет `viewMode` в JSON **точно как было в XML**, включая явный `"Normal"` если он физически присутствовал.
- `skd-compile` эмитит `<viewMode>` только если значение задано в JSON (без `implicit Normal`-подстановки).
При компиляции JSON, написанного с нуля моделью, `viewMode` опускается → платформа применит default `Normal` при загрузке схемы.
---
## 10. Макеты и привязки (templates, groupTemplates)
### templates — компактный DSL (рекомендуемый)
Табличное описание шаблона вывода. Содержимое задаётся через `rows`, оформление — через именованный пресет `style`.
```json
"templates": [
{
"name": "Макет1",
"style": "header",
"widths": [36, 33, 16, 17],
"minHeight": 24.75,
"rows": [
["Виды кассы", "Валюта", "Остаток на начало\nпериода", "Остаток на\nконец\nпериода"],
["|", "|", "|", "|"],
["К1", "К2", "К3", "К4"]
]
},
{
"name": "Макет2",
"style": "data",
"widths": [36, 33, 16, 17],
"rows": [["{ВидКассы}", "{Валюта}", "{ОстатокНачало}", "{ОстатокКонец}"]],
"parameters": [
{ "name": "ВидКассы", "expression": "Представление(СчетМеждународногоУчета)" },
{ "name": "ОстатокНачало", "expression": "ОстатокНаНачалоПериода" }
]
},
{
"name": "Макет3",
"style": "total",
"widths": [36, 33, 16, 17],
"rows": [["Итого", "Х", "{ОстатокНачало}", "{ОстатокКонец}"]],
"parameters": [
{ "name": "ОстатокНачало", "expression": "ОстатокНаНачалоПериода" }
]
}
]
```
#### Свойства шаблона
| Свойство | Описание |
|----------|----------|
| `name` | Имя макета (ссылаются groupTemplate) |
| `rows` | Массив строк; каждая строка — массив ячеек |
| `style` | Именованный пресет оформления (по умолчанию `"data"`) |
| `widths` | Массив ширин колонок (применяется ко всем строкам) |
| `minHeight` | Минимальная высота первой строки (для шапок) |
| `parameters` | Параметры макета — выражения для подстановки (поддерживают `drilldown`) |
#### Синтаксис ячеек
| Значение | Описание |
|----------|----------|
| `"текст"` | Статический текст (`v8:LocalStringType`) |
| `"{Имя}"` | Параметр шаблона (`dcscor:Parameter`), задаётся через `parameters` |
| `"\|"` | Вертикальное объединение с ячейкой выше (`ОбъединятьПоВертикали`) |
| `">"` | Горизонтальное объединение с ячейкой слева (`ОбъединятьПоГоризонтали`) |
| `null` | Пустая ячейка (без содержимого) |
#### Встроенные пресеты стилей
| Пресет | Фон | Шрифт | Выравнивание | Перенос | Рамки |
|--------|-----|-------|-------------|---------|-------|
| `header` | ReportHeaderBackColor | Arial 10 | Center | да | Solid 1px |
| `data` | ReportGroup1BackColor | Arial 10 | — | нет | Solid 1px |
| `subheader` | — | Arial 10 | Center | да | Solid 1px |
| `total` | — | Arial 10 | — | нет | Solid 1px |
#### Пользовательские пресеты (skd-styles.json)
Файл `skd-styles.json` в директории определения или в корне проекта. Переопределяет встроенные пресеты или добавляет новые:
```json
{
"header": {
"bgColor": "style:ReportHeaderBackColor",
"borderColor": "style:ReportLineColor",
"bold": true
},
"myStyle": {
"font": "Arial", "fontSize": 12,
"bgColor": "#FFE0E0"
}
}
```
Допустимые ключи: `font`, `fontSize`, `bold`, `italic`, `hAlign`, `vAlign`, `wrap`, `bgColor`, `textColor`, `borderColor`, `borders`. Недостающие ключи берутся из пресета `data`.
Формат цветов: `"style:ИмяСтиля"` (ссылка на стиль платформы) или `"#RRGGBB"` (прямой цвет).
### templates — raw XML (fallback)
Для нестандартных случаев — raw XML вставляется как есть:
```json
"templates": [
{
"name": "Макет1",
"template": "<raw XML dcsat:AreaTemplate>",
"parameters": [
{ "name": "ТипЦены", "expression": "Представление(ТипЦен)" }
]
}
]
```
Детект: если есть `rows` — используется компактный DSL, иначе — raw XML из `template`.
#### Расшифровка (drilldown) в параметрах шаблона
Ключ `drilldown` в параметре шаблона автоматически генерирует:
1. `DetailsAreaTemplateParameter` с именем `Расшифровка_<значение>`, `fieldExpression` по полю `ИмяРесурса`, `mainAction=DrillDown`
2. Привязку `Расшифровка` в appearance ячеек, ссылающихся на этот параметр через `{Имя}`
```json
"parameters": [
{ "name": "Сырье", "expression": "ПоступлениеСырья", "drilldown": "ПоступлениеСырья" }
]
```
### groupTemplates
```json
"groupTemplates": [
{ "groupName": "ДанныеОтчета", "templateType": "GroupHeader", "template": "Макет1" },
{ "groupField": "Счет", "templateType": "Header", "template": "Макет2" },
{ "groupField": "Счет", "templateType": "OverallHeader", "template": "Макет3" }
]
```
| Ключ | Описание |
|------|----------|
| `groupField` | Привязка к полю группировки → `<groupField>` |
| `groupName` | Привязка к именованной группировке в структуре варианта → `<groupName>` |
| `templateType` | `Header` / `OverallHeader``<groupTemplate>`, `GroupHeader``<groupHeaderTemplate>` |
| `template` | Имя макета |
---
## 11. Полный пример — минимальный
```json
{
"dataSets": [
{
"name": "НаборДанных1",
"query": "ВЫБРАТЬ\n\tНоменклатура.Наименование КАК Наименование,\n\tКОЛИЧЕСТВО(1) КАК Количество\nИЗ\n\tСправочник.Номенклатура КАК Номенклатура\nСГРУППИРОВАТЬ ПО\n\tНоменклатура.Наименование",
"fields": [
{ "dataPath": "Наименование", "title": "Наименование" },
"Количество"
]
}
],
"totalFields": ["Количество: Сумма"],
"settingsVariants": [{
"name": "Основной",
"settings": {
"selection": ["Наименование", "Количество"],
"structure": [{ "type": "group" }]
}
}]
}
```
## 12. Полный пример — средний (с shorthand v2)
```json
{
"dataSets": [
{
"name": "Продажи",
"query": "ВЫБРАТЬ\n\tПродажи.Организация,\n\tПродажи.Номенклатура,\n\tПродажи.Количество,\n\tПродажи.Сумма\nИЗ\n\tРегистрНакопления.Продажи КАК Продажи\n{ГДЕ\n\tПродажи.Период >= &ДатаНачала\n\tИ Продажи.Период < &ДатаОкончания}",
"fields": [
"Организация: СправочникСсылка.Организации @dimension",
"Номенклатура: СправочникСсылка.Номенклатура @dimension",
"Количество: число(15,3)",
"Сумма: число(15,2)"
]
}
],
"totalFields": ["Количество: Сумма", "Сумма: Сумма"],
"parameters": [
"Период: СтандартныйПериод = LastMonth @autoDates"
],
"settingsVariants": [{
"name": "Основной",
"presentation": "Продажи по организациям",
"settings": {
"selection": ["Номенклатура", "Количество", "Сумма", "Auto"],
"filter": ["Организация = _ @off @user"],
"order": ["Сумма desc", "Auto"],
"outputParameters": {
"Заголовок": "Анализ продаж",
"ВыводитьЗаголовок": "Output"
},
"dataParameters": ["Период = LastMonth @user"],
"structure": "Организация > details"
}
}]
}
```
**Сравнение с v1:** средний пример сократился с 58 до 33 строк (−43%). Основная экономия: `@autoDates` (4 строки), structure shorthand (9 строк), filter/dataParam shorthand (4 строки).