| 1 | CREATE OR REPLACE VIEW v_staff_daily_schedule AS
|
|---|
| 2 |
|
|---|
| 3 | SELECT
|
|---|
| 4 | -- Staff
|
|---|
| 5 | a.staff_id,
|
|---|
| 6 | u.first_name || ' ' || u.last_name AS staff_name,
|
|---|
| 7 |
|
|---|
| 8 | sr.role_types,
|
|---|
| 9 | sr.role_types_arr,
|
|---|
| 10 |
|
|---|
| 11 | -- Location
|
|---|
| 12 | cl.city,
|
|---|
| 13 | cl.address,
|
|---|
| 14 |
|
|---|
| 15 | -- Appointment timing
|
|---|
| 16 | a.appointment_date,
|
|---|
| 17 | a.appointment_time AS start_time,
|
|---|
| 18 | a.end_time,
|
|---|
| 19 | asa.total_duration_minutes AS duration_minutes,
|
|---|
| 20 |
|
|---|
| 21 | -- Client
|
|---|
| 22 | uc.first_name || ' ' || uc.last_name AS client_name,
|
|---|
| 23 | c.phone AS client_phone,
|
|---|
| 24 |
|
|---|
| 25 | -- Services & pricing
|
|---|
| 26 | asa.service_names,
|
|---|
| 27 | asa.total_price AS booked_price,
|
|---|
| 28 |
|
|---|
| 29 | -- Appointment meta
|
|---|
| 30 | a.appointment_id,
|
|---|
| 31 | a.status,
|
|---|
| 32 | a.notes,
|
|---|
| 33 |
|
|---|
| 34 | -- Gap to next appointment
|
|---|
| 35 | EXTRACT(EPOCH FROM (
|
|---|
| 36 | LEAD(a.appointment_time)
|
|---|
| 37 | OVER (
|
|---|
| 38 | PARTITION BY a.staff_id, a.appointment_date
|
|---|
| 39 | ORDER BY a.appointment_time
|
|---|
| 40 | ) - a.end_time
|
|---|
| 41 | )) / 60 AS gap_after_minutes
|
|---|
| 42 |
|
|---|
| 43 | FROM appointment a
|
|---|
| 44 |
|
|---|
| 45 | -- Staff
|
|---|
| 46 | JOIN "user" u ON u.user_id = a.staff_id
|
|---|
| 47 | JOIN staff s ON s.staff_id = a.staff_id
|
|---|
| 48 | JOIN company_location cl ON cl.location_id = s.location_id
|
|---|
| 49 |
|
|---|
| 50 | -- Client
|
|---|
| 51 | JOIN "user" uc ON uc.user_id = a.client_id
|
|---|
| 52 | JOIN client c ON c.client_id = a.client_id
|
|---|
| 53 |
|
|---|
| 54 | -- Roles (per staff, not global aggregation)
|
|---|
| 55 | LEFT JOIN LATERAL (
|
|---|
| 56 | SELECT
|
|---|
| 57 | STRING_AGG(st.role_type::TEXT, ', ' ORDER BY st.role_type) AS role_types,
|
|---|
| 58 | ARRAY_AGG(st.role_type ORDER BY st.role_type) AS role_types_arr
|
|---|
| 59 | FROM staff_type st
|
|---|
| 60 | WHERE st.staff_id = a.staff_id
|
|---|
| 61 | ) sr ON TRUE
|
|---|
| 62 |
|
|---|
| 63 | -- Services aggregation (per appointment, not global)
|
|---|
| 64 | LEFT JOIN LATERAL (
|
|---|
| 65 | SELECT
|
|---|
| 66 | STRING_AGG(sv.service_name, ', ' ORDER BY sv.service_name) AS service_names,
|
|---|
| 67 | ARRAY_AGG(sv.service_id ORDER BY sv.service_id) AS service_ids,
|
|---|
| 68 | SUM(aas.price) AS total_price,
|
|---|
| 69 | SUM(aas.duration_minutes) AS total_duration_minutes
|
|---|
| 70 | FROM appointment_service aas
|
|---|
| 71 | JOIN service sv ON sv.service_id = aas.service_id
|
|---|
| 72 | WHERE aas.appointment_id = a.appointment_id
|
|---|
| 73 | ) asa ON TRUE
|
|---|
| 74 |
|
|---|
| 75 | WHERE a.status <> 'cancelled' and a.status<> 'completed';
|
|---|
| 76 |
|
|---|
| 77 | SELECT * FROM v_staff_daily_schedule WHERE staff_id = 35371;
|
|---|
| 78 |
|
|---|
| 79 | CREATE OR REPLACE VIEW v_staff_open_slots AS
|
|---|
| 80 |
|
|---|
| 81 | WITH staff_roles AS (SELECT staff_id,
|
|---|
| 82 | STRING_AGG(role_type::TEXT, ', ' ORDER BY role_type) AS role_types
|
|---|
| 83 | FROM staff_type
|
|---|
| 84 | GROUP BY staff_id),
|
|---|
| 85 |
|
|---|
| 86 | staff_services AS (SELECT ss.staff_id,
|
|---|
| 87 | STRING_AGG(sv.service_name, ', ' ORDER BY sv.service_name) AS service_names,
|
|---|
| 88 | ARRAY_AGG(sv.service_id ORDER BY sv.service_id) AS service_ids
|
|---|
| 89 | FROM staff_service ss
|
|---|
| 90 | JOIN service sv ON sv.service_id = ss.service_id
|
|---|
| 91 | AND sv.is_active = TRUE
|
|---|
| 92 | GROUP BY ss.staff_id),
|
|---|
| 93 |
|
|---|
| 94 | staff_rating AS (SELECT a.staff_id,
|
|---|
| 95 | ROUND(AVG(r.rating), 2) AS avg_rating,
|
|---|
| 96 | COUNT(r.review_id) AS review_count
|
|---|
| 97 | FROM review r
|
|---|
| 98 | JOIN appointment a ON a.appointment_id = r.appointment_id
|
|---|
| 99 | GROUP BY a.staff_id)
|
|---|
| 100 |
|
|---|
| 101 | SELECT ts.slot_id,
|
|---|
| 102 | ts.slot_start,
|
|---|
| 103 | ts.slot_end,
|
|---|
| 104 | ts.slot_start::date AS slot_date,
|
|---|
| 105 | ts.slot_start::time AS slot_time,
|
|---|
| 106 | TO_CHAR(ts.slot_start, 'Dy DD Mon YYYY') AS slot_label,
|
|---|
| 107 |
|
|---|
| 108 | s.staff_id,
|
|---|
| 109 | u.first_name || ' ' || u.last_name AS staff_name,
|
|---|
| 110 | u.profile_image_url,
|
|---|
| 111 | sr.role_types,
|
|---|
| 112 |
|
|---|
| 113 | s.location_id,
|
|---|
| 114 | cl.address,
|
|---|
| 115 | cl.city,
|
|---|
| 116 | cl.phone AS location_phone,
|
|---|
| 117 | cl.company_id,
|
|---|
| 118 |
|
|---|
| 119 | COALESCE(srt.avg_rating, 0) AS staff_avg_rating,
|
|---|
| 120 | COALESCE(srt.review_count, 0) AS staff_review_count,
|
|---|
| 121 |
|
|---|
| 122 | ss.service_ids,
|
|---|
| 123 | ss.service_names
|
|---|
| 124 |
|
|---|
| 125 | FROM staff_time_slot ts
|
|---|
| 126 | JOIN staff s ON s.staff_id = ts.staff_id
|
|---|
| 127 | JOIN "user" u ON u.user_id = s.staff_id AND u.is_active = TRUE
|
|---|
| 128 | JOIN staff_roles sr ON sr.staff_id = s.staff_id
|
|---|
| 129 | JOIN company_location cl ON cl.location_id = s.location_id
|
|---|
| 130 | LEFT JOIN staff_services ss ON ss.staff_id = s.staff_id
|
|---|
| 131 | LEFT JOIN staff_rating srt ON srt.staff_id = s.staff_id
|
|---|
| 132 | LEFT JOIN blocked_time b ON b.staff_id = ts.staff_id
|
|---|
| 133 | AND ts.slot_start >= b.start_datetime
|
|---|
| 134 | AND ts.slot_start < b.end_datetime
|
|---|
| 135 |
|
|---|
| 136 | WHERE ts.appointment_id IS NULL
|
|---|
| 137 | AND ts.slot_start >= NOW()
|
|---|
| 138 | AND ts.slot_start < NOW() + INTERVAL '30 days'
|
|---|
| 139 | AND b.block_id IS null;
|
|---|
| 140 |
|
|---|
| 141 | SELECT * FROM v_staff_open_slots where staff_id = 26027;
|
|---|
| 142 |
|
|---|
| 143 |
|
|---|
| 144 |
|
|---|
| 145 |
|
|---|
| 146 | CREATE OR REPLACE VIEW v_companies_by_category AS
|
|---|
| 147 | WITH company_services AS (
|
|---|
| 148 | SELECT s.company_id,
|
|---|
| 149 | ccc.company_category_id,
|
|---|
| 150 | ARRAY_AGG(DISTINCT s.service_name ORDER BY s.service_name) AS offered_service_names_arr,
|
|---|
| 151 | STRING_AGG(DISTINCT s.service_name, ', ' ORDER BY s.service_name) AS offered_service_names
|
|---|
| 152 | FROM service s
|
|---|
| 153 | JOIN company_company_category ccc ON ccc.company_id = s.company_id
|
|---|
| 154 | WHERE s.is_active = TRUE
|
|---|
| 155 | GROUP BY s.company_id, ccc.company_category_id
|
|---|
| 156 | )
|
|---|
| 157 | SELECT cc.company_category_id,
|
|---|
| 158 | cc.category_name,
|
|---|
| 159 | co.company_id,
|
|---|
| 160 | co.name AS company_name,
|
|---|
| 161 | co.email,
|
|---|
| 162 | co.phone,
|
|---|
| 163 | co.description,
|
|---|
| 164 | co.is_active,
|
|---|
| 165 | cs.offered_service_names_arr,
|
|---|
| 166 | cs.offered_service_names
|
|---|
| 167 | FROM company_company_category ccc
|
|---|
| 168 | JOIN company_category cc ON cc.company_category_id = ccc.company_category_id
|
|---|
| 169 | JOIN company co ON co.company_id = ccc.company_id
|
|---|
| 170 | LEFT JOIN company_services cs
|
|---|
| 171 | ON cs.company_id = co.company_id
|
|---|
| 172 | AND cs.company_category_id = ccc.company_category_id
|
|---|
| 173 | WHERE co.is_active = TRUE;
|
|---|
| 174 |
|
|---|
| 175 |
|
|---|
| 176 | SELECT *
|
|---|
| 177 | from v_companies_by_category
|
|---|
| 178 | WHERE offered_service_names ILIKE '%Haircut%';
|
|---|
| 179 |
|
|---|
| 180 | SELECT *
|
|---|
| 181 | from v_companies_by_category
|
|---|
| 182 | WHERE category_name = 'Hair Salon';
|
|---|
| 183 |
|
|---|
| 184 | SELECT *
|
|---|
| 185 | from v_companies_by_category
|
|---|
| 186 | WHERE category_name = 'Hair Removal'
|
|---|
| 187 | and offered_service_names ILIKE '%Wax%';
|
|---|
| 188 |
|
|---|
| 189 |
|
|---|
| 190 | CREATE OR REPLACE VIEW v_staff_service_menu AS
|
|---|
| 191 | WITH staff_service_ratings AS (SELECT a.staff_id,
|
|---|
| 192 | asv.service_id,
|
|---|
| 193 | ROUND(AVG(r.rating), 2) AS avg_rating,
|
|---|
| 194 | COUNT(r.review_id) AS review_count,
|
|---|
| 195 | COUNT(asv.appointment_id) AS times_performed
|
|---|
| 196 | FROM appointment_service asv
|
|---|
| 197 | JOIN appointment a ON a.appointment_id = asv.appointment_id
|
|---|
| 198 | LEFT JOIN review r ON r.appointment_id = a.appointment_id
|
|---|
| 199 | WHERE a.status = 'completed'
|
|---|
| 200 | GROUP BY a.staff_id, asv.service_id)
|
|---|
| 201 |
|
|---|
| 202 | SELECT ss.staff_id,
|
|---|
| 203 | sv.service_id,
|
|---|
| 204 | sv.service_name,
|
|---|
| 205 | sc.category_name,
|
|---|
| 206 | sv.duration_minutes,
|
|---|
| 207 | sv.price,
|
|---|
| 208 | ss.notes AS staff_service_notes,
|
|---|
| 209 |
|
|---|
| 210 |
|
|---|
| 211 | COALESCE(ssr.avg_rating, 0) AS avg_rating,
|
|---|
| 212 | COALESCE(ssr.review_count, 0) AS review_count,
|
|---|
| 213 | COALESCE(ssr.times_performed, 0) AS times_performed
|
|---|
| 214 |
|
|---|
| 215 | FROM staff_service ss
|
|---|
| 216 | JOIN service sv ON sv.service_id = ss.service_id
|
|---|
| 217 | JOIN service_category sc ON sc.service_category_id = sv.service_category_id
|
|---|
| 218 | LEFT JOIN staff_service_ratings ssr
|
|---|
| 219 | ON ssr.staff_id = ss.staff_id
|
|---|
| 220 | AND ssr.service_id = ss.service_id
|
|---|
| 221 | WHERE sv.is_active = true;
|
|---|
| 222 |
|
|---|
| 223 |
|
|---|
| 224 | select *
|
|---|
| 225 | from v_staff_service_menu
|
|---|
| 226 | where staff_id = 23213
|
|---|
| 227 | order by avg_rating desc, times_performed desc;
|
|---|
| 228 |
|
|---|
| 229 |
|
|---|
| 230 |
|
|---|
| 231 | CREATE VIEW v_monthly_revenue_by_company AS
|
|---|
| 232 | SELECT co.company_id,
|
|---|
| 233 | co.name AS company_name,
|
|---|
| 234 | DATE_TRUNC('month', i.invoice_date)::date AS revenue_month,
|
|---|
| 235 | COUNT(*) AS total_invoices,
|
|---|
| 236 | COUNT(DISTINCT i.client_id) AS unique_clients,
|
|---|
| 237 | SUM(i.subtotal) AS gross_revenue,
|
|---|
| 238 | SUM(i.discount_total) AS total_discounts,
|
|---|
| 239 | SUM(i.tax) AS total_tax,
|
|---|
| 240 | SUM(i.total) AS net_revenue,
|
|---|
| 241 | ROUND(AVG(i.total), 2) AS avg_invoice_value,
|
|---|
| 242 | COUNT(CASE WHEN i.payment_method = 'card' THEN 1 END) AS paid_by_card,
|
|---|
| 243 | COUNT(CASE WHEN i.payment_method = 'cash' THEN 1 END) AS paid_by_cash,
|
|---|
| 244 | COUNT(CASE WHEN i.payment_method = 'loyalty_points' THEN 1 END) AS paid_by_points
|
|---|
| 245 | FROM invoice i
|
|---|
| 246 | JOIN appointment a ON a.appointment_id = i.appointment_id
|
|---|
| 247 | JOIN company_location cl ON cl.location_id = a.location_id
|
|---|
| 248 | JOIN company co ON co.company_id = cl.company_id
|
|---|
| 249 | GROUP BY co.company_id, co.name, DATE_TRUNC('month', i.invoice_date);
|
|---|
| 250 |
|
|---|
| 251 |
|
|---|
| 252 |
|
|---|
| 253 | select *
|
|---|
| 254 | from v_monthly_revenue_by_company
|
|---|
| 255 | where company_id = 198;
|
|---|
| 256 |
|
|---|
| 257 |
|
|---|
| 258 |
|
|---|
| 259 | CREATE OR REPLACE VIEW v_future_appointments_client_o AS
|
|---|
| 260 | SELECT
|
|---|
| 261 | a.appointment_id,
|
|---|
| 262 | a.client_id,
|
|---|
| 263 | a.staff_id,
|
|---|
| 264 | a.location_id,
|
|---|
| 265 | a.appointment_date,
|
|---|
| 266 | a.appointment_time,
|
|---|
| 267 | a.end_time,
|
|---|
| 268 | a.status,
|
|---|
| 269 | a.notes,
|
|---|
| 270 |
|
|---|
| 271 | u.first_name AS client_first_name,
|
|---|
| 272 | u.last_name AS client_last_name,
|
|---|
| 273 |
|
|---|
| 274 | us.first_name AS staff_first_name,
|
|---|
| 275 | us.last_name AS staff_last_name,
|
|---|
| 276 |
|
|---|
| 277 | asa.service_ids,
|
|---|
| 278 | asa.service_names,
|
|---|
| 279 | asa.total_price,
|
|---|
| 280 | asa.total_duration_minutes,
|
|---|
| 281 |
|
|---|
| 282 | cl.address,
|
|---|
| 283 | cl.city,
|
|---|
| 284 | cl.phone AS location_phone
|
|---|
| 285 |
|
|---|
| 286 | FROM appointment a
|
|---|
| 287 | JOIN client c ON c.client_id = a.client_id
|
|---|
| 288 | JOIN "user" u ON u.user_id = a.client_id
|
|---|
| 289 | JOIN staff st ON st.staff_id = a.staff_id
|
|---|
| 290 | JOIN "user" us ON us.user_id = st.staff_id
|
|---|
| 291 | JOIN company_location cl ON cl.location_id = a.location_id
|
|---|
| 292 |
|
|---|
| 293 | LEFT JOIN LATERAL (
|
|---|
| 294 | SELECT
|
|---|
| 295 | STRING_AGG(sv.service_name, ', ' ORDER BY sv.service_name) AS service_names,
|
|---|
| 296 | ARRAY_AGG(sv.service_id ORDER BY sv.service_id) AS service_ids,
|
|---|
| 297 | SUM(aas.price) AS total_price,
|
|---|
| 298 | SUM(aas.duration_minutes) AS total_duration_minutes
|
|---|
| 299 | FROM appointment_service aas
|
|---|
| 300 | JOIN service sv ON sv.service_id = aas.service_id
|
|---|
| 301 | WHERE aas.appointment_id = a.appointment_id
|
|---|
| 302 | ) asa ON TRUE
|
|---|
| 303 |
|
|---|
| 304 | WHERE a.appointment_date >= NOW()::date
|
|---|
| 305 | AND a.status <> 'cancelled';
|
|---|
| 306 |
|
|---|
| 307 | CREATE INDEX idx_appointment_client_future
|
|---|
| 308 | ON appointment (client_id, appointment_date)
|
|---|
| 309 | INCLUDE (staff_id, location_id, appointment_time, end_time, status, notes)
|
|---|
| 310 | WHERE status <> 'cancelled';
|
|---|
| 311 |
|
|---|
| 312 | select *
|
|---|
| 313 | from v_future_appointments_client_o
|
|---|
| 314 | where client_id = 640295;
|
|---|
| 315 |
|
|---|
| 316 |
|
|---|
| 317 | CREATE OR REPLACE VIEW v_client_dashboard AS
|
|---|
| 318 | WITH upcoming AS (SELECT a.client_id,
|
|---|
| 319 | COUNT(a.appointment_id) AS upcoming_appointments,
|
|---|
| 320 | MIN(a.appointment_date) AS next_appointment_date
|
|---|
| 321 | FROM appointment a
|
|---|
| 322 | WHERE a.status NOT IN ('cancelled', 'completed')
|
|---|
| 323 | AND a.appointment_date >= CURRENT_DATE
|
|---|
| 324 | GROUP BY a.client_id),
|
|---|
| 325 | recent_spend AS (SELECT i.client_id,
|
|---|
| 326 | SUM(i.total) AS last_30_days_spend
|
|---|
| 327 | FROM invoice i
|
|---|
| 328 | WHERE i.invoice_date >= CURRENT_DATE - INTERVAL '30 days'
|
|---|
| 329 | GROUP BY i.client_id)
|
|---|
| 330 | SELECT c.client_id,
|
|---|
| 331 | u.first_name || ' ' || u.last_name AS client_name,
|
|---|
| 332 | c.loyalty_points,
|
|---|
| 333 | COALESCE(up.upcoming_appointments, 0) AS upcoming_appointments,
|
|---|
| 334 | up.next_appointment_date,
|
|---|
| 335 | COALESCE(rs.last_30_days_spend, 0) AS last_30_days_spend,
|
|---|
| 336 | u.email,
|
|---|
| 337 | c.phone,
|
|---|
| 338 | c.date_of_birth
|
|---|
| 339 | FROM client c
|
|---|
| 340 | JOIN "user" u ON u.user_id = c.client_id
|
|---|
| 341 | LEFT JOIN upcoming up ON up.client_id = c.client_id
|
|---|
| 342 | LEFT JOIN recent_spend rs ON rs.client_id = c.client_id;
|
|---|
| 343 |
|
|---|
| 344 | select *
|
|---|
| 345 | from v_client_dashboard
|
|---|
| 346 | where client_id = 640295;
|
|---|
| 347 |
|
|---|
| 348 |
|
|---|
| 349 |
|
|---|
| 350 | CREATE MATERIALIZED VIEW mv_staff_avg_rating AS
|
|---|
| 351 | SELECT a.staff_id,
|
|---|
| 352 | ROUND(AVG(r.rating), 2) AS avg_rating,
|
|---|
| 353 | COUNT(r.review_id) AS review_count
|
|---|
| 354 | FROM appointment a
|
|---|
| 355 | JOIN review r ON r.appointment_id = a.appointment_id
|
|---|
| 356 | GROUP BY a.staff_id;
|
|---|
| 357 |
|
|---|
| 358 | -- Index so the main view joins fast
|
|---|
| 359 | CREATE UNIQUE INDEX ON mv_staff_avg_rating (staff_id);
|
|---|
| 360 |
|
|---|
| 361 | CREATE OR REPLACE VIEW v_staff_profile_m AS
|
|---|
| 362 | SELECT s.staff_id,
|
|---|
| 363 | u.first_name,
|
|---|
| 364 | u.last_name,
|
|---|
| 365 | u.first_name || ' ' || u.last_name AS full_name,
|
|---|
| 366 | u.email,
|
|---|
| 367 | u.profile_image_url,
|
|---|
| 368 | u.is_active,
|
|---|
| 369 | st.role_types,
|
|---|
| 370 | s.hourly_rate,
|
|---|
| 371 | s.location_id,
|
|---|
| 372 | cl.address,
|
|---|
| 373 | cl.city,
|
|---|
| 374 | cl.phone AS location_phone,
|
|---|
| 375 | cl.company_id,
|
|---|
| 376 | co.name AS company_name,
|
|---|
| 377 | COALESCE(mr.avg_rating, 0) AS avg_rating,
|
|---|
| 378 | COALESCE(mr.review_count, 0) AS review_count,
|
|---|
| 379 | ss.service_ids,
|
|---|
| 380 | ss.service_names
|
|---|
| 381 | FROM staff s
|
|---|
| 382 | JOIN "user" u ON u.user_id = s.staff_id
|
|---|
| 383 | JOIN company_location cl ON cl.location_id = s.location_id
|
|---|
| 384 | JOIN company co ON co.company_id = cl.company_id
|
|---|
| 385 |
|
|---|
| 386 | -- Pre-computed ratings from materialized view
|
|---|
| 387 | LEFT JOIN mv_staff_avg_rating mr ON mr.staff_id = s.staff_id
|
|---|
| 388 |
|
|---|
| 389 | LEFT JOIN LATERAL (
|
|---|
| 390 | SELECT ARRAY_AGG(sv.service_id ORDER BY sv.service_id) AS service_ids,
|
|---|
| 391 | STRING_AGG(sv.service_name, ', ' ORDER BY sv.service_name) AS service_names
|
|---|
| 392 | FROM staff_service ss_inner
|
|---|
| 393 | JOIN service sv ON sv.service_id = ss_inner.service_id
|
|---|
| 394 | WHERE ss_inner.staff_id = s.staff_id AND sv.is_active = TRUE
|
|---|
| 395 | ) ss ON TRUE
|
|---|
| 396 |
|
|---|
| 397 | LEFT JOIN LATERAL (
|
|---|
| 398 | SELECT STRING_AGG(role_type::TEXT, ', ' ORDER BY role_type) AS role_types
|
|---|
| 399 | FROM staff_type
|
|---|
| 400 | WHERE staff_id = s.staff_id
|
|---|
| 401 | ) st ON TRUE
|
|---|
| 402 |
|
|---|
| 403 | WHERE u.is_active = TRUE;
|
|---|
| 404 |
|
|---|
| 405 | REFRESH MATERIALIZED VIEW CONCURRENTLY mv_staff_avg_rating;
|
|---|
| 406 |
|
|---|
| 407 | CREATE INDEX idx_appointment_staff_rating
|
|---|
| 408 | ON appointment(staff_id) INCLUDE (appointment_id);
|
|---|
| 409 |
|
|---|
| 410 | select *
|
|---|
| 411 | from v_staff_profile_m
|
|---|
| 412 | where company_id = 195
|
|---|
| 413 | and avg_rating > 4;
|
|---|
| 414 |
|
|---|
| 415 | select *
|
|---|
| 416 | from v_staff_profile_m
|
|---|
| 417 | where staff_id = 365045;
|
|---|
| 418 |
|
|---|
| 419 |
|
|---|
| 420 |
|
|---|
| 421 | CREATE OR REPLACE VIEW v_invoice_detail_o AS
|
|---|
| 422 | SELECT i.invoice_id,
|
|---|
| 423 | i.invoice_date,
|
|---|
| 424 | i.payment_method,
|
|---|
| 425 | i.subtotal,
|
|---|
| 426 | i.discount_total,
|
|---|
| 427 | i.tax,
|
|---|
| 428 | i.total,
|
|---|
| 429 |
|
|---|
| 430 | ip.promo_codes_used,
|
|---|
| 431 |
|
|---|
| 432 | a.appointment_id,
|
|---|
| 433 | a.appointment_date,
|
|---|
| 434 | a.appointment_time,
|
|---|
| 435 | a.end_time,
|
|---|
| 436 | a.status AS appointment_status,
|
|---|
| 437 |
|
|---|
| 438 | c.client_id,
|
|---|
| 439 | uc.first_name || ' ' || uc.last_name AS client_name,
|
|---|
| 440 | uc.email AS client_email,
|
|---|
| 441 | c.phone AS client_phone,
|
|---|
| 442 |
|
|---|
| 443 | s.staff_id,
|
|---|
| 444 | us.first_name || ' ' || us.last_name AS staff_name,
|
|---|
| 445 | st.role_types,
|
|---|
| 446 |
|
|---|
| 447 | isv.service_names,
|
|---|
| 448 | isv.service_names_text,
|
|---|
| 449 | isv.services_total,
|
|---|
| 450 |
|
|---|
| 451 | cl.location_id,
|
|---|
| 452 | cl.address,
|
|---|
| 453 | cl.city,
|
|---|
| 454 |
|
|---|
| 455 | cl.company_id,
|
|---|
| 456 | co.name AS company_name
|
|---|
| 457 | FROM invoice i
|
|---|
| 458 | JOIN appointment a ON a.appointment_id = i.appointment_id
|
|---|
| 459 | JOIN client c ON c.client_id = a.client_id
|
|---|
| 460 | JOIN "user" uc ON uc.user_id = c.client_id
|
|---|
| 461 | JOIN staff s ON s.staff_id = a.staff_id
|
|---|
| 462 | JOIN "user" us ON us.user_id = s.staff_id
|
|---|
| 463 | JOIN company_location cl ON cl.location_id = a.location_id
|
|---|
| 464 | JOIN company co ON co.company_id = cl.company_id
|
|---|
| 465 |
|
|---|
| 466 |
|
|---|
| 467 | LEFT JOIN LATERAL (
|
|---|
| 468 | SELECT ARRAY_AGG(sv.service_name ORDER BY sv.service_name) AS service_names,
|
|---|
| 469 | STRING_AGG(sv.service_name, ', ' ORDER BY sv.service_name) AS service_names_text,
|
|---|
| 470 | SUM(asv_in.price) AS services_total
|
|---|
| 471 | FROM appointment_service asv_in
|
|---|
| 472 | JOIN service sv ON sv.service_id = asv_in.service_id
|
|---|
| 473 | WHERE asv_in.appointment_id = a.appointment_id
|
|---|
| 474 | ) isv ON TRUE
|
|---|
| 475 |
|
|---|
| 476 |
|
|---|
| 477 | LEFT JOIN LATERAL (
|
|---|
| 478 | SELECT STRING_AGG(p.code, ', ' ORDER BY p.code) AS promo_codes_used
|
|---|
| 479 | FROM invoice_promo ip_in
|
|---|
| 480 | JOIN promo_code p ON p.promo_id = ip_in.promo_id
|
|---|
| 481 | WHERE ip_in.invoice_id = i.invoice_id
|
|---|
| 482 | ) ip ON TRUE
|
|---|
| 483 |
|
|---|
| 484 |
|
|---|
| 485 | LEFT JOIN LATERAL (
|
|---|
| 486 | SELECT STRING_AGG(role_type::TEXT, ', ' ORDER BY role_type) AS role_types
|
|---|
| 487 | FROM staff_type
|
|---|
| 488 | WHERE staff_id = s.staff_id
|
|---|
| 489 | ) st ON TRUE;
|
|---|
| 490 |
|
|---|
| 491 | select *
|
|---|
| 492 | from v_invoice_detail_o
|
|---|
| 493 | where invoice_id = 1373796;
|
|---|