"""Суммы из OCR-ячеек (§11.1 п. 7): перенос `_parse_amount`/`_is_blank` старого ядра.""" from decimal import Decimal import pytest from src.normalizer.ocr.amounts import ParsedAmount, is_blank, parse_amount @pytest.mark.parametrize( ("raw", "amount", "verified"), [ ("13 070", Decimal("13070"), True), ("(6032409)", Decimal("-6032409"), True), ("(7744536}", Decimal("7744536"), False), # закрывающая скобка не распознана: минус не ставится (решение №12) ("1 234,56", Decimal("1234.56"), True), ("1.234.567", Decimal("1234567"), True), # точки строго через три цифры — разделители тысяч (AURORA-1405, #37) ("30127", Decimal("30127"), True), ("211(1 |", Decimal("2111"), False), ("не ****", None, False), ("", None, True), ("--", None, True), # прочерк: ничего не отброшено, суммы нет (NULL) (":", None, False), # несколько точек: удаляются ВСЕ точки, десятичная часть теряется (`1.234,56` — не 1234.56), всегда не verified ("1.234,56", Decimal("123456"), False), ("1,234.56", Decimal("123456"), False), # запятая-разделитель тысяч (AURORA-1405, scan-gateway#35): удаляется до замены запятой на точку, verified=True ("1,234", Decimal("1234"), True), ("4,200", Decimal("4200"), True), ("(4,200)", Decimal("-4200"), True), ("1,234,567", Decimal("1234567"), True), ("-4,200", Decimal("-4200"), True), ("+4,200", Decimal("4200"), True), ("(-4,200)", Decimal("-4200"), True), ("4,2", Decimal("4.2"), True), ("12,34", Decimal("12.34"), True), ("1,23", Decimal("1.23"), True), # не тысячи: больше двух знаков после запятой остаётся десятичным — `Money` отсекает `document._value` (№30) ("0,125", Decimal("0.125"), True), ("12,3456", Decimal("12.3456"), True), ("4,200,", Decimal("4200"), False), # хвостовая запятая: правило не применяется (две точки удалены, как раньше) ("(4,200}", Decimal("4.200"), False), # нет пары скобок: правило не применяется, минус не ставится # скобки не на всю строку — правило тысяч не применяется, прежний разбор (запятая → точка) ("(4,200) руб", Decimal("-4.200"), False), ("abc(4,200)", Decimal("-4.200"), False), ("(4,200)x", Decimal("-4.200"), False), ("(4,200)(1,000)", Decimal("-4.200"), False), ("1,234(5,678)", Decimal("-5.678"), False), ("((4,200))", Decimal("-4.200"), True), ("1234,567", Decimal("1234.567"), True), # запятая НЕ расширена (R-7): четыре цифры до неё — не тысячи ("1 234,567", Decimal("1234.567"), True), ("01,234", Decimal("1.234"), True), # ведущий ноль — не тысячи ("4,2000", Decimal("4.2000"), True), ("1, 234", Decimal("1234"), True), # пробелы убираются первыми # точка-разделитель тысяч (AURORA-1405, scan-gateway#37): то же правило, что для запятой, verified=True ("4.200", Decimal("4200"), True), ("837.994", Decimal("837994"), True), ("(4.200)", Decimal("-4200"), True), ("-4.200", Decimal("-4200"), True), ("+4.200", Decimal("4200"), True), ("(-4.200)", Decimal("-4200"), True), ("1.234", Decimal("1234"), True), ("100.000", Decimal("100000"), True), ("1. 234", Decimal("1234"), True), # пробелы убираются первыми # ровно три цифры после точки — тысячи независимо от числа цифр до неё (R-3, решение владельца 16.10.2026) ("1 234.567", Decimal("1234567"), True), ("1234.567", Decimal("1234567"), True), ("12345.678", Decimal("12345678"), True), ("(1 234.567)", Decimal("-1234567"), True), ("-1234.567", Decimal("-1234567"), True), ("1234.567.890", Decimal("1234567890"), True), # не тысячи: не три цифры после точки — десятичная дробь, как раньше ("4.2", Decimal("4.2"), True), ("4.20", Decimal("4.20"), True), ("12.34", Decimal("12.34"), True), ("1.2345", Decimal("1.2345"), True), ("0.125", Decimal("0.125"), True), # ведущий ноль — не тысячи ("01.234", Decimal("1.234"), True), ("1234.56", Decimal("1234.56"), True), # дробная часть не из трёх цифр — дробь ("1234.5678", Decimal("1234.5678"), True), # смешанные разделители и прочий мусор — правило не применяется (R-1): прежний разбор ("1.234,567", Decimal("1234567"), False), ("1,234.567", Decimal("1234567"), False), ("1.234.56", Decimal("123456"), False), ("4.200.", Decimal("4200"), False), # хвостовая точка ("(4.200}", Decimal("4.200"), False), # нет пары скобок: правило не применяется, минус не ставится ("(4.200) руб", Decimal("-4.200"), False), ("abc(4.200)", Decimal("-4.200"), False), ("(4.200)(1.000)", Decimal("-4.200"), False), ("1.234(5.678)", Decimal("-5.678"), False), # №13: скобки без содержимого — не сумма, но и не «неразобранный текст» ("()", None, True), ("( )", None, True), ("(.)", None, True), ("(+5)", Decimal("-5"), True), # в скобках знак заменяется минусом ], ) def test_parse_amount(raw: str, amount: Decimal | None, verified: bool) -> None: assert parse_amount(raw) == ParsedAmount(amount, verified) @pytest.mark.parametrize( ("raw", "expected"), [("", True), ("-", True), ("—", True), (" – ", True), ("0", False), ("x", False)], ) def test_is_blank(raw: str, expected: bool) -> None: assert is_blank(raw) is expected