The АдрМестаПриемаВыдача block under СведенияКартаИнБанк (code 1009) has no single АдресСтрока tag, unlike the same-named block under СведенияВнесениеПолучениеНалДС — column 99 was mapped directly onto that nonexistent tag and stayed empty. It now assembles the value from the individual address components (Индекс, КодОКСМ, КодСубъектаПоОКАТО, Район, Пункт, Улица, Дом, Корп, Оф), the same way column 153 already does for registration place. Also disabled allow_short_lookup for this column, since it was previously able to pick up a same-named tag (e.g. Улица) from an unrelated address elsewhere in the file. Added regression tests at both the mapping level and a full parse_xml_content -> build_fixed_row_by_index pipeline level with a synthetic code-1009 XML.
126 lines
3.7 KiB
Python
126 lines
3.7 KiB
Python
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_EXTRA_INFO = _index(34)
|
|
|
|
# Перевод.
|
|
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_FOREIGN_CARD_ADDRESS_STRUCTURED = _index(99)
|
|
COL_CARD_HOLDER_INFO = _index(103)
|
|
COL_EMPLOYEE_SIGN = _index(104)
|
|
COL_FOREIGN_BANK_NAME = _index(105)
|
|
COL_OPERATION_DOCUMENTS = _index(107)
|
|
|
|
# Участник.
|
|
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_STAY_DOCUMENT_TYPE = _index(136)
|
|
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_ADDRESS_ONE_LINE = _index(167)
|
|
|
|
# ЕИО и ценные бумаги.
|
|
COL_EIO_INN = _index(163)
|
|
COL_EIO_OTHER_INFO = _index(164)
|
|
COL_EIO_REG_PLACE_ONE_LINE = _index(178)
|
|
COL_EIO_REG_PLACE_STRUCTURED = _index(179)
|
|
COL_CP_ISSUER_INN = _index(202)
|
|
|
|
# Блоки схемы.
|
|
BLOCK_EIO = COLUMNS.block("eio")
|
|
BLOCK_CP = COLUMNS.block("cp")
|
|
PARTICIPANT_ADDRESS_COMPONENT_COLUMNS = tuple(
|
|
column.index
|
|
for column in COLUMNS.ordered_columns()
|
|
if column.structured_group == "legacy_142" and column.structured_role == "component"
|
|
)
|
|
|
|
# Точные поля наличных, которые исторически очищаются для безналичных переводов.
|
|
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),
|
|
)
|
|
)
|
|
|
|
# Бизнес-константы.
|
|
ACCOUNT_PLACEHOLDER = "00000000000000000000"
|
|
EXPORT_SUBSIDIARY_COMMENT_CODES = frozenset(str(code) for code in range(6102, 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"
|