723 lines
29 KiB
Python
723 lines
29 KiB
Python
from pathlib import Path
|
|
|
|
from one_c_normalizer import (
|
|
COMMON_BRANCH_CHILDREN,
|
|
METADATA_TYPE_BY_BRANCH,
|
|
METADATA_TYPE_BY_CODE,
|
|
build_normalized_project,
|
|
normalize_bsl_source,
|
|
normalize_one_c_project,
|
|
normalize_source_path,
|
|
parse_one_c_xml_file,
|
|
)
|
|
|
|
|
|
def test_normalize_bsl_source_removes_bom_and_normalizes_newlines():
|
|
assert normalize_bsl_source("\ufeffПроцедура X()\r\n A = 1; \r\n\r\n") == (
|
|
"Процедура X()\n A = 1;\n"
|
|
)
|
|
|
|
|
|
def test_normalize_source_path_uses_forward_slashes():
|
|
assert normalize_source_path("src\\module.bsl") == "src/module.bsl"
|
|
|
|
|
|
def test_parse_one_c_xml_file_extracts_ui_objects(tmp_path: Path):
|
|
xml = tmp_path / "form.xml"
|
|
xml.write_text(
|
|
"""
|
|
<Form name="ФормаДокумента" qualifiedName="Документ.Заказ.ФормаДокумента">
|
|
<Command name="Провести" />
|
|
<Attribute name="Контрагент" />
|
|
</Form>
|
|
""",
|
|
encoding="utf-8",
|
|
)
|
|
|
|
objects = parse_one_c_xml_file(xml)
|
|
|
|
assert [item.object_kind for item in objects] == ["FORM", "COMMAND", "ATTRIBUTE"]
|
|
assert objects[0].qualified_name == "Документ.Заказ.ФормаДокумента"
|
|
|
|
|
|
def test_parse_one_c_xml_file_extracts_metadata_objects(tmp_path: Path):
|
|
xml = tmp_path / "metadata.xml"
|
|
xml.write_text(
|
|
"""
|
|
<Configuration>
|
|
<Catalog name="Номенклатура" qualifiedName="Справочник.Номенклатура">
|
|
<Attribute name="Артикул" qualifiedName="Справочник.Номенклатура.Артикул" />
|
|
</Catalog>
|
|
<Document>
|
|
<Name>ЗаказПокупателя</Name>
|
|
<QualifiedName>Документ.ЗаказПокупателя</QualifiedName>
|
|
<TabularSection name="Товары" qualifiedName="Документ.ЗаказПокупателя.Товары" />
|
|
<Form name="ФормаДокумента" qualifiedName="Документ.ЗаказПокупателя.ФормаДокумента" />
|
|
</Document>
|
|
<MetadataObject type="AccumulationRegister">
|
|
<Name>ОстаткиТоваров</Name>
|
|
<QualifiedName>РегистрНакопления.ОстаткиТоваров</QualifiedName>
|
|
</MetadataObject>
|
|
</Configuration>
|
|
""",
|
|
encoding="utf-8",
|
|
)
|
|
|
|
objects = parse_one_c_xml_file(xml)
|
|
|
|
assert [item.object_kind for item in objects] == [
|
|
"CATALOG",
|
|
"ATTRIBUTE",
|
|
"DOCUMENT",
|
|
"TABULAR_SECTION",
|
|
"FORM",
|
|
"ACCUMULATION_REGISTER",
|
|
]
|
|
assert objects[2].qualified_name == "Документ.ЗаказПокупателя"
|
|
assert objects[5].name == "ОстаткиТоваров"
|
|
|
|
|
|
def test_normalize_one_c_project_preserves_configuration_root_metadata(tmp_path: Path):
|
|
xml = tmp_path / "configuration.xml"
|
|
xml.write_text(
|
|
"""
|
|
<Configuration name="УправлениеТорговлей" synonym="Управление торговлей" platformVersion="8.3.24" compatibilityMode="8.3.20">
|
|
<Catalog name="Контрагенты" qualifiedName="Справочник.Контрагенты" />
|
|
</Configuration>
|
|
""",
|
|
encoding="utf-8",
|
|
)
|
|
|
|
normalized = normalize_one_c_project(tmp_path, project_id="configuration-root")
|
|
|
|
assert normalized.configuration.name == "УправлениеТорговлей"
|
|
assert normalized.configuration.metadata["synonym"] == "Управление торговлей"
|
|
assert normalized.configuration.metadata["platformVersion"] == "8.3.24"
|
|
assert normalized.configuration.metadata["compatibilityMode"] == "8.3.20"
|
|
assert normalized.configuration.metadata["source_path"].endswith("configuration.xml")
|
|
assert [group.name for group in normalized.configuration.groups] == ["Справочники"]
|
|
|
|
|
|
def test_parse_edt_mdo_derives_qualified_names(tmp_path: Path):
|
|
mdo = tmp_path / "Товары.mdo"
|
|
mdo.write_text(
|
|
"""
|
|
<mdclass:Catalog xmlns:mdclass="http://g5.1c.ru/v8/dt/metadata/mdclass">
|
|
<name>Товары</name>
|
|
<attributes>
|
|
<name>Артикул</name>
|
|
</attributes>
|
|
<tabularSections>
|
|
<name>Цены</name>
|
|
<attributes>
|
|
<name>ВидЦены</name>
|
|
</attributes>
|
|
</tabularSections>
|
|
<forms>
|
|
<name>ФормаЭлемента</name>
|
|
</forms>
|
|
</mdclass:Catalog>
|
|
""",
|
|
encoding="utf-8",
|
|
)
|
|
|
|
objects = parse_one_c_xml_file(mdo)
|
|
by_name = {item.name: item for item in objects}
|
|
|
|
assert by_name["Товары"].qualified_name == "Справочник.Товары"
|
|
assert by_name["Артикул"].qualified_name == "Справочник.Товары.Артикул"
|
|
assert by_name["Цены"].qualified_name == "Справочник.Товары.Цены"
|
|
assert by_name["ВидЦены"].qualified_name == "Справочник.Товары.Цены.ВидЦены"
|
|
assert by_name["ФормаЭлемента"].qualified_name == "Справочник.Товары.ФормаЭлемента"
|
|
|
|
|
|
def test_normalize_http_service_keeps_url_templates_and_methods(tmp_path: Path):
|
|
mdo = tmp_path / "ПубличныйAPI.mdo"
|
|
mdo.write_text(
|
|
"""
|
|
<mdclass:HTTPService xmlns:mdclass="http://g5.1c.ru/v8/dt/metadata/mdclass">
|
|
<name>ПубличныйAPI</name>
|
|
<rootURL>api</rootURL>
|
|
<urlTemplates>
|
|
<name>Orders</name>
|
|
<template>/orders/{id}</template>
|
|
<methods>
|
|
<httpMethod>GET</httpMethod>
|
|
<handler>ПолучитьЗаказ</handler>
|
|
</methods>
|
|
</urlTemplates>
|
|
</mdclass:HTTPService>
|
|
""",
|
|
encoding="utf-8",
|
|
)
|
|
|
|
normalized = normalize_one_c_project(tmp_path, project_id="http-service")
|
|
http_group = next(group for group in normalized.configuration.groups if group.name == "HTTP-сервисы")
|
|
service = http_group.objects[0]
|
|
|
|
assert service.qualified_name == "HTTPСервис.ПубличныйAPI"
|
|
assert service.metadata["rootURL"] == "api"
|
|
assert service.url_templates[0].name == "Orders"
|
|
assert service.url_templates[0].attributes["template"] == "/orders/{id}"
|
|
assert service.url_templates[0].children[0].kind == "METHOD"
|
|
assert service.url_templates[0].children[0].name == "ПолучитьЗаказ"
|
|
|
|
|
|
def test_normalize_edt_project_keeps_tabular_section_columns_nested(tmp_path: Path):
|
|
mdo = tmp_path / "ЗаказПокупателя.mdo"
|
|
mdo.write_text(
|
|
"""
|
|
<mdclass:Document xmlns:mdclass="http://g5.1c.ru/v8/dt/metadata/mdclass">
|
|
<name>ЗаказПокупателя</name>
|
|
<tabularSections>
|
|
<name>Товары</name>
|
|
<attributes>
|
|
<name>Номенклатура</name>
|
|
</attributes>
|
|
<attributes>
|
|
<name>Количество</name>
|
|
</attributes>
|
|
</tabularSections>
|
|
</mdclass:Document>
|
|
""",
|
|
encoding="utf-8",
|
|
)
|
|
|
|
normalized = normalize_one_c_project(tmp_path, project_id="edt-tabular")
|
|
documents = next(group for group in normalized.configuration.groups if group.name == "Документы")
|
|
document = documents.objects[0]
|
|
|
|
assert document.attributes == []
|
|
assert document.tabular_sections[0].qualified_name == "Документ.ЗаказПокупателя.Товары"
|
|
assert [child.name for child in document.tabular_sections[0].children] == ["Номенклатура", "Количество"]
|
|
assert [child.qualified_name for child in document.tabular_sections[0].children] == [
|
|
"Документ.ЗаказПокупателя.Товары.Номенклатура",
|
|
"Документ.ЗаказПокупателя.Товары.Количество",
|
|
]
|
|
|
|
|
|
def test_normalize_edt_project_preserves_source_path_and_common_object_descriptions(tmp_path: Path):
|
|
common_form = tmp_path / "ФормаПодбора.mdo"
|
|
common_form.write_text(
|
|
"""
|
|
<mdclass:CommonForm xmlns:mdclass="http://g5.1c.ru/v8/dt/metadata/mdclass">
|
|
<name>ФормаПодбора</name>
|
|
<synonym>Форма подбора</synonym>
|
|
<comment>Используется в подборе товаров</comment>
|
|
</mdclass:CommonForm>
|
|
""",
|
|
encoding="utf-8",
|
|
)
|
|
|
|
normalized = normalize_one_c_project(tmp_path, project_id="edt-common")
|
|
groups = {group.name: group for group in normalized.configuration.groups}
|
|
common_forms = groups["Общие формы"].objects
|
|
|
|
assert common_forms[0].qualified_name == "ОбщаяФорма.ФормаПодбора"
|
|
assert common_forms[0].source_path.endswith("ФормаПодбора.mdo")
|
|
assert common_forms[0].metadata["synonym"] == "Форма подбора"
|
|
assert common_forms[0].metadata["comment"] == "Используется в подборе товаров"
|
|
|
|
|
|
def test_normalize_edt_project_knows_full_common_metadata_catalog(tmp_path: Path):
|
|
for file_name, class_name, object_name in [
|
|
("Продажи.mdo", "Subsystem", "Продажи"),
|
|
("Менеджер.mdo", "Role", "Менеджер"),
|
|
("ПроведениеДокументов.mdo", "Sequence", "ПроведениеДокументов"),
|
|
("ОбщийНумератор.mdo", "DocumentNumerator", "ОбщийНумератор"),
|
|
("ДоступностьСкидок.mdo", "FunctionalOption", "ДоступностьСкидок"),
|
|
("ФормаПодбора.mdo", "CommonForm", "ФормаПодбора"),
|
|
("ПубличныйAPI.mdo", "HTTPService", "ПубличныйAPI"),
|
|
]:
|
|
(tmp_path / file_name).write_text(
|
|
f"""
|
|
<mdclass:{class_name} xmlns:mdclass="http://g5.1c.ru/v8/dt/metadata/mdclass">
|
|
<name>{object_name}</name>
|
|
</mdclass:{class_name}>
|
|
""",
|
|
encoding="utf-8",
|
|
)
|
|
|
|
normalized = normalize_one_c_project(tmp_path, project_id="edt-full-common")
|
|
objects = {
|
|
item.qualified_name
|
|
for group in normalized.configuration.groups
|
|
for item in group.objects
|
|
}
|
|
|
|
assert {
|
|
"Подсистема.Продажи",
|
|
"Роль.Менеджер",
|
|
"Последовательность.ПроведениеДокументов",
|
|
"НумераторДокументов.ОбщийНумератор",
|
|
"ФункциональнаяОпция.ДоступностьСкидок",
|
|
"ОбщаяФорма.ФормаПодбора",
|
|
"HTTPСервис.ПубличныйAPI",
|
|
}.issubset(objects)
|
|
|
|
|
|
def test_normalize_project_loads_access_profiles_groups_and_users(tmp_path: Path):
|
|
xml = tmp_path / "access.xml"
|
|
xml.write_text(
|
|
"""
|
|
<AccessData>
|
|
<Role name="ЧтениеПродаж" qualifiedName="Роль.ЧтениеПродаж" />
|
|
<AccessProfile name="МенеджерПродаж">
|
|
<Role name="ЧтениеПродаж" />
|
|
</AccessProfile>
|
|
<AccessGroup name="ОтделПродаж" profile="МенеджерПродаж">
|
|
<Member user="ivanov" />
|
|
</AccessGroup>
|
|
<InfobaseUser name="ivanov" fullName="Иванов Иван" />
|
|
</AccessData>
|
|
""",
|
|
encoding="utf-8",
|
|
)
|
|
|
|
normalized = normalize_one_c_project(tmp_path, project_id="access-data")
|
|
|
|
assert normalized.access.profiles[0].name == "МенеджерПродаж"
|
|
assert normalized.access.profiles[0].roles[0].role_qualified_name == "Роль.ЧтениеПродаж"
|
|
assert normalized.access.groups[0].profile == "МенеджерПродаж"
|
|
assert normalized.access.groups[0].users == ["ivanov"]
|
|
assert normalized.access.users[0].full_name == "Иванов Иван"
|
|
|
|
|
|
def test_normalize_edt_project_preserves_localized_descriptions(tmp_path: Path):
|
|
catalog = tmp_path / "Контрагенты.mdo"
|
|
catalog.write_text(
|
|
"""
|
|
<mdclass:Catalog xmlns:mdclass="http://g5.1c.ru/v8/dt/metadata/mdclass">
|
|
<name>Контрагенты</name>
|
|
<synonym>
|
|
<key>ru</key>
|
|
<value>Контрагенты</value>
|
|
</synonym>
|
|
<comment>
|
|
<key>ru</key>
|
|
<value>Описание справочника контрагентов</value>
|
|
</comment>
|
|
<attributes>
|
|
<name>ИНН</name>
|
|
<synonym>
|
|
<key>ru</key>
|
|
<value>ИНН</value>
|
|
</synonym>
|
|
<comment>
|
|
<key>ru</key>
|
|
<value>Идентификационный номер налогоплательщика</value>
|
|
</comment>
|
|
</attributes>
|
|
</mdclass:Catalog>
|
|
""",
|
|
encoding="utf-8",
|
|
)
|
|
|
|
normalized = normalize_one_c_project(tmp_path, project_id="edt-localized")
|
|
catalogs = next(group for group in normalized.configuration.groups if group.name == "Справочники")
|
|
metadata_object = catalogs.objects[0]
|
|
attribute = metadata_object.attributes[0]
|
|
|
|
assert metadata_object.metadata["synonym"] == "Контрагенты"
|
|
assert metadata_object.metadata["synonym_localized"] == {"ru": "Контрагенты"}
|
|
assert metadata_object.metadata["comment"] == "Описание справочника контрагентов"
|
|
assert metadata_object.metadata["comment_localized"] == {"ru": "Описание справочника контрагентов"}
|
|
assert attribute.attributes["synonym"] == "ИНН"
|
|
assert attribute.attributes["comment"] == "Идентификационный номер налогоплательщика"
|
|
|
|
|
|
def test_normalize_edt_project_attaches_bsl_modules_to_metadata_objects(tmp_path: Path):
|
|
catalog_dir = tmp_path / "Catalogs" / "Контрагенты"
|
|
module_dir = catalog_dir / "Ext"
|
|
module_dir.mkdir(parents=True)
|
|
(catalog_dir / "Контрагенты.mdo").write_text(
|
|
"""
|
|
<mdclass:Catalog xmlns:mdclass="http://g5.1c.ru/v8/dt/metadata/mdclass">
|
|
<name>Контрагенты</name>
|
|
</mdclass:Catalog>
|
|
""",
|
|
encoding="utf-8",
|
|
)
|
|
(module_dir / "ObjectModule.bsl").write_text(
|
|
"""
|
|
Процедура ПроверитьКонтрагента() Экспорт
|
|
КонецПроцедуры
|
|
""",
|
|
encoding="utf-8",
|
|
)
|
|
(module_dir / "ManagerModule.bsl").write_text(
|
|
"""
|
|
Процедура Создать() Экспорт
|
|
КонецПроцедуры
|
|
""",
|
|
encoding="utf-8",
|
|
)
|
|
|
|
normalized = normalize_one_c_project(tmp_path, project_id="edt-modules")
|
|
catalogs = next(group for group in normalized.configuration.groups if group.name == "Справочники")
|
|
catalog = catalogs.objects[0]
|
|
|
|
assert [module.module_kind for module in catalog.modules] == ["MANAGER_MODULE", "OBJECT_MODULE"]
|
|
assert all(module.source_path.endswith(".bsl") for module in catalog.modules)
|
|
assert all(module.attributes["source_hash"] for module in catalog.modules)
|
|
|
|
|
|
def test_normalize_edt_project_attaches_form_modules_to_owner_with_form_name(tmp_path: Path):
|
|
catalog_dir = tmp_path / "Catalogs" / "Контрагенты"
|
|
form_dir = catalog_dir / "Forms" / "ФормаЭлемента" / "Ext"
|
|
form_dir.mkdir(parents=True)
|
|
(catalog_dir / "Контрагенты.mdo").write_text(
|
|
"""
|
|
<mdclass:Catalog xmlns:mdclass="http://g5.1c.ru/v8/dt/metadata/mdclass">
|
|
<name>Контрагенты</name>
|
|
<forms>
|
|
<name>ФормаЭлемента</name>
|
|
</forms>
|
|
</mdclass:Catalog>
|
|
""",
|
|
encoding="utf-8",
|
|
)
|
|
(form_dir / "Module.bsl").write_text(
|
|
"""
|
|
Процедура ПриОткрытии()
|
|
КонецПроцедуры
|
|
""",
|
|
encoding="utf-8",
|
|
)
|
|
|
|
normalized = normalize_one_c_project(tmp_path, project_id="edt-form-module")
|
|
catalog = next(group for group in normalized.configuration.groups if group.name == "Справочники").objects[0]
|
|
|
|
assert catalog.modules[0].module_kind == "FORM_MODULE"
|
|
assert catalog.modules[0].attributes["form_name"] == "ФормаЭлемента"
|
|
assert catalog.modules[0].qualified_name == "Справочник.Контрагенты.Форма.ФормаЭлемента.Модуль"
|
|
|
|
|
|
def test_normalize_edt_project_attaches_common_form_modules(tmp_path: Path):
|
|
common_form_dir = tmp_path / "CommonForms" / "ФормаПодбора"
|
|
module_dir = common_form_dir / "Ext"
|
|
module_dir.mkdir(parents=True)
|
|
(common_form_dir / "ФормаПодбора.mdo").write_text(
|
|
"""
|
|
<mdclass:CommonForm xmlns:mdclass="http://g5.1c.ru/v8/dt/metadata/mdclass">
|
|
<name>ФормаПодбора</name>
|
|
</mdclass:CommonForm>
|
|
""",
|
|
encoding="utf-8",
|
|
)
|
|
(module_dir / "Module.bsl").write_text(
|
|
"""
|
|
Процедура ПриСозданииНаСервере() Экспорт
|
|
КонецПроцедуры
|
|
""",
|
|
encoding="utf-8",
|
|
)
|
|
|
|
normalized = normalize_one_c_project(tmp_path, project_id="edt-common-form-module")
|
|
common_forms = next(group for group in normalized.configuration.groups if group.name == "Общие формы")
|
|
common_form = common_forms.objects[0]
|
|
|
|
assert common_form.qualified_name == "ОбщаяФорма.ФормаПодбора"
|
|
assert len(common_form.modules) == 1
|
|
assert common_form.modules[0].module_kind == "MODULE"
|
|
assert common_form.modules[0].source_path.endswith("Module.bsl")
|
|
|
|
|
|
def test_parse_register_dimensions_and_resources_preserves_attribute_roles(tmp_path: Path):
|
|
mdo = tmp_path / "ОстаткиТоваров.mdo"
|
|
mdo.write_text(
|
|
"""
|
|
<mdclass:AccumulationRegister xmlns:mdclass="http://g5.1c.ru/v8/dt/metadata/mdclass">
|
|
<name>ОстаткиТоваров</name>
|
|
<dimensions>
|
|
<name>Номенклатура</name>
|
|
</dimensions>
|
|
<resources>
|
|
<name>Количество</name>
|
|
</resources>
|
|
<attributes>
|
|
<name>Комментарий</name>
|
|
</attributes>
|
|
</mdclass:AccumulationRegister>
|
|
""",
|
|
encoding="utf-8",
|
|
)
|
|
|
|
objects = parse_one_c_xml_file(mdo)
|
|
by_name = {item.name: item for item in objects}
|
|
|
|
assert by_name["ОстаткиТоваров"].object_kind == "ACCUMULATION_REGISTER"
|
|
assert by_name["ОстаткиТоваров"].qualified_name == "РегистрНакопления.ОстаткиТоваров"
|
|
assert by_name["Номенклатура"].attributes["attribute_role"] == "DIMENSION"
|
|
assert by_name["Количество"].attributes["attribute_role"] == "RESOURCE"
|
|
assert by_name["Комментарий"].attributes["attribute_role"] == "REQUISITE"
|
|
|
|
|
|
def test_normalize_edt_project_preserves_specific_register_kinds(tmp_path: Path):
|
|
for file_name, tag, name in (
|
|
("Цены.mdo", "InformationRegister", "Цены"),
|
|
("ОстаткиТоваров.mdo", "AccumulationRegister", "ОстаткиТоваров"),
|
|
("Хозрасчетный.mdo", "AccountingRegister", "Хозрасчетный"),
|
|
("Начисления.mdo", "CalculationRegister", "Начисления"),
|
|
):
|
|
(tmp_path / file_name).write_text(
|
|
f"""
|
|
<mdclass:{tag} xmlns:mdclass="http://g5.1c.ru/v8/dt/metadata/mdclass">
|
|
<name>{name}</name>
|
|
</mdclass:{tag}>
|
|
""",
|
|
encoding="utf-8",
|
|
)
|
|
|
|
normalized = normalize_one_c_project(tmp_path, project_id="edt-register-kinds")
|
|
groups = {group.name: group for group in normalized.configuration.groups}
|
|
|
|
assert groups["Регистры сведений"].objects[0].object_kind == "INFORMATION_REGISTER"
|
|
assert groups["Регистры накопления"].objects[0].qualified_name == "РегистрНакопления.ОстаткиТоваров"
|
|
assert groups["Регистры бухгалтерии"].objects[0].object_kind == "ACCOUNTING_REGISTER"
|
|
assert groups["Регистры расчета"].objects[0].object_kind == "CALCULATION_REGISTER"
|
|
|
|
|
|
def test_parse_one_c_xml_file_extracts_role_rights(tmp_path: Path):
|
|
xml = tmp_path / "roles.xml"
|
|
xml.write_text(
|
|
"""
|
|
<Configuration>
|
|
<Role name="Менеджер" qualifiedName="Роль.Менеджер">
|
|
<Right object="Документ.ЗаказПокупателя" read="true" write="true" post="true" />
|
|
</Role>
|
|
</Configuration>
|
|
""",
|
|
encoding="utf-8",
|
|
)
|
|
|
|
objects = parse_one_c_xml_file(xml)
|
|
|
|
assert [item.object_kind for item in objects] == ["ROLE", "RIGHT"]
|
|
assert objects[1].name == "Документ.ЗаказПокупателя"
|
|
assert objects[1].attributes["role"] == "Роль.Менеджер"
|
|
assert objects[1].attributes["post"] == "true"
|
|
|
|
|
|
def test_normalized_project_attaches_role_rights(tmp_path: Path):
|
|
xml = tmp_path / "roles.xml"
|
|
xml.write_text(
|
|
"""
|
|
<Configuration>
|
|
<Role name="Менеджер" qualifiedName="Роль.Менеджер">
|
|
<Right object="Документ.ЗаказПокупателя" read="true" write="true" />
|
|
</Role>
|
|
</Configuration>
|
|
""",
|
|
encoding="utf-8",
|
|
)
|
|
|
|
normalized = build_normalized_project(parse_one_c_xml_file(xml), project_id="roles", source_path=str(tmp_path))
|
|
roles_group = next(group for group in normalized.configuration.groups if group.name == "Роли")
|
|
role = roles_group.objects[0]
|
|
|
|
assert role.name == "Менеджер"
|
|
assert role.rights[0].target == "Документ.ЗаказПокупателя"
|
|
assert role.rights[0].permissions["write"] == "true"
|
|
|
|
|
|
def test_parse_one_c_xml_file_extracts_child_element_command_action_and_role_right(tmp_path: Path):
|
|
xml = tmp_path / "metadata.xml"
|
|
xml.write_text(
|
|
"""
|
|
<Configuration>
|
|
<Document>
|
|
<Name>ЗаказПокупателя</Name>
|
|
<QualifiedName>Документ.ЗаказПокупателя</QualifiedName>
|
|
<Form>
|
|
<Name>ФормаДокумента</Name>
|
|
<Command>
|
|
<Name>Провести</Name>
|
|
<Action>ПровестиКоманда</Action>
|
|
</Command>
|
|
</Form>
|
|
</Document>
|
|
<Role>
|
|
<Name>Менеджер</Name>
|
|
<Right read="true">
|
|
<Object>Документ.ЗаказПокупателя</Object>
|
|
</Right>
|
|
</Role>
|
|
</Configuration>
|
|
""",
|
|
encoding="utf-8",
|
|
)
|
|
|
|
objects = parse_one_c_xml_file(xml)
|
|
by_kind = {item.object_kind: item for item in objects}
|
|
command = next(item for item in objects if item.object_kind == "COMMAND")
|
|
right = next(item for item in objects if item.object_kind == "RIGHT")
|
|
|
|
assert by_kind["FORM"].qualified_name == "Документ.ЗаказПокупателя.ФормаДокумента"
|
|
assert command.attributes["Action"] == "ПровестиКоманда"
|
|
assert right.name == "Документ.ЗаказПокупателя"
|
|
assert right.attributes["role"] == "Роль.Менеджер"
|
|
|
|
|
|
def test_normalized_project_groups_extended_1c_objects(tmp_path: Path):
|
|
xml = tmp_path / "extended.xml"
|
|
xml.write_text(
|
|
"""
|
|
<Configuration>
|
|
<Subsystem name="Продажи" qualifiedName="Подсистема.Продажи" />
|
|
<HTTPService name="ПубличныйAPI" qualifiedName="HTTPСервис.ПубличныйAPI" />
|
|
<XDTOPackage name="ИнтеграцияCRM" qualifiedName="XDTO.ИнтеграцияCRM" />
|
|
<Document name="ЗаказПокупателя" qualifiedName="Документ.ЗаказПокупателя">
|
|
<Layout name="ПечатнаяФорма" qualifiedName="Документ.ЗаказПокупателя.ПечатнаяФорма" />
|
|
<Movement name="Остатки" qualifiedName="Документ.ЗаказПокупателя.Движения.Остатки" />
|
|
</Document>
|
|
<Extension name="CRM" version="1.0" />
|
|
</Configuration>
|
|
""",
|
|
encoding="utf-8",
|
|
)
|
|
|
|
objects = parse_one_c_xml_file(xml)
|
|
normalized = build_normalized_project(objects, project_id="extended", source_path=str(tmp_path))
|
|
groups = {group.name: group for group in normalized.configuration.groups}
|
|
document = next(item for item in groups["Документы"].objects if item.name == "ЗаказПокупателя")
|
|
|
|
assert "Подсистемы" in groups
|
|
assert "HTTP-сервисы" in groups
|
|
assert "XDTO-пакеты" in groups
|
|
assert document.layouts[0].name == "ПечатнаяФорма"
|
|
assert document.movements[0].name == "Остатки"
|
|
assert normalized.configuration.extensions[0].name == "CRM"
|
|
|
|
|
|
def test_normalize_one_c_project_skips_unreadable_or_invalid_metadata(tmp_path: Path):
|
|
(tmp_path / "valid.xml").write_text(
|
|
"""
|
|
<Configuration>
|
|
<Catalog name="Контрагенты" qualifiedName="Справочник.Контрагенты" />
|
|
</Configuration>
|
|
""",
|
|
encoding="utf-8",
|
|
)
|
|
(tmp_path / "broken.xml").write_text("<Configuration><Catalog>", encoding="utf-8")
|
|
|
|
normalized = normalize_one_c_project(tmp_path, project_id="skip-invalid")
|
|
catalogs = next(group for group in normalized.configuration.groups if group.name == "Справочники")
|
|
|
|
assert catalogs.objects[0].qualified_name == "Справочник.Контрагенты"
|
|
|
|
|
|
def test_configuration_extension_has_own_metadata_tree_structure(tmp_path: Path):
|
|
xml = tmp_path / "extension.mdo"
|
|
xml.write_text(
|
|
"""
|
|
<mdclass:ConfigurationExtension xmlns:mdclass="http://g5.1c.ru/v8/dt/metadata/mdclass/extension">
|
|
<name>CRM</name>
|
|
<version>1.0</version>
|
|
<catalogs>
|
|
<name>КонтрагентыCRM</name>
|
|
<attributes>
|
|
<name>ВнешнийКод</name>
|
|
</attributes>
|
|
</catalogs>
|
|
<commonModules>
|
|
<name>CRMСервер</name>
|
|
</commonModules>
|
|
</mdclass:ConfigurationExtension>
|
|
""",
|
|
encoding="utf-8",
|
|
)
|
|
|
|
objects = parse_one_c_xml_file(xml)
|
|
normalized = build_normalized_project(objects, project_id="extension-structure", source_path=str(tmp_path))
|
|
|
|
assert normalized.configuration.groups == []
|
|
extension = normalized.configuration.extensions[0]
|
|
assert extension.name == "CRM"
|
|
assert extension.version == "1.0"
|
|
extension_groups = {group.name: group for group in extension.groups}
|
|
assert extension_groups["Справочники"].objects[0].name == "КонтрагентыCRM"
|
|
assert extension_groups["Справочники"].objects[0].attributes[0].name == "ВнешнийКод"
|
|
assert extension_groups["Общие модули"].objects[0].name == "CRMСервер"
|
|
|
|
|
|
def test_report_metadata_parts_include_dcs_variants_settings_and_tabular_documents(tmp_path: Path):
|
|
xml = tmp_path / "report.mdo"
|
|
xml.write_text(
|
|
"""
|
|
<mdclass:Report xmlns:mdclass="http://g5.1c.ru/v8/dt/metadata/mdclass">
|
|
<name>АнализПродаж</name>
|
|
<attributes>
|
|
<name>Период</name>
|
|
</attributes>
|
|
<tabularSections>
|
|
<name>Показатели</name>
|
|
</tabularSections>
|
|
<forms>
|
|
<name>ФормаОтчета</name>
|
|
</forms>
|
|
<templates>
|
|
<name>ПечатнаяФорма</name>
|
|
</templates>
|
|
<tabularDocuments>
|
|
<name>ТабличныйДокумент</name>
|
|
</tabularDocuments>
|
|
<mainDataCompositionSchema>
|
|
<name>ОсновнаяСхемаКомпоновкиДанных</name>
|
|
</mainDataCompositionSchema>
|
|
<reportVariants>
|
|
<name>Основной</name>
|
|
</reportVariants>
|
|
<settings>
|
|
<name>НастройкиПоУмолчанию</name>
|
|
</settings>
|
|
</mdclass:Report>
|
|
""",
|
|
encoding="utf-8",
|
|
)
|
|
|
|
objects = parse_one_c_xml_file(xml)
|
|
normalized = build_normalized_project(objects, project_id="report-parts", source_path=str(tmp_path))
|
|
reports = next(group for group in normalized.configuration.groups if group.name == "Отчеты")
|
|
report = reports.objects[0]
|
|
|
|
assert report.qualified_name == "Отчет.АнализПродаж"
|
|
assert report.attributes[0].name == "Период"
|
|
assert report.tabular_sections[0].name == "Показатели"
|
|
assert report.forms[0].name == "ФормаОтчета"
|
|
assert report.layouts[0].name == "ПечатнаяФорма"
|
|
assert report.tabular_documents[0].name == "ТабличныйДокумент"
|
|
assert report.data_composition_schemas[0].name == "ОсновнаяСхемаКомпоновкиДанных"
|
|
assert report.report_variants[0].name == "Основной"
|
|
assert report.report_settings[0].name == "НастройкиПоУмолчанию"
|
|
|
|
|
|
def test_metadata_catalog_describes_core_1c_tree_branches():
|
|
assert "Общие модули" in COMMON_BRANCH_CHILDREN
|
|
assert "HTTP-сервисы" in COMMON_BRANCH_CHILDREN
|
|
|
|
document = METADATA_TYPE_BY_CODE["DOCUMENT"]
|
|
assert document.tree_branch == "Документы"
|
|
assert "Реквизиты" in document.child_groups
|
|
assert "Табличные части" in document.child_groups
|
|
assert "Движения" in document.child_groups
|
|
assert document.module_kinds == ("Модуль объекта", "Модуль менеджера")
|
|
|
|
register = METADATA_TYPE_BY_CODE["ACCUMULATION_REGISTER"]
|
|
assert register.tree_branch == "Регистры накопления"
|
|
assert "Измерения" in register.child_groups
|
|
assert "Ресурсы" in register.child_groups
|
|
|
|
common_form = METADATA_TYPE_BY_CODE["COMMON_FORM"]
|
|
assert common_form.tree_branch == "Общие формы"
|
|
assert "Модуль формы" in common_form.child_groups
|
|
|
|
report = METADATA_TYPE_BY_CODE["REPORT"]
|
|
assert "СКД" in report.child_groups
|
|
assert "Табличные документы" in report.child_groups
|
|
assert "Варианты отчета" in report.child_groups
|
|
assert "Настройки" in report.child_groups
|
|
|
|
assert METADATA_TYPE_BY_BRANCH["XDTO-пакеты"].code == "XDTO_PACKAGE"
|
|
assert METADATA_TYPE_BY_BRANCH["Сервисы интеграции"].code == "INTEGRATION_SERVICE"
|