187 lines
6.2 KiB
Python
187 lines
6.2 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)
|
|
|
|
# 课程作业:一门课对应多条作业记录
|
|
assignment_ids = fields.One2many(
|
|
'yuthon.school.assignment',
|
|
'course_id',
|
|
string='作业布置',
|
|
)
|
|
|
|
# 学习进展:一门课对应多条学员进度记录
|
|
progress_ids = fields.One2many(
|
|
'yuthon.school.progress',
|
|
'course_id',
|
|
string='学习进展',
|
|
)
|
|
|
|
@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'})
|