Skip to content

feat(approvals): surface Account/Term/Payment/Monthly + user email in Approval queue - #713

Merged
cristim merged 1 commit into
feat/multicloud-web-frontendfrom
feat/704-approval-queue-columns
May 25, 2026
Merged

cristim merged 1 commit into
feat/multicloud-web-frontendfrom
feat/704-approval-queue-columns

Conversation

@cristim

@cristim cristim commented May 25, 2026

Copy link
Copy Markdown
Member

Closes #704.

Approval queue was missing operationally-critical columns (Account, Term, Payment, Monthly Cost) and showing raw user UUIDs instead of emails. Backend already had the data; frontend just didn't expose it.

Changes

  • internal/config/types.go — added CreatedByUserEmail to PurchaseHistoryRecord (excluded from DB persistence).
  • internal/api/handler_history.go — executionToHistoryRow takes a createdByEmail param; new resolveUserEmails (one GetUser per distinct creator UUID, fails gracefully); fetchExecutionsAsHistory builds the cache once and passes the resolved email per row.
  • internal/api/handler_history_test.go — TestHandler_getHistory_CreatedByUserEmailResolved (happy path + graceful lookup-failure).
  • frontend/src/types.ts — HistoryPurchase gains account_id, payment, monthly_cost, created_by_user_email.
  • frontend/src/recommendations.ts — exports getAccountName backed by the existing accountNamesCache so history.ts reuses it.
  • frontend/src/history.ts — renderApprovalQueue adds Account / Term / Payment / Monthly Cost columns; Created-by renders email with UUID then dash fallback.
  • 6 new tests in history-approval-queue.test.ts.

Row 1.3 decision (Effective Savings)

Chose Option B (keep label as 'Monthly Savings' — matches the actual semantic of estimated_savings). No formula change.

Tests

  • backend go test ./internal/api/... → 1234 pass
  • frontend history-approval-queue.test.ts → 13 pass
  • tsc + go vet + pre-commit clean

@cristim cristim added triaged Item has been triaged priority/p2 Backlog-worthy severity/medium Moderate harm urgency/this-sprint Within the current sprint impact/many Affects most users effort/m Days type/feat New capability labels May 25, 2026
@coderabbitai

coderabbitai Bot commented May 25, 2026 •

Copy link
Copy Markdown
Contributor

Warning

Review limit reached

@cristim, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 10 minutes and 13 seconds. Learn how PR review limits work.

Your organization has run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 6091f508-c9d7-42ff-950c-825cc3028bd3

📥 Commits

Reviewing files that changed from the base of the PR and between fdcede3 and e3ca433.

📒 Files selected for processing (7)
  • frontend/src/__tests__/history-approval-queue.test.ts
  • frontend/src/history.ts
  • frontend/src/recommendations.ts
  • frontend/src/types.ts
  • internal/api/handler_history.go
  • internal/api/handler_history_test.go
  • internal/config/types.go
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/704-approval-queue-columns

Comment @coderabbitai help to get the list of available commands and usage tips.

@cristim

cristim commented May 25, 2026

Copy link
Copy Markdown
Member Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented May 25, 2026

Copy link
Copy Markdown
Contributor
✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@cristim

cristim commented May 25, 2026

Copy link
Copy Markdown
Member Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented May 25, 2026

Copy link
Copy Markdown
Contributor
✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@cristim

cristim commented May 25, 2026

Copy link
Copy Markdown
Member Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented May 25, 2026

Copy link
Copy Markdown
Contributor
✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@cristim

cristim commented May 25, 2026

Copy link
Copy Markdown
Member Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented May 25, 2026

Copy link
Copy Markdown
Contributor
✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@cristim

cristim commented May 25, 2026

Copy link
Copy Markdown
Member Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented May 25, 2026

Copy link
Copy Markdown
Contributor
✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

… Approval queue

Add Account, Term, Payment, Monthly Cost columns to the Approval queue
renderer and show the creator's email (resolved from the auth service)
instead of the raw UUID.

Backend: PurchaseHistoryRecord gains CreatedByUserEmail (non-persisted).
executionToHistoryRow accepts the resolved email; fetchExecutionsAsHistory
builds a per-request user-ID-to-email cache via resolveUserEmails (one
GetUser call per distinct creator, logs+skips on failure).

Frontend types: HistoryPurchase extended with account_id, payment,
monthly_cost, created_by_user_email (term was already present).
recommendations.ts exports getAccountName() so history.ts can resolve
account names from the shared cache without duplicating the map.
renderApprovalQueue gains Account/Term/Payment/Monthly Cost columns; the
Created-by cell falls back UUID -> "-" when email is absent.

Effective Savings column: the existing "Monthly Savings" label already
matches the actual semantic (estimated_savings is a monthly figure), so
no rename or formula change is needed (row 1.3 resolved by option B).

Tests: two new Go sub-tests for email resolution and graceful degradation;
six new TS tests covering each new column and the email/UUID fallback chain.

Closes #704
@cristim
cristim force-pushed the feat/704-approval-queue-columns branch from 3532540 to e3ca433 Compare May 25, 2026 22:53
@cristim

cristim commented May 25, 2026

Copy link
Copy Markdown
Member Author

Rebased onto feat/multicloud-web-frontend@6f6b68b4d to resolve conflicts in internal/api/handler_history.go and internal/api/handler_history_test.go (conflict source: #716 history filter params). #716's historyFilters + matchesExecution filter on the executions half is preserved verbatim; #713's resolveUserEmails cache + executionToHistoryRow(... createdByEmail) plumbing + CreatedByUserEmail field is preserved verbatim. The handler now runs the filter check FIRST (cheap short-circuit) and only resolves the email for executions that survive. In the test file, #716's TestParseHistoryDateRange (and its three FilterParams/FilterValidation/DateRangeBoundary siblings) coexists with #713's new TestHandler_getHistory_CreatedByUserEmailResolved.

go test ./internal/api/... ./internal/config/... -> 1819 passed. go vet ./... clean. gofmt -l clean on touched files. Frontend: npx tsc --noEmit clean; jest --testPathPattern=history -> 142 passed (includes the approval-queue suite).

New HEAD: e3ca43308.

@coderabbitai review

@coderabbitai

coderabbitai Bot commented May 25, 2026

Copy link
Copy Markdown
Contributor

@cristim: Thanks for the detailed rebase summary! The conflict resolution approach — running the filter check first as a short-circuit before the email resolution — is a nice optimization. Triggering a review of the updated HEAD (e3ca43308) now.

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@cristim
cristim merged commit 367e447 into feat/multicloud-web-frontend May 25, 2026
6 checks passed
@cristim
cristim deleted the feat/704-approval-queue-columns branch May 25, 2026 23:16
cristim added a commit that referenced this pull request May 27, 2026
…e rows (closes #733) (#734)

PR #713 added the Account, Term, Payment, and Monthly Cost columns to
the Approval queue card; the columns render but every row showed "-"
because the backend never copied those fields onto the synthesised
PurchaseHistoryRecord:

- Account: executionToHistoryRow read exec.CloudAccountID, but the
  web-initiated bulk-purchase flow (buildPendingExecution) only
  populates the per-recommendation CloudAccountID and leaves the
  execution-level field nil. Fall back to a new
  collapseRecommendationAccount helper that returns the shared rec
  CloudAccountID, or "" (rendered as "-") for a basket genuinely
  spanning accounts.
- Payment: projectRecommendationFields populated Service, ResourceType,
  Region, Term, UpfrontCost, EstimatedSavings, and (single-rec only)
  MonthlyCost from the rec, but never set row.Payment. Single-rec now
  copies r.Payment; multi-rec collapses via collapseRecommendationPayment
  (same pattern as the existing Provider/Service/Term collapsers),
  returning "" when recs disagree so the dash fallback stays honest.
- MonthlyCost (multi-rec): only the single-rec branch mapped it; the
  multi-rec branch now sums per-rec MonthlyCost via
  sumRecommendationMonthlyCost (nil contributes 0, matching the
  single-rec treatment of nil MonthlyCost).

Regression tests:
- TestHandler_getHistory_ApprovalQueueColumnsPopulated pins all three
  shapes (single-rec, multi-rec uniform, multi-rec heterogeneous
  Payment) so a future refactor cannot silently re-empty the cells.
- TestHandler_getHistory_InProgressRowMapsRecFields extended with a
  Payment assertion.
- history-approval-queue.test.ts adds a frontend test that mocks the
  populated API shape and asserts the cells show real values, not "-".
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

effort/m Days impact/many Affects most users priority/p2 Backlog-worthy severity/medium Moderate harm triaged Item has been triaged type/feat New capability urgency/this-sprint Within the current sprint

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant