Changes between Version 18 and Version 19 of DatabaseProgramming


Ignore:
Timestamp:
05/09/26 22:58:08 (2 weeks ago)
Author:
231027
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • DatabaseProgramming

    v18 v19  
    33== Функции
    44
    5 
     5=== get_current_price
     6
     7Оваа функција ја пресметува моменталната цена на билетот земајќи ги предвид активните промотивни периоди или поскапувања во реално време. Таа проверува дали за денешниот датум постои дефиниран период за промена на цената и соодветно ја зголемува или намалува основната цена.
     8
     9{{{
     10
     11CREATE OR REPLACE FUNCTION get_current_price(p_ticket_id BIGINT)
     12RETURNS FLOAT4 AS $$
     13DECLARE
     14    v_base_price FLOAT4;
     15    v_happening_id BIGINT;
     16    v_percent INT;
     17    v_increase BOOLEAN;
     18    v_final_price FLOAT4;
     19BEGIN
     20    SELECT base_price, event_happening_id INTO v_base_price, v_happening_id
     21    FROM "Ticket" WHERE ticket_id = p_ticket_id;
     22
     23    SELECT price_change_percent, increase_decrease INTO v_percent, v_increase
     24    FROM "Event_Period"
     25    WHERE event_happening_id = v_happening_id
     26      AND CURRENT_DATE BETWEEN start_date AND end_date
     27    LIMIT 1;
     28
     29    IF FOUND THEN
     30        IF v_increase THEN
     31           v_final_price := v_base_price * (1 + (v_percent / 100.0));
     32        ELSE
     33           v_final_price := v_base_price * (1 - (v_percent / 100.0));
     34        END IF;
     35    ELSE
     36        v_final_price := v_base_price;
     37    END IF;
     38
     39    RETURN v_final_price;
     40END;
     41$$ LANGUAGE plpgsql;
     42
     43}}}
     44
     45=== calculate_refund_amount
     46
     47Оваа функција ја пресметува сумата за рефундација со примена на 15% задршка од оригиналната уплата. Таа го идентификува плаќањето преку неговиот уникатен ID и враќа 85% од износот како финален износ за поврат на средства.
     48
     49{{{
     50
     51CREATE OR REPLACE FUNCTION calculate_refund_amount(p_purchase_id BIGINT)
     52RETURNS FLOAT4 AS $$
     53DECLARE
     54    v_original_price FLOAT4;
     55    v_refund_amount FLOAT4;
     56BEGIN
     57    -- Преземање на износот кој корисникот навистина го платил
     58    SELECT purchase_amount INTO v_original_price
     59    FROM "Ticket_Purchase"
     60    WHERE purchase_id = p_purchase_id;
     61
     62    IF NOT FOUND THEN
     63        RAISE EXCEPTION 'Purchase record not found.';
     64    END IF;
     65
     66    -- Примена на 15% пенали (се враќаат 85% од цената)
     67    v_refund_amount := v_original_price * 0.85;
     68
     69    RETURN v_refund_amount;
     70END;
     71$$ LANGUAGE plpgsql;
     72
     73}}}
    674
    775== Процедури
    876
    9 
     77=== buy_ticket
     78
     79Оваа процедура го извршува целиот процес на купување билет, вклучувајќи пресметка на цена, генерирање на уникатен QR код и креирање на запис за трансакцијата. По успешното купување, процедурата автоматски го менува статусот на билетот во недостапен за да се спречи двојна продажба.
     80
     81{{{
     82
     83CREATE OR REPLACE PROCEDURE buy_ticket(
     84    p_user_id BIGINT,
     85    p_ticket_id BIGINT
     86)
     87AS $$
     88DECLARE
     89    v_price FLOAT4;
     90    v_qr_code TEXT;
     91BEGIN
     92    v_price := get_current_price(p_ticket_id);
     93    v_qr_code := 'QR-' || p_ticket_id || '-' || p_user_id || '-' || EXTRACT(EPOCH FROM NOW());
     94
     95    INSERT INTO "Ticket_Purchase" (ticket_id, user_id, qr_code, purchase_amount)
     96    VALUES (p_ticket_id, p_user_id, v_qr_code, v_price);
     97
     98    UPDATE "Ticket" SET is_available = FALSE WHERE ticket_id = p_ticket_id;
     99   
     100    COMMIT;
     101END;
     102$$ LANGUAGE plpgsql;
     103
     104}}}
     105
     106=== schedule_new_happening
     107
     108Оваа процедура се користи за автоматизирано закажување на нов настан и генерирање на инвентар од билети за сите достапни седишта во објектот. Со еден повик, таа го креира настанот и веднаш ги пополнува соодветните табели со достапни билети за секоја секција во салата.
     109
     110{{{
     111
     112CREATE OR REPLACE PROCEDURE schedule_new_happening(
     113    p_event_id BIGINT,
     114    p_venue_id BIGINT,
     115    p_time TIMESTAMP,
     116    p_duration INT,
     117    p_base_price FLOAT4
     118)
     119AS $$
     120DECLARE
     121    v_happening_id BIGINT;
     122    v_seat_record RECORD;
     123BEGIN
     124    INSERT INTO "Event_Happening" (event_id, event_time, venue_id, duration)
     125    VALUES (p_event_id, p_time, p_venue_id, p_duration)
     126    RETURNING event_happening_id INTO v_happening_id;
     127
     128    FOR v_seat_record IN
     129        SELECT seat_id FROM "Seat" s
     130        JOIN "Section" sec ON s.section_id = sec.section_id
     131        WHERE sec.venue_id = p_venue_id
     132    LOOP
     133        INSERT INTO "Ticket" (ticket_type, base_price, is_available, event_happening_id, seat_id)
     134        VALUES ('Standard', p_base_price, TRUE, v_happening_id, v_seat_record.seat_id);
     135    END LOOP;
     136   
     137    RAISE NOTICE 'Event scheduled and tickets generated.';
     138END;
     139$$ LANGUAGE plpgsql;
     140
     141}}}
    10142
    11143== Тригери
    12144
     145=== trg_check_ticket_availability
     146
     147Овој тригер служи како безбедносен механизам кој пред секое купување проверува дали билетот е навистина слободен. Доколку билетот е веќе продаден, тригерот ја блокира трансакцијата и фрла грешка, со што се спречува конфликт на податоци.
     148
     149{{{
     150
     151CREATE OR REPLACE FUNCTION trg_check_ticket_availability()
     152RETURNS TRIGGER AS $$
     153BEGIN
     154    IF (SELECT is_available FROM "Ticket" WHERE ticket_id = NEW.ticket_id) = FALSE THEN
     155        RAISE EXCEPTION 'Ticket is already sold or unavailable.';
     156    END IF;
     157    RETURN NEW;
     158END;
     159$$ LANGUAGE plpgsql;
     160
     161CREATE TRIGGER check_ticket_availability_before_buy
     162BEFORE INSERT ON "Ticket_Purchase"
     163FOR EACH ROW EXECUTE FUNCTION trg_check_ticket_availability();
     164
     165}}}
     166
     167=== trg_check_user_age
     168
     169Овој тригер врши автоматска проверка на старосната граница на корисникот пред да му дозволи да купи билет за одреден настан. Доколку настанот има ограничување (на пр. 18+), тригерот ја пресметува возраста на корисникот и го блокира внесувањето во табелата за нарачки ако условот не е исполнет.
     170
     171{{{
     172
     173CREATE OR REPLACE FUNCTION trg_check_user_age()
     174RETURNS TRIGGER AS $$
     175DECLARE
     176    v_user_age INT;
     177    v_min_age INT;
     178BEGIN
     179    SELECT DATE_PART('year', AGE(date_of_birth)) INTO v_user_age
     180    FROM "User" WHERE user_id = NEW.user_id;
     181
     182    SELECT e.min_age INTO v_min_age
     183    FROM "Ticket" t
     184    JOIN "Event_Happening" eh ON t.event_happening_id = eh.event_happening_id
     185    JOIN "Event" e ON eh.event_id = e.event_id
     186    WHERE t.ticket_id = NEW.ticket_id;
     187
     188    IF v_user_age < v_min_age THEN
     189        RAISE EXCEPTION 'Access Denied: User is too young.';
     190    END IF;
     191
     192    RETURN NEW;
     193END;
     194$$ LANGUAGE plpgsql;
     195
     196CREATE TRIGGER check_age_before_purchase
     197BEFORE INSERT ON "Ticket_Purchase"
     198FOR EACH ROW EXECUTE FUNCTION trg_check_user_age();
     199
     200}}}