From 4bed6bb9fda6068c837cfedcc3f3b444989d14b5 Mon Sep 17 00:00:00 2001 From: louispaulb Date: Tue, 7 Jul 2026 22:02:10 -0400 Subject: [PATCH] =?UTF-8?q?planif=20:=20extraction=20#4/2=20=E2=80=94=20di?= =?UTF-8?q?alogue=20Synchroniser=20les=20techniciens=20=E2=86=92=20compone?= =?UTF-8?q?nts/planif/TechSyncDialog.vue?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 2e extraction de la décomposition (couplage nul : ne lit AUCUN état partagé). - components/planif/TechSyncDialog.vue (NOUVEAU) : reactive techSync + techSyncSelCount + applyTechSync déplacés ; rapport self-fetch à l'ouverture (watch modelValue) ; v-model pour l'ouverture ; émet `applied` après création → le parent appelle loadBase - PlanificationPage : dialogue + reactive + 2 fonctions retirés ; menu Outils → `showTechSync = true` ; `` - Vérifié en aperçu : ouvre via le menu, rapport chargé (staff 53 · fiches 56 · tech 41), 0 erreur Co-Authored-By: Claude Opus 4.8 --- .../src/components/planif/TechSyncDialog.vue | 80 +++++++++++++++++++ apps/ops/src/pages/PlanificationPage.vue | 67 ++-------------- 2 files changed, 86 insertions(+), 61 deletions(-) create mode 100644 apps/ops/src/components/planif/TechSyncDialog.vue diff --git a/apps/ops/src/components/planif/TechSyncDialog.vue b/apps/ops/src/components/planif/TechSyncDialog.vue new file mode 100644 index 0000000..a4aba4e --- /dev/null +++ b/apps/ops/src/components/planif/TechSyncDialog.vue @@ -0,0 +1,80 @@ + + + diff --git a/apps/ops/src/pages/PlanificationPage.vue b/apps/ops/src/pages/PlanificationPage.vue index 586679e..dfe3b2d 100644 --- a/apps/ops/src/pages/PlanificationPage.vue +++ b/apps/ops/src/pages/PlanificationPage.vue @@ -98,7 +98,7 @@ Générer l'horaire (semaine)solveur de quarts — la semaine affichée Générer les horaires (lot)modèle → plusieurs techs, N semaines Congés / absences - Synchroniser les techniciens + Synchroniser les techniciens 👁  Affichage @@ -1643,45 +1643,8 @@ - - - - -
👥 Synchroniser les techniciens
- - -
- - -
-
+ + @@ -2024,6 +1987,7 @@ import { useSla, SLA_BADGE } from 'src/composables/useSla' // SLA existant (poli import { useAuthStore } from 'src/stores/auth' // email de l'agent (X-Authentik-Email) pour l'envoi de réponses client import TechSelect from 'src/components/shared/TechSelect.vue' import LeaveDialog from 'src/components/planif/LeaveDialog.vue' // Congés & disponibilités (extrait — décomposition #4) +import TechSyncDialog from 'src/components/planif/TechSyncDialog.vue' // Synchroniser les techniciens (extrait — décomposition #4) import TicketStatusControl from 'src/components/shared/TicketStatusControl.vue' import TagEditor from 'src/components/shared/TagEditor.vue' // module de tags/compétences PARTAGÉ (chips colorées, création + palette, niveaux) — SOURCE UNIQUE : jobs ET techs import RouteMap from 'src/components/shared/RouteMap.vue' // carte de tournées réutilisable (revue dispatch auto + onglet Tournées) : OSRM réel, arrêts numérotés, fitTo @@ -3435,27 +3399,8 @@ async function openLegacyBlock (b) { try { legacyDetail.thread = await roster.ticketThread(b.lid) } catch (e) { err(e); legacyDetail.thread = { error: true, messages: [] } } finally { legacyDetail.loading = false } } -// ── Synchroniser les techniciens : rapport de réconciliation (staff legacy ↔ Dispatch Technician ↔ groupe Authentik tech) ── -const techSync = reactive({ open: false, loading: false, applying: false, report: null, sel: {} }) -const techSyncSelCount = computed(() => Object.values(techSync.sel).filter(Boolean).length) -async function openTechSync () { - techSync.open = true; techSync.loading = true; techSync.report = null; techSync.sel = {} - try { - const r = await roster.techSyncReport(); techSync.report = r - for (const s of (r.staff_missing_fiche || [])) techSync.sel[s.staff_id] = true // candidats cochés par défaut - } catch (e) { err(e) } finally { techSync.loading = false } -} -async function applyTechSync () { - const ids = Object.entries(techSync.sel).filter(([, v]) => v).map(([k]) => k) - if (!ids.length) return - techSync.applying = true - try { - const r = await roster.techSyncApply(ids) - $q.notify({ type: r.created ? 'positive' : 'info', icon: 'group_add', message: `${r.created} fiche(s) technicien créée(s)` + (r.results ? ` · ${r.results.filter(x => x.skipped).length} déjà présente(s)` : '') }) - techSync.open = false - await loadBase() // recharge la liste des techniciens dans la grille - } catch (e) { err(e) } finally { techSync.applying = false } -} +// Synchroniser les techniciens → extrait dans components/planif/TechSyncDialog.vue (état + fonctions déplacés ; @applied → loadBase). +const showTechSync = ref(false) const _hasJobLL = (j) => j && j.latitude != null && j.longitude != null && isFinite(+j.latitude) && isFinite(+j.longitude) && (Math.abs(+j.latitude) > 0.01 || Math.abs(+j.longitude) > 0.01) const assignNoCoord = computed(() => assignJobsFiltered.value.filter(j => !_hasJobLL(j)).length) // « sans coords » = dans le filtre courant (cohérent avec la carte) // LOT (pool « à assigner ») : faire correspondre l'adresse de chaque job sans coords à la base RQA → GPS, écrit