From 1186e50bbe933dee0f9f15c0d5138a823549298f Mon Sep 17 00:00:00 2001 From: louispaulb Date: Fri, 8 May 2026 11:21:18 -0400 Subject: [PATCH] fix(ops/client): cancelled subs no longer inflate monthly total + Lieu link in-app MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Three connected dispatcher-facing issues from C-LPB4 audit: 1. **Monthly total was wrong on customer cards.** Section subtotal and `locSubsMonthlyTotal` summed `actual_price` for ALL subscriptions regardless of status, so cancelled rows (rendered with strikethrough) still pumped up the displayed billing figure. C-LPB4 showed "Total mensuel: 86,10$" computed as `196.05 - 109.95 = 86.10`, where 196.05 included 3 cancelled internet plans (Megafibre 80, TEST-E2E-FTTH, FTTH100 — all struck through in the UI). Real active monthly is 5.00$ (109.95 active + 5 frais réseau − 109.95 loyalty rebate). Fixed both `sectionTotal` and `locSubsMonthlyTotal` /`locSubsAnnualTotal` to filter on `status === 'Active'`. 2. **"Lieu" link from a dispatch task pointed to ERPNext desk** which shows a raw doctype form (no abonnements, no totals, no contacts — just the bare fields). Now points in-app to `#/clients/?location=`. ClientDetailPage reads the query string on mount and: • scrolls the matching `loc-card` into view • pulses an indigo halo around it for ~2s so the rep finds it immediately even when the customer has many service locations. 3. **The shipping/billing distinction was invisible** on the customer page. Added an "Adresses de livraison" badge next to the "Lieux de service" section title — clarifies that this section IS the shipping address, distinct from the (future) billing address that will live on the Customer record. Cosmetic for now; the data migration to formalize that distinction is the next step. These three round out the C-LPB4 audit triggered by the wrong mapbox-pin location: now the customer card on the dispatcher's screen shows correct totals, the dispatch link drops them right at the spot they're trying to reach, and the role of each address-bearing record is named explicitly. --- .../src/composables/useSubscriptionGroups.js | 15 ++++- .../dispatch/components/RightPanel.vue | 12 ++-- apps/ops/src/pages/ClientDetailPage.vue | 61 ++++++++++++++++--- apps/ops/src/pages/DispatchPage.vue | 4 +- 4 files changed, 75 insertions(+), 17 deletions(-) diff --git a/apps/ops/src/composables/useSubscriptionGroups.js b/apps/ops/src/composables/useSubscriptionGroups.js index 3ea86a4..c55ac5c 100644 --- a/apps/ops/src/composables/useSubscriptionGroups.js +++ b/apps/ops/src/composables/useSubscriptionGroups.js @@ -73,8 +73,16 @@ export function subSubLabel (sub) { return '' } +// Only Active subs contribute to the displayed monthly total. Cancelled/ +// Suspended/Pending rows are still rendered (with strikethrough) for +// audit visibility but they shouldn't inflate the number the rep +// communicates to the customer. Was a real bug on C-LPB4: 5 internet +// rows summed to 196.05 because the 3 cancelled (Megafibre 80, TEST, +// FTTH100) were included in the math even though shown struck-through. +const isActiveBilling = sub => (sub.status || 'Active') === 'Active' + export function sectionTotal (items) { - return items.reduce((s, sub) => s + parseFloat(sub.actual_price || 0), 0) + return items.reduce((s, sub) => isActiveBilling(sub) ? s + parseFloat(sub.actual_price || 0) : s, 0) } export function annualPrice (sub) { @@ -102,11 +110,12 @@ export function useSubscriptionGroups (subscriptions) { } function locSubsMonthlyTotal (locName) { - return locSubsMonthly(locName).reduce((sum, s) => sum + parseFloat(s.actual_price || 0), 0) + // Same active-only filter as sectionTotal — keep them in sync. + return locSubsMonthly(locName).reduce((sum, s) => isActiveBilling(s) ? sum + parseFloat(s.actual_price || 0) : sum, 0) } function locSubsAnnualTotal (locName) { - return locSubsAnnual(locName).reduce((sum, s) => sum + annualPrice(s), 0) + return locSubsAnnual(locName).reduce((sum, s) => isActiveBilling(s) ? sum + annualPrice(s) : sum, 0) } function locSubsSections (locName, freq) { diff --git a/apps/ops/src/modules/dispatch/components/RightPanel.vue b/apps/ops/src/modules/dispatch/components/RightPanel.vue index 1e26295..c9ffdbd 100644 --- a/apps/ops/src/modules/dispatch/components/RightPanel.vue +++ b/apps/ops/src/modules/dispatch/components/RightPanel.vue @@ -52,11 +52,13 @@ const onDeleteTag = inject('onDeleteTag')
Lieu - - + + {{ panel.data.job.serviceLocation }} diff --git a/apps/ops/src/pages/ClientDetailPage.vue b/apps/ops/src/pages/ClientDetailPage.vue index 2d51b45..7eb627a 100644 --- a/apps/ops/src/pages/ClientDetailPage.vue +++ b/apps/ops/src/pages/ClientDetailPage.vue @@ -15,16 +15,25 @@
Aucun lieu de service
-
+
@@ -955,6 +964,7 @@