Files
SimpleFinanceDash/.planning/phases/05-template-data-model-and-api/05-01-SUMMARY.md
Jean-Luc Makiola eec8f4a9df docs(05-01): complete template data model and API plan
- Create 05-01-SUMMARY.md documenting migration, models, and query functions
- Update STATE.md with decisions, metrics, and progress bar (92%)
- Update ROADMAP.md phase 5 progress (1/2 plans complete)
- Mark requirements TMPL-01, TMPL-02, TMPL-04 complete in REQUIREMENTS.md

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-12 12:08:11 +01:00

6.2 KiB

phase, plan, subsystem, tags, requires, provides, affects, tech-stack, key-files, key-decisions, patterns-established, requirements-completed, duration, completed
phase plan subsystem tags requires provides affects tech-stack key-files key-decisions patterns-established requirements-completed duration completed
05-template-data-model-and-api 01 database
postgres
go
pgx
migrations
templates
budget-items
phase provides
01-foundation users/categories/budgets/budget_items tables and Go query layer
item_tier enum (fixed, variable, one_off) on budget_items
templates table (one-per-user via UNIQUE index)
template_items table with CHECK constraint (no one_off allowed)
Template, TemplateItem, TemplateDetail Go structs
GetTemplate, UpdateTemplateName, CreateTemplateItem, UpdateTemplateItem, DeleteTemplateItem, ReorderTemplateItems query functions
GenerateBudgetFromTemplate query function with duplicate-month detection and locale-aware naming
Updated CreateBudgetItem, UpdateBudgetItem, GetBudgetWithItems, CopyBudgetItems with item_tier support
05-02 (template HTTP handlers will call these query functions)
frontend template UI phases
added patterns
Lazy template creation
CreateTemplateItem upserts template before inserting item
BudgetExistsError struct wraps existing budget ID for 409 response
Default itemTier to one_off at query layer when empty (new items default to one_off)
created modified
backend/migrations/002_templates.sql
backend/internal/models/models.go
backend/internal/db/queries.go
backend/internal/api/handlers.go
New budget items created via API default to item_tier=one_off when not specified
Existing budget_items rows get DEFAULT item_tier='fixed' (migration assumes all prior items were recurring)
Template creation is lazy: CreateTemplateItem upserts template using ON CONFLICT DO UPDATE
GetTemplate returns empty TemplateDetail (not error) when no template exists for user
GenerateBudgetFromTemplate returns BudgetExistsError struct (not plain error) so handler can include existing budget ID in 409 response
Variable template items use budgeted_amount=0 when generating budget (fixed items copy the template amount)
BudgetExistsError: typed error struct for domain-specific errors needing structured data in HTTP response
Locale-aware month names via map[time.Month]string for EN and DE
TMPL-01
TMPL-02
TMPL-04
3min 2026-03-12

Phase 5 Plan 1: Template Data Model and API Summary

PostgreSQL migration and Go query layer for three-tier item model (fixed/variable/one_off), templates table with lazy creation, and GenerateBudgetFromTemplate with duplicate-month detection

Performance

  • Duration: ~3 min
  • Started: 2026-03-12T11:04:04Z
  • Completed: 2026-03-12T11:06:52Z
  • Tasks: 2
  • Files modified: 4 (2 created, 2 updated, 1 auto-fixed)

Accomplishments

  • Migration 002 adds item_tier enum to budget_items, creates templates and template_items tables with DB-level CHECK constraint preventing one_off items in templates
  • All 7 new template query functions implemented (GetTemplate, UpdateTemplateName, CreateTemplateItem, UpdateTemplateItem, DeleteTemplateItem, ReorderTemplateItems, GenerateBudgetFromTemplate)
  • Existing budget item queries (CreateBudgetItem, UpdateBudgetItem, GetBudgetWithItems, CopyBudgetItems) updated to include item_tier

Task Commits

Each task was committed atomically:

  1. Task 1: Migration SQL and Go model types - b3082ca (feat)
  2. Task 2: Database query functions - f9dd409 (feat)

Plan metadata: (to be created next)

Files Created/Modified

  • backend/migrations/002_templates.sql - item_tier enum, ALTER budget_items, templates and template_items tables with CHECK constraint
  • backend/internal/models/models.go - ItemTier type + constants, ItemTier field on BudgetItem, Template/TemplateItem/TemplateDetail structs
  • backend/internal/db/queries.go - All template query functions, updated budget item queries, BudgetExistsError, locale-aware month name maps
  • backend/internal/api/handlers.go - Updated CreateBudgetItem/UpdateBudgetItem calls to pass ItemTier from request body

Decisions Made

  • New API-created budget items default to item_tier=one_off (at the query layer) — new items created mid-month are one-offs unless specified
  • Migration uses DEFAULT 'fixed' for existing rows — prior items came from copy-from-previous, treating them as recurring
  • Template creation is lazy: CreateTemplateItem upserts the template via ON CONFLICT (user_id) DO UPDATE, no separate "create template" endpoint needed
  • GetTemplate returns empty TemplateDetail (not an error) when no template exists, per context decision
  • GenerateBudgetFromTemplate returns a typed BudgetExistsError struct so Plan 02 handler can extract the existing budget ID for a structured 409 response

Deviations from Plan

Auto-fixed Issues

1. [Rule 3 - Blocking] Updated handlers.go to pass ItemTier parameter

  • Found during: Task 2 (query function updates)
  • Issue: Changing CreateBudgetItem and UpdateBudgetItem signatures to include itemTier broke compilation of handlers.go, which calls both functions
  • Fix: Added ItemTier models.ItemTier to both request structs and passed it to the query calls
  • Files modified: backend/internal/api/handlers.go
  • Verification: go vet ./... passes cleanly
  • Committed in: f9dd409 (Task 2 commit)

Total deviations: 1 auto-fixed (1 blocking compile fix) Impact on plan: Necessary for correctness — handler was calling updated function with wrong arity. No scope creep.

Issues Encountered

None — plan executed cleanly with one compile-blocking auto-fix handled inline.

User Setup Required

None - no external service configuration required. Migration will be applied by the DB migration runner on next startup.

Next Phase Readiness

  • All query functions ready for Plan 02 HTTP handlers to consume
  • BudgetExistsError struct available for 409 response in GenerateBudgetFromTemplate handler
  • GetTemplate empty-return behavior documented for frontend to handle gracefully

Self-Check: PASSED

All created files verified on disk. Both task commits (b3082ca, f9dd409) confirmed in git log.


Phase: 05-template-data-model-and-api Completed: 2026-03-12