from odoo import _, api, fields, models from odoo.exceptions import ValidationError class HrApplicant(models.Model): _inherit = "hr.applicant" bridge_ids = fields.One2many("recruitment.employee.bridge", "applicant_id", string="Onboarding Records") bridge_count = fields.Integer(compute="_compute_bridge_count") bridge_employee_id = fields.Many2one( "hr.employee", compute="_compute_bridge_employee", string="Onboarding Employee", ) bridge_employee_name = fields.Char(related="bridge_employee_id.name", string="Employee") bridge_employee_code = fields.Char(related="bridge_employee_id.employee_id", string="Employee Code") def _compute_bridge_count(self): data = self.env["recruitment.employee.bridge"].read_group( [("applicant_id", "in", self.ids), ("active", "=", True)], ["applicant_id"], ["applicant_id"], ) counts = {item["applicant_id"][0]: item["applicant_id_count"] for item in data} for applicant in self: applicant.bridge_count = counts.get(applicant.id, 0) def _compute_bridge_employee(self): bridges = self.env["recruitment.employee.bridge"].search( [("applicant_id", "in", self.ids), ("active", "=", True)], order="id desc", ) bridge_by_applicant = {} for bridge in bridges: bridge_by_applicant.setdefault(bridge.applicant_id.id, bridge) for applicant in self: bridge = bridge_by_applicant.get(applicant.id) applicant.bridge_employee_id = bridge.employee_id if bridge else False def _get_bridge(self, create=False, employee=False, source="recruitment"): self.ensure_one() vals = self._get_recruitment_bridge_vals(source=source) bridge = self.env["recruitment.employee.bridge"].search( ['|','|',('work_email','=',vals['work_email']),('work_phone','=',vals['work_phone']),("applicant_id", "=", self.id), ("active", "=", True)], limit=1, order="id desc", ) if not bridge and create: vals.update({ "applicant_id": self.id, "candidate_id": self.candidate_id.id, }) if employee: vals.update({ "employee_id": employee.id, "company_id": employee.company_id.id or vals["company_id"], "state": "draft", }) bridge = self.env["recruitment.employee.bridge"].create(vals) return bridge def _get_recruitment_bridge_vals(self, source="recruitment"): self.ensure_one() return { "employee_name": self.partner_name or self.candidate_id.partner_name, "work_email": self.email_from or self.candidate_id.email_from, "work_phone": self.partner_phone or self.candidate_id.partner_phone, "job_id": self.job_id.id, "company_id": self.company_id.id or self.candidate_id.company_id.id or self.env.company.id, "source": source, "state": "draft", "doj": self.doj, "gender": self.gender, "birthday": self.birthday, "blood_group": self.blood_group, "marital": self.marital, "marriage_anniversary_date": self.marriage_anniversary_date, "private_street": self.private_street, "private_street2": self.private_street2, "private_city": self.private_city, "private_state_id": self.private_state_id.id, "private_zip": self.private_zip, "private_country_id": self.private_country_id.id, "permanent_street": self.permanent_street, "permanent_street2": self.permanent_street2, "permanent_city": self.permanent_city, "permanent_state_id": self.permanent_state_id.id, "permanent_zip": self.permanent_zip, "permanent_country_id": self.permanent_country_id.id, "pan_no": self.pan_no, "identification_id": self.identification_id, "previous_company_pf_no": self.previous_company_pf_no, "previous_company_uan_no": self.previous_company_uan_no, "passport_no": self.passport_no, "passport_start_date": self.passport_start_date, "passport_end_date": self.passport_end_date, "passport_issued_location": self.passport_issued_location, } def _get_bridge_employee_required(self): self.ensure_one() bridge = self._get_bridge() if not bridge or not bridge.employee_id: raise ValidationError(_("Create or select the bridge employee before validating this section.")) return bridge.employee_id def create_employee_from_applicant(self): self.ensure_one() self.candidate_id._check_interviewer_access() bridge = self._get_bridge(create=True, source="recruitment") return { "name": _("Onboarding"), "type": "ir.actions.act_window", "res_model": "recruitment.employee.bridge", "view_mode": "form", "res_id": bridge.id, } def action_open_bridge_employee(self): self.ensure_one() employee = self._get_bridge_employee_required() return { "name": _("Employee"), "type": "ir.actions.act_window", "res_model": "hr.employee", "view_mode": "form", "res_id": employee.id, } def action_open_bridge(self): self.ensure_one() bridge = self._get_bridge() if not bridge: raise ValidationError(_("No bridge found for this applicant.")) return { "name": _("Onboarding"), "type": "ir.actions.act_window", "res_model": "recruitment.employee.bridge", "view_mode": "form", "res_id": bridge.id, } def action_validate_personal_details(self): for rec in self: employee = rec._get_bridge_employee_required() vals = { "doj": rec.doj, "gender": rec.gender, "birthday": rec.birthday, "blood_group": rec.blood_group, "marital": rec.marital, "marriage_anniversary_date": rec.marriage_anniversary_date, "image_1920": rec.candidate_image, } vals = {key: value for key, value in vals.items() if value not in ["", False, 0]} if not vals: raise ValidationError(_("No values to validate")) employee.write(vals) rec.personal_details_status = "validated" def action_validate_contact_details(self): for rec in self: employee = rec._get_bridge_employee_required() vals = { "private_street": rec.private_street, "private_street2": rec.private_street2, "private_city": rec.private_city, "private_state_id": rec.private_state_id.id, "private_zip": rec.private_zip, "private_country_id": rec.private_country_id.id, "permanent_street": rec.permanent_street, "permanent_street2": rec.permanent_street2, "permanent_city": rec.permanent_city, "permanent_state_id": rec.permanent_state_id.id, "permanent_zip": rec.permanent_zip, "permanent_country_id": rec.permanent_country_id.id, } vals = {key: value for key, value in vals.items() if value not in ["", False, 0]} if not vals: raise ValidationError(_("No values to validate")) employee.write(vals) rec.contact_details_status = "validated" def action_validate_bank_details(self): for rec in self: employee = rec._get_bridge_employee_required() if not all([rec.full_name_as_in_bank, rec.bank_name, rec.bank_branch, rec.bank_account_no, rec.bank_ifsc_code]): raise ValidationError(_("Please Provide all the Bank Related Details")) account_no = self.env["res.partner.bank"].sudo().search([("acc_number", "=", rec.bank_account_no)], limit=1) if account_no: employee.bank_account_id = account_no.id else: bank = self.env["res.bank"].sudo().search([("bic", "=", rec.bank_ifsc_code)], limit=1) if not bank: bank = self.env["res.bank"].sudo().create({ "name": rec.bank_name, "bic": rec.bank_ifsc_code, "branch": rec.bank_branch, }) partner = employee.work_contact_id or employee.user_id.partner_id partner_bank = rec.env["res.partner.bank"].sudo().create({ "acc_number": rec.bank_account_no, "bank_id": bank.id, "full_name": rec.full_name_as_in_bank, "partner_id": partner.id, }) employee.bank_account_id = partner_bank.id rec.bank_details_status = "validated" def action_validate_passport_details(self): for rec in self: employee = rec._get_bridge_employee_required() vals = { "passport_id": rec.passport_no, "passport_start_date": rec.passport_start_date, "passport_end_date": rec.passport_end_date, "passport_issued_location": rec.passport_issued_location, } vals = {key: value for key, value in vals.items() if value not in ["", False, 0]} if not vals: raise ValidationError(_("No values to validate")) employee.write(vals) rec.passport_details_status = "validated" def action_validate_authentication_details(self): for rec in self: employee = rec._get_bridge_employee_required() vals = { "pan_no": rec.pan_no, "identification_id": rec.identification_id, "previous_company_pf_no": rec.previous_company_pf_no, "previous_company_uan_no": rec.previous_company_uan_no, } vals = {key: value for key, value in vals.items() if value not in ["", False, 0]} if not vals: raise ValidationError(_("No values to validate")) employee.write(vals) rec.authentication_details_status = "validated" def action_validate_family_education_employer_details(self): for rec in self: employee = rec._get_bridge_employee_required() if not (rec.education_history or rec.employer_history or rec.family_details): raise ValidationError(_("No Data to Validate")) rec.education_history.write({"employee_id": employee.id}) rec.employer_history.write({"employee_id": employee.id}) rec.family_details.write({"employee_id": employee.id}) rec.family_education_employer_details_status = "validated" bridge = rec._get_bridge() if bridge: bridge.state = "validated" def action_validate_attachments(self): for rec in self: employee = rec._get_bridge_employee_required() if not rec.joining_attachment_ids: raise ValidationError(_("No Data to Validate")) rec.joining_attachment_ids.write({"employee_id": employee.id}) rec.attachments_validation_status = "validated" def send_jod_form_to_employee(self): for rec in self: employee = rec._get_bridge_employee_required() if not employee.employee_id: raise ValidationError(_("Employee Code for the Employee (%s) is missing") % employee.name) bridge = rec._get_bridge() if bridge: return bridge.action_send_jod_form()