fix(meta-compile): порядок стандартных реквизитов ещё четырёх типов + Use у ПВХ

Раундтрип покрывал пять видов объектов из сорока с лишним, поэтому расхождения
порядка в остальных были не видны. Списки расширены до «по три объекта из
каждого вида» (112 объектов, 42 вида) — содержательных расхождений нет нигде,
но всплыли перестановки.

1. Порядок стандартных реквизитов, снят с корпуса acc+erp:
   - ChartOfCharacteristicTypes: PredefinedDataName, ValueType, Description,
     Code, IsFolder, Parent, Predefined, DeletionMark, Ref;
   - BusinessProcess: Started, HeadTask, Completed, Ref, DeletionMark, Date, Number;
   - Task: Executed, Description, RoutePoint, BusinessProcess, Ref, DeletionMark,
     Date, Number;
   - AccountingRegister: Account, Active, LineNumber, Recorder, Period.
   IsFolder добавлен в фикс-список ПВХ: он есть во всех 47 объектных блоках
   корпуса (5 выгрузок) и НЕ связан с иерархичностью — плоских ПВХ вдвое больше
   иерархических (36 против 15), и у них он тоже есть.

2. Новый контекст реквизита `cct` для ПВХ. Структурно реквизит ПВХ совпадает со
   справочником, но <Use> у него идёт ПОСЛЕ <Indexing>, а у справочника — перед
   (корпус: Catalog `Use,Indexing,FullTextSearch`, ПВХ
   `Indexing,Use,FullTextSearch,DataHistory`). Раньше оба шли одним контекстом.

Проверка:
- ПВХ (24 объекта): порядок ≠ 23 → 0; все виды (112): 7 → 1;
- шесть основных списков (4897 объектов) без регрессии: порядок ≠ 0,
  TOTAL diff lines 0, match не просел;
- юнит-тесты 648/648 ps1, 645/648 py;
- 1С-сертификация на 8.3.24: accounting-register, business-process, task,
  chart-of-characteristic-types — все приняты;
- дрейф эталонов 6 файлов: перестановки плюс единственное новое содержимое —
  блок IsFolder (проверено вырезанием: без него мультимножества совпадают).

Остаётся известным: у бухрегистра условные стандартные реквизиты стоят по обе
стороны фикс-списка (PeriodAdjustment перед, ExtDimension1..3 и
ExtDimensionType1..3 после), а эмиттер кладёт все «лишние» ключи вперёд. Это
правка механизма, а не таблицы — отдельной задачей.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Nick Shirokov
2026-08-06 17:37:25 +03:00
co-authored by Claude Opus 5
parent 0a2dba33cf
commit 0fc2d738a2
8 changed files with 434 additions and 365 deletions
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
# meta-compile v1.85 — Compile 1C metadata object from JSON
# meta-compile v1.86 — Compile 1C metadata object from JSON
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
import argparse
@@ -1333,13 +1333,17 @@ standard_attributes_by_type = {
'Enum': ['Order', 'Ref'],
'InformationRegister': ['Active', 'LineNumber', 'Recorder', 'Period'],
'AccumulationRegister': ['Active', 'LineNumber', 'Recorder', 'Period'],
'AccountingRegister': ['Active', 'Period', 'Recorder', 'LineNumber', 'Account'],
'AccountingRegister': ['Account', 'Active', 'LineNumber', 'Recorder', 'Period'],
'CalculationRegister': ['Active', 'Recorder', 'LineNumber', 'RegistrationPeriod', 'CalculationType', 'ReversingEntry'],
'ChartOfAccounts': ['PredefinedDataName', 'Order', 'OffBalance', 'Type', 'Description', 'Code', 'Parent', 'Predefined', 'DeletionMark', 'Ref'],
'ChartOfCharacteristicTypes': ['PredefinedDataName', 'Predefined', 'Ref', 'DeletionMark', 'Description', 'Code', 'Parent', 'ValueType'],
'ChartOfCharacteristicTypes': ['PredefinedDataName', 'ValueType', 'Description', 'Code', 'IsFolder', 'Parent', 'Predefined', 'DeletionMark', 'Ref'],
'ChartOfCalculationTypes': ['PredefinedDataName', 'Predefined', 'Ref', 'DeletionMark', 'ActionPeriodIsBasic', 'Description', 'Code'],
'BusinessProcess': ['Ref', 'DeletionMark', 'Date', 'Number', 'Started', 'Completed', 'HeadTask'],
'Task': ['Ref', 'DeletionMark', 'Date', 'Number', 'Executed', 'Description', 'RoutePoint', 'BusinessProcess'],
# Порядок в каждом списке — канон выгрузки, снят с корпуса acc+erp (внутри типа разброса нет).
# У ПВХ IsFolder входит в фикс-список: он есть у всех 23 объектов корпуса с этим блоком.
# У бухрегистра PeriodAdjustment, наоборот, условен (1 из 3) — он приходит как «лишний»
# ключ и эмитится ПЕРЕД фикс-списком, что совпадает с платформой.
'BusinessProcess': ['Started', 'HeadTask', 'Completed', 'Ref', 'DeletionMark', 'Date', 'Number'],
'Task': ['Executed', 'Description', 'RoutePoint', 'BusinessProcess', 'Ref', 'DeletionMark', 'Date', 'Number'],
# Порядок снят с выгрузки: у плана обмена блок начинается с ThisNode, а не с Ref
# (acc+erp, 8 объектов, разброса нет). Прочие типы в этой таблице совпадают с
# платформой — расхождений порядка по ним корпусный раундтрип не показал.
@@ -2081,8 +2085,13 @@ def emit_attribute(indent, parsed, context, elem_tag='Attribute'):
X(f'{indent}\t\t<ExtDimensionAccountingFlag>{esc_xml_text(str(parsed["extDimensionAccountingFlag"]))}</ExtDimensionAccountingFlag>')
else:
X(f'{indent}\t\t<ExtDimensionAccountingFlag/>')
# Use — у реквизитов справочника и ПВХ. Позиция РАЗНАЯ: справочник пишет Use ПЕРЕД
# Indexing, ПВХ — ПОСЛЕ него (корпус acc+erp: Catalog `Use,Indexing,FullTextSearch`,
# ПВХ `Indexing,Use,FullTextSearch,DataHistory`). Отсюда отдельный контекст 'cct':
# структурно реквизит ПВХ совпадает со справочником, расходится только этим порядком.
use_value = parsed.get("use") or "ForItem"
if context == 'catalog':
X(f'{indent}\t\t<Use>{parsed.get("use") or "ForItem"}</Use>')
X(f'{indent}\t\t<Use>{use_value}</Use>')
if context not in ('processor', 'processor-tabular'):
# Признаки учёта ПС (account-flag) не имеют <Indexing>/<FullTextSearch>, но имеют <DataHistory>.
if context != 'account-flag':
@@ -2096,6 +2105,8 @@ def emit_attribute(indent, parsed, context, elem_tag='Attribute'):
if parsed.get('indexing'):
indexing = parsed['indexing']
X(f'{indent}\t\t<Indexing>{indexing}</Indexing>')
if context == 'cct':
X(f'{indent}\t\t<Use>{use_value}</Use>')
# Реквизит адресации задачи: AddressingDimension (между Indexing и FullTextSearch).
if context == 'task-addressing' and elem_tag == 'AddressingAttribute':
if parsed.get('addressingDimension'):
@@ -4245,7 +4256,7 @@ if obj_type in types_with_attr_ts:
elif obj_type in ('DataProcessor', 'Report'):
context = 'processor'
elif obj_type == 'ChartOfCharacteristicTypes':
context = 'catalog' # реквизиты ПВХ структурно как у справочника (Use/FillFromFillingValue/DataHistory)
context = 'cct' # как catalog (Use/FillFromFillingValue/DataHistory), но Use ПОСЛЕ Indexing
elif obj_type in ('ChartOfAccounts', 'ChartOfCalculationTypes'):
context = 'account' # как catalog, но БЕЗ <Use> (реквизиты ПС/ПВР не иерархичны как справочник)
else: