fix(notifications): Send dialog cancel no longer pre-sends + no duplicate PDF
Two user-reported bugs on S00056 (and visible on any SO/invoice):
Bug 1: Cancelling the Send dialog still sends the email.
action_quotation_send is a button handler that returns a
compose-dialog action synchronously. Our override was calling
_dispatch('quote_sent', ...) AFTER super(), which immediately
sends the email via template.send_mail() before the user ever
sees the dialog. Clicking Cancel at that point only dismisses
the already-sent email's compose window.
Fix: removed the _dispatch call entirely from action_quotation_send.
The Send button IS the manual-send path; Odoo's compose dialog
(pre-populated with our FP: Quotation Sent template thanks to
_find_mail_template) handles the send-or-cancel choice correctly.
If an auto-quote-sent notification is ever wanted, it should be
wired from a cron that scans SOs that just transitioned
draft -> sent, not from the button handler. Noted in a code
comment.
Bug 2: Two copies of the same PDF attached to every email.
The mail.template records now carry report_template_ids (set by
the post_init hook from the previous refactor) which Odoo uses to
auto-attach PDFs on send_mail(). But the fp.notification.template
records ALSO had attach_quotation / attach_sale_order / attach_invoice
flags set, which cause _collect_attachments() to render the same
PDF a second time and pass it in email_values.
Fix: turned those three flags off in the XML data file. Other
flags (attach_coc, attach_bol, attach_receipt, attach_thickness_report,
attach_packing_list, attach_pod) stay on — those are genuinely
different documents, not dupes.
Because the records are noupdate="1", updated the post_init_hook
to also backfill the flag changes onto existing DB rows so
production instances get cleaned up on -u, not just fresh installs.
Smoke:
attach_quotation=False attach_sale_order=False attach_invoice=False on all three records
1 report per template (no dupes)
action_quotation_send no longer contains _dispatch("quote_sent", ...)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,12 +1,17 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<odoo noupdate="1">
|
<odoo noupdate="1">
|
||||||
|
|
||||||
|
<!-- attach_quotation / attach_sale_order / attach_invoice flags are
|
||||||
|
intentionally left off below. The PDF attachment is handled by
|
||||||
|
the mail.template's own `report_template_ids` (configured in
|
||||||
|
mail_template_data.xml); enabling the flags here would add a
|
||||||
|
SECOND copy of the same PDF to every email. -->
|
||||||
|
|
||||||
<record id="fp_notif_quote_sent" model="fp.notification.template">
|
<record id="fp_notif_quote_sent" model="fp.notification.template">
|
||||||
<field name="name">Quotation Sent</field>
|
<field name="name">Quotation Sent</field>
|
||||||
<field name="trigger_event">quote_sent</field>
|
<field name="trigger_event">quote_sent</field>
|
||||||
<field name="mail_template_id" ref="fp_mail_template_quote_sent"/>
|
<field name="mail_template_id" ref="fp_mail_template_quote_sent"/>
|
||||||
<field name="active" eval="True"/>
|
<field name="active" eval="True"/>
|
||||||
<field name="attach_quotation" eval="True"/>
|
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<record id="fp_notif_so_confirmed" model="fp.notification.template">
|
<record id="fp_notif_so_confirmed" model="fp.notification.template">
|
||||||
@@ -14,7 +19,6 @@
|
|||||||
<field name="trigger_event">so_confirmed</field>
|
<field name="trigger_event">so_confirmed</field>
|
||||||
<field name="mail_template_id" ref="fp_mail_template_so_confirmed"/>
|
<field name="mail_template_id" ref="fp_mail_template_so_confirmed"/>
|
||||||
<field name="active" eval="True"/>
|
<field name="active" eval="True"/>
|
||||||
<field name="attach_sale_order" eval="True"/>
|
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<record id="fp_notif_parts_received" model="fp.notification.template">
|
<record id="fp_notif_parts_received" model="fp.notification.template">
|
||||||
@@ -45,7 +49,6 @@
|
|||||||
<field name="trigger_event">invoice_posted</field>
|
<field name="trigger_event">invoice_posted</field>
|
||||||
<field name="mail_template_id" ref="fp_mail_template_invoice_posted"/>
|
<field name="mail_template_id" ref="fp_mail_template_invoice_posted"/>
|
||||||
<field name="active" eval="True"/>
|
<field name="active" eval="True"/>
|
||||||
<field name="attach_invoice" eval="True"/>
|
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<record id="fp_notif_payment_received" model="fp.notification.template">
|
<record id="fp_notif_payment_received" model="fp.notification.template">
|
||||||
|
|||||||
@@ -9,15 +9,19 @@ _logger = logging.getLogger(__name__)
|
|||||||
|
|
||||||
|
|
||||||
def post_init_hook(env):
|
def post_init_hook(env):
|
||||||
"""Force-populate report_template_ids on the mail templates.
|
"""Wire reports onto mail templates + clean up double-attach flags.
|
||||||
|
|
||||||
The mail-template XML records are tagged noupdate="1" so
|
Both the mail-template and fp.notification.template XML records
|
||||||
customer-edited templates aren't overwritten on module update.
|
are tagged noupdate="1" so user customizations aren't overwritten
|
||||||
That means report_template_ids added to the XML AFTER the
|
on module update. This hook runs once to:
|
||||||
templates were first installed won't propagate via the usual
|
|
||||||
-u reload. This hook wires the reports onto the branded
|
1. Point report_template_ids at the current branded reports.
|
||||||
templates on install/upgrade and is safe to re-run.
|
2. Turn off attach_quotation / attach_sale_order / attach_invoice
|
||||||
|
flags on fp.notification.template — those would duplicate the
|
||||||
|
PDF that's now auto-attached via the mail template's
|
||||||
|
report_template_ids.
|
||||||
"""
|
"""
|
||||||
|
# 1. Attach correct reports to mail templates
|
||||||
_apply_report_template(
|
_apply_report_template(
|
||||||
env,
|
env,
|
||||||
'fusion_plating_notifications.fp_mail_template_quote_sent',
|
'fusion_plating_notifications.fp_mail_template_quote_sent',
|
||||||
@@ -34,6 +38,28 @@ def post_init_hook(env):
|
|||||||
'fusion_plating_reports.action_report_fp_invoice_portrait',
|
'fusion_plating_reports.action_report_fp_invoice_portrait',
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# 2. Clear duplicate-attach flags on the auto-dispatch records.
|
||||||
|
# The PDF is already auto-attached by the mail.template's
|
||||||
|
# report_template_ids; leaving these flags on produces 2 PDFs.
|
||||||
|
for xmlid, flags in [
|
||||||
|
('fusion_plating_notifications.fp_notif_quote_sent',
|
||||||
|
{'attach_quotation': False}),
|
||||||
|
('fusion_plating_notifications.fp_notif_so_confirmed',
|
||||||
|
{'attach_sale_order': False}),
|
||||||
|
('fusion_plating_notifications.fp_notif_invoice_posted',
|
||||||
|
{'attach_invoice': False}),
|
||||||
|
]:
|
||||||
|
rec = env.ref(xmlid, raise_if_not_found=False)
|
||||||
|
if not rec:
|
||||||
|
continue
|
||||||
|
needs_write = any(rec[k] != v for k, v in flags.items())
|
||||||
|
if needs_write:
|
||||||
|
rec.write(flags)
|
||||||
|
_logger.info(
|
||||||
|
'fusion_plating_notifications: cleared duplicate-attach '
|
||||||
|
'flags on %s (%s)', xmlid, flags,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def _apply_report_template(env, mail_template_xmlid, report_xmlid):
|
def _apply_report_template(env, mail_template_xmlid, report_xmlid):
|
||||||
"""Replace the template's report_template_ids with exactly [report].
|
"""Replace the template's report_template_ids with exactly [report].
|
||||||
|
|||||||
@@ -43,15 +43,18 @@ class SaleOrder(models.Model):
|
|||||||
)
|
)
|
||||||
return fp_tpl or super()._find_mail_template()
|
return fp_tpl or super()._find_mail_template()
|
||||||
|
|
||||||
def action_quotation_send(self):
|
# NOTE: we intentionally do NOT override action_quotation_send to
|
||||||
"""Fire the quote_sent trigger when a quotation is emailed."""
|
# fire the quote_sent trigger. action_quotation_send returns a
|
||||||
res = super().action_quotation_send()
|
# compose-dialog action synchronously — if we dispatch here the
|
||||||
Dispatch = self.env['fp.notification.template']
|
# email is already sent by the time the user sees the dialog and
|
||||||
for order in self:
|
# decides to Cancel.
|
||||||
Dispatch._dispatch(
|
#
|
||||||
'quote_sent', order, order.partner_id, sale_order=order,
|
# The Send button itself IS the manual-send path; Odoo's compose
|
||||||
)
|
# dialog (populated with our FP: Quotation Sent template via the
|
||||||
return res
|
# _find_mail_template override) handles the send-or-cancel choice
|
||||||
|
# cleanly. If an auto-quote-sent notification is ever desired,
|
||||||
|
# wire it from a cron job that scans SOs that just transitioned
|
||||||
|
# from draft → sent, not from the button handler.
|
||||||
|
|
||||||
def action_confirm(self):
|
def action_confirm(self):
|
||||||
res = super().action_confirm()
|
res = super().action_confirm()
|
||||||
|
|||||||
Reference in New Issue
Block a user