diff --git a/services/targo-hub/lib/legacy-reports.js b/services/targo-hub/lib/legacy-reports.js index 46e1ae3..7c817ac 100644 --- a/services/targo-hub/lib/legacy-reports.js +++ b/services/targo-hub/lib/legacy-reports.js @@ -176,17 +176,29 @@ function buildQuery (url) { return { sql, params, meta: { threshold, segment, includeAddons, cats, limit } } } -// Freshness probe — the most recent invoice date in the legacy copy tells -// us how stale the data is. The copy is a one-shot snapshot (no auto-sync), -// so the report must advertise its as-of date to avoid misleading the -// operator into acting on month-old prices (a re-negotiated client like -// Julie Dupuis won't show their new discount until the copy is refreshed). +// Freshness probe — the copy is a one-shot snapshot (no auto-sync), so the +// report advertises its as-of date so nobody acts on stale prices. +// +// This report reads SERVICES (active plans/discounts), not invoices, so the +// relevant freshness is the newest service.date_orig — NOT the newest +// invoice date. They differ: the snapshot carries services created up to +// ~May 22 but invoices only through Apr 30 (May's recurring billing run +// hadn't happened at dump time). Using the invoice date understated +// freshness by ~3 weeks. We return both; the UI shows the service one. +// (A discount added after the snapshot — e.g. Marc Robidoux's loyalty +// credit, service id 74448 > the copy's max 74393 — still won't appear +// until the copy is refreshed.) async function fetchDataAsOf (pool) { + const out = { services: null, invoices: null } try { - const [r] = await pool.execute('SELECT MAX(date_orig) AS max_ts FROM invoice') - const ts = r?.[0]?.max_ts - return ts ? new Date(ts * 1000).toISOString() : null - } catch { return null } + const [s] = await pool.execute('SELECT MAX(date_orig) AS max_ts FROM service') + if (s?.[0]?.max_ts) out.services = new Date(s[0].max_ts * 1000).toISOString() + } catch { /* ignore */ } + try { + const [i] = await pool.execute('SELECT MAX(date_orig) AS max_ts FROM invoice') + if (i?.[0]?.max_ts) out.invoices = new Date(i[0].max_ts * 1000).toISOString() + } catch { /* ignore */ } + return out } async function handleJson (req, res, url) { @@ -196,12 +208,15 @@ async function handleJson (req, res, url) { try { const t0 = Date.now() const [rows] = await pool.execute(sql, params) - const dataAsOf = await fetchDataAsOf(pool) + const asOf = await fetchDataAsOf(pool) log(`legacy report overpriced-internet: ${rows.length} rows in ${Date.now() - t0}ms (threshold=${meta.threshold}, segment=${meta.segment}, addons=${meta.includeAddons})`) return json(res, 200, { threshold: meta.threshold, segment: meta.segment, include_addons: meta.includeAddons, categories: meta.cats, - data_as_of: dataAsOf, + // data_as_of = service freshness (the relevant one for this report); + // last_invoice kept for reference. + data_as_of: asOf.services, + last_invoice: asOf.invoices, count: rows.length, rows, }) } catch (e) {