-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathschema.sql
More file actions
213 lines (197 loc) · 7.74 KB
/
schema.sql
File metadata and controls
213 lines (197 loc) · 7.74 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
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
// 📊 Cloudflare D1 Database Schema
-- Solo-Spark Innovation Platform Database Schema
-- Users table
CREATE TABLE IF NOT EXISTS users (
id TEXT PRIMARY KEY,
email TEXT UNIQUE NOT NULL,
name TEXT NOT NULL,
avatar_url TEXT,
subscription TEXT DEFAULT 'free' CHECK (subscription IN ('free', 'solo-prototype', 'solo-ultimate')),
language TEXT DEFAULT 'ar' CHECK (language IN ('en', 'ar')),
theme TEXT DEFAULT 'light' CHECK (theme IN ('light', 'dark')),
notifications_enabled BOOLEAN DEFAULT true,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP,
last_login DATETIME DEFAULT CURRENT_TIMESTAMP
);
-- Projects table
CREATE TABLE IF NOT EXISTS projects (
id TEXT PRIMARY KEY,
user_id TEXT NOT NULL,
title TEXT NOT NULL,
description TEXT,
stage TEXT DEFAULT 'idea' CHECK (stage IN ('idea', 'story', 'prd', 'prototype')),
content TEXT, -- JSON content for each stage
tags TEXT, -- JSON array of tags
is_public BOOLEAN DEFAULT false,
github_repo TEXT,
export_urls TEXT, -- JSON object with export URLs
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (user_id) REFERENCES users (id) ON DELETE CASCADE
);
-- Project collaborators
CREATE TABLE IF NOT EXISTS project_collaborators (
id INTEGER PRIMARY KEY AUTOINCREMENT,
project_id TEXT NOT NULL,
user_id TEXT NOT NULL,
role TEXT DEFAULT 'collaborator' CHECK (role IN ('owner', 'collaborator', 'viewer')),
invited_at DATETIME DEFAULT CURRENT_TIMESTAMP,
accepted_at DATETIME,
FOREIGN KEY (project_id) REFERENCES projects (id) ON DELETE CASCADE,
FOREIGN KEY (user_id) REFERENCES users (id) ON DELETE CASCADE,
UNIQUE(project_id, user_id)
);
-- Sessions table (for authentication)
CREATE TABLE IF NOT EXISTS sessions (
id TEXT PRIMARY KEY,
user_id TEXT NOT NULL,
token TEXT UNIQUE NOT NULL,
expires_at DATETIME NOT NULL,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (user_id) REFERENCES users (id) ON DELETE CASCADE
);
-- Analytics events
CREATE TABLE IF NOT EXISTS analytics_events (
id INTEGER PRIMARY KEY AUTOINCREMENT,
user_id TEXT,
project_id TEXT,
event_type TEXT NOT NULL,
event_data TEXT, -- JSON data
ip_address TEXT,
user_agent TEXT,
country TEXT,
city TEXT,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (user_id) REFERENCES users (id) ON DELETE SET NULL,
FOREIGN KEY (project_id) REFERENCES projects (id) ON DELETE SET NULL
);
-- User subscriptions
CREATE TABLE IF NOT EXISTS subscriptions (
id INTEGER PRIMARY KEY AUTOINCREMENT,
user_id TEXT NOT NULL,
plan TEXT NOT NULL,
status TEXT DEFAULT 'active' CHECK (status IN ('active', 'cancelled', 'expired', 'paused')),
stripe_subscription_id TEXT,
current_period_start DATETIME,
current_period_end DATETIME,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (user_id) REFERENCES users (id) ON DELETE CASCADE
);
-- Payment history
CREATE TABLE IF NOT EXISTS payments (
id INTEGER PRIMARY KEY AUTOINCREMENT,
user_id TEXT NOT NULL,
subscription_id INTEGER,
amount INTEGER NOT NULL, -- Amount in halalas (SAR * 100)
currency TEXT DEFAULT 'SAR',
payment_method TEXT, -- stripe, stc_pay, mada
stripe_payment_intent_id TEXT,
status TEXT DEFAULT 'pending' CHECK (status IN ('pending', 'succeeded', 'failed', 'refunded')),
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (user_id) REFERENCES users (id) ON DELETE CASCADE,
FOREIGN KEY (subscription_id) REFERENCES subscriptions (id) ON DELETE SET NULL
);
-- AI usage tracking
CREATE TABLE IF NOT EXISTS ai_usage (
id INTEGER PRIMARY KEY AUTOINCREMENT,
user_id TEXT NOT NULL,
project_id TEXT,
model TEXT NOT NULL,
tokens_used INTEGER NOT NULL,
operation TEXT NOT NULL, -- idea_generation, story_creation, prd_writing, etc.
cost_usd DECIMAL(10, 6),
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (user_id) REFERENCES users (id) ON DELETE CASCADE,
FOREIGN KEY (project_id) REFERENCES projects (id) ON DELETE SET NULL
);
-- Feature usage analytics
CREATE TABLE IF NOT EXISTS feature_usage (
id INTEGER PRIMARY KEY AUTOINCREMENT,
user_id TEXT,
feature_name TEXT NOT NULL,
usage_count INTEGER DEFAULT 1,
last_used DATETIME DEFAULT CURRENT_TIMESTAMP,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (user_id) REFERENCES users (id) ON DELETE SET NULL,
UNIQUE(user_id, feature_name) ON CONFLICT REPLACE
);
-- GitHub integrations
CREATE TABLE IF NOT EXISTS github_integrations (
id INTEGER PRIMARY KEY AUTOINCREMENT,
user_id TEXT NOT NULL,
project_id TEXT NOT NULL,
repo_name TEXT NOT NULL,
repo_url TEXT NOT NULL,
submission_status TEXT DEFAULT 'pending' CHECK (submission_status IN ('pending', 'submitted', 'reviewed', 'approved', 'rejected')),
reviewer_feedback TEXT,
submitted_at DATETIME DEFAULT CURRENT_TIMESTAMP,
reviewed_at DATETIME,
FOREIGN KEY (user_id) REFERENCES users (id) ON DELETE CASCADE,
FOREIGN KEY (project_id) REFERENCES projects (id) ON DELETE CASCADE
);
-- System notifications
CREATE TABLE IF NOT EXISTS notifications (
id INTEGER PRIMARY KEY AUTOINCREMENT,
user_id TEXT NOT NULL,
type TEXT NOT NULL, -- achievement, system, reminder, payment
title TEXT NOT NULL,
message TEXT NOT NULL,
action_url TEXT,
read_at DATETIME,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (user_id) REFERENCES users (id) ON DELETE CASCADE
);
-- User achievements and gamification
CREATE TABLE IF NOT EXISTS achievements (
id INTEGER PRIMARY KEY AUTOINCREMENT,
user_id TEXT NOT NULL,
achievement_type TEXT NOT NULL,
achievement_data TEXT, -- JSON data
earned_at DATETIME DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (user_id) REFERENCES users (id) ON DELETE CASCADE
);
-- Indexes for performance
CREATE INDEX IF NOT EXISTS idx_projects_user_id ON projects (user_id);
CREATE INDEX IF NOT EXISTS idx_projects_stage ON projects (stage);
CREATE INDEX IF NOT EXISTS idx_projects_created_at ON projects (created_at);
CREATE INDEX IF NOT EXISTS idx_sessions_token ON sessions (token);
CREATE INDEX IF NOT EXISTS idx_sessions_expires_at ON sessions (expires_at);
CREATE INDEX IF NOT EXISTS idx_analytics_events_user_id ON analytics_events (user_id);
CREATE INDEX IF NOT EXISTS idx_analytics_events_created_at ON analytics_events (created_at);
CREATE INDEX IF NOT EXISTS idx_payments_user_id ON payments (user_id);
CREATE INDEX IF NOT EXISTS idx_ai_usage_user_id ON ai_usage (user_id);
CREATE INDEX IF NOT EXISTS idx_feature_usage_user_id ON feature_usage (user_id);
CREATE INDEX IF NOT EXISTS idx_notifications_user_id ON notifications (user_id);
CREATE INDEX IF NOT EXISTS idx_achievements_user_id ON achievements (user_id);
-- Sample data for testing
INSERT OR IGNORE INTO users (id, email, name, subscription, language) VALUES
('test-user-1', 'test@brainsait.io', 'مستخدم تجريبي', 'solo-prototype', 'ar');
-- Views for common queries
CREATE VIEW IF NOT EXISTS user_projects_summary AS
SELECT
u.id as user_id,
u.name as user_name,
u.email,
COUNT(p.id) as total_projects,
COUNT(CASE WHEN p.stage = 'idea' THEN 1 END) as idea_projects,
COUNT(CASE WHEN p.stage = 'story' THEN 1 END) as story_projects,
COUNT(CASE WHEN p.stage = 'prd' THEN 1 END) as prd_projects,
COUNT(CASE WHEN p.stage = 'prototype' THEN 1 END) as prototype_projects,
MAX(p.updated_at) as last_project_update
FROM users u
LEFT JOIN projects p ON u.id = p.user_id
GROUP BY u.id, u.name, u.email;
CREATE VIEW IF NOT EXISTS project_analytics AS
SELECT
p.id as project_id,
p.title,
p.stage,
p.user_id,
COUNT(ae.id) as total_events,
COUNT(DISTINCT ae.user_id) as unique_users,
MAX(ae.created_at) as last_activity
FROM projects p
LEFT JOIN analytics_events ae ON p.id = ae.project_id
GROUP BY p.id, p.title, p.stage, p.user_id;