| 39 | == Негативни/нулти количини и цени во {{{ORDER_BATCHES}}} |
| 40 | |
| 41 | Кога се извршува {{{INSERT}}} или {{{UPDATE}}} на {{{ORDER_BATCHES}}}, осигурај {{{quantity > 0}}} и {{{price_per_unit >= 0}}}; пресметај {{{total_price = quantity * price_per_unit}}} и постави {{{timestamps}}}. |
| 42 | |
| 43 | {{{ |
| 44 | CREATE OR REPLACE FUNCTION trg_order_batches_validate() RETURNS trigger AS $ |
| 45 | BEGIN |
| 46 | IF NEW.quantity IS NULL OR NEW.quantity <= 0 THEN |
| 47 | RAISE EXCEPTION 'quantity must be > 0'; |
| 48 | END IF; |
| 49 | IF NEW.price_per_unit IS NULL OR NEW.price_per_unit < 0 THEN |
| 50 | RAISE EXCEPTION 'price_per_unit must be >= 0'; |
| 51 | END IF; |
| 52 | NEW.total_price := NEW.quantity * NEW.price_per_unit; |
| 53 | NEW.updated_at := NOW(); |
| 54 | IF TG_OP = 'INSERT' THEN |
| 55 | NEW.created_at := NOW(); |
| 56 | END IF; |
| 57 | RETURN NEW; |
| 58 | END; |
| 59 | $ LANGUAGE plpgsql; |
| 60 | |
| 61 | CREATE TRIGGER order_batches_validate |
| 62 | BEFORE INSERT OR UPDATE ON order_batches |
| 63 | FOR EACH ROW EXECUTE FUNCTION trg_order_batches_validate(); |
| 64 | }}} |
| 65 | |
| 66 | == Нарачки со истечени серии |
| 67 | |
| 68 | Пред {{{INSERT}}} или {{{UPDATE}}} на {{{ORDER_BATCHES}}}, провери дали повиканата {{{BATCH}}} не е истечена според датумот на нарачката ({{{orders.date}}}). Се фрла {{{exception}}} ако {{{expiration_date < orders.date}}}. |
| 69 | |
| 70 | {{{ |
| 71 | CREATE OR REPLACE FUNCTION trg_order_batches_no_expired() RETURNS trigger AS $ |
| 72 | DECLARE |
| 73 | ord_date DATE; |
| 74 | batch_exp DATE; |
| 75 | BEGIN |
| 76 | SELECT date INTO ord_date FROM orders WHERE id = NEW.order_id; |
| 77 | SELECT expiration_date INTO batch_exp FROM batches WHERE id = NEW.batch_id; |
| 78 | IF ord_date IS NULL OR batch_exp IS NULL THEN |
| 79 | RAISE EXCEPTION 'order or batch not found'; |
| 80 | END IF; |
| 81 | IF batch_exp < ord_date THEN |
| 82 | RAISE EXCEPTION 'cannot add expired batch to order (batch % expired %)', NEW.batch_id, batch_exp; |
| 83 | END IF; |
| 84 | RETURN NEW; |
| 85 | END; |
| 86 | $ LANGUAGE plpgsql; |
| 87 | |
| 88 | CREATE TRIGGER order_batches_no_expired |
| 89 | BEFORE INSERT OR UPDATE ON order_batches |
| 90 | FOR EACH ROW EXECUTE FUNCTION trg_order_batches_no_expired(); |
| 91 | }}} |
| 92 | |
| 93 | == Бришење на {{{PRODUCERS/PRODUCTS/BATCHES}}} кои се реферирани |
| 94 | |
| 95 | Забрането бришење на: |
| 96 | |
| 97 | - {{{producer}}} ако постојат {{{products}}} |
| 98 | - {{{product}}} ако постојат {{{batches}}} |
| 99 | - {{{batch}}} ако е искористен во {{{order_batches}}}. |
| 100 | |
| 101 | {{{ |
| 102 | CREATE OR REPLACE FUNCTION trg_prevent_fk_deletes() RETURNS trigger AS $ |
| 103 | BEGIN |
| 104 | IF TG_TABLE_NAME = 'producers' THEN |
| 105 | IF EXISTS (SELECT 1 FROM products WHERE producer_id = OLD.id) THEN |
| 106 | RAISE EXCEPTION 'cannot delete producer with products'; |
| 107 | END IF; |
| 108 | ELSIF TG_TABLE_NAME = 'products' THEN |
| 109 | IF EXISTS (SELECT 1 FROM batches WHERE product_id = OLD.id) THEN |
| 110 | RAISE EXCEPTION 'cannot delete product with batches'; |
| 111 | END IF; |
| 112 | ELSIF TG_TABLE_NAME = 'batches' THEN |
| 113 | IF EXISTS (SELECT 1 FROM order_batches WHERE batch_id = OLD.id) THEN |
| 114 | RAISE EXCEPTION 'cannot delete batch referenced in orders'; |
| 115 | END IF; |
| 116 | END IF; |
| 117 | RETURN OLD; |
| 118 | END; |
| 119 | $ LANGUAGE plpgsql; |
| 120 | |
| 121 | CREATE TRIGGER prevent_delete_producers |
| 122 | BEFORE DELETE ON producers |
| 123 | FOR EACH ROW EXECUTE FUNCTION trg_prevent_fk_deletes(); |
| 124 | |
| 125 | CREATE TRIGGER prevent_delete_products |
| 126 | BEFORE DELETE ON products |
| 127 | FOR EACH ROW EXECUTE FUNCTION trg_prevent_fk_deletes(); |
| 128 | |
| 129 | CREATE TRIGGER prevent_delete_batches |
| 130 | BEFORE DELETE ON batches |
| 131 | FOR EACH ROW EXECUTE FUNCTION trg_prevent_fk_deletes(); |
| 132 | }}} |
| 133 | |
| 134 | == Автоматско ажурирање на {{{ORDER.status}}} според плаќања |
| 135 | |
| 136 | Кога {{{PAYMENT}}} се означува како {{{paid}}} ({{{payment_status = 'paid'}}} и {{{payment_date}}} не е {{{NULL}}}), провери {{{SUM(payments.amount) >= orders.total_amount}}}, а потоа постави {{{orders.status = 'paid'}}}. |
| 137 | |
| 138 | {{{ |
| 139 | CREATE OR REPLACE FUNCTION trg_payments_update_order_status() RETURNS trigger AS $ |
| 140 | DECLARE |
| 141 | paid_sum NUMERIC; |
| 142 | ord_total NUMERIC; |
| 143 | BEGIN |
| 144 | IF TG_OP = 'DELETE' THEN |
| 145 | RETURN OLD; |
| 146 | END IF; |
| 147 | |
| 148 | SELECT COALESCE(SUM(amount),0) INTO paid_sum FROM payments WHERE order_id = NEW.order_id AND payment_status = 'paid'; |
| 149 | SELECT COALESCE(total_amount,0) INTO ord_total FROM orders WHERE id = NEW.order_id; |
| 150 | |
| 151 | IF paid_sum >= ord_total AND ord_total > 0 THEN |
| 152 | UPDATE orders SET status = 'paid' WHERE id = NEW.order_id; |
| 153 | END IF; |
| 154 | RETURN NEW; |
| 155 | END; |
| 156 | $ LANGUAGE plpgsql; |
| 157 | |
| 158 | CREATE TRIGGER payments_update_order_status |
| 159 | AFTER INSERT OR UPDATE ON payments |
| 160 | FOR EACH ROW EXECUTE FUNCTION trg_payments_update_order_status(); |
| 161 | }}} |
| 162 | |
| 163 | == Известувања за промена на статус на нарачка |
| 164 | |
| 165 | Известување кога нарачката го променила статусот ({{{ORDER.status}}}) — испраќа {{{RAISE NOTICE}}} со ордедена порака |
| 166 | |
| 167 | {{{ |
| 168 | CREATE OR REPLACE FUNCTION trg_order_status_change_fun() |
| 169 | RETURNS trigger AS $ |
| 170 | BEGIN |
| 171 | IF TG_OP = 'UPDATE' AND NEW.status IS DISTINCT FROM OLD.status THEN |
| 172 | RAISE NOTICE 'Order % changed it's status: % → %', NEW.id, OLD.status, NEW.status; |
| 173 | IF NEW.status = 'shipped' OR NEW.status = 'delivered' THEN |
| 174 | RAISE NOTICE 'Good news! Order % is %!', NEW.id, NEW.status; |
| 175 | END IF; |
| 176 | END IF; |
| 177 | RETURN NEW; |
| 178 | END; |
| 179 | $ LANGUAGE plpgsql; |
| 180 | |
| 181 | DROP TRIGGER IF EXISTS trg_order_status_change ON orders; |
| 182 | CREATE TRIGGER trg_order_status_change |
| 183 | AFTER UPDATE ON orders |
| 184 | FOR EACH ROW |
| 185 | WHEN (OLD.status IS DISTINCT FROM NEW.status) |
| 186 | EXECUTE FUNCTION trg_order_status_change_fun(); |
| 187 | }}} |
| 188 | |