"""Метки строк-показателей (§1.3, #58): колонка «Показатели» и текст строки.""" import pytest from gridbuilder import L, M, at, sheet_from_rows from src.parser.detect import TableHeader, find_table_header from src.parser.grid import Sheet from src.parser.indicators import RowLabel, is_indicator_total, read_label from src.parser.rules import Rules, load_rules TITLE = "Оборотно-сальдовая ведомость по счету 60 за 1 квартал 2025 г." LABEL_COL = 2 FIRST_ROW = 4 @pytest.fixture(scope="module") def rules() -> Rules: return load_rules() def _sheet(*labels: str, text: str = "60") -> tuple[Sheet, TableHeader]: rows: list[list[object]] = [ [TITLE], ["Счет", None, M("Сальдо на начало периода", 2), M("Обороты за период", 2), M("Сальдо на конец периода", 2)], ["Счет", "Показатели", "Дебет", "Кредит", "Дебет", "Кредит", "Дебет", "Кредит"], ] rows.extend([L(0), *at({1: text, LABEL_COL: label, 3: 10, 8: 10})] for label in labels) sheet = sheet_from_rows(rows) return sheet, find_table_header(sheet, load_rules()) def _read(label: str, rules: Rules, text: str = "60") -> tuple[RowLabel, int]: sheet, header = _sheet(label, text=text) return read_label(sheet, FIRST_ROW, text, header, rules), FIRST_ROW def test_bu_label_is_data_row(rules: Rules) -> None: result, _ = _read("БУ", rules) assert (result.indicator, result.data_type, result.text) == (False, "BU", None) def test_nu_label_is_indicator_with_label_text(rules: Rules) -> None: result, _ = _read("НУ", rules) assert (result.indicator, result.data_type, result.text, result.warning) == (True, "NU", "НУ", None) def test_untyped_label_has_no_data_type_and_no_warning(rules: Rules) -> None: result, _ = _read("ПР", rules) assert (result.indicator, result.data_type, result.text, result.warning) == (True, None, "ПР", None) def test_unknown_label_warns_with_row_number(rules: Rules) -> None: result, row = _read("Ед.", rules) assert (result.indicator, result.data_type) == (True, None) assert result.warning is not None assert f"строка {row}" in result.warning assert "Ед." in result.warning def test_text_currency_label_without_column(rules: Rules) -> None: sheet = sheet_from_rows( [ [TITLE], ["Счет", M("Сальдо на начало периода", 2), M("Обороты за период", 2), M("Сальдо на конец периода", 2)], ["Счет", "Дебет", "Кредит", "Дебет", "Кредит", "Дебет", "Кредит"], [L(0), *at({1: "В валюте", 2: 10})], [L(0), *at({1: "Валюта USD", 2: 10})], ] ) header = find_table_header(sheet, rules) assert header.indicator_col is None in_currency = read_label(sheet, 4, "В валюте", header, rules) assert (in_currency.indicator, in_currency.data_type, in_currency.text) == (True, "CURRENCY", None) plain = read_label(sheet, 5, "Валюта USD", header, rules) assert (plain.indicator, plain.data_type) == (False, None) def test_is_indicator_total(rules: Rules) -> None: sheet, header = _sheet("НУ", "БУ", "") assert is_indicator_total(sheet, FIRST_ROW, header, rules) assert not is_indicator_total(sheet, FIRST_ROW + 1, header, rules) assert not is_indicator_total(sheet, FIRST_ROW + 2, header, rules)