wiki:Triggers

Version 1 (modified by 222004, 44 hours ago) ( diff )

--

Тригери

Приказ на дефинирани тригери, со нивната улога, кога се активираат и зошто се корисни.

1) Тригер за залиха (inventory_brandedmedicine) – сетирање датум и забрана за негативни количини


Што прави: Автоматски поставува last_changed на денешен датум и спречува quantity < 0.
Кога се активира: Пред INSERT и пред UPDATE.
Зошто е корисен: Осигурува конзистентност на залихата и забрана за нелогични вредности.

CREATE OR REPLACE FUNCTION synergymed.fn_inventory_bm_before()
RETURNS TRIGGER
LANGUAGE plpgsql AS $$
BEGIN
  IF NEW.quantity IS NULL OR NEW.quantity < 0 THEN
    RAISE EXCEPTION 'quantity must be non-negative';
  END IF;
  NEW.last_changed := CURRENT_DATE;
  RETURN NEW;
END;
$$;

DROP TRIGGER IF EXISTS trg_inventory_bm_before_ins ON synergymed.inventory_brandedmedicine;
CREATE TRIGGER trg_inventory_bm_before_ins
BEFORE INSERT ON synergymed.inventory_brandedmedicine
FOR EACH ROW EXECUTE FUNCTION synergymed.fn_inventory_bm_before();

DROP TRIGGER IF EXISTS trg_inventory_bm_before_upd ON synergymed.inventory_brandedmedicine;
CREATE TRIGGER trg_inventory_bm_before_upd
BEFORE UPDATE ON synergymed.inventory_brandedmedicine
FOR EACH ROW EXECUTE FUNCTION synergymed.fn_inventory_bm_before();


2) Тригер за лојалност (payment) – поени на клуб-картичка при успешно плаќање


Што прави: Додава поени на clubcard ако payment.status = 'завршено'.
Кога се активира: По INSERT или UPDATE.
Зошто е корисен: Автоматска интеграција на лојалност со финансиски трансакции.

CREATE OR REPLACE FUNCTION synergymed.fn_payment_loyalty_after()
RETURNS TRIGGER
LANGUAGE plpgsql AS $$
DECLARE v_inc INT;
BEGIN
  IF NEW.status = 'завршено' THEN
    IF EXISTS (SELECT 1 FROM synergymed.clubcard WHERE id = NEW.client_id) THEN
      v_inc := GREATEST(0, FLOOR(COALESCE(NEW.amount,0) / 10));
      UPDATE synergymed.clubcard
      SET points = points + v_inc
      WHERE id = NEW.client_id;
    END IF;
  END IF;
  RETURN NEW;
END;
$$;

DROP TRIGGER IF EXISTS trg_payment_loyalty ON synergymed.payment;
CREATE TRIGGER trg_payment_loyalty
AFTER INSERT OR UPDATE OF status, amount ON synergymed.payment
FOR EACH ROW EXECUTE FUNCTION synergymed.fn_payment_loyalty_after();


3) Тригер за верификација на клиент (sensitiveclientdata) – автоматско одразување во client.is_verified


Што прави: Ако verification_status = 'верифицирано', тогаш client.is_verified = TRUE; ако е 'одбиено' → FALSE.
Кога се активира: По INSERT или UPDATE.
Зошто е корисен: Автоматски ја усогласува регулаторната состојба на клиентот со flag-от во Client.

CREATE OR REPLACE FUNCTION synergymed.fn_sensitiveclientdata_affect_client_after()
RETURNS TRIGGER
LANGUAGE plpgsql AS $$
BEGIN
  IF NEW.verification_status = 'верифицирано' THEN
    UPDATE synergymed.client SET is_verified = TRUE WHERE id = NEW.client_id;
  ELSIF NEW.verification_status = 'одбиено' THEN
    UPDATE synergymed.client SET is_verified = FALSE WHERE id = NEW.client_id;
  END IF;
  RETURN NEW;
END;
$$;

DROP TRIGGER IF EXISTS trg_sensitiveclientdata_affect_client ON synergymed.sensitiveclientdata;
CREATE TRIGGER trg_sensitiveclientdata_affect_client
AFTER INSERT OR UPDATE OF verification_status ON synergymed.sensitiveclientdata
FOR EACH ROW EXECUTE FUNCTION synergymed.fn_sensitiveclientdata_affect_client_after();


4) Тригер за интеракции на лекови (medicineinteraction) – симетрија и анти-рефлексивност


Што прави: Спречува интеракција лек-со-себе, и редоследува пар (id1, id2) така што id1 < id2.
Кога се активира: Пред INSERT и UPDATE.
Зошто е корисен: Гарантира уникатни и чисти парови лекови.

CREATE OR REPLACE FUNCTION synergymed.fn_medicineinteraction_order_before()
RETURNS TRIGGER
LANGUAGE plpgsql AS $$
DECLARE a INT; b INT;
BEGIN
  IF NEW.medicine_id_1 = NEW.medicine_id_2 THEN
    RAISE EXCEPTION 'medicine cannot interact with itself';
  END IF;

  a := LEAST(NEW.medicine_id_1, NEW.medicine_id_2);
  b := GREATEST(NEW.medicine_id_1, NEW.medicine_id_2);
  NEW.medicine_id_1 := a;
  NEW.medicine_id_2 := b;
  RETURN NEW;
END;
$$;

DROP TRIGGER IF EXISTS trg_mi_order_before_ins ON synergymed.medicineinteraction;
CREATE TRIGGER trg_mi_order_before_ins
BEFORE INSERT ON synergymed.medicineinteraction
FOR EACH ROW EXECUTE FUNCTION synergymed.fn_medicineinteraction_order_before();

DROP TRIGGER IF EXISTS trg_mi_order_before_upd ON synergymed.medicineinteraction;
CREATE TRIGGER trg_mi_order_before_upd
BEFORE UPDATE ON synergymed.medicineinteraction
FOR EACH ROW EXECUTE FUNCTION synergymed.fn_medicineinteraction_order_before();

CREATE UNIQUE INDEX IF NOT EXISTS ux_mi_pair
ON synergymed.medicineinteraction (medicine_id_1, medicine_id_2);


5) Тригер за авто-ажурирање на каталогот на аптеки


Што прави: Кога се менува inventory_brandedmedicine, автоматски додава записи во pharmacy_catalog за да гарантира дека секој производ што е во залиха е и во каталогот на аптеката.
Кога се активира: По INSERT или UPDATE на quantity.
Зошто е корисен: Ја одржува усогласеноста меѓу залихи и каталог, без рачна интервенција.

CREATE OR REPLACE FUNCTION synergymed.fn_inventory_autocatalog_after()
RETURNS TRIGGER
LANGUAGE plpgsql AS $$
DECLARE 
  v_pharmacy_id INT;
BEGIN
  SELECT ph.company_id INTO v_pharmacy_id
  FROM synergymed.inventory i
  JOIN synergymed.facility f ON f.id = i.facility_id
  JOIN synergymed.pharmacy ph ON ph.company_id = f.company_id
  WHERE i.id = COALESCE(NEW.inventory_id, OLD.inventory_id)
  LIMIT 1;

  IF v_pharmacy_id IS NOT NULL THEN
    INSERT INTO synergymed.pharmacy_catalog(pharmacy_id, branded_medicine_id)
    VALUES (v_pharmacy_id, COALESCE(NEW.branded_medicine_id, OLD.branded_medicine_id))
    ON CONFLICT DO NOTHING;
  END IF;

  RETURN COALESCE(NEW, OLD);
END;
$$;

DROP TRIGGER IF EXISTS trg_inventory_autocatalog_ins ON synergymed.inventory_brandedmedicine;
CREATE TRIGGER trg_inventory_autocatalog_ins
AFTER INSERT ON synergymed.inventory_brandedmedicine
FOR EACH ROW EXECUTE FUNCTION synergymed.fn_inventory_autocatalog_after();

DROP TRIGGER IF EXISTS trg_inventory_autocatalog_upd ON synergymed.inventory_brandedmedicine;
CREATE TRIGGER trg_inventory_autocatalog_upd
AFTER UPDATE OF quantity ON synergymed.inventory_brandedmedicine
FOR EACH ROW EXECUTE FUNCTION synergymed.fn_inventory_autocatalog_after();

Note: See TracWiki for help on using the wiki.