From d25a1fbdc69489477ef4a68d32518d7779ffbe0f Mon Sep 17 00:00:00 2001 From: younes Date: Mon, 8 Dec 2025 15:18:44 +0100 Subject: [PATCH] [IMP] odex_benefit: IMP benefit --- .../odex_benefit/data/scheduled_actions.xml | 56 ++++-- odex25_benefit/odex_benefit/i18n/ar_001.po | 7 +- odex25_benefit/odex_benefit/models/benefit.py | 32 +++- .../odex_benefit/models/benefit_config.py | 17 +- .../odex_benefit/models/family_members.py | 21 ++- .../views/benefit_config_view.xml | 17 +- .../odex_benefit/views/benefit_view.xml | 168 +++++++++++------- .../odex_benefit/views/family_members.xml | 3 +- .../wizards/suspend_reason_wizard.py | 72 +++++--- .../wizards/suspend_reason_wizard.xml | 4 +- 10 files changed, 278 insertions(+), 119 deletions(-) diff --git a/odex25_benefit/odex_benefit/data/scheduled_actions.xml b/odex25_benefit/odex_benefit/data/scheduled_actions.xml index a2d27c72e..f642fac94 100644 --- a/odex25_benefit/odex_benefit/data/scheduled_actions.xml +++ b/odex25_benefit/odex_benefit/data/scheduled_actions.xml @@ -4,9 +4,9 @@ Recurrence Visit Workflow Scheduler - + 1 - + days -1 @@ -14,16 +14,17 @@ model.create_scheduled_visit() code - + - + Notification: Expiry date Attachment 1 days -1 - + model.send_expiry_date_notification() @@ -34,35 +35,38 @@ 1 days -1 - + model.update_data_automatically() code - - + + Check Temporarily Exception 1 days -1 - + model.action_auto_exception() code - - + + Check Member Temporarily Exception 1 days -1 - + model.action_auto_exception() code - - + + Send Expiring Salary Attachments Notifications code @@ -72,5 +76,29 @@ -1 + + Auto Final Suspend (Benefit) + + code + model.run_auto_final_suspend() + + 1 + days + -1 + + + + Auto Final Suspend (Member) + + code + model.run_auto_final_suspend() + + 1 + days + -1 + + \ No newline at end of file diff --git a/odex25_benefit/odex_benefit/i18n/ar_001.po b/odex25_benefit/odex_benefit/i18n/ar_001.po index 34a134ad4..e2a83cd31 100644 --- a/odex25_benefit/odex_benefit/i18n/ar_001.po +++ b/odex25_benefit/odex_benefit/i18n/ar_001.po @@ -10966,7 +10966,6 @@ msgstr "رابط الاستبيان" #. module: odex_benefit #: model:ir.model.fields.selection,name:odex_benefit.selection__family_member__suspend_type__suspend #: model:ir.model.fields.selection,name:odex_benefit.selection__grant_benefit__suspend_type__suspend -#: model:ir.model.fields.selection,name:odex_benefit.selection__suspend_reason_wizard__suspend_type__suspend msgid "Suspend" msgstr "إيقاف نهائي" @@ -11012,7 +11011,7 @@ msgstr "سبب الإيقاف" #: model:ir.model,name:odex_benefit.model_suspend_reason_wizard #, python-format msgid "Suspend Reason Wizard" -msgstr "سبب إيقاف الخدمات" +msgstr "سبب إيقاف" #. module: odex_benefit #: model_terms:ir.ui.view,arch_db:odex_benefit.family_member_form @@ -11023,7 +11022,6 @@ msgstr "رفض الإيقاف" #. module: odex_benefit #: model:ir.model.fields,field_description:odex_benefit.field_family_member__suspend_type #: model:ir.model.fields,field_description:odex_benefit.field_grant_benefit__suspend_type -#: model:ir.model.fields,field_description:odex_benefit.field_suspend_reason_wizard__suspend_type #: model_terms:ir.ui.view,arch_db:odex_benefit.grant_benefit_search msgid "Suspend Type" msgstr "نوع الإيقاف" @@ -11092,12 +11090,11 @@ msgstr "استثناء مؤقت" #. module: odex_benefit #: model:ir.model.fields.selection,name:odex_benefit.selection__family_member__suspend_type__temporarily_suspend #: model:ir.model.fields.selection,name:odex_benefit.selection__grant_benefit__suspend_type__temporarily_suspend -#: model:ir.model.fields.selection,name:odex_benefit.selection__suspend_reason_wizard__suspend_type__temporarily_suspend #: model_terms:ir.ui.view,arch_db:odex_benefit.family_member_form #: model_terms:ir.ui.view,arch_db:odex_benefit.grant_benefit_form #: model_terms:ir.ui.view,arch_db:odex_benefit.grant_benefit_search msgid "Temporarily Suspended" -msgstr "إيقاف مبدئي" +msgstr "إيقاف" #. module: odex_benefit #: code:addons/odex_benefit/models/benefit.py:0 diff --git a/odex25_benefit/odex_benefit/models/benefit.py b/odex25_benefit/odex_benefit/models/benefit.py index 823b805de..4a8f20328 100644 --- a/odex25_benefit/odex_benefit/models/benefit.py +++ b/odex25_benefit/odex_benefit/models/benefit.py @@ -395,9 +395,11 @@ class GrantBenefitProfile(models.Model): ('complete_info', 'Waiting for Researcher'), ('waiting_approve', 'Waiting for Operation Manager'), ('first_approve', 'Waiting for Branch Manager'), + ('family_services_manager', 'Waiting Family Services Manager'), ('first_refusal', 'First Refusal'), ('second_approve', 'Second Approved'), ('refused', 'Refused'), + ('temporary_suspended', 'Temporary Suspended'), ('suspended_second_approve', 'Suspended Second Approved'), ('exception_second_approve', 'Waiting for General Manager'), ('black_list', 'Black List'), @@ -618,6 +620,7 @@ class GrantBenefitProfile(models.Model): total_father_families = fields.Integer(string="Father Families", compute='_compute_total_families') total_mother_families = fields.Integer(string="Mother Families", compute='_compute_total_families') total_replacement_mother_families = fields.Integer(string="Replacement Mother Families", compute='_compute_total_families') + final_suspend_date = fields.Date(string="Final Suspend Date") _sql_constraints = [ ('unique_code', "unique (code) WHERE state NOT IN ('draft', 'new')", 'This code already exists') @@ -1614,11 +1617,6 @@ class GrantBenefitProfile(models.Model): self.action_type = 'edit_info' def action_suspend(self): - self.is_excluded_suspension = False - for rec in self.member_ids: - rec.is_excluded_suspension = False - if rec.is_member_workflow: - rec.is_member_workflow = False return { 'name': _('Suspend Reason Wizard'), 'view_mode': 'form', @@ -1635,8 +1633,20 @@ class GrantBenefitProfile(models.Model): def action_suspend_second_accept(self): for rec in self: - rec.state = 'suspended_second_approve' rec.action_type = 'suspended' + if rec.suspend_reason.need_service_manager_approval: + rec.state = 'family_services_manager' + elif rec.suspend_reason.suspend_type == 'temporarily_suspend': + rec.state = 'temporary_suspended' + else: + rec.state = 'suspended_second_approve' + + def action_suspend_third_accept(self): + for rec in self: + if rec.suspend_reason.suspend_type == 'temporarily_suspend': + rec.state = 'temporary_suspended' + else: + rec.state = 'suspended_second_approve' def action_auto_suspend(self): # Fetch grants in second approval state that are not excluded from suspension @@ -1715,6 +1725,16 @@ class GrantBenefitProfile(models.Model): for member in rec.member_ids: member.is_excluded_suspension = False + def run_auto_final_suspend(self): + today = date.today() + records = self.search([ + ('state', '=', 'temporary_suspended'), + ('final_suspend_date', '<=', today), + ]) + + for rec in records: + rec.state = 'suspended_second_approve' + def action_exception_refuse(self): for rec in self: rec.state = 'suspended_second_approve' diff --git a/odex25_benefit/odex_benefit/models/benefit_config.py b/odex25_benefit/odex_benefit/models/benefit_config.py index d8d76ee97..aca6faf21 100644 --- a/odex25_benefit/odex_benefit/models/benefit_config.py +++ b/odex25_benefit/odex_benefit/models/benefit_config.py @@ -337,7 +337,7 @@ 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: @@ -347,9 +347,9 @@ class Salary(models.Model): 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.manager_id.work_email, self.benefit_id.branch_custom_id.branch.operation_manager_id.work_email ]) @@ -357,7 +357,7 @@ class Salary(models.Model): 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() @@ -714,6 +714,15 @@ class SuspendReason(models.Model): is_family_return_reason = fields.Boolean(string="Family Return Reason",default=False) is_incomplete_visit_reason = fields.Boolean(string="Incomplete Visit Reason",default=False) active = fields.Boolean(default=True) + entity_type = fields.Selection([('family', 'Family'),('member', 'Member')],string='Entity Type') + allow_service = fields.Boolean(string="Allow Service Use", default=False) + days_before_final_suspend = fields.Integer(string="Days Before Final Suspension", + default=0,help="Number of days before the suspension becomes final.") + suspend_type = fields.Selection( + selection=[('temporarily_suspend', 'Temporarily Suspended'), ('suspend', 'Suspend')], string="Suspend Type",) + need_service_manager_approval = fields.Boolean( + string="Needs Service Manager Approval" + ) class ReturnReason(models.Model): _name = "return.reason" diff --git a/odex25_benefit/odex_benefit/models/family_members.py b/odex25_benefit/odex_benefit/models/family_members.py index 573e33f78..b8396ffe1 100644 --- a/odex25_benefit/odex_benefit/models/family_members.py +++ b/odex25_benefit/odex_benefit/models/family_members.py @@ -209,9 +209,11 @@ class FamilyMemberProfile(models.Model): ('complete_info', 'Waiting for Researcher'), ('waiting_approve', 'Waiting for Operation Manager'), ('first_approve', 'Waiting for Branch Manager'), + ('family_services_manager', 'Waiting Family Services Manager'), ('first_refusal', 'First Refusal'), ('second_approve', 'Second Approved'), ('refused', 'Refused'), + ('temporary_suspended', 'Temporary Suspended'), ('suspended_second_approve', 'Suspended Second Approved'), ('exception_second_approve', 'Waiting for General Manager'), ('black_list', 'Black List'), @@ -222,9 +224,11 @@ class FamilyMemberProfile(models.Model): ('complete_info', 'Waiting for Researcher'), ('waiting_approve', 'Waiting for Operation Manager'), ('first_approve', 'Waiting for Branch Manager'), + ('family_services_manager', 'Waiting Family Services Manager'), ('first_refusal', 'First Refusal'), ('second_approve', 'Second Approved'), ('refused', 'Refused'), + ('temporary_suspended', 'Temporary Suspended'), ('suspended_second_approve', 'Suspended Second Approved'), ('exception_second_approve', 'Waiting for General Manager'), ('black_list', 'Black List'), @@ -243,7 +247,8 @@ class FamilyMemberProfile(models.Model): suspend_reason = fields.Many2one('suspend.reason', string='Suspend Reason') reason = fields.Text(string='Reason') suspend_description = fields.Text(string='Suspend Description') - suspend_attachment = fields.Binary(string='Suspend Attachment', attachment=True) + suspend_attachment = fields.Many2many('ir.attachment','rel_suspend_member_attachment', + 'member_id','attachment_id',string='Suspend Attachment') suspend_type = fields.Selection( selection=[('temporarily_suspend', 'Temporarily Suspended'), ('suspend', 'Suspend')], string="Suspend Type") suspend_method = fields.Selection(selection=[('manual', 'Manual'), ('auto', 'Auto')], string="Suspend Method", @@ -268,6 +273,7 @@ class FamilyMemberProfile(models.Model): is_mother = fields.Boolean('Is Mother?') total_member_service_requests = fields.Integer(compute='_get_total_member_service_requests') non_benefit_reason = fields.Text(string="Non Benefit Reason", tracking=True) + final_suspend_date = fields.Date(string="Final Suspend Date") # def create(self, vals): # for line_vals in vals: @@ -810,9 +816,6 @@ class FamilyMemberProfile(models.Model): # Member Suspend Manual def action_suspend(self): - for rec in self: - rec.is_member_workflow = True - rec.is_excluded_suspension = False return { 'name': _('Suspend Reason Wizard'), 'view_mode': 'form', @@ -874,6 +877,16 @@ class FamilyMemberProfile(models.Model): rec.is_excluded_suspension = False rec.state = 'suspended_second_approve' + def run_auto_final_suspend(self): + today = date.today() + records = self.search([ + ('state', '=', 'temporary_suspended'), + ('final_suspend_date', '<=', today), + ]) + + for rec in records: + rec.state = 'suspended_second_approve' + def action_exception_refuse(self): for rec in self: rec.state_a = 'suspended_second_approve' diff --git a/odex25_benefit/odex_benefit/views/benefit_config_view.xml b/odex25_benefit/odex_benefit/views/benefit_config_view.xml index b79270e4e..9d933338b 100644 --- a/odex25_benefit/odex_benefit/views/benefit_config_view.xml +++ b/odex25_benefit/odex_benefit/views/benefit_config_view.xml @@ -943,10 +943,19 @@ - - + + + + + + + @@ -966,6 +975,7 @@ + @@ -1008,7 +1018,8 @@ - + diff --git a/odex25_benefit/odex_benefit/views/benefit_view.xml b/odex25_benefit/odex_benefit/views/benefit_view.xml index ef84f1851..efad5bda6 100644 --- a/odex25_benefit/odex_benefit/views/benefit_view.xml +++ b/odex25_benefit/odex_benefit/views/benefit_view.xml @@ -66,11 +66,11 @@ - + -
+
@@ -78,17 +78,17 @@
- +
- +
- الفرع: + الفرع: @@ -98,47 +98,53 @@
- +
- +
- +
- تاريخ التسجيل: - + تاريخ التسجيل: + + +
- +
- +
- +
- - الأب: + + + الأب: +
- + @@ -156,13 +162,17 @@
- - الأم: + + + الأم: +
- + @@ -182,24 +192,36 @@
- - + +
أفراد
مستفيدة
- من + + + + من + --
- - - + + +
عدد
الزيارات
@@ -213,9 +235,13 @@
- - - + + +
طلبات
الخدمة
@@ -234,8 +260,9 @@
- - المدينة: + + المدينة: @@ -246,8 +273,9 @@
- - الحي: + + الحي: @@ -258,14 +286,16 @@
- +
- - جوال: + + جوال: - 0 + 0 + @@ -276,11 +306,13 @@
- - الدخل: + + الدخل: - + -- @@ -288,10 +320,11 @@
- +
- - الأخصائى: + + الأخصائى: @@ -306,8 +339,9 @@
- - آخر زيارة: + + آخر زيارة: + @@ -374,7 +408,15 @@ confirm="Are you sure you want to move to black list ?"/> @@ -1654,6 +1701,7 @@ + diff --git a/odex25_benefit/odex_benefit/views/family_members.xml b/odex25_benefit/odex_benefit/views/family_members.xml index 48b08d235..ebd418bc1 100644 --- a/odex25_benefit/odex_benefit/views/family_members.xml +++ b/odex25_benefit/odex_benefit/views/family_members.xml @@ -233,9 +233,10 @@ + - + diff --git a/odex25_benefit/odex_benefit/wizards/suspend_reason_wizard.py b/odex25_benefit/odex_benefit/wizards/suspend_reason_wizard.py index 4d279abfe..e16dc7b2c 100644 --- a/odex25_benefit/odex_benefit/wizards/suspend_reason_wizard.py +++ b/odex25_benefit/odex_benefit/wizards/suspend_reason_wizard.py @@ -1,8 +1,8 @@ # -*- coding: utf-8 -*- -from odoo import models, fields, _ +from odoo import models, fields, _, api from odoo.exceptions import UserError - +from datetime import datetime, timedelta class SuspendReasonWizard(models.TransientModel): _name = 'suspend.reason.wizard' @@ -22,12 +22,28 @@ class SuspendReasonWizard(models.TransientModel): entity_id = fields.Many2one("grant.benefit", string="Entity", default=_default_entity) member_id = fields.Many2one("family.member", string="Member", default=_default_member) - suspend_reason = fields.Many2one('suspend.reason',string='Suspend Reason', required=True) + suspend_reason = fields.Many2one('suspend.reason', string='Suspend Reason', + domain=lambda self: self._get_suspend_reason_domain(), required=True) suspend_description = fields.Text(string='Suspend Description', required=True) suspend_attachment = fields.Binary(string='Suspend Attachment', attachment=True, required=True) - suspend_type = fields.Selection(selection=[('temporarily_suspend', 'Temporarily Suspended'), ('suspend', 'Suspend')], string="Suspend Type", required=True) + final_suspend_date = fields.Date(string="Final Suspend Date",default=fields.Date.context_today) + + @api.onchange('suspend_reason') + def _onchange_compute_final_suspend_date(self): + if self.suspend_reason and self.suspend_reason.suspend_type == 'temporarily_suspend': + days = self.suspend_reason.days_before_final_suspend or 0 + self.final_suspend_date = datetime.today().date() + timedelta(days=days) + else: + self.final_suspend_date = fields.Date.context_today(self) + + def _get_suspend_reason_domain(self): + domain = [('is_stop_reason', '=', True)] + if self._context.get('active_model') == 'family.member': + domain.append(('entity_type', '=', 'member')) + elif self._context.get('active_model') == 'grant.benefit': + domain.append(('entity_type', '=', 'family')) + return domain - def _create_attachment_record_from_binary(self): self.ensure_one() @@ -46,23 +62,39 @@ class SuspendReasonWizard(models.TransientModel): } return self.env['ir.attachment'].create(attachment_vals) - + def action_submit(self): for rec in self: - rec.entity_id.state = 'waiting_approve' - rec.entity_id.action_type = 'suspended' - rec.entity_id.suspend_reason = rec.suspend_reason - rec.entity_id.suspend_description = rec.suspend_description - rec.entity_id.suspend_type = rec.suspend_type - rec.entity_id.suspend_attachment = self._create_attachment_record_from_binary() - rec.entity_id.suspend_method = 'manual' + rec.entity_id.member_ids.write({ + 'is_excluded_suspension': False, + 'is_member_workflow': False, + 'final_suspend_date': rec.final_suspend_date, + }) + attachment = rec._create_attachment_record_from_binary() + rec.entity_id.suspend_attachment = [(4, attachment.id)] + rec.entity_id.write({ + 'state': 'waiting_approve', + 'action_type': 'suspended', + 'suspend_reason': rec.suspend_reason.id, + 'suspend_description': rec.suspend_description, + 'suspend_type': rec.suspend_reason.suspend_type, + 'suspend_method': 'manual', + 'final_suspend_date': rec.final_suspend_date, + 'is_excluded_suspension': False, + }) def action_member_submit(self): for rec in self: - rec.member_id.state_a = 'waiting_approve' - rec.member_id.action_type = 'suspended' - rec.member_id.suspend_reason = rec.suspend_reason - rec.member_id.suspend_description = rec.suspend_description - rec.member_id.suspend_type = rec.suspend_type - rec.member_id.suspend_attachment = self._create_attachment_record_from_binary() - rec.member_id.suspend_method = 'manual' + rec.member_id.write({ + 'state_a': 'waiting_approve', + 'action_type': 'suspended', + 'suspend_reason': rec.suspend_reason.id, + 'suspend_description': rec.suspend_description, + 'suspend_type': rec.suspend_reason.suspend_type, + 'suspend_method': 'manual', + 'final_suspend_date': rec.final_suspend_date, + 'is_member_workflow': True, + 'is_excluded_suspension': False, + }) + attachment = rec._create_attachment_record_from_binary() + rec.member_id.suspend_attachment = [(4, attachment.id)] diff --git a/odex25_benefit/odex_benefit/wizards/suspend_reason_wizard.xml b/odex25_benefit/odex_benefit/wizards/suspend_reason_wizard.xml index 716ca2814..160c956d6 100644 --- a/odex25_benefit/odex_benefit/wizards/suspend_reason_wizard.xml +++ b/odex25_benefit/odex_benefit/wizards/suspend_reason_wizard.xml @@ -13,8 +13,8 @@ - +