diff --git a/services/targo-hub/lib/roster.js b/services/targo-hub/lib/roster.js index fe41cf3..2aca37f 100644 --- a/services/targo-hub/lib/roster.js +++ b/services/targo-hub/lib/roster.js @@ -933,6 +933,29 @@ async function handleFieldTech (req, res, method, path, url) { const startTs = j.actual_start || (onSite ? ts : null) return json(res, up.ok ? 200 : 500, { ok: !!up.ok, on_site: onSite, distance_m: dist, minutes: minutesBetween(startTs, onSite ? ts : j.actual_end), actual_start: patch.actual_start || j.actual_start || '', actual_end: patch.actual_end || j.actual_end || '' }) } + // COMMENTAIRE du tech depuis l'app terrain → fil du ticket. Reste sur OPS (plus de renvoi vers store.targo.ca). + // Par défaut = NOTE INTERNE (jamais envoyée au client). Envoyée au client SEULEMENT si public=true (coché). + if (path === '/field/comment' && method === 'POST') { + const b = await parseBody(req); const name = fieldVerify(b.token || token); if (!name) return json(res, 403, { ok: false, error: 'lien invalide' }) + const text = String(b.text || '').trim(); if (!text) return json(res, 400, { ok: false, error: 'texte requis' }) + const isPublic = !!b.public + let posted = false, sentToCustomer = false + try { + const j = await erp.get('Dispatch Job', name, { fields: ['legacy_ticket_id'] }) + const lid = j && j.legacy_ticket_id + if (lid) { + // Fil legacy (osTicket) = ce que le volet job affiche. public=1 → réponse publique (courriel client) ; sinon note interne. + const msg = isPublic ? text : ('🔧 [Note tech — interne]\n' + text) + const r = await require('./legacy-dispatch-sync').postTicketLegacy(lid, msg, isPublic, '') + posted = !!(r && r.ok !== false); sentToCustomer = isPublic && posted + } else { + // Job natif (pas de ticket legacy) → Comment ERPNext sur le Dispatch Job. + await erp.create('Comment', { comment_type: 'Comment', reference_doctype: 'Dispatch Job', reference_name: name, content: (isPublic ? '📣 [Public] ' : '🔧 [Note tech] ') + text }) + posted = true + } + } catch (e) { return json(res, 500, { ok: false, error: e.message }) } + return json(res, 200, { ok: posted, public: isPublic, sentToCustomer }) + } if ((path === '/field' || path === '/field/app') && method === 'GET') return serveFieldApp(res) // PWA technicien (carte + tickets + photos + scan) if (path === '/field/tech' && method === 'GET') { // jobs du jour (+ demain) du tech, via token PAR TECH const tech = techFieldVerify(token); if (!tech) return json(res, 403, { ok: false, error: 'lien invalide' }) diff --git a/services/targo-hub/public/field-app.html b/services/targo-hub/public/field-app.html index 0a0f22f..609eda8 100644 --- a/services/targo-hub/public/field-app.html +++ b/services/targo-hub/public/field-app.html @@ -48,10 +48,18 @@