Five new boolean flags on res.partner applied to CHILD contacts:
x_fc_receives_certs, _qc, _quotes_so, _invoices, and _is_global_contact.
Single resolver helper res.partner._fp_resolve_notification_recipients
(stream, delivery_location=None) walks location contacts first then
company contacts, returning emails for contacts that opted into the
stream (or flagged themselves global). Falls back to partner.email
when no contact opts in so existing customers keep their exact
pre-Sub-6 routing.
fp.notification.template._dispatch now maps each trigger event to a
stream (so_confirmed→quotes_so, invoice_posted→invoices, shipped→
certs, etc.) and overrides the mail_template's email_to with the
resolved list. fp.delivery passes its delivery_address_id so the
shipped/CoC email routes through location-scoped contacts when they
exist.
Partner form gets a new "Communication Routing" tab on child contact
forms with the 5 flags (hides the per-stream checkboxes when
Global Contact is on, since it overrides them).
fusion_plating_certificates → 19.0.4.0.0 (adds the flag fields)
fusion_plating_notifications → 19.0.5.0.0 (+depends certificates)
Smoke on entech: 11/11 assertions pass including per-stream routing,
delivery-location scoping, zero-flag fallback, email-less skip,
unknown-stream + global behaviour, and case-insensitive dedup.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Three reported PDF bugs from the customer-facing email package:
1. Invoice body was empty — Odoo 19 sets display_type='product' on
regular invoice/SO lines (was empty string in 18.0). Both
report_fp_invoice.xml and report_fp_sale.xml only matched
`not line.display_type`, so every product line was skipped.
Fixed both portrait + landscape variants to also match
display_type == 'product'.
2. CoC PDF was a bare 30 KB header — _fp_generate_cert_pdf was
rendering action_report_coc, which is bound to portal_job and
has minimal content. Rewrote to use the rich fp.certificate-bound
report (action_report_coc_en / action_report_coc_fr based on
cert.partner_id.lang) and slugged the filename to
CoC-<Customer>-<CertName>.pdf so the email attachment reads
nicely instead of CERT-00123.pdf.
3. Thickness cert was an exact duplicate of the CoC — the CoC
template already embeds thickness readings. Skip thickness cert
creation entirely when the customer also wants CoC; only create
a standalone thickness cert when the customer opted out of CoC.
Also: dispatcher in fp_notification_template now prefers
portal_job.coc_attachment_id (the rich one we just generated) and
falls back to rendering action_report_coc_en against fp.certificate
by partner.lang — never the bare portal-job report.
Versions bumped: bridge_mrp 19.0.6.0.0, notifications 19.0.4.0.0,
reports 19.0.4.0.0.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Database stores datetimes naive-UTC, but the dashboards and emails were
showing UTC strings to users in EST/EDT — making 9pm Toronto look like 1am
the next day. Adds a single helper module + auto-detection on install.
Core changes (fusion_plating):
- New fp_tz.py helper: fp_user_tz, fp_format, fp_isoformat_utc, fp_time_ago
Resolves user.tz → company.x_fc_default_tz → UTC.
- res.company.x_fc_default_tz Selection (full pytz IANA list)
- res.config.settings exposes the company tz under a new "Regional
Settings" block in Settings > Fusion Plating
- post_init_hook auto-populates the tz on first install: tries admin
user → server /etc/timezone → America/Toronto fallback
- fp_process_node._to_dict now sends create_date/write_date as ISO with
explicit +00:00 marker so JS new Date() parses it as UTC and the
recipe tree editor's "time ago" math works correctly
Shop-floor controllers:
- shopfloor_controller.py: every fields.Datetime.to_string() and naive
.strftime() swapped for fp_format(env, ...) — due_at, bake times,
last_log_date, gates, server_time all now in user's tz
- _time_ago() removed; replaced with fp_time_ago helper which compares
tz-aware datetimes (the local one was naive-vs-naive and could be
off by hours)
- manager_controller.py date_planned: str(...)[:10] slice replaced
with fp_format MM/DD in user's tz
Notifications + reports:
- mail_template_data.xml: 5 .strftime() calls in body_html → babel
format_datetime / format_date with tz=(user.tz or company tz)
- report_fp_job_traveller.xml: rec.received_date (Datetime) gets
t-options="{'widget':'datetime'}" so Odoo's QWeb renders in user tz
Settings view layout:
- fusion_plating now owns the Settings page "Fusion Plating" app shell
- fusion_plating_certificates xpaths into it instead of redefining
(prevents app-name collision)
Verified on odoo-entech (LXC 111): post_init_hook detects
America/Toronto from /etc/timezone, MO date_start 2026-04-17 05:28 UTC
correctly displays as 2026-04-17 01:28 EDT.
Module versions bumped: fusion_plating 19.0.3.0.0,
fusion_plating_shopfloor 19.0.9.0.0, plus certificates / notifications /
reports → 19.0.3.0.0.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>