Ячейка в строке с подписью «Код» (словарь пакета) не открывает блок формы: «Пояснения» на листах-продолжениях НПЗ больше не даёт DISCLOSURE. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BJKMLHdxMwSUeYcdkwqX4W
142 lines
6.0 KiB
Python
142 lines
6.0 KiB
Python
"""Блоки форм, вид листа и столбцы на словарях `arm_statements` (план 4, задача 4)."""
|
||
|
||
import pytest
|
||
from gridbuilder import at, sheet_from_rows
|
||
|
||
from arm_statements import DocumentType, continuation_type, default_rules
|
||
from src.parser.statements.forms import (
|
||
StatementRules,
|
||
caption_matches,
|
||
classify_statement_sheet,
|
||
codes_of,
|
||
continuation_marker,
|
||
find_blocks,
|
||
is_weak_continuation,
|
||
matches,
|
||
sheet_amount_columns,
|
||
sheet_code_column,
|
||
)
|
||
|
||
CODE_COL = 3
|
||
|
||
|
||
@pytest.fixture(scope="module")
|
||
def rules() -> StatementRules:
|
||
return default_rules()
|
||
|
||
|
||
def test_title_and_okud_without_codes_between_form_one_block(rules: StatementRules) -> None:
|
||
sheet = sheet_from_rows(
|
||
[
|
||
["Бухгалтерская отчетность"],
|
||
[],
|
||
[None, "Бухгалтерский баланс"],
|
||
[],
|
||
[*at({3: "Форма по ОКУД", 5: "0710001"})],
|
||
[*at({1: "Актив", 3: "Код", 4: "На 30.09.2025"})],
|
||
[*at({1: "Основные средства", 3: "1150", 4: 10})],
|
||
]
|
||
)
|
||
[block] = find_blocks(sheet, rules)
|
||
assert (block.type_hint, block.title, block.okud, block.first_row, block.last_row) == (
|
||
DocumentType.BALANCE,
|
||
(3, 2),
|
||
(5, 5),
|
||
1,
|
||
7,
|
||
)
|
||
|
||
|
||
def test_second_title_after_codes_opens_new_block(rules: StatementRules) -> None:
|
||
balance = [at({1: name, 3: code, 4: 10}) for name, code in (("а", 1110), ("б", 1150), ("в", 1170), ("г", 1600))]
|
||
income = [at({1: name, 3: code, 4: 10}) for name, code in (("д", 2110), ("е", 2120), ("ж", 2400))]
|
||
sheet = sheet_from_rows(
|
||
[["Бухгалтерский баланс"], *balance, ["Отчет о финансовых результатах"], *income],
|
||
)
|
||
blocks = find_blocks(sheet, rules)
|
||
assert [(b.type_hint, b.first_row, b.last_row) for b in blocks] == [
|
||
(DocumentType.BALANCE, 1, 5),
|
||
(DocumentType.INCOME, 6, 9),
|
||
]
|
||
|
||
|
||
def test_okud_wins_over_title(rules: StatementRules) -> None:
|
||
blocks = find_blocks(sheet_from_rows([["Бухгалтерский баланс"], ["по ОКУД", "0710002"]]), rules)
|
||
assert [block.type_hint for block in blocks] == [DocumentType.INCOME]
|
||
|
||
|
||
def test_report_title_alone_is_not_a_form(rules: StatementRules) -> None:
|
||
assert find_blocks(sheet_from_rows([["Бухгалтерская отчетность"]]), rules) == []
|
||
|
||
|
||
def test_continuation_marker_is_not_a_block(rules: StatementRules) -> None:
|
||
sheet = sheet_from_rows([["Форма 0710001 с.2"], ["Пассив", "Код", "На 30.09.2025"], ["Капитал", "1310", 10]])
|
||
assert find_blocks(sheet, rules) == []
|
||
assert classify_statement_sheet(sheet, rules) == "continuation"
|
||
|
||
|
||
def test_code_column_ignores_title_codes_block(rules: StatementRules) -> None:
|
||
titles = ["Коды", "0710001", 30, "09", 2025, 12345678, 7700000000, 12267, 16, 384]
|
||
codes = [1110, 1150, 1170, 1100, 1210, 1230]
|
||
rows = [at({6: value}) for value in titles]
|
||
rows += [at({3: code, 4: 10}) for code in codes]
|
||
sheet = sheet_from_rows(rows)
|
||
assert sheet_code_column(sheet, rules, 1, sheet.n_rows) == CODE_COL
|
||
assert codes_of(sheet, rules, CODE_COL, 1, sheet.n_rows) == [str(code) for code in codes]
|
||
|
||
|
||
def test_amount_columns_counts_numeric_columns_right_of_code(rules: StatementRules) -> None:
|
||
rows = [at({1: "Актив", 3: "Код", 4: "На 30.09.2025", 7: "Изменение"})]
|
||
rows += [at({1: "Статья", 3: code, 4: 1, 5: 2, 6: 3, 7: "рост"}) for code in (1110, 1150, 1170, 1100)]
|
||
sheet = sheet_from_rows(rows)
|
||
assert sheet_amount_columns(sheet, rules, CODE_COL, 1, sheet.n_rows) == CODE_COL
|
||
|
||
|
||
def test_weak_and_other_sheets(rules: StatementRules) -> None:
|
||
weak = sheet_from_rows([["Чистая прибыль", "2400", 10, 8]])
|
||
assert classify_statement_sheet(weak, rules) == "other"
|
||
assert is_weak_continuation(weak, rules, DocumentType.INCOME)
|
||
assert not is_weak_continuation(weak, rules, DocumentType.BALANCE)
|
||
notes = sheet_from_rows([["Примечания"], ["Текст пояснения к отчетности"]])
|
||
assert classify_statement_sheet(notes, rules) == "other"
|
||
assert not is_weak_continuation(notes, rules, DocumentType.INCOME)
|
||
|
||
|
||
def test_marker_with_unknown_okud_is_continuation(rules: StatementRules) -> None:
|
||
rows = [["Форма 0710000 с.2"]] + [at({1: "Статья", 3: code, 4: 10}) for code in (1110, 1150, 1170)]
|
||
sheet = sheet_from_rows(rows)
|
||
assert find_blocks(sheet, rules) == []
|
||
assert classify_statement_sheet(sheet, rules) == "continuation"
|
||
marker = continuation_marker(sheet, rules)
|
||
assert marker is not None
|
||
assert marker.text == "Форма 0710000 с.2"
|
||
assert continuation_type(marker.text, rules) is None
|
||
|
||
|
||
def test_labels_with_punctuation_match(rules: StatementRules) -> None:
|
||
assert matches(rules.headers.labels["address"], "Местонахождение (адрес)")
|
||
assert matches(rules.headers.labels["okopf_okfs"], "по ОКОПФ / ОКФС")
|
||
assert matches(rules.headers.legal_form, "АО «Пример»")
|
||
assert caption_matches([rules.headers.code_caption], "Код")
|
||
|
||
|
||
def test_column_caption_in_table_header_is_not_a_form_title(rules: StatementRules) -> None:
|
||
rows = [
|
||
["Форма 0710001 с.2"],
|
||
at({1: "Наименование", 2: "Пояснения", 3: "Код", 4: "На 30.09.2025"}),
|
||
at({1: "Капитал", 3: 1310, 4: 10}),
|
||
]
|
||
sheet = sheet_from_rows(rows)
|
||
assert find_blocks(sheet, rules) == []
|
||
assert classify_statement_sheet(sheet, rules) == "continuation"
|
||
|
||
|
||
def test_real_title_above_same_table_header_stays_a_block(rules: StatementRules) -> None:
|
||
rows = [
|
||
["Бухгалтерский баланс"],
|
||
at({1: "Наименование", 2: "Пояснения", 3: "Код", 4: "На 30.09.2025"}),
|
||
at({1: "Капитал", 3: 1310, 4: 10}),
|
||
]
|
||
[block] = find_blocks(sheet_from_rows(rows), rules)
|
||
assert block.type_hint is DocumentType.BALANCE
|