Andrey Epifancev 55b60f58b2 feat(statements): строки с кодом, значения Decimal, дубликаты кодов, предупреждение о единицах
Refs #14

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Claude-Session: cedd7915-2efe-41e5-988c-a9117033598b
2026-10-06 16:59:02 +04:00

93 lines
4.3 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.

"""Строки с кодом и значения (design D-6; spec «Строки с кодом и значения»)."""
from decimal import Decimal
import pytest
from gridbuilder import sheet_from_rows
from src.parser.rules import Rules, load_rules
from src.parser.statements.columns import find_layout
from src.parser.statements.lines import collect_lines
_FULL_CONFIDENCE = 100
_FRACTIONAL_VALUES_COUNT = 4
_NUMERIC_VALUES_COUNT = 9
_SKIPPED_WITH_SUMS_COUNT = 1
@pytest.fixture(scope="module")
def rules() -> Rules:
return load_rules()
ROWS = [
["Пояснения", "Наименование показателя", "Код", "На 31 декабря 2024 г.", "На 31 декабря 2023 г."],
[None, "АКТИВ"],
[None, "Нематериальные активы", "1110", Decimal("5971264.14"), 27405634],
[None, "Нематериальные активы\nв организации", "11101", Decimal("5852464.14"), "27 214 614,65"],
[None, None, None, 0, 0],
[None, "в том числе:"],
[None, "Финансовые вложения", "1170", None, 10],
[None, "Прочие", "1190", "–", "(2 100)"],
[None, "Запасы", "1210", "н/д", 5],
[None, "Запасы", "1210", 1, 1],
[None, "Итого по разделу I", "1100", Decimal("11823728.28"), 27405644],
]
def test_lines_values_and_skips(rules: Rules) -> None:
sheet = sheet_from_rows(ROWS)
layout = find_layout(sheet, rules, 1, sheet.n_rows)
result = collect_lines(sheet, rules, layout, layout.first_data_row, sheet.n_rows)
codes = [line.line_code for line in result.lines]
assert codes == ["1110", "11101", "1170", "1190", "1210", "1100"]
by_code = {line.line_code: line for line in result.lines}
assert by_code["11101"].line_name == "Нематериальные активы в организации"
assert [value.amount for value in by_code["11101"].values] == [Decimal("5852464.14"), Decimal("27214614.65")]
assert by_code["1170"].values[0].amount is None and by_code["1170"].values[0].is_recognized is True
assert by_code["1190"].values[0].amount is None and by_code["1190"].values[1].amount == Decimal("-2100.00")
unrecognised = by_code["1210"].values[0]
assert unrecognised.amount is None and unrecognised.string_value == "н/д" and unrecognised.is_recognized is False
assert all(value.confidence == _FULL_CONFIDENCE for line in result.lines for value in line.values)
assert all(
line.line_code_confidence == _FULL_CONFIDENCE and line.line_name_confidence == _FULL_CONFIDENCE
for line in result.lines
)
assert [value.column_index for value in by_code["1110"].values] == [0, 1]
assert result.duplicates == ["1210"] and by_code["1210"].values[1].amount == Decimal("5.00")
assert result.skipped_with_sums == _SKIPPED_WITH_SUMS_COUNT # строка нулей без кода
assert result.fractional_values == _FRACTIONAL_VALUES_COUNT and result.numeric_values == _NUMERIC_VALUES_COUNT
def test_fractional_warning_when_units_thousands(rules: Rules) -> None:
sheet = sheet_from_rows(ROWS)
layout = find_layout(sheet, rules, 1, sheet.n_rows)
result = collect_lines(sheet, rules, layout, layout.first_data_row, sheet.n_rows, units="в тыс. рублей")
expected_warning = (
f"значений с дробной частью при единице тыс. руб.: {_FRACTIONAL_VALUES_COUNT} из {_NUMERIC_VALUES_COUNT}"
)
assert any(warning.startswith(expected_warning) for warning in result.warnings)
assert any("строк без кода с суммами пропущено: 1" in warning for warning in result.warnings)
def test_no_fractional_warning_without_thousands(rules: Rules) -> None:
sheet = sheet_from_rows(ROWS)
layout = find_layout(sheet, rules, 1, sheet.n_rows)
result = collect_lines(sheet, rules, layout, layout.first_data_row, sheet.n_rows, units="руб.")
assert not any("дробной частью" in warning for warning in result.warnings)
def test_line_without_name_column(rules: Rules) -> None:
sheet = sheet_from_rows([["Код", "На 31.12.2024"], ["1150", 5], ["1210", 6], ["1600", 11]])
layout = find_layout(sheet, rules, 1, 4)
result = collect_lines(sheet, rules, layout, layout.first_data_row, 4)
assert [line.line_name for line in result.lines] == ["", "", ""]