-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmigration.sql
More file actions
254 lines (221 loc) · 9.8 KB
/
Copy pathmigration.sql
File metadata and controls
254 lines (221 loc) · 9.8 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
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
-- ============================================
-- SehaSport Migration Script
-- Run this if you have existing tables
-- ============================================
-- ============================================
-- 1. ADD NEW COLUMNS TO EXISTING TABLES
-- ============================================
-- Add lat/lng to venues if not exists
DO $$
BEGIN
IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'venues' AND column_name = 'lat') THEN
ALTER TABLE venues ADD COLUMN lat double precision;
END IF;
IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'venues' AND column_name = 'lng') THEN
ALTER TABLE venues ADD COLUMN lng double precision;
END IF;
END $$;
-- Add new columns to events
DO $$
BEGIN
IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'events' AND column_name = 'owner_type') THEN
ALTER TABLE events ADD COLUMN owner_type text CHECK (owner_type IN ('USER', 'COMMUNITY')) DEFAULT 'USER';
END IF;
IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'events' AND column_name = 'owner_id') THEN
ALTER TABLE events ADD COLUMN owner_id text;
END IF;
IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'events' AND column_name = 'court_id') THEN
ALTER TABLE events ADD COLUMN court_id bigint;
END IF;
IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'events' AND column_name = 'start_time') THEN
ALTER TABLE events ADD COLUMN start_time time;
END IF;
IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'events' AND column_name = 'end_time') THEN
ALTER TABLE events ADD COLUMN end_time time;
END IF;
IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'events' AND column_name = 'is_paid') THEN
ALTER TABLE events ADD COLUMN is_paid boolean DEFAULT false;
END IF;
IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'events' AND column_name = 'description') THEN
ALTER TABLE events ADD COLUMN description text;
END IF;
END $$;
-- Migrate existing events: set owner_id from creator_id
UPDATE events SET owner_id = creator_id::text WHERE owner_id IS NULL AND creator_id IS NOT NULL;
-- Add status column to participants if not exists
DO $$
BEGIN
IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'participants' AND column_name = 'status') THEN
ALTER TABLE participants ADD COLUMN status text CHECK (status IN ('interested', 'joined', 'cancelled')) DEFAULT 'joined';
END IF;
END $$;
-- ============================================
-- 2. CREATE NEW TABLES
-- ============================================
-- Courts table
CREATE TABLE IF NOT EXISTS courts (
id bigint generated by default as identity primary key,
venue_id bigint references venues(id) on delete cascade not null,
name text not null,
sport text not null,
capacity int default 4,
is_active boolean default true,
created_at timestamptz default now() not null
);
-- Court Schedules table
CREATE TABLE IF NOT EXISTS court_schedules (
id bigint generated by default as identity primary key,
court_id bigint references courts(id) on delete cascade not null,
day_of_week int check (day_of_week between 0 and 6),
start_time time not null,
end_time time not null,
is_available boolean default true,
created_at timestamptz default now() not null
);
-- Communities table
CREATE TABLE IF NOT EXISTS communities (
id bigint generated by default as identity primary key,
name text not null,
description text,
sport text not null,
image_url text,
is_public boolean default true,
has_membership boolean default false,
created_at timestamptz default now() not null
);
-- Community Members table
CREATE TABLE IF NOT EXISTS community_members (
id bigint generated by default as identity primary key,
community_id bigint references communities(id) on delete cascade not null,
user_id uuid references auth.users not null,
role text check (role in ('LEADER', 'ADMIN', 'MEMBER')) not null default 'MEMBER',
joined_at timestamptz default now() not null,
unique(community_id, user_id)
);
-- Bookings table
CREATE TABLE IF NOT EXISTS bookings (
id bigint generated by default as identity primary key,
court_id bigint references courts(id) on delete cascade not null,
user_id uuid references auth.users not null,
event_id bigint references events(id) on delete cascade,
date date not null,
start_time time not null,
end_time time not null,
status text check (status in ('pending', 'confirmed', 'cancelled')) default 'confirmed',
created_at timestamptz default now() not null
);
-- Add foreign key for court_id in events (if not exists)
DO $$
BEGIN
IF NOT EXISTS (
SELECT 1 FROM information_schema.table_constraints
WHERE constraint_name = 'events_court_id_fkey'
) THEN
ALTER TABLE events ADD CONSTRAINT events_court_id_fkey
FOREIGN KEY (court_id) REFERENCES courts(id);
END IF;
END $$;
-- ============================================
-- 3. ENABLE RLS ON NEW TABLES
-- ============================================
ALTER TABLE courts ENABLE ROW LEVEL SECURITY;
ALTER TABLE court_schedules ENABLE ROW LEVEL SECURITY;
ALTER TABLE communities ENABLE ROW LEVEL SECURITY;
ALTER TABLE community_members ENABLE ROW LEVEL SECURITY;
ALTER TABLE bookings ENABLE ROW LEVEL SECURITY;
-- ============================================
-- 4. CREATE POLICIES FOR NEW TABLES
-- ============================================
-- Courts policies
DROP POLICY IF EXISTS "Courts viewable by everyone" ON courts;
CREATE POLICY "Courts viewable by everyone" ON courts FOR SELECT USING (true);
DROP POLICY IF EXISTS "Venue owners can manage courts" ON courts;
CREATE POLICY "Venue owners can manage courts" ON courts FOR ALL
USING (EXISTS (SELECT 1 FROM venues WHERE venues.id = courts.venue_id AND venues.owner_id = auth.uid()));
-- Court Schedules policies
DROP POLICY IF EXISTS "Court schedules viewable by everyone" ON court_schedules;
CREATE POLICY "Court schedules viewable by everyone" ON court_schedules FOR SELECT USING (true);
-- Communities policies
DROP POLICY IF EXISTS "Public communities viewable" ON communities;
CREATE POLICY "Public communities viewable" ON communities FOR SELECT USING (is_public = true);
DROP POLICY IF EXISTS "Members can view their communities" ON communities;
CREATE POLICY "Members can view their communities" ON communities FOR SELECT
USING (EXISTS (SELECT 1 FROM community_members WHERE community_id = communities.id AND user_id = auth.uid()));
DROP POLICY IF EXISTS "Authenticated can create communities" ON communities;
CREATE POLICY "Authenticated can create communities" ON communities FOR INSERT
WITH CHECK (auth.role() = 'authenticated');
DROP POLICY IF EXISTS "Leaders can update communities" ON communities;
CREATE POLICY "Leaders can update communities" ON communities FOR UPDATE
USING (EXISTS (SELECT 1 FROM community_members WHERE community_id = communities.id AND user_id = auth.uid() AND role = 'LEADER'));
DROP POLICY IF EXISTS "Leaders can delete communities" ON communities;
CREATE POLICY "Leaders can delete communities" ON communities FOR DELETE
USING (EXISTS (SELECT 1 FROM community_members WHERE community_id = communities.id AND user_id = auth.uid() AND role = 'LEADER'));
-- Community Members policies
DROP POLICY IF EXISTS "Community members viewable" ON community_members;
CREATE POLICY "Community members viewable" ON community_members FOR SELECT USING (true);
DROP POLICY IF EXISTS "Users can join public communities" ON community_members;
CREATE POLICY "Users can join public communities" ON community_members FOR INSERT
WITH CHECK (
auth.uid() = user_id AND
role = 'MEMBER' AND
EXISTS (SELECT 1 FROM communities WHERE id = community_id AND is_public = true)
);
DROP POLICY IF EXISTS "Leaders can manage members" ON community_members;
CREATE POLICY "Leaders can manage members" ON community_members FOR ALL
USING (EXISTS (
SELECT 1 FROM community_members cm
WHERE cm.community_id = community_members.community_id
AND cm.user_id = auth.uid()
AND cm.role IN ('LEADER', 'ADMIN')
));
-- Bookings policies
DROP POLICY IF EXISTS "Bookings viewable by everyone" ON bookings;
CREATE POLICY "Bookings viewable by everyone" ON bookings FOR SELECT USING (true);
DROP POLICY IF EXISTS "Authenticated can create bookings" ON bookings;
CREATE POLICY "Authenticated can create bookings" ON bookings FOR INSERT
WITH CHECK (auth.uid() = user_id);
DROP POLICY IF EXISTS "Users can update own bookings" ON bookings;
CREATE POLICY "Users can update own bookings" ON bookings FOR UPDATE
USING (auth.uid() = user_id);
-- ============================================
-- 5. HELPER FUNCTIONS
-- ============================================
-- Check court availability function
CREATE OR REPLACE FUNCTION check_court_availability(
p_court_id bigint,
p_date date,
p_start_time time,
p_end_time time
) RETURNS boolean AS $$
BEGIN
RETURN NOT EXISTS (
SELECT 1 FROM bookings
WHERE court_id = p_court_id
AND date = p_date
AND status != 'cancelled'
AND (start_time < p_end_time AND end_time > p_start_time)
);
END;
$$ LANGUAGE plpgsql;
-- Enforce single leader trigger
CREATE OR REPLACE FUNCTION enforce_single_leader()
RETURNS TRIGGER AS $$
BEGIN
IF NEW.role = 'LEADER' THEN
UPDATE community_members
SET role = 'ADMIN'
WHERE community_id = NEW.community_id
AND role = 'LEADER'
AND id != NEW.id;
END IF;
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
-- Drop and recreate trigger
DROP TRIGGER IF EXISTS ensure_single_leader ON community_members;
CREATE TRIGGER ensure_single_leader
AFTER INSERT OR UPDATE ON community_members
FOR EACH ROW EXECUTE FUNCTION enforce_single_leader();
-- ============================================
-- DONE! Migration complete.
-- ============================================