Three bugs combined to make CTR-00008 (and likely others) land silently:
1. Fallback was count-based, not outcome-based.
_fireFlowTrigger returned >0 when a broken Flow Template (FT-00005)
"matched" on_contract_signed but did nothing. We took that as success
and skipped the built-in install chain. Now we ALWAYS run the built-in
chain; the idempotency check inside (look up existing Issue linked to
contract) lets a healthy Flow Template short-circuit us naturally.
2. scheduled_date was null on all chained jobs.
createDeferredJobs passed '' when no step.scheduled_date was set, and
the fiber_install template doesn't set one. Jobs with null dates are
filtered out of most dispatch board views, giving the user-visible
"Aucune job disponible pour dispatch" symptom even after the chain was
built. Default to today (via ctx.scheduled_date) so jobs appear on the
board; dispatcher reschedules per capacity.
3. No post-sign acknowledgment to the customer.
Previously the Flow Template was expected to send the confirmation SMS;
since the template was broken, the customer got nothing after signing.
Add _sendPostSignAcknowledgment that sends a "Bon de commande reçu"
SMS with contract ref + service details + next steps. Fires only when
the chain is actually created (not on idempotent skip) so we never
double-notify.
Also:
- Resolve phone/email from cell_phone + email_billing (legacy-migrated
Customer records use those fields, not Frappe defaults mobile_no /
email_id) — otherwise we'd keep skipping SMS with "no phone on file".
- _createBuiltInInstallChain now returns { created, issue, jobs,
scheduled_date, reason } so callers can branch on outcome.
- Export sendPostSignAcknowledgment so one-shot backfill scripts can
re-notify customers whose contracts were signed during the broken
window.
- Set order_source='Contract' (existing Select options patched separately
to include 'Contract' alongside Manual/Online/Quotation).
Backfilled CTR-00008: ISS-0000250003 + 4 chained Dispatch Jobs all with
scheduled_date=2026-04-23, ack SMS delivered to Louis-Paul's cell.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- contracts.js: built-in install chain fallback when no Flow Template matches
on_contract_signed — every accepted contract now creates a master Issue +
chained Dispatch Jobs (fiber_install template) so we never lose a signed
contract to a missing flow config.
- acceptance.js: export createDeferredJobs + propagate assigned_group into
Dispatch Job payload (was only in notes, not queryable).
- dispatch.js: chain-walk helpers (unblockDependents, _isChainTerminal,
setJobStatusWithChain) + terminal-node detection that activates pending
Service Subscriptions (En attente → Actif, start_date=tomorrow) and emits
a prorated Sales Invoice covering tomorrow → EOM. Courtesy-day billing
convention: activation day is free, first period starts next day.
- dispatch.js: fix Sales Invoice 417 by resolving company default income
account (Ventes - T) and passing company + income_account on each item.
- dispatch.js: GET /dispatch/group-jobs + POST /dispatch/claim-job for tech
self-assignment from the group queue; enriches with customer_name /
service_location via per-job fetches since those fetch_from fields aren't
queryable in list API.
- TechTasksPage.vue: redesigned mobile-first UI with progress arc, status
chips, and new "Tâches du groupe" section showing claimable unassigned
jobs with a "Prendre" CTA. Live updates via SSE job-claimed / job-unblocked.
- NetworkPage.vue + poller-control.js: poller toggle semantics flipped —
green when enabled, red/gray when paused; explicit status chips for clarity.
E2E verified end-to-end: CTR-00007 → 4 chained jobs → claim → In Progress →
Completed walks chain → SUB-0000100002 activated (start=2026-04-24) →
SINV-2026-700012 prorata $9.32 (= 39.95 × 7/30).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Dispatch performance:
- Replace sequential batch fetches (batches of 15, one after another)
with full parallel Promise.all — all doc fetches fire simultaneously
- With 20 jobs: was ~3 sequential round-trips, now ~2 (1 list + 1 parallel)
Order traceability:
- Add sales_order (Link) and order_source (Select) fields to Dispatch Job
- checkout.js sets order_source='Online' + sales_order link on job creation
- acceptance.js sets order_source='Quotation' on quotation-sourced jobs
- Store maps new fields: salesOrder, orderSource
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>