= Тригери == 1. Тригер за спречување на преклопени договори по оглас * Тригер за забрана на преклопени изнајмувања (Lease) за ист оглас (Listing) ]. Целта е да се спречи креирање на изнајмувања со ранг на датуми кои се преклопуваат за ист Listing. Доколку новото (или изменетото) изнајмување се поклопува со постоечко, операцијата ќе биде одбиена со `RAISE EXCEPTION`. {{{ CREATE OR REPLACE FUNCTION domify.f_lease_no_overlap() RETURNS TRIGGER AS $$ DECLARE cnt INT; BEGIN SELECT COUNT(*) INTO cnt FROM domify."lease" WHERE listing_id = NEW.listing_id AND id <> COALESCE(NEW.id, -1) AND daterange(start_date, end_date, '[]') && daterange(NEW.start_date, NEW.end_date, '[]'); IF cnt > 0 THEN RAISE EXCEPTION 'Listing % веќе има договор кој се преклопува со периодот %–%', NEW.listing_id, NEW.start_date, NEW.end_date; END IF; RETURN NEW; END; $$ LANGUAGE plpgsql; CREATE TRIGGER t_lease_no_overlap BEFORE INSERT OR UPDATE ON domify."lease" FOR EACH ROW EXECUTE FUNCTION domify.f_lease_no_overlap(); }}} == 2. Тригери за суспендирање на рејтингот на станар при повеќекратни задоцнети плаќања * Доколку станар има три или повеќе задоцнети плаќања низ сите негови изнајмувања, неговиот UserD.rating се поставува на 0, а во биографијата се додава напомена дека е суспендиран. {{{ CREATE OR REPLACE FUNCTION suspend_rating_on_repeated_delinquency() RETURNS TRIGGER AS $$ DECLARE tenant_rec domify.Lease%ROWTYPE; late_payments INT; BEGIN SELECT * INTO tenant_rec FROM domify.Lease WHERE id = NEW.lease_id; IF FOUND THEN SELECT COUNT(*) INTO late_payments FROM domify.Payment p JOIN domify.Lease l ON p.lease_id = l.id WHERE l.tenant_id = tenant_rec.tenant_id AND p.status = 'доцнење'; IF late_payments >= 3 THEN UPDATE domify.UserD SET rating = 0.00, bio = 'Суспендиран станар поради повеќе доцнења на плаќање' WHERE id = (SELECT id FROM domify.UserD WHERE id = tenant_rec.tenant_id); END IF; END IF; RETURN NEW; END; $$ LANGUAGE plpgsql; CREATE TRIGGER trg_suspend_tenant_on_late_payments AFTER INSERT OR UPDATE ON domify.Payment FOR EACH ROW WHEN (NEW.status = 'доцнење') EXECUTE FUNCTION suspend_rating_on_repeated_delinquency(); }}} == 3. Тригер за закажување на инспекција на единицата веднаш по креирање на договор * Со овој тригер се креираат 3 инспекции на единицата веднаш по креирање на договорот, првата е пред да се всели изнајмувачот, втората се закажува за оние единици чии договор трае повеќе од 8 месеци и третата се закажува 7 дена пред да заврши договорот за да се направи финална проверка на единицата. Дополнително се прави проверка дали датумот за секоја од овие 3 инспекции е викенд, со што се прави поместување +1 за недела, +2дена за сабота со цел инспекциите да се одвиваат во работна недела. {{{ CREATE OR REPLACE FUNCTION domify.f_schedule_mandatory_inspections() RETURNS TRIGGER AS $$ DECLARE lease_duration_months INT; initial_inspection_date DATE; midterm_inspection_date DATE; final_inspection_date DATE; BEGIN lease_duration_months := EXTRACT(MONTH FROM AGE(NEW.end_date, NEW.start_date)) + EXTRACT(YEAR FROM AGE(NEW.end_date, NEW.start_date)) * 12; initial_inspection_date := domify.f_adjust_for_weekend((NEW.start_date - INTERVAL '1 day')::DATE); midterm_inspection_date := domify.f_adjust_for_weekend((NEW.start_date + INTERVAL '6 months')::DATE); final_inspection_date := domify.f_adjust_for_weekend((NEW.end_date - INTERVAL '7 days')::DATE); IF NEW.start_date > CURRENT_DATE + INTERVAL '1 day' THEN INSERT INTO domify.Inspection ( inspection_date, notes, lease_id, landlord_id ) VALUES ( initial_inspection_date, 'Почетна инспекција - проверка дали се е добро пред вселување' || CASE WHEN initial_inspection_date != (NEW.start_date - INTERVAL '1 day')::DATE THEN ' (поместена од викенд)' ELSE '' END, NEW.id, NEW.landlord_id ); END IF; IF lease_duration_months >= 8 THEN INSERT INTO domify.Inspection ( inspection_date, notes, lease_id, landlord_id ) VALUES ( midterm_inspection_date, 'Полугодишна инспекција - проверка на состојбата во која се наоѓа единицата' || CASE WHEN midterm_inspection_date != (NEW.start_date + INTERVAL '6 months')::DATE THEN ' (поместена од викенд)' ELSE '' END, NEW.id, NEW.landlord_id ); END IF; INSERT INTO domify.Inspection ( inspection_date, notes, lease_id, landlord_id ) VALUES ( final_inspection_date, 'Финална инспекција - оценка на штети и депозит' || CASE WHEN final_inspection_date != (NEW.end_date - INTERVAL '7 days')::DATE THEN ' (поместена од викенд)' ELSE '' END, NEW.id, NEW.landlord_id ); RETURN NEW; END; $$ LANGUAGE plpgsql; CREATE TRIGGER t_schedule_mandatory_inspections AFTER INSERT ON domify.Lease FOR EACH ROW EXECUTE FUNCTION domify.f_schedule_mandatory_inspections(); }}} Функцијата која се користи за поместувањето: {{{ CREATE OR REPLACE FUNCTION domify.f_adjust_for_weekend(input_date DATE) RETURNS DATE AS $$ BEGIN CASE EXTRACT(DOW FROM input_date) WHEN 0 THEN RETURN input_date + INTERVAL '1 day'; WHEN 6 THEN RETURN input_date + INTERVAL '2 days'; ELSE RETURN input_date; END CASE; END; $$ LANGUAGE plpgsql; }}}