- shared priorityMeta/PRIORITY_LEVELS → 3 levels: Haute (RED) · Moyenne
(neutral grey) · Basse. Default/medium = grey outlined_flag. Aliases
urgent→high, normal→medium for old conversation data.
- conversations: priority endpoint accepts 'medium' (keeps old values for
back-compat); the flag menu now shows the 3 levels.
- jobs: dropped the parallel job-flags override store — the job flag now
writes the REAL ERPNext priority (low/medium/high) via patchJob/
updateJob, same source as the pool sheet (no more two mechanisms).
setEntryPriority reuses patchJob. Solver: high never dropped + served
early, low dropped first.
Verified: job flag + conversation flag both grey-by-default, menu Haute/
Moyenne/Basse, high=red.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Planificateur « Suggérer » : 4 stratégies (smart / meilleurs d'abord / équilibré /
juste ce qu'il faut), compétences+niveaux par tech (édition inline), niveau requis
par compétence + par job, carte des tournées (1 couleur/tech, domicile→arrêts,
sélecteur de jour), fenêtre de dispatch auj.+demain (dates sélectionnées), règle
week-end + placeholder « en attente du quart », clustering + lasso + filtre-date
sur la carte, accès rapide « À assigner » (badge).
Boîte : liste /conversations allégée (45 Mo → ~1 Mo, 17×) + messages chargés à
l'ouverture. Rapports : cache SWR sur revenue-explorer (22×). Session : keep-alive
+ timeout fetch global + authFetch durci → fin des rechargements manuels.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Comms: sélecteur d'expéditeur « De: » (défaut groupe Support TARGO) via resolveSendFrom + alias vérifiés
- Notifs: prefs de feeds PAR utilisateur (/conversations/notif-prefs) + cloche à bascules ; boot tooltip-ux (clic prioritaire + anti-empilement)
- Courriel: invitation à évaluer = modèle Unlayer éditable (transactional-rating-invite-*) ; test-send via Gmail + expansion {{rating}} ; logo TARGO auto-hébergé sur le magasin d'actifs du hub
- Planif: bloc « sans déplacement » (damier, début de quart, alerte si pas de quart), quart éditable dans l'éditeur de jour, icônes de compétence en vue jour (TV pour télé), clic cellule → éditeur, clic gauche lane → liste / clic droit → menu quart, lien ↗ ticket par job
- Tickets: défaut « Non fermés » + correction du filtre « Mes tickets » (owner)
- Inbox: poll Gmail 1 min + rafraîchir à la demande (poll-now)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sender identity on outbound:
- Replies/new emails now go out as e.g. "Gilles Drolet" <support@targo.ca> instead
of the generic alias name "Service TARGO". The name is derived from the agent's SSO
email (gilles.drolet@ -> "Gilles Drolet"); the ADDRESS stays the monitored alias so
replies still land in the shared inbox. Verified: Gmail honors the custom display
name on the send-as alias (sent From header = "Gilles Drolet <support@targo.ca>").
- gmail.sendFrom() exported; conversation.js agentSendFrom() builds the From from the
stamped msg.agent (replies) / x-authentik-email (new sends via email-new).
UI cleanup (space + clarity, Gmail-style):
- One thin separator line between messages; removed the rounded gray card box around
emails (.email-card flat), the email-card-head bar, and the blue expanded-head
highlight.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Root cause: some F customer records carry our own/staff addresses in email_billing,
so matchCustomer's `email_billing LIKE '%addr%'` resolved support@targo.ca -> "Guylaine
Gagnon" and gilles@targointernet.com -> "Sylvie Juteau". Every thread on one of our
addresses then inherited that wrong customer + name.
- OWN_DOMAINS promoted to a single source in lib/helpers.js (was duplicated in
conversation.js); inbox-triage.matchCustomer() now returns null for any own-domain
address — a customer is never reachable at targo.ca / targointernet.com / gigafibre.ca.
- conversation.js consumes the shared OWN_DOMAINS (removes the local copy).
Also ran a one-shot repair (temporary endpoint, since removed) that unlinked the 6
already-contaminated threads and reset their display name to the real address.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Inbox identity/grouping (fixes mislabeled threads):
- customerName = real From display name, then a customer matched BY EMAIL,
then the raw address — never the AI's content-guessed name (a gilles@ relay
showed as "Sylvie Juteau").
- never group a thread by one of our own domains (support@targo.ca,
*@targointernet.com): re-ingested outbound was collapsing unrelated threads
into one mislabeled "Guylaine Gagnon" thread.
Refactor: queues/TYPES/QUEUE_OF/CAT centralized in lib/categories.js (were
drifting across conversation.js + inbox-triage.js; telephonie/television had
no matching triage type). Removed dead export findConversationByEmail.
Feat: addMessage stamps msg.agent on outbound replies -> per-agent stats.
Historique (/historique, HistoriquePage.vue): tournées par technicien (ALL
statuses incl. Completed/Cancelled — the board hid them), tech leaderboard,
inbox leaderboard. Hub: /dispatch/history, /dispatch/leaderboard,
/conversations/leaderboard.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Replaces hand-rolled `erpFetch` + `encodeURIComponent(JSON.stringify(...))`
URL building with a structured wrapper: erp.get/list/listRaw/create/update/
remove/getMany/hydrateLabels/raw.
Key wins:
- erp.list auto-retries up to 5 times when v16 rejects a fetched/linked
field with "Field not permitted in query" — the field is dropped and the
call continues, so callers don't have to know which fields v16 allows.
- erp.hydrateLabels batches link-label resolution (customer_name,
service_location_name, …) in one query per link field — no N+1, no
v16 breakage.
- Consistent {ok, error, status} shape for mutations.
Migrated call sites:
- otp.js: Customer email lookup + verifyOTP customer detail fetch +
Contact email fallback + Service Location listing
- referral.js: Referral Credit fetch / update / generate
- tech-absence-sms.js: lookupTechByPhone, set/clear absence
- conversation.js: Issue archive create
- magic-link.js: Tech lookup for /refresh
- ical.js: Tech lookup + jobs listing for iCal feed
- tech-mobile.js: 13 erpFetch sites → erp wrapper
Remaining erpFetch callers (dispatch.js, acceptance.js, payments.js,
contracts.js, checkout.js, …) deliberately left untouched this pass —
they each have 10+ sites and need individual smoke-tests.
Live-tested against production ERPNext: tech-mobile page renders 54K
bytes, no runtime errors in targo-hub logs post-restart.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>