source: petify-backend/src/main/resources/db/migration/R__reviews_rules_and_views.sql

Last change on this file was 92e7c7a, checked in by veronika-ils <ilioskaveronika@…>, 8 hours ago

Petify fullstack project

  • Property mode set to 100644
File size: 4.6 KB
Line 
1DROP TRIGGER IF EXISTS trg_reviews_no_update ON reviews;
2DROP TRIGGER IF EXISTS trg_clinic_reviews_no_update ON clinic_reviews;
3DROP FUNCTION IF EXISTS petify_trg_reviews_no_update() cascade;
4
5
6-- A review_id can belong to either user_reviews or clinic_reviews, but not both
7CREATE OR REPLACE FUNCTION petify_trg_user_review_exclusive()
8 RETURNS trigger
9 LANGUAGE plpgsql
10AS $$
11BEGIN
12 IF EXISTS (
13 SELECT 1
14 FROM clinic_reviews cr
15 WHERE cr.review_id = NEW.review_id
16 ) THEN
17 RAISE EXCEPTION
18 'review_id % already used as clinic review (cannot also be user review)',
19 NEW.review_id;
20 END IF;
21
22 RETURN NEW;
23END;
24$$;
25
26
27DROP TRIGGER IF EXISTS trg_user_review_exclusive ON user_reviews;
28CREATE TRIGGER trg_user_review_exclusive
29 BEFORE INSERT
30 ON user_reviews
31 FOR EACH ROW
32EXECUTE FUNCTION petify_trg_user_review_exclusive();
33
34
35CREATE OR REPLACE FUNCTION petify_trg_clinic_review_exclusive()
36 RETURNS trigger
37 LANGUAGE plpgsql
38AS $$
39BEGIN
40 IF EXISTS (
41 SELECT 1
42 FROM user_reviews ur
43 WHERE ur.review_id = NEW.review_id
44 ) THEN
45 RAISE EXCEPTION
46 'review_id % already used as user review (cannot also be clinic review)',
47 NEW.review_id;
48 END IF;
49
50 RETURN NEW;
51END;
52$$;
53
54
55DROP TRIGGER IF EXISTS trg_clinic_review_exclusive ON clinic_reviews;
56CREATE TRIGGER trg_clinic_review_exclusive
57 BEFORE INSERT
58 ON clinic_reviews
59 FOR EACH ROW
60EXECUTE FUNCTION petify_trg_clinic_review_exclusive();
61
62
63-- Cooldown
64CREATE OR REPLACE FUNCTION petify_trg_user_reviews_cooldown()
65 RETURNS trigger
66 LANGUAGE plpgsql
67AS $$
68DECLARE
69 v_reviewer bigint;
70 v_created timestamp;
71BEGIN
72 SELECT reviewer_id, created_at
73 INTO v_reviewer, v_created
74 FROM reviews
75 WHERE review_id = NEW.review_id;
76
77 IF v_reviewer IS NULL THEN
78 RAISE EXCEPTION 'Base review % not found', NEW.review_id;
79 END IF;
80
81 IF v_reviewer = NEW.target_user_id THEN
82 RAISE EXCEPTION 'User cannot review themselves (user_id=%)', v_reviewer;
83 END IF;
84
85 IF EXISTS (
86 SELECT 1
87 FROM user_reviews ur
88 JOIN reviews r ON r.review_id = ur.review_id
89 WHERE r.reviewer_id = v_reviewer
90 AND ur.target_user_id = NEW.target_user_id
91 AND r.is_deleted = false
92 AND r.created_at >= v_created - interval '30 days'
93 AND r.review_id <> NEW.review_id
94 ) THEN
95 RAISE EXCEPTION
96 'Cooldown: reviewer % already reviewed user % within last 30 days',
97 v_reviewer, NEW.target_user_id;
98 END IF;
99
100 RETURN NEW;
101END;
102$$;
103
104
105DROP TRIGGER IF EXISTS trg_user_reviews_cooldown ON user_reviews;
106CREATE TRIGGER trg_user_reviews_cooldown
107 BEFORE INSERT
108 ON user_reviews
109 FOR EACH ROW
110EXECUTE FUNCTION petify_trg_user_reviews_cooldown();
111
112
113-- Cooldown
114CREATE OR REPLACE FUNCTION petify_trg_clinic_reviews_cooldown()
115 RETURNS trigger
116 LANGUAGE plpgsql
117AS $$
118DECLARE
119 v_reviewer bigint;
120 v_created timestamp;
121BEGIN
122 SELECT reviewer_id, created_at
123 INTO v_reviewer, v_created
124 FROM reviews
125 WHERE review_id = NEW.review_id;
126
127 IF v_reviewer IS NULL THEN
128 RAISE EXCEPTION 'Base review % not found', NEW.review_id;
129 END IF;
130
131 IF EXISTS (
132 SELECT 1
133 FROM clinic_reviews cr
134 JOIN reviews r ON r.review_id = cr.review_id
135 WHERE r.reviewer_id = v_reviewer
136 AND cr.target_clinic_id = NEW.target_clinic_id
137 AND r.is_deleted = false
138 AND r.created_at >= v_created - interval '30 days'
139 AND r.review_id <> NEW.review_id
140 ) THEN
141 RAISE EXCEPTION
142 'Cooldown: reviewer % already reviewed clinic % within last 30 days',
143 v_reviewer, NEW.target_clinic_id;
144 END IF;
145
146 RETURN NEW;
147END;
148$$;
149
150
151DROP TRIGGER IF EXISTS trg_clinic_reviews_cooldown ON clinic_reviews;
152CREATE TRIGGER trg_clinic_reviews_cooldown
153 BEFORE INSERT
154 ON clinic_reviews
155 FOR EACH ROW
156EXECUTE FUNCTION petify_trg_clinic_reviews_cooldown();
157
158
159CREATE OR REPLACE VIEW v_user_ratings AS
160SELECT
161 ur.target_user_id,
162 COUNT(*) FILTER (WHERE r.is_deleted = false) AS review_count,
163 ROUND(AVG(r.rating) FILTER (WHERE r.is_deleted = false), 2) AS avg_rating
164FROM user_reviews ur
165 JOIN reviews r ON r.review_id = ur.review_id
166GROUP BY ur.target_user_id;
167
168
169CREATE OR REPLACE VIEW v_clinic_ratings AS
170SELECT
171 cr.target_clinic_id,
172 COUNT(*) FILTER (WHERE r.is_deleted = false) AS review_count,
173 ROUND(AVG(r.rating) FILTER (WHERE r.is_deleted = false), 2) AS avg_rating
174FROM clinic_reviews cr
175 JOIN reviews r ON r.review_id = cr.review_id
176GROUP BY cr.target_clinic_id;
Note: See TracBrowser for help on using the repository browser.