/** Statusautomaten für Bestellung und Vertrag. Zustandsänderungen laufen ausschließlich über `transition`. */ export type OrderStatus = 'pending_approval' | 'approved' | 'provisioning' | 'completed' | 'failed' | 'rejected' | 'cancelled'; export type OrderEvent = 'approve' | 'reject' | 'cancel' | 'start_provisioning' | 'complete' | 'fail' | 'retry'; export type ContractStatus = 'pending' | 'active' | 'suspended' | 'cancelled' | 'expired' | 'failed'; export type ContractEvent = 'activate' | 'suspend' | 'unsuspend' | 'cancel' | 'expire' | 'fail'; type Machine = Partial>>>; export const ORDER_MACHINE: Machine = { pending_approval: { approve: 'approved', reject: 'rejected', cancel: 'cancelled' }, approved: { start_provisioning: 'provisioning', cancel: 'cancelled' }, provisioning: { complete: 'completed', fail: 'failed' }, failed: { retry: 'provisioning', cancel: 'cancelled' }, }; export const CONTRACT_MACHINE: Machine = { pending: { activate: 'active', fail: 'failed', cancel: 'cancelled' }, active: { suspend: 'suspended', cancel: 'cancelled', expire: 'expired' }, suspended: { unsuspend: 'active', cancel: 'cancelled', expire: 'expired' }, }; export class InvalidTransition extends Error { constructor(public from: string, public event: string) { super(`Ungültiger Statuswechsel: ${event} ist im Zustand ${from} nicht erlaubt`); } } export function transition(m: Machine, from: S, event: E): S { const to = m[from]?.[event]; if (!to) throw new InvalidTransition(from, event); return to; } export const terminalOrder = (s: OrderStatus) => ['completed', 'rejected', 'cancelled'].includes(s);