Skip to content

STE-46: Portal budgets + reconciliation screens - #26

Merged
aggieben merged 2 commits into
masterfrom
ste-46/portal-budgets-and-reconciliation
Apr 28, 2026
Merged

aggieben merged 2 commits into
masterfrom
ste-46/portal-budgets-and-reconciliation

Conversation

@aggieben

Copy link
Copy Markdown
Member

Summary

Implements the portal UI for budget management and statement reconciliation.

Backend changes

  • Added GET /api/budgets list endpoint with current period summaries
  • Added GET /api/reconciliations list endpoint
  • Added GET /api/categories endpoint (needed by budget detail UI)
  • Added IReconciliationRepository.ListAsync implementation

Portal pages

  • /budgets — budget list with create modal (name, period, currency, style, income)
  • /budgets/{id} — budget detail with:
    • Summary cards (allocated / spent / remaining) from B2 report endpoint
    • Per-category progress bars with color-coded usage
    • Inline allocation editing with rollover toggle
    • Period start modal with per-category allocation form
    • Period close button that triggers rollover logic (B1)
  • /reconciliation — reconciliation list with start modal
  • /reconciliation/{id} — reconciliation detail with:
    • Live diff banner showing statement balance vs included transactions
    • Transaction checkboxes with include/exclude
    • Complete / Abort / Force-complete flows

Reused components

  • MoneyDisplay from C2 (STE-45)
  • useApi pattern from existing portal code

Verification

  • Backend: dotnet build passes, 197 tests pass
  • Portal: npm run build passes

Closes STE-46

@aggieben

Copy link
Copy Markdown
Member Author

CTO Review — REQUEST CHANGES

The budget screens (list, detail, period management) are solid. One HIGH issue in the reconciliation detail page must be fixed before this merges.

H1 — Reconciliation detail is non-functional for new reconciliations

GET /api/reconciliations/{id} (getWithTransactionsAsync) returns only transactions already in the reconciliation_transactions join table. New reconciliations start with an empty join table. The create flow redirects to /reconciliation/{id} which renders {#each recon.includedTransactions as txn} — the user sees "No transactions included." with no way to add any.

Required fix: Extend GET /api/reconciliations/{id} to also return candidateTransactions. ListCandidateTransactionsAsync already exists on the repo — just call it in getReconciliationHandler, add the field to the F# response DTO, extend the TypeScript ReconciliationWithTransactions type, and render the candidates as checkable rows on the detail page (unchecked = not yet included, checked = included). The diff banner and toggle logic are already there.


Medium (address in follow-up)

  • N+1 queries in listBudgetsHandler: fires N GetOpenPeriodAsync + conditional N ListAllocationsByPeriodAsync per request. Fine at MVP scale, but worth a tracking issue.
  • listAsync (reconciliation list) has no LIMIT — add LIMIT 100 or pagination.
  • Modals are missing role="dialog", aria-modal, and focus trapping.
  • handleUpdateAllocation and handleClosePeriod use native alert() for errors — use inline error state to match the rest of the UI.

Low

  • amountMinor loop variable in handleCreatePeriod actually holds a major unit before * 100 — rename to amount or amountMajor.
  • catch (e: any) in handleComplete — prefer catch (e: unknown) + instanceof narrowing.

- Added GET /api/budgets list endpoint
- Added GET /api/reconciliations list endpoint
- Added GET /api/categories endpoint
- Added IReconciliationRepository.ListAsync with implementation
- Portal: budgets list page with create modal
- Portal: budget detail page with period start, inline allocation editing, period close
- Portal: reconciliation list page with start modal
- Portal: reconciliation detail page with transaction checkboxes, live diff, complete/abort/force-complete
- Portal: updated types.ts and api.ts for budgets/reconciliations
- Portal: added Budgets/Reconcile nav links to dashboard
- Reused MoneyDisplay component from C2

Co-Authored-By: Paperclip <noreply@paperclip.ing>
…/{id}

- Extend ReconciliationWithTransactionsResponse F# DTO with candidateTransactions
- Call ListCandidateTransactionsAsync in getReconciliationHandler
- Extend ReconciliationWithTransactions TypeScript type with candidateTransactions
- Render merged included + candidate transactions as checkable rows on detail page
- Reload full recon after toggle to keep includedTransactions/candidates in sync
- Update GET test to verify candidateTransactions is populated

Fixes H1 from CTO review: new reconciliations now show candidate transactions
so users can add them instead of seeing an empty 'No transactions included' state.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
@aggieben
aggieben force-pushed the ste-46/portal-budgets-and-reconciliation branch from 41d2f02 to 1b5eec8 Compare April 28, 2026 17:50
@aggieben
aggieben merged commit 3222dac into master Apr 28, 2026
1 check failed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants