- Couleurs liées aux skills (éditable/cohérent) : hub deptToSkill() déduit une compétence du type legacy
→ /roster/unassigned-jobs renvoie required_skill ; PlanificationPage colore la carte par getTagColor(required_skill)
(même couleur que le chip skill) ; bordure 5px
- Fil complet du ticket : hub /dispatch/legacy-sync/ticket-thread (ticket_msg + auteur staff, HTML nettoyé) ;
api legacyTicketThread ; RightPanel bouton « 💬 Voir le fil / commentaires » (chargé au clic, messages+auteurs+dates)
- Order-by du pool dispatch : useBottomPanel.bottomSort (date|city|priority) + dropdown ⇅ dans BottomPanel
(ville = 2e segment adresse / token sujet avant |)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- pont : extrait le lien connect_ministra.php du ticket_msg (déjà posté par le wizard legacy à la vente)
→ champ legacy_activation_url sur le Dispatch Job (backfill des 10 tickets TV). Read-only legacy, aucun 2e
chemin d'écriture → zéro risque de double-facturation (cf. analyse processus).
- store _mapJob : expose legacyActivationUrl ; RightPanel : bouton violet « 📺 Activer STB (Ministra) »
(MÊME lien que le tech reçoit, ouvre connect_ministra.php avec tid/did/sid/cr/m intacts).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- useHelpers.legacyReplyUrl(job, staffId?) → https://store.targo.ca/targo/reply_ticket.php?ticket=<legacy_ticket_id>&staff=<3301 par défaut = Tech Targo>
- RightPanel : n° ticket legacy cliquable + bouton d'action « 📝 Répondre dans legacy »
- permet au tech d'écrire dans le ticket legacy depuis ERPNext (lecture seule de notre côté)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- BottomPanel : pastille couleur (jobColor → type legacy) par ligne + badge ⏰ EN RETARD
sur les groupes de date passée (le pool est déjà groupé/trié par date)
- RightPanel : badge « en retard » près de la date planifiée (hors Completed)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- pont : stocke legacy_dept (dept osTicket) sur le Dispatch Job + backfill des 70 existants
- useHelpers.jobColor/legacyDeptColor : palette comme legacy (Installation vert, Réparation or,
Télé rose, Téléphonie vert pâle, Désinstallation rouge foncé) ; tech en pause = rouge vif prioritaire
- store _mapJob : expose legacyDept + legacyTicketId
- RightPanel : champ « Ticket legacy » (#id · dept) — le client est déjà un lien cliquable vers la fiche
- doc mise à jour
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Three connected dispatcher-facing issues from C-LPB4 audit:
1. **Monthly total was wrong on customer cards.** Section subtotal and
`locSubsMonthlyTotal` summed `actual_price` for ALL subscriptions
regardless of status, so cancelled rows (rendered with strikethrough)
still pumped up the displayed billing figure. C-LPB4 showed
"Total mensuel: 86,10$" computed as `196.05 - 109.95 = 86.10`,
where 196.05 included 3 cancelled internet plans (Megafibre 80,
TEST-E2E-FTTH, FTTH100 — all struck through in the UI). Real
active monthly is 5.00$ (109.95 active + 5 frais réseau − 109.95
loyalty rebate). Fixed both `sectionTotal` and `locSubsMonthlyTotal`
/`locSubsAnnualTotal` to filter on `status === 'Active'`.
2. **"Lieu" link from a dispatch task pointed to ERPNext desk** which
shows a raw doctype form (no abonnements, no totals, no contacts —
just the bare fields). Now points in-app to
`#/clients/<customer>?location=<SL>`. ClientDetailPage reads the
query string on mount and:
• scrolls the matching `loc-card` into view
• pulses an indigo halo around it for ~2s so the rep finds it
immediately even when the customer has many service locations.
3. **The shipping/billing distinction was invisible** on the customer
page. Added an "Adresses de livraison" badge next to the "Lieux de
service" section title — clarifies that this section IS the
shipping address, distinct from the (future) billing address that
will live on the Customer record. Cosmetic for now; the data
migration to formalize that distinction is the next step.
These three round out the C-LPB4 audit triggered by the wrong
mapbox-pin location: now the customer card on the dispatcher's
screen shows correct totals, the dispatch link drops them right at
the spot they're trying to reach, and the role of each address-bearing
record is named explicitly.
Two things ride together because the user noticed the URL bug while
testing the work-in-progress address validation:
1. **Broken Frappe URL pattern.** Three places in the dispatch UI
were generating `/desk/Service Location/<id>` and
`/desk/Dispatch Technician/<id>` links — both return "Page not
found" on Frappe v14+ (= our v16) because the modern desk URL
format is `/app/<slug>/<id>` where slug is lowercase + hyphens.
Fixed in:
• RightPanel.vue (Lieu link in the job details panel)
• DispatchPage.vue (Lieu in the job ctx menu)
• DispatchPage.vue (Ouvrir dans ERPNext in the tech ctx menu)
2. **`POST /address/validate` endpoint** on the hub. Wraps the
existing RQA Supabase search (`address-search.js`) with a
confidence-scored output:
• exact_match (boolean) — score >= 0.7
• best (the top RQA candidate with aq_address_id, lat, lng)
• candidates[] (top 5 ranked)
• confidence (0..1)
• recommendation: validated | review | unmatched
Score combines civic-number exact match, road-name fuzzy overlap,
FSA+full postal-code bonuses, and city-name bonus. The endpoint
is called from ops UI when adding/editing a Service Location to
auto-populate aq_address_id + canonical lat/lng instead of
trusting human typing or Mapbox geocode.
(Custom Fields aq_address_id, address_validation_status,
address_validated_at, linked_address have been added on Service
Location via the Frappe REST API in a separate operation — not in
this commit since they're DB-only.)
Two related issues, one PR:
1. **Bad coords** on customer C-LPB4's "Wifi buggy" job (DJ-MNP8WIKT).
Address on file is `691 rue des Hirondelles, Saint-Michel J0L2J0`,
but the saved lat/lng (-73.677086, 45.159206) reverse-geocodes to
`2336 rue René-Vinet, Sainte-Clotilde J0L1W0` — ~9 km away. The
delta matches the Gigafibre HQ default fallback (-73.6756, 45.1599)
pretty closely, suggesting the geocoder either failed silently at
Service Location creation time or got pinned to the HQ centroid.
Fixed live in DB (UPDATE on tabService Location LOC-0000000004 +
tabDispatch Job DJ-MNP8WIKT to lng=-73.5792377, lat=45.2408452,
verified via Nominatim against the typed address). The job pin
should now show on the correct house.
2. **No way to jump from a job to the client** — the dispatcher had
to memorize/type the customer ID. Now both the RightPanel and the
job context-menu surface clickable shortcuts:
• Client → `#/clients/<id>` (opens ClientDetailPage in-app)
• Lieu → `/desk/Service Location/<id>` (opens ERPNext in a new
tab; the ops SPA doesn't have a dedicated SL detail page)
Required wiring `customer` + `serviceLocation` into the job map in
`stores/dispatch.js` — the API (`fetchJobsFast` uses `["*"]`) was
already returning the fields, the store just wasn't surfacing them.
Note on the deeper bug: the SL lat/lng is the source of truth and the
job currently *copies* it at creation time (rather than reading from
the SL link dynamically). If a Service Location's coords are corrected
after a job exists, the job retains stale coords. A follow-up could
either (a) re-read on render, or (b) trigger a backfill when SL coords
change. Out of scope for this fix — for now, the dispatcher who fixes
an SL must also update any open jobs at that location.
Ops app (Vue/Quasar PWA) with dispatch V2 integration, tag system,
customer 360, tickets, and dashboard. Served via standalone nginx
container at erp.gigafibre.ca/ops/ with Traefik StripPrefix + Authentik SSO.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>