from odoo import fields, models, api class SchoolProgress(models.Model): """学习进展——记录每位学员在每门课程中的学习情况。""" _name = 'yuthon.school.progress' _description = '学习进展' _order = 'course_id, student_id' _rec_name = 'name' name = fields.Char(string='名称', compute='_compute_name', store=True) course_id = fields.Many2one( 'yuthon.school.course', string='课程', required=True, ondelete='cascade') student_id = fields.Many2one( 'yuthon.school.student', string='学员', required=True, ondelete='cascade') teacher_id = fields.Many2one( 'res.users', string='任课教师', related='course_id.teacher_id', readonly=True, store=True) # 章节进度(基于课程章节完成情况动态计算,仅用于展示,不入库) chapter_total = fields.Integer(string='章节总数', compute='_compute_chapter_progress') chapter_done = fields.Integer(string='已完成章节', compute='_compute_chapter_progress') progress_rate = fields.Float(string='学习进度(%)', compute='_compute_chapter_progress') # 状态:普通可写字段(搜索/过滤需用 stored 字段),由章节完成情况触发更新 status = fields.Selection( [('not_started', '未开始'), ('in_progress', '进行中'), ('completed', '已完成')], string='状态', default='not_started', index=True, required=True) last_study_date = fields.Date(string='最近学习日期') score = fields.Float(string='综合得分') note = fields.Text(string='备注') active = fields.Boolean(string='启用', default=True) def _compute_chapter_progress(self): """根据课程章节的「已完成学员」计算该学员的进度(展示用)。""" for r in self: chapters = r.course_id.chapter_ids if r.course_id else self.env['yuthon.school.course.chapter'] total = len(chapters) done = sum(1 for c in chapters if r.student_id in c.completed_student_ids) r.chapter_total = total r.chapter_done = done r.progress_rate = (done / total * 100.0) if total else 0.0 def recompute_status(self): """依据章节完成情况刷新状态(在章节完成状态变化时调用)。""" for r in self: total = r.chapter_total done = r.chapter_done if total == 0 or done == 0: new_status = 'not_started' elif done >= total: new_status = 'completed' else: new_status = 'in_progress' if r.status != new_status: r.write({'status': new_status}) @api.model_create_multi def create(self, vals_list): recs = super().create(vals_list) recs.recompute_status() return recs @api.depends('course_id', 'student_id') def _compute_name(self): for r in self: r.name = '%s · %s' % (r.course_id.name or '', r.student_id.name or '')