116 lines
4.4 KiB
Python
116 lines
4.4 KiB
Python
from typing import Any
|
||
|
||
from arm_statements.header import parse_header
|
||
from arm_statements.loader import Rules
|
||
from arm_statements.model import LineStatus, StatementWarning
|
||
from arm_statements.rows import RawLine, collect_raw_lines
|
||
from arm_statements.segments import find_layout
|
||
from arm_statements.tests.builders import excel, hdr, ocr
|
||
|
||
HEAD = ["Наименование показателя", "Код", "На 30.09.2025", "На 31.12.2024"]
|
||
OK, UNREADABLE, DETAIL, MISSING = LineStatus.OK, LineStatus.UNREADABLE, LineStatus.DETAIL, LineStatus.MISSING
|
||
|
||
|
||
def lines_of(rows: Any, rules: Rules, source: str = "ocr") -> tuple[list[RawLine], list[StatementWarning]]:
|
||
cand = ocr(rows) if source == "ocr" else excel([("Баланс", rows)])
|
||
layout = find_layout(cand, parse_header(hdr(), rules), rules)
|
||
return collect_raw_lines(cand, layout, rules)
|
||
|
||
|
||
def test_junk_code_lines_survive(rules: Rules) -> None:
|
||
lines, _ = lines_of(
|
||
[
|
||
HEAD,
|
||
["НМА", "1110", "5", "4"],
|
||
["Запасы", "1150", "5", "4"],
|
||
["Мусор", "ИЧ,250", "7", "6"],
|
||
["в том числе: прочее", "", "1", ""],
|
||
["", "44 30\nI |", "", ""],
|
||
["Итого", "1100", "10", "8"],
|
||
],
|
||
rules,
|
||
)
|
||
assert [(ln.line_status, ln.code) for ln in lines] == [
|
||
(OK, "1110"),
|
||
(OK, "1150"),
|
||
(UNREADABLE, None),
|
||
(DETAIL, None),
|
||
(UNREADABLE, None),
|
||
(OK, "1100"),
|
||
]
|
||
assert lines[3].parent_ref == lines[1].ref == "row:2"
|
||
assert [ln.row_index for ln in lines] == [0, 1, 2, 3, 4, 5]
|
||
|
||
|
||
def test_lookalike_only_code_cells_are_empty(rules: Rules) -> None:
|
||
lines, _ = lines_of(
|
||
[
|
||
HEAD,
|
||
["НМА", "1110", "5", "4"],
|
||
["Запасы", "1150", "5", "4"],
|
||
["", "изо :", ("3", 0.0), ""],
|
||
["", "НИ", "I", ""],
|
||
["", "| 140", "2", "1"],
|
||
["Итого", "1100", "12", "9"],
|
||
],
|
||
rules,
|
||
)
|
||
assert [(ln.line_status, ln.code, ln.code_fixed) for ln in lines] == [
|
||
(OK, "1110", False),
|
||
(OK, "1150", False),
|
||
(DETAIL, None, False),
|
||
(DETAIL, None, False),
|
||
(OK, "1140", True),
|
||
(OK, "1100", False),
|
||
]
|
||
assert [ln.parent_ref for ln in lines[2:4]] == ["row:2", "row:2"]
|
||
assert len({ln.ref for ln in lines}) == len(lines)
|
||
|
||
|
||
def test_missing_before_first_code_and_name_only_row(rules: Rules) -> None:
|
||
lines, _ = lines_of(
|
||
[HEAD, ["Выручка", "", "100", "90"], ["Раздел I. Активы", "", "", ""], ["Запасы", "1150", "5", "4"]], rules
|
||
)
|
||
assert [ln.line_status for ln in lines] == [MISSING, OK]
|
||
|
||
|
||
def test_duplicate_code_both_ok(rules: Rules) -> None:
|
||
lines, _ = lines_of([HEAD, ["Налог", "2410", "100", "1"], ["Налог УСН", "2410", "649", "2"]], rules)
|
||
assert [(ln.line_status, ln.code) for ln in lines] == [(OK, "2410"), (OK, "2410")]
|
||
|
||
|
||
def test_split_glued_rows(rules: Rules) -> None:
|
||
lines, warnings = lines_of(
|
||
[HEAD, ["Запасы", "1150", "5", "4"], ["Займы\nКредиторы", "1500\n1700", "917 775\n2 371 333", "1\n2"]], rules
|
||
)
|
||
split = lines[1:]
|
||
assert [(ln.ref, ln.code, ln.split) for ln in split] == [("row:2#1", "1500", True), ("row:2#2", "1700", True)]
|
||
assert [ln.cells[0][1].text for ln in split if ln.cells[0][1] is not None] == ["917 775", "2 371 333"]
|
||
assert [ln.name.text for ln in split if ln.name is not None] == ["Займы", "Кредиторы"]
|
||
assert [(w.code, w.line_refs) for w in warnings] == [("ROW_SPLIT", ("row:2#1", "row:2#2"))]
|
||
|
||
|
||
def test_not_split_when_no_part_in_column_range(rules: Rules) -> None:
|
||
lines, warnings = lines_of(
|
||
[
|
||
HEAD,
|
||
["НМА", "1110", "5", "4"],
|
||
["Запасы", "1150", "5", "4"],
|
||
["", "44 30\nI |", "1\n2", ""],
|
||
["Итого", "1100", "10", "8"],
|
||
],
|
||
rules,
|
||
)
|
||
assert [ln.line_status for ln in lines] == [OK, OK, UNREADABLE, OK] and warnings == []
|
||
|
||
|
||
def test_excel_signature_text_is_not_content(rules: Rules) -> None:
|
||
rows = [
|
||
["Наименование", "", "Код", "На 30.09.2025"],
|
||
["Запасы", "", "1150", "5"],
|
||
["Руководитель", "", "", "Иванов"],
|
||
["", "", "", "(расшифровка подписи)"],
|
||
]
|
||
lines, _ = lines_of(rows, rules, source="excel")
|
||
assert [ln.ref for ln in lines] == ["Баланс!C2"]
|