209 | | |
210 | | |
211 | | ---- |
212 | | |
213 | | |
214 | | = Triggers = |
215 | | |
216 | | == 1. Update free seats based on ticket purchase == |
217 | | |
218 | | This trigger calculates the number of available tickets after purchasing a ticket and can be tested via the application, by trying to buy new tickets. |
219 | | |
220 | | {{{ |
221 | | -- TRIGGER TO UPDATE FREE SEATS |
222 | | CREATE OR REPLACE FUNCTION update_free_seats() |
223 | | RETURNS TRIGGER AS $$ |
224 | | BEGIN |
225 | | IF TG_OP = 'INSERT' THEN |
226 | | UPDATE trip |
227 | | SET free_seats = free_seats - 1 |
228 | | WHERE trip_id = NEW.trip_id; |
229 | | RETURN NEW; |
230 | | ELSIF TG_OP = 'DELETE' THEN |
231 | | UPDATE trip |
232 | | SET free_seats = free_seats + 1 |
233 | | WHERE trip_id = OLD.trip_id; |
234 | | RETURN OLD; |
235 | | END IF; |
236 | | RETURN NULL; |
237 | | END; |
238 | | $$ LANGUAGE plpgsql; |
239 | | |
240 | | CREATE TRIGGER ticket_insert_update_seats |
241 | | AFTER INSERT ON ticket |
242 | | FOR EACH ROW |
243 | | EXECUTE FUNCTION update_free_seats(); |
244 | | |
245 | | CREATE TRIGGER ticket_delete_update_seats |
246 | | AFTER DELETE ON ticket |
247 | | FOR EACH ROW |
248 | | EXECUTE FUNCTION update_free_seats(); |
249 | | }}} |
250 | | |
251 | | |
252 | | Here's a short example: |
253 | | |
254 | | [[Image(trip_before.png)]] |
255 | | |
256 | | If we purchase 3 tickets: |
257 | | |
258 | | [[Image(purchase.png)]] |
259 | | |
260 | | |
261 | | We get the new seat availability: |
262 | | |
263 | | [[Image(trip_after.png)]] |
264 | | |
265 | | |
266 | | == 2. Trigger to apply discount to student and child tickets == |
267 | | |
268 | | When purchasing a ticket, if its a student or a child ticket there exist special discounts. Since the application supports only buying regular tickets (covered by the application use cases), we will present how buying tickets of this type will automatically apply the discounts. |
269 | | |
270 | | |
271 | | {{{ |
272 | | -- TRIGGER TO CALCULATE TICKET PRICE WITH DISCOUNTS |
273 | | CREATE OR REPLACE FUNCTION apply_ticket_discount() |
274 | | RETURNS TRIGGER AS $$ |
275 | | BEGIN |
276 | | UPDATE ticket |
277 | | SET price = tr.base_price - (tr.base_price * NEW.discount / 100) |
278 | | FROM trip tr |
279 | | WHERE ticket.ticket_id = NEW.ticket_id AND ticket.trip_id = tr.trip_id; |
280 | | RETURN NEW; |
281 | | END; |
282 | | $$ LANGUAGE plpgsql; |
283 | | CREATE TRIGGER apply_student_ticket_discount |
284 | | BEFORE INSERT ON student_ticket |
285 | | FOR EACH ROW EXECUTE FUNCTION apply_ticket_discount(); |
286 | | |
287 | | CREATE TRIGGER apply_child_ticket_discount |
288 | | BEFORE INSERT ON child_ticket F |
289 | | OR EACH ROW EXECUTE FUNCTION apply_ticket_discount(); |
290 | | }}} |
291 | | |
292 | | ''Example: If we select the existing child tickets and their appropriate base prices (i.e original prices) using a simple query:'' |
293 | | |
294 | | |
295 | | {{{ |
296 | | SELECT |
297 | | t.ticket_id, |
298 | | t.price AS discounted_price, |
299 | | ct.discount, |
300 | | tr.base_price AS original_price |
301 | | FROM ticket t |
302 | | JOIN child_ticket ct ON ct.ticket_id = t.ticket_id |
303 | | JOIN trip tr ON tr.trip_id = t.trip_id; |
304 | | }}} |
305 | | |
306 | | ''We will get the following results:'' |
307 | | |
308 | | [[Image(child_ticket_prices.png)]] |
309 | | |
310 | | |
311 | | == 3. Update total payment == |
312 | | |
313 | | This trigger calculates the total payment for an account and should work together with the previous trigger for situations where we buy multiple tickets, including special types of tickets (child and student tickets). It is executed **AFTER** applying the discounts. |
314 | | |
315 | | {{{ |
316 | | -- UPDATE TOTAL PAYMENT TOTAL PRICE (TRIGGER AFTER CHILD/STUDENT DISCOUNT IS APPLIED) |
317 | | |
318 | | CREATE OR REPLACE FUNCTION update_payment_total() |
319 | | RETURNS TRIGGER AS $$ |
320 | | BEGIN UPDATE payment |
321 | | SET total_price = ( SELECT COALESCE(SUM(price), 0) |
322 | | FROM ticket |
323 | | WHERE payment_id = NEW.payment_id) |
324 | | WHERE payment_id = NEW.payment_id; |
325 | | |
326 | | RETURN NEW; END; $$ |
327 | | LANGUAGE plpgsql; |
328 | | |
329 | | CREATE TRIGGER trg_update_payment_total_insert |
330 | | AFTER INSERT ON ticket |
331 | | FOR EACH ROW EXECUTE FUNCTION update_payment_total(); |
332 | | |
333 | | CREATE TRIGGER trg_update_payment_total_update |
334 | | AFTER UPDATE OF price, payment_id ON ticket |
335 | | FOR EACH ROW EXECUTE FUNCTION update_payment_total(); |
336 | | |
337 | | CREATE TRIGGER trg_update_payment_total_delete |
338 | | AFTER DELETE ON ticket |
339 | | FOR EACH ROW EXECUTE FUNCTION update_payment_total(); |
340 | | }}} |
341 | | |
342 | | |
343 | | |