fix: черновик продолжения несёт число колонок сумм (#54)

M-1: _separate считает form_amount_columns, следующий лист без маркера
больше не получает ложный SHEET_NOT_JOINED.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BJKMLHdxMwSUeYcdkwqX4W
This commit is contained in:
Andrey Epifancev 2026-10-18 22:05:06 +04:00
parent 2fce78080b
commit 0d82b5cf5e
2 changed files with 35 additions and 4 deletions

View File

@ -129,14 +129,21 @@ def _form_block_drafts(sheet: Sheet, rules: StatementRules) -> list[_Draft]:
return drafts return drafts
def _separate(sheet: Sheet, type_hint: DocumentType | None) -> _Draft: def _separate(sheet: Sheet, type_hint: DocumentType | None, rules: StatementRules) -> _Draft:
"""Отдельный кандидат из листа-продолжения; число колонок сумм считается, как у блока формы: следующий лист без
маркера сравнивается с ним, а не с нулём."""
formats: set[str] = set() formats: set[str] = set()
col = sheet_code_column(sheet, rules, 1, sheet.n_rows)
if col is None and type_hint is not None:
col = sheet_code_column(sheet, rules, 1, sheet.n_rows, relaxed=type_hint)
amounts = 0 if col is None else sheet_amount_columns(sheet, rules, col, 1, sheet.n_rows)
return _Draft( return _Draft(
type_hint=type_hint, type_hint=type_hint,
sheet_names=[sheet.name], sheet_names=[sheet.name],
evidence=Evidence(), evidence=Evidence(),
header=HeaderCells(), header=HeaderCells(),
rows=grid_rows(sheet, 1, sheet.n_rows, sheet.n_cols, formats), rows=grid_rows(sheet, 1, sheet.n_rows, sheet.n_cols, formats),
form_amount_columns=amounts,
formats=formats, formats=formats,
) )
@ -160,11 +167,11 @@ def _continuation(sheet: Sheet, drafts: list[_Draft], rules: StatementRules) ->
marker = continuation_marker(sheet, rules) marker = continuation_marker(sheet, rules)
marker_type = None if marker is None else continuation_type(marker.text, rules) marker_type = None if marker is None else continuation_type(marker.text, rules)
if open_form is None: if open_form is None:
drafts.append(_separate(sheet, marker_type)) drafts.append(_separate(sheet, marker_type, rules))
return return
locator = f"sheet:{sheet.name}" locator = f"sheet:{sheet.name}"
if marker_type is not None and marker_type != open_form.type_hint: if marker_type is not None and marker_type != open_form.type_hint:
separate = _separate(sheet, marker_type) separate = _separate(sheet, marker_type, rules)
message = ( message = (
f"лист «{sheet.name}»: тип формы в маркере продолжения ({marker_type}) не совпадает с типом " f"лист «{sheet.name}»: тип формы в маркере продолжения ({marker_type}) не совпадает с типом "
f"открытой формы ({open_form.type_hint})" f"открытой формы ({open_form.type_hint})"
@ -173,7 +180,7 @@ def _continuation(sheet: Sheet, drafts: list[_Draft], rules: StatementRules) ->
drafts.append(separate) drafts.append(separate)
return return
if marker is None and not _sheet_joins(sheet, open_form, rules): if marker is None and not _sheet_joins(sheet, open_form, rules):
separate = _separate(sheet, None) separate = _separate(sheet, None, rules)
message = ( message = (
f"лист «{sheet.name}» не присоединён к форме «{open_form.sheet_names[0]}»: коды или число колонок " f"лист «{sheet.name}» не присоединён к форме «{open_form.sheet_names[0]}»: коды или число колонок "
"сумм не подходят" "сумм не подходят"

View File

@ -151,3 +151,27 @@ def test_is_osv_sheet_by_marker() -> None:
osv = sheet_from_rows([["Оборотно-сальдовая ведомость по счету 60"]]) osv = sheet_from_rows([["Оборотно-сальдовая ведомость по счету 60"]])
assert is_osv_sheet(osv, rules) assert is_osv_sheet(osv, rules)
assert not is_osv_sheet(sheet_from_rows([["Бухгалтерский баланс"]]), rules) assert not is_osv_sheet(sheet_from_rows([["Бухгалтерский баланс"]]), rules)
def test_unmarked_page_joins_separate_draft_without_open_form(rules: StatementRules) -> None:
"""M-1: черновик продолжения без открытой формы несёт число колонок сумм — стр. 3 без маркера присоединяется."""
page2 = _form("", (1210, 1230, 1600), "Баланс (2)", marker="Форма 0710001 с.2")
page3 = _form("", (1250, 1260, 1700), "Баланс (3)")
candidates = build_candidates([(page2, CONTINUATION), (page3, CONTINUATION)], rules, NO_DEADLINE, xlsb=False)
[candidate] = candidates
assert candidate.type_hint is DocumentType.BALANCE
assert candidate.segment_breaks == (page2.n_rows,)
assert candidate.warnings == ()
def test_unmarked_page_joins_draft_after_type_conflict(rules: StatementRules) -> None:
"""M-1: то же после CONTINUATION_TYPE_CONFLICT — следующий лист присоединяется к конфликтному черновику."""
balance = _form("Бухгалтерский баланс", BALANCE_CODES, "Баланс")
conflict = _form("", INCOME_CODES, "Лист 2", marker="Форма 0710002 с.2")
page3 = _form("", (2200, 2300, 2410), "Лист 3")
first, second = build_candidates(
[(balance, STATEMENT), (conflict, CONTINUATION), (page3, CONTINUATION)], rules, NO_DEADLINE, xlsb=False
)
assert first.warnings == ()
assert [w.code for w in second.warnings] == ["CONTINUATION_TYPE_CONFLICT"]
assert second.segment_breaks == (conflict.n_rows,)