| 1 | create or replace procedure PurchaseTicket(
|
|---|
| 2 | PassengerID_P int,
|
|---|
| 3 | FlightID_P int,
|
|---|
| 4 | SeatClassID_P int,
|
|---|
| 5 | SeatID_P int,
|
|---|
| 6 | ReservationID_P int
|
|---|
| 7 | ) as $$
|
|---|
| 8 | declare
|
|---|
| 9 | Departure timestamp;
|
|---|
| 10 | Distance_V int;
|
|---|
| 11 | SeatReserved bool;
|
|---|
| 12 | SeatFlightID int;
|
|---|
| 13 | SeatSurcharge numeric(10, 2);
|
|---|
| 14 | SeatActualClassID int;
|
|---|
| 15 | ClassMultiplier numeric(4, 2);
|
|---|
| 16 | BasePrice_V numeric(10, 2);
|
|---|
| 17 | FinalPrice_V int;
|
|---|
| 18 | CanceledTicketStatus int;
|
|---|
| 19 | ClassCapacity int;
|
|---|
| 20 | ClassSold int;
|
|---|
| 21 | begin
|
|---|
| 22 | if SeatClassID_P is null then
|
|---|
| 23 | raise exception 'Seat class must be specified!';
|
|---|
| 24 | end if;
|
|---|
| 25 |
|
|---|
| 26 | if not exists (select 1 from seatclass where id = SeatClassID_P) then
|
|---|
| 27 | raise exception 'Seat class does not exist!';
|
|---|
| 28 | end if;
|
|---|
| 29 |
|
|---|
| 30 | select id into strict CanceledTicketStatus
|
|---|
| 31 | from ticketstatus where name = 'Canceled Flight';
|
|---|
| 32 |
|
|---|
| 33 | select f.departure, sf.distance
|
|---|
| 34 | into Departure, Distance_V
|
|---|
| 35 | from flight f
|
|---|
| 36 | join scheduledflight sf on sf.id = f.scheduleid
|
|---|
| 37 | where f.id = FlightID_P
|
|---|
| 38 | for update of f;
|
|---|
| 39 |
|
|---|
| 40 | if not found then
|
|---|
| 41 | raise exception 'Flight does not exist!';
|
|---|
| 42 | end if;
|
|---|
| 43 |
|
|---|
| 44 | if Departure <= now() + interval '3 hours' then
|
|---|
| 45 | raise exception 'Not allowed to purchase ticket for this flight!';
|
|---|
| 46 | end if;
|
|---|
| 47 |
|
|---|
| 48 | if exists (select 1 from canceledflight where flightid = FlightID_P) then
|
|---|
| 49 | raise exception 'Flight has been canceled!';
|
|---|
| 50 | end if;
|
|---|
| 51 |
|
|---|
| 52 | if not exists (select 1 from passenger where id = PassengerID_P) then
|
|---|
| 53 | raise exception 'Passenger does not exist!';
|
|---|
| 54 | end if;
|
|---|
| 55 |
|
|---|
| 56 | if not exists (
|
|---|
| 57 | select 1 from reservation
|
|---|
| 58 | where id = ReservationID_P and passengerid = PassengerID_P
|
|---|
| 59 | ) then
|
|---|
| 60 | raise exception 'Reservation does not exist or does not belong to the right passenger!';
|
|---|
| 61 | end if;
|
|---|
| 62 |
|
|---|
| 63 | if SeatID_P is not null then
|
|---|
| 64 | select s.reserved, s.flightid, sc.price, sc.seatclassid
|
|---|
| 65 | into SeatReserved, SeatFlightID, SeatSurcharge, SeatActualClassID
|
|---|
| 66 | from seat s
|
|---|
| 67 | join seatconfiguration sc on sc.id = s.seatconfigurationid
|
|---|
| 68 | where s.id = SeatID_P
|
|---|
| 69 | for update of s;
|
|---|
| 70 |
|
|---|
| 71 | if not found then
|
|---|
| 72 | raise exception 'Seat does not exist!';
|
|---|
| 73 | end if;
|
|---|
| 74 |
|
|---|
| 75 | if SeatFlightID <> FlightID_P then
|
|---|
| 76 | raise exception 'Seat is not for the correct flight!';
|
|---|
| 77 | end if;
|
|---|
| 78 |
|
|---|
| 79 | if SeatReserved then
|
|---|
| 80 | raise exception 'Seat is already reserved!';
|
|---|
| 81 | end if;
|
|---|
| 82 |
|
|---|
| 83 | if SeatActualClassID <> SeatClassID_P then
|
|---|
| 84 | raise exception 'Seat class does not match the chosen seat!';
|
|---|
| 85 | end if;
|
|---|
| 86 | else
|
|---|
| 87 | SeatSurcharge := 0;
|
|---|
| 88 |
|
|---|
| 89 | select count(*)
|
|---|
| 90 | into ClassCapacity
|
|---|
| 91 | from seat s
|
|---|
| 92 | join seatconfiguration sc on sc.id = s.seatconfigurationid
|
|---|
| 93 | where s.flightid = FlightID_P
|
|---|
| 94 | and sc.seatclassid = SeatClassID_P;
|
|---|
| 95 |
|
|---|
| 96 | select count(*)
|
|---|
| 97 | into ClassSold
|
|---|
| 98 | from ticket
|
|---|
| 99 | where flightid = FlightID_P
|
|---|
| 100 | and seatclassid = SeatClassID_P
|
|---|
| 101 | and ticketstatusid <> CanceledTicketStatus;
|
|---|
| 102 |
|
|---|
| 103 | if ClassSold >= ClassCapacity then
|
|---|
| 104 | raise exception 'No more seats available in the chosen class!';
|
|---|
| 105 | end if;
|
|---|
| 106 | end if;
|
|---|
| 107 |
|
|---|
| 108 | ClassMultiplier := case SeatClassID_P
|
|---|
| 109 | when 1 then 1
|
|---|
| 110 | when 2 then 1.5
|
|---|
| 111 | when 3 then 2
|
|---|
| 112 | when 4 then 3
|
|---|
| 113 | end;
|
|---|
| 114 |
|
|---|
| 115 | BasePrice_V := Distance_V * ClassMultiplier;
|
|---|
| 116 | FinalPrice_V := ceil(BasePrice_V + SeatSurcharge);
|
|---|
| 117 |
|
|---|
| 118 | insert into ticket(
|
|---|
| 119 | seatid, passengerid, baseprice, finalprice,
|
|---|
| 120 | seatclassid, reservationid, flightid
|
|---|
| 121 | )
|
|---|
| 122 | values (
|
|---|
| 123 | SeatID_P, PassengerID_P, BasePrice_V, FinalPrice_V,
|
|---|
| 124 | SeatClassID_P, ReservationID_P, FlightID_P
|
|---|
| 125 | );
|
|---|
| 126 | end;
|
|---|
| 127 | $$ language plpgsql; |
|---|