DDL, DML and Views: planora_views.sql

File planora_views.sql, 11.6 KB (added by 231116, 6 days ago)
Line 
1-- views
2-- za host da vidi detalji za eden booking
3CREATE OR REPLACE VIEW vw_booking_overview AS
4SELECT
5 b.booking_id,
6 b.booking_status,
7 b.booked_at,
8 b.check_in_date,
9 b.check_out_date,
10 (b.check_out_date - b.check_in_date) AS nights,
11 b.guests_count,
12 b.total_price,
13
14 g.guest_id,
15 u_g.user_id AS guest_user_id,
16 u_g.first_name || ' ' || u_g.last_name AS guest_full_name,
17 u_g.email AS guest_email,
18
19 r.room_id,
20 r.room_name,
21 r.capacity AS room_capacity,
22 r.price_per_night,
23 rt.type_name AS room_type,
24
25 p.property_id,
26 p.title AS property_title,
27 p.status AS property_status,
28 lt.type_name AS listing_type,
29
30 a.city,
31 a.street,
32 co.country_name,
33
34 u_h.user_id AS host_user_id,
35 u_h.first_name || ' ' || u_h.last_name AS host_full_name,
36 u_h.email AS host_email
37
38FROM bookings b
39JOIN guests g ON g.guest_id = b.guest_id
40JOIN users u_g ON u_g.user_id = g.user_id
41JOIN rooms r ON r.room_id = b.room_id
42JOIN room_types rt ON rt.room_type_id = r.room_type_id
43JOIN properties p ON p.property_id = r.property_id
44JOIN listing_types lt ON lt.listing_type_id = p.listing_type_id
45JOIN addresses a ON a.address_id = p.address_id
46JOIN countries co ON co.country_id = a.country_id
47JOIN hosts h ON h.user_id = p.host_id
48JOIN users u_h ON u_h.user_id = h.user_id;
49
50-- za host da vidi status na plakjanje za sekoj booking
51CREATE OR REPLACE VIEW vw_payment_status AS
52SELECT
53 b.booking_id,
54 b.booking_status,
55 b.total_price AS booking_total,
56 b.check_in_date,
57 b.check_out_date,
58
59 pay.payment_id,
60 pay.payment_status,
61 pay.amount AS payment_amount,
62 pay.paid_at,
63 pm.method_name AS payment_method,
64
65 CASE
66 WHEN pay.payment_id IS NULL THEN 'NO_PAYMENT'
67 WHEN pay.payment_status = 'PAID' AND pay.amount < b.total_price THEN 'UNDERPAID'
68 WHEN pay.payment_status = 'PAID' AND pay.amount > b.total_price THEN 'OVERPAID'
69 ELSE pay.payment_status
70 END AS reconciliation_status,
71
72 u_g.first_name || ' ' || u_g.last_name AS guest_full_name,
73 u_g.email AS guest_email,
74
75 p.property_id,
76 p.title AS property_title,
77
78 u_h.first_name || ' ' || u_h.last_name AS host_full_name
79
80FROM bookings b
81JOIN guests g ON g.guest_id = b.guest_id
82JOIN users u_g ON u_g.user_id = g.user_id
83JOIN rooms r ON r.room_id = b.room_id
84JOIN properties p ON p.property_id = r.property_id
85JOIN hosts h ON h.user_id = p.host_id
86JOIN users u_h ON u_h.user_id = h.user_id
87LEFT JOIN payments pay ON pay.booking_id = b.booking_id
88LEFT JOIN payment_methods pm ON pm.payment_method_id = pay.payment_method_id;
89
90
91-- za gosti da mozat da vidat celosni informacii za eden property
92CREATE OR REPLACE VIEW vw_property_summary AS
93SELECT
94 p.property_id,
95 p.title,
96 p.description,
97 p.base_price,
98 p.max_guests,
99 p.status,
100 p.created_at,
101 lt.type_name AS listing_type,
102
103 a.street,
104 a.city,
105 a.zip_code,
106 co.country_name,
107 co.country_code,
108
109 h.user_id AS host_id,
110 u.first_name || ' ' || u.last_name AS host_full_name,
111 u.email AS host_email,
112
113 COUNT(DISTINCT r.room_id) AS room_count,
114 MIN(r.price_per_night) AS min_room_price,
115 MAX(r.price_per_night) AS max_room_price,
116
117 COUNT(DISTINCT rv.review_id) AS review_count,
118 ROUND(AVG(rv.rating)::numeric, 2) AS avg_rating,
119
120 cp.policy_name,
121 cp.refund_percentage,
122 cp.days_before_checking
123
124FROM properties p
125JOIN listing_types lt ON lt.listing_type_id = p.listing_type_id
126JOIN addresses a ON a.address_id = p.address_id
127JOIN countries co ON co.country_id = a.country_id
128JOIN hosts h ON h.user_id = p.host_id
129JOIN users u ON u.user_id = h.user_id
130LEFT JOIN rooms r ON r.property_id = p.property_id
131LEFT JOIN reviews rv ON rv.property_id = p.property_id
132LEFT JOIN cancellation_policies cp ON cp.property_id = p.property_id
133GROUP BY
134 p.property_id, p.title, p.description, p.base_price, p.max_guests,
135 p.status, p.created_at, lt.type_name,
136 a.street, a.city, a.zip_code,
137 co.country_name, co.country_code,
138 h.user_id, u.first_name, u.last_name, u.email,
139 cp.policy_name, cp.refund_percentage, cp.days_before_checking;
140
141
142-- za host da vidi svoi performansi
143CREATE OR REPLACE VIEW vw_host_performance AS
144SELECT
145 h.user_id AS host_id,
146 u.first_name || ' ' || u.last_name AS host_full_name,
147 u.email,
148 u.created_at AS member_since,
149
150 COUNT(DISTINCT p.property_id) AS total_properties,
151 COUNT(DISTINCT r.room_id) AS total_rooms,
152
153 COUNT(DISTINCT b.booking_id) AS total_bookings,
154 COUNT(DISTINCT b.booking_id) FILTER (WHERE b.booking_status = 'COMPLETED') AS completed_bookings,
155 COUNT(DISTINCT b.booking_id) FILTER (WHERE b.booking_status = 'CANCELLED') AS cancelled_bookings,
156
157 COALESCE(SUM(pay.amount) FILTER (WHERE pay.payment_status = 'PAID'), 0) AS total_revenue,
158
159 ROUND(AVG(rv.rating)::numeric, 2) AS avg_rating,
160 COUNT(DISTINCT rv.review_id) AS total_reviews
161
162FROM hosts h
163JOIN users u ON u.user_id = h.user_id
164LEFT JOIN properties p ON p.host_id = h.user_id
165LEFT JOIN rooms r ON r.property_id = p.property_id
166LEFT JOIN bookings b ON b.room_id = r.room_id
167LEFT JOIN payments pay ON pay.booking_id = b.booking_id
168LEFT JOIN reviews rv ON rv.property_id = p.property_id
169GROUP BY h.user_id, u.first_name, u.last_name, u.email, u.created_at;
170
171
172
173-- za sekoj gost da se vidi negovata aktivnost
174CREATE OR REPLACE VIEW vw_guest_activity AS
175SELECT
176 g.guest_id,
177 u.user_id,
178 u.first_name || ' ' || u.last_name AS guest_full_name,
179 u.email,
180 u.phone,
181 u.created_at AS member_since,
182
183 COUNT(DISTINCT b.booking_id) AS total_bookings,
184 COUNT(DISTINCT b.booking_id) FILTER (WHERE b.booking_status = 'COMPLETED') AS completed_bookings,
185 COUNT(DISTINCT b.booking_id) FILTER (WHERE b.booking_status = 'CANCELLED') AS cancelled_bookings,
186 COUNT(DISTINCT b.booking_id) FILTER (WHERE b.booking_status = 'NO_SHOW') AS no_shows,
187
188 COALESCE(SUM(b.total_price) FILTER (WHERE b.booking_status = 'COMPLETED'), 0) AS total_spend,
189
190 ROUND(AVG(b.total_price) FILTER (WHERE b.booking_status = 'COMPLETED')::numeric, 2) AS avg_booking_value,
191
192 COUNT(DISTINCT rv.review_id) AS reviews_written,
193 ROUND(AVG(rv.rating)::numeric, 2) AS avg_rating_given,
194
195 COUNT(DISTINCT fl.favorite_id) AS total_favorites,
196
197 MAX(b.booked_at) AS last_booking_at
198
199FROM guests g
200JOIN users u ON u.user_id = g.user_id
201LEFT JOIN bookings b ON b.guest_id = g.guest_id
202LEFT JOIN reviews rv ON rv.guest_id = g.guest_id
203LEFT JOIN favorite_listings fl ON fl.user_id = u.user_id
204WHERE g.guest_id <> -1
205GROUP BY g.guest_id, u.user_id, u.first_name, u.last_name, u.email, u.phone, u.created_at;
206
207
208
209-- pregled na prihodi po property
210CREATE OR REPLACE VIEW vw_revenue_by_property AS
211SELECT
212 p.property_id,
213 p.title AS property_title,
214 p.status AS property_status,
215 lt.type_name AS listing_type,
216 a.city,
217 co.country_name,
218
219 u.user_id AS host_id,
220 u.first_name || ' ' || u.last_name AS host_full_name,
221
222 COUNT(DISTINCT b.booking_id) AS total_bookings,
223 COUNT(DISTINCT b.booking_id) FILTER (WHERE b.booking_status = 'COMPLETED') AS completed_bookings,
224 COUNT(DISTINCT b.booking_id) FILTER (WHERE b.booking_status = 'CANCELLED') AS cancelled_bookings,
225
226 COALESCE(SUM(pay.amount) FILTER (WHERE pay.payment_status = 'PAID'), 0) AS total_revenue,
227
228 ROUND(
229 COALESCE(SUM(pay.amount) FILTER (WHERE pay.payment_status = 'PAID'), 0)
230 / NULLIF(COUNT(DISTINCT b.booking_id) FILTER (WHERE pay.payment_status = 'PAID'), 0),
231 2) AS avg_revenue_per_booking,
232
233 ROUND(AVG(rv.rating)::numeric, 2) AS avg_rating,
234 COUNT(DISTINCT rv.review_id) AS review_count
235
236FROM properties p
237JOIN listing_types lt ON lt.listing_type_id = p.listing_type_id
238JOIN addresses a ON a.address_id = p.address_id
239JOIN countries co ON co.country_id = a.country_id
240JOIN hosts h ON h.user_id = p.host_id
241JOIN users u ON u.user_id = h.user_id
242LEFT JOIN rooms r ON r.property_id = p.property_id
243LEFT JOIN bookings b ON b.room_id = r.room_id
244LEFT JOIN payments pay ON pay.booking_id = b.booking_id
245LEFT JOIN reviews rv ON rv.property_id = p.property_id
246GROUP BY
247 p.property_id, p.title, p.status, lt.type_name,
248 a.city, co.country_name, u.user_id, u.first_name, u.last_name;
249
250
251
252-- Za host i za gost - celosni informacii za sekoj review
253CREATE OR REPLACE VIEW vw_review_summary AS
254SELECT
255 rv.review_id,
256 rv.rating,
257 rv.comment,
258 rv.created_at AS reviewed_at,
259
260 rv.booking_id,
261 b.check_in_date,
262 b.check_out_date,
263 b.booking_status,
264
265 u_g.user_id AS guest_user_id,
266 u_g.first_name || ' ' || u_g.last_name AS guest_full_name,
267
268 p.property_id,
269 p.title AS property_title,
270 a.city,
271 co.country_name,
272
273 u_h.user_id AS host_user_id,
274 u_h.first_name || ' ' || u_h.last_name AS host_full_name,
275
276 ROUND(AVG(rv.rating) OVER (PARTITION BY p.property_id)::numeric, 2) AS property_avg_rating
277
278FROM reviews rv
279JOIN bookings b ON b.booking_id = rv.booking_id
280JOIN guests g ON g.guest_id = rv.guest_id
281JOIN users u_g ON u_g.user_id = g.user_id
282JOIN properties p ON p.property_id = rv.property_id
283JOIN addresses a ON a.address_id = p.address_id
284JOIN countries co ON co.country_id = a.country_id
285JOIN hosts h ON h.user_id = p.host_id
286JOIN users u_h ON u_h.user_id = h.user_id;
287
288
289
290-- za gosti da vidat detalji za sekoja soba
291CREATE OR REPLACE VIEW vw_room_details AS
292SELECT
293 r.room_id,
294 r.room_name,
295 r.status AS room_status,
296 r.capacity,
297 r.extra_capacity,
298 r.capacity + r.extra_capacity AS max_capacity,
299 r.price_per_night,
300 r.extra_guest_price,
301 r.description AS room_description,
302 rt.type_name AS room_type,
303
304 p.property_id,
305 p.title AS property_title,
306 p.status AS property_status,
307 p.base_price AS property_base_price,
308 lt.type_name AS listing_type,
309
310 a.city,
311 a.street,
312 co.country_name,
313
314 u.user_id AS host_id,
315 u.first_name || ' ' || u.last_name AS host_full_name,
316
317 COUNT(DISTINCT ra.amenity_id) AS amenity_count
318
319FROM rooms r
320JOIN room_types rt ON rt.room_type_id = r.room_type_id
321JOIN properties p ON p.property_id = r.property_id
322JOIN listing_types lt ON lt.listing_type_id = p.listing_type_id
323JOIN addresses a ON a.address_id = p.address_id
324JOIN countries co ON co.country_id = a.country_id
325JOIN hosts h ON h.user_id = p.host_id
326JOIN users u ON u.user_id = h.user_id
327LEFT JOIN room_amenities ra ON ra.room_id = r.room_id
328LEFT JOIN bookings b ON b.room_id = r.room_id
329LEFT JOIN availability_blocks ab ON ab.room_id = r.room_id
330GROUP BY
331 r.room_id, r.room_name, r.status, r.capacity, r.extra_capacity,
332 r.price_per_night, r.extra_guest_price, r.description,
333 rt.type_name, p.property_id, p.title, p.status, p.base_price,
334 lt.type_name, a.city, a.street, co.country_name,
335 u.user_id, u.first_name, u.last_name;
336
337
338
339-- Za gosti da vidat koga nekoja soba vo nekoj property e slobodna
340CREATE OR REPLACE VIEW vw_availability_windows AS
341SELECT
342 aw.availability_window_id,
343 aw.room_id,
344
345 r.room_name,
346 r.capacity,
347 r.extra_capacity,
348 r.price_per_night,
349 r.status AS room_status,
350
351 aw.available_date,
352 aw.status AS availability_status,
353
354 CASE
355 WHEN aw.available_date < CURRENT_DATE THEN 'EXPIRED'
356 WHEN aw.status = 'AVAILABLE' THEN 'AVAILABLE'
357 WHEN aw.status = 'TAKEN' THEN 'TAKEN'
358 ELSE aw.status
359 END AS final_availability_status
360
361FROM availability_windows aw
362JOIN rooms r ON r.room_id = aw.room_id
363WHERE r.status = 'ACTIVE';