"""Отображаемое значение числа по числовому формату ячейки (#42, R-2…R-6): примеры из реальных выгрузок 1С.""" from decimal import Decimal import pytest from src.parser.statements.number_format import display_amount def shown(raw: str, fmt: str) -> tuple[str, Decimal | None]: result = display_amount(Decimal(raw), fmt) return result.kind, result.value @pytest.mark.parametrize( ("raw", "fmt", "expected"), [ ("10741981390", "#,##0,", "10741981.00"), ("586260.26", "0,", "586.00"), ("898852.21795", "#,##0", "898852.00"), ("898852.5", "#,##0", "898853.00"), ("1234.5", "#,##0.00", "1234.50"), ("1234.567", "#,##0.00", "1234.57"), ("1500", "#,##0,", "2.00"), ("-1500", "#,##0,", "-2.00"), ("1499.99", "#,##0,", "1.00"), ("-1499.99", "#,##0,", "-1.00"), ("586260.26", "0.00,", "586.26"), ("5000000", "#,##0,,", "5.00"), ("1500", '#,##0,;(#,##0,);"-"', "2.00"), ("-1500", '#,##0,;(#,##0,);"-"', "-2.00"), ("1500", "#,##0;(#,##0)", "1500.00"), ("-1500", "#,##0;(#,##0)", "-1500.00"), ("-1500", "#,##0;#,##0", "-1500.00"), ("1500", "[Red]#,##0", "1500.00"), ("1500", "[$-419]#,##0", "1500.00"), ("1500", "#,##0_);[Red](#,##0)", "1500.00"), ("-1500", "#,##0_);[Red](#,##0)", "-1500.00"), ("1500.126", "0.000", "1500.13"), ("1500", '0 "тыс."', "1500.00"), ("-872206880.07", '[=-872206880.07]"(872 207)";#,##0,', "-872207.00"), ("-872206881", '[=-872206880.07]"(872 207)";#,##0,', "-872207.00"), ("-646532", '[=-646532]"(647)"', "-647.00"), ("12345678", '[=-872206880.07]"(872 207)";#,##0,', "12346.00"), ], ) def test_value(raw: str, fmt: str, expected: str) -> None: kind, value = shown(raw, fmt) assert kind == "value" assert value is not None assert str(value) == expected @pytest.mark.parametrize( ("raw", "fmt"), [ ("0", '[=0]"-"'), ("0", '[=0]""'), ("0", '[=0]"-";General'), ("-0.79", '[=-0.79]"-"'), ("0", '#,##0,;(#,##0,);"-"'), ], ) def test_no_value(raw: str, fmt: str) -> None: assert shown(raw, fmt) == ("value", None) @pytest.mark.parametrize( ("raw", "fmt"), [ ("5", '[=0]"-"'), ("5", "0%"), ("5", "0.00E+00"), ("5", "# ?/?"), ("5", "@"), ("5", "dd.mm.yyyy"), ("5", "h:mm AM/PM"), ("0", '[=0]"н/д"'), ("5", '"н/д"'), ("5", "0 руб"), ], ) def test_unparsed(raw: str, fmt: str) -> None: assert shown(raw, fmt) == ("unparsed", None) @pytest.mark.parametrize("fmt", ["General", "general", "", " "]) def test_raw(fmt: str) -> None: assert shown("5.5", fmt) == ("raw", None) def test_general_section_after_condition() -> None: assert shown("5.5", '[=0]"-";General') == ("raw", None) @pytest.mark.parametrize( ("raw", "fmt", "expected"), [ ("5", "[<10]0;[>=10]0,", "5.00"), ("20000", "[<10]0;[>=10]0,", "20.00"), ("5", "[<>5]0;0.0", "5.0"), ], ) def test_comparison_conditions(raw: str, fmt: str, expected: str) -> None: kind, value = shown(raw, fmt) assert kind == "value" assert value is not None assert Decimal(expected) == value def test_fourth_section_ignored() -> None: assert shown("1500", "#,##0,;(#,##0,);0;@") == ("value", Decimal("2.00")) def test_semicolon_in_quotes_does_not_split() -> None: assert shown("0", '[=0]"a;b"') == ("unparsed", None) def test_escaped_char_is_decoration() -> None: assert shown("1500", "#,##0\\ \\р") == ("value", Decimal("1500.00")) def test_huge_value_out_of_range_is_unparsed() -> None: assert shown("1" + "0" * 40, "#,##0") == ("unparsed", None) def test_max_numeric_18_2_range() -> None: assert shown("9999999999999999", "0") == ("value", Decimal("9999999999999999.00")) assert shown("99999999999999999", "0") == ("unparsed", None) def test_scaled_huge_value_fits() -> None: assert shown("99999999999999999000", "0,") == ("unparsed", None) assert shown("9999999999999999000", "0,") == ("value", Decimal("9999999999999999.00"))