Удалены api/rules/statement_checks.yaml, load_check_rules, run_checks и правила соотношений; в domain/statement_checks.py остались межформенная проверка 1370/2400 и subline_parents. Тест test_name_dictionary_codes_in_code_orders сверяет справочник имён с перечнями редакций пакета. CLAUDE.md и README.md: §7 — копия arm_statements, нарушения хранятся в document_issue. Решения P3-50…P3-52. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
67 lines
2.9 KiB
Python
67 lines
2.9 KiB
Python
"""Остатки проверок §7 в ядре: межформенная проверка и родители подстрок.
|
||
|
||
Остальные проверки §7 считает пакет `arm_statements` (тесты пакета и `test_statements_recompute*`); копии словаря
|
||
в ядре нет (часть Б, B6)."""
|
||
|
||
from decimal import Decimal
|
||
from pathlib import Path
|
||
|
||
import pytest
|
||
|
||
from src.domain.statement_checks import FailedCheck, cross_form_check, subline_parents
|
||
|
||
D = Decimal
|
||
API_DIR = Path(__file__).resolve().parents[1]
|
||
|
||
|
||
def test_no_core_check_rules() -> None:
|
||
"""Копии словаря §7 и загрузчика/исполнителя правил в ядре нет (B6)."""
|
||
assert not (API_DIR / "rules" / "statement_checks.yaml").exists()
|
||
forbidden = ("load_check_rules", "run_checks", "statement_checks.yaml")
|
||
for source in (API_DIR / "src").rglob("*.py"):
|
||
text = source.read_text(encoding="utf-8")
|
||
for name in forbidden:
|
||
assert name not in text, f"{source.relative_to(API_DIR)}: {name}"
|
||
|
||
|
||
@pytest.mark.parametrize(
|
||
("b1370", "i2400", "expected"),
|
||
[
|
||
((D("500"), D("300")), D("200"), None),
|
||
(
|
||
(D("500"), D("300")),
|
||
D("150"),
|
||
FailedCheck(-1, "1370 − 1370(начало года) = 2400", D("200"), D("150"), ("1370", "2400")),
|
||
),
|
||
((None, D("300")), D("200"), None),
|
||
((D("500"), D("300")), None, None),
|
||
],
|
||
)
|
||
def test_cross_form(
|
||
b1370: tuple[Decimal | None, Decimal | None], i2400: Decimal | None, expected: FailedCheck | None
|
||
) -> None:
|
||
assert cross_form_check(b1370, i2400, D("1")) == expected
|
||
|
||
|
||
def test_subline_parents_nearest_parent_above_with_same_group() -> None:
|
||
# 12310 и 12320 относятся к 1230 (ближайшая выше с теми же тремя цифрами), а не к 1231
|
||
codes = ["1231", "1230", "12310", "12320"]
|
||
assert subline_parents(codes) == {"12310": "1230", "12320": "1230"}
|
||
|
||
|
||
def test_subline_parents_fallback_to_four_digit_prefix() -> None:
|
||
# выше подстроки нет родителя той же группы — родитель по первым четырём цифрам, если такая строка есть
|
||
assert subline_parents(["11101", "1110"]) == {"11101": "1110"}
|
||
assert subline_parents(["1100", "1110", "1120", "11101"]) == {"11101": "1110"}
|
||
|
||
|
||
def test_subline_parents_orphans_and_non_sublines_are_absent() -> None:
|
||
assert subline_parents(["1100", "11101", "1700", "123"]) == {}
|
||
assert subline_parents([]) == {}
|
||
|
||
|
||
def test_subline_parents_follow_given_order() -> None:
|
||
# порядок задаёт вызывающий (порядок кодов `statement_amounts`): «ближайшая выше» считается по нему
|
||
assert subline_parents(["1230", "1231", "12310"]) == {"12310": "1231"}
|
||
assert subline_parents(["1231", "1230", "12310"]) == {"12310": "1230"}
|