mirror of
https://github.com/Nikolay-Shirokov/cc-1c-skills.git
synced 2026-09-17 23:35:22 +03:00
fix(meta-compile,meta-validate): канон стандартных реквизитов регистров
Справочник порядка StandardAttributes был неполон у трёх видов регистров, а неизвестные имена эмитятся перед фикс-списком — платформа их вкрапляет, и роундтрип переставал быть побайтовым. Порядок снят с выгрузки платформы, присутствие условных реквизитов теперь выводится из свойств объекта (periodAdjustmentLength, correspondence, registerType), а не из наличия ключа в DSL: иначе регистр, создаваемый с нуля, терял реквизит, который платформа обязана материализовать. Наличие ключа осталось дополняющим условием, чтобы роундтрип не зависел от точности вывода. - регистр расчёта: 11 реквизитов, состав безусловен (проверено матрицей actionPeriod × basePeriod × периодичность на 8.3.27) - регистр бухгалтерии: PeriodAdjustment при длине периода корректировки > 0, RecordType при correspondence=false - регистр накопления: RecordType только у регистра остатков meta-validate: снято ложное предупреждение об «unexpected» RecordType у бухрегистра, условные реквизиты исключены из проверки missing. Проверка: 739 регистров по шести конфигурациям — 0 расхождений; снэпшоты пересняты и верифицированы загрузкой в 1С. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
707a5c293f
commit
16199deb92
@@ -1,4 +1,4 @@
|
||||
# meta-compile v1.92 — Compile 1C metadata object from JSON (+write_xml_file/write_utf8_bom: общий эталон записи)
|
||||
# meta-compile v1.93 — Compile 1C metadata object from JSON
|
||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||
param(
|
||||
[Parameter(Mandatory)]
|
||||
@@ -1311,20 +1311,20 @@ $script:standardAttributesByType = @{
|
||||
"Document" = @("Posted","Ref","DeletionMark","Date","Number")
|
||||
"Enum" = @("Order","Ref")
|
||||
"InformationRegister" = @("Active","LineNumber","Recorder","Period")
|
||||
"AccumulationRegister" = @("Active","LineNumber","Recorder","Period")
|
||||
"AccountingRegister" = @("PeriodAdjustment","Account","Active","LineNumber","Recorder","Period")
|
||||
"CalculationRegister" = @("Active","Recorder","LineNumber","RegistrationPeriod","CalculationType","ReversingEntry")
|
||||
"AccumulationRegister" = @("RecordType","Active","LineNumber","Recorder","Period")
|
||||
"AccountingRegister" = @("PeriodAdjustment","Account","RecordType","Active","LineNumber","Recorder","Period")
|
||||
"CalculationRegister" = @("RegistrationPeriod","ReversingEntry","Active","EndOfBasePeriod","BegOfBasePeriod","EndOfActionPeriod","BegOfActionPeriod","ActionPeriod","CalculationType","LineNumber","Recorder")
|
||||
"ChartOfAccounts" = @("PredefinedDataName","Order","OffBalance","Type","Description","Code","Parent","Predefined","DeletionMark","Ref")
|
||||
"ChartOfCharacteristicTypes" = @("PredefinedDataName","ValueType","Description","Code","IsFolder","Parent","Predefined","DeletionMark","Ref")
|
||||
"ChartOfCalculationTypes" = @("PredefinedDataName","Predefined","Ref","DeletionMark","ActionPeriodIsBasic","Description","Code")
|
||||
"BusinessProcess" = @("Started","HeadTask","Completed","Ref","DeletionMark","Date","Number")
|
||||
"Task" = @("Executed","Description","RoutePoint","BusinessProcess","Ref","DeletionMark","Date","Number")
|
||||
# Порядок в каждом списке — канон выгрузки, снят с корпуса acc+erp (внутри типа разброса нет).
|
||||
# Условные члены перечислены в $script:stdAttrOptional — они эмитятся только при наличии
|
||||
# ключа в DSL, но позицию берут отсюда.
|
||||
# Условные члены перечислены в $script:stdAttrConditions — позицию они берут отсюда, а
|
||||
# присутствие определяется свойствами объекта.
|
||||
# У ПВХ IsFolder входит в фикс-список: он есть у всех 23 объектов корпуса с этим блоком.
|
||||
# У бухрегистра PeriodAdjustment, наоборот, условен (1 из 3) — он приходит как «лишний»
|
||||
# ключ и эмитится ПЕРЕД фикс-списком, что совпадает с платформой.
|
||||
# У регистра расчёта список безусловен: реквизиты периода действия и базового периода
|
||||
# платформа пишет при любых ActionPeriod/BasePeriod/Periodicity (синтетика, все 4 комбинации).
|
||||
"ExchangePlan" = @("ThisNode","ReceivedNo","SentNo","Ref","DeletionMark","Description","Code")
|
||||
"DocumentJournal" = @("Type","Ref","Date","Posted","DeletionMark","Number")
|
||||
}
|
||||
@@ -1445,10 +1445,17 @@ function Emit-StandardAttribute {
|
||||
# Миграция типа = добавить его в stdAttrConditionalTypes + stdAttrProfile и переснять снэпшоты; КОД НЕ ТРОГАЕМ.
|
||||
$script:stdAttrConditionalTypes = @('Catalog', 'ExchangePlan', 'ChartOfCharacteristicTypes', 'ChartOfAccounts', 'ChartOfCalculationTypes', 'Document')
|
||||
|
||||
# Условные члены списка типа: позиция берётся из $script:standardAttributesByType, а сам
|
||||
# реквизит эмитится только при наличии ключа в DSL (у бухрегистра PeriodAdjustment — 2 из 5).
|
||||
$script:stdAttrOptional = @{
|
||||
"AccountingRegister" = @("PeriodAdjustment")
|
||||
# Условные члены списка типа: позиция берётся из $script:standardAttributesByType, а присутствие —
|
||||
# из свойств самого объекта, как у платформы. Предикат ОБЯЗАН принимать определение параметром:
|
||||
# scriptblock не видит $def вызывающей функции, и отказ был бы молчаливым.
|
||||
$script:stdAttrConditions = @{
|
||||
"AccountingRegister" = @{
|
||||
"PeriodAdjustment" = { param($d) $v = 0; if ($null -ne $d.periodAdjustmentLength) { $v = [int]"$($d.periodAdjustmentLength)" }; $v -gt 0 }
|
||||
"RecordType" = { param($d) -not ($d.correspondence -eq $true) }
|
||||
}
|
||||
"AccumulationRegister" = @{
|
||||
"RecordType" = { param($d) $raw = if ($d.registerType) { "$($d.registerType)" } else { "Balance" }; (Normalize-EnumValue "RegisterType" $raw) -eq "Balance" }
|
||||
}
|
||||
}
|
||||
|
||||
# Хвостовая группа: реквизиты, которых нет в списке типа и которые идут ПОСЛЕ него.
|
||||
@@ -1469,9 +1476,9 @@ function Emit-StandardAttributes {
|
||||
$profile = $script:stdAttrProfile[$objectType]; if (-not $profile) { $profile = @{} }
|
||||
# Список типа задаёт ПОРЯДОК всех известных стандартных реквизитов, включая условные:
|
||||
# их позиция бывает и до, и после обязательных (у бухрегистра PeriodAdjustment идёт
|
||||
# перед Account, а ExtDimension1..3/ExtDimensionType1..3 — после Period), поэтому
|
||||
# «условные скопом вперёд» не выражает канон. Условный эмитим по факту наличия в DSL.
|
||||
$optional = $script:stdAttrOptional[$objectType]; if (-not $optional) { $optional = @() }
|
||||
# перед Account, RecordType — после, а ExtDimension1..3/ExtDimensionType1..3 — после Period),
|
||||
# поэтому «условные скопом вперёд» не выражает канон.
|
||||
$cond = $script:stdAttrConditions[$objectType]
|
||||
# Ключи, которых нет в списке типа ВООБЩЕ. По умолчанию их позиция — ПЕРЕД списком
|
||||
# (легаси вроде ExchangeDate у части планов обмена). Подходящие под хвостовой шаблон
|
||||
# типа идут ПОСЛЕ, в порядке номера, а внутри номера — сначала ExtDimensionN, затем
|
||||
@@ -1487,7 +1494,12 @@ function Emit-StandardAttributes {
|
||||
$tail = @($tail | Sort-Object @{e={[int]([regex]::Match($_, '\d+').Value)}}, @{e={ if ($_ -match 'Type\d+$') { 1 } else { 0 } }})
|
||||
X "$indent<StandardAttributes>"
|
||||
foreach ($a in ($extra + $attrs + $tail)) {
|
||||
if (($optional -contains $a) -and (-not ($sa -and $sa.PSObject.Properties[$a]))) { continue }
|
||||
# Условный реквизит: эмитим, если так велят свойства объекта ЛИБО если ключ есть в DSL.
|
||||
# Дизъюнкция страхует роундтрип — декомпилятор перечисляет все имена блока.
|
||||
if ($cond -and $cond.ContainsKey($a)) {
|
||||
$present = ($sa -and $sa.PSObject.Properties[$a]) -or (& $cond[$a] $def)
|
||||
if (-not $present) { continue }
|
||||
}
|
||||
$ov = @{}
|
||||
if ($profile.ContainsKey($a)) { foreach ($k in $profile[$a].Keys) { $ov[$k] = $profile[$a][$k] } }
|
||||
if ($sa) { # DSL-override применяем всегда при наличии ключа (для не-условных типов тоже, напр. ExchangePlan)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env python3
|
||||
# meta-compile v1.92 — Compile 1C metadata object from JSON (+write_xml_file/write_utf8_bom: общий эталон записи)
|
||||
# meta-compile v1.93 — Compile 1C metadata object from JSON
|
||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||
|
||||
import argparse
|
||||
@@ -1350,16 +1350,18 @@ standard_attributes_by_type = {
|
||||
'Document': ['Posted', 'Ref', 'DeletionMark', 'Date', 'Number'],
|
||||
'Enum': ['Order', 'Ref'],
|
||||
'InformationRegister': ['Active', 'LineNumber', 'Recorder', 'Period'],
|
||||
'AccumulationRegister': ['Active', 'LineNumber', 'Recorder', 'Period'],
|
||||
'AccountingRegister': ['PeriodAdjustment', 'Account', 'Active', 'LineNumber', 'Recorder', 'Period'],
|
||||
'CalculationRegister': ['Active', 'Recorder', 'LineNumber', 'RegistrationPeriod', 'CalculationType', 'ReversingEntry'],
|
||||
'AccumulationRegister': ['RecordType', 'Active', 'LineNumber', 'Recorder', 'Period'],
|
||||
'AccountingRegister': ['PeriodAdjustment', 'Account', 'RecordType', 'Active', 'LineNumber', 'Recorder', 'Period'],
|
||||
'CalculationRegister': ['RegistrationPeriod', 'ReversingEntry', 'Active', 'EndOfBasePeriod', 'BegOfBasePeriod', 'EndOfActionPeriod', 'BegOfActionPeriod', 'ActionPeriod', 'CalculationType', 'LineNumber', 'Recorder'],
|
||||
'ChartOfAccounts': ['PredefinedDataName', 'Order', 'OffBalance', 'Type', 'Description', 'Code', 'Parent', 'Predefined', 'DeletionMark', 'Ref'],
|
||||
'ChartOfCharacteristicTypes': ['PredefinedDataName', 'ValueType', 'Description', 'Code', 'IsFolder', 'Parent', 'Predefined', 'DeletionMark', 'Ref'],
|
||||
'ChartOfCalculationTypes': ['PredefinedDataName', 'Predefined', 'Ref', 'DeletionMark', 'ActionPeriodIsBasic', 'Description', 'Code'],
|
||||
# Порядок в каждом списке — канон выгрузки, снят с корпуса acc+erp (внутри типа разброса нет).
|
||||
# Условные члены перечислены в std_attr_conditions — позицию они берут отсюда, а
|
||||
# присутствие определяется свойствами объекта.
|
||||
# У ПВХ IsFolder входит в фикс-список: он есть у всех 23 объектов корпуса с этим блоком.
|
||||
# У бухрегистра PeriodAdjustment, наоборот, условен (1 из 3) — он приходит как «лишний»
|
||||
# ключ и эмитится ПЕРЕД фикс-списком, что совпадает с платформой.
|
||||
# У регистра расчёта список безусловен: реквизиты периода действия и базового периода
|
||||
# платформа пишет при любых ActionPeriod/BasePeriod/Periodicity (синтетика, все 4 комбинации).
|
||||
'BusinessProcess': ['Started', 'HeadTask', 'Completed', 'Ref', 'DeletionMark', 'Date', 'Number'],
|
||||
'Task': ['Executed', 'Description', 'RoutePoint', 'BusinessProcess', 'Ref', 'DeletionMark', 'Date', 'Number'],
|
||||
# Порядок снят с выгрузки: у плана обмена блок начинается с ThisNode, а не с Ref
|
||||
@@ -1486,10 +1488,21 @@ def emit_standard_attribute(indent, attr_name, ov=None):
|
||||
# Прочие типы → блок всегда (текущее поведение). Миграция типа = +строчка в оба справочника + снэпшоты.
|
||||
std_attr_conditional_types = {'Catalog', 'ExchangePlan', 'ChartOfCharacteristicTypes', 'ChartOfAccounts', 'ChartOfCalculationTypes', 'Document'}
|
||||
|
||||
# Условные члены списка типа: позиция берётся из standard_attributes_by_type, а сам
|
||||
# реквизит эмитится только при наличии ключа в DSL (у бухрегистра PeriodAdjustment — 2 из 5).
|
||||
std_attr_optional = {
|
||||
'AccountingRegister': ('PeriodAdjustment',),
|
||||
# Условные члены списка типа: позиция берётся из standard_attributes_by_type, а присутствие —
|
||||
# из свойств самого объекта, как у платформы. Предикат принимает определение параметром
|
||||
# (зеркало .ps1, где scriptblock не видит $def вызывающей функции).
|
||||
def _period_adjustment_used(d):
|
||||
v = d.get('periodAdjustmentLength')
|
||||
return v is not None and int(str(v)) > 0
|
||||
|
||||
std_attr_conditions = {
|
||||
'AccountingRegister': {
|
||||
'PeriodAdjustment': _period_adjustment_used,
|
||||
'RecordType': lambda d: d.get('correspondence') is not True,
|
||||
},
|
||||
'AccumulationRegister': {
|
||||
'RecordType': lambda d: normalize_enum_value('RegisterType', str(d.get('registerType') or 'Balance')) == 'Balance',
|
||||
},
|
||||
}
|
||||
|
||||
# Хвостовая группа: реквизиты, которых нет в списке типа и которые идут ПОСЛЕ него.
|
||||
@@ -1512,9 +1525,9 @@ def emit_standard_attributes(indent, object_type):
|
||||
profile = std_attr_profile.get(object_type, {})
|
||||
# Список типа задаёт ПОРЯДОК всех известных стандартных реквизитов, включая условные:
|
||||
# их позиция бывает и до, и после обязательных (у бухрегистра PeriodAdjustment идёт
|
||||
# перед Account, а ExtDimension1..3/ExtDimensionType1..3 — после Period), поэтому
|
||||
# «условные скопом вперёд» не выражает канон. Условный эмитим по факту наличия в DSL.
|
||||
optional = std_attr_optional.get(object_type, ())
|
||||
# перед Account, RecordType — после, а ExtDimension1..3/ExtDimensionType1..3 — после Period),
|
||||
# поэтому «условные скопом вперёд» не выражает канон.
|
||||
cond = std_attr_conditions.get(object_type)
|
||||
# Ключи, которых нет в списке типа ВООБЩЕ. По умолчанию их позиция — ПЕРЕД списком
|
||||
# (легаси вроде ExchangeDate у части планов обмена). Подходящие под хвостовой шаблон
|
||||
# типа идут ПОСЛЕ, в порядке номера, а внутри номера — сначала ExtDimensionN, затем
|
||||
@@ -1532,8 +1545,12 @@ def emit_standard_attributes(indent, object_type):
|
||||
tail.sort(key=lambda k: (int(re.search(r'\d+', k).group()), 1 if re.search(r'Type\d+$', k) else 0))
|
||||
X(f'{indent}<StandardAttributes>')
|
||||
for a in extra + list(attrs) + tail:
|
||||
if a in optional and not (isinstance(sa, dict) and a in sa):
|
||||
continue
|
||||
# Условный реквизит: эмитим, если так велят свойства объекта ЛИБО если ключ есть в DSL.
|
||||
# Дизъюнкция страхует роундтрип — декомпилятор перечисляет все имена блока.
|
||||
if cond and a in cond:
|
||||
present = (isinstance(sa, dict) and a in sa) or cond[a](defn)
|
||||
if not present:
|
||||
continue
|
||||
ov = dict(profile.get(a, {}))
|
||||
if isinstance(sa, dict):
|
||||
d = sa.get(a)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# meta-validate v1.16 — Validate 1C metadata object structure (+format_rank: свести к общему эталону)
|
||||
# meta-validate v1.17 — Validate 1C metadata object structure
|
||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||
param(
|
||||
[Parameter(Mandatory)]
|
||||
@@ -209,7 +209,7 @@ $standardAttributesByType = @{
|
||||
"Enum" = @("Order","Ref")
|
||||
"InformationRegister" = @("Active","LineNumber","Recorder","Period")
|
||||
"AccumulationRegister" = @("Active","LineNumber","Recorder","Period","RecordType")
|
||||
"AccountingRegister" = @("Active","Period","Recorder","LineNumber","Account")
|
||||
"AccountingRegister" = @("Active","Period","Recorder","LineNumber","Account","PeriodAdjustment","RecordType")
|
||||
"CalculationRegister" = @("Active","Recorder","LineNumber","RegistrationPeriod","CalculationType","ReversingEntry","ActionPeriod","BegOfActionPeriod","EndOfActionPeriod","BegOfBasePeriod","EndOfBasePeriod")
|
||||
"ChartOfAccounts" = @("PredefinedDataName","Predefined","Ref","DeletionMark","Description","Code","Parent","Order","Type","OffBalance")
|
||||
"ChartOfCharacteristicTypes" = @("PredefinedDataName","Predefined","Ref","DeletionMark","Description","Code","Parent","IsFolder","ValueType")
|
||||
@@ -220,6 +220,14 @@ $standardAttributesByType = @{
|
||||
"DocumentJournal" = @("Type","Ref","Date","Posted","DeletionMark","Number")
|
||||
}
|
||||
|
||||
# Стандартные реквизиты, присутствие которых зависит от свойств объекта: у бухрегистра
|
||||
# PeriodAdjustment — от длины периода корректировки, RecordType — от корреспонденции; у регистра
|
||||
# накопления RecordType — от вида регистра. Их отсутствие законно, в «Missing» не попадают.
|
||||
$stdAttrConditionalNames = @{
|
||||
"AccountingRegister" = @("PeriodAdjustment","RecordType")
|
||||
"AccumulationRegister" = @("RecordType")
|
||||
}
|
||||
|
||||
# Types that have StandardAttributes block
|
||||
$typesWithStdAttrs = @(
|
||||
"Catalog","Document","Enum",
|
||||
@@ -607,11 +615,9 @@ if ($typesWithStdAttrs -contains $mdType) {
|
||||
if ($saName) {
|
||||
$foundNames += $saName
|
||||
if ($expectedStdAttrs -notcontains $saName) {
|
||||
# AccountingRegister has dynamic ExtDimension{N}/ExtDimensionType{N} and optional PeriodAdjustment
|
||||
$isDynamic = ($mdType -eq "AccountingRegister" -and ($saName -match '^ExtDimension\d+$' -or $saName -match '^ExtDimensionType\d+$' -or $saName -eq "PeriodAdjustment"))
|
||||
# CalculationRegister has conditional period attrs
|
||||
$isCalcDynamic = ($mdType -eq "CalculationRegister" -and $saName -in @("ActionPeriod","BegOfActionPeriod","EndOfActionPeriod","BegOfBasePeriod","EndOfBasePeriod"))
|
||||
if (-not $isDynamic -and -not $isCalcDynamic) {
|
||||
# AccountingRegister: пары субконто, число которых задаётся планом счетов
|
||||
$isDynamic = ($mdType -eq "AccountingRegister" -and ($saName -match '^ExtDimension\d+$' -or $saName -match '^ExtDimensionType\d+$'))
|
||||
if (-not $isDynamic) {
|
||||
Report-Warn "5. Unexpected StandardAttribute '$saName' for $mdType"
|
||||
}
|
||||
}
|
||||
@@ -622,7 +628,8 @@ if ($typesWithStdAttrs -contains $mdType) {
|
||||
}
|
||||
|
||||
if ($expectedStdAttrs) {
|
||||
$missingAttrs = @($expectedStdAttrs | Where-Object { $foundNames -notcontains $_ })
|
||||
$condNames = $stdAttrConditionalNames[$mdType]; if (-not $condNames) { $condNames = @() }
|
||||
$missingAttrs = @($expectedStdAttrs | Where-Object { $foundNames -notcontains $_ -and $condNames -notcontains $_ })
|
||||
if ($missingAttrs.Count -gt 0) {
|
||||
Report-Warn "5. Missing StandardAttributes: $($missingAttrs -join ', ')"
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# meta-validate v1.16 — Validate 1C metadata object structure (Python port) (+format_rank: свести к общему эталону)
|
||||
# meta-validate v1.17 — Validate 1C metadata object structure (Python port)
|
||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||
import argparse
|
||||
import os
|
||||
@@ -209,7 +209,7 @@ standard_attributes_by_type = {
|
||||
"Enum": ["Order", "Ref"],
|
||||
"InformationRegister": ["Active", "LineNumber", "Recorder", "Period"],
|
||||
"AccumulationRegister": ["Active", "LineNumber", "Recorder", "Period", "RecordType"],
|
||||
"AccountingRegister": ["Active", "Period", "Recorder", "LineNumber", "Account"],
|
||||
"AccountingRegister": ["Active", "Period", "Recorder", "LineNumber", "Account", "PeriodAdjustment", "RecordType"],
|
||||
"CalculationRegister": ["Active", "Recorder", "LineNumber", "RegistrationPeriod", "CalculationType", "ReversingEntry", "ActionPeriod", "BegOfActionPeriod", "EndOfActionPeriod", "BegOfBasePeriod", "EndOfBasePeriod"],
|
||||
"ChartOfAccounts": ["PredefinedDataName", "Predefined", "Ref", "DeletionMark", "Description", "Code", "Parent", "Order", "Type", "OffBalance"],
|
||||
"ChartOfCharacteristicTypes": ["PredefinedDataName", "Predefined", "Ref", "DeletionMark", "Description", "Code", "Parent", "IsFolder", "ValueType"],
|
||||
@@ -220,6 +220,14 @@ standard_attributes_by_type = {
|
||||
"DocumentJournal": ["Type", "Ref", "Date", "Posted", "DeletionMark", "Number"],
|
||||
}
|
||||
|
||||
# Стандартные реквизиты, присутствие которых зависит от свойств объекта: у бухрегистра
|
||||
# PeriodAdjustment — от длины периода корректировки, RecordType — от корреспонденции; у регистра
|
||||
# накопления RecordType — от вида регистра. Их отсутствие законно, в «Missing» не попадают.
|
||||
std_attr_conditional_names = {
|
||||
"AccountingRegister": ("PeriodAdjustment", "RecordType"),
|
||||
"AccumulationRegister": ("RecordType",),
|
||||
}
|
||||
|
||||
# Types that have StandardAttributes block
|
||||
types_with_std_attrs = (
|
||||
"Catalog", "Document", "Enum",
|
||||
@@ -595,23 +603,19 @@ if md_type in types_with_std_attrs:
|
||||
if sa_name:
|
||||
found_names.append(sa_name)
|
||||
if sa_name not in expected_std_attrs:
|
||||
# AccountingRegister has dynamic attrs
|
||||
# AccountingRegister: пары субконто, число которых задаётся планом счетов
|
||||
is_dynamic = (md_type == "AccountingRegister" and
|
||||
(re.match(r'^ExtDimension\d+$', sa_name) or
|
||||
re.match(r'^ExtDimensionType\d+$', sa_name) or
|
||||
sa_name == "PeriodAdjustment"))
|
||||
# CalculationRegister has conditional period attrs
|
||||
is_calc_dynamic = (md_type == "CalculationRegister" and
|
||||
sa_name in ("ActionPeriod", "BegOfActionPeriod", "EndOfActionPeriod",
|
||||
"BegOfBasePeriod", "EndOfBasePeriod"))
|
||||
if not is_dynamic and not is_calc_dynamic:
|
||||
re.match(r'^ExtDimensionType\d+$', sa_name)))
|
||||
if not is_dynamic:
|
||||
report_warn(f"5. Unexpected StandardAttribute '{sa_name}' for {md_type}")
|
||||
else:
|
||||
report_error("5. StandardAttribute without 'name' attribute")
|
||||
check5_ok = False
|
||||
|
||||
if expected_std_attrs:
|
||||
missing_attrs = [a for a in expected_std_attrs if a not in found_names]
|
||||
cond_names = std_attr_conditional_names.get(md_type, ())
|
||||
missing_attrs = [a for a in expected_std_attrs if a not in found_names and a not in cond_names]
|
||||
if missing_attrs:
|
||||
report_warn(f"5. Missing StandardAttributes: {', '.join(missing_attrs)}")
|
||||
|
||||
|
||||
Reference in New Issue
Block a user