2026-09-28 11:03:02 +05:30

170 lines
6.4 KiB
Python

from odoo import api, fields, models
from odoo.exceptions import ValidationError
class DanceRehearsal(models.Model):
_name = "dance.rehearsal"
_description = "Dance Event Rehearsal"
_order = "date desc, start_time desc, id desc"
name = fields.Char(compute="_compute_name", store=True)
event_id = fields.Many2one("dance.event", required=True, ondelete="cascade")
date = fields.Date(required=True, default=fields.Date.context_today)
start_time = fields.Float(string="Start Time", required=True)
end_time = fields.Float(string="End Time")
display_time = fields.Char(compute="_compute_display_time")
room = fields.Char()
status = fields.Selection(
[
("scheduled", "Scheduled"),
("completed", "Completed"),
("cancelled", "Cancelled"),
],
default="scheduled",
required=True,
)
attendance_ids = fields.One2many(
"dance.rehearsal.attendance",
"rehearsal_id",
string="Attendance",
)
attendance_count = fields.Integer(compute="_compute_attendance_counts")
present_count = fields.Integer(compute="_compute_attendance_counts")
absent_count = fields.Integer(compute="_compute_attendance_counts")
late_count = fields.Integer(compute="_compute_attendance_counts")
notes = fields.Text()
@api.depends("event_id", "date", "start_time")
def _compute_name(self):
for rehearsal in self:
if rehearsal.event_id and rehearsal.date:
rehearsal.name = "%s rehearsal - %s" % (
rehearsal.event_id.name,
rehearsal.date,
)
else:
rehearsal.name = "New Rehearsal"
@api.depends("start_time", "end_time")
def _compute_display_time(self):
for rehearsal in self:
rehearsal.display_time = rehearsal._float_to_time(rehearsal.start_time)
if rehearsal.end_time:
rehearsal.display_time += " - %s" % rehearsal._float_to_time(rehearsal.end_time)
@api.depends("attendance_ids.status")
def _compute_attendance_counts(self):
for rehearsal in self:
rehearsal.attendance_count = len(rehearsal.attendance_ids)
rehearsal.present_count = len(
rehearsal.attendance_ids.filtered(lambda line: line.status == "present")
)
rehearsal.absent_count = len(
rehearsal.attendance_ids.filtered(lambda line: line.status == "absent")
)
rehearsal.late_count = len(
rehearsal.attendance_ids.filtered(lambda line: line.status == "late")
)
@api.constrains("start_time", "end_time")
def _check_times(self):
for rehearsal in self:
if rehearsal.end_time and rehearsal.start_time and rehearsal.end_time <= rehearsal.start_time:
raise ValidationError("End time must be after start time.")
def action_load_students(self):
for rehearsal in self:
students = rehearsal.event_id.performance_ids.mapped("student_id") or rehearsal.event_id.student_ids
existing_student_ids = set(rehearsal.attendance_ids.mapped("student_id").ids)
vals_list = []
for student in students:
if student.id in existing_student_ids:
continue
vals_list.append(
{
"rehearsal_id": rehearsal.id,
"student_id": student.id,
"status": "present",
}
)
if vals_list:
self.env["dance.rehearsal.attendance"].create(vals_list)
return True
def action_mark_all_present(self):
for rehearsal in self:
if not rehearsal.attendance_ids:
rehearsal.action_load_students()
rehearsal.attendance_ids.write({"status": "present"})
return True
def action_complete(self):
self.write({"status": "completed"})
return True
def action_cancel(self):
self.write({"status": "cancelled"})
return True
def action_send_rehearsal_reminder(self):
for rehearsal in self:
students = rehearsal.attendance_ids.mapped("student_id") or rehearsal.event_id.performance_ids.mapped("student_id") or rehearsal.event_id.student_ids
rehearsal.event_id._create_whatsapp_logs(
"rehearsal_reminder",
students,
rehearsal=rehearsal,
)
return True
def _float_to_time(self, value):
hours = int(value or 0)
minutes = int(round(((value or 0) - hours) * 60))
suffix = "AM" if hours < 12 else "PM"
display_hours = hours % 12 or 12
return "%d:%02d %s" % (display_hours, minutes, suffix)
class DanceRehearsalAttendance(models.Model):
_name = "dance.rehearsal.attendance"
_description = "Dance Rehearsal Attendance"
_order = "rehearsal_id desc, student_id"
rehearsal_id = fields.Many2one("dance.rehearsal", required=True, ondelete="cascade")
event_id = fields.Many2one(related="rehearsal_id.event_id", store=True, readonly=True)
student_id = fields.Many2one(
"res.partner",
required=True,
domain="[('is_student', '=', True)]",
ondelete="restrict",
)
date = fields.Date(related="rehearsal_id.date", store=True, readonly=True)
status = fields.Selection(
[
("present", "Present"),
("absent", "Absent"),
("late", "Late"),
],
default="present",
required=True,
)
remarks = fields.Text()
_sql_constraints = [
(
"unique_rehearsal_attendance",
"unique(student_id, rehearsal_id)",
"Attendance is already marked for this student in this rehearsal.",
),
]
@api.constrains("student_id", "rehearsal_id")
def _check_student_in_event(self):
for attendance in self:
if attendance.student_id and attendance.rehearsal_id:
event = attendance.rehearsal_id.event_id
event_students = event.performance_ids.mapped("student_id") or event.student_ids
if attendance.student_id not in event_students:
raise ValidationError(
"Attendance can only be marked for students participating in this event."
)