diff --git a/odex25_purchase/odex25_annual_purchase/__manifest__.py b/odex25_purchase/odex25_annual_purchase/__manifest__.py
index 5a629b2b3..fc5cb08e3 100644
--- a/odex25_purchase/odex25_annual_purchase/__manifest__.py
+++ b/odex25_purchase/odex25_annual_purchase/__manifest__.py
@@ -11,6 +11,7 @@
"security/ir.model.access.csv",
"data/sequence.xml",
+
"views/annual_request_views.xml",
"views/addendum_views.xml",
"views/purchase_requisition.xml",
@@ -20,6 +21,7 @@
"views/annual_rfq_views.xml",
"views/report_annual_rfq.xml",
"data/mail_template_annual_rfq.xml",
+ 'data/mail_direct.xml',
"views/select_reason_rfq_views.xml",
"wizard/annual_cancel_wizard_view.xml"
diff --git a/odex25_purchase/odex25_annual_purchase/data/mail_direct.xml b/odex25_purchase/odex25_annual_purchase/data/mail_direct.xml
new file mode 100644
index 000000000..223aea33a
--- /dev/null
+++ b/odex25_purchase/odex25_annual_purchase/data/mail_direct.xml
@@ -0,0 +1,98 @@
+
+
+
+
+ Annual Request - Direct Manager Approval
+
+ Annual Purchase Request #${object.name} - Action Required
+
+
+
Dear ${object.employee_id.parent_id.name or 'Manager'},
+
You have an Annual Purchase Request
+ ${object.name}
+ pending your approval:
+
+
+
+
+
+ ${object.employee_id.lang}
+
+
+
+ Annual Request - Purchase Manager Approval
+
+ Annual Purchase Request #${object.name} - Approval Required
+
+
+
Dear Purchase Manager,
+
You have an Annual Purchase Request
+ ${object.name}
+ pending your approval:
+
+
+
+
+ ${object.employee_id.lang}
+
+
+
+ Annual Request - Services Manager Approval
+
+ Annual Purchase Request #${object.name} - SSD Approval Required
+
+
+
Dear Services Manager,
+
You have an Annual Purchase Request
+ ${object.name}
+ pending your approval:
+
+
+
+
+
+ ${object.employee_id.lang}
+
+
+
+ Annual Request - General Manager Approval
+
+ Annual Purchase Request #${object.name} - CEO Approval Required
+
+
+
Dear General Manager,
+
You have an Annual Purchase Request
+ ${object.name}
+ pending your approval:
+
+
+
+
+
+ ${object.employee_id.lang}
+
+
+ Annual Request - Committee Members Notification
+
+ RFQs Created for Request #${object.name} - Please Review
+
+
+
Dear Committee Member,
+
RFQ requests have been created for Request No.
+ ${object.name}
+
+
Please proceed to open and review the technical/financial offers
+
+
+
+
+ ${object.employee_id.lang}
+
+
+
+
+
+
+
diff --git a/odex25_purchase/odex25_annual_purchase/i18n/ar_001.po b/odex25_purchase/odex25_annual_purchase/i18n/ar_001.po
index 45b519fea..8fe31e4c4 100644
--- a/odex25_purchase/odex25_annual_purchase/i18n/ar_001.po
+++ b/odex25_purchase/odex25_annual_purchase/i18n/ar_001.po
@@ -1338,3 +1338,116 @@ msgstr ""
#: model:mail.template,subject:odex25_annual_purchase.email_template_annual_rfq_new
msgid "Request for Quotation ${object.name or ''}"
msgstr "طلب عرض سعر ${object.name or ''}"
+
+#. module: odex25_annual_purchase
+#: model:mail.template,body_html:odex25_annual_purchase.email_template_direct_manager_x
+msgid ""
+"
\n"
+"
Dear ${object.employee_id.parent_id.name or 'Manager'},
\n"
+"
You have an Annual Purchase Request \n"
+" ${object.name}\n"
+" pending your approval:
\n"
+"
\n"
+"\n"
+"
\n"
+" "
+msgstr ""
+"\n"
+"
عزيزي ${object.employee_id.parent_id.name or 'المدير'},
\n"
+"
لديك طلب شراء سنوي \n"
+" ${object.name}\n"
+" بحاجة الى اعتماد:
\n"
+"
\n"
+"\n"
+"
\n"
+" "
+
+#. module: odex25_annual_purchase
+#: model:mail.template,body_html:odex25_annual_purchase.email_template_purchase_manager
+msgid ""
+"\n"
+"
Dear Purchase Manager,
\n"
+"
You have an Annual Purchase Request \n"
+" ${object.name}\n"
+" pending your approval:
\n"
+"
\n"
+"
\n"
+" "
+msgstr ""
+"\n"
+" "
+
+#. module: odex25_annual_purchase
+#: model:mail.template,body_html:odex25_annual_purchase.email_template_services_manager
+msgid ""
+"\n"
+"
Dear Services Manager,
\n"
+"
You have an Annual Purchase Request\n"
+" ${object.name}\n"
+" pending your approval:\n"
+"
\n"
+"
\n"
+"
\n"
+" "
+msgstr ""
+"\n"
+"
عزيزي مدير الخدمات,
\n"
+"
لديك طلب شراء سنوي\n"
+" ${object.name}\n"
+" بحاجة الى اعتماد:\n"
+"
\n"
+"
\n"
+"
\n"
+" "
+
+#. module: odex25_annual_purchase
+#: model:mail.template,body_html:odex25_annual_purchase.email_template_general_manager
+msgid ""
+"\n"
+"
Dear General Manager,
\n"
+"
You have an Annual Purchase Request\n"
+" ${object.name}\n"
+" pending your approval:\n"
+"
\n"
+"
\n"
+"
\n"
+" "
+msgstr ""
+"\n"
+"
عزيزي المدير التنفيذي,
\n"
+"
لديك طلب شراء سنوي\n"
+" ${object.name}\n"
+" بحاجة الى اعتماد:\n"
+"
\n"
+"
\n"
+"
\n"
+" "
+
+#. module: odex25_annual_purchase
+#: model:mail.template,body_html:odex25_annual_purchase.email_template_committee_members
+msgid ""
+"\n"
+"
Dear Committee Member,
\n"
+"
RFQ requests have been created for Request No.\n"
+" ${object.name}\n"
+"
\n"
+"
Please proceed to open and review the technical/financial offers
\n"
+"
\n"
+"
\n"
+" "
+msgstr ""
+"\n"
+"
عزيزي عضو اللجنة,
\n"
+"
تم إنشاء طلبات RFQ للطلب رقم\n"
+" ${object.name}\n"
+"
\n"
+"
يرجى فتح العروض ومراجعة العروض الفنية/المالية
\n"
+"
\n"
+"
\n"
+" "
diff --git a/odex25_purchase/odex25_annual_purchase/models/annual_request.py b/odex25_purchase/odex25_annual_purchase/models/annual_request.py
index 045dda1dd..71be5245a 100644
--- a/odex25_purchase/odex25_annual_purchase/models/annual_request.py
+++ b/odex25_purchase/odex25_annual_purchase/models/annual_request.py
@@ -299,6 +299,16 @@ class AnnualPurchaseRequest(models.Model):
self._check_lines()
for rec in self:
rec.write({'state': 'to_manager'})
+ manager = rec.sudo().employee_id.parent_id
+ if manager and manager.user_id and manager.user_id.email:
+ try:
+ template = self.env.ref('odex25_annual_purchase.email_template_direct_manager_x')
+ template.send_mail(rec.id, force_send=True)
+ rec.message_post(body=_("Email sent to Direct Manager: %s") % manager.user_id.name)
+ except Exception as e:
+ rec.message_post(body=_("Failed to send email: %s") % str(e))
+ else:
+ rec.message_post(body=_("No direct manager email found"))
def action_to_draft(self):
for rec in self:
@@ -308,12 +318,47 @@ class AnnualPurchaseRequest(models.Model):
for rec in self:
manager = rec.sudo().employee_id.parent_id
if manager:
- if manager.user_id.id == rec.env.uid :
- rec.write({'state': 'procurement'})
- else:
- raise UserError(_("Sorry, The Approval For The Direct Manager '%s' Only !")%(rec.employee_id.parent_id.name))
+ if manager.user_id.id == rec.env.uid:
+ rec.write({'state': 'procurement'})
+ purchase_group = self.env.ref('purchase.group_purchase_manager')
+ managers = self.env['res.users'].search([
+ ('groups_id', '=', purchase_group.id),
+ ('email', '!=', False)
+ ])
+ if managers:
+ try:
+ template = self.env.ref('odex25_annual_purchase.email_template_purchase_manager')
+ first_manager = managers[0]
+ cc_emails = ','.join(managers[1:].mapped('email')) if len(managers) > 1 else ''
+ template.with_context(
+ default_email_to=first_manager.email,
+ default_email_cc=cc_emails
+ ).send_mail(rec.id, force_send=True)
+ rec.message_post(body=_("Email sent to %s Purchase Manager(s)") % len(managers))
+ except Exception as e:
+ rec.message_post(body=_("Failed to send email: %s") % str(e))
+ else:
+ raise UserError(
+ _("Sorry, The Approval For The Direct Manager '%s' Only !") % (rec.employee_id.parent_id.name))
else:
rec.write({'state': 'procurement'})
+ purchase_group = self.env.ref('purchase.group_purchase_manager')
+ managers = self.env['res.users'].search([
+ ('groups_id', '=', purchase_group.id),
+ ('email', '!=', False)
+ ])
+ if managers:
+ try:
+ template = self.env.ref('odex25_annual_purchase.email_template_purchase_manager')
+ first_manager = managers[0]
+ cc_emails = ','.join(managers[1:].mapped('email')) if len(managers) > 1 else ''
+ template.with_context(
+ default_email_to=first_manager.email,
+ default_email_cc=cc_emails
+ ).send_mail(rec.id, force_send=True)
+ rec.message_post(body=_("Email sent to %s Purchase Manager(s)") % len(managers))
+ except Exception as e:
+ rec.message_post(body=_("Failed to send email: %s") % str(e))
def action_manager_reject(self):
self.ensure_one()
@@ -334,11 +379,27 @@ class AnnualPurchaseRequest(models.Model):
'sent_to_commitee': True,
'state': 'committee'
})
-
rec.rfq_ids.write({'state': 'committee'})
+ template = self.env.ref('odex25_annual_purchase.email_template_committee_members')
+ sent_count = 0
+
+ for member in rec.committe_members:
+ if member.email:
+ try:
+ template.with_context(
+ default_email_to=member.email
+ ).send_mail(rec.id, force_send=True)
+ sent_count += 1
+ except Exception as e:
+ rec.message_post(body=_("Failed to send to %s: %s") % (member.name, str(e)))
+
+ rec.message_post(
+ body=_("Emails sent to %s/%s committee members") % (sent_count, len(rec.committe_members)))
+
else:
raise UserError("لا يمكن الإرسال إلى اللجنة لأن عدد RFQs يساوي صفر.")
+
def action_send_to_ssd(self):
self.write({'state':'ssd'})
@@ -354,7 +415,24 @@ class AnnualPurchaseRequest(models.Model):
def action_ssd_approve(self):
if self.seo_approve:
- self.write({'state':'ceo'})
+ self.write({'state': 'ceo'})
+ gm_group = self.env.ref('hr_base.group_general_manager')
+ managers = self.env['res.users'].search([
+ ('groups_id', '=', gm_group.id),
+ ('email', '!=', False)
+ ])
+ if managers:
+ try:
+ template = self.env.ref('odex25_annual_purchase.email_template_general_manager')
+ first_manager = managers[0]
+ cc_emails = ','.join(managers[1:].mapped('email')) if len(managers) > 1 else ''
+ template.with_context(
+ default_email_to=first_manager.email,
+ default_email_cc=cc_emails
+ ).send_mail(self.id, force_send=True)
+ self.message_post(body=_("Email sent to %s General Manager(s)") % len(managers))
+ except Exception as e:
+ self.message_post(body=_("Failed to send email: %s") % str(e))
else:
self.write({'state': 'purchase'})
diff --git a/odex25_purchase/odex25_annual_purchase/models/annual_rfq.py b/odex25_purchase/odex25_annual_purchase/models/annual_rfq.py
index 6cf2e512d..b51d1ee06 100644
--- a/odex25_purchase/odex25_annual_purchase/models/annual_rfq.py
+++ b/odex25_purchase/odex25_annual_purchase/models/annual_rfq.py
@@ -6,7 +6,7 @@ class PurchaseRFQ(models.Model):
_name = 'annual.rfq'
_description = 'Request for Quotation'
_inherit = ['mail.thread', 'mail.activity.mixin']
- _copy = False # تعطيل النسخ لحجب زر الاستنساخ
+ _copy = False
name = fields.Char(string='Reference Number', default='New', copy=False, tracking=True)
@@ -412,10 +412,11 @@ class PurchaseRFQ(models.Model):
}
rline.write(vals)
+
def action_sign_rfq(self):
for rec in self:
rec._validate_lines_simple()
- if self.source_request_ref.committee_enabled and self.no_of_approve < self.source_request_ref.min_approve:
+ if rec.source_request_ref.committee_enabled and rec.no_of_approve < rec.source_request_ref.min_approve:
raise ValidationError(
_("Sorry You cannot sign this quotation ,YOU NEED MORE COMMITTE MEMBERS TO choose it"))
@@ -424,8 +425,44 @@ class PurchaseRFQ(models.Model):
rec.state = 'po'
if rec.source_request_ref.ssd_approve:
rec.source_request_ref.state = 'ssd'
+ services_group = self.env.ref('hr_base.group_services_manager')
+ managers = self.env['res.users'].search([
+ ('groups_id', '=', services_group.id),
+ ('email', '!=', False)
+ ])
+ if managers:
+ try:
+ template = self.env.ref('odex25_annual_purchase.email_template_services_manager')
+ first_manager = managers[0]
+ cc_emails = ','.join(managers[1:].mapped('email')) if len(managers) > 1 else ''
+ template.with_context(
+ default_email_to=first_manager.email,
+ default_email_cc=cc_emails
+ ).send_mail(rec.source_request_ref.id, force_send=True)
+ rec.source_request_ref.message_post(
+ body=_("Email sent to %s Services Manager(s)") % len(managers))
+ except Exception as e:
+ rec.source_request_ref.message_post(body=_("Failed to send email: %s") % str(e))
elif rec.source_request_ref.seo_approve:
rec.source_request_ref.state = 'ceo'
+ gm_group = self.env.ref('hr_base.group_general_manager')
+ managers = self.env['res.users'].search([
+ ('groups_id', '=', gm_group.id),
+ ('email', '!=', False)
+ ])
+ if managers:
+ try:
+ template = self.env.ref('odex25_annual_purchase.email_template_general_manager')
+ first_manager = managers[0]
+ cc_emails = ','.join(managers[1:].mapped('email')) if len(managers) > 1 else ''
+ template.with_context(
+ default_email_to=first_manager.email,
+ default_email_cc=cc_emails
+ ).send_mail(rec.source_request_ref.id, force_send=True)
+ rec.source_request_ref.message_post(
+ body=_("Email sent to %s General Manager(s)") % len(managers))
+ except Exception as e:
+ rec.source_request_ref.message_post(body=_("Failed to send email: %s") % str(e))
else:
rec.source_request_ref.state = 'purchase'
else:
@@ -433,9 +470,6 @@ class PurchaseRFQ(models.Model):
'Cannot continue: the source document is Approval stage.'
))
-
-
-
@api.depends('line_ids.subtotal', 'line_ids.tax_amount')
def _compute_amounts(self):
for rec in self: