-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathsupabase-schema.sql
More file actions
217 lines (189 loc) · 5.94 KB
/
supabase-schema.sql
File metadata and controls
217 lines (189 loc) · 5.94 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
214
215
216
217
-- Volcano Nightclub Database Schema for Supabase
-- Run this SQL in the Supabase SQL Editor
-- Enable UUID extension
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
-- Profiles table (extends Supabase Auth)
CREATE TABLE IF NOT EXISTS profiles (
id UUID PRIMARY KEY REFERENCES auth.users(id) ON DELETE CASCADE,
full_name TEXT,
phone TEXT,
role TEXT DEFAULT 'customer' CHECK (role IN ('customer', 'employee', 'admin')),
created_at TIMESTAMPTZ DEFAULT NOW()
);
-- Events table
CREATE TABLE IF NOT EXISTS events (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
title TEXT NOT NULL,
description TEXT,
date TIMESTAMPTZ NOT NULL,
image_url TEXT,
is_active BOOLEAN DEFAULT true,
created_at TIMESTAMPTZ DEFAULT NOW()
);
-- Ticket types table
CREATE TABLE IF NOT EXISTS ticket_types (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
event_id UUID REFERENCES events(id) ON DELETE CASCADE,
name TEXT NOT NULL,
price DECIMAL(10,2) NOT NULL,
description TEXT,
perks TEXT[] DEFAULT '{}',
quantity_available INTEGER NOT NULL,
quantity_sold INTEGER DEFAULT 0,
stripe_price_id TEXT
);
-- Tickets table
CREATE TABLE IF NOT EXISTS tickets (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
user_id UUID REFERENCES profiles(id),
ticket_type_id UUID REFERENCES ticket_types(id),
event_id UUID REFERENCES events(id),
qr_code TEXT UNIQUE NOT NULL,
status TEXT DEFAULT 'valid' CHECK (status IN ('valid', 'used', 'cancelled', 'expired')),
purchase_date TIMESTAMPTZ DEFAULT NOW(),
validated_at TIMESTAMPTZ,
validated_by UUID REFERENCES profiles(id),
stripe_payment_id TEXT,
price_paid DECIMAL(10,2)
);
-- Orders table
CREATE TABLE IF NOT EXISTS orders (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
user_id UUID REFERENCES profiles(id),
stripe_session_id TEXT,
stripe_payment_intent TEXT,
total DECIMAL(10,2) NOT NULL,
status TEXT DEFAULT 'pending' CHECK (status IN ('pending', 'completed', 'failed', 'refunded')),
created_at TIMESTAMPTZ DEFAULT NOW()
);
-- Function to increment tickets sold
CREATE OR REPLACE FUNCTION increment_tickets_sold(ticket_type_id UUID, amount INTEGER)
RETURNS VOID AS $$
BEGIN
UPDATE ticket_types
SET quantity_sold = quantity_sold + amount
WHERE id = ticket_type_id;
END;
$$ LANGUAGE plpgsql SECURITY DEFINER;
-- Trigger to create profile on user signup
CREATE OR REPLACE FUNCTION public.handle_new_user()
RETURNS TRIGGER AS $$
BEGIN
INSERT INTO public.profiles (id, full_name, phone)
VALUES (
NEW.id,
NEW.raw_user_meta_data->>'full_name',
NEW.raw_user_meta_data->>'phone'
);
RETURN NEW;
END;
$$ LANGUAGE plpgsql SECURITY DEFINER;
-- Create trigger for new users
DROP TRIGGER IF EXISTS on_auth_user_created ON auth.users;
CREATE TRIGGER on_auth_user_created
AFTER INSERT ON auth.users
FOR EACH ROW EXECUTE FUNCTION public.handle_new_user();
-- Row Level Security (RLS) Policies
-- Enable RLS
ALTER TABLE profiles ENABLE ROW LEVEL SECURITY;
ALTER TABLE events ENABLE ROW LEVEL SECURITY;
ALTER TABLE ticket_types ENABLE ROW LEVEL SECURITY;
ALTER TABLE tickets ENABLE ROW LEVEL SECURITY;
ALTER TABLE orders ENABLE ROW LEVEL SECURITY;
-- Profiles policies
CREATE POLICY "Users can view their own profile"
ON profiles FOR SELECT
USING (auth.uid() = id);
CREATE POLICY "Users can update their own profile"
ON profiles FOR UPDATE
USING (auth.uid() = id);
CREATE POLICY "Employees can view all profiles"
ON profiles FOR SELECT
USING (
EXISTS (
SELECT 1 FROM profiles
WHERE id = auth.uid()
AND role IN ('employee', 'admin')
)
);
CREATE POLICY "Admins can update any profile"
ON profiles FOR UPDATE
USING (
EXISTS (
SELECT 1 FROM profiles
WHERE id = auth.uid()
AND role = 'admin'
)
);
-- Events policies (public read)
CREATE POLICY "Anyone can view active events"
ON events FOR SELECT
USING (is_active = true);
CREATE POLICY "Admins can manage events"
ON events FOR ALL
USING (
EXISTS (
SELECT 1 FROM profiles
WHERE id = auth.uid()
AND role = 'admin'
)
);
-- Ticket types policies (public read)
CREATE POLICY "Anyone can view ticket types"
ON ticket_types FOR SELECT
USING (true);
CREATE POLICY "Admins can manage ticket types"
ON ticket_types FOR ALL
USING (
EXISTS (
SELECT 1 FROM profiles
WHERE id = auth.uid()
AND role = 'admin'
)
);
-- Tickets policies
CREATE POLICY "Users can view their own tickets"
ON tickets FOR SELECT
USING (user_id = auth.uid());
CREATE POLICY "Employees can view all tickets"
ON tickets FOR SELECT
USING (
EXISTS (
SELECT 1 FROM profiles
WHERE id = auth.uid()
AND role IN ('employee', 'admin')
)
);
CREATE POLICY "Employees can update ticket status"
ON tickets FOR UPDATE
USING (
EXISTS (
SELECT 1 FROM profiles
WHERE id = auth.uid()
AND role IN ('employee', 'admin')
)
);
CREATE POLICY "Service role can insert tickets"
ON tickets FOR INSERT
WITH CHECK (true);
-- Orders policies
CREATE POLICY "Users can view their own orders"
ON orders FOR SELECT
USING (user_id = auth.uid());
CREATE POLICY "Users can create orders"
ON orders FOR INSERT
WITH CHECK (user_id = auth.uid());
CREATE POLICY "Service role can update orders"
ON orders FOR UPDATE
WITH CHECK (true);
-- Create indexes for performance
CREATE INDEX IF NOT EXISTS idx_tickets_user_id ON tickets(user_id);
CREATE INDEX IF NOT EXISTS idx_tickets_event_id ON tickets(event_id);
CREATE INDEX IF NOT EXISTS idx_tickets_status ON tickets(status);
CREATE INDEX IF NOT EXISTS idx_orders_user_id ON orders(user_id);
CREATE INDEX IF NOT EXISTS idx_events_date ON events(date);
CREATE INDEX IF NOT EXISTS idx_events_is_active ON events(is_active);
-- Insert sample data (optional - remove in production)
-- INSERT INTO events (title, description, date, is_active) VALUES
-- ('NEON NIGHTS', 'The ultimate electronic music experience', '2024-02-15 22:00:00+00', true),
-- ('LATIN HEAT', 'Salsa, reggaeton, and more', '2024-02-22 21:00:00+00', true);