Changes between Initial Version and Version 1 of DatabaseProgramming


Ignore:
Timestamp:
05/26/26 22:16:26 (16 hours ago)
Author:
231203
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • DatabaseProgramming

    v1 v1  
     1= Procedures =
     2
     3== create_parking_reservation ==
     4
     5{{{
     6CREATE OR REPLACE PROCEDURE public.create_parking_reservation(
     7    IN p_user_id integer,
     8    IN p_vehicle_id integer,
     9    IN p_parking_id integer,
     10    IN p_reservation_status_id integer,
     11    IN p_start_time timestamp without time zone,
     12    IN p_end_time timestamp without time zone
     13)
     14LANGUAGE plpgsql
     15AS $procedure$
     16BEGIN
     17    IF NOT EXISTS (SELECT 1 FROM app_user WHERE user_id = p_user_id) THEN
     18        RAISE EXCEPTION 'User does not exist.';
     19    END IF;
     20
     21    IF NOT EXISTS (
     22        SELECT 1 FROM vehicle
     23        WHERE vehicle_id = p_vehicle_id AND user_id = p_user_id
     24    ) THEN
     25        RAISE EXCEPTION 'Vehicle does not exist or does not belong to this user.';
     26    END IF;
     27
     28    IF NOT EXISTS (SELECT 1 FROM parking WHERE parking_id = p_parking_id) THEN
     29        RAISE EXCEPTION 'Parking does not exist.';
     30    END IF;
     31
     32    IF NOT EXISTS (
     33        SELECT 1 FROM parking
     34        WHERE parking_id = p_parking_id AND supports_reservation = true
     35    ) THEN
     36        RAISE EXCEPTION 'Parking does not support reservations.';
     37    END IF;
     38
     39    IF p_start_time >= p_end_time THEN
     40        RAISE EXCEPTION 'Start time must be before end time.';
     41    END IF;
     42
     43    IF NOT EXISTS (
     44        SELECT 1 FROM parking_spot
     45        WHERE parking_id = p_parking_id AND status = 'free'
     46    ) THEN
     47        RAISE EXCEPTION 'No free parking spots available.';
     48    END IF;
     49
     50    INSERT INTO reservation (
     51        user_id,
     52        vehicle_id,
     53        parking_id,
     54        reservation_status_id,
     55        start_time,
     56        end_time,
     57        reservation_code
     58    )
     59    VALUES (
     60        p_user_id,
     61        p_vehicle_id,
     62        p_parking_id,
     63        p_reservation_status_id,
     64        p_start_time,
     65        p_end_time,
     66        'RES-' || p_user_id || '-' || EXTRACT(EPOCH FROM NOW())::INT
     67    );
     68
     69    UPDATE parking_spot
     70    SET status = 'reserved'
     71    WHERE parking_spot_id = (
     72        SELECT parking_spot_id
     73        FROM parking_spot
     74        WHERE parking_id = p_parking_id AND status = 'free'
     75        LIMIT 1
     76    );
     77END;
     78$procedure$;
     79}}}
     80
     81Оваа процедура креира нова паркинг резервација само доколку се исполнети сите потребни услови, како постоење на корисник, возило, паркинг и слободно место.
     82Ја имплементира бизнис логиката за управување со резервации и автоматски резервира слободно паркинг место.
     83
     84== cancel_reservation ==
     85
     86{{{
     87CREATE OR REPLACE PROCEDURE public.cancel_reservation(
     88    IN p_reservation_id integer
     89)
     90LANGUAGE plpgsql
     91AS $procedure$
     92BEGIN
     93    IF NOT EXISTS (
     94        SELECT 1 FROM reservation
     95        WHERE reservation_id = p_reservation_id
     96    ) THEN
     97        RAISE EXCEPTION 'Reservation does not exist.';
     98    END IF;
     99
     100    IF EXISTS (
     101        SELECT 1 FROM reservation
     102        WHERE reservation_id = p_reservation_id
     103          AND reservation_status = 'cancelled'
     104    ) THEN
     105        RAISE EXCEPTION 'Reservation is already cancelled.';
     106    END IF;
     107
     108    IF EXISTS (
     109        SELECT 1 FROM reservation
     110        WHERE reservation_id = p_reservation_id
     111          AND reservation_status = 'completed'
     112    ) THEN
     113        RAISE EXCEPTION 'Completed reservation cannot be cancelled.';
     114    END IF;
     115
     116    UPDATE reservation
     117    SET reservation_status = 'cancelled'
     118    WHERE reservation_id = p_reservation_id;
     119END;
     120$procedure$;
     121}}}
     122
     123Оваа процедура овозможува откажување на постоечка резервација, при што спречува откажување на веќе завршени или претходно откажани резервации.
     124Ја имплементира бизнис логиката за контрола и правилно управување со статусите на резервациите.
     125
     126== complete_reservation ==
     127
     128{{{
     129CREATE OR REPLACE PROCEDURE public.complete_reservation(
     130    IN p_reservation_id integer
     131)
     132LANGUAGE plpgsql
     133AS $procedure$
     134BEGIN
     135    IF NOT EXISTS (
     136        SELECT 1 FROM reservation
     137        WHERE reservation_id = p_reservation_id
     138    ) THEN
     139        RAISE EXCEPTION 'Reservation does not exist.';
     140    END IF;
     141
     142    IF EXISTS (
     143        SELECT 1 FROM reservation
     144        WHERE reservation_id = p_reservation_id
     145          AND reservation_status = 'completed'
     146    ) THEN
     147        RAISE EXCEPTION 'Reservation is already completed.';
     148    END IF;
     149
     150    IF EXISTS (
     151        SELECT 1 FROM reservation
     152        WHERE reservation_id = p_reservation_id
     153          AND reservation_status = 'cancelled'
     154    ) THEN
     155        RAISE EXCEPTION 'Cancelled reservation cannot be completed.';
     156    END IF;
     157
     158    UPDATE reservation
     159    SET reservation_status = 'completed'
     160    WHERE reservation_id = p_reservation_id;
     161END;
     162$procedure$;
     163}}}
     164
     165Оваа процедура ја означува резервацијата како завршена, при што врши проверки за валидност на тековниот статус.
     166Ја имплементира бизнис логиката за правилно завршување на процесот на резервација и спречување нелогични промени.
     167
     168== end_parking_session ==
     169
     170{{{
     171CREATE OR REPLACE PROCEDURE public.end_parking_session(
     172    IN p_session_id integer,
     173    IN p_session_status_id integer
     174)
     175LANGUAGE plpgsql
     176AS $procedure$
     177BEGIN
     178    IF NOT EXISTS (SELECT 1 FROM parking_session WHERE session_id = p_session_id) THEN
     179        RAISE EXCEPTION 'Parking session does not exist.';
     180    END IF;
     181
     182    IF EXISTS (
     183        SELECT 1 FROM parking_session
     184        WHERE session_id = p_session_id AND end_time IS NOT NULL
     185    ) THEN
     186        RAISE EXCEPTION 'Parking session is already finished.';
     187    END IF;
     188
     189    IF NOT EXISTS (
     190        SELECT 1 FROM session_status
     191        WHERE session_status_id = p_session_status_id
     192    ) THEN
     193        RAISE EXCEPTION 'Session status does not exist.';
     194    END IF;
     195
     196    UPDATE parking_session
     197    SET end_time = NOW(),
     198        session_status_id = p_session_status_id
     199    WHERE session_id = p_session_id;
     200END;
     201$procedure$;
     202}}}
     203
     204Оваа процедура ја завршува активната паркинг сесија со поставување на крајно време и ажурирање на нејзиниот статус.
     205Ја имплементира бизнис логиката за правилно затворање на паркинг сесиите и спречување повторно завршување на веќе затворени сесии.
     206
     207== fill_total_amount ==
     208
     209{{{
     210CREATE OR REPLACE PROCEDURE public.fill_total_amount(
     211    IN p_session_id integer
     212)
     213LANGUAGE plpgsql
     214AS $procedure$
     215BEGIN
     216    IF NOT EXISTS (SELECT 1 FROM parking_session WHERE session_id = p_session_id) THEN
     217        RAISE EXCEPTION 'Parking session does not exist.';
     218    END IF;
     219
     220    IF EXISTS (
     221        SELECT 1 FROM parking_session
     222        WHERE session_id = p_session_id AND end_time IS NULL
     223    ) THEN
     224        RAISE EXCEPTION 'Parking session is still active.';
     225    END IF;
     226
     227    UPDATE parking_session
     228    SET total_amount = calculate_session_amount(p_session_id)
     229    WHERE session_id = p_session_id;
     230END;
     231$procedure$;
     232}}}
     233
     234Оваа процедура го пресметува и ажурира вкупниот износ за завршена паркинг сесија користејќи функција за пресметка на цена.
     235Ја имплементира бизнис логиката за автоматска наплата според времетраењето и тарифата на паркирањето.
     236
     237== start_parking_session ==
     238
     239{{{
     240CREATE OR REPLACE PROCEDURE public.start_parking_session(
     241    IN p_user_id integer,
     242    IN p_vehicle_id integer,
     243    IN p_parking_id integer,
     244    IN p_tariff_id integer,
     245    IN p_session_status_id integer
     246)
     247LANGUAGE plpgsql
     248AS $procedure$
     249BEGIN
     250    IF NOT EXISTS (SELECT 1 FROM app_user WHERE user_id = p_user_id) THEN
     251        RAISE EXCEPTION 'User does not exist.';
     252    END IF;
     253
     254    IF NOT EXISTS (
     255        SELECT 1 FROM vehicle
     256        WHERE vehicle_id = p_vehicle_id AND user_id = p_user_id
     257    ) THEN
     258        RAISE EXCEPTION 'Vehicle does not exist or does not belong to this user.';
     259    END IF;
     260
     261    IF NOT EXISTS (SELECT 1 FROM parking WHERE parking_id = p_parking_id) THEN
     262        RAISE EXCEPTION 'Parking does not exist.';
     263    END IF;
     264
     265    IF NOT EXISTS (SELECT 1 FROM tariff WHERE tariff_id = p_tariff_id) THEN
     266        RAISE EXCEPTION 'Tariff does not exist.';
     267    END IF;
     268
     269    IF NOT EXISTS (
     270        SELECT 1 FROM session_status WHERE session_status_id = p_session_status_id
     271    ) THEN
     272        RAISE EXCEPTION 'Session status does not exist.';
     273    END IF;
     274
     275    IF has_active_session(p_user_id) THEN
     276        RAISE EXCEPTION 'User already has an active parking session.';
     277    END IF;
     278
     279    IF NOT EXISTS (
     280        SELECT 1 FROM parking_spot
     281        WHERE parking_id = p_parking_id AND status = 'free'
     282    ) THEN
     283        RAISE EXCEPTION 'No free parking spots available.';
     284    END IF;
     285
     286    INSERT INTO parking_session (
     287        user_id,
     288        vehicle_id,
     289        parking_id,
     290        tariff_id,
     291        session_status_id,
     292        start_time,
     293        end_time,
     294        total_amount
     295    )
     296    VALUES (
     297        p_user_id,
     298        p_vehicle_id,
     299        p_parking_id,
     300        p_tariff_id,
     301        p_session_status_id,
     302        NOW(),
     303        NULL,
     304        0.00
     305    );
     306
     307    UPDATE parking_spot
     308    SET status = 'occupied'
     309    WHERE parking_spot_id = (
     310        SELECT parking_spot_id
     311        FROM parking_spot
     312        WHERE parking_id = p_parking_id AND status = 'free'
     313        LIMIT 1
     314    );
     315END;
     316$procedure$;
     317}}}
     318
     319Оваа процедура започнува нова паркинг сесија доколку корисникот ги исполнува сите услови и има достапно слободно место.
     320Ја имплементира бизнис логиката за иницирање на паркирање, контрола на активни сесии и автоматско зафаќање на паркинг место.
     321
     322= Functions =
     323
     324== calculate_session_amount ==
     325
     326{{{
     327CREATE OR REPLACE FUNCTION public.calculate_session_amount(p_session_id integer)
     328RETURNS numeric
     329LANGUAGE plpgsql
     330AS $function$
     331DECLARE
     332    v_start TIMESTAMP;
     333    v_end TIMESTAMP;
     334    v_tariff_id INT;
     335    v_price NUMERIC;
     336    v_hours NUMERIC;
     337BEGIN
     338    SELECT start_time, end_time, tariff_id
     339    INTO v_start, v_end, v_tariff_id
     340    FROM parking_session
     341    WHERE session_id = p_session_id;
     342
     343    IF NOT FOUND THEN
     344        RAISE EXCEPTION 'Parking session does not exist.';
     345    END IF;
     346
     347    IF v_end IS NULL THEN
     348        RETURN 0.00;
     349    END IF;
     350
     351    v_hours := CEIL(EXTRACT(EPOCH FROM (v_end - v_start)) / 3600.0);
     352
     353    SELECT price
     354    INTO v_price
     355    FROM price_list
     356    WHERE tariff_id = v_tariff_id
     357      AND CURRENT_DATE BETWEEN valid_from AND valid_to
     358    ORDER BY valid_from DESC
     359    LIMIT 1;
     360
     361    IF NOT FOUND THEN
     362        RAISE EXCEPTION 'Valid price for tariff does not exist.';
     363    END IF;
     364
     365    RETURN ROUND(v_hours * v_price, 2);
     366END;
     367$function$;
     368}}}
     369
     370Оваа функција ја пресметува вкупната цена за дадена паркинг сесија според времетраењето и важечката тарифа.
     371Ја имплементира бизнис логиката за автоматска пресметка на наплата и се користи при ажурирање на вкупниот износ за завршена сесија.
     372
     373== has_active_session ==
     374
     375{{{
     376CREATE OR REPLACE FUNCTION public.has_active_session(p_user_id integer)
     377RETURNS boolean
     378LANGUAGE plpgsql
     379AS $function$
     380DECLARE
     381    v_exists BOOLEAN;
     382BEGIN
     383    IF NOT EXISTS (
     384        SELECT 1
     385        FROM app_user
     386        WHERE user_id = p_user_id
     387    ) THEN
     388        RAISE EXCEPTION 'User does not exist.';
     389    END IF;
     390
     391    SELECT EXISTS (
     392        SELECT 1
     393        FROM parking_session
     394        WHERE user_id = p_user_id
     395          AND end_time IS NULL
     396    )
     397    INTO v_exists;
     398
     399    RETURN v_exists;
     400END;
     401$function$;
     402}}}
     403
     404Оваа функција проверува дали даден корисник има активна паркинг сесија, односно сесија која сè уште нема крајно време.
     405Ја имплементира бизнис логиката за спречување на повеќе активни сесии кај ист корисник и се користи при започнување нова паркинг сесија.
     406
     407== trg_set_total_amount ==
     408
     409{{{
     410CREATE OR REPLACE FUNCTION public.trg_set_total_amount()
     411RETURNS trigger
     412LANGUAGE plpgsql
     413AS $function$
     414DECLARE
     415    v_price NUMERIC;
     416    v_hours NUMERIC;
     417BEGIN
     418    IF NEW.end_time IS NULL THEN
     419        NEW.total_amount := 0.00;
     420    ELSE
     421        IF NEW.start_time IS NULL THEN
     422            RAISE EXCEPTION 'Start time cannot be null.';
     423        END IF;
     424
     425        IF NEW.end_time <= NEW.start_time THEN
     426            RAISE EXCEPTION 'End time must be after start time.';
     427        END IF;
     428
     429        SELECT price
     430        INTO v_price
     431        FROM price_list
     432        WHERE tariff_id = NEW.tariff_id
     433          AND CURRENT_DATE BETWEEN valid_from AND valid_to
     434        ORDER BY valid_from DESC
     435        LIMIT 1;
     436
     437        IF NOT FOUND THEN
     438            RAISE EXCEPTION 'Valid price for tariff does not exist.';
     439        END IF;
     440
     441        v_hours := CEIL(EXTRACT(EPOCH FROM (NEW.end_time - NEW.start_time)) / 3600.0);
     442
     443        NEW.total_amount := ROUND(v_hours * v_price, 2);
     444    END IF;
     445
     446    RETURN NEW;
     447END;
     448$function$;
     449}}}
     450
     451Оваа trigger функција автоматски го поставува или пресметува вкупниот износ на паркинг сесијата при внесување или ажурирање на податоци.
     452Ја имплементира бизнис логиката за автоматска наплата според времетраењето на сесијата и важечката тарифа.
     453
     454= Triggers =
     455
     456== trg_update_total_amount ==
     457
     458{{{
     459CREATE TRIGGER trg_update_total_amount
     460BEFORE INSERT OR UPDATE OF end_time
     461ON public.parking_session
     462FOR EACH ROW
     463EXECUTE FUNCTION trg_set_total_amount();
     464}}}
     465
     466Овој trigger автоматски се активира при креирање нова паркинг сесија или при промена на крајното време на постоечка сесија.
     467Ја имплементира бизнис логиката за автоматска пресметка на вкупниот износ за паркирање без потреба од рачна интервенција, преку повикување на trigger функцијата trg_set_total_amount().