Supersedes the flat per-module onboarding templates: milestoneTemplate(db, code)
now returns [...front, ...tail]. front is a shared setting
(project.milestone_template.front, FRONT_FALLBACK code default: enquiry ->
visit/meeting -> quotation sent -> quotation approved) prepended to every
module's checklist. tail resolves per-module setting -> global setting ->
TAIL_FALLBACK (the old generic list), unchanged in precedence.
- STEP_STATUS gains quotation_approved -> ordered (never-downgrade guard kept).
- seed.ts seeds the front once plus SMS/RTGS/MOBILEAPP tails (advance/balance
payment steps collapsed into a single payment_received tail step); no longer
seeds a bare project.milestone_template default.
- migrate-onboarding-templates.ts KEY_MAP updated so advance_paid, balance_paid,
advance_payment and balance_payment all carry forward to payment_received;
its idempotency check holds against the longer composed list.
- Updated seed-templates, milestones-templates, milestone-status,
migrate-onboarding-templates, milestones and milestone-payment tests to the
composed content/mappings (TDD: reverted the implementation, confirmed the
updated tests red, restored the implementation, confirmed green).
Backend + tests only; the live-DB migration run is a separate step.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
project_milestone: each client_module (a project) carries a checklist
seeded from the dated project.milestone_template setting (advance paid /
setup / installed / go-live / balance / AMC — owner-editable). Ticking
stamps the date; audited. ensureProjectMilestones is idempotent and
back-fills imported projects. Cross-project board (per-milestone pending
counts) + drill-down (who's pending go-live). Routes: GET/POST
/client-modules/:id/milestones, GET /projects/board, /projects/pending/:key.
assignModule seeds the checklist for new projects.
Also fixes a latent flaky-ordering bug: uuidv7() now bumps monotonically
within a process, so ORDER BY id is genuine creation order (the guarantee
pagination + the sync cursor already assume) — sub-millisecond ties no
longer fall back to the random tail. Suite 377 green, stable across runs.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>