mirror of
https://github.com/Nikolay-Shirokov/cc-1c-skills.git
synced 2026-07-20 01:20:59 +03:00
Merge branch 'dev'
This commit is contained in:
@@ -1,4 +1,6 @@
|
|||||||
param(
|
# epf-add-form v1.0 — Add managed form to 1C processor
|
||||||
|
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||||
|
param(
|
||||||
[Parameter(Mandatory)]
|
[Parameter(Mandatory)]
|
||||||
[string]$ProcessorName,
|
[string]$ProcessorName,
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
param(
|
# epf-add-help v1.0 — Add built-in help to 1C processor
|
||||||
|
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||||
|
param(
|
||||||
[Parameter(Mandatory)]
|
[Parameter(Mandatory)]
|
||||||
[string]$ProcessorName,
|
[string]$ProcessorName,
|
||||||
|
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ allowed-tools:
|
|||||||
|---------------|:------------:|-----------------|--------------------------------------------------|
|
|---------------|:------------:|-----------------|--------------------------------------------------|
|
||||||
| ProcessorName | да | — | Имя обработки |
|
| ProcessorName | да | — | Имя обработки |
|
||||||
| TemplateName | да | — | Имя макета |
|
| TemplateName | да | — | Имя макета |
|
||||||
| TemplateType | да | — | Тип: HTML, Text, SpreadsheetDocument, BinaryData |
|
| TemplateType | да | — | Тип: HTML, Text, SpreadsheetDocument, BinaryData, DataCompositionSchema |
|
||||||
| Synonym | нет | = TemplateName | Синоним макета |
|
| Synonym | нет | = TemplateName | Синоним макета |
|
||||||
| SrcDir | нет | `src` | Каталог исходников |
|
| SrcDir | нет | `src` | Каталог исходников |
|
||||||
|
|
||||||
@@ -45,6 +45,7 @@ pwsh -NoProfile -File .claude/skills/epf-add-template/scripts/add-template.ps1 -
|
|||||||
| Text, текстовый документ, текст | TextDocument | `.txt` | Пустой файл |
|
| Text, текстовый документ, текст | TextDocument | `.txt` | Пустой файл |
|
||||||
| SpreadsheetDocument, табличный документ, MXL | SpreadsheetDocument | `.xml` | Минимальный spreadsheet |
|
| SpreadsheetDocument, табличный документ, MXL | SpreadsheetDocument | `.xml` | Минимальный spreadsheet |
|
||||||
| BinaryData, двоичные данные | BinaryData | `.bin` | Пустой файл |
|
| BinaryData, двоичные данные | BinaryData | `.bin` | Пустой файл |
|
||||||
|
| DataCompositionSchema, СКД, схема компоновки | DataCompositionSchema | `.xml` | Минимальная DCS-схема |
|
||||||
|
|
||||||
## Конвенция именования
|
## Конвенция именования
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
param(
|
# epf-add-template v1.0 — Add template to 1C processor
|
||||||
|
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||||
|
param(
|
||||||
[Parameter(Mandatory)]
|
[Parameter(Mandatory)]
|
||||||
[string]$ProcessorName,
|
[string]$ProcessorName,
|
||||||
|
|
||||||
@@ -6,7 +8,7 @@
|
|||||||
[string]$TemplateName,
|
[string]$TemplateName,
|
||||||
|
|
||||||
[Parameter(Mandatory)]
|
[Parameter(Mandatory)]
|
||||||
[ValidateSet("HTML", "Text", "SpreadsheetDocument", "BinaryData")]
|
[ValidateSet("HTML", "Text", "SpreadsheetDocument", "BinaryData", "DataCompositionSchema")]
|
||||||
[string]$TemplateType,
|
[string]$TemplateType,
|
||||||
|
|
||||||
[string]$Synonym = $TemplateName,
|
[string]$Synonym = $TemplateName,
|
||||||
@@ -23,6 +25,7 @@ $typeMap = @{
|
|||||||
"Text" = @{ TemplateType = "TextDocument"; Ext = ".txt" }
|
"Text" = @{ TemplateType = "TextDocument"; Ext = ".txt" }
|
||||||
"SpreadsheetDocument" = @{ TemplateType = "SpreadsheetDocument"; Ext = ".xml" }
|
"SpreadsheetDocument" = @{ TemplateType = "SpreadsheetDocument"; Ext = ".xml" }
|
||||||
"BinaryData" = @{ TemplateType = "BinaryData"; Ext = ".bin" }
|
"BinaryData" = @{ TemplateType = "BinaryData"; Ext = ".bin" }
|
||||||
|
"DataCompositionSchema" = @{ TemplateType = "DataCompositionSchema"; Ext = ".xml" }
|
||||||
}
|
}
|
||||||
|
|
||||||
$tmpl = $typeMap[$TemplateType]
|
$tmpl = $typeMap[$TemplateType]
|
||||||
@@ -111,6 +114,25 @@ switch ($TemplateType) {
|
|||||||
"BinaryData" {
|
"BinaryData" {
|
||||||
[System.IO.File]::WriteAllBytes($templateFilePath, @())
|
[System.IO.File]::WriteAllBytes($templateFilePath, @())
|
||||||
}
|
}
|
||||||
|
"DataCompositionSchema" {
|
||||||
|
$content = @"
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<DataCompositionSchema xmlns="http://v8.1c.ru/8.1/data-composition-system/schema"
|
||||||
|
xmlns:dcscom="http://v8.1c.ru/8.1/data-composition-system/common"
|
||||||
|
xmlns:dcscor="http://v8.1c.ru/8.1/data-composition-system/core"
|
||||||
|
xmlns:dcsset="http://v8.1c.ru/8.1/data-composition-system/settings"
|
||||||
|
xmlns:v8="http://v8.1c.ru/8.1/data/core"
|
||||||
|
xmlns:v8ui="http://v8.1c.ru/8.1/data/ui"
|
||||||
|
xmlns:xs="http://www.w3.org/2001/XMLSchema"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||||
|
<dataSource>
|
||||||
|
<name>ИсточникДанных1</name>
|
||||||
|
<dataSourceType>Local</dataSourceType>
|
||||||
|
</dataSource>
|
||||||
|
</DataCompositionSchema>
|
||||||
|
"@
|
||||||
|
[System.IO.File]::WriteAllText($templateFilePath, $content, $encBom)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
# --- 3. Модификация корневого XML ---
|
# --- 3. Модификация корневого XML ---
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
param(
|
# epf-init v1.0 — Init 1C external data processor scaffold
|
||||||
|
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||||
|
param(
|
||||||
[Parameter(Mandatory)]
|
[Parameter(Mandatory)]
|
||||||
[string]$Name,
|
[string]$Name,
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
param(
|
# epf-remove-form v1.0 — Remove form from 1C processor
|
||||||
|
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||||
|
param(
|
||||||
[Parameter(Mandatory)]
|
[Parameter(Mandatory)]
|
||||||
[string]$ProcessorName,
|
[string]$ProcessorName,
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
param(
|
# epf-remove-template v1.0 — Remove template from 1C processor
|
||||||
|
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||||
|
param(
|
||||||
[Parameter(Mandatory)]
|
[Parameter(Mandatory)]
|
||||||
[string]$ProcessorName,
|
[string]$ProcessorName,
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
param(
|
# form-add v1.0 — Add managed form to 1C config object
|
||||||
|
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||||
|
param(
|
||||||
[Parameter(Mandatory)]
|
[Parameter(Mandatory)]
|
||||||
[string]$ObjectPath,
|
[string]$ObjectPath,
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
param(
|
# form-compile v1.0 — Compile 1C managed form from JSON
|
||||||
|
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||||
|
param(
|
||||||
[Parameter(Mandatory)]
|
[Parameter(Mandatory)]
|
||||||
[string]$JsonPath,
|
[string]$JsonPath,
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
param(
|
# form-edit v1.0 — Edit 1C managed form elements
|
||||||
|
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||||
|
param(
|
||||||
[Parameter(Mandatory)]
|
[Parameter(Mandatory)]
|
||||||
[string]$FormPath,
|
[string]$FormPath,
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
param(
|
# form-info v1.0 — Analyze 1C managed form structure
|
||||||
|
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||||
|
param(
|
||||||
[Parameter(Mandatory=$true)]
|
[Parameter(Mandatory=$true)]
|
||||||
[string]$FormPath,
|
[string]$FormPath,
|
||||||
[int]$Limit = 150,
|
[int]$Limit = 150,
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
param(
|
# form-validate v1.0 — Validate 1C managed form
|
||||||
|
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||||
|
param(
|
||||||
[Parameter(Mandatory)]
|
[Parameter(Mandatory)]
|
||||||
[string]$FormPath,
|
[string]$FormPath,
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
param(
|
# mxl-compile v1.0 — Compile 1C spreadsheet from JSON
|
||||||
|
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||||
|
param(
|
||||||
[Parameter(Mandatory)]
|
[Parameter(Mandatory)]
|
||||||
[string]$JsonPath,
|
[string]$JsonPath,
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
param(
|
# mxl-decompile v1.0 — Decompile 1C spreadsheet to JSON
|
||||||
|
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||||
|
param(
|
||||||
[Parameter(Mandatory)]
|
[Parameter(Mandatory)]
|
||||||
[string]$TemplatePath,
|
[string]$TemplatePath,
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
param(
|
# mxl-info v1.0 — Analyze 1C spreadsheet structure
|
||||||
|
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||||
|
param(
|
||||||
[string]$TemplatePath,
|
[string]$TemplatePath,
|
||||||
[string]$ProcessorName,
|
[string]$ProcessorName,
|
||||||
[string]$TemplateName,
|
[string]$TemplateName,
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
param(
|
# mxl-validate v1.0 — Validate 1C spreadsheet
|
||||||
|
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||||
|
param(
|
||||||
[string]$TemplatePath,
|
[string]$TemplatePath,
|
||||||
[string]$ProcessorName,
|
[string]$ProcessorName,
|
||||||
[string]$TemplateName,
|
[string]$TemplateName,
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
param(
|
# role-compile v1.0 — Compile 1C role from JSON
|
||||||
|
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||||
|
param(
|
||||||
[Parameter(Mandatory)]
|
[Parameter(Mandatory)]
|
||||||
[string]$JsonPath,
|
[string]$JsonPath,
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
param(
|
# role-info v1.0 — Analyze 1C role rights
|
||||||
|
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||||
|
param(
|
||||||
[Parameter(Mandatory=$true)][string]$RightsPath,
|
[Parameter(Mandatory=$true)][string]$RightsPath,
|
||||||
[switch]$ShowDenied,
|
[switch]$ShowDenied,
|
||||||
[int]$Limit = 150,
|
[int]$Limit = 150,
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
param(
|
# role-validate v1.0 — Validate 1C role structure
|
||||||
|
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||||
|
param(
|
||||||
[Parameter(Mandatory)]
|
[Parameter(Mandatory)]
|
||||||
[string]$RightsPath,
|
[string]$RightsPath,
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,225 @@
|
|||||||
|
---
|
||||||
|
name: skd-compile
|
||||||
|
description: Компиляция схемы компоновки данных 1С (СКД) — Template.xml из компактного JSON-определения
|
||||||
|
argument-hint: <JsonPath> <OutputPath>
|
||||||
|
allowed-tools:
|
||||||
|
- Bash
|
||||||
|
- Read
|
||||||
|
- Write
|
||||||
|
- Glob
|
||||||
|
---
|
||||||
|
|
||||||
|
# /skd-compile — генерация СКД из JSON DSL
|
||||||
|
|
||||||
|
Принимает JSON-определение схемы компоновки данных → генерирует Template.xml (DataCompositionSchema).
|
||||||
|
|
||||||
|
## Параметры и команда
|
||||||
|
|
||||||
|
| Параметр | Описание |
|
||||||
|
|----------|----------|
|
||||||
|
| `JsonPath` | Путь к JSON-определению СКД |
|
||||||
|
| `OutputPath` | Путь к выходному Template.xml |
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
powershell.exe -NoProfile -File .claude\skills\skd-compile\scripts\skd-compile.ps1 -JsonPath "<json>" -OutputPath "<Template.xml>"
|
||||||
|
```
|
||||||
|
|
||||||
|
## JSON DSL — краткий справочник
|
||||||
|
|
||||||
|
Полная спецификация: `docs/skd-dsl-spec.md`.
|
||||||
|
|
||||||
|
### Корневая структура
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"dataSets": [...],
|
||||||
|
"calculatedFields": [...],
|
||||||
|
"totalFields": [...],
|
||||||
|
"parameters": [...],
|
||||||
|
"dataSetLinks": [...],
|
||||||
|
"settingsVariants": [...]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Умолчания: `dataSources` → авто `ИсточникДанных1/Local`; `settingsVariants` → авто "Основной" с деталями.
|
||||||
|
|
||||||
|
### Наборы данных
|
||||||
|
|
||||||
|
Тип по ключу: `query` → DataSetQuery, `objectName` → DataSetObject, `items` → DataSetUnion.
|
||||||
|
|
||||||
|
```json
|
||||||
|
{ "name": "Продажи", "query": "ВЫБРАТЬ ...", "fields": [...] }
|
||||||
|
```
|
||||||
|
|
||||||
|
### Поля — shorthand
|
||||||
|
|
||||||
|
```
|
||||||
|
"Наименование" — просто имя
|
||||||
|
"Количество: decimal(15,2)" — имя + тип
|
||||||
|
"Организация: CatalogRef.Организации @dimension" — + роль
|
||||||
|
"Служебное: string #noFilter #noOrder" — + ограничения
|
||||||
|
```
|
||||||
|
|
||||||
|
Типы: `string`, `string(N)`, `decimal(D,F)`, `boolean`, `date`, `dateTime`, `CatalogRef.X`, `DocumentRef.X`, `EnumRef.X`, `StandardPeriod`. Ссылочные типы эмитируются с inline namespace `d5p1:` (`http://v8.1c.ru/8.1/data/enterprise/current-config`). Сборка EPF со ссылочными типами требует базу с соответствующей конфигурацией.
|
||||||
|
|
||||||
|
**Синонимы типов** (русские и альтернативные): `число` = decimal, `строка` = string, `булево` = boolean, `дата` = date, `датаВремя` = dateTime, `СтандартныйПериод` = StandardPeriod, `СправочникСсылка.X` = CatalogRef.X, `ДокументСсылка.X` = DocumentRef.X, `int`/`number` = decimal, `bool` = boolean. Регистронезависимые.
|
||||||
|
|
||||||
|
Роли: `@dimension`, `@account`, `@balance`, `@period`.
|
||||||
|
|
||||||
|
Ограничения: `#noField`, `#noFilter`, `#noGroup`, `#noOrder`.
|
||||||
|
|
||||||
|
### Итоги (shorthand)
|
||||||
|
|
||||||
|
```json
|
||||||
|
"totalFields": ["Количество: Сумма", "Стоимость: Сумма(Кол * Цена)"]
|
||||||
|
```
|
||||||
|
|
||||||
|
### Параметры (shorthand + @autoDates)
|
||||||
|
|
||||||
|
```json
|
||||||
|
"parameters": [
|
||||||
|
"Период: StandardPeriod = LastMonth @autoDates"
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
`@autoDates` — автоматически генерирует параметры `ДатаНачала` и `ДатаОкончания` с выражениями `&Период.ДатаНачала` / `&Период.ДатаОкончания` и `availableAsField=false`. Заменяет 5 строк на 1.
|
||||||
|
|
||||||
|
### Фильтры — shorthand
|
||||||
|
|
||||||
|
```json
|
||||||
|
"filter": [
|
||||||
|
"Организация = _ @off @user",
|
||||||
|
"Дата >= 2024-01-01T00:00:00",
|
||||||
|
"Статус filled"
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
Формат: `"Поле оператор значение @флаги"`. Значение `_` = пустое (placeholder). Флаги: `@off` (use=false), `@user` (userSettingID=auto), `@quickAccess`, `@normal`, `@inaccessible`.
|
||||||
|
|
||||||
|
В объектной форме доступны: `viewMode`, `userSettingID`, `userSettingPresentation`.
|
||||||
|
|
||||||
|
Группы фильтров (Or/And/Not):
|
||||||
|
```json
|
||||||
|
{ "group": "Or", "items": [
|
||||||
|
{ "group": "And", "items": [
|
||||||
|
{ "field": "Статус", "op": "=", "value": "Активен" },
|
||||||
|
{ "field": "Сумма", "op": ">", "value": 1000 }
|
||||||
|
]},
|
||||||
|
{ "field": "Количество", "op": "filled" }
|
||||||
|
]}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Параметры данных — shorthand
|
||||||
|
|
||||||
|
```json
|
||||||
|
"dataParameters": [
|
||||||
|
"Период = LastMonth @user",
|
||||||
|
"Организация @off @user"
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
Формат: `"Имя [= значение] @флаги"`. Для StandardPeriod варианты (LastMonth, ThisYear и т.д.) распознаются автоматически.
|
||||||
|
|
||||||
|
### Структура — string shorthand
|
||||||
|
|
||||||
|
```json
|
||||||
|
"structure": "Организация > details"
|
||||||
|
"structure": "Организация > Номенклатура > details"
|
||||||
|
```
|
||||||
|
|
||||||
|
`>` разделяет уровни группировки. `details` (или `детали`) = детальные записи. `selection` и `order` по умолчанию `["Auto"]` на каждом уровне.
|
||||||
|
|
||||||
|
Для сложных случаев (таблицы, диаграммы, фильтры на уровне группировки) используется объектная форма.
|
||||||
|
|
||||||
|
### Варианты настроек
|
||||||
|
|
||||||
|
```json
|
||||||
|
"settingsVariants": [{
|
||||||
|
"name": "Основной",
|
||||||
|
"settings": {
|
||||||
|
"selection": ["Номенклатура", "Количество", "Auto"],
|
||||||
|
"filter": ["Организация = _ @off @user"],
|
||||||
|
"order": ["Количество desc", "Auto"],
|
||||||
|
"conditionalAppearance": [
|
||||||
|
{
|
||||||
|
"filter": ["Просрочено = true"],
|
||||||
|
"appearance": { "ЦветТекста": "style:ПросроченныеДанныеЦвет" },
|
||||||
|
"presentation": "Выделять просроченные",
|
||||||
|
"viewMode": "Normal",
|
||||||
|
"userSettingID": "auto"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"outputParameters": { "Заголовок": "Мой отчёт" },
|
||||||
|
"dataParameters": ["Период = LastMonth @user"],
|
||||||
|
"structure": "Организация > details"
|
||||||
|
}
|
||||||
|
}]
|
||||||
|
```
|
||||||
|
|
||||||
|
### Условное оформление (conditionalAppearance)
|
||||||
|
|
||||||
|
```json
|
||||||
|
"conditionalAppearance": [
|
||||||
|
{
|
||||||
|
"selection": ["Поле1"],
|
||||||
|
"filter": ["Поле1 notFilled"],
|
||||||
|
"appearance": { "Текст": "Не указано", "ЦветТекста": "style:XXX" },
|
||||||
|
"presentation": "Описание",
|
||||||
|
"viewMode": "Normal",
|
||||||
|
"userSettingID": "auto"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
Типы значений appearance: `style:XXX`/`web:XXX`/`win:XXX` → Color, `true`/`false` → Boolean, параметр `Текст` → LocalStringType, прочее → String.
|
||||||
|
|
||||||
|
### Итоги с привязкой к группировкам
|
||||||
|
|
||||||
|
```json
|
||||||
|
"totalFields": [
|
||||||
|
{ "dataPath": "Кол", "expression": "Сумма(Кол)", "group": ["Группа1", "Группа1 Иерархия", "ОбщийИтог"] }
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
## Примеры
|
||||||
|
|
||||||
|
### Минимальный
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"dataSets": [{
|
||||||
|
"query": "ВЫБРАТЬ Номенклатура.Наименование КАК Наименование ИЗ Справочник.Номенклатура КАК Номенклатура",
|
||||||
|
"fields": ["Наименование"]
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### С ресурсами, параметрами и @autoDates
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"dataSets": [{
|
||||||
|
"query": "ВЫБРАТЬ Продажи.Номенклатура, Продажи.Количество, Продажи.Сумма ИЗ РегистрНакопления.Продажи КАК Продажи",
|
||||||
|
"fields": ["Номенклатура: СправочникСсылка.Номенклатура @dimension", "Количество: число(15,3)", "Сумма: число(15,2)"]
|
||||||
|
}],
|
||||||
|
"totalFields": ["Количество: Сумма", "Сумма: Сумма"],
|
||||||
|
"parameters": ["Период: СтандартныйПериод = LastMonth @autoDates"],
|
||||||
|
"settingsVariants": [{
|
||||||
|
"name": "Основной",
|
||||||
|
"settings": {
|
||||||
|
"selection": ["Номенклатура", "Количество", "Сумма", "Auto"],
|
||||||
|
"filter": ["Организация = _ @off @user"],
|
||||||
|
"dataParameters": ["Период = LastMonth @user"],
|
||||||
|
"structure": "Организация > details"
|
||||||
|
}
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Верификация
|
||||||
|
|
||||||
|
```
|
||||||
|
/skd-validate <OutputPath> — валидация структуры XML
|
||||||
|
/skd-info <OutputPath> — визуальная сводка
|
||||||
|
/skd-info <OutputPath> -Mode variant -Name 1 — проверка варианта настроек
|
||||||
|
```
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,217 @@
|
|||||||
|
---
|
||||||
|
name: skd-edit
|
||||||
|
description: Точечное редактирование схемы компоновки данных 1С (СКД) — добавление/удаление полей, итогов, фильтров, параметров, вычисляемых полей
|
||||||
|
argument-hint: <TemplatePath> -Operation <op> -Value <value>
|
||||||
|
allowed-tools:
|
||||||
|
- Bash
|
||||||
|
- Read
|
||||||
|
- Write
|
||||||
|
- Glob
|
||||||
|
---
|
||||||
|
|
||||||
|
# /skd-edit — точечное редактирование СКД (Template.xml)
|
||||||
|
|
||||||
|
Атомарные операции модификации существующей схемы компоновки данных: добавление, удаление и модификация полей, итогов, фильтров, параметров, настроек варианта, управление структурой, замена запроса.
|
||||||
|
|
||||||
|
## Параметры и команда
|
||||||
|
|
||||||
|
| Параметр | Описание |
|
||||||
|
|----------|----------|
|
||||||
|
| `TemplatePath` | Путь к Template.xml (или к папке — автодополнение Ext/Template.xml) |
|
||||||
|
| `Operation` | Операция (см. список ниже) |
|
||||||
|
| `Value` | Значение операции (shorthand-строка или текст запроса) |
|
||||||
|
| `DataSet` | (опц.) Имя набора данных (умолч. первый) |
|
||||||
|
| `Variant` | (опц.) Имя варианта настроек (умолч. первый) |
|
||||||
|
| `NoSelection` | (опц.) Не добавлять поле в selection варианта |
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
powershell.exe -NoProfile -File .claude\skills\skd-edit\scripts\skd-edit.ps1 -TemplatePath "<path>" -Operation <op> -Value "<value>"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Пакетный режим (batch)
|
||||||
|
|
||||||
|
Несколько значений в одном вызове через разделитель `;;`:
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
-Operation add-field -Value "Цена: decimal(15,2) ;; Количество: decimal(15,3) ;; Сумма: decimal(15,2)"
|
||||||
|
```
|
||||||
|
|
||||||
|
Работает для всех операций кроме `set-query`, `set-structure` и `add-dataSet`.
|
||||||
|
|
||||||
|
## Операции
|
||||||
|
|
||||||
|
### add-field — добавить поле в набор данных
|
||||||
|
|
||||||
|
Shorthand: `"Имя [Заголовок]: тип @роль #ограничение"`.
|
||||||
|
|
||||||
|
```
|
||||||
|
"Цена: decimal(15,2)"
|
||||||
|
"Организация [Орг-ция]: CatalogRef.Организации @dimension"
|
||||||
|
"Служебное: string #noFilter #noOrder"
|
||||||
|
```
|
||||||
|
|
||||||
|
Поле добавляется в набор и в selection варианта (если нет `-NoSelection`). Дубликат dataPath — предупреждение, пропуск.
|
||||||
|
|
||||||
|
### add-total — добавить итог
|
||||||
|
|
||||||
|
```
|
||||||
|
"Цена: Среднее"
|
||||||
|
"Стоимость: Сумма(Кол * Цена)"
|
||||||
|
```
|
||||||
|
|
||||||
|
### add-calculated-field — добавить вычисляемое поле
|
||||||
|
|
||||||
|
Shorthand: `"Имя [Заголовок]: тип = Выражение"`.
|
||||||
|
|
||||||
|
```
|
||||||
|
"Маржа = Продажа - Закупка"
|
||||||
|
"Наценка [Наценка, %]: decimal(10,2) = Маржа / Закупка * 100"
|
||||||
|
```
|
||||||
|
|
||||||
|
Также добавляется в selection варианта.
|
||||||
|
|
||||||
|
### add-parameter — добавить параметр
|
||||||
|
|
||||||
|
```
|
||||||
|
"Период: StandardPeriod = LastMonth @autoDates"
|
||||||
|
"Организация: CatalogRef.Организации"
|
||||||
|
```
|
||||||
|
|
||||||
|
`@autoDates` генерирует `ДатаНачала` и `ДатаОкончания` автоматически.
|
||||||
|
|
||||||
|
### add-filter — добавить фильтр в вариант
|
||||||
|
|
||||||
|
Shorthand: `"Поле оператор значение @флаги"`. Флаги: `@off`, `@user`, `@quickAccess`, `@normal`, `@inaccessible`.
|
||||||
|
|
||||||
|
```
|
||||||
|
"Номенклатура = _ @off @user"
|
||||||
|
"Дата >= 2024-01-01T00:00:00"
|
||||||
|
"Статус filled"
|
||||||
|
```
|
||||||
|
|
||||||
|
### add-dataParameter — добавить параметр данных в вариант
|
||||||
|
|
||||||
|
Shorthand: `"Имя [= значение] @флаги"`.
|
||||||
|
|
||||||
|
```
|
||||||
|
"Период = LastMonth @user"
|
||||||
|
"Организация @off @user"
|
||||||
|
```
|
||||||
|
|
||||||
|
### add-order — добавить сортировку
|
||||||
|
|
||||||
|
Shorthand: `"Поле [desc]"`. По умолчанию asc. `Auto` — авто-элемент.
|
||||||
|
|
||||||
|
```
|
||||||
|
"Количество desc"
|
||||||
|
"Auto"
|
||||||
|
```
|
||||||
|
|
||||||
|
### add-selection — добавить элемент выборки
|
||||||
|
|
||||||
|
```
|
||||||
|
"Номенклатура"
|
||||||
|
"Auto"
|
||||||
|
```
|
||||||
|
|
||||||
|
### add-dataSetLink — добавить связь наборов данных
|
||||||
|
|
||||||
|
Shorthand: `"Источник > Приёмник on ВырИсточника = ВырПриёмника [param Имя]"`.
|
||||||
|
|
||||||
|
```
|
||||||
|
"Набор1 > Набор2 on Поле1 = Поле2"
|
||||||
|
"Набор1 > Набор2 on Поле1 = Поле2 [param Связь]"
|
||||||
|
```
|
||||||
|
|
||||||
|
### add-dataSet — добавить набор данных
|
||||||
|
|
||||||
|
Shorthand: `"Имя: ТЕКСТ_ЗАПРОСА"` или `"ТЕКСТ_ЗАПРОСА"` (авто-имя `НаборДанныхN`).
|
||||||
|
|
||||||
|
```
|
||||||
|
"Доп: ВЫБРАТЬ 1 КАК Тест"
|
||||||
|
"ВЫБРАТЬ Ссылка ИЗ Справочник.Номенклатура"
|
||||||
|
```
|
||||||
|
|
||||||
|
`dataSource` берётся из первого существующего. Дубликат имени — предупреждение, пропуск. Не поддерживает пакетный режим (запрос может содержать `;;`).
|
||||||
|
|
||||||
|
### add-variant — добавить вариант настроек
|
||||||
|
|
||||||
|
Shorthand: `"Имя [Представление]"`. Представление опционально, по умолчанию = имя.
|
||||||
|
|
||||||
|
```
|
||||||
|
"Детальный"
|
||||||
|
"Детальный [Детальный отчёт]"
|
||||||
|
```
|
||||||
|
|
||||||
|
Создаёт вариант с Auto selection + detail group. Дубликат имени — предупреждение, пропуск.
|
||||||
|
|
||||||
|
### add-conditionalAppearance — добавить условное оформление
|
||||||
|
|
||||||
|
Shorthand: `"Параметр = значение [when условие] [for Поле1, Поле2]"`. Блок `when` — синтаксис `add-filter` (Поле оператор значение).
|
||||||
|
|
||||||
|
```
|
||||||
|
"ЦветТекста = web:Red when Сумма < 0"
|
||||||
|
"ЦветФона = web:LightGreen when Статус = Одобрен for Статус"
|
||||||
|
"МинимальнаяШирина = 50 for Организация"
|
||||||
|
"Формат = ЧДЦ=2 for Цена, Сумма"
|
||||||
|
```
|
||||||
|
|
||||||
|
Типы значений (автодетект): `web:*`/`style:*`/`win:*` → цвет, `true`/`false` → boolean, иначе строка.
|
||||||
|
|
||||||
|
### set-query — заменить текст запроса
|
||||||
|
|
||||||
|
Не поддерживает пакетный режим. Value — полный текст запроса.
|
||||||
|
|
||||||
|
### set-outputParameter — установить параметр вывода
|
||||||
|
|
||||||
|
```
|
||||||
|
"Заголовок = Мой отчёт"
|
||||||
|
"ВыводитьЗаголовок = true"
|
||||||
|
```
|
||||||
|
|
||||||
|
Если параметр уже существует — заменяет значение.
|
||||||
|
|
||||||
|
### set-structure — установить структуру варианта
|
||||||
|
|
||||||
|
Shorthand: `"Поле1 > Поле2 > details"`. `details`/`детали` — детальные записи. Заменяет всю структуру. Не поддерживает пакетный режим.
|
||||||
|
|
||||||
|
```
|
||||||
|
"Организация > Номенклатура > details"
|
||||||
|
"details"
|
||||||
|
```
|
||||||
|
|
||||||
|
### modify-field — изменить существующее поле
|
||||||
|
|
||||||
|
Тот же shorthand что и `add-field`. Находит по dataPath, объединяет свойства (непустые переопределяют), сохраняет позицию.
|
||||||
|
|
||||||
|
```
|
||||||
|
"Цена [Цена USD]: decimal(10,4) @dimension"
|
||||||
|
```
|
||||||
|
|
||||||
|
### modify-filter — изменить существующий фильтр
|
||||||
|
|
||||||
|
Тот же shorthand что и `add-filter`. Находит по полю, обновляет оператор/значение/флаги.
|
||||||
|
|
||||||
|
### modify-dataParameter — изменить параметр данных
|
||||||
|
|
||||||
|
Тот же shorthand что и `add-dataParameter`. Находит по имени, обновляет значение/флаги.
|
||||||
|
|
||||||
|
### remove-* и clear-*
|
||||||
|
|
||||||
|
| Операция | Value | Действие |
|
||||||
|
|----------|-------|----------|
|
||||||
|
| `remove-field` | dataPath | Удаляет поле из набора + из selection варианта |
|
||||||
|
| `remove-total` | dataPath | Удаляет итог |
|
||||||
|
| `remove-calculated-field` | dataPath | Удаляет вычисляемое поле + из selection |
|
||||||
|
| `remove-parameter` | name | Удаляет параметр |
|
||||||
|
| `remove-filter` | поле | Удаляет первый фильтр с указанным полем |
|
||||||
|
| `clear-selection` | `*` | Очищает все элементы selection |
|
||||||
|
| `clear-order` | `*` | Очищает все элементы order |
|
||||||
|
| `clear-filter` | `*` | Очищает все элементы filter |
|
||||||
|
|
||||||
|
## Верификация
|
||||||
|
|
||||||
|
```
|
||||||
|
/skd-validate <TemplatePath> — валидация структуры после редактирования
|
||||||
|
/skd-info <TemplatePath> — визуальная сводка
|
||||||
|
```
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,74 @@
|
|||||||
|
---
|
||||||
|
name: skd-info
|
||||||
|
description: Анализ структуры схемы компоновки данных 1С (СКД) — наборы, поля, параметры, варианты
|
||||||
|
argument-hint: <TemplatePath> [-Mode overview|query|fields|links|calculated|resources|params|variant|templates|trace] [-Name <dataset|variant|field|group>]
|
||||||
|
allowed-tools:
|
||||||
|
- Bash
|
||||||
|
- Read
|
||||||
|
- Glob
|
||||||
|
---
|
||||||
|
|
||||||
|
# /skd-info — Анализ схемы компоновки данных
|
||||||
|
|
||||||
|
Читает Template.xml схемы компоновки данных (СКД) и выводит компактную сводку. Заменяет необходимость читать тысячи строк XML.
|
||||||
|
|
||||||
|
## Параметры и команда
|
||||||
|
|
||||||
|
| Параметр | Описание |
|
||||||
|
|----------|----------|
|
||||||
|
| `TemplatePath` | Путь к Template.xml или каталогу макета (авто-резолв в `Ext/Template.xml`) |
|
||||||
|
| `Mode` | Режим анализа (по умолчанию `overview`) |
|
||||||
|
| `Name` | Имя набора (query), поля (fields/calculated/resources/trace), варианта (variant) или группировки/поля (templates) |
|
||||||
|
| `Batch` | Номер пакета запроса, 0 = все (только query) |
|
||||||
|
| `Limit` / `Offset` | Пагинация (по умолчанию 150 строк) |
|
||||||
|
| `OutFile` | Записать результат в файл (UTF-8 BOM) |
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
powershell.exe -NoProfile -File .claude\skills\skd-info\scripts\skd-info.ps1 -TemplatePath "<путь>"
|
||||||
|
```
|
||||||
|
|
||||||
|
С указанием режима:
|
||||||
|
```powershell
|
||||||
|
... -Mode query -Name НоменклатураСЦенами
|
||||||
|
... -Mode query -Name ДанныеТ13 -Batch 3
|
||||||
|
... -Mode fields -Name КадастроваяСтоимость
|
||||||
|
... -Mode calculated -Name КоэффициентКи
|
||||||
|
... -Mode resources -Name СуммаНалога
|
||||||
|
... -Mode trace -Name "Коэффициент Ки"
|
||||||
|
... -Mode variant -Name 1
|
||||||
|
... -Mode templates
|
||||||
|
... -Mode templates -Name ВидНалоговойБазы
|
||||||
|
```
|
||||||
|
|
||||||
|
## Режимы
|
||||||
|
|
||||||
|
| Режим | Без `-Name` | С `-Name` |
|
||||||
|
|-------|-------------|-----------|
|
||||||
|
| `overview` | Навигационная карта схемы + подсказки Next | — |
|
||||||
|
| `query` | — | Текст запроса набора (с оглавлением батчей) |
|
||||||
|
| `fields` | Карта: имена полей по наборам | Деталь поля: набор, тип, роль, формат |
|
||||||
|
| `links` | Все связи наборов | — |
|
||||||
|
| `calculated` | Карта: имена вычисляемых полей | Выражение + заголовок + ограничения |
|
||||||
|
| `resources` | Карта: имена ресурсов (`*` = групповые формулы) | Формулы агрегации по группировкам |
|
||||||
|
| `params` | Таблица параметров: тип, значение, видимость | — |
|
||||||
|
| `variant` | Список вариантов | Структура группировок + фильтры + вывод |
|
||||||
|
| `templates` | Карта привязок шаблонов (field/group) | Содержимое шаблона: строки, ячейки, выражения |
|
||||||
|
| `trace` | — | Полная цепочка: набор → вычисление → ресурс |
|
||||||
|
|
||||||
|
Паттерн: без `-Name` — карта/индекс, с `-Name` — деталь конкретного элемента.
|
||||||
|
|
||||||
|
## Типичный workflow
|
||||||
|
|
||||||
|
1. `overview` — понять структуру, увидеть подсказки
|
||||||
|
2. `trace -Name <поле>` — узнать как считается колонка отчёта (от заголовка до запроса за один вызов)
|
||||||
|
3. `query -Name <набор>` — посмотреть текст SQL-запроса
|
||||||
|
4. `variant -Name <N>` — посмотреть группировки и фильтры варианта
|
||||||
|
|
||||||
|
Подробные примеры вывода каждого режима — в `modes-reference.md`.
|
||||||
|
|
||||||
|
## Верификация
|
||||||
|
|
||||||
|
```
|
||||||
|
/skd-info <path> — overview (точка входа)
|
||||||
|
/skd-info <path> -Mode trace -Name <field> — трассировка поля
|
||||||
|
```
|
||||||
@@ -0,0 +1,246 @@
|
|||||||
|
# /skd-info — полная справка по режимам
|
||||||
|
|
||||||
|
Компактное описание — в [SKILL.md](SKILL.md).
|
||||||
|
|
||||||
|
## overview (по умолчанию) — карта схемы
|
||||||
|
|
||||||
|
Компактная навигационная карта (10-25 строк). Показывает структуру и подсказывает следующие шаги:
|
||||||
|
|
||||||
|
```
|
||||||
|
=== DCS: ОсновнаяСхемаКомпоновкиДанных (362 lines) ===
|
||||||
|
|
||||||
|
Sources: ИсточникДанных1 (Local)
|
||||||
|
|
||||||
|
Datasets:
|
||||||
|
[Query] НоменклатураСЦенами 7 fields, query 40 lines
|
||||||
|
Calculated: 1
|
||||||
|
Resources: 1
|
||||||
|
Templates: 1 templates, 1 group bindings
|
||||||
|
Params: (none)
|
||||||
|
|
||||||
|
Variants:
|
||||||
|
[1] НоменклатураИЦены "Номенклатура и цены" Table(detail) 3 filters
|
||||||
|
[2] НоменклатураБезЦен "Номенклатура без цен" Group(detail) 2 filters
|
||||||
|
|
||||||
|
Next:
|
||||||
|
-Mode query query text
|
||||||
|
-Mode fields field tables by dataset
|
||||||
|
-Mode calculated calculated field expressions
|
||||||
|
-Mode resources resource aggregation
|
||||||
|
-Mode variant -Name <N> variant structure (1..2)
|
||||||
|
```
|
||||||
|
|
||||||
|
Для DataSetUnion — дерево наборов + связи:
|
||||||
|
```
|
||||||
|
Datasets:
|
||||||
|
[Union] РасчетНалогаНаИмущество 52 fields
|
||||||
|
├─ [Query] РасчетНалогаНаИмущество 51 fields, query 181 lines
|
||||||
|
├─ [Query] ДанныеПоКадастровой 29 fields, query 40 lines
|
||||||
|
├─ [Query] ДанныеПоСреднегодовой 34 fields, query 41 lines
|
||||||
|
Links: РасчетНалогаНаИмущество -> СостояниеОС (2 fields)
|
||||||
|
```
|
||||||
|
|
||||||
|
Параметры разделяются на видимые/скрытые:
|
||||||
|
```
|
||||||
|
Params: 18 (7 visible, 11 hidden): Период, Ответственный, ...
|
||||||
|
```
|
||||||
|
|
||||||
|
## query — текст запроса
|
||||||
|
|
||||||
|
`-Name <набор>` — имя DataSet (обязателен если наборов > 1).
|
||||||
|
|
||||||
|
Извлекает raw-текст запроса с деэкранированием XML (`&`→`&`, `>`→`>`). Для пакетных запросов — оглавление батчей:
|
||||||
|
|
||||||
|
```
|
||||||
|
=== Query: ДанныеТ13 (334 lines, 13 batches) ===
|
||||||
|
Batch 1: lines 1-8 → ПОМЕСТИТЬ Представления_Периоды
|
||||||
|
Batch 2: lines 9-26 → ПОМЕСТИТЬ Представления_СотрудникиОрганизации
|
||||||
|
...
|
||||||
|
--- Batch 1 ---
|
||||||
|
ВЫБРАТЬ
|
||||||
|
ДАТАВРЕМЯ(1, 1, 1) КАК Период
|
||||||
|
ПОМЕСТИТЬ Представления_Периоды
|
||||||
|
...
|
||||||
|
```
|
||||||
|
|
||||||
|
Фильтр по номеру батча: `-Batch 3` покажет только 3-й пакет.
|
||||||
|
|
||||||
|
## fields — поля наборов данных
|
||||||
|
|
||||||
|
Без `-Name` — карта: имена полей по наборам:
|
||||||
|
```
|
||||||
|
=== Fields map ===
|
||||||
|
СостояниеОС [Query] (3): Организация, ОсновноеСредство, ДатаСостояния
|
||||||
|
РасчетНалогаНаИмущество [Union] (52): ДоляСтоимостиЧислитель, ...
|
||||||
|
РасчетНалогаНаИмущество [Query] (51): КадастроваяСтоимость, ...
|
||||||
|
```
|
||||||
|
|
||||||
|
С `-Name <поле>` — детали конкретного поля:
|
||||||
|
```
|
||||||
|
=== Field: ДатаСостояния "Дата ввода в эксплуатацию" ===
|
||||||
|
|
||||||
|
Dataset: СостояниеОС [Query]
|
||||||
|
Format: ДФ=dd.MM.yyyy
|
||||||
|
```
|
||||||
|
|
||||||
|
Показывает: dataset, title, type, role, useRestriction, format, presentationExpression.
|
||||||
|
|
||||||
|
## links — связи наборов данных
|
||||||
|
|
||||||
|
```
|
||||||
|
=== Links (4) ===
|
||||||
|
|
||||||
|
РасчетНалогаНаИмущество -> СостояниеОС :
|
||||||
|
Организация -> Организация
|
||||||
|
ОсновноеСредство -> ОсновноеСредство
|
||||||
|
```
|
||||||
|
|
||||||
|
Группирует по парам наборов. Показывает поля связи и параметры.
|
||||||
|
|
||||||
|
## calculated — вычисляемые поля
|
||||||
|
|
||||||
|
Без `-Name` — карта: имена и заголовки:
|
||||||
|
```
|
||||||
|
=== Calculated fields (23) ===
|
||||||
|
ДоляСтоимости "Доля стоимости"
|
||||||
|
КоэффициентКи "Коэффициент Ки"
|
||||||
|
...
|
||||||
|
```
|
||||||
|
|
||||||
|
С `-Name <поле>` — полное выражение:
|
||||||
|
```
|
||||||
|
=== Calculated: ДоляСтоимости ===
|
||||||
|
|
||||||
|
Expression:
|
||||||
|
ВЫБОР КОГДА ... ТОГДА "1" ИНАЧЕ ... КОНЕЦ
|
||||||
|
Title: Доля стоимости
|
||||||
|
Restrict: condition
|
||||||
|
```
|
||||||
|
|
||||||
|
## resources — ресурсы (итоги по группировкам)
|
||||||
|
|
||||||
|
Без `-Name` — карта: имена полей, `*` = есть формулы по группировкам:
|
||||||
|
```
|
||||||
|
=== Resources (51) ===
|
||||||
|
НалоговаяБаза
|
||||||
|
КоэффициентКи *
|
||||||
|
...
|
||||||
|
* = has group-level formulas
|
||||||
|
```
|
||||||
|
|
||||||
|
С `-Name <поле>` — формулы агрегации:
|
||||||
|
```
|
||||||
|
=== Resource: ДатаСостояния ===
|
||||||
|
|
||||||
|
[ОсновноеСредство] ЕстьNull(ДатаСостояния, "")
|
||||||
|
```
|
||||||
|
|
||||||
|
## params — параметры схемы
|
||||||
|
|
||||||
|
```
|
||||||
|
=== Parameters (16) ===
|
||||||
|
Name Type Default Visible Expression
|
||||||
|
Период StandardPeriod LastMonth yes -
|
||||||
|
НачалоПериода DateTime - hidden &Период.ДатаНачала
|
||||||
|
Организация CatalogRef.Организации null yes -
|
||||||
|
```
|
||||||
|
|
||||||
|
## variant — варианты отчёта
|
||||||
|
|
||||||
|
Без `-Name` — список вариантов:
|
||||||
|
```
|
||||||
|
=== Variants (2) ===
|
||||||
|
[1] НоменклатураИЦены "Номенклатура и цены" Table(detail) 3 filters
|
||||||
|
[2] НоменклатураБезЦен "Номенклатура без цен" Group(detail) 2 filters
|
||||||
|
```
|
||||||
|
|
||||||
|
С `-Name <N|имя>` — структура конкретного варианта:
|
||||||
|
```
|
||||||
|
=== Variant [1]: НоменклатураИЦены "Номенклатура и цены" ===
|
||||||
|
|
||||||
|
Structure:
|
||||||
|
Table "Таблица"
|
||||||
|
├── Columns: [ТипЦен Items]
|
||||||
|
│ Selection: Auto, Цена
|
||||||
|
└── Rows: [Номенклатура Items]
|
||||||
|
Selection: Номенклатура, УИД, Auto
|
||||||
|
|
||||||
|
Filter:
|
||||||
|
[ ] Номенклатура InHierarchy [user]
|
||||||
|
[ ] ТипЦен Equal
|
||||||
|
[x] ВАрхиве = false "Исключая скрытые товары"
|
||||||
|
|
||||||
|
DataParams: КлючВарианта="НоменклатураИЦены"
|
||||||
|
Output: style=ЧерноБелый groups=Separately totalsH=None totalsV=None
|
||||||
|
```
|
||||||
|
|
||||||
|
## templates — привязки шаблонов вывода
|
||||||
|
|
||||||
|
Три типа привязок: `fieldTemplate` (к полю), `groupTemplate` (к группировке, Header/Footer), `groupHeaderTemplate` (заголовок группы).
|
||||||
|
|
||||||
|
Без `-Name` — карта привязок:
|
||||||
|
```
|
||||||
|
=== Templates (70 defined: 49 field, 37 group) ===
|
||||||
|
|
||||||
|
Field bindings (49): (all trivial)
|
||||||
|
ОстаточнаяСтоимостьНа0101, ОстаточнаяСтоимостьНа0102, ...
|
||||||
|
|
||||||
|
Group bindings (37):
|
||||||
|
ВидНалоговойБазы
|
||||||
|
Header -> Макет3 (1 rows, 1 params)
|
||||||
|
СреднегодоваяСтоимость2019
|
||||||
|
Footer -> Макет50 (1 rows) spacer
|
||||||
|
GroupHeader -> Макет40 (3 rows)
|
||||||
|
```
|
||||||
|
|
||||||
|
С `-Name <группировка|поле>` — содержимое шаблонов:
|
||||||
|
```
|
||||||
|
=== Templates: СреднегодоваяСтоимость2019 ===
|
||||||
|
|
||||||
|
Footer -> Макет50 [1 rows, 1 cells]:
|
||||||
|
Row 1: (empty)
|
||||||
|
|
||||||
|
GroupHeader -> Макет40 [3 rows, 78 cells]:
|
||||||
|
Row 1: "№ п/п" | "###Группировки1###" | "Инв. номер" | ...
|
||||||
|
Row 2: "01.01" | "01.02" | ... | "31.12"
|
||||||
|
Row 3: "1" | "2" | ... | "26"
|
||||||
|
```
|
||||||
|
|
||||||
|
Для field-привязок:
|
||||||
|
```
|
||||||
|
=== Field template: ОстаточнаяСтоимостьНа0101 -> Макет4 ===
|
||||||
|
[1 rows, 1 cells]
|
||||||
|
Row 1: {ОстаточнаяСтоимостьНа0101}
|
||||||
|
(all params trivial)
|
||||||
|
```
|
||||||
|
|
||||||
|
**Тривиальность выражений**: `Поле = Поле` и `Поле = Представление(Поле)` считаются тривиальными и НЕ выводятся. Показываются только нетривиальные — когда выражение содержит другое поле, вызов метода, пустую строку и т.д.
|
||||||
|
|
||||||
|
## trace — трассировка поля от заголовка до запроса
|
||||||
|
|
||||||
|
Ищет поле по dataPath ИЛИ заголовку (включая подстроку) и показывает полную цепочку происхождения за один вызов:
|
||||||
|
|
||||||
|
```
|
||||||
|
=== Trace: КоэффициентКи "Коэффициент Ки" ===
|
||||||
|
|
||||||
|
Dataset: (schema-level only, not in dataset fields)
|
||||||
|
|
||||||
|
Calculated:
|
||||||
|
ВЫБОР КОГДА ... ТОГДА 0 ИНАЧЕ ... КОНЕЦ
|
||||||
|
Operands:
|
||||||
|
КоличествоМесяцевИспользования -> РасчетНалогаНаИмущество [Query]
|
||||||
|
КоличествоМесяцевВладения -> РасчетНалогаНаИмущество [Query]
|
||||||
|
|
||||||
|
Resource:
|
||||||
|
[ОсновноеСредство] Сумма(КоэффициентКи)
|
||||||
|
```
|
||||||
|
|
||||||
|
Типичный сценарий: пользователь видит колонку "Коэффициент Ки" в отчёте и спрашивает как она считается. Один вызов `trace` показывает: формулу вычисления, откуда берутся операнды, как агрегируется в ресурс.
|
||||||
|
|
||||||
|
## Что не выводится
|
||||||
|
|
||||||
|
- XML namespace-декларации
|
||||||
|
- Обёртки v8:item/v8:lang/v8:content (извлекаем чистый текст)
|
||||||
|
- userSettingID (GUID-ы пользовательских настроек)
|
||||||
|
- Дефолтные periodAdditionBegin/End = 0001-01-01
|
||||||
|
- viewMode
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,74 @@
|
|||||||
|
---
|
||||||
|
name: skd-validate
|
||||||
|
description: Валидация структурной корректности схемы компоновки данных 1С (СКД) — Template.xml
|
||||||
|
argument-hint: <TemplatePath> [-MaxErrors 20]
|
||||||
|
allowed-tools:
|
||||||
|
- Bash
|
||||||
|
- Read
|
||||||
|
- Glob
|
||||||
|
---
|
||||||
|
|
||||||
|
# /skd-validate — валидация СКД (DataCompositionSchema)
|
||||||
|
|
||||||
|
Проверяет структурную корректность Template.xml схемы компоновки данных. Выявляет ошибки формата, битые ссылки, дубликаты имён.
|
||||||
|
|
||||||
|
## Параметры и команда
|
||||||
|
|
||||||
|
| Параметр | Описание |
|
||||||
|
|----------|----------|
|
||||||
|
| `TemplatePath` | Путь к Template.xml или каталогу макета (авто-резолв в `Ext/Template.xml`) |
|
||||||
|
| `MaxErrors` | Макс. ошибок до остановки (по умолчанию 20) |
|
||||||
|
| `OutFile` | Записать результат в файл |
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
powershell.exe -NoProfile -File .claude\skills\skd-validate\scripts\skd-validate.ps1 -TemplatePath "<путь>"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Проверки (~30)
|
||||||
|
|
||||||
|
| Группа | Что проверяется |
|
||||||
|
|--------|-----------------|
|
||||||
|
| **Root** | XML parse, корневой элемент `DataCompositionSchema`, default namespace, ns-префиксы |
|
||||||
|
| **DataSource** | Наличие, name не пуст, type валиден (Local/External), уникальность имён |
|
||||||
|
| **DataSet** | Наличие, xsi:type валиден, name не пуст, уникальность, ссылка на dataSource, query не пуст |
|
||||||
|
| **Fields** | dataPath не пуст, field не пуст, уникальность dataPath в наборе |
|
||||||
|
| **Links** | source/dest ссылаются на существующие наборы, expressions не пусты |
|
||||||
|
| **CalcFields** | dataPath не пуст, expression не пуст, уникальность, коллизии с полями наборов |
|
||||||
|
| **TotalFields** | dataPath не пуст, expression не пуст |
|
||||||
|
| **Parameters** | name не пуст, уникальность |
|
||||||
|
| **Templates** | name не пуст, уникальность |
|
||||||
|
| **GroupTemplates** | template ссылается на существующий template, templateType валиден |
|
||||||
|
| **Variants** | Наличие, name не пуст, settings element присутствует |
|
||||||
|
| **Settings** | selection/filter/order ссылаются на известные поля, comparisonType валиден, structure items типизированы |
|
||||||
|
|
||||||
|
## Коды выхода
|
||||||
|
|
||||||
|
| Код | Значение |
|
||||||
|
|-----|----------|
|
||||||
|
| 0 | Ошибок нет (могут быть предупреждения) |
|
||||||
|
| 1 | Есть ошибки |
|
||||||
|
|
||||||
|
## Пример вывода
|
||||||
|
|
||||||
|
```
|
||||||
|
=== Validation: Template.xml ===
|
||||||
|
|
||||||
|
[OK] XML parsed successfully
|
||||||
|
[OK] Root element: DataCompositionSchema
|
||||||
|
[OK] Default namespace correct
|
||||||
|
[OK] 1 dataSource(s) found, names unique
|
||||||
|
[OK] 1 dataSet(s) found, names unique
|
||||||
|
[OK] DataSet "НаборДанных1": 2 fields, dataPath unique
|
||||||
|
[OK] 1 totalField(s): dataPath and expression present
|
||||||
|
[OK] 1 settingsVariant(s) found
|
||||||
|
|
||||||
|
=== Result: 0 errors, 0 warnings ===
|
||||||
|
```
|
||||||
|
|
||||||
|
## Верификация
|
||||||
|
|
||||||
|
```
|
||||||
|
/skd-compile <JsonPath> <OutputPath> — генерация XML
|
||||||
|
/skd-validate <OutputPath> — проверка результата
|
||||||
|
/skd-info <OutputPath> — визуальная сводка
|
||||||
|
```
|
||||||
@@ -0,0 +1,719 @@
|
|||||||
|
# skd-validate v1.0 — Validate 1C DCS structure
|
||||||
|
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||||
|
param(
|
||||||
|
[Parameter(Mandatory)]
|
||||||
|
[string]$TemplatePath,
|
||||||
|
|
||||||
|
[int]$MaxErrors = 20,
|
||||||
|
|
||||||
|
[string]$OutFile
|
||||||
|
)
|
||||||
|
|
||||||
|
$ErrorActionPreference = "Stop"
|
||||||
|
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8
|
||||||
|
|
||||||
|
# --- Resolve path ---
|
||||||
|
|
||||||
|
if (-not $TemplatePath.EndsWith(".xml")) {
|
||||||
|
$candidate = Join-Path (Join-Path $TemplatePath "Ext") "Template.xml"
|
||||||
|
if (Test-Path $candidate) {
|
||||||
|
$TemplatePath = $candidate
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (-not (Test-Path $TemplatePath)) {
|
||||||
|
Write-Error "File not found: $TemplatePath"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
$resolvedPath = (Resolve-Path $TemplatePath).Path
|
||||||
|
$fileName = [System.IO.Path]::GetFileName($resolvedPath)
|
||||||
|
|
||||||
|
# --- Output infrastructure ---
|
||||||
|
|
||||||
|
$script:errors = 0
|
||||||
|
$script:warnings = 0
|
||||||
|
$script:stopped = $false
|
||||||
|
$script:output = New-Object System.Text.StringBuilder 4096
|
||||||
|
|
||||||
|
function Out-Line {
|
||||||
|
param([string]$msg)
|
||||||
|
$script:output.AppendLine($msg) | Out-Null
|
||||||
|
}
|
||||||
|
|
||||||
|
function Report-OK {
|
||||||
|
param([string]$msg)
|
||||||
|
Out-Line "[OK] $msg"
|
||||||
|
}
|
||||||
|
|
||||||
|
function Report-Error {
|
||||||
|
param([string]$msg)
|
||||||
|
$script:errors++
|
||||||
|
Out-Line "[ERROR] $msg"
|
||||||
|
if ($script:errors -ge $MaxErrors) {
|
||||||
|
$script:stopped = $true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function Report-Warn {
|
||||||
|
param([string]$msg)
|
||||||
|
$script:warnings++
|
||||||
|
Out-Line "[WARN] $msg"
|
||||||
|
}
|
||||||
|
|
||||||
|
$finalize = {
|
||||||
|
Out-Line ""
|
||||||
|
Out-Line "=== Result: $($script:errors) errors, $($script:warnings) warnings ==="
|
||||||
|
|
||||||
|
$result = $script:output.ToString()
|
||||||
|
Write-Host $result
|
||||||
|
|
||||||
|
if ($OutFile) {
|
||||||
|
$utf8Bom = New-Object System.Text.UTF8Encoding $true
|
||||||
|
[System.IO.File]::WriteAllText($OutFile, $result, $utf8Bom)
|
||||||
|
Write-Host "Written to: $OutFile"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Out-Line "=== Validation: $fileName ==="
|
||||||
|
Out-Line ""
|
||||||
|
|
||||||
|
# --- 1. Parse XML ---
|
||||||
|
|
||||||
|
$xmlDoc = $null
|
||||||
|
try {
|
||||||
|
$xmlDoc = New-Object System.Xml.XmlDocument
|
||||||
|
$xmlDoc.PreserveWhitespace = $false
|
||||||
|
$xmlDoc.Load($resolvedPath)
|
||||||
|
Report-OK "XML parsed successfully"
|
||||||
|
} catch {
|
||||||
|
Report-Error "XML parse failed: $($_.Exception.Message)"
|
||||||
|
# Cannot continue
|
||||||
|
$result = $script:output.ToString()
|
||||||
|
Write-Host $result
|
||||||
|
if ($OutFile) {
|
||||||
|
$utf8Bom = New-Object System.Text.UTF8Encoding $true
|
||||||
|
[System.IO.File]::WriteAllText($OutFile, $result, $utf8Bom)
|
||||||
|
}
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# --- 2. Register namespaces ---
|
||||||
|
|
||||||
|
$ns = New-Object System.Xml.XmlNamespaceManager($xmlDoc.NameTable)
|
||||||
|
$ns.AddNamespace("s", "http://v8.1c.ru/8.1/data-composition-system/schema")
|
||||||
|
$ns.AddNamespace("dcscom", "http://v8.1c.ru/8.1/data-composition-system/common")
|
||||||
|
$ns.AddNamespace("dcscor", "http://v8.1c.ru/8.1/data-composition-system/core")
|
||||||
|
$ns.AddNamespace("dcsset", "http://v8.1c.ru/8.1/data-composition-system/settings")
|
||||||
|
$ns.AddNamespace("v8", "http://v8.1c.ru/8.1/data/core")
|
||||||
|
$ns.AddNamespace("v8ui", "http://v8.1c.ru/8.1/data/ui")
|
||||||
|
$ns.AddNamespace("xs", "http://www.w3.org/2001/XMLSchema")
|
||||||
|
$ns.AddNamespace("xsi", "http://www.w3.org/2001/XMLSchema-instance")
|
||||||
|
$ns.AddNamespace("dcsat", "http://v8.1c.ru/8.1/data-composition-system/area-template")
|
||||||
|
|
||||||
|
$root = $xmlDoc.DocumentElement
|
||||||
|
|
||||||
|
# --- 3. Root element checks ---
|
||||||
|
|
||||||
|
if ($root.LocalName -ne "DataCompositionSchema") {
|
||||||
|
Report-Error "Root element is '$($root.LocalName)', expected 'DataCompositionSchema'"
|
||||||
|
} else {
|
||||||
|
Report-OK "Root element: DataCompositionSchema"
|
||||||
|
}
|
||||||
|
|
||||||
|
$expectedNs = "http://v8.1c.ru/8.1/data-composition-system/schema"
|
||||||
|
if ($root.NamespaceURI -ne $expectedNs) {
|
||||||
|
Report-Error "Default namespace is '$($root.NamespaceURI)', expected '$expectedNs'"
|
||||||
|
} else {
|
||||||
|
Report-OK "Default namespace correct"
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($script:stopped) { & $finalize; exit 1 }
|
||||||
|
|
||||||
|
# --- 4. Collect inventories ---
|
||||||
|
|
||||||
|
# DataSources
|
||||||
|
$dataSourceNodes = $root.SelectNodes("s:dataSource", $ns)
|
||||||
|
$dataSourceNames = @{}
|
||||||
|
foreach ($dsn in $dataSourceNodes) {
|
||||||
|
$name = $dsn.SelectSingleNode("s:name", $ns)
|
||||||
|
if ($name) { $dataSourceNames[$name.InnerText] = $true }
|
||||||
|
}
|
||||||
|
|
||||||
|
# DataSets (recursive for unions)
|
||||||
|
$dataSetNodes = $root.SelectNodes("s:dataSet", $ns)
|
||||||
|
$dataSetNames = @{}
|
||||||
|
$allFieldPaths = @{} # Global: dataPath → dataSet name
|
||||||
|
|
||||||
|
function Collect-DataSetFields {
|
||||||
|
param($dsNode, [string]$dsName)
|
||||||
|
|
||||||
|
$fields = $dsNode.SelectNodes("s:field", $ns)
|
||||||
|
$localPaths = @{}
|
||||||
|
foreach ($f in $fields) {
|
||||||
|
$dp = $f.SelectSingleNode("s:dataPath", $ns)
|
||||||
|
if ($dp) {
|
||||||
|
$path = $dp.InnerText
|
||||||
|
$localPaths[$path] = $true
|
||||||
|
$allFieldPaths[$path] = $dsName
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Union items
|
||||||
|
$items = $dsNode.SelectNodes("s:item", $ns)
|
||||||
|
foreach ($item in $items) {
|
||||||
|
$itemName = $item.SelectSingleNode("s:name", $ns)
|
||||||
|
if ($itemName) {
|
||||||
|
Collect-DataSetFields -dsNode $item -dsName $itemName.InnerText
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $localPaths
|
||||||
|
}
|
||||||
|
|
||||||
|
$dataSetFieldMap = @{} # dsName → hashtable of dataPath
|
||||||
|
foreach ($ds in $dataSetNodes) {
|
||||||
|
$nameNode = $ds.SelectSingleNode("s:name", $ns)
|
||||||
|
if ($nameNode) {
|
||||||
|
$dsName = $nameNode.InnerText
|
||||||
|
$dataSetNames[$dsName] = $true
|
||||||
|
$dataSetFieldMap[$dsName] = Collect-DataSetFields -dsNode $ds -dsName $dsName
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# CalculatedFields
|
||||||
|
$calcFieldNodes = $root.SelectNodes("s:calculatedField", $ns)
|
||||||
|
$calcFieldPaths = @{}
|
||||||
|
foreach ($cf in $calcFieldNodes) {
|
||||||
|
$dp = $cf.SelectSingleNode("s:dataPath", $ns)
|
||||||
|
if ($dp) { $calcFieldPaths[$dp.InnerText] = $true }
|
||||||
|
}
|
||||||
|
|
||||||
|
# TotalFields
|
||||||
|
$totalFieldNodes = $root.SelectNodes("s:totalField", $ns)
|
||||||
|
|
||||||
|
# Parameters
|
||||||
|
$paramNodes = $root.SelectNodes("s:parameter", $ns)
|
||||||
|
$paramNames = @{}
|
||||||
|
foreach ($p in $paramNodes) {
|
||||||
|
$nameNode = $p.SelectSingleNode("s:name", $ns)
|
||||||
|
if ($nameNode) { $paramNames[$nameNode.InnerText] = $true }
|
||||||
|
}
|
||||||
|
|
||||||
|
# Templates
|
||||||
|
$templateNodes = $root.SelectNodes("s:template", $ns)
|
||||||
|
$templateNames = @{}
|
||||||
|
foreach ($t in $templateNodes) {
|
||||||
|
$nameNode = $t.SelectSingleNode("s:name", $ns)
|
||||||
|
if ($nameNode) { $templateNames[$nameNode.InnerText] = $true }
|
||||||
|
}
|
||||||
|
|
||||||
|
# GroupTemplates
|
||||||
|
$groupTemplateNodes = $root.SelectNodes("s:groupTemplate", $ns)
|
||||||
|
|
||||||
|
# SettingsVariants
|
||||||
|
$variantNodes = $root.SelectNodes("s:settingsVariant", $ns)
|
||||||
|
|
||||||
|
# Known fields = dataset fields + calculated fields
|
||||||
|
$knownFields = @{}
|
||||||
|
foreach ($key in $allFieldPaths.Keys) { $knownFields[$key] = $true }
|
||||||
|
foreach ($key in $calcFieldPaths.Keys) { $knownFields[$key] = $true }
|
||||||
|
|
||||||
|
# --- 5. DataSource checks ---
|
||||||
|
|
||||||
|
if ($dataSourceNodes.Count -eq 0) {
|
||||||
|
Report-Warn "No dataSource elements found (settings-only DCS?)"
|
||||||
|
} else {
|
||||||
|
$dsNamesSeen = @{}
|
||||||
|
$dsOk = $true
|
||||||
|
foreach ($dsn in $dataSourceNodes) {
|
||||||
|
$name = $dsn.SelectSingleNode("s:name", $ns)
|
||||||
|
$type = $dsn.SelectSingleNode("s:dataSourceType", $ns)
|
||||||
|
if (-not $name -or -not $name.InnerText) {
|
||||||
|
Report-Error "DataSource has empty name"
|
||||||
|
$dsOk = $false
|
||||||
|
} elseif ($dsNamesSeen.ContainsKey($name.InnerText)) {
|
||||||
|
Report-Error "Duplicate dataSource name: $($name.InnerText)"
|
||||||
|
$dsOk = $false
|
||||||
|
} else {
|
||||||
|
$dsNamesSeen[$name.InnerText] = $true
|
||||||
|
}
|
||||||
|
if ($type) {
|
||||||
|
$tv = $type.InnerText
|
||||||
|
if ($tv -ne "Local" -and $tv -ne "External") {
|
||||||
|
Report-Warn "DataSource '$($name.InnerText)' has unusual type: $tv"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ($dsOk) {
|
||||||
|
Report-OK "$($dataSourceNodes.Count) dataSource(s) found, names unique"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($script:stopped) { & $finalize; exit 1 }
|
||||||
|
|
||||||
|
# --- 6. DataSet checks ---
|
||||||
|
|
||||||
|
$validDsTypes = @("DataSetQuery", "DataSetObject", "DataSetUnion")
|
||||||
|
|
||||||
|
if ($dataSetNodes.Count -eq 0) {
|
||||||
|
Report-Warn "No dataSet elements found (settings-only DCS?)"
|
||||||
|
} else {
|
||||||
|
$dsNamesSeen = @{}
|
||||||
|
$dsOk = $true
|
||||||
|
foreach ($ds in $dataSetNodes) {
|
||||||
|
$xsiType = $ds.GetAttribute("type", "http://www.w3.org/2001/XMLSchema-instance")
|
||||||
|
$nameNode = $ds.SelectSingleNode("s:name", $ns)
|
||||||
|
$dsName = if ($nameNode) { $nameNode.InnerText } else { "(unnamed)" }
|
||||||
|
|
||||||
|
if (-not $nameNode -or -not $nameNode.InnerText) {
|
||||||
|
Report-Error "DataSet has empty name"
|
||||||
|
$dsOk = $false
|
||||||
|
} elseif ($dsNamesSeen.ContainsKey($dsName)) {
|
||||||
|
Report-Error "Duplicate dataSet name: $dsName"
|
||||||
|
$dsOk = $false
|
||||||
|
} else {
|
||||||
|
$dsNamesSeen[$dsName] = $true
|
||||||
|
}
|
||||||
|
|
||||||
|
if (-not $xsiType) {
|
||||||
|
Report-Error "DataSet '$dsName' missing xsi:type"
|
||||||
|
$dsOk = $false
|
||||||
|
} elseif ($validDsTypes -notcontains $xsiType) {
|
||||||
|
Report-Warn "DataSet '$dsName' has unusual xsi:type: $xsiType"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Check dataSource reference
|
||||||
|
if ($xsiType -ne "DataSetUnion") {
|
||||||
|
$srcNode = $ds.SelectSingleNode("s:dataSource", $ns)
|
||||||
|
if ($srcNode -and $srcNode.InnerText) {
|
||||||
|
if (-not $dataSourceNames.ContainsKey($srcNode.InnerText)) {
|
||||||
|
Report-Error "DataSet '$dsName' references unknown dataSource: $($srcNode.InnerText)"
|
||||||
|
$dsOk = $false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Check query not empty for Query type
|
||||||
|
if ($xsiType -eq "DataSetQuery") {
|
||||||
|
$queryNode = $ds.SelectSingleNode("s:query", $ns)
|
||||||
|
if (-not $queryNode -or -not $queryNode.InnerText.Trim()) {
|
||||||
|
Report-Warn "DataSet '$dsName' (Query) has empty query"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Check objectName for Object type
|
||||||
|
if ($xsiType -eq "DataSetObject") {
|
||||||
|
$objNode = $ds.SelectSingleNode("s:objectName", $ns)
|
||||||
|
if (-not $objNode -or -not $objNode.InnerText.Trim()) {
|
||||||
|
Report-Error "DataSet '$dsName' (Object) has empty objectName"
|
||||||
|
$dsOk = $false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($dsOk) {
|
||||||
|
Report-OK "$($dataSetNodes.Count) dataSet(s) found, names unique"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($script:stopped) { & $finalize; exit 1 }
|
||||||
|
|
||||||
|
# --- 7. Field checks ---
|
||||||
|
|
||||||
|
function Check-DataSetFields {
|
||||||
|
param($dsNode, [string]$dsName)
|
||||||
|
|
||||||
|
$fields = $dsNode.SelectNodes("s:field", $ns)
|
||||||
|
if ($fields.Count -eq 0) { return }
|
||||||
|
|
||||||
|
$pathsSeen = @{}
|
||||||
|
$fieldOk = $true
|
||||||
|
|
||||||
|
foreach ($f in $fields) {
|
||||||
|
$dp = $f.SelectSingleNode("s:dataPath", $ns)
|
||||||
|
$fn = $f.SelectSingleNode("s:field", $ns)
|
||||||
|
|
||||||
|
if (-not $dp -or -not $dp.InnerText) {
|
||||||
|
Report-Error "DataSet '$dsName': field has empty dataPath"
|
||||||
|
$fieldOk = $false
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
$path = $dp.InnerText
|
||||||
|
if ($pathsSeen.ContainsKey($path)) {
|
||||||
|
Report-Warn "DataSet '$dsName': duplicate dataPath '$path'"
|
||||||
|
} else {
|
||||||
|
$pathsSeen[$path] = $true
|
||||||
|
}
|
||||||
|
|
||||||
|
if (-not $fn -or -not $fn.InnerText) {
|
||||||
|
Report-Warn "DataSet '$dsName': field '$path' has empty <field> element"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($fieldOk) {
|
||||||
|
Report-OK "DataSet `"$dsName`": $($fields.Count) fields, dataPath unique"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Check union items recursively
|
||||||
|
$items = $dsNode.SelectNodes("s:item", $ns)
|
||||||
|
foreach ($item in $items) {
|
||||||
|
$itemName = $item.SelectSingleNode("s:name", $ns)
|
||||||
|
$iName = if ($itemName) { $itemName.InnerText } else { "(unnamed item)" }
|
||||||
|
Check-DataSetFields -dsNode $item -dsName $iName
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($ds in $dataSetNodes) {
|
||||||
|
$nameNode = $ds.SelectSingleNode("s:name", $ns)
|
||||||
|
$dsName = if ($nameNode) { $nameNode.InnerText } else { "(unnamed)" }
|
||||||
|
Check-DataSetFields -dsNode $ds -dsName $dsName
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($script:stopped) { & $finalize; exit 1 }
|
||||||
|
|
||||||
|
# --- 8. DataSetLink checks ---
|
||||||
|
|
||||||
|
$linkNodes = $root.SelectNodes("s:dataSetLink", $ns)
|
||||||
|
if ($linkNodes.Count -gt 0) {
|
||||||
|
$linkOk = $true
|
||||||
|
foreach ($link in $linkNodes) {
|
||||||
|
$src = $link.SelectSingleNode("s:sourceDataSet", $ns)
|
||||||
|
$dst = $link.SelectSingleNode("s:destinationDataSet", $ns)
|
||||||
|
$srcExpr = $link.SelectSingleNode("s:sourceExpression", $ns)
|
||||||
|
$dstExpr = $link.SelectSingleNode("s:destinationExpression", $ns)
|
||||||
|
|
||||||
|
if ($src -and $src.InnerText -and -not $dataSetNames.ContainsKey($src.InnerText)) {
|
||||||
|
Report-Error "DataSetLink: sourceDataSet '$($src.InnerText)' not found"
|
||||||
|
$linkOk = $false
|
||||||
|
}
|
||||||
|
if ($dst -and $dst.InnerText -and -not $dataSetNames.ContainsKey($dst.InnerText)) {
|
||||||
|
Report-Error "DataSetLink: destinationDataSet '$($dst.InnerText)' not found"
|
||||||
|
$linkOk = $false
|
||||||
|
}
|
||||||
|
if (-not $srcExpr -or -not $srcExpr.InnerText.Trim()) {
|
||||||
|
Report-Error "DataSetLink: empty sourceExpression"
|
||||||
|
$linkOk = $false
|
||||||
|
}
|
||||||
|
if (-not $dstExpr -or -not $dstExpr.InnerText.Trim()) {
|
||||||
|
Report-Error "DataSetLink: empty destinationExpression"
|
||||||
|
$linkOk = $false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ($linkOk) {
|
||||||
|
Report-OK "$($linkNodes.Count) dataSetLink(s): references valid"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($script:stopped) { & $finalize; exit 1 }
|
||||||
|
|
||||||
|
# --- 9. CalculatedField checks ---
|
||||||
|
|
||||||
|
if ($calcFieldNodes.Count -gt 0) {
|
||||||
|
$cfOk = $true
|
||||||
|
$cfSeen = @{}
|
||||||
|
foreach ($cf in $calcFieldNodes) {
|
||||||
|
$dp = $cf.SelectSingleNode("s:dataPath", $ns)
|
||||||
|
$expr = $cf.SelectSingleNode("s:expression", $ns)
|
||||||
|
|
||||||
|
if (-not $dp -or -not $dp.InnerText) {
|
||||||
|
Report-Error "CalculatedField has empty dataPath"
|
||||||
|
$cfOk = $false
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
$path = $dp.InnerText
|
||||||
|
if ($cfSeen.ContainsKey($path)) {
|
||||||
|
Report-Error "Duplicate calculatedField dataPath: $path"
|
||||||
|
$cfOk = $false
|
||||||
|
} else {
|
||||||
|
$cfSeen[$path] = $true
|
||||||
|
}
|
||||||
|
|
||||||
|
if (-not $expr -or -not $expr.InnerText.Trim()) {
|
||||||
|
Report-Error "CalculatedField '$path' has empty expression"
|
||||||
|
$cfOk = $false
|
||||||
|
}
|
||||||
|
|
||||||
|
# Warn if collides with a dataset field
|
||||||
|
if ($allFieldPaths.ContainsKey($path)) {
|
||||||
|
Report-Warn "CalculatedField '$path' shadows dataSet field in '$($allFieldPaths[$path])'"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($cfOk) {
|
||||||
|
Report-OK "$($calcFieldNodes.Count) calculatedField(s): dataPath and expression valid"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($script:stopped) { & $finalize; exit 1 }
|
||||||
|
|
||||||
|
# --- 10. TotalField checks ---
|
||||||
|
|
||||||
|
if ($totalFieldNodes.Count -gt 0) {
|
||||||
|
$tfOk = $true
|
||||||
|
foreach ($tf in $totalFieldNodes) {
|
||||||
|
$dp = $tf.SelectSingleNode("s:dataPath", $ns)
|
||||||
|
$expr = $tf.SelectSingleNode("s:expression", $ns)
|
||||||
|
|
||||||
|
if (-not $dp -or -not $dp.InnerText) {
|
||||||
|
Report-Error "TotalField has empty dataPath"
|
||||||
|
$tfOk = $false
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if (-not $expr -or -not $expr.InnerText.Trim()) {
|
||||||
|
Report-Error "TotalField '$($dp.InnerText)' has empty expression"
|
||||||
|
$tfOk = $false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($tfOk) {
|
||||||
|
Report-OK "$($totalFieldNodes.Count) totalField(s): dataPath and expression present"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($script:stopped) { & $finalize; exit 1 }
|
||||||
|
|
||||||
|
# --- 11. Parameter checks ---
|
||||||
|
|
||||||
|
if ($paramNodes.Count -gt 0) {
|
||||||
|
$paramOk = $true
|
||||||
|
$paramSeen = @{}
|
||||||
|
foreach ($p in $paramNodes) {
|
||||||
|
$nameNode = $p.SelectSingleNode("s:name", $ns)
|
||||||
|
if (-not $nameNode -or -not $nameNode.InnerText) {
|
||||||
|
Report-Error "Parameter has empty name"
|
||||||
|
$paramOk = $false
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
$pName = $nameNode.InnerText
|
||||||
|
if ($paramSeen.ContainsKey($pName)) {
|
||||||
|
Report-Error "Duplicate parameter name: $pName"
|
||||||
|
$paramOk = $false
|
||||||
|
} else {
|
||||||
|
$paramSeen[$pName] = $true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ($paramOk) {
|
||||||
|
Report-OK "$($paramNodes.Count) parameter(s): names unique"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($script:stopped) { & $finalize; exit 1 }
|
||||||
|
|
||||||
|
# --- 12. Template checks ---
|
||||||
|
|
||||||
|
if ($templateNodes.Count -gt 0) {
|
||||||
|
$tplOk = $true
|
||||||
|
$tplSeen = @{}
|
||||||
|
foreach ($t in $templateNodes) {
|
||||||
|
$nameNode = $t.SelectSingleNode("s:name", $ns)
|
||||||
|
if (-not $nameNode -or -not $nameNode.InnerText) {
|
||||||
|
Report-Error "Template has empty name"
|
||||||
|
$tplOk = $false
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
$tName = $nameNode.InnerText
|
||||||
|
if ($tplSeen.ContainsKey($tName)) {
|
||||||
|
Report-Error "Duplicate template name: $tName"
|
||||||
|
$tplOk = $false
|
||||||
|
} else {
|
||||||
|
$tplSeen[$tName] = $true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ($tplOk) {
|
||||||
|
Report-OK "$($templateNodes.Count) template(s): names unique"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# --- 13. GroupTemplate checks ---
|
||||||
|
|
||||||
|
if ($groupTemplateNodes.Count -gt 0) {
|
||||||
|
$gtOk = $true
|
||||||
|
$validTplTypes = @("Header", "Footer", "Overall", "OverallHeader", "OverallFooter")
|
||||||
|
foreach ($gt in $groupTemplateNodes) {
|
||||||
|
$tplRef = $gt.SelectSingleNode("s:template", $ns)
|
||||||
|
$tplType = $gt.SelectSingleNode("s:templateType", $ns)
|
||||||
|
|
||||||
|
if ($tplRef -and $tplRef.InnerText -and -not $templateNames.ContainsKey($tplRef.InnerText)) {
|
||||||
|
Report-Error "GroupTemplate references unknown template: $($tplRef.InnerText)"
|
||||||
|
$gtOk = $false
|
||||||
|
}
|
||||||
|
if ($tplType -and $validTplTypes -notcontains $tplType.InnerText) {
|
||||||
|
Report-Warn "GroupTemplate has unusual templateType: $($tplType.InnerText)"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ($gtOk) {
|
||||||
|
Report-OK "$($groupTemplateNodes.Count) groupTemplate(s): references valid"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($script:stopped) { & $finalize; exit 1 }
|
||||||
|
|
||||||
|
# --- 14. Settings helper functions ---
|
||||||
|
|
||||||
|
$validComparisonTypes = @(
|
||||||
|
"Equal","NotEqual","Greater","GreaterOrEqual","Less","LessOrEqual",
|
||||||
|
"InList","NotInList","InHierarchy","InListByHierarchy",
|
||||||
|
"Contains","NotContains","BeginsWith","NotBeginsWith",
|
||||||
|
"Filled","NotFilled"
|
||||||
|
)
|
||||||
|
|
||||||
|
$validStructureTypes = @(
|
||||||
|
"dcsset:StructureItemGroup",
|
||||||
|
"dcsset:StructureItemTable",
|
||||||
|
"dcsset:StructureItemChart",
|
||||||
|
"dcsset:StructureItemNestedObject"
|
||||||
|
)
|
||||||
|
|
||||||
|
function Check-FilterItems {
|
||||||
|
param($parentNode, [string]$variantName)
|
||||||
|
|
||||||
|
$filterItems = $parentNode.SelectNodes("dcsset:filter/dcsset:item", $ns)
|
||||||
|
foreach ($fi in $filterItems) {
|
||||||
|
if ($script:stopped) { return }
|
||||||
|
$xsiType = $fi.GetAttribute("type", "http://www.w3.org/2001/XMLSchema-instance")
|
||||||
|
if ($xsiType -eq "dcsset:FilterItemComparison") {
|
||||||
|
$compType = $fi.SelectSingleNode("dcsset:comparisonType", $ns)
|
||||||
|
if ($compType -and $validComparisonTypes -notcontains $compType.InnerText) {
|
||||||
|
Report-Error "Variant '$variantName' filter: invalid comparisonType '$($compType.InnerText)'"
|
||||||
|
}
|
||||||
|
} elseif ($xsiType -eq "dcsset:FilterItemGroup") {
|
||||||
|
$groupType = $fi.SelectSingleNode("dcsset:groupType", $ns)
|
||||||
|
if ($groupType) {
|
||||||
|
$validGroupTypes = @("AndGroup","OrGroup","NotGroup")
|
||||||
|
if ($validGroupTypes -notcontains $groupType.InnerText) {
|
||||||
|
Report-Warn "Variant '$variantName' filter group: unusual groupType '$($groupType.InnerText)'"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
# Recurse into nested items
|
||||||
|
$nestedItems = $fi.SelectNodes("dcsset:item", $ns)
|
||||||
|
foreach ($ni in $nestedItems) {
|
||||||
|
$niType = $ni.GetAttribute("type", "http://www.w3.org/2001/XMLSchema-instance")
|
||||||
|
if ($niType -eq "dcsset:FilterItemComparison") {
|
||||||
|
$compType = $ni.SelectSingleNode("dcsset:comparisonType", $ns)
|
||||||
|
if ($compType -and $validComparisonTypes -notcontains $compType.InnerText) {
|
||||||
|
Report-Error "Variant '$variantName' filter: invalid comparisonType '$($compType.InnerText)'"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function Check-StructureItem {
|
||||||
|
param($itemNode, [string]$variantName)
|
||||||
|
|
||||||
|
if ($script:stopped) { return }
|
||||||
|
|
||||||
|
$xsiType = $itemNode.GetAttribute("type", "http://www.w3.org/2001/XMLSchema-instance")
|
||||||
|
if (-not $xsiType) {
|
||||||
|
Report-Error "Variant '$variantName': structure item missing xsi:type"
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if ($validStructureTypes -notcontains $xsiType) {
|
||||||
|
Report-Warn "Variant '$variantName': unusual structure item type '$xsiType'"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Recurse into nested items (groups can contain groups)
|
||||||
|
$nestedItems = $itemNode.SelectNodes("dcsset:item", $ns)
|
||||||
|
foreach ($ni in $nestedItems) {
|
||||||
|
Check-StructureItem -itemNode $ni -variantName $variantName
|
||||||
|
}
|
||||||
|
|
||||||
|
# Check column/row in tables
|
||||||
|
if ($xsiType -eq "dcsset:StructureItemTable") {
|
||||||
|
$columns = $itemNode.SelectNodes("dcsset:column", $ns)
|
||||||
|
$rows = $itemNode.SelectNodes("dcsset:row", $ns)
|
||||||
|
if ($columns.Count -eq 0) {
|
||||||
|
Report-Warn "Variant '$variantName': table has no columns"
|
||||||
|
}
|
||||||
|
if ($rows.Count -eq 0) {
|
||||||
|
Report-Warn "Variant '$variantName': table has no rows"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function Check-Settings {
|
||||||
|
param($settingsNode, [string]$variantName)
|
||||||
|
|
||||||
|
if ($script:stopped) { return }
|
||||||
|
|
||||||
|
# Selection
|
||||||
|
$selItems = $settingsNode.SelectNodes("dcsset:selection/dcsset:item", $ns)
|
||||||
|
foreach ($si in $selItems) {
|
||||||
|
$xsiType = $si.GetAttribute("type", "http://www.w3.org/2001/XMLSchema-instance")
|
||||||
|
if ($xsiType -eq "dcsset:SelectedItemField") {
|
||||||
|
$field = $si.SelectSingleNode("dcsset:field", $ns)
|
||||||
|
if ($field -and $field.InnerText -and $field.InnerText -ne "SystemFields.Number") {
|
||||||
|
$basePath = ($field.InnerText -split '\.')[0]
|
||||||
|
if (-not $knownFields.ContainsKey($field.InnerText) -and -not $knownFields.ContainsKey($basePath)) {
|
||||||
|
# Soft check — autoFillFields may add fields not listed explicitly
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Filter
|
||||||
|
Check-FilterItems -parentNode $settingsNode -variantName $variantName
|
||||||
|
|
||||||
|
# Order
|
||||||
|
$orderItems = $settingsNode.SelectNodes("dcsset:order/dcsset:item", $ns)
|
||||||
|
foreach ($oi in $orderItems) {
|
||||||
|
$xsiType = $oi.GetAttribute("type", "http://www.w3.org/2001/XMLSchema-instance")
|
||||||
|
if ($xsiType -eq "dcsset:OrderItemField") {
|
||||||
|
$orderType = $oi.SelectSingleNode("dcsset:orderType", $ns)
|
||||||
|
if ($orderType -and $orderType.InnerText -ne "Asc" -and $orderType.InnerText -ne "Desc") {
|
||||||
|
Report-Warn "Variant '$variantName' order: invalid orderType '$($orderType.InnerText)'"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Structure items
|
||||||
|
$structItems = $settingsNode.SelectNodes("dcsset:item", $ns)
|
||||||
|
foreach ($si in $structItems) {
|
||||||
|
Check-StructureItem -itemNode $si -variantName $variantName
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# --- 15. SettingsVariant checks ---
|
||||||
|
|
||||||
|
if ($variantNodes.Count -eq 0) {
|
||||||
|
Report-Warn "No settingsVariant elements found"
|
||||||
|
} else {
|
||||||
|
$vOk = $true
|
||||||
|
$vIdx = 0
|
||||||
|
foreach ($v in $variantNodes) {
|
||||||
|
$vIdx++
|
||||||
|
$vName = $v.SelectSingleNode("dcsset:name", $ns)
|
||||||
|
if (-not $vName -or -not $vName.InnerText) {
|
||||||
|
Report-Error "SettingsVariant #$vIdx has empty name"
|
||||||
|
$vOk = $false
|
||||||
|
}
|
||||||
|
|
||||||
|
$settings = $v.SelectSingleNode("dcsset:settings", $ns)
|
||||||
|
if (-not $settings) {
|
||||||
|
Report-Error "SettingsVariant '$($vName.InnerText)' has no settings element"
|
||||||
|
$vOk = $false
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
# Check settings internals
|
||||||
|
Check-Settings -settingsNode $settings -variantName "$($vName.InnerText)"
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($vOk) {
|
||||||
|
Report-OK "$($variantNodes.Count) settingsVariant(s) found"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# --- Final output ---
|
||||||
|
|
||||||
|
& $finalize
|
||||||
|
|
||||||
|
if ($script:errors -gt 0) {
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
exit 0
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2025-2026 Nick Shirokov
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
@@ -1,5 +1,7 @@
|
|||||||
# 1C Skills for Claude Code
|
# 1C Skills for Claude Code
|
||||||
|
|
||||||
|
> **Work in progress** — проект в стадии активной разработки. Набор навыков и операций расширяется.
|
||||||
|
|
||||||
Набор [Claude Code Skills](https://docs.anthropic.com/en/docs/claude-code/skills) для работы с артефактами 1С:Предприятия 8.3. Позволяет создавать и модифицировать обработки, макеты печатных форм и другие объекты из XML-исходников, не запоминая детали формата.
|
Набор [Claude Code Skills](https://docs.anthropic.com/en/docs/claude-code/skills) для работы с артефактами 1С:Предприятия 8.3. Позволяет создавать и модифицировать обработки, макеты печатных форм и другие объекты из XML-исходников, не запоминая детали формата.
|
||||||
|
|
||||||
## Быстрый старт
|
## Быстрый старт
|
||||||
@@ -23,6 +25,7 @@
|
|||||||
| Табличный документ (MXL) | 4 навыка `/mxl-*` | Анализ, создание, компиляция макетов печатных форм | [Подробнее](docs/mxl-guide.md) |
|
| Табличный документ (MXL) | 4 навыка `/mxl-*` | Анализ, создание, компиляция макетов печатных форм | [Подробнее](docs/mxl-guide.md) |
|
||||||
| Управляемые формы (Form) | 6 навыков `/form-*` | Создание, анализ, генерация, модификация, валидация управляемых форм | [Подробнее](docs/form-guide.md) |
|
| Управляемые формы (Form) | 6 навыков `/form-*` | Создание, анализ, генерация, модификация, валидация управляемых форм | [Подробнее](docs/form-guide.md) |
|
||||||
| Роли (Role) | 3 навыка `/role-*` | Анализ прав роли, создание из JSON DSL, валидация | [Подробнее](docs/role-guide.md) |
|
| Роли (Role) | 3 навыка `/role-*` | Анализ прав роли, создание из JSON DSL, валидация | [Подробнее](docs/role-guide.md) |
|
||||||
|
| Схема компоновки (СКД) | 4 навыка `/skd-*` | Анализ, генерация из JSON DSL, точечное редактирование, валидация схем компоновки данных | [Подробнее](docs/skd-guide.md) |
|
||||||
| Утилиты | `/img-grid` | Наложение сетки на изображение для определения пропорций колонок | — |
|
| Утилиты | `/img-grid` | Наложение сетки на изображение для определения пропорций колонок | — |
|
||||||
|
|
||||||
## Требования
|
## Требования
|
||||||
@@ -41,6 +44,8 @@
|
|||||||
- [Form DSL](docs/form-dsl-spec.md) — JSON-формат описания формы для `/form-compile`
|
- [Form DSL](docs/form-dsl-spec.md) — JSON-формат описания формы для `/form-compile`
|
||||||
- [Роли (Rights.xml)](docs/1c-role-spec.md) — XML-формат прав роли, типы объектов, RLS
|
- [Роли (Rights.xml)](docs/1c-role-spec.md) — XML-формат прав роли, типы объектов, RLS
|
||||||
- [Role DSL](docs/role-dsl-spec.md) — JSON-формат описания ролей для `/role-compile`
|
- [Role DSL](docs/role-dsl-spec.md) — JSON-формат описания ролей для `/role-compile`
|
||||||
|
- [Схема компоновки данных (DCS)](docs/1c-dcs-spec.md) — XML-формат DataCompositionSchema, 930 схем проанализировано
|
||||||
|
- [SKD DSL](docs/skd-dsl-spec.md) — JSON-формат описания СКД для `/skd-compile`
|
||||||
|
|
||||||
## Структура репозитория
|
## Структура репозитория
|
||||||
|
|
||||||
@@ -69,12 +74,17 @@
|
|||||||
├── role-info/ # Анализ прав роли
|
├── role-info/ # Анализ прав роли
|
||||||
├── role-compile/ # Создание роли из JSON DSL
|
├── role-compile/ # Создание роли из JSON DSL
|
||||||
├── role-validate/ # Валидация роли
|
├── role-validate/ # Валидация роли
|
||||||
|
├── skd-info/ # Анализ схемы компоновки данных
|
||||||
|
├── skd-compile/ # Компиляция СКД из JSON DSL
|
||||||
|
├── skd-edit/ # Точечное редактирование СКД (25 операций)
|
||||||
|
├── skd-validate/ # Валидация СКД
|
||||||
└── img-grid/ # Сетка для анализа изображений
|
└── img-grid/ # Сетка для анализа изображений
|
||||||
docs/
|
docs/
|
||||||
├── epf-guide.md # Гайд: внешние обработки
|
├── epf-guide.md # Гайд: внешние обработки
|
||||||
├── mxl-guide.md # Гайд: табличный документ
|
├── mxl-guide.md # Гайд: табличный документ
|
||||||
├── form-guide.md # Гайд: управляемые формы
|
├── form-guide.md # Гайд: управляемые формы
|
||||||
├── role-guide.md # Гайд: роли
|
├── role-guide.md # Гайд: роли
|
||||||
|
├── skd-guide.md # Гайд: схема компоновки данных
|
||||||
├── 1c-xml-format-spec.md # Спецификация XML-формата
|
├── 1c-xml-format-spec.md # Спецификация XML-формата
|
||||||
├── 1c-form-spec.md # Спецификация управляемых форм
|
├── 1c-form-spec.md # Спецификация управляемых форм
|
||||||
├── 1c-help-spec.md # Спецификация встроенной справки
|
├── 1c-help-spec.md # Спецификация встроенной справки
|
||||||
@@ -82,5 +92,8 @@ docs/
|
|||||||
├── 1c-spreadsheet-spec.md # Спецификация табличного документа
|
├── 1c-spreadsheet-spec.md # Спецификация табличного документа
|
||||||
├── mxl-dsl-spec.md # Спецификация MXL DSL
|
├── mxl-dsl-spec.md # Спецификация MXL DSL
|
||||||
├── form-dsl-spec.md # Спецификация Form DSL
|
├── form-dsl-spec.md # Спецификация Form DSL
|
||||||
└── 1c-role-spec.md # Спецификация ролей (Rights.xml)
|
├── 1c-role-spec.md # Спецификация ролей (Rights.xml)
|
||||||
|
├── 1c-dcs-spec.md # Спецификация СКД (DataCompositionSchema)
|
||||||
|
├── skd-dsl-spec.md # Спецификация SKD DSL
|
||||||
|
└── role-dsl-spec.md # Спецификация Role DSL
|
||||||
```
|
```
|
||||||
|
|||||||
+34
-4
@@ -299,7 +299,8 @@ DataCompositionSchema
|
|||||||
| `dcscom:accountTypeExpression` | Выражение для определения типа счёта |
|
| `dcscom:accountTypeExpression` | Выражение для определения типа счёта |
|
||||||
| `dcscom:balance` | Поле является остатком |
|
| `dcscom:balance` | Поле является остатком |
|
||||||
| `dcscom:balanceGroup` | Группа остатка |
|
| `dcscom:balanceGroup` | Группа остатка |
|
||||||
| `dcscom:period` | Поле — период |
|
| `dcscom:periodNumber` | Номер периода (обычно `1`) |
|
||||||
|
| `dcscom:periodType` | Тип периода (`Main`, `Additional`) |
|
||||||
|
|
||||||
### 4.7. Тип значения (valueType)
|
### 4.7. Тип значения (valueType)
|
||||||
|
|
||||||
@@ -313,7 +314,15 @@ DataCompositionSchema
|
|||||||
</valueType>
|
</valueType>
|
||||||
```
|
```
|
||||||
|
|
||||||
Типы: `xs:string`, `xs:dateTime`, `xs:decimal`, `xs:boolean`, ссылочные (`d4p1:CatalogRef.Номенклатура`).
|
Типы: `xs:string`, `xs:dateTime`, `xs:decimal`, `xs:boolean`, ссылочные типы конфигурации.
|
||||||
|
|
||||||
|
Ссылочные типы объявляются с inline namespace на элементе `<v8:Type>`:
|
||||||
|
|
||||||
|
```xml
|
||||||
|
<v8:Type xmlns:d5p1="http://v8.1c.ru/8.1/data/enterprise/current-config">d5p1:CatalogRef.Номенклатура</v8:Type>
|
||||||
|
```
|
||||||
|
|
||||||
|
Префикс (`d5p1`, `d4p1` и т.д.) — автогенерируемый, суть в URI `http://v8.1c.ru/8.1/data/enterprise/current-config`. Поддерживаются: `CatalogRef`, `DocumentRef`, `EnumRef`, `ChartOfAccountsRef`, `ChartOfCharacteristicTypesRef` и др.
|
||||||
|
|
||||||
Квалификаторы:
|
Квалификаторы:
|
||||||
- `v8:StringQualifiers` → `v8:Length`, `v8:AllowedLength` (Fixed/Variable)
|
- `v8:StringQualifiers` → `v8:Length`, `v8:AllowedLength` (Fixed/Variable)
|
||||||
@@ -446,7 +455,28 @@ DataCompositionSchema
|
|||||||
|---|---|---|
|
|---|---|---|
|
||||||
| `dataPath` | да | Путь к полю |
|
| `dataPath` | да | Путь к полю |
|
||||||
| `expression` | да | Агрегатная функция: `Сумма(...)`, `Количество(...)`, `Максимум(...)`, `Минимум(...)`, `Среднее(...)` |
|
| `expression` | да | Агрегатная функция: `Сумма(...)`, `Количество(...)`, `Максимум(...)`, `Минимум(...)`, `Среднее(...)` |
|
||||||
| `group` | нет | Для какой группировки считать итоги |
|
| `group` | нет | Имя группировки, для которой считать итоги. Без `group` — для всех группировок |
|
||||||
|
|
||||||
|
### Разные формулы для разных группировок
|
||||||
|
|
||||||
|
Одно поле может иметь несколько записей `totalField` с разными формулами для разных группировок:
|
||||||
|
|
||||||
|
```xml
|
||||||
|
<!-- Для группировки "ОбъектМетаданных" — агрегация самого поля -->
|
||||||
|
<totalField>
|
||||||
|
<dataPath>ПравоИнтерактивное</dataPath>
|
||||||
|
<expression>Максимум(ПравоИнтерактивное)</expression>
|
||||||
|
<group>ОбъектМетаданных</group>
|
||||||
|
</totalField>
|
||||||
|
<!-- Для группировки "Отчет" — агрегация другого поля -->
|
||||||
|
<totalField>
|
||||||
|
<dataPath>ПравоИнтерактивное</dataPath>
|
||||||
|
<expression>Максимум(ПравоОтчета)</expression>
|
||||||
|
<group>Отчет</group>
|
||||||
|
</totalField>
|
||||||
|
```
|
||||||
|
|
||||||
|
Это позволяет вычислять ресурс по-разному в зависимости от контекста группировки.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -494,7 +524,7 @@ DataCompositionSchema
|
|||||||
| Дата | `xs:dateTime` | `0001-01-01T00:00:00` |
|
| Дата | `xs:dateTime` | `0001-01-01T00:00:00` |
|
||||||
| Строка | `xs:string` | `Т13` |
|
| Строка | `xs:string` | `Т13` |
|
||||||
| Стандартный период | `v8:StandardPeriod` | `<v8:variant>LastMonth</v8:variant>` |
|
| Стандартный период | `v8:StandardPeriod` | `<v8:variant>LastMonth</v8:variant>` |
|
||||||
| Ссылка | `d4p1:CatalogRef.ИмяСправочника` | `xsi:nil="true"` |
|
| Ссылка | `d5p1:CatalogRef.ИмяСправочника` (с `xmlns:d5p1="http://v8.1c.ru/8.1/data/enterprise/current-config"`) | `xsi:nil="true"` |
|
||||||
| null | — | `xsi:nil="true"` |
|
| null | — | `xsi:nil="true"` |
|
||||||
|
|
||||||
Стандартные варианты периодов (`v8:StandardPeriodVariant`): `Custom`, `Today`, `ThisWeek`, `ThisMonth`, `ThisQuarter`, `ThisYear`, `LastMonth`, `LastQuarter`, `LastYear` и др.
|
Стандартные варианты периодов (`v8:StandardPeriodVariant`): `Custom`, `Today`, `ThisWeek`, `ThisMonth`, `ThisQuarter`, `ThisYear`, `LastMonth`, `LastQuarter`, `LastYear` и др.
|
||||||
|
|||||||
@@ -0,0 +1,790 @@
|
|||||||
|
# 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) |
|
||||||
|
| `objectName` | да* | Имя объекта (DataSetObject) |
|
||||||
|
| `items` | да* | Вложенные наборы (DataSetUnion) |
|
||||||
|
| `fields` | нет | Массив полей |
|
||||||
|
| `autoFillFields` | нет | `false` — отключить автозаполнение (по умолчанию не выводится = true) |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. Поля — shorthand и объектная форма
|
||||||
|
|
||||||
|
### Shorthand-строка
|
||||||
|
|
||||||
|
```
|
||||||
|
"<dataPath>[: <type>] [@role...] [#restrict...]"
|
||||||
|
```
|
||||||
|
|
||||||
|
Примеры:
|
||||||
|
|
||||||
|
```json
|
||||||
|
"fields": [
|
||||||
|
"Наименование",
|
||||||
|
"Количество: decimal(15,2)",
|
||||||
|
"Организация: CatalogRef.Организации @dimension",
|
||||||
|
"Служебное: string #noFilter #noOrder",
|
||||||
|
"Счёт: CatalogRef.Хозрасчетный @account",
|
||||||
|
"Сумма: decimal(15,2) @balance"
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
### Объектная форма
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"dataPath": "Сумма",
|
||||||
|
"field": "Сумма",
|
||||||
|
"title": "Сумма продаж",
|
||||||
|
"type": "decimal(15,2)",
|
||||||
|
"role": { "dimension": true },
|
||||||
|
"restrict": ["noFilter", "noGroup"],
|
||||||
|
"attrRestrict": ["noFilter"],
|
||||||
|
"appearance": { "Формат": "ЧДЦ=2" },
|
||||||
|
"presentationExpression": "Формат(Сумма, \"ЧДЦ=2\")"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Парсинг shorthand
|
||||||
|
|
||||||
|
1. Разделить по пробелам; найти `@`-роли и `#`-ограничения
|
||||||
|
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)`.
|
||||||
|
|
||||||
|
### Роли
|
||||||
|
|
||||||
|
| DSL shorthand | Объектная форма | XML |
|
||||||
|
|---------------|----------------|-----|
|
||||||
|
| `@dimension` | `"role": "dimension"` или `{"dimension": true}` | `<dcscom:dimension>true</dcscom:dimension>` |
|
||||||
|
| `@account` | `"role": "account"` или `{"account": true}` | `<dcscom:account>true</dcscom:account>` |
|
||||||
|
| `@balance` | `"role": "balance"` или `{"balance": true}` | `<dcscom:balance>true</dcscom:balance>` |
|
||||||
|
| `@period` | `"role": "period"` или `{"period": true}` | `<dcscom:periodNumber>1</dcscom:periodNumber>` + `<dcscom:periodType>Main</dcscom:periodType>` |
|
||||||
|
|
||||||
|
Объектная форма с доп. полями:
|
||||||
|
```json
|
||||||
|
"role": {
|
||||||
|
"account": true,
|
||||||
|
"accountTypeExpression": "Счёт.ВидСчёта",
|
||||||
|
"balanceGroup": "/Остатки"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Ограничения
|
||||||
|
|
||||||
|
| 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]"
|
||||||
|
```
|
||||||
|
|
||||||
|
Примеры:
|
||||||
|
|
||||||
|
```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"]
|
||||||
|
```
|
||||||
|
|
||||||
|
### Объектная форма
|
||||||
|
|
||||||
|
```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` — скрыть из полей |
|
||||||
|
| `useRestriction` | `true` — скрыть от пользователя |
|
||||||
|
| `use` | `"Always"`, `"Auto"` |
|
||||||
|
|
||||||
|
### Значения параметров по типу
|
||||||
|
|
||||||
|
| Тип | 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" }
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 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": {
|
||||||
|
"selection": [...],
|
||||||
|
"filter": [...],
|
||||||
|
"order": [...],
|
||||||
|
"conditionalAppearance": [...],
|
||||||
|
"outputParameters": {...},
|
||||||
|
"dataParameters": [...],
|
||||||
|
"structure": [...]
|
||||||
|
}
|
||||||
|
}]
|
||||||
|
```
|
||||||
|
|
||||||
|
### selection
|
||||||
|
|
||||||
|
```json
|
||||||
|
"selection": [
|
||||||
|
"Наименование",
|
||||||
|
{ "field": "Количество", "title": "Кол-во" },
|
||||||
|
"Auto"
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
- Строка → `SelectedItemField`
|
||||||
|
- `"Auto"` → `SelectedItemAuto` (только на уровне группировок; на верхнем уровне settings игнорируется)
|
||||||
|
- Объект с `field`/`title` → `SelectedItemField` с `lwsTitle`
|
||||||
|
|
||||||
|
### 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`
|
||||||
|
- `@inaccessible` → `viewMode=Inaccessible`
|
||||||
|
- Типы значений автоопределяются: `true`/`false` → boolean, `2024-01-01T00:00:00` → dateTime, числа → decimal, прочее → string
|
||||||
|
|
||||||
|
#### Объектная форма
|
||||||
|
|
||||||
|
```json
|
||||||
|
"filter": [
|
||||||
|
{ "field": "Организация", "op": "=", "use": false, "userSettingID": "auto" },
|
||||||
|
{ "field": "Дата", "op": ">=", "value": "0001-01-01T00:00:00", "valueType": "xs:dateTime" },
|
||||||
|
{ "group": "Or", "items": [
|
||||||
|
{ "field": "Статус", "op": "=", "value": true, "valueType": "xs:boolean" },
|
||||||
|
{ "field": "Пометка", "op": "filled" }
|
||||||
|
]}
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
| Поле | Описание |
|
||||||
|
|------|----------|
|
||||||
|
| `field` | Имя поля |
|
||||||
|
| `op` | Оператор (см. таблицу) |
|
||||||
|
| `value` | Правая часть (опц.) |
|
||||||
|
| `valueType` | xsi:type для значения (опц.) |
|
||||||
|
| `use` | Включён (`true` по умолчанию) |
|
||||||
|
| `presentation` | Текст подсказки |
|
||||||
|
| `viewMode` | `"Normal"`, `"QuickAccess"`, `"Inaccessible"` |
|
||||||
|
| `userSettingID` | `"auto"` → генерировать GUID |
|
||||||
|
| `userSettingPresentation` | Отображаемое имя настройки (LocalStringType) |
|
||||||
|
|
||||||
|
Операторы:
|
||||||
|
|
||||||
|
| 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`.
|
||||||
|
|
||||||
|
### order
|
||||||
|
|
||||||
|
```json
|
||||||
|
"order": ["Количество desc", "Наименование", "Auto"]
|
||||||
|
```
|
||||||
|
|
||||||
|
- `"Field"` → `OrderItemField`, `orderType=Asc`
|
||||||
|
- `"Field desc"` → `OrderItemField`, `orderType=Desc`
|
||||||
|
- `"Field asc"` → `OrderItemField`, `orderType=Asc`
|
||||||
|
- `"Auto"` → `OrderItemAuto` (только на уровне группировок; на верхнем уровне settings игнорируется)
|
||||||
|
|
||||||
|
### 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
|
||||||
|
|
||||||
|
#### 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) |
|
||||||
|
| `children` | Вложенные элементы структуры |
|
||||||
|
|
||||||
|
Пустой `groupBy` (или `[]`) = детальные записи (без `groupItems` в XML).
|
||||||
|
|
||||||
|
#### Таблица (table)
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"type": "table",
|
||||||
|
"name": "Таблица",
|
||||||
|
"rows": [
|
||||||
|
{ "groupBy": ["Номенклатура"], "selection": ["Auto"], "order": ["Auto"] }
|
||||||
|
],
|
||||||
|
"columns": [
|
||||||
|
{ "groupBy": ["Период"], "selection": ["Auto"], "order": ["Auto"] }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Диаграмма (chart)
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"type": "chart",
|
||||||
|
"points": { "groupBy": ["Организация"], "order": ["Auto"] },
|
||||||
|
"series": { "groupBy": ["Месяц"], "order": ["Auto"] },
|
||||||
|
"selection": ["Сумма"]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 10. Макеты и привязки (templates, groupTemplates)
|
||||||
|
|
||||||
|
Редко используются. Поддерживаются в объектной форме, близкой к XML.
|
||||||
|
|
||||||
|
### templates
|
||||||
|
|
||||||
|
```json
|
||||||
|
"templates": [
|
||||||
|
{
|
||||||
|
"name": "Макет1",
|
||||||
|
"template": "<raw XML dcsat:AreaTemplate>",
|
||||||
|
"parameters": [
|
||||||
|
{ "name": "ТипЦены", "expression": "Представление(ТипЦен)" }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
### groupTemplates
|
||||||
|
|
||||||
|
```json
|
||||||
|
"groupTemplates": [
|
||||||
|
{ "groupField": "ТипЦен", "templateType": "Header", "template": "Макет1" }
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 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 строки).
|
||||||
@@ -0,0 +1,177 @@
|
|||||||
|
# Схема компоновки данных (СКД)
|
||||||
|
|
||||||
|
Навыки группы `/skd-*` позволяют анализировать, создавать, редактировать и проверять схемы компоновки данных 1С — XML-файлы DataCompositionSchema (Template.xml).
|
||||||
|
|
||||||
|
## Навыки
|
||||||
|
|
||||||
|
| Навык | Параметры | Описание |
|
||||||
|
|-------|-----------|----------|
|
||||||
|
| `/skd-info` | `<TemplatePath> [-Mode] [-Name]` | Анализ структуры СКД: наборы, поля, параметры, ресурсы, варианты (10 режимов) |
|
||||||
|
| `/skd-compile` | `<JsonPath> <OutputPath>` | Генерация Template.xml из JSON DSL: наборы, поля, итоги, параметры, варианты |
|
||||||
|
| `/skd-edit` | `<TemplatePath> -Operation <op> -Value "<value>"` | Точечное редактирование: 25 атомарных операций (add/set/modify/clear/remove) |
|
||||||
|
| `/skd-validate` | `<TemplatePath> [-MaxErrors 20]` | Валидация структурной корректности: ~30 проверок |
|
||||||
|
|
||||||
|
## Рабочий цикл
|
||||||
|
|
||||||
|
```
|
||||||
|
Описание отчёта (текст) → JSON DSL → /skd-compile → Template.xml → /skd-validate
|
||||||
|
↕ /skd-edit → /skd-info
|
||||||
|
```
|
||||||
|
|
||||||
|
1. Claude формирует JSON-определение СКД (shorthand-поля, параметры, итоги, варианты)
|
||||||
|
2. `/skd-compile` генерирует Template.xml с корректными namespace, типами, группировками
|
||||||
|
3. `/skd-edit` вносит точечные изменения: добавление полей, фильтров, наборов данных, вариантов, условного оформления и т.д.
|
||||||
|
4. `/skd-validate` проверяет корректность XML
|
||||||
|
5. `/skd-info` выводит компактную сводку для визуальной проверки
|
||||||
|
|
||||||
|
## JSON DSL — компактный формат
|
||||||
|
|
||||||
|
СКД описываются в JSON с двумя уровнями детализации для каждой секции:
|
||||||
|
|
||||||
|
### Минимальный пример
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"dataSets": [{
|
||||||
|
"query": "ВЫБРАТЬ Номенклатура.Наименование ИЗ Справочник.Номенклатура КАК Номенклатура",
|
||||||
|
"fields": ["Наименование"]
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Умолчания: dataSource создаётся автоматически (`ИсточникДанных1/Local`), набор получает имя `НаборДанных1`, вариант настроек "Основной" с деталями.
|
||||||
|
|
||||||
|
### Поля — shorthand
|
||||||
|
|
||||||
|
```json
|
||||||
|
"fields": [
|
||||||
|
"Наименование",
|
||||||
|
"Количество: decimal(15,2)",
|
||||||
|
"Организация: CatalogRef.Организации @dimension",
|
||||||
|
"Служебное: string #noFilter #noOrder"
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
Формат: `Имя[: Тип] [@роль...] [#ограничение...]`. Роли: `@dimension`, `@account`, `@balance`, `@period`. Ограничения: `#noField`, `#noFilter`, `#noGroup`, `#noOrder`.
|
||||||
|
|
||||||
|
### Итоги — shorthand
|
||||||
|
|
||||||
|
```json
|
||||||
|
"totalFields": ["Количество: Сумма", "Стоимость: Сумма(Кол * Цена)"]
|
||||||
|
```
|
||||||
|
|
||||||
|
Формат: `Поле: Функция` или `Поле: Функция(выражение)`. Объектная форма поддерживает привязку к группировкам: `{ "dataPath": "X", "expression": "Сумма(X)", "group": ["Группа1", "ОбщийИтог"] }`.
|
||||||
|
|
||||||
|
### Параметры — shorthand + @autoDates
|
||||||
|
|
||||||
|
```json
|
||||||
|
"parameters": [
|
||||||
|
"Период: StandardPeriod = LastMonth @autoDates",
|
||||||
|
"Организация: CatalogRef.Организации"
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
`@autoDates` автоматически генерирует параметры `ДатаНачала`/`ДатаОкончания` (заменяет 5 строк на 1).
|
||||||
|
|
||||||
|
### Вычисляемые поля — shorthand
|
||||||
|
|
||||||
|
```json
|
||||||
|
"calculatedFields": ["Итого = Количество * Цена"]
|
||||||
|
```
|
||||||
|
|
||||||
|
### Варианты настроек — shorthand
|
||||||
|
|
||||||
|
```json
|
||||||
|
"settingsVariants": [{
|
||||||
|
"name": "Основной",
|
||||||
|
"settings": {
|
||||||
|
"selection": ["Номенклатура", "Количество", "Сумма"],
|
||||||
|
"filter": ["Организация = _ @off @user"],
|
||||||
|
"order": ["Сумма desc"],
|
||||||
|
"dataParameters": ["Период = LastMonth @user"],
|
||||||
|
"outputParameters": { "Заголовок": "Мой отчёт" },
|
||||||
|
"structure": "Организация > details"
|
||||||
|
}
|
||||||
|
}]
|
||||||
|
```
|
||||||
|
|
||||||
|
- **filter shorthand**: `"Поле оператор значение @флаги"` — флаги `@off`, `@user`, `@quickAccess`, `@normal`, `@inaccessible`
|
||||||
|
- **dataParameters shorthand**: `"Имя = значение @флаги"`
|
||||||
|
- **structure shorthand**: `"Поле1 > Поле2 > details"` — `>` разделяет уровни группировки
|
||||||
|
- **conditionalAppearance**: условное оформление с автоопределением типов значений (Color, Boolean, LocalStringType)
|
||||||
|
|
||||||
|
### Объектная форма
|
||||||
|
|
||||||
|
Все секции поддерживают полную объектную форму для сложных случаев (title, appearance, role с выражениями, userSettingID, userSettingPresentation, conditionalAppearance, группы фильтров And/Or/Not и т.д.). Подробности — в [спецификации SKD DSL](skd-dsl-spec.md).
|
||||||
|
|
||||||
|
## Сценарии использования
|
||||||
|
|
||||||
|
### Анализ существующей СКД
|
||||||
|
|
||||||
|
```
|
||||||
|
> Проанализируй схему компоновки отчёта Reports/АнализНДФЛ/Templates/ОсновнаяСхемаКомпоновкиДанных
|
||||||
|
```
|
||||||
|
|
||||||
|
Claude вызовет `/skd-info` (overview → trace → query → variant) и опишет:
|
||||||
|
- наборы данных и их поля
|
||||||
|
- параметры и значения по умолчанию
|
||||||
|
- ресурсы и формулы агрегации
|
||||||
|
- структуру группировок в вариантах настроек
|
||||||
|
|
||||||
|
### Создание СКД по описанию
|
||||||
|
|
||||||
|
```
|
||||||
|
> Создай СКД для отчёта по продажам: группировка по организациям,
|
||||||
|
> поля Номенклатура, Количество, Сумма. Период — параметр.
|
||||||
|
```
|
||||||
|
|
||||||
|
Claude сформирует JSON:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"dataSets": [{
|
||||||
|
"name": "Продажи",
|
||||||
|
"query": "ВЫБРАТЬ ...",
|
||||||
|
"fields": [
|
||||||
|
"Организация: CatalogRef.Организации @dimension",
|
||||||
|
"Номенклатура: CatalogRef.Номенклатура @dimension",
|
||||||
|
"Количество: decimal(15,3)",
|
||||||
|
"Сумма: decimal(15,2)"
|
||||||
|
]
|
||||||
|
}],
|
||||||
|
"totalFields": ["Количество: Сумма", "Сумма: Сумма"],
|
||||||
|
"parameters": ["Период: StandardPeriod = LastMonth @autoDates"],
|
||||||
|
"settingsVariants": [{
|
||||||
|
"name": "Основной",
|
||||||
|
"settings": {
|
||||||
|
"selection": ["Номенклатура", "Количество", "Сумма"],
|
||||||
|
"dataParameters": ["Период = LastMonth @user"],
|
||||||
|
"structure": "Организация > details"
|
||||||
|
}
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
И вызовет `/skd-compile` → `/skd-validate` → `/skd-info`.
|
||||||
|
|
||||||
|
### Проверка существующей СКД
|
||||||
|
|
||||||
|
```
|
||||||
|
> Проверь корректность СКД Reports/МойОтчёт/Templates/ОсновнаяСхемаКомпоновкиДанных/Ext/Template.xml
|
||||||
|
```
|
||||||
|
|
||||||
|
Claude вызовет `/skd-validate` и покажет результат: ошибки (битые ссылки, дубликаты, невалидные типы) и предупреждения.
|
||||||
|
|
||||||
|
## Структура файлов СКД
|
||||||
|
|
||||||
|
```
|
||||||
|
<Объект>/Templates/
|
||||||
|
├── ИмяМакета.xml # Метаданные (UUID, TemplateType=DataCompositionSchema)
|
||||||
|
└── ИмяМакета/
|
||||||
|
└── Ext/
|
||||||
|
└── Template.xml # Тело схемы (DataCompositionSchema)
|
||||||
|
```
|
||||||
|
|
||||||
|
## Спецификации
|
||||||
|
|
||||||
|
- [1c-dcs-spec.md](1c-dcs-spec.md) — XML-формат DataCompositionSchema, namespace, элементы, типы
|
||||||
|
- [skd-dsl-spec.md](skd-dsl-spec.md) — JSON DSL для описания СКД (формат входных данных `/skd-compile`)
|
||||||
Reference in New Issue
Block a user