All tables per PRD data model with default config seeds. Migration runner tracks applied migrations in DB. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
93 lines
3.1 KiB
SQL
93 lines
3.1 KiB
SQL
-- App configuration (key/value store)
|
|
CREATE TABLE IF NOT EXISTS config (
|
|
key TEXT PRIMARY KEY,
|
|
value TEXT NOT NULL
|
|
);
|
|
|
|
-- Seed default config
|
|
INSERT INTO config (key, value) VALUES
|
|
('paycheck1_day', '1'),
|
|
('paycheck2_day', '15'),
|
|
('paycheck1_gross', '0'),
|
|
('paycheck1_net', '0'),
|
|
('paycheck2_gross', '0'),
|
|
('paycheck2_net', '0')
|
|
ON CONFLICT (key) DO NOTHING;
|
|
|
|
-- Bill definitions
|
|
CREATE TABLE IF NOT EXISTS bills (
|
|
id SERIAL PRIMARY KEY,
|
|
name TEXT NOT NULL,
|
|
amount NUMERIC(10,2) NOT NULL,
|
|
due_day INTEGER NOT NULL CHECK (due_day BETWEEN 1 AND 31),
|
|
assigned_paycheck INTEGER NOT NULL CHECK (assigned_paycheck IN (1, 2)),
|
|
category TEXT NOT NULL DEFAULT 'General',
|
|
active BOOLEAN NOT NULL DEFAULT TRUE,
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
);
|
|
|
|
-- Paycheck instances per period
|
|
CREATE TABLE IF NOT EXISTS paychecks (
|
|
id SERIAL PRIMARY KEY,
|
|
period_year INTEGER NOT NULL,
|
|
period_month INTEGER NOT NULL CHECK (period_month BETWEEN 1 AND 12),
|
|
paycheck_number INTEGER NOT NULL CHECK (paycheck_number IN (1, 2)),
|
|
pay_date DATE NOT NULL,
|
|
gross NUMERIC(10,2) NOT NULL DEFAULT 0,
|
|
net NUMERIC(10,2) NOT NULL DEFAULT 0,
|
|
UNIQUE (period_year, period_month, paycheck_number)
|
|
);
|
|
|
|
-- Bills assigned to a paycheck period
|
|
CREATE TABLE IF NOT EXISTS paycheck_bills (
|
|
id SERIAL PRIMARY KEY,
|
|
paycheck_id INTEGER NOT NULL REFERENCES paychecks(id) ON DELETE CASCADE,
|
|
bill_id INTEGER NOT NULL REFERENCES bills(id) ON DELETE CASCADE,
|
|
amount_override NUMERIC(10,2),
|
|
paid BOOLEAN NOT NULL DEFAULT FALSE,
|
|
paid_at TIMESTAMPTZ,
|
|
UNIQUE (paycheck_id, bill_id)
|
|
);
|
|
|
|
-- Savings goals
|
|
CREATE TABLE IF NOT EXISTS savings_goals (
|
|
id SERIAL PRIMARY KEY,
|
|
name TEXT NOT NULL,
|
|
amount NUMERIC(10,2) NOT NULL,
|
|
assigned_paycheck INTEGER NOT NULL CHECK (assigned_paycheck IN (1, 2)),
|
|
active BOOLEAN NOT NULL DEFAULT TRUE
|
|
);
|
|
|
|
-- One-time expenses
|
|
CREATE TABLE IF NOT EXISTS one_time_expenses (
|
|
id SERIAL PRIMARY KEY,
|
|
paycheck_id INTEGER NOT NULL REFERENCES paychecks(id) ON DELETE CASCADE,
|
|
name TEXT NOT NULL,
|
|
amount NUMERIC(10,2) NOT NULL,
|
|
paid BOOLEAN NOT NULL DEFAULT FALSE,
|
|
paid_at TIMESTAMPTZ
|
|
);
|
|
|
|
-- Variable expense categories
|
|
CREATE TABLE IF NOT EXISTS expense_categories (
|
|
id SERIAL PRIMARY KEY,
|
|
name TEXT NOT NULL UNIQUE
|
|
);
|
|
|
|
-- Seed default categories
|
|
INSERT INTO expense_categories (name) VALUES
|
|
('Groceries'), ('Gas'), ('Dining'), ('Entertainment'), ('Medical'), ('Other')
|
|
ON CONFLICT (name) DO NOTHING;
|
|
|
|
-- Actual spending log
|
|
CREATE TABLE IF NOT EXISTS actuals (
|
|
id SERIAL PRIMARY KEY,
|
|
paycheck_id INTEGER NOT NULL REFERENCES paychecks(id) ON DELETE CASCADE,
|
|
category_id INTEGER REFERENCES expense_categories(id),
|
|
bill_id INTEGER REFERENCES bills(id),
|
|
amount NUMERIC(10,2) NOT NULL,
|
|
note TEXT,
|
|
date DATE NOT NULL DEFAULT CURRENT_DATE,
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
);
|