Refs #14 Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com> Claude-Session: cedd7915-2efe-41e5-988c-a9117033598b
93 lines
4.3 KiB
Python
93 lines
4.3 KiB
Python
"""Строки с кодом и значения (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] == ["", "", ""]
|