Files
shcool/college/models/course.py
T

173 lines
5.9 KiB
Python

from odoo import api, fields, models
_COLLEGE_SELECTION = [
('computer', '计算机学院'),
('software', '软件学院'),
('business', '商学院'),
('foreign', '外国语学院'),
('mechanic', '机械工程学院'),
('electric', '电子信息学院'),
('math', '数学学院'),
('other', '其他'),
]
_SEMESTER_SELECTION = [
('2025_1', '2025-2026学年第一学期'),
('2025_2', '2025-2026学年第二学期'),
('2026_1', '2026-2027学年第一学期'),
('2026_2', '2026-2027学年第二学期'),
]
class SchoolCourse(models.Model):
"""课程——每位老师独立管理自己的课程。
学院 / 学期 作为课程上的字段(非独立模型)。
课程模块支持 理论 / 实践。
"""
_name = 'yuthon.school.course'
_description = '课程'
_inherit = ['mail.thread', 'mail.activity.mixin']
_order = 'semester, college, name'
name = fields.Char(string='课程名称', required=True, index=True)
code = fields.Char(string='课程编号', index=True)
teacher_id = fields.Many2one(
'res.users',
string='任课教师',
default=lambda self: self.env.user,
required=True,
index=True,
help='课程归属教师,默认带出当前登录用户;每位老师独立管理自己的课程。',
)
# 学院 / 学期:课程上的字段,不是独立模型
college = fields.Selection(_COLLEGE_SELECTION, string='学院', index=True)
semester = fields.Selection(_SEMESTER_SELECTION, string='学期', index=True)
# 课程模块(参考站:理论 / 实践)
course_type = fields.Selection(
[('theory', '理论'), ('practice', '实践')],
string='课程模块',
default='theory',
required=True,
index=True,
)
hours = fields.Integer(string='课时', required=True, default=32)
start_date = fields.Date(string='开始日期')
end_date = fields.Date(string='结束日期')
is_public = fields.Boolean(
string='公开',
default=False,
help='开启后可在高校优质课堂等公开渠道展示推广。',
)
# 视频 / 课件(PPT 等)
video_file = fields.Binary(string='视频文件', attachment=True)
video_filename = fields.Char(string='视频文件名')
ppt_file = fields.Binary(string='PPT / 课件', attachment=True)
ppt_filename = fields.Char(string='课件文件名')
# 课程详情
introduction = fields.Html(string='课程介绍', sanitize=True)
objectives = fields.Html(string='课程目标', sanitize=True)
features = fields.Html(string='课程特色', sanitize=True)
syllabus = fields.Html(string='课程大纲', sanitize=True)
business_scenario = fields.Html(string='业务情景', sanitize=True)
# 学员分配
student_ids = fields.Many2many(
'yuthon.school.student',
string='选课学员',
help='老师为课程分配的学员(选课名单)。',
)
student_count = fields.Integer(
string='学员人数',
compute='_compute_student_count',
store=True,
)
# 看板状态
state = fields.Selection(
[('draft', '草稿'), ('published', '已发布'), ('archived', '已归档')],
string='状态',
default='draft',
required=True,
index=True,
)
active = fields.Boolean(string='启用', default=True)
# 课程章节(老师端维护,学生端作为学习目录,同源联动)
chapter_ids = fields.One2many(
'yuthon.school.course.chapter', 'course_id', string='课程章节')
chapter_count = fields.Integer(
string='章节数', compute='_compute_chapter_count', store=True)
@api.depends('student_ids')
def _compute_student_count(self):
for record in self:
record.student_count = len(record.student_ids)
@api.depends('chapter_ids')
def _compute_chapter_count(self):
for record in self:
record.chapter_count = len(record.chapter_ids)
@api.model_create_multi
def create(self, vals_list):
courses = super().create(vals_list)
for course in courses:
course._sync_progress_records()
return courses
def write(self, vals):
if 'student_ids' in vals:
# 先记录旧学员, super 写入后再按差异同步学习进展
old_students_map = {course.id: course.student_ids for course in self}
res = super().write(vals)
for course in self:
old_students = old_students_map.get(course.id, self.env['yuthon.school.student'])
course._sync_progress_records(old_students)
return res
return super().write(vals)
def _sync_progress_records(self, old_students=None):
"""根据课程选课学员变化,自动增删学习进展记录。"""
self.ensure_one()
Progress = self.env['yuthon.school.progress'].sudo()
old_students = old_students or self.env['yuthon.school.student']
new_students = self.student_ids
added = new_students - old_students
removed = old_students - new_students
if added:
existing = Progress.search([
('course_id', '=', self.id),
('student_id', 'in', added.ids),
]).mapped('student_id')
to_create = added - existing
Progress.create([{
'course_id': self.id,
'student_id': student.id,
} for student in to_create])
if removed:
Progress.search([
('course_id', '=', self.id),
('student_id', 'in', removed.ids),
]).unlink()
# 状态流转
def action_publish(self):
self.write({'state': 'published'})
def action_archive(self):
self.write({'state': 'archived'})
def action_to_draft(self):
self.write({'state': 'draft'})