forked from rohitdash08/FinMind
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathschema.sql
More file actions
150 lines (133 loc) · 5.03 KB
/
schema.sql
File metadata and controls
150 lines (133 loc) · 5.03 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
-- PostgreSQL schema for FinMind
CREATE TABLE IF NOT EXISTS users (
id SERIAL PRIMARY KEY,
email VARCHAR(255) UNIQUE NOT NULL,
password_hash VARCHAR(255) NOT NULL,
preferred_currency VARCHAR(10) NOT NULL DEFAULT 'INR',
role VARCHAR(20) NOT NULL DEFAULT 'USER',
created_at TIMESTAMP NOT NULL DEFAULT NOW()
);
ALTER TABLE users
ADD COLUMN IF NOT EXISTS preferred_currency VARCHAR(10) NOT NULL DEFAULT 'INR';
CREATE TABLE IF NOT EXISTS categories (
id SERIAL PRIMARY KEY,
user_id INT NOT NULL REFERENCES users(id) ON DELETE CASCADE,
name VARCHAR(100) NOT NULL,
created_at TIMESTAMP NOT NULL DEFAULT NOW()
);
CREATE TABLE IF NOT EXISTS expenses (
id SERIAL PRIMARY KEY,
user_id INT NOT NULL REFERENCES users(id) ON DELETE CASCADE,
category_id INT REFERENCES categories(id) ON DELETE SET NULL,
amount NUMERIC(12,2) NOT NULL,
currency VARCHAR(10) NOT NULL DEFAULT 'INR',
expense_type VARCHAR(20) NOT NULL DEFAULT 'EXPENSE',
notes VARCHAR(500),
spent_at DATE NOT NULL DEFAULT CURRENT_DATE,
created_at TIMESTAMP NOT NULL DEFAULT NOW()
);
CREATE INDEX IF NOT EXISTS idx_expenses_user_spent_at ON expenses(user_id, spent_at DESC);
ALTER TABLE expenses
ADD COLUMN IF NOT EXISTS expense_type VARCHAR(20) NOT NULL DEFAULT 'EXPENSE';
DO $$ BEGIN
CREATE TYPE recurring_cadence AS ENUM ('DAILY','WEEKLY','MONTHLY','YEARLY');
EXCEPTION
WHEN duplicate_object THEN NULL;
END $$;
CREATE TABLE IF NOT EXISTS recurring_expenses (
id SERIAL PRIMARY KEY,
user_id INT NOT NULL REFERENCES users(id) ON DELETE CASCADE,
category_id INT REFERENCES categories(id) ON DELETE SET NULL,
amount NUMERIC(12,2) NOT NULL,
currency VARCHAR(10) NOT NULL DEFAULT 'INR',
expense_type VARCHAR(20) NOT NULL DEFAULT 'EXPENSE',
notes VARCHAR(500) NOT NULL,
cadence recurring_cadence NOT NULL,
start_date DATE NOT NULL,
end_date DATE,
active BOOLEAN NOT NULL DEFAULT TRUE,
created_at TIMESTAMP NOT NULL DEFAULT NOW()
);
CREATE INDEX IF NOT EXISTS idx_recurring_expenses_user_start ON recurring_expenses(user_id, start_date);
ALTER TABLE expenses
ADD COLUMN IF NOT EXISTS source_recurring_id INT REFERENCES recurring_expenses(id) ON DELETE SET NULL;
DO $$ BEGIN
CREATE TYPE bill_cadence AS ENUM ('MONTHLY','WEEKLY','YEARLY','ONCE');
EXCEPTION
WHEN duplicate_object THEN NULL;
END $$;
CREATE TABLE IF NOT EXISTS bills (
id SERIAL PRIMARY KEY,
user_id INT NOT NULL REFERENCES users(id) ON DELETE CASCADE,
name VARCHAR(200) NOT NULL,
amount NUMERIC(12,2) NOT NULL,
currency VARCHAR(10) NOT NULL DEFAULT 'INR',
next_due_date DATE NOT NULL,
cadence bill_cadence NOT NULL,
autopay_enabled BOOLEAN NOT NULL DEFAULT FALSE,
channel_whatsapp BOOLEAN NOT NULL DEFAULT FALSE,
channel_email BOOLEAN NOT NULL DEFAULT TRUE,
active BOOLEAN NOT NULL DEFAULT TRUE,
created_at TIMESTAMP NOT NULL DEFAULT NOW()
);
CREATE INDEX IF NOT EXISTS idx_bills_user_due ON bills(user_id, next_due_date);
ALTER TABLE bills
ADD COLUMN IF NOT EXISTS autopay_enabled BOOLEAN NOT NULL DEFAULT FALSE;
CREATE TABLE IF NOT EXISTS reminders (
id SERIAL PRIMARY KEY,
user_id INT NOT NULL REFERENCES users(id) ON DELETE CASCADE,
bill_id INT REFERENCES bills(id) ON DELETE SET NULL,
message VARCHAR(500) NOT NULL,
send_at TIMESTAMP NOT NULL,
sent BOOLEAN NOT NULL DEFAULT FALSE,
channel VARCHAR(20) NOT NULL DEFAULT 'email'
);
CREATE INDEX IF NOT EXISTS idx_reminders_due ON reminders(user_id, sent, send_at);
CREATE TABLE IF NOT EXISTS ad_impressions (
id SERIAL PRIMARY KEY,
user_id INT REFERENCES users(id) ON DELETE SET NULL,
placement VARCHAR(100) NOT NULL,
created_at TIMESTAMP NOT NULL DEFAULT NOW()
);
CREATE TABLE IF NOT EXISTS subscription_plans (
id SERIAL PRIMARY KEY,
name VARCHAR(50) NOT NULL,
price_cents INT NOT NULL,
interval VARCHAR(20) NOT NULL DEFAULT 'monthly'
);
CREATE TABLE IF NOT EXISTS user_subscriptions (
id SERIAL PRIMARY KEY,
user_id INT NOT NULL REFERENCES users(id) ON DELETE CASCADE,
plan_id INT NOT NULL REFERENCES subscription_plans(id) ON DELETE RESTRICT,
active BOOLEAN NOT NULL DEFAULT FALSE,
started_at TIMESTAMP NOT NULL DEFAULT NOW()
);
CREATE TABLE IF NOT EXISTS background_jobs (
id SERIAL PRIMARY KEY,
name VARCHAR(200) NOT NULL,
status VARCHAR(20) NOT NULL DEFAULT 'PENDING',
attempts INT NOT NULL DEFAULT 0,
max_retries INT NOT NULL DEFAULT 3,
last_error TEXT,
result TEXT,
created_at TIMESTAMP NOT NULL DEFAULT NOW(),
started_at TIMESTAMP,
completed_at TIMESTAMP,
next_retry_at TIMESTAMP
);
CREATE INDEX IF NOT EXISTS idx_background_jobs_status ON background_jobs(status);
CREATE TABLE IF NOT EXISTS job_history (
id SERIAL PRIMARY KEY,
job_id INT NOT NULL REFERENCES background_jobs(id) ON DELETE CASCADE,
attempt INT NOT NULL,
status VARCHAR(20) NOT NULL,
error TEXT,
created_at TIMESTAMP NOT NULL DEFAULT NOW()
);
CREATE INDEX IF NOT EXISTS idx_job_history_job ON job_history(job_id, attempt);
CREATE TABLE IF NOT EXISTS audit_logs (
id SERIAL PRIMARY KEY,
user_id INT REFERENCES users(id) ON DELETE SET NULL,
action VARCHAR(100) NOT NULL,
created_at TIMESTAMP NOT NULL DEFAULT NOW()
);