odex30_standard/hr_docs_expiry/models/employee_documents.py

299 lines
12 KiB
Python

# -*- coding: utf-8 -*-
from odoo import api, fields, models, _
from datetime import datetime, date, timedelta
from odoo.exceptions import UserError
class HrEmployeeDocument(models.Model):
_name = "hr.employee.document"
_description = "HR Employee Documents"
_inherit = ['mail.thread', 'mail.activity.mixin']
@api.model
def mail_reminder(self):
now = datetime.now() + timedelta(days=1)
date_now = now.date()
match = self.search([])
for i in match:
if i.expiry_date:
exp_date = fields.Date.from_string(i.expiry_date) - timedelta(days=i.reminder_before)
if date_now >= exp_date and i.employee_ref.state not in ['draft', 'out_of_service']:
template = self.env.ref('hr_docs_expiry.email_template_document_expiry_reminder')
template.send_mail(i.id)
# template.send_mail(i.id, force_send=True, raise_exception=False)
if i.employee_ref.state not in ['draft', 'out_of_service'] and i.employee_ref.employee_dependant:
for dependant in i.employee_ref.employee_dependant:
if dependant.relation == 'child' and dependant.age >= 18:
template2 = self.env.ref('hr_docs_expiry.email_template_child_age_check')
template2.send_mail(i.id)
# template.send_mail(i.id, force_send=True, raise_exception=False)
@api.constrains('expiry_date', 'saudi_id', 'iqama_id', 'issue_date')
def check_expr_date(self):
for each in self:
if self.expiry_date:
exp_date = fields.Date.from_string(each.expiry_date)
if exp_date < date.today():
raise UserError(_('Your Document Is Expired.'))
if self.saudi_id:
if len(self.saudi_id) != 10:
raise UserError(_('Saudi ID must be 10 digits'))
if self.saudi_id[0] != '1':
raise UserError(_('The Saudi ID number should begin with 1'))
if self.iqama_id:
if len(self.iqama_id) != 10:
raise UserError(_('Identity must be 10 digits'))
if self.iqama_id[0] != '2' and self.iqama_id[0] != '4' and self.iqama_id[0] != '3':
raise UserError(_('Identity must begin with 2 or 3 or 4'))
if self.expiry_date and self.issue_date:
if self.expiry_date <= self.issue_date:
raise UserError(_('Error, date of issue must be less than expiry date'))
if date.today() >= self.expiry_date:
raise UserError(_("Error,the expiry date must be greater than the date of the day"))
saudi_id = fields.Char(string="Saudi ID")
license_id = fields.Char(string="License ID")
passport_id = fields.Char(string="Passport Number")
iqama_id = fields.Char(string="Identity No")
place_issue_id = fields.Char(string="Place of Issue")
name = fields.Char(string="Document Name", required=True, copy=False)
document_name = fields.Many2one(comodel_name="employee.checklist", string="Document")
description = fields.Text(string="Description", copy=False)
expiry_date = fields.Date(string="Expiry Date", tracking=True)
employee_ref = fields.Many2one('hr.employee',copy=False, string="Employee Name")
doc_attachment_id = fields.Many2many(
"ir.attachment",
"doc_attach_rel",
"doc_id",
"attach_id3",
string="Attachment",
help="You can attach the copy of your document",
copy=False)
file_examination = fields.Char()
document_type = fields.Selection([
("passport", "Passport"),
("license", "License"),
("Iqama", "Identity"),
("saudi", "Saudi ID"),
("medical_Examination", "medical Examination"),
("professional_certificates", "Professional Certificates"),
("other", "Other")])
issue_date = fields.Date(string="Issue Date", default=fields.datetime.now(), copy=False, tracking=True)
reminder_before = fields.Integer(default=0)
job_id = fields.Many2one("hr.job", "Job Position")
emp_iqama_job = fields.Char("Job Position")
membership_type = fields.Many2one(comodel_name="membership.types", string="Membership Type")
specialization = fields.Char(string="Specialization")
category = fields.Many2one(comodel_name="membership.categorys",string="Category")
company_id = fields.Many2one('res.company',string="Company", related="employee_ref.company_id", store=True)
# Removed - contract_id.name does not exist in Odoo 18
# employee_number = fields.Char(related="employee_ref.contract_id.name", copy=False, string='Employee Number')
def set_last_document(self):
self.ensure_one()
emp_id = self.env["hr.employee"].search([("id", "=", self.employee_ref.id)])
if emp_id:
if self.document_type == "passport":
emp_id.passport_id = self.id
elif self.document_type == "Iqama":
emp_id.iqama_number = self.id
elif self.document_type == "saudi":
emp_id.saudi_number = self.id
elif self.document_type == "license":
emp_id.license_number_id = self.id
elif self.document_type == "medical_Examination":
emp_id.copy_examination_file = self.id
@api.model_create_multi
def create(self, vals_list):
records = super(HrEmployeeDocument, self).create(vals_list)
for res in records:
res.set_last_document()
return records
def name_get(self):
result = []
for rec in self:
if rec.saudi_id:
result.append((rec.id, "" + rec.saudi_id))
if rec.passport_id:
result.append((rec.id, "" + rec.passport_id))
if rec.iqama_id:
result.append((rec.id,""+ rec.iqama_id))
if rec.license_id:
result.append((rec.id, "" + rec.license_id))
if rec.file_examination:
result.append((rec.id, "" + rec.file_examination))
if rec.document_type == "other":
result.append((rec.id, rec.name))
return result
@api.constrains( "passport_id", "saudi_id", "iqama_id", "license_id", "file_examination")
def unique_fields(self):
for item in self:
if item.document_type == "passport":
passport_num = self.search([("passport_id", "=", item.passport_id),("document_type", "=", item.document_type)])
if len(passport_num) > 1:
raise UserError(_("This Passport Number already Exiting"))
if item.document_type == "saudi":
saudi_num = self.search([("saudi_id", "=", item.saudi_id),("document_type", "=", item.document_type)])
if len(saudi_num) > 1:
raise UserError(_("This Saudi Identity already Exiting"))
if item.document_type == "Iqama":
iqama_num = self.search( [("iqama_id", "=", item.iqama_id),("document_type", "=", item.document_type)])
if len(iqama_num) > 1:
raise UserError(_("This Identity Number already Exiting"))
if item.document_type == "license":
license_num = self.search(
[("license_id", "=", item.license_id),("document_type", "=", item.document_type)])
if len(license_num) > 1:
raise UserError(_("This License Number already Exiting"))
if item.document_type == "medical_Examination":
medical_num = self.search(
[("file_examination", "=", item.file_examination),("document_type", "=", item.document_type)])
if len(medical_num) > 1:
raise UserError(_("This Medical Examination Number already Exiting"))
class HrEmployee(models.Model):
_inherit = "hr.employee"
passport_id = fields.Many2one(
"hr.employee.document",
domain=[("document_type", "=", "passport")],
tracking=True,
)
def _auto_init(self):
"""Handle migration from Char to Many2one for passport_id field"""
cr = self._cr
# Check if column exists and is varchar
cr.execute("""
SELECT data_type
FROM information_schema.columns
WHERE table_name = 'hr_employee'
AND column_name = 'passport_id'
""")
result = cr.fetchone()
if result and result[0] in ('character varying', 'varchar', 'text'):
# Find all foreign key constraints on passport_id column using pg_constraint
cr.execute("""
SELECT DISTINCT c.conname
FROM pg_constraint c
JOIN pg_class t ON c.conrelid = t.oid
JOIN pg_attribute a ON a.attrelid = c.conrelid
WHERE t.relname = 'hr_employee'
AND c.contype = 'f'
AND a.attname = 'passport_id'
AND a.attnum = ANY(c.conkey)
""")
constraints = cr.fetchall()
# Drop all found constraints
for (constraint_name,) in constraints:
try:
# Escape constraint name properly
escaped_name = constraint_name.replace('"', '""')
cr.execute('ALTER TABLE hr_employee DROP CONSTRAINT IF EXISTS "{}" CASCADE'.format(escaped_name))
except Exception:
pass
# Also try dropping by common constraint name patterns
constraint_patterns = [
'hr_employee_passport_id_fkey',
'hr_employee_passport_id_fk',
'passport_id_fkey',
]
for pattern in constraint_patterns:
try:
cr.execute('ALTER TABLE hr_employee DROP CONSTRAINT IF EXISTS {} CASCADE'.format(pattern))
except Exception:
pass
# Drop the varchar column with CASCADE to drop any remaining dependencies
try:
cr.execute("ALTER TABLE hr_employee DROP COLUMN IF EXISTS passport_id CASCADE")
except Exception:
# If CASCADE fails, try without it
try:
cr.execute("ALTER TABLE hr_employee DROP COLUMN IF EXISTS passport_id")
except Exception:
# Column might not exist or might already be dropped
pass
return super()._auto_init()
expiry_license = fields.Date(
related="license_number_id.expiry_date",
readonly=True,
string="License Expiry Date"
)
document_count = fields.Integer(compute="_document_count", string="# Documents")
# Relational fields
license_number_id = fields.Many2one(
comodel_name="hr.employee.document", domain="[('document_type','=','license')]"
)
def _document_count(self):
for each in self:
document_ids = self.env["hr.employee.document"].search([("employee_ref", "=", each.id)])
each.document_count = len(document_ids)
def document_view(self):
self.ensure_one()
domain = [("employee_ref", "=", self.id)]
return {
"name": _("Documents"),
"domain": domain,
"res_model": "hr.employee.document",
"type": "ir.actions.act_window",
"view_id": False,
"view_mode": "list,form",
"help": _(
"""<p class="oe_view_nocontent_create">
Click to Create for New Documents
</p>"""
),
"limit": 80,
"context": "{'default_employee_ref': '%s'}" % self.id,
}
class HrEmployeeAttachment(models.Model):
_inherit = "ir.attachment"
doc_attach_rel = fields.Many2many("hr.employee.document","doc_attachment_id","attach_id3","doc_id",
string="Attachment")
class membership_types(models.Model):
_name = 'membership.types'
_description = 'Membership Types'
name = fields.Char()
class membership_categorys(models.Model):
_name = 'membership.categorys'
_description = 'Membership Categories'
name = fields.Char()