diff --git a/api/tests/unit/parser/statements/test_header.py b/api/tests/unit/parser/statements/test_header.py index ba92d37..32ec74a 100644 --- a/api/tests/unit/parser/statements/test_header.py +++ b/api/tests/unit/parser/statements/test_header.py @@ -184,3 +184,47 @@ def test_inn_from_auditor_block_only_is_none(rules: Rules) -> None: header, _ = parse_header(sheet, rules, 1, 9, _block(sheet, rules)) assert header.inn is None, f"Should not pick up auditor INN 9999999999, got {header.inn}" + + +def test_inn_not_taken_from_auditor_block_above_organization_inn(rules: Rules) -> None: + """Guard test (b): auditor block ABOVE org INN; guard excludes auditor INN. + + Layout (intentionally reversed from real files): + - Auditor block starts at row 3 (auditor_from=3) + - Auditor INN at row 4: value 7716021332 + - Organization INN at row 8: value 3249004697 + + With guard (search 1..auditor_from-1=1..2): Neither INN found → header.inn is None ✓ + Without guard (search 1..last_row=1..9): Auditor INN at row 4 found first → **FAIL** ✗ + + This test verifies auditor INN is never taken, even when it appears before org INN. + """ + sheet = sheet_from_rows( + [ + [*at({3: "Бухгалтерский баланс"})], + [*at({3: "на 31 декабря 2024 г."})], + [*at({2: "Наименование аудиторской организации"})], + [*at({2: 'АО "ЮНИКОН"'})], + [ + *at( + { + 2: "Идентификационный номер налогоплательщика аудиторской организации", + 33: "ИНН", + 34: "7716021332", + } + ) + ], + [*at({7: 'ООО "ЗАВОД"'})], + [*at({3: "Организация", 7: 'ООО "ЗАВОД"', 13: "по ОКПО", 14: "16098811"})], + [*at({2: "Идентификационный номер налогоплательщика", 33: "ИНН", 34: "3249004697"})], + [*at({2: "Единица измерения", 7: "в тыс. рублей", 33: "по ОКЕИ", 34: "384"})], + ] + ) + + header, _ = parse_header(sheet, rules, 1, 9, _block(sheet, rules)) + + assert header.inn is None, ( + f"Auditor INN 7716021332 at row 4 is above auditor_from boundary; " + f"org INN 3249004697 at row 8 is below. Guard excludes both. " + f"Got {header.inn}" + )