from odoo import models, fields, tools, api class BenchManagementLine(models.Model): _name = "bench.management.line" _description = "Employee Availability (Bench)" _auto = False _rec_name = 'employee_id' employee_id = fields.Many2one("hr.employee", readonly=True) job_id = fields.Many2one("hr.job", readonly=True) company_id = fields.Many2one("res.company", related="employee_id.company_id") project_line_ids = fields.Many2many( 'project.team.line', compute='_compute_bench_details', string='Project Assignments', readonly=True, ) limited_project_line_ids = fields.Many2many( compute='_compute_bench_details', comodel_name='project.team.line', string='Kanban Projects', readonly=True, ) project_names_tooltip = fields.Text( string="Project Names", compute='_compute_bench_details', readonly=True, ) project_count = fields.Integer( string="Project Count", compute='_compute_bench_details', readonly=True, ) active_project_count = fields.Integer( string="Active Projects", compute='_compute_bench_details', readonly=True, ) future_project_count = fields.Integer( string="Upcoming Projects", compute='_compute_bench_details', readonly=True, ) completed_project_count = fields.Integer( string="Completed Projects", compute='_compute_bench_details', readonly=True, ) status = fields.Selection([ ("bench", "Bench"), ("partial", "Partial"), ("full", "Full"), ], readonly=True) def _get_line_availability_status(self, line, today): return line.status or 'not_started' def _compute_bench_details(self): project_team_line = self.env['project.team.line'].sudo() today = fields.Date.context_today(self) for rec in self: project_lines = project_team_line.search( [('employee_id', '=', rec.employee_id.id)], order='start_date desc, id desc' ) active_lines = project_lines.filtered( lambda line: rec._get_line_availability_status(line, today) == 'in_progress' ) future_lines = project_lines.filtered( lambda line: rec._get_line_availability_status(line, today) == 'not_started' ) completed_lines = project_lines.filtered( lambda line: rec._get_line_availability_status(line, today) == 'done' ) project_records = project_lines.mapped('project_id') if active_lines: bench_status = 'full' elif future_lines: bench_status = 'partial' else: bench_status = 'bench' rec.project_line_ids = project_lines rec.limited_project_line_ids = project_lines[:3] rec.project_count = len(project_records) rec.active_project_count = len(active_lines) rec.future_project_count = len(future_lines) rec.completed_project_count = len(completed_lines) rec.project_names_tooltip = '\n'.join( f"{line.project_id.display_name or 'No Project'} - {dict(line._fields['status'].selection).get(rec._get_line_availability_status(line, today), 'N/A')}" for line in project_lines ) or '' def init(self): tools.drop_view_if_exists(self.env.cr, self._table) self.env.cr.execute(""" CREATE OR REPLACE VIEW bench_management_line AS ( SELECT he.id AS id, he.id AS employee_id, he.job_id AS job_id, CASE WHEN EXISTS ( SELECT 1 FROM project_team_line tpl WHERE tpl.employee_id = he.id AND tpl.status = 'in_progress' ) THEN 'full' WHEN EXISTS ( SELECT 1 FROM project_team_line tpl WHERE tpl.employee_id = he.id AND tpl.status = 'not_started' ) THEN 'partial' ELSE 'bench' END AS status FROM hr_employee he ) """) class ProjectTeamLine(models.Model): _inherit = 'project.team.line' line_status_color = fields.Integer( compute='_compute_line_status_color', string='Status Color', readonly=True, ) @api.depends('status') def _compute_line_status_color(self): color_map = { 'not_started': 8, 'in_progress': 2, 'done': 10, } for line in self: line.line_status_color = color_map.get(line.status, 0) def name_get(self): result = [] for rec in self: name = rec.project_id.display_name or 'No Project' result.append((rec.id, name)) return result def _sync_project_members(self): if self.env.context.get('skip_project_team_member_sync'): return True self.mapped('project_id')._sync_members_from_team_lines() return True @api.model_create_multi def create(self, vals_list): records = super().create(vals_list) records._sync_project_members() return records def write(self, vals): projects = self.mapped('project_id') res = super().write(vals) (projects | self.mapped('project_id'))._sync_members_from_team_lines() return res def unlink(self): projects = self.mapped('project_id') res = super().unlink() projects._sync_members_from_team_lines() return res