feat(workflows): migrate the dunning ladder onto the engine (cutover)
Makes the built-in dunning flow a faithful replacement for the hardcoded reminder ladder instead of a disabled representation: - queue_payment_check action delegates to invoiceService.queuePaymentCheckEmail, so the proven confirm + reminder_level + Mahngebühr state machine (recordPaymentCheckAction) stays the single source of truth — the workflow only decides WHEN the payment-check email (the gate) fires. - runScheduledTasks now SKIPS the hardcoded reminder batches when workflows is on AND the invoice_dunning built-in is enabled, so the two never double-send. - The built-in graph is re-authored to the delegation model (wait→due, grace, loop: check-paid → payment-check → wait-gap), dropping the redundant gate + generic reminder emails. A SEED_VERSION re-seeds the disabled, never-activated built-in on boot but never touches an enabled/edited one. Tests: delegation graph shape, re-seed-when-stale, enabled-protection (9 engine + 8 route = 17 passing).
This commit is contained in:
@@ -66,6 +66,19 @@ registry.registerAction('send_email', async (ctx) => {
|
||||
return { sent_to: to, recipientClass, respectBusinessHours };
|
||||
});
|
||||
|
||||
// Fire the existing admin payment-check email (the dunning gate). Delegates to
|
||||
// invoiceService.queuePaymentCheckEmail so the proven escalation +
|
||||
// Mahngebühr / reminder_level state machine (recordPaymentCheckAction) stays
|
||||
// the single source of truth — the workflow only decides WHEN it fires. This
|
||||
// is what makes the built-in dunning flow a faithful replacement for the
|
||||
// hardcoded ladder (paired with the mutual-exclusion guard in runScheduledTasks).
|
||||
registry.registerAction('queue_payment_check', async (ctx) => {
|
||||
const id = ctx.run.entity_id;
|
||||
if (!id) return { skipped: true, reason: 'no invoice entity' };
|
||||
await require('../invoiceService').queuePaymentCheckEmail(id);
|
||||
return { payment_check_queued: id };
|
||||
});
|
||||
|
||||
// Create/prepare-document actions — registered so flows referencing them are
|
||||
// valid; service wiring is a follow-up. Records a skipped step (observable).
|
||||
for (const key of DOCUMENT_ACTIONS) {
|
||||
|
||||
Reference in New Issue
Block a user