From 83b289de3286643eedf32063b13a2347af565c08 Mon Sep 17 00:00:00 2001 From: Nick Shirokov Date: Fri, 10 Apr 2026 21:22:40 +0300 Subject: [PATCH] feat(skd): canonical @autoDates pattern + new params operations + use preservation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix-pack from skills-improvements-v4 feedback addressing 6 issues found during real-world ФСД report development. skd-compile (v1.10 → v1.11): - @autoDates: emit canonical БСП pattern for ДатаНачала/ДатаОкончания — with title, useRestriction=true, value 0001-01-01T00:00:00, expression. Removed availableAsField=false so БСП creates two separate Start/End fields in the quick settings panel (was rendering as a single picker). - StandardPeriod value: always emit v8:startDate/v8:endDate to match how 1C Designer saves the schema (avoids spurious diff on first re-save). - parameter shorthand: support [Title] syntax mirroring add-field. skd-edit (v1.9 → v1.10): - modify-filter / modify-dataParameter: preserve when @off/@on not explicitly set (was silently stripping false). Tristate parser: None=don't touch, False=@off, True=@on. - modify-parameter: support [Title] for setting/replacing . - rename-parameter: new operation "OldName => NewName" — atomically renames parameter, updates &Name references in expressions of other parameters (full identifier match only), and dcscor:parameter entries in dataParameters of all variants. Query text is not touched. - reorder-parameters: new operation "Name1, Name2, ..." — partial list, named params go first in given order, rest preserve original order. - StandardPeriod value: same v8:startDate/v8:endDate fix as compile. Tests: 4 new test cases (rename-parameter, reorder-parameters, modify-parameter-title, modify-dataParameter-preserves-use). 48/48 passing on both PowerShell and Python runtimes. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --- .claude/skills/skd-compile/SKILL.md | 8 +- .../skd-compile/scripts/skd-compile.ps1 | 42 +- .../skills/skd-compile/scripts/skd-compile.py | 33 +- .claude/skills/skd-edit/SKILL.md | 40 +- .claude/skills/skd-edit/scripts/skd-edit.ps1 | 246 +- .claude/skills/skd-edit/scripts/skd-edit.py | 191 +- .../snapshots/full-example/Template.xml | 22 +- .../snapshots/horizontal-merge/Template.xml | 4570 ++++++++--------- .../snapshots/with-filters/Template.xml | 22 +- .../snapshots/with-parameters/Template.xml | 20 +- .../modify-dataParameter-preserves-use.json | 30 + .../skd-edit/modify-parameter-title.json | 22 + .../cases/skd-edit/rename-parameter.json | 33 + .../cases/skd-edit/reorder-parameters.json | 28 + .../snapshots/add-parameter/Template.xml | 20 +- .../Template.xml | 67 + .../modify-parameter-combined/Template.xml | 170 +- .../modify-parameter-title/Template.xml | 64 + .../snapshots/rename-parameter/Template.xml | 117 + .../snapshots/reorder-parameters/Template.xml | 92 + .../overview-with-params/Template.xml | 22 +- .../snapshots/valid-full/Template.xml | 22 +- .../snapshots/valid-with-params/Template.xml | 20 +- 23 files changed, 3469 insertions(+), 2432 deletions(-) create mode 100644 tests/skills/cases/skd-edit/modify-dataParameter-preserves-use.json create mode 100644 tests/skills/cases/skd-edit/modify-parameter-title.json create mode 100644 tests/skills/cases/skd-edit/rename-parameter.json create mode 100644 tests/skills/cases/skd-edit/reorder-parameters.json create mode 100644 tests/skills/cases/skd-edit/snapshots/modify-dataParameter-preserves-use/Template.xml create mode 100644 tests/skills/cases/skd-edit/snapshots/modify-parameter-title/Template.xml create mode 100644 tests/skills/cases/skd-edit/snapshots/rename-parameter/Template.xml create mode 100644 tests/skills/cases/skd-edit/snapshots/reorder-parameters/Template.xml diff --git a/.claude/skills/skd-compile/SKILL.md b/.claude/skills/skd-compile/SKILL.md index 2804cb62..e6f281c4 100644 --- a/.claude/skills/skd-compile/SKILL.md +++ b/.claude/skills/skd-compile/SKILL.md @@ -95,16 +95,18 @@ powershell.exe -NoProfile -File .claude/skills/skd-compile/scripts/skd-compile.p ```json "parameters": [ - "Период: StandardPeriod = LastMonth @autoDates" + "Период [Отчетный период]: StandardPeriod = LastMonth @autoDates" ] ``` +Shorthand: `"Имя [Заголовок]: тип = значение @флаги"`. `[Заголовок]` опциональный — добавляет `<title>` (LocalStringType). + Флаги shorthand: -- `@autoDates` — автоматически генерирует параметры `ДатаНачала` и `ДатаОкончания` с выражениями `&Период.ДатаНачала` / `&Период.ДатаОкончания` и `availableAsField=false` +- `@autoDates` — генерирует пару скрытых параметров `ДатаНачала`/`ДатаОкончания` с выражениями `&Имя.ДатаНачала`/`&Имя.ДатаОкончания`. Используется для StandardPeriod в БСП-отчётах: БСП превращает эту пару в два отдельных поля «Начало/Конец» в панели быстрых настроек. - `@valueList` — `<valueListAllowed>true</valueListAllowed>` — разрешает передавать список значений - `@hidden` — скрытый параметр: `availableAsField=false` + исключается из `"dataParameters": "auto"` -Объектная форма: `hidden: true`, `valueListAllowed: true`, `availableAsField: false`, `denyIncompleteValues: true`, `use: "Always"`. +Объектная форма: `title`, `hidden: true`, `valueListAllowed: true`, `availableAsField: false`, `denyIncompleteValues: true`, `use: "Always"`. Список допустимых значений (availableValues): diff --git a/.claude/skills/skd-compile/scripts/skd-compile.ps1 b/.claude/skills/skd-compile/scripts/skd-compile.ps1 index a0b8cdb2..ef671c3c 100644 --- a/.claude/skills/skd-compile/scripts/skd-compile.ps1 +++ b/.claude/skills/skd-compile/scripts/skd-compile.ps1 @@ -1,4 +1,4 @@ -# skd-compile v1.10 — Compile 1C DCS from JSON +# skd-compile v1.11 — Compile 1C DCS from JSON # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills param( [string]$DefinitionFile, @@ -322,7 +322,7 @@ function Parse-TotalShorthand { function Parse-ParamShorthand { param([string]$s) - $result = @{ name = ""; type = ""; value = $null; autoDates = $false } + $result = @{ name = ""; type = ""; value = $null; autoDates = $false; title = $null } # Extract @autoDates flag if ($s -match '@autoDates') { @@ -342,6 +342,12 @@ function Parse-ParamShorthand { $s = $s -replace '\s*@hidden', '' } + # Extract optional [Title] (mirrors Parse-FieldShorthand) + if ($s -match '\[([^\]]*)\]') { + $result.title = $Matches[1].Trim() + $s = ($s -replace '\s*\[[^\]]*\]\s*', ' ').Trim() + } + # Split "Name: Type = Value" if ($s -match '^([^:]+):\s*(\S+)(\s*=\s*(.+))?$') { $result.name = $Matches[1].Trim() @@ -863,8 +869,13 @@ function Emit-SingleParam { X "`t<parameter>" X "`t`t<name>$(Esc-Xml $parsed.name)</name>" - # Title - $title = if ($p -isnot [string] -and $p.title) { "$($p.title)" } else { "" } + # Title (from parsed first, then from object form) + $title = "" + if ($parsed.title) { + $title = "$($parsed.title)" + } elseif ($p -isnot [string] -and $p.title) { + $title = "$($p.title)" + } if ($title) { Emit-MLText -tag "title" -text $title -indent "`t`t" } @@ -966,17 +977,21 @@ function Emit-Parameters { # Track parameter for auto dataParameters $script:allParams += @{ name = $parsed.name; hidden = [bool]$parsed.hidden; type = "$($parsed.type)"; value = $parsed.value } - # @autoDates: auto-generate ДатаНачала and ДатаОкончания + # @autoDates: auto-generate ДатаНачала and ДатаОкончания (canonical БСП pattern) if ($parsed.autoDates) { $paramName = $parsed.name $beginParsed = @{ - name = "ДатаНачала"; type = "date"; value = $null - expression = "&$paramName.ДатаНачала"; availableAsField = $false + name = "ДатаНачала"; title = "Начало периода" + type = "date"; value = "0001-01-01T00:00:00" + useRestriction = $true + expression = "&$paramName.ДатаНачала" } Emit-SingleParam -p $null -parsed $beginParsed $endParsed = @{ - name = "ДатаОкончания"; type = "date"; value = $null - expression = "&$paramName.ДатаОкончания"; availableAsField = $false + name = "ДатаОкончания"; title = "Конец периода" + type = "date"; value = "0001-01-01T00:00:00" + useRestriction = $true + expression = "&$paramName.ДатаОкончания" } Emit-SingleParam -p $null -parsed $endParsed } @@ -991,9 +1006,12 @@ function Emit-ParamValue { $valStr = "$val" if ($type -eq "StandardPeriod") { - # val is a period variant string like "LastMonth" + # val is a period variant string like "LastMonth" or "Custom". + # Always emit startDate/endDate to match how 1C Designer saves the schema. X "$indent<value xsi:type=`"v8:StandardPeriod`">" X "$indent`t<v8:variant xsi:type=`"v8:StandardPeriodVariant`">$(Esc-Xml $valStr)</v8:variant>" + X "$indent`t<v8:startDate>0001-01-01T00:00:00</v8:startDate>" + X "$indent`t<v8:endDate>0001-01-01T00:00:00</v8:endDate>" X "$indent</value>" } elseif ($type -match '^date') { X "$indent<value xsi:type=`"xs:dateTime`">$(Esc-Xml $valStr)</value>" @@ -1755,11 +1773,15 @@ function Emit-DataParameters { # StandardPeriod (object form from JSON) X "$indent`t`t<dcscor:value xsi:type=`"v8:StandardPeriod`">" X "$indent`t`t`t<v8:variant xsi:type=`"v8:StandardPeriodVariant`">$(Esc-Xml "$($dp.value.variant)")</v8:variant>" + X "$indent`t`t`t<v8:startDate>0001-01-01T00:00:00</v8:startDate>" + X "$indent`t`t`t<v8:endDate>0001-01-01T00:00:00</v8:endDate>" X "$indent`t`t</dcscor:value>" } elseif ($dp.value -is [hashtable] -and $dp.value.variant) { # StandardPeriod (hashtable from shorthand parser) X "$indent`t`t<dcscor:value xsi:type=`"v8:StandardPeriod`">" X "$indent`t`t`t<v8:variant xsi:type=`"v8:StandardPeriodVariant`">$(Esc-Xml "$($dp.value.variant)")</v8:variant>" + X "$indent`t`t`t<v8:startDate>0001-01-01T00:00:00</v8:startDate>" + X "$indent`t`t`t<v8:endDate>0001-01-01T00:00:00</v8:endDate>" X "$indent`t`t</dcscor:value>" } elseif ($dp.value -is [bool]) { $bv = "$($dp.value)".ToLower() diff --git a/.claude/skills/skd-compile/scripts/skd-compile.py b/.claude/skills/skd-compile/scripts/skd-compile.py index 4f216e05..a0fa8d49 100644 --- a/.claude/skills/skd-compile/scripts/skd-compile.py +++ b/.claude/skills/skd-compile/scripts/skd-compile.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# skd-compile v1.10 — Compile 1C DCS from JSON +# skd-compile v1.11 — Compile 1C DCS from JSON # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse import json @@ -238,7 +238,7 @@ def parse_total_shorthand(s): # --- Parameter shorthand parser --- def parse_param_shorthand(s): - result = {'name': '', 'type': '', 'value': None, 'autoDates': False} + result = {'name': '', 'type': '', 'value': None, 'autoDates': False, 'title': None} # Extract @autoDates flag if '@autoDates' in s: @@ -255,6 +255,12 @@ def parse_param_shorthand(s): result['hidden'] = True s = re.sub(r'\s*@hidden', '', s) + # Extract optional [Title] (mirrors parse_field_shorthand) + m = re.search(r'\[([^\]]*)\]', s) + if m: + result['title'] = m.group(1).strip() + s = re.sub(r'\s*\[[^\]]*\]\s*', ' ', s).strip() + # Split "Name: Type = Value" m = re.match(r'^([^:]+):\s*(\S+)(\s*=\s*(.+))?$', s) if m: @@ -708,8 +714,11 @@ def emit_param_value(lines, type_str, val, indent): val_str = str(val) if type_str == 'StandardPeriod': + # Always emit startDate/endDate to match how 1C Designer saves the schema. lines.append(f'{indent}<value xsi:type="v8:StandardPeriod">') lines.append(f'{indent}\t<v8:variant xsi:type="v8:StandardPeriodVariant">{esc_xml(val_str)}</v8:variant>') + lines.append(f'{indent}\t<v8:startDate>0001-01-01T00:00:00</v8:startDate>') + lines.append(f'{indent}\t<v8:endDate>0001-01-01T00:00:00</v8:endDate>') lines.append(f'{indent}</value>') elif type_str and re.match(r'^date', type_str): lines.append(f'{indent}<value xsi:type="xs:dateTime">{esc_xml(val_str)}</value>') @@ -735,9 +744,11 @@ def emit_single_param(lines, p, parsed): lines.append('\t<parameter>') lines.append(f'\t\t<name>{esc_xml(parsed["name"])}</name>') - # Title + # Title (from parsed first, then from object form) title = '' - if p is not None and not isinstance(p, str) and p.get('title'): + if parsed.get('title'): + title = str(parsed['title']) + elif p is not None and not isinstance(p, str) and p.get('title'): title = str(p['title']) if title: emit_mltext(lines, '\t\t', 'title', title) @@ -842,21 +853,23 @@ def emit_parameters(lines, defn): 'value': parsed.get('value'), }) - # @autoDates: auto-generate ДатаНачала and ДатаОкончания + # @autoDates: auto-generate ДатаНачала and ДатаОкончания (canonical БСП pattern) if parsed.get('autoDates'): param_name = parsed['name'] begin_parsed = { 'name': '\u0414\u0430\u0442\u0430\u041d\u0430\u0447\u0430\u043b\u0430', - 'type': 'date', 'value': None, + 'title': '\u041d\u0430\u0447\u0430\u043b\u043e \u043f\u0435\u0440\u0438\u043e\u0434\u0430', + 'type': 'date', 'value': '0001-01-01T00:00:00', + 'useRestriction': True, 'expression': f'&{param_name}.\u0414\u0430\u0442\u0430\u041d\u0430\u0447\u0430\u043b\u0430', - 'availableAsField': False, } emit_single_param(lines, None, begin_parsed) end_parsed = { 'name': '\u0414\u0430\u0442\u0430\u041e\u043a\u043e\u043d\u0447\u0430\u043d\u0438\u044f', - 'type': 'date', 'value': None, + 'title': '\u041a\u043e\u043d\u0435\u0446 \u043f\u0435\u0440\u0438\u043e\u0434\u0430', + 'type': 'date', 'value': '0001-01-01T00:00:00', + 'useRestriction': True, 'expression': f'&{param_name}.\u0414\u0430\u0442\u0430\u041e\u043a\u043e\u043d\u0447\u0430\u043d\u0438\u044f', - 'availableAsField': False, } emit_single_param(lines, None, end_parsed) @@ -1487,6 +1500,8 @@ def emit_data_parameters(lines, items, indent): # StandardPeriod lines.append(f'{indent}\t\t<dcscor:value xsi:type="v8:StandardPeriod">') lines.append(f'{indent}\t\t\t<v8:variant xsi:type="v8:StandardPeriodVariant">{esc_xml(str(val["variant"]))}</v8:variant>') + lines.append(f'{indent}\t\t\t<v8:startDate>0001-01-01T00:00:00</v8:startDate>') + lines.append(f'{indent}\t\t\t<v8:endDate>0001-01-01T00:00:00</v8:endDate>') lines.append(f'{indent}\t\t</dcscor:value>') elif isinstance(val, bool): bv = str(val).lower() diff --git a/.claude/skills/skd-edit/SKILL.md b/.claude/skills/skd-edit/SKILL.md index 1b69b351..1c212ea1 100644 --- a/.claude/skills/skd-edit/SKILL.md +++ b/.claude/skills/skd-edit/SKILL.md @@ -76,11 +76,13 @@ Shorthand: `"Имя [Заголовок]: тип = Выражение #noFilter ### add-parameter — добавить параметр ``` -"Период: StandardPeriod = LastMonth @autoDates" +"Период [Отчетный период]: StandardPeriod = LastMonth @autoDates" "Организация: CatalogRef.Организации" ``` -`@autoDates` генерирует `ДатаНачала` и `ДатаОкончания` автоматически. +Shorthand: `"Имя [Заголовок]: тип = значение @флаги"`. `[Заголовок]` опциональный — добавляет `<title>`. + +`@autoDates` генерирует пару скрытых параметров `ДатаНачала`/`ДатаОкончания` для StandardPeriod-параметра — для БСП-отчётов, чтобы получить пару полей «Начало/Конец» в панели быстрых настроек. ### modify-parameter — изменить существующий параметр @@ -88,15 +90,34 @@ Shorthand: `"Имя [Заголовок]: тип = Выражение #noFilter ``` "ПорядокОкругления use=Always" -"ПорядокОкругления denyIncompleteValues=true" +"ПорядокОкругления [Округление сумм] denyIncompleteValues=true" +"ПериодОтчета [Отчетный период]" # только title "ПорядокОкругления availableValue=Перечисление.Округления.Окр1 presentation=руб." ``` +`[Заголовок]` опциональный — устанавливает или заменяет `<title>`. Можно вызывать без других kv-пар, чтобы только обновить title. + `availableValue=` добавляет один элемент списка допустимых значений (можно несколько через `;;`). Тип значения определяется автоматически (DesignTimeValue для ссылок). +### rename-parameter — переименовать параметр + +Shorthand: `"OldName => NewName"`. Атомарно обновляет имя параметра, ссылки `&Имя` в выражениях других параметров (только полные совпадения, `&ПериодX` не задевается), и записи в `dataParameters` всех вариантов. Текст запроса не трогает — переименование строго в области параметров. + +``` +"Период => ПериодОтчета" +``` + +### reorder-parameters — переставить параметры в указанном порядке + +Shorthand: `"Имя1, Имя2, Имя3"`. Частичный список — указанные параметры идут первыми в заданном порядке, остальные сохраняют исходный порядок и идут в конце. Параметры из списка, которых нет в схеме — warning, пропуск. + +``` +"ПериодОтчета, НачалоПериода, КонецПериода" +``` + ### add-filter — добавить фильтр в вариант -Shorthand: `"Поле оператор значение @флаги"`. Флаги: `@off`, `@user`, `@quickAccess`, `@normal`, `@inaccessible`. +Shorthand: `"Поле оператор значение @флаги"`. Флаги: `@off` (use=false), `@user` (userSettingID=auto), `@quickAccess`, `@normal`, `@inaccessible`. ``` "Номенклатура = _ @off @user" @@ -248,11 +269,18 @@ Shorthand: `"Поле1 > Поле2 > details"`. `details`/`детали` — д ### modify-filter — изменить существующий фильтр -Тот же shorthand что и `add-filter`. Находит по полю, обновляет оператор/значение/флаги. +Тот же shorthand что и `add-filter`. Находит по полю, обновляет оператор/значение/флаги. См. правило для `<use>` ниже. ### modify-dataParameter — изменить параметр данных -Тот же shorthand что и `add-dataParameter`. Находит по имени, обновляет значение/флаги. +Тот же shorthand что и `add-dataParameter`. Находит по имени, обновляет значение/флаги. См. правило для `<use>` ниже. + +#### Правило `<use>` для modify-filter / modify-dataParameter + +В отличие от `add-*`, в `modify-*` поле `<use>` обновляется **только если флаг задан явно**: +- `@off` — установить `<use>false</use>` +- `@on` — убрать существующий `<use>false</use>` (включить параметр) +- ни `@off`, ни `@on` не задано — `<use>` не трогается, существующее значение сохраняется (важно: это значит, что отключённый параметр останется отключённым после модификации других свойств) ### remove-* и clear-* diff --git a/.claude/skills/skd-edit/scripts/skd-edit.ps1 b/.claude/skills/skd-edit/scripts/skd-edit.ps1 index 95df06f9..7a8cc25d 100644 --- a/.claude/skills/skd-edit/scripts/skd-edit.ps1 +++ b/.claude/skills/skd-edit/scripts/skd-edit.ps1 @@ -1,4 +1,4 @@ -# skd-edit v1.9 — Atomic 1C DCS editor +# skd-edit v1.10 — Atomic 1C DCS editor # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills param( [Parameter(Mandatory)] @@ -11,6 +11,7 @@ param( "add-dataSet","add-variant","add-conditionalAppearance","add-drilldown", "set-query","patch-query","set-outputParameter","set-structure", "modify-field","modify-filter","modify-dataParameter","modify-parameter", + "rename-parameter","reorder-parameters", "clear-selection","clear-order","clear-filter", "remove-field","remove-total","remove-calculated-field","remove-parameter","remove-filter")] [string]$Operation, @@ -285,13 +286,19 @@ function Parse-CalcShorthand { function Parse-ParamShorthand { param([string]$s) - $result = @{ name = ""; type = ""; value = $null; autoDates = $false } + $result = @{ name = ""; type = ""; value = $null; autoDates = $false; title = $null } if ($s -match '@autoDates') { $result.autoDates = $true $s = $s -replace '\s*@autoDates', '' } + # Extract optional [Title] (mirrors Parse-FieldShorthand) + if ($s -match '\[([^\]]*)\]') { + $result.title = $Matches[1].Trim() + $s = ($s -replace '\s*\[[^\]]*\]\s*', ' ').Trim() + } + if ($s -match '^([^:]+):\s*(\S+)(\s*=\s*(.+))?$') { $result.name = $Matches[1].Trim() $result.type = Resolve-TypeStr ($Matches[2].Trim()) @@ -308,7 +315,9 @@ function Parse-ParamShorthand { function Parse-FilterShorthand { param([string]$s) - $result = @{ field = ""; op = "Equal"; value = $null; use = $true; userSettingID = $null; viewMode = $null } + # use is tristate: $null = not specified (modify-* won't touch), + # $false = @off (explicit), $true = @on (explicit). add-* writes <use>false</use> only when $false. + $result = @{ field = ""; op = "Equal"; value = $null; use = $null; userSettingID = $null; viewMode = $null } if ($s -match '@user') { $result.userSettingID = "auto" @@ -318,6 +327,10 @@ function Parse-FilterShorthand { $result.use = $false $s = $s -replace '\s*@off', '' } + if ($s -match '@on\b') { + $result.use = $true + $s = $s -replace '\s*@on\b', '' + } if ($s -match '@quickAccess') { $result.viewMode = "QuickAccess" $s = $s -replace '\s*@quickAccess', '' @@ -383,7 +396,9 @@ function Parse-FilterShorthand { function Parse-DataParamShorthand { param([string]$s) - $result = @{ parameter = ""; value = $null; use = $true; userSettingID = $null; viewMode = $null } + # use is tristate: $null = not specified (modify-* won't touch), + # $false = @off (explicit), $true = @on (explicit). add-* writes <use>false</use> only when $false. + $result = @{ parameter = ""; value = $null; use = $null; userSettingID = $null; viewMode = $null } if ($s -match '@user') { $result.userSettingID = "auto" @@ -393,6 +408,10 @@ function Parse-DataParamShorthand { $result.use = $false $s = $s -replace '\s*@off', '' } + if ($s -match '@on\b') { + $result.use = $true + $s = $s -replace '\s*@on\b', '' + } if ($s -match '@quickAccess') { $result.viewMode = "QuickAccess" $s = $s -replace '\s*@quickAccess', '' @@ -784,6 +803,10 @@ function Build-ParamFragment { $lines += "$i<parameter>" $lines += "$i`t<name>$(Esc-Xml $parsed.name)</name>" + if ($parsed.title) { + $lines += (Build-MLTextXml -tag "title" -text $parsed.title -indent "$i`t") + } + if ($parsed.type) { $lines += "$i`t<valueType>" $lines += (Build-ValueTypeXml -typeStr $parsed.type -indent "$i`t`t") @@ -795,6 +818,8 @@ function Build-ParamFragment { if ($parsed.type -eq "StandardPeriod") { $lines += "$i`t<value xsi:type=`"v8:StandardPeriod`">" $lines += "$i`t`t<v8:variant xsi:type=`"v8:StandardPeriodVariant`">$(Esc-Xml $valStr)</v8:variant>" + $lines += "$i`t`t<v8:startDate>0001-01-01T00:00:00</v8:startDate>" + $lines += "$i`t`t<v8:endDate>0001-01-01T00:00:00</v8:endDate>" $lines += "$i`t</value>" } elseif ($parsed.type -match '^date') { $lines += "$i`t<value xsi:type=`"xs:dateTime`">$(Esc-Xml $valStr)</value>" @@ -813,25 +838,30 @@ function Build-ParamFragment { if ($parsed.autoDates) { $paramName = $parsed.name + # Canonical БСП pattern: title + valueType + value + useRestriction + expression $bLines = @() $bLines += "$i<parameter>" $bLines += "$i`t<name>ДатаНачала</name>" + $bLines += (Build-MLTextXml -tag "title" -text "Начало периода" -indent "$i`t") $bLines += "$i`t<valueType>" $bLines += (Build-ValueTypeXml -typeStr "date" -indent "$i`t`t") $bLines += "$i`t</valueType>" + $bLines += "$i`t<value xsi:type=`"xs:dateTime`">0001-01-01T00:00:00</value>" + $bLines += "$i`t<useRestriction>true</useRestriction>" $bLines += "$i`t<expression>$(Esc-Xml "&$paramName.ДатаНачала")</expression>" - $bLines += "$i`t<availableAsField>false</availableAsField>" $bLines += "$i</parameter>" $fragments += ($bLines -join "`r`n") $eLines = @() $eLines += "$i<parameter>" $eLines += "$i`t<name>ДатаОкончания</name>" + $eLines += (Build-MLTextXml -tag "title" -text "Конец периода" -indent "$i`t") $eLines += "$i`t<valueType>" $eLines += (Build-ValueTypeXml -typeStr "date" -indent "$i`t`t") $eLines += "$i`t</valueType>" + $eLines += "$i`t<value xsi:type=`"xs:dateTime`">0001-01-01T00:00:00</value>" + $eLines += "$i`t<useRestriction>true</useRestriction>" $eLines += "$i`t<expression>$(Esc-Xml "&$paramName.ДатаОкончания")</expression>" - $eLines += "$i`t<availableAsField>false</availableAsField>" $eLines += "$i</parameter>" $fragments += ($eLines -join "`r`n") } @@ -929,6 +959,8 @@ function Build-DataParamFragment { if ($parsed.value -is [hashtable] -and $parsed.value.variant) { $lines += "$i`t<dcscor:value xsi:type=`"v8:StandardPeriod`">" $lines += "$i`t`t<v8:variant xsi:type=`"v8:StandardPeriodVariant`">$(Esc-Xml $parsed.value.variant)</v8:variant>" + $lines += "$i`t`t<v8:startDate>0001-01-01T00:00:00</v8:startDate>" + $lines += "$i`t`t<v8:endDate>0001-01-01T00:00:00</v8:endDate>" $lines += "$i`t</dcscor:value>" } elseif ("$($parsed.value)" -match '^\d{4}-\d{2}-\d{2}T') { $lines += "$i`t<dcscor:value xsi:type=`"xs:dateTime`">$(Esc-Xml "$($parsed.value)")</dcscor:value>" @@ -1711,7 +1743,14 @@ switch ($Operation) { "modify-parameter" { foreach ($val in $values) { - # Parse: "ParamName key=value key=value" + # Parse: "ParamName [Title] key=value key=value" + # Extract optional [Title] first (mirrors Parse-FieldShorthand) + $titleVal = $null + if ($val -match '\[([^\]]*)\]') { + $titleVal = $Matches[1].Trim() + $val = ($val -replace '\s*\[[^\]]*\]\s*', ' ').Trim() + } + $parts = $val -split '\s+', 2 $paramName = $parts[0].Trim() $rest = if ($parts.Count -gt 1) { $parts[1].Trim() } else { "" } @@ -1725,6 +1764,32 @@ switch ($Operation) { $childIndent = Get-ChildIndent $paramEl + # Set/replace title (must come right after <name>, before <valueType>) + if ($null -ne $titleVal) { + $existingTitle = $null + foreach ($ch in $paramEl.ChildNodes) { + if ($ch.NodeType -eq 'Element' -and $ch.LocalName -eq 'title') { + $existingTitle = $ch; break + } + } + if ($existingTitle) { + Remove-NodeWithWhitespace $existingTitle + } + # Insert before first of (valueType, value, useRestriction, expression, availableAsField, ...) + $titleRef = $null + foreach ($ch in $paramEl.ChildNodes) { + if ($ch.NodeType -eq 'Element' -and $ch.LocalName -ne 'name') { + $titleRef = $ch; break + } + } + $titleFrag = Build-MLTextXml -tag "title" -text $titleVal -indent $childIndent + $titleNodes = Import-Fragment $xmlDoc $titleFrag + foreach ($node in $titleNodes) { + Insert-BeforeElement $paramEl $node $titleRef $childIndent + } + Write-Host "[OK] Parameter `"$paramName`": title set to `"$titleVal`"" + } + # Separate availableValue=... from simple kv pairs $simpleRest = $rest $avPart = $null @@ -1809,6 +1874,160 @@ switch ($Operation) { } } + "rename-parameter" { + foreach ($val in $values) { + # Shorthand: "OldName => NewName" + if ($val -notmatch '^\s*(.+?)\s*=>\s*(.+?)\s*$') { + Write-Host "[WARN] rename-parameter expects 'OldName => NewName', got: $val" + continue + } + $oldName = $Matches[1].Trim() + $newName = $Matches[2].Trim() + + if ($oldName -eq $newName) { + Write-Host "[WARN] rename-parameter: old and new names are equal — skipped" + continue + } + + # 1. Rename <parameter><name>OldName</name> + $root = $xmlDoc.DocumentElement + $paramEl = Find-ElementByChildValue $root "parameter" "name" $oldName $schNs + if (-not $paramEl) { + Write-Host "[WARN] Parameter `"$oldName`" not found — skipped" + continue + } + foreach ($ch in $paramEl.ChildNodes) { + if ($ch.NodeType -eq 'Element' -and $ch.LocalName -eq 'name' -and $ch.NamespaceURI -eq $schNs) { + $ch.InnerText = $newName + break + } + } + + # 2. Update <expression> in other <parameter> elements. + # Regex matches "&OldName" only when followed by a non-identifier char (or end), + # so "&Период" matches "&Период.ДатаНачала" but NOT "&ПериодОтчета". + $escOld = [regex]::Escape($oldName) + $exprRegex = "&$escOld(?=[^\w\u0400-\u04FF]|$)" + $exprUpdated = 0 + foreach ($ch in $root.ChildNodes) { + if ($ch.NodeType -ne 'Element' -or $ch.LocalName -ne 'parameter' -or $ch.NamespaceURI -ne $schNs) { continue } + foreach ($gc in $ch.ChildNodes) { + if ($gc.NodeType -eq 'Element' -and $gc.LocalName -eq 'expression' -and $gc.NamespaceURI -eq $schNs) { + $oldExpr = $gc.InnerText + $newExpr = [regex]::Replace($oldExpr, $exprRegex, "&$newName") + if ($newExpr -ne $oldExpr) { + $gc.InnerText = $newExpr + $exprUpdated++ + } + } + } + } + + # 3. Update <dcscor:parameter>OldName</dcscor:parameter> in dataParameters of all variants. + # Note: <settingsVariant> is in schNs, but <settings> and <dataParameters> are in setNs. + # IMPORTANT: don't use $variant — it collides with script parameter [string]$Variant + # (PowerShell vars are case-insensitive, and the [string] type would coerce XmlNode to ""). + $dpUpdated = 0 + foreach ($variantNode in $root.ChildNodes) { + if ($variantNode.NodeType -ne 'Element' -or $variantNode.LocalName -ne 'settingsVariant' -or $variantNode.NamespaceURI -ne $schNs) { continue } + $settings = Find-FirstElement $variantNode @("settings") $setNs + if (-not $settings) { continue } + $dpEl = Find-FirstElement $settings @("dataParameters") $setNs + if (-not $dpEl) { continue } + foreach ($item in $dpEl.ChildNodes) { + if ($item.NodeType -ne 'Element' -or $item.LocalName -ne 'item') { continue } + foreach ($gc in $item.ChildNodes) { + if ($gc.NodeType -eq 'Element' -and $gc.LocalName -eq 'parameter' -and $gc.NamespaceURI -eq $corNs) { + if ($gc.InnerText.Trim() -eq $oldName) { + $gc.InnerText = $newName + $dpUpdated++ + } + } + } + } + } + + Write-Host "[OK] Parameter renamed: `"$oldName`" => `"$newName`" (expressions updated: $exprUpdated, dataParameters updated: $dpUpdated)" + } + } + + "reorder-parameters" { + foreach ($val in $values) { + # Shorthand: "Name1, Name2, Name3" — partial list, listed names go first in order, rest preserve original order + $order = @($val -split ',' | ForEach-Object { $_.Trim() } | Where-Object { $_ }) + if ($order.Count -eq 0) { + Write-Host "[WARN] reorder-parameters: empty list — skipped" + continue + } + + $root = $xmlDoc.DocumentElement + + # Collect all <parameter> in document order with their child indent + $allParams = @() + foreach ($ch in $root.ChildNodes) { + if ($ch.NodeType -eq 'Element' -and $ch.LocalName -eq 'parameter' -and $ch.NamespaceURI -eq $schNs) { + $allParams += $ch + } + } + if ($allParams.Count -eq 0) { + Write-Host "[WARN] reorder-parameters: no parameters in schema" + continue + } + + $childIndent = Get-ChildIndent $root + + # Build name -> element map + $byName = @{} + foreach ($pe in $allParams) { + foreach ($gc in $pe.ChildNodes) { + if ($gc.NodeType -eq 'Element' -and $gc.LocalName -eq 'name' -and $gc.NamespaceURI -eq $schNs) { + $byName[$gc.InnerText.Trim()] = $pe + break + } + } + } + + # Build new order + $newOrder = @() + $used = @{} + foreach ($name in $order) { + if ($byName.ContainsKey($name)) { + $newOrder += $byName[$name] + $used[$name] = $true + } else { + Write-Host "[WARN] reorder-parameters: parameter `"$name`" not found — skipped" + } + } + foreach ($pe in $allParams) { + $peName = $null + foreach ($gc in $pe.ChildNodes) { + if ($gc.NodeType -eq 'Element' -and $gc.LocalName -eq 'name' -and $gc.NamespaceURI -eq $schNs) { + $peName = $gc.InnerText.Trim(); break + } + } + if ($peName -and -not $used.ContainsKey($peName)) { + $newOrder += $pe + } + } + + # Find anchor: element right after the last parameter in original order + $lastParam = $allParams[-1] + $anchor = $lastParam.NextSibling + + # Remove all parameters with surrounding whitespace + foreach ($pe in $allParams) { + Remove-NodeWithWhitespace $pe + } + + # Re-insert in new order before anchor + foreach ($pe in $newOrder) { + Insert-BeforeElement $root $pe $anchor $childIndent + } + + Write-Host "[OK] Parameters reordered ($($allParams.Count) total, $($order.Count) explicit)" + } + } + "add-filter" { $settings = Resolve-VariantSettings $varName = Get-VariantName @@ -2276,11 +2495,11 @@ switch ($Operation) { Set-OrCreateChildElementWithAttr $filterItem "right" $setNs "$($parsed.value)" $vt $itemIndent } - # Update use + # Update use (only when explicitly set via @off / @on) if ($parsed.use -eq $false) { Set-OrCreateChildElement $filterItem "use" $setNs "false" $itemIndent - } else { - # If explicitly not @off, remove use=false if exists + } elseif ($parsed.use -eq $true) { + # @on: remove existing use=false if any $useEl = $null foreach ($ch in $filterItem.ChildNodes) { if ($ch.NodeType -eq 'Element' -and $ch.LocalName -eq 'use' -and $ch.NamespaceURI -eq $setNs) { @@ -2346,6 +2565,8 @@ switch ($Operation) { if ($parsed.value -is [hashtable] -and $parsed.value.variant) { $valLines += "$itemIndent<dcscor:value xsi:type=`"v8:StandardPeriod`">" $valLines += "$itemIndent`t<v8:variant xsi:type=`"v8:StandardPeriodVariant`">$(Esc-Xml $parsed.value.variant)</v8:variant>" + $valLines += "$itemIndent`t<v8:startDate>0001-01-01T00:00:00</v8:startDate>" + $valLines += "$itemIndent`t<v8:endDate>0001-01-01T00:00:00</v8:endDate>" $valLines += "$itemIndent</dcscor:value>" } elseif ("$($parsed.value)" -match '^\d{4}-\d{2}-\d{2}T') { $valLines += "$itemIndent<dcscor:value xsi:type=`"xs:dateTime`">$(Esc-Xml "$($parsed.value)")</dcscor:value>" @@ -2361,10 +2582,11 @@ switch ($Operation) { } } - # Update use + # Update use (only when explicitly set via @off / @on) if ($parsed.use -eq $false) { Set-OrCreateChildElement $dpItem "use" $corNs "false" $itemIndent - } else { + } elseif ($parsed.use -eq $true) { + # @on: remove existing use=false if any $useEl = $null foreach ($ch in $dpItem.ChildNodes) { if ($ch.NodeType -eq 'Element' -and $ch.LocalName -eq 'use' -and $ch.NamespaceURI -eq $corNs) { diff --git a/.claude/skills/skd-edit/scripts/skd-edit.py b/.claude/skills/skd-edit/scripts/skd-edit.py index 2b79718a..b63ed1d6 100644 --- a/.claude/skills/skd-edit/scripts/skd-edit.py +++ b/.claude/skills/skd-edit/scripts/skd-edit.py @@ -1,4 +1,4 @@ -# skd-edit v1.9 — Atomic 1C DCS editor (Python port) +# skd-edit v1.10 — Atomic 1C DCS editor (Python port) # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse import os @@ -19,6 +19,7 @@ VALID_OPS = [ "add-dataSet", "add-variant", "add-conditionalAppearance", "add-drilldown", "set-query", "patch-query", "set-outputParameter", "set-structure", "modify-field", "modify-filter", "modify-dataParameter", "modify-parameter", + "rename-parameter", "reorder-parameters", "clear-selection", "clear-order", "clear-filter", "remove-field", "remove-total", "remove-calculated-field", "remove-parameter", "remove-filter", ] @@ -282,12 +283,18 @@ def parse_calc_shorthand(s): def parse_param_shorthand(s): - result = {"name": "", "type": "", "value": None, "autoDates": False} + result = {"name": "", "type": "", "value": None, "autoDates": False, "title": None} if re.search(r'@autoDates', s): result["autoDates"] = True s = re.sub(r'\s*@autoDates', '', s) + # Extract optional [Title] (mirrors parse_field_shorthand) + m = re.search(r'\[([^\]]*)\]', s) + if m: + result["title"] = m.group(1).strip() + s = re.sub(r'\s*\[[^\]]*\]\s*', ' ', s).strip() + m = re.match(r'^([^:]+):\s*(\S+)(\s*=\s*(.+))?$', s) if m: result["name"] = m.group(1).strip() @@ -301,7 +308,9 @@ def parse_param_shorthand(s): def parse_filter_shorthand(s): - result = {"field": "", "op": "Equal", "value": None, "use": True, "userSettingID": None, "viewMode": None} + # use is tristate: None = not specified (modify-* won't touch), + # False = @off (explicit), True = @on (explicit). add-* writes <use>false</use> only when False. + result = {"field": "", "op": "Equal", "value": None, "use": None, "userSettingID": None, "viewMode": None} if re.search(r'@user', s): result["userSettingID"] = "auto" @@ -309,6 +318,9 @@ def parse_filter_shorthand(s): if re.search(r'@off', s): result["use"] = False s = re.sub(r'\s*@off', '', s) + if re.search(r'@on\b', s): + result["use"] = True + s = re.sub(r'\s*@on\b', '', s) if re.search(r'@quickAccess', s): result["viewMode"] = "QuickAccess" s = re.sub(r'\s*@quickAccess', '', s) @@ -366,7 +378,9 @@ def parse_filter_shorthand(s): def parse_data_param_shorthand(s): - result = {"parameter": "", "value": None, "use": True, "userSettingID": None, "viewMode": None} + # use is tristate: None = not specified (modify-* won't touch), + # False = @off (explicit), True = @on (explicit). add-* writes <use>false</use> only when False. + result = {"parameter": "", "value": None, "use": None, "userSettingID": None, "viewMode": None} if re.search(r'@user', s): result["userSettingID"] = "auto" @@ -374,6 +388,9 @@ def parse_data_param_shorthand(s): if re.search(r'@off', s): result["use"] = False s = re.sub(r'\s*@off', '', s) + if re.search(r'@on\b', s): + result["use"] = True + s = re.sub(r'\s*@on\b', '', s) if re.search(r'@quickAccess', s): result["viewMode"] = "QuickAccess" s = re.sub(r'\s*@quickAccess', '', s) @@ -696,6 +713,10 @@ def build_param_fragment(parsed, indent): fragments = [] lines = [f"{i}<parameter>", f"{i}\t<name>{esc_xml(parsed['name'])}</name>"] + + if parsed.get("title"): + lines.append(build_mltext_xml("title", parsed["title"], f"{i}\t")) + if parsed.get("type"): lines.append(f"{i}\t<valueType>") lines.append(build_value_type_xml(parsed["type"], f"{i}\t\t")) @@ -706,6 +727,8 @@ def build_param_fragment(parsed, indent): if parsed.get("type") == "StandardPeriod": lines.append(f'{i}\t<value xsi:type="v8:StandardPeriod">') lines.append(f'{i}\t\t<v8:variant xsi:type="v8:StandardPeriodVariant">{esc_xml(val_str)}</v8:variant>') + lines.append(f"{i}\t\t<v8:startDate>0001-01-01T00:00:00</v8:startDate>") + lines.append(f"{i}\t\t<v8:endDate>0001-01-01T00:00:00</v8:endDate>") lines.append(f"{i}\t</value>") elif parsed.get("type", "").startswith("date"): lines.append(f'{i}\t<value xsi:type="xs:dateTime">{esc_xml(val_str)}</value>') @@ -721,14 +744,17 @@ def build_param_fragment(parsed, indent): if parsed.get("autoDates"): param_name = parsed["name"] + # Canonical БСП pattern: title + valueType + value + useRestriction + expression b_lines = [ f"{i}<parameter>", f"{i}\t<name>\u0414\u0430\u0442\u0430\u041d\u0430\u0447\u0430\u043b\u0430</name>", + build_mltext_xml("title", "\u041d\u0430\u0447\u0430\u043b\u043e \u043f\u0435\u0440\u0438\u043e\u0434\u0430", f"{i}\t"), f"{i}\t<valueType>", build_value_type_xml("date", f"{i}\t\t"), f"{i}\t</valueType>", + f'{i}\t<value xsi:type="xs:dateTime">0001-01-01T00:00:00</value>', + f"{i}\t<useRestriction>true</useRestriction>", f"{i}\t<expression>{esc_xml('&' + param_name + '.\u0414\u0430\u0442\u0430\u041d\u0430\u0447\u0430\u043b\u0430')}</expression>", - f"{i}\t<availableAsField>false</availableAsField>", f"{i}</parameter>", ] fragments.append("\r\n".join(b_lines)) @@ -736,11 +762,13 @@ def build_param_fragment(parsed, indent): e_lines = [ f"{i}<parameter>", f"{i}\t<name>\u0414\u0430\u0442\u0430\u041e\u043a\u043e\u043d\u0447\u0430\u043d\u0438\u044f</name>", + build_mltext_xml("title", "\u041a\u043e\u043d\u0435\u0446 \u043f\u0435\u0440\u0438\u043e\u0434\u0430", f"{i}\t"), f"{i}\t<valueType>", build_value_type_xml("date", f"{i}\t\t"), f"{i}\t</valueType>", + f'{i}\t<value xsi:type="xs:dateTime">0001-01-01T00:00:00</value>', + f"{i}\t<useRestriction>true</useRestriction>", f"{i}\t<expression>{esc_xml('&' + param_name + '.\u0414\u0430\u0442\u0430\u041e\u043a\u043e\u043d\u0447\u0430\u043d\u0438\u044f')}</expression>", - f"{i}\t<availableAsField>false</availableAsField>", f"{i}</parameter>", ] fragments.append("\r\n".join(e_lines)) @@ -824,6 +852,8 @@ def build_data_param_fragment(parsed, indent): if isinstance(val, dict) and val.get("variant"): lines.append(f'{i}\t<dcscor:value xsi:type="v8:StandardPeriod">') lines.append(f'{i}\t\t<v8:variant xsi:type="v8:StandardPeriodVariant">{esc_xml(val["variant"])}</v8:variant>') + lines.append(f"{i}\t\t<v8:startDate>0001-01-01T00:00:00</v8:startDate>") + lines.append(f"{i}\t\t<v8:endDate>0001-01-01T00:00:00</v8:endDate>") lines.append(f"{i}\t</dcscor:value>") elif re.match(r'^\d{4}-\d{2}-\d{2}T', str(val)): lines.append(f'{i}\t<dcscor:value xsi:type="xs:dateTime">{esc_xml(str(val))}</dcscor:value>') @@ -1480,6 +1510,13 @@ elif operation == "add-parameter": elif operation == "modify-parameter": for val in values: + # Extract optional [Title] first (mirrors parse_field_shorthand) + title_val = None + m_title = re.search(r'\[([^\]]*)\]', val) + if m_title: + title_val = m_title.group(1).strip() + val = re.sub(r'\s*\[[^\]]*\]\s*', ' ', val).strip() + parts = val.split(None, 1) param_name = parts[0].strip() rest = parts[1].strip() if len(parts) > 1 else "" @@ -1491,6 +1528,18 @@ elif operation == "modify-parameter": child_indent = get_child_indent(param_el) + # Set/replace title (must come right after <name>, before <valueType>) + if title_val is not None: + existing_title = next((ch for ch in param_el if isinstance(ch.tag, str) and local_name(ch) == "title"), None) + if existing_title is not None: + remove_node_with_whitespace(existing_title) + # Insert before the first child after <name> + title_ref = next((ch for ch in param_el if isinstance(ch.tag, str) and local_name(ch) != "name"), None) + title_frag = build_mltext_xml("title", title_val, child_indent) + for node in import_fragment(xml_doc, title_frag): + insert_before_element(param_el, node, title_ref, child_indent) + print(f'[OK] Parameter "{param_name}": title set to "{title_val}"') + # Separate availableValue=... from simple kv pairs simple_rest = rest av_part = None @@ -1553,6 +1602,126 @@ elif operation == "modify-parameter": insert_before_element(param_el, node, ref_node, child_indent) print(f'[OK] Parameter "{param_name}": availableValue added') +elif operation == "rename-parameter": + root = xml_doc + for val in values: + m_rn = re.match(r'^\s*(.+?)\s*=>\s*(.+?)\s*$', val) + if not m_rn: + print(f'[WARN] rename-parameter expects "OldName => NewName", got: {val}') + continue + old_name = m_rn.group(1).strip() + new_name = m_rn.group(2).strip() + + if old_name == new_name: + print('[WARN] rename-parameter: old and new names are equal -- skipped') + continue + + # 1. Rename <parameter><name>OldName</name> + param_el = find_element_by_child_value(root, "parameter", "name", old_name, SCH_NS) + if param_el is None: + print(f'[WARN] Parameter "{old_name}" not found -- skipped') + continue + for ch in param_el: + if isinstance(ch.tag, str) and local_name(ch) == "name" and etree.QName(ch.tag).namespace == SCH_NS: + ch.text = new_name + break + + # 2. Update <expression> in other <parameter> elements. + # Regex matches "&OldName" only when followed by a non-identifier char (or end), + # so "&Период" matches "&Период.ДатаНачала" but NOT "&ПериодОтчета". + esc_old = re.escape(old_name) + expr_regex = re.compile(rf'&{esc_old}(?=[^\w\u0400-\u04FF]|$)') + expr_updated = 0 + for ch in root: + if not (isinstance(ch.tag, str) and local_name(ch) == "parameter" and etree.QName(ch.tag).namespace == SCH_NS): + continue + for gc in ch: + if isinstance(gc.tag, str) and local_name(gc) == "expression" and etree.QName(gc.tag).namespace == SCH_NS: + old_expr = gc.text or "" + new_expr = expr_regex.sub(f'&{new_name}', old_expr) + if new_expr != old_expr: + gc.text = new_expr + expr_updated += 1 + + # 3. Update <dcscor:parameter>OldName</dcscor:parameter> in dataParameters of all variants. + dp_updated = 0 + for variant_node in root: + if not (isinstance(variant_node.tag, str) and local_name(variant_node) == "settingsVariant" and etree.QName(variant_node.tag).namespace == SCH_NS): + continue + settings_node = find_first_element(variant_node, ["settings"], SET_NS) + if settings_node is None: + continue + dp_el = find_first_element(settings_node, ["dataParameters"], SET_NS) + if dp_el is None: + continue + for item in dp_el: + if not (isinstance(item.tag, str) and local_name(item) == "item"): + continue + for gc in item: + if isinstance(gc.tag, str) and local_name(gc) == "parameter" and etree.QName(gc.tag).namespace == COR_NS: + if (gc.text or "").strip() == old_name: + gc.text = new_name + dp_updated += 1 + + print(f'[OK] Parameter renamed: "{old_name}" => "{new_name}" (expressions updated: {expr_updated}, dataParameters updated: {dp_updated})') + +elif operation == "reorder-parameters": + root = xml_doc + for val in values: + order = [s.strip() for s in val.split(",") if s.strip()] + if not order: + print('[WARN] reorder-parameters: empty list -- skipped') + continue + + all_params = [] + for ch in root: + if isinstance(ch.tag, str) and local_name(ch) == "parameter" and etree.QName(ch.tag).namespace == SCH_NS: + all_params.append(ch) + if not all_params: + print('[WARN] reorder-parameters: no parameters in schema') + continue + + child_indent = get_child_indent(root) + + by_name = {} + for pe in all_params: + for gc in pe: + if isinstance(gc.tag, str) and local_name(gc) == "name" and etree.QName(gc.tag).namespace == SCH_NS: + by_name[(gc.text or "").strip()] = pe + break + + new_order = [] + used = set() + for name in order: + if name in by_name: + new_order.append(by_name[name]) + used.add(name) + else: + print(f'[WARN] reorder-parameters: parameter "{name}" not found -- skipped') + + for pe in all_params: + pe_name = None + for gc in pe: + if isinstance(gc.tag, str) and local_name(gc) == "name" and etree.QName(gc.tag).namespace == SCH_NS: + pe_name = (gc.text or "").strip() + break + if pe_name and pe_name not in used: + new_order.append(pe) + + # Anchor: element right after the last parameter in original order + last_param = all_params[-1] + anchor = last_param.getnext() + + # Remove all parameters with surrounding whitespace + for pe in all_params: + remove_node_with_whitespace(pe) + + # Re-insert in new order before anchor + for pe in new_order: + insert_before_element(root, pe, anchor, child_indent) + + print(f'[OK] Parameters reordered ({len(all_params)} total, {len(order)} explicit)') + elif operation == "add-filter": settings = resolve_variant_settings() var_name = get_variant_name() @@ -1922,9 +2091,11 @@ elif operation == "modify-filter": vt = parsed.get("valueType", "xs:string") set_or_create_child_element_with_attr(filter_item, "right", SET_NS, str(parsed["value"]), vt, item_indent) + # Update use (only when explicitly set via @off / @on) if parsed.get("use") is False: set_or_create_child_element(filter_item, "use", SET_NS, "false", item_indent) - else: + elif parsed.get("use") is True: + # @on: remove existing use=false if any for ch in filter_item: if isinstance(ch.tag, str) and local_name(ch) == "use" and etree.QName(ch.tag).namespace == SET_NS: if (ch.text or "").strip() == "false": @@ -1971,6 +2142,8 @@ elif operation == "modify-dataParameter": if isinstance(pv, dict) and pv.get("variant"): val_lines.append(f'{item_indent}<dcscor:value xsi:type="v8:StandardPeriod">') val_lines.append(f'{item_indent}\t<v8:variant xsi:type="v8:StandardPeriodVariant">{esc_xml(pv["variant"])}</v8:variant>') + val_lines.append(f"{item_indent}\t<v8:startDate>0001-01-01T00:00:00</v8:startDate>") + val_lines.append(f"{item_indent}\t<v8:endDate>0001-01-01T00:00:00</v8:endDate>") val_lines.append(f"{item_indent}</dcscor:value>") elif re.match(r'^\d{4}-\d{2}-\d{2}T', str(pv)): val_lines.append(f'{item_indent}<dcscor:value xsi:type="xs:dateTime">{esc_xml(str(pv))}</dcscor:value>') @@ -1984,9 +2157,11 @@ elif operation == "modify-dataParameter": for node in val_nodes: insert_before_element(dp_item, node, None, item_indent) + # Update use (only when explicitly set via @off / @on) if parsed.get("use") is False: set_or_create_child_element(dp_item, "use", COR_NS, "false", item_indent) - else: + elif parsed.get("use") is True: + # @on: remove existing use=false if any for ch in dp_item: if isinstance(ch.tag, str) and local_name(ch) == "use" and etree.QName(ch.tag).namespace == COR_NS: if (ch.text or "").strip() == "false": diff --git a/tests/skills/cases/skd-compile/snapshots/full-example/Template.xml b/tests/skills/cases/skd-compile/snapshots/full-example/Template.xml index 72736534..928301c9 100644 --- a/tests/skills/cases/skd-compile/snapshots/full-example/Template.xml +++ b/tests/skills/cases/skd-compile/snapshots/full-example/Template.xml @@ -65,29 +65,45 @@ </valueType> <value xsi:type="v8:StandardPeriod"> <v8:variant xsi:type="v8:StandardPeriodVariant">LastMonth</v8:variant> + <v8:startDate>0001-01-01T00:00:00</v8:startDate> + <v8:endDate>0001-01-01T00:00:00</v8:endDate> </value> </parameter> <parameter> <name>ДатаНачала</name> + <title xsi:type="v8:LocalStringType"> + <v8:item> + <v8:lang>ru</v8:lang> + <v8:content>Начало периода</v8:content> + </v8:item> + xs:dateTime Date + 0001-01-01T00:00:00 + true &Период.ДатаНачала - false ДатаОкончания + + <v8:item> + <v8:lang>ru</v8:lang> + <v8:content>Конец периода</v8:content> + </v8:item> + xs:dateTime Date + 0001-01-01T00:00:00 + true &Период.ДатаОкончания - false Основной @@ -122,6 +138,8 @@ Период LastMonth + 0001-01-01T00:00:00 + 0001-01-01T00:00:00 UUID-002 diff --git a/tests/skills/cases/skd-compile/snapshots/horizontal-merge/Template.xml b/tests/skills/cases/skd-compile/snapshots/horizontal-merge/Template.xml index 31909b56..c891619f 100644 --- a/tests/skills/cases/skd-compile/snapshots/horizontal-merge/Template.xml +++ b/tests/skills/cases/skd-compile/snapshots/horizontal-merge/Template.xml @@ -1,2285 +1,2285 @@ - - - - ИсточникДанных1 - Local - - - Основной - - Счет - Счет - - xs:string - - 0 - Variable - - - - - Остаток - Остаток - - xs:decimal - - 15 - 2 - Any - - - - - Пост1 - Пост1 - - xs:decimal - - 15 - 2 - Any - - - - - Пост2 - Пост2 - - xs:decimal - - 15 - 2 - Any - - - - - Пост3 - Пост3 - - xs:decimal - - 15 - 2 - Any - - - - - Выб1 - Выб1 - - xs:decimal - - 15 - 2 - Any - - - - - Выб2 - Выб2 - - xs:decimal - - 15 - 2 - Any - - - - - Итого - Итого - - xs:decimal - - 15 - 2 - Any - - - - ИсточникДанных1 - ВЫБРАТЬ Т.Счет, Т.Остаток, Т.Пост1, Т.Пост2, Т.Пост3, Т.Выб1, Т.Выб2, Т.Итого ИЗ Регистр КАК Т - - - - - Основной - - - ru - Основной - - - - - - - - - - - - - - - - + + + + ИсточникДанных1 + Local + + + Основной + + Счет + Счет + + xs:string + + 0 + Variable + + + + + Остаток + Остаток + + xs:decimal + + 15 + 2 + Any + + + + + Пост1 + Пост1 + + xs:decimal + + 15 + 2 + Any + + + + + Пост2 + Пост2 + + xs:decimal + + 15 + 2 + Any + + + + + Пост3 + Пост3 + + xs:decimal + + 15 + 2 + Any + + + + + Выб1 + Выб1 + + xs:decimal + + 15 + 2 + Any + + + + + Выб2 + Выб2 + + xs:decimal + + 15 + 2 + Any + + + + + Итого + Итого + + xs:decimal + + 15 + 2 + Any + + + + ИсточникДанных1 + ВЫБРАТЬ Т.Счет, Т.Остаток, Т.Пост1, Т.Пост2, Т.Пост3, Т.Выб1, Т.Выб2, Т.Итого ИЗ Регистр КАК Т + + + + + Основной + + + ru + Основной + + + + + + + + + + + + + + + + diff --git a/tests/skills/cases/skd-compile/snapshots/with-filters/Template.xml b/tests/skills/cases/skd-compile/snapshots/with-filters/Template.xml index ac039ef0..b21ff151 100644 --- a/tests/skills/cases/skd-compile/snapshots/with-filters/Template.xml +++ b/tests/skills/cases/skd-compile/snapshots/with-filters/Template.xml @@ -60,29 +60,45 @@ LastMonth + 0001-01-01T00:00:00 + 0001-01-01T00:00:00 ДатаНачала + + <v8:item> + <v8:lang>ru</v8:lang> + <v8:content>Начало периода</v8:content> + </v8:item> + xs:dateTime Date + 0001-01-01T00:00:00 + true &Период.ДатаНачала - false ДатаОкончания + + <v8:item> + <v8:lang>ru</v8:lang> + <v8:content>Конец периода</v8:content> + </v8:item> + xs:dateTime Date + 0001-01-01T00:00:00 + true &Период.ДатаОкончания - false Основной @@ -129,6 +145,8 @@ Период LastMonth + 0001-01-01T00:00:00 + 0001-01-01T00:00:00 UUID-002 diff --git a/tests/skills/cases/skd-compile/snapshots/with-parameters/Template.xml b/tests/skills/cases/skd-compile/snapshots/with-parameters/Template.xml index 13acb5d5..0b58ff9e 100644 --- a/tests/skills/cases/skd-compile/snapshots/with-parameters/Template.xml +++ b/tests/skills/cases/skd-compile/snapshots/with-parameters/Template.xml @@ -57,29 +57,45 @@ LastMonth + 0001-01-01T00:00:00 + 0001-01-01T00:00:00 ДатаНачала + + <v8:item> + <v8:lang>ru</v8:lang> + <v8:content>Начало периода</v8:content> + </v8:item> + xs:dateTime Date + 0001-01-01T00:00:00 + true &Период.ДатаНачала - false ДатаОкончания + + <v8:item> + <v8:lang>ru</v8:lang> + <v8:content>Конец периода</v8:content> + </v8:item> + xs:dateTime Date + 0001-01-01T00:00:00 + true &Период.ДатаОкончания - false Организация diff --git a/tests/skills/cases/skd-edit/modify-dataParameter-preserves-use.json b/tests/skills/cases/skd-edit/modify-dataParameter-preserves-use.json new file mode 100644 index 00000000..3cb7843c --- /dev/null +++ b/tests/skills/cases/skd-edit/modify-dataParameter-preserves-use.json @@ -0,0 +1,30 @@ +{ + "name": "modify-dataParameter: сохраняет существующий false когда @off не задан", + "preRun": [ + { + "script": "skd-compile/scripts/skd-compile", + "input": { + "dataSets": [{ + "name": "Основной", + "query": "ВЫБРАТЬ Т.Сумма ИЗ Регистр КАК Т", + "fields": ["Сумма: decimal(15,2)"] + }], + "parameters": ["ПериодОтчета: StandardPeriod = LastMonth"], + "settingsVariants": [{ + "name": "Основной", + "settings": { + "selection": ["Auto"], + "dataParameters": ["ПериодОтчета = LastMonth @off"], + "structure": "details" + } + }] + }, + "args": { "-DefinitionFile": "{inputFile}", "-OutputPath": "{workDir}/Template.xml" } + } + ], + "params": { + "templatePath": "Template.xml", + "operation": "modify-dataParameter", + "value": "ПериодОтчета = Custom" + } +} diff --git a/tests/skills/cases/skd-edit/modify-parameter-title.json b/tests/skills/cases/skd-edit/modify-parameter-title.json new file mode 100644 index 00000000..f8c8ea9d --- /dev/null +++ b/tests/skills/cases/skd-edit/modify-parameter-title.json @@ -0,0 +1,22 @@ +{ + "name": "modify-parameter: установка title через [Заголовок]", + "preRun": [ + { + "script": "skd-compile/scripts/skd-compile", + "input": { + "dataSets": [{ + "name": "Основной", + "query": "ВЫБРАТЬ Т.Сумма ИЗ Регистр КАК Т", + "fields": ["Сумма: decimal(15,2)"] + }], + "parameters": ["ПериодОтчета: StandardPeriod = LastMonth"] + }, + "args": { "-DefinitionFile": "{inputFile}", "-OutputPath": "{workDir}/Template.xml" } + } + ], + "params": { + "templatePath": "Template.xml", + "operation": "modify-parameter", + "value": "ПериодОтчета [Отчетный период] use=Always denyIncompleteValues=true" + } +} diff --git a/tests/skills/cases/skd-edit/rename-parameter.json b/tests/skills/cases/skd-edit/rename-parameter.json new file mode 100644 index 00000000..8854afe2 --- /dev/null +++ b/tests/skills/cases/skd-edit/rename-parameter.json @@ -0,0 +1,33 @@ +{ + "name": "rename-parameter: переименование с обновлением expressions и dataParameters", + "preRun": [ + { + "script": "skd-compile/scripts/skd-compile", + "input": { + "dataSets": [{ + "name": "Основной", + "query": "ВЫБРАТЬ Т.Сумма ИЗ Регистр КАК Т", + "fields": ["Сумма: decimal(15,2)"] + }], + "parameters": [ + "Период: StandardPeriod = LastMonth @autoDates", + "Организация: string" + ], + "settingsVariants": [{ + "name": "Основной", + "settings": { + "selection": ["Auto"], + "dataParameters": ["Период = LastMonth @user", "Организация @off"], + "structure": "details" + } + }] + }, + "args": { "-DefinitionFile": "{inputFile}", "-OutputPath": "{workDir}/Template.xml" } + } + ], + "params": { + "templatePath": "Template.xml", + "operation": "rename-parameter", + "value": "Период => ПериодОтчета" + } +} diff --git a/tests/skills/cases/skd-edit/reorder-parameters.json b/tests/skills/cases/skd-edit/reorder-parameters.json new file mode 100644 index 00000000..8dcdd532 --- /dev/null +++ b/tests/skills/cases/skd-edit/reorder-parameters.json @@ -0,0 +1,28 @@ +{ + "name": "reorder-parameters: явный частичный список + остальные сохраняют порядок", + "preRun": [ + { + "script": "skd-compile/scripts/skd-compile", + "input": { + "dataSets": [{ + "name": "Основной", + "query": "ВЫБРАТЬ Т.Сумма ИЗ Регистр КАК Т", + "fields": ["Сумма: decimal(15,2)"] + }], + "parameters": [ + "Организация: string", + "ПрекращаемаяДеятельность: boolean", + "ПериодОтчета: StandardPeriod = LastMonth", + "ПланСчетовМеждународный: string", + "ПорядокОкругленияСумм: string" + ] + }, + "args": { "-DefinitionFile": "{inputFile}", "-OutputPath": "{workDir}/Template.xml" } + } + ], + "params": { + "templatePath": "Template.xml", + "operation": "reorder-parameters", + "value": "ПериодОтчета, ПланСчетовМеждународный, ПорядокОкругленияСумм" + } +} diff --git a/tests/skills/cases/skd-edit/snapshots/add-parameter/Template.xml b/tests/skills/cases/skd-edit/snapshots/add-parameter/Template.xml index 49e00602..c169bb35 100644 --- a/tests/skills/cases/skd-edit/snapshots/add-parameter/Template.xml +++ b/tests/skills/cases/skd-edit/snapshots/add-parameter/Template.xml @@ -20,29 +20,45 @@ LastMonth + 0001-01-01T00:00:00 + 0001-01-01T00:00:00 ДатаНачала + + <v8:item> + <v8:lang>ru</v8:lang> + <v8:content>Начало периода</v8:content> + </v8:item> + xs:dateTime Date + 0001-01-01T00:00:00 + true &Период.ДатаНачала - false ДатаОкончания + + <v8:item> + <v8:lang>ru</v8:lang> + <v8:content>Конец периода</v8:content> + </v8:item> + xs:dateTime Date + 0001-01-01T00:00:00 + true &Период.ДатаОкончания - false Основной diff --git a/tests/skills/cases/skd-edit/snapshots/modify-dataParameter-preserves-use/Template.xml b/tests/skills/cases/skd-edit/snapshots/modify-dataParameter-preserves-use/Template.xml new file mode 100644 index 00000000..823e8e10 --- /dev/null +++ b/tests/skills/cases/skd-edit/snapshots/modify-dataParameter-preserves-use/Template.xml @@ -0,0 +1,67 @@ + + + + ИсточникДанных1 + Local + + + Основной + + Сумма + Сумма + + xs:decimal + + 15 + 2 + Any + + + + ИсточникДанных1 + ВЫБРАТЬ Т.Сумма ИЗ Регистр КАК Т + + + ПериодОтчета + + v8:StandardPeriod + + + LastMonth + 0001-01-01T00:00:00 + 0001-01-01T00:00:00 + + + + Основной + + + ru + Основной + + + + + + + + false + ПериодОтчета + + Custom + 0001-01-01T00:00:00 + 0001-01-01T00:00:00 + + + + + + + + + + + + + + diff --git a/tests/skills/cases/skd-edit/snapshots/modify-parameter-combined/Template.xml b/tests/skills/cases/skd-edit/snapshots/modify-parameter-combined/Template.xml index 2e531531..52bd3990 100644 --- a/tests/skills/cases/skd-edit/snapshots/modify-parameter-combined/Template.xml +++ b/tests/skills/cases/skd-edit/snapshots/modify-parameter-combined/Template.xml @@ -1,85 +1,85 @@ - - - - ИсточникДанных1 - Local - - - Основной - - Сумма - Сумма - - xs:decimal - - 15 - 2 - Any - - - - ИсточникДанных1 - ВЫБРАТЬ Т.Сумма ИЗ Регистр КАК Т - - - ПорядокОкругления - - xs:string - - 0 - Variable - - - Окр1_00 - - Перечисление.Округления.Окр1_00 - - - ru - руб. коп - - - - - Перечисление.Округления.Окр1 - - - ru - руб. - - - - - Перечисление.Округления.Окр1000 - - - ru - тыс. руб - - - - true - Always - - - Основной - - - ru - Основной - - - - - - - - - - - - - - - - + + + + ИсточникДанных1 + Local + + + Основной + + Сумма + Сумма + + xs:decimal + + 15 + 2 + Any + + + + ИсточникДанных1 + ВЫБРАТЬ Т.Сумма ИЗ Регистр КАК Т + + + ПорядокОкругления + + xs:string + + 0 + Variable + + + Окр1_00 + + Перечисление.Округления.Окр1_00 + + + ru + руб. коп + + + + + Перечисление.Округления.Окр1 + + + ru + руб. + + + + + Перечисление.Округления.Окр1000 + + + ru + тыс. руб + + + + true + Always + + + Основной + + + ru + Основной + + + + + + + + + + + + + + + + diff --git a/tests/skills/cases/skd-edit/snapshots/modify-parameter-title/Template.xml b/tests/skills/cases/skd-edit/snapshots/modify-parameter-title/Template.xml new file mode 100644 index 00000000..a6e14541 --- /dev/null +++ b/tests/skills/cases/skd-edit/snapshots/modify-parameter-title/Template.xml @@ -0,0 +1,64 @@ + + + + ИсточникДанных1 + Local + + + Основной + + Сумма + Сумма + + xs:decimal + + 15 + 2 + Any + + + + ИсточникДанных1 + ВЫБРАТЬ Т.Сумма ИЗ Регистр КАК Т + + + ПериодОтчета + + <v8:item> + <v8:lang>ru</v8:lang> + <v8:content>Отчетный период</v8:content> + </v8:item> + + + v8:StandardPeriod + + + LastMonth + 0001-01-01T00:00:00 + 0001-01-01T00:00:00 + + true + Always + + + Основной + + + ru + Основной + + + + + + + + + + + + + + + + diff --git a/tests/skills/cases/skd-edit/snapshots/rename-parameter/Template.xml b/tests/skills/cases/skd-edit/snapshots/rename-parameter/Template.xml new file mode 100644 index 00000000..9714c5ba --- /dev/null +++ b/tests/skills/cases/skd-edit/snapshots/rename-parameter/Template.xml @@ -0,0 +1,117 @@ + + + + ИсточникДанных1 + Local + + + Основной + + Сумма + Сумма + + xs:decimal + + 15 + 2 + Any + + + + ИсточникДанных1 + ВЫБРАТЬ Т.Сумма ИЗ Регистр КАК Т + + + ПериодОтчета + + v8:StandardPeriod + + + LastMonth + 0001-01-01T00:00:00 + 0001-01-01T00:00:00 + + + + ДатаНачала + + <v8:item> + <v8:lang>ru</v8:lang> + <v8:content>Начало периода</v8:content> + </v8:item> + + + xs:dateTime + + Date + + + 0001-01-01T00:00:00 + true + &ПериодОтчета.ДатаНачала + + + ДатаОкончания + + <v8:item> + <v8:lang>ru</v8:lang> + <v8:content>Конец периода</v8:content> + </v8:item> + + + xs:dateTime + + Date + + + 0001-01-01T00:00:00 + true + &ПериодОтчета.ДатаОкончания + + + Организация + + xs:string + + 0 + Variable + + + + + Основной + + + ru + Основной + + + + + + + + ПериодОтчета + + LastMonth + 0001-01-01T00:00:00 + 0001-01-01T00:00:00 + + UUID-001 + + + false + Организация + + + + + + + + + + + + + diff --git a/tests/skills/cases/skd-edit/snapshots/reorder-parameters/Template.xml b/tests/skills/cases/skd-edit/snapshots/reorder-parameters/Template.xml new file mode 100644 index 00000000..76e17c33 --- /dev/null +++ b/tests/skills/cases/skd-edit/snapshots/reorder-parameters/Template.xml @@ -0,0 +1,92 @@ + + + + ИсточникДанных1 + Local + + + Основной + + Сумма + Сумма + + xs:decimal + + 15 + 2 + Any + + + + ИсточникДанных1 + ВЫБРАТЬ Т.Сумма ИЗ Регистр КАК Т + + ПериодОтчета + + v8:StandardPeriod + + + LastMonth + 0001-01-01T00:00:00 + 0001-01-01T00:00:00 + + + + ПланСчетовМеждународный + + xs:string + + 0 + Variable + + + + + ПорядокОкругленияСумм + + xs:string + + 0 + Variable + + + + + Организация + + xs:string + + 0 + Variable + + + + + ПрекращаемаяДеятельность + + xs:boolean + + + + + Основной + + + ru + Основной + + + + + + + + + + + + + + + + diff --git a/tests/skills/cases/skd-info/snapshots/overview-with-params/Template.xml b/tests/skills/cases/skd-info/snapshots/overview-with-params/Template.xml index 14e99316..56bee234 100644 --- a/tests/skills/cases/skd-info/snapshots/overview-with-params/Template.xml +++ b/tests/skills/cases/skd-info/snapshots/overview-with-params/Template.xml @@ -65,29 +65,45 @@ LastMonth + 0001-01-01T00:00:00 + 0001-01-01T00:00:00 ДатаНачала + + <v8:item> + <v8:lang>ru</v8:lang> + <v8:content>Начало периода</v8:content> + </v8:item> + xs:dateTime Date + 0001-01-01T00:00:00 + true &Период.ДатаНачала - false ДатаОкончания + + <v8:item> + <v8:lang>ru</v8:lang> + <v8:content>Конец периода</v8:content> + </v8:item> + xs:dateTime Date + 0001-01-01T00:00:00 + true &Период.ДатаОкончания - false Основной @@ -122,6 +138,8 @@ Период LastMonth + 0001-01-01T00:00:00 + 0001-01-01T00:00:00 UUID-002 diff --git a/tests/skills/cases/skd-validate/snapshots/valid-full/Template.xml b/tests/skills/cases/skd-validate/snapshots/valid-full/Template.xml index 066b8386..39321403 100644 --- a/tests/skills/cases/skd-validate/snapshots/valid-full/Template.xml +++ b/tests/skills/cases/skd-validate/snapshots/valid-full/Template.xml @@ -75,29 +75,45 @@ LastMonth + 0001-01-01T00:00:00 + 0001-01-01T00:00:00 ДатаНачала + + <v8:item> + <v8:lang>ru</v8:lang> + <v8:content>Начало периода</v8:content> + </v8:item> + xs:dateTime Date + 0001-01-01T00:00:00 + true &Период.ДатаНачала - false ДатаОкончания + + <v8:item> + <v8:lang>ru</v8:lang> + <v8:content>Конец периода</v8:content> + </v8:item> + xs:dateTime Date + 0001-01-01T00:00:00 + true &Период.ДатаОкончания - false Основной @@ -135,6 +151,8 @@ Период LastMonth + 0001-01-01T00:00:00 + 0001-01-01T00:00:00 UUID-002 diff --git a/tests/skills/cases/skd-validate/snapshots/valid-with-params/Template.xml b/tests/skills/cases/skd-validate/snapshots/valid-with-params/Template.xml index 6c4ba7f5..849bed83 100644 --- a/tests/skills/cases/skd-validate/snapshots/valid-with-params/Template.xml +++ b/tests/skills/cases/skd-validate/snapshots/valid-with-params/Template.xml @@ -65,29 +65,45 @@ LastMonth + 0001-01-01T00:00:00 + 0001-01-01T00:00:00 ДатаНачала + + <v8:item> + <v8:lang>ru</v8:lang> + <v8:content>Начало периода</v8:content> + </v8:item> + xs:dateTime Date + 0001-01-01T00:00:00 + true &Период.ДатаНачала - false ДатаОкончания + + <v8:item> + <v8:lang>ru</v8:lang> + <v8:content>Конец периода</v8:content> + </v8:item> + xs:dateTime Date + 0001-01-01T00:00:00 + true &Период.ДатаОкончания - false Основной