You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
feat(frontend/recs): On-Demand Monthly column should use provider on_demand_cost directly (no reconstruction) #330
Change onDemandMonthly() in frontend/src/recommendations.ts to return the
provider-supplied r.on_demand_cost directly instead of reconstructing it from monthly_cost + savings + (upfront_cost / months_in_term). When on_demand_cost is missing or zero, render — instead of falling back to a
reconstructed value.
Why
PR #322 deliberately scoped the On-Demand Monthly column to a reconstruction-only helper (its commit comment says: "It does NOT use
on_demand_cost even when available, because the column's purpose is to display
the reconstructed denominator so users can verify the formula against the raw
fields visible in the same row").
In practice, post-#277 / #312 / #324 every supported provider (AWS, Azure, GCP)
plumbs on_demand_cost through to the frontend, and effectiveSavingsPct()
already prefers the provider value when present (see frontend/src/recommendations.ts:738-756 — hasOnDemand branch). The two
columns therefore disagree for any row where the formula reconstruction drifts
from the provider's billed on-demand price (rounding, partial-day proration,
provider-specific list price quirks, AWS On-Demand Capacity Reservations, etc.).
The product decision: surface the authoritative number from the provider,
not a teaching-tool reconstruction. Users who want to verify the formula can
still see monthly_cost + savings + upfront_cost/term in the row's other
columns and do the arithmetic themselves; making On-Demand Monthlymatch effectiveSavingsPct's denominator is more important than making it reconstructible.
Scope
onDemandMonthly(): drop the reconstruction. Return r.on_demand_cost when
it's a positive number; return null otherwise (so the cell shows —,
consistent with the existing monthly_cost == null em-dash rendering).
Update the doc comment on onDemandMonthly() to reflect the new contract.
Update the unit tests in frontend/src/__tests__/recommendations.test.ts:
keep "prefer explicit on_demand_cost",
replace "fall back to reconstruction" tests with "return null when on_demand_cost is null/missing/zero",
the existing reconstruction-arithmetic tests can be deleted — they're
asserting behaviour we're explicitly removing.
AC1 – returns r.on_demand_cost when > 0: onDemandMonthly now contains exactly if (r.on_demand_cost != null && r.on_demand_cost > 0) { return r.on_demand_cost; } — the arithmetic reconstruction is gone. Test: "returns provider on_demand_cost directly when populated" asserts odm === 500 with all supporting fields set to different values.
AC2 – returns null for null, undefined, or 0: Three dedicated unit tests cover each case explicitly; the delete r.on_demand_cost (missing-field) case is also covered.
AC4 – sort null-last / numeric-filter NaN sentinel unchanged: Sort comparator comment and SORTABLE_NUMERIC_COLUMNS entry are unchanged in logic (?? Number.POSITIVE_INFINITY still present); numericCellValue still returns Number.NaN for null. Filter regression test updated to trigger null via missing on_demand_cost and still asserts the row does not match = 0.
AC5 – unit tests updated; full suite green: 7 reconstruction-arithmetic tests replaced with 5 new-contract tests; 3 column-rendering tests updated; PR reports 1578 passed / 0 failed across 42 suites.
AC6 – no regressions in column ordering / sort / filter tests: effectiveSavingsPct fallback logic untouched; sort/filter column tests updated to align fixtures with new null condition and all pass.
Activity
fix(frontend/recs): cover explicit-undefined + freshen filter comment…
feat(frontend/recs): On-Demand Monthly uses provider on_demand_cost d…
cristim commentedon May 13, 2026
Verified resolved by PR #331 (merged 2026-05-11).
r.on_demand_costwhen> 0:onDemandMonthlynow contains exactlyif (r.on_demand_cost != null && r.on_demand_cost > 0) { return r.on_demand_cost; }— the arithmetic reconstruction is gone. Test: "returns provider on_demand_cost directly when populated" assertsodm === 500with all supporting fields set to different values.nullfornull,undefined, or0: Three dedicated unit tests cover each case explicitly; thedelete r.on_demand_cost(missing-field) case is also covered.—for null cases: Column-rendering test "On-Demand Monthly column renders em-dash when on_demand_cost is missing" confirms the em-dash path still fires; the fixture now omitson_demand_costrather than usingmonthly_cost: null, which is the correct null trigger post-feat(frontend/recs): On-Demand Monthly column should use provider on_demand_cost directly (no reconstruction) #330.SORTABLE_NUMERIC_COLUMNSentry are unchanged in logic (?? Number.POSITIVE_INFINITYstill present);numericCellValuestill returnsNumber.NaNfor null. Filter regression test updated to trigger null via missingon_demand_costand still asserts the row does not match= 0.effectiveSavingsPctfallback logic untouched; sort/filter column tests updated to align fixtures with new null condition and all pass.Recommending closure.