diff --git a/.claude/skills/meta-compile/scripts/meta-compile.ps1 b/.claude/skills/meta-compile/scripts/meta-compile.ps1 index 1f99abb2..417e7cb9 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.46 — Compile 1C metadata object from JSON +# meta-compile v1.47 — Compile 1C metadata object from JSON # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills param( [Parameter(Mandatory)] @@ -843,6 +843,11 @@ function Parse-AttributeShorthand { mainFilter = if ($val.mainFilter -eq $true) { $true } else { $false } denyIncompleteValues = if ($val.denyIncompleteValues -eq $true) { $true } else { $false } useInTotals = if ($null -ne $val.useInTotals) { ($val.useInTotals -eq $true) } else { $true } + baseDimension = if ($val.baseDimension -eq $true) { $true } else { $false } + scheduleLink = $val.scheduleLink + balance = if ($val.balance -eq $true) { $true } else { $false } + accountingFlag = $val.accountingFlag + extDimensionAccountingFlag = $val.extDimensionAccountingFlag } } @@ -1092,7 +1097,18 @@ function Emit-StandardAttribute { $efmt = OvOr 'EditFormat' $null $chi = OvOr 'ChoiceHistoryOnInput' 'Auto' X "$indent" - X "$indent`t" + # LinkByType стандартного реквизита (напр. ExtDimensionN→Account у регистра бухгалтерии). DataPath verbatim (полный). + $lbt = OvOr 'LinkByType' $null + if ($lbt) { + $lbtDp = if ($lbt.dataPath) { "$($lbt.dataPath)" } else { "$lbt" } + $lbtLi = if ($null -ne $lbt.linkItem) { $lbt.linkItem } else { 0 } + X "$indent`t" + X "$indent`t`t$(Esc-Xml $lbtDp)" + X "$indent`t`t$lbtLi" + X "$indent`t" + } else { + X "$indent`t" + } X "$indent`t$fc" X "$indent`tfalse" X "$indent`t$ffv" @@ -1167,6 +1183,7 @@ function Emit-StandardAttributes { if ($null -ne $d.format) { $ov['Format'] = $d.format } # строка ИЛИ {ru,en} if ($null -ne $d.editFormat) { $ov['EditFormat'] = $d.editFormat } if ($d.choiceForm) { $ov['ChoiceForm'] = "$($d.choiceForm)" } + if ($null -ne $d.linkByType) { $ov['LinkByType'] = $d.linkByType } } } Emit-StandardAttribute "$indent`t" $a $ov @@ -1607,7 +1624,7 @@ function Emit-Attribute { # FillFromFillingValue — not for tabular/processor/chart/register-other/register-accum # (Chart*, AccumulationRegister/AccountingRegister/CalculationRegister don't support these) - if ($context -notin @("tabular", "processor", "chart", "register-other", "register-accum")) { + if ($context -notin @("tabular", "processor", "chart", "register-other", "register-accum", "register-calc", "register-account")) { # Флаг-shorthand `master` у ведущего измерения регистра конвенционально ставит и FillFromFillingValue=true # (эргономика авторинга; декомпилятор пишет key-форму master:true + явный fillFromFillingValue → роундтрип цел). $ffv = if ($parsed.fillFromFillingValue -eq $true -or ($elemTag -eq "Dimension" -and $parsed.flags -contains "master")) { "true" } else { "false" } @@ -1615,7 +1632,7 @@ function Emit-Attribute { } # FillValue — same restriction - if ($context -notin @("tabular", "processor", "chart", "register-other", "register-accum")) { + if ($context -notin @("tabular", "processor", "chart", "register-other", "register-accum", "register-calc", "register-account")) { Emit-FillValue "$indent`t`t" $typeStr $parsed.fillValue $parsed.hasFillValue } @@ -1653,6 +1670,33 @@ function Emit-Attribute { X "$indent`t`t$denyIncomplete" } + # Измерение регистра расчёта: DenyIncompleteValues + BaseDimension (между ChoiceHistoryOnInput и ScheduleLink/Indexing). + if ($elemTag -eq "Dimension" -and $context -eq "register-calc") { + $denyIncomplete = if ($parsed.denyIncompleteValues -eq $true -or $parsed.flags -contains "denyincomplete") { "true" } else { "false" } + $baseDimension = if ($parsed.baseDimension -eq $true -or $parsed.flags -contains "base") { "true" } else { "false" } + X "$indent`t`t$denyIncomplete" + X "$indent`t`t$baseDimension" + } + # Регистр расчёта: ScheduleLink у измерений и реквизитов (НЕ ресурсов), перед Indexing. Дефолт пустой. + if ($context -eq "register-calc" -and $elemTag -in @("Dimension", "Attribute")) { + if ($parsed.scheduleLink) { X "$indent`t`t$(Esc-Xml "$($parsed.scheduleLink)")" } + else { X "$indent`t`t" } + } + + # Измерение/ресурс регистра бухгалтерии: Balance + AccountingFlag (ссылка на признак учёта ПС), затем + # DenyIncompleteValues (измерение) / ExtDimensionAccountingFlag (ресурс). Всё между ChoiceHistoryOnInput и Indexing. + if ($context -eq "register-account" -and $elemTag -in @("Dimension", "Resource")) { + $balance = if ($parsed.balance -eq $true -or $parsed.flags -contains "balance") { "true" } else { "false" } + X "$indent`t`t$balance" + if ($parsed.accountingFlag) { X "$indent`t`t$(Esc-Xml "$($parsed.accountingFlag)")" } else { X "$indent`t`t" } + if ($elemTag -eq "Dimension") { + $denyIncomplete = if ($parsed.denyIncompleteValues -eq $true -or $parsed.flags -contains "denyincomplete") { "true" } else { "false" } + X "$indent`t`t$denyIncomplete" + } else { + if ($parsed.extDimensionAccountingFlag) { X "$indent`t`t$(Esc-Xml "$($parsed.extDimensionAccountingFlag)")" } else { X "$indent`t`t" } + } + } + # Use — only for catalog top-level attributes if ($context -eq "catalog") { $use = if ($parsed.use) { $parsed.use } else { "ForItem" } @@ -1663,8 +1707,8 @@ function Emit-Attribute { if ($context -notin @("processor", "processor-tabular")) { # Признаки учёта ПС (account-flag) не имеют /, но имеют . if ($context -ne "account-flag") { - # Ресурс регистра накопления НЕ имеет (только ); измерение/реквизит — имеют. - if (-not ($context -eq "register-accum" -and $elemTag -eq "Resource")) { + # Ресурс регистра накопления/расчёта/бухгалтерии НЕ имеет (только ); измерение/реквизит — имеют. + if (-not ($context -in @("register-accum", "register-calc", "register-account") -and $elemTag -eq "Resource")) { $indexing = "DontIndex" if ($parsed.flags -contains "index") { $indexing = "Index" } if ($parsed.flags -contains "indexadditional") { $indexing = "IndexWithAdditionalOrder" } @@ -1681,7 +1725,7 @@ function Emit-Attribute { X "$indent`t`t$useInTotals" } # DataHistory — not for Chart* types and non-InformationRegister register family - if ($context -notin @("chart", "register-other", "register-accum")) { + if ($context -notin @("chart", "register-other", "register-accum", "register-calc", "register-account")) { $dh = if ($parsed.dataHistory) { $parsed.dataHistory } else { "Use" } X "$indent`t`t$dh" } @@ -2902,13 +2946,14 @@ function Emit-AccountingRegisterProperties { X "$i$(Esc-Xml $objName)" Emit-MLText $i "Synonym" $synonym - X "$i" - X "$itrue" - X "$i" - X "$i" + if ($def.comment) { X "$i$(Esc-XmlText "$($def.comment)")" } else { X "$i" } + $useStdCmd = if (Get-BoolProp "useStandardCommands" $true) { "true" } else { "false" } + X "$i$useStdCmd" + $inclHelp = if (Get-BoolProp "includeHelpInContents" $false) { "true" } else { "false" } + X "$i$inclHelp" $chartOfAccounts = if ($def.chartOfAccounts) { "$($def.chartOfAccounts)" } else { "" } - if ($chartOfAccounts) { X "$i$chartOfAccounts" } + if ($chartOfAccounts) { X "$i$(Esc-Xml $chartOfAccounts)" } else { X "$i" } $correspondence = if ($def.correspondence -eq $true) { "true" } else { "false" } @@ -2917,19 +2962,23 @@ function Emit-AccountingRegisterProperties { $periodAdjLen = if ($null -ne $def.periodAdjustmentLength) { "$($def.periodAdjustmentLength)" } else { "0" } X "$i$periodAdjLen" - X "$ifalse" + Emit-FormRef $i "DefaultListForm" $def.defaultListForm + Emit-FormRef $i "AuxiliaryListForm" $def.auxiliaryListForm Emit-StandardAttributes $i "AccountingRegister" $dataLockControlMode = Get-EnumProp "DataLockControlMode" "dataLockControlMode" "Automatic" X "$i$dataLockControlMode" + $enableTotalsSplitting = if ($def.enableTotalsSplitting -eq $false) { "false" } else { "true" } + X "$i$enableTotalsSplitting" + $fullTextSearch = Get-EnumProp "FullTextSearch" "fullTextSearch" "Use" X "$i$fullTextSearch" - X "$i" - X "$i" - X "$i" + Emit-MLText $i "ListPresentation" $def.listPresentation + Emit-MLText $i "ExtendedListPresentation" $def.extendedListPresentation + Emit-MLText $i "Explanation" $def.explanation } # Стандартные ТЧ Плана видов расчёта: Ведущие/Вытесняющие/Базовые виды расчёта. Обёртка платформенно-константна @@ -3049,14 +3098,11 @@ function Emit-CalculationRegisterProperties { X "$i$(Esc-Xml $objName)" Emit-MLText $i "Synonym" $synonym - X "$i" - X "$itrue" - X "$i" - X "$i" - - $chartOfCalcTypes = if ($def.chartOfCalculationTypes) { "$($def.chartOfCalculationTypes)" } else { "" } - if ($chartOfCalcTypes) { X "$i$chartOfCalcTypes" } - else { X "$i" } + if ($def.comment) { X "$i$(Esc-XmlText "$($def.comment)")" } else { X "$i" } + $useStdCmd = if (Get-BoolProp "useStandardCommands" $true) { "true" } else { "false" } + X "$i$useStdCmd" + Emit-FormRef $i "DefaultListForm" $def.defaultListForm + Emit-FormRef $i "AuxiliaryListForm" $def.auxiliaryListForm $periodicity = Get-EnumProp "InformationRegisterPeriodicity" "periodicity" "Month" X "$i$periodicity" @@ -3068,15 +3114,20 @@ function Emit-CalculationRegisterProperties { X "$i$basePeriod" $schedule = if ($def.schedule) { "$($def.schedule)" } else { "" } - if ($schedule) { X "$i$schedule" } else { X "$i" } + if ($schedule) { X "$i$(Esc-Xml $schedule)" } else { X "$i" } $scheduleValue = if ($def.scheduleValue) { "$($def.scheduleValue)" } else { "" } - if ($scheduleValue) { X "$i$scheduleValue" } else { X "$i" } + if ($scheduleValue) { X "$i$(Esc-Xml $scheduleValue)" } else { X "$i" } $scheduleDate = if ($def.scheduleDate) { "$($def.scheduleDate)" } else { "" } - if ($scheduleDate) { X "$i$scheduleDate" } else { X "$i" } + if ($scheduleDate) { X "$i$(Esc-Xml $scheduleDate)" } else { X "$i" } - X "$ifalse" + $chartOfCalcTypes = if ($def.chartOfCalculationTypes) { "$($def.chartOfCalculationTypes)" } else { "" } + if ($chartOfCalcTypes) { X "$i$(Esc-Xml $chartOfCalcTypes)" } + else { X "$i" } + + $inclHelp = if (Get-BoolProp "includeHelpInContents" $false) { "true" } else { "false" } + X "$i$inclHelp" Emit-StandardAttributes $i "CalculationRegister" @@ -3086,9 +3137,9 @@ function Emit-CalculationRegisterProperties { $fullTextSearch = Get-EnumProp "FullTextSearch" "fullTextSearch" "Use" X "$i$fullTextSearch" - X "$i" - X "$i" - X "$i" + Emit-MLText $i "ListPresentation" $def.listPresentation + Emit-MLText $i "ExtendedListPresentation" $def.extendedListPresentation + Emit-MLText $i "Explanation" $def.explanation } # --- 13e. Wave 5: BusinessProcess, Task --- @@ -3698,12 +3749,11 @@ if ($objType -in @("InformationRegister","AccumulationRegister","AccountingRegis if ($dims.Count -gt 0 -or $resources.Count -gt 0 -or $regAttrs.Count -gt 0 -or $regCommands.Count -gt 0) { $hasChildren = $true X "`t`t" - # InformationRegister.Attribute supports FillFromFillingValue/FillValue/DataHistory; - # AccumulationRegister/AccountingRegister/CalculationRegister.Attribute do NOT. - $regCtx = if ($objType -eq "InformationRegister") { "register-info" } else { "register-other" } - # InformationRegister/AccumulationRegister: ресурсы/измерения — через богатый Emit-Attribute (общий слой - # object-свойств). Прочие регистры (Accounting/Calculation) — легаси Emit-Resource/Emit-Dimension (пока не портированы). - $dimResCtx = switch ($objType) { "InformationRegister" { "register-info" } "AccumulationRegister" { "register-accum" } default { $null } } + # InformationRegister.Attribute supports FillFromFillingValue/FillValue/DataHistory; прочие — нет. + # CalculationRegister.Attribute несёт → отдельный контекст register-calc. + $regCtx = switch ($objType) { "InformationRegister" { "register-info" } "CalculationRegister" { "register-calc" } default { "register-other" } } + # Все семейства регистров: ресурсы/измерения — через богатый Emit-Attribute (общий слой object-свойств). + $dimResCtx = switch ($objType) { "InformationRegister" { "register-info" } "AccumulationRegister" { "register-accum" } "CalculationRegister" { "register-calc" } "AccountingRegister" { "register-account" } default { $null } } foreach ($r in $resources) { if ($dimResCtx) { Emit-Attribute "`t`t`t" $r $dimResCtx "Resource" } else { Emit-Resource "`t`t`t" $r $objType } diff --git a/.claude/skills/meta-compile/scripts/meta-compile.py b/.claude/skills/meta-compile/scripts/meta-compile.py index 49c98a40..91de027e 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.46 — Compile 1C metadata object from JSON +# meta-compile v1.47 — Compile 1C metadata object from JSON # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse @@ -870,6 +870,11 @@ def parse_attribute_shorthand(val): 'mainFilter': val.get('mainFilter') is True, 'denyIncompleteValues': val.get('denyIncompleteValues') is True, 'useInTotals': (val.get('useInTotals') is True) if val.get('useInTotals') is not None else True, + 'baseDimension': val.get('baseDimension') is True, + 'scheduleLink': val.get('scheduleLink'), + 'balance': val.get('balance') is True, + 'accountingFlag': val.get('accountingFlag'), + 'extDimensionAccountingFlag': val.get('extDimensionAccountingFlag'), } def parse_enum_value_shorthand(val): @@ -1106,7 +1111,17 @@ def emit_standard_attribute(indent, attr_name, ov=None): efmt = ov.get('EditFormat') chi = ov.get('ChoiceHistoryOnInput', 'Auto') X(f'{indent}') - X(f'{indent}\t') + # LinkByType стандартного реквизита (напр. ExtDimensionN→Account у регистра бухгалтерии). DataPath verbatim. + lbt = ov.get('LinkByType') + if lbt: + lbt_dp = str(lbt.get('dataPath')) if isinstance(lbt, dict) else str(lbt) + lbt_li = lbt.get('linkItem', 0) if isinstance(lbt, dict) else 0 + X(f'{indent}\t') + X(f'{indent}\t\t{esc_xml(lbt_dp)}') + X(f'{indent}\t\t{lbt_li}') + X(f'{indent}\t') + else: + X(f'{indent}\t') X(f'{indent}\t{fc}') X(f'{indent}\tfalse') X(f'{indent}\t{ffv}') @@ -1201,6 +1216,8 @@ def emit_standard_attributes(indent, object_type): ov['EditFormat'] = d['editFormat'] if d.get('choiceForm'): ov['ChoiceForm'] = str(d['choiceForm']) + if d.get('linkByType') is not None: + ov['LinkByType'] = d['linkByType'] emit_standard_attribute(f'{indent}\t', a, ov) X(f'{indent}') @@ -1681,10 +1698,10 @@ def emit_attribute(indent, parsed, context, elem_tag='Attribute'): emit_min_max_value(f'{indent}\t\t', 'MaxValue', parsed.get('maxValue')) # FillFromFillingValue / FillValue — not for tabular/processor/chart/register-other # (Chart*, AccumulationRegister/AccountingRegister/CalculationRegister don't support these) - if context not in ('tabular', 'processor', 'chart', 'register-other', 'register-accum'): + if context not in ('tabular', 'processor', 'chart', 'register-other', 'register-accum', 'register-calc', 'register-account'): ffv = 'true' if (parsed.get('fillFromFillingValue') is True or (elem_tag == 'Dimension' and 'master' in parsed.get('flags', []))) else 'false' X(f'{indent}\t\t{ffv}') - if context not in ('tabular', 'processor', 'chart', 'register-other', 'register-accum'): + if context not in ('tabular', 'processor', 'chart', 'register-other', 'register-accum', 'register-calc', 'register-account'): emit_fill_value(f'{indent}\t\t', type_str, parsed.get('fillValue'), parsed.get('hasFillValue')) fill_checking = 'DontCheck' if 'req' in parsed.get('flags', []): @@ -1713,13 +1730,41 @@ def emit_attribute(indent, parsed, context, elem_tag='Attribute'): if elem_tag == 'Dimension' and context == 'register-accum': deny_incomplete = 'true' if (parsed.get('denyIncompleteValues') is True or 'denyincomplete' in parsed.get('flags', [])) else 'false' X(f'{indent}\t\t{deny_incomplete}') + # Измерение регистра расчёта: DenyIncompleteValues + BaseDimension. + if elem_tag == 'Dimension' and context == 'register-calc': + deny_incomplete = 'true' if (parsed.get('denyIncompleteValues') is True or 'denyincomplete' in parsed.get('flags', [])) else 'false' + base_dimension = 'true' if (parsed.get('baseDimension') is True or 'base' in parsed.get('flags', [])) else 'false' + X(f'{indent}\t\t{deny_incomplete}') + X(f'{indent}\t\t{base_dimension}') + # Регистр расчёта: ScheduleLink у измерений и реквизитов (НЕ ресурсов), перед Indexing. Дефолт пустой. + if context == 'register-calc' and elem_tag in ('Dimension', 'Attribute'): + if parsed.get('scheduleLink'): + X(f'{indent}\t\t{esc_xml(str(parsed["scheduleLink"]))}') + else: + X(f'{indent}\t\t') + # Измерение/ресурс регистра бухгалтерии: Balance + AccountingFlag, затем DenyIncompleteValues (изм.) / ExtDimensionAccountingFlag (рес.). + if context == 'register-account' and elem_tag in ('Dimension', 'Resource'): + balance = 'true' if (parsed.get('balance') is True or 'balance' in parsed.get('flags', [])) else 'false' + X(f'{indent}\t\t{balance}') + if parsed.get('accountingFlag'): + X(f'{indent}\t\t{esc_xml(str(parsed["accountingFlag"]))}') + else: + X(f'{indent}\t\t') + if elem_tag == 'Dimension': + deny_incomplete = 'true' if (parsed.get('denyIncompleteValues') is True or 'denyincomplete' in parsed.get('flags', [])) else 'false' + X(f'{indent}\t\t{deny_incomplete}') + else: + if parsed.get('extDimensionAccountingFlag'): + X(f'{indent}\t\t{esc_xml(str(parsed["extDimensionAccountingFlag"]))}') + else: + X(f'{indent}\t\t') if context == 'catalog': X(f'{indent}\t\t{parsed.get("use") or "ForItem"}') if context not in ('processor', 'processor-tabular'): # Признаки учёта ПС (account-flag) не имеют /, но имеют . if context != 'account-flag': # Ресурс регистра накопления НЕ имеет (только ); измерение/реквизит — имеют. - if not (context == 'register-accum' and elem_tag == 'Resource'): + if not (context in ('register-accum', 'register-calc', 'register-account') and elem_tag == 'Resource'): indexing = 'DontIndex' if 'index' in parsed.get('flags', []): indexing = 'Index' @@ -1734,7 +1779,7 @@ def emit_attribute(indent, parsed, context, elem_tag='Attribute'): use_in_totals = 'false' if (parsed.get('useInTotals') is False or 'nouseintotals' in parsed.get('flags', [])) else 'true' X(f'{indent}\t\t{use_in_totals}') # DataHistory — not for Chart* types and non-InformationRegister register family - if context not in ('chart', 'register-other', 'register-accum'): + if context not in ('chart', 'register-other', 'register-accum', 'register-calc', 'register-account'): X(f'{indent}\t\t{parsed.get("dataHistory") or "Use"}') X(f'{indent}\t') X(f'{indent}') @@ -2802,28 +2847,32 @@ def emit_accounting_register_properties(indent): i = indent X(f'{i}{esc_xml(obj_name)}') emit_mltext(i, 'Synonym', synonym) - X(f'{i}') - X(f'{i}true') - X(f'{i}') - X(f'{i}') + if defn.get('comment'): + X(f'{i}{esc_xml_text(str(defn["comment"]))}') + else: + X(f'{i}') + X(f'{i}{"true" if get_bool_prop("useStandardCommands", True) else "false"}') + X(f'{i}{"true" if get_bool_prop("includeHelpInContents", False) else "false"}') chart_of_accounts = str(defn['chartOfAccounts']) if defn.get('chartOfAccounts') else '' if chart_of_accounts: - X(f'{i}{chart_of_accounts}') + X(f'{i}{esc_xml(chart_of_accounts)}') else: X(f'{i}') correspondence = 'true' if defn.get('correspondence') is True else 'false' X(f'{i}{correspondence}') period_adj_len = str(defn['periodAdjustmentLength']) if defn.get('periodAdjustmentLength') is not None else '0' X(f'{i}{period_adj_len}') - X(f'{i}false') + emit_form_ref(i, 'DefaultListForm', defn.get('defaultListForm')) + emit_form_ref(i, 'AuxiliaryListForm', defn.get('auxiliaryListForm')) emit_standard_attributes(i, 'AccountingRegister') data_lock_control_mode = get_enum_prop('DataLockControlMode', 'dataLockControlMode', 'Automatic') X(f'{i}{data_lock_control_mode}') + X(f'{i}{"false" if defn.get("enableTotalsSplitting") is False else "true"}') full_text_search = get_enum_prop('FullTextSearch', 'fullTextSearch', 'Use') X(f'{i}{full_text_search}') - X(f'{i}') - X(f'{i}') - X(f'{i}') + emit_mltext(i, 'ListPresentation', defn.get('listPresentation')) + emit_mltext(i, 'ExtendedListPresentation', defn.get('extendedListPresentation')) + emit_mltext(i, 'Explanation', defn.get('explanation')) # Стандартные ТЧ ПВР: Ведущие/Вытесняющие/Базовые виды расчёта (обёртка платформенно-константна, пустой lang; # вложены Predefined/CalculationType(ShowError)/LineNumber). @@ -2925,15 +2974,13 @@ def emit_calculation_register_properties(indent): i = indent X(f'{i}{esc_xml(obj_name)}') emit_mltext(i, 'Synonym', synonym) - X(f'{i}') - X(f'{i}true') - X(f'{i}') - X(f'{i}') - chart_of_calc_types = str(defn['chartOfCalculationTypes']) if defn.get('chartOfCalculationTypes') else '' - if chart_of_calc_types: - X(f'{i}{chart_of_calc_types}') + if defn.get('comment'): + X(f'{i}{esc_xml_text(str(defn["comment"]))}') else: - X(f'{i}') + X(f'{i}') + X(f'{i}{"true" if get_bool_prop("useStandardCommands", True) else "false"}') + emit_form_ref(i, 'DefaultListForm', defn.get('defaultListForm')) + emit_form_ref(i, 'AuxiliaryListForm', defn.get('auxiliaryListForm')) periodicity = get_enum_prop('InformationRegisterPeriodicity', 'periodicity', 'Month') X(f'{i}{periodicity}') action_period = 'true' if defn.get('actionPeriod') is True else 'false' @@ -2942,28 +2989,33 @@ def emit_calculation_register_properties(indent): X(f'{i}{base_period}') schedule = str(defn['schedule']) if defn.get('schedule') else '' if schedule: - X(f'{i}{schedule}') + X(f'{i}{esc_xml(schedule)}') else: X(f'{i}') schedule_value = str(defn['scheduleValue']) if defn.get('scheduleValue') else '' if schedule_value: - X(f'{i}{schedule_value}') + X(f'{i}{esc_xml(schedule_value)}') else: X(f'{i}') schedule_date = str(defn['scheduleDate']) if defn.get('scheduleDate') else '' if schedule_date: - X(f'{i}{schedule_date}') + X(f'{i}{esc_xml(schedule_date)}') else: X(f'{i}') - X(f'{i}false') + chart_of_calc_types = str(defn['chartOfCalculationTypes']) if defn.get('chartOfCalculationTypes') else '' + if chart_of_calc_types: + X(f'{i}{esc_xml(chart_of_calc_types)}') + else: + X(f'{i}') + X(f'{i}{"true" if get_bool_prop("includeHelpInContents", False) else "false"}') emit_standard_attributes(i, 'CalculationRegister') data_lock_control_mode = get_enum_prop('DataLockControlMode', 'dataLockControlMode', 'Automatic') X(f'{i}{data_lock_control_mode}') full_text_search = get_enum_prop('FullTextSearch', 'fullTextSearch', 'Use') X(f'{i}{full_text_search}') - X(f'{i}') - X(f'{i}') - X(f'{i}') + emit_mltext(i, 'ListPresentation', defn.get('listPresentation')) + emit_mltext(i, 'ExtendedListPresentation', defn.get('extendedListPresentation')) + emit_mltext(i, 'Explanation', defn.get('explanation')) def emit_business_process_properties(indent): i = indent @@ -3503,12 +3555,12 @@ if obj_type in ('InformationRegister', 'AccumulationRegister', 'AccountingRegist if dims or resources or reg_attrs or reg_commands: has_children = True X('\t\t') - # InformationRegister.Attribute supports FillFromFillingValue/FillValue/DataHistory; - # AccumulationRegister/AccountingRegister/CalculationRegister.Attribute do NOT. - reg_ctx = 'register-info' if obj_type == 'InformationRegister' else 'register-other' - # InformationRegister/AccumulationRegister: ресурсы/измерения — через богатый emit_attribute (общий слой - # object-свойств). Прочие регистры (Accounting/Calculation) — легаси emit_resource/emit_dimension (не портированы). - dim_res_ctx = {'InformationRegister': 'register-info', 'AccumulationRegister': 'register-accum'}.get(obj_type) + # InformationRegister.Attribute несёт FillFromFillingValue/FillValue/DataHistory; CalculationRegister.Attribute + # несёт (register-calc); прочие — register-other. + reg_ctx = {'InformationRegister': 'register-info', 'CalculationRegister': 'register-calc'}.get(obj_type, 'register-other') + # Все семейства регистров: ресурсы/измерения — через богатый emit_attribute (общий слой object-свойств). + dim_res_ctx = {'InformationRegister': 'register-info', 'AccumulationRegister': 'register-accum', + 'CalculationRegister': 'register-calc', 'AccountingRegister': 'register-account'}.get(obj_type) for r in resources: if dim_res_ctx: emit_attribute('\t\t\t', r, dim_res_ctx, 'Resource') diff --git a/.claude/skills/meta-decompile/scripts/meta-decompile.ps1 b/.claude/skills/meta-decompile/scripts/meta-decompile.ps1 index 37522481..11c9d69f 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.38 — XML объекта метаданных 1С → JSON-черновик формата meta-compile +# meta-decompile v0.39 — XML объекта метаданных 1С → JSON-черновик формата meta-compile # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills # # Поддержаны: Catalog, ExchangePlan, ChartOfCharacteristicTypes, ChartOfAccounts, ChartOfCalculationTypes, Document. Инверс meta-compile (omit-on-default: ключ эмитим только @@ -91,8 +91,8 @@ foreach ($c in $rootEl.ChildNodes) { if ($c.NodeType -eq 'Element') { $objNode = if (-not $objNode) { [Console]::Error.WriteLine("meta-decompile: пустой MetaDataObject"); exit 3 } $objType = $objNode.LocalName -if ($objType -notin @('Catalog', 'ExchangePlan', 'ChartOfCharacteristicTypes', 'ChartOfAccounts', 'ChartOfCalculationTypes', 'Document', 'InformationRegister', 'AccumulationRegister')) { - [Console]::Error.WriteLine("meta-decompile: тип '$objType' пока не поддержан (Catalog, ExchangePlan, ChartOfCharacteristicTypes, ChartOfAccounts, ChartOfCalculationTypes, Document, InformationRegister, AccumulationRegister)"); exit 3 +if ($objType -notin @('Catalog', 'ExchangePlan', 'ChartOfCharacteristicTypes', 'ChartOfAccounts', 'ChartOfCalculationTypes', 'Document', 'InformationRegister', 'AccumulationRegister', 'AccountingRegister', 'CalculationRegister')) { + [Console]::Error.WriteLine("meta-decompile: тип '$objType' пока не поддержан (Catalog, ExchangePlan, ChartOfCharacteristicTypes, ChartOfAccounts, ChartOfCalculationTypes, Document, InformationRegister, AccumulationRegister, AccountingRegister, CalculationRegister)"); exit 3 } $props = $objNode.SelectSingleNode('md:Properties', $nsm) @@ -298,6 +298,11 @@ function Attr-ToDsl { $v = & $en 'MainFilter'; if ($v -eq 'true') { $extra['mainFilter'] = $true } $v = & $en 'DenyIncompleteValues'; if ($v -eq 'true') { $extra['denyIncompleteValues'] = $true } $v = & $en 'UseInTotals'; if ($v -eq 'false') { $extra['useInTotals'] = $false } # дефолт true → захват при false + $v = & $en 'BaseDimension'; if ($v -eq 'true') { $extra['baseDimension'] = $true } + $v = & $en 'ScheduleLink'; if ($v) { $extra['scheduleLink'] = $v } # ссылка на измерение графика (пустой → пропуск) + $v = & $en 'Balance'; if ($v -eq 'true') { $extra['balance'] = $true } + $v = & $en 'AccountingFlag'; if ($v) { $extra['accountingFlag'] = $v } # ссылка на признак учёта ПС (пустой → пропуск) + $v = & $en 'ExtDimensionAccountingFlag'; if ($v) { $extra['extDimensionAccountingFlag'] = $v } # MinValue/MaxValue — граница диапазона (omit при nil). Тип сохраняем: xs:string→строка, xs:decimal→число. foreach ($mm in @('MinValue','MaxValue')) { $mn = $ap.SelectSingleNode("md:$mm", $nsm) @@ -522,6 +527,23 @@ if ($objType -eq 'AccumulationRegister') { Add-EnumProp 'registerType' 'RegisterType' 'Balance' Add-BoolProp 'enableTotalsSplitting' 'EnableTotalsSplitting' $true } +# AccountingRegister-специфичные свойства: ПС-связь, корреспонденция, коррекция периода, разделение итогов. +if ($objType -eq 'AccountingRegister') { + $coa = P 'ChartOfAccounts'; if ($coa) { $dsl['chartOfAccounts'] = $coa } + Add-BoolProp 'correspondence' 'Correspondence' $false + Add-IntProp 'periodAdjustmentLength' 'PeriodAdjustmentLength' 0 + Add-BoolProp 'enableTotalsSplitting' 'EnableTotalsSplitting' $true +} +# CalculationRegister-специфичные свойства: ПВР-связь, периоды расчёта, график (все ссылки/enum — verbatim). +if ($objType -eq 'CalculationRegister') { + $cct = P 'ChartOfCalculationTypes'; if ($cct) { $dsl['chartOfCalculationTypes'] = $cct } + Add-EnumProp 'periodicity' 'Periodicity' 'Month' + Add-BoolProp 'actionPeriod' 'ActionPeriod' $false + Add-BoolProp 'basePeriod' 'BasePeriod' $false + $sch = P 'Schedule'; if ($sch) { $dsl['schedule'] = $sch } + $schv = P 'ScheduleValue'; if ($schv) { $dsl['scheduleValue'] = $schv } + $schd = P 'ScheduleDate'; if ($schd) { $dsl['scheduleDate'] = $schd } +} # Короткая форма поля: ..StandardAttribute.X / .Attribute.X → StandardAttribute.X / Attribute.X # (Expand-DataPath компилятора разворачивает частичную форму обратно — dogfood резолвера). @@ -705,12 +727,22 @@ if ($saNode) { $saCf = $sa.SelectSingleNode('xr:ChoiceForm', $nsm); if ($saCf -and $saCf.InnerText) { $ov['choiceForm'] = $saCf.InnerText } $saCpl = Parse-ChoiceParameterLinks $sa 'xr:ChoiceParameterLinks'; if ($null -ne $saCpl) { $ov['choiceParameterLinks'] = $saCpl } $saCp = Parse-ChoiceParameters $sa 'xr:ChoiceParameters'; if ($null -ne $saCp) { $ov['choiceParameters'] = $saCp } + # LinkByType стандартного реквизита (ExtDimensionN→Account у регистра бухгалтерии). DataPath полный verbatim. + $saLbt = $sa.SelectSingleNode('xr:LinkByType', $nsm) + if ($saLbt) { + $saLbtDp = $saLbt.SelectSingleNode('xr:DataPath', $nsm) + if ($saLbtDp -and $saLbtDp.InnerText) { + $saLbtLi = $saLbt.SelectSingleNode('xr:LinkItem', $nsm) + $li = if ($saLbtLi -and $saLbtLi.InnerText) { [int]$saLbtLi.InnerText } else { 0 } + $ov['linkByType'] = [ordered]@{ dataPath = $saLbtDp.InnerText; linkItem = $li } + } + } # Доп./опциональный реквизит (не в фикс-списке) — эмитим по присутствию даже без отклонений. if ($ov.Count -gt 0 -or ($stdFixed -notcontains $an)) { $saMap[$an] = $ov } } # Условный тип (Catalog): пустой $saMap = триггер блока. Не-условный (ExchangePlan): блок и так эмитится → пустой не пишем. if ($saMap.Count -gt 0 -or ($stdConditionalTypes -contains $objType)) { $dsl['standardAttributes'] = $saMap } -} elseif ($objType -in @('InformationRegister', 'AccumulationRegister')) { +} elseif ($objType -in @('InformationRegister', 'AccumulationRegister', 'AccountingRegister', 'CalculationRegister')) { # Регистр опускает all-default блок стандартных реквизитов (~5-9%, правило не выводимо) — компилятор эмитит его # по дефолту, поэтому отсутствие фиксируем opt-out `standardAttributes:""` (дом-конвенция суппресса). $dsl['standardAttributes'] = '' diff --git a/docs/meta-dsl-spec.md b/docs/meta-dsl-spec.md index 78bdd1b8..0c454755 100644 --- a/docs/meta-dsl-spec.md +++ b/docs/meta-dsl-spec.md @@ -854,6 +854,37 @@ choiceParameters/indexing/fullTextSearch/dataHistory/…, см. §3–4). При Признаки измерения — флаги shorthand (`denyIncomplete`, `nouseintotals`) ЛИБО object-ключи (`denyIncompleteValues`, `useInTotals`: bool, дефолт true). Ресурс РН НЕ имеет `` (только ``). +### 7.6a AccountingRegister (Регистр бухгалтерии) + +| Поле JSON | Умолчание | XML элемент | +|-----------|----------|-------------| +| `chartOfAccounts` | пусто | ChartOfAccounts (MDObjectRef `ChartOfAccounts.X`) | +| `correspondence` | `false` | Correspondence (bool) | +| `periodAdjustmentLength` | `0` | PeriodAdjustmentLength (int) | +| `enableTotalsSplitting` | `true` | EnableTotalsSplitting | +| `dataLockControlMode` | `Automatic` | DataLockControlMode | +| общие (comment/useStandardCommands/includeHelpInContents/defaultListForm/auxiliaryListForm/презентации ML) | — | — | +| `dimensions` / `resources` / `attributes` / `commands` | `[]` | → ChildObjects | + +Измерения/ресурсы РБ несут `balance` (bool), `accountingFlag` (ссылка `ChartOfAccounts.X.AccountingFlag.Y`); +ресурсы дополнительно `extDimensionAccountingFlag`, измерения — `denyIncompleteValues`. Стандартные реквизиты +ExtDimension1..N связаны с Account через `linkByType` (в блоке `standardAttributes`, §7.1.1; DataPath полный). + +### 7.6b CalculationRegister (Регистр расчёта) + +| Поле JSON | Умолчание | XML элемент | +|-----------|----------|-------------| +| `chartOfCalculationTypes` | пусто | ChartOfCalculationTypes (ссылка) | +| `periodicity` | `Month` | Periodicity | +| `actionPeriod` / `basePeriod` | `false` | ActionPeriod / BasePeriod (bool) | +| `schedule` / `scheduleValue` / `scheduleDate` | пусто | Schedule* (ссылки на регистр-график и его поля) | +| `dataLockControlMode` | `Automatic` | DataLockControlMode | +| общие (comment/useStandardCommands/includeHelpInContents/defaultListForm/auxiliaryListForm/презентации ML) | — | — | +| `dimensions` / `resources` / `attributes` / `commands` | `[]` | → ChildObjects | + +Измерения РР несут `denyIncompleteValues`, `baseDimension` (bool), `scheduleLink` (ссылка на измерение графика); +реквизиты — `scheduleLink`; ресурсы — только `` (без Indexing). + ### 7.7 DefinedType | Поле JSON | Умолчание | XML элемент | diff --git a/tests/skills/cases/meta-compile/snapshots/accounting-register/AccountingRegisters/Хозрасчетный.xml b/tests/skills/cases/meta-compile/snapshots/accounting-register/AccountingRegisters/Хозрасчетный.xml index 81c294a9..1c907b95 100644 --- a/tests/skills/cases/meta-compile/snapshots/accounting-register/AccountingRegisters/Хозрасчетный.xml +++ b/tests/skills/cases/meta-compile/snapshots/accounting-register/AccountingRegisters/Хозрасчетный.xml @@ -41,12 +41,12 @@ true - - + false ChartOfAccounts.Хозрасчетный true 0 - false + + @@ -180,6 +180,7 @@ Automatic + true Use @@ -223,6 +224,10 @@ Auto + false + + + Use @@ -257,6 +262,9 @@ Auto + false + + false DontIndex Use diff --git a/tests/skills/cases/meta-compile/snapshots/calculation-register/CalculationRegisters/Начисления.xml b/tests/skills/cases/meta-compile/snapshots/calculation-register/CalculationRegisters/Начисления.xml index da2c690f..f6969bb7 100644 --- a/tests/skills/cases/meta-compile/snapshots/calculation-register/CalculationRegisters/Начисления.xml +++ b/tests/skills/cases/meta-compile/snapshots/calculation-register/CalculationRegisters/Начисления.xml @@ -43,13 +43,13 @@ true - ChartOfCalculationTypes.ВидыНачислений Month false false + ChartOfCalculationTypes.ВидыНачислений false @@ -253,6 +253,7 @@ Auto + Use @@ -292,6 +293,7 @@ Auto + Use @@ -326,6 +328,9 @@ Auto + false + false + DontIndex Use @@ -366,6 +371,7 @@ Auto + DontIndex Use