| 1 | -- views
|
|---|
| 2 | -- za host da vidi detalji za eden booking
|
|---|
| 3 | CREATE OR REPLACE VIEW vw_booking_overview AS
|
|---|
| 4 | SELECT
|
|---|
| 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 |
|
|---|
| 38 | FROM bookings b
|
|---|
| 39 | JOIN guests g ON g.guest_id = b.guest_id
|
|---|
| 40 | JOIN users u_g ON u_g.user_id = g.user_id
|
|---|
| 41 | JOIN rooms r ON r.room_id = b.room_id
|
|---|
| 42 | JOIN room_types rt ON rt.room_type_id = r.room_type_id
|
|---|
| 43 | JOIN properties p ON p.property_id = r.property_id
|
|---|
| 44 | JOIN listing_types lt ON lt.listing_type_id = p.listing_type_id
|
|---|
| 45 | JOIN addresses a ON a.address_id = p.address_id
|
|---|
| 46 | JOIN countries co ON co.country_id = a.country_id
|
|---|
| 47 | JOIN hosts h ON h.user_id = p.host_id
|
|---|
| 48 | JOIN users u_h ON u_h.user_id = h.user_id;
|
|---|
| 49 |
|
|---|
| 50 | -- za host da vidi status na plakjanje za sekoj booking
|
|---|
| 51 | CREATE OR REPLACE VIEW vw_payment_status AS
|
|---|
| 52 | SELECT
|
|---|
| 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 |
|
|---|
| 80 | FROM bookings b
|
|---|
| 81 | JOIN guests g ON g.guest_id = b.guest_id
|
|---|
| 82 | JOIN users u_g ON u_g.user_id = g.user_id
|
|---|
| 83 | JOIN rooms r ON r.room_id = b.room_id
|
|---|
| 84 | JOIN properties p ON p.property_id = r.property_id
|
|---|
| 85 | JOIN hosts h ON h.user_id = p.host_id
|
|---|
| 86 | JOIN users u_h ON u_h.user_id = h.user_id
|
|---|
| 87 | LEFT JOIN payments pay ON pay.booking_id = b.booking_id
|
|---|
| 88 | LEFT 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
|
|---|
| 92 | CREATE OR REPLACE VIEW vw_property_summary AS
|
|---|
| 93 | SELECT
|
|---|
| 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 |
|
|---|
| 124 | FROM properties p
|
|---|
| 125 | JOIN listing_types lt ON lt.listing_type_id = p.listing_type_id
|
|---|
| 126 | JOIN addresses a ON a.address_id = p.address_id
|
|---|
| 127 | JOIN countries co ON co.country_id = a.country_id
|
|---|
| 128 | JOIN hosts h ON h.user_id = p.host_id
|
|---|
| 129 | JOIN users u ON u.user_id = h.user_id
|
|---|
| 130 | LEFT JOIN rooms r ON r.property_id = p.property_id
|
|---|
| 131 | LEFT JOIN reviews rv ON rv.property_id = p.property_id
|
|---|
| 132 | LEFT JOIN cancellation_policies cp ON cp.property_id = p.property_id
|
|---|
| 133 | GROUP 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
|
|---|
| 143 | CREATE OR REPLACE VIEW vw_host_performance AS
|
|---|
| 144 | SELECT
|
|---|
| 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 |
|
|---|
| 162 | FROM hosts h
|
|---|
| 163 | JOIN users u ON u.user_id = h.user_id
|
|---|
| 164 | LEFT JOIN properties p ON p.host_id = h.user_id
|
|---|
| 165 | LEFT JOIN rooms r ON r.property_id = p.property_id
|
|---|
| 166 | LEFT JOIN bookings b ON b.room_id = r.room_id
|
|---|
| 167 | LEFT JOIN payments pay ON pay.booking_id = b.booking_id
|
|---|
| 168 | LEFT JOIN reviews rv ON rv.property_id = p.property_id
|
|---|
| 169 | GROUP 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
|
|---|
| 174 | CREATE OR REPLACE VIEW vw_guest_activity AS
|
|---|
| 175 | SELECT
|
|---|
| 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 |
|
|---|
| 199 | FROM guests g
|
|---|
| 200 | JOIN users u ON u.user_id = g.user_id
|
|---|
| 201 | LEFT JOIN bookings b ON b.guest_id = g.guest_id
|
|---|
| 202 | LEFT JOIN reviews rv ON rv.guest_id = g.guest_id
|
|---|
| 203 | LEFT JOIN favorite_listings fl ON fl.user_id = u.user_id
|
|---|
| 204 | WHERE g.guest_id <> -1
|
|---|
| 205 | GROUP 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
|
|---|
| 210 | CREATE OR REPLACE VIEW vw_revenue_by_property AS
|
|---|
| 211 | SELECT
|
|---|
| 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 |
|
|---|
| 236 | FROM properties p
|
|---|
| 237 | JOIN listing_types lt ON lt.listing_type_id = p.listing_type_id
|
|---|
| 238 | JOIN addresses a ON a.address_id = p.address_id
|
|---|
| 239 | JOIN countries co ON co.country_id = a.country_id
|
|---|
| 240 | JOIN hosts h ON h.user_id = p.host_id
|
|---|
| 241 | JOIN users u ON u.user_id = h.user_id
|
|---|
| 242 | LEFT JOIN rooms r ON r.property_id = p.property_id
|
|---|
| 243 | LEFT JOIN bookings b ON b.room_id = r.room_id
|
|---|
| 244 | LEFT JOIN payments pay ON pay.booking_id = b.booking_id
|
|---|
| 245 | LEFT JOIN reviews rv ON rv.property_id = p.property_id
|
|---|
| 246 | GROUP 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
|
|---|
| 253 | CREATE OR REPLACE VIEW vw_review_summary AS
|
|---|
| 254 | SELECT
|
|---|
| 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 |
|
|---|
| 278 | FROM reviews rv
|
|---|
| 279 | JOIN bookings b ON b.booking_id = rv.booking_id
|
|---|
| 280 | JOIN guests g ON g.guest_id = rv.guest_id
|
|---|
| 281 | JOIN users u_g ON u_g.user_id = g.user_id
|
|---|
| 282 | JOIN properties p ON p.property_id = rv.property_id
|
|---|
| 283 | JOIN addresses a ON a.address_id = p.address_id
|
|---|
| 284 | JOIN countries co ON co.country_id = a.country_id
|
|---|
| 285 | JOIN hosts h ON h.user_id = p.host_id
|
|---|
| 286 | JOIN users u_h ON u_h.user_id = h.user_id;
|
|---|
| 287 |
|
|---|
| 288 |
|
|---|
| 289 |
|
|---|
| 290 | -- za gosti da vidat detalji za sekoja soba
|
|---|
| 291 | CREATE OR REPLACE VIEW vw_room_details AS
|
|---|
| 292 | SELECT
|
|---|
| 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 |
|
|---|
| 319 | FROM rooms r
|
|---|
| 320 | JOIN room_types rt ON rt.room_type_id = r.room_type_id
|
|---|
| 321 | JOIN properties p ON p.property_id = r.property_id
|
|---|
| 322 | JOIN listing_types lt ON lt.listing_type_id = p.listing_type_id
|
|---|
| 323 | JOIN addresses a ON a.address_id = p.address_id
|
|---|
| 324 | JOIN countries co ON co.country_id = a.country_id
|
|---|
| 325 | JOIN hosts h ON h.user_id = p.host_id
|
|---|
| 326 | JOIN users u ON u.user_id = h.user_id
|
|---|
| 327 | LEFT JOIN room_amenities ra ON ra.room_id = r.room_id
|
|---|
| 328 | LEFT JOIN bookings b ON b.room_id = r.room_id
|
|---|
| 329 | LEFT JOIN availability_blocks ab ON ab.room_id = r.room_id
|
|---|
| 330 | GROUP 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
|
|---|
| 340 | CREATE OR REPLACE VIEW vw_availability_windows AS
|
|---|
| 341 | SELECT
|
|---|
| 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 |
|
|---|
| 361 | FROM availability_windows aw
|
|---|
| 362 | JOIN rooms r ON r.room_id = aw.room_id
|
|---|
| 363 | WHERE r.status = 'ACTIVE'; |
|---|