Ревью #208 (I-7): осиротевшая APPLIED-корректировка требует проверки

attach_corrections молча пропускала (continue) корректировку, чей
агрегат (rule_id, пара ЮЛ) больше не существует после пересчёта
разнесения ВГО — вместо этого, как и в остальных ветках функции,
поднимаем ConflictError("CORRECTION_REVIEW_REQUIRED").
This commit is contained in:
Andrey Epifancev 2026-11-02 20:17:48 +04:00
parent 948724cf1e
commit d542a228e0
2 changed files with 57 additions and 1 deletions

View File

@ -31,7 +31,7 @@ def attach_corrections(
for key, corrections in grouped.items():
aggregate = by_key.get(key)
if aggregate is None:
continue
raise ConflictError("CORRECTION_REVIEW_REQUIRED", "Корректировка ссылается на агрегат, которого больше нет")
ordered = sorted(corrections, key=lambda c: (c.parent_correction_id is not None, c.id))
roots = [c for c in ordered if c.parent_correction_id is None]
root_ids = {c.id for c in roots}

View File

@ -0,0 +1,56 @@
import uuid
from decimal import Decimal
import pytest
from src.common.exceptions import ConflictError
from src.models.kfo import Correction
from src.schemas.consolidations import RefOut
from src.schemas.corrections import AggregateSideOut, CorrectionAggregateOut
from src.services.corrections_view import attach_corrections
ZERO = Decimal("0")
def _side() -> AggregateSideOut:
return AggregateSideOut(article_line="1230", accounts=[], amount=ZERO, entries=[])
def _aggregate(rule_id: uuid.UUID, company_1: uuid.UUID, company_2: uuid.UUID) -> CorrectionAggregateOut:
return CorrectionAggregateOut(
rule_id=rule_id,
rule_no=1,
company_1=RefOut(id=company_1, name="А"),
company_2=RefOut(id=company_2, name="Б"),
side_1=_side(),
side_2=_side(),
deviation_amount=ZERO,
deviation_percent=None,
exceeds_threshold=False,
status="AUTO",
eliminated_amount=ZERO,
correction=None,
)
def _correction(rule_id: uuid.UUID, legal_entity_id: uuid.UUID, counterparty_id: uuid.UUID) -> Correction:
return Correction(
id=uuid.uuid4(),
rule_id=rule_id,
legal_entity_id=legal_entity_id,
counterparty_id=counterparty_id,
parent_correction_id=None,
comment="комментарий",
version_no=1,
)
async def test_attach_corrections_rejects_correction_for_aggregate_that_no_longer_exists() -> None:
rule_id, company_1, company_2 = uuid.uuid4(), uuid.uuid4(), uuid.uuid4()
aggregates = [_aggregate(uuid.uuid4(), company_1, company_2)]
corrections = [_correction(rule_id, company_1, company_2)]
with pytest.raises(ConflictError) as excinfo:
attach_corrections(aggregates, corrections, {})
assert excinfo.value.code == "CORRECTION_REVIEW_REQUIRED"