| | 1 | = UC0007 Prototype Implementation - View Resource Usage Analytics = |
| | 2 | |
| | 3 | '''Initiating actor:''' Faculty Administrator |
| | 4 | |
| | 5 | '''Other actors:''' None |
| | 6 | |
| | 7 | The administrator accesses an analytics dashboard with seven reports covering reservation statistics, resource utilization, user activity, and trends. Each report runs an aggregate SQL query and displays the results as a formatted table. |
| | 8 | |
| | 9 | == Scenario == |
| | 10 | |
| | 11 | 1. The administrator selects ''View Resource Usage Analytics'' from the main menu. The system shows the analytics sub-menu. |
| | 12 | {{{ |
| | 13 | === Resource Usage Analytics === |
| | 14 | |
| | 15 | 1. Summary Overview |
| | 16 | 2. Reservations per Resource |
| | 17 | 3. Most Active Users |
| | 18 | 4. Reservation Status Distribution |
| | 19 | 5. Busiest Days of the Week |
| | 20 | 6. Resource Type Utilization |
| | 21 | 7. Monthly Reservation Trends |
| | 22 | 8. Show All Reports |
| | 23 | 0. Cancel / Go back |
| | 24 | }}} |
| | 25 | |
| | 26 | 2. The administrator selects ''Summary Overview''. The system runs the following query: |
| | 27 | {{{ |
| | 28 | SELECT COUNT(*) AS total_reservations, |
| | 29 | COUNT(*) FILTER (WHERE status = 'approved') AS approved, |
| | 30 | COUNT(*) FILTER (WHERE status = 'pending') AS pending, |
| | 31 | COUNT(*) FILTER (WHERE status = 'rejected') AS rejected, |
| | 32 | COUNT(*) FILTER (WHERE status = 'completed') AS completed, |
| | 33 | COUNT(*) FILTER (WHERE status = 'cancelled') AS cancelled, |
| | 34 | COUNT(DISTINCT user_id) AS unique_users, |
| | 35 | COUNT(DISTINCT resource_id) AS unique_resources |
| | 36 | FROM reservations; |
| | 37 | }}} |
| | 38 | |
| | 39 | The system displays the summary: |
| | 40 | {{{ |
| | 41 | --- Summary Overview --- |
| | 42 | Total: 26 |
| | 43 | Approved: 17 |
| | 44 | Pending: 4 |
| | 45 | Rejected: 1 |
| | 46 | Completed: 3 |
| | 47 | Cancelled: 1 |
| | 48 | Unique Users: 10 |
| | 49 | Unique Resources: 16 |
| | 50 | }}} |
| | 51 | |
| | 52 | 3. The administrator selects ''Reservation Status Distribution''. The system runs: |
| | 53 | {{{ |
| | 54 | SELECT status, COUNT(*) AS count, |
| | 55 | ROUND(COUNT(*) * 100.0 / SUM(COUNT(*)) OVER (), 1) AS percentage |
| | 56 | FROM reservations |
| | 57 | GROUP BY status |
| | 58 | ORDER BY count DESC; |
| | 59 | }}} |
| | 60 | |
| | 61 | The system displays the breakdown with percentages: |
| | 62 | {{{ |
| | 63 | --- Reservation Status Distribution --- |
| | 64 | Status | Count | Percentage (%) |
| | 65 | ----------+-------+--------------- |
| | 66 | approved | 17 | 65.4 |
| | 67 | pending | 4 | 15.4 |
| | 68 | completed | 3 | 11.5 |
| | 69 | rejected | 1 | 3.8 |
| | 70 | cancelled | 1 | 3.8 |
| | 71 | }}} |
| | 72 | |
| | 73 | 4. The administrator selects ''Most Active Users''. The system runs: |
| | 74 | {{{ |
| | 75 | SELECT u.first_name || ' ' || u.last_name, ut.type_name, |
| | 76 | COUNT(res.reservation_id) AS total, |
| | 77 | COUNT(res.reservation_id) FILTER (WHERE res.status IN ('approved', 'completed')) AS successful, |
| | 78 | COUNT(res.reservation_id) FILTER (WHERE res.status = 'rejected') AS rejected |
| | 79 | FROM users u |
| | 80 | JOIN user_types ut ON u.type_id = ut.type_id |
| | 81 | LEFT JOIN reservations res ON u.user_id = res.user_id |
| | 82 | GROUP BY u.user_id, u.first_name, u.last_name, ut.type_name |
| | 83 | HAVING COUNT(res.reservation_id) > 0 |
| | 84 | ORDER BY total DESC; |
| | 85 | }}} |
| | 86 | |
| | 87 | The system displays the most active users: |
| | 88 | {{{ |
| | 89 | --- Most Active Users --- |
| | 90 | User | Role | Total | Successful | Rejected |
| | 91 | ------------------------+----------------+-------+------------+--------- |
| | 92 | Nikola Trajkovski | Teaching Staff | 8 | 7 | 1 |
| | 93 | Elena Stojanova | Teaching Staff | 6 | 5 | 0 |
| | 94 | Ivana Kostadinova | Teaching Staff | 3 | 3 | 0 |
| | 95 | Aleksandar Georgieski | Teaching Staff | 2 | 1 | 0 |
| | 96 | Stefan Nikolov | Student | 2 | 2 | 0 |
| | 97 | ... |
| | 98 | }}} |
| | 99 | |
| | 100 | 5. The administrator selects ''Busiest Days of the Week''. The system queries only approved or completed reservations on physical resources: |
| | 101 | {{{ |
| | 102 | SELECT TRIM(TO_CHAR(res.start_time, 'Day')), |
| | 103 | COUNT(*) AS reservation_count |
| | 104 | FROM reservations res |
| | 105 | JOIN resources r ON res.resource_id = r.resource_id |
| | 106 | JOIN resource_types rt ON r.type_id = rt.type_id |
| | 107 | WHERE rt.is_physical = TRUE |
| | 108 | AND res.status IN ('approved', 'completed') |
| | 109 | GROUP BY TO_CHAR(res.start_time, 'Day'), EXTRACT(ISODOW FROM res.start_time) |
| | 110 | ORDER BY EXTRACT(ISODOW FROM res.start_time); |
| | 111 | }}} |
| | 112 | |
| | 113 | The system displays the results: |
| | 114 | {{{ |
| | 115 | --- Busiest Days of the Week (Physical Resources) --- |
| | 116 | Day | Reservations |
| | 117 | -----------+------------- |
| | 118 | Tuesday | 4 |
| | 119 | Wednesday | 3 |
| | 120 | Thursday | 3 |
| | 121 | Friday | 5 |
| | 122 | Sunday | 1 |
| | 123 | }}} |
| | 124 | |
| | 125 | 6. The administrator selects ''Resource Type Utilization''. The system runs: |
| | 126 | {{{ |
| | 127 | SELECT rt.type_name, |
| | 128 | CASE WHEN rt.is_physical THEN 'Physical' ELSE 'Digital' END, |
| | 129 | COUNT(DISTINCT r.resource_id) AS total_resources, |
| | 130 | COUNT(res.reservation_id) AS total_reservations, |
| | 131 | ROUND(COUNT(res.reservation_id)::NUMERIC / |
| | 132 | NULLIF(COUNT(DISTINCT r.resource_id), 0), 1) |
| | 133 | FROM resource_types rt |
| | 134 | LEFT JOIN resources r ON rt.type_id = r.type_id |
| | 135 | LEFT JOIN reservations res ON r.resource_id = res.resource_id |
| | 136 | GROUP BY rt.type_id, rt.type_name, rt.is_physical |
| | 137 | ORDER BY total_reservations DESC; |
| | 138 | }}} |
| | 139 | |
| | 140 | The system displays the utilization per resource type: |
| | 141 | {{{ |
| | 142 | --- Resource Type Utilization --- |
| | 143 | Type | Category | Resources | Reservations | Avg/Resource |
| | 144 | --------------------+----------+-----------+--------------+------------- |
| | 145 | Classroom | Physical | 6 | 10 | 1.7 |
| | 146 | Computer Laboratory | Physical | 4 | 5 | 1.3 |
| | 147 | Conference Room | Physical | 3 | 2 | 0.7 |
| | 148 | 3D Printer | Physical | 2 | 2 | 1.0 |
| | 149 | Virtual Machine | Digital | 3 | 2 | 0.7 |
| | 150 | Online Service | Digital | 3 | 2 | 0.7 |
| | 151 | Projector | Physical | 2 | 2 | 1.0 |
| | 152 | Software License | Digital | 4 | 1 | 0.3 |
| | 153 | }}} |
| | 154 | |
| | 155 | 7. The administrator selects ''Monthly Reservation Trends''. The system runs: |
| | 156 | {{{ |
| | 157 | SELECT TO_CHAR(DATE_TRUNC('month', created_at), 'YYYY-MM'), |
| | 158 | COUNT(*) AS created, |
| | 159 | COUNT(*) FILTER (WHERE status IN ('approved', 'completed')) AS successful, |
| | 160 | COUNT(*) FILTER (WHERE status = 'rejected') AS rejected, |
| | 161 | COUNT(*) FILTER (WHERE status = 'cancelled') AS cancelled |
| | 162 | FROM reservations |
| | 163 | GROUP BY DATE_TRUNC('month', created_at) |
| | 164 | ORDER BY DATE_TRUNC('month', created_at); |
| | 165 | }}} |
| | 166 | |
| | 167 | The system displays the monthly trend: |
| | 168 | {{{ |
| | 169 | --- Monthly Reservation Trends --- |
| | 170 | Month | Created | Successful | Rejected | Cancelled |
| | 171 | --------+---------+------------+----------+---------- |
| | 172 | 2026-01 | 15 | 14 | 0 | 0 |
| | 173 | 2026-02 | 11 | 6 | 1 | 1 |
| | 174 | }}} |