From 73b07a6fbc934d1907dbf82f9f73cd6672af0c62 Mon Sep 17 00:00:00 2001 From: Nick Shirokov Date: Fri, 12 Jun 2026 19:38:14 +0300 Subject: [PATCH] =?UTF-8?q?feat(form-decompile,form-compile):=20=D0=B2?= =?UTF-8?q?=D1=8B=D1=87=D0=B8=D1=81=D0=BB=D1=8F=D0=B5=D0=BC=D1=8B=D0=B5=20?= =?UTF-8?q?=D0=BF=D0=BE=D0=BB=D1=8F=20+=20valueType=20=D0=BF=D0=BE=D0=BB?= =?UTF-8?q?=D1=8F=20DataSet=20=D0=B4=D0=B8=D0=BD=D1=81=D0=BF=D0=B8=D1=81?= =?UTF-8?q?=D0=BA=D0=B0=20(=D0=BA=D0=BB=D0=B0=D1=81=D1=82=D0=B5=D1=80=20C)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Две части пробела DataSet динамического списка: 1. Field valueType (63 формы/54). Поле набора может нести (тип значения; кастомные/вычисляемые поля). Декомпилятор ловил field/dataPath/title/nested, теперь и valueType (переиспользует Decompile-Type); компилятор эмитит после title через существующий emit_dl_value_type. 0 потерь на выборке. 2. CalculatedField (6 форм, редкое). Новый ключ settings.calculatedFields — зеркало skd: shorthand "Имя [Заголовок]: тип = Выражение #noField #noFilter #noGroup #noOrder" (порт Parse-CalcShorthand) или объект. Форм-специфика: dcssch:-теги, presentationExpression, orderExpression* (структура {expression,orderType,autoOrder} в namespace dcscommon с локальным xmlns), useRestriction{field,condition,group,order}. Эмиттер форм-специфичный (skd использует dcscom:-префикс и не имеет pres/orderExpression). Позиция в DataSet — после Field*, до Parameter*. Декомпилятор Build-CalcField (объектная форма для точного round-trip). Выборка calc-форм: calc-теги ушли из диффов (3/6 match, остаток — отдельный field appearance/presentationExpression). Кейс dynamic-list-form (+grouping +calculatedFields: shorthand с флагами + объект с presentationExpression/orderExpression/valueType) сертифицирован загрузкой в 1С (порядок детей CalculatedField подтверждён платформой). Регресс 43/43 (ps1+py). ps1==py байт-в-байт (сверено на кейсе). Фикс по пути: ps1 Parse-CalcShorthand — `\b` в generator-heredoc превратился в backspace 0x08 → #-флаги не парсились (py был верен); поймано прямой сверкой вывода ps1 vs py. C-остаток (в BACKLOG): свойства обычного — presentationExpression + appearance (формат/цвет поля) — отдельный подкластер. Co-Authored-By: Claude Opus 4.8 (1M context) --- .../form-compile/scripts/form-compile.ps1 | 80 +++++++++++++++- .../form-compile/scripts/form-compile.py | 92 ++++++++++++++++++- .../form-decompile/scripts/form-decompile.ps1 | 50 +++++++++- docs/form-dsl-spec.md | 25 ++++- .../cases/form-compile/dynamic-list-form.json | 5 + .../Товары/Forms/ФормаСписка/Ext/Form.xml | 44 +++++++++ 6 files changed, 292 insertions(+), 4 deletions(-) diff --git a/.claude/skills/form-compile/scripts/form-compile.ps1 b/.claude/skills/form-compile/scripts/form-compile.ps1 index b79c0a87..5d9aa810 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.139 — Compile 1C managed form from JSON or object metadata +# form-compile v1.140 — Compile 1C managed form from JSON or object metadata # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills param( [string]$JsonPath, @@ -2067,6 +2067,80 @@ function Emit-ListGrouping { Emit-ListGroupingLevels $levels 0 $indent } +# === Вычисляемые поля DataSet динамического списка () === +# Зеркало skd: shorthand "Имя [Заголовок]: тип = Выражение #noField #noFilter #noGroup #noOrder" +# или объект. Форм-специфика: dcssch:-теги + presentationExpression/orderExpression (dcscommon ns). +$script:calcRestrictMap = @{ 'noField'='field'; 'noFilter'='condition'; 'noCondition'='condition'; 'noGroup'='group'; 'noOrder'='order' } +$script:dcsCommonNs = 'http://v8.1c.ru/8.1/data-composition-system/common' + +function Parse-CalcShorthand { + param([string]$s) + $restrict = @() + foreach ($m in [regex]::Matches($s, '#(noField|noFilter|noCondition|noGroup|noOrder)\b')) { $restrict += $m.Groups[1].Value } + $s = [regex]::Replace($s, '\s*#(noField|noFilter|noCondition|noGroup|noOrder)\b', '') + $eq = $s.IndexOf('=') + if ($eq -gt 0) { $lhs = $s.Substring(0, $eq); $rhs = $s.Substring($eq + 1).Trim() } else { $lhs = $s; $rhs = '' } + $title = '' + if ($lhs -match '\[([^\]]+)\]') { $title = $Matches[1]; $lhs = $lhs -replace '\s*\[[^\]]+\]', '' } + $lhs = $lhs.Trim() + $type = ''; $dataPath = $lhs + if ($lhs.Contains(':')) { $parts = $lhs -split ':', 2; $dataPath = $parts[0].Trim(); $type = Resolve-TypeStr ($parts[1].Trim()) } + return @{ dataPath = $dataPath; expression = $rhs; type = $type; title = $title; restrict = $restrict } +} + +function Emit-CalcFields { + param($calcFields, [string]$indent) + if (-not $calcFields) { return } + foreach ($cf in $calcFields) { + $pres = $null; $orderExpr = $null; $restrict = @() + if ($cf -is [string]) { + $p = Parse-CalcShorthand $cf + $dataPath = "$($p.dataPath)"; $expression = "$($p.expression)"; $title = $p.title; $typeStr = "$($p.type)" + foreach ($r in $p.restrict) { if ($script:calcRestrictMap[$r]) { $restrict += $script:calcRestrictMap[$r] } } + } else { + $dataPath = if ($cf.dataPath) { "$($cf.dataPath)" } elseif ($cf.field) { "$($cf.field)" } else { "$($cf.name)" } + $expression = "$($cf.expression)" + $title = $cf.title + $typeStr = if ($cf.valueType) { "$($cf.valueType)" } elseif ($cf.type) { "$($cf.type)" } else { '' } + $ur = if ($cf.useRestriction) { $cf.useRestriction } elseif ($cf.restrict) { $cf.restrict } else { $null } + if ($ur -is [System.Management.Automation.PSCustomObject] -or $ur -is [hashtable]) { + foreach ($k in 'field','condition','group','order') { if ($ur.$k -eq $true) { $restrict += $k } } + } elseif ($ur -is [string]) { + foreach ($tok in ($ur -split '\s+')) { $t = $tok.Trim().TrimStart('#'); if ($t) { $restrict += $(if ($script:calcRestrictMap[$t]) { $script:calcRestrictMap[$t] } else { $t }) } } + } elseif ($ur) { + foreach ($r in $ur) { $rr = "$r"; $restrict += $(if ($script:calcRestrictMap[$rr]) { $script:calcRestrictMap[$rr] } else { $rr }) } + } + $pres = $cf.presentationExpression + $orderExpr = $cf.orderExpression + } + $ci = "$indent`t" + X "$indent" + X "$ci$(Esc-Xml $dataPath)" + X "$ci$(Esc-Xml $expression)" + if ($title) { Emit-MLText -tag 'dcssch:title' -text $title -indent $ci -xsiType 'v8:LocalStringType' } + if ($restrict.Count -gt 0) { + X "$ci" + foreach ($r in @('field','condition','group','order')) { if ($restrict -contains $r) { X "$ci`ttrue" } } + X "$ci" + } + if ($pres) { X "$ci$(Esc-Xml "$pres")" } + if ($orderExpr) { + $oeList = if ($orderExpr -is [System.Collections.IList]) { $orderExpr } else { @($orderExpr) } + foreach ($oe in $oeList) { + if ($oe -is [string]) { $exprV = $oe; $oType = 'Asc'; $auto = 'false' } + else { $exprV = "$($oe.expression)"; $oType = if ($oe.orderType) { "$($oe.orderType)" } else { 'Asc' }; $auto = if ($oe.autoOrder) { 'true' } else { 'false' } } + X "$ci" + X "$ci`t$(Esc-Xml $exprV)" + X "$ci`t$oType" + X "$ci`t$auto" + X "$ci" + } + } + if ($typeStr) { Emit-DLValueType -typeStr $typeStr -indent $ci } + X "$indent" + } +} + # --- 5. Type emitter --- $script:formTypeSynonyms = New-Object System.Collections.Hashtable @@ -5552,9 +5626,13 @@ function Emit-Attributes { Emit-MLItems -val $fld.title -indent "$si`t`t" X "$si`t" } + # valueType поля набора (тип значения; вычисляемые/кастомные поля) + if ($fld.valueType) { Emit-DLValueType -typeStr "$($fld.valueType)" -indent "$si`t" } X "$si" } } + # Вычисляемые поля DataSet () — после Field*, до Parameter*. + Emit-CalcFields -calcFields $st.calculatedFields -indent $si # Schema-параметры дин-списка (DataCompositionSchemaParameter) — после Field*, до MainTable. Emit-DLParameters -params $st.parameters -indent $si if ($st.mainTable) { X "$si$(Normalize-MetaTypeRef "$($st.mainTable)")" } diff --git a/.claude/skills/form-compile/scripts/form-compile.py b/.claude/skills/form-compile/scripts/form-compile.py index 6642700f..8d42caf0 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.139 — Compile 1C managed form from JSON or object metadata +# form-compile v1.140 — Compile 1C managed form from JSON or object metadata # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse import copy @@ -1747,6 +1747,91 @@ def emit_list_grouping(lines, grouping, indent): emit_list_grouping_levels(lines, levels, 0, indent) +# === Вычисляемые поля DataSet динамического списка () === +# Зеркало skd calculatedFields: shorthand "Имя [Заголовок]: тип = Выражение #noField #noFilter +# #noGroup #noOrder" или объект. Форм-специфика: dcssch:-теги + presentationExpression/orderExpression. +_CALC_RESTRICT_MAP = {'noField': 'field', 'noFilter': 'condition', 'noCondition': 'condition', + 'noGroup': 'group', 'noOrder': 'order'} +_DCS_COMMON_NS = 'http://v8.1c.ru/8.1/data-composition-system/common' + + +def parse_calc_shorthand(s): + restrict = re.findall(r'#(noField|noFilter|noCondition|noGroup|noOrder)\b', s) + s = re.sub(r'\s*#(?:noField|noFilter|noCondition|noGroup|noOrder)\b', '', s) + eq = s.find('=') + lhs, rhs = (s[:eq], s[eq + 1:].strip()) if eq > 0 else (s, '') + title = '' + m = re.search(r'\[([^\]]+)\]', lhs) + if m: + title = m.group(1) + lhs = re.sub(r'\s*\[[^\]]+\]', '', lhs) + lhs = lhs.strip() + typ, data_path = '', lhs + if ':' in lhs: + data_path, t = lhs.split(':', 1) + data_path, typ = data_path.strip(), resolve_type_str(t.strip()) + return {'dataPath': data_path, 'expression': rhs, 'type': typ, 'title': title, 'restrict': restrict} + + +def emit_calc_fields(lines, calc_fields, indent): + if not calc_fields: + return + for cf in calc_fields: + if isinstance(cf, str): + p = parse_calc_shorthand(cf) + data_path, expression, title = p['dataPath'], p['expression'], p['title'] + type_str = p['type'] + restrict = [_CALC_RESTRICT_MAP[r] for r in p['restrict'] if r in _CALC_RESTRICT_MAP] + pres_expr = order_expr = None + else: + data_path = str(cf.get('dataPath') or cf.get('field') or cf.get('name', '')) + expression = str(cf.get('expression', '')) + title = cf.get('title') + type_str = cf.get('valueType') or cf.get('type') + type_str = str(type_str) if type_str else None + ur = cf.get('useRestriction') or cf.get('restrict') + if isinstance(ur, dict): + restrict = [k for k in ('field', 'condition', 'group', 'order') if ur.get(k)] + elif isinstance(ur, str): + restrict = [_CALC_RESTRICT_MAP.get(t.strip().lstrip('#'), t.strip().lstrip('#')) for t in ur.split() if t.strip()] + elif isinstance(ur, list): + restrict = [_CALC_RESTRICT_MAP.get(str(r), str(r)) for r in ur] + else: + restrict = [] + pres_expr = cf.get('presentationExpression') + order_expr = cf.get('orderExpression') + ci = f'{indent}\t' + lines.append(f'{indent}') + lines.append(f'{ci}{esc_xml(data_path)}') + lines.append(f'{ci}{esc_xml(expression)}') + if title: + emit_mltext(lines, ci, 'dcssch:title', title, xsi_type='v8:LocalStringType') + if restrict: + lines.append(f'{ci}') + for r in ('field', 'condition', 'group', 'order'): + if r in restrict: + lines.append(f'{ci}\ttrue') + lines.append(f'{ci}') + if pres_expr: + lines.append(f'{ci}{esc_xml(str(pres_expr))}') + if order_expr: + for oe in (order_expr if isinstance(order_expr, list) else [order_expr]): + if isinstance(oe, str): + expr_v, otype, auto = oe, 'Asc', 'false' + else: + expr_v = str(oe.get('expression', '')) + otype = str(oe.get('orderType', 'Asc')) + auto = 'true' if oe.get('autoOrder') else 'false' + lines.append(f'{ci}') + lines.append(f'{ci}\t{esc_xml(expr_v)}') + lines.append(f'{ci}\t{otype}') + lines.append(f'{ci}\t{auto}') + lines.append(f'{ci}') + if type_str: + emit_dl_value_type(lines, type_str, ci) + lines.append(f'{indent}') + + def emit_conditional_appearance(lines, items, indent, block_view_mode=None, block_user_setting_id=None, wrap_tag='dcsset:conditionalAppearance'): has_items = bool(items) and len(items) > 0 has_block_meta = (block_view_mode is not None) or (block_user_setting_id is not None) @@ -5288,7 +5373,12 @@ def emit_attributes(lines, attrs, indent, conditional_appearance=None): lines.append(f'{si}\t') emit_ml_items(lines, f'{si}\t\t', fld['title']) lines.append(f'{si}\t') + # valueType поля набора (тип значения; вычисляемые/кастомные поля) + if fld.get('valueType'): + emit_dl_value_type(lines, fld['valueType'], f'{si}\t') lines.append(f'{si}') + # Вычисляемые поля DataSet () — после Field*, до Parameter*. + emit_calc_fields(lines, s.get('calculatedFields'), si) # Schema-параметры дин-списка (DataCompositionSchemaParameter) — после Field*, до MainTable. emit_dl_parameters(lines, s.get('parameters'), si) if s.get('mainTable'): diff --git a/.claude/skills/form-decompile/scripts/form-decompile.ps1 b/.claude/skills/form-decompile/scripts/form-decompile.ps1 index 1f2d0d74..38decacb 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.112 — Decompile 1C managed Form.xml to JSON DSL (draft) +# form-decompile v0.113 — Decompile 1C managed Form.xml to JSON DSL (draft) # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills # ВНИМАНИЕ: раундтрип не гарантируется. Навык исключён из авто-использования моделью. param( @@ -1246,6 +1246,44 @@ function Decompile-Type { return ($parts -join ' | ') } +# Вычисляемое поле DataSet динамического списка () → объектная модель. +# Зеркало эмиссии form-compile (Emit-CalcFields). Грамматика — как skd calculatedFields, +# + форм-extras presentationExpression/orderExpression (в namespace dcscommon). +function Build-CalcField { + param($cfNode) + $o = [ordered]@{} + $o['dataPath'] = Get-Child $cfNode 'dataPath' + $o['expression'] = Get-Child $cfNode 'expression' + $tn = $cfNode.SelectSingleNode("dcssch:title", $ns) + if ($tn) { $t = Get-LangText $tn; if ($null -ne $t) { $o['title'] = $t } } + $vt = $cfNode.SelectSingleNode("dcssch:valueType", $ns) + if ($vt) { $v = Decompile-Type $vt; if ($v) { $o['valueType'] = $v } } + $ur = $cfNode.SelectSingleNode("dcssch:useRestriction", $ns) + if ($ur) { + $r = [ordered]@{} + foreach ($k in 'field','condition','group','order') { if ((Get-Child $ur $k) -eq 'true') { $r[$k] = $true } } + if ($r.Count -gt 0) { $o['useRestriction'] = $r } + } + $pe = Get-Child $cfNode 'presentationExpression' + if ($null -ne $pe -and $pe -ne '') { $o['presentationExpression'] = $pe } + $oeNodes = @($cfNode.SelectNodes("dcssch:orderExpression", $ns)) + if ($oeNodes.Count -gt 0) { + $oes = New-Object System.Collections.ArrayList + foreach ($oen in $oeNodes) { + $eo = [ordered]@{} + $exprN = $oen.SelectSingleNode("*[local-name()='expression']") + $otN = $oen.SelectSingleNode("*[local-name()='orderType']") + $aoN = $oen.SelectSingleNode("*[local-name()='autoOrder']") + $eo['expression'] = if ($exprN) { $exprN.InnerText } else { '' } + if ($otN -and $otN.InnerText -ne 'Asc') { $eo['orderType'] = $otN.InnerText } + if ($aoN -and $aoN.InnerText -eq 'true') { $eo['autoOrder'] = $true } + [void]$oes.Add($eo) + } + $o['orderExpression'] = @($oes) + } + return $o +} + # Schema-параметры динамического списка ( под ) — зеркало эмиссии # form-compile (Emit-DLParameters). Инверсия контекстных дефолтов: useRestriction=true и # title==Title-FromName опускаем (компилятор восстановит). Сущность = DataCompositionSchemaParameter. @@ -2573,10 +2611,20 @@ if ($attrsNode) { if ($fn.GetAttribute("type", $NS_XSI) -match 'NestedDataSet$') { $fo['nested'] = $true } $ftn = $fn.SelectSingleNode("dcssch:title", $ns) if ($ftn) { $t = Get-LangText $ftn; if ($null -ne $t) { $fo['title'] = $t } } + # valueType поля набора (тип значения; вычисляемые/кастомные поля). Грамматика типа. + $fvt = $fn.SelectSingleNode("dcssch:valueType", $ns) + if ($fvt) { $fvtVal = Decompile-Type $fvt; if ($fvtVal) { $fo['valueType'] = $fvtVal } } [void]$fields.Add($fo) } $so['fields'] = @($fields) } + # Вычисляемые поля DataSet () — после Field*, до Parameter*. + $calcNodes = @($setNode.SelectNodes("lf:CalculatedField", $ns)) + if ($calcNodes.Count -gt 0) { + $cfs = New-Object System.Collections.ArrayList + foreach ($cn in $calcNodes) { [void]$cfs.Add((Build-CalcField $cn)) } + $so['calculatedFields'] = @($cfs) + } # Schema-параметры дин-списка (прямые под Settings, не в ListSettings) $paramNodes = @($setNode.SelectNodes("lf:Parameter", $ns)) if ($paramNodes.Count -gt 0) { diff --git a/docs/form-dsl-spec.md b/docs/form-dsl-spec.md index 088bee5f..9eba688e 100644 --- a/docs/form-dsl-spec.md +++ b/docs/form-dsl-spec.md @@ -940,7 +940,8 @@ Forgiving-синонимы типа: XML-имя (`SpreadSheetDocumentField`) и | `query` | string | Текст запроса (`ManualQuery=true`). Поддерживает `@file.sql` (путь относительно JSON) | | `dynamicDataRead` | bool | Динамическое считывание. **Умолчание `true`** — указывать только для отключения (`false`) | | `autoFillAvailableFields` | bool | Автозаполнение доступных полей (``). **Умолчание `true`** — указывать только для отключения (`false`; тогда поля берутся из явного запроса, не авто). Эмитится первым в `` | -| `fields` | array | Явные поля набора (редко): `{ field, dataPath?, title?, nested? }` — для переопределения заголовка. `nested: true` помечает поле-вложенный набор (`DataSetFieldNestedDataSet` = реквизит табличной части объекта; дефолт — `DataSetFieldField`). Обычно поля выводятся из запроса автоматически | +| `fields` | array | Явные поля набора (редко): `{ field, dataPath?, title?, valueType?, nested? }` — для переопределения заголовка/типа. `valueType` — тип значения поля (грамматика типа). `nested: true` помечает поле-вложенный набор (`DataSetFieldNestedDataSet` = реквизит табличной части объекта; дефолт — `DataSetFieldField`). Обычно поля выводятся из запроса автоматически | +| `calculatedFields` | array | Вычисляемые поля набора (см. ниже) | | `parameters` | array | Параметры схемы запроса (`DataCompositionSchemaParameter`) — см. ниже | | `order` | array | Сортировка списка (см. ниже) | | `filter` | array | Отбор списка (грамматика как в СКД) | @@ -1013,6 +1014,28 @@ Forgiving-синонимы типа: XML-имя (`SpreadSheetDocumentField`) и > Грамматика уровня совпадает с элементом `groupBy`/`groupFields` структуры СКД (см. [skd-dsl-spec.md](skd-dsl-spec.md)); отличие от СКД — плоская модель (нет `children`/`selection`/`order`/детальных записей, которых у группировки списка не бывает). +#### calculatedFields — вычисляемые поля набора + +Поля, вычисляемые выражением (XML: `` в DataSet). Грамматика как в СКД (см. [skd-dsl-spec.md](skd-dsl-spec.md)). + +Shorthand: `"Имя [Заголовок]: тип = Выражение #noField #noFilter #noGroup #noOrder"` — всё кроме имени опционально: +```json +"calculatedFields": [ + "Метка = Code + \" \" + Description", + "Маржа [Маржа, руб]: decimal(15,2) = Цена - Закупка #noFilter #noGroup" +] +``` +Флаги `#noField`/`#noFilter`(=condition)/`#noGroup`/`#noOrder` → ограничения использования (`useRestriction`). + +Объектная форма — для форм-специфичных `presentationExpression` / `orderExpression`: +```json +{ "dataPath": "Сорт", "expression": "Code", "title": "Сорт", "valueType": "string(10)", + "presentationExpression": "Code", + "orderExpression": [ { "expression": "Code", "orderType": "Asc" } ], + "useRestriction": { "condition": true, "group": true } } +``` +`useRestriction` — объект `{ field?, condition?, group?, order? }` (bool) или флаг-строка `"#noFilter #noGroup"`. `orderExpression` — массив `{ expression, orderType?, autoOrder? }`. Тип — `valueType` (синоним `type`). + #### order / filter / conditionalAppearance Грамматика этих ключей идентична настройкам СКД — см. [skd-dsl-spec.md](skd-dsl-spec.md) (разделы filter / order / conditionalAppearance). Кратко: diff --git a/tests/skills/cases/form-compile/dynamic-list-form.json b/tests/skills/cases/form-compile/dynamic-list-form.json index c265c257..9c0ea8af 100644 --- a/tests/skills/cases/form-compile/dynamic-list-form.json +++ b/tests/skills/cases/form-compile/dynamic-list-form.json @@ -21,6 +21,11 @@ "mainTable": "Catalog.Товары", "dynamicDataRead": true, "autoSaveUserSettings": false, "parameters": [ { "name": "ВыборТовара", "type": "CatalogRef.Товары", "valueListAllowed": true, "value": null } ], "grouping": "Description > Code", + "calculatedFields": [ + "Метка [Метка строки]: string = Code + \" \" + Description #noFilter #noGroup", + { "dataPath": "Сорт", "expression": "Code", "title": "Сорт", "valueType": "string(10)", + "presentationExpression": "Code", "orderExpression": [ { "expression": "Code" } ] } + ], "order": [ "Description", "Code desc" ], "filter": [ "Артикул = _ @off @user", "Артикул like %тест%", "Description подобно %abc%", { "field": "Code", "op": "=", "userSettingID": "auto", "userSettingPresentation": "Код товара" }, diff --git a/tests/skills/cases/form-compile/snapshots/dynamic-list-form/Catalogs/Товары/Forms/ФормаСписка/Ext/Form.xml b/tests/skills/cases/form-compile/snapshots/dynamic-list-form/Catalogs/Товары/Forms/ФормаСписка/Ext/Form.xml index 12c6746c..75e1435a 100644 --- a/tests/skills/cases/form-compile/snapshots/dynamic-list-form/Catalogs/Товары/Forms/ФормаСписка/Ext/Form.xml +++ b/tests/skills/cases/form-compile/snapshots/dynamic-list-form/Catalogs/Товары/Forms/ФормаСписка/Ext/Form.xml @@ -100,6 +100,50 @@ false true + + Метка + Code + " " + Description + + + ru + Метка строки + + + + true + true + + + xs:string + + 0 + Variable + + + + + Сорт + Code + + + ru + Сорт + + + Code + + Code + Asc + false + + + xs:string + + 10 + Variable + + + ВыборТовара