diff --git a/.claude/skills/cf-edit/scripts/cf-edit.ps1 b/.claude/skills/cf-edit/scripts/cf-edit.ps1 index 1e876400..0973ae9c 100644 --- a/.claude/skills/cf-edit/scripts/cf-edit.ps1 +++ b/.claude/skills/cf-edit/scripts/cf-edit.ps1 @@ -1,4 +1,4 @@ -# cf-edit v1.7 — Edit 1C configuration root (Configuration.xml) +# cf-edit v1.8 — Edit 1C configuration root (Configuration.xml) # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills param( [Parameter(Mandatory)][Alias('Path')][string]$ConfigPath, @@ -196,7 +196,7 @@ Info "Configuration: $($script:objName)" $script:typeOrder = @( "Language","Subsystem","StyleItem","Style", "CommonPicture","SessionParameter","Role","CommonTemplate", - "FilterCriterion","CommonModule","CommonAttribute","ExchangePlan", + "FilterCriterion","CommonModule","Bot","CommonAttribute","ExchangePlan", "XDTOPackage","WebService","HTTPService","WSReference", "EventSubscription","ScheduledJob","SettingsStorage","FunctionalOption", "FunctionalOptionsParameter","DefinedType","CommonCommand","CommandGroup", @@ -212,7 +212,7 @@ $script:typeOrder = @( $script:typeToDir = @{ "Language"="Languages"; "Subsystem"="Subsystems"; "StyleItem"="StyleItems"; "Style"="Styles" "CommonPicture"="CommonPictures"; "SessionParameter"="SessionParameters"; "Role"="Roles"; "CommonTemplate"="CommonTemplates" - "FilterCriterion"="FilterCriteria"; "CommonModule"="CommonModules"; "CommonAttribute"="CommonAttributes"; "ExchangePlan"="ExchangePlans" + "FilterCriterion"="FilterCriteria"; "CommonModule"="CommonModules"; "Bot"="Bots"; "CommonAttribute"="CommonAttributes"; "ExchangePlan"="ExchangePlans" "XDTOPackage"="XDTOPackages"; "WebService"="WebServices"; "HTTPService"="HTTPServices"; "WSReference"="WSReferences" "EventSubscription"="EventSubscriptions"; "ScheduledJob"="ScheduledJobs"; "SettingsStorage"="SettingsStorages"; "FunctionalOption"="FunctionalOptions" "FunctionalOptionsParameter"="FunctionalOptionsParameters"; "DefinedType"="DefinedTypes"; "CommonCommand"="CommonCommands"; "CommandGroup"="CommandGroups" @@ -700,6 +700,7 @@ $script:ruTypeMap = @{ "регистррасчёта" = "CalculationRegister" "бизнеспроцесс" = "BusinessProcess" "задача" = "Task" + "бот" = "Bot" "планобмена" = "ExchangePlan" "хранилищенастроек" = "SettingsStorage" } diff --git a/.claude/skills/cf-edit/scripts/cf-edit.py b/.claude/skills/cf-edit/scripts/cf-edit.py index f10bffef..9aa6c5c8 100644 --- a/.claude/skills/cf-edit/scripts/cf-edit.py +++ b/.claude/skills/cf-edit/scripts/cf-edit.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# cf-edit v1.7 — Edit 1C configuration root (Configuration.xml) +# cf-edit v1.8 — Edit 1C configuration root (Configuration.xml) # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse @@ -182,7 +182,7 @@ XS_NS = "http://www.w3.org/2001/XMLSchema" TYPE_ORDER = [ "Language", "Subsystem", "StyleItem", "Style", "CommonPicture", "SessionParameter", "Role", "CommonTemplate", - "FilterCriterion", "CommonModule", "CommonAttribute", "ExchangePlan", + "FilterCriterion", "CommonModule", "Bot", "CommonAttribute", "ExchangePlan", "XDTOPackage", "WebService", "HTTPService", "WSReference", "EventSubscription", "ScheduledJob", "SettingsStorage", "FunctionalOption", "FunctionalOptionsParameter", "DefinedType", "CommonCommand", "CommandGroup", @@ -198,7 +198,7 @@ TYPE_ORDER = [ TYPE_TO_DIR = { "Language": "Languages", "Subsystem": "Subsystems", "StyleItem": "StyleItems", "Style": "Styles", "CommonPicture": "CommonPictures", "SessionParameter": "SessionParameters", "Role": "Roles", "CommonTemplate": "CommonTemplates", - "FilterCriterion": "FilterCriteria", "CommonModule": "CommonModules", "CommonAttribute": "CommonAttributes", "ExchangePlan": "ExchangePlans", + "FilterCriterion": "FilterCriteria", "CommonModule": "CommonModules", "Bot": "Bots", "CommonAttribute": "CommonAttributes", "ExchangePlan": "ExchangePlans", "XDTOPackage": "XDTOPackages", "WebService": "WebServices", "HTTPService": "HTTPServices", "WSReference": "WSReferences", "EventSubscription": "EventSubscriptions", "ScheduledJob": "ScheduledJobs", "SettingsStorage": "SettingsStorages", "FunctionalOption": "FunctionalOptions", "FunctionalOptionsParameter": "FunctionalOptionsParameters", "DefinedType": "DefinedTypes", "CommonCommand": "CommonCommands", "CommandGroup": "CommandGroups", @@ -771,6 +771,7 @@ def main(): "регистррасчета": "CalculationRegister", "регистррасчёта": "CalculationRegister", "бизнеспроцесс": "BusinessProcess", + "бот": "Bot", "задача": "Task", "планобмена": "ExchangePlan", "хранилищенастроек": "SettingsStorage", } diff --git a/.claude/skills/cf-info/scripts/cf-info.ps1 b/.claude/skills/cf-info/scripts/cf-info.ps1 index be050f68..b2d5a1b2 100644 --- a/.claude/skills/cf-info/scripts/cf-info.ps1 +++ b/.claude/skills/cf-info/scripts/cf-info.ps1 @@ -1,4 +1,4 @@ -# cf-info v1.3 — Compact summary of 1C configuration root +# cf-info v1.4 — Compact summary of 1C configuration root # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills param( [Parameter(Mandatory=$true)][Alias('Path')][string]$ConfigPath, @@ -89,7 +89,7 @@ function Get-PropML([string]$propName) { $typeOrder = @( "Language","Subsystem","StyleItem","Style", "CommonPicture","SessionParameter","Role","CommonTemplate", - "FilterCriterion","CommonModule","CommonAttribute","ExchangePlan", + "FilterCriterion","CommonModule","Bot","CommonAttribute","ExchangePlan", "XDTOPackage","WebService","HTTPService","WSReference", "EventSubscription","ScheduledJob","SettingsStorage","FunctionalOption", "FunctionalOptionsParameter","DefinedType","CommonCommand","CommandGroup", @@ -105,6 +105,7 @@ $typeRuNames = @{ "Language"="Языки"; "Subsystem"="Подсистемы"; "StyleItem"="Элементы стиля"; "Style"="Стили" "CommonPicture"="Общие картинки"; "SessionParameter"="Параметры сеанса"; "Role"="Роли" "CommonTemplate"="Общие макеты"; "FilterCriterion"="Критерии отбора"; "CommonModule"="Общие модули" + "Bot"="Боты" "CommonAttribute"="Общие реквизиты"; "ExchangePlan"="Планы обмена"; "XDTOPackage"="XDTO-пакеты" "WebService"="Веб-сервисы"; "HTTPService"="HTTP-сервисы"; "WSReference"="WS-ссылки" "EventSubscription"="Подписки на события"; "ScheduledJob"="Регламентные задания" diff --git a/.claude/skills/cf-info/scripts/cf-info.py b/.claude/skills/cf-info/scripts/cf-info.py index 4814cc27..eada7323 100644 --- a/.claude/skills/cf-info/scripts/cf-info.py +++ b/.claude/skills/cf-info/scripts/cf-info.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# cf-info v1.3 — Compact summary of 1C configuration root +# cf-info v1.4 — Compact summary of 1C configuration root # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse @@ -95,7 +95,7 @@ def get_prop_ml(prop_name): type_order = [ "Language", "Subsystem", "StyleItem", "Style", "CommonPicture", "SessionParameter", "Role", "CommonTemplate", - "FilterCriterion", "CommonModule", "CommonAttribute", "ExchangePlan", + "FilterCriterion", "CommonModule", "Bot", "CommonAttribute", "ExchangePlan", "XDTOPackage", "WebService", "HTTPService", "WSReference", "EventSubscription", "ScheduledJob", "SettingsStorage", "FunctionalOption", "FunctionalOptionsParameter", "DefinedType", "CommonCommand", "CommandGroup", @@ -111,6 +111,7 @@ type_ru_names = { "Language": "Языки", "Subsystem": "Подсистемы", "StyleItem": "Элементы стиля", "Style": "Стили", "CommonPicture": "Общие картинки", "SessionParameter": "Параметры сеанса", "Role": "Роли", "CommonTemplate": "Общие макеты", "FilterCriterion": "Критерии отбора", "CommonModule": "Общие модули", + "Bot": "Боты", "CommonAttribute": "Общие реквизиты", "ExchangePlan": "Планы обмена", "XDTOPackage": "XDTO-пакеты", "WebService": "Веб-сервисы", "HTTPService": "HTTP-сервисы", "WSReference": "WS-ссылки", "EventSubscription": "Подписки на события", "ScheduledJob": "Регламентные задания", diff --git a/.claude/skills/cf-validate/scripts/cf-validate.ps1 b/.claude/skills/cf-validate/scripts/cf-validate.ps1 index 365853b9..e59ff3c6 100644 --- a/.claude/skills/cf-validate/scripts/cf-validate.ps1 +++ b/.claude/skills/cf-validate/scripts/cf-validate.ps1 @@ -1,4 +1,4 @@ -# cf-validate v1.3 — Validate 1C configuration root structure +# cf-validate v1.4 — Validate 1C configuration root structure # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills param( [Parameter(Mandatory)] @@ -104,11 +104,11 @@ $validClassIds = @( "fb282519-d103-4dd3-bc12-cb271d631dfc" # home page / client app interface ) -# 44 types in canonical order +# 45 types in canonical order $childObjectTypes = @( "Language","Subsystem","StyleItem","Style", "CommonPicture","SessionParameter","Role","CommonTemplate", - "FilterCriterion","CommonModule","CommonAttribute","ExchangePlan", + "FilterCriterion","CommonModule","Bot","CommonAttribute","ExchangePlan", "XDTOPackage","WebService","HTTPService","WSReference", "EventSubscription","ScheduledJob","SettingsStorage","FunctionalOption", "FunctionalOptionsParameter","DefinedType","CommonCommand","CommandGroup", @@ -125,6 +125,7 @@ $childTypeDirMap = @{ "Language"="Languages"; "Subsystem"="Subsystems"; "StyleItem"="StyleItems"; "Style"="Styles" "CommonPicture"="CommonPictures"; "SessionParameter"="SessionParameters"; "Role"="Roles" "CommonTemplate"="CommonTemplates"; "FilterCriterion"="FilterCriteria"; "CommonModule"="CommonModules" + "Bot"="Bots" "CommonAttribute"="CommonAttributes"; "ExchangePlan"="ExchangePlans"; "XDTOPackage"="XDTOPackages" "WebService"="WebServices"; "HTTPService"="HTTPServices"; "WSReference"="WSReferences" "EventSubscription"="EventSubscriptions"; "ScheduledJob"="ScheduledJobs" diff --git a/.claude/skills/cf-validate/scripts/cf-validate.py b/.claude/skills/cf-validate/scripts/cf-validate.py index df1426d9..9b3ba9b6 100644 --- a/.claude/skills/cf-validate/scripts/cf-validate.py +++ b/.claude/skills/cf-validate/scripts/cf-validate.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# cf-validate v1.3 — Validate 1C configuration XML structure +# cf-validate v1.4 — Validate 1C configuration XML structure # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills """Validates Configuration.xml: root structure, InternalInfo, properties, ChildObjects, languages.""" import sys, os, argparse, re @@ -33,11 +33,11 @@ VALID_CLASS_IDS = [ 'fb282519-d103-4dd3-bc12-cb271d631dfc', # home page / client app interface ] -# 44 types in canonical order +# 45 types in canonical order CHILD_OBJECT_TYPES = [ 'Language', 'Subsystem', 'StyleItem', 'Style', 'CommonPicture', 'SessionParameter', 'Role', 'CommonTemplate', - 'FilterCriterion', 'CommonModule', 'CommonAttribute', 'ExchangePlan', + 'FilterCriterion', 'CommonModule', 'Bot', 'CommonAttribute', 'ExchangePlan', 'XDTOPackage', 'WebService', 'HTTPService', 'WSReference', 'EventSubscription', 'ScheduledJob', 'SettingsStorage', 'FunctionalOption', 'FunctionalOptionsParameter', 'DefinedType', 'CommonCommand', 'CommandGroup', @@ -54,6 +54,7 @@ CHILD_TYPE_DIR_MAP = { 'Language': 'Languages', 'Subsystem': 'Subsystems', 'StyleItem': 'StyleItems', 'Style': 'Styles', 'CommonPicture': 'CommonPictures', 'SessionParameter': 'SessionParameters', 'Role': 'Roles', 'CommonTemplate': 'CommonTemplates', 'FilterCriterion': 'FilterCriteria', 'CommonModule': 'CommonModules', + 'Bot': 'Bots', 'CommonAttribute': 'CommonAttributes', 'ExchangePlan': 'ExchangePlans', 'XDTOPackage': 'XDTOPackages', 'WebService': 'WebServices', 'HTTPService': 'HTTPServices', 'WSReference': 'WSReferences', 'EventSubscription': 'EventSubscriptions', 'ScheduledJob': 'ScheduledJobs', diff --git a/.claude/skills/meta-compile/scripts/meta-compile.ps1 b/.claude/skills/meta-compile/scripts/meta-compile.ps1 index 1424c784..f0a881fe 100644 --- a/.claude/skills/meta-compile/scripts/meta-compile.ps1 +++ b/.claude/skills/meta-compile/scripts/meta-compile.ps1 @@ -1,4 +1,4 @@ -# meta-compile v1.49 — Compile 1C metadata object from JSON +# meta-compile v1.50 — Compile 1C metadata object from JSON # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills param( [Parameter(Mandatory)] diff --git a/.claude/skills/meta-compile/scripts/meta-compile.py b/.claude/skills/meta-compile/scripts/meta-compile.py index ddfa5eb7..66e895ec 100644 --- a/.claude/skills/meta-compile/scripts/meta-compile.py +++ b/.claude/skills/meta-compile/scripts/meta-compile.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# meta-compile v1.49 — Compile 1C metadata object from JSON +# meta-compile v1.50 — Compile 1C metadata object from JSON # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse @@ -4031,21 +4031,19 @@ reg_result = None child_tag = obj_type if os.path.isfile(config_xml_path): - # Parse preserving whitespace via raw string manipulation - with open(config_xml_path, 'r', encoding='utf-8-sig') as f: + # Read raw content, preserving BOM/EOL byte-for-byte (newline='' => no translation). + with open(config_xml_path, 'r', encoding='utf-8-sig', newline='') as f: config_content = f.read() ns = 'http://v8.1c.ru/8.3/MDClasses' - ET.register_namespace('', ns) - # Parse all namespaces used in the file - # Use iterparse to collect namespace prefixes - namespaces_in_file = {} - for evt, elem in ET.iterparse(config_xml_path, events=['start-ns']): - prefix, uri = elem - if prefix: - namespaces_in_file[prefix] = uri - ET.register_namespace(prefix, uri) - + # ET is used ONLY read-only here: to locate ChildObjects and detect a duplicate. + # We deliberately do NOT re-serialize Configuration.xml with ElementTree.write(): + # it drops every xmlns declaration used only inside attribute VALUES (e.g. + # xsi:type="app:ApplicationUsePurpose" in UsePurposes) because ET never sees those + # prefixes in element/attribute names. The dropped declaration makes XDTO read the + # value as anyType and Designer refuses to load the file (issue #38). Registration is + # therefore done by raw-text insertion, preserving BOM, EOL and all namespaces + # byte-for-byte (same approach as subsystem-compile). tree = ET.parse(config_xml_path) root = tree.getroot() @@ -4056,41 +4054,47 @@ if os.path.isfile(config_xml_path): if config_elem is not None: child_objects = config_elem.find(f'{{{ns}}}ChildObjects') - if child_objects is not None: + if child_objects is None: + reg_result = 'no-childobj' + else: existing = child_objects.findall(f'{{{ns}}}{child_tag}') - already_exists = False - for e in existing: - if (e.text or '').strip() == obj_name: - already_exists = True - break + already_exists = any((e.text or '').strip() == obj_name for e in existing) if already_exists: reg_result = 'already' else: - new_elem = ET.SubElement(child_objects, f'{{{ns}}}{child_tag}') - new_elem.text = obj_name + eol = '\r\n' if '\r\n' in config_content else '\n' + entry = f'<{child_tag}>{esc_xml(obj_name)}' - if existing: - # Insert after last existing element of same type - last_elem = existing[-1] - all_children = list(child_objects) - idx = all_children.index(last_elem) - child_objects.remove(new_elem) - child_objects.insert(idx + 1, new_elem) - - # Write back preserving BOM - tree.write(config_xml_path, encoding='utf-8', xml_declaration=True) - # Re-read to add BOM, fix declaration quotes, ensure trailing newline - with open(config_xml_path, 'r', encoding='utf-8') as f: - raw = f.read() - if raw.startswith(""): - raw = raw.replace("", '', 1) - if not raw.endswith('\n'): - raw += '\n' - write_utf8_bom(config_xml_path, raw) - reg_result = 'added' - else: - reg_result = 'no-childobj' + block = re.search(r'.*?', config_content, re.S) + if block is None: + # Empty self-closing => open it with the first entry. + empty = re.search(r'', config_content) + if empty is None: + reg_result = 'no-childobj' + else: + replacement = f'{eol}\t\t\t{entry}{eol}\t\t' + new_content = config_content[:empty.start()] + replacement + config_content[empty.end():] + write_utf8_bom(config_xml_path, new_content) + reg_result = 'added' + else: + close_same = f'' + last_same = config_content.rfind(close_same, block.start(), block.end()) + if last_same != -1: + # After the last element of the same type (keeps them grouped). + insert_at = last_same + len(close_same) + new_content = (config_content[:insert_at] + + f'{eol}\t\t\t{entry}' + + config_content[insert_at:]) + else: + # No element of this type yet: new line before , + # reusing the block's existing closing indent for . + close_at = config_content.rfind('', block.start(), block.end()) + new_content = (config_content[:close_at] + + f'\t{entry}{eol}\t\t' + + config_content[close_at:]) + write_utf8_bom(config_xml_path, new_content) + reg_result = 'added' else: reg_result = 'no-config' diff --git a/docs/1c-configuration-spec.md b/docs/1c-configuration-spec.md index 8a9d08ab..3afc40a3 100644 --- a/docs/1c-configuration-spec.md +++ b/docs/1c-configuration-spec.md @@ -193,6 +193,7 @@ ClassId — фиксированные идентификаторы классо fresh ДокументыПоВидуОплаты АвтоматическиеСкидки + КомментарийЯзык1 ОбновлениеИнформационнойБазы AgentScripts @@ -244,40 +245,41 @@ ClassId — фиксированные идентификаторы классо | 8 | `CommonTemplate` | `CommonTemplates/` | Общие макеты | | 9 | `FilterCriterion` | `FilterCriteria/` | Критерии отбора | | 10 | `CommonModule` | `CommonModules/` | Общие модули | -| 11 | `CommonAttribute` | `CommonAttributes/` | Общие реквизиты | -| 12 | `ExchangePlan` | `ExchangePlans/` | Планы обмена | -| 13 | `XDTOPackage` | `XDTOPackages/` | XDTO-пакеты | -| 14 | `WebService` | `WebServices/` | Веб-сервисы | -| 15 | `HTTPService` | `HTTPServices/` | HTTP-сервисы | -| 16 | `WSReference` | `WSReferences/` | WS-ссылки | -| 17 | `EventSubscription` | `EventSubscriptions/` | Подписки на события | -| 18 | `ScheduledJob` | `ScheduledJobs/` | Регламентные задания | -| 19 | `SettingsStorage` | `SettingsStorages/` | Хранилища настроек | -| 20 | `FunctionalOption` | `FunctionalOptions/` | Функциональные опции | -| 21 | `FunctionalOptionsParameter` | `FunctionalOptionsParameters/` | Параметры ФО | -| 22 | `DefinedType` | `DefinedTypes/` | Определяемые типы | -| 23 | `CommonCommand` | `CommonCommands/` | Общие команды | -| 24 | `CommandGroup` | `CommandGroups/` | Группы команд | -| 25 | `Constant` | `Constants/` | Константы | -| 26 | `CommonForm` | `CommonForms/` | Общие формы | -| 27 | `Catalog` | `Catalogs/` | Справочники | -| 28 | `Document` | `Documents/` | Документы | -| 29 | `DocumentNumerator` | `DocumentNumerators/` | Нумераторы документов | -| 30 | `Sequence` | `Sequences/` | Последовательности | -| 31 | `DocumentJournal` | `DocumentJournals/` | Журналы документов | -| 32 | `Enum` | `Enums/` | Перечисления | -| 33 | `Report` | `Reports/` | Отчёты | -| 34 | `DataProcessor` | `DataProcessors/` | Обработки | -| 35 | `InformationRegister` | `InformationRegisters/` | Регистры сведений | -| 36 | `AccumulationRegister` | `AccumulationRegisters/` | Регистры накопления | -| 37 | `ChartOfCharacteristicTypes` | `ChartsOfCharacteristicTypes/` | Планы видов характеристик | -| 38 | `ChartOfAccounts` | `ChartsOfAccounts/` | Планы счетов | -| 39 | `AccountingRegister` | `AccountingRegisters/` | Регистры бухгалтерии | -| 40 | `ChartOfCalculationTypes` | `ChartsOfCalculationTypes/` | Планы видов расчёта | -| 41 | `CalculationRegister` | `CalculationRegisters/` | Регистры расчёта | -| 42 | `BusinessProcess` | `BusinessProcesses/` | Бизнес-процессы | -| 43 | `Task` | `Tasks/` | Задачи | -| 44 | `IntegrationService` | `IntegrationServices/` | Сервисы интеграции | +| 11 | `Bot` | `Bots/` | Боты (платформа 8.3.18+) | +| 12 | `CommonAttribute` | `CommonAttributes/` | Общие реквизиты | +| 13 | `ExchangePlan` | `ExchangePlans/` | Планы обмена | +| 14 | `XDTOPackage` | `XDTOPackages/` | XDTO-пакеты | +| 15 | `WebService` | `WebServices/` | Веб-сервисы | +| 16 | `HTTPService` | `HTTPServices/` | HTTP-сервисы | +| 17 | `WSReference` | `WSReferences/` | WS-ссылки | +| 18 | `EventSubscription` | `EventSubscriptions/` | Подписки на события | +| 19 | `ScheduledJob` | `ScheduledJobs/` | Регламентные задания | +| 20 | `SettingsStorage` | `SettingsStorages/` | Хранилища настроек | +| 21 | `FunctionalOption` | `FunctionalOptions/` | Функциональные опции | +| 22 | `FunctionalOptionsParameter` | `FunctionalOptionsParameters/` | Параметры ФО | +| 23 | `DefinedType` | `DefinedTypes/` | Определяемые типы | +| 24 | `CommonCommand` | `CommonCommands/` | Общие команды | +| 25 | `CommandGroup` | `CommandGroups/` | Группы команд | +| 26 | `Constant` | `Constants/` | Константы | +| 27 | `CommonForm` | `CommonForms/` | Общие формы | +| 28 | `Catalog` | `Catalogs/` | Справочники | +| 29 | `Document` | `Documents/` | Документы | +| 30 | `DocumentNumerator` | `DocumentNumerators/` | Нумераторы документов | +| 31 | `Sequence` | `Sequences/` | Последовательности | +| 32 | `DocumentJournal` | `DocumentJournals/` | Журналы документов | +| 33 | `Enum` | `Enums/` | Перечисления | +| 34 | `Report` | `Reports/` | Отчёты | +| 35 | `DataProcessor` | `DataProcessors/` | Обработки | +| 36 | `InformationRegister` | `InformationRegisters/` | Регистры сведений | +| 37 | `AccumulationRegister` | `AccumulationRegisters/` | Регистры накопления | +| 38 | `ChartOfCharacteristicTypes` | `ChartsOfCharacteristicTypes/` | Планы видов характеристик | +| 39 | `ChartOfAccounts` | `ChartsOfAccounts/` | Планы счетов | +| 40 | `AccountingRegister` | `AccountingRegisters/` | Регистры бухгалтерии | +| 41 | `ChartOfCalculationTypes` | `ChartsOfCalculationTypes/` | Планы видов расчёта | +| 42 | `CalculationRegister` | `CalculationRegisters/` | Регистры расчёта | +| 43 | `BusinessProcess` | `BusinessProcesses/` | Бизнес-процессы | +| 44 | `Task` | `Tasks/` | Задачи | +| 45 | `IntegrationService` | `IntegrationServices/` | Сервисы интеграции | Внутри одного типа объекты отсортированы по имени (алфавитный порядок). Типы, для которых нет объектов, в ChildObjects не записываются. diff --git a/tests/skills/cases/cf-edit/add-bot.json b/tests/skills/cases/cf-edit/add-bot.json new file mode 100644 index 00000000..45cf651d --- /dev/null +++ b/tests/skills/cases/cf-edit/add-bot.json @@ -0,0 +1,7 @@ +{ + "name": "Регистрация Bot в ChildObjects", + "setup": "fixture:add-bot", + "input": [ + { "operation": "add-childObject", "value": "Bot.ОповещенияПользователейОСобытиях" } + ] +} diff --git a/tests/skills/cases/cf-edit/fixtures/add-bot/Bots/ОповещенияПользователейОСобытиях.xml b/tests/skills/cases/cf-edit/fixtures/add-bot/Bots/ОповещенияПользователейОСобытиях.xml new file mode 100644 index 00000000..0c700217 --- /dev/null +++ b/tests/skills/cases/cf-edit/fixtures/add-bot/Bots/ОповещенияПользователейОСобытиях.xml @@ -0,0 +1,12 @@ + + + + + ОповещенияПользователейОСобытиях + + + true + + + + diff --git a/tests/skills/cases/cf-edit/fixtures/add-bot/Configuration.xml b/tests/skills/cases/cf-edit/fixtures/add-bot/Configuration.xml new file mode 100644 index 00000000..3a873eda --- /dev/null +++ b/tests/skills/cases/cf-edit/fixtures/add-bot/Configuration.xml @@ -0,0 +1,67 @@ + + + + + + 9cd510cd-abfc-11d4-9434-004095e12fc7 + 2145bb60-cbf8-459a-aa10-bea7f44e3f2f + + + 9fcd25a0-4822-11d4-9414-008048da11f9 + 6a26f594-55f0-4be3-ac78-98f735640668 + + + e3687481-0a87-462c-a166-9f34594f9bba + 7a4686f3-b998-4656-8cba-2dd53cca2c29 + + + 9de14907-ec23-4a07-96f0-85521cb6b53b + 1078616c-b4eb-469d-a25c-2ff8b13eeb1e + + + 51f2d5d8-ea4d-4064-8892-82951750031e + db007a87-7b0a-416f-bf30-ccf10c265e5e + + + e68182ea-4237-4383-967f-90c1e3370bc7 + de40bd20-2175-4d6f-a131-e4ba036aaf5f + + + fb282519-d103-4dd3-bc12-cb271d631dfc + b26c5d95-9559-4a74-bdde-db40d73f3596 + + + + БотДемо + + + ru + Бот демо + + + + + Version8_3_24 + ManagedApplication + + PlatformApplication + + Russian + + + + Version8_3_24 + Language.Русский + Managed + NotAutoFree + DontUse + DontUse + TaxiEnableVersion8_2 + Normal + + + + Русский + + + diff --git a/tests/skills/cases/cf-edit/fixtures/add-bot/Languages/Русский.xml b/tests/skills/cases/cf-edit/fixtures/add-bot/Languages/Русский.xml new file mode 100644 index 00000000..21119ca7 --- /dev/null +++ b/tests/skills/cases/cf-edit/fixtures/add-bot/Languages/Русский.xml @@ -0,0 +1,16 @@ + + + + + Русский + + + ru + Русский + + + + ru + + + diff --git a/tests/skills/cases/cf-info/fixtures/with-bot/Bots/ОповещенияПользователейОСобытиях.xml b/tests/skills/cases/cf-info/fixtures/with-bot/Bots/ОповещенияПользователейОСобытиях.xml new file mode 100644 index 00000000..0c700217 --- /dev/null +++ b/tests/skills/cases/cf-info/fixtures/with-bot/Bots/ОповещенияПользователейОСобытиях.xml @@ -0,0 +1,12 @@ + + + + + ОповещенияПользователейОСобытиях + + + true + + + + diff --git a/tests/skills/cases/cf-info/fixtures/with-bot/Configuration.xml b/tests/skills/cases/cf-info/fixtures/with-bot/Configuration.xml new file mode 100644 index 00000000..f4ad7c07 --- /dev/null +++ b/tests/skills/cases/cf-info/fixtures/with-bot/Configuration.xml @@ -0,0 +1,68 @@ + + + + + + 9cd510cd-abfc-11d4-9434-004095e12fc7 + 2145bb60-cbf8-459a-aa10-bea7f44e3f2f + + + 9fcd25a0-4822-11d4-9414-008048da11f9 + 6a26f594-55f0-4be3-ac78-98f735640668 + + + e3687481-0a87-462c-a166-9f34594f9bba + 7a4686f3-b998-4656-8cba-2dd53cca2c29 + + + 9de14907-ec23-4a07-96f0-85521cb6b53b + 1078616c-b4eb-469d-a25c-2ff8b13eeb1e + + + 51f2d5d8-ea4d-4064-8892-82951750031e + db007a87-7b0a-416f-bf30-ccf10c265e5e + + + e68182ea-4237-4383-967f-90c1e3370bc7 + de40bd20-2175-4d6f-a131-e4ba036aaf5f + + + fb282519-d103-4dd3-bc12-cb271d631dfc + b26c5d95-9559-4a74-bdde-db40d73f3596 + + + + БотДемо + + + ru + Бот демо + + + + + Version8_3_24 + ManagedApplication + + PlatformApplication + + Russian + + + + Version8_3_24 + Language.Русский + Managed + NotAutoFree + DontUse + DontUse + TaxiEnableVersion8_2 + Normal + + + + Русский + ОповещенияПользователейОСобытиях + + + diff --git a/tests/skills/cases/cf-info/fixtures/with-bot/Languages/Русский.xml b/tests/skills/cases/cf-info/fixtures/with-bot/Languages/Русский.xml new file mode 100644 index 00000000..21119ca7 --- /dev/null +++ b/tests/skills/cases/cf-info/fixtures/with-bot/Languages/Русский.xml @@ -0,0 +1,16 @@ + + + + + Русский + + + ru + Русский + + + + ru + + + diff --git a/tests/skills/cases/cf-info/with-bot.json b/tests/skills/cases/cf-info/with-bot.json new file mode 100644 index 00000000..312e5a4b --- /dev/null +++ b/tests/skills/cases/cf-info/with-bot.json @@ -0,0 +1,5 @@ +{ + "name": "Bot попадает в состав конфигурации", + "setup": "fixture:with-bot", + "expect": { "stdoutContains": "Боты" } +} diff --git a/tests/skills/cases/cf-validate/fixtures/with-bot/Bots/ОповещенияПользователейОСобытиях.xml b/tests/skills/cases/cf-validate/fixtures/with-bot/Bots/ОповещенияПользователейОСобытиях.xml new file mode 100644 index 00000000..0c700217 --- /dev/null +++ b/tests/skills/cases/cf-validate/fixtures/with-bot/Bots/ОповещенияПользователейОСобытиях.xml @@ -0,0 +1,12 @@ + + + + + ОповещенияПользователейОСобытиях + + + true + + + + diff --git a/tests/skills/cases/cf-validate/fixtures/with-bot/Configuration.xml b/tests/skills/cases/cf-validate/fixtures/with-bot/Configuration.xml new file mode 100644 index 00000000..f4ad7c07 --- /dev/null +++ b/tests/skills/cases/cf-validate/fixtures/with-bot/Configuration.xml @@ -0,0 +1,68 @@ + + + + + + 9cd510cd-abfc-11d4-9434-004095e12fc7 + 2145bb60-cbf8-459a-aa10-bea7f44e3f2f + + + 9fcd25a0-4822-11d4-9414-008048da11f9 + 6a26f594-55f0-4be3-ac78-98f735640668 + + + e3687481-0a87-462c-a166-9f34594f9bba + 7a4686f3-b998-4656-8cba-2dd53cca2c29 + + + 9de14907-ec23-4a07-96f0-85521cb6b53b + 1078616c-b4eb-469d-a25c-2ff8b13eeb1e + + + 51f2d5d8-ea4d-4064-8892-82951750031e + db007a87-7b0a-416f-bf30-ccf10c265e5e + + + e68182ea-4237-4383-967f-90c1e3370bc7 + de40bd20-2175-4d6f-a131-e4ba036aaf5f + + + fb282519-d103-4dd3-bc12-cb271d631dfc + b26c5d95-9559-4a74-bdde-db40d73f3596 + + + + БотДемо + + + ru + Бот демо + + + + + Version8_3_24 + ManagedApplication + + PlatformApplication + + Russian + + + + Version8_3_24 + Language.Русский + Managed + NotAutoFree + DontUse + DontUse + TaxiEnableVersion8_2 + Normal + + + + Русский + ОповещенияПользователейОСобытиях + + + diff --git a/tests/skills/cases/cf-validate/fixtures/with-bot/Languages/Русский.xml b/tests/skills/cases/cf-validate/fixtures/with-bot/Languages/Русский.xml new file mode 100644 index 00000000..21119ca7 --- /dev/null +++ b/tests/skills/cases/cf-validate/fixtures/with-bot/Languages/Русский.xml @@ -0,0 +1,16 @@ + + + + + Русский + + + ru + Русский + + + + ru + + + diff --git a/tests/skills/cases/cf-validate/with-bot.json b/tests/skills/cases/cf-validate/with-bot.json new file mode 100644 index 00000000..b2889993 --- /dev/null +++ b/tests/skills/cases/cf-validate/with-bot.json @@ -0,0 +1,4 @@ +{ + "name": "Bot в ChildObjects проходит валидацию", + "setup": "fixture:with-bot" +} diff --git a/tests/skills/runner.mjs b/tests/skills/runner.mjs index ec9790c0..8a1dec65 100644 --- a/tests/skills/runner.mjs +++ b/tests/skills/runner.mjs @@ -292,7 +292,7 @@ function buildArgs(skillConfig, caseData, workDir, inputFilePath, runtime) { const UUID_RE = /[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/gi; -function normalizeXmlContent(text) { +function normalizeXmlContent(text, opts = {}) { let s = text; // 1. XML declaration: normalize quotes and encoding case s = s.replace( @@ -301,8 +301,13 @@ function normalizeXmlContent(text) { ); // 2. Remove (CR encoded as XML entity by Python etree) s = s.replace(/ /g, ''); - // 3. Strip xmlns declarations (Python etree strips unused ones) - s = s.replace(/\s+xmlns(?::[\w]+)?="[^"]*"/g, ''); + // 3. Strip xmlns declarations (Python etree strips unused ones). + // Skipped for Configuration.xml: those declarations are load-bearing (they back + // xsi:type values like app:ApplicationUsePurpose in UsePurposes) and dropping them + // is exactly the corruption of issue #38 — keeping them lets the test guard against it. + if (!opts.keepXmlns) { + s = s.replace(/\s+xmlns(?::[\w]+)?="[^"]*"/g, ''); + } // 4. Normalize self-closing tags: remove space before /> s = s.replace(/\s*\/>/g, '/>'); // 5. Collapse whitespace between tags: "> \n\t <" → "><" @@ -314,14 +319,15 @@ function normalizeXmlContent(text) { return s; } -function normalizeContent(text, config) { +function normalizeContent(text, config, relFile) { // Strip BOM let s = text.replace(/^\uFEFF/, ''); // Normalize line endings s = s.replace(/\r\n/g, '\n'); // Normalize XML differences (Python etree serialization quirks) if (config?.runtime === 'python') { - s = normalizeXmlContent(s); + const base = relFile ? relFile.split(/[\\/]/).pop() : ''; + s = normalizeXmlContent(s, { keepXmlns: base === 'Configuration.xml' }); } // Normalize UUIDs @@ -403,8 +409,8 @@ function compareSnapshot(workDir, snapshotDir, snapshotConfig) { const actualRaw = readFileSync(actualPath, 'utf8'); const snapshotRaw = readFileSync(snapshotPath, 'utf8'); - const actual = normalizeContent(actualRaw, snapshotConfig); - const expected = normalizeContent(snapshotRaw, snapshotConfig); + const actual = normalizeContent(actualRaw, snapshotConfig, relFile); + const expected = normalizeContent(snapshotRaw, snapshotConfig, relFile); if (actual !== expected) { // Find first differing line @@ -446,7 +452,7 @@ function updateSnapshot(workDir, snapshotDir, snapshotConfig) { mkdirSync(dirname(dst), { recursive: true }); const raw = readFileSync(src, 'utf8'); - const normalized = normalizeContent(raw, snapshotConfig); + const normalized = normalizeContent(raw, snapshotConfig, relFile); writeFileSync(dst, normalized, 'utf8'); } } diff --git a/tests/skills/verify-snapshots.mjs b/tests/skills/verify-snapshots.mjs index 42f17036..0689af58 100644 --- a/tests/skills/verify-snapshots.mjs +++ b/tests/skills/verify-snapshots.mjs @@ -357,6 +357,16 @@ function buildSkillArgs(skillConfig, caseData, workDir, inputFile, runtime) { function runPreSteps(preRun, workDir, runtime, log) { if (!preRun) return; for (const step of preRun) { + // writeFile step — записать произвольный файл в workDir перед запуском скрипта + if (step.writeFile) { + const wfPath = join(workDir, step.writeFile.path); + const wfContent = typeof step.writeFile.content === 'string' + ? step.writeFile.content + : JSON.stringify(step.writeFile.content, null, 2); + writeFileSync(wfPath, wfContent, 'utf8'); + log(`preRun: writeFile ${step.writeFile.path}`, true); + continue; + } const preArgs = []; for (const [flag, value] of Object.entries(step.args || {})) { preArgs.push(flag);