[UPD] odex_benefit: add cron for expiry salary attachment & add constrains for dates

This commit is contained in:
Samir Ladoui 2025-01-30 12:50:49 +01:00
parent bb128b65ab
commit 63b3052680
4 changed files with 119 additions and 0 deletions

View File

@ -62,5 +62,15 @@
<field name="code">model.action_auto_exception()</field>
<field name="state">code</field>
</record>
<record id="cron_send_attachment_expiry_emails" model="ir.cron">
<field name="name">Send Expiring Salary Attachments Notifications</field>
<field name="model_id" ref="model_salary_line"/>
<field name="state">code</field>
<field name="code">model.action_send_attachment_expiry_email()</field>
<field name="interval_number">1</field>
<field name="interval_type">days</field>
<field name="numbercall">-1</field>
<field name="active" eval="True"/>
</record>
</data>
</odoo>

View File

@ -549,6 +549,42 @@ class GrantBenefitProfile(models.Model):
replacement_weak_study = fields.Many2many('study.material',relation='grant_benefit_replacement_weak_study_rel',string='Weak Study')
sponsorship_id = fields.Many2one('takaful.sponsorship',string='Sponsorship')
def _validate_required_attachments(self):
"""Validate required Many2many attachments"""
for rec in self:
if not rec.father_dead_certificate:
raise ValidationError("Father Dead Certificate is required.")
if rec.state != 'draft' and not rec.national_address_attachment:
raise ValidationError("National Address Attachment is required when the state is not Draft.")
@api.constrains('father_birth_date', 'father_dead_date', 'mother_birth_date', 'replacement_mother_birth_date')
def _check_dates(self):
today = date.today()
for rec in self:
# Check that dates are not in the future
if rec.father_birth_date and rec.father_birth_date > today:
raise ValidationError("Father's Birth Date cannot be in the future.")
if rec.father_dead_date and rec.father_dead_date > today:
raise ValidationError("Father's Death Date cannot be in the future.")
if rec.mother_birth_date and rec.mother_birth_date > today:
raise ValidationError("Mother's Birth Date cannot be in the future.")
if rec.replacement_mother_birth_date and rec.replacement_mother_birth_date > today:
raise ValidationError("Replacement Mother's Birth Date cannot be in the future.")
# Check that father_dead_date is after father_birth_date
if (
rec.father_birth_date
and rec.father_dead_date
and rec.father_dead_date < rec.father_birth_date
):
raise ValidationError("Father's Death Date must be after the Birth Date.")
@api.depends('attachment_ids')
def get_required_attach(self):
for rec in self.attachment_ids:
@ -873,10 +909,16 @@ class GrantBenefitProfile(models.Model):
if 'salary_ids' in fields:
res['salary_ids'] = income_attachments_data
return res
def write(self, vals):
res = super(GrantBenefitProfile, self).write(vals)
self._validate_required_attachments()
return res
@api.model
def create(self, vals):
res = super(GrantBenefitProfile, self).create(vals)
res._validate_required_attachments()
if not res.code or res.code == _('New'):
res.code = self.env['ir.sequence'].sudo().next_by_code('benefit.sequence') or _('New')
return res

View File

@ -1,8 +1,11 @@
# -*- coding: utf-8 -*-
from odoo import models, fields, api, _
from odoo.exceptions import ValidationError
from random import randint
from datetime import date
import logging
import os
_logger = logging.getLogger(__name__)
@ -316,6 +319,50 @@ class Salary(models.Model):
def action_refuse(self):
self.state = 'refused'
def get_salary_attachment_name(self):
"""Return salary attachment name without extension."""
if self.salary_attach:
return os.path.splitext(self.salary_attach.name)[0]
return ''
def get_notification_emails(self):
"""Return a list of valid emails to notify, removing False values."""
emails = self.benefit_id.researcher_id.employee_id.mapped('work_email') or []
emails.extend([
self.benefit_id.branch_custom_id.branch.manager_id.work_email,
self.benefit_id.branch_custom_id.branch.operation_manager_id.work_email
])
# Remove False or None values
emails = list(filter(None, emails)) # Filters out None and False values
return ','.join(emails) if emails else 'admin@example.com'
def action_send_attachment_expiry_email(self):
"""Send email notifications for attachments expiring today and log the body in the chatter."""
today = date.today()
salary_lines = self.search([('attach_end_date', '=', today)])
mail_template = self.env.ref('odex_benefit.email_salary_attachment_expiry')
if not mail_template:
raise ValidationError("Salary Attachment Expiry Mail template not found!")
for salary_line in salary_lines:
# Render the email body
email_body = mail_template._render_field('body_html', [salary_line.id], compute_lang=True)[salary_line.id]
# Send the email
mail_template.send_mail(salary_line.id, force_send=True)
# Post the email body in the chatter of benefit_id
if salary_line.benefit_id:
salary_line.benefit_id.message_post(
body=email_body,
subtype_xmlid="mail.mt_note" # Log as a note in the chatter
)
class ibanBanks(models.Model):
_inherit = 'res.bank'

View File

@ -32,6 +32,26 @@
</field>
</record>
<!-- Salary Attachment Expiry -->
<record id="email_salary_attachment_expiry" model="mail.template">
<field name="name">إشعار بانتهاء صلاحية مرفق الدخل</field>
<field name="model_id" ref="model_salary_line"/>
<field name="email_from">
<![CDATA[${user.company_id.name} <${(user.company_id.email or user.partner_id.email or 'noreply@localhost')|safe}>]]>
</field>
<field name="email_to">${object.get_notification_emails()}</field>
<field name="subject"><![CDATA[إشعار بانتهاء صلاحية مرفق الدخل]]></field>
<field name="body_html">
<![CDATA[
<div style="text-align: right; direction: rtl;">
<p style="font-size: 16px;">السلام عليكم ورحمة الله،</p>
<p style="font-size: 16px;">تم انتهاء صلاحية مرفق الدخل <strong>${object.get_salary_attachment_name()}</strong> التابع للأسرة <strong>${object.benefit_id.name}</strong> (كودها: <strong>${object.benefit_id.code}</strong>).</p>
<p style="font-size: 16px;">يرجى اتخاذ اللازم.</p>
</div>
]]>
</field>
</record>
<!--Approve Message done-->
<record id="approval_benefit_email" model="mail.template">
<field name="name">رسالة تفيد بتدقيق طلب التسجيل والتفعيل </field>