| | 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 | |