From d6b3e73cb7a80be5fd686e0c3f8cc2695b261d77 Mon Sep 17 00:00:00 2001 From: Raykov-MS Date: Sat, 1 Aug 2026 10:00:29 +0300 Subject: [PATCH] refactor --- app/pipeline/column_constants.py | 120 ++ app/pipeline/column_registry.py | 365 +++++ app/pipeline/mapping.py | 827 +++++----- app/pipeline/mapping_table.json | 2252 +++++++++++++++++++++++++++- app/pipeline/report.py | 121 +- tests/unit/test_column_registry.py | 135 ++ tests/unit/test_report.py | 16 +- 7 files changed, 3307 insertions(+), 529 deletions(-) create mode 100644 app/pipeline/column_constants.py create mode 100644 app/pipeline/column_registry.py create mode 100644 tests/unit/test_column_registry.py diff --git a/app/pipeline/column_constants.py b/app/pipeline/column_constants.py new file mode 100644 index 0000000..51bcf44 --- /dev/null +++ b/app/pipeline/column_constants.py @@ -0,0 +1,120 @@ +from __future__ import annotations + +from .column_registry import COLUMNS + + +def _index(legacy_position: int) -> int: + return COLUMNS.index_of(f"legacy_{legacy_position:03d}") + + +# Служебные поля и операция. +COL_FILE_NAME = _index(1) +COL_RECORD_ID = _index(7) +COL_FTR_SIGN = _index(10) +COL_SUSPENSION_BASIS = _index(11) +COL_OPERATION_SIGN = _index(14) +COL_ESP_SIGN = _index(15) +COL_OPERATION_CODE = _index(19) +COL_EXTRA_CODES = _index(20) +COL_UNUSUAL_CODES = _index(21) +COL_CURRENCY = _index(22) +COL_AMOUNT_CURRENCY = _index(23) +COL_AMOUNT_RUB = _index(24) +COL_SALE_CURRENCY = _index(25) +COL_SALE_AMOUNT = _index(26) +COL_CURRENCY_SIGN = _index(27) +COL_SUSPICIOUS_ID = _index(28) +COL_METAL_CODE = _index(29) +COL_METAL_NAME = _index(30) +COL_ITEM_TYPE = _index(31) + +# Перевод. +COL_TRANSFER_TYPE = _index(35) +COL_TERRITORY_CODE = _index(36) +COL_OPERATOR_TYPE = _index(37) +COL_PAYER_ACCOUNT = _index(38) +COL_PAYER_ESP = _index(39) +COL_PAYER_BANK_NAME = _index(40) +COL_PAYER_BANK_BIK = _index(41) +COL_RECIPIENT_BANK_NAME = _index(42) +COL_RECIPIENT_BANK_BIK = _index(43) +COL_PAYER_BANK_ACCOUNT = _index(44) +COL_RECIPIENT_BANK_ACCOUNT = _index(45) +COL_RECIPIENT_ACCOUNT = _index(46) +COL_RECIPIENT_ESP = _index(47) +COL_TRANSFER_STATUS = _index(62) + +# Карты и место операции. +COL_TERRITORY_CODE_CARD = _index(96) +COL_CARD_HOLDER_INFO = _index(103) +COL_EMPLOYEE_SIGN = _index(104) +COL_FOREIGN_BANK_NAME = _index(105) + +# Участник. +COL_PARTICIPANT_TYPE = _index(109) +COL_RESIDENT_SIGN = _index(110) +COL_CLIENT_SIGN = _index(111) +COL_IDENT_FL = _index(119) +COL_INN = _index(120) +COL_KPP = _index(122) +COL_BIRTH_REG_DATE = _index(123) +COL_BRANCH_SIGN = _index(124) +COL_INSURANCE_NUMBER = _index(125) +COL_COUNTRY_CODE = _index(126) +COL_ADDRESS_ONE_LINE = _index(141) +COL_ADDRESS_STRUCTURED = _index(142) +COL_REG_PLACE_ONE_LINE = _index(152) +COL_REG_PLACE_STRUCTURED = _index(153) + +# ЕИО и ценные бумаги. +COL_EIO_INN = _index(163) +COL_EIO_REG_PLACE_ONE_LINE = _index(178) +COL_CP_ISSUER_INN = _index(202) + +# Блоки схемы. +BLOCK_EIO = COLUMNS.block("eio") +BLOCK_CP = COLUMNS.block("cp") + +# Точные поля наличных, которые исторически очищаются для безналичных переводов. +CASHLESS_CLEARED_COLUMNS = tuple( + _index(position) for position in (50, 61, 65, 76, 84, 95, 99, 101) +) + +OKATO_COUNTRY_PAIRS: tuple[tuple[int, int], ...] = tuple( + (_index(country), _index(okato)) + for country, okato in ( + (52, 53), + (67, 68), + (86, 87), + (144, 145), + (170, 171), + ) +) + +# Текущая перестановка адресного блока при выгрузке в целевой шаблон. +PARTICIPANT_ADDRESS_OUTPUT_SOURCES: dict[int, int] = { + _index(141): _index(142), + **{_index(target): _index(target + 1) for target in range(142, 151)}, + _index(151): _index(141), +} + +# Бизнес-константы. +ACCOUNT_PLACEHOLDER = "00000000000000000000" +CURRENCY_OPERATION_CODES = frozenset(str(code) for code in range(6101, 6127)) +CASHLESS_TRANSFER_TYPES = frozenset( + {"1", "2", "3", "4", "7", "10", "11", "12", "13", "14"} +) +VALID_FTR_SIGNS = frozenset({"0", "1", "2", "3", "4", "5"}) +VALID_SUSPENSION_BASES = frozenset({"1", "2", "3"}) +VALID_ESP_SIGNS = frozenset({"1", "2", "3", "4"}) +PRECIOUS_ITEM_CODES = frozenset({"5020", "5021", "5022", "5023"}) +SUSPICIOUS_CODE = "6001" +TERRITORY_CODE = "5016" +PRECIOUS_METAL_CODE = "C99" +EMPLOYEE_ABSENT_CODE = "0" +RUSSIA_COUNTRY_CODE = "643" + +PARTICIPANT_TYPE_UL = "1" +PARTICIPANT_TYPE_FL = "2" +PARTICIPANT_TYPE_IP = "3" +PARTICIPANT_TYPE_FLCHP = "4" diff --git a/app/pipeline/column_registry.py b/app/pipeline/column_registry.py new file mode 100644 index 0000000..869a696 --- /dev/null +++ b/app/pipeline/column_registry.py @@ -0,0 +1,365 @@ +from __future__ import annotations + +import json +from collections import defaultdict +from dataclasses import dataclass +from pathlib import Path + +EXPECTED_COLUMN_COUNT = 204 +MAPPING_DATA_FILE = Path(__file__).resolve().with_name("mapping_table.json") +REPORT_GROUP_TITLES: dict[str, str] = { + "service": "Служебные поля", + "message_bank": "Реквизиты сообщения/КО/филиала", + "record_control": "Идентификация записи и контрольные признаки", + "operation_parameters": "Параметры операции", + "transfer_settlement": "Перевод ДС и реквизиты расчетов", + "cash_receipt_authorization": ("Места приема/выдачи наличных и авторизация ЭСП"), + "same_operator_place": "Внесение/выдача у одного оператора (место операции)", + "cash_form_basis": "Наличная форма и основание операции", + "participant_base": "Участник операции (базовые сведения)", + "participant_identity": ("Участник операции (идентификация, документы, адреса)"), + "eio": "ЕИО/Бенефициар (идентификация, документы, адреса)", + "cp": "Сведения о ценных бумагах (ЦП)", +} +BUSINESS_BLOCKS = frozenset( + { + "file_metadata", + "message_header", + "operation_base", + "transfer", + "cash_receipt", + "transfer_status", + "cash_payment", + "network", + "cash_operation", + "foreign_card", + "operation_basis", + "participant_base", + "participant_name", + "participant_identity", + "participant_documents", + "participant_address", + "participant_extra", + "eio", + "cp", + } +) + + +class ColumnSchemaError(ValueError): + """Ошибка целостности схемы колонок отчёта.""" + + +class AmbiguousColumnNameError(LookupError): + """Имя колонки соответствует нескольким позициям отчёта.""" + + +@dataclass(frozen=True) +class ColumnMeta: + index: int + column_id: str + name: str + block: str + report_group: str + xml_tag: str + xml_path: str + source_scope: str + allow_short_lookup: bool + allow_direct_mapping: bool + structured_value: bool + structured_group: str + structured_role: str + structured_order: int + join_with_space: bool + + +@dataclass(frozen=True) +class ReportGroup: + group_id: str + title: str + indexes: tuple[int, ...] + + @property + def start_index(self) -> int: + return self.indexes[0] + + @property + def end_index(self) -> int: + return self.indexes[-1] + + +class ColumnRegistry: + def __init__(self, columns: list[ColumnMeta]) -> None: + ordered = tuple(sorted(columns, key=lambda column: column.index)) + self._validate_columns(ordered) + self._ordered = ordered + self._by_index = {column.index: column for column in ordered} + self._by_id = {column.column_id: column for column in ordered} + + by_name: dict[str, list[int]] = defaultdict(list) + by_block: dict[str, list[int]] = defaultdict(list) + for column in ordered: + by_name[column.name].append(column.index) + by_block[column.block].append(column.index) + self._by_name = {name: tuple(indexes) for name, indexes in by_name.items()} + self._by_block = {block: tuple(indexes) for block, indexes in by_block.items()} + self._report_groups = self._build_report_groups(ordered) + + def index_of(self, column_id: str) -> int: + """Возвращает текущую позицию стабильной колонки.""" + try: + return self._by_id[column_id].index + except KeyError as exc: + raise KeyError(f"Неизвестный column_id: {column_id}") from exc + + def meta(self, index: int) -> ColumnMeta: + """Возвращает метаданные колонки по текущей позиции.""" + return self._by_index[index] + + def by_id(self, column_id: str) -> ColumnMeta: + """Возвращает метаданные по стабильному идентификатору.""" + try: + return self._by_id[column_id] + except KeyError as exc: + raise KeyError(f"Неизвестный column_id: {column_id}") from exc + + def block(self, block_name: str) -> tuple[int, ...]: + """Возвращает позиции всех колонок бизнес-блока.""" + return self._by_block.get(block_name, ()) + + def indices_named(self, name: str) -> tuple[int, ...]: + """Возвращает все позиции с указанным отображаемым именем.""" + return self._by_name.get(name, ()) + + def index_named(self, name: str, *, block: str | None = None) -> int: + """Ищет имя без молчаливого выбора среди дубликатов.""" + indexes = self.indices_named(name) + if block is not None: + indexes = tuple( + index for index in indexes if self.meta(index).block == block + ) + if not indexes: + raise KeyError(f"Колонка не найдена: {name}") + if len(indexes) > 1: + raise AmbiguousColumnNameError( + f"Имя колонки неоднозначно: {name!r}, позиции {indexes}" + ) + return indexes[0] + + def ordered_columns(self) -> tuple[ColumnMeta, ...]: + """Возвращает всю схему в порядке вывода.""" + return self._ordered + + def all_columns(self) -> tuple[str, ...]: + """Возвращает отображаемые имена в порядке вывода.""" + return tuple(column.name for column in self._ordered) + + def report_groups(self) -> tuple[ReportGroup, ...]: + """Возвращает непрерывные группы верхней шапки.""" + return self._report_groups + + @classmethod + def load(cls, json_path: Path) -> ColumnRegistry: + raw = json.loads(json_path.read_text(encoding="utf-8")) + if not isinstance(raw, list): + raise ColumnSchemaError("Корень mapping_table.json должен быть списком") + columns: list[ColumnMeta] = [] + for position, item in enumerate(raw, start=1): + if not isinstance(item, dict): + raise ColumnSchemaError( + f"Запись {position} mapping_table.json должна быть объектом" + ) + try: + columns.append( + ColumnMeta( + index=cls._required_int(item, "index"), + column_id=cls._required_str(item, "column_id"), + name=cls._required_str(item, "column_name"), + block=cls._required_str(item, "block"), + report_group=cls._required_str(item, "report_group"), + xml_tag=cls._required_str(item, "xml_tag"), + xml_path=cls._required_str(item, "xml_path"), + source_scope=cls._required_str(item, "source_scope"), + allow_short_lookup=cls._required_bool( + item, "allow_short_lookup" + ), + allow_direct_mapping=cls._required_bool( + item, "allow_direct_mapping" + ), + structured_value=cls._required_bool(item, "structured_value"), + structured_group=cls._required_str(item, "structured_group"), + structured_role=cls._required_str(item, "structured_role"), + structured_order=cls._required_int(item, "structured_order"), + join_with_space=cls._required_bool(item, "join_with_space"), + ) + ) + except (KeyError, TypeError, ValueError) as exc: + raise ColumnSchemaError( + f"Некорректная запись схемы в позиции {position}: {exc}" + ) from exc + return cls(columns) + + @staticmethod + def _required_bool(item: dict[object, object], key: str) -> bool: + value = item[key] + if not isinstance(value, bool): + raise TypeError(f"{key} должен быть bool") + return value + + @staticmethod + def _required_str(item: dict[object, object], key: str) -> str: + value = item[key] + if not isinstance(value, str): + raise TypeError(f"{key} должен быть строкой") + return value.strip() + + @staticmethod + def _required_int(item: dict[object, object], key: str) -> int: + value = item[key] + if isinstance(value, bool) or not isinstance(value, int): + raise TypeError(f"{key} должен быть целым числом") + return value + + @staticmethod + def _validate_columns(columns: tuple[ColumnMeta, ...]) -> None: + if len(columns) != EXPECTED_COLUMN_COUNT: + raise ColumnSchemaError( + f"Ожидалось {EXPECTED_COLUMN_COUNT} колонок, получено {len(columns)}" + ) + indexes = tuple(column.index for column in columns) + expected_indexes = tuple(range(1, EXPECTED_COLUMN_COUNT + 1)) + if indexes != expected_indexes: + raise ColumnSchemaError( + "Индексы колонок должны непрерывно идти от 1 до 204" + ) + + column_ids = [column.column_id for column in columns] + if len(column_ids) != len(set(column_ids)): + raise ColumnSchemaError("column_id должны быть уникальными") + + valid_sources = {"any", "operation", "participant"} + valid_roles = {"", "aggregate", "one_line", "component"} + for column in columns: + if not column.column_id or not column.name: + raise ColumnSchemaError( + f"Колонка {column.index}: пустой column_id или column_name" + ) + if not column.block or not column.report_group: + raise ColumnSchemaError( + f"Колонка {column.index}: block и report_group обязательны" + ) + if column.block not in BUSINESS_BLOCKS: + raise ColumnSchemaError(f"Колонка {column.index}: неизвестный block") + if column.report_group not in REPORT_GROUP_TITLES: + raise ColumnSchemaError( + f"Колонка {column.index}: неизвестный report_group" + ) + if column.source_scope not in valid_sources: + raise ColumnSchemaError( + f"Колонка {column.index}: неизвестный source_scope" + ) + if column.structured_role not in valid_roles: + raise ColumnSchemaError( + f"Колонка {column.index}: неизвестная structured_role" + ) + if bool(column.structured_group) != bool(column.structured_role): + raise ColumnSchemaError( + f"Колонка {column.index}: группа и роль структуры задаются вместе" + ) + ColumnRegistry._validate_structured_groups(columns) + + @staticmethod + def _validate_structured_groups(columns: tuple[ColumnMeta, ...]) -> None: + grouped: dict[str, list[ColumnMeta]] = defaultdict(list) + for column in columns: + if column.structured_group: + grouped[column.structured_group].append(column) + elif column.structured_order != 0 or column.join_with_space: + raise ColumnSchemaError( + f"Колонка {column.index}: настройки структуры заданы без группы" + ) + + for group_id, members in grouped.items(): + aggregates = [ + member for member in members if member.structured_role == "aggregate" + ] + components = [ + member for member in members if member.structured_role == "component" + ] + if len(aggregates) != 1: + raise ColumnSchemaError( + f"Группа {group_id!r} должна иметь один aggregate" + ) + aggregate = aggregates[0] + if aggregate.column_id != group_id: + raise ColumnSchemaError( + f"Группа {group_id!r} должна ссылаться на column_id aggregate" + ) + if not aggregate.structured_value or aggregate.structured_order != 0: + raise ColumnSchemaError( + f"Aggregate группы {group_id!r} настроен некорректно" + ) + if not components: + raise ColumnSchemaError( + f"Группа {group_id!r} должна содержать components" + ) + + for role in ("one_line", "component"): + role_members = [ + member for member in members if member.structured_role == role + ] + orders = [member.structured_order for member in role_members] + if any(order < 1 for order in orders) or len(orders) != len( + set(orders) + ): + raise ColumnSchemaError( + f"Группа {group_id!r}: порядок роли {role} некорректен" + ) + if any(member.structured_value for member in role_members): + raise ColumnSchemaError( + f"Группа {group_id!r}: только aggregate может быть structured_value" + ) + if any(member.join_with_space for member in role_members): + raise ColumnSchemaError( + f"Группа {group_id!r}: join_with_space допустим только aggregate" + ) + + @staticmethod + def _build_report_groups( + columns: tuple[ColumnMeta, ...], + ) -> tuple[ReportGroup, ...]: + result: list[ReportGroup] = [] + seen_groups: set[str] = set() + current_id = "" + current_indexes: list[int] = [] + for column in columns: + if column.report_group == current_id: + current_indexes.append(column.index) + continue + if current_indexes: + result.append( + ReportGroup( + current_id, + REPORT_GROUP_TITLES[current_id], + tuple(current_indexes), + ) + ) + seen_groups.add(current_id) + if column.report_group in seen_groups: + raise ColumnSchemaError( + f"report_group {column.report_group!r} разбит на несколько диапазонов" + ) + current_id = column.report_group + current_indexes = [column.index] + if current_indexes: + result.append( + ReportGroup( + current_id, + REPORT_GROUP_TITLES[current_id], + tuple(current_indexes), + ) + ) + return tuple(result) + + +COLUMNS = ColumnRegistry.load(MAPPING_DATA_FILE) diff --git a/app/pipeline/mapping.py b/app/pipeline/mapping.py index 99eea6e..3cfe2ad 100644 --- a/app/pipeline/mapping.py +++ b/app/pipeline/mapping.py @@ -1,19 +1,96 @@ from __future__ import annotations -import json import re from dataclasses import dataclass -from pathlib import Path + +from .column_constants import ( + ACCOUNT_PLACEHOLDER, + BLOCK_CP, + BLOCK_EIO, + CASHLESS_CLEARED_COLUMNS, + CASHLESS_TRANSFER_TYPES, + COL_ADDRESS_ONE_LINE, + COL_AMOUNT_CURRENCY, + COL_AMOUNT_RUB, + COL_BIRTH_REG_DATE, + COL_BRANCH_SIGN, + COL_CARD_HOLDER_INFO, + COL_CLIENT_SIGN, + COL_COUNTRY_CODE, + COL_CP_ISSUER_INN, + COL_CURRENCY, + COL_CURRENCY_SIGN, + COL_EIO_INN, + COL_EIO_REG_PLACE_ONE_LINE, + COL_EMPLOYEE_SIGN, + COL_ESP_SIGN, + COL_EXTRA_CODES, + COL_FILE_NAME, + COL_FOREIGN_BANK_NAME, + COL_FTR_SIGN, + COL_IDENT_FL, + COL_INN, + COL_INSURANCE_NUMBER, + COL_ITEM_TYPE, + COL_KPP, + COL_METAL_CODE, + COL_METAL_NAME, + COL_OPERATION_CODE, + COL_OPERATION_SIGN, + COL_OPERATOR_TYPE, + COL_PARTICIPANT_TYPE, + COL_PAYER_ACCOUNT, + COL_PAYER_BANK_ACCOUNT, + COL_PAYER_BANK_BIK, + COL_PAYER_BANK_NAME, + COL_PAYER_ESP, + COL_RECIPIENT_ACCOUNT, + COL_RECIPIENT_BANK_ACCOUNT, + COL_RECIPIENT_BANK_BIK, + COL_RECIPIENT_BANK_NAME, + COL_RECIPIENT_ESP, + COL_RECORD_ID, + COL_REG_PLACE_ONE_LINE, + COL_REG_PLACE_STRUCTURED, + COL_RESIDENT_SIGN, + COL_SALE_AMOUNT, + COL_SALE_CURRENCY, + COL_SUSPENSION_BASIS, + COL_SUSPICIOUS_ID, + COL_TERRITORY_CODE, + COL_TERRITORY_CODE_CARD, + COL_TRANSFER_STATUS, + COL_TRANSFER_TYPE, + COL_UNUSUAL_CODES, + CURRENCY_OPERATION_CODES, + EMPLOYEE_ABSENT_CODE, + OKATO_COUNTRY_PAIRS, + PARTICIPANT_TYPE_FL, + PARTICIPANT_TYPE_FLCHP, + PARTICIPANT_TYPE_IP, + PARTICIPANT_TYPE_UL, + PRECIOUS_ITEM_CODES, + PRECIOUS_METAL_CODE, + RUSSIA_COUNTRY_CODE, + SUSPICIOUS_CODE, + TERRITORY_CODE, + VALID_ESP_SIGNS, + VALID_FTR_SIGNS, + VALID_SUSPENSION_BASES, +) +from .column_registry import COLUMNS, ColumnMeta @dataclass(frozen=True) class MappingRule: column_index: int + column_id: str column_name: str candidate_keys: tuple[str, ...] source: str = "any" allow_direct_mapping: bool = True allow_short_lookup: bool = True + structured_value: bool = False @dataclass(frozen=True) @@ -24,63 +101,9 @@ class StructuredGroupRule: join_with_space: bool = False -MAPPING_DATA_FILE = Path(__file__).resolve().with_name("mapping_table.json") -TARGET_REPORT_COLUMNS_COUNT = 204 - -_MANUAL_COLUMN_NAME_FIXES: dict[int, str] = { - 1: "Имя XML файла", - 178: "Место государственной регистрации ЕИО/Бенефициара (одной строкой)", - 183: "Номер", -} - _INVALID_TAGS = {"", "-", "Источник", "путь", "подразумеваются", "тэга", "нашла"} -def _load_mapping_data() -> list[dict[str, str | int]]: - raw = json.loads(MAPPING_DATA_FILE.read_text(encoding="utf-8")) - if not isinstance(raw, list): - return [] - result: list[dict[str, str | int]] = [] - for item in raw: - if not isinstance(item, dict): - continue - idx = int(item.get("index", 0)) - if not 1 <= idx <= TARGET_REPORT_COLUMNS_COUNT: - continue - column_name = str(item.get("column_name", "")).strip() - xml_tag = str(item.get("xml_tag", "")).strip() - xml_path = str(item.get("xml_path", "")).strip() - if idx in _MANUAL_COLUMN_NAME_FIXES: - column_name = _MANUAL_COLUMN_NAME_FIXES[idx] - column_name = _cleanup_column_name(column_name) - result.append( - { - "index": idx, - "column_name": column_name, - "xml_tag": xml_tag, - "xml_path": xml_path, - } - ) - return sorted(result, key=lambda row: int(row["index"])) - - -def _cleanup_column_name(value: str) -> str: - cleaned = re.sub(r"\s+", " ", value).strip() - cleaned = re.sub(r"\s+не\s+нашла.*$", "", cleaned, flags=re.IGNORECASE) - return cleaned.strip(" -") - - -def _build_fixed_columns(mapping_data: list[dict[str, str | int]]) -> tuple[str, ...]: - columns: list[str] = [] - for row in mapping_data: - column = str(row.get("column_name", "")).strip() - columns.append(column or f"Колонка {row['index']}") - if len(columns) < TARGET_REPORT_COLUMNS_COUNT: - for index in range(len(columns) + 1, TARGET_REPORT_COLUMNS_COUNT + 1): - columns.append(f"Колонка {index}") - return tuple(columns[:TARGET_REPORT_COLUMNS_COUNT]) - - def _bank_bik_candidate_keys(bank_block: str) -> tuple[str, ...]: candidates: list[str] = [] for transfers_block in ("СведенияПереводыДС", "СвединияПереводыДС"): @@ -97,33 +120,17 @@ def _bank_bik_candidate_keys(bank_block: str) -> tuple[str, ...]: return tuple(candidates) -def _build_rules(mapping_data: list[dict[str, str | int]]) -> tuple[MappingRule, ...]: +def _build_rules(mapping_data: tuple[ColumnMeta, ...]) -> tuple[MappingRule, ...]: rules: list[MappingRule] = [] - participant_columns = { - "Признак резидента участника", - "Тип участника", - "ИНН участника", - "Наименование участника", - "Счет участника", - "Фамилия", - "Имя", - "Отчество", - "ФИО (по структуре полностью)", - "ФИО (в одной строке)", - "ФИО ( в одной строке)", - "Код страны гражданства", - "Признак принадлежности к публичным лицам", - } - for row in mapping_data: - index = int(row.get("index", 0)) - column = str(row.get("column_name", "")).strip() - tag = str(row.get("xml_tag", "")).strip() - path = str(row.get("xml_path", "")).strip() + for meta in mapping_data: + index = meta.index + column = meta.name + tag = meta.xml_tag + path = meta.xml_path if not column or tag in _INVALID_TAGS: continue - is_structured_target = _is_structured_column(column) or index == 153 candidates = list(_extract_tag_candidate_keys(tag)) - if column.startswith("ИНН") and index < 154: + if index == COL_INN: candidates = ["ИННФЛИП", "ИННФЛ", "ИННЮЛ", "ИНН", *candidates] if column == "Тип участника": candidates = ["Тип", "ТипУчастника", *candidates] @@ -135,41 +142,34 @@ def _build_rules(mapping_data: list[dict[str, str | int]]) -> tuple[MappingRule, for path_tag in path_candidates: if path_tag not in candidates: candidates.append(path_tag) - allow_short_lookup = True - if column == "БИК банка плательщика": + if index == COL_PAYER_BANK_BIK: candidates = list(_bank_bik_candidate_keys("СведБанкПлательщик")) - allow_short_lookup = False - elif column == "БИК банка получателя": + elif index == COL_RECIPIENT_BANK_BIK: candidates = list(_bank_bik_candidate_keys("СведБанкПолучатель")) - allow_short_lookup = False - elif column == "Код страны гражданства": + elif index == COL_COUNTRY_CODE: candidates = [ candidate for candidate in [*path_candidates, *candidates] if candidate.endswith("СведФЛИП.КодОКСМ") ] - allow_short_lookup = False - elif index == 119: + elif index == COL_IDENT_FL: candidates = [ candidate for candidate in [*path_candidates, *candidates] if candidate.endswith("ИдентификацияФЛ") ] - allow_short_lookup = False - elif index == 123: + elif index == COL_BIRTH_REG_DATE: candidates = [ candidate for candidate in [*path_candidates, *candidates] - if candidate.endswith("ДатаРегЮЛ") or candidate.endswith("ДатаРождения") + if candidate.endswith(("ДатаРегЮЛ", "ДатаРождения")) ] - allow_short_lookup = False - elif index == 152: + elif index == COL_REG_PLACE_ONE_LINE: candidates = [ "УчастникЮЛ.СведЮЛ.АдрРегЮЛ.АдресСтрока", "СообщОперКО.ИнформЧасть.СведКО.Операция.УчастникОП.УчастникЮЛ.СведЮЛ.АдрРегЮЛ.АдресСтрока", ] - allow_short_lookup = False - elif index == 153: + elif index == COL_REG_PLACE_STRUCTURED: base_paths = ( "УчастникЮЛ.СведЮЛ.АдрРегЮЛ", "СообщОперКО.ИнформЧасть.СведКО.Операция.УчастникОП.УчастникЮЛ.СведЮЛ.АдрРегЮЛ", @@ -188,16 +188,12 @@ def _build_rules(mapping_data: list[dict[str, str | int]]) -> tuple[MappingRule, candidates = [ f"{base_path}.{tag}" for base_path in base_paths for tag in address_tags ] - allow_short_lookup = False - elif index == 202: + elif index == COL_CP_ISSUER_INN: candidates = [ candidate for candidate in [*path_candidates, *candidates] if candidate.endswith("ИННЭмитентЦП") ] - allow_short_lookup = False - elif 49 <= index <= 101 or 155 <= index <= 204: - allow_short_lookup = False if not candidates: candidates = list(_extract_tag_candidate_keys(tag)) non_one_line_candidates = [ @@ -205,181 +201,71 @@ def _build_rules(mapping_data: list[dict[str, str | int]]) -> tuple[MappingRule, for candidate in candidates if not _is_one_line_candidate(candidate) ] - one_line_candidates = [ - candidate for candidate in candidates if _is_one_line_candidate(candidate) - ] direct_candidates = candidates - allow_direct_mapping = True - if is_structured_target and one_line_candidates and not non_one_line_candidates: - allow_direct_mapping = False - if is_structured_target and non_one_line_candidates: + if meta.structured_value and non_one_line_candidates: direct_candidates = non_one_line_candidates - if 194 <= index <= 204 or index in {41, 43}: - source = "operation" - elif 155 <= index <= 193: - source = "participant" - elif index in {119, 122, 124}: - source = "participant" - else: - source = ( - "participant" - if ( - column in participant_columns - or column.startswith("ИНН") - or index in range(128, 140) - ) - else "any" - ) rules.append( MappingRule( column_index=index, + column_id=meta.column_id, column_name=column, candidate_keys=tuple(direct_candidates), - source=source, - allow_direct_mapping=allow_direct_mapping, - allow_short_lookup=allow_short_lookup, + source=meta.source_scope, + allow_direct_mapping=meta.allow_direct_mapping, + allow_short_lookup=meta.allow_short_lookup, + structured_value=meta.structured_value, ) ) return tuple(rules) -def _is_one_line_column(column_name: str) -> bool: - normalized = column_name.lower().replace("ё", "е") - return "одной строк" in normalized - - def _is_one_line_candidate(candidate: str) -> bool: return "строка" in candidate.lower() -def _is_structured_column(column_name: str) -> bool: - normalized = column_name.lower().replace("ё", "е") - return "структур" in normalized or "(целый)" in normalized - - -def _split_paths(path: str) -> tuple[str, ...]: - result: list[str] = [] - for chunk in path.split("|"): - candidate = chunk.strip() - if candidate: - result.append(candidate.rstrip("/")) - return tuple(result) - - -def _common_prefix_depth(path_a: str, path_b: str) -> int: - parts_a = [part for part in path_a.strip("/").split("/") if part] - parts_b = [part for part in path_b.strip("/").split("/") if part] - depth = 0 - for left, right in zip(parts_a, parts_b): - if left != right: - break - depth += 1 - return depth - - -def _paths_related( - struct_paths: tuple[str, ...], candidate_paths: tuple[str, ...] -) -> bool: - if not struct_paths or not candidate_paths: - return False - for struct_path in struct_paths: - for candidate_path in candidate_paths: - if _common_prefix_depth(struct_path, candidate_path) >= 6: - return True - return False - - -def _is_path_under_any_base(path: str, base_paths: tuple[str, ...]) -> bool: - for base_path in base_paths: - if path == base_path or path.startswith(f"{base_path}/"): - return True - return False - - def _build_structured_group_rules( - mapping_data: list[dict[str, str | int]], + mapping_data: tuple[ColumnMeta, ...], ) -> tuple[StructuredGroupRule, ...]: - by_index: dict[int, dict[str, str | int]] = { - int(item["index"]): item for item in mapping_data - } - sorted_indexes = sorted(by_index.keys()) + grouped: dict[str, list[ColumnMeta]] = {} + for meta in mapping_data: + if meta.structured_group: + grouped.setdefault(meta.structured_group, []).append(meta) + rules: list[StructuredGroupRule] = [] - - for index in sorted_indexes: - item = by_index[index] - structured_name = str(item.get("column_name", "")).strip() - if not _is_structured_column(structured_name): - continue - - struct_paths = _split_paths(str(item.get("xml_path", ""))) - struct_base_paths = tuple( - path.rsplit("/", maxsplit=1)[0] for path in struct_paths if "/" in path - ) - is_address_structured = "адрес" in structured_name.lower().replace("ё", "е") - one_line_indexes: list[int] = [] - component_indexes: list[int] = [] - - # Поле "в одной строке" может располагаться слева от структурного. - left = by_index.get(index - 1) - if left: - left_name = str(left.get("column_name", "")).strip() - if _is_one_line_column(left_name): - left_paths = _split_paths(str(left.get("xml_path", ""))) - if _paths_related(struct_paths, left_paths): - one_line_indexes.append(index - 1) - - right_boundary = next( - ( - candidate - for candidate in sorted_indexes - if candidate > index - and _is_structured_column( - str(by_index[candidate].get("column_name", "")).strip() - ) - ), - None, - ) - block_end = right_boundary or (sorted_indexes[-1] + 1) - - for right_index in sorted_indexes: - if right_index <= index or right_index >= block_end: - continue - right = by_index[right_index] - right_name = str(right.get("column_name", "")).strip() - right_tag = str(right.get("xml_tag", "")).strip() - right_paths = _split_paths(str(right.get("xml_path", ""))) - if is_address_structured: - is_related = any( - _is_path_under_any_base(candidate_path, struct_base_paths) - for candidate_path in right_paths - ) - else: - is_related = _paths_related(struct_paths, right_paths) - if not is_related: - if component_indexes: - break - continue - if _is_one_line_column(right_name): - one_line_indexes.append(right_index) - if component_indexes: - break - continue - if "|" in right_tag: - continue - component_indexes.append(right_index) - - if not component_indexes: - continue - - rules.append( - StructuredGroupRule( - structured_column=index, - one_line_columns=tuple(dict.fromkeys(one_line_indexes)), - component_columns=tuple(dict.fromkeys(component_indexes)), - join_with_space="фио" in structured_name.lower(), + for group_id, members in grouped.items(): + aggregates = [ + member for member in members if member.structured_role == "aggregate" + ] + if len(aggregates) != 1: + raise ValueError( + f"Структурная группа {group_id!r} должна иметь один aggregate" + ) + aggregate = aggregates[0] + one_line_columns = tuple( + member.index + for member in sorted( + (item for item in members if item.structured_role == "one_line"), + key=lambda item: item.structured_order, ) ) - return tuple(rules) + component_columns = tuple( + member.index + for member in sorted( + (item for item in members if item.structured_role == "component"), + key=lambda item: item.structured_order, + ) + ) + if not component_columns: + raise ValueError(f"Структурная группа {group_id!r} не содержит components") + rules.append( + StructuredGroupRule( + structured_column=aggregate.index, + one_line_columns=one_line_columns, + component_columns=component_columns, + join_with_space=aggregate.join_with_space, + ) + ) + return tuple(sorted(rules, key=lambda rule: rule.structured_column)) def _extract_tag_candidate_keys(tag: str) -> tuple[str, ...]: @@ -406,14 +292,12 @@ def _extract_path_candidate_keys(path: str) -> tuple[str, ...]: return tuple(candidates) -_MAPPING_DATA = _load_mapping_data() -FIXED_REPORT_COLUMNS: tuple[str, ...] = _build_fixed_columns(_MAPPING_DATA) +_MAPPING_DATA = COLUMNS.ordered_columns() +FIXED_REPORT_COLUMNS: tuple[str, ...] = COLUMNS.all_columns() REPORT_MAPPING_RULES: tuple[MappingRule, ...] = _build_rules(_MAPPING_DATA) STRUCTURED_GROUP_RULES: tuple[StructuredGroupRule, ...] = _build_structured_group_rules( _MAPPING_DATA ) -_ACCOUNT_PLACEHOLDER = "00000000000000000000" -_CURRENCY_OPERATION_CODES = frozenset(str(code) for code in range(6101, 6127)) def build_fixed_row_by_index( @@ -425,8 +309,8 @@ def build_fixed_row_by_index( participant_fields: dict[str, str], ) -> dict[int, str]: row: dict[int, str] = { - 1: file_name, - 7: record_id, + COL_FILE_NAME: file_name, + COL_RECORD_ID: record_id, } merged = _merge_fields(operation_fields, participant_fields) merged_suffix_index = _build_suffix_index(merged) @@ -463,15 +347,13 @@ def build_fixed_row_by_index( else: source_payload = merged suffix_index = merged_suffix_index - if _is_structured_column(rule.column_name) or rule.column_index == 153: + if rule.structured_value: row[rule.column_index] = _pick_structured_value( source_payload=source_payload, suffix_index=suffix_index, candidates=rule.candidate_keys, join_with_space="фио" in rule.column_name.lower(), - allow_short_lookup=( - rule.allow_short_lookup if rule.column_index == 153 else True - ), + allow_short_lookup=rule.allow_short_lookup, ) else: row[rule.column_index] = _pick_value( @@ -482,17 +364,13 @@ def build_fixed_row_by_index( ) _apply_participant_identity_rules(row, participant_fields) _apply_structured_group_rules(row) - _apply_conditional_rules_1_74(row) - _apply_conditional_rules_75_123(row) - _apply_conditional_rules_124_203(row) - if not has_eio_block: - for index in range(155, 194): - _set_row_value(row, index, "") - if not has_cp_block: - for index in range(194, 205): - _set_row_value(row, index, "") - for index in range(1, TARGET_REPORT_COLUMNS_COUNT + 1): - row.setdefault(index, "") + _apply_business_rules( + row, + has_eio_block=has_eio_block, + has_cp_block=has_cp_block, + ) + for meta in COLUMNS.ordered_columns(): + row.setdefault(meta.index, "") return row @@ -512,34 +390,33 @@ def build_fixed_row( participant_fields=participant_fields, ) by_name: dict[str, str] = {} - for index, column_name in enumerate(FIXED_REPORT_COLUMNS, start=1): - by_name.setdefault(column_name, by_index.get(index, "")) + for meta in COLUMNS.ordered_columns(): + by_name.setdefault(meta.name, by_index.get(meta.index, "")) return by_name def _apply_structured_group_rules(row: dict[int, str]) -> None: for rule in STRUCTURED_GROUP_RULES: one_line_has_value = any( - _row_value(row, column_index).strip() - for column_index in rule.one_line_columns + _get(row, column_index).strip() for column_index in rule.one_line_columns ) if one_line_has_value: - _set_row_value(row, rule.structured_column, "") + _set(row, rule.structured_column, "") for component_column_index in rule.component_columns: - _set_row_value(row, component_column_index, "") + _set(row, component_column_index, "") continue values = [ - _row_value(row, component_column_index).strip() + _get(row, component_column_index).strip() for component_column_index in rule.component_columns - if _row_value(row, component_column_index).strip() + if _get(row, component_column_index).strip() ] if not values: - _set_row_value(row, rule.structured_column, "") + _set(row, rule.structured_column, "") continue separator = " " if rule.join_with_space else ", " - _set_row_value(row, rule.structured_column, separator.join(values)) + _set(row, rule.structured_column, separator.join(values)) def _merge_fields( @@ -569,7 +446,7 @@ def _pick_scoped_payload_value(payload: dict[str, str], scoped_path: str) -> str def _apply_participant_identity_rules( row: dict[int, str], participant_fields: dict[str, str] ) -> None: - participant_type = _normalize_code(_row_value(row, 109)) + participant_type = _normalize_code(_get(row, COL_PARTICIPANT_TYPE)) has_legal_entity = _has_payload_block(participant_fields, "УчастникЮЛ") has_physical_person = _has_payload_block(participant_fields, "УчастникФЛИП") has_foreign_structure = _has_payload_block(participant_fields, "УчастникИНБОЮЛ") @@ -578,11 +455,11 @@ def _apply_participant_identity_rules( identification = _pick_scoped_payload_value( participant_fields, "УчастникФЛИП.ИдентификацияФЛ" ) - _set_row_value(row, 119, identification) + _set(row, COL_IDENT_FL, identification) else: - _set_row_value(row, 119, "") + _set(row, COL_IDENT_FL, "") - if has_legal_entity or participant_type == "1": + if has_legal_entity or participant_type == PARTICIPANT_TYPE_UL: value = _pick_scoped_payload_value( participant_fields, "УчастникЮЛ.СведЮЛ.КППЮЛ" ) @@ -597,7 +474,7 @@ def _apply_participant_identity_rules( ) else: value = "" - _set_row_value(row, 122, value) + _set(row, COL_KPP, value) def _has_any_prefixed_key(payload: dict[str, str], prefixes: tuple[str, ...]) -> bool: @@ -622,13 +499,13 @@ def _pick_value( allow_short_lookup: bool = True, ) -> str: for key in candidates: - if key in payload and payload[key]: - return payload[key] + if value := payload.get(key): + return value if not allow_short_lookup: continue short = key.rsplit(".", maxsplit=1)[-1] - if short in payload and payload[short]: - return payload[short] + if value := payload.get(short): + return value if short in suffix_index: return suffix_index[short] return "" @@ -658,12 +535,8 @@ def _pick_structured_value( return separator.join(values) -def _column(index: int) -> str: - return FIXED_REPORT_COLUMNS[index - 1] - - -def _row_value(row: dict[int, str], index: int) -> str: - return str(row.get(index, "")).strip() +def _get(row: dict[int, str], column: int) -> str: + return str(row.get(column, "")).strip() def _normalize_code(value: str) -> str: @@ -673,200 +546,274 @@ def _normalize_code(value: str) -> str: return normalized -def _set_row_value(row: dict[int, str], index: int, value: str) -> None: - row[index] = value +def _set(row: dict[int, str], column: int, value: str) -> None: + row[column] = value + + +def _clear_columns(row: dict[int, str], columns: tuple[int, ...]) -> None: + for column in columns: + _set(row, column, "") def _extract_numeric_codes(value: str) -> set[str]: return {match for match in re.findall(r"\d+", value)} -def _operation_and_extra_codes(row: dict[int, str]) -> set[str]: - op_code = _row_value(row, 19) - extra_codes = _row_value(row, 20) +def _operation_codes(row: dict[int, str]) -> set[str]: + op_code = _get(row, COL_OPERATION_CODE) + extra_codes = _get(row, COL_EXTRA_CODES) return _extract_numeric_codes(op_code) | _extract_numeric_codes(extra_codes) -def _apply_conditional_rules_1_74(row: dict[int, str]) -> None: - codes = _operation_and_extra_codes(row) - op_type_code = _row_value(row, 14) - transfer_type = _row_value(row, 35) - operator_type = _row_value(row, 37) +def _apply_business_rules( + row: dict[int, str], + *, + has_eio_block: bool, + has_cp_block: bool, +) -> None: + codes = _operation_codes(row) + operation_sign = _get(row, COL_OPERATION_SIGN) + transfer_type = _get(row, COL_TRANSFER_TYPE) + operator_type = _get(row, COL_OPERATOR_TYPE) + participant_type = _normalize_code(_get(row, COL_PARTICIPANT_TYPE)) - # 10. Допустимые значения: 0..5, иначе очищаем. - if _row_value(row, 10) not in {"0", "1", "2", "3", "4", "5"}: - _set_row_value(row, 10, "") + _rule_ftr_sign(row) + _rule_suspension_basis(row) + _rule_esp_sign(row) + _rule_unusual_codes(row, codes) + _rule_digital_rights_currency(row, operation_sign) + _rule_sale_currency(row) + _rule_currency_sign(row, codes) + _rule_suspicious_activity(row, codes) + _rule_metal_name(row) + _rule_item_type(row, codes) + _rule_territory_codes(row, codes) - # 11. Заполняется только для приостановлений и валидных кодов основания. - if _row_value(row, 11) not in {"1", "2", "3"}: - _set_row_value(row, 11, "") + _rule_payer_account(row, transfer_type) + _rule_esp_identifiers(row, operation_sign) + _rule_payer_bank(row, operator_type) + _rule_recipient_bank(row, operator_type) + _rule_correspondent_accounts(row, operator_type, transfer_type) + _rule_recipient_account(row, transfer_type) + _rule_transfer_status(row, transfer_type) - # 15. Заполняется только для допустимых значений признака ЭСП. - if _row_value(row, 15) not in {"1", "2", "3", "4"}: - _set_row_value(row, 15, "") + _rule_cashless_clears_cash_columns(row, transfer_type) + _rule_card_without_employee(row) - # 21. Коды необычной операции заполняются только при признаке 6001. - if "6001" not in codes: - _set_row_value(row, 21, "") + _rule_participant_identity(row, participant_type) + _rule_branch_sign(row, participant_type) + _rule_snils_for_ip(row, participant_type) + _rule_address_one_line(row) + _rule_okato_by_country(row) + _rule_eio_inn_for_physical_person(row, participant_type) - # 22-24. Для операций с цифровыми правами (код 8) не заполняем. - if op_type_code == "8": - _set_row_value(row, 22, "") - _set_row_value(row, 23, "") - _set_row_value(row, 24, "") + if not has_eio_block: + _clear_columns(row, BLOCK_EIO) + if not has_cp_block: + _clear_columns(row, BLOCK_CP) - # 26. Сумма продаваемой валюты выводится только при конверсии и не равна нулю. - conversion_amount = _row_value(row, 26) + +def _rule_ftr_sign(row: dict[int, str]) -> None: + """Правило 10: оставляем только допустимые значения признака ФТР.""" + if _get(row, COL_FTR_SIGN) not in VALID_FTR_SIGNS: + _set(row, COL_FTR_SIGN, "") + + +def _rule_suspension_basis(row: dict[int, str]) -> None: + """Правило 11: основание приостановления должно быть допустимым.""" + if _get(row, COL_SUSPENSION_BASIS) not in VALID_SUSPENSION_BASES: + _set(row, COL_SUSPENSION_BASIS, "") + + +def _rule_esp_sign(row: dict[int, str]) -> None: + """Правило 15: признак ЭСП должен быть допустимым.""" + if _get(row, COL_ESP_SIGN) not in VALID_ESP_SIGNS: + _set(row, COL_ESP_SIGN, "") + + +def _rule_unusual_codes(row: dict[int, str], codes: set[str]) -> None: + """Правило 21: коды необычной операции относятся только к 6001.""" + if SUSPICIOUS_CODE not in codes: + _set(row, COL_UNUSUAL_CODES, "") + + +def _rule_digital_rights_currency(row: dict[int, str], operation_sign: str) -> None: + """Правила 22-24: для цифровых прав валютные суммы не выводятся.""" + if operation_sign == "8": + _set(row, COL_CURRENCY, "") + _set(row, COL_AMOUNT_CURRENCY, "") + _set(row, COL_AMOUNT_RUB, "") + + +def _rule_sale_currency(row: dict[int, str]) -> None: + """Правило 26: нулевая сумма или отсутствие конверсии дают пустое поле.""" + conversion_amount = _get(row, COL_SALE_AMOUNT) normalized_amount = conversion_amount.replace(",", ".") - if not _row_value(row, 25) or re.fullmatch(r"[+-]?0+(?:\.0+)?", normalized_amount): - _set_row_value(row, 26, "") + if not _get(row, COL_SALE_CURRENCY) or re.fullmatch( + r"[+-]?0+(?:\.0+)?", normalized_amount + ): + _set(row, COL_SALE_AMOUNT, "") - # 27. Признак VO относится только к валютным операциям 6101-6126. - if not codes & _CURRENCY_OPERATION_CODES: - _set_row_value(row, 27, "") - # 28. Идентификатор подозрительной деятельности только для 6001. - if "6001" not in codes: - _set_row_value(row, 28, "") +def _rule_currency_sign(row: dict[int, str], codes: set[str]) -> None: + """Правило 27: признак VO только для валютных операций 6101-6126.""" + if not codes & CURRENCY_OPERATION_CODES: + _set(row, COL_CURRENCY_SIGN, "") - # 30. Наименование драгметалла только для кода C99. - if _row_value(row, 29).upper() != "C99": - _set_row_value(row, 30, "") - # 31. Предмет операции только для кодов 5020..5023. - if not {"5020", "5021", "5022", "5023"} & codes: - _set_row_value(row, 31, "") +def _rule_suspicious_activity(row: dict[int, str], codes: set[str]) -> None: + """Правило 28: идентификатор подозрительной деятельности только для 6001.""" + if SUSPICIOUS_CODE not in codes: + _set(row, COL_SUSPICIOUS_ID, "") - # 36. Код территории заполняется только для признака 5016. - if "5016" not in codes: - _set_row_value(row, 36, "") - # 38. Счет плательщика обязателен для видов перевода 1/2/3/10 с заглушкой. +def _rule_metal_name(row: dict[int, str]) -> None: + """Правило 30: наименование металла только для кода C99.""" + if _get(row, COL_METAL_CODE).upper() != PRECIOUS_METAL_CODE: + _set(row, COL_METAL_NAME, "") + + +def _rule_item_type(row: dict[int, str], codes: set[str]) -> None: + """Правило 31: предмет операции только для кодов 5020-5023.""" + if not codes & PRECIOUS_ITEM_CODES: + _set(row, COL_ITEM_TYPE, "") + + +def _rule_territory_codes(row: dict[int, str], codes: set[str]) -> None: + """Правила 36 и 96: код территории только для операции 5016.""" + if TERRITORY_CODE not in codes: + _set(row, COL_TERRITORY_CODE, "") + _set(row, COL_TERRITORY_CODE_CARD, "") + + +def _rule_payer_account(row: dict[int, str], transfer_type: str) -> None: + """Правило 38: счёт плательщика зависит от вида перевода.""" if transfer_type in {"1", "2", "3", "10"}: - if not _row_value(row, 38): - _set_row_value(row, 38, _ACCOUNT_PLACEHOLDER) - elif transfer_type in {"12", "13", "14"}: - pass - else: - _set_row_value(row, 38, "") + if not _get(row, COL_PAYER_ACCOUNT): + _set(row, COL_PAYER_ACCOUNT, ACCOUNT_PLACEHOLDER) + elif transfer_type not in {"12", "13", "14"}: + _set(row, COL_PAYER_ACCOUNT, "") - # 39 / 47. Идентификаторы ЭСП отсутствуют для признака операции 9. - if op_type_code == "9": - _set_row_value(row, 39, "") - _set_row_value(row, 47, "") - # 40. Банк плательщика заполняется только при типе оператора 2 или 4. +def _rule_esp_identifiers(row: dict[int, str], operation_sign: str) -> None: + """Правила 39 и 47: идентификаторы ЭСП отсутствуют для признака 9.""" + if operation_sign == "9": + _set(row, COL_PAYER_ESP, "") + _set(row, COL_RECIPIENT_ESP, "") + + +def _rule_payer_bank(row: dict[int, str], operator_type: str) -> None: + """Правило 40: банк плательщика только для типов оператора 2 и 4.""" if operator_type not in {"2", "4"}: - _set_row_value(row, 40, "") + _set(row, COL_PAYER_BANK_NAME, "") - # 42/43. Реквизиты банка получателя только при типе оператора 1 или 4. + +def _rule_recipient_bank(row: dict[int, str], operator_type: str) -> None: + """Правила 42-43: банк получателя только для типов оператора 1 и 4.""" if operator_type not in {"1", "4"}: - _set_row_value(row, 42, "") - _set_row_value(row, 43, "") + _set(row, COL_RECIPIENT_BANK_NAME, "") + _set(row, COL_RECIPIENT_BANK_BIK, "") - # 44. Корсчет банка плательщика с заглушкой там, где это применимо. + +def _rule_correspondent_accounts( + row: dict[int, str], operator_type: str, transfer_type: str +) -> None: + """Правила 44-45: корсчета зависят от оператора и вида перевода.""" if operator_type in {"3", "5"} or transfer_type in {"12", "13"}: - _set_row_value(row, 44, "") - elif not _row_value(row, 44): - _set_row_value(row, 44, _ACCOUNT_PLACEHOLDER) + _set(row, COL_PAYER_BANK_ACCOUNT, "") + elif not _get(row, COL_PAYER_BANK_ACCOUNT): + _set(row, COL_PAYER_BANK_ACCOUNT, ACCOUNT_PLACEHOLDER) - # 45. Корсчет банка получателя с заглушкой там, где это применимо. if operator_type in {"3", "5"} or transfer_type in {"10", "11"}: - _set_row_value(row, 45, "") - elif not _row_value(row, 45): - _set_row_value(row, 45, _ACCOUNT_PLACEHOLDER) + _set(row, COL_RECIPIENT_BANK_ACCOUNT, "") + elif not _get(row, COL_RECIPIENT_BANK_ACCOUNT): + _set(row, COL_RECIPIENT_BANK_ACCOUNT, ACCOUNT_PLACEHOLDER) - # 46. Счет получателя с заглушкой для обязательных видов перевода. + +def _rule_recipient_account(row: dict[int, str], transfer_type: str) -> None: + """Правило 46: счёт получателя зависит от вида перевода.""" if transfer_type in {"1", "4", "7", "12"}: - if not _row_value(row, 46): - _set_row_value(row, 46, _ACCOUNT_PLACEHOLDER) - elif transfer_type in {"10", "11", "14"}: - pass - else: - _set_row_value(row, 46, "") + if not _get(row, COL_RECIPIENT_ACCOUNT): + _set(row, COL_RECIPIENT_ACCOUNT, ACCOUNT_PLACEHOLDER) + elif transfer_type not in {"10", "11", "14"}: + _set(row, COL_RECIPIENT_ACCOUNT, "") - # 62. Статус перевода заполняется только для видов 2/5/8. + +def _rule_transfer_status(row: dict[int, str], transfer_type: str) -> None: + """Правило 62: статус перевода только для видов 2, 5 и 8.""" if transfer_type not in {"2", "5", "8"}: - _set_row_value(row, 62, "") - - # Для безналичных операций не заполняем блоки приема/выдачи наличных. - if transfer_type in {"1", "2", "3", "4", "7", "10", "11", "12", "13", "14"}: - for column_index in (50, 61, 65): - _set_row_value(row, column_index, "") + _set(row, COL_TRANSFER_STATUS, "") -def _apply_conditional_rules_75_123(row: dict[int, str]) -> None: - codes = _operation_and_extra_codes(row) +def _rule_cashless_clears_cash_columns(row: dict[int, str], transfer_type: str) -> None: + """Для безналичных переводов очищаем согласованные наличные поля.""" + if transfer_type in CASHLESS_TRANSFER_TYPES: + _clear_columns(row, CASHLESS_CLEARED_COLUMNS) - # 96. Код территории заполняется только для признака 5016 (дубль 36). - if "5016" not in codes: - _set_row_value(row, 96, "") - # 103. Если операция без участия сотрудника и данных нет -> подставляем заглушку. - if _row_value(row, 104) == "0" and not _row_value(row, 103): - _set_row_value(row, 103, "Информация отсутствует") +def _rule_card_without_employee(row: dict[int, str]) -> None: + """Правила 103 и 105: подставляем заглушку при отсутствии сотрудника.""" + if _get(row, COL_EMPLOYEE_SIGN) != EMPLOYEE_ABSENT_CODE: + return + if not _get(row, COL_CARD_HOLDER_INFO): + _set(row, COL_CARD_HOLDER_INFO, "Информация отсутствует") + if not _get(row, COL_FOREIGN_BANK_NAME): + _set(row, COL_FOREIGN_BANK_NAME, "Информация отсутствует") - # 105. Аналогично для наименования иностранного банка. - if _row_value(row, 104) == "0" and not _row_value(row, 105): - _set_row_value(row, 105, "Информация отсутствует") - transfer_type = _row_value(row, 35) - if transfer_type in {"1", "2", "3", "4", "7", "10", "11", "12", "13", "14"}: - for column_index in (76, 84, 95, 99, 101): - _set_row_value(row, column_index, "") +def _rule_participant_identity(row: dict[int, str], participant_type: str) -> None: + """Правила 119 и 122: идентификация и КПП зависят от типа участника.""" + if participant_type in {PARTICIPANT_TYPE_UL, PARTICIPANT_TYPE_FL}: + _set(row, COL_IDENT_FL, "") + if participant_type == PARTICIPANT_TYPE_FL: + _set(row, COL_KPP, "") - participant_type = _normalize_code(_row_value(row, 109)) - # 119. Для ЮЛ и ФЛ поле ППЦР не заполняется. - if participant_type in {"1", "2"}: - _set_row_value(row, 119, "") +def _rule_branch_sign(row: dict[int, str], participant_type: str) -> None: + """Правило 124: показатель отсутствует для ФЛ, ИП и ФЛЧП.""" + if participant_type in { + PARTICIPANT_TYPE_FL, + PARTICIPANT_TYPE_IP, + PARTICIPANT_TYPE_FLCHP, + }: + _set(row, COL_BRANCH_SIGN, "") - # 122. Для ФЛ идентификация не подставляется вместо отсутствующего КПП. - if participant_type == "2": - _set_row_value(row, 122, "") + +def _rule_snils_for_ip(row: dict[int, str], participant_type: str) -> None: + """Правило 125: СНИЛС не выводится для ИП.""" + if participant_type != PARTICIPANT_TYPE_IP: + return + insurance_value = _get(row, COL_INSURANCE_NUMBER) + if re.fullmatch(r"\d{3}-?\d{3}-?\d{3}\s?\d{2}", insurance_value): + _set(row, COL_INSURANCE_NUMBER, "") def _allow_one_line_address(row: dict[int, str]) -> bool: - resident_flag = _row_value(row, 110) - client_flag = _row_value(row, 111) + resident_flag = _get(row, COL_RESIDENT_SIGN) + client_flag = _get(row, COL_CLIENT_SIGN) if not resident_flag and not client_flag: return True return resident_flag in {"0", "9"} or (resident_flag == "1" and client_flag == "0") -def _apply_conditional_rules_124_203(row: dict[int, str]) -> None: - participant_type = _normalize_code(_row_value(row, 109)) - - # 124. Для ФЛ, ИП и ФЛЧП показатель отсутствует. - if participant_type in {"2", "3", "4"}: - _set_row_value(row, 124, "") - - # 125. Для ИП СНИЛС не выводится. - if participant_type == "3": - insurance_value = _row_value(row, 125) - if re.fullmatch(r"\d{3}-?\d{3}-?\d{3}\s?\d{2}", insurance_value): - _set_row_value(row, 125, "") - - # 140/151/177. Однострочные адреса только для нерезидента, - # неопределенного резидентства или резидента-не клиента. +def _rule_address_one_line(row: dict[int, str]) -> None: + """Правила 141, 152 и 178: однострочные адреса только для нерезидентов.""" if not _allow_one_line_address(row): - _set_row_value(row, 141, "") - _set_row_value(row, 152, "") - _set_row_value(row, 178, "") + _set(row, COL_ADDRESS_ONE_LINE, "") + _set(row, COL_REG_PLACE_ONE_LINE, "") + _set(row, COL_EIO_REG_PLACE_ONE_LINE, "") - # Правило КодОКСМ/КодОКАТО в адресных блоках: - # ОКАТО заполняется только при российском коде страны 643. - okato_country_pairs = ( - (52, 53), - (67, 68), - (86, 87), - (144, 145), - (170, 171), - ) - for country_col, okato_col in okato_country_pairs: - if _row_value(row, country_col) != "643": - _set_row_value(row, okato_col, "") - # 162. Для ФЛ показатель отсутствует. - if participant_type == "2": - _set_row_value(row, 163, "") +def _rule_okato_by_country(row: dict[int, str]) -> None: + """ОКАТО адресного блока заполняется только для России.""" + for country_column, okato_column in OKATO_COUNTRY_PAIRS: + if _get(row, country_column) != RUSSIA_COUNTRY_CODE: + _set(row, okato_column, "") + + +def _rule_eio_inn_for_physical_person( + row: dict[int, str], participant_type: str +) -> None: + """Правило 163: показатель ЕИО отсутствует для ФЛ.""" + if participant_type == PARTICIPANT_TYPE_FL: + _set(row, COL_EIO_INN, "") diff --git a/app/pipeline/mapping_table.json b/app/pipeline/mapping_table.json index f93955b..d26b273 100644 --- a/app/pipeline/mapping_table.json +++ b/app/pipeline/mapping_table.json @@ -1,1836 +1,4080 @@ [ { "index": 1, - "column_name": "Имя XML-файла", + "column_id": "legacy_001", + "column_name": "Имя XML файла", + "block": "file_metadata", + "report_group": "service", "xml_tag": "-", "xml_path": "/ММ/ГГГГ", + "source_scope": "any", + "allow_short_lookup": true, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "", + "structured_role": "", + "structured_order": 0, + "join_with_space": false, "multiplies": "нет", "required": "Обязательно", "comment": "Данные берутся из названия входящего файла в формате \"ДД/ММ/ГГГГ\"" }, { "index": 2, + "column_id": "legacy_002", "column_name": "Дата сообщения", + "block": "message_header", + "report_group": "message_bank", "xml_tag": "ДатаСообщения", "xml_path": "/СообщОперКО/СлужЧасть/ДатаСообщения", + "source_scope": "any", + "allow_short_lookup": true, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "", + "structured_role": "", + "structured_order": 0, + "join_with_space": false, "multiplies": "нет", "required": "Обязательно", "comment": "Дата формирования ФЭС. Совпадает с датой, указанной в наименовании файла ФЭС." }, { "index": 3, + "column_id": "legacy_003", "column_name": "Тип информации", + "block": "message_header", + "report_group": "message_bank", "xml_tag": "ТипИнф", "xml_path": "/СообщОперКО/СлужЧасть/ТипИнф", + "source_scope": "any", + "allow_short_lookup": true, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "", + "structured_role": "", + "structured_order": 0, + "join_with_space": false, "multiplies": "нет", "required": "Обязательно", "comment": "Числовое поле." }, { "index": 4, + "column_id": "legacy_004", "column_name": "ОКАТО", + "block": "message_header", + "report_group": "message_bank", "xml_tag": "ОКАТОФл", "xml_path": "/СообщОперКО/ИнформЧасть/СведКО/ИнфФилиал/ОКАТОФл", + "source_scope": "any", + "allow_short_lookup": true, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "", + "structured_role": "", + "structured_order": 0, + "join_with_space": false, "multiplies": "нет", "required": "необязательно", "comment": "Числовое поле. Код территории кредитной организации. Показатель отсутствует только в случае заграничных кредитных организаций." }, { "index": 5, + "column_id": "legacy_005", "column_name": "БИК", + "block": "message_header", + "report_group": "message_bank", "xml_tag": "БИКФл", "xml_path": "/СообщОперКО/ИнформЧасть/СведКО/ИнфФилиал/БИКФл", + "source_scope": "any", + "allow_short_lookup": true, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "", + "structured_role": "", + "structured_order": 0, + "join_with_space": false, "multiplies": "нет", "required": "необязательно", "comment": "числовое поле. Значения может быть пустое." }, { "index": 6, + "column_id": "legacy_006", "column_name": "Номер филиала", + "block": "message_header", + "report_group": "message_bank", "xml_tag": "НомФл", "xml_path": "/СообщОперКО/ИнформЧасть/СведКО/ИнфФилиал/НомФл", + "source_scope": "any", + "allow_short_lookup": true, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "", + "structured_role": "", + "structured_order": 0, + "join_with_space": false, "multiplies": "нет", "required": "Обязательно", "comment": "Числовое поле, порядковый номер филиала." }, { "index": 7, + "column_id": "legacy_007", "column_name": "Идентификатор записи", + "block": "operation_base", + "report_group": "record_control", "xml_tag": "НомерЗаписи", "xml_path": "/СообщОперКО/ИнформЧасть/СведКо/Операция/НомерЗаписи", + "source_scope": "any", + "allow_short_lookup": true, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "", + "structured_role": "", + "structured_order": 0, + "join_with_space": false, "multiplies": "нет", "required": "Обязательно", "comment": "Текстовое поле" }, { "index": 8, + "column_id": "legacy_008", "column_name": "Тип записи (action)", + "block": "operation_base", + "report_group": "record_control", "xml_tag": "ТипЗаписи", "xml_path": "/СообщОперКО/ИнформЧасть/СведКо/Операция/ТипЗаписи", + "source_scope": "any", + "allow_short_lookup": true, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "", + "structured_role": "", + "structured_order": 0, + "join_with_space": false, "multiplies": "нет", "required": "Обязательно", "comment": "Не нашла информацию о \"типе записи\" в документации. Есть тип записи ФЭС, таб. 3.2 пункт 4 Это одно и тоже?" }, { "index": 9, + "column_id": "legacy_009", "column_name": "Уникальный номер операции", + "block": "operation_base", + "report_group": "record_control", "xml_tag": "НомерОперация", "xml_path": "/СообщОперКО/ИнформЧасть/СведКо/Операция/НомерОперация", + "source_scope": "any", + "allow_short_lookup": true, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "", + "structured_role": "", + "structured_order": 0, + "join_with_space": false, "multiplies": "нет", "required": "необязательно", "comment": "Числовой показатель, поле может быть пустым так как данные могут не передаваться в XML" }, { "index": 10, + "column_id": "legacy_010", "column_name": "Признак операции, связанной с фин. терроризма", + "block": "operation_base", + "report_group": "record_control", "xml_tag": "ПризнФТр", "xml_path": "/СообщОперКО/ИнформЧасть/СведКо/Операция/ПризнФТр", + "source_scope": "any", + "allow_short_lookup": true, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "", + "structured_role": "", + "structured_order": 0, + "join_with_space": false, "multiplies": "Множится", "required": "обязательно", "comment": "Числовой показатель" }, { "index": 11, + "column_id": "legacy_011", "column_name": "Основание приостановления", + "block": "operation_base", + "report_group": "record_control", "xml_tag": "ОснПриостановление", "xml_path": "/СообщОперКО/ИнформЧасть/СведКо/Операция/ОснПриостановление", + "source_scope": "any", + "allow_short_lookup": true, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "", + "structured_role": "", + "structured_order": 0, + "join_with_space": false, "multiplies": "нет", "required": "необязательно", "comment": "Числовой показатель, поле может остаться пустым так как данные могут не передаваться в XML" }, { "index": 12, + "column_id": "legacy_012", "column_name": "Дата совершения(приостановл.)", + "block": "operation_base", + "report_group": "record_control", "xml_tag": "ДатаОперации", "xml_path": "/СообщОперКО/ИнформЧасть/СведКо/Операция/ДатаОперации", + "source_scope": "any", + "allow_short_lookup": true, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "", + "structured_role": "", + "structured_order": 0, + "join_with_space": false, "multiplies": "нет", "required": "обязательно", "comment": "Формат дата \"ДД/ММ/ГГГГ\"" }, { "index": 13, + "column_id": "legacy_013", "column_name": "Дата выявления", + "block": "operation_base", + "report_group": "record_control", "xml_tag": "ДатаВыявления", "xml_path": "/СообщОперКО/ИнформЧасть/СведКо/Операция/ДатаВыявления", + "source_scope": "any", + "allow_short_lookup": true, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "", + "structured_role": "", + "structured_order": 0, + "join_with_space": false, "multiplies": "нет", "required": "необязательно", "comment": "Поле дата может оставаться пустым не поступать в XML.." }, { "index": 14, + "column_id": "legacy_014", "column_name": "Код призн.", + "block": "operation_base", + "report_group": "operation_parameters", "xml_tag": "КодПризнОперации", "xml_path": "/СообщОперКО/Операция/КодПризнОперации", + "source_scope": "any", + "allow_short_lookup": true, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "", + "structured_role": "", + "structured_order": 0, + "join_with_space": false, "multiplies": "нет", "required": "обязательно", "comment": "Числовое поле." }, { "index": 15, + "column_id": "legacy_015", "column_name": "Призн. Совершения оп. с испол. ЭСП", + "block": "operation_base", + "report_group": "operation_parameters", "xml_tag": "ПризнакОперацияЭСП", "xml_path": "/СообщОперКО/ИнформЧасть/СведКо/Операция/ПризнакОперацияЭСП", + "source_scope": "any", + "allow_short_lookup": true, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "", + "structured_role": "", + "structured_order": 0, + "join_with_space": false, "multiplies": "нет", "required": "необязательно", "comment": "Числовое поле, может оставаться пустым и не поступать в XML" }, { "index": 16, + "column_id": "legacy_016", "column_name": "Наименование плат. системы на стороне лица соверш. операцию", + "block": "operation_base", + "report_group": "operation_parameters", "xml_tag": "НаимПлатежнаяСистема1", "xml_path": "/СообщОперКО/ИнформЧасть/СведКо/Операция/НаимПлатежнаяСистема1", + "source_scope": "any", + "allow_short_lookup": true, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "", + "structured_role": "", + "structured_order": 0, + "join_with_space": false, "multiplies": "нет", "required": "необязательно", "comment": "текстовое поле, может оставаться пустым и не поступать в XML" }, { "index": 17, + "column_id": "legacy_017", "column_name": "Наименование плат. системы на стороне получателя", + "block": "operation_base", + "report_group": "operation_parameters", "xml_tag": "НаимПлатежнаяСистема2", "xml_path": "/СообщОперКО/ИнформЧасть/СведКо/Операция/НаимПлатежнаяСистема2", + "source_scope": "any", + "allow_short_lookup": true, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "", + "structured_role": "", + "structured_order": 0, + "join_with_space": false, "multiplies": "нет", "required": "необязательно", "comment": "текстовое поле, может оставаться пустым и не поступать в XML" }, { "index": 18, + "column_id": "legacy_018", "column_name": "Время совершения транзакции с испол. ЭСП", + "block": "operation_base", + "report_group": "operation_parameters", "xml_tag": "ВремяТранзакцияЭСП", "xml_path": "/СообщОперКО/ИнформЧасть/СведКо/Операция/ВремяТранзакцияЭСП", + "source_scope": "any", + "allow_short_lookup": true, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "", + "structured_role": "", + "structured_order": 0, + "join_with_space": false, "multiplies": "нет", "required": "необязательно", "comment": "Указывается точное время операции Пример: 09:37:51 (МСК-01:00) (г. Калининград) ; 11:45:43 (МСК+03:00) (г. Омск) ; 10:50:40 (МСК+00:00) (г. Москва) ." }, { "index": 19, + "column_id": "legacy_019", "column_name": "Код вида операции", + "block": "operation_base", + "report_group": "operation_parameters", "xml_tag": "КодОперации", "xml_path": "/СообщОперКО/ИнформЧасть/СведКо/Операция/КодОперации", + "source_scope": "any", + "allow_short_lookup": true, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "", + "structured_role": "", + "structured_order": 0, + "join_with_space": false, "multiplies": "нет", "required": "необязательно", "comment": "Числовое поле" }, { "index": 20, + "column_id": "legacy_020", "column_name": "Доп. коды", + "block": "operation_base", + "report_group": "operation_parameters", "xml_tag": "ДопКодОперации", "xml_path": "/СообщОперКО/ИнформЧасть/СведКо/Операция/ДопКодОперации", + "source_scope": "any", + "allow_short_lookup": true, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "", + "structured_role": "", + "structured_order": 0, + "join_with_space": false, "multiplies": "Множится", "required": "необязательно", "comment": "Числовое поле, может оставаться пустым и не поступать в XML" }, { "index": 21, + "column_id": "legacy_021", "column_name": "Коды призн. необычной операции", + "block": "operation_base", + "report_group": "operation_parameters", "xml_tag": "ПризнНеобОперации", "xml_path": "/СообщОперКО/ИнформЧасть/СведКо/Операция/ПризнНеобОперации", + "source_scope": "any", + "allow_short_lookup": true, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "", + "structured_role": "", + "structured_order": 0, + "join_with_space": false, "multiplies": "Множится", "required": "необязательно", "comment": "Числовое поле, может оставаться пустым и не поступать в XML" }, { "index": 22, + "column_id": "legacy_022", "column_name": "Валюта", + "block": "operation_base", + "report_group": "operation_parameters", "xml_tag": "КодВал", "xml_path": "/СообщОперКО/ИнформЧасть/СведКо/Операция/КодВал", + "source_scope": "any", + "allow_short_lookup": true, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "", + "structured_role": "", + "structured_order": 0, + "join_with_space": false, "multiplies": "нет", "required": "необязательно", "comment": "Числовое поле, может оставаться пустым и не поступать в XML" }, { "index": 23, + "column_id": "legacy_023", "column_name": "Сумма в валюте проведения", + "block": "operation_base", + "report_group": "operation_parameters", "xml_tag": "СумОперации", "xml_path": "/СообщОперКО/ИнформЧасть/СведКо/Операция/СумОперации", + "source_scope": "any", + "allow_short_lookup": true, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "", + "structured_role": "", + "structured_order": 0, + "join_with_space": false, "multiplies": "нет", "required": "необязательно", "comment": "Числовое поле, допускаются не целые числа. может оставаться пустым и не поступать в XML" }, { "index": 24, + "column_id": "legacy_024", "column_name": "Сумма в рубл. эквиваленте", + "block": "operation_base", + "report_group": "operation_parameters", "xml_tag": "СумРуб", "xml_path": "/СообщОперКО/ИнформЧасть/СведКо/Операция/СумРуб", + "source_scope": "any", + "allow_short_lookup": true, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "", + "structured_role": "", + "structured_order": 0, + "join_with_space": false, "multiplies": "нет", "required": "необязательно", "comment": "Числовое поле, допускаются не целые числа. может оставаться пустым и не поступать в XML" }, { "index": 25, + "column_id": "legacy_025", "column_name": "Продаваемая валюта", + "block": "operation_base", + "report_group": "operation_parameters", "xml_tag": "КодВалКонверсия", "xml_path": "/СообщОперКО/ИнформЧасть/СведКо/Операция/КодВалКонверсия", + "source_scope": "any", + "allow_short_lookup": true, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "", + "structured_role": "", + "structured_order": 0, + "join_with_space": false, "multiplies": "множится", "required": "необязательно", "comment": "может оставаться пустым и не поступать в XML" }, { "index": 26, + "column_id": "legacy_026", "column_name": "Сумма прод. валюты в ед. соответ. валюты", + "block": "operation_base", + "report_group": "operation_parameters", "xml_tag": "СумКонверсия", "xml_path": "/СообщОперКО/ИнформЧасть/СведКо/Операция/СумКонверсия", + "source_scope": "any", + "allow_short_lookup": true, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "", + "structured_role": "", + "structured_order": 0, + "join_with_space": false, "multiplies": "нет", "required": "необязательно", "comment": "текстовый показатель, поле может остаться пустым и не поступать в XML" }, { "index": 27, + "column_id": "legacy_027", "column_name": "Признак валютной операции", + "block": "operation_base", + "report_group": "operation_parameters", "xml_tag": "ПризнВалОперации", "xml_path": "/СообщОперКО/ИнформЧасть/СведКо/Операция/ПризнВалОперации", + "source_scope": "any", + "allow_short_lookup": true, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "", + "structured_role": "", + "structured_order": 0, + "join_with_space": false, "multiplies": "нет", "required": "необязательно", "comment": "текстовый показатель, поле может остаться пустым и не поступать в XML" }, { "index": 28, + "column_id": "legacy_028", "column_name": "Идентификатор подозрительной деятельности", + "block": "operation_base", + "report_group": "operation_parameters", "xml_tag": "ИдентификаторПД", "xml_path": "/СообщОперКО/ИнформЧасть/СведКО/Операция/ИдентификаторПД", + "source_scope": "any", + "allow_short_lookup": true, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "", + "structured_role": "", + "structured_order": 0, + "join_with_space": false, "multiplies": "нет", "required": "обязательно", "comment": "Поле помечено как обязательное, но ни в одном XML и XSD его не нашла." }, { "index": 29, + "column_id": "legacy_029", "column_name": "Код драг. металла", + "block": "operation_base", + "report_group": "operation_parameters", "xml_tag": "КодДрагМеталл", "xml_path": "/СообщОперКО/ИнформЧасть/СведКО/Операция/СведДрагМеталл/КодДрагМеталл", + "source_scope": "any", + "allow_short_lookup": true, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "", + "structured_role": "", + "structured_order": 0, + "join_with_space": false, "multiplies": "нет", "required": "Обязательно", "comment": "Поле помечено как обязательное, но ни в одном XML и XSD его не нашла." }, { "index": 30, + "column_id": "legacy_030", "column_name": "Наименование металла", + "block": "operation_base", + "report_group": "operation_parameters", "xml_tag": "НаимДрагМеталл", "xml_path": "/СообщОперКО/ИнформЧасть/СведКО/Операция/СведДрагМеталл/НаимДрагМеталл", + "source_scope": "any", + "allow_short_lookup": true, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "", + "structured_role": "", + "structured_order": 0, + "join_with_space": false, "multiplies": "нет", "required": "необязательно", "comment": "поле может остаться пустым и не поступать в XML" }, { "index": 31, + "column_id": "legacy_031", "column_name": "Предмет купли-продажи", + "block": "operation_base", + "report_group": "operation_parameters", "xml_tag": "КодПредмет", "xml_path": "/СообщОперКО/ИнформЧасть/СведКО/Операция/СведДрагМеталл/КодПредмет", + "source_scope": "any", + "allow_short_lookup": true, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "", + "structured_role": "", + "structured_order": 0, + "join_with_space": false, "multiplies": "нет", "required": "необязательно", "comment": "поле может остаться пустым и не поступать в XML" }, { "index": 32, + "column_id": "legacy_032", "column_name": "Характеристика операции", + "block": "operation_base", + "report_group": "operation_parameters", "xml_tag": "ХарактерОп", "xml_path": "/СообщОперКО/ИнформЧасть/СведКО/Операция/ХарактерОп", + "source_scope": "any", + "allow_short_lookup": true, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "", + "structured_role": "", + "structured_order": 0, + "join_with_space": false, "multiplies": "нет", "required": "необязательно", "comment": "поле может остаться пустыми не поступать в XML" }, { "index": 33, + "column_id": "legacy_033", "column_name": "Назначение платежа", + "block": "operation_base", + "report_group": "operation_parameters", "xml_tag": "НазначениеПлатежа", "xml_path": "/СообщОперКО/ИнформЧасть/СведКО/Операция/НазначениеПлатежа", + "source_scope": "any", + "allow_short_lookup": true, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "", + "structured_role": "", + "structured_order": 0, + "join_with_space": false, "multiplies": "нет", "required": "необязательно", "comment": "поле может остаться пустыми не поступать в XML" }, { "index": 34, + "column_id": "legacy_034", "column_name": "Доп. сведения", + "block": "operation_base", + "report_group": "operation_parameters", "xml_tag": "КомментУчастник", "xml_path": "/СообщОперКО/ИнформЧасть/СведКО/Операция/УчастникОп/КомментУчастник", + "source_scope": "any", + "allow_short_lookup": true, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "", + "structured_role": "", + "structured_order": 0, + "join_with_space": false, "multiplies": "нет", "required": "необязательно", "comment": "текстовый показатель. Поле может оставаться пустым. и не поступать в XML" }, { "index": 35, + "column_id": "legacy_035", "column_name": "Вид перевода", + "block": "transfer", + "report_group": "operation_parameters", "xml_tag": "ВидПереводДС", "xml_path": "/СообщОперКО/ИнформЧасть/СведКО/Операция/СведенияПереводыДС/ВидПереводДС", + "source_scope": "any", + "allow_short_lookup": true, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "", + "structured_role": "", + "structured_order": 0, + "join_with_space": false, "multiplies": "нет", "required": "Обязательно", "comment": "числовой показатель" }, { "index": 36, + "column_id": "legacy_036", "column_name": "Код территории (5016)", + "block": "transfer", + "report_group": "operation_parameters", "xml_tag": "КодТерИнГос", "xml_path": "/СообщОперКО/ИнформЧасть/СведКО/Операция/СведенияПереводыДС/КодТерИнГос", + "source_scope": "any", + "allow_short_lookup": true, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "", + "structured_role": "", + "structured_order": 0, + "join_with_space": false, "multiplies": "нет", "required": "необязательно", "comment": "Числовой показатель, поле может остаться пустым и не поступать в XML" }, { "index": 37, + "column_id": "legacy_037", "column_name": "Тип оператора", + "block": "transfer", + "report_group": "transfer_settlement", "xml_tag": "ТипОператорДС", "xml_path": "/СообщОперКО/ИнформЧасть/СведКО/Операция/СведенияПереводыДС/ТипОператорДС", + "source_scope": "any", + "allow_short_lookup": true, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "", + "structured_role": "", + "structured_order": 0, + "join_with_space": false, "multiplies": "нет", "required": "Обязательно", "comment": "числовой показатель" }, { "index": 38, + "column_id": "legacy_038", "column_name": "Номер счета плательщика", + "block": "transfer", + "report_group": "transfer_settlement", "xml_tag": "НомерСчетПлательщик", "xml_path": "/СообщОперКО/ИнформЧасть/СведКО/Операция/СведенияПереводыДС/НомерСчетПлательщик", + "source_scope": "any", + "allow_short_lookup": true, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "", + "structured_role": "", + "structured_order": 0, + "join_with_space": false, "multiplies": "нет", "required": "необязательно", "comment": "Числовой показатель, поле может остаться пустым и не поступать в XML" }, { "index": 39, + "column_id": "legacy_039", "column_name": "Идентификатор ЭСП плательщика", + "block": "transfer", + "report_group": "transfer_settlement", "xml_tag": "ИдентЭСППлательщик", "xml_path": "/СообщОперКО/ИнформЧасть/СведКО/Операция/СведенияПереводыДС/ИдентЭСППлательщик", + "source_scope": "any", + "allow_short_lookup": true, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "", + "structured_role": "", + "structured_order": 0, + "join_with_space": false, "multiplies": "нет", "required": "необязательно", "comment": "Числовой показатель, поле может остаться пустым и не поступать в XML" }, { "index": 40, + "column_id": "legacy_040", "column_name": "Наименование банка плательщика", + "block": "transfer", + "report_group": "transfer_settlement", "xml_tag": "СведБанкПлательщик", "xml_path": "/СообщОперКО/ИнформЧасть/СведКО/Операция/СведенияПереводыДС/СведБанкПлательщик/НаимКО", + "source_scope": "any", + "allow_short_lookup": true, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "", + "structured_role": "", + "structured_order": 0, + "join_with_space": false, "multiplies": "нет", "required": "необязательно", "comment": "Данные передаются в XML в виде <НаимКО> АО \"АЛЬФА-БАНК\" в отчет заносятся в виде: Банк ВТБ (ПАО), филиал Филиал \"Центральный\" Банка ВТБ (ПАО)" }, { "index": 41, + "column_id": "legacy_041", "column_name": "БИК банка плательщика", + "block": "transfer", + "report_group": "transfer_settlement", "xml_tag": "БИККО", "xml_path": "/СообщОперКО/ИнформЧасть/СведКО/Операция/СведенияПереводыДС/СведБанкПлательщик/БИККО", + "source_scope": "operation", + "allow_short_lookup": false, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "", + "structured_role": "", + "structured_order": 0, + "join_with_space": false, "multiplies": "нет", "required": "необязательно", "comment": "Данные передаются в XML в виде: <БИККО> 044525593 в отчет заносятся в виде: 044525411" }, { "index": 42, + "column_id": "legacy_042", "column_name": "Наименование банка получателя", + "block": "transfer", + "report_group": "transfer_settlement", "xml_tag": "СведБанкПолучатель", "xml_path": "/СообщОперКО/ИнформЧасть/СведКО/Операция/СведенияПереводыДС/СведБанкПолучатель/НаимКО", + "source_scope": "any", + "allow_short_lookup": true, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "", + "structured_role": "", + "structured_order": 0, + "join_with_space": false, "multiplies": "нет", "required": "необязательно", "comment": "Числовой показатель, поле может остаться пустым и не поступать в XML" }, { "index": 43, + "column_id": "legacy_043", "column_name": "БИК банка получателя", + "block": "transfer", + "report_group": "transfer_settlement", "xml_tag": "БИККО", "xml_path": "/СообщОперКО/ИнформЧасть/СведКО/Операция/СведенияПереводыДС/СведБанкПолучатель/БИККО", + "source_scope": "operation", + "allow_short_lookup": false, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "", + "structured_role": "", + "structured_order": 0, + "join_with_space": false, "multiplies": "нет", "required": "необязательно", "comment": "Числовой показатель, поле может остаться пустым и не поступать в XML" }, { "index": 44, + "column_id": "legacy_044", "column_name": "Номер счета банка плательщика", + "block": "transfer", + "report_group": "transfer_settlement", "xml_tag": "СчетБанкПлательщик", "xml_path": "/СообщОперКО/ИнформЧасть/СведКО/Операция/СведенияПереводыДС/СчетБанкПлательщик", + "source_scope": "any", + "allow_short_lookup": true, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "", + "structured_role": "", + "structured_order": 0, + "join_with_space": false, "multiplies": "нет", "required": "необязательно", "comment": "Данные передаются в XML в виде: <СчетБанкПлательщик> 30101810300000000711 в отчет заносятся в виде: 30101810300000000711" }, { "index": 45, + "column_id": "legacy_045", "column_name": "Номер счета банка получателя", + "block": "transfer", + "report_group": "transfer_settlement", "xml_tag": "СчетБанкПолучатель", "xml_path": "/СообщОперКО/ИнформЧасть/СведКО/Операция/СведенияПереводыДС/СчетБанкПолучатель", + "source_scope": "any", + "allow_short_lookup": true, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "", + "structured_role": "", + "structured_order": 0, + "join_with_space": false, "multiplies": "нет", "required": "необязательно", "comment": "Данные передаются в XML в виде: <СчетБанкПолучатель> 30101810200000000704 в отчет заносятся в виде: 30101810200000000704" }, { "index": 46, + "column_id": "legacy_046", "column_name": "Номер счета получателя", + "block": "transfer", + "report_group": "transfer_settlement", "xml_tag": "НомерСчетПолучатель", "xml_path": "/СообщОперКО/ИнформЧасть/СведКО/Операция/СведенияПереводыДС/НомерСчетПолучатель", + "source_scope": "any", + "allow_short_lookup": true, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "", + "structured_role": "", + "structured_order": 0, + "join_with_space": false, "multiplies": "нет", "required": "необязательно", "comment": "Данные передаются в XML в виде: <НомерСчетПолучатель> 40703810000000000000 в отчет заносятся в виде: 40703810000000000000" }, { "index": 47, + "column_id": "legacy_047", "column_name": "Идентификатор ЭСП получателя", + "block": "transfer", + "report_group": "transfer_settlement", "xml_tag": "ИдентЭСППолучателя", "xml_path": "/СообщОперКО/ИнформЧасть/СведКО/Операция/СведенияПереводыДС/ИдентЭСППолучателя", + "source_scope": "any", + "allow_short_lookup": true, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "", + "structured_role": "", + "structured_order": 0, + "join_with_space": false, "multiplies": "нет", "required": "необязательно", "comment": "Числовой показатель, поле может остаться пустым и не поступать в XML" }, { "index": 48, + "column_id": "legacy_048", "column_name": "Номер банкомата", + "block": "cash_receipt", + "report_group": "transfer_settlement", "xml_tag": "ИдТерминал", "xml_path": "/СообщОперКО/ИнформЧасть/СведКО/Операция/СведенияПереводыДс/СведПриемНалДС/ИдТерминал", + "source_scope": "any", + "allow_short_lookup": true, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "", + "structured_role": "", + "structured_order": 0, + "join_with_space": false, "multiplies": "нет", "required": "необязательно", "comment": "Числовой показатель, поле может остаться пустым и не передаваться в XML" }, { "index": 49, + "column_id": "legacy_049", "column_name": "Адрес места приема наличных денежных средств(в одной строке)", + "block": "cash_receipt", + "report_group": "cash_receipt_authorization", "xml_tag": "АдрМестаПриемаВыдача", "xml_path": "/СообщОперКО/ИнформЧасть/СведКО/Операция/СведенияПереводыДс/СведПриемНалДС/АдрМестоПриемаВыдача/АдресСтрока", + "source_scope": "any", + "allow_short_lookup": false, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "legacy_050", + "structured_role": "one_line", + "structured_order": 1, + "join_with_space": false, "multiplies": "нет", "required": "необязательно", "comment": "текстовый показатель, поле может остаться пустым и не передаваться в XML" }, { "index": 50, + "column_id": "legacy_050", "column_name": "Адрес места приема (по структуре полный)", + "block": "cash_receipt", + "report_group": "cash_receipt_authorization", "xml_tag": "АдрМестаПриемаВыдача", "xml_path": "/СообщОперКО/ИнформЧасть/СведКО/Операция/СведенияПереводыДс/СведПриемНалДС/АдрМестоПриемаВыдача/АдресСтрока", + "source_scope": "any", + "allow_short_lookup": true, + "allow_direct_mapping": true, + "structured_value": true, + "structured_group": "legacy_050", + "structured_role": "aggregate", + "structured_order": 0, + "join_with_space": false, "multiplies": "нет", "required": "необязательно", "comment": "текстовый показатель, поле может остаться пустым и не передаваться в XML Чем они отличаются?" }, { "index": 51, + "column_id": "legacy_051", "column_name": "Индекс", + "block": "cash_receipt", + "report_group": "cash_receipt_authorization", "xml_tag": "АдрМестаПриемаВыдача", "xml_path": "/СообщОперКО/ИнформЧасть/СведКО/Операция/СведенияПереводыДс/СведПриемНалДС/АдрМестоПриемаВыдача/Индекс", + "source_scope": "any", + "allow_short_lookup": false, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "legacy_050", + "structured_role": "component", + "structured_order": 1, + "join_with_space": false, "multiplies": "нет", "required": "необязательно", "comment": "Числовой показатель, поле может остаться пустым и не передаваться в XML" }, { "index": 52, + "column_id": "legacy_052", "column_name": "Код страны", + "block": "cash_receipt", + "report_group": "cash_receipt_authorization", "xml_tag": "АдрМестаПриемаВыдача", "xml_path": "/СообщОперКО/ИнформЧасть/СведКО/Операция/СведенияПереводыДс/СведПриемНалДС/АдрМестоПриемаВыдача/КодОКСМ", + "source_scope": "any", + "allow_short_lookup": false, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "legacy_050", + "structured_role": "component", + "structured_order": 2, + "join_with_space": false, "multiplies": "нет", "required": "необязательно", "comment": "Числовой показатель, поле может остаться пустым и не передаваться в XML" }, { "index": 53, + "column_id": "legacy_053", "column_name": "Код ОКАТО", + "block": "cash_receipt", + "report_group": "cash_receipt_authorization", "xml_tag": "АдрМестаПриемаВыдача", "xml_path": "/СообщОперКО/ИнформЧасть/СведКО/Операция/СведенияПереводыДс/СведПриемНалДС/АдрМестоПриемаВыдача/КодСубъектаПоОКАТО", + "source_scope": "any", + "allow_short_lookup": false, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "legacy_050", + "structured_role": "component", + "structured_order": 3, + "join_with_space": false, "multiplies": "нет", "required": "необязательно", "comment": "Числовой показатель, поле может остаться пустым и не передаваться в XML" }, { "index": 54, + "column_id": "legacy_054", "column_name": "Район", + "block": "cash_receipt", + "report_group": "cash_receipt_authorization", "xml_tag": "АдрМестаПриемаВыдача", "xml_path": "/СообщОперКО/ИнформЧасть/СведКО/Операция/СведенияПереводыДс/СведПриемНалДС/АдрМестоПриемаВыдача/Район", + "source_scope": "any", + "allow_short_lookup": false, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "legacy_050", + "structured_role": "component", + "structured_order": 4, + "join_with_space": false, "multiplies": "нет", "required": "необязательно", "comment": "Текстовый показатель, поле может остаться пустым и не передаваться в XML" }, { "index": 55, + "column_id": "legacy_055", "column_name": "Населенный пункт", + "block": "cash_receipt", + "report_group": "cash_receipt_authorization", "xml_tag": "АдрМестаПриемаВыдача", "xml_path": "/СообщОперКО/ИнформЧасть/СведКО/Операция/СведенияПереводыДс/СведПриемНалДС/АдрМестоПриемаВыдача/Пункт", + "source_scope": "any", + "allow_short_lookup": false, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "legacy_050", + "structured_role": "component", + "structured_order": 5, + "join_with_space": false, "multiplies": "нет", "required": "необязательно", "comment": "Текстовый показатель, поле может остаться пустым и не передаваться в XML" }, { "index": 56, + "column_id": "legacy_056", "column_name": "Улица", + "block": "cash_receipt", + "report_group": "cash_receipt_authorization", "xml_tag": "АдрМестаПриемаВыдача", "xml_path": "/СообщОперКО/ИнформЧасть/СведКО/Операция/СведенияПереводыДс/СведПриемНалДС/АдрМестоПриемаВыдача/Улица", + "source_scope": "any", + "allow_short_lookup": false, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "legacy_050", + "structured_role": "component", + "structured_order": 6, + "join_with_space": false, "multiplies": "нет", "required": "необязательно", "comment": "Текстовый показатель, поле может остаться пустым и не передаваться в XML" }, { "index": 57, + "column_id": "legacy_057", "column_name": "Дом", + "block": "cash_receipt", + "report_group": "cash_receipt_authorization", "xml_tag": "АдрМестаПриемаВыдача", "xml_path": "/СообщОперКО/ИнформЧасть/СведКО/Операция/СведенияПереводыДс/СведПриемНалДС/АдрМестоПриемаВыдача/Дом", + "source_scope": "any", + "allow_short_lookup": false, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "legacy_050", + "structured_role": "component", + "structured_order": 7, + "join_with_space": false, "multiplies": "нет", "required": "необязательно", "comment": "Текстовый показатель, поле может остаться пустым и не передаваться в XML" }, { "index": 58, + "column_id": "legacy_058", "column_name": "Корпус/строение", + "block": "cash_receipt", + "report_group": "cash_receipt_authorization", "xml_tag": "АдрМестаПриемаВыдача", "xml_path": "/СообщОперКО/ИнформЧасть/СведКО/Операция/СведенияПереводыДс/СведПриемНалДС/АдрМестоПриемаВыдача/Корп", + "source_scope": "any", + "allow_short_lookup": false, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "legacy_050", + "structured_role": "component", + "structured_order": 8, + "join_with_space": false, "multiplies": "нет", "required": "необязательно", "comment": "Текстовый показатель, поле может остаться пустым и не передаваться в XML" }, { "index": 59, + "column_id": "legacy_059", "column_name": "Офис/Квартира", + "block": "cash_receipt", + "report_group": "cash_receipt_authorization", "xml_tag": "АдрМестаПриемаВыдача", "xml_path": "/СообщОперКО/ИнформЧасть/СведКО/Операция/СведенияПереводыДс/СведПриемНалДС/АдрМестоПриемаВыдача/Оф", + "source_scope": "any", + "allow_short_lookup": false, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "legacy_050", + "structured_role": "component", + "structured_order": 9, + "join_with_space": false, "multiplies": "нет", "required": "необязательно", "comment": "Числовой показатель, поле может остаться пустым и не передаваться в XML" }, { "index": 60, + "column_id": "legacy_060", "column_name": "Наименование банка, обслуживающего участника операции", + "block": "cash_receipt", + "report_group": "cash_receipt_authorization", "xml_tag": "НаимКО", "xml_path": "/СообщОперКО/ИнформЧасть/СведКО/Операция/СведенияПереводыДс/СведПриемНалДС/НаимКО", + "source_scope": "any", + "allow_short_lookup": false, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "", + "structured_role": "", + "structured_order": 0, + "join_with_space": false, "multiplies": "нет", "required": "необязательно", "comment": "Текстовый показатель, поле может остаться пустым и не передаваться в XML" }, { "index": 61, + "column_id": "legacy_061", "column_name": "БИК банка, обслуживающего участника операции", + "block": "cash_receipt", + "report_group": "cash_receipt_authorization", "xml_tag": "БИККО", "xml_path": "/СообщОперКО/ИнформЧасть/СведКО/Операция/СведенияПереводыДс/СведПриемНалДС/БИККО", + "source_scope": "any", + "allow_short_lookup": false, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "", + "structured_role": "", + "structured_order": 0, + "join_with_space": false, "multiplies": "нет", "required": "Обязательно", "comment": "Числовой показатель" }, { "index": 62, + "column_id": "legacy_062", "column_name": "Статус перевода", + "block": "transfer_status", + "report_group": "cash_receipt_authorization", "xml_tag": "СтатусПеревод", "xml_path": "/СообщОперКО/ИнформЧасть/СведКО/Операция/СведенияПереводыДс/СтатусПеревод", + "source_scope": "any", + "allow_short_lookup": false, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "", + "structured_role": "", + "structured_order": 0, + "join_with_space": false, "multiplies": "нет", "required": "необязательно", "comment": "Текстовый показатель, поле может остаться пустым. Не нашла в XML" }, { "index": 63, + "column_id": "legacy_063", "column_name": "Номер банкомата", + "block": "cash_payment", + "report_group": "cash_receipt_authorization", "xml_tag": "ИдТерминал", "xml_path": "/СообщОперКО/ИнформЧасть/СведКО/Операция/СведенияПереводыДс/СведВыдачаНалДС/ИдТерминал", + "source_scope": "any", + "allow_short_lookup": false, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "", + "structured_role": "", + "structured_order": 0, + "join_with_space": false, "multiplies": "нет", "required": "необязательно", "comment": "Текстовый показатель, поле может остаться пустым и не передаваться в XML" }, { "index": 64, + "column_id": "legacy_064", "column_name": "Адрес места выдачи наличных денежных средств ( в одной строке)", + "block": "cash_payment", + "report_group": "cash_receipt_authorization", "xml_tag": "АдрМестаПриемаВыдача", "xml_path": "/СообщОперКО/ИнформЧасть/СведКО/Операция/СведенияПереводыДС/СведВыдачаНалДС/АдрМестаПриемаВыдача/АдресСтрока", + "source_scope": "any", + "allow_short_lookup": false, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "legacy_065", + "structured_role": "one_line", + "structured_order": 1, + "join_with_space": false, "multiplies": "нет", "required": "необязательно", "comment": "текстовый показатель, поле может остаться пустым и не передаваться в XML" }, { "index": 65, + "column_id": "legacy_065", "column_name": "Адрес места выдачи (по структуре полный)", + "block": "cash_payment", + "report_group": "cash_receipt_authorization", "xml_tag": "АдрМестаПриемаВыдача", "xml_path": "/СообщОперКО/ИнформЧасть/СведКО/Операция/СведенияПереводыДС/СведВыдачаНалДС/АдрМестаПриемаВыдача/АдресСтрока", + "source_scope": "any", + "allow_short_lookup": true, + "allow_direct_mapping": true, + "structured_value": true, + "structured_group": "legacy_065", + "structured_role": "aggregate", + "structured_order": 0, + "join_with_space": false, "multiplies": "нет", "required": "необязательно", "comment": "текстовый показатель, поле может остаться пустым и не передаваться в XML Чем они отличаются?" }, { "index": 66, + "column_id": "legacy_066", "column_name": "Индекс", + "block": "cash_payment", + "report_group": "cash_receipt_authorization", "xml_tag": "АдрМестаПриемаВыдача", "xml_path": "/СообщОперКО/ИнформЧасть/СведКО/Операция/СведенияПереводыДС/СведВыдачаНалДС/АдрМестаПриемаВыдача/Индекс", + "source_scope": "any", + "allow_short_lookup": false, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "legacy_065", + "structured_role": "component", + "structured_order": 1, + "join_with_space": false, "multiplies": "нет", "required": "необязательно", "comment": "Числовой показатель, поле может остаться пустым и не передаваться в XML" }, { "index": 67, + "column_id": "legacy_067", "column_name": "Код страны", + "block": "cash_payment", + "report_group": "same_operator_place", "xml_tag": "АдрМестаПриемаВыдача", "xml_path": "/СообщОперКО/ИнформЧасть/СведКО/Операция/СведенияПереводыДС/СведВыдачаНалДС/АдрМестаПриемаВыдача/КодОКСМ", + "source_scope": "any", + "allow_short_lookup": false, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "legacy_065", + "structured_role": "component", + "structured_order": 2, + "join_with_space": false, "multiplies": "нет", "required": "необязательно", "comment": "Числовой показатель, поле может остаться пустым и не передаваться в XML" }, { "index": 68, + "column_id": "legacy_068", "column_name": "Код ОКАТО", + "block": "cash_payment", + "report_group": "same_operator_place", "xml_tag": "АдрМестаПриемаВыдача", "xml_path": "/СообщОперКО/ИнформЧасть/СведКО/Операция/СведенияПереводыДС/СведВыдачаНалДС/АдрМестаПриемаВыдача/КодСубъектаПоОКАТО", + "source_scope": "any", + "allow_short_lookup": false, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "legacy_065", + "structured_role": "component", + "structured_order": 3, + "join_with_space": false, "multiplies": "нет", "required": "необязательно", "comment": "Числовой показатель, поле может остаться пустым и не передаваться в XML" }, { "index": 69, + "column_id": "legacy_069", "column_name": "Район", + "block": "cash_payment", + "report_group": "same_operator_place", "xml_tag": "АдрМестаПриемаВыдача", "xml_path": "/СообщОперКО/ИнформЧасть/СведКО/Операция/СведенияПереводыДС/СведВыдачаНалДС/АдрМестаПриемаВыдача/Район", + "source_scope": "any", + "allow_short_lookup": false, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "legacy_065", + "structured_role": "component", + "structured_order": 4, + "join_with_space": false, "multiplies": "нет", "required": "необязательно", "comment": "Текстовый показатель, поле может остаться пустым и не передаваться в XML" }, { "index": 70, + "column_id": "legacy_070", "column_name": "Населенный пункт", + "block": "cash_payment", + "report_group": "same_operator_place", "xml_tag": "АдрМестаПриемаВыдача", "xml_path": "/СообщОперКО/ИнформЧасть/СведКО/Операция/СведенияПереводыДС/СведВыдачаНалДС/АдрМестаПриемаВыдача/Пункт", + "source_scope": "any", + "allow_short_lookup": false, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "legacy_065", + "structured_role": "component", + "structured_order": 5, + "join_with_space": false, "multiplies": "нет", "required": "необязательно", "comment": "Текстовый показатель, поле может остаться пустым и не передаваться в XML" }, { "index": 71, + "column_id": "legacy_071", "column_name": "Улица", + "block": "cash_payment", + "report_group": "same_operator_place", "xml_tag": "АдрМестаПриемаВыдача", "xml_path": "/СообщОперКО/ИнформЧасть/СведКО/Операция/СведенияПереводыДС/СведВыдачаНалДС/АдрМестаПриемаВыдача/Улица", + "source_scope": "any", + "allow_short_lookup": false, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "legacy_065", + "structured_role": "component", + "structured_order": 6, + "join_with_space": false, "multiplies": "нет", "required": "необязательно", "comment": "Текстовый показатель, поле может остаться пустым и не передаваться в XML" }, { "index": 72, + "column_id": "legacy_072", "column_name": "Дом", + "block": "cash_payment", + "report_group": "same_operator_place", "xml_tag": "АдрМестаПриемаВыдача", "xml_path": "/СообщОперКО/ИнформЧасть/СведКО/Операция/СведенияПереводыДС/СведВыдачаНалДС/АдрМестаПриемаВыдача/Дом", + "source_scope": "any", + "allow_short_lookup": false, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "legacy_065", + "structured_role": "component", + "structured_order": 7, + "join_with_space": false, "multiplies": "нет", "required": "необязательно", "comment": "Текстовый показатель, поле может остаться пустым и не передаваться в XML" }, { "index": 73, + "column_id": "legacy_073", "column_name": "Корпус/строение", + "block": "cash_payment", + "report_group": "same_operator_place", "xml_tag": "АдрМестаПриемаВыдача", "xml_path": "/СообщОперКО/ИнформЧасть/СведКО/Операция/СведенияПереводыДС/СведВыдачаНалДС/АдрМестаПриемаВыдача/Корп", + "source_scope": "any", + "allow_short_lookup": false, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "legacy_065", + "structured_role": "component", + "structured_order": 8, + "join_with_space": false, "multiplies": "нет", "required": "необязательно", "comment": "Текстовый показатель, поле может остаться пустым и не передаваться в XML" }, { "index": 74, + "column_id": "legacy_074", "column_name": "Офис/Квартира", - "xml_tag": "АдрМестаПриемаВыдача", + "block": "cash_payment", + "report_group": "same_operator_place", + "xml_tag": "АдрМестаПриемаВыдача", "xml_path": "/СообщОперКО/ИнформЧасть/СведКО/Операция/СведенияПереводыДС/СведВыдачаНалДС/АдрМестаПриемаВыдача/Оф", + "source_scope": "any", + "allow_short_lookup": false, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "legacy_065", + "structured_role": "component", + "structured_order": 9, + "join_with_space": false, "multiplies": "нет", "required": "необязательно", "comment": "Числовой показатель, поле может остаться пустым и не передаваться в XML" }, { "index": 75, + "column_id": "legacy_075", "column_name": "Наименование банка, обслуживающего участника операции", + "block": "cash_payment", + "report_group": "same_operator_place", "xml_tag": "НаимКО", "xml_path": "/СообщОперКО/ИнформЧасть/СведКО/Операция/СведенияПереводыДС/СведВыдачаНалДС/НаимКО", + "source_scope": "any", + "allow_short_lookup": false, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "", + "structured_role": "", + "structured_order": 0, + "join_with_space": false, "multiplies": "нет", "required": "необязательно", "comment": "Текстовый показатель, поле может остаться пустым и не передаваться в XML" }, { "index": 76, + "column_id": "legacy_076", "column_name": "БИК банка, обслуживающего участника операции", + "block": "cash_payment", + "report_group": "cash_form_basis", "xml_tag": "БИККО", "xml_path": "/СообщОперКО/ИнформЧасть/СведКО/Операция/СведенияПереводыДС/СведВыдачаНалДС/БИККО", + "source_scope": "any", + "allow_short_lookup": false, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "", + "structured_role": "", + "structured_order": 0, + "join_with_space": false, "multiplies": "нет", "required": "Обязательно", "comment": "Числовой показатель" }, { "index": 77, + "column_id": "legacy_077", "column_name": "IP-адрес сетевого оборудования плательщика", + "block": "network", + "report_group": "cash_form_basis", "xml_tag": "АдресIP", "xml_path": "/СообщОперКО/ИнформЧасть/СведКО/Операция/СведенияПереводыДС/АдресIP", + "source_scope": "any", + "allow_short_lookup": false, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "", + "structured_role": "", + "structured_order": 0, + "join_with_space": false, "multiplies": "нет", "required": "необязательно", "comment": "Числовой показатель, поле может остаться пустым и не передаваться в XML" }, { "index": 78, + "column_id": "legacy_078", "column_name": "MAC-адрес сетевого оборудования плательщика", + "block": "network", + "report_group": "cash_form_basis", "xml_tag": "АдресMAC", "xml_path": "/СообщОперКО/ИнформЧасть/СведКО/Операция/СведенияПереводыДС/АдресMAC", + "source_scope": "any", + "allow_short_lookup": false, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "", + "structured_role": "", + "structured_order": 0, + "join_with_space": false, "multiplies": "нет", "required": "необязательно", "comment": "Числовой показатель, поле может остаться пустым и не передаваться в XML" }, { "index": 79, + "column_id": "legacy_079", "column_name": "Код характера операции", + "block": "cash_operation", + "report_group": "cash_form_basis", "xml_tag": "КодХарактерОп", "xml_path": "/СообщОперКО/ИнформЧасть/СведКО/Операция/СведенияВнесениеПолучениеНалДС/КодХарактерОп", + "source_scope": "any", + "allow_short_lookup": false, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "", + "structured_role": "", + "structured_order": 0, + "join_with_space": false, "multiplies": "нет", "required": "обязательное", "comment": "Числовой показатель" }, { "index": 80, + "column_id": "legacy_080", "column_name": "Номер счета клиента", + "block": "cash_operation", + "report_group": "cash_form_basis", "xml_tag": "НомерСчетКлиент", "xml_path": "/СообщОперКО/ИнформЧасть/СведКО/Операция/СведенияВнесениеПолучениеНалДС/НомерСчетКлиент", + "source_scope": "any", + "allow_short_lookup": false, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "", + "structured_role": "", + "structured_order": 0, + "join_with_space": false, "multiplies": "нет", "required": "обязательное", "comment": "Числовой показатель" }, { "index": 81, + "column_id": "legacy_081", "column_name": "Номер платежной карты", + "block": "cash_operation", + "report_group": "cash_form_basis", "xml_tag": "НомерКарта", "xml_path": "/СообщОперКО/ИнформЧасть/СведКО/Операция/СведенияВнесениеПолучениеНалДС/НомерКарта", + "source_scope": "any", + "allow_short_lookup": false, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "", + "structured_role": "", + "structured_order": 0, + "join_with_space": false, "multiplies": "нет", "required": "необязательно", "comment": "Показатель в XML передается зашифрованными ***************, в отчет попадают цифры" }, { "index": 82, + "column_id": "legacy_082", "column_name": "Номер банкомата", + "block": "cash_operation", + "report_group": "cash_form_basis", "xml_tag": "ИдТерминал", "xml_path": "/СообщОперКО/ИнформЧасть/СведКО/Операция/СведенияВнесениеПолучениеНалДС/СведПриемВыдача/ИдТерминал", + "source_scope": "any", + "allow_short_lookup": false, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "", + "structured_role": "", + "structured_order": 0, + "join_with_space": false, "multiplies": "нет", "required": "необязательно", "comment": "Числовой показатель, поле может остаться пустым и не передаваться в XML" }, { "index": 83, + "column_id": "legacy_083", "column_name": "Адрес места приема наличных денежных средств ( в одной строке)", + "block": "cash_operation", + "report_group": "cash_form_basis", "xml_tag": "АдрМестаПриемаВыдача", "xml_path": "/СообщОперКО/ИнформЧасть/СведКО/Операция/СведенияВнесениеПолучениеНалДС/СведПриемВыдача/АдрМестаПриемаВыдача/АдресСтрока", + "source_scope": "any", + "allow_short_lookup": false, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "legacy_084", + "structured_role": "one_line", + "structured_order": 1, + "join_with_space": false, "multiplies": "нет", "required": "необязательно", "comment": "текстовый показатель, поле может остаться пустым и не передаваться в XML" }, { "index": 84, + "column_id": "legacy_084", "column_name": "Адрес места приема (по структуре полный)", + "block": "cash_operation", + "report_group": "cash_form_basis", "xml_tag": "АдрМестаПриемаВыдача", "xml_path": "/СообщОперКО/ИнформЧасть/СведКО/Операция/СведенияВнесениеПолучениеНалДС/СведПриемВыдача/АдрМестаПриемаВыдача/АдресСтрока", + "source_scope": "any", + "allow_short_lookup": true, + "allow_direct_mapping": true, + "structured_value": true, + "structured_group": "legacy_084", + "structured_role": "aggregate", + "structured_order": 0, + "join_with_space": false, "multiplies": "нет", "required": "необязательно", "comment": "текстовый показатель, поле может остаться пустым и не передаваться в XML Чем они отличаются?" }, { "index": 85, + "column_id": "legacy_085", "column_name": "Индекс", + "block": "cash_operation", + "report_group": "cash_form_basis", "xml_tag": "АдрМестаПриемаВыдача", "xml_path": "/СообщОперКО/ИнформЧасть/СведКО/Операция/СведенияВнесениеПолучениеНалДС/СведПриемВыдача/АдрМестаПриемаВыдача/Индекс", + "source_scope": "any", + "allow_short_lookup": false, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "legacy_084", + "structured_role": "component", + "structured_order": 1, + "join_with_space": false, "multiplies": "нет", "required": "необязательно", "comment": "Числовой показатель, поле может остаться пустым и не передаваться в XML" }, { "index": 86, + "column_id": "legacy_086", "column_name": "Код страны", + "block": "cash_operation", + "report_group": "cash_form_basis", "xml_tag": "АдрМестаПриемаВыдача", "xml_path": "/СообщОперКО/ИнформЧасть/СведКО/Операция/СведенияВнесениеПолучениеНалДС/СведПриемВыдача/АдрМестаПриемаВыдача/КодОКСМ", + "source_scope": "any", + "allow_short_lookup": false, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "legacy_084", + "structured_role": "component", + "structured_order": 2, + "join_with_space": false, "multiplies": "нет", "required": "необязательно", "comment": "Числовой показатель, поле может остаться пустым и не передаваться в XML" }, { "index": 87, + "column_id": "legacy_087", "column_name": "Код ОКАТО", + "block": "cash_operation", + "report_group": "participant_base", "xml_tag": "АдрМестаПриемаВыдача", "xml_path": "/СообщОперКО/ИнформЧасть/СведКО/Операция/СведенияВнесениеПолучениеНалДС/СведПриемВыдача/АдрМестаПриемаВыдача/КодСубъектаПоОКАТО", + "source_scope": "any", + "allow_short_lookup": false, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "legacy_084", + "structured_role": "component", + "structured_order": 3, + "join_with_space": false, "multiplies": "нет", "required": "необязательно", "comment": "Числовой показатель, поле может остаться пустым и не передаваться в XML" }, { "index": 88, + "column_id": "legacy_088", "column_name": "Район", + "block": "cash_operation", + "report_group": "participant_base", "xml_tag": "АдрМестаПриемаВыдача", "xml_path": "/СообщОперКО/ИнформЧасть/СведКО/Операция/СведенияВнесениеПолучениеНалДС/СведПриемВыдача/АдрМестаПриемаВыдача/Район", + "source_scope": "any", + "allow_short_lookup": false, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "legacy_084", + "structured_role": "component", + "structured_order": 4, + "join_with_space": false, "multiplies": "нет", "required": "необязательно", "comment": "Текстовый показатель, поле может остаться пустым и не передаваться в XML" }, { "index": 89, + "column_id": "legacy_089", "column_name": "Населенный пункт", + "block": "cash_operation", + "report_group": "participant_base", "xml_tag": "АдрМестаПриемаВыдача", "xml_path": "/СообщОперКО/ИнформЧасть/СведКО/Операция/СведенияВнесениеПолучениеНалДС/СведПриемВыдача/АдрМестаПриемаВыдача/Пункт", + "source_scope": "any", + "allow_short_lookup": false, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "legacy_084", + "structured_role": "component", + "structured_order": 5, + "join_with_space": false, "multiplies": "нет", "required": "необязательно", "comment": "Текстовый показатель, поле может остаться пустым и не передаваться в XML" }, { "index": 90, + "column_id": "legacy_090", "column_name": "Улица", + "block": "cash_operation", + "report_group": "participant_base", "xml_tag": "АдрМестаПриемаВыдача", "xml_path": "/СообщОперКО/ИнформЧасть/СведКО/Операция/СведенияВнесениеПолучениеНалДС/СведПриемВыдача/АдрМестаПриемаВыдача/Улица", + "source_scope": "any", + "allow_short_lookup": false, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "legacy_084", + "structured_role": "component", + "structured_order": 6, + "join_with_space": false, "multiplies": "нет", "required": "необязательно", "comment": "Текстовый показатель, поле может остаться пустым и не передаваться в XML" }, { "index": 91, + "column_id": "legacy_091", "column_name": "Дом", + "block": "cash_operation", + "report_group": "participant_base", "xml_tag": "АдрМестаПриемаВыдача", "xml_path": "/СообщОперКО/ИнформЧасть/СведКО/Операция/СведенияВнесениеПолучениеНалДС/СведПриемВыдача/АдрМестаПриемаВыдача/Дом", + "source_scope": "any", + "allow_short_lookup": false, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "legacy_084", + "structured_role": "component", + "structured_order": 7, + "join_with_space": false, "multiplies": "нет", "required": "необязательно", "comment": "Текстовый показатель, поле может остаться пустым и не передаваться в XML" }, { "index": 92, + "column_id": "legacy_092", "column_name": "Корпус/строение", + "block": "cash_operation", + "report_group": "participant_base", "xml_tag": "АдрМестаПриемаВыдача", "xml_path": "/СообщОперКО/ИнформЧасть/СведКО/Операция/СведенияВнесениеПолучениеНалДС/СведПриемВыдача/АдрМестаПриемаВыдача/Корп", + "source_scope": "any", + "allow_short_lookup": false, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "legacy_084", + "structured_role": "component", + "structured_order": 8, + "join_with_space": false, "multiplies": "нет", "required": "необязательно", "comment": "Текстовый показатель, поле может остаться пустым и не передаваться в XML" }, { "index": 93, + "column_id": "legacy_093", "column_name": "Офис/Квартира", + "block": "cash_operation", + "report_group": "participant_base", "xml_tag": "АдрМестаПриемаВыдача", "xml_path": "/СообщОперКО/ИнформЧасть/СведКО/Операция/СведенияВнесениеПолучениеНалДС/СведПриемВыдача/АдрМестаПриемаВыдача/Оф", + "source_scope": "any", + "allow_short_lookup": false, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "legacy_084", + "structured_role": "component", + "structured_order": 9, + "join_with_space": false, "multiplies": "нет", "required": "необязательно", "comment": "Числовой показатель, поле может остаться пустым и не передаваться в XML" }, { "index": 94, + "column_id": "legacy_094", "column_name": "Наименование банка, обслуживающего участника операции", + "block": "cash_operation", + "report_group": "participant_base", "xml_tag": "НаимКО", "xml_path": "/СообщОперКО/ИнформЧасть/СведКО/Операция/СведенияВнесениеПолучениеНалДС/СведПриемВыдача/НаимКО", + "source_scope": "any", + "allow_short_lookup": false, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "", + "structured_role": "", + "structured_order": 0, + "join_with_space": false, "multiplies": "нет", "required": "необязательно", "comment": "Текстовый показатель, поле может остаться пустым и не передаваться в XML" }, { "index": 95, + "column_id": "legacy_095", "column_name": "БИК банка, обслуживающего участника операции", + "block": "cash_operation", + "report_group": "participant_base", "xml_tag": "БИККО", "xml_path": "/СообщОперКО/ИнформЧасть/СведКО/Операция/СведенияВнесениеПолучениеНалДС/СведПриемВыдача/БИККО", + "source_scope": "any", + "allow_short_lookup": false, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "", + "structured_role": "", + "structured_order": 0, + "join_with_space": false, "multiplies": "нет", "required": "Обязательно", "comment": "Числовой показатель" }, { "index": 96, + "column_id": "legacy_096", "column_name": "Код территории", + "block": "cash_operation", + "report_group": "participant_base", "xml_tag": "КодТерИнГос", "xml_path": "/СообщОперКО/ИнформЧасть/СведКО/Операция/СведенияВнесениеПолучениеНалДС/КодТерИнГос", + "source_scope": "any", + "allow_short_lookup": false, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "", + "structured_role": "", + "structured_order": 0, + "join_with_space": false, "multiplies": "нет", "required": "необязательно", "comment": "Числовой показатель, поле может остаться пустым и не поступать в XML" }, { "index": 97, + "column_id": "legacy_097", "column_name": "Номер банкомата", + "block": "foreign_card", + "report_group": "participant_base", "xml_tag": "ИдТерминал", "xml_path": "СообщОперКО/ИнформЧасть/СведКО/Операция/СведенияКартаИнБанк/СведМестоОперация/ИдТерминал", + "source_scope": "any", + "allow_short_lookup": false, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "", + "structured_role": "", + "structured_order": 0, + "join_with_space": false, "multiplies": "нет", "required": "необязательно", "comment": "Числовой показатель, поле может остаться пустым и не передаваться в XML" }, { "index": 98, + "column_id": "legacy_098", "column_name": "Код страны", + "block": "foreign_card", + "report_group": "participant_base", "xml_tag": "КодОКСМ", "xml_path": "СообщОперКО/ИнформЧасть/СведКО/Операция/СведенияКартаИнБанк/СведМестоОперация/АдрМестаПриемаВыдача/КодОКСМ", + "source_scope": "any", + "allow_short_lookup": false, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "", + "structured_role": "", + "structured_order": 0, + "join_with_space": false, "multiplies": "нет", "required": "необязательно", "comment": "текстовый показатель, поле может остаться пустым и не передаваться в XML" }, { "index": 99, + "column_id": "legacy_099", "column_name": "Адрес места приема наличных денежных средств (по структуре полный)", + "block": "foreign_card", + "report_group": "participant_base", "xml_tag": "АдрМестаПриемаВыдача", "xml_path": "СообщОперКО/ИнформЧасть/СведКО/Операция/СведенияКартаИнБанк/СведМестоОперация/АдрМестаПриемаВыдача/АдресСтрока", + "source_scope": "any", + "allow_short_lookup": true, + "allow_direct_mapping": true, + "structured_value": true, + "structured_group": "", + "structured_role": "", + "structured_order": 0, + "join_with_space": false, "multiplies": "нет", "required": "необязательно", "comment": "текстовый показатель, поле может остаться пустым и не передаваться в XML" }, { "index": 100, + "column_id": "legacy_100", "column_name": "Наименование банка, обслуживающего участника операции", + "block": "foreign_card", + "report_group": "participant_base", "xml_tag": "НаимКО", "xml_path": "СообщОперКО/ИнформЧасть/СведКО/Операция/СведенияКартаИнБанк/СведМестоОперация/НаимКО", + "source_scope": "any", + "allow_short_lookup": false, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "", + "structured_role": "", + "structured_order": 0, + "join_with_space": false, "multiplies": "нет", "required": "необязательно", "comment": "Текстовый показатель, поле может остаться пустым и не передаваться в XML" }, { "index": 101, + "column_id": "legacy_101", "column_name": "БИК банка, обслуживающего участника операции", + "block": "foreign_card", + "report_group": "participant_base", "xml_tag": "БИККО", "xml_path": "СообщОперКО/ИнформЧасть/СведКО/Операция/СведенияКартаИнБанк/СведМестоОперация/БИККО", + "source_scope": "any", + "allow_short_lookup": false, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "", + "structured_role": "", + "structured_order": 0, + "join_with_space": false, "multiplies": "нет", "required": "Обязательно", "comment": "Числовой показатель" }, { "index": 102, + "column_id": "legacy_102", "column_name": "Номер платежной карты", + "block": "foreign_card", + "report_group": "participant_base", "xml_tag": "НомерКарта", "xml_path": "СообщОперКО/ИнформЧасть/СведКО/Операция/СведенияКартаИнБанк/НомерКарта", + "source_scope": "any", + "allow_short_lookup": true, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "", + "structured_role": "", + "structured_order": 0, + "join_with_space": false, "multiplies": "нет", "required": "необязательно", "comment": "Показатель в XML передается зашифрованными ***************, в отчет попадают цифры" }, { "index": 103, + "column_id": "legacy_103", "column_name": "Сведения о держателе платежной карты", + "block": "foreign_card", + "report_group": "participant_base", "xml_tag": "СведДержательКарты", "xml_path": "СообщОперКО/ИнформЧасть/СведКО/Операция/СведенияКартаИнБанк/СведДержательКарты", + "source_scope": "any", + "allow_short_lookup": true, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "", + "structured_role": "", + "structured_order": 0, + "join_with_space": false, "multiplies": "нет", "required": "обязательно", "comment": "" }, { "index": 104, + "column_id": "legacy_104", "column_name": "Пр-ак соверш/ опер. с уч-ем УС КО", + "block": "foreign_card", + "report_group": "participant_base", "xml_tag": "ПризнакСотрудник", "xml_path": "СообщОперКО/ИнформЧасть/СведКО/Операция/СведенияКартаИнБанк/ПризнакСотрудник", + "source_scope": "any", + "allow_short_lookup": true, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "", + "structured_role": "", + "structured_order": 0, + "join_with_space": false, "multiplies": "нет", "required": "обязательно", "comment": "Числовой показатель" }, { "index": 105, + "column_id": "legacy_105", "column_name": "Наименование иностранного банка", + "block": "foreign_card", + "report_group": "participant_base", "xml_tag": "НаимИнБанк", "xml_path": "СообщОперКО/ИнформЧасть/СведКО/Операция/СведенияКартаИнБанк/НаимИнБанк", + "source_scope": "any", + "allow_short_lookup": true, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "", + "structured_role": "", + "structured_order": 0, + "join_with_space": false, "multiplies": "нет", "required": "обязательно", "comment": "" }, { "index": 106, + "column_id": "legacy_106", "column_name": "СВИФТ", + "block": "foreign_card", + "report_group": "participant_base", "xml_tag": "СВИФТИнБанк", "xml_path": "СообщОперКО/ИнформЧасть/СведКО/Операция/СведенияКартаИнБанк/СВИФТИнБанк", + "source_scope": "any", + "allow_short_lookup": true, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "", + "structured_role": "", + "structured_order": 0, + "join_with_space": false, "multiplies": "нет", "required": "необязательно", "comment": "поле может остаться пустым и не передаваться в XML" }, { "index": 107, + "column_id": "legacy_107", "column_name": "Сведения о документе, подтверждающем совершение операции", + "block": "operation_basis", + "report_group": "participant_base", "xml_tag": "СодДок", "xml_path": "СообщОперКО/ИнформЧасть/СведКО/Операция/ОснованиеОп/СодДок", + "source_scope": "any", + "allow_short_lookup": true, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "", + "structured_role": "", + "structured_order": 0, + "join_with_space": false, "multiplies": "нет", "required": "необязательно", "comment": "поле может остаться пустым и не передаваться в XML" }, { "index": 108, + "column_id": "legacy_108", "column_name": "Код статуса участника операции (сделки)", + "block": "participant_base", + "report_group": "participant_base", "xml_tag": "СтатусУчастника", "xml_path": "/СообщОперКО/ИнформЧасть/СведКО/Операция/УчастникОп/СтатусУчастника", + "source_scope": "any", + "allow_short_lookup": true, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "", + "structured_role": "", + "structured_order": 0, + "join_with_space": false, "multiplies": "нет", "required": "обязательно", "comment": "Числовой показатель" }, { "index": 109, + "column_id": "legacy_109", "column_name": "Тип участника", + "block": "participant_base", + "report_group": "participant_base", "xml_tag": "ТипУчастника", "xml_path": "/СообщОперКО/ИнформЧасть/СведКО/Операция/УчастникОп/ТипУчастника", + "source_scope": "participant", + "allow_short_lookup": true, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "", + "structured_role": "", + "structured_order": 0, + "join_with_space": false, "multiplies": "нет", "required": "обязательно", "comment": "Числовой показатель" }, { "index": 110, + "column_id": "legacy_110", "column_name": "Признак резидента", + "block": "participant_base", + "report_group": "participant_base", "xml_tag": "ПризнУчастника", "xml_path": "/СообщОперКО/ИнформЧасть/СведКО/Операция/УчастникОп/ПризнУчастника", + "source_scope": "any", + "allow_short_lookup": true, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "", + "structured_role": "", + "structured_order": 0, + "join_with_space": false, "multiplies": "нет", "required": "обязательно", "comment": "Числовой показатель" }, { "index": 111, + "column_id": "legacy_111", "column_name": "Признак участника операции (сделки)", + "block": "participant_base", + "report_group": "participant_base", "xml_tag": "ПризнКлиент", "xml_path": "/СообщОперКО/ИнформЧасть/СведКО/Операция/УчастникОп/ПризнКлиент", + "source_scope": "any", + "allow_short_lookup": true, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "", + "structured_role": "", + "structured_order": 0, + "join_with_space": false, "multiplies": "нет", "required": "обязательно", "comment": "Числовой показатель" }, { "index": 112, + "column_id": "legacy_112", "column_name": "Ид уч операции, включенного в Перечень,Решение, и (или) пер. ФРОМУ", + "block": "participant_base", + "report_group": "participant_base", "xml_tag": "КодЮЛФЛ", "xml_path": "/СообщОперКО/ИнформЧасть/СведКО/Операция/УчастникОп/КодЮЛФЛ", + "source_scope": "any", + "allow_short_lookup": true, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "", + "structured_role": "", + "structured_order": 0, + "join_with_space": false, "multiplies": "нет", "required": "необязательный", "comment": "Числовой показатель, поле может остаться пустым и не передаваться в XML" }, { "index": 113, + "column_id": "legacy_113", "column_name": "Наименование участника операции", + "block": "participant_base", + "report_group": "participant_base", "xml_tag": "НаимЮЛ|ПолноеНаимИНБОЮЛ", "xml_path": "/СообщОперКО/ИнформЧасть/СведКО/Операция/УчастникОП/УчастникЮЛ/СведЮЛ/НаимЮЛ/ | /СообщОперКО/ИнформЧасть/СведКО/Операция/УчастникОП/УчастникИНБОЮЛ/СведИНБОЮЛ/полноеНаимИНБОЮЛ", + "source_scope": "any", + "allow_short_lookup": true, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "", + "structured_role": "", + "structured_order": 0, + "join_with_space": false, "multiplies": "нет", "required": "необязательный", "comment": "поле может остаться пустым и не передаваться в XML" }, { "index": 114, + "column_id": "legacy_114", "column_name": "ФИО (по структуре полностью)", + "block": "participant_name", + "report_group": "participant_base", "xml_tag": "ФИОСтрока", "xml_path": "/СообщОперКО/ИнформЧасть/СведКО/Операция/УчастникОП/УчастникФЛИП/СведФЛИП/ФИОФЛИП/ФИОСтрока", + "source_scope": "participant", + "allow_short_lookup": true, + "allow_direct_mapping": false, + "structured_value": true, + "structured_group": "legacy_114", + "structured_role": "aggregate", + "structured_order": 0, + "join_with_space": true, "multiplies": "нет", "required": "необязательный", "comment": "поле может остаться пустым и не передаваться в XML" }, { "index": 115, + "column_id": "legacy_115", "column_name": "Фамилия", + "block": "participant_name", + "report_group": "participant_base", "xml_tag": "Фам", "xml_path": "/СообщОперКО/ИнформЧасть/СведКО/Операция/УчастникОП/УчастникФЛИП/СведФЛИП/ФИОФЛИП/Фам", + "source_scope": "participant", + "allow_short_lookup": true, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "legacy_114", + "structured_role": "component", + "structured_order": 1, + "join_with_space": false, "multiplies": "нет", "required": "необязательный", "comment": "поле может остаться пустым и не передаваться в XML" }, { "index": 116, + "column_id": "legacy_116", "column_name": "Имя", + "block": "participant_name", + "report_group": "participant_base", "xml_tag": "Имя", "xml_path": "/СообщОперКО/ИнформЧасть/СведКО/Операция/УчастникОП/УчастникФЛИП/СведФЛИП/ФИОФЛИП/Имя", + "source_scope": "participant", + "allow_short_lookup": true, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "legacy_114", + "structured_role": "component", + "structured_order": 2, + "join_with_space": false, "multiplies": "нет", "required": "необязательный", "comment": "поле может остаться пустым и не передаваться в XML" }, { "index": 117, + "column_id": "legacy_117", "column_name": "Отчество", + "block": "participant_name", + "report_group": "participant_base", "xml_tag": "Отч", "xml_path": "/СообщОперКО/ИнформЧасть/СведКО/Операция/УчастникОП/УчастникФЛИП/СведФЛИП/ФИОФЛИП/Отч", + "source_scope": "participant", + "allow_short_lookup": true, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "legacy_114", + "structured_role": "component", + "structured_order": 3, + "join_with_space": false, "multiplies": "нет", "required": "необязательный", "comment": "поле может остаться пустым и не передаваться в XML" }, { "index": 118, + "column_id": "legacy_118", "column_name": "ФИО (в одной строке)", + "block": "participant_name", + "report_group": "participant_base", "xml_tag": "ФИОСтрока", "xml_path": "/СообщОперКО/ИнформЧасть/СведКО/Операция/УчастникОП/УчастникФЛИП/СведФЛИП/ФИОФЛИП/ФИОСтрока", + "source_scope": "participant", + "allow_short_lookup": true, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "legacy_114", + "structured_role": "one_line", + "structured_order": 1, + "join_with_space": false, "multiplies": "нет", "required": "необязательный", "comment": "поле может остаться пустым и не передаваться в XML Уточнить это одно и то же с пунктом 114" }, { "index": 119, + "column_id": "legacy_119", "column_name": "Идентификатор ППЦР", + "block": "participant_identity", + "report_group": "participant_base", "xml_tag": "ИдентификацияФЛ", "xml_path": "/СообщОперКО/ИнформЧасть/СведКО/Операция/УчастникОП/УчастникФЛИП/ИдентификацияФЛ", + "source_scope": "participant", + "allow_short_lookup": false, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "", + "structured_role": "", + "structured_order": 0, + "join_with_space": false, "multiplies": "нет", "required": "обязательно", "comment": "числовой показатель" }, { "index": 120, + "column_id": "legacy_120", "column_name": "ИНН", + "block": "participant_identity", + "report_group": "participant_base", "xml_tag": "ИННЮЛ|ИННФЛИП", - "xml_path": " /СообщОперКО/ИнформЧасть/СведКО/Операция/УчастникОП/УчастникЮЛ/СведЮЛ/ИННЮЛ | /СообщОперКО/ИнформЧасть/СведКО/Операция/УчастникОП/УчастникФЛИП/СведФЛИП/ИННФЛИП", + "xml_path": "/СообщОперКО/ИнформЧасть/СведКО/Операция/УчастникОП/УчастникЮЛ/СведЮЛ/ИННЮЛ | /СообщОперКО/ИнформЧасть/СведКО/Операция/УчастникОП/УчастникФЛИП/СведФЛИП/ИННФЛИП", + "source_scope": "participant", + "allow_short_lookup": true, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "", + "structured_role": "", + "structured_order": 0, + "join_with_space": false, "multiplies": "нет", "required": "обязательно", "comment": "" }, { "index": 121, + "column_id": "legacy_121", "column_name": "ОГРН", + "block": "participant_identity", + "report_group": "participant_base", "xml_tag": "ОГРНЮЛ|ОГРНИП|РегнНомер|РегИНБОЮЛ", "xml_path": "/СообщОперКО/ИнформЧасть/СведКО/Операция/УчастникОП/УчастникЮЛ/СведЮЛ/ОГРНЮЛ | /СообщОперКО/ИнформЧасть/СведКО/Операция/УчастникОП/УчастникФЛИП/СведФЛИП/ОГРНИП | /СообщОперКО/ИнформЧасть/СведКО/Операция/УчастникОП/УчастникФЛИП/СведФЛИП/РегнНомер | /СообщОперКО/ИнформЧасть/СведКО/Операция/УчастникОП/УчастникИНБОЮЛ/СвебИНБОЮЛ/РегИНБОЮЛ", + "source_scope": "any", + "allow_short_lookup": true, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "", + "structured_role": "", + "structured_order": 0, + "join_with_space": false, "multiplies": "нет", "required": "обязательно", "comment": "Уточнить, что значит \"(совокупность показателей таб.2.11 1)\"" }, { "index": 122, + "column_id": "legacy_122", "column_name": "КПП (ПРИЗНАК ИСБОЮЛ) /Пр ид-ии ФЛ:", + "block": "participant_identity", + "report_group": "participant_base", "xml_tag": "КППЮЛ|ИдентификацияФЛ|ПризнакОргФормаИНБОЮЛ", "xml_path": "/СообщОперКО/ИнформЧасть/СведКО/Операция/УчастникОп/УчастникЮЛ/СведЮЛ/КППЮЛ | /СообщОперКО/ИнформЧасть/СведКО/Операция/УчастникОП/УчастникФЛИП/ИдентификацияФЛ | /СообщОперКО/ИнформЧасть/СведКО/Операция/УчастникОП/УчастникИНБОЮЛ/СведИНБОЮЛ/ПризнакОргФормаИНБОЮЛ", + "source_scope": "participant", + "allow_short_lookup": true, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "", + "structured_role": "", + "structured_order": 0, + "join_with_space": false, "multiplies": "нет", "required": "обязательно", "comment": "" }, { "index": 123, + "column_id": "legacy_123", "column_name": "Дата государственной регистрации :/ Дата рождения:", + "block": "participant_identity", + "report_group": "participant_base", "xml_tag": "ДатаРегЮЛ|ДатаРождения", "xml_path": "/СообщОперКО/ИнформЧасть/СведКО/Операция/УчастникОП/УчастникЮЛ/СведЮЛ/ДатаРегЮЛ | /СообщОперКО/ИнформЧасть/СведКО/Операция/УчастникОП/УчастникФЛИП/СведФЛИП/ДатаРождения", + "source_scope": "any", + "allow_short_lookup": false, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "", + "structured_role": "", + "structured_order": 0, + "join_with_space": false, "multiplies": "нет", "required": "необязательно", "comment": "Показатель в формате ДД/ММ/ГГГГ." }, { "index": 124, + "column_id": "legacy_124", "column_name": "Признак филиала: / Тип ФЛЧП", + "block": "participant_identity", + "report_group": "participant_base", "xml_tag": "ПризнакФлЮЛ|ТипФЛЧастнаяПрактика", "xml_path": "/СообщОперКО/ИнформЧасть/СведКО/Операция/УчастникОП/УчастникЮЛ/СведЮЛ/ПризнакФлЮЛ | /СообщОперКО/ИнформЧасть/СведКО/Операция/УчастникОП/УчпстникФЛИП/СветФЛИП/ТипФЛЧастнаяПрактика", + "source_scope": "participant", + "allow_short_lookup": true, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "", + "structured_role": "", + "structured_order": 0, + "join_with_space": false, "multiplies": "нет", "required": "обязательно", "comment": "" }, { "index": 125, + "column_id": "legacy_125", "column_name": "ОМС/СНИЛС/Номер телефона", + "block": "participant_identity", + "report_group": "participant_base", "xml_tag": "СНИЛСФЛ|ПолисНомер|ТелефонНомер", "xml_path": "/СообщОперКО/ИнформЧасть/СведКО/Операция/УчастникОП/УчастникФЛИП/СведФЛИП/СНИЛСФЛ | /СообщОперКО/ИнформЧасть/СведКО/Операция/УчастникОП/УчастникФЛИП/СведФЛИП/ПолисНомер | /СообщОперКО/ИнформЧасть/СведКО/Операция/УчастникОП/УчастникФЛИП/СведФЛИП/ТелефонНомер", + "source_scope": "any", + "allow_short_lookup": true, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "", + "structured_role": "", + "structured_order": 0, + "join_with_space": false, "multiplies": "нет", "required": "необязательно", "comment": "Все показатели записываются в одном столбце, поле может оставаться пустым." }, { "index": 126, + "column_id": "legacy_126", "column_name": "Код страны гражданства", + "block": "participant_identity", + "report_group": "participant_base", "xml_tag": "КодОКСМ", "xml_path": "/СообщОперКО/ИнформЧасть/СведКО/Операция/УчастникОП/УчастникФЛИП/СведФЛИП/КодОКСМ", + "source_scope": "participant", + "allow_short_lookup": false, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "", + "structured_role": "", + "structured_order": 0, + "join_with_space": false, "multiplies": "нет", "required": "обязательно", "comment": "числовой показатель. Пример СНИЛС: | ОМС: | Номер телефона:" }, { "index": 127, + "column_id": "legacy_127", "column_name": "Признак принадлежности к публичным лицам", + "block": "participant_identity", + "report_group": "participant_identity", "xml_tag": "ПризнакПубЛицо", "xml_path": "/СообщОперКО/ИнформЧасть/СведКО/Операция/УчастникОП/УчастникФЛИП/СведФЛИП/ПризнакПубЛицо", + "source_scope": "participant", + "allow_short_lookup": true, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "", + "structured_role": "", + "structured_order": 0, + "join_with_space": false, "multiplies": "нет", "required": "необязательно", "comment": "Числовой показатель, может оставаться пустым и не передаваться в XML" }, { "index": 128, + "column_id": "legacy_128", "column_name": "ДУЛ (структура полностью)", + "block": "participant_documents", + "report_group": "participant_identity", "xml_tag": "ВидДокКод|ИноеНаименованиеДок|СерияДок|НомДок|ДатВыдачиДок|КемВыданДок|КодПодр|СведДокУдЛичн", "xml_path": "/СообщОперКО/ИнформЧасть/СведКО/Операция/УчастникОП/УчастникФЛИП/СведФЛИП/СведДокУдЛичн", + "source_scope": "participant", + "allow_short_lookup": true, + "allow_direct_mapping": true, + "structured_value": true, + "structured_group": "legacy_128", + "structured_role": "aggregate", + "structured_order": 0, + "join_with_space": false, "multiplies": "нет", "required": "обязательно", "comment": "Данные собранные в одном поле. Не все теги могут быть переданы в XML пример Вид документа: 21 | Серия документа: 0104 | Номер документа: 476635 | Орган, выдавший документ: Отделом внутренних дел Красногорского района Алтайского края | Код подразделения: 222-022 | Дата выдачи: 23/08/2005" }, { "index": 129, + "column_id": "legacy_129", "column_name": "Признак ДУЛ", + "block": "participant_documents", + "report_group": "participant_identity", "xml_tag": "ДокУдЛичн", "xml_path": "/СообщОперКО/ИнформЧасть/СведКО/Операция/УчастникОП/УчастникФЛИП/СведФЛИП/ДокУдЛичн", + "source_scope": "participant", + "allow_short_lookup": true, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "legacy_128", + "structured_role": "component", + "structured_order": 1, + "join_with_space": false, "multiplies": "нет", "required": "обязательно", "comment": "Данные могут оставаться пустыми" }, { "index": 130, + "column_id": "legacy_130", "column_name": "Код вида документа/Наименование", + "block": "participant_documents", + "report_group": "participant_identity", "xml_tag": "ВидДокКод", "xml_path": "/СообщОперКО/ИнформЧасть/СведКО/Операция/УчастникОП/УчастникФЛИП/СведФЛИП/СведДокУдЛичн/ВидДокКод", + "source_scope": "participant", + "allow_short_lookup": true, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "legacy_128", + "structured_role": "component", + "structured_order": 2, + "join_with_space": false, "multiplies": "нет", "required": "обязательно", "comment": "числовой показатель." }, { "index": 131, + "column_id": "legacy_131", "column_name": "Серия", + "block": "participant_documents", + "report_group": "participant_identity", "xml_tag": "СерияДок", "xml_path": "/СообщОперКО/ИнформЧасть/СведКО/Операция/УчастникОП/УчастникФЛИП/СведФЛИП/СведДокУдЛичн/СерияДок", + "source_scope": "participant", + "allow_short_lookup": true, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "legacy_128", + "structured_role": "component", + "structured_order": 3, + "join_with_space": false, "multiplies": "нет", "required": "обязательно", "comment": "числовой показатель" }, { "index": 132, + "column_id": "legacy_132", "column_name": "Номер", + "block": "participant_documents", + "report_group": "participant_identity", "xml_tag": "НомДок", "xml_path": "/СообщОперКО/ИнформЧасть/СведКО/Операция/УчастникОП/УчастникФЛИП/СведФЛИП/СведДокУдЛичн/НомДок", + "source_scope": "participant", + "allow_short_lookup": true, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "legacy_128", + "structured_role": "component", + "structured_order": 4, + "join_with_space": false, "multiplies": "нет", "required": "обязательно", "comment": "числовой показатель" }, { "index": 133, + "column_id": "legacy_133", "column_name": "Орган, выдавший документ", + "block": "participant_documents", + "report_group": "participant_identity", "xml_tag": "КемВыданДок", "xml_path": "/СообщОперКО/ИнформЧасть/СведКО/Операция/УчастникОП/УчастникФЛИП/СведФЛИП/СведДокУдЛичн/КемВыданДок", + "source_scope": "participant", + "allow_short_lookup": true, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "legacy_128", + "structured_role": "component", + "structured_order": 5, + "join_with_space": false, "multiplies": "нет", "required": "необязательно", "comment": "текст" }, { "index": 134, + "column_id": "legacy_134", "column_name": "КП", + "block": "participant_documents", + "report_group": "participant_identity", "xml_tag": "КодПодр", "xml_path": "/СообщОперКО/ИнформЧасть/СведКО/Операция/УчастникОП/УчастникФЛИП/СведФЛИП/СведДокУдЛичн/КодПодр", + "source_scope": "participant", + "allow_short_lookup": true, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "legacy_128", + "structured_role": "component", + "structured_order": 6, + "join_with_space": false, "multiplies": "", "required": "", "comment": "" }, { "index": 135, + "column_id": "legacy_135", "column_name": "Дата выдачи", + "block": "participant_documents", + "report_group": "participant_identity", "xml_tag": "ДатВыдачиДок", "xml_path": "/СообщОперКО/ИнформЧасть/СведКО/Операция/ММ/ГГГГ/УчастникОП/УчастникФЛИП/СведФЛИП/СведДокУдЛичн/ДатВыдачиДок", + "source_scope": "participant", + "allow_short_lookup": true, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "", + "structured_role": "", + "structured_order": 0, + "join_with_space": false, "multiplies": "нет", "required": "обязательно", "comment": "дата, формат ДД/ММ/ГГГГ" }, { "index": 136, + "column_id": "legacy_136", "column_name": "Код вида документа/Наименование", + "block": "participant_documents", + "report_group": "participant_identity", "xml_tag": "ВидДокКод", "xml_path": "/СообщОперКО/ИнформЧасть/СведКО/Операция/УчастникОП/УчастникФЛИП/СведФЛИП/СведДокУдЛичн/ВидДокКод", + "source_scope": "participant", + "allow_short_lookup": true, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "", + "structured_role": "", + "structured_order": 0, + "join_with_space": false, "multiplies": "нет", "required": "обязательно", "comment": "" }, { "index": 137, + "column_id": "legacy_137", "column_name": "Серия", + "block": "participant_documents", + "report_group": "participant_identity", "xml_tag": "СерияДокПреб", "xml_path": "/СообщОперКО/ИнформЧасть/СведКО/Операция/УчастникОП/УчастникФЛИП/СведФЛИП/СведДокПреб/СерияДокПреб", + "source_scope": "participant", + "allow_short_lookup": true, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "", + "structured_role": "", + "structured_order": 0, + "join_with_space": false, "multiplies": "нет", "required": "обязательно", "comment": "" }, { "index": 138, + "column_id": "legacy_138", "column_name": "Номер", + "block": "participant_documents", + "report_group": "participant_identity", "xml_tag": "НомДокПреб", "xml_path": "/СообщОперКО/ИнформЧасть/СведКО/Операция/УчастникОП/УчастникФЛИП/СведФЛИП/СведДокПреб/НомДокПреб", + "source_scope": "participant", + "allow_short_lookup": true, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "", + "structured_role": "", + "structured_order": 0, + "join_with_space": false, "multiplies": "нет", "required": "обязательно", "comment": "" }, { "index": 139, + "column_id": "legacy_139", "column_name": "Дата начала/окончания срока", + "block": "participant_documents", + "report_group": "participant_identity", "xml_tag": "НачПравПреб", "xml_path": "/СообщОперКО/ИнформЧасть/СведКО/Операция/УчастникОП/УчастникФЛИП/СведФЛИП/СведДокПреб/НачПравПреб", + "source_scope": "participant", + "allow_short_lookup": true, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "", + "structured_role": "", + "structured_order": 0, + "join_with_space": false, "multiplies": "нет", "required": "обязательно", "comment": "" }, { "index": 140, + "column_id": "legacy_140", "column_name": "Сведения миграционной карты", + "block": "participant_documents", + "report_group": "participant_identity", "xml_tag": "", "xml_path": "", + "source_scope": "any", + "allow_short_lookup": true, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "", + "structured_role": "", + "structured_order": 0, + "join_with_space": false, "multiplies": "", "required": "", "comment": "" }, { "index": 141, + "column_id": "legacy_141", "column_name": "Адрес в одной строке", + "block": "participant_address", + "report_group": "participant_identity", "xml_tag": "АдресСтрока", "xml_path": "/СообщОперКО/ИнформЧасть/СведКО/Операция/УчастникОП/УчастникЮЛ/СведЮЛ/АдрРегЮЛ/АдресСтрока | /СообщОперКО/ИнформЧасть/СведКО/Операция/УчастникОП/УчастникФлип/СведФЛИП/АдрРег/АдресСтрока | /СообщОперКО/ИнформЧасть/СведКО/Операция/УчастникОП/УчастникИНБОЮЛ/СведИНБОЮЛ/МестоДеятельностьИНБОЮЛ/АдресСтрока", + "source_scope": "any", + "allow_short_lookup": true, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "legacy_142", + "structured_role": "one_line", + "structured_order": 1, + "join_with_space": false, "multiplies": "нет", "required": "Обязательно", "comment": "Текстовое поле" }, { "index": 142, + "column_id": "legacy_142", "column_name": "Адрес по структуре (целый)", + "block": "participant_address", + "report_group": "participant_identity", "xml_tag": "Индекс|КодОКСМ|КодСубъектаПоОКАТО|Район|Пункт|Улица|Дом|Корп|Оф", "xml_path": "/СообщОперКО/ИнформЧасть/СведКО/Операция/УчастникОП/УчастникЮЛ/СведЮЛ/АдрРегЮЛ/ | /СообщОперКО/ИнформЧасть/СведКО/Операция/УчастникОП/УчастникФлип/СведФЛИП/АдрРег/ | /СообщОперКО/ИнформЧасть/СведКО/Операция/УчастникОП/УчастникИНБОЮЛ/СведИНБОЮЛ/МестоДеятельностьИНБОЮЛ/", + "source_scope": "any", + "allow_short_lookup": true, + "allow_direct_mapping": true, + "structured_value": true, + "structured_group": "legacy_142", + "structured_role": "aggregate", + "structured_order": 0, + "join_with_space": false, "multiplies": "нет", "required": "Обязательно", "comment": "Текстовое поле. Пример заполнения 674500, 643, , 76, КРАЙ ЗАБАЙКАЛЬСКИЙ, Оловяннинский р-н, Оловянная пгт, Новая ул, 5, , 1," }, { "index": 143, + "column_id": "legacy_143", "column_name": "Индекс", + "block": "participant_address", + "report_group": "participant_identity", "xml_tag": "Индекс", "xml_path": "/СообщОперКО/ИнформЧасть/СведКО/Операция/УчастникОП/УчастникЮЛ/СведЮЛ/АдрРегЮЛ/Индекс | /СообщОперКО/ИнформЧасть/СведКО/Операция/УчастникОП/УчастникФлип/СведФЛИП/АдрРег/Индекс | /СообщОперКО/ИнформЧасть/СведКО/Операция/УчастникОП/УчастникИНБОЮЛ/СведИНБОЮЛ/МестоДеятельностьИНБОЮЛ/Индекс", + "source_scope": "any", + "allow_short_lookup": true, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "legacy_142", + "structured_role": "component", + "structured_order": 1, + "join_with_space": false, "multiplies": "нет", "required": "Обязательно", "comment": "Текст" }, { "index": 144, + "column_id": "legacy_144", "column_name": "Код страны", + "block": "participant_address", + "report_group": "participant_identity", "xml_tag": "КодОКСМ", "xml_path": "/СообщОперКО/ИнформЧасть/СведКО/Операция/УчастникОП/УчастникЮЛ/СведЮЛ/АдрРегЮЛ/КодОКСМ | /СообщОперКО/ИнформЧасть/СведКО/Операция/УчастникОП/УчастникФлип/СведФЛИП/АдрРег/КодОКСМ | /СообщОперКО/ИнформЧасть/СведКО/Операция/УчастникОП/УчастникИНБОЮЛ/СведИНБОЮЛ/МестоДеятельностьИНБОЮЛ/КодОКСМ", + "source_scope": "any", + "allow_short_lookup": true, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "legacy_142", + "structured_role": "component", + "structured_order": 2, + "join_with_space": false, "multiplies": "нет", "required": "Обязательно", "comment": "текст" }, { "index": 145, + "column_id": "legacy_145", "column_name": "Код ОКАТО", + "block": "participant_address", + "report_group": "participant_identity", "xml_tag": "КодСубъектаПоОКАТО", "xml_path": "/СообщОперКО/ИнформЧасть/СведКО/Операция/УчастникОП/УчастникЮЛ/СведЮЛ/АдрРегЮЛ/КодСубъектаПоОКАТО | /СообщОперКО/ИнформЧасть/СведКО/Операция/УчастникОП/УчастникФлип/СведФЛИП/АдрРег/КодСубъектаПоОКАТО | /СообщОперКО/ИнформЧасть/СведКО/Операция/УчастникОП/УчастникИНБОЮЛ/СведИНБОЮЛ/МестоДеятельностьИНБОЮЛ/КодСубъектаПоОКАТО", + "source_scope": "any", + "allow_short_lookup": true, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "legacy_142", + "structured_role": "component", + "structured_order": 3, + "join_with_space": false, "multiplies": "нет", "required": "Обязательно", "comment": "текст" }, { "index": 146, + "column_id": "legacy_146", "column_name": "Район", + "block": "participant_address", + "report_group": "participant_identity", "xml_tag": "Район", "xml_path": "/СообщОперКО/ИнформЧасть/СведКО/Операция/УчастникОП/УчастникЮЛ/СведЮЛ/АдрРегЮЛ/Район | /СообщОперКО/ИнформЧасть/СведКО/Операция/УчастникОП/УчастникФлип/СведФЛИП/АдрРег/Район | /СообщОперКО/ИнформЧасть/СведКО/Операция/УчастникОП/УчастникИНБОЮЛ/СведИНБОЮЛ/МестоДеятельностьИНБОЮЛ/Район", + "source_scope": "any", + "allow_short_lookup": true, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "legacy_142", + "structured_role": "component", + "structured_order": 4, + "join_with_space": false, "multiplies": "нет", "required": "Обязательно", "comment": "текст" }, { "index": 147, + "column_id": "legacy_147", "column_name": "Населенный пункт", + "block": "participant_address", + "report_group": "participant_identity", "xml_tag": "Пункт", "xml_path": "/СообщОперКО/ИнформЧасть/СведКО/Операция/УчастникОП/УчастникЮЛ/СведЮЛ/АдрРегЮЛ/Пункт | /СообщОперКО/ИнформЧасть/СведКО/Операция/УчастникОП/УчастникФлип/СведФЛИП/АдрРег/Пункт | /СообщОперКО/ИнформЧасть/СведКО/Операция/УчастникОП/УчастникИНБОЮЛ/СведИНБОЮЛ/МестоДеятельностьИНБОЮЛ/Пункт", + "source_scope": "any", + "allow_short_lookup": true, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "legacy_142", + "structured_role": "component", + "structured_order": 5, + "join_with_space": false, "multiplies": "нет", "required": "Обязательно", "comment": "текст" }, { "index": 148, + "column_id": "legacy_148", "column_name": "Улица", + "block": "participant_address", + "report_group": "participant_identity", "xml_tag": "Улица", "xml_path": "/СообщОперКО/ИнформЧасть/СведКО/Операция/УчастникОП/УчастникЮЛ/СведЮЛ/АдрРегЮЛ/Улица | /СообщОперКО/ИнформЧасть/СведКО/Операция/УчастникОП/УчастникФлип/СведФЛИП/АдрРег/Улица | /СообщОперКО/ИнформЧасть/СведКО/Операция/УчастникОП/УчастникИНБОЮЛ/СведИНБОЮЛ/МестоДеятельностьИНБОЮЛ/Улица", + "source_scope": "any", + "allow_short_lookup": true, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "legacy_142", + "structured_role": "component", + "structured_order": 6, + "join_with_space": false, "multiplies": "нет", "required": "Обязательно", "comment": "текст" }, { "index": 149, + "column_id": "legacy_149", "column_name": "Дом", + "block": "participant_address", + "report_group": "participant_identity", "xml_tag": "Дом", "xml_path": "/СообщОперКО/ИнформЧасть/СведКО/Операция/УчастникОП/УчастникЮЛ/СведЮЛ/АдрРегЮЛ/Дом | /СообщОперКО/ИнформЧасть/СведКО/Операция/УчастникОП/УчастникФлип/СведФЛИП/АдрРег/Дом | /СообщОперКО/ИнформЧасть/СведКО/Операция/УчастникОП/УчастникИНБОЮЛ/СведИНБОЮЛ/МестоДеятельностьИНБОЮЛ/Дом", + "source_scope": "any", + "allow_short_lookup": true, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "legacy_142", + "structured_role": "component", + "structured_order": 7, + "join_with_space": false, "multiplies": "нет", "required": "Обязательно", "comment": "текст" }, { "index": 150, + "column_id": "legacy_150", "column_name": "Корпус/строение", + "block": "participant_address", + "report_group": "participant_identity", "xml_tag": "Корп", "xml_path": "/СообщОперКО/ИнформЧасть/СведКО/Операция/УчастникОП/УчастникЮЛ/СведЮЛ/АдрРегЮЛ/Корп | /СообщОперКО/ИнформЧасть/СведКО/Операция/УчастникОП/УчастникФлип/СведФЛИП/АдрРег/Корп | /СообщОперКО/ИнформЧасть/СведКО/Операция/УчастникОП/УчастникИНБОЮЛ/СведИНБОЮЛ/МестоДеятельностьИНБОЮЛ/Корп", + "source_scope": "any", + "allow_short_lookup": true, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "legacy_142", + "structured_role": "component", + "structured_order": 8, + "join_with_space": false, "multiplies": "нет", "required": "Обязательно", "comment": "текст" }, { "index": 151, + "column_id": "legacy_151", "column_name": "Квартира", + "block": "participant_address", + "report_group": "participant_identity", "xml_tag": "Оф", "xml_path": "/СообщОперКО/ИнформЧасть/СведКО/Операция/УчастникОП/УчастникЮЛ/СведЮЛ/АдрРегЮЛ/Оф | /СообщОперКО/ИнформЧасть/СведКО/Операция/УчастникОП/УчастникФлип/СведФЛИП/АдрРег/Оф | /СообщОперКО/ИнформЧасть/СведКО/Операция/УчастникОП/УчастникИНБОЮЛ/СведИНБОЮЛ/МестоДеятельностьИНБОЮЛ/Оф", + "source_scope": "any", + "allow_short_lookup": true, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "legacy_142", + "structured_role": "component", + "structured_order": 9, + "join_with_space": false, "multiplies": "нет", "required": "Обязательно", "comment": "текст" }, { "index": 152, + "column_id": "legacy_152", "column_name": "Место государственной регистрации ( в одной строке)", + "block": "participant_address", + "report_group": "participant_identity", "xml_tag": "АдресСтрока", "xml_path": "/СообщОперКО/ИнформЧасть/СведКО/Операция/УчастникОП/УчастникЮЛ/СведЮЛ/АдрРегЮЛ/АдресСтрока", + "source_scope": "any", + "allow_short_lookup": false, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "legacy_142", + "structured_role": "one_line", + "structured_order": 2, + "join_with_space": false, "multiplies": "нет", "required": "Обязательно", "comment": "Текстовое поле" }, { "index": 153, + "column_id": "legacy_153", "column_name": "Место государственной регистрации", + "block": "participant_address", + "report_group": "participant_identity", "xml_tag": "Индекс|КодОКСМ|КодСубъектаПоОКАТО|Район|Пункт|Улица|Дом|Корп|Оф", "xml_path": "/СообщОперКО/ИнформЧасть/СведКО/Операция/УчастникОП/УчастникЮЛ/СведЮЛ/АдрРегЮЛ/", + "source_scope": "any", + "allow_short_lookup": false, + "allow_direct_mapping": true, + "structured_value": true, + "structured_group": "", + "structured_role": "", + "structured_order": 0, + "join_with_space": false, "multiplies": "нет", "required": "Обязательно", "comment": "Текстовое поле. Пример заполнения 674500, 643, , 76, КРАЙ ЗАБАЙКАЛЬСКИЙ, Оловяннинский р-н, Оловянная пгт, Новая ул, 5, , 1," }, { "index": 154, + "column_id": "legacy_154", "column_name": "Дополнительная информация об участнике операции (сделки)", + "block": "participant_extra", + "report_group": "participant_identity", "xml_tag": "КомментУчастник", "xml_path": "/СообщОперКО/ИнформЧасть/СведКО/Операция/УчастникОП/КомментУчастник", + "source_scope": "any", + "allow_short_lookup": true, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "", + "structured_role": "", + "structured_order": 0, + "join_with_space": false, "multiplies": "нет", "required": "обязательно", "comment": "текстовое поле" }, { "index": 155, + "column_id": "legacy_155", "column_name": "Тип ЕИО/Бенефициара", + "block": "eio", + "report_group": "eio", "xml_tag": "ТипЕИО/ИдентБенефициар", "xml_path": "/СообщОперКО/ИнформЧасть/СведКО/Операция/УчастникОП/УчастникЮЛ/СведЕИО/ТипЕИО | /СообщОперКО/ИнформЧасть/СведКО/Операция/УчастникОП/УчастникЮЛ/БенефициарЮЛ/ИдентБенефициар", + "source_scope": "participant", + "allow_short_lookup": false, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "", + "structured_role": "", + "structured_order": 0, + "join_with_space": false, "multiplies": "нет", "required": "обязательно", "comment": "поле может оставаться пустым" }, { "index": 156, + "column_id": "legacy_156", "column_name": "Признак ЕИО/Бенефициара", + "block": "eio", + "report_group": "eio", "xml_tag": "ПризнЕИО/ПризнБенефициар", "xml_path": "/СообщОперКО/ИнформЧасть/СведКО/Операция/УчастникОП/УчастникЮЛ/СведЕИО/ПризнЕИО | /СообщОперКО/ИнформЧасть/СведКО/Операция/УчастникОП/УчастникЮЛ/БенефициарЮЛ/ПризнБенефициар", + "source_scope": "participant", + "allow_short_lookup": false, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "", + "structured_role": "", + "structured_order": 0, + "join_with_space": false, "multiplies": "нет", "required": "обязательно", "comment": "поле может оставаться пустым" }, { "index": 157, + "column_id": "legacy_157", "column_name": "Наименование ЮЛ/ФИО ( по структуре полный)", + "block": "eio", + "report_group": "eio", "xml_tag": "НаимЮЛ/ФИОФЛИП/НаимУчредитель", "xml_path": "/СообщОперКО/ИнформЧасть/СведКО/Операция/УчастникОП/УчастникЮЛ/СведЮЛ/НаимЮЛ | /СообщОперКО/ИнформЧасть/СведКО/Операция/УчастникОП/УчастникФЛИП/СведФЛИП/ФИОФЛИП/Фам | /СообщОперКО/ИнформЧасть/СведКО/Операция/УчастникОП/УчастникФЛИП/СведФЛИП/ФИОФЛИП/Имя | /СообщОперКО/ИнформЧасть/СведКО/Операция/УчастникОП/УчастникФЛИП/СведФЛИП/ФИОФЛИП/Отч | /СообщОперКО/ИнформЧасть/СведКО/Операция/УчастникОП/УчастникИНБОЮЛ/СведИНБОЮЛ/Учредитель/НаимУчредитель/ЮрЛицо | /СообщОперКО/ИнформЧасть/СведКО/Операция/УчастникОП/УчастникИНБОЮЛ/СведИНБОЮЛ/Учредитель/НаимУчредитель/ФизЛицо/Фам | /СообщОперКО/ИнформЧасть/СведКО/Операция/УчастникОП/УчастникИНБОЮЛ/СведИНБОЮЛ/Учредитель/НаимУчредитель/ФизЛицо/Имя | /СообщОперКО/ИнформЧасть/СведКО/Операция/УчастникОП/УчастникИНБОЮЛ/СведИНБОЮЛ/Учредитель/НаимУчредитель/ФизЛицо/Отч", + "source_scope": "participant", + "allow_short_lookup": true, + "allow_direct_mapping": true, + "structured_value": true, + "structured_group": "legacy_157", + "structured_role": "aggregate", + "structured_order": 0, + "join_with_space": true, "multiplies": "", "required": "", "comment": "" }, { "index": 158, + "column_id": "legacy_158", "column_name": "ФИО ( в одной строке)", + "block": "eio", + "report_group": "eio", "xml_tag": "ФИОФЛИП", "xml_path": "/СообщОперКО/ИнформЧасть/СведКО/Операция/УчастникОП/УчастникФЛИП/СведФЛИП/ФИОФЛИП/ФИОСтрока", + "source_scope": "participant", + "allow_short_lookup": false, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "legacy_157", + "structured_role": "one_line", + "structured_order": 1, + "join_with_space": false, "multiplies": "нетнет", "required": "обязательнообязательно", "comment": "Текстовый формат. Пример: Иванов Иван ИвановичТекстовый формат. Пример: Иванов Иван Иванович" }, { "index": 159, + "column_id": "legacy_159", "column_name": "Фамилия", + "block": "eio", + "report_group": "eio", "xml_tag": "Фам", "xml_path": "/СообщОперКО/ИнформЧасть/СведКО/Операция/УчастникОП/УчастникФЛИП/СведФЛИП/ФИОФЛИП/Фам", + "source_scope": "participant", + "allow_short_lookup": false, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "legacy_157", + "structured_role": "component", + "structured_order": 1, + "join_with_space": false, "multiplies": "нет", "required": "условно необязательныйусловно необязательный", "comment": "в какие части XML смотреть для верного раскладывания данных" }, { "index": 160, + "column_id": "legacy_160", "column_name": "Имя", + "block": "eio", + "report_group": "eio", "xml_tag": "Имя", "xml_path": "/СообщОперКО/ИнформЧасть/СведКО/Операция/УчастникОП/УчастникФЛИП/СведФЛИП/ФИОФЛИП/Имя", + "source_scope": "participant", + "allow_short_lookup": false, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "legacy_157", + "structured_role": "component", + "structured_order": 2, + "join_with_space": false, "multiplies": "нет", "required": "условно необязательный", "comment": "" }, { "index": 161, + "column_id": "legacy_161", "column_name": "Отчество", + "block": "eio", + "report_group": "eio", "xml_tag": "Отч", "xml_path": "/СообщОперКО/ИнформЧасть/СведКО/Операция/УчастникОП/УчастникФЛИП/СведФЛИП/ФИОФЛИП/Отч", + "source_scope": "participant", + "allow_short_lookup": false, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "legacy_157", + "structured_role": "component", + "structured_order": 3, + "join_with_space": false, "multiplies": "нет", "required": "условно необязательный", "comment": "" }, { "index": 162, + "column_id": "legacy_162", "column_name": "ИНН ЕИО/Бенефициара", + "block": "eio", + "report_group": "eio", "xml_tag": "ИННЮЛ/ИННФЛИП", "xml_path": "/СообщОперКО/ИнформЧасть/СведКО/Операция/УчастникОП/УчастникЮЛ/СведЮЛ/ИННЮЛ | /СообщОперКО/ИнформЧасть/СведКО/Операция/УчастникОП/УчастникФЛИП/СведФЛИП/ИННФЛИП", + "source_scope": "participant", + "allow_short_lookup": false, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "legacy_157", + "structured_role": "component", + "structured_order": 4, + "join_with_space": false, "multiplies": "нет", "required": "обязательно", "comment": "Поле может оставаться пустым. Для юр лиц используется \"ИННЮЛ\" Для физ лиц и ИП \"ИННФЛИП\"" }, { "index": 163, + "column_id": "legacy_163", "column_name": "ОГРН ЕИО/Бенефициара", + "block": "eio", + "report_group": "eio", "xml_tag": "ОГРНЮЛ|ОГРНИП|ТипФЛЧастнаяПрактика", "xml_path": "/СообщОперКО/ИнформЧасть/СведКО/Операция/УчастникОП/УчастникЮЛ/СведЮЛ/ОГРНЮЛ | /СообщОперКО/ИнформЧасть/СведКО/Операция/УчастникОП/УчастникФЛИП/СведФЛИП/ОГРНИП | /СообщОперКО/ИнформЧасть/СведКО/Операция/УчастникОП/УчастникФЛИП/СведФЛИП/ТипФЛЧастнаяПрактика", + "source_scope": "participant", + "allow_short_lookup": false, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "", + "structured_role": "", + "structured_order": 0, + "join_with_space": false, "multiplies": "нет", "required": "обязательно", "comment": "Поле может оставаться пустым. | |" }, { "index": 164, + "column_id": "legacy_164", "column_name": "Иные сведения ЕИО/Бенефициара", + "block": "eio", + "report_group": "eio", "xml_tag": "", "xml_path": "", + "source_scope": "any", + "allow_short_lookup": true, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "", + "structured_role": "", + "structured_order": 0, + "join_with_space": false, "multiplies": "нет нет", "required": "Обязательно Обязательно", "comment": "Текстовое поле, может оставаться пустым и не передаваться в XML Текстовое поле, может оставаться пустым и не передаваться в XML |" }, { "index": 165, + "column_id": "legacy_165", "column_name": "Код страны гражданства ЕИО/Бенефициара", + "block": "eio", + "report_group": "eio", "xml_tag": "", "xml_path": "", + "source_scope": "any", + "allow_short_lookup": true, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "", + "structured_role": "", + "structured_order": 0, + "join_with_space": false, "multiplies": "нет", "required": "Обязательно", "comment": "Уточнить, что подразумевается под цифрой \"2\"" }, { "index": 166, + "column_id": "legacy_166", "column_name": "Признак принадлеж к ПДЛ ЕИО/Бенефициара", + "block": "eio", + "report_group": "eio", "xml_tag": "ПризнакПубЛицо", "xml_path": "/СообщОперКО/ИнформЧасть/СведКО/Операция/УчастникОП/УчастникФЛИП/СведФЛИП/ПризнакПубЛицо", + "source_scope": "participant", + "allow_short_lookup": false, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "", + "structured_role": "", + "structured_order": 0, + "join_with_space": false, "multiplies": "нет", "required": "Обязательно", "comment": "Числовое поле, может оставаться пустым и не передаваться в XML" }, { "index": 167, + "column_id": "legacy_167", "column_name": "Адрес ЮЛ/ Адрес места жительства (места нахождения) ЕИО/Бенефициара (по структуре полный)", + "block": "eio", + "report_group": "eio", "xml_tag": "АдресСтрока|АдрУчредитель", "xml_path": "/СообщОперКО/ИнформЧасть/СведКО/Операция/УчастникОП/УчастникЮЛ/СведЮЛ/АдрРегЮЛ/АдресСтрока | /СообщОперКО/ИнформЧасть/СведКО/Операция/УчастникОП/УчастникИНБОЮЛ/СведИНБОЮЛ/Учредитель/АдрУчредитель/АдресСтрока", + "source_scope": "participant", + "allow_short_lookup": true, + "allow_direct_mapping": true, + "structured_value": true, + "structured_group": "", + "structured_role": "", + "structured_order": 0, + "join_with_space": false, "multiplies": "нет", "required": "Обязательно", "comment": "Текстовое поле , может оставаться пустым" }, { "index": 168, + "column_id": "legacy_168", "column_name": "Адрес ЮЛ/ Адрес места жительства (места нахождения) ЕИО/Бенефициара (структура полностью)", + "block": "eio", + "report_group": "eio", "xml_tag": "Индекс|КодОКСМ|КодСубъектаПоОКАТО|Район|Пункт|Улица|Дом|Корп|Оф|АдрУчредитель", "xml_path": "/СообщОперКО/ИнформЧасть/СведКО/Операция/УчастникОП/УчастникЮЛ/СведЮЛ/АдрРегЮЛ/ | /СообщОперКО/ИнформЧасть/СведКО/Операция/УчастникОП/УчастникИНБОЮЛ/СведИНБОЮЛ/Учредитель/АдрУчредитель", + "source_scope": "participant", + "allow_short_lookup": true, + "allow_direct_mapping": true, + "structured_value": true, + "structured_group": "legacy_168", + "structured_role": "aggregate", + "structured_order": 0, + "join_with_space": false, "multiplies": "нет", "required": "Обязательно", "comment": "Текстовое поле, не все показатели моут присутствовать в XML Пример заполнения: 121467, 643, , 45, Г МОСКВА, , Москва г, Молодогвардейская ул, 8, 1, КВ. 28, |" }, { "index": 169, + "column_id": "legacy_169", "column_name": "Индекс", + "block": "eio", + "report_group": "eio", "xml_tag": "Индекс", "xml_path": "/СообщОперКО/ИнформЧасть/СведКО/Операция/УчастникОП/УчастникЮЛ/СведЮЛ/АдрРегЮЛ/Индекс | /СообщОперКО/ИнформЧасть/СведКО/Операция/УчастникОП/УчастникИНБОЮЛ/СведИНБОЮЛ/Учредитель/АдрУчредитель/Индекс", + "source_scope": "participant", + "allow_short_lookup": false, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "legacy_168", + "structured_role": "component", + "structured_order": 1, + "join_with_space": false, "multiplies": "нет", "required": "Обязательно", "comment": "Текст" }, { "index": 170, + "column_id": "legacy_170", "column_name": "Код страны", + "block": "eio", + "report_group": "eio", "xml_tag": "КодОКСМ", "xml_path": "/СообщОперКО/ИнформЧасть/СведКО/Операция/УчастникОП/УчастникЮЛ/СведЮЛ/АдрРегЮЛ/КодОКСМ | /СообщОперКО/ИнформЧасть/СведКО/Операция/УчастникОП/УчастникИНБОЮЛ/СведИНБОЮЛ/Учредитель/АдрУчредитель/КодОКСМ", + "source_scope": "participant", + "allow_short_lookup": false, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "legacy_168", + "structured_role": "component", + "structured_order": 2, + "join_with_space": false, "multiplies": "нет", "required": "Обязательно", "comment": "текст" }, { "index": 171, + "column_id": "legacy_171", "column_name": "ОКАТО", + "block": "eio", + "report_group": "eio", "xml_tag": "КодСубъектаПоОКАТО", "xml_path": "/СообщОперКО/ИнформЧасть/СведКО/Операция/УчастникОП/УчастникЮЛ/СведЮЛ/АдрРегЮЛ/КодСубъектаПоОКАТО | /СообщОперКО/ИнформЧасть/СведКО/Операция/УчастникОП/УчастникИНБОЮЛ/СведИНБОЮЛ/Учредитель/АдрУчредитель/КодСубъектаПоОКАТО", + "source_scope": "participant", + "allow_short_lookup": false, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "legacy_168", + "structured_role": "component", + "structured_order": 3, + "join_with_space": false, "multiplies": "нет", "required": "Обязательно", "comment": "текст" }, { "index": 172, + "column_id": "legacy_172", "column_name": "Район", + "block": "eio", + "report_group": "eio", "xml_tag": "Район", "xml_path": "/СообщОперКО/ИнформЧасть/СведКО/Операция/УчастникОП/УчастникЮЛ/СведЮЛ/АдрРегЮЛ/Район | /СообщОперКО/ИнформЧасть/СведКО/Операция/УчастникОП/УчастникИНБОЮЛ/СведИНБОЮЛ/Учредитель/АдрУчредитель/Район", + "source_scope": "participant", + "allow_short_lookup": false, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "legacy_168", + "structured_role": "component", + "structured_order": 4, + "join_with_space": false, "multiplies": "нет", "required": "Обязательно", "comment": "текст" }, { "index": 173, + "column_id": "legacy_173", "column_name": "Населенный пункт", + "block": "eio", + "report_group": "eio", "xml_tag": "Пункт", "xml_path": "/СообщОперКО/ИнформЧасть/СведКО/Операция/УчастникОП/УчастникЮЛ/СведЮЛ/АдрРегЮЛ/Пункт | /СообщОперКО/ИнформЧасть/СведКО/Операция/УчастникОП/УчастникИНБОЮЛ/СведИНБОЮЛ/Учредитель/АдрУчредитель/Пункт", + "source_scope": "participant", + "allow_short_lookup": false, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "legacy_168", + "structured_role": "component", + "structured_order": 5, + "join_with_space": false, "multiplies": "нет", "required": "Обязательно", "comment": "текст" }, { "index": 174, + "column_id": "legacy_174", "column_name": "Улица", + "block": "eio", + "report_group": "eio", "xml_tag": "Улица", "xml_path": "/СообщОперКО/ИнформЧасть/СведКО/Операция/УчастникОП/УчастникЮЛ/СведЮЛ/АдрРегЮЛ/Улица | /СообщОперКО/ИнформЧасть/СведКО/Операция/УчастникОП/УчастникИНБОЮЛ/СведИНБОЮЛ/Учредитель/АдрУчредитель/Улица", + "source_scope": "participant", + "allow_short_lookup": false, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "legacy_168", + "structured_role": "component", + "structured_order": 6, + "join_with_space": false, "multiplies": "нет", "required": "Обязательно", "comment": "текст" }, { "index": 175, + "column_id": "legacy_175", "column_name": "Дом", + "block": "eio", + "report_group": "eio", "xml_tag": "Дом", "xml_path": "/СообщОперКО/ИнформЧасть/СведКО/Операция/УчастникОП/УчастникЮЛ/СведЮЛ/АдрРегЮЛ/Дом | /СообщОперКО/ИнформЧасть/СведКО/Операция/УчастникОП/УчастникИНБОЮЛ/СведИНБОЮЛ/Учредитель/АдрУчредитель/Дом", + "source_scope": "participant", + "allow_short_lookup": false, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "legacy_168", + "structured_role": "component", + "structured_order": 7, + "join_with_space": false, "multiplies": "нет", "required": "Обязательно", "comment": "текст" }, { "index": 176, + "column_id": "legacy_176", "column_name": "Корпус", + "block": "eio", + "report_group": "eio", "xml_tag": "Корп", "xml_path": "/СообщОперКО/ИнформЧасть/СведКО/Операция/УчастникОП/УчастникЮЛ/СведЮЛ/АдрРегЮЛ/Корп | /СообщОперКО/ИнформЧасть/СведКО/Операция/УчастникОП/УчастникИНБОЮЛ/СведИНБОЮЛ/Учредитель/АдрУчредитель/Корп", + "source_scope": "participant", + "allow_short_lookup": false, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "legacy_168", + "structured_role": "component", + "structured_order": 8, + "join_with_space": false, "multiplies": "нет", "required": "Обязательно", "comment": "текст" }, { "index": 177, + "column_id": "legacy_177", "column_name": "Квартира", + "block": "eio", + "report_group": "eio", "xml_tag": "Оф", "xml_path": "/СообщОперКО/ИнформЧасть/СведКО/Операция/УчастникОП/УчастникЮЛ/СведЮЛ/АдрРегЮЛ/Оф | /СообщОперКО/ИнформЧасть/СведКО/Операция/УчастникОП/УчастникИНБОЮЛ/СведИНБОЮЛ/Учредитель/АдрУчредитель/Оф", + "source_scope": "participant", + "allow_short_lookup": false, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "legacy_168", + "structured_role": "component", + "structured_order": 9, + "join_with_space": false, "multiplies": "нет", "required": "Обязательно", "comment": "текст" }, { "index": 178, + "column_id": "legacy_178", "column_name": "Место государственной регистрации ЕИО/Бенефициара (одной строкой)", + "block": "eio", + "report_group": "eio", "xml_tag": "АдресСтрока", "xml_path": "/СообщОперКО/ИнформЧасть/СведКО/Операция/УчастникОП/УчастникЮЛ/СведЕИО/ЮЛЕИО/АдресСтрока | /СообщОперКО/ИнформЧасть/СведКО/Операция/УчастникОП/УчастникЮЛ/БенефициарЮЛ/ФЛБенефициар/АдрРег/АдресСтрока", + "source_scope": "participant", + "allow_short_lookup": false, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "", + "structured_role": "", + "structured_order": 0, + "join_with_space": false, "multiplies": "нет", "required": "Обязательно", "comment": "Текстовое поле" }, { "index": 179, + "column_id": "legacy_179", "column_name": "Место государственной регистрации ЕИО/Бенефициара (структура полностью)", + "block": "eio", + "report_group": "eio", "xml_tag": "Индекс|КодОКСМ|КодСубъектаПоОКАТО|Район|Пункт|Улица|Дом|Корп|Оф", "xml_path": "/СообщОперКО/ИнформЧасть/СведКО/Операция/УчастникОП/УчастникЮЛ/СведЕИО/ЮЛЕИО/АдрРегЮЛ/ | /СообщОперКО/ИнформЧасть/СведКО/Операция/УчастникОП/УчастникЮЛ/БенефициарЮЛ/ФЛБенефициар/АдрРег/", + "source_scope": "participant", + "allow_short_lookup": true, + "allow_direct_mapping": true, + "structured_value": true, + "structured_group": "", + "structured_role": "", + "structured_order": 0, + "join_with_space": false, "multiplies": "нет", "required": "Обязательно", "comment": "Текстовое поле, не все показатели моут присутствовать в XML Пример заполнения: 121467, 643, , 45, Г МОСКВА, , Москва г, Молодогвардейская ул, 8, 1, КВ. 28, |" }, { "index": 180, + "column_id": "legacy_180", "column_name": "ДУЛ ЕИО/Бенефициара (структура полностью)", + "block": "eio", + "report_group": "eio", "xml_tag": "ВидДокКод|ИноеНаименованиеДок|СерияДок|НомДок|ДатВыдачиДок|КемВыданДок|КодПодр|СведДокУдЛич", "xml_path": "/СообщОперКО/ИнформЧасть/СведКО/Операция/УчастникОП/УчастникЮЛ/СведЕИО/ФЛЕИО/СведДокУдЛичн/ВидДокКод | /СообщОперКО/ИнформЧасть/СведКО/Операция/УчастникОП/УчастникЮЛ/БенефициарЮЛ/ФЛБенефициар/СведДокУдЛичн", + "source_scope": "participant", + "allow_short_lookup": true, + "allow_direct_mapping": true, + "structured_value": true, + "structured_group": "legacy_180", + "structured_role": "aggregate", + "structured_order": 0, + "join_with_space": false, "multiplies": "нет", "required": "обязательно", "comment": "Данные собранные в одном поле. Не все теги могут быть переданы в XML пример Вид документа: 21 Серия документа: 0104 Номер документа: 476635 Орган, выдавший документ: Отделом внутренних дел Красногорского района Алтайского края Код подразделения: 222-022Дата выдачи: 23/08/2005 | Серия документа: 0104 | Номер документа: 476635 | Орган, выдавший документ: Отделом внутренних дел Красногорского района Алтайского края | Код подразделения: 222-022 | Дата выдачи: 23/08/2005" }, { "index": 181, + "column_id": "legacy_181", "column_name": "Признак ДУЛ", + "block": "eio", + "report_group": "eio", "xml_tag": "ДокУдЛичн", "xml_path": "/СообщОперКО/ИнформЧасть/СведКО/Операция/УчастникОП/УчастникЮЛ/СведЕИО/ФЛЕИО/Док/УдЛичн | /СообщОперКО/ИнформЧасть/СведКО/Операция/УчастникОП/УчастникЮЛ/БенефициарЮЛ/ФЛБенефициар/ДокУдЛичн", + "source_scope": "participant", + "allow_short_lookup": false, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "legacy_180", + "structured_role": "component", + "structured_order": 1, + "join_with_space": false, "multiplies": "нет", "required": "обязательно", "comment": "Данные могут оставаться пустыми" }, { "index": 182, + "column_id": "legacy_182", "column_name": "Код вида документа/Наименование", + "block": "eio", + "report_group": "eio", "xml_tag": "ВидДокКод", "xml_path": "/СообщОперКО/ИнформЧасть/СведКО/Операция/УчастникОП/УчастникЮЛ/СведЕИО/ФЛЕИО/СведДокУдЛичн/ВидДокКод | /СообщОперКО/ИнформЧасть/СведКО/Операция/УчастникОП/УчастникЮЛ/БенефициарЮЛ/ФЛБенефициар/СведДокУдЛичн/ВидДокКод", + "source_scope": "participant", + "allow_short_lookup": false, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "legacy_180", + "structured_role": "component", + "structured_order": 2, + "join_with_space": false, "multiplies": "нет", "required": "обязательно", "comment": "числовой показатель." }, { "index": 183, - "column_name": "Серия", + "column_id": "legacy_183", + "column_name": "Номер", + "block": "eio", + "report_group": "eio", "xml_tag": "СерияДок", "xml_path": "/СообщОперКО/ИнформЧасть/СведКО/Операция/УчастникОП/УчастникЮЛ/СведЕИО/ФЛЕИО/СведДокУдЛичн/СерияДок | /СообщОперКО/ИнформЧасть/СведКО/Операция/УчастникОП/УчастникЮЛ/БенефициарЮЛ/ФЛБенефициар/СведДокУдЛичн/СерияДок", + "source_scope": "participant", + "allow_short_lookup": false, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "legacy_180", + "structured_role": "component", + "structured_order": 3, + "join_with_space": false, "multiplies": "нет", "required": "обязательно", "comment": "числовой показатель" }, { "index": 184, + "column_id": "legacy_184", "column_name": "Номер", + "block": "eio", + "report_group": "eio", "xml_tag": "НомДок", "xml_path": "/СообщОперКО/ИнформЧасть/СведКО/Операция/УчастникОП/УчастникЮЛ/СведЕИО/ФЛЕИО/СведДокУдЛичн/НомДок | /СообщОперКО/ИнформЧасть/СведКО/Операция/УчастникОП/УчастникЮЛ/БенефициарЮЛ/ФЛБенефициар/СведДокУдЛичн/НомДок", + "source_scope": "participant", + "allow_short_lookup": false, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "legacy_180", + "structured_role": "component", + "structured_order": 4, + "join_with_space": false, "multiplies": "нет", "required": "обязательно", "comment": "числовой показатель" }, { "index": 185, + "column_id": "legacy_185", "column_name": "Орган, выдавший документ", + "block": "eio", + "report_group": "eio", "xml_tag": "КемВыданДок", "xml_path": "/СообщОперКО/ИнформЧасть/СведКО/Операция/УчастникОП/УчастникЮЛ/СведЕИО/ФЛЕИО/СведДокУдЛичн/КемВыданДок | /СообщОперКО/ИнформЧасть/СведКО/Операция/УчастникОП/УчастникЮЛ/БенефициарЮЛ/ФЛБенефициар/СведДокУдЛичн/КемВыданДок", + "source_scope": "participant", + "allow_short_lookup": false, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "legacy_180", + "structured_role": "component", + "structured_order": 5, + "join_with_space": false, "multiplies": "нет", "required": "необязательно", "comment": "текст" }, { "index": 186, + "column_id": "legacy_186", "column_name": "КП", + "block": "eio", + "report_group": "eio", "xml_tag": "КодПодр", "xml_path": "/СообщОперКО/ИнформЧасть/СведКО/Операция/УчастникОП/УчастникЮЛ/СведЕИО/ФЛЕИО/СведДокУдЛичн/КодПодр | /СообщОперКО/ИнформЧасть/СведКО/Операция/УчастникОП/УчастникЮЛ/БенефициарЮЛ/ФЛБенефициар/СведДокУдЛичн/КодПодр", + "source_scope": "participant", + "allow_short_lookup": false, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "legacy_180", + "structured_role": "component", + "structured_order": 6, + "join_with_space": false, "multiplies": "", "required": "", "comment": "" }, { "index": 187, + "column_id": "legacy_187", "column_name": "Дата выдачи", + "block": "eio", + "report_group": "eio", "xml_tag": "ДатВыдачиДок", "xml_path": "/СообщОперКО/ИнформЧасть/СведКО/Операция/УчастникОП/УчастникЮЛ/СведЕИО/ФЛЕИО/СведДокУдЛичн/ДатВыдачиДок | /СообщОперКО/ИнформЧасть/СведКО/Операция/УчастникОП/УчастникЮЛ/БенефициарЮЛ/ФЛБенефициар/СведДокУдЛичн/ДатВыдачиДок", + "source_scope": "participant", + "allow_short_lookup": false, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "legacy_180", + "structured_role": "component", + "structured_order": 7, + "join_with_space": false, "multiplies": "нет", "required": "обязательно", "comment": "дата, формат ДД/ММ/ГГГГ" }, { "index": 188, + "column_id": "legacy_188", "column_name": "Подтверждающий документ (структура полностью)", + "block": "eio", + "report_group": "eio", "xml_tag": "ВидДокКод|ИноеНаименованиеДок|СерияДокПреб|НомДокПреб|НачПравПреб|ОкончПравПреб", "xml_path": "/СообщОперКО/ИнформЧасть/СведКО/Операция/УчастникОП/УчастникЮЛ/СведЕИО/ФЛЕИО/СведДокПреб/ВидДокКод | /СообщОперКО/ИнформЧасть/СведКО/Операция/УчастникОП/УчастникЮЛ/БенефициарЮЛ/ФЛБенефициар/СведДокПреб/ВидДокКод | /СообщОперКО/ИнформЧасть/СведКО/Операция/УчастникОП/УчастникЮЛ/БенефициарЮЛ/ФЛБенефициар/СведДокПреб/ИноеНаименованиеДок | /СообщОперКО/ИнформЧасть/СведКО/Операция/УчастникОП/УчастникЮЛ/БенефициарЮЛ/ФЛБенефициар/СведДокПреб/СерияДокПреб | /СообщОперКО/ИнформЧасть/СведКО/Операция/УчастникОП/УчастникЮЛ/БенефициарЮЛ/ФЛБенефициар/СведДокПреб/НомДокПреб | /СообщОперКО/ИнформЧасть/СведКО/Операция/УчастникОП/УчастникЮЛ/БенефициарЮЛ/ФЛБенефициар/СведДокПреб/НачПравПреб | /СообщОперКО/ИнформЧасть/СведКО/Операция/УчастникОП/УчастникЮЛ/БенефициарЮЛ/ФЛБенефициар/СведДокПреб/ОкончПравПреб", + "source_scope": "participant", + "allow_short_lookup": true, + "allow_direct_mapping": true, + "structured_value": true, + "structured_group": "legacy_188", + "structured_role": "aggregate", + "structured_order": 0, + "join_with_space": false, "multiplies": "нет", "required": "обязательно", "comment": "текстовый показатель. данные могут оставаться пустыми текстовый показатель. данные могут оставаться пустыми" }, { "index": 189, + "column_id": "legacy_189", "column_name": "Код вида документа/Наименование", + "block": "eio", + "report_group": "eio", "xml_tag": "ВидДокКод", "xml_path": "/СообщОперКО/ИнформЧасть/СведКО/Операция/УчастникОП/УчастникЮЛ/СведЕИО/ФЛЕИО/СведДокПреб/ВидДокКод | /СообщОперКО/ИнформЧасть/СведКО/Операция/УчастникОП/УчастникЮЛ/БенефициарЮЛ/ФЛБенефициар/СведДокПреб/ВидДокКод", + "source_scope": "participant", + "allow_short_lookup": false, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "legacy_188", + "structured_role": "component", + "structured_order": 1, + "join_with_space": false, "multiplies": "нет", "required": "необязательно", "comment": "текстовый показатель. данные могут оставаться пустыми" }, { "index": 190, + "column_id": "legacy_190", "column_name": "Серия", + "block": "eio", + "report_group": "eio", "xml_tag": "СерияДокПреб", "xml_path": "/СообщОперКО/ИнформЧасть/СведКО/Операция/УчастникОП/УчастникЮЛ/СведЕИО/ФЛЕИО/СведДокПреб/СерияДокПреб | /СообщОперКО/ИнформЧасть/СведКО/Операция/УчастникОП/УчастникЮЛ/БенефициарЮЛ/ФЛБенефициар/СведДокПреб/СерияДокПреб", + "source_scope": "participant", + "allow_short_lookup": false, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "legacy_188", + "structured_role": "component", + "structured_order": 2, + "join_with_space": false, "multiplies": "нет", "required": "необязательно", "comment": "данные могут не передаваться в XML и оставаться пустыми" }, { "index": 191, + "column_id": "legacy_191", "column_name": "Номер", + "block": "eio", + "report_group": "eio", "xml_tag": "НомДокПреб", "xml_path": "/СообщОперКО/ИнформЧасть/СведКО/Операция/УчастникОП/УчастникЮЛ/СведЕИО/ФЛЕИО/СведДокПреб/НомДокПреб | /СообщОперКО/ИнформЧасть/СведКО/Операция/УчастникОП/УчастникЮЛ/БенефициарЮЛ/ФЛБенефициар/СведДокПреб/НомДокПреб", + "source_scope": "participant", + "allow_short_lookup": false, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "legacy_188", + "structured_role": "component", + "structured_order": 3, + "join_with_space": false, "multiplies": "нет", "required": "необязательно", "comment": "данные могут не передаваться в XML и оставаться пустыми" }, { "index": 192, + "column_id": "legacy_192", "column_name": "Дата начала/окончания срока", + "block": "eio", + "report_group": "eio", "xml_tag": "НачПравПреб", "xml_path": "/СообщОперКО/ИнформЧасть/СведКО/Операция/УчастникОП/УчастникЮЛ/СведЕИО/ФЛЕИО/СведДокПреб/НачПравПреб | /СообщОперКО/ИнформЧасть/СведКО/Операция/УчастникОП/УчастникЮЛ/БенефициарЮЛ/ФЛБенефициар/СведДокПреб/НачПравПреб", + "source_scope": "participant", + "allow_short_lookup": false, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "legacy_188", + "structured_role": "component", + "structured_order": 4, + "join_with_space": false, "multiplies": "нет", "required": "необязательно", "comment": "данные могут не передаваться в XML и оставаться пустыми. Формат: ДД/ММ/ГГ" }, { "index": 193, + "column_id": "legacy_193", "column_name": "Сведения миграционной карты ЕИО/Бенефициара", + "block": "eio", + "report_group": "eio", "xml_tag": "", "xml_path": "", + "source_scope": "any", + "allow_short_lookup": true, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "", + "structured_role": "", + "structured_order": 0, + "join_with_space": false, "multiplies": "", "required": "", "comment": "" }, { "index": 194, + "column_id": "legacy_194", "column_name": "Вид ЦП", + "block": "cp", + "report_group": "cp", "xml_tag": "ВидЦП", "xml_path": "/СообщОперКО/ИнформЧасть/СведКО/Операция/СведЦП/ВидЦП", + "source_scope": "operation", + "allow_short_lookup": false, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "", + "structured_role": "", + "structured_order": 0, + "join_with_space": false, "multiplies": "нет", "required": "обязательно", "comment": "показатель считается обязательным, но в XML нет данных" }, { "index": 195, + "column_id": "legacy_195", "column_name": "Идентиф номер выпуска ЦП", + "block": "cp", + "report_group": "cp", "xml_tag": "ИдентификаторЦП", "xml_path": "/СообщОперКО/ИнформЧасть/СведКО/Операция/СведЦП/ИдентификаторЦП", + "source_scope": "operation", + "allow_short_lookup": false, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "", + "structured_role": "", + "structured_order": 0, + "join_with_space": false, "multiplies": "нет", "required": "обязательно", "comment": "показатель считается обязательным, но в XML нет данных" }, { "index": 196, + "column_id": "legacy_196", "column_name": "Код валюты", + "block": "cp", + "report_group": "cp", "xml_tag": "КодВалЦП", "xml_path": "/СообщОперКО/ИнформЧасть/СведКО/Операция/СведЦП/КодВалЦП", + "source_scope": "operation", + "allow_short_lookup": false, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "", + "structured_role": "", + "structured_order": 0, + "join_with_space": false, "multiplies": "нет", "required": "обязательно", "comment": "Данные могут оставаться пустыми" }, { "index": 197, + "column_id": "legacy_197", "column_name": "Стоимость ЦП", + "block": "cp", + "report_group": "cp", "xml_tag": "СтоимостьЦП", "xml_path": "/СообщОперКО/ИнформЧасть/СведКО/Операция/СведЦП/СтоимостьЦП", + "source_scope": "operation", + "allow_short_lookup": false, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "", + "structured_role": "", + "structured_order": 0, + "join_with_space": false, "multiplies": "нет", "required": "обязательно", "comment": "Данные могут оставаться пустыми" }, { "index": 198, + "column_id": "legacy_198", "column_name": "Количество ЦП", + "block": "cp", + "report_group": "cp", "xml_tag": "КолЦП", "xml_path": "/СообщОперКО/ИнформЧасть/СведКО/Операция/СведЦП/КолЦП", + "source_scope": "operation", + "allow_short_lookup": false, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "", + "structured_role": "", + "structured_order": 0, + "join_with_space": false, "multiplies": "нет", "required": "обязательно", "comment": "показатель считается обязательным, но в XML нет данных" }, { "index": 199, + "column_id": "legacy_199", "column_name": "Наименование/ ФИО эмитента ЦП", + "block": "cp", + "report_group": "cp", "xml_tag": "НаимЭмитентЦП", "xml_path": "/СообщОперКО/ИнформЧасть/СведКО/Операция/СведЦП/Эмитент/НаимЭмитентЦП/ЮрЛицо | /СообщОперКО/ИнформЧасть/СведКО/Операция/СведЦП/Эмитент/НаимЭмитентЦП/ФизЛицо/ФИОСтрока", + "source_scope": "operation", + "allow_short_lookup": false, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "", + "structured_role": "", + "structured_order": 0, + "join_with_space": false, "multiplies": "нет", "required": "обязательно", "comment": "показатель считается обязательным, но в XML нет данных" }, { "index": 200, + "column_id": "legacy_200", "column_name": "Тип эмитента", + "block": "cp", + "report_group": "cp", "xml_tag": "ТипЭмитентЦП", "xml_path": "/СообщОперКО/ИнформЧасть/СведКО/Операция/СведЦП/Эмитент/ТипЭмитентЦП", + "source_scope": "operation", + "allow_short_lookup": false, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "", + "structured_role": "", + "structured_order": 0, + "join_with_space": false, "multiplies": "нет", "required": "обязательно", "comment": "показатель считается обязательным, но в XML нет данных" }, { "index": 201, + "column_id": "legacy_201", "column_name": "Признак резидентства", + "block": "cp", + "report_group": "cp", "xml_tag": "ПризнЭмитентЦП", "xml_path": "/СообщОперКО/ИнформЧасть/СведКО/Операция/СведЦП/Эмитент/ПризнЭмитентЦП", + "source_scope": "operation", + "allow_short_lookup": false, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "", + "structured_role": "", + "structured_order": 0, + "join_with_space": false, "multiplies": "нет", "required": "обязательно", "comment": "показатель считается обязательным, но в XML нет данных" }, { "index": 202, + "column_id": "legacy_202", "column_name": "ИНН эмитента", + "block": "cp", + "report_group": "cp", "xml_tag": "ИННЭмитентЦП", "xml_path": "/СообщОперКО/ИнформЧасть/СведКО/Операция/СведЦП/Эмитент/ИННЭмитентЦП", + "source_scope": "operation", + "allow_short_lookup": false, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "", + "structured_role": "", + "structured_order": 0, + "join_with_space": false, "multiplies": "нет", "required": "обязательно", "comment": "Данные могут оставаться пустыми" }, { "index": 203, + "column_id": "legacy_203", "column_name": "ОГРН (ОГРНИП) эмитента", + "block": "cp", + "report_group": "cp", "xml_tag": "ОГРНЭмитентЦП", "xml_path": "/СообщОперКО/ИнформЧасть/СведКО/Операция/СведЦП/Эмитент/ОГРНЭмитентЦП", + "source_scope": "operation", + "allow_short_lookup": false, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "", + "structured_role": "", + "structured_order": 0, + "join_with_space": false, "multiplies": "нет", "required": "обязательно", "comment": "показатель считается обязательным, но в XML нет данных" }, { "index": 204, + "column_id": "legacy_204", "column_name": "Дополнительные сведения", + "block": "cp", + "report_group": "cp", "xml_tag": "КомментЦП", "xml_path": "/СообщОперКО/ИнформЧасть/СведКО/Операция/СведЦП/КомментЦП", + "source_scope": "operation", + "allow_short_lookup": false, + "allow_direct_mapping": true, + "structured_value": false, + "structured_group": "", + "structured_role": "", + "structured_order": 0, + "join_with_space": false, "multiplies": "нет", "required": "обязательно", "comment": "Данные могут оставаться пустыми" diff --git a/app/pipeline/report.py b/app/pipeline/report.py index f6fdf06..4edc803 100644 --- a/app/pipeline/report.py +++ b/app/pipeline/report.py @@ -2,15 +2,22 @@ from __future__ import annotations import re import shutil +from collections.abc import Iterable from dataclasses import dataclass from datetime import date, datetime from decimal import Decimal, InvalidOperation from pathlib import Path from tempfile import NamedTemporaryFile -from typing import Iterable import xlsxwriter +from .column_constants import ( + COL_KPP, + COL_PARTICIPANT_TYPE, + PARTICIPANT_ADDRESS_OUTPUT_SOURCES, + PARTICIPANT_TYPE_UL, +) +from .column_registry import COLUMNS from .mapping import FIXED_REPORT_COLUMNS, build_fixed_row_by_index @@ -30,72 +37,21 @@ class GroupHeader: title: str -# Верхняя группирующая шапка согласно согласованным логическим категориям. -TOP_GROUP_HEADERS: tuple[GroupHeader, ...] = ( - GroupHeader(start_col=1, end_col=1, title="Служебные поля"), - GroupHeader(start_col=2, end_col=6, title="Реквизиты сообщения/КО/филиала"), +TOP_GROUP_HEADERS: tuple[GroupHeader, ...] = tuple( GroupHeader( - start_col=7, - end_col=13, - title="Идентификация записи и контрольные признаки", - ), - GroupHeader(start_col=14, end_col=36, title="Параметры операции"), - GroupHeader( - start_col=37, - end_col=48, - title="Перевод ДС и реквизиты расчетов", - ), - GroupHeader( - start_col=49, - end_col=66, - title="Места приема/выдачи наличных и авторизация ЭСП", - ), - GroupHeader( - start_col=67, - end_col=75, - title="Внесение/выдача у одного оператора (место операции)", - ), - GroupHeader( - start_col=76, - end_col=86, - title="Наличная форма и основание операции", - ), - GroupHeader( - start_col=87, - end_col=126, - title="Участник операции (базовые сведения)", - ), - GroupHeader( - start_col=127, - end_col=154, - title="Участник операции (идентификация, документы, адреса)", - ), - GroupHeader( - start_col=155, - end_col=193, - title="ЕИО/Бенефициар (идентификация, документы, адреса)", - ), - GroupHeader( - start_col=194, - end_col=204, - title="Сведения о ценных бумагах (ЦП)", - ), - GroupHeader( - start_col=205, - end_col=205, - title=( - "Колонки вне согласованной группировки (если количество полей расширится)" - ), - ), + start_col=group.start_index, + end_col=group.end_index, + title=group.title, + ) + for group in COLUMNS.report_groups() ) class StreamingReportWriter: def __init__(self) -> None: self.columns = list(FIXED_REPORT_COLUMNS) - temp_file = NamedTemporaryFile(suffix=".xlsx", delete=False) - self._temp_report_path = Path(temp_file.name) - temp_file.close() + with NamedTemporaryFile(suffix=".xlsx", delete=False) as temp_file: + self._temp_report_path = Path(temp_file.name) self.workbook = xlsxwriter.Workbook( str(self._temp_report_path), {"constant_memory": True}, @@ -138,9 +94,10 @@ class StreamingReportWriter: operation_fields=row.operation_fields, participant_fields=row.participant_fields, ) - for index, column_name in enumerate(self.columns): - raw_value = self._resolve_output_value(index + 1, data_by_index) - default_format = self._column_formats[index] + for output_index, column_name in enumerate(self.columns, start=1): + zero_based_index = output_index - 1 + raw_value = self._resolve_output_value(output_index, data_by_index) + default_format = self._column_formats[zero_based_index] value, cell_format = self._normalize_cell_value( column_name=column_name, raw_value=raw_value, @@ -148,23 +105,25 @@ class StreamingReportWriter: ) if isinstance(value, datetime) and cell_format is self._date_format: self.sheet.write_datetime( - self._next_data_row, index, value, cell_format + self._next_data_row, zero_based_index, value, cell_format ) elif self._is_text_identifier_column(column_name): self.sheet.write_string( self._next_data_row, - index, + zero_based_index, self._normalize_identifier_string( column_name, value, - column_index=index + 1, + column_index=output_index, row_by_index=data_by_index, ), ) elif cell_format is not None: - self.sheet.write(self._next_data_row, index, value, cell_format) + self.sheet.write( + self._next_data_row, zero_based_index, value, cell_format + ) else: - self.sheet.write(self._next_data_row, index, value) + self.sheet.write(self._next_data_row, zero_based_index, value) self._next_data_row += 1 def _resolve_output_value( @@ -172,15 +131,10 @@ class StreamingReportWriter: column_index: int, row_by_index: dict[int, str], ) -> object: - # В целевом шаблоне адресный блок участника ожидается со структурным - # адресом в колонке 141, поэтому на этапе выгрузки делаем сдвиг. - if column_index == 141: - return row_by_index.get(142, "") - if 142 <= column_index <= 150: - return row_by_index.get(column_index + 1, "") - if column_index == 151: - return row_by_index.get(141, "") - return row_by_index.get(column_index, "") + source_index = PARTICIPANT_ADDRESS_OUTPUT_SOURCES.get( + column_index, column_index + ) + return row_by_index.get(source_index, "") def save(self, destination: Path) -> None: destination.parent.mkdir(parents=True, exist_ok=True) @@ -261,9 +215,9 @@ class StreamingReportWriter: if "БИК" in column_name: return normalized.zfill(9) if "КПП" in column_name: - participant_type = str(row_by_index.get(109, "")).strip() + participant_type = str(row_by_index.get(COL_PARTICIPANT_TYPE, "")).strip() normalized_type = participant_type.lstrip("0") or "0" - if column_index == 122 and normalized_type != "1": + if column_index == COL_KPP and normalized_type != PARTICIPANT_TYPE_UL: return normalized return normalized.zfill(9) if "ИНН" in column_name: @@ -300,7 +254,7 @@ class StreamingReportWriter: date_part = normalized.split()[0] for fmt in ("%Y-%m-%d", "%d/%m/%Y", "%d.%m.%Y", "%Y/%m/%d"): try: - return datetime.strptime(date_part, fmt) + return datetime.strptime(date_part, fmt) # noqa: DTZ007 except ValueError: continue return None @@ -309,15 +263,16 @@ class StreamingReportWriter: try: self._temp_report_path.unlink(missing_ok=True) except Exception: # noqa: BLE001 - pass + return def __del__(self) -> None: if not getattr(self, "_is_closed", True): try: self.workbook.close() except Exception: # noqa: BLE001 - pass - self._is_closed = True + self._is_closed = True + else: + self._is_closed = True self._cleanup_temp_file() diff --git a/tests/unit/test_column_registry.py b/tests/unit/test_column_registry.py new file mode 100644 index 0000000..8fb87b0 --- /dev/null +++ b/tests/unit/test_column_registry.py @@ -0,0 +1,135 @@ +from __future__ import annotations + +import json +from pathlib import Path + +import pytest + +from app.pipeline.column_registry import ( + COLUMNS, + MAPPING_DATA_FILE, + AmbiguousColumnNameError, + ColumnRegistry, + ColumnSchemaError, +) + + +def test_registry_keeps_stable_file_name_column_id() -> None: + assert COLUMNS.index_of("legacy_001") == 1 + assert COLUMNS.meta(1).name == "Имя XML файла" + + +def test_registry_covers_all_report_columns_without_gaps() -> None: + indexes = tuple(column.index for column in COLUMNS.ordered_columns()) + + assert indexes == tuple(range(1, 205)) + assert all(column.block for column in COLUMNS.ordered_columns()) + assert all(column.report_group for column in COLUMNS.ordered_columns()) + + +def test_registry_assigns_card_columns_missing_from_original_plan() -> None: + assert COLUMNS.block("foreign_card") == tuple(range(97, 107)) + + +def test_registry_explicitly_preserves_structured_lookup_compatibility() -> None: + assert COLUMNS.meta(180).allow_short_lookup is True + assert COLUMNS.meta(153).allow_short_lookup is False + + +def test_registry_rejects_ambiguous_display_name_lookup() -> None: + assert COLUMNS.indices_named("ОКАТО") == (4, 171) + + with pytest.raises(AmbiguousColumnNameError): + COLUMNS.index_named("ОКАТО") + + +def test_registry_report_groups_are_contiguous_and_cover_schema() -> None: + covered_indexes: list[int] = [] + + for group in COLUMNS.report_groups(): + assert group.indexes == tuple(range(group.start_index, group.end_index + 1)) + covered_indexes.extend(group.indexes) + + assert covered_indexes == list(range(1, 205)) + + +@pytest.mark.parametrize( + ("field", "invalid_value"), + ( + ("index", True), + ("column_id", None), + ("column_name", ["Имя"]), + ("source_scope", {"scope": "any"}), + ("structured_order", False), + ), +) +def test_registry_rejects_invalid_scalar_types( + tmp_path: Path, field: str, invalid_value: object +) -> None: + data = _mapping_data() + data[0][field] = invalid_value + + with pytest.raises(ColumnSchemaError): + ColumnRegistry.load(_write_mapping(tmp_path, data)) + + +def test_registry_rejects_unknown_report_group(tmp_path: Path) -> None: + data = _mapping_data() + data[0]["report_group"] = "unknown_group" + + with pytest.raises(ColumnSchemaError): + ColumnRegistry.load(_write_mapping(tmp_path, data)) + + +def test_registry_rejects_unknown_business_block(tmp_path: Path) -> None: + data = _mapping_data() + data[0]["block"] = "unknown_block" + + with pytest.raises(ColumnSchemaError): + ColumnRegistry.load(_write_mapping(tmp_path, data)) + + +def test_registry_rejects_duplicate_column_ids_and_index_gaps( + tmp_path: Path, +) -> None: + data = _mapping_data() + data[1]["column_id"] = data[0]["column_id"] + data[1]["index"] = 3 + + with pytest.raises(ColumnSchemaError): + ColumnRegistry.load(_write_mapping(tmp_path, data)) + + +def test_registry_rejects_structured_group_without_aggregate( + tmp_path: Path, +) -> None: + data = _mapping_data() + aggregate = next(item for item in data if item["index"] == 50) + aggregate["structured_role"] = "component" + aggregate["structured_order"] = 10 + aggregate["structured_value"] = False + + with pytest.raises(ColumnSchemaError): + ColumnRegistry.load(_write_mapping(tmp_path, data)) + + +def test_registry_rejects_duplicate_structured_component_order( + tmp_path: Path, +) -> None: + data = _mapping_data() + first = next(item for item in data if item["index"] == 51) + second = next(item for item in data if item["index"] == 52) + second["structured_order"] = first["structured_order"] + + with pytest.raises(ColumnSchemaError): + ColumnRegistry.load(_write_mapping(tmp_path, data)) + + +def _mapping_data() -> list[dict[str, object]]: + return json.loads(MAPPING_DATA_FILE.read_text(encoding="utf-8")) + + +def _write_mapping(tmp_path: Path, data: list[dict[str, object]]) -> Path: + path = tmp_path / "mapping_table.json" + path.write_text(json.dumps(data, ensure_ascii=False), encoding="utf-8") + return path diff --git a/tests/unit/test_report.py b/tests/unit/test_report.py index 6170a1a..f4a9595 100644 --- a/tests/unit/test_report.py +++ b/tests/unit/test_report.py @@ -1,11 +1,12 @@ from __future__ import annotations -from datetime import datetime +from datetime import date, datetime from pathlib import Path from unittest.mock import patch from openpyxl import load_workbook +from app.pipeline.column_registry import COLUMNS from app.pipeline.mapping import FIXED_REPORT_COLUMNS from app.pipeline.report import TOP_GROUP_HEADERS, ReportRow, write_report @@ -64,6 +65,17 @@ def test_write_report_contains_top_group_header_row(tmp_path: Path) -> None: assert merged_ranges == expected_ranges +def test_top_group_headers_follow_registry_report_groups() -> None: + actual_ranges = tuple( + (header.start_col, header.end_col) for header in TOP_GROUP_HEADERS + ) + registry_ranges = tuple( + (group.start_index, group.end_index) for group in COLUMNS.report_groups() + ) + + assert actual_ranges == registry_ranges + + def test_write_report_converts_date_string_to_excel_date(tmp_path: Path) -> None: destination = tmp_path / "report.xlsx" rows = [ @@ -83,7 +95,7 @@ def test_write_report_converts_date_string_to_excel_date(tmp_path: Path) -> None date_col_idx = FIXED_REPORT_COLUMNS.index("Дата сообщения") + 1 cell = sheet.cell(row=3, column=date_col_idx) assert isinstance(cell.value, datetime) - assert cell.value.date() == datetime(2005, 8, 23).date() + assert cell.value.date() == date(2005, 8, 23) assert cell.number_format == "DD.MM.YYYY"