fix(reports/legacy): freshness from service date, not invoice date
Marc Robidoux flagged as overpriced (129.95$) — he has a loyalty discount
(service id 74448) that should lower it. Investigation: 74448 doesn't
exist in the copy (its max service id is 74393), so the discount was added
after the snapshot. Same freshness issue as Julie Dupuis — not a calc bug.
But this also exposed that the freshness banner was wrong: it read the
newest INVOICE date (Apr 30) while the snapshot actually carries SERVICES
created through May 22 — May's recurring billing run simply hadn't executed
at dump time, so invoices lag services by ~3 weeks. For a report that reads
active services/plans/discounts, the service date is the right freshness
signal.
fetchDataAsOf now returns both {services, invoices}; data_as_of (shown in
the banner) is the service date (May 22), with last_invoice kept for
reference. The copy is ~10 days stale, not ~1 month. Marc's loyalty credit
still won't show until the copy is refreshed (task #38).
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
7413743572
commit
ab57a3e135
|
|
@ -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) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user