import type { DomainEvent } from "@/lib/events"; import type { ServiceCtx } from "@/server/services/context"; /** * Emit a domain event AFTER the mutation succeeded. Never throws: a failing notification * must not roll back business data — failures are logged and surfaced via sync/notification * monitoring. Lanes call ONLY this function; the notifications lane owns the handler. */ export async function emitEvent(ctx: ServiceCtx, event: DomainEvent): Promise { try { const { handleEvent } = await import("@/server/services/notifications/handle-event"); await handleEvent(ctx, event); } catch (err) { console.error(`[events] ${event.type} for ${event.entityType}:${event.entityId} failed:`, (err as Error).message); } // L14 Abrechnungsübersicht: billing candidates after billing release / daily report approval (idempotent, never throws) if (event.type === "work_order.released_for_billing" || event.type === "report.approved") { try { const { onBillingEvent } = await import("@/server/services/billing/events"); await onBillingEvent(ctx, event); } catch (err) { console.error(`[events] billing hook for ${event.type} ${event.entityId} failed:`, (err as Error).message); } } }