1444 lines
53 KiB
Python
1444 lines
53 KiB
Python
from __future__ import annotations
|
||
|
||
from app.pipeline import mapping
|
||
from app.pipeline.mapping import (
|
||
FIXED_REPORT_COLUMNS,
|
||
_extract_tag_candidate_keys,
|
||
build_fixed_row,
|
||
build_fixed_row_by_index,
|
||
)
|
||
|
||
|
||
def _column_with(prefix: str) -> str:
|
||
for column in FIXED_REPORT_COLUMNS:
|
||
if column.startswith(prefix):
|
||
return column
|
||
raise AssertionError(f"Колонка с префиксом '{prefix}' не найдена")
|
||
|
||
|
||
def test_build_fixed_row_maps_known_fields() -> None:
|
||
row = build_fixed_row(
|
||
file_name="f.xml",
|
||
record_id="R1",
|
||
operation_index=2,
|
||
operation_fields={
|
||
"ИдФайл": "FILE_01",
|
||
"НомерОперация": "OP_2",
|
||
"КодОперации": "5007",
|
||
"СумОперации": "100.55",
|
||
},
|
||
participant_fields={
|
||
"ИННФЛ": "123456789012",
|
||
"Тип": "01",
|
||
},
|
||
)
|
||
|
||
assert row["Имя XML файла"] == "f.xml"
|
||
assert row["Идентификатор записи"] == "R1"
|
||
assert row["Уникальный номер операции"] == "OP_2"
|
||
assert row["Код вида операции"] == "5007"
|
||
assert row["Сумма в валюте проведения"] == "100.55"
|
||
assert row[_column_with("ИНН")] == "123456789012"
|
||
assert row["Тип участника"] == "01"
|
||
|
||
|
||
def test_build_fixed_row_keeps_missing_values_empty() -> None:
|
||
row = build_fixed_row(
|
||
file_name="f.xml",
|
||
record_id="R1",
|
||
operation_index=1,
|
||
operation_fields={},
|
||
participant_fields={},
|
||
)
|
||
for column in FIXED_REPORT_COLUMNS:
|
||
assert column in row
|
||
assert row["Код вида операции"] == ""
|
||
assert row[_column_with("ИНН")] == ""
|
||
|
||
|
||
def test_build_fixed_row_does_not_take_operation_inn_for_participant() -> None:
|
||
row = build_fixed_row(
|
||
file_name="f.xml",
|
||
record_id="R1",
|
||
operation_index=1,
|
||
operation_fields={
|
||
"ИНН": "0000000000",
|
||
"Тип": "99",
|
||
},
|
||
participant_fields={
|
||
"ИННФЛ": "111111111111",
|
||
"Тип": "01",
|
||
},
|
||
)
|
||
assert row[_column_with("ИНН")] == "111111111111"
|
||
assert row["Тип участника"] == "01"
|
||
|
||
|
||
def test_fixed_report_columns_over_200() -> None:
|
||
assert len(FIXED_REPORT_COLUMNS) == 204
|
||
assert FIXED_REPORT_COLUMNS[126] == "Признак принадлежности к публичным лицам"
|
||
|
||
|
||
def test_build_fixed_row_uses_alternative_path_leaf_for_emitent_name() -> None:
|
||
row = build_fixed_row(
|
||
file_name="f.xml",
|
||
record_id="R1",
|
||
operation_index=1,
|
||
operation_fields={
|
||
"СведЦП.Эмитент.НаимЭмитентЦП.ФизЛицо.ФИОСтрока": "Эмитент ФЛ",
|
||
},
|
||
participant_fields={},
|
||
)
|
||
assert row["Наименование/ ФИО эмитента ЦП"] == "Эмитент ФЛ"
|
||
|
||
|
||
def test_build_fixed_row_maps_dotted_participant_keys() -> None:
|
||
row = build_fixed_row(
|
||
file_name="f.xml",
|
||
record_id="R1",
|
||
operation_index=1,
|
||
operation_fields={},
|
||
participant_fields={
|
||
"УчастникФЛИП.СведФЛИП.ИННФЛИП": "123456789012",
|
||
"УчастникФЛИП.СведФЛИП.СведДокУдЛичн.НомДок": "451099",
|
||
},
|
||
)
|
||
assert row[_column_with("ИНН")] == "123456789012"
|
||
assert row["Номер"] == "451099"
|
||
|
||
|
||
def test_build_fixed_row_splits_pipe_separated_xml_tag_values() -> None:
|
||
row = build_fixed_row(
|
||
file_name="f.xml",
|
||
record_id="R1",
|
||
operation_index=1,
|
||
operation_fields={},
|
||
participant_fields={
|
||
"УчастникФЛИП.СведФЛИП.АдрРег.Индекс": "674500",
|
||
},
|
||
)
|
||
assert row["Адрес по структуре (целый)"] == "674500"
|
||
|
||
|
||
def test_extract_tag_candidate_keys_supports_comma_separator() -> None:
|
||
candidates = _extract_tag_candidate_keys(
|
||
"КППЮЛ, ИдентификацияФЛ, ПризнакОргФормаИНБОЮЛ"
|
||
)
|
||
assert candidates == ("КППЮЛ", "ИдентификацияФЛ", "ПризнакОргФормаИНБОЮЛ")
|
||
|
||
|
||
def test_build_fixed_row_uses_first_suffix_value_from_index() -> None:
|
||
row = build_fixed_row(
|
||
file_name="f.xml",
|
||
record_id="R1",
|
||
operation_index=1,
|
||
operation_fields={},
|
||
participant_fields={
|
||
"УчастникФЛИП.Первый.ИННФЛИП": "111111111111",
|
||
"УчастникФЛИП.Второй.ИННФЛИП": "222222222222",
|
||
},
|
||
)
|
||
assert row[_column_with("ИНН")] == "111111111111"
|
||
|
||
|
||
def test_build_fixed_row_skips_empty_suffix_values_in_index() -> None:
|
||
row = build_fixed_row(
|
||
file_name="f.xml",
|
||
record_id="R1",
|
||
operation_index=1,
|
||
operation_fields={},
|
||
participant_fields={
|
||
"УчастникФЛИП.Первый.ИННФЛИП": "",
|
||
"УчастникФЛИП.Второй.ИННФЛИП": "222222222222",
|
||
},
|
||
)
|
||
assert row[_column_with("ИНН")] == "222222222222"
|
||
|
||
|
||
def test_mapping_normalizes_each_payload_path_only_constant_times(monkeypatch) -> None:
|
||
calls = 0
|
||
original = mapping._normalize_indexed_path
|
||
|
||
def counted(path: str) -> str:
|
||
nonlocal calls
|
||
calls += 1
|
||
return original(path)
|
||
|
||
monkeypatch.setattr(mapping, "_normalize_indexed_path", counted)
|
||
|
||
operation_fields = {
|
||
"НомерОперация": "OP1",
|
||
"КодОперации": "6001",
|
||
}
|
||
participant_fields = {
|
||
"УчастникЮЛ.СведЮЛ.НаимЮЛ": "АО СИРИУС",
|
||
"УчастникЮЛ.СведЮЛ.ИННЮЛ": "2820000210",
|
||
"УчастникЮЛ.СведЕИО[0].ФЛЕИО.ФИОФЛИП.Фам": "Музалёв",
|
||
"УчастникЮЛ.СведЕИО[0].ФЛЕИО.ИННФЛИП": "410116812922",
|
||
}
|
||
build_fixed_row_by_index(
|
||
file_name="f.xml",
|
||
record_id="R1",
|
||
operation_index=1,
|
||
operation_fields=operation_fields,
|
||
participant_fields=participant_fields,
|
||
)
|
||
|
||
assert calls == 2 * (len(operation_fields) + len(participant_fields))
|
||
|
||
|
||
def test_structured_address_is_built_from_right_columns() -> None:
|
||
row = build_fixed_row(
|
||
file_name="f.xml",
|
||
record_id="R1",
|
||
operation_index=1,
|
||
operation_fields={},
|
||
participant_fields={
|
||
"УчастникФЛИП.СведФЛИП.АдрРег.Индекс": "674500",
|
||
"УчастникФЛИП.СведФЛИП.АдрРег.КодОКСМ": "643",
|
||
"УчастникФЛИП.СведФЛИП.АдрРег.Пункт": "Москва",
|
||
"УчастникФЛИП.СведФЛИП.АдрРег.Улица": "Тверская",
|
||
"УчастникФЛИП.СведФЛИП.АдрРег.Дом": "1",
|
||
},
|
||
)
|
||
assert row["Адрес по структуре (целый)"] == "674500, 643, Москва, Тверская, 1"
|
||
|
||
|
||
def test_one_line_address_clears_structured_and_component_columns() -> None:
|
||
row = build_fixed_row(
|
||
file_name="f.xml",
|
||
record_id="R1",
|
||
operation_index=1,
|
||
operation_fields={},
|
||
participant_fields={
|
||
"АдресСтрока": "г. Москва, Тверская, 1",
|
||
"Индекс": "674500",
|
||
"КодОКСМ": "643",
|
||
"Улица": "Тверская",
|
||
"Дом": "1",
|
||
},
|
||
)
|
||
assert row["Адрес в одной строке"] == "г. Москва, Тверская, 1"
|
||
assert row["Адрес по структуре (целый)"] == ""
|
||
assert row["Индекс"] == ""
|
||
assert row["Код страны"] == ""
|
||
assert row["Улица"] == ""
|
||
assert row["Дом"] == ""
|
||
|
||
|
||
def test_fio_columns_prefer_participant_fields_over_operation_common_fields() -> None:
|
||
row = build_fixed_row(
|
||
file_name="f.xml",
|
||
record_id="R1",
|
||
operation_index=1,
|
||
operation_fields={
|
||
"Фам": "Кузнецов",
|
||
"Имя": "Сергей",
|
||
"Отч": "Владимирович",
|
||
},
|
||
participant_fields={
|
||
"УчастникФЛИП.СведФЛИП.ФИОФЛИП.Фам": "Азимов",
|
||
"УчастникФЛИП.СведФЛИП.ФИОФЛИП.Имя": "Ислом",
|
||
"УчастникФЛИП.СведФЛИП.ФИОФЛИП.Отч": "Каримович",
|
||
},
|
||
)
|
||
assert row["Фамилия"] == "Азимов"
|
||
assert row["Имя"] == "Ислом"
|
||
assert row["Отчество"] == "Каримович"
|
||
assert row["ФИО (по структуре полностью)"] == "Азимов Ислом Каримович"
|
||
|
||
|
||
def test_one_line_fio_clears_structured_and_component_fio_columns() -> None:
|
||
row = build_fixed_row(
|
||
file_name="f.xml",
|
||
record_id="R1",
|
||
operation_index=1,
|
||
operation_fields={},
|
||
participant_fields={
|
||
"ФИОСтрока": "Азимов Ислом Каримович",
|
||
"Фам": "Азимов",
|
||
"Имя": "Ислом",
|
||
"Отч": "Каримович",
|
||
},
|
||
)
|
||
assert row["ФИО (в одной строке)"] == "Азимов Ислом Каримович"
|
||
assert row["ФИО (по структуре полностью)"] == ""
|
||
assert row["Фамилия"] == ""
|
||
assert row["Имя"] == ""
|
||
assert row["Отчество"] == ""
|
||
assert row["Наименование ЮЛ/ФИО ( по структуре полный)"] == ""
|
||
|
||
|
||
def test_structured_column_is_not_filled_directly_from_single_line_tag() -> None:
|
||
row = build_fixed_row(
|
||
file_name="f.xml",
|
||
record_id="R1",
|
||
operation_index=1,
|
||
operation_fields={},
|
||
participant_fields={
|
||
"АдресСтрока": "г. Москва, ул. Пример, д. 1",
|
||
},
|
||
)
|
||
assert row["Адрес в одной строке"] == "г. Москва, ул. Пример, д. 1"
|
||
assert (
|
||
row[
|
||
"Адрес ЮЛ/ Адрес места жительства (места нахождения) "
|
||
"ЕИО/Бенефициара (одной строкой)"
|
||
]
|
||
== ""
|
||
)
|
||
|
||
|
||
def test_structured_column_without_component_block_joins_candidate_values() -> None:
|
||
row = build_fixed_row(
|
||
file_name="f.xml",
|
||
record_id="R1",
|
||
operation_index=1,
|
||
operation_fields={},
|
||
participant_fields={
|
||
"УчастникЮЛ.СведЕИО.ЮЛЕИО.АдрРег.Индекс": "121467",
|
||
"УчастникЮЛ.СведЕИО.ЮЛЕИО.АдрРег.КодОКСМ": "643",
|
||
"УчастникЮЛ.СведЕИО.ЮЛЕИО.АдрРег.Пункт": "Москва",
|
||
"УчастникЮЛ.СведЕИО.ЮЛЕИО.АдрРег.Улица": "Молодогвардейская",
|
||
"УчастникЮЛ.СведЕИО.ЮЛЕИО.АдрРег.Дом": "8",
|
||
"УчастникЮЛ.СведЕИО.ЮЛЕИО.АдрРег.Корп": "1",
|
||
"УчастникЮЛ.СведЕИО.ЮЛЕИО.АдрРег.Оф": "28",
|
||
},
|
||
)
|
||
assert (
|
||
row["Место государственной регистрации ЕИО/Бенефициара (структура полностью)"]
|
||
== "121467, 643, Москва, Молодогвардейская, 8, 1, 28"
|
||
)
|
||
|
||
|
||
def test_structured_column_uses_non_one_line_candidate_when_mixed_tags() -> None:
|
||
row = build_fixed_row(
|
||
file_name="f.xml",
|
||
record_id="R1",
|
||
operation_index=1,
|
||
operation_fields={},
|
||
participant_fields={
|
||
"УчастникЮЛ.БенефициарЮЛ.ФЛБенефициар.АдрРег.АдрУчредитель": (
|
||
"г. Москва, ул. Пушкина, д. 1"
|
||
),
|
||
},
|
||
)
|
||
assert row["Адрес в одной строке"] == ""
|
||
assert row[
|
||
"Адрес ЮЛ/ Адрес места жительства (места нахождения) "
|
||
"ЕИО/Бенефициара (одной строкой)"
|
||
] == ("г. Москва, ул. Пушкина, д. 1")
|
||
assert (
|
||
row[
|
||
"Адрес ЮЛ/ Адрес места жительства (места нахождения) "
|
||
"ЕИО/Бенефициара (структура полностью)"
|
||
]
|
||
== ""
|
||
)
|
||
|
||
|
||
def test_digital_rights_operation_clears_currency_amount_fields() -> None:
|
||
row = build_fixed_row(
|
||
file_name="f.xml",
|
||
record_id="R1",
|
||
operation_index=1,
|
||
operation_fields={
|
||
"КодПризнОперации": "8",
|
||
"КодВал": "643",
|
||
"СумОперации": "100.00",
|
||
"СумРуб": "100.00",
|
||
},
|
||
participant_fields={},
|
||
)
|
||
assert row["Валюта"] == ""
|
||
assert row["Сумма в валюте проведения"] == ""
|
||
assert row["Сумма в рубл. эквиваленте"] == ""
|
||
|
||
|
||
def test_abnormal_operation_codes_only_for_6001() -> None:
|
||
row_without_6001 = build_fixed_row(
|
||
file_name="f.xml",
|
||
record_id="R1",
|
||
operation_index=1,
|
||
operation_fields={
|
||
"КодОперации": "5007",
|
||
"ПризнНеобОперации": "1101",
|
||
},
|
||
participant_fields={},
|
||
)
|
||
assert row_without_6001["Коды призн. необычной операции"] == ""
|
||
|
||
row_with_6001 = build_fixed_row(
|
||
file_name="f.xml",
|
||
record_id="R1",
|
||
operation_index=1,
|
||
operation_fields={
|
||
"КодОперации": "6001",
|
||
"ПризнНеобОперации": "1101",
|
||
},
|
||
participant_fields={},
|
||
)
|
||
assert row_with_6001["Коды призн. необычной операции"] == "1101"
|
||
|
||
|
||
def test_transfer_accounts_get_placeholder_when_required() -> None:
|
||
row = build_fixed_row(
|
||
file_name="f.xml",
|
||
record_id="R1",
|
||
operation_index=1,
|
||
operation_fields={
|
||
"ВидПереводДС": "1",
|
||
"ТипОператорДС": "4",
|
||
},
|
||
participant_fields={},
|
||
)
|
||
assert row["Номер счета плательщика"] == "00000000000000000000"
|
||
assert row["Номер счета банка плательщика"] == "00000000000000000000"
|
||
assert row["Номер счета банка получателя"] == "00000000000000000000"
|
||
assert row["Номер счета получателя"] == "00000000000000000000"
|
||
|
||
|
||
def test_transfer_accounts_stay_empty_without_transfer_block() -> None:
|
||
row = build_fixed_row_by_index(
|
||
file_name="SKO115FZ_01_044525111_20260810_000001.xml",
|
||
record_id="R1",
|
||
operation_index=1,
|
||
operation_fields={
|
||
"НомерОперация": "ЦФТ-БАНК_1361233603059",
|
||
"ПризнакОперации": "5",
|
||
"СведенияВнесениеПолучениеНалДС.СуммаНал": "1000.00",
|
||
},
|
||
participant_fields={},
|
||
)
|
||
|
||
assert row[38] == ""
|
||
assert row[44] == ""
|
||
assert row[45] == ""
|
||
assert row[46] == ""
|
||
|
||
|
||
def test_operator_type_conditions_clear_irrelevant_bank_fields() -> None:
|
||
row = build_fixed_row(
|
||
file_name="f.xml",
|
||
record_id="R1",
|
||
operation_index=1,
|
||
operation_fields={
|
||
"ТипОператорДС": "3",
|
||
"НаимКО": "Банк плательщика",
|
||
"СведБанкПолучатель.НаимКО": "Банк получателя",
|
||
"СведБанкПолучатель.БИККО": "044525225",
|
||
"СчетБанкПлательщик": "30101810000000000001",
|
||
"СчетБанкПолучатель": "30101810000000000002",
|
||
},
|
||
participant_fields={},
|
||
)
|
||
assert row["Наименование банка плательщика"] == ""
|
||
assert row["Наименование банка получателя"] == ""
|
||
assert row["БИК банка получателя"] == ""
|
||
assert row["Номер счета банка плательщика"] == ""
|
||
assert row["Номер счета банка получателя"] == ""
|
||
|
||
|
||
def test_col96_territory_code_cleared_when_operation_is_not_5016() -> None:
|
||
row = build_fixed_row(
|
||
file_name="f.xml",
|
||
record_id="R1",
|
||
operation_index=1,
|
||
operation_fields={
|
||
"КодОперации": "5007",
|
||
"КодТерИнГос": "840",
|
||
},
|
||
participant_fields={},
|
||
)
|
||
assert row["Код территории"] == ""
|
||
|
||
|
||
def test_col103_and_105_fill_info_absent_when_no_employee_and_empty() -> None:
|
||
row = build_fixed_row(
|
||
file_name="f.xml",
|
||
record_id="R1",
|
||
operation_index=1,
|
||
operation_fields={
|
||
"ПризнакСотрудник": "0",
|
||
},
|
||
participant_fields={},
|
||
)
|
||
assert row["Сведения о держателе платежной карты"] == "Информация отсутствует"
|
||
assert row["Наименование иностранного банка"] == "Информация отсутствует"
|
||
|
||
|
||
def test_col103_and_105_keep_original_values_when_present() -> None:
|
||
row = build_fixed_row(
|
||
file_name="f.xml",
|
||
record_id="R1",
|
||
operation_index=1,
|
||
operation_fields={
|
||
"ПризнакСотрудник": "0",
|
||
"СведДержательКарты": "Иванов И.И.",
|
||
"НаимИнБанк": "FOREIGN BANK",
|
||
},
|
||
participant_fields={},
|
||
)
|
||
assert row["Сведения о держателе платежной карты"] == "Иванов И.И."
|
||
assert row["Наименование иностранного банка"] == "FOREIGN BANK"
|
||
|
||
|
||
def test_patronymic_supports_typo_tag_ocht() -> None:
|
||
row = build_fixed_row(
|
||
file_name="f.xml",
|
||
record_id="R1",
|
||
operation_index=1,
|
||
operation_fields={},
|
||
participant_fields={
|
||
"УчастникФЛИП.СведФЛИП.ФИОФЛИП.Фам": "Азимов",
|
||
"УчастникФЛИП.СведФЛИП.ФИОФЛИП.Имя": "Ислом",
|
||
"УчастникФЛИП.СведФЛИП.ФИОФЛИП.Очт": "Каримович",
|
||
},
|
||
)
|
||
assert row["Отчество"] == "Каримович"
|
||
|
||
|
||
def test_col124_cleared_for_physical_person_and_ip() -> None:
|
||
row_fl = build_fixed_row(
|
||
file_name="f.xml",
|
||
record_id="R1",
|
||
operation_index=1,
|
||
operation_fields={"ТипФЛЧастнаяПрактика": "1"},
|
||
participant_fields={"ТипУчастника": "2"},
|
||
)
|
||
assert row_fl["Признак филиала: / Тип ФЛЧП"] == ""
|
||
|
||
row_ip = build_fixed_row(
|
||
file_name="f.xml",
|
||
record_id="R1",
|
||
operation_index=1,
|
||
operation_fields={"ТипФЛЧастнаяПрактика": "1"},
|
||
participant_fields={"ТипУчастника": "3"},
|
||
)
|
||
assert row_ip["Признак филиала: / Тип ФЛЧП"] == ""
|
||
|
||
|
||
def test_col125_snils_cleared_for_ip() -> None:
|
||
row = build_fixed_row(
|
||
file_name="f.xml",
|
||
record_id="R1",
|
||
operation_index=1,
|
||
operation_fields={},
|
||
participant_fields={"ТипУчастника": "3", "СНИЛСФЛ": "123-456-789 00"},
|
||
)
|
||
assert row["ОМС/СНИЛС/Номер телефона"] == ""
|
||
|
||
|
||
def test_one_line_address_columns_cleared_when_participant_is_resident_client() -> None:
|
||
row = build_fixed_row(
|
||
file_name="f.xml",
|
||
record_id="R1",
|
||
operation_index=1,
|
||
operation_fields={
|
||
"ПризнУчастника": "1",
|
||
"ПризнКлиент": "1",
|
||
"АдресСтрока": "г. Москва, ул. Тестовая, д. 1",
|
||
},
|
||
participant_fields={},
|
||
)
|
||
assert row["Адрес в одной строке"] == ""
|
||
assert row["Место государственной регистрации ( в одной строке)"] == ""
|
||
assert (
|
||
row["Место государственной регистрации ЕИО/Бенефициара (одной строкой)"] == ""
|
||
)
|
||
|
||
|
||
def test_eio_one_line_address_obeys_participant_residency_rule() -> None:
|
||
participant_fields = {
|
||
"УчастникЮЛ.СведЕИО.ФЛЕИО.АдрРег.АдресСтрока": "г. Москва, ул. Тестовая",
|
||
"УчастникЮЛ.СведЕИО.ФЛЕИО.АдрРег.Индекс": "101000",
|
||
"УчастникЮЛ.СведЕИО.ФЛЕИО.АдрРег.КодОКСМ": "643",
|
||
}
|
||
resident_client = build_fixed_row_by_index(
|
||
file_name="f.xml",
|
||
record_id="R1",
|
||
operation_index=1,
|
||
operation_fields={"ПризнУчастника": "1", "ПризнКлиент": "1"},
|
||
participant_fields=participant_fields,
|
||
)
|
||
nonresident = build_fixed_row_by_index(
|
||
file_name="f.xml",
|
||
record_id="R2",
|
||
operation_index=2,
|
||
operation_fields={"ПризнУчастника": "0", "ПризнКлиент": "1"},
|
||
participant_fields=participant_fields,
|
||
)
|
||
|
||
assert resident_client[167] == ""
|
||
assert resident_client[169] == "101000"
|
||
assert resident_client[170] == "643"
|
||
assert nonresident[167] == "г. Москва, ул. Тестовая"
|
||
|
||
|
||
def test_foreign_structure_founder_address_populates_eio_address_block() -> None:
|
||
row = build_fixed_row_by_index(
|
||
file_name="f.xml",
|
||
record_id="R1",
|
||
operation_index=1,
|
||
operation_fields={},
|
||
participant_fields={
|
||
"УчастникИНБОЮЛ.СведИНБОЮЛ.Учредитель.АдрУчредитель.Индекс": "101000",
|
||
"УчастникИНБОЮЛ.СведИНБОЮЛ.Учредитель.АдрУчредитель.КодОКСМ": "643",
|
||
"УчастникИНБОЮЛ.СведИНБОЮЛ.Учредитель.АдрУчредитель.Пункт": "Москва",
|
||
},
|
||
)
|
||
|
||
assert row[167] == ""
|
||
assert row[168] == "101000, 643, Москва"
|
||
assert row[169] == "101000"
|
||
assert row[170] == "643"
|
||
assert row[173] == "Москва"
|
||
|
||
|
||
def test_foreign_structure_founder_one_line_address_activates_eio_block() -> None:
|
||
row = build_fixed_row_by_index(
|
||
file_name="f.xml",
|
||
record_id="R1",
|
||
operation_index=1,
|
||
operation_fields={"ПризнУчастника": "0"},
|
||
participant_fields={
|
||
"УчастникИНБОЮЛ.СведИНБОЮЛ.Учредитель.АдрУчредитель.АдресСтрока": (
|
||
"г. Москва, ул. Пушкина, д. 1"
|
||
),
|
||
},
|
||
)
|
||
|
||
assert row[167] == "г. Москва, ул. Пушкина, д. 1"
|
||
assert row[168] == ""
|
||
|
||
|
||
def test_okato_cleared_when_country_code_is_not_russia() -> None:
|
||
row = build_fixed_row(
|
||
file_name="f.xml",
|
||
record_id="R1",
|
||
operation_index=1,
|
||
operation_fields={
|
||
"КодОКСМ": "840",
|
||
"КодСубъектаПоОКАТО": "45",
|
||
},
|
||
participant_fields={},
|
||
)
|
||
assert row["Код ОКАТО"] == ""
|
||
assert row["ОКАТО"] == ""
|
||
|
||
|
||
def test_col163_ogrn_eio_benef_cleared_for_physical_person() -> None:
|
||
row = build_fixed_row(
|
||
file_name="f.xml",
|
||
record_id="R1",
|
||
operation_index=1,
|
||
operation_fields={"ОГРНИП": "123456789012345"},
|
||
participant_fields={"ТипУчастника": "2"},
|
||
)
|
||
assert row["ОГРН ЕИО/Бенефициара"] == ""
|
||
|
||
|
||
def test_dul_sign_for_legal_entity_does_not_use_operation_doc_fields() -> None:
|
||
row = build_fixed_row(
|
||
file_name="f.xml",
|
||
record_id="R1",
|
||
operation_index=1,
|
||
operation_fields={"ДокУдЛичн": "451099", "ТипУчастника": "1"},
|
||
participant_fields={},
|
||
)
|
||
assert row["Признак ДУЛ"] == ""
|
||
|
||
|
||
def test_dul_columns_128_134_keep_expected_positions() -> None:
|
||
row = build_fixed_row(
|
||
file_name="f.xml",
|
||
record_id="R1",
|
||
operation_index=1,
|
||
operation_fields={},
|
||
participant_fields={
|
||
"ВидДокКод": "21",
|
||
"СерияДок": "0104",
|
||
"НомДок": "476635",
|
||
"КемВыданДок": "ОВД",
|
||
"КодПодр": "222-022",
|
||
"ДатВыдачиДок": "23/08/2005",
|
||
"ДокУдЛичн": "1",
|
||
},
|
||
)
|
||
assert row["ДУЛ (структура полностью)"] == "1, 21, 0104, 476635, ОВД, 222-022"
|
||
assert row["Признак ДУЛ"] == "1"
|
||
assert row["Код вида документа/Наименование"] == "21"
|
||
assert row["Серия"] == "0104"
|
||
assert row["Номер"] == "476635"
|
||
assert row["Орган, выдавший документ"] == "ОВД"
|
||
assert row["КП"] == "222-022"
|
||
|
||
|
||
def test_col136_does_not_use_identity_document_type_without_stay_document() -> None:
|
||
row = build_fixed_row_by_index(
|
||
file_name="f.xml",
|
||
record_id="R1",
|
||
operation_index=1,
|
||
operation_fields={},
|
||
participant_fields={
|
||
"УчастникФЛИП.СведФЛИП.СведДокУдЛичн.ВидДокКод": "21",
|
||
},
|
||
)
|
||
|
||
assert row[136] == ""
|
||
|
||
|
||
def test_col136_uses_stay_document_type_instead_of_identity_document_type() -> None:
|
||
row = build_fixed_row_by_index(
|
||
file_name="f.xml",
|
||
record_id="R1",
|
||
operation_index=1,
|
||
operation_fields={},
|
||
participant_fields={
|
||
"УчастникФЛИП.СведФЛИП.СведДокУдЛичн.ВидДокКод": "21",
|
||
"УчастникФЛИП.СведФЛИП.СведДокПреб.ВидДокКод": "10",
|
||
},
|
||
)
|
||
|
||
assert row[136] == "10"
|
||
|
||
|
||
def test_col136_rejects_stay_document_type_from_unrelated_participant_path() -> None:
|
||
row = build_fixed_row_by_index(
|
||
file_name="f.xml",
|
||
record_id="R1",
|
||
operation_index=1,
|
||
operation_fields={},
|
||
participant_fields={
|
||
"ДругойБлок.СведДокПреб.ВидДокКод": "99",
|
||
},
|
||
)
|
||
|
||
assert row[136] == ""
|
||
|
||
|
||
def test_bank_bik_columns_use_transfer_bank_paths_instead_of_common_bikko() -> None:
|
||
row = build_fixed_row(
|
||
file_name="f.xml",
|
||
record_id="R1",
|
||
operation_index=1,
|
||
operation_fields={
|
||
"БИККО": "044525111",
|
||
"ТипОператорДС": "4",
|
||
"СвединияПереводыДС.СведБанкПлательщик.БИККО": "011012100",
|
||
"СвединияПереводыДС.СведБанкПолучатель.БИККО": "022202220",
|
||
},
|
||
participant_fields={},
|
||
)
|
||
assert row["БИК банка плательщика"] == "011012100"
|
||
assert row["БИК банка получателя"] == "022202220"
|
||
|
||
|
||
def test_transfer_bank_fields_do_not_leak_into_unrelated_bank_blocks() -> None:
|
||
row = build_fixed_row_by_index(
|
||
file_name="f.xml",
|
||
record_id="R1",
|
||
operation_index=1,
|
||
operation_fields={
|
||
"ТипОператорДС": "2",
|
||
"ВидПереводДС": "1",
|
||
"СведенияПереводыДС.СведБанкПлательщик.НаимКО": "ПАО Сбербанк",
|
||
"СведенияПереводыДС.СведБанкПлательщик.БИККО": "044525225",
|
||
},
|
||
participant_fields={},
|
||
)
|
||
|
||
assert row[40] == "ПАО Сбербанк"
|
||
assert row[41] == "044525225"
|
||
for column_index in (60, 61, 75, 76, 94, 95, 100, 101):
|
||
assert row[column_index] == ""
|
||
|
||
|
||
def test_cash_bank_fields_fill_only_their_own_block() -> None:
|
||
row = build_fixed_row_by_index(
|
||
file_name="f.xml",
|
||
record_id="R1",
|
||
operation_index=1,
|
||
operation_fields={
|
||
"СведенияВнесениеПолучениеНалДС.СведПриемВыдача.НаимКО": "АО Наличный банк",
|
||
"СведенияВнесениеПолучениеНалДС.СведПриемВыдача.БИККО": "040407777",
|
||
"СведенияВнесениеПолучениеНалДС.СведПриемВыдача.КодОКСМ": "643",
|
||
},
|
||
participant_fields={},
|
||
)
|
||
|
||
assert row[94] == "АО Наличный банк"
|
||
assert row[95] == "040407777"
|
||
for column_index in (40, 41, 42, 43, 60, 61, 75, 76, 98, 100, 101):
|
||
assert row[column_index] == ""
|
||
|
||
|
||
def test_citizenship_country_code_uses_only_direct_svedflip_value() -> None:
|
||
row = build_fixed_row(
|
||
file_name="f.xml",
|
||
record_id="R1",
|
||
operation_index=1,
|
||
operation_fields={},
|
||
participant_fields={
|
||
"УчастникФЛИП.СведФЛИП.АдрРег.КодОКСМ": "643",
|
||
"УчастникФЛИП.СведФЛИП.КодОКСМ": "762",
|
||
},
|
||
)
|
||
assert row["Код страны гражданства"] == "762"
|
||
|
||
|
||
def test_citizenship_country_code_is_empty_when_only_address_code_exists() -> None:
|
||
row = build_fixed_row(
|
||
file_name="f.xml",
|
||
record_id="R1",
|
||
operation_index=1,
|
||
operation_fields={},
|
||
participant_fields={"УчастникФЛИП.СведФЛИП.АдрРег.КодОКСМ": "643"},
|
||
)
|
||
assert row["Код страны гражданства"] == ""
|
||
|
||
|
||
def test_okato_column_4_uses_branch_okatofl_and_not_bank_okatoko() -> None:
|
||
row = build_fixed_row(
|
||
file_name="f.xml",
|
||
record_id="R1",
|
||
operation_index=1,
|
||
operation_fields={
|
||
"ОКАТОКО": "45",
|
||
"ОКАТОФл": "10",
|
||
"АдресСтрока": "г. Москва",
|
||
},
|
||
participant_fields={},
|
||
)
|
||
assert FIXED_REPORT_COLUMNS[3] == "ОКАТО"
|
||
assert row["ОКАТО"] == "10"
|
||
|
||
|
||
def test_col9_uses_operation_number_from_xml() -> None:
|
||
row = build_fixed_row_by_index(
|
||
file_name="f.xml",
|
||
record_id="R1",
|
||
operation_index=7,
|
||
operation_fields={"НомерОперация": "ЦФТ-БАНК_1177326777530"},
|
||
participant_fields={},
|
||
)
|
||
assert row[9] == "ЦФТ-БАНК_1177326777530"
|
||
|
||
|
||
def test_structured_cash_address_does_not_include_bank_fields() -> None:
|
||
row = build_fixed_row_by_index(
|
||
file_name="f.xml",
|
||
record_id="R1",
|
||
operation_index=1,
|
||
operation_fields={
|
||
"СведенияПереводыДс.СведПриемНалДС.АдрМестоПриемаВыдача.Индекс": "675520",
|
||
"СведенияПереводыДс.СведПриемНалДС.АдрМестоПриемаВыдача.КодОКСМ": "643",
|
||
"СведенияПереводыДс.СведПриемНалДС.АдрМестоПриемаВыдача.КодСубъектаПоОКАТО": "10",
|
||
"СведенияПереводыДс.СведПриемНалДС.АдрМестоПриемаВыдача.Пункт": "Чигири с",
|
||
"СведенияПереводыДс.СведПриемНалДС.АдрМестоПриемаВыдача.Улица": "Зеленая ул",
|
||
"СведенияПереводыДс.СведПриемНалДС.АдрМестоПриемаВыдача.Дом": "1",
|
||
"СведенияПереводыДс.СведПриемНалДС.БИККО": "044525111",
|
||
"СведенияПереводыДс.СведПриемНалДС.НаимКО": "АО РСХБ",
|
||
},
|
||
participant_fields={},
|
||
)
|
||
assert row[50] == "675520, 643, 10, Чигири с, Зеленая ул, 1"
|
||
assert "044525111" not in row[50]
|
||
assert "АО РСХБ" not in row[50]
|
||
|
||
|
||
def test_participant_structured_address_stays_in_142_and_components_143_plus() -> None:
|
||
row = build_fixed_row_by_index(
|
||
file_name="f.xml",
|
||
record_id="R1",
|
||
operation_index=1,
|
||
operation_fields={},
|
||
participant_fields={
|
||
"УчастникФЛИП.СведФЛИП.АдрРег.Индекс": "123456",
|
||
"УчастникФЛИП.СведФЛИП.АдрРег.КодОКСМ": "643",
|
||
"УчастникФЛИП.СведФЛИП.АдрРег.КодСубъектаПоОКАТО": "45",
|
||
"УчастникФЛИП.СведФЛИП.АдрРег.Пункт": "Москва",
|
||
"УчастникФЛИП.СведФЛИП.АдрРег.Улица": "Тверская",
|
||
"УчастникФЛИП.СведФЛИП.АдрРег.Дом": "1",
|
||
},
|
||
)
|
||
assert row[141] == ""
|
||
assert row[142] == "123456, 643, 45, Москва, Тверская, 1"
|
||
assert row[143] == "123456"
|
||
assert row[144] == "643"
|
||
|
||
|
||
def test_participant_address_does_not_use_citizenship_without_address_block() -> None:
|
||
row = build_fixed_row_by_index(
|
||
file_name="f.xml",
|
||
record_id="R1",
|
||
operation_index=1,
|
||
operation_fields={},
|
||
participant_fields={
|
||
"ТипУчастника": "3",
|
||
"УчастникФЛИП.СведФЛИП.КодОКСМ": "643",
|
||
},
|
||
)
|
||
|
||
assert row[126] == "643"
|
||
assert row[142] == ""
|
||
assert row[144] == ""
|
||
|
||
|
||
def test_participant_address_country_is_isolated_from_citizenship() -> None:
|
||
row = build_fixed_row_by_index(
|
||
file_name="f.xml",
|
||
record_id="R1",
|
||
operation_index=1,
|
||
operation_fields={},
|
||
participant_fields={
|
||
"ТипУчастника": "2",
|
||
"УчастникФЛИП.СведФЛИП.КодОКСМ": "762",
|
||
"УчастникФЛИП.СведФЛИП.АдрРег.Индекс": "123456",
|
||
"УчастникФЛИП.СведФЛИП.АдрРег.КодОКСМ": "643",
|
||
"УчастникФЛИП.СведФЛИП.АдрРег.Пункт": "Москва",
|
||
},
|
||
)
|
||
|
||
assert row[126] == "762"
|
||
assert row[142] == "123456, 643, Москва"
|
||
assert row[144] == "643"
|
||
|
||
|
||
def test_participant_address_components_reject_unrelated_address_fields() -> None:
|
||
row = build_fixed_row_by_index(
|
||
file_name="f.xml",
|
||
record_id="R1",
|
||
operation_index=1,
|
||
operation_fields={
|
||
"ДругойАдрес.Индекс": "999999",
|
||
"ДругойАдрес.Район": "Чужой район",
|
||
"ДругойАдрес.Дом": "9",
|
||
},
|
||
participant_fields={
|
||
"ТипУчастника": "3",
|
||
"УчастникФЛИП.СведФЛИП.КодОКСМ": "643",
|
||
},
|
||
)
|
||
|
||
assert row[142] == ""
|
||
assert row[143] == ""
|
||
assert row[144] == ""
|
||
assert row[146] == ""
|
||
assert row[149] == ""
|
||
|
||
|
||
def test_col153_uses_only_legal_entity_registration_address_components() -> None:
|
||
row = build_fixed_row_by_index(
|
||
file_name="f.xml",
|
||
record_id="R1",
|
||
operation_index=1,
|
||
operation_fields={"КодОКСМ": "643", "Индекс": "999999"},
|
||
participant_fields={
|
||
"УчастникЮЛ.СведЮЛ.АдрРегЮЛ.Индекс": "675520",
|
||
"УчастникЮЛ.СведЮЛ.АдрРегЮЛ.КодОКСМ": "643",
|
||
"УчастникЮЛ.СведЮЛ.АдрРегЮЛ.КодСубъектаПоОКАТО": "10",
|
||
"УчастникЮЛ.СведЮЛ.АдрРегЮЛ.Район": "Благовещенский р-н",
|
||
"УчастникЮЛ.СведЮЛ.АдрРегЮЛ.Пункт": "Чигири с",
|
||
"УчастникЮЛ.СведЮЛ.АдрРегЮЛ.Улица": "Зеленая ул",
|
||
"УчастникЮЛ.СведЮЛ.АдрРегЮЛ.Дом": "1",
|
||
},
|
||
)
|
||
assert row[153] == "675520, 643, 10, Благовещенский р-н, Чигири с, Зеленая ул, 1"
|
||
|
||
|
||
def test_col153_is_cleared_when_registration_address_one_line_exists() -> None:
|
||
row = build_fixed_row_by_index(
|
||
file_name="f.xml",
|
||
record_id="R1",
|
||
operation_index=1,
|
||
operation_fields={},
|
||
participant_fields={
|
||
"УчастникЮЛ.СведЮЛ.АдрРегЮЛ.АдресСтрока": "Москва, Тверская, 1",
|
||
"УчастникЮЛ.СведЮЛ.АдрРегЮЛ.Индекс": "123456",
|
||
"УчастникЮЛ.СведЮЛ.АдрРегЮЛ.КодОКСМ": "643",
|
||
"УчастникЮЛ.СведЮЛ.АдрРегЮЛ.Пункт": "Москва",
|
||
},
|
||
)
|
||
|
||
assert row[152] == "Москва, Тверская, 1"
|
||
assert row[153] == ""
|
||
|
||
|
||
def test_col179_is_cleared_when_eio_registration_one_line_exists() -> None:
|
||
row = build_fixed_row_by_index(
|
||
file_name="f.xml",
|
||
record_id="R1",
|
||
operation_index=1,
|
||
operation_fields={},
|
||
participant_fields={
|
||
"УчастникЮЛ.СведЕИО.ЮЛЕИО.АдресСтрока": "Москва, Арбат, 1",
|
||
"УчастникЮЛ.СведЕИО.ЮЛЕИО.АдрРегЮЛ.Индекс": "123456",
|
||
"УчастникЮЛ.СведЕИО.ЮЛЕИО.АдрРегЮЛ.КодОКСМ": "643",
|
||
"УчастникЮЛ.СведЕИО.ЮЛЕИО.АдрРегЮЛ.Пункт": "Москва",
|
||
},
|
||
)
|
||
|
||
assert row[178] == "Москва, Арбат, 1"
|
||
assert row[179] == ""
|
||
|
||
|
||
def test_col179_keeps_structured_eio_registration_without_one_line() -> None:
|
||
row = build_fixed_row_by_index(
|
||
file_name="f.xml",
|
||
record_id="R1",
|
||
operation_index=1,
|
||
operation_fields={},
|
||
participant_fields={
|
||
"УчастникЮЛ.СведЕИО.ЮЛЕИО.АдрРегЮЛ.Индекс": "123456",
|
||
"УчастникЮЛ.СведЕИО.ЮЛЕИО.АдрРегЮЛ.КодОКСМ": "643",
|
||
"УчастникЮЛ.СведЕИО.ЮЛЕИО.АдрРегЮЛ.Пункт": "Москва",
|
||
},
|
||
)
|
||
|
||
assert row[178] == ""
|
||
assert row[179] == "123456, 643, Москва"
|
||
|
||
|
||
def test_cash_columns_cleared_for_cashless_transfer_type_1() -> None:
|
||
row = build_fixed_row_by_index(
|
||
file_name="f.xml",
|
||
record_id="R1",
|
||
operation_index=1,
|
||
operation_fields={
|
||
"ВидПереводДС": "1",
|
||
"КодОперации": "4006",
|
||
"БИККО": "044525111",
|
||
"СведенияПереводыДс.СведПриемНалДС.БИККО": "044525111",
|
||
},
|
||
participant_fields={},
|
||
)
|
||
for index in (50, 61, 65, 76, 84, 95, 99, 101):
|
||
assert row[index] == ""
|
||
|
||
|
||
def test_col119_is_empty_for_legal_entity_and_uses_flip_identifier() -> None:
|
||
row_ul = build_fixed_row_by_index(
|
||
file_name="f.xml",
|
||
record_id="R1",
|
||
operation_index=1,
|
||
operation_fields={},
|
||
participant_fields={"ТипУчастника": "1", "ИдентификацияФЛ": "1"},
|
||
)
|
||
assert row_ul[119] == ""
|
||
|
||
row_flip = build_fixed_row_by_index(
|
||
file_name="f.xml",
|
||
record_id="R1",
|
||
operation_index=1,
|
||
operation_fields={},
|
||
participant_fields={
|
||
"ТипУчастника": "3",
|
||
"УчастникФЛИП.ИдентификацияФЛ": "1",
|
||
},
|
||
)
|
||
assert row_flip[119] == "1"
|
||
|
||
|
||
def test_physical_person_type_2_does_not_fill_cols_119_and_122() -> None:
|
||
row = build_fixed_row_by_index(
|
||
file_name="f.xml",
|
||
record_id="R1",
|
||
operation_index=1,
|
||
operation_fields={},
|
||
participant_fields={
|
||
"СтатусУчастника": "3",
|
||
"ТипУчастника": "2",
|
||
"УчастникФЛИП.ИдентификацияФЛ": "1",
|
||
"УчастникФЛИП.СведФЛИП.ИННФЛИП": "410116812922",
|
||
},
|
||
)
|
||
assert row[119] == ""
|
||
assert row[120] == "410116812922"
|
||
assert row[122] == ""
|
||
|
||
|
||
def test_col123_uses_registration_date_for_legal_entity() -> None:
|
||
row = build_fixed_row_by_index(
|
||
file_name="f.xml",
|
||
record_id="R1",
|
||
operation_index=1,
|
||
operation_fields={},
|
||
participant_fields={
|
||
"ТипУчастника": "1",
|
||
"УчастникЮЛ.СведЮЛ.ДатаРегЮЛ": "23/08/2005",
|
||
"УчастникФЛИП.СведФЛИП.ДатаРождения": "01/01/1990",
|
||
},
|
||
)
|
||
assert row[123] == "23/08/2005"
|
||
|
||
|
||
def test_eio_block_is_empty_when_eio_and_beneficiary_are_absent() -> None:
|
||
row = build_fixed_row_by_index(
|
||
file_name="f.xml",
|
||
record_id="R1",
|
||
operation_index=1,
|
||
operation_fields={},
|
||
participant_fields={
|
||
"ТипУчастника": "1",
|
||
"УчастникЮЛ.СведЮЛ.ИННЮЛ": "2820000210",
|
||
"УчастникЮЛ.СведЮЛ.ОГРНЮЛ": "1022801198573",
|
||
"УчастникЮЛ.СведЮЛ.АдрРегЮЛ.КодСубъектаПоОКАТО": "45",
|
||
},
|
||
)
|
||
for index in (157, 162, 163, 168, 171):
|
||
assert row[index] == ""
|
||
|
||
|
||
def test_participant_and_beneficiary_inn_are_scoped_regardless_of_field_order() -> None:
|
||
own_inn = ("УчастникЮЛ.СведЮЛ.ИННЮЛ", "2820000210")
|
||
beneficiary_fields = (
|
||
("УчастникЮЛ.БенефициарЮЛ.ФЛБенефициар.ФИОФЛИП.Фам", "Иванов"),
|
||
("УчастникЮЛ.БенефициарЮЛ.ФЛБенефициар.ФИОФЛИП.Имя", "Иван"),
|
||
("УчастникЮЛ.БенефициарЮЛ.ФЛБенефициар.ФИОФЛИП.Отч", "Иванович"),
|
||
("УчастникЮЛ.БенефициарЮЛ.ФЛБенефициар.ИННФЛИП", "111111111111"),
|
||
)
|
||
|
||
for items in (
|
||
(own_inn, *beneficiary_fields),
|
||
(*reversed(beneficiary_fields), own_inn),
|
||
):
|
||
row = build_fixed_row_by_index(
|
||
file_name="f.xml",
|
||
record_id="R1",
|
||
operation_index=1,
|
||
operation_fields={},
|
||
participant_fields=dict(items),
|
||
)
|
||
|
||
assert row[120] == "2820000210"
|
||
assert row[157] == "Иванов Иван Иванович"
|
||
assert row[162] == "111111111111"
|
||
assert "111111111111" not in row[157]
|
||
|
||
|
||
def test_legal_entity_and_eio_representative_inn_remain_strictly_scoped() -> None:
|
||
row = build_fixed_row_by_index(
|
||
file_name="f.xml",
|
||
record_id="R1",
|
||
operation_index=1,
|
||
operation_fields={},
|
||
participant_fields={
|
||
"УчастникЮЛ.СведЮЛ.НаимЮЛ": "АО СИРИУС",
|
||
"УчастникЮЛ.СведЮЛ.ИННЮЛ": "2820000210",
|
||
"УчастникЮЛ.СведЕИО[0].ФЛЕИО.ФИОФЛИП.Фам": "Музалёв",
|
||
"УчастникЮЛ.СведЕИО[0].ФЛЕИО.ФИОФЛИП.Имя": "Александр",
|
||
"УчастникЮЛ.СведЕИО[0].ФЛЕИО.ФИОФЛИП.Отч": "Сергеевич",
|
||
"УчастникЮЛ.СведЕИО[0].ФЛЕИО.ИННФЛИП": "410116812922",
|
||
},
|
||
)
|
||
|
||
assert row[120] == "2820000210"
|
||
assert row[157] == "Музалёв Александр Сергеевич"
|
||
assert row[162] == "410116812922"
|
||
|
||
|
||
def test_flip_beneficiary_is_scoped_to_eio_columns() -> None:
|
||
row = build_fixed_row_by_index(
|
||
file_name="f.xml",
|
||
record_id="R1",
|
||
operation_index=1,
|
||
operation_fields={},
|
||
participant_fields={
|
||
"УчастникФЛИП.СведФЛИП.ИННФЛИП": "222222222222",
|
||
"УчастникФЛИП.БенефициарФЛИП.ФЛБенефициар.ИННФЛИП": "111111111111",
|
||
},
|
||
)
|
||
|
||
assert row[120] == "222222222222"
|
||
assert row[162] == "111111111111"
|
||
|
||
|
||
def test_legal_entity_eio_name_is_preserved_in_structured_column() -> None:
|
||
row = build_fixed_row_by_index(
|
||
file_name="f.xml",
|
||
record_id="R1",
|
||
operation_index=1,
|
||
operation_fields={},
|
||
participant_fields={
|
||
"УчастникЮЛ.СведЕИО.ЮЛЕИО.НаимЮЛ": "ООО Управляющая компания",
|
||
"УчастникЮЛ.СведЕИО.ЮЛЕИО.ИННЮЛ": "7707083893",
|
||
},
|
||
)
|
||
|
||
assert row[157] == "ООО Управляющая компания"
|
||
assert row[162] == "7707083893"
|
||
|
||
|
||
def test_continuation_row_validates_local_codes_without_filling_defaults() -> None:
|
||
row = build_fixed_row_by_index(
|
||
file_name="f.xml",
|
||
record_id="R1",
|
||
operation_index=1,
|
||
operation_fields={"ПризнФТр": "9"},
|
||
participant_fields={},
|
||
is_continuation=True,
|
||
)
|
||
|
||
assert row[10] == ""
|
||
assert row[44] == ""
|
||
assert row[45] == ""
|
||
|
||
|
||
def test_cp_block_is_empty_without_sved_cp_and_uses_emitent_inn_when_present() -> None:
|
||
row_without_cp = build_fixed_row_by_index(
|
||
file_name="f.xml",
|
||
record_id="R1",
|
||
operation_index=1,
|
||
operation_fields={},
|
||
participant_fields={"ИННЮЛ": "2820000210"},
|
||
)
|
||
assert row_without_cp[202] == ""
|
||
|
||
row_with_cp = build_fixed_row_by_index(
|
||
file_name="f.xml",
|
||
record_id="R1",
|
||
operation_index=1,
|
||
operation_fields={"СведЦП.Эмитент.ИННЭмитентЦП": "7707083893"},
|
||
participant_fields={"ИННЮЛ": "2820000210"},
|
||
)
|
||
assert row_with_cp[202] == "7707083893"
|
||
|
||
|
||
def test_currency_sign_is_preserved_independently_of_operation_code() -> None:
|
||
non_conversion = build_fixed_row_by_index(
|
||
file_name="f.xml",
|
||
record_id="R1",
|
||
operation_index=1,
|
||
operation_fields={
|
||
"КодОперации": "6001",
|
||
"СумКонверсия": "0.00",
|
||
"ПризнВалОперации": "VO",
|
||
},
|
||
participant_fields={},
|
||
)
|
||
assert non_conversion[26] == ""
|
||
assert non_conversion[27] == "VO"
|
||
|
||
conversion = build_fixed_row_by_index(
|
||
file_name="f.xml",
|
||
record_id="R2",
|
||
operation_index=2,
|
||
operation_fields={
|
||
"КодОперации": "6101",
|
||
"КодВалКонверсия": "978",
|
||
"СумКонверсия": "100.50",
|
||
"ПризнВалОперации": "VO",
|
||
},
|
||
participant_fields={},
|
||
)
|
||
assert conversion[26] == "100.50"
|
||
assert conversion[27] == "VO"
|
||
|
||
zero_conversion = build_fixed_row_by_index(
|
||
file_name="f.xml",
|
||
record_id="R3",
|
||
operation_index=3,
|
||
operation_fields={
|
||
"КодОперации": "6126",
|
||
"КодВалКонверсия": "840",
|
||
"СумКонверсия": "0.00",
|
||
"ПризнВалОперации": "VO",
|
||
},
|
||
participant_fields={},
|
||
)
|
||
assert zero_conversion[26] == ""
|
||
assert zero_conversion[27] == "VO"
|
||
|
||
for operation_code in ("6100", "6127"):
|
||
boundary_row = build_fixed_row_by_index(
|
||
file_name="f.xml",
|
||
record_id=operation_code,
|
||
operation_index=4,
|
||
operation_fields={
|
||
"КодОперации": operation_code,
|
||
"ПризнВалОперации": "VO",
|
||
},
|
||
participant_fields={},
|
||
)
|
||
assert boundary_row[27] == "VO"
|
||
|
||
|
||
def test_extra_info_uses_operation_comment() -> None:
|
||
row = build_fixed_row_by_index(
|
||
file_name="f.xml",
|
||
record_id="R1",
|
||
operation_index=1,
|
||
operation_fields={"КодОперации": "9003", "Коммент": "Комментарий операции"},
|
||
participant_fields={},
|
||
)
|
||
|
||
assert row[34] == "Комментарий операции"
|
||
|
||
|
||
def test_extra_info_ignores_nested_operation_comment() -> None:
|
||
row = build_fixed_row_by_index(
|
||
file_name="f.xml",
|
||
record_id="R1",
|
||
operation_index=1,
|
||
operation_fields={
|
||
"КодОперации": "9003",
|
||
"СведенияПереводыДС.Коммент": "Комментарий вложенного блока",
|
||
},
|
||
participant_fields={},
|
||
)
|
||
|
||
assert row[34] == ""
|
||
|
||
|
||
def test_extra_info_rejects_participant_comment_outside_allowed_codes() -> None:
|
||
row = build_fixed_row_by_index(
|
||
file_name="f.xml",
|
||
record_id="R1",
|
||
operation_index=1,
|
||
operation_fields={"КодОперации": "9003"},
|
||
participant_fields={"КомментУчастник": "Посторонний комментарий"},
|
||
)
|
||
|
||
assert row[34] == ""
|
||
|
||
|
||
def test_extra_info_is_not_directly_mapped_on_continuation_row() -> None:
|
||
row = build_fixed_row_by_index(
|
||
file_name="f.xml",
|
||
record_id="R1",
|
||
operation_index=1,
|
||
operation_fields={"КодОперации": "9003"},
|
||
participant_fields={"КомментУчастник": "Посторонний комментарий"},
|
||
is_continuation=True,
|
||
)
|
||
|
||
assert row[34] == ""
|
||
|
||
|
||
def test_extra_info_accepts_participant_comment_for_main_or_extra_code() -> None:
|
||
for operation_fields in (
|
||
{"КодОперации": "6102"},
|
||
{"КодОперации": "9003", "ДопКодОперации": "6126"},
|
||
):
|
||
row = build_fixed_row_by_index(
|
||
file_name="f.xml",
|
||
record_id="R1",
|
||
operation_index=1,
|
||
operation_fields=operation_fields,
|
||
participant_fields={"КомментУчастник": "Комментарий участника"},
|
||
)
|
||
|
||
assert row[34] == "Комментарий участника"
|
||
|
||
|
||
def test_extra_info_joins_distinct_allowed_comments_without_duplicates() -> None:
|
||
combined = build_fixed_row_by_index(
|
||
file_name="f.xml",
|
||
record_id="R1",
|
||
operation_index=1,
|
||
operation_fields={"КодОперации": "6102", "Коммент": "Общий комментарий"},
|
||
participant_fields={"КомментУчастник": "Комментарий участника"},
|
||
)
|
||
duplicate = build_fixed_row_by_index(
|
||
file_name="f.xml",
|
||
record_id="R2",
|
||
operation_index=2,
|
||
operation_fields={"КодОперации": "6102", "Коммент": "Одинаковый текст"},
|
||
participant_fields={"КомментУчастник": "Одинаковый текст"},
|
||
)
|
||
|
||
assert combined[34] == "Общий комментарий; Комментарий участника"
|
||
assert duplicate[34] == "Одинаковый текст"
|
||
|
||
|
||
def test_bank_bik_columns_accept_canonical_transfer_block_spelling() -> None:
|
||
row = build_fixed_row_by_index(
|
||
file_name="f.xml",
|
||
record_id="R1",
|
||
operation_index=1,
|
||
operation_fields={
|
||
"ТипОператорДС": "4",
|
||
"СведенияПереводыДС.СведБанкПлательщик.БИККО": "011012100",
|
||
"СведенияПереводыДС.СведБанкПолучатель.БИККО": "022202220",
|
||
},
|
||
participant_fields={},
|
||
)
|
||
assert row[41] == "011012100"
|
||
assert row[43] == "022202220"
|
||
|
||
|
||
def test_legal_entity_blocks_do_not_use_physical_person_identification() -> None:
|
||
row = build_fixed_row_by_index(
|
||
file_name="f.xml",
|
||
record_id="R1",
|
||
operation_index=1,
|
||
operation_fields={},
|
||
participant_fields={
|
||
"ТипУчастника": "4",
|
||
"УчастникЮЛ.СведЮЛ.НаимЮЛ": "ООО Тест",
|
||
"ИдентификацияФЛ": "1",
|
||
},
|
||
)
|
||
assert row[119] == ""
|
||
assert row[122] == ""
|
||
|
||
|
||
def test_col124_is_empty_for_private_practice_participant_type_4() -> None:
|
||
row = build_fixed_row_by_index(
|
||
file_name="f.xml",
|
||
record_id="R1",
|
||
operation_index=1,
|
||
operation_fields={},
|
||
participant_fields={
|
||
"ТипУчастника": "4",
|
||
"УчастникФЛИП.СведФЛИП.ТипФЛЧастнаяПрактика": "1",
|
||
},
|
||
)
|
||
assert row[124] == ""
|
||
|
||
padded_type_row = build_fixed_row_by_index(
|
||
file_name="f.xml",
|
||
record_id="R2",
|
||
operation_index=2,
|
||
operation_fields={},
|
||
participant_fields={
|
||
"ТипУчастника": "04",
|
||
"УчастникФЛИП.СведФЛИП.ТипФЛЧастнаяПрактика": "1",
|
||
},
|
||
)
|
||
assert padded_type_row[124] == ""
|
||
|
||
|
||
def test_col119_is_not_included_in_structured_fio_or_cleared_by_one_line_fio() -> None:
|
||
participant_fields = {
|
||
"ТипУчастника": "2",
|
||
"УчастникФЛИП.СведФЛИП.ФИОФЛИП.Фам": "Азимов",
|
||
"УчастникФЛИП.СведФЛИП.ФИОФЛИП.Имя": "Ислом",
|
||
"УчастникФЛИП.СведФЛИП.ФИОФЛИП.Отч": "Каримович",
|
||
"УчастникФЛИП.ИдентификацияФЛ": "1",
|
||
}
|
||
row = build_fixed_row_by_index(
|
||
file_name="f.xml",
|
||
record_id="R1",
|
||
operation_index=1,
|
||
operation_fields={},
|
||
participant_fields=participant_fields,
|
||
)
|
||
assert row[114] == "Азимов Ислом Каримович"
|
||
assert row[119] == ""
|
||
assert row[122] == ""
|
||
|
||
row_with_one_line_fio = build_fixed_row_by_index(
|
||
file_name="f.xml",
|
||
record_id="R2",
|
||
operation_index=2,
|
||
operation_fields={},
|
||
participant_fields={
|
||
**participant_fields,
|
||
"УчастникФЛИП.СведФЛИП.ФИОФЛИП.ФИОСтрока": ("Азимов Ислом Каримович"),
|
||
},
|
||
)
|
||
assert row_with_one_line_fio[119] == ""
|
||
assert row_with_one_line_fio[122] == ""
|