-
Notifications
You must be signed in to change notification settings - Fork 151
Expand file tree
/
Copy pathschema.sql
More file actions
147 lines (130 loc) · 4.96 KB
/
schema.sql
File metadata and controls
147 lines (130 loc) · 4.96 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
-- 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 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()
);
CREATE TABLE IF NOT EXISTS webhook_subscriptions (
id SERIAL PRIMARY KEY,
user_id INT NOT NULL REFERENCES users(id) ON DELETE CASCADE,
target_url VARCHAR(500) NOT NULL,
secret_key VARCHAR(100) NOT NULL,
event_types JSON NOT NULL,
active BOOLEAN NOT NULL DEFAULT TRUE,
created_at TIMESTAMP NOT NULL DEFAULT NOW()
);
CREATE TABLE IF NOT EXISTS webhook_delivery_logs (
id SERIAL PRIMARY KEY,
subscription_id INT NOT NULL REFERENCES webhook_subscriptions(id) ON DELETE CASCADE,
event_type VARCHAR(100) NOT NULL,
payload JSON NOT NULL,
response_status INT,
response_body TEXT,
success BOOLEAN NOT NULL DEFAULT FALSE,
attempt_count INT NOT NULL DEFAULT 1,
created_at TIMESTAMP NOT NULL DEFAULT NOW()
);