diff --git a/api/tests/unit/parser/statements/test_checks.py b/api/tests/unit/parser/statements/test_checks.py index f1f9559..8083ba0 100644 --- a/api/tests/unit/parser/statements/test_checks.py +++ b/api/tests/unit/parser/statements/test_checks.py @@ -94,16 +94,24 @@ def test_relation_holds_with_abs_terms(rules: Rules) -> None: one_c = [ line("2110", "1000"), line("2120", "-600"), - line("2100", "400"), # 2100 = 2110 - 2120 = 1000 - (-600) = 1600 (plain) | 1000 - abs(-600) = 400 (abs) - line("2200", "400"), # 2200 = 2100 - 2210 - 2220 = 400 - 0 - 0 = 400 (plain) | abs - line("2300", "400"), # 2300 = 2200 + 2310 + … = 400 + 0 + … = 400 + line("2100", "400"), # 1000 - (-600) = 1600 plain | 1000 - abs(-600) = 400 (abs) ✓ + line("2210", "-50"), + line("2220", "-30"), + line("2200", "320"), # 400 - (-50) - (-30) = 480 plain | 400 - 50 - 30 = 320 (abs) ✓ + line("2330", "-20"), + line("2350", "-10"), + line("2300", "290"), # 320 - (-20) - (-10) = 350 plain | 320 - 20 - 10 = 290 (abs) ✓ ] brackets = [ line("2110", "1000"), line("2120", "600"), - line("2100", "400"), # 2100 = 2110 - 2120 = 1000 - 600 = 400 - line("2200", "400"), # 2200 = 2100 - 2210 - 2220 = 400 - 0 - 0 = 400 - line("2300", "400"), # 2300 = 2200 + … = 400 + line("2100", "400"), # 1000 - 600 = 400 ✓ + line("2210", "50"), + line("2220", "30"), + line("2200", "320"), # 400 - 50 - 30 = 320 ✓ + line("2330", "20"), + line("2350", "10"), + line("2300", "290"), # 320 - 20 - 10 = 290 ✓ ] assert run_statement_checks(one_c, 1, "INCOME", rules)[0].relations_failed == [] @@ -153,3 +161,29 @@ def test_null_values_count_as_zero_and_empty_form_passes(rules: Rules) -> None: checks, _ = run_statement_checks(lines, 1, "BALANCE", rules) assert checks.relations_failed == [] + + +def test_target_absent_no_violations(rules: Rules) -> None: + """R-6: Если цели правила нет в данных, проверка пропускается → нарушений нет.""" + # INCOME: 2100, 2110, 2120 есть; 2200 НЕТУ → правило 2200 не проверяется + lines_income = [line("2110", "1000"), line("2120", "-600"), line("2100", "400")] + checks_income, _ = run_statement_checks(lines_income, 1, "INCOME", rules) + assert checks_income.relations_failed == [] + assert checks_income.soft_relations_failed == [] + + # BALANCE: только 1150 БЕЗ 1100 → правило 1100 не проверяется (1100 это цель правила) + lines_balance = [line("1150", "100")] + checks_balance, _ = run_statement_checks(lines_balance, 1, "BALANCE", rules) + assert checks_balance.relations_failed == [] + + +def test_target_present_members_absent_as_zero(rules: Rules) -> None: + """R-6: Цель есть, члены отсутствуют (= 0) → соотношение с нарушением.""" + # BALANCE: 1100 = 100 БЕЗ подстатей → 1100 = 0 + 0 + … = 0 (не совпадает с 100) + lines = [line("1100", "100")] + + checks, _ = run_statement_checks(lines, 1, "BALANCE", rules) + + # Правило 1100 = 1105 + … (strict: true) должно нарушиться + failed_relations = [item.relation for item in checks.relations_failed] + assert any("1100 =" in rel for rel in failed_relations)