feat(meta-compile,meta-decompile): поддержка Sequence + FilterCriterion + DocumentNumerator + SettingsStorage (v1.56/v0.47)

20-23-й типы (хвост «мелких» служебных), 64 объекта acc×3+erp. Все НОВЫЕ (компилятор
не поддерживал). ПОЛНЫЙ КОРПУС 64/64 match, TOTAL 0 — byte-exact order-preserved.
Регресс 56/56 ps1+py, ps1==py identical.

- **Sequence** (последовательность документов): InternalInfo(Record/Manager/RecordSet)
  + MoveBoundaryOnPosting(дефолт DontMove)/Documents/RegisterRecords/DataLockControlMode
  (дефолт Automatic). Измерения с **DocumentMap/RegisterRecordsMap** (списки MDObjectRef —
  соответствие реквизитам документов/движениям) — гард общего dimensions-захвата,
  объектная форма измерения. Общий хелпер Emit-MDRefList.
- **FilterCriterion** (критерий отбора): InternalInfo(Manager/List) + Type(составной) +
  Content(объекты отбора) + формы + презентации. Несёт <Command> → эмиссия команд.
- **DocumentNumerator** (нумератор): БЕЗ InternalInfo/ChildObjects. NumberType/Length/
  AllowedLength/Periodicity/CheckUnique (дефолты String/11/Variable/Year/true).
- **SettingsStorage** (хранилище настроек): InternalInfo(Manager) + Default/Auxiliary
  Save/LoadForm (verbatim). Пустой ChildObjects (Form вне скоупа).

Прощающий ввод MDObjectRef (Documents/Content/documentMap) — Normalize-MDObjectRef.
spec §7.15a-d, кейсы sequence/filter-criterion/document-numerator/settings-storage.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Nick Shirokov
2026-07-10 11:12:53 +03:00
co-authored by Claude Opus 4.8
parent b4e6037fd4
commit f4fb260f68
24 changed files with 1788 additions and 10 deletions
@@ -1,4 +1,4 @@
# meta-compile v1.55 — Compile 1C metadata object from JSON
# meta-compile v1.56 — Compile 1C metadata object from JSON
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
param(
[Parameter(Mandatory)]
@@ -347,7 +347,8 @@ $validTypes = @("Catalog","Document","Enum","Constant","InformationRegister","Ac
"AccountingRegister","CalculationRegister","ChartOfAccounts","ChartOfCharacteristicTypes",
"ChartOfCalculationTypes","BusinessProcess","Task","ExchangePlan","DocumentJournal",
"Report","DataProcessor","CommonModule","ScheduledJob","EventSubscription",
"HTTPService","WebService","DefinedType","FunctionalOption")
"HTTPService","WebService","DefinedType","FunctionalOption",
"Sequence","FilterCriterion","DocumentNumerator","SettingsStorage")
if ($objType -notin $validTypes) {
Write-Error "Unsupported type: $objType. Valid: $($validTypes -join ', ')"
exit 1
@@ -1084,6 +1085,18 @@ $script:generatedTypes = @{
@{ prefix = "DataProcessorObject"; category = "Object" }
@{ prefix = "DataProcessorManager"; category = "Manager" }
)
"Sequence" = @(
@{ prefix = "SequenceRecord"; category = "Record" }
@{ prefix = "SequenceManager"; category = "Manager" }
@{ prefix = "SequenceRecordSet"; category = "RecordSet" }
)
"FilterCriterion" = @(
@{ prefix = "FilterCriterionManager"; category = "Manager" }
@{ prefix = "FilterCriterionList"; category = "List" }
)
"SettingsStorage" = @(
@{ prefix = "SettingsStorageManager"; category = "Manager" }
)
}
function Emit-InternalInfo {
@@ -2523,6 +2536,104 @@ function Emit-FunctionalOptionProperties {
}
}
# Общий эмиттер списка MDObjectRef (Documents/RegisterRecords с обёрткой <xr:Item>). omit-on-empty.
function Emit-MDRefList {
param([string]$indent, [string]$tag, $items)
$arr = @(); if ($items) { $arr = @($items) }
if ($arr.Count -gt 0) {
X "$indent<$tag>"
foreach ($it in $arr) { X "$indent`t<xr:Item xsi:type=`"xr:MDObjectRef`">$(Esc-Xml (Normalize-MDObjectRef "$it"))</xr:Item>" }
X "$indent</$tag>"
} else {
X "$indent<$tag/>"
}
}
function Emit-SequenceProperties {
param([string]$indent)
$i = $indent
X "$i<Name>$(Esc-Xml $objName)</Name>"
Emit-MLText $i "Synonym" $synonym
if ($def.comment) { X "$i<Comment>$(Esc-XmlText $def.comment)</Comment>" } else { X "$i<Comment/>" }
X "$i<MoveBoundaryOnPosting>$(Get-EnumProp 'MoveBoundaryOnPosting' 'moveBoundaryOnPosting' 'DontMove')</MoveBoundaryOnPosting>"
Emit-MDRefList $i "Documents" $def.documents
Emit-MDRefList $i "RegisterRecords" $def.registerRecords
X "$i<DataLockControlMode>$(Get-EnumProp 'DataLockControlMode' 'dataLockControlMode' 'Automatic')</DataLockControlMode>"
}
function Emit-FilterCriterionProperties {
param([string]$indent)
$i = $indent
X "$i<Name>$(Esc-Xml $objName)</Name>"
Emit-MLText $i "Synonym" $synonym
if ($def.comment) { X "$i<Comment>$(Esc-XmlText $def.comment)</Comment>" } else { X "$i<Comment/>" }
$vt = if ($def.valueType) { "$($def.valueType)" } elseif ($def.valueTypes) { (@($def.valueTypes) | ForEach-Object { "$_" }) -join ' + ' } else { '' }
if ($vt) { Emit-ValueType $i $vt } else { X "$i<Type/>" }
$useStdCmds = if (Get-BoolProp "useStandardCommands" $true) { "true" } else { "false" }
X "$i<UseStandardCommands>$useStdCmds</UseStandardCommands>"
# Content — объекты (реквизиты), по которым идёт отбор.
$content = @(); if ($def.content) { $content = @($def.content) }
if ($content.Count -gt 0) {
X "$i<Content>"
foreach ($obj in $content) { X "$i`t<xr:Item xsi:type=`"xr:MDObjectRef`">$(Esc-Xml (Normalize-MDObjectRef "$obj"))</xr:Item>" }
X "$i</Content>"
} else {
X "$i<Content/>"
}
Emit-VerbatimRef $i "DefaultForm" $def.defaultForm
Emit-VerbatimRef $i "AuxiliaryForm" $def.auxiliaryForm
Emit-MLText $i "ListPresentation" $def.listPresentation
Emit-MLText $i "ExtendedListPresentation" $def.extendedListPresentation
Emit-MLText $i "Explanation" $def.explanation
}
function Emit-DocumentNumeratorProperties {
param([string]$indent)
$i = $indent
X "$i<Name>$(Esc-Xml $objName)</Name>"
Emit-MLText $i "Synonym" $synonym
if ($def.comment) { X "$i<Comment>$(Esc-XmlText $def.comment)</Comment>" } else { X "$i<Comment/>" }
X "$i<NumberType>$(Get-EnumProp 'NumberType' 'numberType' 'String')</NumberType>"
X "$i<NumberLength>$(if ($null -ne $def.numberLength) { "$($def.numberLength)" } else { '11' })</NumberLength>"
X "$i<NumberAllowedLength>$(Get-EnumProp 'NumberAllowedLength' 'numberAllowedLength' 'Variable')</NumberAllowedLength>"
X "$i<NumberPeriodicity>$(Get-EnumProp 'NumberPeriodicity' 'numberPeriodicity' 'Year')</NumberPeriodicity>"
X "$i<CheckUnique>$(if (Get-BoolProp 'checkUnique' $true) { 'true' } else { 'false' })</CheckUnique>"
}
function Emit-SettingsStorageProperties {
param([string]$indent)
$i = $indent
X "$i<Name>$(Esc-Xml $objName)</Name>"
Emit-MLText $i "Synonym" $synonym
if ($def.comment) { X "$i<Comment>$(Esc-XmlText $def.comment)</Comment>" } else { X "$i<Comment/>" }
Emit-VerbatimRef $i "DefaultSaveForm" $def.defaultSaveForm
Emit-VerbatimRef $i "DefaultLoadForm" $def.defaultLoadForm
Emit-VerbatimRef $i "AuxiliarySaveForm" $def.auxiliarySaveForm
Emit-VerbatimRef $i "AuxiliaryLoadForm" $def.auxiliaryLoadForm
}
# Измерение последовательности: Name/Synonym/Comment/Type + DocumentMap/RegisterRecordsMap (списки MDObjectRef —
# соответствие измерения реквизитам документов/движениям регистров).
function Emit-SequenceDimension {
param([string]$indent, $dimDef)
$uuid = New-Guid-String
$parsed = Parse-AttributeShorthand $dimDef
X "$indent<Dimension uuid=`"$uuid`">"
X "$indent`t<Properties>"
X "$indent`t`t<Name>$(Esc-Xml $parsed.name)</Name>"
Emit-MLText "$indent`t`t" "Synonym" $parsed.synonym
if ($parsed.comment) { X "$indent`t`t<Comment>$(Esc-XmlText $parsed.comment)</Comment>" } else { X "$indent`t`t<Comment/>" }
if ($parsed.typeEmpty) { X "$indent`t`t<Type/>" }
elseif ($parsed.type) { Emit-ValueType "$indent`t`t" $parsed.type }
else { X "$indent`t`t<Type/>" }
$dm = if ($dimDef -is [string]) { $null } else { $dimDef.documentMap }
$rrm = if ($dimDef -is [string]) { $null } else { $dimDef.registerRecordsMap }
Emit-MDRefList "$indent`t`t" "DocumentMap" $dm
Emit-MDRefList "$indent`t`t" "RegisterRecordsMap" $rrm
X "$indent`t</Properties>"
X "$indent</Dimension>"
}
function Emit-CommonModuleProperties {
param([string]$indent)
$i = $indent
@@ -3606,6 +3717,10 @@ switch ($objType) {
"AccumulationRegister" { Emit-AccumulationRegisterProperties "`t`t`t" }
"DefinedType" { Emit-DefinedTypeProperties "`t`t`t" }
"FunctionalOption" { Emit-FunctionalOptionProperties "`t`t`t" }
"Sequence" { Emit-SequenceProperties "`t`t`t" }
"FilterCriterion" { Emit-FilterCriterionProperties "`t`t`t" }
"DocumentNumerator" { Emit-DocumentNumeratorProperties "`t`t`t" }
"SettingsStorage" { Emit-SettingsStorageProperties "`t`t`t" }
"CommonModule" { Emit-CommonModuleProperties "`t`t`t" }
"ScheduledJob" { Emit-ScheduledJobProperties "`t`t`t" }
"EventSubscription" { Emit-EventSubscriptionProperties "`t`t`t" }
@@ -3826,6 +3941,41 @@ if ($objType -eq "DocumentJournal") {
}
}
# --- Sequence: dimensions ---
if ($objType -eq "Sequence") {
$seqDims = @()
if ($def.dimensions) { $seqDims = @($def.dimensions) }
if ($seqDims.Count -gt 0) {
$hasChildren = $true
X "`t`t<ChildObjects>"
foreach ($d in $seqDims) { Emit-SequenceDimension "`t`t`t" $d }
X "`t`t</ChildObjects>"
} else {
X "`t`t<ChildObjects/>"
}
}
# --- FilterCriterion / SettingsStorage: ChildObjects (формы вне скоупа; FilterCriterion может нести <Command>) ---
if ($objType -in @("FilterCriterion", "SettingsStorage")) {
$fcCommands = @()
if ($def.commands) {
if ($def.commands -is [array] -or $def.commands.GetType().Name -eq 'Object[]') {
foreach ($c in $def.commands) { $fcCommands += @{ name = "$($c.name)"; def = $c } }
} else {
$def.commands.PSObject.Properties | ForEach-Object { $fcCommands += @{ name = $_.Name; def = $_.Value } }
}
}
if ($fcCommands.Count -gt 0) {
$hasChildren = $true
X "`t`t<ChildObjects>"
foreach ($cmd in $fcCommands) { Emit-Command "`t`t`t" $cmd.name $cmd.def }
X "`t`t</ChildObjects>"
} else {
X "`t`t<ChildObjects/>"
}
}
# DocumentNumerator: ChildObjects нет вовсе (не эмитим).
# --- HTTPService: URLTemplates ---
if ($objType -eq "HTTPService") {
$urlTemplates = @{}
@@ -3901,6 +4051,10 @@ $script:typePluralMap = @{
"WebService" = "WebServices"
"DefinedType" = "DefinedTypes"
"FunctionalOption" = "FunctionalOptions"
"Sequence" = "Sequences"
"FilterCriterion" = "FilterCriteria"
"DocumentNumerator" = "DocumentNumerators"
"SettingsStorage" = "SettingsStorages"
}
$typePlural = $script:typePluralMap[$objType]
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
# meta-compile v1.55 — Compile 1C metadata object from JSON
# meta-compile v1.56 — Compile 1C metadata object from JSON
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
import argparse
@@ -462,6 +462,7 @@ valid_types = [
'Report', 'DataProcessor', 'CommonModule', 'ScheduledJob',
'EventSubscription', 'HTTPService', 'WebService', 'DefinedType',
'FunctionalOption',
'Sequence', 'FilterCriterion', 'DocumentNumerator', 'SettingsStorage',
]
if obj_type not in valid_types:
print(f"Unsupported type: {obj_type}. Valid: {', '.join(valid_types)}", file=sys.stderr)
@@ -1104,6 +1105,18 @@ generated_types = {
{'prefix': 'DataProcessorObject', 'category': 'Object'},
{'prefix': 'DataProcessorManager', 'category': 'Manager'},
],
'Sequence': [
{'prefix': 'SequenceRecord', 'category': 'Record'},
{'prefix': 'SequenceManager', 'category': 'Manager'},
{'prefix': 'SequenceRecordSet', 'category': 'RecordSet'},
],
'FilterCriterion': [
{'prefix': 'FilterCriterionManager', 'category': 'Manager'},
{'prefix': 'FilterCriterionList', 'category': 'List'},
],
'SettingsStorage': [
{'prefix': 'SettingsStorageManager', 'category': 'Manager'},
],
}
def emit_internal_info(indent, object_type, object_name):
@@ -2521,6 +2534,116 @@ def emit_functional_option_properties(indent):
else:
X(f'{i}<Content/>')
def emit_md_ref_list(indent, tag, items):
"""Список MDObjectRef (Documents/RegisterRecords/DocumentMap/…) с <xr:Item>. omit-on-empty."""
arr = list(items) if items else []
if arr:
X(f'{indent}<{tag}>')
for it in arr:
X(f'{indent}\t<xr:Item xsi:type="xr:MDObjectRef">{esc_xml(normalize_md_object_ref(str(it)))}</xr:Item>')
X(f'{indent}</{tag}>')
else:
X(f'{indent}<{tag}/>')
def emit_sequence_properties(indent):
i = indent
X(f'{i}<Name>{esc_xml(obj_name)}</Name>')
emit_mltext(i, 'Synonym', synonym)
if defn.get('comment'):
X(f'{i}<Comment>{esc_xml_text(str(defn["comment"]))}</Comment>')
else:
X(f'{i}<Comment/>')
X(f'{i}<MoveBoundaryOnPosting>{get_enum_prop("MoveBoundaryOnPosting", "moveBoundaryOnPosting", "DontMove")}</MoveBoundaryOnPosting>')
emit_md_ref_list(i, 'Documents', defn.get('documents'))
emit_md_ref_list(i, 'RegisterRecords', defn.get('registerRecords'))
X(f'{i}<DataLockControlMode>{get_enum_prop("DataLockControlMode", "dataLockControlMode", "Automatic")}</DataLockControlMode>')
def emit_filter_criterion_properties(indent):
i = indent
X(f'{i}<Name>{esc_xml(obj_name)}</Name>')
emit_mltext(i, 'Synonym', synonym)
if defn.get('comment'):
X(f'{i}<Comment>{esc_xml_text(str(defn["comment"]))}</Comment>')
else:
X(f'{i}<Comment/>')
if defn.get('valueType'):
vt = str(defn['valueType'])
elif defn.get('valueTypes'):
vt = ' + '.join(str(x) for x in defn['valueTypes'])
else:
vt = ''
if vt:
emit_value_type(i, vt)
else:
X(f'{i}<Type/>')
use_std_cmds = 'true' if get_bool_prop('useStandardCommands', True) else 'false'
X(f'{i}<UseStandardCommands>{use_std_cmds}</UseStandardCommands>')
content = list(defn['content']) if defn.get('content') else []
if content:
X(f'{i}<Content>')
for obj in content:
X(f'{i}\t<xr:Item xsi:type="xr:MDObjectRef">{esc_xml(normalize_md_object_ref(str(obj)))}</xr:Item>')
X(f'{i}</Content>')
else:
X(f'{i}<Content/>')
emit_verbatim_ref(i, 'DefaultForm', defn.get('defaultForm'))
emit_verbatim_ref(i, 'AuxiliaryForm', defn.get('auxiliaryForm'))
emit_mltext(i, 'ListPresentation', defn.get('listPresentation'))
emit_mltext(i, 'ExtendedListPresentation', defn.get('extendedListPresentation'))
emit_mltext(i, 'Explanation', defn.get('explanation'))
def emit_document_numerator_properties(indent):
i = indent
X(f'{i}<Name>{esc_xml(obj_name)}</Name>')
emit_mltext(i, 'Synonym', synonym)
if defn.get('comment'):
X(f'{i}<Comment>{esc_xml_text(str(defn["comment"]))}</Comment>')
else:
X(f'{i}<Comment/>')
X(f'{i}<NumberType>{get_enum_prop("NumberType", "numberType", "String")}</NumberType>')
num_len = str(defn['numberLength']) if defn.get('numberLength') is not None else '11'
X(f'{i}<NumberLength>{num_len}</NumberLength>')
X(f'{i}<NumberAllowedLength>{get_enum_prop("NumberAllowedLength", "numberAllowedLength", "Variable")}</NumberAllowedLength>')
X(f'{i}<NumberPeriodicity>{get_enum_prop("NumberPeriodicity", "numberPeriodicity", "Year")}</NumberPeriodicity>')
X(f'{i}<CheckUnique>{"true" if get_bool_prop("checkUnique", True) else "false"}</CheckUnique>')
def emit_settings_storage_properties(indent):
i = indent
X(f'{i}<Name>{esc_xml(obj_name)}</Name>')
emit_mltext(i, 'Synonym', synonym)
if defn.get('comment'):
X(f'{i}<Comment>{esc_xml_text(str(defn["comment"]))}</Comment>')
else:
X(f'{i}<Comment/>')
emit_verbatim_ref(i, 'DefaultSaveForm', defn.get('defaultSaveForm'))
emit_verbatim_ref(i, 'DefaultLoadForm', defn.get('defaultLoadForm'))
emit_verbatim_ref(i, 'AuxiliarySaveForm', defn.get('auxiliarySaveForm'))
emit_verbatim_ref(i, 'AuxiliaryLoadForm', defn.get('auxiliaryLoadForm'))
def emit_sequence_dimension(indent, dim_def):
uid = new_uuid()
parsed = parse_attribute_shorthand(dim_def)
X(f'{indent}<Dimension uuid="{uid}">')
X(f'{indent}\t<Properties>')
X(f'{indent}\t\t<Name>{esc_xml(parsed["name"])}</Name>')
emit_mltext(f'{indent}\t\t', 'Synonym', parsed['synonym'])
if parsed.get('comment'):
X(f'{indent}\t\t<Comment>{esc_xml_text(parsed["comment"])}</Comment>')
else:
X(f'{indent}\t\t<Comment/>')
if parsed.get('typeEmpty'):
X(f'{indent}\t\t<Type/>')
elif parsed['type']:
emit_value_type(f'{indent}\t\t', parsed['type'])
else:
X(f'{indent}\t\t<Type/>')
dm = None if isinstance(dim_def, str) else dim_def.get('documentMap')
rrm = None if isinstance(dim_def, str) else dim_def.get('registerRecordsMap')
emit_md_ref_list(f'{indent}\t\t', 'DocumentMap', dm)
emit_md_ref_list(f'{indent}\t\t', 'RegisterRecordsMap', rrm)
X(f'{indent}\t</Properties>')
X(f'{indent}</Dimension>')
def emit_common_module_properties(indent):
i = indent
X(f'{i}<Name>{esc_xml(obj_name)}</Name>')
@@ -3467,6 +3590,10 @@ property_emitters = {
'AccumulationRegister': emit_accumulation_register_properties,
'DefinedType': emit_defined_type_properties,
'FunctionalOption': emit_functional_option_properties,
'Sequence': emit_sequence_properties,
'FilterCriterion': emit_filter_criterion_properties,
'DocumentNumerator': emit_document_numerator_properties,
'SettingsStorage': emit_settings_storage_properties,
'CommonModule': emit_common_module_properties,
'ScheduledJob': emit_scheduled_job_properties,
'EventSubscription': emit_event_subscription_properties,
@@ -3678,6 +3805,39 @@ if obj_type == 'DocumentJournal':
else:
X('\t\t<ChildObjects/>')
# --- Sequence: dimensions ---
if obj_type == 'Sequence':
seq_dims = list(defn.get('dimensions', []))
if seq_dims:
has_children = True
X('\t\t<ChildObjects>')
for d in seq_dims:
emit_sequence_dimension('\t\t\t', d)
X('\t\t</ChildObjects>')
else:
X('\t\t<ChildObjects/>')
# --- FilterCriterion / SettingsStorage: ChildObjects (формы стрипаются; FilterCriterion может нести <Command>) ---
if obj_type in ('FilterCriterion', 'SettingsStorage'):
fc_commands = []
if defn.get('commands'):
cd = defn['commands']
if isinstance(cd, list):
for c in cd:
fc_commands.append({'name': str(c.get('name', '')), 'def': c})
else:
for k, v in cd.items():
fc_commands.append({'name': k, 'def': v})
if fc_commands:
has_children = True
X('\t\t<ChildObjects>')
for cmd in fc_commands:
emit_command('\t\t\t', cmd['name'], cmd['def'])
X('\t\t</ChildObjects>')
else:
X('\t\t<ChildObjects/>')
# DocumentNumerator: ChildObjects нет вовсе (не эмитим).
# --- HTTPService: URLTemplates ---
if obj_type == 'HTTPService':
url_templates = {}
@@ -3748,6 +3908,10 @@ type_plural_map = {
'WebService': 'WebServices',
'DefinedType': 'DefinedTypes',
'FunctionalOption': 'FunctionalOptions',
'Sequence': 'Sequences',
'FilterCriterion': 'FilterCriteria',
'DocumentNumerator': 'DocumentNumerators',
'SettingsStorage': 'SettingsStorages',
}
type_plural = type_plural_map[obj_type]
@@ -1,4 +1,4 @@
# meta-decompile v0.46 — XML объекта метаданных 1С → JSON-черновик формата meta-compile
# meta-decompile v0.47 — XML объекта метаданных 1С → JSON-черновик формата meta-compile
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
#
# Поддержаны: Catalog, ExchangePlan, ChartOfCharacteristicTypes, ChartOfAccounts, ChartOfCalculationTypes, Document,
@@ -92,8 +92,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', 'AccountingRegister', 'CalculationRegister', 'BusinessProcess', 'Task', 'Enum', 'Report', 'DataProcessor', 'Constant', 'DefinedType', 'FunctionalOption', 'DocumentJournal')) {
[Console]::Error.WriteLine("meta-decompile: тип '$objType' пока не поддержан (Catalog, ExchangePlan, ChartOfCharacteristicTypes, ChartOfAccounts, ChartOfCalculationTypes, Document, InformationRegister, AccumulationRegister, AccountingRegister, CalculationRegister, BusinessProcess, Task, Enum, Report, DataProcessor, Constant, DefinedType, FunctionalOption, DocumentJournal)"); exit 3
if ($objType -notin @('Catalog', 'ExchangePlan', 'ChartOfCharacteristicTypes', 'ChartOfAccounts', 'ChartOfCalculationTypes', 'Document', 'InformationRegister', 'AccumulationRegister', 'AccountingRegister', 'CalculationRegister', 'BusinessProcess', 'Task', 'Enum', 'Report', 'DataProcessor', 'Constant', 'DefinedType', 'FunctionalOption', 'DocumentJournal', 'Sequence', 'FilterCriterion', 'DocumentNumerator', 'SettingsStorage')) {
[Console]::Error.WriteLine("meta-decompile: тип '$objType' пока не поддержан (…, Sequence, FilterCriterion, DocumentNumerator, SettingsStorage)"); exit 3
}
$props = $objNode.SelectSingleNode('md:Properties', $nsm)
@@ -421,9 +421,9 @@ Add-EnumProp 'subordinationUse' 'SubordinationUse' 'ToItems'
$descrLenDef = switch ($objType) { 'ExchangePlan' { 150 } 'ChartOfCharacteristicTypes' { 100 } 'ChartOfCalculationTypes' { 100 } default { 25 } }
$codeLenDef = if ($objType -eq 'ChartOfCalculationTypes') { 5 } else { 9 }
$createInpDef = if ($objType -in @('Catalog', 'Document')) { 'Use' } else { 'DontUse' }
$dataLockDef = if ($objType -in @('Catalog', 'ChartOfAccounts', 'ChartOfCalculationTypes')) { 'Automatic' } else { 'Managed' }
$dataLockDef = if ($objType -in @('Catalog', 'ChartOfAccounts', 'ChartOfCalculationTypes', 'Sequence')) { 'Automatic' } else { 'Managed' }
$codeSeriesDef = switch ($objType) { 'ChartOfCharacteristicTypes' { 'WholeCharacteristicKind' } 'ChartOfAccounts' { 'WholeChartOfAccounts' } default { 'WholeCatalog' } }
$checkUniqueDef = ($objType -in @('ChartOfCharacteristicTypes', 'ChartOfAccounts', 'Document')) # ПВХ/ПС/Документ дефолт true, Catalog false
$checkUniqueDef = ($objType -in @('ChartOfCharacteristicTypes', 'ChartOfAccounts', 'Document', 'DocumentNumerator')) # ПВХ/ПС/Документ/Нумератор дефолт true, Catalog false
$defPresDef = if ($objType -eq 'ChartOfAccounts') { 'AsCode' } else { 'AsDescription' } # ПС по умолчанию AsCode
Add-IntProp 'codeLength' 'CodeLength' $codeLenDef
Add-IntProp 'descriptionLength' 'DescriptionLength' $descrLenDef
@@ -619,6 +619,43 @@ if ($objType -eq 'DocumentJournal') {
if ($rdItems.Count -gt 0) { $dsl['registeredDocuments'] = [System.Collections.ArrayList]@($rdItems) }
}
}
# Sequence — последовательность документов: граница, документы, движения, измерения (ChildObjects ниже).
if ($objType -eq 'Sequence') {
Add-EnumProp 'moveBoundaryOnPosting' 'MoveBoundaryOnPosting' 'DontMove'
foreach ($ll in @(@('Documents','documents'), @('RegisterRecords','registerRecords'))) {
$ln = $props.SelectSingleNode("md:$($ll[0])", $nsm)
if ($ln) {
$items = @($ln.SelectNodes('xr:Item', $nsm) | ForEach-Object { $_.InnerText })
if ($items.Count -gt 0) { $dsl[$ll[1]] = [System.Collections.ArrayList]@($items) }
}
}
# dataLockControlMode покрыт общим блоком (дефолт Automatic для Sequence).
}
# FilterCriterion — критерий отбора: тип значения + состав (объекты отбора) + формы.
if ($objType -eq 'FilterCriterion') {
$vt = Get-TypeShorthand ($props.SelectSingleNode('md:Type', $nsm)); if ($vt) { $dsl['valueType'] = $vt }
$cn = $props.SelectSingleNode('md:Content', $nsm)
if ($cn) {
$items = @($cn.SelectNodes('xr:Item', $nsm) | ForEach-Object { $_.InnerText })
if ($items.Count -gt 0) { $dsl['content'] = [System.Collections.ArrayList]@($items) }
}
$dfm = P 'DefaultForm'; if ($dfm) { $dsl['defaultForm'] = $dfm }
$afm = P 'AuxiliaryForm'; if ($afm) { $dsl['auxiliaryForm'] = $afm }
}
# DocumentNumerator — нумератор документов: параметры нумерации (без InternalInfo/ChildObjects).
if ($objType -eq 'DocumentNumerator') {
Add-EnumProp 'numberType' 'NumberType' 'String'
Add-IntProp 'numberLength' 'NumberLength' 11
Add-EnumProp 'numberAllowedLength' 'NumberAllowedLength' 'Variable'
Add-EnumProp 'numberPeriodicity' 'NumberPeriodicity' 'Year'
# checkUnique покрыт общим блоком (дефолт true для DocumentNumerator).
}
# SettingsStorage — хранилище настроек: формы сохранения/загрузки (плоские ref).
if ($objType -eq 'SettingsStorage') {
foreach ($fp in @(@('DefaultSaveForm','defaultSaveForm'), @('DefaultLoadForm','defaultLoadForm'), @('AuxiliarySaveForm','auxiliarySaveForm'), @('AuxiliaryLoadForm','auxiliaryLoadForm'))) {
$fv = P $fp[0]; if ($fv) { $dsl[$fp[1]] = $fv }
}
}
# Constant — богатый одиночный реквизит: Type + свойства значения (как у реквизита) + object-уровень.
if ($objType -eq 'Constant') {
$vt = Get-TypeShorthand ($props.SelectSingleNode('md:Type', $nsm))
@@ -946,9 +983,31 @@ if ($childObjs) {
foreach ($a in $extDimFlagNodes) { [void]$arr.Add((Attr-ToDsl $a)) }
$dsl['extDimensionAccountingFlags'] = $arr
}
# Регистры: измерения и ресурсы — структурно как реквизит (Attr-ToDsl захватывает общий слой + регистро-специфику).
# Sequence: измерения несут DocumentMap/RegisterRecordsMap (соответствие реквизитам документов/движениям) —
# Attr-ToDsl их не знает → отдельный захват объектной формой. Прочие типы (регистры) — общий Attr-ToDsl.
$dimNodes = @($childObjs.SelectNodes('md:Dimension', $nsm))
if ($dimNodes.Count -gt 0) {
if ($dimNodes.Count -gt 0 -and $objType -eq 'Sequence') {
$arr = [System.Collections.ArrayList]@()
foreach ($dn in $dimNodes) {
$dp = $dn.SelectSingleNode('md:Properties', $nsm)
$dName = ($dp.SelectSingleNode('md:Name', $nsm)).InnerText
$o = [ordered]@{ name = $dName }
$dSyn = Get-MLValue ($dp.SelectSingleNode('md:Synonym', $nsm))
if ($dSyn -is [string]) { if ($dSyn -ne (Split-CamelWords $dName)) { $o['synonym'] = $dSyn } }
elseif ($null -ne $dSyn) { $o['synonym'] = $dSyn }
$dCmtN = $dp.SelectSingleNode('md:Comment', $nsm); if ($dCmtN -and $dCmtN.InnerText) { $o['comment'] = $dCmtN.InnerText }
$dt = Get-TypeShorthand ($dp.SelectSingleNode('md:Type', $nsm)); if ($dt) { $o['type'] = $dt }
foreach ($mp in @(@('DocumentMap','documentMap'), @('RegisterRecordsMap','registerRecordsMap'))) {
$mn = $dp.SelectSingleNode("md:$($mp[0])", $nsm)
if ($mn) {
$mItems = @($mn.SelectNodes('xr:Item', $nsm) | ForEach-Object { $_.InnerText })
if ($mItems.Count -gt 0) { $o[$mp[1]] = [System.Collections.ArrayList]@($mItems) }
}
}
[void]$arr.Add($o)
}
$dsl['dimensions'] = $arr
} elseif ($dimNodes.Count -gt 0) {
$arr = [System.Collections.ArrayList]@()
foreach ($a in $dimNodes) { [void]$arr.Add((Attr-ToDsl $a)) }
$dsl['dimensions'] = $arr