[BTAPI-65] Add GET /one-time/transactions #82

Merged
chris merged 4 commits from feature/BTAPI-65 into main 2026-08-30 11:39:28 -06:00
Owner

Ticket

BTAPI-65 Add GET /one-time/transactions — one-time transactions for a calendar year

Summary

  • Adds GET /one-time/transactions?year=YYYY, returning every one-time-tagged transaction for a calendar year (defaulting to the current year in America/Edmonton), newest first. Backs the upcoming One-Time screen (BTAPP-50), which is blocked on this ticket.
  • Validated via a new oneTimeTransactionsQuerySchema (four-digit integer, optional); malformed years return 400, an empty year returns 200 [].
  • Extracted a shared currentYear()/yearWindow(year) pair into @lib/budget (alongside the existing startOfBudgetWeek/countsTowardBudget) so the calendar-year-window computation isn't duplicated across the new route, the one-time data layer, and the pre-existing tag-summary window — getSummaries in @lib/tags now uses the same helper.
  • Full test coverage at all three layers (schema, data layer, route), including the Edmonton-timezone year boundary (both ends), refunds/credits, and transactions carrying an ignoring tag rather than the ignored flag.

Deferred

A performance review found getTransactionsForYear/spentFromPool walk every one-time-tagged transaction ever recorded rather than just the requested year, since no index currently covers tags.name + date together. Measured impact is ~1ms at household data volumes — confirmed low severity and deliberately not addressed here. A compound index { 'tags.name': 1, date: -1 } in ensureIndexes() (server/lib/data/transaction/index.ts) would close this if it's ever worth doing.

## Ticket [BTAPI-65](http://192.168.2.100:7123/home/browse/BTAPI-65/) Add GET /one-time/transactions — one-time transactions for a calendar year ## Summary - Adds `GET /one-time/transactions?year=YYYY`, returning every one-time-tagged transaction for a calendar year (defaulting to the current year in `America/Edmonton`), newest first. Backs the upcoming One-Time screen (BTAPP-50), which is blocked on this ticket. - Validated via a new `oneTimeTransactionsQuerySchema` (four-digit integer, optional); malformed years return 400, an empty year returns `200 []`. - Extracted a shared `currentYear()`/`yearWindow(year)` pair into `@lib/budget` (alongside the existing `startOfBudgetWeek`/`countsTowardBudget`) so the calendar-year-window computation isn't duplicated across the new route, the one-time data layer, and the pre-existing tag-summary window — `getSummaries` in `@lib/tags` now uses the same helper. - Full test coverage at all three layers (schema, data layer, route), including the Edmonton-timezone year boundary (both ends), refunds/credits, and transactions carrying an ignoring tag rather than the `ignored` flag. ## Deferred A performance review found `getTransactionsForYear`/`spentFromPool` walk every one-time-tagged transaction ever recorded rather than just the requested year, since no index currently covers `tags.name` + `date` together. Measured impact is ~1ms at household data volumes — confirmed low severity and deliberately not addressed here. A compound index `{ 'tags.name': 1, date: -1 }` in `ensureIndexes()` (`server/lib/data/transaction/index.ts`) would close this if it's ever worth doing.
chris merged commit 6836f79772 into main 2026-08-30 11:39:28 -06:00
chris deleted branch feature/BTAPI-65 2026-08-30 11:39:28 -06:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
chris/budget-tracker!82
No description provided.