mirror of
https://github.com/Nikolay-Shirokov/cc-1c-skills.git
synced 2026-06-15 02:14:57 +03:00
feat(form-decompile,form-compile): вычисляемые поля + valueType поля DataSet динсписка (кластер C)
Две части пробела DataSet динамического списка:
1. Field valueType (63 формы/54). Поле набора <Field DataSetFieldField> может нести
<dcssch:valueType> (тип значения; кастомные/вычисляемые поля). Декомпилятор ловил
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): свойства обычного <Field> — presentationExpression + appearance
(формат/цвет поля) — отдельный подкластер.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -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 динамического списка (<CalculatedField>) ===
|
||||
# Зеркало 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<CalculatedField>"
|
||||
X "$ci<dcssch:dataPath>$(Esc-Xml $dataPath)</dcssch:dataPath>"
|
||||
X "$ci<dcssch:expression>$(Esc-Xml $expression)</dcssch:expression>"
|
||||
if ($title) { Emit-MLText -tag 'dcssch:title' -text $title -indent $ci -xsiType 'v8:LocalStringType' }
|
||||
if ($restrict.Count -gt 0) {
|
||||
X "$ci<dcssch:useRestriction>"
|
||||
foreach ($r in @('field','condition','group','order')) { if ($restrict -contains $r) { X "$ci`t<dcssch:$r>true</dcssch:$r>" } }
|
||||
X "$ci</dcssch:useRestriction>"
|
||||
}
|
||||
if ($pres) { X "$ci<dcssch:presentationExpression>$(Esc-Xml "$pres")</dcssch:presentationExpression>" }
|
||||
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<dcssch:orderExpression>"
|
||||
X "$ci`t<expression xmlns=`"$($script:dcsCommonNs)`">$(Esc-Xml $exprV)</expression>"
|
||||
X "$ci`t<orderType xmlns=`"$($script:dcsCommonNs)`">$oType</orderType>"
|
||||
X "$ci`t<autoOrder xmlns=`"$($script:dcsCommonNs)`">$auto</autoOrder>"
|
||||
X "$ci</dcssch:orderExpression>"
|
||||
}
|
||||
}
|
||||
if ($typeStr) { Emit-DLValueType -typeStr $typeStr -indent $ci }
|
||||
X "$indent</CalculatedField>"
|
||||
}
|
||||
}
|
||||
|
||||
# --- 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</dcssch:title>"
|
||||
}
|
||||
# valueType поля набора (тип значения; вычисляемые/кастомные поля)
|
||||
if ($fld.valueType) { Emit-DLValueType -typeStr "$($fld.valueType)" -indent "$si`t" }
|
||||
X "$si</Field>"
|
||||
}
|
||||
}
|
||||
# Вычисляемые поля DataSet (<CalculatedField>) — после 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<MainTable>$(Normalize-MetaTypeRef "$($st.mainTable)")</MainTable>" }
|
||||
|
||||
@@ -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 динамического списка (<CalculatedField>) ===
|
||||
# Зеркало 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}<CalculatedField>')
|
||||
lines.append(f'{ci}<dcssch:dataPath>{esc_xml(data_path)}</dcssch:dataPath>')
|
||||
lines.append(f'{ci}<dcssch:expression>{esc_xml(expression)}</dcssch:expression>')
|
||||
if title:
|
||||
emit_mltext(lines, ci, 'dcssch:title', title, xsi_type='v8:LocalStringType')
|
||||
if restrict:
|
||||
lines.append(f'{ci}<dcssch:useRestriction>')
|
||||
for r in ('field', 'condition', 'group', 'order'):
|
||||
if r in restrict:
|
||||
lines.append(f'{ci}\t<dcssch:{r}>true</dcssch:{r}>')
|
||||
lines.append(f'{ci}</dcssch:useRestriction>')
|
||||
if pres_expr:
|
||||
lines.append(f'{ci}<dcssch:presentationExpression>{esc_xml(str(pres_expr))}</dcssch:presentationExpression>')
|
||||
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}<dcssch:orderExpression>')
|
||||
lines.append(f'{ci}\t<expression xmlns="{_DCS_COMMON_NS}">{esc_xml(expr_v)}</expression>')
|
||||
lines.append(f'{ci}\t<orderType xmlns="{_DCS_COMMON_NS}">{otype}</orderType>')
|
||||
lines.append(f'{ci}\t<autoOrder xmlns="{_DCS_COMMON_NS}">{auto}</autoOrder>')
|
||||
lines.append(f'{ci}</dcssch:orderExpression>')
|
||||
if type_str:
|
||||
emit_dl_value_type(lines, type_str, ci)
|
||||
lines.append(f'{indent}</CalculatedField>')
|
||||
|
||||
|
||||
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<dcssch:title xsi:type="v8:LocalStringType">')
|
||||
emit_ml_items(lines, f'{si}\t\t', fld['title'])
|
||||
lines.append(f'{si}\t</dcssch:title>')
|
||||
# valueType поля набора (тип значения; вычисляемые/кастомные поля)
|
||||
if fld.get('valueType'):
|
||||
emit_dl_value_type(lines, fld['valueType'], f'{si}\t')
|
||||
lines.append(f'{si}</Field>')
|
||||
# Вычисляемые поля DataSet (<CalculatedField>) — после 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'):
|
||||
|
||||
@@ -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 динамического списка (<CalculatedField>) → объектная модель.
|
||||
# Зеркало эмиссии 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-параметры динамического списка (<Parameter> под <Settings>) — зеркало эмиссии
|
||||
# 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 (<CalculatedField>) — после 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-параметры дин-списка (прямые <Parameter> под Settings, не в ListSettings)
|
||||
$paramNodes = @($setNode.SelectNodes("lf:Parameter", $ns))
|
||||
if ($paramNodes.Count -gt 0) {
|
||||
|
||||
+24
-1
@@ -940,7 +940,8 @@ Forgiving-синонимы типа: XML-имя (`SpreadSheetDocumentField`) и
|
||||
| `query` | string | Текст запроса (`ManualQuery=true`). Поддерживает `@file.sql` (путь относительно JSON) |
|
||||
| `dynamicDataRead` | bool | Динамическое считывание. **Умолчание `true`** — указывать только для отключения (`false`) |
|
||||
| `autoFillAvailableFields` | bool | Автозаполнение доступных полей (`<AutoFillAvailableFields>`). **Умолчание `true`** — указывать только для отключения (`false`; тогда поля берутся из явного запроса, не авто). Эмитится первым в `<Settings>` |
|
||||
| `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: `<CalculatedField>` в 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). Кратко:
|
||||
|
||||
@@ -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": "Код товара" },
|
||||
|
||||
+44
@@ -100,6 +100,50 @@
|
||||
<Settings xsi:type="DynamicList">
|
||||
<ManualQuery>false</ManualQuery>
|
||||
<DynamicDataRead>true</DynamicDataRead>
|
||||
<CalculatedField>
|
||||
<dcssch:dataPath>Метка</dcssch:dataPath>
|
||||
<dcssch:expression>Code + " " + Description</dcssch:expression>
|
||||
<dcssch:title xsi:type="v8:LocalStringType">
|
||||
<v8:item>
|
||||
<v8:lang>ru</v8:lang>
|
||||
<v8:content>Метка строки</v8:content>
|
||||
</v8:item>
|
||||
</dcssch:title>
|
||||
<dcssch:useRestriction>
|
||||
<dcssch:condition>true</dcssch:condition>
|
||||
<dcssch:group>true</dcssch:group>
|
||||
</dcssch:useRestriction>
|
||||
<dcssch:valueType>
|
||||
<v8:Type>xs:string</v8:Type>
|
||||
<v8:StringQualifiers>
|
||||
<v8:Length>0</v8:Length>
|
||||
<v8:AllowedLength>Variable</v8:AllowedLength>
|
||||
</v8:StringQualifiers>
|
||||
</dcssch:valueType>
|
||||
</CalculatedField>
|
||||
<CalculatedField>
|
||||
<dcssch:dataPath>Сорт</dcssch:dataPath>
|
||||
<dcssch:expression>Code</dcssch:expression>
|
||||
<dcssch:title xsi:type="v8:LocalStringType">
|
||||
<v8:item>
|
||||
<v8:lang>ru</v8:lang>
|
||||
<v8:content>Сорт</v8:content>
|
||||
</v8:item>
|
||||
</dcssch:title>
|
||||
<dcssch:presentationExpression>Code</dcssch:presentationExpression>
|
||||
<dcssch:orderExpression>
|
||||
<expression xmlns="http://v8.1c.ru/8.1/data-composition-system/common">Code</expression>
|
||||
<orderType xmlns="http://v8.1c.ru/8.1/data-composition-system/common">Asc</orderType>
|
||||
<autoOrder xmlns="http://v8.1c.ru/8.1/data-composition-system/common">false</autoOrder>
|
||||
</dcssch:orderExpression>
|
||||
<dcssch:valueType>
|
||||
<v8:Type>xs:string</v8:Type>
|
||||
<v8:StringQualifiers>
|
||||
<v8:Length>10</v8:Length>
|
||||
<v8:AllowedLength>Variable</v8:AllowedLength>
|
||||
</v8:StringQualifiers>
|
||||
</dcssch:valueType>
|
||||
</CalculatedField>
|
||||
<Parameter>
|
||||
<dcssch:name>ВыборТовара</dcssch:name>
|
||||
<dcssch:title xsi:type="v8:LocalStringType">
|
||||
|
||||
Reference in New Issue
Block a user