This commit is contained in:
gsinghpal
2026-04-26 15:05:17 -04:00
parent 160198edb1
commit d9f58b9851
110 changed files with 6210 additions and 1182 deletions

View File

@@ -5,7 +5,7 @@
{
'name': 'Fusion Plating — Notifications',
'version': '19.0.5.0.0',
'version': '19.0.6.0.0',
'category': 'Manufacturing/Plating',
'summary': 'Auto-email notifications at workflow milestones with configurable templates, PDF attachments, and audit log.',
'author': 'Nexa Systems Inc.',
@@ -20,12 +20,10 @@
'fusion_plating_certificates',
'fusion_plating_receiving',
'fusion_plating_invoicing',
'fusion_plating_bridge_mrp',
'fusion_plating_logistics',
'fusion_plating_reports',
'sale_management',
'account',
'mrp',
'mail',
],
'data': [

View File

@@ -179,58 +179,10 @@
</field>
</record>
<!-- ============================================================= -->
<!-- 4. Manufacturing Complete (Info, #2B6CB0) -->
<!-- ============================================================= -->
<record id="fp_mail_template_mo_complete" model="mail.template">
<field name="name">FP: Manufacturing Complete</field>
<field name="model_id" ref="mrp.model_mrp_production"/>
<field name="subject">Job Complete — {{ object.x_fc_portal_job_id.name or object.name }}</field>
<field name="email_from">{{ (object.company_id.email or user.email) }}</field>
<field name="email_to">{{ object.x_fc_portal_job_id.partner_id.email }}</field>
<field name="auto_delete" eval="True"/>
<field name="body_html" type="html">
<div style="font-family: -apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Arial,sans-serif; max-width: 600px; margin: 0 auto; padding: 32px 24px;">
<div style="height: 4px; background-color: #2B6CB0; margin-bottom: 28px;"></div>
<div style="font-size: 11px; text-transform: uppercase; letter-spacing: 1px; color: #2B6CB0; font-weight: 600; margin-bottom: 8px;">
EN Technologies
</div>
<h2 style="margin: 0 0 8px 0; font-size: 22px; font-weight: bold;">Manufacturing Complete — Ready to Ship</h2>
<p style="margin: 0 0 20px 0; font-size: 15px; opacity: 0.65;">
Hi <t t-out="object.x_fc_portal_job_id.partner_id.name or ''"/>, your job has cleared production and quality. We are preparing it for shipment.
</p>
<table style="width: 100%; border-collapse: collapse; margin: 20px 0;">
<tr style="border-bottom: 2px solid rgba(128,128,128,0.35);">
<th style="text-align: left; padding: 8px 4px; font-size: 12px; text-transform: uppercase; opacity: 0.55; font-weight: 600;">Detail</th>
<th style="text-align: right; padding: 8px 4px; font-size: 12px; text-transform: uppercase; opacity: 0.55; font-weight: 600;">Value</th>
</tr>
<tr style="border-bottom: 1px solid rgba(128,128,128,0.25);">
<td style="padding: 8px 4px;">Job Reference</td>
<td style="padding: 8px 4px; text-align: right; font-family: monospace;"><t t-out="object.x_fc_portal_job_id.name or object.name"/></td>
</tr>
<tr style="border-bottom: 1px solid rgba(128,128,128,0.25); background: rgba(128,128,128,0.06);">
<td style="padding: 8px 4px;">Sale Order</td>
<td style="padding: 8px 4px; text-align: right; font-family: monospace;"><t t-out="object.origin or '—'"/></td>
</tr>
<tr style="border-bottom: 1px solid rgba(128,128,128,0.25);">
<td style="padding: 8px 4px;">Quantity</td>
<td style="padding: 8px 4px; text-align: right;"><t t-out="int(object.product_qty)"/></td>
</tr>
</table>
<div style="border-left: 3px solid #2B6CB0; padding: 12px 16px; margin: 20px 0; font-size: 14px;">
<strong>Next:</strong> Your Certificate of Conformance will be issued with the shipment. Delivery scheduling to follow.
</div>
<div style="margin-top: 32px; font-size: 14px;">
Best regards,<br/>
<strong><t t-out="user.name or ''"/></strong><br/>
EN Technologies Inc.
</div>
<div style="margin-top: 40px; padding-top: 16px; border-top: 1px solid rgba(128,128,128,0.25); font-size: 11px; opacity: 0.5; text-align: center;">
This is an automated notification from EN Technologies production system.
</div>
</div>
</field>
</record>
<!-- Phase 5 (Sub 11) — fp_mail_template_mo_complete removed.
The native equivalent fires from fp.job.button_mark_done via
fp.notification.template's `job_complete` trigger, defined
in fp_notification_template_data.xml. -->
<!-- ============================================================= -->
<!-- 5. Shipped / Delivered (Success, #38a169) -->

View File

@@ -10,5 +10,7 @@ from . import sale_order
from . import fp_receiving
from . import account_move
from . import account_payment
from . import mrp_production
# Phase 5 (Sub 11) — mrp.production hook retired. The native equivalent
# fires from fp.job.button_mark_done -> _fp_fire_notification('job_complete').
# from . import mrp_production
from . import fp_delivery

View File

@@ -12,19 +12,18 @@ class FpDelivery(models.Model):
def action_mark_delivered(self):
res = super().action_mark_delivered()
Dispatch = self.env['fp.notification.template']
Job = self.env.get('fp.job')
for rec in self:
if not rec.partner_id:
continue
so = False
if rec.job_ref:
# Delivery's job_ref is the MO name; find the SO via MO origin.
mo = self.env['mrp.production'].search(
[('name', '=', rec.job_ref)], limit=1,
)
if mo and mo.origin:
so = self.env['sale.order'].search(
[('name', '=', mo.origin)], limit=1,
)
# Native: fp.job direct link.
if Job is not None and 'x_fc_job_id' in rec._fields and rec.x_fc_job_id:
so = rec.x_fc_job_id.sale_order_id or False
elif Job is not None and rec.job_ref:
job = Job.search([('name', '=', rec.job_ref)], limit=1)
if job:
so = job.sale_order_id or False
# Sub 6 — pass the delivery address so location-scoped
# contacts receive the 'shipped' notification.
Dispatch._dispatch(

View File

@@ -3,7 +3,7 @@
# License OPL-1 (Odoo Proprietary License v1.0)
# Part of the Fusion Plating product family.
from odoo import fields, models
from odoo import api, fields, models
from .fp_notification_template import TRIGGER_EVENTS
@@ -29,3 +29,20 @@ class FpNotificationLog(models.Model):
)
error_message = fields.Text(string='Error Message')
mail_mail_id = fields.Many2one('mail.mail', string='Mail Record')
@api.depends('template_id', 'partner_id', 'sent_date', 'status')
def _compute_display_name(self):
trigger_labels = dict(self._fields['trigger_event'].selection)
for rec in self:
bits = []
label = (
rec.template_id.display_name
or trigger_labels.get(rec.trigger_event)
or 'Notification'
)
bits.append(label)
if rec.partner_id:
bits.append('%s' % rec.partner_id.display_name)
if rec.sent_date:
bits.append(rec.sent_date.strftime('%Y-%m-%d %H:%M'))
rec.display_name = ' '.join(bits)