feat(skd-compile,skd-edit): calculatedFields — shorthand и объектные синонимы

- skd-compile v1.13: Parse-CalcShorthand теперь понимает "[Title]:type=expr#flags"
  (синхронно со skd-edit). Emit-CalcFields принимает name как синоним
  field/dataPath и строковую форму useRestriction ("#noField #noFilter ...").
- skd-edit v1.11: #restrict парсится по known-names pattern — исключает ложные
  срабатывания на # внутри строковых литералов в выражении.

Закрывает три ловушки из upload/bug-skd-compile-calculated-field-datapath.md,
где модель писала name вместо field и строковый useRestriction по аналогии
с shorthand-флагами.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Nick Shirokov
2026-04-16 20:31:14 +03:00
parent 00fafd4af5
commit 1cea9e794e
9 changed files with 521 additions and 139 deletions
+17
View File
@@ -85,6 +85,23 @@ powershell.exe -NoProfile -File .claude/skills/skd-compile/scripts/skd-compile.p
В объектной форме: `"useRestriction": { "field": true, "condition": true, "group": true, "order": true }` или `"restrict": ["noField", "noFilter"]`.
### Вычисляемые поля (calculatedFields)
Shorthand: `"Имя [Заголовок]: тип = Выражение #noField #noFilter #noGroup #noOrder"` — все части кроме имени опциональны.
```json
"calculatedFields": [
"Маржа = Цена - Закупка",
"Наценка [Наценка, %]: decimal(10,2) = Маржа / Закупка * 100",
"Служебное: string = \"\" #noField #noFilter #noGroup #noOrder"
]
```
Объектная форма — когда нужна `appearance`:
```json
{ "name": "Маржа", "title": "Маржа", "expression": "Цена - Закупка", "type": "decimal(15,2)", "useRestriction": "#noField #noFilter" }
```
### Итоги (shorthand)
```json
@@ -1,4 +1,4 @@
# skd-compile v1.12 — Compile 1C DCS from JSON
# skd-compile v1.13 — Compile 1C DCS from JSON
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
param(
[string]$DefinitionFile,
@@ -367,15 +367,51 @@ function Parse-ParamShorthand {
function Parse-CalcShorthand {
param([string]$s)
# "DataPath = Expression"
$idx = $s.IndexOf('=')
if ($idx -gt 0) {
return @{
dataPath = $s.Substring(0, $idx).Trim()
expression = $s.Substring($idx + 1).Trim()
}
# Pattern: "Name [Title]: type = Expression #noField #noFilter ...".
# - `[Title]` is extracted only from the LHS of '=' so that `[...]` inside
# an expression (e.g. index access) isn't interpreted as a title.
# - `#restrict` flags use a known-names pattern and are extracted globally —
# the docs put them after `=`, and the closed flag set avoids matching
# `#word` that happens to appear inside a string literal.
$restrictPattern = '#(noField|noFilter|noCondition|noGroup|noOrder)\b'
$restrict = @()
foreach ($m in [regex]::Matches($s, $restrictPattern)) {
$restrict += $m.Groups[1].Value
}
$s = [regex]::Replace($s, "\s*$restrictPattern", '')
$eqIdx = $s.IndexOf('=')
if ($eqIdx -gt 0) {
$lhs = $s.Substring(0, $eqIdx)
$rhs = $s.Substring($eqIdx + 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
}
return @{ dataPath = $s.Trim(); expression = "" }
}
# --- 8b. DataParameter shorthand parser ---
@@ -771,64 +807,90 @@ function Emit-DataSetLinks {
# === CalculatedFields ===
function Emit-CalcFields {
if (-not $def.calculatedFields) { return }
$restrictMap = @{
"noField" = "field"; "noFilter" = "condition"; "noCondition" = "condition"
"noGroup" = "group"; "noOrder" = "order"
}
foreach ($cf in $def.calculatedFields) {
# Collect dataPath/expression/title/type/restrict/appearance from either
# shorthand string or object form. Object form accepts dataPath/field/name
# as synonyms; useRestriction/restrict accepts object, array, or flag string.
$title = ""
$typeStr = ""
$restrictTokens = @()
$restrictObj = $null
$appearance = $null
if ($cf -is [string]) {
$parsed = Parse-CalcShorthand $cf
$dataPath = "$($parsed.dataPath)"
$expression = "$($parsed.expression)"
$title = "$($parsed.title)"
$typeStr = "$($parsed.type)"
if ($parsed.restrict) { $restrictTokens = @($parsed.restrict) }
} else {
$dp = if ($cf.dataPath) { "$($cf.dataPath)" } else { "$($cf.field)" }
$parsed = @{
dataPath = $dp
expression = "$($cf.expression)"
}
}
$dataPath = if ($cf.dataPath) { "$($cf.dataPath)" }
elseif ($cf.field) { "$($cf.field)" }
else { "$($cf.name)" }
$expression = "$($cf.expression)"
if ($cf.title) { $title = "$($cf.title)" }
if ($cf.type) { $typeStr = Resolve-TypeStr "$($cf.type)" }
X "`t<calculatedField>"
X "`t`t<dataPath>$(Esc-Xml $parsed.dataPath)</dataPath>"
X "`t`t<expression>$(Esc-Xml $parsed.expression)</expression>"
if ($cf -isnot [string]) {
if ($cf.title) {
Emit-MLText -tag "title" -text "$($cf.title)" -indent "`t`t"
}
if ($cf.type) {
$cfType = Resolve-TypeStr "$($cf.type)"
X "`t`t<valueType>"
Emit-ValueType -typeStr $cfType -indent "`t`t`t"
X "`t`t</valueType>"
}
$restrictVal = if ($cf.restrict) { $cf.restrict } elseif ($cf.useRestriction) { $cf.useRestriction } else { $null }
if ($restrictVal) {
X "`t`t<useRestriction>"
if ($restrictVal -is [System.Management.Automation.PSCustomObject] -or $restrictVal -is [hashtable]) {
# Object form: { "field": true, "condition": true, ... }
foreach ($prop in $restrictVal.PSObject.Properties) {
if ($prop.Value -eq $true) {
X "`t`t`t<$($prop.Name)>true</$($prop.Name)>"
}
$restrictObj = $restrictVal
} elseif ($restrictVal -is [string]) {
# Flag-string form: "#noField #noFilter #noGroup #noOrder" (or without `#`)
foreach ($tok in ($restrictVal -split '\s+')) {
$t = $tok.Trim().TrimStart('#')
if ($t) { $restrictTokens += $t }
}
} else {
# Array form: ["noField", "noFilter", ...]
$restrictMap = @{
"noField" = "field"; "noFilter" = "condition"; "noCondition" = "condition"
"noGroup" = "group"; "noOrder" = "order"
}
foreach ($r in $restrictVal) {
$xmlName = $restrictMap["$r"]
if ($xmlName) { X "`t`t`t<$xmlName>true</$xmlName>" }
foreach ($r in $restrictVal) { $restrictTokens += "$r" }
}
}
if ($cf.appearance) { $appearance = $cf.appearance }
}
X "`t<calculatedField>"
X "`t`t<dataPath>$(Esc-Xml $dataPath)</dataPath>"
X "`t`t<expression>$(Esc-Xml $expression)</expression>"
if ($title) {
Emit-MLText -tag "title" -text $title -indent "`t`t"
}
if ($typeStr) {
X "`t`t<valueType>"
Emit-ValueType -typeStr $typeStr -indent "`t`t`t"
X "`t`t</valueType>"
}
if ($restrictObj -or $restrictTokens.Count -gt 0) {
X "`t`t<useRestriction>"
if ($restrictObj) {
foreach ($prop in $restrictObj.PSObject.Properties) {
if ($prop.Value -eq $true) {
X "`t`t`t<$($prop.Name)>true</$($prop.Name)>"
}
}
X "`t`t</useRestriction>"
}
if ($cf.appearance) {
X "`t`t<appearance>"
foreach ($prop in $cf.appearance.PSObject.Properties) {
X "`t`t`t<dcscor:item xsi:type=`"dcsset:SettingsParameterValue`">"
X "`t`t`t`t<dcscor:parameter>$(Esc-Xml $prop.Name)</dcscor:parameter>"
X "`t`t`t`t<dcscor:value xsi:type=`"xs:string`">$(Esc-Xml "$($prop.Value)")</dcscor:value>"
X "`t`t`t</dcscor:item>"
} else {
foreach ($r in $restrictTokens) {
$xmlName = $restrictMap["$r"]
if ($xmlName) { X "`t`t`t<$xmlName>true</$xmlName>" }
}
X "`t`t</appearance>"
}
X "`t`t</useRestriction>"
}
if ($appearance) {
X "`t`t<appearance>"
foreach ($prop in $appearance.PSObject.Properties) {
X "`t`t`t<dcscor:item xsi:type=`"dcsset:SettingsParameterValue`">"
X "`t`t`t`t<dcscor:parameter>$(Esc-Xml $prop.Name)</dcscor:parameter>"
X "`t`t`t`t<dcscor:value xsi:type=`"xs:string`">$(Esc-Xml "$($prop.Value)")</dcscor:value>"
X "`t`t`t</dcscor:item>"
}
X "`t`t</appearance>"
}
X "`t</calculatedField>"
+105 -47
View File
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
# skd-compile v1.12 — Compile 1C DCS from JSON
# skd-compile v1.13 — Compile 1C DCS from JSON
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
import argparse
import json
@@ -277,13 +277,46 @@ def parse_param_shorthand(s):
# --- Calculated field shorthand parser ---
def parse_calc_shorthand(s):
idx = s.find('=')
if idx > 0:
return {
'dataPath': s[:idx].strip(),
'expression': s[idx + 1:].strip(),
}
return {'dataPath': s.strip(), 'expression': ''}
# Pattern: "Name [Title]: type = Expression #noField #noFilter ...".
# - `[Title]` is extracted only from the LHS of '=' so that `[...]` inside
# an expression (e.g. index access) isn't interpreted as a title.
# - `#restrict` flags use a known-names pattern and are extracted globally —
# the docs put them after `=`, and the closed flag set avoids matching
# `#word` that happens to appear inside a string literal.
restrict_pattern = r'#(noField|noFilter|noCondition|noGroup|noOrder)\b'
restrict = re.findall(restrict_pattern, s)
s = re.sub(r'\s*' + restrict_pattern, '', s)
eq_idx = s.find('=')
if eq_idx > 0:
lhs = s[:eq_idx]
rhs = s[eq_idx + 1:].strip()
else:
lhs = s
rhs = ''
title = ''
m = re.search(r'\[([^\]]+)\]', lhs)
if m:
title = m.group(1)
lhs = re.sub(r'\s*\[[^\]]+\]', '', lhs)
lhs = lhs.strip()
type_str = ''
data_path = lhs
if ':' in lhs:
colon_idx = lhs.index(':')
data_path = lhs[:colon_idx].strip()
type_str = resolve_type_str(lhs[colon_idx + 1:].strip())
return {
'dataPath': data_path,
'expression': rhs,
'type': type_str,
'title': title,
'restrict': restrict,
}
# --- DataParameter shorthand parser ---
@@ -623,56 +656,81 @@ def emit_data_set_links(lines, defn):
def emit_calc_fields(lines, defn):
if not defn.get('calculatedFields'):
return
restrict_map = {
'noField': 'field', 'noFilter': 'condition', 'noCondition': 'condition',
'noGroup': 'group', 'noOrder': 'order',
}
for cf in defn['calculatedFields']:
# Collect dataPath/expression/title/type/restrict/appearance from either
# shorthand string or object form. Object form accepts dataPath/field/name
# as synonyms; useRestriction/restrict accepts object, array, or flag string.
title = ''
type_str = ''
restrict_tokens = []
restrict_obj = None
appearance = None
if isinstance(cf, str):
parsed = parse_calc_shorthand(cf)
is_obj = False
data_path = parsed['dataPath']
expression = parsed['expression']
title = parsed.get('title', '') or ''
type_str = parsed.get('type', '') or ''
restrict_tokens = list(parsed.get('restrict') or [])
else:
parsed = {
'dataPath': str(cf.get('dataPath') or cf.get('field', '')),
'expression': str(cf.get('expression', '')),
}
is_obj = True
lines.append('\t<calculatedField>')
lines.append(f'\t\t<dataPath>{esc_xml(parsed["dataPath"])}</dataPath>')
lines.append(f'\t\t<expression>{esc_xml(parsed["expression"])}</expression>')
if is_obj:
data_path = str(cf.get('dataPath') or cf.get('field') or cf.get('name') or '')
expression = str(cf.get('expression', ''))
if cf.get('title'):
emit_mltext(lines, '\t\t', 'title', str(cf['title']))
title = str(cf['title'])
if cf.get('type'):
cf_type = resolve_type_str(str(cf['type']))
lines.append('\t\t<valueType>')
emit_value_type(lines, cf_type, '\t\t\t')
lines.append('\t\t</valueType>')
restrict_val = cf.get('restrict') or cf.get('useRestriction')
type_str = resolve_type_str(str(cf['type']))
restrict_val = cf.get('restrict') if cf.get('restrict') is not None else cf.get('useRestriction')
if restrict_val:
lines.append('\t\t<useRestriction>')
if isinstance(restrict_val, dict):
# Object form: { "field": true, "condition": true, ... }
for xml_name, flag in restrict_val.items():
if flag:
lines.append(f'\t\t\t<{esc_xml(str(xml_name))}>true</{esc_xml(str(xml_name))}>')
restrict_obj = restrict_val
elif isinstance(restrict_val, str):
# Flag-string form: "#noField #noFilter #noGroup #noOrder" (or without `#`)
for tok in restrict_val.split():
t = tok.strip().lstrip('#')
if t:
restrict_tokens.append(t)
else:
# Array form: ["noField", "noFilter", ...]
restrict_map = {
'noField': 'field', 'noFilter': 'condition', 'noCondition': 'condition',
'noGroup': 'group', 'noOrder': 'order',
}
for r in restrict_val:
xml_name = restrict_map.get(str(r))
if xml_name:
lines.append(f'\t\t\t<{xml_name}>true</{xml_name}>')
lines.append('\t\t</useRestriction>')
if cf.get('appearance'):
lines.append('\t\t<appearance>')
for k, v in cf['appearance'].items():
lines.append('\t\t\t<dcscor:item xsi:type="dcsset:SettingsParameterValue">')
lines.append(f'\t\t\t\t<dcscor:parameter>{esc_xml(k)}</dcscor:parameter>')
lines.append(f'\t\t\t\t<dcscor:value xsi:type="xs:string">{esc_xml(str(v))}</dcscor:value>')
lines.append('\t\t\t</dcscor:item>')
lines.append('\t\t</appearance>')
restrict_tokens.append(str(r))
appearance = cf.get('appearance')
lines.append('\t<calculatedField>')
lines.append(f'\t\t<dataPath>{esc_xml(data_path)}</dataPath>')
lines.append(f'\t\t<expression>{esc_xml(expression)}</expression>')
if title:
emit_mltext(lines, '\t\t', 'title', title)
if type_str:
lines.append('\t\t<valueType>')
emit_value_type(lines, type_str, '\t\t\t')
lines.append('\t\t</valueType>')
if restrict_obj or restrict_tokens:
lines.append('\t\t<useRestriction>')
if restrict_obj:
for xml_name, flag in restrict_obj.items():
if flag:
lines.append(f'\t\t\t<{esc_xml(str(xml_name))}>true</{esc_xml(str(xml_name))}>')
else:
for r in restrict_tokens:
xml_name = restrict_map.get(str(r))
if xml_name:
lines.append(f'\t\t\t<{xml_name}>true</{xml_name}>')
lines.append('\t\t</useRestriction>')
if appearance:
lines.append('\t\t<appearance>')
for k, v in appearance.items():
lines.append('\t\t\t<dcscor:item xsi:type="dcsset:SettingsParameterValue">')
lines.append(f'\t\t\t\t<dcscor:parameter>{esc_xml(k)}</dcscor:parameter>')
lines.append(f'\t\t\t\t<dcscor:value xsi:type="xs:string">{esc_xml(str(v))}</dcscor:value>')
lines.append('\t\t\t</dcscor:item>')
lines.append('\t\t</appearance>')
lines.append('\t</calculatedField>')
+33 -23
View File
@@ -1,4 +1,4 @@
# skd-edit v1.10 — Atomic 1C DCS editor
# skd-edit v1.11 — Atomic 1C DCS editor
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
param(
[Parameter(Mandatory)]
@@ -251,36 +251,46 @@ function Parse-TotalShorthand {
function Parse-CalcShorthand {
param([string]$s)
$title = ""
# Extract [Title] first
if ($s -match '\[([^\]]+)\]') {
$title = $Matches[1]
$s = $s -replace '\s*\[[^\]]+\]', ''
}
# Pattern: "Name [Title]: type = Expression #noField #noFilter ...".
# - `[Title]` is extracted only from the LHS of '=' so that `[...]` inside
# an expression (e.g. index access) isn't interpreted as a title.
# - `#restrict` flags use a known-names pattern and are extracted globally —
# the docs put them after `=`, and the closed flag set avoids matching
# `#word` that happens to appear inside a string literal.
$restrictPattern = '#(noField|noFilter|noCondition|noGroup|noOrder)\b'
# Extract #restrictions
$restrict = @()
$restrictMatches = [regex]::Matches($s, '#(\w+)')
foreach ($m in $restrictMatches) {
foreach ($m in [regex]::Matches($s, $restrictPattern)) {
$restrict += $m.Groups[1].Value
}
$s = [regex]::Replace($s, '\s*#\w+', '')
$s = [regex]::Replace($s, "\s*$restrictPattern", '')
# Support "Name: Type = Expression" and "Name = Expression"
$eqIdx = $s.IndexOf('=')
if ($eqIdx -gt 0) {
$left = $s.Substring(0, $eqIdx).Trim()
$expression = $s.Substring($eqIdx + 1).Trim()
if ($left.Contains(':')) {
$colonIdx = $left.IndexOf(':')
$dataPath = $left.Substring(0, $colonIdx).Trim()
$type = Resolve-TypeStr ($left.Substring($colonIdx + 1).Trim())
return @{ dataPath = $dataPath; expression = $expression; type = $type; title = $title; restrict = $restrict }
}
return @{ dataPath = $left; expression = $expression; type = ""; title = $title; restrict = $restrict }
$lhs = $s.Substring(0, $eqIdx)
$rhs = $s.Substring($eqIdx + 1).Trim()
} else {
$lhs = $s
$rhs = $null
}
return @{ dataPath = $s.Trim(); expression = ""; type = ""; title = $title; restrict = $restrict }
$title = ""
if ($lhs -match '\[([^\]]+)\]') {
$title = $Matches[1]
$lhs = $lhs -replace '\s*\[[^\]]+\]', ''
}
$lhs = $lhs.Trim()
if ($null -ne $rhs) {
if ($lhs.Contains(':')) {
$colonIdx = $lhs.IndexOf(':')
$dataPath = $lhs.Substring(0, $colonIdx).Trim()
$type = Resolve-TypeStr ($lhs.Substring($colonIdx + 1).Trim())
return @{ dataPath = $dataPath; expression = $rhs; type = $type; title = $title; restrict = $restrict }
}
return @{ dataPath = $lhs; expression = $rhs; type = ""; title = $title; restrict = $restrict }
}
return @{ dataPath = $lhs; expression = ""; type = ""; title = $title; restrict = $restrict }
}
function Parse-ParamShorthand {
+33 -17
View File
@@ -1,4 +1,4 @@
# skd-edit v1.10 — Atomic 1C DCS editor (Python port)
# skd-edit v1.11 — Atomic 1C DCS editor (Python port)
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
import argparse
import os
@@ -260,26 +260,42 @@ def parse_total_shorthand(s):
def parse_calc_shorthand(s):
title = ""
m = re.search(r'\[([^\]]+)\]', s)
if m:
title = m.group(1)
s = re.sub(r'\s*\[[^\]]+\]', '', s)
# Pattern: "Name [Title]: type = Expression #noField #noFilter ...".
# - `[Title]` is extracted only from the LHS of '=' so that `[...]` inside
# an expression (e.g. index access) isn't interpreted as a title.
# - `#restrict` flags use a known-names pattern and are extracted globally —
# the docs put them after `=`, and the closed flag set avoids matching
# `#word` that happens to appear inside a string literal.
restrict_pattern = r'#(noField|noFilter|noCondition|noGroup|noOrder)\b'
restrict_matches = re.findall(r'#(\w+)', s)
s = re.sub(r'\s*#\w+', '', s)
restrict_matches = re.findall(restrict_pattern, s)
s = re.sub(r'\s*' + restrict_pattern, '', s)
eq_idx = s.find("=")
if eq_idx > 0:
left = s[:eq_idx].strip()
expression = s[eq_idx + 1:].strip()
if ":" in left:
colon_idx = left.index(":")
data_path = left[:colon_idx].strip()
type_str = resolve_type_str(left[colon_idx + 1:].strip())
return {"dataPath": data_path, "expression": expression, "type": type_str, "title": title, "restrict": restrict_matches}
return {"dataPath": left, "expression": expression, "type": "", "title": title, "restrict": restrict_matches}
return {"dataPath": s.strip(), "expression": "", "type": "", "title": title, "restrict": restrict_matches}
lhs = s[:eq_idx]
rhs = s[eq_idx + 1:].strip()
has_rhs = True
else:
lhs = s
rhs = ""
has_rhs = False
title = ""
m = re.search(r'\[([^\]]+)\]', lhs)
if m:
title = m.group(1)
lhs = re.sub(r'\s*\[[^\]]+\]', '', lhs)
lhs = lhs.strip()
if has_rhs:
if ":" in lhs:
colon_idx = lhs.index(":")
data_path = lhs[:colon_idx].strip()
type_str = resolve_type_str(lhs[colon_idx + 1:].strip())
return {"dataPath": data_path, "expression": rhs, "type": type_str, "title": title, "restrict": restrict_matches}
return {"dataPath": lhs, "expression": rhs, "type": "", "title": title, "restrict": restrict_matches}
return {"dataPath": lhs, "expression": "", "type": "", "title": title, "restrict": restrict_matches}
def parse_param_shorthand(s):
@@ -0,0 +1,23 @@
{
"name": "calculatedFields объектная форма с name и строковым useRestriction",
"params": { "outputPath": "Template.xml" },
"input": {
"dataSets": [{
"name": "Основной",
"query": "ВЫБРАТЬ Т.Номенклатура, Т.Сумма ИЗ Регистр КАК Т",
"fields": ["Номенклатура", "Сумма: decimal(15,2)"]
}],
"calculatedFields": [
{
"name": "ИмяРесурса",
"title": "Имя ресурса",
"expression": "\"\"",
"useRestriction": "#noField #noFilter #noGroup #noOrder"
}
]
},
"validatePath": "Template.xml",
"expect": {
"files": ["Template.xml"]
}
}
@@ -0,0 +1,19 @@
{
"name": "calculatedFields shorthand с [Title], :type, =expr, #restrict",
"params": { "outputPath": "Template.xml" },
"input": {
"dataSets": [{
"name": "Основной",
"query": "ВЫБРАТЬ Т.Цена, Т.Закупка ИЗ Регистр КАК Т",
"fields": ["Цена: decimal(15,2)", "Закупка: decimal(15,2)"]
}],
"calculatedFields": [
"ИмяРесурса [Имя ресурса]: string = \"\" #noField #noFilter #noGroup #noOrder",
"Маржа [Маржа]: decimal(15,2) = Цена - Закупка"
]
},
"validatePath": "Template.xml",
"expect": {
"files": ["Template.xml"]
}
}
@@ -0,0 +1,72 @@
<?xml version="1.0" encoding="UTF-8"?>
<DataCompositionSchema xmlns="http://v8.1c.ru/8.1/data-composition-system/schema"
xmlns:dcscom="http://v8.1c.ru/8.1/data-composition-system/common"
xmlns:dcscor="http://v8.1c.ru/8.1/data-composition-system/core"
xmlns:dcsset="http://v8.1c.ru/8.1/data-composition-system/settings"
xmlns:v8="http://v8.1c.ru/8.1/data/core"
xmlns:v8ui="http://v8.1c.ru/8.1/data/ui"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<dataSource>
<name>ИсточникДанных1</name>
<dataSourceType>Local</dataSourceType>
</dataSource>
<dataSet xsi:type="DataSetQuery">
<name>Основной</name>
<field xsi:type="DataSetFieldField">
<dataPath>Номенклатура</dataPath>
<field>Номенклатура</field>
</field>
<field xsi:type="DataSetFieldField">
<dataPath>Сумма</dataPath>
<field>Сумма</field>
<valueType>
<v8:Type>xs:decimal</v8:Type>
<v8:NumberQualifiers>
<v8:Digits>15</v8:Digits>
<v8:FractionDigits>2</v8:FractionDigits>
<v8:AllowedSign>Any</v8:AllowedSign>
</v8:NumberQualifiers>
</valueType>
</field>
<dataSource>ИсточникДанных1</dataSource>
<query>ВЫБРАТЬ Т.Номенклатура, Т.Сумма ИЗ Регистр КАК Т</query>
</dataSet>
<calculatedField>
<dataPath>ИмяРесурса</dataPath>
<expression>&quot;&quot;</expression>
<title xsi:type="v8:LocalStringType">
<v8:item>
<v8:lang>ru</v8:lang>
<v8:content>Имя ресурса</v8:content>
</v8:item>
</title>
<useRestriction>
<field>true</field>
<condition>true</condition>
<group>true</group>
<order>true</order>
</useRestriction>
</calculatedField>
<settingsVariant>
<dcsset:name>Основной</dcsset:name>
<dcsset:presentation xsi:type="v8:LocalStringType">
<v8:item>
<v8:lang>ru</v8:lang>
<v8:content>Основной</v8:content>
</v8:item>
</dcsset:presentation>
<dcsset:settings xmlns:style="http://v8.1c.ru/8.1/data/ui/style" xmlns:sys="http://v8.1c.ru/8.1/data/ui/fonts/system" xmlns:web="http://v8.1c.ru/8.1/data/ui/colors/web" xmlns:win="http://v8.1c.ru/8.1/data/ui/colors/windows">
<dcsset:selection>
</dcsset:selection>
<dcsset:item xsi:type="dcsset:StructureItemGroup">
<dcsset:order>
<dcsset:item xsi:type="dcsset:OrderItemAuto"/>
</dcsset:order>
<dcsset:selection>
<dcsset:item xsi:type="dcsset:SelectedItemAuto"/>
</dcsset:selection>
</dcsset:item>
</dcsset:settings>
</settingsVariant>
</DataCompositionSchema>
@@ -0,0 +1,105 @@
<?xml version="1.0" encoding="UTF-8"?>
<DataCompositionSchema xmlns="http://v8.1c.ru/8.1/data-composition-system/schema"
xmlns:dcscom="http://v8.1c.ru/8.1/data-composition-system/common"
xmlns:dcscor="http://v8.1c.ru/8.1/data-composition-system/core"
xmlns:dcsset="http://v8.1c.ru/8.1/data-composition-system/settings"
xmlns:v8="http://v8.1c.ru/8.1/data/core"
xmlns:v8ui="http://v8.1c.ru/8.1/data/ui"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<dataSource>
<name>ИсточникДанных1</name>
<dataSourceType>Local</dataSourceType>
</dataSource>
<dataSet xsi:type="DataSetQuery">
<name>Основной</name>
<field xsi:type="DataSetFieldField">
<dataPath>Цена</dataPath>
<field>Цена</field>
<valueType>
<v8:Type>xs:decimal</v8:Type>
<v8:NumberQualifiers>
<v8:Digits>15</v8:Digits>
<v8:FractionDigits>2</v8:FractionDigits>
<v8:AllowedSign>Any</v8:AllowedSign>
</v8:NumberQualifiers>
</valueType>
</field>
<field xsi:type="DataSetFieldField">
<dataPath>Закупка</dataPath>
<field>Закупка</field>
<valueType>
<v8:Type>xs:decimal</v8:Type>
<v8:NumberQualifiers>
<v8:Digits>15</v8:Digits>
<v8:FractionDigits>2</v8:FractionDigits>
<v8:AllowedSign>Any</v8:AllowedSign>
</v8:NumberQualifiers>
</valueType>
</field>
<dataSource>ИсточникДанных1</dataSource>
<query>ВЫБРАТЬ Т.Цена, Т.Закупка ИЗ Регистр КАК Т</query>
</dataSet>
<calculatedField>
<dataPath>ИмяРесурса</dataPath>
<expression>&quot;&quot;</expression>
<title xsi:type="v8:LocalStringType">
<v8:item>
<v8:lang>ru</v8:lang>
<v8:content>Имя ресурса</v8:content>
</v8:item>
</title>
<valueType>
<v8:Type>xs:string</v8:Type>
<v8:StringQualifiers>
<v8:Length>0</v8:Length>
<v8:AllowedLength>Variable</v8:AllowedLength>
</v8:StringQualifiers>
</valueType>
<useRestriction>
<field>true</field>
<condition>true</condition>
<group>true</group>
<order>true</order>
</useRestriction>
</calculatedField>
<calculatedField>
<dataPath>Маржа</dataPath>
<expression>Цена - Закупка</expression>
<title xsi:type="v8:LocalStringType">
<v8:item>
<v8:lang>ru</v8:lang>
<v8:content>Маржа</v8:content>
</v8:item>
</title>
<valueType>
<v8:Type>xs:decimal</v8:Type>
<v8:NumberQualifiers>
<v8:Digits>15</v8:Digits>
<v8:FractionDigits>2</v8:FractionDigits>
<v8:AllowedSign>Any</v8:AllowedSign>
</v8:NumberQualifiers>
</valueType>
</calculatedField>
<settingsVariant>
<dcsset:name>Основной</dcsset:name>
<dcsset:presentation xsi:type="v8:LocalStringType">
<v8:item>
<v8:lang>ru</v8:lang>
<v8:content>Основной</v8:content>
</v8:item>
</dcsset:presentation>
<dcsset:settings xmlns:style="http://v8.1c.ru/8.1/data/ui/style" xmlns:sys="http://v8.1c.ru/8.1/data/ui/fonts/system" xmlns:web="http://v8.1c.ru/8.1/data/ui/colors/web" xmlns:win="http://v8.1c.ru/8.1/data/ui/colors/windows">
<dcsset:selection>
</dcsset:selection>
<dcsset:item xsi:type="dcsset:StructureItemGroup">
<dcsset:order>
<dcsset:item xsi:type="dcsset:OrderItemAuto"/>
</dcsset:order>
<dcsset:selection>
<dcsset:item xsi:type="dcsset:SelectedItemAuto"/>
</dcsset:selection>
</dcsset:item>
</dcsset:settings>
</settingsVariant>
</DataCompositionSchema>