Skip to content

fix(analytics): Savings History chart ignores the global Provider filter (only account honored) #25

Description

@cristim

The Savings-over-time analytics chart (getSavingsAnalytics -> /history/analytics, and getSavingsBreakdown -> /history/breakdown) accepts only account_id + date range + interval. getHistoryAnalytics/getHistoryBreakdown read NO provider param, and QueryHistory/QueryBreakdown WHERE is timestamp >= $1 AND timestamp <= $2 [+ account dual-column clause] (they GROUP BY provider but never restrict to one). So selecting a single Provider in the global top-bar filter does NOT filter the Savings History chart.

QA row 305 (LeanerCloud/cloud-commitments-cli#701) expects a Provider selection to filter Approval Queue + Savings History + Purchase History. The Approval Queue and Purchase History lists DO honor the provider filter; the Savings History chart does not. Account filtering of the chart works (fixed by LeanerCloud/cloud-commitments-cli#956). This gap is pre-existing - the analytics path never took a provider param; LeanerCloud/cloud-commitments-cli#956's scope was the account-id (UUID vs external) representation bug.

Fix

Plumb provider into getHistoryAnalytics/getHistoryBreakdown -> QueryHistory/QueryBreakdown WHERE (AND provider = $n when set), and have the FE getSavingsAnalytics/getSavingsBreakdown forward the global provider chip. Add a test asserting a provider-only selection restricts the chart. If an all-providers trend is the intended UX, close as wontfix with a note.

Found during adversarial verification of LeanerCloud/cloud-commitments-cli#956 (zero-ambiguity confirm of the analytics provider-only case).

Findings from the 2026-09-02 codebase audit

Added by an automated audit of 3c0f8ac94048a2c36fce5ccddee54e6c4849a5cd (tip of origin/main). Each item below was reported by one reviewer and independently confirmed by a second that did not write it. Full report: docs/audits/codebase-audit-2026-09-02.md.

A11-014 (medium)

The account dimension has the same shape as the provider gap described here, and the fix should probably land together. getSavingsAnalytics (frontend/src/api/history.ts:43-45) sends both account_ids=a,b,c and account_id=a, but the analytics handlers read only the singular param (accountID := params["account_id"] at internal/api/handler_analytics.go:40, :131, :197, then resolveSingleAccountFilterIDs) and account_ids is parsed nowhere for these routes. So with three accounts selected the chart silently renders only account A's savings while the chip row advertises three, an under-reported figure with no indication that two were dropped. The sibling getHistory (history.ts:22) sends only the plural form, which internal/api/handler_history.go:678 does honour, so the two panels on the same page disagree for the same filter. Either plumb account_ids through the analytics path alongside provider, or have the caller disable/annotate the chart when more than one account is selected. Audit finding A11-014.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions