@@ -4,68 +4,192 @@ import (
44 "UnlockEdv2/src/models"
55)
66
7- func (db * DB ) GetClassDashboardMetrics (ctx * models.QueryContext , facilityID * uint ) (int64 , int64 , int64 , int64 , error ) {
8- var activeClasses int64
9- var totalEnrollments int64
10- var totalSeats int64
11- var attendanceConcerns int64
7+ func (db * DB ) GetClassDashboardMetrics (ctx * models.QueryContext , facilityID * uint ) (models.ClassDashboardMetrics , error ) {
8+ var metrics models.ClassDashboardMetrics
9+
10+ var err error
11+ if metrics .ActiveClasses , err = db .GetActiveClassCount (ctx , facilityID ); err != nil {
12+ return metrics , err
13+ }
14+ if metrics .TotalSeats , err = db .GetTotalSeatCount (ctx , facilityID ); err != nil {
15+ return metrics , err
16+ }
17+ if metrics .ScheduledClasses , err = db .GetScheduledClassCount (ctx , facilityID ); err != nil {
18+ return metrics , err
19+ }
20+ if metrics .TotalEnrollments , err = db .GetTotalEnrollmentsCount (ctx , facilityID ); err != nil {
21+ return metrics , err
22+ }
23+ if metrics .AttendanceConcerns , err = db .GetAttendanceConcernsCount (ctx , facilityID ); err != nil {
24+ return metrics , err
25+ }
1226
13- classQuery := db .WithContext (ctx .Ctx ).
27+ return metrics , nil
28+ }
29+
30+ func (db * DB ) GetActiveClassCount (ctx * models.QueryContext , facilityID * uint ) (int64 , error ) {
31+ var count int64
32+ query := db .WithContext (ctx .Ctx ).
1433 Model (& models.ProgramClass {}).
1534 Where ("status = ?" , models .Active ).
1635 Where ("archived_at IS NULL" )
1736 if facilityID != nil {
18- classQuery = classQuery .Where ("facility_id = ?" , * facilityID )
37+ query = query .Where ("facility_id = ?" , * facilityID )
38+ }
39+ if err := query .Count (& count ).Error ; err != nil {
40+ return 0 , err
1941 }
42+ return count , nil
43+ }
2044
21- if err := classQuery .Count (& activeClasses ).Error ; err != nil {
22- return 0 , 0 , 0 , 0 , err
45+ func (db * DB ) GetTotalSeatCount (ctx * models.QueryContext , facilityID * uint ) (int64 , error ) {
46+ var totalSeats int64
47+ query := db .WithContext (ctx .Ctx ).
48+ Model (& models.ProgramClass {}).
49+ Where ("status = ?" , models .Active ).
50+ Where ("archived_at IS NULL" )
51+ if facilityID != nil {
52+ query = query .Where ("facility_id = ?" , * facilityID )
2353 }
54+ if err := query .Select ("COALESCE(SUM(capacity), 0)" ).Scan (& totalSeats ).Error ; err != nil {
55+ return 0 , err
56+ }
57+ return totalSeats , nil
58+ }
2459
25- if err := classQuery .Select ("COALESCE(SUM(capacity), 0)" ).Scan (& totalSeats ).Error ; err != nil {
26- return 0 , 0 , 0 , 0 , err
60+ func (db * DB ) GetScheduledClassCount (ctx * models.QueryContext , facilityID * uint ) (int64 , error ) {
61+ var count int64
62+ query := db .WithContext (ctx .Ctx ).
63+ Model (& models.ProgramClass {}).
64+ Where ("status = ?" , models .Scheduled ).
65+ Where ("archived_at IS NULL" )
66+ if facilityID != nil {
67+ query = query .Where ("facility_id = ?" , * facilityID )
68+ }
69+ if err := query .Count (& count ).Error ; err != nil {
70+ return 0 , err
2771 }
72+ return count , nil
73+ }
2874
29- enrollmentQuery := db .WithContext (ctx .Ctx ).
75+ func (db * DB ) GetTotalEnrollmentsCount (ctx * models.QueryContext , facilityID * uint ) (int64 , error ) {
76+ var count int64
77+ query := db .WithContext (ctx .Ctx ).
3078 Table ("program_class_enrollments e" ).
3179 Select ("COUNT(*)" ).
3280 Joins ("JOIN program_classes c ON c.id = e.class_id" ).
3381 Where ("e.enrollment_status = ?" , models .Enrolled ).
3482 Where ("c.status = ?" , models .Active ).
3583 Where ("c.archived_at IS NULL" )
3684 if facilityID != nil {
37- enrollmentQuery = enrollmentQuery .Where ("c.facility_id = ?" , * facilityID )
85+ query = query .Where ("c.facility_id = ?" , * facilityID )
3886 }
39- if err := enrollmentQuery .Scan (& totalEnrollments ).Error ; err != nil {
40- return 0 , 0 , 0 , 0 , err
87+ if err := query .Scan (& count ).Error ; err != nil {
88+ return 0 , err
4189 }
90+ return count , nil
91+ }
4292
43- attendanceSQL := `
44- SELECT COUNT(DISTINCT c.id)
45- FROM program_classes c
46- JOIN program_class_enrollments e ON e.class_id = c.id
47- WHERE c.status = ?
48- AND c.archived_at IS NULL
49- AND e.enrollment_status = ?
50- `
93+ func (db * DB ) GetAttendanceConcernsCount (ctx * models.QueryContext , facilityID * uint ) (int64 , error ) {
94+ attendanceSQL := `SELECT COUNT(DISTINCT c.id)
95+ FROM program_classes c
96+ JOIN program_class_enrollments e ON e.class_id = c.id
97+ WHERE c.status = ?
98+ AND c.archived_at IS NULL
99+ AND e.enrollment_status = ? `
51100 args := []any {models .Active , models .Enrolled }
52101 if facilityID != nil {
53- attendanceSQL += "AND c.facility_id = ?\n "
102+ attendanceSQL += "AND c.facility_id = ? "
54103 args = append (args , * facilityID )
55104 }
56- attendanceSQL += `
57- AND (
105+ attendanceSQL += ` AND (
58106 select count(*)
59107 from program_class_events evt
60108 inner join program_class_event_attendance att on att.event_id = evt.id
61109 where evt.class_id = c.id
62110 and att.user_id = e.user_id
63111 and att.attendance_status = 'absent_unexcused'
64- ) >= 3
65- `
66- if err := db .WithContext (ctx .Ctx ).Raw (attendanceSQL , args ... ).Scan (& attendanceConcerns ).Error ; err != nil {
67- return 0 , 0 , 0 , 0 , err
112+ ) >= 3 `
113+ var count int64
114+ if err := db .WithContext (ctx .Ctx ).Raw (attendanceSQL , args ... ).Scan (& count ).Error ; err != nil {
115+ return 0 , err
68116 }
117+ return count , nil
118+ }
69119
70- return activeClasses , totalEnrollments , totalSeats , attendanceConcerns , nil
120+ type facilityCount struct {
121+ FacilityID uint `gorm:"column:facility_id"`
122+ Count int64 `gorm:"column:count"`
123+ }
124+
125+ func (db * DB ) GetFacilityHealthSummaries (ctx * models.QueryContext , facilityID * uint ) ([]models.FacilityHealthSummary , error ) {
126+ var summaries []models.FacilityHealthSummary
127+ query := `SELECT
128+ f.id as facility_id,
129+ f.name as facility_name,
130+ COALESCE(COUNT(DISTINCT p.id), 0) as programs,
131+ COALESCE(COUNT(DISTINCT pc.id), 0) as active_classes,
132+ COALESCE(COUNT(DISTINCT pce.id), 0) as enrollment
133+ FROM facilities f
134+ LEFT JOIN facilities_programs fp
135+ ON fp.facility_id = f.id
136+ AND fp.deleted_at IS NULL
137+ LEFT JOIN programs p
138+ ON p.id = fp.program_id
139+ AND p.is_active = true
140+ AND p.deleted_at IS NULL
141+ AND p.archived_at IS NULL
142+ LEFT JOIN program_classes pc
143+ ON pc.facility_id = f.id
144+ AND pc.status = ?
145+ AND pc.archived_at IS NULL
146+ LEFT JOIN program_class_enrollments pce
147+ ON pce.class_id = pc.id
148+ AND pce.enrollment_status = ?
149+ WHERE f.deleted_at IS NULL `
150+ args := []any {models .Active , models .Enrolled }
151+ if facilityID != nil {
152+ query += " AND f.id = ? "
153+ args = append (args , * facilityID )
154+ }
155+ query += "GROUP BY f.id, f.name ORDER BY f.name"
156+
157+ if err := db .WithContext (ctx .Ctx ).Raw (query , args ... ).Scan (& summaries ).Error ; err != nil {
158+ return nil , err
159+ }
160+ return summaries , nil
161+ }
162+
163+ func (db * DB ) GetFacilityAttendanceConcerns (ctx * models.QueryContext , facilityID * uint ) (map [uint ]int64 , error ) {
164+ attendanceSQL := `SELECT c.facility_id as facility_id, COUNT(DISTINCT c.id) as count
165+ FROM program_classes c
166+ JOIN program_class_enrollments e ON e.class_id = c.id
167+ WHERE c.status = ?
168+ AND c.archived_at IS NULL
169+ AND e.enrollment_status = ?`
170+ args := []any {models .Active , models .Enrolled }
171+ if facilityID != nil {
172+ attendanceSQL += "AND c.facility_id = ? "
173+ args = append (args , * facilityID )
174+ }
175+ attendanceSQL += ` AND (
176+ select count(*)
177+ from program_class_events evt
178+ inner join program_class_event_attendance att on att.event_id = evt.id
179+ where evt.class_id = c.id
180+ and att.user_id = e.user_id
181+ and att.attendance_status = 'absent_unexcused'
182+ ) >= 3
183+ GROUP BY c.facility_id`
184+
185+ var counts []facilityCount
186+ if err := db .WithContext (ctx .Ctx ).Raw (attendanceSQL , args ... ).Scan (& counts ).Error ; err != nil {
187+ return nil , err
188+ }
189+
190+ results := make (map [uint ]int64 , len (counts ))
191+ for _ , entry := range counts {
192+ results [entry .FacilityID ] = entry .Count
193+ }
194+ return results , nil
71195}
0 commit comments