From 90a05a58e22bc2910f5ae3a8ccdcd8a058f873fb Mon Sep 17 00:00:00 2001 From: Nick Shirokov Date: Sun, 5 Jul 2026 20:30:58 +0300 Subject: [PATCH] =?UTF-8?q?feat(meta-compile,meta-decompile):=20=C2=AB?= =?UTF-8?q?=D0=A2=D0=BE=D0=BB=D1=8C=D0=BA=D0=BE=20=D0=BE=D0=B1=D0=BE=D1=80?= =?UTF-8?q?=D0=BE=D1=82=D1=8B=C2=BB=20=D0=BA=D0=B0=D0=BA=20=D1=82=D0=BE?= =?UTF-8?q?=D0=BA=D0=B5=D0=BD-=D0=BF=D1=80=D0=B8=D0=B7=D0=BD=D0=B0=D0=BA?= =?UTF-8?q?=20=D1=81=D1=83=D0=B1=D0=BA=D0=BE=D0=BD=D1=82=D0=BE=20(v1.39/v0?= =?UTF-8?q?.28)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit «Только обороты» () — предопределённый (встроенный) признак учёта субконто. Теперь он выражается токеном `Turnover` (синонимы ТолькоОбороты/«Только обороты») в том же списке признаков, что и добавленные: "Номенклатура | Turnover, Суммовой". Строковая форма стала полностью самодостаточной — объектная {type, turnover?, flags?} остаётся принимаемым эквивалентом. Компилятор вынимает токен turnover из списка flags (регистронезависимо) → true. Декомпилятор всегда пишет строкой, ставя `Turnover` первым при Turnover=true (объектную форму больше не порождает). Роундтрип 3/3 match; обе формы + смешанный массив проверены, ps1↔py identical. Регресс 47/47 ps1+py. spec §7.2c. Co-Authored-By: Claude Opus 4.8 (1M context) --- .../meta-compile/scripts/meta-compile.ps1 | 9 +++++++- .../meta-compile/scripts/meta-compile.py | 12 +++++++++- .../meta-decompile/scripts/meta-decompile.ps1 | 23 ++++++++----------- docs/meta-dsl-spec.md | 5 ++-- 4 files changed, 31 insertions(+), 18 deletions(-) diff --git a/.claude/skills/meta-compile/scripts/meta-compile.ps1 b/.claude/skills/meta-compile/scripts/meta-compile.ps1 index 0771ebb1..f5a28b6d 100644 --- a/.claude/skills/meta-compile/scripts/meta-compile.ps1 +++ b/.claude/skills/meta-compile/scripts/meta-compile.ps1 @@ -1,4 +1,4 @@ -# meta-compile v1.38 — Compile 1C metadata object from JSON +# meta-compile v1.39 — Compile 1C metadata object from JSON # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills param( [Parameter(Mandatory)] @@ -3809,6 +3809,9 @@ function Build-PredefinedXml { # --- Предопределённые СЧЕТА Плана счетов (отдельная грамматика: AccountType/OffBalance/Order/AccountingFlags/ # ExtDimensionTypes/ChildItems). Флаги перечисляем по def-порядку списков признаков плана; в DSL — только TRUE. --- $script:predefAccGet = { param($o, [string[]]$keys) foreach ($k in $keys) { if ($o -is [System.Collections.IDictionary]) { if ($o.Contains($k)) { return $o[$k] } } elseif ($o.PSObject -and $o.PSObject.Properties[$k]) { return $o.$k } } return $null } +# «Только обороты» () — предопределённый признак учёта субконто. В DSL — токен в списке flags +# наравне с добавленными признаками (ЛИБО отдельный ключ turnover). Распознаём по имени (регистронезависимо). +$script:subcontoTurnoverTokens = @('turnover', 'толькообороты', 'только обороты', 'оборотный') function Emit-PredefAccountFlags { param($sb, [string]$indent, [string]$tag, [string]$refKind, [string]$objName, [string[]]$flagNames, $trueSet) if (-not $flagNames -or $flagNames.Count -eq 0) { [void]$sb.Append("$indent<$tag/>`n"); return } @@ -3861,7 +3864,11 @@ function Emit-PredefAccount { # Короткая запись: голое имя значения → префикс ПВХ видов субконто плана (extDimensionTypes); иначе резолв синонима. if (-not $scType.Contains('.')) { if ($extDimTypesRef) { $scType = "$extDimTypesRef.$scType" } } else { $scType = Resolve-TypePrefixSyn $scType } + # «Только обороты» — токен в списке flags (или отдельный ключ turnover); вынимаем из настоящих признаков. $scTurn = if ($scTurnV -eq $true) { 'true' } else { 'false' } + $scFlagsReal = @() + foreach ($f in @($scFlags)) { if ("$f".Trim().ToLower() -in $script:subcontoTurnoverTokens) { $scTurn = 'true' } else { $scFlagsReal += $f } } + $scFlags = $scFlagsReal [void]$sb.Append("$indent`t`t`n") [void]$sb.Append("$indent`t`t`t$scTurn`n") Emit-PredefAccountFlags $sb "$indent`t`t`t" 'AccountingFlags' 'ExtDimensionAccountingFlag' $objName $extDimFlagNames $scFlags diff --git a/.claude/skills/meta-compile/scripts/meta-compile.py b/.claude/skills/meta-compile/scripts/meta-compile.py index 91ad98b1..02ef7497 100644 --- a/.claude/skills/meta-compile/scripts/meta-compile.py +++ b/.claude/skills/meta-compile/scripts/meta-compile.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# meta-compile v1.38 — Compile 1C metadata object from JSON +# meta-compile v1.39 — Compile 1C metadata object from JSON # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse @@ -662,6 +662,8 @@ fill_bool_true = ('true', 'истина', 'да') fill_bool_false = ('false', 'ложь', 'нет') # Значения платформенного перечисления ВидСчета (ent:AccountType) — FillValue реквизита Тип у Плана счетов. ACCOUNT_TYPE_VALUES = ('Active', 'Passive', 'ActivePassive') +# «Только обороты» () — предопределённый признак учёта субконто; токен в списке flags наравне с добавленными. +SUBCONTO_TURNOVER_TOKENS = ('turnover', 'толькообороты', 'только обороты', 'оборотный') # XxxRef (тип реквизита) → корень DTR-пути (для разворота короткой записи значения). fill_ref_kind_root = { 'catalogref': 'Catalog', 'documentref': 'Document', 'enumref': 'Enum', @@ -3718,7 +3720,15 @@ def emit_predef_account(out, val, indent, obj_nm, acct_flag_names, ext_dim_flag_ sc_type = f'{ext_dim_types_ref}.{sc_type}' else: sc_type = resolve_type_prefix_syn(sc_type) + # «Только обороты» — токен в списке flags (или отдельный ключ turnover); вынимаем из настоящих признаков. sc_turn = 'true' if sc_turn_v is True else 'false' + real_flags = [] + for f in (sc_flags or []): + if str(f).strip().lower() in SUBCONTO_TURNOVER_TOKENS: + sc_turn = 'true' + else: + real_flags.append(f) + sc_flags = real_flags out.append(f'{indent}\t\t') out.append(f'{indent}\t\t\t{sc_turn}') emit_predef_account_flags(out, f'{indent}\t\t\t', 'AccountingFlags', 'ExtDimensionAccountingFlag', obj_nm, ext_dim_flag_names, sc_flags) diff --git a/.claude/skills/meta-decompile/scripts/meta-decompile.ps1 b/.claude/skills/meta-decompile/scripts/meta-decompile.ps1 index e457d89b..bc378e1a 100644 --- a/.claude/skills/meta-decompile/scripts/meta-decompile.ps1 +++ b/.claude/skills/meta-decompile/scripts/meta-decompile.ps1 @@ -1,4 +1,4 @@ -# meta-decompile v0.27 — XML объекта метаданных 1С → JSON-черновик формата meta-compile +# meta-decompile v0.28 — XML объекта метаданных 1С → JSON-черновик формата meta-compile # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills # # Поддержаны: Catalog, ExchangePlan, ChartOfCharacteristicTypes, ChartOfAccounts. Инверс meta-compile (omit-on-default: ключ эмитим только @@ -808,27 +808,22 @@ if (Test-Path -LiteralPath $predefPath) { foreach ($fl in @($itemEl.SelectNodes("*[local-name()='AccountingFlags']/*[local-name()='Flag']"))) { if ($fl.InnerText -eq 'true') { $r = $fl.GetAttribute('ref'); $trueFlags += ($r -split '\.')[-1] } } - # ExtDimensionTypes → subconto. Короткая запись: срезаем префикс ПВХ видов субконто плана (extDimensionTypes). - # turnover=false → строка "Тип | Признак1, Признак2" (или "Тип" без признаков); turnover=true → объект. + # ExtDimensionTypes → subconto. Короткая запись "Тип | Признак1, Признак2": срезаем префикс ПВХ видов субконто + # плана (extDimensionTypes); «Только обороты» (Turnover=true) — предопределённый признак-токен `Turnover` первым + # в списке (наравне с добавленными). Захватываем только TRUE-признаки (компилятор развернёт по def-порядку). $edtPfx = if ($dsl['extDimensionTypes']) { "$($dsl['extDimensionTypes'])." } else { $null } $subconto = [System.Collections.ArrayList]@() foreach ($edt in @($itemEl.SelectNodes("*[local-name()='ExtDimensionTypes']/*[local-name()='ExtDimensionType']"))) { $scT = $edt.GetAttribute('name') if ($edtPfx -and $scT.StartsWith($edtPfx)) { $scT = $scT.Substring($edtPfx.Length) } $tEl = $edt.SelectSingleNode("*[local-name()='Turnover']") - $scTurn = ($tEl -and $tEl.InnerText -eq 'true') - $stf = @() + $scFlagsOut = @() + if ($tEl -and $tEl.InnerText -eq 'true') { $scFlagsOut += 'Turnover' } foreach ($fl in @($edt.SelectNodes("*[local-name()='AccountingFlags']/*[local-name()='Flag']"))) { - if ($fl.InnerText -eq 'true') { $r = $fl.GetAttribute('ref'); $stf += ($r -split '\.')[-1] } - } - if (-not $scTurn) { - if ($stf.Count -gt 0) { [void]$subconto.Add("$scT | " + ($stf -join ', ')) } - else { [void]$subconto.Add($scT) } - } else { - $so = [ordered]@{ type = $scT; turnover = $true } - if ($stf.Count -gt 0) { $so['flags'] = [System.Collections.ArrayList]@($stf) } - [void]$subconto.Add($so) + if ($fl.InnerText -eq 'true') { $r = $fl.GetAttribute('ref'); $scFlagsOut += ($r -split '\.')[-1] } } + if ($scFlagsOut.Count -gt 0) { [void]$subconto.Add("$scT | " + ($scFlagsOut -join ', ')) } + else { [void]$subconto.Add($scT) } } $childContainer = $itemEl.SelectSingleNode("*[local-name()='ChildItems']") $kids = @(if ($childContainer) { $childContainer.SelectNodes("*[local-name()='Item']") } else { @() }) diff --git a/docs/meta-dsl-spec.md b/docs/meta-dsl-spec.md index 93141c3d..7170cc09 100644 --- a/docs/meta-dsl-spec.md +++ b/docs/meta-dsl-spec.md @@ -701,8 +701,9 @@ Split-CamelCase имени. **Субконто** (`subconto`) — короткая строка **`"Вид | Признак1, Признак2"`** (после `|` — включённые признаки учёта субконто): `type` — голое имя предопределённого значения ПВХ, компилятор разворачивает через `extDimensionTypes` плана (`Номенклатура` → `ChartOfCharacteristicTypes.ВидыСубконто.Номенклатура`); признаки — только TRUE, разворот по def-порядку -`extDimensionAccountingFlags`. Объектная форма `{type, turnover?, flags?}` — когда нужен `turnover: true` -(`` = «Только обороты»: субконто ведётся только по оборотам, без остатков; синоним `толькоОбороты`). +`extDimensionAccountingFlags`. **«Только обороты»** (`` — субконто ведётся только по оборотам, без остатков) — +предопределённый признак-токен **`Turnover`** (синонимы `ТолькоОбороты`/`Только обороты`) в том же списке признаков: +`"Номенклатура | Turnover, Суммовой"`. Объектная форма `{type, turnover?, flags?}` тоже принимается (эквивалент). ```json "predefined": [