shcool/learning_center/models/course_student_score.py
2026-06-15 23:57:01 +08:00

112 lines
6.0 KiB
Python

from odoo import api, fields, models
from odoo.exceptions import ValidationError
class CourseStudentScore(models.Model):
_name = 'course.student.score'
_description = '学生成绩'
_rec_name = 'display_name'
_order = 'course_id, student_id'
_inherit = ['mail.thread']
display_name = fields.Char(string='显示名称', compute='_compute_display_name', store=True)
@api.depends('course_name', 'stu_name')
def _compute_display_name(self):
for record in self:
record.display_name = f"{record.stu_name} - {record.course_name}"
course_id = fields.Many2one('learning.course', string='课程', required=True, ondelete='cascade')
# 课程扩展只读字段(替代视图嵌套写法)
course_code = fields.Char(string="课程代码", related="course_id.code", readonly=True)
course_credit = fields.Float(string="学分", related="course_id.credit", readonly=True)
course_exam_type = fields.Selection(string="考核方式", related="course_id.exam_type", readonly=True)
course_name = fields.Char(related='course_id.name', string='课程', required=True, ondelete='cascade')
student_id = fields.Many2one('student.info', string='学生', required=True)
student_no = fields.Char(string="学号", related="student_id.stu_num", readonly=True)
student_class_id = fields.Many2one( string="班级", related="student_id.class_id", readonly=True)
student_major_id = fields.Many2one( string="专业", related="student_id.major_id", readonly=True)
stu_name=fields.Char(related='student_id.stu_name',required=True, ondelete='cascade',string='学生姓名')
score_ids = fields.One2many('course.student.score.detail', 'student_score_id', string='成绩明细')
teaching_class_id=fields.Many2one('course.teaching_class',string='教学班')
# 教学班相关只读关联字段
teaching_class_name = fields.Char(string="教学班名称", related="teaching_class_id.display_name", readonly=True)
teaching_class_semester = fields.Selection(string="学期", related="teaching_class_id.semester", readonly=True)
teaching_class_main_teacher = fields.Many2one('hr.employee', string="主讲教师",
related="teaching_class_id.main_teacher_id", readonly=True)
total_score = fields.Float(string='综合成绩', compute='_compute_total_score', store=True)
grade_level = fields.Selection([
('A', '优秀(A)'),
('B', '良好(B)'),
('C', '中等(C)'),
('D', '及格(D)'),
('F', '不及格(F)'),
], string='等级', compute='_compute_total_score', store=True)
@api.depends('score_ids.score', 'score_ids.weight')
def _compute_total_score(self):
for record in self:
total = 0.0
for detail in record.score_ids:
if detail.score and detail.weight:
total += detail.score * detail.weight / 100
record.total_score = round(total, 2)
if record.total_score >= 90:
record.grade_level = 'A'
elif record.total_score >= 80:
record.grade_level = 'B'
elif record.total_score >= 70:
record.grade_level = 'C'
elif record.total_score >= 60:
record.grade_level = 'D'
else:
record.grade_level = 'F'
class CourseStudentScoreDetail(models.Model):
_name = 'course.student.score.detail'
_description = '学生成绩明细'
_rec_name = 'display_name'
_order = 'student_score_id, score_item_id'
_inherit = ['mail.thread']
display_name = fields.Char(string='显示名称', compute='_compute_display_name', store=True)
@api.depends('student_score_displayname', 'score_item_id.name')
def _compute_display_name(self):
for record in self:
record.display_name = f"{record.student_score_displayname} - {record.score_item_id.name}"
# 关联学生成绩主表
student_score_id = fields.Many2one('course.student.score', string='学生成绩', required=True, ondelete='cascade')
student_score_displayname=fields.Char(related='student_score_id.display_name',required=True, ondelete='cascade',string='显示名称')
# 关联成绩项目
score_item_id = fields.Many2one('course.score.item', string='成绩项目', required=True, ondelete='restrict')
# 得分
score = fields.Float(string='得分', help='该项目实际得分')
# 从成绩项目继承的字段(用于显示和计算)
weight = fields.Float(string='权重(%)', related='score_item_id.weight', store=True, readonly=True)
full_score = fields.Float(string='满分', related='score_item_id.full_score', store=True, readonly=True)
score_type = fields.Selection(string='成绩类型', related='score_item_id.score_type', store=True, readonly=True)
# 备注
remark = fields.Char(string='备注')
# 关联课程和学生(用于视图显示)
course_id = fields.Many2one('learning.course', string='课程', related='student_score_id.course_id', store=True,
readonly=True)
student_id = fields.Many2one('student.info', string='学生', related='student_score_id.student_id', store=True,
readonly=True)
# 完成率(得分/满分)
completion_rate = fields.Float(string='完成率(%)', compute='_compute_completion_rate', store=True)
@api.depends('score', 'full_score')
def _compute_completion_rate(self):
for record in self:
if record.full_score and record.score:
record.completion_rate = round(record.score / record.full_score * 100, 1)
else:
record.completion_rate = 0.0
@api.constrains('score', 'full_score')
def _check_score(self):
for record in self:
if record.score and record.full_score and record.score > record.full_score:
raise ValidationError(f'得分({record.score})不能超过满分({record.full_score})')
if record.score and record.score < 0:
raise ValidationError('得分不能为负数')