Stand vor Einführung des Nacht-Agenten

This commit is contained in:
Kundencenter 2026-09-27 00:51:32 +02:00
commit 4763548bfb
168 changed files with 12726 additions and 0 deletions

View file

@ -0,0 +1,27 @@
/** 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<S extends string, E extends string> = Partial<Record<S, Partial<Record<E, S>>>>;
export const ORDER_MACHINE: Machine<OrderStatus, OrderEvent> = {
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<ContractStatus, ContractEvent> = {
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<S extends string, E extends string>(m: Machine<S, E>, 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);