From 7be5510753b8a42f29613f90598e7d9887c8cce8 Mon Sep 17 00:00:00 2001 From: juancwu Date: Mon, 6 Apr 2026 14:49:36 +0000 Subject: [PATCH] feat: new minimal db schema --- ...> 00001_create_identity_access_tables.sql} | 18 +++ .../migrations/00001_create_users_table.sql | 21 ---- ..._create_workspace_collaboration_tables.sql | 35 ++++++ ...003_create_financial_management_tables.sql | 44 +++++++ .../00003_create_profiles_table.sql | 19 --- .../migrations/00004_create_files_table.sql | 30 ----- .../migrations/00005_create_spaces_tables.sql | 32 ----- .../00006_create_features_tables.sql | 48 -------- .../00007_create_expenses_tables.sql | 42 ------- .../00008_create_space_invitations_table.sql | 25 ---- .../00009_create_money_accounts_tables.sql | 37 ------ .../00010_create_payment_methods_table.sql | 23 ---- .../00011_create_recurring_expenses_table.sql | 44 ------- .../migrations/00012_create_budgets_table.sql | 24 ---- .../db/migrations/00013_budget_tags_table.sql | 92 --------------- .../00014_create_recurring_deposits_table.sql | 31 ----- .../00015_add_timezone_to_profiles.sql | 5 - .../00016_add_timezone_to_spaces.sql | 5 - ...00017_create_loans_and_receipts_tables.sql | 110 ------------------ .../00018_add_decimal_amount_columns.sql | 54 --------- .../00019_fix_decimal_amount_values.sql | 97 --------------- 21 files changed, 97 insertions(+), 739 deletions(-) rename internal/db/migrations/{00002_create_tokens_table.sql => 00001_create_identity_access_tables.sql} (54%) delete mode 100644 internal/db/migrations/00001_create_users_table.sql create mode 100644 internal/db/migrations/00002_create_workspace_collaboration_tables.sql create mode 100644 internal/db/migrations/00003_create_financial_management_tables.sql delete mode 100644 internal/db/migrations/00003_create_profiles_table.sql delete mode 100644 internal/db/migrations/00004_create_files_table.sql delete mode 100644 internal/db/migrations/00005_create_spaces_tables.sql delete mode 100644 internal/db/migrations/00006_create_features_tables.sql delete mode 100644 internal/db/migrations/00007_create_expenses_tables.sql delete mode 100644 internal/db/migrations/00008_create_space_invitations_table.sql delete mode 100644 internal/db/migrations/00009_create_money_accounts_tables.sql delete mode 100644 internal/db/migrations/00010_create_payment_methods_table.sql delete mode 100644 internal/db/migrations/00011_create_recurring_expenses_table.sql delete mode 100644 internal/db/migrations/00012_create_budgets_table.sql delete mode 100644 internal/db/migrations/00013_budget_tags_table.sql delete mode 100644 internal/db/migrations/00014_create_recurring_deposits_table.sql delete mode 100644 internal/db/migrations/00015_add_timezone_to_profiles.sql delete mode 100644 internal/db/migrations/00016_add_timezone_to_spaces.sql delete mode 100644 internal/db/migrations/00017_create_loans_and_receipts_tables.sql delete mode 100644 internal/db/migrations/00018_add_decimal_amount_columns.sql delete mode 100644 internal/db/migrations/00019_fix_decimal_amount_values.sql diff --git a/internal/db/migrations/00002_create_tokens_table.sql b/internal/db/migrations/00001_create_identity_access_tables.sql similarity index 54% rename from internal/db/migrations/00002_create_tokens_table.sql rename to internal/db/migrations/00001_create_identity_access_tables.sql index 8c1003d..866cd42 100644 --- a/internal/db/migrations/00002_create_tokens_table.sql +++ b/internal/db/migrations/00001_create_identity_access_tables.sql @@ -1,5 +1,19 @@ -- +goose Up -- +goose StatementBegin +CREATE TABLE IF NOT EXISTS users ( + id TEXT PRIMARY KEY NOT NULL, + email TEXT UNIQUE NOT NULL, + name TEXT NULL, + password_hash TEXT NULL, -- Allow null for passwordless login + pending_email TEXT NULL, -- Store new email when changing email + email_verified_at TIMESTAMP NULL, + created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP +); + +CREATE INDEX IF NOT EXISTS idx_users_email ON users(email); +CREATE INDEX IF NOT EXISTS idx_users_passwordless ON users(id) WHERE password_hash IS NULL; + CREATE TABLE IF NOT EXISTS tokens ( id TEXT PRIMARY KEY NOT NULL, user_id TEXT NOT NULL, @@ -22,4 +36,8 @@ DROP INDEX IF EXISTS idx_tokens_user_id; DROP INDEX IF EXISTS idx_tokens_expires_at; DROP INDEX IF EXISTS idx_tokens_token; DROP TABLE IF EXISTS tokens; + +DROP INDEX IF EXISTS idx_users_passwordless; +DROP INDEX IF EXISTS idx_users_email; +DROP TABLE IF EXISTS users; -- +goose StatementEnd diff --git a/internal/db/migrations/00001_create_users_table.sql b/internal/db/migrations/00001_create_users_table.sql deleted file mode 100644 index 3f25a13..0000000 --- a/internal/db/migrations/00001_create_users_table.sql +++ /dev/null @@ -1,21 +0,0 @@ --- +goose Up --- +goose StatementBegin -CREATE TABLE IF NOT EXISTS users ( - id TEXT PRIMARY KEY NOT NULL, - email TEXT UNIQUE NOT NULL, - password_hash TEXT NULL, -- Allow null for passwordless login - pending_email TEXT NULL, -- Store new email when changing email - email_verified_at TIMESTAMP NULL, - created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP -); - -CREATE INDEX IF NOT EXISTS idx_users_email ON users(email); -CREATE INDEX IF NOT EXISTS idx_users_passwordless ON users(id) WHERE password_hash IS NULL; --- +goose StatementEnd - --- +goose Down --- +goose StatementBegin -DROP INDEX IF EXISTS idx_users_passwordless; -DROP INDEX IF EXISTS idx_users_email; -DROP TABLE IF EXISTS users; --- +goose StatementEnd diff --git a/internal/db/migrations/00002_create_workspace_collaboration_tables.sql b/internal/db/migrations/00002_create_workspace_collaboration_tables.sql new file mode 100644 index 0000000..0359ee7 --- /dev/null +++ b/internal/db/migrations/00002_create_workspace_collaboration_tables.sql @@ -0,0 +1,35 @@ +-- +goose Up +-- +goose StatementBegin +CREATE TABLE spaces ( + id TEXT PRIMARY KEY NOT NULL, + name TEXT NOT NULL, + created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP +); + +CREATE TABLE space_members ( + space_id TEXT NOT NULL, + user_id TEXT NOT NULL, + role TEXT NOT NULL, + joined_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (space_id, user_id), + FOREIGN KEY (space_id) REFERENCES spaces(id) ON DELETE CASCADE, + FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE +); + +CREATE TABLE space_invitations ( + token TEXT PRIMARY KEY NOT NULL, + space_id TEXT NOT NULL REFERENCES spaces(id) ON DELETE CASCADE, + inviter_id TEXT NOT NULL REFERENCES users(id) ON DELETE CASCADE, + invitee_email TEXT NOT NULL, + expires_at TIMESTAMP NOT NULL, + created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP +); +-- +goose StatementEnd + +-- +goose Down +-- +goose StatementBegin +DROP TABLE space_invitations; +DROP TABLE space_members; +DROP TABLE spaces; +-- +goose StatementEnd diff --git a/internal/db/migrations/00003_create_financial_management_tables.sql b/internal/db/migrations/00003_create_financial_management_tables.sql new file mode 100644 index 0000000..55a6371 --- /dev/null +++ b/internal/db/migrations/00003_create_financial_management_tables.sql @@ -0,0 +1,44 @@ +-- +goose Up +-- +goose StatementBegin +CREATE TABLE accounts ( + id TEXT NOT NULL PRIMARY KEY, + name TEXT NOT NULL, + space_id TEXT NOT NULL REFERENCES spaces(id) ON DELETE CASCADE, + created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP +); + +CREATE TABLE transactions ( + id TEXT NOT NULL PRIMARY KEY, + value TEXT NOT NULL, + type TEXT NOT NULL, + account_id TEXT NOT NULL REFERENCES accounts(id) ON DELETE CASCADE, + description TEXT, + related_transaction_id TEXT REFERENCES transactions(id) ON DELETE SET NULL, + created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP +); + +CREATE TABLE tags ( + id TEXT NOT NULL PRIMARY KEY, + name TEXT NOT NULL, + space_id TEXT NOT NULL REFERENCES spaces(id) ON DELETE CASCADE, + created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP +); + +CREATE TABLE transaction_tags ( + tag_id TEXT NOT NULL REFERENCES tags(id) ON DELETE CASCADE, + transaction_id TEXT NOT NULL REFERENCES transactions(id) ON DELETE CASCADE, + created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (tag_id, transaction_id) +); +-- +goose StatementEnd + +-- +goose Down +-- +goose StatementBegin +DROP TABLE transaction_tags; +DROP TABLE tags; +DROP TABLE transactions; +DROP TABLE accounts; +-- +goose StatementEnd diff --git a/internal/db/migrations/00003_create_profiles_table.sql b/internal/db/migrations/00003_create_profiles_table.sql deleted file mode 100644 index 390f6e6..0000000 --- a/internal/db/migrations/00003_create_profiles_table.sql +++ /dev/null @@ -1,19 +0,0 @@ --- +goose Up --- +goose StatementBegin -CREATE TABLE IF NOT EXISTS profiles ( - id TEXT PRIMARY KEY NOT NULL, - user_id TEXT UNIQUE NOT NULL, - name TEXT NOT NULL, - created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, - updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, - FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE -); - -CREATE INDEX IF NOT EXISTS idx_profiles_user_id ON profiles(user_id); --- +goose StatementEnd - --- +goose Down --- +goose StatementBegin -DROP INDEX IF EXISTS idx_profiles_user_id; -DROP TABLE IF EXISTS profiles; --- +goose StatementEnd diff --git a/internal/db/migrations/00004_create_files_table.sql b/internal/db/migrations/00004_create_files_table.sql deleted file mode 100644 index 2ea0a01..0000000 --- a/internal/db/migrations/00004_create_files_table.sql +++ /dev/null @@ -1,30 +0,0 @@ --- +goose Up --- +goose StatementBegin -CREATE TABLE IF NOT EXISTS files ( - id TEXT PRIMARY KEY NOT NULL, - user_id TEXT NOT NULL, - owner_type TEXT NOT NULL, - owner_id TEXT NOT NULL, - type TEXT NOT NULL, - filename TEXT NOT NULL, - original_name TEXT, - mime_type TEXT, - size INTEGER, - storage_path TEXT NOT NULL, - public BOOLEAN DEFAULT true, - created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, - FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE -); - -CREATE INDEX IF NOT EXISTS idx_files_user_id ON files(user_id); -CREATE INDEX IF NOT EXISTS idx_files_owner ON files(owner_type, owner_id); -CREATE UNIQUE INDEX IF NOT EXISTS idx_files_owner_type ON files(owner_type, owner_id, type) WHERE type IN ('avatar'); --- +goose StatementEnd - --- +goose Down --- +goose StatementBegin -DROP INDEX IF EXISTS idx_files_owner_type; -DROP INDEX IF EXISTS idx_files_owner; -DROP INDEX IF EXISTS idx_files_user_id; -DROP TABLE IF EXISTS files; --- +goose StatementEnd diff --git a/internal/db/migrations/00005_create_spaces_tables.sql b/internal/db/migrations/00005_create_spaces_tables.sql deleted file mode 100644 index 8334601..0000000 --- a/internal/db/migrations/00005_create_spaces_tables.sql +++ /dev/null @@ -1,32 +0,0 @@ --- +goose Up --- +goose StatementBegin -CREATE TABLE IF NOT EXISTS spaces ( - id TEXT PRIMARY KEY NOT NULL, - name TEXT NOT NULL, - owner_id TEXT NOT NULL, - created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, - updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, - FOREIGN KEY (owner_id) REFERENCES users(id) ON DELETE CASCADE -); - -CREATE TABLE IF NOT EXISTS space_members ( - space_id TEXT NOT NULL, - user_id TEXT NOT NULL, - role TEXT NOT NULL CHECK (role IN ('owner', 'member')), - joined_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, - PRIMARY KEY (space_id, user_id), - FOREIGN KEY (space_id) REFERENCES spaces(id) ON DELETE CASCADE, - FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE -); - -CREATE INDEX IF NOT EXISTS idx_spaces_owner ON spaces(owner_id); -CREATE INDEX IF NOT EXISTS idx_space_members_user ON space_members(user_id); --- +goose StatementEnd - --- +goose Down --- +goose StatementBegin -DROP INDEX IF EXISTS idx_space_members_user; -DROP INDEX IF EXISTS idx_spaces_owner; -DROP TABLE IF EXISTS space_members; -DROP TABLE IF EXISTS spaces; --- +goose StatementEnd diff --git a/internal/db/migrations/00006_create_features_tables.sql b/internal/db/migrations/00006_create_features_tables.sql deleted file mode 100644 index 8092729..0000000 --- a/internal/db/migrations/00006_create_features_tables.sql +++ /dev/null @@ -1,48 +0,0 @@ --- +goose Up --- +goose StatementBegin -CREATE TABLE IF NOT EXISTS tags ( - id TEXT PRIMARY KEY NOT NULL, - space_id TEXT NOT NULL, - name TEXT NOT NULL, - color TEXT, - created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, - updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, - UNIQUE (space_id, name), - FOREIGN KEY (space_id) REFERENCES spaces(id) ON DELETE CASCADE -); - -CREATE TABLE IF NOT EXISTS shopping_lists ( - id TEXT PRIMARY KEY NOT NULL, - space_id TEXT NOT NULL, - name TEXT NOT NULL, - created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, - updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, - FOREIGN KEY (space_id) REFERENCES spaces(id) ON DELETE CASCADE -); - -CREATE TABLE IF NOT EXISTS list_items ( - id TEXT PRIMARY KEY NOT NULL, - list_id TEXT NOT NULL, - name TEXT NOT NULL, - is_checked BOOLEAN NOT NULL DEFAULT FALSE, - created_by TEXT NOT NULL, - created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, - updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, - FOREIGN KEY (list_id) REFERENCES shopping_lists(id) ON DELETE CASCADE, - FOREIGN KEY (created_by) REFERENCES users(id) ON DELETE CASCADE -); - -CREATE INDEX IF NOT EXISTS idx_tags_space_id ON tags(space_id); -CREATE INDEX IF NOT EXISTS idx_shopping_lists_space_id ON shopping_lists(space_id); -CREATE INDEX IF NOT EXISTS idx_list_items_list_id ON list_items(list_id); --- +goose StatementEnd - --- +goose Down --- +goose StatementBegin -DROP INDEX IF EXISTS idx_list_items_list_id; -DROP INDEX IF EXISTS idx_shopping_lists_space_id; -DROP INDEX IF EXISTS idx_tags_space_id; -DROP TABLE IF EXISTS list_items; -DROP TABLE IF EXISTS shopping_lists; -DROP TABLE IF EXISTS tags; --- +goose StatementEnd diff --git a/internal/db/migrations/00007_create_expenses_tables.sql b/internal/db/migrations/00007_create_expenses_tables.sql deleted file mode 100644 index fc321dc..0000000 --- a/internal/db/migrations/00007_create_expenses_tables.sql +++ /dev/null @@ -1,42 +0,0 @@ --- +goose Up --- +goose StatementBegin -CREATE TABLE IF NOT EXISTS expenses ( - id TEXT PRIMARY KEY NOT NULL, - space_id TEXT NOT NULL, - created_by TEXT NOT NULL, - description TEXT NOT NULL, - amount_cents INTEGER NOT NULL, - type TEXT NOT NULL CHECK (type IN ('expense', 'topup')), - date TIMESTAMP NOT NULL, - created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, - updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, - FOREIGN KEY (space_id) REFERENCES spaces(id) ON DELETE CASCADE, - FOREIGN KEY (created_by) REFERENCES users(id) ON DELETE CASCADE -); - -CREATE TABLE IF NOT EXISTS expense_tags ( - expense_id TEXT NOT NULL, - tag_id TEXT NOT NULL, - PRIMARY KEY (expense_id, tag_id), - FOREIGN KEY (expense_id) REFERENCES expenses(id) ON DELETE CASCADE, - FOREIGN KEY (tag_id) REFERENCES tags(id) ON DELETE CASCADE -); - -CREATE TABLE IF NOT EXISTS expense_items ( - expense_id TEXT NOT NULL, - item_id TEXT NOT NULL, - PRIMARY KEY (expense_id, item_id), - FOREIGN KEY (expense_id) REFERENCES expenses(id) ON DELETE CASCADE, - FOREIGN KEY (item_id) REFERENCES list_items(id) ON DELETE CASCADE -); - -CREATE INDEX IF NOT EXISTS idx_expenses_space_id ON expenses(space_id); --- +goose StatementEnd - --- +goose Down --- +goose StatementBegin -DROP INDEX IF EXISTS idx_expenses_space_id; -DROP TABLE IF EXISTS expense_items; -DROP TABLE IF EXISTS expense_tags; -DROP TABLE IF EXISTS expenses; --- +goose StatementEnd diff --git a/internal/db/migrations/00008_create_space_invitations_table.sql b/internal/db/migrations/00008_create_space_invitations_table.sql deleted file mode 100644 index 6521cb1..0000000 --- a/internal/db/migrations/00008_create_space_invitations_table.sql +++ /dev/null @@ -1,25 +0,0 @@ --- +goose Up --- +goose StatementBegin -CREATE TABLE IF NOT EXISTS space_invitations ( - token TEXT PRIMARY KEY NOT NULL, - space_id TEXT NOT NULL, - inviter_id TEXT NOT NULL, - email TEXT NOT NULL, - status TEXT NOT NULL CHECK (status IN ('pending', 'accepted', 'expired')), - expires_at TIMESTAMP NOT NULL, - created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, - updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, - FOREIGN KEY (space_id) REFERENCES spaces(id) ON DELETE CASCADE, - FOREIGN KEY (inviter_id) REFERENCES users(id) ON DELETE CASCADE -); - -CREATE INDEX IF NOT EXISTS idx_space_invitations_email ON space_invitations(email); -CREATE INDEX IF NOT EXISTS idx_space_invitations_space_id ON space_invitations(space_id); --- +goose StatementEnd - --- +goose Down --- +goose StatementBegin -DROP INDEX IF EXISTS idx_space_invitations_space_id; -DROP INDEX IF EXISTS idx_space_invitations_email; -DROP TABLE IF EXISTS space_invitations; --- +goose StatementEnd diff --git a/internal/db/migrations/00009_create_money_accounts_tables.sql b/internal/db/migrations/00009_create_money_accounts_tables.sql deleted file mode 100644 index 5912dac..0000000 --- a/internal/db/migrations/00009_create_money_accounts_tables.sql +++ /dev/null @@ -1,37 +0,0 @@ --- +goose Up --- +goose StatementBegin -CREATE TABLE IF NOT EXISTS money_accounts ( - id TEXT PRIMARY KEY NOT NULL, - space_id TEXT NOT NULL, - name TEXT NOT NULL, - created_by TEXT NOT NULL, - created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, - updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, - UNIQUE(space_id, name), - FOREIGN KEY (space_id) REFERENCES spaces(id) ON DELETE CASCADE, - FOREIGN KEY (created_by) REFERENCES users(id) ON DELETE CASCADE -); - -CREATE TABLE IF NOT EXISTS account_transfers ( - id TEXT PRIMARY KEY NOT NULL, - account_id TEXT NOT NULL, - amount_cents INTEGER NOT NULL, - direction TEXT NOT NULL CHECK (direction IN ('deposit', 'withdrawal')), - note TEXT NOT NULL DEFAULT '', - created_by TEXT NOT NULL, - created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, - FOREIGN KEY (account_id) REFERENCES money_accounts(id) ON DELETE CASCADE, - FOREIGN KEY (created_by) REFERENCES users(id) ON DELETE CASCADE -); - -CREATE INDEX IF NOT EXISTS idx_money_accounts_space_id ON money_accounts(space_id); -CREATE INDEX IF NOT EXISTS idx_account_transfers_account_id ON account_transfers(account_id); --- +goose StatementEnd - --- +goose Down --- +goose StatementBegin -DROP INDEX IF EXISTS idx_account_transfers_account_id; -DROP INDEX IF EXISTS idx_money_accounts_space_id; -DROP TABLE IF EXISTS account_transfers; -DROP TABLE IF EXISTS money_accounts; --- +goose StatementEnd diff --git a/internal/db/migrations/00010_create_payment_methods_table.sql b/internal/db/migrations/00010_create_payment_methods_table.sql deleted file mode 100644 index 9e0f015..0000000 --- a/internal/db/migrations/00010_create_payment_methods_table.sql +++ /dev/null @@ -1,23 +0,0 @@ --- +goose Up -CREATE TABLE payment_methods ( - id TEXT PRIMARY KEY NOT NULL, - space_id TEXT NOT NULL, - name TEXT NOT NULL, - type TEXT NOT NULL CHECK (type IN ('credit', 'debit')), - last_four TEXT NOT NULL, - created_by TEXT NOT NULL, - created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, - updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, - UNIQUE(space_id, name), - FOREIGN KEY (space_id) REFERENCES spaces(id) ON DELETE CASCADE, - FOREIGN KEY (created_by) REFERENCES users(id) ON DELETE CASCADE -); -ALTER TABLE expenses ADD COLUMN payment_method_id TEXT REFERENCES payment_methods(id) ON DELETE SET NULL; -CREATE INDEX idx_payment_method_space_id ON payment_methods(space_id); -CREATE INDEX idx_expenses_payment_method_id ON expenses(payment_method_id); - --- +goose Down -DROP INDEX IF EXISTS idx_expenses_payment_method_id; -DROP INDEX IF EXISTS idx_payment_method_space_id; -ALTER TABLE expenses DROP COLUMN IF EXISTS payment_method_id; -DROP TABLE IF EXISTS payment_methods; diff --git a/internal/db/migrations/00011_create_recurring_expenses_table.sql b/internal/db/migrations/00011_create_recurring_expenses_table.sql deleted file mode 100644 index 9eb5acf..0000000 --- a/internal/db/migrations/00011_create_recurring_expenses_table.sql +++ /dev/null @@ -1,44 +0,0 @@ --- +goose Up -CREATE TABLE recurring_expenses ( - id TEXT PRIMARY KEY NOT NULL, - space_id TEXT NOT NULL, - created_by TEXT NOT NULL, - description TEXT NOT NULL, - amount_cents INTEGER NOT NULL, - type TEXT NOT NULL CHECK (type IN ('expense', 'topup')), - payment_method_id TEXT, - frequency TEXT NOT NULL CHECK (frequency IN ('daily', 'weekly', 'biweekly', 'monthly', 'yearly')), - start_date DATE NOT NULL, - end_date DATE, - next_occurrence DATE NOT NULL, - is_active BOOLEAN NOT NULL DEFAULT TRUE, - created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, - updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, - FOREIGN KEY (space_id) REFERENCES spaces(id) ON DELETE CASCADE, - FOREIGN KEY (created_by) REFERENCES users(id) ON DELETE CASCADE, - FOREIGN KEY (payment_method_id) REFERENCES payment_methods(id) ON DELETE SET NULL -); - -CREATE TABLE recurring_expense_tags ( - recurring_expense_id TEXT NOT NULL, - tag_id TEXT NOT NULL, - PRIMARY KEY (recurring_expense_id, tag_id), - FOREIGN KEY (recurring_expense_id) REFERENCES recurring_expenses(id) ON DELETE CASCADE, - FOREIGN KEY (tag_id) REFERENCES tags(id) ON DELETE CASCADE -); - -ALTER TABLE expenses ADD COLUMN recurring_expense_id TEXT REFERENCES recurring_expenses(id) ON DELETE SET NULL; - -CREATE INDEX idx_recurring_expenses_space_id ON recurring_expenses(space_id); -CREATE INDEX idx_recurring_expenses_next_occurrence ON recurring_expenses(next_occurrence); -CREATE INDEX idx_recurring_expenses_active ON recurring_expenses(is_active); -CREATE INDEX idx_expenses_recurring_expense_id ON expenses(recurring_expense_id); - --- +goose Down -DROP INDEX IF EXISTS idx_expenses_recurring_expense_id; -DROP INDEX IF EXISTS idx_recurring_expenses_active; -DROP INDEX IF EXISTS idx_recurring_expenses_next_occurrence; -DROP INDEX IF EXISTS idx_recurring_expenses_space_id; -ALTER TABLE expenses DROP COLUMN IF EXISTS recurring_expense_id; -DROP TABLE IF EXISTS recurring_expense_tags; -DROP TABLE IF EXISTS recurring_expenses; diff --git a/internal/db/migrations/00012_create_budgets_table.sql b/internal/db/migrations/00012_create_budgets_table.sql deleted file mode 100644 index d14836a..0000000 --- a/internal/db/migrations/00012_create_budgets_table.sql +++ /dev/null @@ -1,24 +0,0 @@ --- +goose Up -CREATE TABLE budgets ( - id TEXT PRIMARY KEY NOT NULL, - space_id TEXT NOT NULL, - tag_id TEXT NOT NULL, - amount_cents INTEGER NOT NULL, - period TEXT NOT NULL CHECK (period IN ('weekly', 'monthly', 'yearly')), - start_date DATE NOT NULL, - end_date DATE, - is_active BOOLEAN NOT NULL DEFAULT TRUE, - created_by TEXT NOT NULL, - created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, - updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, - UNIQUE(space_id, tag_id, period), - FOREIGN KEY (space_id) REFERENCES spaces(id) ON DELETE CASCADE, - FOREIGN KEY (tag_id) REFERENCES tags(id) ON DELETE CASCADE, - FOREIGN KEY (created_by) REFERENCES users(id) ON DELETE CASCADE -); - -CREATE INDEX idx_budgets_space_id ON budgets(space_id); - --- +goose Down -DROP INDEX IF EXISTS idx_budgets_space_id; -DROP TABLE IF EXISTS budgets; diff --git a/internal/db/migrations/00013_budget_tags_table.sql b/internal/db/migrations/00013_budget_tags_table.sql deleted file mode 100644 index f2954a7..0000000 --- a/internal/db/migrations/00013_budget_tags_table.sql +++ /dev/null @@ -1,92 +0,0 @@ --- +goose Up --- Drop index before rename (SQLite keeps index names after table rename) -DROP INDEX IF EXISTS idx_budgets_space_id; - --- Rename old budgets table so we can recreate it without tag_id -ALTER TABLE budgets RENAME TO budgets_old; - --- Recreate budgets table without tag_id (SQLite can't DROP COLUMN with constraints) -CREATE TABLE budgets ( - id TEXT PRIMARY KEY NOT NULL, - space_id TEXT NOT NULL, - amount_cents INTEGER NOT NULL, - period TEXT NOT NULL CHECK (period IN ('weekly', 'monthly', 'yearly')), - start_date DATE NOT NULL, - end_date DATE, - is_active BOOLEAN NOT NULL DEFAULT TRUE, - created_by TEXT NOT NULL, - created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, - updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, - FOREIGN KEY (space_id) REFERENCES spaces(id) ON DELETE CASCADE, - FOREIGN KEY (created_by) REFERENCES users(id) ON DELETE CASCADE -); - -INSERT INTO budgets (id, space_id, amount_cents, period, start_date, end_date, is_active, created_by, created_at, updated_at) -SELECT id, space_id, amount_cents, period, start_date, end_date, is_active, created_by, created_at, updated_at FROM budgets_old; - -CREATE INDEX idx_budgets_space_id ON budgets(space_id); - --- Create budget_tags join table for many-to-many relationship -CREATE TABLE budget_tags ( - budget_id TEXT NOT NULL, - tag_id TEXT NOT NULL, - PRIMARY KEY (budget_id, tag_id), - FOREIGN KEY (budget_id) REFERENCES budgets(id) ON DELETE CASCADE, - FOREIGN KEY (tag_id) REFERENCES tags(id) ON DELETE CASCADE -); - -CREATE INDEX idx_budget_tags_tag_id ON budget_tags(tag_id); - --- Migrate existing tag_id data to the join table -INSERT INTO budget_tags (budget_id, tag_id) -SELECT id, tag_id FROM budgets_old WHERE tag_id IS NOT NULL; - --- Drop the old table (nothing references it now) -DROP TABLE budgets_old; - --- +goose Down --- Drop budget_tags first (it references budgets) -DROP INDEX IF EXISTS idx_budget_tags_tag_id; - --- Save tag mappings before dropping budget_tags -CREATE TEMP TABLE budget_tag_mappings AS -SELECT budget_id, tag_id FROM budget_tags; - -DROP TABLE budget_tags; - --- Drop index before rename (SQLite keeps index names after table rename) -DROP INDEX IF EXISTS idx_budgets_space_id; - --- Rename current budgets out of the way -ALTER TABLE budgets RENAME TO budgets_new; - --- Recreate budgets table with tag_id column -CREATE TABLE budgets ( - id TEXT PRIMARY KEY NOT NULL, - space_id TEXT NOT NULL, - tag_id TEXT NOT NULL, - amount_cents INTEGER NOT NULL, - period TEXT NOT NULL CHECK (period IN ('weekly', 'monthly', 'yearly')), - start_date DATE NOT NULL, - end_date DATE, - is_active BOOLEAN NOT NULL DEFAULT TRUE, - created_by TEXT NOT NULL, - created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, - updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, - UNIQUE(space_id, tag_id, period), - FOREIGN KEY (space_id) REFERENCES spaces(id) ON DELETE CASCADE, - FOREIGN KEY (tag_id) REFERENCES tags(id) ON DELETE CASCADE, - FOREIGN KEY (created_by) REFERENCES users(id) ON DELETE CASCADE -); - --- Copy data back, restoring first tag from saved mappings -INSERT INTO budgets (id, space_id, tag_id, amount_cents, period, start_date, end_date, is_active, created_by, created_at, updated_at) -SELECT b.id, b.space_id, - COALESCE((SELECT m.tag_id FROM budget_tag_mappings m WHERE m.budget_id = b.id LIMIT 1), ''), - b.amount_cents, b.period, b.start_date, b.end_date, b.is_active, b.created_by, b.created_at, b.updated_at -FROM budgets_new b; - -CREATE INDEX idx_budgets_space_id ON budgets(space_id); - -DROP TABLE budgets_new; -DROP TABLE budget_tag_mappings; diff --git a/internal/db/migrations/00014_create_recurring_deposits_table.sql b/internal/db/migrations/00014_create_recurring_deposits_table.sql deleted file mode 100644 index 1c20cda..0000000 --- a/internal/db/migrations/00014_create_recurring_deposits_table.sql +++ /dev/null @@ -1,31 +0,0 @@ --- +goose Up -CREATE TABLE recurring_deposits ( - id TEXT PRIMARY KEY NOT NULL, - space_id TEXT NOT NULL, - account_id TEXT NOT NULL, - amount_cents INTEGER NOT NULL, - frequency TEXT NOT NULL CHECK (frequency IN ('daily', 'weekly', 'biweekly', 'monthly', 'yearly')), - start_date DATE NOT NULL, - end_date DATE, - next_occurrence DATE NOT NULL, - is_active BOOLEAN NOT NULL DEFAULT TRUE, - title TEXT NOT NULL DEFAULT '', - created_by TEXT NOT NULL, - created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, - updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, - FOREIGN KEY (space_id) REFERENCES spaces(id) ON DELETE CASCADE, - FOREIGN KEY (account_id) REFERENCES money_accounts(id) ON DELETE CASCADE, - FOREIGN KEY (created_by) REFERENCES users(id) ON DELETE CASCADE -); - -CREATE INDEX idx_recurring_deposits_space_id ON recurring_deposits(space_id); -CREATE INDEX idx_recurring_deposits_account_id ON recurring_deposits(account_id); -CREATE INDEX idx_recurring_deposits_next_occurrence ON recurring_deposits(next_occurrence); -CREATE INDEX idx_recurring_deposits_active ON recurring_deposits(is_active); - -ALTER TABLE account_transfers ADD COLUMN recurring_deposit_id TEXT - REFERENCES recurring_deposits(id) ON DELETE SET NULL; - --- +goose Down -ALTER TABLE account_transfers DROP COLUMN IF EXISTS recurring_deposit_id; -DROP TABLE IF EXISTS recurring_deposits; diff --git a/internal/db/migrations/00015_add_timezone_to_profiles.sql b/internal/db/migrations/00015_add_timezone_to_profiles.sql deleted file mode 100644 index e4f6e8c..0000000 --- a/internal/db/migrations/00015_add_timezone_to_profiles.sql +++ /dev/null @@ -1,5 +0,0 @@ --- +goose Up -ALTER TABLE profiles ADD COLUMN timezone TEXT; - --- +goose Down -ALTER TABLE profiles DROP COLUMN IF EXISTS timezone; diff --git a/internal/db/migrations/00016_add_timezone_to_spaces.sql b/internal/db/migrations/00016_add_timezone_to_spaces.sql deleted file mode 100644 index 584bf53..0000000 --- a/internal/db/migrations/00016_add_timezone_to_spaces.sql +++ /dev/null @@ -1,5 +0,0 @@ --- +goose Up -ALTER TABLE spaces ADD COLUMN timezone TEXT; - --- +goose Down -ALTER TABLE spaces DROP COLUMN IF EXISTS timezone; diff --git a/internal/db/migrations/00017_create_loans_and_receipts_tables.sql b/internal/db/migrations/00017_create_loans_and_receipts_tables.sql deleted file mode 100644 index 7f045e8..0000000 --- a/internal/db/migrations/00017_create_loans_and_receipts_tables.sql +++ /dev/null @@ -1,110 +0,0 @@ --- +goose Up - -CREATE TABLE loans ( - id TEXT PRIMARY KEY NOT NULL, - space_id TEXT NOT NULL, - name TEXT NOT NULL, - description TEXT NOT NULL DEFAULT '', - original_amount_cents INTEGER NOT NULL, - interest_rate_bps INTEGER NOT NULL DEFAULT 0, - start_date DATE NOT NULL, - end_date DATE, - is_paid_off BOOLEAN NOT NULL DEFAULT FALSE, - created_by TEXT NOT NULL, - created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, - updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, - FOREIGN KEY (space_id) REFERENCES spaces(id) ON DELETE CASCADE, - FOREIGN KEY (created_by) REFERENCES users(id) ON DELETE CASCADE -); - -CREATE INDEX idx_loans_space_id ON loans(space_id); - -CREATE TABLE recurring_receipts ( - id TEXT PRIMARY KEY NOT NULL, - loan_id TEXT NOT NULL, - space_id TEXT NOT NULL, - description TEXT NOT NULL DEFAULT '', - total_amount_cents INTEGER NOT NULL, - frequency TEXT NOT NULL CHECK (frequency IN ('daily', 'weekly', 'biweekly', 'monthly', 'yearly')), - start_date DATE NOT NULL, - end_date DATE, - next_occurrence DATE NOT NULL, - is_active BOOLEAN NOT NULL DEFAULT TRUE, - created_by TEXT NOT NULL, - created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, - updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, - FOREIGN KEY (loan_id) REFERENCES loans(id) ON DELETE CASCADE, - FOREIGN KEY (space_id) REFERENCES spaces(id) ON DELETE CASCADE, - FOREIGN KEY (created_by) REFERENCES users(id) ON DELETE CASCADE -); - -CREATE INDEX idx_recurring_receipts_space_id ON recurring_receipts(space_id); -CREATE INDEX idx_recurring_receipts_loan_id ON recurring_receipts(loan_id); -CREATE INDEX idx_recurring_receipts_next_occurrence ON recurring_receipts(next_occurrence); -CREATE INDEX idx_recurring_receipts_active ON recurring_receipts(is_active); - -CREATE TABLE recurring_receipt_sources ( - id TEXT PRIMARY KEY NOT NULL, - recurring_receipt_id TEXT NOT NULL, - source_type TEXT NOT NULL CHECK (source_type IN ('balance', 'account')), - account_id TEXT, - amount_cents INTEGER NOT NULL, - FOREIGN KEY (recurring_receipt_id) REFERENCES recurring_receipts(id) ON DELETE CASCADE, - FOREIGN KEY (account_id) REFERENCES money_accounts(id) ON DELETE SET NULL -); - -CREATE INDEX idx_recurring_receipt_sources_recurring_receipt_id ON recurring_receipt_sources(recurring_receipt_id); - -CREATE TABLE receipts ( - id TEXT PRIMARY KEY NOT NULL, - loan_id TEXT NOT NULL, - space_id TEXT NOT NULL, - description TEXT NOT NULL DEFAULT '', - total_amount_cents INTEGER NOT NULL, - date DATE NOT NULL, - recurring_receipt_id TEXT, - created_by TEXT NOT NULL, - created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, - updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, - FOREIGN KEY (loan_id) REFERENCES loans(id) ON DELETE CASCADE, - FOREIGN KEY (space_id) REFERENCES spaces(id) ON DELETE CASCADE, - FOREIGN KEY (recurring_receipt_id) REFERENCES recurring_receipts(id) ON DELETE SET NULL, - FOREIGN KEY (created_by) REFERENCES users(id) ON DELETE CASCADE -); - -CREATE INDEX idx_receipts_loan_id ON receipts(loan_id); -CREATE INDEX idx_receipts_space_id ON receipts(space_id); -CREATE INDEX idx_receipts_recurring_receipt_id ON receipts(recurring_receipt_id); - -CREATE TABLE receipt_funding_sources ( - id TEXT PRIMARY KEY NOT NULL, - receipt_id TEXT NOT NULL, - source_type TEXT NOT NULL CHECK (source_type IN ('balance', 'account')), - account_id TEXT, - amount_cents INTEGER NOT NULL, - linked_expense_id TEXT, - linked_transfer_id TEXT, - FOREIGN KEY (receipt_id) REFERENCES receipts(id) ON DELETE CASCADE, - FOREIGN KEY (account_id) REFERENCES money_accounts(id) ON DELETE SET NULL, - FOREIGN KEY (linked_expense_id) REFERENCES expenses(id) ON DELETE SET NULL, - FOREIGN KEY (linked_transfer_id) REFERENCES account_transfers(id) ON DELETE SET NULL -); - -CREATE INDEX idx_receipt_funding_sources_receipt_id ON receipt_funding_sources(receipt_id); - --- +goose Down -DROP INDEX IF EXISTS idx_receipt_funding_sources_receipt_id; -DROP INDEX IF EXISTS idx_receipts_recurring_receipt_id; -DROP INDEX IF EXISTS idx_receipts_space_id; -DROP INDEX IF EXISTS idx_receipts_loan_id; -DROP INDEX IF EXISTS idx_recurring_receipt_sources_recurring_receipt_id; -DROP INDEX IF EXISTS idx_recurring_receipts_active; -DROP INDEX IF EXISTS idx_recurring_receipts_next_occurrence; -DROP INDEX IF EXISTS idx_recurring_receipts_loan_id; -DROP INDEX IF EXISTS idx_recurring_receipts_space_id; -DROP INDEX IF EXISTS idx_loans_space_id; -DROP TABLE IF EXISTS receipt_funding_sources; -DROP TABLE IF EXISTS receipts; -DROP TABLE IF EXISTS recurring_receipt_sources; -DROP TABLE IF EXISTS recurring_receipts; -DROP TABLE IF EXISTS loans; diff --git a/internal/db/migrations/00018_add_decimal_amount_columns.sql b/internal/db/migrations/00018_add_decimal_amount_columns.sql deleted file mode 100644 index bad2b44..0000000 --- a/internal/db/migrations/00018_add_decimal_amount_columns.sql +++ /dev/null @@ -1,54 +0,0 @@ --- +goose Up - --- expenses -ALTER TABLE expenses ADD COLUMN amount TEXT NOT NULL DEFAULT '0'; -UPDATE expenses SET amount = CAST(amount_cents / 100 AS TEXT) || '.' || SUBSTR('00' || CAST(ABS(amount_cents) % 100 AS TEXT), -2, 2); - --- account_transfers -ALTER TABLE account_transfers ADD COLUMN amount TEXT NOT NULL DEFAULT '0'; -UPDATE account_transfers SET amount = CAST(amount_cents / 100 AS TEXT) || '.' || SUBSTR('00' || CAST(ABS(amount_cents) % 100 AS TEXT), -2, 2); - --- recurring_expenses -ALTER TABLE recurring_expenses ADD COLUMN amount TEXT NOT NULL DEFAULT '0'; -UPDATE recurring_expenses SET amount = CAST(amount_cents / 100 AS TEXT) || '.' || SUBSTR('00' || CAST(ABS(amount_cents) % 100 AS TEXT), -2, 2); - --- budgets -ALTER TABLE budgets ADD COLUMN amount TEXT NOT NULL DEFAULT '0'; -UPDATE budgets SET amount = CAST(amount_cents / 100 AS TEXT) || '.' || SUBSTR('00' || CAST(ABS(amount_cents) % 100 AS TEXT), -2, 2); - --- recurring_deposits -ALTER TABLE recurring_deposits ADD COLUMN amount TEXT NOT NULL DEFAULT '0'; -UPDATE recurring_deposits SET amount = CAST(amount_cents / 100 AS TEXT) || '.' || SUBSTR('00' || CAST(ABS(amount_cents) % 100 AS TEXT), -2, 2); - --- loans -ALTER TABLE loans ADD COLUMN original_amount TEXT NOT NULL DEFAULT '0'; -UPDATE loans SET original_amount = CAST(original_amount_cents / 100 AS TEXT) || '.' || SUBSTR('00' || CAST(ABS(original_amount_cents) % 100 AS TEXT), -2, 2); - --- recurring_receipts -ALTER TABLE recurring_receipts ADD COLUMN total_amount TEXT NOT NULL DEFAULT '0'; -UPDATE recurring_receipts SET total_amount = CAST(total_amount_cents / 100 AS TEXT) || '.' || SUBSTR('00' || CAST(ABS(total_amount_cents) % 100 AS TEXT), -2, 2); - --- recurring_receipt_sources -ALTER TABLE recurring_receipt_sources ADD COLUMN amount TEXT NOT NULL DEFAULT '0'; -UPDATE recurring_receipt_sources SET amount = CAST(amount_cents / 100 AS TEXT) || '.' || SUBSTR('00' || CAST(ABS(amount_cents) % 100 AS TEXT), -2, 2); - --- receipts -ALTER TABLE receipts ADD COLUMN total_amount TEXT NOT NULL DEFAULT '0'; -UPDATE receipts SET total_amount = CAST(total_amount_cents / 100 AS TEXT) || '.' || SUBSTR('00' || CAST(ABS(total_amount_cents) % 100 AS TEXT), -2, 2); - --- receipt_funding_sources -ALTER TABLE receipt_funding_sources ADD COLUMN amount TEXT NOT NULL DEFAULT '0'; -UPDATE receipt_funding_sources SET amount = CAST(amount_cents / 100 AS TEXT) || '.' || SUBSTR('00' || CAST(ABS(amount_cents) % 100 AS TEXT), -2, 2); - --- +goose Down --- SQLite does not support DROP COLUMN in older versions, but modernc.org/sqlite supports it. -ALTER TABLE expenses DROP COLUMN amount; -ALTER TABLE account_transfers DROP COLUMN amount; -ALTER TABLE recurring_expenses DROP COLUMN amount; -ALTER TABLE budgets DROP COLUMN amount; -ALTER TABLE recurring_deposits DROP COLUMN amount; -ALTER TABLE loans DROP COLUMN original_amount; -ALTER TABLE recurring_receipts DROP COLUMN total_amount; -ALTER TABLE recurring_receipt_sources DROP COLUMN amount; -ALTER TABLE receipts DROP COLUMN total_amount; -ALTER TABLE receipt_funding_sources DROP COLUMN amount; diff --git a/internal/db/migrations/00019_fix_decimal_amount_values.sql b/internal/db/migrations/00019_fix_decimal_amount_values.sql deleted file mode 100644 index 69ab1c4..0000000 --- a/internal/db/migrations/00019_fix_decimal_amount_values.sql +++ /dev/null @@ -1,97 +0,0 @@ --- +goose Up --- Fix amount column values that were incorrectly converted from amount_cents --- in migration 00018. The SUBSTR(..., -2, 2) approach works in SQLite but --- fails in PostgreSQL where negative offsets mean "before string start". - --- expenses -UPDATE expenses SET amount = - CASE WHEN amount_cents < 0 THEN '-' ELSE '' END || - CAST(ABS(amount_cents) / 100 AS TEXT) || '.' || - CASE WHEN ABS(amount_cents) % 100 < 10 - THEN '0' || CAST(ABS(amount_cents) % 100 AS TEXT) - ELSE CAST(ABS(amount_cents) % 100 AS TEXT) - END; - --- account_transfers -UPDATE account_transfers SET amount = - CASE WHEN amount_cents < 0 THEN '-' ELSE '' END || - CAST(ABS(amount_cents) / 100 AS TEXT) || '.' || - CASE WHEN ABS(amount_cents) % 100 < 10 - THEN '0' || CAST(ABS(amount_cents) % 100 AS TEXT) - ELSE CAST(ABS(amount_cents) % 100 AS TEXT) - END; - --- recurring_expenses -UPDATE recurring_expenses SET amount = - CASE WHEN amount_cents < 0 THEN '-' ELSE '' END || - CAST(ABS(amount_cents) / 100 AS TEXT) || '.' || - CASE WHEN ABS(amount_cents) % 100 < 10 - THEN '0' || CAST(ABS(amount_cents) % 100 AS TEXT) - ELSE CAST(ABS(amount_cents) % 100 AS TEXT) - END; - --- budgets -UPDATE budgets SET amount = - CASE WHEN amount_cents < 0 THEN '-' ELSE '' END || - CAST(ABS(amount_cents) / 100 AS TEXT) || '.' || - CASE WHEN ABS(amount_cents) % 100 < 10 - THEN '0' || CAST(ABS(amount_cents) % 100 AS TEXT) - ELSE CAST(ABS(amount_cents) % 100 AS TEXT) - END; - --- recurring_deposits -UPDATE recurring_deposits SET amount = - CASE WHEN amount_cents < 0 THEN '-' ELSE '' END || - CAST(ABS(amount_cents) / 100 AS TEXT) || '.' || - CASE WHEN ABS(amount_cents) % 100 < 10 - THEN '0' || CAST(ABS(amount_cents) % 100 AS TEXT) - ELSE CAST(ABS(amount_cents) % 100 AS TEXT) - END; - --- loans -UPDATE loans SET original_amount = - CASE WHEN original_amount_cents < 0 THEN '-' ELSE '' END || - CAST(ABS(original_amount_cents) / 100 AS TEXT) || '.' || - CASE WHEN ABS(original_amount_cents) % 100 < 10 - THEN '0' || CAST(ABS(original_amount_cents) % 100 AS TEXT) - ELSE CAST(ABS(original_amount_cents) % 100 AS TEXT) - END; - --- recurring_receipts -UPDATE recurring_receipts SET total_amount = - CASE WHEN total_amount_cents < 0 THEN '-' ELSE '' END || - CAST(ABS(total_amount_cents) / 100 AS TEXT) || '.' || - CASE WHEN ABS(total_amount_cents) % 100 < 10 - THEN '0' || CAST(ABS(total_amount_cents) % 100 AS TEXT) - ELSE CAST(ABS(total_amount_cents) % 100 AS TEXT) - END; - --- recurring_receipt_sources -UPDATE recurring_receipt_sources SET amount = - CASE WHEN amount_cents < 0 THEN '-' ELSE '' END || - CAST(ABS(amount_cents) / 100 AS TEXT) || '.' || - CASE WHEN ABS(amount_cents) % 100 < 10 - THEN '0' || CAST(ABS(amount_cents) % 100 AS TEXT) - ELSE CAST(ABS(amount_cents) % 100 AS TEXT) - END; - --- receipts -UPDATE receipts SET total_amount = - CASE WHEN total_amount_cents < 0 THEN '-' ELSE '' END || - CAST(ABS(total_amount_cents) / 100 AS TEXT) || '.' || - CASE WHEN ABS(total_amount_cents) % 100 < 10 - THEN '0' || CAST(ABS(total_amount_cents) % 100 AS TEXT) - ELSE CAST(ABS(total_amount_cents) % 100 AS TEXT) - END; - --- receipt_funding_sources -UPDATE receipt_funding_sources SET amount = - CASE WHEN amount_cents < 0 THEN '-' ELSE '' END || - CAST(ABS(amount_cents) / 100 AS TEXT) || '.' || - CASE WHEN ABS(amount_cents) % 100 < 10 - THEN '0' || CAST(ABS(amount_cents) % 100 AS TEXT) - ELSE CAST(ABS(amount_cents) % 100 AS TEXT) - END; - --- +goose Down --- No-op: this migration fixes corrupted data from migration 00018.