mirror of
https://github.com/Nikolay-Shirokov/cc-1c-skills.git
synced 2026-09-17 15:25:23 +03:00
feat(meta-compile): пары субконто бухрегистра из плана счетов
Компилятор эмитил ExtDimensionN/ExtDimensionTypeN только по ключам DSL, поэтому регистр, созданный по неполному описанию, не совпадал с тем, что материализует платформа: пары дописывались лишь при загрузке. Теперь их число выводится из MaxExtDimensionCount плана счетов, на который ссылается регистр, — файл читается из выгрузки, как версия формата из Configuration.xml. ExtDimensionN получает LinkByType на Account с LinkItem по номеру. Выведенный хвост дополняет DSL, а не заменяет: ключи из описания остаются, недостающее добавляется. План счетов не найден в выгрузке (ещё не создан, лежит вне каталога) — пары не генерируются, в вывод идёт [HINT]: платформа допишет их сама при загрузке. Проверка: матрица из трёх случаев (план с 3 субконто, план с 0, план отсутствует) на обоих портах; синтетика загружена в 1С и выгружена обратно — состав и порядок совпали; корпусный роундтрип 739 регистров без расхождений. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
16199deb92
commit
4622234b52
@@ -1465,6 +1465,34 @@ $script:stdAttrConditions = @{
|
||||
$script:stdAttrTailPattern = @{
|
||||
"AccountingRegister" = '^ExtDimension(Type)?\d+$'
|
||||
}
|
||||
|
||||
# Состав хвоста задаёт не DSL, а объект, на который регистр ссылается: пар субконто столько,
|
||||
# сколько у плана счетов MaxExtDimensionCount. Читаем его из выгрузки — как версию формата из
|
||||
# Configuration.xml, — чтобы регистр, описанный неполным DSL, совпал с тем, что материализует
|
||||
# платформа. План не найден → хвост не генерируем и говорим об этом в выводе.
|
||||
$script:stdAttrTailHint = $null
|
||||
$script:stdAttrTailDerived = @{
|
||||
"AccountingRegister" = {
|
||||
param($d, $objectName, $outDir)
|
||||
$ref = "$($d.chartOfAccounts)"
|
||||
if (-not $ref) { return @() }
|
||||
$chartName = $ref -replace '^.*\.', '' # ссылка вида ChartOfAccounts.X (имя объекта точек не содержит)
|
||||
$path = Join-Path (Join-Path $outDir "ChartsOfAccounts") "$chartName.xml"
|
||||
if (-not (Test-Path -LiteralPath $path)) {
|
||||
$script:stdAttrTailHint = "ChartOfAccounts '$chartName' not found in dump — ExtDimension pairs not generated (platform will add them on load)"
|
||||
return @()
|
||||
}
|
||||
$n = 0
|
||||
if ([System.IO.File]::ReadAllText($path) -match '<MaxExtDimensionCount>(\d+)</MaxExtDimensionCount>') { $n = [int]$matches[1] }
|
||||
$out = @()
|
||||
for ($i = 1; $i -le $n; $i++) {
|
||||
# ExtDimensionN связан с Account через LinkByType (LinkItem = номер), ExtDimensionTypeN — нет.
|
||||
$out += @{ name = "ExtDimension$i"; ov = @{ LinkByType = @{ dataPath = "AccountingRegister.$objectName.StandardAttribute.Account"; linkItem = $i } } }
|
||||
$out += @{ name = "ExtDimensionType$i"; ov = @{} }
|
||||
}
|
||||
return $out
|
||||
}
|
||||
}
|
||||
function Emit-StandardAttributes {
|
||||
param([string]$indent, [string]$objectType)
|
||||
$attrs = $script:standardAttributesByType[$objectType]
|
||||
@@ -1491,6 +1519,16 @@ function Emit-StandardAttributes {
|
||||
if ($tailRe -and $k -match $tailRe) { $tail += $k } else { $extra += $k }
|
||||
}
|
||||
}
|
||||
# Хвост, выведенный из связанного объекта: дополняет DSL, а не заменяет его — лишнее из DSL
|
||||
# остаётся (прощаем), недостающее добавляется вместе со своими значениями по умолчанию.
|
||||
$derivedOv = @{}
|
||||
$gen = $script:stdAttrTailDerived[$objectType]
|
||||
if ($gen) {
|
||||
foreach ($e in @(& $gen $def $objName $OutputDir)) {
|
||||
$derivedOv[$e.name] = $e.ov
|
||||
if ($tail -notcontains $e.name) { $tail += $e.name }
|
||||
}
|
||||
}
|
||||
$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)) {
|
||||
@@ -1502,6 +1540,7 @@ function Emit-StandardAttributes {
|
||||
}
|
||||
$ov = @{}
|
||||
if ($profile.ContainsKey($a)) { foreach ($k in $profile[$a].Keys) { $ov[$k] = $profile[$a][$k] } }
|
||||
if ($derivedOv.ContainsKey($a)) { foreach ($k in $derivedOv[$a].Keys) { $ov[$k] = $derivedOv[$a][$k] } }
|
||||
if ($sa) { # DSL-override применяем всегда при наличии ключа (для не-условных типов тоже, напр. ExchangePlan)
|
||||
$d = $sa.$a
|
||||
if ($d) {
|
||||
@@ -5261,6 +5300,9 @@ switch ($regResult) {
|
||||
}
|
||||
|
||||
# Cross-reference hints
|
||||
if ($script:stdAttrTailHint) {
|
||||
Write-Host "[HINT] $($script:stdAttrTailHint)"
|
||||
}
|
||||
if ($objType -eq "AccountingRegister" -and -not $def.chartOfAccounts) {
|
||||
Write-Host "[HINT] AccountingRegister requires ChartOfAccounts reference:"
|
||||
Write-Host " /meta-edit -Operation modify-property -Value `"ChartOfAccounts=ChartOfAccounts.XXX`""
|
||||
|
||||
@@ -1512,6 +1512,39 @@ std_attr_conditions = {
|
||||
std_attr_tail_pattern = {
|
||||
'AccountingRegister': r'^ExtDimension(Type)?\d+$',
|
||||
}
|
||||
|
||||
# Состав хвоста задаёт не DSL, а объект, на который регистр ссылается: пар субконто столько,
|
||||
# сколько у плана счетов MaxExtDimensionCount. Читаем его из выгрузки — как версию формата из
|
||||
# Configuration.xml, — чтобы регистр, описанный неполным DSL, совпал с тем, что материализует
|
||||
# платформа. План не найден → хвост не генерируем и говорим об этом в выводе.
|
||||
std_attr_tail_hint = None
|
||||
|
||||
def _acc_register_ext_dimension_tail(d, object_name, out_dir):
|
||||
global std_attr_tail_hint
|
||||
ref = str(d.get('chartOfAccounts') or '')
|
||||
if not ref:
|
||||
return []
|
||||
chart_name = re.sub(r'^.*\.', '', ref) # ссылка вида ChartOfAccounts.X (имя объекта точек не содержит)
|
||||
path = os.path.join(out_dir, 'ChartsOfAccounts', chart_name + '.xml')
|
||||
if not os.path.isfile(path):
|
||||
std_attr_tail_hint = ("ChartOfAccounts '%s' not found in dump — ExtDimension pairs not generated "
|
||||
"(platform will add them on load)" % chart_name)
|
||||
return []
|
||||
with open(path, encoding='utf-8-sig') as f:
|
||||
m = re.search(r'<MaxExtDimensionCount>(\d+)</MaxExtDimensionCount>', f.read())
|
||||
n = int(m.group(1)) if m else 0
|
||||
out = []
|
||||
for i in range(1, n + 1):
|
||||
# ExtDimensionN связан с Account через LinkByType (LinkItem = номер), ExtDimensionTypeN — нет.
|
||||
out.append(('ExtDimension%d' % i,
|
||||
{'LinkByType': {'dataPath': 'AccountingRegister.%s.StandardAttribute.Account' % object_name,
|
||||
'linkItem': i}}))
|
||||
out.append(('ExtDimensionType%d' % i, {}))
|
||||
return out
|
||||
|
||||
std_attr_tail_derived = {
|
||||
'AccountingRegister': _acc_register_ext_dimension_tail,
|
||||
}
|
||||
def emit_standard_attributes(indent, object_type):
|
||||
attrs = standard_attributes_by_type.get(object_type)
|
||||
if not attrs:
|
||||
@@ -1542,6 +1575,15 @@ def emit_standard_attributes(indent, object_type):
|
||||
tail.append(k)
|
||||
else:
|
||||
extra.append(k)
|
||||
# Хвост, выведенный из связанного объекта: дополняет DSL, а не заменяет его — лишнее из DSL
|
||||
# остаётся (прощаем), недостающее добавляется вместе со своими значениями по умолчанию.
|
||||
derived_ov = {}
|
||||
gen = std_attr_tail_derived.get(object_type)
|
||||
if gen:
|
||||
for name, dov in gen(defn, obj_name, output_dir):
|
||||
derived_ov[name] = dov
|
||||
if name not in tail:
|
||||
tail.append(name)
|
||||
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:
|
||||
@@ -1552,6 +1594,7 @@ def emit_standard_attributes(indent, object_type):
|
||||
if not present:
|
||||
continue
|
||||
ov = dict(profile.get(a, {}))
|
||||
ov.update(derived_ov.get(a, {}))
|
||||
if isinstance(sa, dict):
|
||||
d = sa.get(a)
|
||||
if d:
|
||||
@@ -5159,6 +5202,8 @@ elif reg_result == 'no-config':
|
||||
print(f' Configuration.xml: not found at {config_xml_path} (register manually)')
|
||||
|
||||
# Cross-reference hints
|
||||
if std_attr_tail_hint:
|
||||
print(f'[HINT] {std_attr_tail_hint}')
|
||||
if obj_type == 'AccountingRegister' and not defn.get('chartOfAccounts'):
|
||||
print('[HINT] AccountingRegister requires ChartOfAccounts reference:')
|
||||
print(' /meta-edit -Operation modify-property -Value "ChartOfAccounts=ChartOfAccounts.XXX"')
|
||||
|
||||
Reference in New Issue
Block a user