Lifecycle States
State machines for each domain with allowed transitions. Terminal states have no outbound transitions. Transition methods validate allowed moves and fire middag/{domain}/status_changed events.
Entitlement
| From | Allowed To |
|---|---|
active | suspended, expired, cancelled |
suspended | active, cancelled |
expired | active, cancelled |
cancelled | (terminal) |
Quote
| From | Allowed To |
|---|---|
draft | sent, cancelled |
sent | viewed, accepted, rejected, expired |
viewed | accepted, rejected, expired |
accepted | paid, cancelled |
paid | fulfilled |
fulfilled | (terminal) |
rejected | (terminal) |
expired | (terminal) |
cancelled | (terminal) |
Environment
| From | Allowed To |
|---|---|
provisioning | active, cancelled |
active | maintenance, suspended, decommissioned |
maintenance | active |
suspended | active, decommissioned |
decommissioned | (terminal) |
Service
Defined in ServiceStatus enum with allowedTransitions():
| From | Allowed To |
|---|---|
proposal | approved, cancelled |
approved | in_progress, cancelled |
in_progress | on_hold, delivered, cancelled |
on_hold | in_progress, cancelled |
delivered | closed, in_progress |
closed | (terminal) |
cancelled | (terminal) |
Ticket
Defined in TicketStatus enum with allowedTransitions():
| From | Allowed To |
|---|---|
open | in_progress, waiting, cancelled |
in_progress | waiting, resolved, cancelled |
waiting | in_progress, cancelled |
resolved | closed, in_progress |
closed | (terminal) |
cancelled | (terminal) |
Contract
| From | Allowed To |
|---|---|
draft | active, cancelled |
active | suspended, expired, renewed, cancelled |
suspended | active, cancelled |
expired | renewed |
renewed | (terminal) |
cancelled | (terminal) |
Transition Enforcement
Status transitions are validated in domain services before persistence:
php
// ServiceStatus enum
public function allowedTransitions(): array
{
return match ($this) {
self::Proposal => ['approved', 'cancelled'],
self::Approved => ['in_progress', 'cancelled'],
// ...
self::Closed => [],
self::Cancelled => [],
};
}Invalid transitions throw InvalidArgumentException. The status_changed event fires only after a successful transition.
Related
- Status Labels -- All status values
- Extension Points --
status_changedevents