| | 1 | = UC0007: View Resource Usage Analytics = |
| | 2 | |
| | 3 | '''Initiating actor:''' Faculty Administrator |
| | 4 | |
| | 5 | '''Other actors:''' None |
| | 6 | |
| | 7 | A faculty administrator wants to analyze how resources are being utilized across the faculty. The system provides analytical reports including reservation counts per resource, most active users, reservation status distribution, busiest days of the week, and resource type utilization rates. These reports support data-driven decisions about resource allocation and scheduling policies. |
| | 8 | |
| | 9 | == Scenario == |
| | 10 | |
| | 11 | 1. The administrator (Marko Dimitrovski, user_id = 2) opens the usage analytics dashboard. The system displays a summary overview with total counts. |
| | 12 | {{{ |
| | 13 | SELECT |
| | 14 | COUNT(*) AS total_reservations, |
| | 15 | COUNT(*) FILTER (WHERE status = 'approved') AS approved, |
| | 16 | COUNT(*) FILTER (WHERE status = 'pending') AS pending, |
| | 17 | COUNT(*) FILTER (WHERE status = 'rejected') AS rejected, |
| | 18 | COUNT(*) FILTER (WHERE status = 'completed') AS completed, |
| | 19 | COUNT(*) FILTER (WHERE status = 'cancelled') AS cancelled, |
| | 20 | COUNT(DISTINCT user_id) AS unique_users, |
| | 21 | COUNT(DISTINCT resource_id) AS unique_resources |
| | 22 | FROM project.reservations; |
| | 23 | }}} |
| | 24 | |
| | 25 | 2. The administrator views the ''Reservations per Resource'' report. The system shows resources ranked by total number of reservations. |
| | 26 | {{{ |
| | 27 | SELECT r.name AS resource_name, |
| | 28 | rt.type_name AS resource_type, |
| | 29 | COUNT(res.reservation_id) AS total_reservations, |
| | 30 | COUNT(res.reservation_id) FILTER (WHERE res.status = 'approved') AS approved, |
| | 31 | COUNT(res.reservation_id) FILTER (WHERE res.status = 'completed') AS completed, |
| | 32 | COUNT(res.reservation_id) FILTER (WHERE res.status = 'rejected') AS rejected |
| | 33 | FROM project.resources r |
| | 34 | JOIN project.resource_types rt ON r.type_id = rt.type_id |
| | 35 | LEFT JOIN project.reservations res ON r.resource_id = res.resource_id |
| | 36 | GROUP BY r.resource_id, r.name, rt.type_name |
| | 37 | ORDER BY total_reservations DESC; |
| | 38 | }}} |
| | 39 | |
| | 40 | 3. The administrator views the ''Most Active Users'' report. The system shows users ranked by number of reservations made. |
| | 41 | {{{ |
| | 42 | SELECT u.first_name || ' ' || u.last_name AS user_name, |
| | 43 | ut.type_name AS user_role, |
| | 44 | COUNT(res.reservation_id) AS total_reservations, |
| | 45 | COUNT(res.reservation_id) FILTER (WHERE res.status IN ('approved', 'completed')) AS successful, |
| | 46 | COUNT(res.reservation_id) FILTER (WHERE res.status = 'rejected') AS rejected |
| | 47 | FROM project.users u |
| | 48 | JOIN project.user_types ut ON u.type_id = ut.type_id |
| | 49 | LEFT JOIN project.reservations res ON u.user_id = res.user_id |
| | 50 | GROUP BY u.user_id, u.first_name, u.last_name, ut.type_name |
| | 51 | HAVING COUNT(res.reservation_id) > 0 |
| | 52 | ORDER BY total_reservations DESC; |
| | 53 | }}} |
| | 54 | |
| | 55 | 4. The administrator views the ''Reservation Status Distribution'' report. The system shows the breakdown of all reservations by status with percentages. |
| | 56 | {{{ |
| | 57 | SELECT status, |
| | 58 | COUNT(*) AS count, |
| | 59 | ROUND(COUNT(*) * 100.0 / SUM(COUNT(*)) OVER (), 1) AS percentage |
| | 60 | FROM project.reservations |
| | 61 | GROUP BY status |
| | 62 | ORDER BY count DESC; |
| | 63 | }}} |
| | 64 | |
| | 65 | 5. The administrator views the ''Busiest Days of the Week'' report. The system shows how many approved or completed reservations fall on each weekday for physical resources. |
| | 66 | {{{ |
| | 67 | SELECT |
| | 68 | TO_CHAR(res.start_time, 'Day') AS day_of_week, |
| | 69 | EXTRACT(ISODOW FROM res.start_time) AS day_number, |
| | 70 | COUNT(*) AS reservation_count |
| | 71 | FROM project.reservations res |
| | 72 | JOIN project.resources r ON res.resource_id = r.resource_id |
| | 73 | JOIN project.resource_types rt ON r.type_id = rt.type_id |
| | 74 | WHERE rt.is_physical = TRUE |
| | 75 | AND res.status IN ('approved', 'completed') |
| | 76 | GROUP BY TO_CHAR(res.start_time, 'Day'), EXTRACT(ISODOW FROM res.start_time) |
| | 77 | ORDER BY day_number; |
| | 78 | }}} |
| | 79 | |
| | 80 | 6. The administrator views the ''Resource Type Utilization'' report. The system shows usage per resource category with averages. |
| | 81 | {{{ |
| | 82 | SELECT rt.type_name, |
| | 83 | CASE WHEN rt.is_physical THEN 'Physical' ELSE 'Digital' END AS category, |
| | 84 | COUNT(DISTINCT r.resource_id) AS total_resources, |
| | 85 | COUNT(res.reservation_id) AS total_reservations, |
| | 86 | ROUND(COUNT(res.reservation_id)::NUMERIC / |
| | 87 | NULLIF(COUNT(DISTINCT r.resource_id), 0), 1) AS avg_reservations_per_resource |
| | 88 | FROM project.resource_types rt |
| | 89 | LEFT JOIN project.resources r ON rt.type_id = r.type_id |
| | 90 | LEFT JOIN project.reservations res ON r.resource_id = res.resource_id |
| | 91 | GROUP BY rt.type_id, rt.type_name, rt.is_physical |
| | 92 | ORDER BY total_reservations DESC; |
| | 93 | }}} |
| | 94 | |
| | 95 | 7. The administrator views the ''Monthly Reservation Trends'' report. The system shows how many reservations were created each month and their outcomes. |
| | 96 | {{{ |
| | 97 | SELECT |
| | 98 | TO_CHAR(DATE_TRUNC('month', created_at), 'YYYY-MM') AS month, |
| | 99 | COUNT(*) AS reservations_created, |
| | 100 | COUNT(*) FILTER (WHERE status IN ('approved', 'completed')) AS successful, |
| | 101 | COUNT(*) FILTER (WHERE status = 'rejected') AS rejected, |
| | 102 | COUNT(*) FILTER (WHERE status = 'cancelled') AS cancelled |
| | 103 | FROM project.reservations |
| | 104 | GROUP BY DATE_TRUNC('month', created_at) |
| | 105 | ORDER BY month; |
| | 106 | }}} |