wiki:Triggers

Version 6 (modified by 222004, 37 hours ago) ( diff )

--

Тригери

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

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


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

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 'Количината не смее да биде негативна';
  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 на табелата payment.
Зошто е корисен: Автоматска интеграција на лојалност со финансиски трансакции.

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 на табелата sensitiveclientdata.
Зошто е корисен: Автоматски ја усогласува регулаторната состојба на клиентот со 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 на табелата medicineinteraction.
Зошто е корисен: Гарантира уникатни и чисти парови лекови.

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 'Лек не може да биде во интеракција сам со себе';
  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 на табелата inventory_brandedmedicine.
Зошто е корисен: Ја одржува усогласеноста меѓу залихи и каталог, без рачна интервенција.

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();


6) Тригер за блокирање на клиент со повеќе неуспешни плаќања


Што прави: Кога клиент има 3 или повеќе неуспешни плаќања во последните 10 дена, автоматски го поставува is_verified = FALSE во табелата Client.
Кога се активира: По INSERT или UPDATE на табелата payment кога статусот е „неуспешно“.
Зошто е корисен: Спречува понатамошни обиди за нарачки и злоупотреба од клиенти со повеќекратни неуспешни трансакции, со што ја зголемува безбедноста и стабилноста на системот.

CREATE OR REPLACE FUNCTION synergymed.fn_block_client_after_failed_payment()
RETURNS TRIGGER
LANGUAGE plpgsql
AS $$
DECLARE
  v_failures INT;
BEGIN
  SELECT COUNT(*) INTO v_failures
  FROM synergymed.payment p
  WHERE p.client_id = NEW.client_id
    AND p.status = 'неуспешно'
    AND p.payment_date >= (CURRENT_DATE - INTERVAL '10 days');

  IF v_failures >= 3 THEN
    UPDATE synergymed.client
    SET is_verified = FALSE
    WHERE user_id = NEW.client_id;
  END IF;

  RETURN NEW;
END;
$$;

DROP TRIGGER IF EXISTS trg_block_client_after_failed_payment ON synergymed.payment;

CREATE TRIGGER trg_block_client_after_failed_payment
AFTER INSERT OR UPDATE OF status ON synergymed.payment
FOR EACH ROW
WHEN (NEW.status = 'неуспешно')
EXECUTE FUNCTION synergymed.fn_block_client_after_failed_payment();

Note: See TracWiki for help on using the wiki.