from odoo import api, fields, models from odoo.exceptions import ValidationError from datetime import timedelta class TeamRoster(models.Model): _name = 'team.roster' _description = 'Team Roster' _inherit = ['mail.thread', 'mail.activity.mixin'] name = fields.Char( required=True ) start_date = fields.Date( required=True ) end_date = fields.Date( required=True ) state = fields.Selection([ ('draft', 'Draft'), ('generated', 'Generated'), ('approved', 'Approved') ], default='draft') line_ids = fields.One2many( 'team.roster.line', 'roster_id' ) def action_generate_roster(self): shifts = self.env[ 'resource.calendar' ].search([]) employees = self.env[ 'hr.employee' ].search([ ('active', '=', True) ]) if not shifts: return self.line_ids.unlink() shift_count = len(shifts) current_date = self.start_date counter = 0 while current_date <= self.end_date: for emp in employees: self.env[ 'team.roster.line' ].create({ 'roster_id': self.id, 'employee_id': emp.id, 'shift_id': shifts[ counter % shift_count ].id, 'roster_date': current_date }) counter += 1 current_date += timedelta(days=1) self.state = 'generated' class TeamRosterLine(models.Model): _name = 'team.roster.line' _description = 'Team Roster Line' roster_id = fields.Many2one( 'team.roster' ) employee_id = fields.Many2one( 'hr.employee', required=True ) shift_id = fields.Many2one( 'resource.calendar', required=True, string="Shift" ) roster_date = fields.Date( required=True ) department_id = fields.Many2one( related='employee_id.department_id', store=True ) @api.constrains( 'employee_id', 'roster_date' ) def _check_duplicate(self): for rec in self: duplicate = self.search([ ('employee_id', '=', rec.employee_id.id), ('roster_date', '=', rec.roster_date), ('id', '!=', rec.id) ]) if duplicate: raise ValidationError( "Employee already has a shift assigned." )