69 lines
3.2 KiB
Python
69 lines
3.2 KiB
Python
from odoo import models, fields, api
|
|
from odoo.exceptions import ValidationError
|
|
|
|
class EducationGradingSystem(models.Model):
|
|
_name = 'education.grading.system'
|
|
_description = 'Grading System'
|
|
|
|
name = fields.Char(string='Name', required=True)
|
|
code = fields.Char(string='Code', required=True)
|
|
scale_type = fields.Selection([
|
|
('percentage', 'Percentage'),
|
|
('gpa_4', 'GPA 4.0'),
|
|
('gpa_10', 'GPA 10.0')
|
|
], string='Scale Type', required=True, default='percentage')
|
|
active = fields.Boolean(default=True)
|
|
grade_ids = fields.One2many('education.grade', 'grading_system_id', string='Grades')
|
|
|
|
def get_grade(self, percentage):
|
|
self.ensure_one()
|
|
grade = self.grade_ids.filtered(lambda g: g.min_percentage <= percentage <= g.max_percentage)
|
|
if grade:
|
|
# If multiple match due to floating point edge cases, take the highest grade point
|
|
return grade.sorted('grade_point', reverse=True)[0]
|
|
return self.env['education.grade']
|
|
|
|
class EducationGrade(models.Model):
|
|
_name = 'education.grade'
|
|
_description = 'Education Grade'
|
|
_order = 'sequence, id'
|
|
|
|
grading_system_id = fields.Many2one('education.grading.system', string='Grading System', required=True, ondelete='cascade')
|
|
name = fields.Char(string='Name', required=True)
|
|
code = fields.Char(string='Code')
|
|
min_percentage = fields.Float(string='Minimum Percentage', required=True)
|
|
max_percentage = fields.Float(string='Maximum Percentage', required=True)
|
|
grade_point = fields.Float(string='Grade Point', required=True)
|
|
result_status = fields.Selection([
|
|
('pass', 'Pass'),
|
|
('fail', 'Fail')
|
|
], string='Result Status', required=True, default='pass')
|
|
sequence = fields.Integer(string='Sequence', default=10)
|
|
active = fields.Boolean(default=True)
|
|
|
|
@api.constrains('min_percentage', 'max_percentage')
|
|
def _check_percentages(self):
|
|
for record in self:
|
|
if record.min_percentage < 0 or record.max_percentage > 100:
|
|
raise ValidationError("Percentages must be between 0 and 100.")
|
|
if record.min_percentage > record.max_percentage:
|
|
raise ValidationError("Minimum percentage cannot be greater than maximum percentage.")
|
|
|
|
# Check overlaps
|
|
domain = [
|
|
('grading_system_id', '=', record.grading_system_id.id),
|
|
('id', '!=', record.id),
|
|
'|', '|',
|
|
'&', ('min_percentage', '<=', record.min_percentage), ('max_percentage', '>=', record.min_percentage),
|
|
'&', ('min_percentage', '<=', record.max_percentage), ('max_percentage', '>=', record.max_percentage),
|
|
'&', ('min_percentage', '>=', record.min_percentage), ('max_percentage', '<=', record.max_percentage),
|
|
]
|
|
if self.search_count(domain) > 0:
|
|
raise ValidationError("Grade percentage ranges cannot overlap within the same grading system.")
|
|
|
|
@api.constrains('grade_point')
|
|
def _check_grade_point(self):
|
|
for record in self:
|
|
if record.grade_point < 0:
|
|
raise ValidationError("Grade point cannot be negative.")
|