Skip to content

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 ​

FromAllowed To
activesuspended, expired, cancelled
suspendedactive, cancelled
expiredactive, cancelled
cancelled(terminal)

Quote ​

FromAllowed To
draftsent, cancelled
sentviewed, accepted, rejected, expired
viewedaccepted, rejected, expired
acceptedpaid, cancelled
paidfulfilled
fulfilled(terminal)
rejected(terminal)
expired(terminal)
cancelled(terminal)

Environment ​

FromAllowed To
provisioningactive, cancelled
activemaintenance, suspended, decommissioned
maintenanceactive
suspendedactive, decommissioned
decommissioned(terminal)

Service ​

Defined in ServiceStatus enum with allowedTransitions():

FromAllowed To
proposalapproved, cancelled
approvedin_progress, cancelled
in_progresson_hold, delivered, cancelled
on_holdin_progress, cancelled
deliveredclosed, in_progress
closed(terminal)
cancelled(terminal)

Ticket ​

Defined in TicketStatus enum with allowedTransitions():

FromAllowed To
openin_progress, waiting, cancelled
in_progresswaiting, resolved, cancelled
waitingin_progress, cancelled
resolvedclosed, in_progress
closed(terminal)
cancelled(terminal)

Contract ​

FromAllowed To
draftactive, cancelled
activesuspended, expired, renewed, cancelled
suspendedactive, cancelled
expiredrenewed
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.