refactor(workflow): delegate transition_state to TestEntity
Some checks failed
Aegis CI / lint-and-test (push) Has been cancelled

transition_state() now hydrates a TestEntity from the ORM model and delegates state validation to entity.transition_to(). The entity is authoritative for which transitions are valid; VALID_TRANSITIONS and can_transition() are kept for backward compatibility.

Also adds public transition_to() method to TestEntity as the stable API surface for callers that need a single validated transition without lifecycle side-effects.
This commit is contained in:
2026-02-18 13:54:01 +01:00
parent 611e10620e
commit 633c8e46ad
2 changed files with 341 additions and 13 deletions

View File

@@ -19,6 +19,7 @@ from sqlalchemy.orm import Session
from app.config import settings
from app.domain.exceptions import InvalidOperationError, InvalidTransitionError
from app.domain.test_entity import TestEntity
from app.models.enums import TestState
from app.models.test import Test
from app.models.user import User
@@ -61,21 +62,18 @@ def transition_state(
action_name: str = "transition_state",
extra_details: dict | None = None,
) -> Test:
"""Validate and perform a state transition, log it, and commit.
"""Validate and perform a state transition, log it, and flush.
Raises :class:`InvalidTransitionError` when the transition is invalid.
Delegates validation to :class:`TestEntity` which raises
:class:`InvalidStateTransition` (aliased as ``InvalidTransitionError``)
when the transition is illegal. The entity is authoritative for which
transitions are valid; the module-level ``VALID_TRANSITIONS`` dict is
kept temporarily for backward compatibility of ``can_transition()``.
"""
if not can_transition(test, target_state):
current = test.state if isinstance(test.state, TestState) else TestState(test.state)
valid = [s.value for s in VALID_TRANSITIONS.get(current, [])]
raise InvalidTransitionError(
current_state=current.value,
target_state=target_state.value,
valid_transitions=valid,
)
entity = TestEntity.from_orm(test)
previous_state = entity.transition_to(target_state)
previous_state = test.state.value if isinstance(test.state, TestState) else test.state
test.state = target_state
test.state = entity.state
db.flush()
details: dict = {
@@ -96,7 +94,6 @@ def transition_state(
details=details,
)
# Dispatch in-app notifications for the new state
try:
notify_test_state_change(db, test, target_state.value)
except Exception as e: