Repository navigation
fix(dashboard): call the Active Commitments figure estimated savings - #1716
Conversation
The Active Commitments card showed "$X/mo committed", but committed_monthly is the sum of the active commitments' EstimatedSavings (calculateCommitmentMetrics in handler_dashboard.go): monthly savings, not what the commitments cost. The card now says "$X/mo estimated savings". The API field keeps its name so existing API clients don't break; its Go doc comment and OpenAPI description now say what it holds. Closes #1709 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
@coderabbitai review |
|
Warning Review limit reachedYou've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository. Next included review available in 25 minutes. View limit details
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. |
Action not completed
|
|
Independent review (claude-qa-ui-4, cold): APPROVED 96c7659 The label matches what the field holds. Trace from storage to the card:
OpenAPI and Go docs: both new descriptions ("estimated monthly savings of the active commitments (the sum of their estimated savings), not what the commitments cost") match the code above. Other consumers: the only UI reader of Evidence (scratch worktree at this head,
Heads-up, non-blocking: #1707 also edits Not merging. |
Cold review verdict: APPROVE at 96c7659Reviewer: claude-as-qa-2 (cold, no author context). Base Verified (scratch worktree at the head,
|
| Step | Code | What it holds |
|---|---|---|
| Write | internal/purchase/execution.go:1040 savePurchaseHistory sets EstimatedSavings: rec.Savings, next to MonthlyCost: rec.MonthlyCost |
the recommendation's savings |
| Unit | RecommendationRecord.Savings is monthly: the frontend rebuilds on-demand as monthly_cost + savings + amortized_upfront (internal/config/types.go:662-663). calculateCommitmentMetrics documents EstimatedSavings as monthly (internal/api/handler_dashboard.go:707-710), and YTD multiplies it by elapsed months (:755) |
monthly |
| Read | GetActivePurchaseHistory (internal/config/store_postgres.go:2657) selects estimated_savings from purchase_history WHERE term > 0, not expired, revoked_at IS NULL, scoped by account |
active rows only |
| Aggregate | aggregateActiveCommitmentsPerService sums p.EstimatedSavings behind isActiveCommitment (handler_dashboard.go:635-649); committedMonthly is the sum of that map (:728-731); the provider filter is applied in fetchCommitmentPurchases |
Σ estimated monthly savings of active commitments |
| Card | dashboard.ts:410 ${formatCurrency(data.committed_monthly)}/mo estimated savings |
matches |
Nothing on this path reads monthly_cost or upfront_cost, so "committed" (cost) was wrong and "estimated savings" with "/mo" is right. The OpenAPI description ("Estimated monthly savings of the active commitments (the sum of their estimated savings), not what the commitments cost") and the types.go comment say the same and are accurate. The other "Committed" wording in dashboard.ts is the savings chart's "Current / Committed" layer, which plots the same EstimatedSavings per service, so it stays consistent.
No findings. Not merging.
Summary
The Home Active Commitments card read "$X/mo committed".
committed_monthlyis built incalculateCommitmentMetrics(internal/api/handler_dashboard.go) fromaggregateActiveCommitmentsPerService, which sums each active purchase'sEstimatedSavings. That is monthly savings, not the monthly cost of the commitments.frontend/src/dashboard.ts).committed_monthlyfield keeps its name, because renaming it would break existing API clients. Its Go doc comment (internal/api/types.go) and its OpenAPI description (internal/api/openapi.yaml) now say what it holds.The issue's other option, showing actual committed spend (amortized upfront plus recurring), would need a new backend figure. I left it out because no caller needs it yet.
This sits next to #1707's YTD caption change in the same tile list, so whichever merges second needs a one-line rebase.
Tests
main(received "$500/mo committed").npm test(4715 passed, 1 skipped),npm run lint(0 errors),npm run build, andgo test ./internal/api/ -run "OpenAPI|Openapi|Dashboard"pass.Closes #1709
🤖 Generated with Claude Code