From b631fabf91a58383ea02f08796fde0c264d6b583 Mon Sep 17 00:00:00 2001 From: louispaulb Date: Mon, 1 Jun 2026 19:12:49 -0400 Subject: [PATCH] fix(reports/legacy): exclude expired credits; confirm monthly price model MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed against docs/archive/LEGACY-ACCOUNTING-ANALYSIS.md (the migration audit) which surfaced two things to check in the overpriced-internet report: 1. service.payment_recurrence (0=annual, 2=monthly, 5=semestrial...) — checked whether per-cycle prices needed /N normalization. They do NOT: verified a semestrial FTTH1500I carries product.price=109.95, identical to the monthly one (billed 6×109.95 every 6 months). Per §6.1 "prix = quantité × prix_unitaire", product.price is already the monthly unit price. The original monthly logic was correct — no division. The SKU-LIKE-'%ANN' /12 special-case stays (true annual plans where price IS the yearly amount, e.g. FTTH_ANN @ 480$/yr). 2. Promo credits carry an actif_until end date (§10). A discount line whose actif_until is past no longer reduces today's bill, so counting it understates what the client actually pays. Now excluded. NULL-safety: the exclusion needs an explicit `actif_until IS NOT NULL` guard — without it, `NOT (price<0 AND actif_until>0 AND actif_until --- services/targo-hub/lib/legacy-reports.js | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/services/targo-hub/lib/legacy-reports.js b/services/targo-hub/lib/legacy-reports.js index 179dc26..590d944 100644 --- a/services/targo-hub/lib/legacy-reports.js +++ b/services/targo-hub/lib/legacy-reports.js @@ -22,15 +22,26 @@ * * Effective monthly price of a service line: * base = service.hijack=1 ? service.hijack_price : product.price - * // Annual plans (SKU ends in "ANN", e.g. FTTH_ANN @ 480$/yr) are - * // normalized to a monthly equivalent so the threshold compares apples - * // to apples — otherwise a $480/yr (=$40/mo) plan falsely shows as $480. + * // product.price is ALREADY the monthly unit price regardless of the + * // service's billing frequency — a semestrial FTTH1500I has price + * // 109.95 (same as the monthly one) and is billed 6×109.95 every 6 + * // months. Verified against the legacy billing logic (LEGACY- + * // ACCOUNTING-ANALYSIS.md §6.1: "prix = quantité × prix_unitaire"). + * // So we do NOT divide by service.payment_recurrence. + * // The one exception: true annual plans (SKU ends in "ANN", e.g. + * // FTTH_ANN @ 480$/yr where price IS the yearly amount) → normalize /12. * monthly = base / (sku LIKE '%ANN' ? 12 : 1) * * Only recurring lines count: product.price_recurr_type = 1. Type 0 is * one-time charges (equipment, installation) which don't belong on a * recurring monthly bill. * + * Expired credits excluded: a discount line (price<0) whose service + * actif_until is in the past no longer reduces the real bill — counting + * it would understate what the client actually pays today. (Per + * LEGACY-ACCOUNTING-ANALYSIS.md §10: promo credits carry an actif_until + * end date.) + * * Internet product categories: * 32 Mensualités fibre, 4 Mensualités sans-fil, 23 Internet camping * (add-ons) 16 Téléch. supp, 17 IP fixe, 21 Location point-à-point @@ -106,6 +117,7 @@ function buildQuery (url) { JOIN product p ON p.id = s.product_id WHERE p.category IN (${catPlaceholders}) AND p.price_recurr_type = 1 + AND NOT (p.price < 0 AND s.actif_until IS NOT NULL AND s.actif_until > 0 AND s.actif_until < UNIX_TIMESTAMP()) ${commercialClause} GROUP BY d.id HAVING net_internet > ?