SFM/tests/unit/test_mapping.py
Raykov-MS bef38dedd8 fix
2026-08-11 13:08:00 +03:00

1088 lines
40 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

from __future__ import annotations
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={
"Индекс": "674500",
},
participant_fields={},
)
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_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_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_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_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_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_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_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_columns_apply_only_to_conversion_and_currency_operations() -> 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] == ""
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] == ""
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] == ""