improve(booking): SMS de confirmation transactionnel quand le client réserve via /book

À la confirmation d'un créneau (confirmWindow, donc Option A « choisir » ET Option B « proposer 3 » qui aboutit), on
texte le client : « votre rendez-vous technique est confirmé : <date> à <heure> (technicien X) ». Déclenché par SA
sélection (transactionnel), fire-and-forget (ne bloque pas la réponse). Complète le .ics — le client a une trace immédiate.
Téléphone résolu depuis Customer.mobile_no. Déployé, hub sain ; pas de test d'envoi réel (client réel).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
louispaulb 2026-07-19 16:41:12 -04:00
parent 6b9f7b41fa
commit 81af69e68c

View File

@ -898,8 +898,8 @@ async function confirmWindow (jobName, date, start, duration, skill) {
const st = start.length === 5 ? start + ':00' : start
// Garde F : si le ticket legacy est déjà assigné à un AUTRE tech dans F, on N'ÉCRASE PAS (côté client, pas de force).
// On enregistre le créneau choisi (booking_status Proposé) et on laisse le répartiteur confirmer le bon tech.
let legacyId = ''
try { const jb = await erp.get('Dispatch Job', jobName, { fields: ['legacy_ticket_id'] }); legacyId = (jb && jb.legacy_ticket_id) || '' } catch (e) {}
let legacyId = '', customer = ''
try { const jb = await erp.get('Dispatch Job', jobName, { fields: ['legacy_ticket_id', 'customer'] }); legacyId = (jb && jb.legacy_ticket_id) || ''; customer = (jb && jb.customer) || '' } catch (e) {}
const cf = await fConflict(legacyId, slot.tech)
if (cf) {
const rp = await retryWrite(() => erp.update('Dispatch Job', jobName, { scheduled_date: date, start_time: st, booking_status: 'Proposé', booking_prefs: JSON.stringify([{ date, start }]) }))
@ -907,7 +907,19 @@ async function confirmWindow (jobName, date, start, duration, skill) {
return { ok: true, confirmed: false, message: 'Créneau enregistré — nous confirmerons le technicien sous peu.' }
}
const r = await retryWrite(() => erp.update('Dispatch Job', jobName, { scheduled_date: date, start_time: st, assigned_tech: slot.tech, status: 'assigned', booking_status: 'Confirmé' }))
if (r.ok) releaseHold(date + '|' + start)
if (r.ok) {
releaseHold(date + '|' + start)
// SMS de confirmation TRANSACTIONNEL au client (déclenché par SA sélection) — fire-and-forget, ne bloque pas la réponse.
if (customer) {
(async () => {
try {
const c = await erp.get('Customer', customer, { fields: ['mobile_no'] })
const phone = c && c.mobile_no
if (phone) await require('./twilio').sendSmsInternal(phone, 'Gigafibre — votre rendez-vous technique est confirmé : ' + date + ' à ' + start + (slot.tech_name ? ' (technicien ' + slot.tech_name + ')' : '') + '. Merci !', customer)
} catch (e) {}
})()
}
}
return r.ok ? { ok: true, confirmed: true, date, start, tech: slot.tech_name } : { ok: false, message: r.error || 'échec' }
}