mirror of
https://github.com/Nikolay-Shirokov/cc-1c-skills.git
synced 2026-07-19 00:59:40 +03:00
fix(meta-compile,meta-validate): fix 7 e2e bugs, add hints and reserved name checks
Group 1: ExchangePlan — remove invalid CodeType/CheckUnique/Autonumbering; Flowchart.xml — add version="2.17"; Content.xml — fix namespace + version. Group 2: Add missing GeneratedType categories — DefinedType, ChartOfAccounts ExtDimensionTypes/Row, CalculationRegister RecalculationsManager/Recalcs. Group 3: BusinessProcess — emit <Task> property from DSL. Group 4: Cross-reference [HINT] output after compilation for AccountingRegister, CalculationRegister, BusinessProcess, ChartOfAccounts (oriented to /meta-edit DSL). Group 5: Reserved attribute name warnings in meta-compile and meta-validate (Check 7b); cross-reference validation in Check 10 with [HINT] output. All changes synced to both PS1 and PY versions. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -436,13 +436,16 @@ $script:generatedTypes = @{
|
||||
@{ prefix = "CalculationRegisterList"; category = "List" }
|
||||
@{ prefix = "CalculationRegisterRecordSet"; category = "RecordSet" }
|
||||
@{ prefix = "CalculationRegisterRecordKey"; category = "RecordKey" }
|
||||
@{ prefix = "RecalculationsManager"; category = "Recalcs" }
|
||||
)
|
||||
"ChartOfAccounts" = @(
|
||||
@{ prefix = "ChartOfAccountsObject"; category = "Object" }
|
||||
@{ prefix = "ChartOfAccountsRef"; category = "Ref" }
|
||||
@{ prefix = "ChartOfAccountsSelection"; category = "Selection" }
|
||||
@{ prefix = "ChartOfAccountsList"; category = "List" }
|
||||
@{ prefix = "ChartOfAccountsManager"; category = "Manager" }
|
||||
@{ prefix = "ChartOfAccountsObject"; category = "Object" }
|
||||
@{ prefix = "ChartOfAccountsRef"; category = "Ref" }
|
||||
@{ prefix = "ChartOfAccountsSelection"; category = "Selection" }
|
||||
@{ prefix = "ChartOfAccountsList"; category = "List" }
|
||||
@{ prefix = "ChartOfAccountsManager"; category = "Manager" }
|
||||
@{ prefix = "ChartOfAccountsExtDimensionTypes"; category = "ExtDimensionTypes" }
|
||||
@{ prefix = "ChartOfAccountsExtDimensionTypesRow"; category = "ExtDimensionTypesRow" }
|
||||
)
|
||||
"ChartOfCharacteristicTypes" = @(
|
||||
@{ prefix = "ChartOfCharacteristicTypesObject"; category = "Object" }
|
||||
@@ -487,6 +490,9 @@ $script:generatedTypes = @{
|
||||
@{ prefix = "ExchangePlanList"; category = "List" }
|
||||
@{ prefix = "ExchangePlanManager"; category = "Manager" }
|
||||
)
|
||||
"DefinedType" = @(
|
||||
@{ prefix = "DefinedType"; category = "DefinedType" }
|
||||
)
|
||||
"DocumentJournal" = @(
|
||||
@{ prefix = "DocumentJournalSelection"; category = "Selection" }
|
||||
@{ prefix = "DocumentJournalList"; category = "List" }
|
||||
@@ -592,9 +598,26 @@ function Emit-TabularStandardAttributes {
|
||||
|
||||
# --- 8. Attribute emitter ---
|
||||
|
||||
$script:reservedAttrNames = @{
|
||||
"Ref"="Ссылка"; "DeletionMark"="ПометкаУдаления"; "Code"="Код"; "Description"="Наименование"
|
||||
"Date"="Дата"; "Number"="Номер"; "Posted"="Проведен"; "Parent"="Родитель"; "Owner"="Владелец"
|
||||
"IsFolder"="ЭтоГруппа"; "Predefined"="Предопределенный"; "PredefinedDataName"="ИмяПредопределенныхДанных"
|
||||
"Recorder"="Регистратор"; "Period"="Период"; "LineNumber"="НомерСтроки"; "Active"="Активность"
|
||||
"Order"="Порядок"; "Type"="Тип"; "OffBalance"="Забалансовый"
|
||||
"Started"="Стартован"; "Completed"="Завершен"; "HeadTask"="ВедущаяЗадача"
|
||||
"Executed"="Выполнена"; "RoutePoint"="ТочкаМаршрута"; "BusinessProcess"="БизнесПроцесс"
|
||||
"ThisNode"="ЭтотУзел"; "SentNo"="НомерОтправленного"; "ReceivedNo"="НомерПринятого"
|
||||
"CalculationType"="ВидРасчета"; "RegistrationPeriod"="ПериодРегистрации"; "ReversingEntry"="СторноЗапись"
|
||||
"Account"="Счет"; "ValueType"="ТипЗначения"; "ActionPeriodIsBasic"="ПериодДействияБазовый"
|
||||
}
|
||||
|
||||
function Emit-Attribute {
|
||||
param([string]$indent, $parsed, [string]$context)
|
||||
# $context: "catalog", "document", "object", "processor", "tabular", "processor-tabular", "register"
|
||||
$attrName = $parsed.name
|
||||
if ($script:reservedAttrNames.ContainsKey($attrName) -or $script:reservedAttrNames.ContainsValue($attrName)) {
|
||||
Write-Warning "Attribute '$attrName' conflicts with a standard attribute name. This may cause errors when loading into 1C."
|
||||
}
|
||||
$uuid = New-Guid-String
|
||||
X "$indent<Attribute uuid=`"$uuid`">"
|
||||
X "$indent`t<Properties>"
|
||||
@@ -1440,19 +1463,13 @@ function Emit-ExchangePlanProperties {
|
||||
|
||||
$codeLength = if ($null -ne $def.codeLength) { "$($def.codeLength)" } else { "9" }
|
||||
$descriptionLength = if ($null -ne $def.descriptionLength) { "$($def.descriptionLength)" } else { "100" }
|
||||
$codeType = if ($def.codeType) { "$($def.codeType)" } else { "String" }
|
||||
$codeAllowedLength = if ($def.codeAllowedLength) { "$($def.codeAllowedLength)" } else { "Variable" }
|
||||
$autonumbering = if ($def.autonumbering -eq $false) { "false" } else { "true" }
|
||||
$checkUnique = if ($def.checkUnique -eq $true) { "true" } else { "false" }
|
||||
|
||||
X "$i<CodeLength>$codeLength</CodeLength>"
|
||||
X "$i<CodeType>$codeType</CodeType>"
|
||||
X "$i<CodeAllowedLength>$codeAllowedLength</CodeAllowedLength>"
|
||||
X "$i<DescriptionLength>$descriptionLength</DescriptionLength>"
|
||||
X "$i<DefaultPresentation>AsDescription</DefaultPresentation>"
|
||||
X "$i<EditType>InDialog</EditType>"
|
||||
X "$i<CheckUnique>$checkUnique</CheckUnique>"
|
||||
X "$i<Autonumbering>$autonumbering</Autonumbering>"
|
||||
|
||||
Emit-StandardAttributes $i "ExchangePlan"
|
||||
|
||||
@@ -1941,6 +1958,13 @@ function Emit-BusinessProcessProperties {
|
||||
Emit-StandardAttributes $i "BusinessProcess"
|
||||
X "$i<Characteristics/>"
|
||||
|
||||
$task = if ($def.task) { "$($def.task)" } else { "" }
|
||||
if ($task) {
|
||||
X "$i<Task>$task</Task>"
|
||||
} else {
|
||||
X "$i<Task/>"
|
||||
}
|
||||
|
||||
X "$i<BasedOn/>"
|
||||
X "$i<InputByString>"
|
||||
X "$i`t<xr:Field>BusinessProcess.$objName.StandardAttribute.Number</xr:Field>"
|
||||
@@ -2708,7 +2732,7 @@ if ($objType -in $typesWithModule) {
|
||||
if ($objType -eq "ExchangePlan") {
|
||||
$contentPath = Join-Path $extDir "Content.xml"
|
||||
if (-not (Test-Path $contentPath)) {
|
||||
$contentXml = "<?xml version=`"1.0`" encoding=`"UTF-8`"?>`r`n<ExchangePlanContent xmlns=`"http://v8.1c.ru/8.3/MDClasses`" xmlns:xs=`"http://www.w3.org/2001/XMLSchema`" xmlns:xsi=`"http://www.w3.org/2001/XMLSchema-instance`"/>`r`n"
|
||||
$contentXml = "<?xml version=`"1.0`" encoding=`"UTF-8`"?>`r`n<ExchangePlanContent xmlns=`"http://v8.1c.ru/8.3/xcf/extrnprops`" xmlns:xr=`"http://v8.1c.ru/8.3/xcf/readable`" version=`"2.17`"/>`r`n"
|
||||
[System.IO.File]::WriteAllText($contentPath, $contentXml, $enc)
|
||||
$modulesCreated += $contentPath
|
||||
}
|
||||
@@ -2716,7 +2740,7 @@ if ($objType -eq "ExchangePlan") {
|
||||
if ($objType -eq "BusinessProcess") {
|
||||
$flowchartPath = Join-Path $extDir "Flowchart.xml"
|
||||
if (-not (Test-Path $flowchartPath)) {
|
||||
$flowchartXml = "<?xml version=`"1.0`" encoding=`"UTF-8`"?>`r`n<Flowchart xmlns=`"http://v8.1c.ru/8.3/MDClasses`"/>`r`n"
|
||||
$flowchartXml = "<?xml version=`"1.0`" encoding=`"UTF-8`"?>`r`n<Flowchart xmlns=`"http://v8.1c.ru/8.3/MDClasses`" version=`"2.17`"/>`r`n"
|
||||
[System.IO.File]::WriteAllText($flowchartPath, $flowchartXml, $enc)
|
||||
$modulesCreated += $flowchartPath
|
||||
}
|
||||
@@ -2842,3 +2866,24 @@ switch ($regResult) {
|
||||
"no-childobj" { Write-Warning "Configuration.xml found but <ChildObjects> not found" }
|
||||
"no-config" { Write-Host " Configuration.xml: not found at $configXmlPath (register manually)" }
|
||||
}
|
||||
|
||||
# Cross-reference hints
|
||||
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`""
|
||||
}
|
||||
if ($objType -eq "CalculationRegister" -and -not $def.chartOfCalculationTypes) {
|
||||
Write-Host "[HINT] CalculationRegister requires ChartOfCalculationTypes reference:"
|
||||
Write-Host " /meta-edit -Operation modify-property -Value `"ChartOfCalculationTypes=ChartOfCalculationTypes.XXX`""
|
||||
}
|
||||
if ($objType -eq "BusinessProcess" -and -not $def.task) {
|
||||
Write-Host "[HINT] BusinessProcess requires Task reference:"
|
||||
Write-Host " /meta-edit -Operation modify-property -Value `"Task=Task.XXX`""
|
||||
}
|
||||
if ($objType -eq "ChartOfAccounts") {
|
||||
$maxExtDim = if ($null -ne $def.maxExtDimensionCount) { [int]$def.maxExtDimensionCount } else { 0 }
|
||||
if ($maxExtDim -gt 0 -and -not $def.extDimensionTypes) {
|
||||
Write-Host "[HINT] ChartOfAccounts with MaxExtDimensionCount>0 requires ExtDimensionTypes:"
|
||||
Write-Host " /meta-edit -Operation modify-property -Value `"ExtDimensionTypes=ChartOfCharacteristicTypes.XXX`""
|
||||
}
|
||||
}
|
||||
|
||||
@@ -406,6 +406,7 @@ generated_types = {
|
||||
{'prefix': 'CalculationRegisterList', 'category': 'List'},
|
||||
{'prefix': 'CalculationRegisterRecordSet', 'category': 'RecordSet'},
|
||||
{'prefix': 'CalculationRegisterRecordKey', 'category': 'RecordKey'},
|
||||
{'prefix': 'RecalculationsManager', 'category': 'Recalcs'},
|
||||
],
|
||||
'ChartOfAccounts': [
|
||||
{'prefix': 'ChartOfAccountsObject', 'category': 'Object'},
|
||||
@@ -413,6 +414,8 @@ generated_types = {
|
||||
{'prefix': 'ChartOfAccountsSelection', 'category': 'Selection'},
|
||||
{'prefix': 'ChartOfAccountsList', 'category': 'List'},
|
||||
{'prefix': 'ChartOfAccountsManager', 'category': 'Manager'},
|
||||
{'prefix': 'ChartOfAccountsExtDimensionTypes', 'category': 'ExtDimensionTypes'},
|
||||
{'prefix': 'ChartOfAccountsExtDimensionTypesRow', 'category': 'ExtDimensionTypesRow'},
|
||||
],
|
||||
'ChartOfCharacteristicTypes': [
|
||||
{'prefix': 'ChartOfCharacteristicTypesObject', 'category': 'Object'},
|
||||
@@ -457,6 +460,9 @@ generated_types = {
|
||||
{'prefix': 'ExchangePlanList', 'category': 'List'},
|
||||
{'prefix': 'ExchangePlanManager', 'category': 'Manager'},
|
||||
],
|
||||
'DefinedType': [
|
||||
{'prefix': 'DefinedType', 'category': 'DefinedType'},
|
||||
],
|
||||
'DocumentJournal': [
|
||||
{'prefix': 'DocumentJournalSelection', 'category': 'Selection'},
|
||||
{'prefix': 'DocumentJournalList', 'category': 'List'},
|
||||
@@ -554,7 +560,40 @@ def emit_tabular_standard_attributes(indent):
|
||||
# 8. Attribute emitter
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
RESERVED_ATTR_NAMES = {
|
||||
'Ref', 'DeletionMark', 'Code', 'Description', 'Date', 'Number', 'Posted',
|
||||
'Parent', 'Owner', 'IsFolder', 'Predefined', 'PredefinedDataName',
|
||||
'Recorder', 'Period', 'LineNumber', 'Active', 'Order', 'Type', 'OffBalance',
|
||||
'Started', 'Completed', 'HeadTask', 'Executed', 'RoutePoint', 'BusinessProcess',
|
||||
'ThisNode', 'SentNo', 'ReceivedNo', 'CalculationType', 'RegistrationPeriod',
|
||||
'ReversingEntry', 'Account', 'ValueType', 'ActionPeriodIsBasic',
|
||||
}
|
||||
RESERVED_ATTR_NAMES_RU = {
|
||||
'\u0421\u0441\u044b\u043b\u043a\u0430', '\u041f\u043e\u043c\u0435\u0442\u043a\u0430\u0423\u0434\u0430\u043b\u0435\u043d\u0438\u044f',
|
||||
'\u041a\u043e\u0434', '\u041d\u0430\u0438\u043c\u0435\u043d\u043e\u0432\u0430\u043d\u0438\u0435',
|
||||
'\u0414\u0430\u0442\u0430', '\u041d\u043e\u043c\u0435\u0440', '\u041f\u0440\u043e\u0432\u0435\u0434\u0435\u043d',
|
||||
'\u0420\u043e\u0434\u0438\u0442\u0435\u043b\u044c', '\u0412\u043b\u0430\u0434\u0435\u043b\u0435\u0446',
|
||||
'\u042d\u0442\u043e\u0413\u0440\u0443\u043f\u043f\u0430', '\u041f\u0440\u0435\u0434\u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u044b\u0439',
|
||||
'\u0418\u043c\u044f\u041f\u0440\u0435\u0434\u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u044b\u0445\u0414\u0430\u043d\u043d\u044b\u0445',
|
||||
'\u0420\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0442\u043e\u0440', '\u041f\u0435\u0440\u0438\u043e\u0434',
|
||||
'\u041d\u043e\u043c\u0435\u0440\u0421\u0442\u0440\u043e\u043a\u0438', '\u0410\u043a\u0442\u0438\u0432\u043d\u043e\u0441\u0442\u044c',
|
||||
'\u041f\u043e\u0440\u044f\u0434\u043e\u043a', '\u0422\u0438\u043f', '\u0417\u0430\u0431\u0430\u043b\u0430\u043d\u0441\u043e\u0432\u044b\u0439',
|
||||
'\u0421\u0442\u0430\u0440\u0442\u043e\u0432\u0430\u043d', '\u0417\u0430\u0432\u0435\u0440\u0448\u0435\u043d',
|
||||
'\u0412\u0435\u0434\u0443\u0449\u0430\u044f\u0417\u0430\u0434\u0430\u0447\u0430',
|
||||
'\u0412\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0430', '\u0422\u043e\u0447\u043a\u0430\u041c\u0430\u0440\u0448\u0440\u0443\u0442\u0430',
|
||||
'\u0411\u0438\u0437\u043d\u0435\u0441\u041f\u0440\u043e\u0446\u0435\u0441\u0441',
|
||||
'\u042d\u0442\u043e\u0442\u0423\u0437\u0435\u043b', '\u041d\u043e\u043c\u0435\u0440\u041e\u0442\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u043d\u043e\u0433\u043e',
|
||||
'\u041d\u043e\u043c\u0435\u0440\u041f\u0440\u0438\u043d\u044f\u0442\u043e\u0433\u043e',
|
||||
'\u0412\u0438\u0434\u0420\u0430\u0441\u0447\u0435\u0442\u0430', '\u041f\u0435\u0440\u0438\u043e\u0434\u0420\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u0438',
|
||||
'\u0421\u0442\u043e\u0440\u043d\u043e\u0417\u0430\u043f\u0438\u0441\u044c',
|
||||
'\u0421\u0447\u0435\u0442', '\u0422\u0438\u043f\u0417\u043d\u0430\u0447\u0435\u043d\u0438\u044f',
|
||||
'\u041f\u0435\u0440\u0438\u043e\u0434\u0414\u0435\u0439\u0441\u0442\u0432\u0438\u044f\u0411\u0430\u0437\u043e\u0432\u044b\u0439',
|
||||
}
|
||||
|
||||
def emit_attribute(indent, parsed, context):
|
||||
attr_name = parsed['name']
|
||||
if attr_name in RESERVED_ATTR_NAMES or attr_name in RESERVED_ATTR_NAMES_RU:
|
||||
print(f"WARNING: Attribute '{attr_name}' conflicts with a standard attribute name. This may cause errors when loading into 1C.", file=sys.stderr)
|
||||
uid = new_uuid()
|
||||
X(f'{indent}<Attribute uuid="{uid}">')
|
||||
X(f'{indent}\t<Properties>')
|
||||
@@ -1250,18 +1289,12 @@ def emit_exchange_plan_properties(indent):
|
||||
X(f'{i}<UseStandardCommands>true</UseStandardCommands>')
|
||||
code_length = str(defn['codeLength']) if defn.get('codeLength') is not None else '9'
|
||||
description_length = str(defn['descriptionLength']) if defn.get('descriptionLength') is not None else '100'
|
||||
code_type = str(defn['codeType']) if defn.get('codeType') else 'String'
|
||||
code_allowed_length = str(defn['codeAllowedLength']) if defn.get('codeAllowedLength') else 'Variable'
|
||||
autonumbering = 'false' if defn.get('autonumbering') is False else 'true'
|
||||
check_unique = 'true' if defn.get('checkUnique') is True else 'false'
|
||||
X(f'{i}<CodeLength>{code_length}</CodeLength>')
|
||||
X(f'{i}<CodeType>{code_type}</CodeType>')
|
||||
X(f'{i}<CodeAllowedLength>{code_allowed_length}</CodeAllowedLength>')
|
||||
X(f'{i}<DescriptionLength>{description_length}</DescriptionLength>')
|
||||
X(f'{i}<DefaultPresentation>AsDescription</DefaultPresentation>')
|
||||
X(f'{i}<EditType>InDialog</EditType>')
|
||||
X(f'{i}<CheckUnique>{check_unique}</CheckUnique>')
|
||||
X(f'{i}<Autonumbering>{autonumbering}</Autonumbering>')
|
||||
emit_standard_attributes(i, 'ExchangePlan')
|
||||
distributed = 'true' if defn.get('distributedInfoBase') is True else 'false'
|
||||
include_ext = 'true' if defn.get('includeConfigurationExtensions') is True else 'false'
|
||||
@@ -1664,6 +1697,11 @@ def emit_business_process_properties(indent):
|
||||
X(f'{i}<Autonumbering>{autonumbering}</Autonumbering>')
|
||||
emit_standard_attributes(i, 'BusinessProcess')
|
||||
X(f'{i}<Characteristics/>')
|
||||
task_ref = str(defn['task']) if defn.get('task') else ''
|
||||
if task_ref:
|
||||
X(f'{i}<Task>{task_ref}</Task>')
|
||||
else:
|
||||
X(f'{i}<Task/>')
|
||||
X(f'{i}<BasedOn/>')
|
||||
X(f'{i}<InputByString>')
|
||||
X(f'{i}\t<xr:Field>BusinessProcess.{obj_name}.StandardAttribute.Number</xr:Field>')
|
||||
@@ -2335,14 +2373,14 @@ if obj_type in types_with_module:
|
||||
if obj_type == 'ExchangePlan':
|
||||
content_path = os.path.join(ext_dir, 'Content.xml')
|
||||
if not os.path.isfile(content_path):
|
||||
content_xml = '<?xml version="1.0" encoding="UTF-8"?>\r\n<ExchangePlanContent xmlns="http://v8.1c.ru/8.3/MDClasses" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"/>\r\n'
|
||||
content_xml = '<?xml version="1.0" encoding="UTF-8"?>\r\n<ExchangePlanContent xmlns="http://v8.1c.ru/8.3/xcf/extrnprops" xmlns:xr="http://v8.1c.ru/8.3/xcf/readable" version="2.17"/>\r\n'
|
||||
write_utf8_bom(content_path, content_xml)
|
||||
modules_created.append(content_path)
|
||||
|
||||
if obj_type == 'BusinessProcess':
|
||||
flowchart_path = os.path.join(ext_dir, 'Flowchart.xml')
|
||||
if not os.path.isfile(flowchart_path):
|
||||
flowchart_xml = '<?xml version="1.0" encoding="UTF-8"?>\r\n<Flowchart xmlns="http://v8.1c.ru/8.3/MDClasses"/>\r\n'
|
||||
flowchart_xml = '<?xml version="1.0" encoding="UTF-8"?>\r\n<Flowchart xmlns="http://v8.1c.ru/8.3/MDClasses" version="2.17"/>\r\n'
|
||||
write_utf8_bom(flowchart_path, flowchart_xml)
|
||||
modules_created.append(flowchart_path)
|
||||
|
||||
@@ -2464,3 +2502,19 @@ elif reg_result == 'no-childobj':
|
||||
print('WARNING: Configuration.xml found but <ChildObjects> not found', file=sys.stderr)
|
||||
elif reg_result == 'no-config':
|
||||
print(f' Configuration.xml: not found at {config_xml_path} (register manually)')
|
||||
|
||||
# Cross-reference hints
|
||||
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"')
|
||||
if obj_type == 'CalculationRegister' and not defn.get('chartOfCalculationTypes'):
|
||||
print('[HINT] CalculationRegister requires ChartOfCalculationTypes reference:')
|
||||
print(' /meta-edit -Operation modify-property -Value "ChartOfCalculationTypes=ChartOfCalculationTypes.XXX"')
|
||||
if obj_type == 'BusinessProcess' and not defn.get('task'):
|
||||
print('[HINT] BusinessProcess requires Task reference:')
|
||||
print(' /meta-edit -Operation modify-property -Value "Task=Task.XXX"')
|
||||
if obj_type == 'ChartOfAccounts':
|
||||
max_ext_dim = int(defn['maxExtDimensionCount']) if defn.get('maxExtDimensionCount') is not None else 0
|
||||
if max_ext_dim > 0 and not defn.get('extDimensionTypes'):
|
||||
print('[HINT] ChartOfAccounts with MaxExtDimensionCount>0 requires ExtDimensionTypes:')
|
||||
print(' /meta-edit -Operation modify-property -Value "ExtDimensionTypes=ChartOfCharacteristicTypes.XXX"')
|
||||
|
||||
@@ -649,6 +649,41 @@ if ($childObjNode) {
|
||||
|
||||
if ($script:stopped) { & $finalize; exit 1 }
|
||||
|
||||
# --- Check 7b: Reserved attribute names ---
|
||||
|
||||
$reservedAttrNames = @(
|
||||
"Ref","DeletionMark","Code","Description","Date","Number","Posted","Parent","Owner",
|
||||
"IsFolder","Predefined","PredefinedDataName","Recorder","Period","LineNumber","Active",
|
||||
"Order","Type","OffBalance","Started","Completed","HeadTask","Executed","RoutePoint",
|
||||
"BusinessProcess","ThisNode","SentNo","ReceivedNo","CalculationType","RegistrationPeriod",
|
||||
"ReversingEntry","Account","ValueType","ActionPeriodIsBasic"
|
||||
)
|
||||
|
||||
if ($childObjNode) {
|
||||
$check7bOk = $true
|
||||
$attrNodes = $childObjNode.SelectNodes("md:Attribute", $ns)
|
||||
foreach ($attrNode in $attrNodes) {
|
||||
$attrProps = $attrNode.SelectSingleNode("md:Properties", $ns)
|
||||
if ($attrProps) {
|
||||
$attrNameNode = $attrProps.SelectSingleNode("md:Name", $ns)
|
||||
if ($attrNameNode -and $attrNameNode.InnerText) {
|
||||
$an = $attrNameNode.InnerText
|
||||
if ($reservedAttrNames -contains $an) {
|
||||
Report-Warn "7b. Attribute '$an' conflicts with a standard attribute name"
|
||||
$check7bOk = $false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($check7bOk) {
|
||||
Report-OK "7b. Reserved attribute names: no conflicts"
|
||||
}
|
||||
} else {
|
||||
Report-OK "7b. Reserved attribute names: N/A"
|
||||
}
|
||||
|
||||
if ($script:stopped) { & $finalize; exit 1 }
|
||||
|
||||
# --- Check 8: Name uniqueness ---
|
||||
|
||||
function Check-Uniqueness {
|
||||
@@ -887,6 +922,51 @@ if ($propsNode) {
|
||||
$check10Issues++
|
||||
}
|
||||
}
|
||||
|
||||
# AccountingRegister: ChartOfAccounts must not be empty
|
||||
if ($mdType -eq "AccountingRegister") {
|
||||
$coa = $propsNode.SelectSingleNode("md:ChartOfAccounts", $ns)
|
||||
if (-not $coa -or -not $coa.InnerText.Trim()) {
|
||||
Report-Error "10. AccountingRegister: empty ChartOfAccounts"
|
||||
$check10Ok = $false
|
||||
$check10Issues++
|
||||
Write-Host "[HINT] /meta-edit -Operation modify-property -Value `"ChartOfAccounts=ChartOfAccounts.XXX`""
|
||||
}
|
||||
}
|
||||
|
||||
# CalculationRegister: ChartOfCalculationTypes must not be empty
|
||||
if ($mdType -eq "CalculationRegister") {
|
||||
$coct = $propsNode.SelectSingleNode("md:ChartOfCalculationTypes", $ns)
|
||||
if (-not $coct -or -not $coct.InnerText.Trim()) {
|
||||
Report-Error "10. CalculationRegister: empty ChartOfCalculationTypes"
|
||||
$check10Ok = $false
|
||||
$check10Issues++
|
||||
Write-Host "[HINT] /meta-edit -Operation modify-property -Value `"ChartOfCalculationTypes=ChartOfCalculationTypes.XXX`""
|
||||
}
|
||||
}
|
||||
|
||||
# BusinessProcess: Task should not be empty
|
||||
if ($mdType -eq "BusinessProcess") {
|
||||
$taskProp = $propsNode.SelectSingleNode("md:Task", $ns)
|
||||
if (-not $taskProp -or -not $taskProp.InnerText.Trim()) {
|
||||
Report-Warn "10. BusinessProcess: empty Task reference"
|
||||
$check10Issues++
|
||||
Write-Host "[HINT] /meta-edit -Operation modify-property -Value `"Task=Task.XXX`""
|
||||
}
|
||||
}
|
||||
|
||||
# ChartOfAccounts: ExtDimensionTypes should be set if MaxExtDimensionCount > 0
|
||||
if ($mdType -eq "ChartOfAccounts") {
|
||||
$maxExtDim = $propsNode.SelectSingleNode("md:MaxExtDimensionCount", $ns)
|
||||
if ($maxExtDim -and [int]$maxExtDim.InnerText -gt 0) {
|
||||
$edt = $propsNode.SelectSingleNode("md:ExtDimensionTypes", $ns)
|
||||
if (-not $edt -or -not $edt.InnerText.Trim()) {
|
||||
Report-Warn "10. ChartOfAccounts: MaxExtDimensionCount>0 but ExtDimensionTypes is empty"
|
||||
$check10Issues++
|
||||
Write-Host "[HINT] /meta-edit -Operation modify-property -Value `"ExtDimensionTypes=ChartOfCharacteristicTypes.XXX`""
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($check10Ok -and $check10Issues -eq 0) {
|
||||
|
||||
@@ -626,6 +626,37 @@ if stopped:
|
||||
finalize()
|
||||
sys.exit(1)
|
||||
|
||||
# ── Check 7b: Reserved attribute names ───────────────────────
|
||||
|
||||
RESERVED_ATTR_NAMES = {
|
||||
'Ref', 'DeletionMark', 'Code', 'Description', 'Date', 'Number', 'Posted',
|
||||
'Parent', 'Owner', 'IsFolder', 'Predefined', 'PredefinedDataName',
|
||||
'Recorder', 'Period', 'LineNumber', 'Active', 'Order', 'Type', 'OffBalance',
|
||||
'Started', 'Completed', 'HeadTask', 'Executed', 'RoutePoint', 'BusinessProcess',
|
||||
'ThisNode', 'SentNo', 'ReceivedNo', 'CalculationType', 'RegistrationPeriod',
|
||||
'ReversingEntry', 'Account', 'ValueType', 'ActionPeriodIsBasic',
|
||||
}
|
||||
|
||||
if child_obj_node is not None:
|
||||
check7b_ok = True
|
||||
for attr_node in find_all(child_obj_node, 'md:Attribute'):
|
||||
attr_props = find(attr_node, 'md:Properties')
|
||||
if attr_props is not None:
|
||||
attr_name_node = find(attr_props, 'md:Name')
|
||||
if attr_name_node is not None and inner_text(attr_name_node):
|
||||
an = inner_text(attr_name_node)
|
||||
if an in RESERVED_ATTR_NAMES:
|
||||
report_warn(f"7b. Attribute '{an}' conflicts with a standard attribute name")
|
||||
check7b_ok = False
|
||||
if check7b_ok:
|
||||
report_ok("7b. Reserved attribute names: no conflicts")
|
||||
else:
|
||||
report_ok("7b. Reserved attribute names: N/A")
|
||||
|
||||
if stopped:
|
||||
finalize()
|
||||
sys.exit(1)
|
||||
|
||||
# ── Check 8: Name uniqueness ─────────────────────────────────
|
||||
|
||||
|
||||
@@ -841,6 +872,47 @@ if props_node is not None:
|
||||
check10_ok = False
|
||||
check10_issues += 1
|
||||
|
||||
# AccountingRegister: ChartOfAccounts must not be empty
|
||||
if md_type == 'AccountingRegister':
|
||||
coa = find(props_node, 'md:ChartOfAccounts')
|
||||
if coa is None or not text_of(coa):
|
||||
report_error('10. AccountingRegister: empty ChartOfAccounts')
|
||||
check10_ok = False
|
||||
check10_issues += 1
|
||||
print('[HINT] /meta-edit -Operation modify-property -Value "ChartOfAccounts=ChartOfAccounts.XXX"')
|
||||
|
||||
# CalculationRegister: ChartOfCalculationTypes must not be empty
|
||||
if md_type == 'CalculationRegister':
|
||||
coct = find(props_node, 'md:ChartOfCalculationTypes')
|
||||
if coct is None or not text_of(coct):
|
||||
report_error('10. CalculationRegister: empty ChartOfCalculationTypes')
|
||||
check10_ok = False
|
||||
check10_issues += 1
|
||||
print('[HINT] /meta-edit -Operation modify-property -Value "ChartOfCalculationTypes=ChartOfCalculationTypes.XXX"')
|
||||
|
||||
# BusinessProcess: Task should not be empty
|
||||
if md_type == 'BusinessProcess':
|
||||
task_prop = find(props_node, 'md:Task')
|
||||
if task_prop is None or not text_of(task_prop):
|
||||
report_warn('10. BusinessProcess: empty Task reference')
|
||||
check10_issues += 1
|
||||
print('[HINT] /meta-edit -Operation modify-property -Value "Task=Task.XXX"')
|
||||
|
||||
# ChartOfAccounts: ExtDimensionTypes should be set if MaxExtDimensionCount > 0
|
||||
if md_type == 'ChartOfAccounts':
|
||||
max_ext_dim = find(props_node, 'md:MaxExtDimensionCount')
|
||||
if max_ext_dim is not None:
|
||||
try:
|
||||
med_val = int(inner_text(max_ext_dim) or '0')
|
||||
except ValueError:
|
||||
med_val = 0
|
||||
if med_val > 0:
|
||||
edt = find(props_node, 'md:ExtDimensionTypes')
|
||||
if edt is None or not text_of(edt):
|
||||
report_warn('10. ChartOfAccounts: MaxExtDimensionCount>0 but ExtDimensionTypes is empty')
|
||||
check10_issues += 1
|
||||
print('[HINT] /meta-edit -Operation modify-property -Value "ExtDimensionTypes=ChartOfCharacteristicTypes.XXX"')
|
||||
|
||||
if check10_ok and check10_issues == 0:
|
||||
report_ok("10. Cross-property consistency")
|
||||
|
||||
|
||||
@@ -580,6 +580,7 @@ DSL для `columns` (§12).
|
||||
| `autonumbering` | `true` | Autonumbering |
|
||||
| `dataLockControlMode` | `Automatic` | DataLockControlMode |
|
||||
| `fullTextSearch` | `Use` | FullTextSearch |
|
||||
| `task` | `""` | Task (ссылка на Task.XXX) |
|
||||
| `attributes` | `[]` | → Attribute в ChildObjects |
|
||||
| `tabularSections` | `{}` | → TabularSection в ChildObjects |
|
||||
|
||||
@@ -587,7 +588,7 @@ DSL для `columns` (§12).
|
||||
Дополнительно: `Ext/Flowchart.xml` (заглушка карты маршрута).
|
||||
|
||||
```json
|
||||
{ "type": "BusinessProcess", "name": "Задание", "attributes": ["Описание: String(200)"] }
|
||||
{ "type": "BusinessProcess", "name": "Задание", "task": "Task.ЗадачаИсполнителя", "attributes": ["Описание: String(200)"] }
|
||||
```
|
||||
|
||||
### 7.21 Task
|
||||
|
||||
Reference in New Issue
Block a user