-- 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() );