feat(workflows): admin review gates before sends + migrate lifecycle/time triggers
Booking built-ins now gate every outbound document on an explicit admin OK: prepare_* drafts the doc, the admin adjusts line items/terms, confirms the "Review … before sending" gate, and only then does send_document fire. Added to booking_full (contract + invoice) and booking_simple (invoice); seed versions bumped so the disabled built-ins self-heal. Migrated the remaining time- and event-driven triggers into the engine, all additive / best-effort / fail-closed (no behaviour change when the flag is off): - gallery.published (event creation) - gallery.expiring + gallery.expired (expiration checker, alongside the email) - quote.sent (was queued but never emitted — gap closed) - contract.sent + contract.signed (sent, fully-signed via counter-sign or wet upload) - customer.created (direct add + invitation accept) - invoice.overdue (status→overdue flip, deduped per invoice) Editor trigger list extended to match. Tests assert the review gates wire confirm→send on both booking flows.
This commit is contained in:
@@ -2710,6 +2710,27 @@ async function applyReminder(invoice, lineItems, level, adminId) {
|
||||
if (await hasColumnCached('invoices', 'late_fee_vat_minor')) update.late_fee_vat_minor = lateFeeVat;
|
||||
await db('invoices').where({ id: invoice.id }).update(update);
|
||||
|
||||
// Fire invoice.overdue at the status→overdue flip. Deduped per (workflow,
|
||||
// invoice), so across the reminder ladder it triggers a flow at most once.
|
||||
// Best-effort / fail-closed.
|
||||
try {
|
||||
await require('./workflows').emitWorkflowEvent('invoice.overdue', {
|
||||
entityType: 'invoice',
|
||||
entityId: invoice.id,
|
||||
payload: {
|
||||
invoiceId: invoice.id,
|
||||
invoiceNumber: invoice.invoice_number,
|
||||
eventId: invoice.event_id || null,
|
||||
customerAccountId: invoice.customer_account_id,
|
||||
customerEmail: customer?.email || null,
|
||||
dueDate: invoice.due_date,
|
||||
reminderLevel: level,
|
||||
totalMinor: invoice.total_amount_minor,
|
||||
currency: invoice.currency,
|
||||
},
|
||||
});
|
||||
} catch (_) {}
|
||||
|
||||
// Render the MAHNUNG (reminder letter). The original invoice PDF is left
|
||||
// UNTOUCHED (immutable). The Mahnung reuses the invoice layout via a
|
||||
// 'mahnung' kind: same line items + the Mahngebühr row + the new total, with
|
||||
|
||||
Reference in New Issue
Block a user