feat(05-01): migration SQL and Go model types for template system

- Create 002_templates.sql: item_tier enum, ALTER budget_items, templates and template_items tables with CHECK constraint
- Add ItemTier type with fixed/variable/one_off constants to models.go
- Add ItemTier field to BudgetItem struct
- Add Template, TemplateItem, TemplateDetail structs
This commit is contained in:
2026-03-12 12:05:01 +01:00
parent 31a62a247f
commit b3082ca14f
2 changed files with 63 additions and 0 deletions

View File

@@ -18,6 +18,14 @@ const (
CategoryIncome CategoryType = "income"
)
type ItemTier string
const (
ItemTierFixed ItemTier = "fixed"
ItemTierVariable ItemTier = "variable"
ItemTierOneOff ItemTier = "one_off"
)
type User struct {
ID uuid.UUID `json:"id"`
Email string `json:"email"`
@@ -58,6 +66,7 @@ type BudgetItem struct {
CategoryID uuid.UUID `json:"category_id"`
CategoryName string `json:"category_name,omitempty"`
CategoryType CategoryType `json:"category_type,omitempty"`
ItemTier ItemTier `json:"item_tier"`
BudgetedAmount decimal.Decimal `json:"budgeted_amount"`
ActualAmount decimal.Decimal `json:"actual_amount"`
Notes string `json:"notes"`
@@ -86,3 +95,30 @@ type BudgetDetail struct {
Items []BudgetItem `json:"items"`
Totals BudgetTotals `json:"totals"`
}
type Template struct {
ID uuid.UUID `json:"id"`
UserID uuid.UUID `json:"user_id"`
Name string `json:"name"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
type TemplateItem struct {
ID uuid.UUID `json:"id"`
TemplateID uuid.UUID `json:"template_id"`
CategoryID uuid.UUID `json:"category_id"`
CategoryName string `json:"category_name,omitempty"`
CategoryType CategoryType `json:"category_type,omitempty"`
CategoryIcon string `json:"category_icon,omitempty"`
ItemTier ItemTier `json:"item_tier"`
BudgetedAmount *decimal.Decimal `json:"budgeted_amount"`
SortOrder int `json:"sort_order"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
type TemplateDetail struct {
Template
Items []TemplateItem `json:"items"`
}

View File

@@ -0,0 +1,27 @@
CREATE TYPE item_tier AS ENUM ('fixed', 'variable', 'one_off');
ALTER TABLE budget_items ADD COLUMN item_tier item_tier NOT NULL DEFAULT 'fixed';
CREATE TABLE IF NOT EXISTS templates (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
name TEXT NOT NULL DEFAULT 'My Template',
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
CREATE UNIQUE INDEX idx_templates_user_id ON templates (user_id);
CREATE TABLE IF NOT EXISTS template_items (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
template_id UUID NOT NULL REFERENCES templates(id) ON DELETE CASCADE,
category_id UUID NOT NULL REFERENCES categories(id) ON DELETE RESTRICT,
item_tier item_tier NOT NULL,
budgeted_amount NUMERIC(12, 2),
sort_order INT NOT NULL DEFAULT 0,
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),
CONSTRAINT chk_template_items_no_one_off CHECK (item_tier IN ('fixed', 'variable'))
);
CREATE INDEX idx_template_items_template_id ON template_items (template_id);