From b692a81ea5c4711f4a5ab9138927b8e1e739bd2d Mon Sep 17 00:00:00 2001 From: Nick Shirokov Date: Sun, 7 Jun 2026 19:29:47 +0300 Subject: [PATCH] =?UTF-8?q?feat(form-decompile,form-compile):=20schema-?= =?UTF-8?q?=D0=BF=D0=B0=D1=80=D0=B0=D0=BC=D0=B5=D1=82=D1=80=D1=8B=20=D0=B4?= =?UTF-8?q?=D0=B8=D0=BD=D0=B0=D0=BC=D0=B8=D1=87=D0=B5=D1=81=D0=BA=D0=BE?= =?UTF-8?q?=D0=B3=D0=BE=20=D1=81=D0=BF=D0=B8=D1=81=D0=BA=D0=B0=20(=D0=BA?= =?UTF-8?q?=D0=BB=D0=B0=D1=81=D1=82=D0=B5=D1=80=20DynamicList=20Settings>P?= =?UTF-8?q?arameters)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Захват/эмиссия (DataCompositionSchemaParameter) внутри — та же сущность, что параметры СКД, но обёртка + дети dcssch:. Ранее теряли при декомпиляции и не умели эмитить (компилятор обрывал на Field*→MainTable). Корпус acc+erp 8.3.24: 123 формы, 406 параметров. DSL: ключ settings.parameters переиспользует грамматику параметров СКД ОДИН-В-ОДИН (shorthand "Имя [Заголовок]: Тип = Значение @valueList @hidden" + объектная форма; ключи value/type/ availableValues/inputParameters/use/denyIncompleteValues/expression/availableAsField). Новых сущностей не вводим — модель переносит знание skd-параметров напрямую. Контекстные дефолты дин-списка (паттерн «умный дефолт у всегда-эмитируемого тега», для модели невидимы — просто опускает ключ): - useRestriction: эмитим ВСЕГДА, дефолт true (в СКД дефолт false); false → объект useRestriction:false; - title: авто из имени через Title-FromName (camelCase-split с сохранением аббревиатур); явный заголовок — только при отклонении от авто-вывода; - value: пустое всегда xsi:nil, даже при известном типе (в отличие от типизированного пустого в СКД). Канон. порядок детей по корпусу: name, title, valueType, value, useRestriction, expression, availableValue*, valueListAllowed, availableAsField, inputParameters, denyIncompleteValues, use. Декомпилятор PS-only (зеркало в py отложено, как и весь form-decompile); компилятор зеркалён в py. Валидация: round-trip бит-в-бит на ФормаОстатков (субсет) + ПроверкаПользовательскихНастроек (полная грамматика: availableValues/inputParameters/denyIncompleteValues/use). Регресс 35/35 ps+py. Тест-кейс dynamic-list-parameters (+снэпшот). spec обновлён. Версии: form-compile v1.64, form-decompile v0.46. --- .../form-compile/scripts/form-compile.ps1 | 255 +++++++++++- .../form-compile/scripts/form-compile.py | 284 ++++++++++++- .../form-decompile/scripts/form-decompile.ps1 | 114 +++++- docs/form-dsl-spec.md | 27 ++ .../form-compile/dynamic-list-parameters.json | 47 +++ .../Catalogs/Товары.xml | 373 ++++++++++++++++++ .../Catalogs/Товары/Ext/ObjectModule.bsl | 0 .../Catalogs/Товары/Forms/ФормаСписка.xml | 21 + .../Товары/Forms/ФормаСписка/Ext/Form.xml | 208 ++++++++++ .../Forms/ФормаСписка/Ext/Form/Module.bsl | 19 + .../dynamic-list-parameters/Configuration.xml | 252 ++++++++++++ .../Ext/ClientApplicationInterface.xml | 18 + .../Languages/Русский.xml | 16 + 13 files changed, 1631 insertions(+), 3 deletions(-) create mode 100644 tests/skills/cases/form-compile/dynamic-list-parameters.json create mode 100644 tests/skills/cases/form-compile/snapshots/dynamic-list-parameters/Catalogs/Товары.xml create mode 100644 tests/skills/cases/form-compile/snapshots/dynamic-list-parameters/Catalogs/Товары/Ext/ObjectModule.bsl create mode 100644 tests/skills/cases/form-compile/snapshots/dynamic-list-parameters/Catalogs/Товары/Forms/ФормаСписка.xml create mode 100644 tests/skills/cases/form-compile/snapshots/dynamic-list-parameters/Catalogs/Товары/Forms/ФормаСписка/Ext/Form.xml create mode 100644 tests/skills/cases/form-compile/snapshots/dynamic-list-parameters/Catalogs/Товары/Forms/ФормаСписка/Ext/Form/Module.bsl create mode 100644 tests/skills/cases/form-compile/snapshots/dynamic-list-parameters/Configuration.xml create mode 100644 tests/skills/cases/form-compile/snapshots/dynamic-list-parameters/Ext/ClientApplicationInterface.xml create mode 100644 tests/skills/cases/form-compile/snapshots/dynamic-list-parameters/Languages/Русский.xml diff --git a/.claude/skills/form-compile/scripts/form-compile.ps1 b/.claude/skills/form-compile/scripts/form-compile.ps1 index f18570ec..a15b202e 100644 --- a/.claude/skills/form-compile/scripts/form-compile.ps1 +++ b/.claude/skills/form-compile/scripts/form-compile.ps1 @@ -1,4 +1,4 @@ -# form-compile v1.63 — Compile 1C managed form from JSON or object metadata +# form-compile v1.64 — Compile 1C managed form from JSON or object metadata # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills param( [string]$JsonPath, @@ -3684,6 +3684,257 @@ function Emit-AttrColumn { X "$indent" } +# --- Schema-параметры динамического списка (DataCompositionSchemaParameter) --- +# Та же сущность, что параметры СКД (см. skd-compile), но в форме: обёртка +# + дети с префиксом dcssch:. DSL переиспользует грамматику параметров СКД (shorthand + +# объект). Контекстные дефолты дин-списка (паттерн «умный дефолт у всегда-эмитируемого тега»): +# useRestriction — эмитим ВСЕГДА, дефолт TRUE (в СКД дефолт false); +# title — авто из имени (Title-FromName), если ключ не задан. +# Канон. порядок детей (по корпусу acc/erp 8.3.24): name, title, valueType, value, +# useRestriction, expression, availableValue*, valueListAllowed, availableAsField, +# inputParameters, denyIncompleteValues, use. + +# Многоязычный текст в DCS-контексте — с xsi:type="v8:LocalStringType" (form-compile +# Emit-MLText его НЕ ставит, т.к. формовые голые; в dcssch:* — обязателен). +function Emit-DLMLText { + param([string]$tag, $text, [string]$indent) + X "$indent<$tag xsi:type=`"v8:LocalStringType`">" + Emit-MLItems -val $text -indent "$indent`t" + X "$indent</$tag>" +} + +function Has-DLProp { + param($obj, [string]$name) + if ($null -eq $obj) { return $false } + if ($obj -is [System.Collections.IDictionary]) { return $obj.Contains($name) } + if ($obj.PSObject -and $obj.PSObject.Properties[$name]) { return $true } + return $false +} + +function Split-DLValueListCsv { + param([string]$s) + $result = @() + if ($null -eq $s) { return ,$result } + $items = @(); $buf = New-Object System.Text.StringBuilder; $inQuote = $null + for ($i = 0; $i -lt $s.Length; $i++) { + $ch = $s[$i] + if ($inQuote) { [void]$buf.Append($ch); if ($ch -eq $inQuote) { $inQuote = $null } } + elseif ($ch -eq "'" -or $ch -eq '"') { $inQuote = $ch; [void]$buf.Append($ch) } + elseif ($ch -eq ',') { $items += $buf.ToString(); [void]$buf.Clear() } + else { [void]$buf.Append($ch) } + } + if ($buf.Length -gt 0) { $items += $buf.ToString() } + foreach ($raw in $items) { + $t = $raw.Trim() + if ($t.Length -ge 2 -and (($t[0] -eq "'" -and $t[-1] -eq "'") -or ($t[0] -eq '"' -and $t[-1] -eq '"'))) { $t = $t.Substring(1, $t.Length - 2) } + if ($t -ne "") { $result += $t } + } + return ,$result +} + +# Shorthand: "Имя [Заголовок]: Тип = Значение @valueList @hidden" +function Parse-DLParamShorthand { + param([string]$s) + $result = @{ name = ""; type = ""; value = $null; title = $null } + if ($s -match '@valueList') { $result.valueListAllowed = $true; $s = $s -replace '\s*@valueList', '' } + if ($s -match '@hidden') { $result.hidden = $true; $s = $s -replace '\s*@hidden', '' } + 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()) + if ($Matches[4]) { + $rhs = $Matches[4].Trim() + $items = Split-DLValueListCsv $rhs + if ($items.Count -ge 2) { $result.value = $items; $result.valueListAllowed = $true } + elseif ($items.Count -eq 1) { $result.value = $items[0] } + else { $result.value = $rhs } + } + } else { $result.name = $s.Trim() } + return $result +} + +function Test-DLEmptyValue { + param($v) + if ($null -eq $v) { return $true } + $s = "$v".Trim() + if ($s -eq "" -or $s -eq "_" -or $s.ToLowerInvariant() -eq "null") { return $true } + return $false +} + +# Эмиссия <dcssch:value> по типу/значению (xs:* или dcscor:DesignTimeValue для ссылок). +function Emit-DLValue { + param([string]$type, $val, [string]$indent, [bool]$valueListAllowed = $false) + if (Test-DLEmptyValue $val) { + # Дин-список: пустое значение платформа ВСЕГДА пишет как xsi:nil, даже при известном + # типе (в отличие от типизированного пустого в параметрах отчёта СКД). + if ($valueListAllowed) { return } + X "$indent<dcssch:value xsi:nil=`"true`"/>" + return + } + $valStr = if ($val -is [bool]) { if ($val) { 'true' } else { 'false' } } else { "$val" } + if ($type -match '^(date|dateTime|time)') { X "$indent<dcssch:value xsi:type=`"xs:dateTime`">$(Esc-Xml $valStr)</dcssch:value>" } + elseif ($type -eq "boolean") { X "$indent<dcssch:value xsi:type=`"xs:boolean`">$(Esc-Xml $valStr)</dcssch:value>" } + elseif ($type -match '^decimal') { X "$indent<dcssch:value xsi:type=`"xs:decimal`">$(Esc-Xml $valStr)</dcssch:value>" } + elseif ($type -match '^string') { X "$indent<dcssch:value xsi:type=`"xs:string`">$(Esc-Xml $valStr)</dcssch:value>" } + elseif ($type -match '^(CatalogRef|DocumentRef|EnumRef|ChartOfAccountsRef|ChartOfCharacteristicTypesRef|ChartOfCalculationTypesRef|BusinessProcessRef|TaskRef|ExchangePlanRef)\.') { X "$indent<dcssch:value xsi:type=`"dcscor:DesignTimeValue`">$(Esc-Xml $valStr)</dcssch:value>" } + else { + if ($valStr -match '^\d{4}-\d{2}-\d{2}T') { X "$indent<dcssch:value xsi:type=`"xs:dateTime`">$(Esc-Xml $valStr)</dcssch:value>" } + elseif ($valStr -eq "true" -or $valStr -eq "false") { X "$indent<dcssch:value xsi:type=`"xs:boolean`">$(Esc-Xml $valStr)</dcssch:value>" } + elseif ($valStr -match '^(ПланСчетов|Справочник|Перечисление|Документ|ПланВидовХарактеристик|ПланВидовРасчета|БизнесПроцесс|Задача|РегистрСведений|ПланОбмена)\.' -or $valStr -match '^(ChartOfAccounts|Catalog|Enum|Document|ChartOfCharacteristicTypes|ChartOfCalculationTypes|BusinessProcess|Task|InformationRegister|ExchangePlan)\.') { X "$indent<dcssch:value xsi:type=`"dcscor:DesignTimeValue`">$(Esc-Xml $valStr)</dcssch:value>" } + else { X "$indent<dcssch:value xsi:type=`"xs:string`">$(Esc-Xml $valStr)</dcssch:value>" } + } +} + +# <dcssch:valueType> — обёртка + тело через Emit-SingleType (ref-типы → cfg:, как в форме). +function Emit-DLValueType { + param($typeStr, [string]$indent) + if (-not $typeStr) { return } + X "$indent<dcssch:valueType>" + $parts = "$typeStr" -split '\s*[|+]\s*' + foreach ($part in $parts) { Emit-SingleType -typeStr $part.Trim() -indent "$indent`t" } + X "$indent</dcssch:valueType>" +} + +function Emit-DLAvailableValue { + param($av, [string]$type, [string]$indent) + X "$indent<dcssch:availableValue>" + $avVal = if (Has-DLProp $av 'value') { $av.value } else { $null } + Emit-DLValue -type $type -val $avVal -indent "$indent`t" -valueListAllowed $false + $pres = if ($av.presentation) { $av.presentation } elseif ($av.title) { $av.title } else { $null } + if ($pres) { Emit-DLMLText -tag "dcssch:presentation" -text $pres -indent "$indent`t" } + X "$indent</dcssch:availableValue>" +} + +# <dcssch:inputParameters> — ChoiceParameters / ChoiceParameterLinks / простое значение (порт из skd). +function Emit-DLInputParameters { + param($ip, [string]$indent) + if ($null -eq $ip) { return } + $items = @($ip) + if ($items.Count -eq 0) { return } + X "$indent<dcssch:inputParameters>" + foreach ($item in $items) { + X "$indent`t<dcscor:item>" + if ((Has-DLProp $item 'use') -and $null -ne $item.use -and -not $item.use) { X "$indent`t`t<dcscor:use>false</dcscor:use>" } + X "$indent`t`t<dcscor:parameter>$(Esc-Xml "$($item.parameter)")</dcscor:parameter>" + if (Has-DLProp $item 'choiceParameters') { + $cpItems = if ($null -ne $item.choiceParameters) { @($item.choiceParameters) } else { @() } + if ($cpItems.Count -eq 0) { X "$indent`t`t<dcscor:value xsi:type=`"dcscor:ChoiceParameters`"/>" } + else { + X "$indent`t`t<dcscor:value xsi:type=`"dcscor:ChoiceParameters`">" + foreach ($cpItem in $cpItems) { + X "$indent`t`t`t<dcscor:item>" + X "$indent`t`t`t`t<dcscor:choiceParameter>$(Esc-Xml "$($cpItem.name)")</dcscor:choiceParameter>" + foreach ($v in @($cpItem.values)) { + if ($v -is [bool]) { X "$indent`t`t`t`t<dcscor:value xsi:type=`"xs:boolean`">$(if ($v) { 'true' } else { 'false' })</dcscor:value>" } + elseif ($v -is [int] -or $v -is [long] -or $v -is [double] -or $v -is [decimal]) { X "$indent`t`t`t`t<dcscor:value xsi:type=`"xs:decimal`">$v</dcscor:value>" } + else { X "$indent`t`t`t`t<dcscor:value xsi:type=`"dcscor:DesignTimeValue`">$(Esc-Xml "$v")</dcscor:value>" } + } + X "$indent`t`t`t</dcscor:item>" + } + X "$indent`t`t</dcscor:value>" + } + } elseif (Has-DLProp $item 'choiceParameterLinks') { + $cplItems = if ($null -ne $item.choiceParameterLinks) { @($item.choiceParameterLinks) } else { @() } + if ($cplItems.Count -eq 0) { X "$indent`t`t<dcscor:value xsi:type=`"dcscor:ChoiceParameterLinks`"/>" } + else { + X "$indent`t`t<dcscor:value xsi:type=`"dcscor:ChoiceParameterLinks`">" + foreach ($cplItem in $cplItems) { + X "$indent`t`t`t<dcscor:item>" + X "$indent`t`t`t`t<dcscor:choiceParameter>$(Esc-Xml "$($cplItem.name)")</dcscor:choiceParameter>" + X "$indent`t`t`t`t<dcscor:value>$(Esc-Xml "$($cplItem.value)")</dcscor:value>" + $mode = if ($cplItem.mode) { "$($cplItem.mode)" } else { 'Auto' } + X "$indent`t`t`t`t<dcscor:mode xmlns:d8p1=`"http://v8.1c.ru/8.1/data/enterprise`" xsi:type=`"d8p1:LinkedValueChangeMode`">$mode</dcscor:mode>" + X "$indent`t`t`t</dcscor:item>" + } + X "$indent`t`t</dcscor:value>" + } + } elseif (Has-DLProp $item 'value') { + $val = $item.value + if ($val -is [bool]) { X "$indent`t`t<dcscor:value xsi:type=`"xs:boolean`">$(if ($val) { 'true' } else { 'false' })</dcscor:value>" } + elseif ($val -is [int] -or $val -is [long] -or $val -is [double] -or $val -is [decimal]) { X "$indent`t`t<dcscor:value xsi:type=`"xs:decimal`">$val</dcscor:value>" } + elseif ($val -is [hashtable] -or $val -is [System.Collections.IDictionary] -or $val -is [PSCustomObject]) { Emit-DLMLText -tag "dcscor:value" -text $val -indent "$indent`t`t" } + else { X "$indent`t`t<dcscor:value xsi:type=`"xs:string`">$(Esc-Xml "$val")</dcscor:value>" } + } + X "$indent`t</dcscor:item>" + } + X "$indent</dcssch:inputParameters>" +} + +function Emit-DLParameter { + param($p, $parsed, [string]$indent) + X "$indent<Parameter>" + $ci = "$indent`t" + X "$ci<dcssch:name>$(Esc-Xml $parsed.name)</dcssch:name>" + # Title: явный override (shorthand [..] / объект title/presentation) или авто из имени. + $title = $null + if ($parsed.title) { $title = $parsed.title } + elseif ($p -isnot [string] -and (Has-DLProp $p 'title') -and $p.title) { $title = $p.title } + elseif ($p -isnot [string] -and (Has-DLProp $p 'presentation') -and $p.presentation) { $title = $p.presentation } + if ($null -eq $title -or ($title -is [string] -and $title -eq '')) { $title = Title-FromName -name $parsed.name } + Emit-DLMLText -tag "dcssch:title" -text $title -indent $ci + # valueType + if ($parsed.type) { Emit-DLValueType -typeStr $parsed.type -indent $ci } + # value (дефолт nil; при valueListAllowed пустое — опускаем) + $vla = [bool]$parsed.valueListAllowed + $valIsArray = ($parsed.value -is [array]) -or ($parsed.value -is [System.Collections.IList] -and $parsed.value -isnot [string]) + if ($valIsArray) { + foreach ($v in @($parsed.value)) { Emit-DLValue -type $parsed.type -val $v -indent $ci -valueListAllowed $false } + } else { + Emit-DLValue -type $parsed.type -val $parsed.value -indent $ci -valueListAllowed $vla + } + # useRestriction — ВСЕГДА; дефолт true; false только при явном useRestriction:false. + $ur = $true + if ($p -isnot [string] -and (Has-DLProp $p 'useRestriction')) { $ur = [bool]$p.useRestriction } + X "$ci<dcssch:useRestriction>$(if ($ur) { 'true' } else { 'false' })</dcssch:useRestriction>" + # expression + $expr = $null + if ($p -isnot [string] -and (Has-DLProp $p 'expression') -and $p.expression) { $expr = "$($p.expression)" } + if ($expr) { X "$ci<dcssch:expression>$(Esc-Xml $expr)</dcssch:expression>" } + # availableValues + if ($p -isnot [string] -and (Has-DLProp $p 'availableValues') -and $p.availableValues) { + foreach ($av in @($p.availableValues)) { Emit-DLAvailableValue -av $av -type $parsed.type -indent $ci } + } + # valueListAllowed + if ($vla) { X "$ci<dcssch:valueListAllowed>true</dcssch:valueListAllowed>" } + # availableAsField=false (hidden или явный) + $aaf = $null + if ($parsed.hidden -eq $true) { $aaf = $false } + if ($p -isnot [string] -and (Has-DLProp $p 'availableAsField')) { $aaf = [bool]$p.availableAsField } + if ($aaf -eq $false) { X "$ci<dcssch:availableAsField>false</dcssch:availableAsField>" } + # inputParameters + if ($p -isnot [string] -and (Has-DLProp $p 'inputParameters') -and $p.inputParameters) { Emit-DLInputParameters -ip $p.inputParameters -indent $ci } + # denyIncompleteValues + if ($p -isnot [string] -and (Has-DLProp $p 'denyIncompleteValues') -and $p.denyIncompleteValues -eq $true) { X "$ci<dcssch:denyIncompleteValues>true</dcssch:denyIncompleteValues>" } + # use + $useVal = $null + if ($p -isnot [string] -and (Has-DLProp $p 'use') -and $p.use) { $useVal = "$($p.use)" } + if ($useVal) { X "$ci<dcssch:use>$(Esc-Xml $useVal)</dcssch:use>" } + X "$indent</Parameter>" +} + +function Emit-DLParameters { + param($params, [string]$indent) + if (-not $params) { return } + foreach ($p in @($params)) { + if ($p -is [string]) { + $parsed = Parse-DLParamShorthand $p + } else { + $resolvedType = "" + if ((Has-DLProp $p 'type') -and $p.type) { + if ($p.type -is [array] -or ($p.type -is [System.Collections.IList] -and $p.type -isnot [string])) { + $resolvedType = (@($p.type | ForEach-Object { Resolve-TypeStr "$_" })) -join ' | ' + } else { $resolvedType = Resolve-TypeStr "$($p.type)" } + } elseif ((Has-DLProp $p 'valueType') -and $p.valueType) { + $resolvedType = Resolve-TypeStr "$($p.valueType)" + } + $parsed = @{ name = "$($p.name)"; type = $resolvedType; value = $(if (Has-DLProp $p 'value') { $p.value } else { $null }); title = $null } + if ((Has-DLProp $p 'valueListAllowed') -and $p.valueListAllowed -eq $true) { $parsed.valueListAllowed = $true } + if ((Has-DLProp $p 'hidden') -and $p.hidden -eq $true) { $parsed.hidden = $true } + } + Emit-DLParameter -p $p -parsed $parsed -indent $indent + } +} + function Emit-Attributes { param($attrs, [string]$indent) @@ -3807,6 +4058,8 @@ function Emit-Attributes { X "$si</Field>" } } + # Schema-параметры дин-списка (DataCompositionSchemaParameter) — после Field*, до MainTable. + Emit-DLParameters -params $st.parameters -indent $si if ($st.mainTable) { X "$si<MainTable>$(Normalize-MetaTypeRef "$($st.mainTable)")</MainTable>" } # ListSettings: filter/order/conditionalAppearance (skd-грамматика) + каноничные блок-GUID. # Нет items → контейнеры всё равно эмитятся (blockMeta) = каноничный пустой скелет платформы. diff --git a/.claude/skills/form-compile/scripts/form-compile.py b/.claude/skills/form-compile/scripts/form-compile.py index 52f17dc4..702962d8 100644 --- a/.claude/skills/form-compile/scripts/form-compile.py +++ b/.claude/skills/form-compile/scripts/form-compile.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# form-compile v1.63 — Compile 1C managed form from JSON or object metadata +# form-compile v1.64 — Compile 1C managed form from JSON or object metadata # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse import copy @@ -3374,6 +3374,286 @@ def emit_attr_column(lines, col, indent): lines.append(f'{indent}</Column>') +# --- Schema-параметры динамического списка (DataCompositionSchemaParameter) --- +# Зеркало form-compile.ps1 (Emit-DLParameters). Та же сущность, что параметры СКД, но в +# форме: обёртка <Parameter> + дети dcssch:. DSL переиспользует грамматику параметров СКД. +# Контекстные дефолты: useRestriction эмитим ВСЕГДА, дефолт true (в СКД false); title — авто +# из имени; пустое value — всегда xsi:nil (даже при известном типе). Канон. порядок детей +# (по корпусу): name, title, valueType, value, useRestriction, expression, availableValue*, +# valueListAllowed, availableAsField, inputParameters, denyIncompleteValues, use. + +def emit_dl_mltext(lines, indent, tag, text): + # ML-текст с xsi:type="v8:LocalStringType" (в dcssch:* обязателен; emit_mltext его не ставит). + lines.append(f'{indent}<{tag} xsi:type="v8:LocalStringType">') + emit_ml_items(lines, f'{indent}\t', text) + lines.append(f'{indent}</{tag}>') + + +def split_dl_valuelist_csv(s): + result = [] + if s is None: + return result + items = [] + buf = [] + in_quote = None + for ch in s: + if in_quote: + buf.append(ch) + if ch == in_quote: + in_quote = None + elif ch in ("'", '"'): + in_quote = ch + buf.append(ch) + elif ch == ',': + items.append(''.join(buf)); buf = [] + else: + buf.append(ch) + if buf: + items.append(''.join(buf)) + for raw in items: + t = raw.strip() + if len(t) >= 2 and ((t[0] == "'" and t[-1] == "'") or (t[0] == '"' and t[-1] == '"')): + t = t[1:-1] + if t != '': + result.append(t) + return result + + +def parse_dl_param_shorthand(s): + result = {'name': '', 'type': '', 'value': None, 'title': None} + if '@valueList' in s: + result['valueListAllowed'] = True + s = re.sub(r'\s*@valueList', '', s) + if '@hidden' in s: + result['hidden'] = True + s = re.sub(r'\s*@hidden', '', s) + 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() + result['type'] = resolve_type_str(m.group(2).strip()) + if m.group(4): + rhs = m.group(4).strip() + items = split_dl_valuelist_csv(rhs) + if len(items) >= 2: + result['value'] = items + result['valueListAllowed'] = True + elif len(items) == 1: + result['value'] = items[0] + else: + result['value'] = rhs + else: + result['name'] = s.strip() + return result + + +def is_dl_empty_value(v): + if v is None: + return True + sv = str(v).strip() + return sv == '' or sv == '_' or sv.lower() == 'null' + + +def emit_dl_value(lines, type_str, val, indent, value_list_allowed=False): + if is_dl_empty_value(val): + # Дин-список: пустое значение платформа ВСЕГДА пишет как xsi:nil (даже при известном типе). + if value_list_allowed: + return + lines.append(f'{indent}<dcssch:value xsi:nil="true"/>') + return + if isinstance(val, bool): + val_str = 'true' if val else 'false' + else: + val_str = str(val) + t = type_str or '' + if re.match(r'^(date|dateTime|time)', t): + lines.append(f'{indent}<dcssch:value xsi:type="xs:dateTime">{esc_xml(val_str)}</dcssch:value>') + elif t == 'boolean': + lines.append(f'{indent}<dcssch:value xsi:type="xs:boolean">{esc_xml(val_str)}</dcssch:value>') + elif re.match(r'^decimal', t): + lines.append(f'{indent}<dcssch:value xsi:type="xs:decimal">{esc_xml(val_str)}</dcssch:value>') + elif re.match(r'^string', t): + lines.append(f'{indent}<dcssch:value xsi:type="xs:string">{esc_xml(val_str)}</dcssch:value>') + elif re.match(r'^(CatalogRef|DocumentRef|EnumRef|ChartOfAccountsRef|ChartOfCharacteristicTypesRef|ChartOfCalculationTypesRef|BusinessProcessRef|TaskRef|ExchangePlanRef)\.', t): + lines.append(f'{indent}<dcssch:value xsi:type="dcscor:DesignTimeValue">{esc_xml(val_str)}</dcssch:value>') + else: + if re.match(r'^\d{4}-\d{2}-\d{2}T', val_str): + lines.append(f'{indent}<dcssch:value xsi:type="xs:dateTime">{esc_xml(val_str)}</dcssch:value>') + elif val_str in ('true', 'false'): + lines.append(f'{indent}<dcssch:value xsi:type="xs:boolean">{esc_xml(val_str)}</dcssch:value>') + elif re.match(r'^(ПланСчетов|Справочник|Перечисление|Документ|ПланВидовХарактеристик|ПланВидовРасчета|БизнесПроцесс|Задача|РегистрСведений|ПланОбмена)\.', val_str) or re.match(r'^(ChartOfAccounts|Catalog|Enum|Document|ChartOfCharacteristicTypes|ChartOfCalculationTypes|BusinessProcess|Task|InformationRegister|ExchangePlan)\.', val_str): + lines.append(f'{indent}<dcssch:value xsi:type="dcscor:DesignTimeValue">{esc_xml(val_str)}</dcssch:value>') + else: + lines.append(f'{indent}<dcssch:value xsi:type="xs:string">{esc_xml(val_str)}</dcssch:value>') + + +def emit_dl_value_type(lines, type_str, indent): + if not type_str: + return + lines.append(f'{indent}<dcssch:valueType>') + for part in re.split(r'\s*[|+]\s*', str(type_str)): + emit_single_type(lines, part.strip(), f'{indent}\t') + lines.append(f'{indent}</dcssch:valueType>') + + +def emit_dl_available_value(lines, av, type_str, indent): + lines.append(f'{indent}<dcssch:availableValue>') + av_val = av.get('value') if isinstance(av, dict) else None + emit_dl_value(lines, type_str, av_val, f'{indent}\t', False) + pres = (av.get('presentation') or av.get('title')) if isinstance(av, dict) else None + if pres: + emit_dl_mltext(lines, f'{indent}\t', 'dcssch:presentation', pres) + lines.append(f'{indent}</dcssch:availableValue>') + + +def emit_dl_input_parameters(lines, ip, indent): + if ip is None: + return + items = ip if isinstance(ip, list) else [ip] + if len(items) == 0: + return + lines.append(f'{indent}<dcssch:inputParameters>') + for item in items: + lines.append(f'{indent}\t<dcscor:item>') + if 'use' in item and item.get('use') is not None and not item.get('use'): + lines.append(f'{indent}\t\t<dcscor:use>false</dcscor:use>') + lines.append(f'{indent}\t\t<dcscor:parameter>{esc_xml(str(item.get("parameter", "")))}</dcscor:parameter>') + if 'choiceParameters' in item: + cp_items = item.get('choiceParameters') or [] + if len(cp_items) == 0: + lines.append(f'{indent}\t\t<dcscor:value xsi:type="dcscor:ChoiceParameters"/>') + else: + lines.append(f'{indent}\t\t<dcscor:value xsi:type="dcscor:ChoiceParameters">') + for cp in cp_items: + lines.append(f'{indent}\t\t\t<dcscor:item>') + lines.append(f'{indent}\t\t\t\t<dcscor:choiceParameter>{esc_xml(str(cp.get("name", "")))}</dcscor:choiceParameter>') + for v in (cp.get('values') or []): + if isinstance(v, bool): + lines.append(f'{indent}\t\t\t\t<dcscor:value xsi:type="xs:boolean">{"true" if v else "false"}</dcscor:value>') + elif isinstance(v, (int, float)): + lines.append(f'{indent}\t\t\t\t<dcscor:value xsi:type="xs:decimal">{v}</dcscor:value>') + else: + lines.append(f'{indent}\t\t\t\t<dcscor:value xsi:type="dcscor:DesignTimeValue">{esc_xml(str(v))}</dcscor:value>') + lines.append(f'{indent}\t\t\t</dcscor:item>') + lines.append(f'{indent}\t\t</dcscor:value>') + elif 'choiceParameterLinks' in item: + cpl_items = item.get('choiceParameterLinks') or [] + if len(cpl_items) == 0: + lines.append(f'{indent}\t\t<dcscor:value xsi:type="dcscor:ChoiceParameterLinks"/>') + else: + lines.append(f'{indent}\t\t<dcscor:value xsi:type="dcscor:ChoiceParameterLinks">') + for cpl in cpl_items: + lines.append(f'{indent}\t\t\t<dcscor:item>') + lines.append(f'{indent}\t\t\t\t<dcscor:choiceParameter>{esc_xml(str(cpl.get("name", "")))}</dcscor:choiceParameter>') + lines.append(f'{indent}\t\t\t\t<dcscor:value>{esc_xml(str(cpl.get("value", "")))}</dcscor:value>') + mode = str(cpl.get('mode') or 'Auto') + lines.append(f'{indent}\t\t\t\t<dcscor:mode xmlns:d8p1="http://v8.1c.ru/8.1/data/enterprise" xsi:type="d8p1:LinkedValueChangeMode">{mode}</dcscor:mode>') + lines.append(f'{indent}\t\t\t</dcscor:item>') + lines.append(f'{indent}\t\t</dcscor:value>') + elif 'value' in item: + val = item.get('value') + if isinstance(val, bool): + lines.append(f'{indent}\t\t<dcscor:value xsi:type="xs:boolean">{"true" if val else "false"}</dcscor:value>') + elif isinstance(val, (int, float)): + lines.append(f'{indent}\t\t<dcscor:value xsi:type="xs:decimal">{val}</dcscor:value>') + elif isinstance(val, dict): + emit_dl_mltext(lines, f'{indent}\t\t', 'dcscor:value', val) + else: + lines.append(f'{indent}\t\t<dcscor:value xsi:type="xs:string">{esc_xml(str(val))}</dcscor:value>') + lines.append(f'{indent}\t</dcscor:item>') + lines.append(f'{indent}</dcssch:inputParameters>') + + +def emit_dl_parameter(lines, p, parsed, indent): + is_obj = not isinstance(p, str) + lines.append(f'{indent}<Parameter>') + ci = f'{indent}\t' + lines.append(f'{ci}<dcssch:name>{esc_xml(parsed["name"])}</dcssch:name>') + # Title: явный override (shorthand [..] / объект title/presentation) или авто из имени. + title = None + if parsed.get('title'): + title = parsed['title'] + elif is_obj and p.get('title'): + title = p['title'] + elif is_obj and p.get('presentation'): + title = p['presentation'] + if title is None or (isinstance(title, str) and title == ''): + title = title_from_name(parsed['name']) + emit_dl_mltext(lines, ci, 'dcssch:title', title) + # valueType + if parsed.get('type'): + emit_dl_value_type(lines, parsed['type'], ci) + # value (дефолт nil; при valueListAllowed пустое — опускаем) + vla = bool(parsed.get('valueListAllowed')) + pv = parsed.get('value') + if isinstance(pv, list): + for v in pv: + emit_dl_value(lines, parsed.get('type', ''), v, ci, False) + else: + emit_dl_value(lines, parsed.get('type', ''), pv, ci, vla) + # useRestriction — ВСЕГДА; дефолт true; false только при явном useRestriction:false. + ur = True + if is_obj and 'useRestriction' in p: + ur = bool(p['useRestriction']) + lines.append(f'{ci}<dcssch:useRestriction>{"true" if ur else "false"}</dcssch:useRestriction>') + # expression + expr = str(p['expression']) if (is_obj and p.get('expression')) else None + if expr: + lines.append(f'{ci}<dcssch:expression>{esc_xml(expr)}</dcssch:expression>') + # availableValues + if is_obj and p.get('availableValues'): + for av in p['availableValues']: + emit_dl_available_value(lines, av, parsed.get('type', ''), ci) + # valueListAllowed + if vla: + lines.append(f'{ci}<dcssch:valueListAllowed>true</dcssch:valueListAllowed>') + # availableAsField=false (hidden или явный) + aaf = None + if parsed.get('hidden') is True: + aaf = False + if is_obj and 'availableAsField' in p: + aaf = bool(p['availableAsField']) + if aaf is False: + lines.append(f'{ci}<dcssch:availableAsField>false</dcssch:availableAsField>') + # inputParameters + if is_obj and p.get('inputParameters'): + emit_dl_input_parameters(lines, p['inputParameters'], ci) + # denyIncompleteValues + if is_obj and p.get('denyIncompleteValues') is True: + lines.append(f'{ci}<dcssch:denyIncompleteValues>true</dcssch:denyIncompleteValues>') + # use + if is_obj and p.get('use'): + lines.append(f'{ci}<dcssch:use>{esc_xml(str(p["use"]))}</dcssch:use>') + lines.append(f'{indent}</Parameter>') + + +def emit_dl_parameters(lines, params, indent): + if not params: + return + for p in params: + if isinstance(p, str): + parsed = parse_dl_param_shorthand(p) + else: + resolved_type = '' + if p.get('type'): + if isinstance(p['type'], list): + resolved_type = ' | '.join(resolve_type_str(str(x)) for x in p['type']) + else: + resolved_type = resolve_type_str(str(p['type'])) + elif p.get('valueType'): + resolved_type = resolve_type_str(str(p['valueType'])) + parsed = {'name': str(p.get('name', '')), 'type': resolved_type, + 'value': p.get('value') if 'value' in p else None, 'title': None} + if p.get('valueListAllowed') is True: + parsed['valueListAllowed'] = True + if p.get('hidden') is True: + parsed['hidden'] = True + emit_dl_parameter(lines, p, parsed, indent) + + def emit_attributes(lines, attrs, indent): if not attrs or len(attrs) == 0: return @@ -3482,6 +3762,8 @@ def emit_attributes(lines, attrs, indent): emit_ml_items(lines, f'{si}\t\t', fld['title']) lines.append(f'{si}\t</dcssch:title>') lines.append(f'{si}</Field>') + # Schema-параметры дин-списка (DataCompositionSchemaParameter) — после Field*, до MainTable. + emit_dl_parameters(lines, s.get('parameters'), si) if s.get('mainTable'): lines.append(f'{si}<MainTable>{normalize_meta_type_ref(str(s["mainTable"]))}</MainTable>') # ListSettings: filter/order/conditionalAppearance (skd-грамматика) + каноничные блок-GUID. diff --git a/.claude/skills/form-decompile/scripts/form-decompile.ps1 b/.claude/skills/form-decompile/scripts/form-decompile.ps1 index 6a512a7d..f108d9f1 100644 --- a/.claude/skills/form-decompile/scripts/form-decompile.ps1 +++ b/.claude/skills/form-decompile/scripts/form-decompile.ps1 @@ -1,4 +1,4 @@ -# form-decompile v0.45 — Decompile 1C managed Form.xml to JSON DSL (draft) +# form-decompile v0.46 — Decompile 1C managed Form.xml to JSON DSL (draft) # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills # ВНИМАНИЕ: раундтрип не гарантируется. Навык исключён из авто-использования моделью. param( @@ -949,6 +949,111 @@ function Decompile-Type { return ($parts -join ' | ') } +# Schema-параметры динамического списка (<Parameter> под <Settings>) — зеркало эмиссии +# form-compile (Emit-DLParameters). Инверсия контекстных дефолтов: useRestriction=true и +# title==Title-FromName опускаем (компилятор восстановит). Сущность = DataCompositionSchemaParameter. +function Build-DLInputParameters { + param($ipNode) + $items = New-Object System.Collections.ArrayList + foreach ($it in @($ipNode.SelectNodes("dcscor:item", $ns))) { + $io = [ordered]@{} + $io['parameter'] = Get-Child $it 'parameter' + $useN = $it.SelectSingleNode("dcscor:use", $ns) + if ($useN -and $useN.InnerText -eq 'false') { $io['use'] = $false } + $valN = $it.SelectSingleNode("dcscor:value", $ns) + if ($valN) { + $vt = $valN.GetAttribute("type", $NS_XSI) + if ($vt -match 'ChoiceParameters$') { + $cps = New-Object System.Collections.ArrayList + foreach ($cpi in @($valN.SelectNodes("dcscor:item", $ns))) { + $cpo = [ordered]@{} + $cpo['name'] = Get-Child $cpi 'choiceParameter' + $vals = New-Object System.Collections.ArrayList + foreach ($cv in @($cpi.SelectNodes("dcscor:value", $ns))) { + [void]$vals.Add((Convert-TypedValue -raw $cv.InnerText -xsiType ($cv.GetAttribute("type", $NS_XSI)))) + } + $cpo['values'] = @($vals) + [void]$cps.Add($cpo) + } + $io['choiceParameters'] = @($cps) + } elseif ($vt -match 'ChoiceParameterLinks$') { + $cpls = New-Object System.Collections.ArrayList + foreach ($cpi in @($valN.SelectNodes("dcscor:item", $ns))) { + $cpo = [ordered]@{} + $cpo['name'] = Get-Child $cpi 'choiceParameter' + $cpo['value'] = Get-Child $cpi 'value' + $md = Get-Child $cpi 'mode'; if ($md -and $md -ne 'Auto') { $cpo['mode'] = $md } + [void]$cpls.Add($cpo) + } + $io['choiceParameterLinks'] = @($cpls) + } else { + if ($valN.GetAttribute("nil", $NS_XSI) -ne 'true') { $io['value'] = Convert-TypedValue -raw $valN.InnerText -xsiType $vt } + } + } + [void]$items.Add($io) + } + return @($items) +} + +function Build-DLParameter { + param($pNode) + $name = Get-Child $pNode 'name' + $o = [ordered]@{} + $o['name'] = $name + # title — опускаем, если совпадает с авто-выводом из имени (ru-only) + $titleNode = $pNode.SelectSingleNode("dcssch:title", $ns) + if ($titleNode) { + $t = Get-LangText $titleNode + if ($null -ne $t) { + $auto = Title-FromName -name $name + if (-not (($t -is [string]) -and ($t -eq $auto))) { $o['title'] = $t } + } + } + # valueType + $vtNode = $pNode.SelectSingleNode("dcssch:valueType", $ns) + $typeVal = $null + if ($vtNode) { $typeVal = Decompile-Type $vtNode; if ($typeVal) { $o['type'] = $typeVal } } + # value — опускаем nil (дефолт) + $vNode = $pNode.SelectSingleNode("dcssch:value", $ns) + if ($vNode -and ($vNode.GetAttribute("nil", $NS_XSI) -ne 'true')) { + $o['value'] = Convert-TypedValue -raw $vNode.InnerText -xsiType ($vNode.GetAttribute("type", $NS_XSI)) + } + # useRestriction — опускаем true (дефолт), фиксируем false + if ((Get-Child $pNode 'useRestriction') -eq 'false') { $o['useRestriction'] = $false } + # expression + $expr = Get-Child $pNode 'expression'; if ($null -ne $expr -and $expr -ne '') { $o['expression'] = $expr } + # availableValues + $avNodes = @($pNode.SelectNodes("dcssch:availableValue", $ns)) + if ($avNodes.Count -gt 0) { + $avs = New-Object System.Collections.ArrayList + foreach ($avn in $avNodes) { + $avo = [ordered]@{} + $avv = $avn.SelectSingleNode("dcssch:value", $ns) + if ($avv -and ($avv.GetAttribute("nil", $NS_XSI) -ne 'true')) { $avo['value'] = Convert-TypedValue -raw $avv.InnerText -xsiType ($avv.GetAttribute("type", $NS_XSI)) } + else { $avo['value'] = $null } + $avp = $avn.SelectSingleNode("dcssch:presentation", $ns) + if ($avp) { $pres = Get-LangText $avp; if ($null -ne $pres) { $avo['presentation'] = $pres } } + [void]$avs.Add($avo) + } + $o['availableValues'] = @($avs) + } + # valueListAllowed / availableAsField + if ((Get-Child $pNode 'valueListAllowed') -eq 'true') { $o['valueListAllowed'] = $true } + if ((Get-Child $pNode 'availableAsField') -eq 'false') { $o['availableAsField'] = $false } + # inputParameters + $ipNode = $pNode.SelectSingleNode("dcssch:inputParameters", $ns) + if ($ipNode) { $ip = Build-DLInputParameters $ipNode; if (@($ip).Count -gt 0) { $o['inputParameters'] = $ip } } + # denyIncompleteValues / use + if ((Get-Child $pNode 'denyIncompleteValues') -eq 'true') { $o['denyIncompleteValues'] = $true } + $use = Get-Child $pNode 'use'; if ($null -ne $use -and $use -ne '') { $o['use'] = $use } + + # Компактизация: {name} → строка "name"; {name, type} → "name: type"; иначе объект. + $keys = @($o.Keys) + if ($keys.Count -eq 1) { return $name } + if ($keys.Count -eq 2 -and $o.Contains('type') -and ($typeVal -is [string])) { return ("{0}: {1}" -f $name, $typeVal) } + return $o +} + # --- 4. Element dispatch --- $ELEMENT_KEY = @{ 'UsualGroup'='group'; 'ColumnGroup'='columnGroup'; 'ButtonGroup'='buttonGroup'; 'InputField'='input'; 'CheckBoxField'='check'; @@ -1468,6 +1573,13 @@ if ($attrsNode) { } $so['fields'] = @($fields) } + # Schema-параметры дин-списка (прямые <Parameter> под Settings, не в ListSettings) + $paramNodes = @($setNode.SelectNodes("lf:Parameter", $ns)) + if ($paramNodes.Count -gt 0) { + $dlPars = New-Object System.Collections.ArrayList + foreach ($pn in $paramNodes) { [void]$dlPars.Add((Build-DLParameter $pn)) } + $so['parameters'] = @($dlPars) + } # ListSettings: пустой скелет (только viewMode+GUID) опускаем — компилятор # регенерит каноничный скелет. Захватываем только контейнеры с реальными # dcsset:item (filter/order/conditionalAppearance) в формат компилятора. diff --git a/docs/form-dsl-spec.md b/docs/form-dsl-spec.md index b541704a..d6c10c09 100644 --- a/docs/form-dsl-spec.md +++ b/docs/form-dsl-spec.md @@ -670,6 +670,7 @@ Pages поддерживает `pagesRepresentation`: `None`, `TabsOnTop`, `Tabs | `query` | string | Текст запроса (`ManualQuery=true`). Поддерживает `@file.sql` (путь относительно JSON) | | `dynamicDataRead` | bool | Динамическое считывание. **Умолчание `true`** — указывать только для отключения (`false`) | | `fields` | array | Явные поля набора (редко): `{ field, dataPath?, title? }` — для переопределения заголовка. Обычно поля выводятся из запроса автоматически | +| `parameters` | array | Параметры схемы запроса (`DataCompositionSchemaParameter`) — см. ниже | | `order` | array | Сортировка списка (см. ниже) | | `filter` | array | Отбор списка (грамматика как в СКД) | | `conditionalAppearance` | array | Условное оформление списка (грамматика как в СКД) | @@ -678,6 +679,32 @@ Pages поддерживает `pagesRepresentation`: `None`, `TabsOnTop`, `Tabs Пустой блок настроек компоновщика (`ListSettings`) генерируется автоматически (каноничный скелет платформы); указывать ничего не нужно. +#### parameters — параметры схемы дин-списка + +Параметры запроса дин-списка — это та же сущность `DataCompositionSchemaParameter`, что и параметры СКД (`&Параметр` в тексте запроса). **Грамматика идентична параметрам СКД** (см. [skd-dsl-spec.md](skd-dsl-spec.md)): shorthand `"Имя [Заголовок]: Тип = Значение @valueList @hidden"` или объект. Используй те же ключи — модель переносит знание один-в-один. + +```json +"settings": { + "query": "ВЫБРАТЬ … ГДЕ Товары.Артикул = &Артикул И … ПОДОБНО &Маска", + "parameters": [ + "Артикул", + "Маска: string = %", + { "name": "ВидЦен", "valueListAllowed": true }, + { "name": "Период", "type": "dateTime", "useRestriction": false } + ] +} +``` + +Отличия контекста дин-списка от параметров отчёта СКД (видимы только в дефолтах — модель просто опускает ключ): + +| Поведение | Дин-список | +|-----------|-----------| +| `title` | Авто из имени (camelCase → «Заполнена серия»); явный `title`/`[Заголовок]` — только для переопределения | +| `useRestriction` | Эмитится всегда, **умолчание `true`**; для выключения — объект `{ "useRestriction": false }` | +| `value` | Умолчание — пустое (`xsi:nil`), даже при заданном типе | + +Объектные ключи (как в СКД): `name`, `title`, `type`/`valueType`, `value`, `valueListAllowed`, `useRestriction`, `availableAsField`, `expression`, `availableValues` (`[{ value, presentation }]`), `inputParameters`, `denyIncompleteValues`, `use`. + #### order / filter / conditionalAppearance Грамматика этих ключей идентична настройкам СКД — см. [skd-dsl-spec.md](skd-dsl-spec.md) (разделы filter / order / conditionalAppearance). Кратко: diff --git a/tests/skills/cases/form-compile/dynamic-list-parameters.json b/tests/skills/cases/form-compile/dynamic-list-parameters.json new file mode 100644 index 00000000..be147a4d --- /dev/null +++ b/tests/skills/cases/form-compile/dynamic-list-parameters.json @@ -0,0 +1,47 @@ +{ + "name": "DynamicList — schema-параметры (DataCompositionSchemaParameter): shorthand + объект + полная грамматика", + "preRun": [ + { + "script": "meta-compile/scripts/meta-compile", + "input": { "type": "Catalog", "name": "Товары", "attributes": [{ "name": "Артикул", "type": "String", "length": 25 }] }, + "args": { "-JsonPath": "{inputFile}", "-OutputDir": "{workDir}" } + }, + { + "script": "form-add/scripts/form-add", + "args": { "-ObjectPath": "{workDir}/Catalogs/Товары.xml", "-FormName": "ФормаСписка", "-Purpose": "List" } + } + ], + "params": { "outputPath": "Catalogs/Товары/Forms/ФормаСписка/Ext/Form.xml" }, + "validatePath": "Catalogs/Товары/Forms/ФормаСписка/Ext/Form.xml", + "input": { + "title": "Товары", + "attributes": [ + { "name": "Список", "type": "DynamicList", "main": true, "settings": { + "mainTable": "Catalog.Товары", + "query": "ВЫБРАТЬ\n\tТовары.Ссылка КАК Ссылка,\n\tТовары.Код КАК Код,\n\tТовары.Наименование КАК Наименование,\n\tТовары.Артикул КАК Артикул\nИЗ\n\tСправочник.Товары КАК Товары\nГДЕ\n\tТовары.Артикул = &Артикул\n\tИ Товары.Наименование ПОДОБНО &Маска", + "parameters": [ + "Артикул", + "Маска: string = %", + { "name": "ВидЦен", "valueListAllowed": true }, + { "name": "Период", "type": "dateTime", "useRestriction": false }, + { + "name": "Порог", "type": "decimal(10,2)", "value": 0, + "title": "Порог округления", + "availableValues": [ + { "value": null, "presentation": "Нет" }, + { "value": 1, "presentation": "Один" } + ], + "denyIncompleteValues": true, + "use": "Always" + } + ] + } } + ], + "elements": [ + { "table": "Список", "path": "Список", "columns": [ + { "input": "Код", "path": "Список.Code" }, + { "input": "Наименование", "path": "Список.Description" } + ]} + ] + } +} diff --git a/tests/skills/cases/form-compile/snapshots/dynamic-list-parameters/Catalogs/Товары.xml b/tests/skills/cases/form-compile/snapshots/dynamic-list-parameters/Catalogs/Товары.xml new file mode 100644 index 00000000..fc0e9a99 --- /dev/null +++ b/tests/skills/cases/form-compile/snapshots/dynamic-list-parameters/Catalogs/Товары.xml @@ -0,0 +1,373 @@ +<?xml version="1.0" encoding="utf-8"?> +<MetaDataObject xmlns="http://v8.1c.ru/8.3/MDClasses" xmlns:app="http://v8.1c.ru/8.2/managed-application/core" xmlns:cfg="http://v8.1c.ru/8.1/data/enterprise/current-config" xmlns:cmi="http://v8.1c.ru/8.2/managed-application/cmi" xmlns:ent="http://v8.1c.ru/8.1/data/enterprise" xmlns:lf="http://v8.1c.ru/8.2/managed-application/logform" xmlns:style="http://v8.1c.ru/8.1/data/ui/style" xmlns:sys="http://v8.1c.ru/8.1/data/ui/fonts/system" xmlns:v8="http://v8.1c.ru/8.1/data/core" xmlns:v8ui="http://v8.1c.ru/8.1/data/ui" xmlns:web="http://v8.1c.ru/8.1/data/ui/colors/web" xmlns:win="http://v8.1c.ru/8.1/data/ui/colors/windows" xmlns:xen="http://v8.1c.ru/8.3/xcf/enums" xmlns:xpr="http://v8.1c.ru/8.3/xcf/predef" xmlns:xr="http://v8.1c.ru/8.3/xcf/readable" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.17"> + <Catalog uuid="UUID-001"> + <InternalInfo> + <xr:GeneratedType name="CatalogObject.Товары" category="Object"> + <xr:TypeId>UUID-002</xr:TypeId> + <xr:ValueId>UUID-003</xr:ValueId> + </xr:GeneratedType> + <xr:GeneratedType name="CatalogRef.Товары" category="Ref"> + <xr:TypeId>UUID-004</xr:TypeId> + <xr:ValueId>UUID-005</xr:ValueId> + </xr:GeneratedType> + <xr:GeneratedType name="CatalogSelection.Товары" category="Selection"> + <xr:TypeId>UUID-006</xr:TypeId> + <xr:ValueId>UUID-007</xr:ValueId> + </xr:GeneratedType> + <xr:GeneratedType name="CatalogList.Товары" category="List"> + <xr:TypeId>UUID-008</xr:TypeId> + <xr:ValueId>UUID-009</xr:ValueId> + </xr:GeneratedType> + <xr:GeneratedType name="CatalogManager.Товары" category="Manager"> + <xr:TypeId>UUID-010</xr:TypeId> + <xr:ValueId>UUID-011</xr:ValueId> + </xr:GeneratedType> + </InternalInfo> + <Properties> + <Name>Товары</Name> + <Synonym> + <v8:item> + <v8:lang>ru</v8:lang> + <v8:content>Товары</v8:content> + </v8:item> + </Synonym> + <Comment /> + <Hierarchical>false</Hierarchical> + <HierarchyType>HierarchyFoldersAndItems</HierarchyType> + <LimitLevelCount>false</LimitLevelCount> + <LevelCount>2</LevelCount> + <FoldersOnTop>true</FoldersOnTop> + <UseStandardCommands>true</UseStandardCommands> + <Owners /> + <SubordinationUse>ToItems</SubordinationUse> + <CodeLength>9</CodeLength> + <DescriptionLength>25</DescriptionLength> + <CodeType>String</CodeType> + <CodeAllowedLength>Variable</CodeAllowedLength> + <CodeSeries>WholeCatalog</CodeSeries> + <CheckUnique>false</CheckUnique> + <Autonumbering>true</Autonumbering> + <DefaultPresentation>AsDescription</DefaultPresentation> + <StandardAttributes> + <xr:StandardAttribute name="PredefinedDataName"> + <xr:LinkByType /> + <xr:FillChecking>DontCheck</xr:FillChecking> + <xr:MultiLine>false</xr:MultiLine> + <xr:FillFromFillingValue>false</xr:FillFromFillingValue> + <xr:CreateOnInput>Auto</xr:CreateOnInput> + <xr:MaxValue xsi:nil="true" /> + <xr:ToolTip /> + <xr:ExtendedEdit>false</xr:ExtendedEdit> + <xr:Format /> + <xr:ChoiceForm /> + <xr:QuickChoice>Auto</xr:QuickChoice> + <xr:ChoiceHistoryOnInput>Auto</xr:ChoiceHistoryOnInput> + <xr:EditFormat /> + <xr:PasswordMode>false</xr:PasswordMode> + <xr:DataHistory>Use</xr:DataHistory> + <xr:MarkNegatives>false</xr:MarkNegatives> + <xr:MinValue xsi:nil="true" /> + <xr:Synonym /> + <xr:Comment /> + <xr:FullTextSearch>Use</xr:FullTextSearch> + <xr:ChoiceParameterLinks /> + <xr:FillValue xsi:nil="true" /> + <xr:Mask /> + <xr:ChoiceParameters /> + </xr:StandardAttribute> + <xr:StandardAttribute name="Predefined"> + <xr:LinkByType /> + <xr:FillChecking>DontCheck</xr:FillChecking> + <xr:MultiLine>false</xr:MultiLine> + <xr:FillFromFillingValue>false</xr:FillFromFillingValue> + <xr:CreateOnInput>Auto</xr:CreateOnInput> + <xr:MaxValue xsi:nil="true" /> + <xr:ToolTip /> + <xr:ExtendedEdit>false</xr:ExtendedEdit> + <xr:Format /> + <xr:ChoiceForm /> + <xr:QuickChoice>Auto</xr:QuickChoice> + <xr:ChoiceHistoryOnInput>Auto</xr:ChoiceHistoryOnInput> + <xr:EditFormat /> + <xr:PasswordMode>false</xr:PasswordMode> + <xr:DataHistory>Use</xr:DataHistory> + <xr:MarkNegatives>false</xr:MarkNegatives> + <xr:MinValue xsi:nil="true" /> + <xr:Synonym /> + <xr:Comment /> + <xr:FullTextSearch>Use</xr:FullTextSearch> + <xr:ChoiceParameterLinks /> + <xr:FillValue xsi:nil="true" /> + <xr:Mask /> + <xr:ChoiceParameters /> + </xr:StandardAttribute> + <xr:StandardAttribute name="Ref"> + <xr:LinkByType /> + <xr:FillChecking>DontCheck</xr:FillChecking> + <xr:MultiLine>false</xr:MultiLine> + <xr:FillFromFillingValue>false</xr:FillFromFillingValue> + <xr:CreateOnInput>Auto</xr:CreateOnInput> + <xr:MaxValue xsi:nil="true" /> + <xr:ToolTip /> + <xr:ExtendedEdit>false</xr:ExtendedEdit> + <xr:Format /> + <xr:ChoiceForm /> + <xr:QuickChoice>Auto</xr:QuickChoice> + <xr:ChoiceHistoryOnInput>Auto</xr:ChoiceHistoryOnInput> + <xr:EditFormat /> + <xr:PasswordMode>false</xr:PasswordMode> + <xr:DataHistory>Use</xr:DataHistory> + <xr:MarkNegatives>false</xr:MarkNegatives> + <xr:MinValue xsi:nil="true" /> + <xr:Synonym /> + <xr:Comment /> + <xr:FullTextSearch>Use</xr:FullTextSearch> + <xr:ChoiceParameterLinks /> + <xr:FillValue xsi:nil="true" /> + <xr:Mask /> + <xr:ChoiceParameters /> + </xr:StandardAttribute> + <xr:StandardAttribute name="DeletionMark"> + <xr:LinkByType /> + <xr:FillChecking>DontCheck</xr:FillChecking> + <xr:MultiLine>false</xr:MultiLine> + <xr:FillFromFillingValue>false</xr:FillFromFillingValue> + <xr:CreateOnInput>Auto</xr:CreateOnInput> + <xr:MaxValue xsi:nil="true" /> + <xr:ToolTip /> + <xr:ExtendedEdit>false</xr:ExtendedEdit> + <xr:Format /> + <xr:ChoiceForm /> + <xr:QuickChoice>Auto</xr:QuickChoice> + <xr:ChoiceHistoryOnInput>Auto</xr:ChoiceHistoryOnInput> + <xr:EditFormat /> + <xr:PasswordMode>false</xr:PasswordMode> + <xr:DataHistory>Use</xr:DataHistory> + <xr:MarkNegatives>false</xr:MarkNegatives> + <xr:MinValue xsi:nil="true" /> + <xr:Synonym /> + <xr:Comment /> + <xr:FullTextSearch>Use</xr:FullTextSearch> + <xr:ChoiceParameterLinks /> + <xr:FillValue xsi:nil="true" /> + <xr:Mask /> + <xr:ChoiceParameters /> + </xr:StandardAttribute> + <xr:StandardAttribute name="IsFolder"> + <xr:LinkByType /> + <xr:FillChecking>DontCheck</xr:FillChecking> + <xr:MultiLine>false</xr:MultiLine> + <xr:FillFromFillingValue>false</xr:FillFromFillingValue> + <xr:CreateOnInput>Auto</xr:CreateOnInput> + <xr:MaxValue xsi:nil="true" /> + <xr:ToolTip /> + <xr:ExtendedEdit>false</xr:ExtendedEdit> + <xr:Format /> + <xr:ChoiceForm /> + <xr:QuickChoice>Auto</xr:QuickChoice> + <xr:ChoiceHistoryOnInput>Auto</xr:ChoiceHistoryOnInput> + <xr:EditFormat /> + <xr:PasswordMode>false</xr:PasswordMode> + <xr:DataHistory>Use</xr:DataHistory> + <xr:MarkNegatives>false</xr:MarkNegatives> + <xr:MinValue xsi:nil="true" /> + <xr:Synonym /> + <xr:Comment /> + <xr:FullTextSearch>Use</xr:FullTextSearch> + <xr:ChoiceParameterLinks /> + <xr:FillValue xsi:nil="true" /> + <xr:Mask /> + <xr:ChoiceParameters /> + </xr:StandardAttribute> + <xr:StandardAttribute name="Owner"> + <xr:LinkByType /> + <xr:FillChecking>DontCheck</xr:FillChecking> + <xr:MultiLine>false</xr:MultiLine> + <xr:FillFromFillingValue>false</xr:FillFromFillingValue> + <xr:CreateOnInput>Auto</xr:CreateOnInput> + <xr:MaxValue xsi:nil="true" /> + <xr:ToolTip /> + <xr:ExtendedEdit>false</xr:ExtendedEdit> + <xr:Format /> + <xr:ChoiceForm /> + <xr:QuickChoice>Auto</xr:QuickChoice> + <xr:ChoiceHistoryOnInput>Auto</xr:ChoiceHistoryOnInput> + <xr:EditFormat /> + <xr:PasswordMode>false</xr:PasswordMode> + <xr:DataHistory>Use</xr:DataHistory> + <xr:MarkNegatives>false</xr:MarkNegatives> + <xr:MinValue xsi:nil="true" /> + <xr:Synonym /> + <xr:Comment /> + <xr:FullTextSearch>Use</xr:FullTextSearch> + <xr:ChoiceParameterLinks /> + <xr:FillValue xsi:nil="true" /> + <xr:Mask /> + <xr:ChoiceParameters /> + </xr:StandardAttribute> + <xr:StandardAttribute name="Parent"> + <xr:LinkByType /> + <xr:FillChecking>DontCheck</xr:FillChecking> + <xr:MultiLine>false</xr:MultiLine> + <xr:FillFromFillingValue>false</xr:FillFromFillingValue> + <xr:CreateOnInput>Auto</xr:CreateOnInput> + <xr:MaxValue xsi:nil="true" /> + <xr:ToolTip /> + <xr:ExtendedEdit>false</xr:ExtendedEdit> + <xr:Format /> + <xr:ChoiceForm /> + <xr:QuickChoice>Auto</xr:QuickChoice> + <xr:ChoiceHistoryOnInput>Auto</xr:ChoiceHistoryOnInput> + <xr:EditFormat /> + <xr:PasswordMode>false</xr:PasswordMode> + <xr:DataHistory>Use</xr:DataHistory> + <xr:MarkNegatives>false</xr:MarkNegatives> + <xr:MinValue xsi:nil="true" /> + <xr:Synonym /> + <xr:Comment /> + <xr:FullTextSearch>Use</xr:FullTextSearch> + <xr:ChoiceParameterLinks /> + <xr:FillValue xsi:nil="true" /> + <xr:Mask /> + <xr:ChoiceParameters /> + </xr:StandardAttribute> + <xr:StandardAttribute name="Description"> + <xr:LinkByType /> + <xr:FillChecking>DontCheck</xr:FillChecking> + <xr:MultiLine>false</xr:MultiLine> + <xr:FillFromFillingValue>false</xr:FillFromFillingValue> + <xr:CreateOnInput>Auto</xr:CreateOnInput> + <xr:MaxValue xsi:nil="true" /> + <xr:ToolTip /> + <xr:ExtendedEdit>false</xr:ExtendedEdit> + <xr:Format /> + <xr:ChoiceForm /> + <xr:QuickChoice>Auto</xr:QuickChoice> + <xr:ChoiceHistoryOnInput>Auto</xr:ChoiceHistoryOnInput> + <xr:EditFormat /> + <xr:PasswordMode>false</xr:PasswordMode> + <xr:DataHistory>Use</xr:DataHistory> + <xr:MarkNegatives>false</xr:MarkNegatives> + <xr:MinValue xsi:nil="true" /> + <xr:Synonym /> + <xr:Comment /> + <xr:FullTextSearch>Use</xr:FullTextSearch> + <xr:ChoiceParameterLinks /> + <xr:FillValue xsi:nil="true" /> + <xr:Mask /> + <xr:ChoiceParameters /> + </xr:StandardAttribute> + <xr:StandardAttribute name="Code"> + <xr:LinkByType /> + <xr:FillChecking>DontCheck</xr:FillChecking> + <xr:MultiLine>false</xr:MultiLine> + <xr:FillFromFillingValue>false</xr:FillFromFillingValue> + <xr:CreateOnInput>Auto</xr:CreateOnInput> + <xr:MaxValue xsi:nil="true" /> + <xr:ToolTip /> + <xr:ExtendedEdit>false</xr:ExtendedEdit> + <xr:Format /> + <xr:ChoiceForm /> + <xr:QuickChoice>Auto</xr:QuickChoice> + <xr:ChoiceHistoryOnInput>Auto</xr:ChoiceHistoryOnInput> + <xr:EditFormat /> + <xr:PasswordMode>false</xr:PasswordMode> + <xr:DataHistory>Use</xr:DataHistory> + <xr:MarkNegatives>false</xr:MarkNegatives> + <xr:MinValue xsi:nil="true" /> + <xr:Synonym /> + <xr:Comment /> + <xr:FullTextSearch>Use</xr:FullTextSearch> + <xr:ChoiceParameterLinks /> + <xr:FillValue xsi:nil="true" /> + <xr:Mask /> + <xr:ChoiceParameters /> + </xr:StandardAttribute> + </StandardAttributes> + <Characteristics /> + <PredefinedDataUpdate>Auto</PredefinedDataUpdate> + <EditType>InDialog</EditType> + <QuickChoice>false</QuickChoice> + <ChoiceMode>BothWays</ChoiceMode> + <InputByString> + <xr:Field>Catalog.Товары.StandardAttribute.Description</xr:Field> + <xr:Field>Catalog.Товары.StandardAttribute.Code</xr:Field> + </InputByString> + <SearchStringModeOnInputByString>Begin</SearchStringModeOnInputByString> + <FullTextSearchOnInputByString>DontUse</FullTextSearchOnInputByString> + <ChoiceDataGetModeOnInputByString>Directly</ChoiceDataGetModeOnInputByString> + <DefaultObjectForm /> + <DefaultFolderForm /> + <DefaultListForm>Catalog.Товары.Form.ФормаСписка</DefaultListForm> + <DefaultChoiceForm /> + <DefaultFolderChoiceForm /> + <AuxiliaryObjectForm /> + <AuxiliaryFolderForm /> + <AuxiliaryListForm /> + <AuxiliaryChoiceForm /> + <AuxiliaryFolderChoiceForm /> + <IncludeHelpInContents>false</IncludeHelpInContents> + <BasedOn /> + <DataLockFields /> + <DataLockControlMode>Automatic</DataLockControlMode> + <FullTextSearch>Use</FullTextSearch> + <ObjectPresentation /> + <ExtendedObjectPresentation /> + <ListPresentation /> + <ExtendedListPresentation /> + <Explanation /> + <CreateOnInput>DontUse</CreateOnInput> + <ChoiceHistoryOnInput>Auto</ChoiceHistoryOnInput> + <DataHistory>DontUse</DataHistory> + <UpdateDataHistoryImmediatelyAfterWrite>false</UpdateDataHistoryImmediatelyAfterWrite> + <ExecuteAfterWriteDataHistoryVersionProcessing>false</ExecuteAfterWriteDataHistoryVersionProcessing> + </Properties> + <ChildObjects> + <Attribute uuid="UUID-012"> + <Properties> + <Name>Артикул</Name> + <Synonym> + <v8:item> + <v8:lang>ru</v8:lang> + <v8:content>Артикул</v8:content> + </v8:item> + </Synonym> + <Comment /> + <Type> + <v8:Type>xs:string</v8:Type> + <v8:StringQualifiers> + <v8:Length>25</v8:Length> + <v8:AllowedLength>Variable</v8:AllowedLength> + </v8:StringQualifiers> + </Type> + <PasswordMode>false</PasswordMode> + <Format /> + <EditFormat /> + <ToolTip /> + <MarkNegatives>false</MarkNegatives> + <Mask /> + <MultiLine>false</MultiLine> + <ExtendedEdit>false</ExtendedEdit> + <MinValue xsi:nil="true" /> + <MaxValue xsi:nil="true" /> + <FillFromFillingValue>false</FillFromFillingValue> + <FillValue xsi:type="xs:string" /> + <FillChecking>DontCheck</FillChecking> + <ChoiceFoldersAndItems>Items</ChoiceFoldersAndItems> + <ChoiceParameterLinks /> + <ChoiceParameters /> + <QuickChoice>Auto</QuickChoice> + <CreateOnInput>Auto</CreateOnInput> + <ChoiceForm /> + <LinkByType /> + <ChoiceHistoryOnInput>Auto</ChoiceHistoryOnInput> + <Use>ForItem</Use> + <Indexing>DontIndex</Indexing> + <FullTextSearch>Use</FullTextSearch> + <DataHistory>Use</DataHistory> + </Properties> + </Attribute> + <Form>ФормаСписка</Form> + </ChildObjects> + </Catalog> +</MetaDataObject> diff --git a/tests/skills/cases/form-compile/snapshots/dynamic-list-parameters/Catalogs/Товары/Ext/ObjectModule.bsl b/tests/skills/cases/form-compile/snapshots/dynamic-list-parameters/Catalogs/Товары/Ext/ObjectModule.bsl new file mode 100644 index 00000000..e69de29b diff --git a/tests/skills/cases/form-compile/snapshots/dynamic-list-parameters/Catalogs/Товары/Forms/ФормаСписка.xml b/tests/skills/cases/form-compile/snapshots/dynamic-list-parameters/Catalogs/Товары/Forms/ФормаСписка.xml new file mode 100644 index 00000000..79ff6a75 --- /dev/null +++ b/tests/skills/cases/form-compile/snapshots/dynamic-list-parameters/Catalogs/Товары/Forms/ФормаСписка.xml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="UTF-8"?> +<MetaDataObject xmlns="http://v8.1c.ru/8.3/MDClasses" xmlns:app="http://v8.1c.ru/8.2/managed-application/core" xmlns:cfg="http://v8.1c.ru/8.1/data/enterprise/current-config" xmlns:cmi="http://v8.1c.ru/8.2/managed-application/cmi" xmlns:ent="http://v8.1c.ru/8.1/data/enterprise" xmlns:lf="http://v8.1c.ru/8.2/managed-application/logform" xmlns:style="http://v8.1c.ru/8.1/data/ui/style" xmlns:sys="http://v8.1c.ru/8.1/data/ui/fonts/system" xmlns:v8="http://v8.1c.ru/8.1/data/core" xmlns:v8ui="http://v8.1c.ru/8.1/data/ui" xmlns:web="http://v8.1c.ru/8.1/data/ui/colors/web" xmlns:win="http://v8.1c.ru/8.1/data/ui/colors/windows" xmlns:xen="http://v8.1c.ru/8.3/xcf/enums" xmlns:xpr="http://v8.1c.ru/8.3/xcf/predef" xmlns:xr="http://v8.1c.ru/8.3/xcf/readable" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.17"> + <Form uuid="UUID-001"> + <Properties> + <Name>ФормаСписка</Name> + <Synonym> + <v8:item> + <v8:lang>ru</v8:lang> + <v8:content>ФормаСписка</v8:content> + </v8:item> + </Synonym> + <Comment/> + <FormType>Managed</FormType> + <IncludeHelpInContents>false</IncludeHelpInContents> + <UsePurposes> + <v8:Value xsi:type="app:ApplicationUsePurpose">PlatformApplication</v8:Value> + <v8:Value xsi:type="app:ApplicationUsePurpose">MobilePlatformApplication</v8:Value> + </UsePurposes> + </Properties> + </Form> +</MetaDataObject> \ No newline at end of file diff --git a/tests/skills/cases/form-compile/snapshots/dynamic-list-parameters/Catalogs/Товары/Forms/ФормаСписка/Ext/Form.xml b/tests/skills/cases/form-compile/snapshots/dynamic-list-parameters/Catalogs/Товары/Forms/ФормаСписка/Ext/Form.xml new file mode 100644 index 00000000..b1397e07 --- /dev/null +++ b/tests/skills/cases/form-compile/snapshots/dynamic-list-parameters/Catalogs/Товары/Forms/ФормаСписка/Ext/Form.xml @@ -0,0 +1,208 @@ +<?xml version="1.0" encoding="UTF-8"?> +<Form xmlns="http://v8.1c.ru/8.3/xcf/logform" xmlns:app="http://v8.1c.ru/8.2/managed-application/core" xmlns:cfg="http://v8.1c.ru/8.1/data/enterprise/current-config" xmlns:dcscor="http://v8.1c.ru/8.1/data-composition-system/core" xmlns:dcssch="http://v8.1c.ru/8.1/data-composition-system/schema" xmlns:dcsset="http://v8.1c.ru/8.1/data-composition-system/settings" xmlns:ent="http://v8.1c.ru/8.1/data/enterprise" xmlns:lf="http://v8.1c.ru/8.2/managed-application/logform" xmlns:style="http://v8.1c.ru/8.1/data/ui/style" xmlns:sys="http://v8.1c.ru/8.1/data/ui/fonts/system" xmlns:v8="http://v8.1c.ru/8.1/data/core" xmlns:v8ui="http://v8.1c.ru/8.1/data/ui" xmlns:web="http://v8.1c.ru/8.1/data/ui/colors/web" xmlns:win="http://v8.1c.ru/8.1/data/ui/colors/windows" xmlns:xr="http://v8.1c.ru/8.3/xcf/readable" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.17"> + <Title> + <v8:item> + <v8:lang>ru</v8:lang> + <v8:content>Товары</v8:content> + </v8:item> + + false + + + + Список + None + Список.DefaultPicture + false + 60 + + Custom + 0001-01-01T00:00:00 + 0001-01-01T00:00:00 + + Items + false + + true + false + Auto + true + + + false + + + + + Список + SearchStringRepresentation + + + + + + + Список + ViewStatusRepresentation + + + + + + + Список + SearchControl + + + + + + + Список.Code + + + + + Список.Description + + + + +
+
+ + + + cfg:DynamicList + + true + + true + true + ВЫБРАТЬ + Товары.Ссылка КАК Ссылка, + Товары.Код КАК Код, + Товары.Наименование КАК Наименование, + Товары.Артикул КАК Артикул +ИЗ + Справочник.Товары КАК Товары +ГДЕ + Товары.Артикул = &Артикул + И Товары.Наименование ПОДОБНО &Маска + + Артикул + + + ru + Артикул + + + + true + + + Маска + + + ru + Маска + + + + xs:string + + 0 + Variable + + + % + true + + + ВидЦен + + + ru + Вид цен + + + true + true + + + Период + + + ru + Период + + + + xs:dateTime + + DateTime + + + + false + + + Порог + + + ru + Порог округления + + + + xs:decimal + + 10 + 2 + Any + + + 0 + true + + + + + ru + Нет + + + + + 1 + + + ru + Один + + + + true + Always + + Catalog.Товары + + + Normal + UUID-001 + + + Normal + UUID-002 + + + Normal + UUID-003 + + Normal + UUID-004 + + + + + diff --git a/tests/skills/cases/form-compile/snapshots/dynamic-list-parameters/Catalogs/Товары/Forms/ФормаСписка/Ext/Form/Module.bsl b/tests/skills/cases/form-compile/snapshots/dynamic-list-parameters/Catalogs/Товары/Forms/ФормаСписка/Ext/Form/Module.bsl new file mode 100644 index 00000000..8ead4cec --- /dev/null +++ b/tests/skills/cases/form-compile/snapshots/dynamic-list-parameters/Catalogs/Товары/Forms/ФормаСписка/Ext/Form/Module.bsl @@ -0,0 +1,19 @@ +#Область ОбработчикиСобытийФормы + +#КонецОбласти + +#Область ОбработчикиСобытийЭлементовФормы + +#КонецОбласти + +#Область ОбработчикиКомандФормы + +#КонецОбласти + +#Область ОбработчикиОповещений + +#КонецОбласти + +#Область СлужебныеПроцедурыИФункции + +#КонецОбласти \ No newline at end of file diff --git a/tests/skills/cases/form-compile/snapshots/dynamic-list-parameters/Configuration.xml b/tests/skills/cases/form-compile/snapshots/dynamic-list-parameters/Configuration.xml new file mode 100644 index 00000000..5405b1b5 --- /dev/null +++ b/tests/skills/cases/form-compile/snapshots/dynamic-list-parameters/Configuration.xml @@ -0,0 +1,252 @@ + + + + + + UUID-002 + UUID-003 + + + UUID-004 + UUID-005 + + + UUID-006 + UUID-007 + + + UUID-008 + UUID-009 + + + UUID-010 + UUID-011 + + + UUID-012 + UUID-013 + + + UUID-014 + UUID-015 + + + + TestConfig + + + ru + TestConfig + + + + + Version8_3_24 + ManagedApplication + + PlatformApplication + + Russian + + + + + false + false + false + + + + + + + + + + + + + + + + + + + + + + Biometrics + true + + + Location + false + + + BackgroundLocation + false + + + BluetoothPrinters + false + + + WiFiPrinters + false + + + Contacts + false + + + Calendars + false + + + PushNotifications + false + + + LocalNotifications + false + + + InAppPurchases + false + + + PersonalComputerFileExchange + false + + + Ads + false + + + NumberDialing + false + + + CallProcessing + false + + + CallLog + false + + + AutoSendSMS + false + + + ReceiveSMS + false + + + SMSLog + false + + + Camera + false + + + Microphone + false + + + MusicLibrary + false + + + PictureAndVideoLibraries + false + + + AudioPlaybackAndVibration + false + + + BackgroundAudioPlaybackAndVibration + false + + + InstallPackages + false + + + OSBackup + true + + + ApplicationUsageStatistics + false + + + BarcodeScanning + false + + + BackgroundAudioRecording + false + + + AllFilesAccess + false + + + Videoconferences + false + + + NFC + false + + + DocumentScanning + false + + + SpeechToText + false + + + Geofences + false + + + IncomingShareRequests + false + + + AllIncomingShareRequestsTypesProcessing + false + + + + + + Normal + + + Language.Русский + + + + + + Managed + NotAutoFree + DontUse + DontUse + TaxiEnableVersion8_2 + DontUse + Version8_3_24 + + + + Русский + Товары + + + \ No newline at end of file diff --git a/tests/skills/cases/form-compile/snapshots/dynamic-list-parameters/Ext/ClientApplicationInterface.xml b/tests/skills/cases/form-compile/snapshots/dynamic-list-parameters/Ext/ClientApplicationInterface.xml new file mode 100644 index 00000000..3c1161b2 --- /dev/null +++ b/tests/skills/cases/form-compile/snapshots/dynamic-list-parameters/Ext/ClientApplicationInterface.xml @@ -0,0 +1,18 @@ + + + + + UUID-002 + + + + + UUID-004 + + + + + + + + \ No newline at end of file diff --git a/tests/skills/cases/form-compile/snapshots/dynamic-list-parameters/Languages/Русский.xml b/tests/skills/cases/form-compile/snapshots/dynamic-list-parameters/Languages/Русский.xml new file mode 100644 index 00000000..37c60d78 --- /dev/null +++ b/tests/skills/cases/form-compile/snapshots/dynamic-list-parameters/Languages/Русский.xml @@ -0,0 +1,16 @@ + + + + + Русский + + + ru + Русский + + + + ru + + + \ No newline at end of file