gigafibre-fsm/scripts/migration/backfill_dispatch_address.sql
louispaulb e51007327d feat(dispatch): pont d'écriture legacy + adresses/coords/carte/UX Planification
Pont d'écriture Ops → legacy osTicket via endpoint PHP token-gated (hérite des
droits write de l'app facturation.targo.ca → AUCUN grant DB). Fidèle à ticket_view.php :
réassignation (assign_to + participant[assistants] + followed_by + ticket_msg + lock
respecté) + fermeture (status=closed + date_closed + closed_by + réouverture des enfants).
Auteur du log = utilisateur Authentik réel (email → staff legacy par email/nom).

Hub (legacy-dispatch-sync.js):
- adresse de SERVICE importée (champ address) + reimportAddresses + fillMissingCoords
- garde TERRITOIRE (rejette les homonymes hors-zone Gaspésie/Outaouais/Estrie) + centroïde CP/ville
- purgeStaleOrphans (anciens imports TT- périmés), # ticket legacy dans titre + description
- legacyWrite (POST form + X-Ops-Token lu d'un fichier), pushAssignments (reassign), closeTicketLegacy
roster.js: occupancy + unassigned-jobs exposent address/latitude/longitude.

Ops (PlanificationPage.vue):
- carte des jobs à assigner (pins couleur=compétence + lettre repère liste↔carte), chips
  filtre par type, panneau ouvert par défaut
- clics cellule: bande quart/garde + blocs jobs → tournée ; fond → menu horaire (fini le clic droit)
- éditeur de tournée: itinéraire routier réel + adresse + fil ticket (expand), refresh occupation à l'assignation
- bouton « Publier au legacy » (aperçu + ✕ désassigner) + « Fermer le ticket »
- fix dates (lundi calculé en local — plus de décalage UTC) + nav ±1 jour

services/legacy-bridge/ops_reassign.php: endpoint (placeholders; secrets injectés au déploiement, hors repo).
scripts/migration: backfill_dispatch_address.sql + diagnostics.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-07 22:32:00 -04:00

52 lines
2.4 KiB
PL/PgSQL

-- backfill_dispatch_address.sql — remplit le champ `address` (adresse de service) des Dispatch Jobs
-- issus du pont legacy, qui ne l'écrivait jamais (175 jobs, address vide).
-- A) jobs AVEC service_location → adresse depuis la SL (address_line + ville, en ignorant 'N/A')
-- B) jobs SANS service_location → adresse extraite du sujet (partie après ' · ', l'ancien append du pont)
-- Le pont écrit désormais `address` directement (création + backfill update) ; ce script rattrape l'historique.
-- Idempotent (ne touche que address = '' / NULL). À lancer AVANT toute re-sync (qui nettoie le sujet).
\timing on
SELECT character_maximum_length AS address_maxlen FROM information_schema.columns
WHERE table_name = 'tabDispatch Job' AND column_name = 'address';
BEGIN;
-- A) depuis la Service Location liée
WITH a AS (
UPDATE "tabDispatch Job" dj
SET address = left(NULLIF(trim(both ', ' FROM concat_ws(', ', NULLIF(sl.address_line,''), NULLIF(sl.city,'N/A'))), ''), 140),
modified = NOW()
FROM "tabService Location" sl
WHERE dj.service_location = sl.name
AND coalesce(dj.legacy_ticket_id,'') <> ''
AND coalesce(dj.address,'') = ''
AND NULLIF(trim(both ', ' FROM concat_ws(', ', NULLIF(sl.address_line,''), NULLIF(sl.city,'N/A'))), '') IS NOT NULL
RETURNING 1
)
SELECT count(*) AS rempli_via_service_location FROM a;
-- B) depuis le sujet (jobs sans SL : le pont y avait collé l'adresse après ' · ')
WITH b AS (
UPDATE "tabDispatch Job" dj
SET address = left(trim(split_part(subject, ' · ', 2)), 140),
modified = NOW()
WHERE coalesce(dj.legacy_ticket_id,'') <> ''
AND coalesce(dj.address,'') = ''
AND position(' · ' IN subject) > 0
AND length(trim(split_part(subject, ' · ', 2))) > 0
RETURNING 1
)
SELECT count(*) AS rempli_via_sujet FROM b;
COMMIT;
-- État final
SELECT count(*) FILTER (WHERE coalesce(address,'') <> '') AS addr_ok,
count(*) FILTER (WHERE coalesce(address,'') = '') AS addr_vide,
count(*) AS total
FROM "tabDispatch Job" WHERE coalesce(legacy_ticket_id,'') <> '';
-- Reste-t-il des jobs ACTIFS (open/assigned) sans adresse ? (à diagnostiquer le cas échéant)
SELECT name, status, left(subject,70) AS subject, service_location
FROM "tabDispatch Job"
WHERE coalesce(legacy_ticket_id,'') <> '' AND coalesce(address,'') = ''
AND status IN ('open','assigned','in_progress')
ORDER BY modified DESC LIMIT 10;