- Restructure: move backend from new_project/ to backend/ - Add full React/TypeScript frontend (37 pages, 17 services, 16 type defs, 11 query hooks) - Add docs/ with SRS specs, user stories, and workflow documentation - Update .gitignore for new directory layout Workflows implemented: WF1 User Signup, WF2 Placement Test, WF3 Exam Configuration, WF4 General English Exam, WF5 Course Generation, WF6 Entity Student Onboarding, AI Course Generation, Adaptive Learning Engine UI, White-Label Branding, Score Release Made-with: Cursor
68 lines
2.8 KiB
Python
68 lines
2.8 KiB
Python
import logging
|
|
from datetime import timedelta
|
|
|
|
from odoo import fields
|
|
|
|
_logger = logging.getLogger(__name__)
|
|
|
|
|
|
class AdaptiveAlertService:
|
|
"""Checks for students with no learning progress and creates teacher alerts."""
|
|
|
|
@classmethod
|
|
def check_no_progress(cls, env):
|
|
"""Find students with no adaptive events within threshold days and alert teachers.
|
|
|
|
Called by scheduled action (ir.cron).
|
|
"""
|
|
Settings = env['encoach.adaptive.settings'].sudo()
|
|
Event = env['encoach.adaptive.event'].sudo()
|
|
Path = env['encoach.adaptive.path'].sudo()
|
|
Activity = env['mail.activity'].sudo()
|
|
|
|
all_settings = Settings.search([])
|
|
if not all_settings:
|
|
all_settings = Settings.new({'no_progress_alert_days': 3})
|
|
|
|
for setting in all_settings:
|
|
days = setting.no_progress_alert_days or 3
|
|
cutoff = fields.Datetime.now() - timedelta(days=days)
|
|
teacher = setting.teacher_id
|
|
|
|
if not teacher:
|
|
continue
|
|
|
|
# Find students with active paths but no recent events
|
|
paths = Path.search([])
|
|
for path in paths:
|
|
student_id = path.student_id.id
|
|
recent_events = Event.search_count([
|
|
('student_id', '=', student_id),
|
|
('created_at', '>=', cutoff),
|
|
])
|
|
|
|
if recent_events == 0:
|
|
# Check if alert already exists for this student
|
|
existing = Activity.search([
|
|
('res_model', '=', 'res.users'),
|
|
('res_id', '=', student_id),
|
|
('user_id', '=', teacher.id),
|
|
('summary', 'ilike', 'No learning progress'),
|
|
('date_deadline', '>=', fields.Date.today()),
|
|
], limit=1)
|
|
|
|
if not existing:
|
|
activity_type = env.ref('mail.mail_activity_data_todo', raise_if_not_found=False)
|
|
Activity.create({
|
|
'res_model_id': env['ir.model']._get_id('res.users'),
|
|
'res_id': student_id,
|
|
'user_id': teacher.id,
|
|
'activity_type_id': activity_type.id if activity_type else False,
|
|
'summary': f'No learning progress for {days}+ days',
|
|
'note': f'Student {path.student_id.name} has not shown any '
|
|
f'learning activity in the last {days} days.',
|
|
'date_deadline': fields.Date.today(),
|
|
})
|
|
_logger.info('Created no-progress alert for student %s → teacher %s',
|
|
path.student_id.name, teacher.name)
|