| Version 6 (modified by , 6 hours ago) ( diff ) |
|---|
Функции, Процедури и Тригери
Во оваа фаза беа имплементирани функции, процедури и тригери кои ја поддржуваат основната бизнис логика на системот Safe City Security. Тие овозможуваат автоматизација на процеси како проверка на статус на казна, пресметка на износ, евидентирање плаќање, поднесување жалба, архивирање снимки и автоматско ажурирање на податоци преку тригери.
Функции
Функциите се користат за пресметување и враќање на вредности кои се потребни во повеќе делови од системот.
1. fn_status_kazna
CREATE OR REPLACE FUNCTION fn_status_kazna(p_kazna_id INTEGER)
RETURNS VARCHAR
AS $$
DECLARE
v_status VARCHAR;
BEGIN
SELECT sk.ime
INTO v_status
FROM Kazna k
JOIN StatusKazna sk ON sk.status_kazna_id = k.status_kazna_id
WHERE k.kazna_id = p_kazna_id;
IF v_status IS NULL THEN
RETURN 'Kaznata ne postoi';
ELSIF LOWER(v_status) = 'platena' THEN
RETURN 'Kaznata e platena';
ELSIF LOWER(v_status) = 'neplatena' THEN
RETURN 'Kaznata ne e platena';
ELSIF LOWER(v_status) = 'ponishtena' THEN
RETURN 'Kaznata e ponishtena';
ELSE
RETURN 'Nepoznat status na kazna';
END IF;
END;
$$
LANGUAGE plpgsql;
Функцијата fn_status_kazna го враќа статусот на одредена казна според нејзиниот идентификатор. Како влезен параметар прима p_kazna_id, а потоа од табелата Kazna и поврзаната табела StatusKazna го зема името на статусот на казната. Ако казната не постои, функцијата враќа Kaznata ne postoi. Ако статусот е platena, враќа Kaznata e platena. Ако статусот е neplatena, враќа Kaznata ne e platena. Ако статусот е ponishtena, враќа Kaznata e ponishtena, а во останатите случаи враќа Nepoznat status na kazna.
Оваа функција е корисна кога системот треба брзо да прикаже дали одредена казна е платена, неплатена или поништена, без секогаш рачно да се проверува статусот преку табелите Kazna и StatusKazna.
2. fn_presmetaj_iznos_kazna
CREATE OR REPLACE FUNCTION fn_presmetaj_iznos_kazna(p_tip_prekrsok_id INTEGER)
RETURNS INTEGER
AS $$
DECLARE
v_iznos INTEGER;
BEGIN
SELECT iznos
INTO v_iznos
FROM TipPrekrsok
WHERE tip_prekrsok_id = p_tip_prekrsok_id;
IF v_iznos IS NULL THEN
RAISE EXCEPTION 'Ne postoi tip na prekrsok so id %', p_tip_prekrsok_id;
ELSIF v_iznos <= 0 THEN
RAISE EXCEPTION 'Iznosot na kaznata mora da bide pogolem od 0';
ELSE
RETURN v_iznos;
END IF;
END;
$$
LANGUAGE plpgsql;
Функцијата fn_presmetaj_iznos_kazna се користи за пресметување на износот на казната според типот на прекршок. Како параметар прима tip_prekrsok_id, а потоа од табелата TipPrekrsok го зема соодветниот износ.
Оваа функција се користи во процедурата за креирање прекршок со казна, каде што прво се пресметува износот, а потоа автоматски се креира запис во табелата Kazna.
Процедури
Процедурите се користат за извршување операции врз базата, како внесување, ажурирање и архивирање податоци.
1. sp_evidentiraj_plakanje
CREATE OR REPLACE PROCEDURE sp_evidentiraj_plakanje(
p_kazna_id INTEGER,
p_metod_plakanje_id INTEGER
)
AS $$
DECLARE
v_postoi_kazna INTEGER;
v_postoi_metod INTEGER;
v_status VARCHAR;
BEGIN
SELECT COUNT(*)
INTO v_postoi_kazna
FROM Kazna
WHERE kazna_id = p_kazna_id;
IF v_postoi_kazna = 0 THEN
RAISE EXCEPTION 'Ne postoi kazna so id %', p_kazna_id;
END IF;
SELECT COUNT(*)
INTO v_postoi_metod
FROM MetodPlakanje
WHERE metod_plakanje_id = p_metod_plakanje_id;
IF v_postoi_metod = 0 THEN
RAISE EXCEPTION 'Ne postoi metod na plakanje so id %', p_metod_plakanje_id;
END IF;
SELECT sk.ime
INTO v_status
FROM Kazna k
JOIN StatusKazna sk ON sk.status_kazna_id = k.status_kazna_id
WHERE k.kazna_id = p_kazna_id;
IF LOWER(v_status) = 'platena' THEN
RAISE EXCEPTION 'Kaznata e vekje platena';
ELSIF LOWER(v_status) = 'ponishtena' THEN
RAISE EXCEPTION 'Ponisthena kazna ne moze da se plati';
ELSE
INSERT INTO Plakanje(
metod_plakanje_id,
datum,
kazna_id
)
VALUES(
p_metod_plakanje_id,
CURRENT_DATE,
p_kazna_id
);
END IF;
END;
$$
LANGUAGE plpgsql;
Процедурата sp_evidentiraj_plakanje служи за евидентирање плаќање на казна. Како влезни параметри прима p_kazna_id, односно идентификатор на казната, и p_metod_plakanje_id, односно идентификатор на методот на плаќање. Најпрво процедурата проверува дали постои казна со дадениот идентификатор во табелата Kazna. Доколку не постои, се прикажува грешка. Потоа проверува дали постои метод на плаќање со дадениот идентификатор во табелата MetodPlakanje.
Со помош на IF / ELSIF / ELSE проверки, процедурата го зема моменталниот статус на казната преку табелата StatusKazna. Ако казната е веќе platena, се прикажува грешка дека казната е веќе платена. Ако казната е ponishtena, се прикажува грешка дека поништена казна не може да се плати. Во спротивно, ако казната може да се плати, се креира нов запис во табелата Plakanje, каде што се зачувуваат методот на плаќање, тековниот датум и идентификаторот на казната.
Оваа процедура е корисна бидејќи ја автоматизира операцијата за плаќање казна и спречува нелогични ситуации, како повторно плаќање на веќе платена казна или плаќање на поништена казна.
2. sp_podnesi_zalba
CREATE OR REPLACE PROCEDURE sp_podnesi_zalba(
p_sodrzina VARCHAR,
p_korisnik_id INTEGER,
p_prekrsok_id INTEGER
)
AS $$
DECLARE
v_status_podnesena INTEGER;
v_postoi_korisnik INTEGER;
v_postoi_prekrsok INTEGER;
BEGIN
IF p_sodrzina IS NULL OR LENGTH(TRIM(p_sodrzina)) = 0 THEN
RAISE EXCEPTION 'Zalbata mora da ima sodrzina';
END IF;
SELECT COUNT(*)
INTO v_postoi_korisnik
FROM Korisnik
WHERE korisnik_id = p_korisnik_id;
IF v_postoi_korisnik = 0 THEN
RAISE EXCEPTION 'Ne postoi korisnik so id %', p_korisnik_id;
END IF;
SELECT COUNT(*)
INTO v_postoi_prekrsok
FROM Prekrsok
WHERE prekrsok_id = p_prekrsok_id;
IF v_postoi_prekrsok = 0 THEN
RAISE EXCEPTION 'Ne postoi prekrsok so id %', p_prekrsok_id;
END IF;
SELECT status_zalba_id
INTO v_status_podnesena
FROM StatusZalba
WHERE LOWER(ime) = 'podnesena';
IF v_status_podnesena IS NULL THEN
RAISE EXCEPTION 'Vo StatusZalba ne postoi status podnesena';
ELSE
INSERT INTO Zalba(
sodrzina,
datum_na_podnesuvanje,
status_zalba_id,
korisnik_id,
prekrsok_id
)
VALUES(
p_sodrzina,
CURRENT_DATE,
v_status_podnesena,
p_korisnik_id,
p_prekrsok_id
);
END IF;
END;
$$
LANGUAGE plpgsql;
Процедурата sp_podnesi_zalba се користи за поднесување жалба од страна на корисник. Како параметри прима содржина на жалбата, идентификатор на корисник и идентификатор на прекршок. При внесување, статусот автоматски се поставува на podnesena.
Ова овозможува секоја нова жалба да започне со почетен статус и да биде поврзана со конкретен корисник и конкретен прекршок.
3. sp_razgledaj_zalba
CREATE OR REPLACE PROCEDURE sp_razgledaj_zalba(
p_zalba_id INTEGER,
p_administrator_id INTEGER,
p_nov_status VARCHAR
)
AS $$
DECLARE
v_status_id INTEGER;
v_postoi_zalba INTEGER;
v_postoi_admin INTEGER;
BEGIN
SELECT COUNT(*)
INTO v_postoi_zalba
FROM Zalba
WHERE zalba_id = p_zalba_id;
IF v_postoi_zalba = 0 THEN
RAISE EXCEPTION 'Ne postoi zalba so id %', p_zalba_id;
END IF;
SELECT COUNT(*)
INTO v_postoi_admin
FROM Administrator
WHERE administrator_id = p_administrator_id;
IF v_postoi_admin = 0 THEN
RAISE EXCEPTION 'Ne postoi administrator so id %', p_administrator_id;
END IF;
SELECT status_zalba_id
INTO v_status_id
FROM StatusZalba
WHERE LOWER(ime) = LOWER(p_nov_status);
IF v_status_id IS NULL THEN
RAISE EXCEPTION 'Ne postoi status na zalba so ime %', p_nov_status;
ELSE
UPDATE Zalba
SET administrator_id = p_administrator_id,
status_zalba_id = v_status_id
WHERE zalba_id = p_zalba_id;
END IF;
END;
$$
LANGUAGE plpgsql;
Процедурата sp_razgledaj_zalba се користи кога администратор разгледува жалба. Таа го ажурира администраторот кој ја обработува жалбата и го менува нејзиниот статус.
Оваа процедура ја претставува логиката за управување со жалби во системот, односно премин од поднесена жалба кон понатамошна обработка.
4. sp_arhiviraj_stari_snimki
CREATE OR REPLACE PROCEDURE sp_arhiviraj_stari_snimki()
AS $$
DECLARE
v_broj_snimki INTEGER;
BEGIN
SELECT COUNT(*)
INTO v_broj_snimki
FROM Snimka
WHERE datum < CURRENT_DATE - INTERVAL '365 days'
AND arhivirana = FALSE;
IF v_broj_snimki = 0 THEN
RAISE NOTICE 'Nema snimki za arhiviranje';
ELSE
UPDATE Snimka
SET arhivirana = TRUE,
datum_arhiviranje = CURRENT_DATE
WHERE datum < CURRENT_DATE - INTERVAL '365 days'
AND arhivirana = FALSE;
RAISE NOTICE 'Arhivirani se % snimki', v_broj_snimki;
END IF;
END;
$$
LANGUAGE plpgsql;
Процедурата sp_arhiviraj_stari_snimki ги архивира старите снимки кои се постари од една година. Таа ги ажурира записите во табелата Snimka, поставува arhivirana = TRUE и внесува датум на архивирање.
Оваа процедура е корисна за одржување на базата, бидејќи старите снимки не мора постојано да се третираат како активни податоци.
5. sp_kreiraj_prekrsok_so_kazna
CREATE OR REPLACE PROCEDURE sp_kreiraj_prekrsok_so_kazna(
p_opis VARCHAR,
p_vreme TIME,
p_datum DATE,
p_detektirana_brzina INTEGER,
p_tip_prekrsok_id INTEGER,
p_kamera_id INTEGER,
p_storitel_embg VARCHAR
)
AS $$
DECLARE
v_kazna_id INTEGER;
v_prekrsok_id INTEGER;
v_iznos INTEGER;
v_status_kazna_id INTEGER;
v_status_prekrsok_id INTEGER;
v_postoi_tip INTEGER;
v_postoi_kamera INTEGER;
v_postoi_gragjanin INTEGER;
BEGIN
IF p_opis IS NULL OR LENGTH(TRIM(p_opis)) = 0 THEN
RAISE EXCEPTION 'Opisot na prekrsokot ne smee da bide prazen';
END IF;
IF p_datum IS NULL THEN
p_datum := CURRENT_DATE;
END IF;
IF p_detektirana_brzina IS NULL OR p_detektirana_brzina <= 0 THEN
RAISE EXCEPTION 'Detektiranata brzina mora da bide pogolema od 0';
END IF;
IF p_storitel_embg IS NULL OR LENGTH(TRIM(p_storitel_embg)) <> 13 THEN
RAISE EXCEPTION 'EMBG na storitelot mora da ima 13 karakteri';
END IF;
SELECT COUNT(*)
INTO v_postoi_gragjanin
FROM Gragjanin
WHERE embg = p_storitel_embg;
IF v_postoi_gragjanin = 0 THEN
RAISE EXCEPTION 'Ne postoi gragjanin so EMBG %', p_storitel_embg;
END IF;
SELECT COUNT(*)
INTO v_postoi_tip
FROM TipPrekrsok
WHERE tip_prekrsok_id = p_tip_prekrsok_id;
IF v_postoi_tip = 0 THEN
RAISE EXCEPTION 'Ne postoi tip prekrsok so id %', p_tip_prekrsok_id;
END IF;
SELECT COUNT(*)
INTO v_postoi_kamera
FROM Kamera
WHERE kamera_id = p_kamera_id;
IF v_postoi_kamera = 0 THEN
RAISE EXCEPTION 'Ne postoi kamera so id %', p_kamera_id;
END IF;
SELECT status_kazna_id
INTO v_status_kazna_id
FROM StatusKazna
WHERE LOWER(ime) = 'neplatena';
IF v_status_kazna_id IS NULL THEN
RAISE EXCEPTION 'Vo StatusKazna ne postoi status neplatena';
END IF;
SELECT status_prekrsok_id
INTO v_status_prekrsok_id
FROM StatusPrekrsok
WHERE LOWER(ime) = 'aktiven';
IF v_status_prekrsok_id IS NULL THEN
RAISE EXCEPTION 'Vo StatusPrekrsok ne postoi status aktiven';
END IF;
v_iznos := fn_presmetaj_iznos_kazna(p_tip_prekrsok_id);
INSERT INTO Kazna(
datum,
status_kazna_id,
iznos_za_plakanje
)
VALUES(
CURRENT_DATE,
v_status_kazna_id,
v_iznos
)
RETURNING kazna_id INTO v_kazna_id;
INSERT INTO Prekrsok(
opis,
vreme,
status_prekrsok_id,
datum,
detektirana_brzina,
tip_prekrsok_id,
kamera_id,
kazna_id
)
VALUES(
p_opis,
p_vreme,
v_status_prekrsok_id,
p_datum,
p_detektirana_brzina,
p_tip_prekrsok_id,
p_kamera_id,
v_kazna_id
)
RETURNING prekrsok_id INTO v_prekrsok_id;
INSERT INTO Prekrsok_Storitel(
prekrsok_id,
storitel_embg
)
VALUES(
v_prekrsok_id,
p_storitel_embg
);
END;
$$
LANGUAGE plpgsql;
Процедурата sp_kreiraj_prekrsok_so_kazna автоматски креира прекршок заедно со соодветна казна. Најпрво се повикува функцијата fn_presmetaj_iznos_kazna, со која се пресметува износот на казната според типот на прекршок. Потоа се внесува нов запис во табелата Kazna, а добиениот kazna_id се користи при внесување на нов прекршок во табелата Prekrsok.
Оваа процедура е важна бидејќи поврзува две операции во една целина: креирање казна и креирање прекршок.
Тригери
Тригерите се користат за автоматско извршување логика при внесување или промена на податоци во табелите.
1. trg_auto_rok_kazna
CREATE OR REPLACE FUNCTION trg_fn_auto_rok_kazna()
RETURNS TRIGGER
AS $$
BEGIN
IF NEW.datum IS NULL THEN
NEW.datum := CURRENT_DATE;
END IF;
IF NEW.rok_na_plakanje IS NULL THEN
NEW.rok_na_plakanje := NEW.datum + INTERVAL '30 days';
ELSIF NEW.rok_na_plakanje < NEW.datum THEN
RAISE EXCEPTION 'Rokot za plakanje ne moze da bide pred datumot na kaznata';
ELSE
RETURN NEW;
END IF;
RETURN NEW;
END;
$$
LANGUAGE plpgsql;
Тригерот trg_auto_rok_kazna се активира пред внесување нова казна во табелата Kazna. Ако не е внесен датум, автоматски се поставува тековниот датум. Ако не е внесен рок за плаќање, тој автоматски се пресметува како 30 дена по датумот на казната.
Со ова се избегнува рачно внесување на рок за секоја казна и се обезбедува конзистентност во системот.
2. trg_kazna_platena
CREATE OR REPLACE FUNCTION trg_fn_kazna_platena()
RETURNS TRIGGER
AS $$
DECLARE
v_status_platena_id INTEGER;
v_status_momentalen VARCHAR;
BEGIN
SELECT sk.ime
INTO v_status_momentalen
FROM Kazna k
JOIN StatusKazna sk ON sk.status_kazna_id = k.status_kazna_id
WHERE k.kazna_id = NEW.kazna_id;
IF v_status_momentalen IS NULL THEN
RAISE EXCEPTION 'Kaznata ne postoi';
ELSIF LOWER(v_status_momentalen) = 'ponishtena' THEN
RAISE EXCEPTION 'Ponisthena kazna ne moze da se oznaci kako platena';
ELSE
SELECT status_kazna_id
INTO v_status_platena_id
FROM StatusKazna
WHERE LOWER(ime) = 'platena';
IF v_status_platena_id IS NULL THEN
RAISE EXCEPTION 'Vo StatusKazna ne postoi status platena';
ELSE
UPDATE Kazna
SET status_kazna_id = v_status_platena_id
WHERE kazna_id = NEW.kazna_id;
END IF;
END IF;
RETURN NEW;
END;
$$
LANGUAGE plpgsql;
Тригерот trg_kazna_platena се активира по внесување запис во табелата Plakanje. Кога ќе се евидентира плаќање, тригерот автоматски го ажурира статусот на соодветната казна во табелата Kazna и го поставува на 1, што означува дека казната е платена.
Ова овозможува автоматско поврзување меѓу плаќањето и статусот на казната.
3. trg_validacija_zalba
CREATE OR REPLACE FUNCTION trg_fn_validacija_zalba()
RETURNS TRIGGER
AS $$
DECLARE
v_status_prekrsok VARCHAR;
BEGIN
IF NEW.sodrzina IS NULL OR LENGTH(TRIM(NEW.sodrzina)) = 0 THEN
RAISE EXCEPTION 'Zalbata mora da ima sodrzina';
END IF;
IF NEW.datum_na_podnesuvanje IS NULL THEN
NEW.datum_na_podnesuvanje := CURRENT_DATE;
END IF;
SELECT sp.ime
INTO v_status_prekrsok
FROM Prekrsok p
JOIN StatusPrekrsok sp ON sp.status_prekrsok_id = p.status_prekrsok_id
WHERE p.prekrsok_id = NEW.prekrsok_id;
IF v_status_prekrsok IS NULL THEN
RAISE EXCEPTION 'Ne postoi prekrsok za koj se podnesuva zalbata';
ELSIF LOWER(v_status_prekrsok) = 'ponishten' THEN
RAISE EXCEPTION 'Ne moze da se podnese zalba za ponishten prekrsok';
ELSE
RETURN NEW;
END IF;
END;
$$
LANGUAGE plpgsql;
Тригерот trg_validacija_zalba се активира пред внесување нова жалба во табелата Zalba. Тој проверува дали содржината на жалбата е празна или NULL. Ако нема содржина, тригерот фрла грешка и не дозволува внесување на невалидна жалба.
Овој тригер служи како дополнителна заштита за квалитетот на податоците во базата.
Attachments (1)
- phase04.sql (11.8 KB ) - added by 6 hours ago.
Download all attachments as: .zip
