ngwakomadikwe commited on
Commit
6be52bf
Β·
verified Β·
1 Parent(s): cb049d7

Create school_service.py (School Data Service)

Browse files
school_service.py (School Data Service) ADDED
@@ -0,0 +1,328 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ School Service Layer for ThutoAI
3
+ Handles all school-related data operations
4
+ """
5
+ from models import DatabaseManager
6
+ from datetime import datetime, date
7
+ import json
8
+
9
+ class SchoolService:
10
+ def __init__(self):
11
+ self.db = DatabaseManager()
12
+
13
+ def get_recent_announcements(self, limit=5):
14
+ """Get recent active announcements"""
15
+ conn = self.db.get_connection()
16
+ cursor = conn.cursor()
17
+
18
+ cursor.execute('''
19
+ SELECT title, content, priority, created_at
20
+ FROM announcements
21
+ WHERE is_active = 1
22
+ AND (expires_at IS NULL OR expires_at > datetime('now'))
23
+ ORDER BY priority DESC, created_at DESC
24
+ LIMIT ?
25
+ ''', (limit,))
26
+
27
+ announcements = cursor.fetchall()
28
+ conn.close()
29
+
30
+ return [
31
+ {
32
+ 'title': ann[0],
33
+ 'content': ann[1],
34
+ 'priority': ann[2],
35
+ 'date': ann[3]
36
+ }
37
+ for ann in announcements
38
+ ]
39
+
40
+ def get_upcoming_exams(self, days_ahead=30):
41
+ """Get upcoming examinations"""
42
+ conn = self.db.get_connection()
43
+ cursor = conn.cursor()
44
+
45
+ cursor.execute('''
46
+ SELECT exam_name, subject, exam_date, exam_time, location, instructions
47
+ FROM examinations
48
+ WHERE exam_date >= date('now')
49
+ AND exam_date <= date('now', '+{} days')
50
+ ORDER BY exam_date ASC, exam_time ASC
51
+ '''.format(days_ahead))
52
+
53
+ exams = cursor.fetchall()
54
+ conn.close()
55
+
56
+ return [
57
+ {
58
+ 'name': exam[0],
59
+ 'subject': exam[1],
60
+ 'date': exam[2],
61
+ 'time': exam[3],
62
+ 'location': exam[4],
63
+ 'instructions': exam[5]
64
+ }
65
+ for exam in exams
66
+ ]
67
+
68
+ def get_upcoming_tests_assignments(self, days_ahead=14):
69
+ """Get upcoming tests and assignments"""
70
+ conn = self.db.get_connection()
71
+ cursor = conn.cursor()
72
+
73
+ cursor.execute('''
74
+ SELECT title, subject, type, due_date, due_time, description, total_marks
75
+ FROM tests_assignments
76
+ WHERE due_date >= date('now')
77
+ AND due_date <= date('now', '+{} days')
78
+ ORDER BY due_date ASC, due_time ASC
79
+ '''.format(days_ahead))
80
+
81
+ tests = cursor.fetchall()
82
+ conn.close()
83
+
84
+ return [
85
+ {
86
+ 'title': test[0],
87
+ 'subject': test[1],
88
+ 'type': test[2],
89
+ 'due_date': test[3],
90
+ 'due_time': test[4],
91
+ 'description': test[5],
92
+ 'total_marks': test[6]
93
+ }
94
+ for test in tests
95
+ ]
96
+
97
+ def get_student_grades(self, student_id, subject=None, limit=10):
98
+ """Get student grades, optionally filtered by subject"""
99
+ conn = self.db.get_connection()
100
+ cursor = conn.cursor()
101
+
102
+ if subject:
103
+ cursor.execute('''
104
+ SELECT subject, assessment_type, assessment_name, marks_obtained,
105
+ total_marks, percentage, grade_letter, date_recorded, teacher_comments
106
+ FROM grades
107
+ WHERE student_id = ? AND subject = ?
108
+ ORDER BY date_recorded DESC
109
+ LIMIT ?
110
+ ''', (student_id, subject, limit))
111
+ else:
112
+ cursor.execute('''
113
+ SELECT subject, assessment_type, assessment_name, marks_obtained,
114
+ total_marks, percentage, grade_letter, date_recorded, teacher_comments
115
+ FROM grades
116
+ WHERE student_id = ?
117
+ ORDER BY date_recorded DESC
118
+ LIMIT ?
119
+ ''', (student_id, limit))
120
+
121
+ grades = cursor.fetchall()
122
+ conn.close()
123
+
124
+ return [
125
+ {
126
+ 'subject': grade[0],
127
+ 'type': grade[1],
128
+ 'name': grade[2],
129
+ 'marks_obtained': grade[3],
130
+ 'total_marks': grade[4],
131
+ 'percentage': grade[5],
132
+ 'grade': grade[6],
133
+ 'date': grade[7],
134
+ 'comments': grade[8]
135
+ }
136
+ for grade in grades
137
+ ]
138
+
139
+ def get_upcoming_events(self, days_ahead=30):
140
+ """Get upcoming school events"""
141
+ conn = self.db.get_connection()
142
+ cursor = conn.cursor()
143
+
144
+ cursor.execute('''
145
+ SELECT event_name, event_date, event_time, location, description, event_type, is_holiday
146
+ FROM school_events
147
+ WHERE event_date >= date('now')
148
+ AND event_date <= date('now', '+{} days')
149
+ ORDER BY event_date ASC, event_time ASC
150
+ '''.format(days_ahead))
151
+
152
+ events = cursor.fetchall()
153
+ conn.close()
154
+
155
+ return [
156
+ {
157
+ 'name': event[0],
158
+ 'date': event[1],
159
+ 'time': event[2],
160
+ 'location': event[3],
161
+ 'description': event[4],
162
+ 'type': event[5],
163
+ 'is_holiday': bool(event[6])
164
+ }
165
+ for event in events
166
+ ]
167
+
168
+ def get_student_summary(self, student_id="STU001"):
169
+ """Get comprehensive student summary"""
170
+ return {
171
+ 'announcements': self.get_recent_announcements(3),
172
+ 'upcoming_exams': self.get_upcoming_exams(30),
173
+ 'upcoming_tests': self.get_upcoming_tests_assignments(14),
174
+ 'recent_grades': self.get_student_grades(student_id, limit=5),
175
+ 'upcoming_events': self.get_upcoming_events(30),
176
+ 'syllabus': self.get_student_syllabus("Grade 10"),
177
+ 'timetable': self.get_student_timetable("10-A")
178
+ }
179
+
180
+ def get_student_syllabus(self, grade_level):
181
+ """Get syllabus for student's grade level"""
182
+ conn = self.db.get_connection()
183
+ cursor = conn.cursor()
184
+
185
+ cursor.execute('''
186
+ SELECT subject, chapter_title, topics, learning_objectives, duration_weeks, resources
187
+ FROM syllabus
188
+ WHERE grade_level = ? AND is_active = 1
189
+ ORDER BY subject, chapter_number
190
+ ''', (grade_level,))
191
+
192
+ syllabus_data = cursor.fetchall()
193
+ conn.close()
194
+
195
+ return [
196
+ {
197
+ 'subject': syl[0],
198
+ 'chapter_title': syl[1],
199
+ 'topics': json.loads(syl[2]) if syl[2] else [],
200
+ 'learning_objectives': syl[3],
201
+ 'duration_weeks': syl[4],
202
+ 'resources': json.loads(syl[5]) if syl[5] else []
203
+ }
204
+ for syl in syllabus_data
205
+ ]
206
+
207
+ def get_student_timetable(self, class_section):
208
+ """Get timetable for student's class"""
209
+ conn = self.db.get_connection()
210
+ cursor = conn.cursor()
211
+
212
+ cursor.execute('''
213
+ SELECT day_of_week, period_number, start_time, end_time, subject, teacher_name, room_number
214
+ FROM timetable
215
+ WHERE class_section = ? AND is_active = 1
216
+ ORDER BY day_of_week, period_number
217
+ ''', (class_section,))
218
+
219
+ timetable_data = cursor.fetchall()
220
+ conn.close()
221
+
222
+ # Group by day of week
223
+ timetable_by_day = {}
224
+ for tt in timetable_data:
225
+ day = tt[0]
226
+ if day not in timetable_by_day:
227
+ timetable_by_day[day] = []
228
+
229
+ timetable_by_day[day].append({
230
+ 'period': tt[1],
231
+ 'start_time': tt[2],
232
+ 'end_time': tt[3],
233
+ 'subject': tt[4],
234
+ 'teacher': tt[5],
235
+ 'room': tt[6]
236
+ })
237
+
238
+ return timetable_by_day
239
+
240
+ def search_school_info(self, query):
241
+ """Search across all school information"""
242
+ query = query.lower()
243
+ results = []
244
+
245
+ # Search announcements
246
+ announcements = self.get_recent_announcements(10)
247
+ for ann in announcements:
248
+ if query in ann['title'].lower() or query in ann['content'].lower():
249
+ results.append({
250
+ 'type': 'announcement',
251
+ 'title': ann['title'],
252
+ 'content': ann['content'],
253
+ 'priority': ann['priority']
254
+ })
255
+
256
+ # Search exams
257
+ exams = self.get_upcoming_exams(60)
258
+ for exam in exams:
259
+ if query in exam['name'].lower() or query in exam['subject'].lower():
260
+ results.append({
261
+ 'type': 'exam',
262
+ 'name': exam['name'],
263
+ 'subject': exam['subject'],
264
+ 'date': exam['date'],
265
+ 'time': exam['time']
266
+ })
267
+
268
+ # Search tests/assignments
269
+ tests = self.get_upcoming_tests_assignments(30)
270
+ for test in tests:
271
+ if query in test['title'].lower() or query in test['subject'].lower():
272
+ results.append({
273
+ 'type': 'test_assignment',
274
+ 'title': test['title'],
275
+ 'subject': test['subject'],
276
+ 'type_detail': test['type'],
277
+ 'due_date': test['due_date']
278
+ })
279
+
280
+ return results
281
+
282
+ def format_school_context_for_ai(self, student_id="STU001"):
283
+ """Format school information as context for AI"""
284
+ summary = self.get_student_summary(student_id)
285
+
286
+ context = "SCHOOL INFORMATION CONTEXT:\n\n"
287
+
288
+ # Recent announcements
289
+ if summary['announcements']:
290
+ context += "πŸ“’ RECENT ANNOUNCEMENTS:\n"
291
+ for ann in summary['announcements']:
292
+ context += f"- {ann['title']}: {ann['content']}\n"
293
+ context += "\n"
294
+
295
+ # Upcoming exams
296
+ if summary['upcoming_exams']:
297
+ context += "πŸ“ UPCOMING EXAMS:\n"
298
+ for exam in summary['upcoming_exams']:
299
+ context += f"- {exam['name']} ({exam['subject']}) on {exam['date']} at {exam['time']}\n"
300
+ context += "\n"
301
+
302
+ # Upcoming tests/assignments
303
+ if summary['upcoming_tests']:
304
+ context += "πŸ“š UPCOMING TESTS & ASSIGNMENTS:\n"
305
+ for test in summary['upcoming_tests']:
306
+ context += f"- {test['title']} ({test['subject']}) due {test['due_date']}\n"
307
+ context += "\n"
308
+
309
+ # Recent grades
310
+ if summary['recent_grades']:
311
+ context += "πŸ“Š RECENT GRADES:\n"
312
+ for grade in summary['recent_grades']:
313
+ context += f"- {grade['subject']}: {grade['percentage']}% ({grade['grade']}) in {grade['name']}\n"
314
+ context += "\n"
315
+
316
+ # Upcoming events
317
+ if summary['upcoming_events']:
318
+ context += "πŸŽ‰ UPCOMING EVENTS:\n"
319
+ for event in summary['upcoming_events']:
320
+ context += f"- {event['name']} on {event['date']}\n"
321
+ context += "\n"
322
+
323
+ context += "Use this information to provide contextual and helpful responses to the student."
324
+
325
+ return context
326
+
327
+ # Initialize service
328
+ school_service = SchoolService()