FunctionsProceduresTriggers: 02_databaseProcedures.sql

File 02_databaseProcedures.sql, 8.9 KB (added by 231184, 9 days ago)

databaseProcedures

Line 
1-- =====================================================
2-- PROCEDURES FOR REZERVO PROJECT
3-- =====================================================
4
5
6-- =====================================================
7-- 1. Book appointment
8-- Inserts appointment and marks selected slot as unavailable
9-- =====================================================
10
11CREATE OR REPLACE PROCEDURE book_appointment(
12 p_customer_id INT,
13 p_employee_id INT,
14 p_business_id INT,
15 p_service_id INT,
16 p_slot_id INT
17)
18 LANGUAGE plpgsql
19AS $$
20BEGIN
21 IF NOT EXISTS (
22 SELECT 1
23 FROM time_slot
24 WHERE slot_id = p_slot_id
25 AND is_available = TRUE
26 ) THEN
27 RAISE EXCEPTION 'Slot % is not available', p_slot_id;
28 END IF;
29
30 INSERT INTO appointment (
31 customer_id,
32 employee_id,
33 business_id,
34 service_id,
35 slot_id,
36 status,
37 created_at
38 )
39 VALUES (
40 p_customer_id,
41 p_employee_id,
42 p_business_id,
43 p_service_id,
44 p_slot_id,
45 'confirmed',
46 CURRENT_TIMESTAMP
47 );
48
49 UPDATE time_slot
50 SET is_available = FALSE
51 WHERE slot_id = p_slot_id;
52END;
53$$;
54
55
56-- Example:
57-- CALL book_appointment(100, 1000002, 1, 1, 5);
58
59
60
61-- =====================================================
62-- 2. Cancel appointment
63-- Updates appointment status, frees slot and inserts cancellation
64-- =====================================================
65
66CREATE OR REPLACE PROCEDURE cancel_appointment(
67 p_appointment_id INT,
68 p_cancelled_by TEXT,
69 p_reason TEXT,
70 p_employee_id INT DEFAULT NULL
71)
72 LANGUAGE plpgsql
73AS $$
74DECLARE
75 v_slot_id INT;
76BEGIN
77 SELECT slot_id
78 INTO v_slot_id
79 FROM appointment
80 WHERE appointment_id = p_appointment_id;
81
82 IF v_slot_id IS NULL THEN
83 RAISE EXCEPTION 'Appointment % does not exist', p_appointment_id;
84 END IF;
85
86 UPDATE appointment
87 SET status = 'cancelled'
88 WHERE appointment_id = p_appointment_id;
89
90 UPDATE time_slot
91 SET is_available = TRUE
92 WHERE slot_id = v_slot_id;
93
94 INSERT INTO cancellation (
95 appointment_id,
96 cancelled_by,
97 reason,
98 refund_amount,
99 created_at,
100 employee_id
101 )
102 VALUES (
103 p_appointment_id,
104 p_cancelled_by,
105 p_reason,
106 0,
107 CURRENT_TIMESTAMP,
108 p_employee_id
109 );
110END;
111$$;
112
113
114-- Example:
115-- CALL cancel_appointment(100, 'customer', 'Customer cannot attend', NULL);
116
117
118
119-- =====================================================
120-- 3. Create review for appointment
121-- =====================================================
122
123CREATE OR REPLACE PROCEDURE create_review_for_appointment(
124 p_appointment_id INT,
125 p_customer_id INT,
126 p_employee_id INT,
127 p_manager_id INT,
128 p_business_id INT,
129 p_rating INT,
130 p_comment TEXT
131)
132 LANGUAGE plpgsql
133AS $$
134BEGIN
135 IF p_rating < 1 OR p_rating > 5 THEN
136 RAISE EXCEPTION 'Rating must be between 1 and 5';
137 END IF;
138
139 IF NOT EXISTS (
140 SELECT 1
141 FROM appointment
142 WHERE appointment_id = p_appointment_id
143 ) THEN
144 RAISE EXCEPTION 'Appointment % does not exist', p_appointment_id;
145 END IF;
146
147 INSERT INTO review (
148 appointment_id,
149 customer_id,
150 employee_id,
151 manager_id,
152 business_id,
153 rating,
154 comment,
155 created_at
156 )
157 VALUES (
158 p_appointment_id,
159 p_customer_id,
160 p_employee_id,
161 p_manager_id,
162 p_business_id,
163 p_rating,
164 p_comment,
165 CURRENT_TIMESTAMP
166 );
167END;
168$$;
169
170
171-- Example:
172-- CALL create_review_for_appointment(100, 100, 1000002, 1, 1, 5, 'Great service');
173
174
175
176-- =====================================================
177-- 4. Request reschedule
178-- Creates pending reschedule request
179-- =====================================================
180
181CREATE OR REPLACE PROCEDURE request_reschedule(
182 p_appointment_id INT,
183 p_old_slot_id INT,
184 p_new_slot_id INT,
185 p_manager_id INT,
186 p_employee_id INT,
187 p_reason TEXT
188)
189 LANGUAGE plpgsql
190AS $$
191BEGIN
192 IF NOT EXISTS (
193 SELECT 1
194 FROM appointment
195 WHERE appointment_id = p_appointment_id
196 ) THEN
197 RAISE EXCEPTION 'Appointment % does not exist', p_appointment_id;
198 END IF;
199
200 IF NOT EXISTS (
201 SELECT 1
202 FROM time_slot
203 WHERE slot_id = p_new_slot_id
204 AND is_available = TRUE
205 ) THEN
206 RAISE EXCEPTION 'New slot % is not available', p_new_slot_id;
207 END IF;
208
209 INSERT INTO reschedule_request (
210 appointment_id,
211 old_slot_id,
212 new_slot_id,
213 manager_id,
214 employee_id,
215 status,
216 reason,
217 created_at
218 )
219 VALUES (
220 p_appointment_id,
221 p_old_slot_id,
222 p_new_slot_id,
223 p_manager_id,
224 p_employee_id,
225 'pending',
226 p_reason,
227 CURRENT_TIMESTAMP
228 );
229END;
230$$;
231
232
233-- Example:
234-- CALL request_reschedule(100, 5, 6, 1, 1000002, 'Customer requested another time');
235
236
237
238-- =====================================================
239-- 5. Approve reschedule request
240-- Updates appointment slot and request status
241-- =====================================================
242
243CREATE OR REPLACE PROCEDURE approve_reschedule_request(
244 p_request_id INT
245)
246 LANGUAGE plpgsql
247AS $$
248DECLARE
249 v_appointment_id INT;
250 v_old_slot_id INT;
251 v_new_slot_id INT;
252BEGIN
253 SELECT appointment_id, old_slot_id, new_slot_id
254 INTO v_appointment_id, v_old_slot_id, v_new_slot_id
255 FROM reschedule_request
256 WHERE request_id = p_request_id
257 AND status = 'pending';
258
259 IF v_appointment_id IS NULL THEN
260 RAISE EXCEPTION 'Pending reschedule request % does not exist', p_request_id;
261 END IF;
262
263 IF NOT EXISTS (
264 SELECT 1
265 FROM time_slot
266 WHERE slot_id = v_new_slot_id
267 AND is_available = TRUE
268 ) THEN
269 RAISE EXCEPTION 'New slot % is not available', v_new_slot_id;
270 END IF;
271
272 UPDATE appointment
273 SET slot_id = v_new_slot_id
274 WHERE appointment_id = v_appointment_id;
275
276 UPDATE time_slot
277 SET is_available = TRUE
278 WHERE slot_id = v_old_slot_id;
279
280 UPDATE time_slot
281 SET is_available = FALSE
282 WHERE slot_id = v_new_slot_id;
283
284 UPDATE reschedule_request
285 SET status = 'approved'
286 WHERE request_id = p_request_id;
287END;
288$$;
289
290
291-- Example:
292-- CALL approve_reschedule_request(1);
293
294
295
296-- =====================================================
297-- 6. Reject reschedule request
298-- =====================================================
299
300CREATE OR REPLACE PROCEDURE reject_reschedule_request(
301 p_request_id INT
302)
303 LANGUAGE plpgsql
304AS $$
305BEGIN
306 UPDATE reschedule_request
307 SET status = 'rejected'
308 WHERE request_id = p_request_id
309 AND status = 'pending';
310
311 IF NOT FOUND THEN
312 RAISE EXCEPTION 'Pending reschedule request % does not exist', p_request_id;
313 END IF;
314END;
315$$;
316
317
318-- Example:
319-- CALL reject_reschedule_request(1);
320
321CREATE OR REPLACE PROCEDURE make_employee_slots_unavailable(
322 p_employee_id INT,
323 p_date_from DATE,
324 p_date_to DATE,
325 p_reason TEXT DEFAULT 'Employee unavailable',
326 p_business_id INT DEFAULT NULL
327)
328 LANGUAGE plpgsql
329AS $$
330DECLARE
331 v_booked_count INT;
332 v_updated_count INT;
333BEGIN
334 IF p_date_from > p_date_to THEN
335 RAISE EXCEPTION 'date_from cannot be after date_to';
336 END IF;
337
338 SELECT COUNT(*)
339 INTO v_booked_count
340 FROM time_slot ts
341 JOIN appointment a ON a.slot_id = ts.slot_id
342 WHERE ts.employee_id = p_employee_id
343 AND ts.date BETWEEN p_date_from AND p_date_to
344 AND a.status <> 'cancelled'
345 AND (
346 p_business_id IS NULL
347 OR ts.business_id = p_business_id
348 );
349
350 IF v_booked_count > 0 THEN
351 RAISE EXCEPTION
352 'Cannot make slots unavailable. Employee % has % booked slots between % and %.',
353 p_employee_id, v_booked_count, p_date_from, p_date_to;
354 END IF;
355
356 UPDATE time_slot
357 SET is_available = FALSE
358 WHERE employee_id = p_employee_id
359 AND date BETWEEN p_date_from AND p_date_to
360 AND (
361 p_business_id IS NULL
362 OR business_id = p_business_id
363 );
364
365 GET DIAGNOSTICS v_updated_count = ROW_COUNT;
366
367 RAISE NOTICE
368 'Marked % slots as unavailable for employee % between % and %. Reason: %',
369 v_updated_count, p_employee_id, p_date_from, p_date_to, p_reason;
370END;
371$$;
372
373CALL make_employee_slots_unavailable(
374 1000002,
375 '2026-05-01',
376 '2026-05-07',
377 'Vacation'
378 );
379
380SELECT ts.slot_id, ts.employee_id, ts.date, a.appointment_id, a.status
381FROM time_slot ts
382 JOIN appointment a ON a.slot_id = ts.slot_id
383WHERE ts.employee_id = 1000002
384 AND ts.date BETWEEN '2026-05-01' AND '2026-05-07'
385 AND a.status <> 'cancelled';