diff --git a/api/src/parser/classify.py b/api/src/parser/classify.py index a2f80e2..eddb1a6 100644 --- a/api/src/parser/classify.py +++ b/api/src/parser/classify.py @@ -31,7 +31,7 @@ from src.parser.deadline import Deadline from src.parser.detect import GROUP_ORDER, ColumnMap, TableHeader, first_data_row, is_header_repeat from src.parser.grid import Sheet, column_letter from src.parser.hierarchy import BodyRow, Levels -from src.parser.indicators import is_indicator_total, read_label, row_data_type +from src.parser.indicators import is_indicator_total, read_label from src.parser.numbers import column_inn, split_inn_suffix, to_money from src.parser.rules import GroupType, Rules @@ -43,7 +43,6 @@ __all__ = [ "RowGroupType", "classify_rows", "collect_body_rows", - "row_data_type", ] # Код счёта: две-три цифры и до двух сегментов субсчёта («60», «60.01», «76.07.1», «001»); сегмент — 1–2 цифры или diff --git a/api/src/parser/osv.py b/api/src/parser/osv.py index 69ec6c4..3c0809c 100644 --- a/api/src/parser/osv.py +++ b/api/src/parser/osv.py @@ -200,7 +200,7 @@ class OsvParser: data_type = doc.data_type or DEFAULT_DATA_TYPE # Вид данных шапки не указан: строки без метки приняты как БУ — предупреждение, если умолчание сработало defaulted = doc.data_type is None and any( - not item.indicator and item.label_data_type is None for item in body + not item.indicator and item.label_data_type is None for item in glue.rows ) classified = classify_rows( glue.rows, diff --git a/api/tests/unit/parser/test_classify.py b/api/tests/unit/parser/test_classify.py index 75eba01..e120156 100644 --- a/api/tests/unit/parser/test_classify.py +++ b/api/tests/unit/parser/test_classify.py @@ -12,13 +12,14 @@ import pytest from gridbuilder import C, L, M, sheet_from_rows from src.contract.common import DataType -from src.parser.classify import ACCOUNT_RE, ClassifiedRow, classify_rows, collect_body_rows, row_data_type +from src.parser.classify import ACCOUNT_RE, ClassifiedRow, classify_rows, collect_body_rows from src.parser.deadline import Deadline from src.parser.detect import find_table_header from src.parser.errors import ParseTimeoutError from src.parser.grid import Sheet from src.parser.header import build_group_levels from src.parser.hierarchy import TRIVIAL_STRATEGY, Levels, resolve_levels +from src.parser.indicators import row_data_type from src.parser.inn_rows import glue_inn_rows from src.parser.rules import Rules, load_rules diff --git a/api/tests/unit/parser/test_inn_rows_osv.py b/api/tests/unit/parser/test_inn_rows_osv.py index 3c44a80..6d90416 100644 --- a/api/tests/unit/parser/test_inn_rows_osv.py +++ b/api/tests/unit/parser/test_inn_rows_osv.py @@ -47,3 +47,41 @@ def test_inn_glued_to_row_that_is_not_a_counterparty_needs_check(rules: Rules) - assert not ok expected = f"строка 10: ИНН {INN_A} отнесён к строке 11, но она не контрагент — проверьте" assert expected in warnings, warnings + + +# --- Умолчание вида данных (#58, T6.1) --- + +BU_DEFAULT_WARNING = "вид данных в шапке не указан — строки без метки приняты как БУ" + + +def _labelled_sheet(bu_label: object) -> object: + return sheet_from_rows( + [ + ["Оборотно-сальдовая ведомость по счету 60 за 1 квартал 2025 г."], + [ + "Счет", + None, + M("Сальдо на начало периода", 2), + M("Обороты за период", 2), + M("Сальдо на конец периода", 2), + ], + ["Контрагенты", "Показатели", "Дебет", "Кредит", "Дебет", "Кредит", "Дебет", "Кредит"], + [L(0), "60", bu_label, *A], + [L(1), "ООО Альфа", bu_label, *A], + [L(1), None, "НУ", *A], + [L(0), "Итого", bu_label, *A], + ] + ) + + +def test_default_warning_not_given_when_all_rows_are_labelled(rules: Rules) -> None: + result = OsvParser(rules).parse_sheet(_labelled_sheet("БУ"), Deadline(TIMEOUT_SECONDS)) # type: ignore[arg-type] + + assert BU_DEFAULT_WARNING not in [note.message for note in result.notes] + assert result.document.header.data_type is None + + +def test_default_warning_given_once_when_rows_have_no_label(rules: Rules) -> None: + result = OsvParser(rules).parse_sheet(_labelled_sheet(None), Deadline(TIMEOUT_SECONDS)) # type: ignore[arg-type] + + assert [note.message for note in result.notes].count(BU_DEFAULT_WARNING) == 1