feat(checks): «родитель = Σ подстрок» не проверяется при пустой детализации (#45, AURORA-1527)
По колонке соотношение считается, только если хотя бы одна подстрока родителя имеет значение (amount не null; ноль — значение). Совпадает с arm-core. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
295b9924af
commit
f017c37c51
@ -6,6 +6,7 @@
|
||||
Правило проверяется, если целевой код в данных (подстроки всегда).
|
||||
OQ-138: жёсткое нарушение не больше `rounding_tolerance_percent` от наибольшего |числа| соотношения — округление,
|
||||
уходит в мягкие.
|
||||
AURORA-1527: «родитель = Σ подстрок» по колонке — только если хотя бы одна подстрока в ней непуста (amount не null).
|
||||
M-9: пятизначная подстрока относится к ближайшей четырёхзначной строке выше с теми же первыми тремя цифрами.
|
||||
"""
|
||||
|
||||
@ -33,6 +34,16 @@ def _amounts(lines: Sequence[StatementLine], column_count: int) -> list[dict[str
|
||||
return columns
|
||||
|
||||
|
||||
def _filled(lines: Sequence[StatementLine], column_count: int) -> list[set[str]]:
|
||||
"""Коды строк, у которых в колонке есть значение (`amount` не null; ноль — значение)."""
|
||||
columns: list[set[str]] = [set() for _ in range(column_count)]
|
||||
for item in lines:
|
||||
for value in item.values:
|
||||
if 0 <= value.column_index < column_count and value.amount is not None:
|
||||
columns[value.column_index].add(item.line_code)
|
||||
return columns
|
||||
|
||||
|
||||
def _rhs(amounts: dict[str, Decimal], rule: RelationRule, *, absolute: bool) -> Decimal:
|
||||
total = _ZERO
|
||||
for sign, code in rule.terms:
|
||||
@ -102,6 +113,7 @@ def run_statement_checks(
|
||||
hard: list[FailedRelation] = []
|
||||
soft: list[FailedRelation] = []
|
||||
warnings: list[str] = []
|
||||
filled = _filled(lines, column_count)
|
||||
for column_index, amounts in enumerate(_amounts(lines, column_count)):
|
||||
for rule in relations:
|
||||
# Явные правила из конфига пропускаются, если цель отсутствует в данных колонки.
|
||||
@ -109,6 +121,9 @@ def run_statement_checks(
|
||||
is_subline = rule in subline_rules
|
||||
if not is_subline and rule.target not in amounts:
|
||||
continue
|
||||
# AURORA-1527: детализации нет (все подстроки родителя в колонке пусты) — соотношение не проверяется
|
||||
if is_subline and not any(code in filled[column_index] for _, code in rule.terms):
|
||||
continue
|
||||
holds, expected, actual = _holds(amounts, rule, config.tolerance)
|
||||
if holds:
|
||||
continue
|
||||
|
||||
@ -300,3 +300,28 @@ def test_rounding_base_is_the_largest_number_of_the_relation(rules: Rules) -> No
|
||||
|
||||
assert checks.relations_failed == []
|
||||
assert "2200 = 2100 - 2210 - 2220" in [item.relation for item in checks.soft_relations_failed]
|
||||
|
||||
|
||||
# --- AURORA-1527: детализации нет — соотношение подстрок не проверяется ---
|
||||
|
||||
|
||||
def test_sublines_all_empty_in_column_are_not_checked(rules: Rules) -> None:
|
||||
lines = [line("1150", "90", "90"), line("11501", None, None), line("11502", None, None)]
|
||||
checks, warnings = run_statement_checks(lines, 2, "BALANCE", rules)
|
||||
assert [f for f in checks.soft_relations_failed if f.relation.startswith("1150 =")] == []
|
||||
assert not any("1150 =" in w for w in warnings)
|
||||
|
||||
|
||||
def test_sublines_check_is_per_column(rules: Rules) -> None:
|
||||
lines = [line("1150", "90", "90"), line("11501", None, "10"), line("11502", None, None)]
|
||||
checks, _ = run_statement_checks(lines, 2, "BALANCE", rules)
|
||||
failed = [f for f in checks.soft_relations_failed if f.relation == "1150 = 11501 + 11502"]
|
||||
assert [(f.column_index, f.expected, f.actual) for f in failed] == [(1, Decimal("90"), Decimal("10"))]
|
||||
|
||||
|
||||
def test_subline_zero_is_a_value(rules: Rules) -> None:
|
||||
lines = [line("1150", "90"), line("11501", "0"), line("11502", None)]
|
||||
checks, _ = run_statement_checks(lines, 1, "BALANCE", rules)
|
||||
assert [f.relation for f in checks.soft_relations_failed if f.relation.startswith("1150 =")] == [
|
||||
"1150 = 11501 + 11502"
|
||||
]
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user