from odoo import api, fields, models from odoo.exceptions import ValidationError class DanceEnrollment(models.Model): _name = "dance.enrollment" _description = "Dance Enrollment" _order = "enrollment_date desc, id desc" name = fields.Char(compute="_compute_name", store=True) student_id = fields.Many2one( "res.partner", required=True, domain="[('is_student', '=', True)]", ondelete="restrict", ) batch_id = fields.Many2one( "dance.batch", required=True, ondelete="restrict", ) enrollment_date = fields.Date(default=fields.Date.context_today, required=True) status = fields.Selection( [ ("active", "Active"), ("hold", "Hold"), ("dropped", "Dropped"), ("completed", "Completed"), ], default="active", required=True, ) notes = fields.Text() _sql_constraints = [ ( "student_batch_unique", "unique(student_id, batch_id)", "This student is already enrolled in this batch.", ), ] @api.depends("student_id", "batch_id") def _compute_name(self): for enrollment in self: if enrollment.student_id and enrollment.batch_id: enrollment.name = "%s - %s" % ( enrollment.student_id.display_name, enrollment.batch_id.name, ) else: enrollment.name = "New Enrollment" @api.constrains("batch_id", "status") def _check_batch_capacity(self): for enrollment in self: if enrollment.status != "active" or not enrollment.batch_id.capacity: continue active_count = self.search_count( [ ("batch_id", "=", enrollment.batch_id.id), ("status", "=", "active"), ("id", "!=", enrollment.id), ] ) if active_count + 1 > enrollment.batch_id.capacity: raise ValidationError("This batch is already at full capacity.") @api.constrains("student_id") def _check_student_flag(self): for enrollment in self: if enrollment.student_id and not enrollment.student_id.is_student: raise ValidationError("Only student contacts can be enrolled in a batch.") @api.onchange("batch_id", "status") def _onchange_batch_capacity_warning(self): if ( self.batch_id and self.status == "active" and self.batch_id.capacity and self.batch_id.active_enrollment_count < self.batch_id.capacity and self.batch_id.available_seats <= 2 ): return { "warning": { "title": "Batch almost full", "message": "Batch almost full (%s/%s)." % ( self.batch_id.active_enrollment_count, self.batch_id.capacity, ), } } return {}