feat(tablet): mail template + notification + cleanup cron (Task 5)
Mail template renders the 4-digit code in both subject (mobile notification glance) and body (big bold display). Per Rule 25 only core res.users fields referenced; the code itself comes from ctx. fp.notification.template wrapper enables admin UI customization of the body without touching code. tablet_pin_reset_requested added to TRIGGER_EVENTS selection. Daily ir.cron purges used/expired rows > 7 days old (audit trail lives in fp.tablet.session.event, not here, so aggressive cleanup is safe). Manifest bump 19.0.34.2.0 -> 19.0.35.0.0 (triggers asset cache invalidation on -u so the new template + SCSS load cleanly). Phase 1 backend complete. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -28,6 +28,8 @@ TRIGGER_EVENTS = [
|
||||
('cert_awaiting_issuance', 'Cert Awaiting Issuance'),
|
||||
('cert_voided_re_notify', 'Cert Voided — Please Re-Issue'),
|
||||
('job_shipped', 'Job Shipped (manual mark)'),
|
||||
# Spec 2026-05-25 — tablet PIN self-service reset
|
||||
('tablet_pin_reset_requested', 'Tablet PIN Reset Code Requested'),
|
||||
]
|
||||
|
||||
# Sub 6 — map each trigger event to a communication stream. Contacts on
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
{
|
||||
'name': 'Fusion Plating — Shop Floor',
|
||||
'version': '19.0.34.2.0',
|
||||
'version': '19.0.35.0.0',
|
||||
'category': 'Manufacturing/Plating',
|
||||
'summary': 'Shop-floor tablet stations, QR scanning, bake window enforcer.',
|
||||
'description': """
|
||||
@@ -59,6 +59,7 @@ Copyright (c) 2026 Nexa Systems Inc. All rights reserved.
|
||||
],
|
||||
'demo': [
|
||||
'data/fp_demo_shopfloor_data.xml',
|
||||
'data/fp_tablet_pin_reset_template.xml',
|
||||
],
|
||||
'assets': {
|
||||
'web.assets_backend': [
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright 2026 Nexa Systems Inc.
|
||||
License OPL-1 (Odoo Proprietary License v1.0)
|
||||
|
||||
Spec: docs/superpowers/specs/2026-05-25-tablet-pin-self-service-design.md
|
||||
|
||||
Email template + notification-template wrapper + cleanup cron for
|
||||
the tablet PIN self-service reset flow.
|
||||
|
||||
Per CLAUDE.md Rule 25 the mail.template references ONLY core
|
||||
res.users fields (object.name, object.email, object.login,
|
||||
object.company_id). The 4-digit code is passed in via context
|
||||
(ctx.code) when /fp/tablet/request_reset_code calls send_mail.
|
||||
-->
|
||||
<odoo noupdate="1">
|
||||
|
||||
<!-- ===== Mail template ============================================ -->
|
||||
<record id="fp_mail_template_tablet_pin_reset" model="mail.template">
|
||||
<field name="name">FP: Tablet PIN Reset Code</field>
|
||||
<field name="model_id" ref="base.model_res_users"/>
|
||||
<field name="subject">🔒 Your ENTECH tablet temporary PIN: {{ ctx.get('code', '----') }}</field>
|
||||
<field name="email_from">{{ (object.company_id.email or user.email) }}</field>
|
||||
<field name="email_to">{{ object.email or object.login }}</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: #1d4ed8; margin-bottom: 28px;"></div>
|
||||
<div style="font-size: 11px; text-transform: uppercase; letter-spacing: 1px; color: #1d4ed8; font-weight: 600; margin-bottom: 8px;">
|
||||
Electroless Nickel Technologies Inc. (ENTECH)
|
||||
</div>
|
||||
<h2 style="margin: 0 0 8px 0; font-size: 22px; font-weight: bold;">Your tablet temporary PIN</h2>
|
||||
<p style="margin: 0 0 20px 0; font-size: 15px; opacity: 0.75;">
|
||||
Hi <t t-out="object.name"/>, use this 4-digit PIN to unlock the
|
||||
shop-floor tablet and set a new permanent PIN.
|
||||
</p>
|
||||
<div style="text-align: center; margin: 32px 0; padding: 24px; background: #f3f4f6; border-radius: 8px; font-family: ui-monospace, 'SF Mono', Menlo, Consolas, monospace; font-size: 48px; font-weight: 700; letter-spacing: 0.3em; color: #1d4ed8;">
|
||||
<t t-out="ctx.get('code', '----')"/>
|
||||
</div>
|
||||
<p style="margin: 16px 0; font-size: 13px; opacity: 0.65;">
|
||||
This code expires in 72 hours. If you didn't request it, ignore
|
||||
this email — no action needed. The previous PIN (if any) stays
|
||||
valid until you successfully complete the reset on the tablet.
|
||||
</p>
|
||||
</div>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- ===== fp.notification.template wrapper ========================= -->
|
||||
<record id="fp_notif_tablet_pin_reset" model="fp.notification.template">
|
||||
<field name="name">Tablet PIN Reset Code</field>
|
||||
<field name="trigger_event">tablet_pin_reset_requested</field>
|
||||
<field name="mail_template_id" ref="fp_mail_template_tablet_pin_reset"/>
|
||||
<field name="active" eval="True"/>
|
||||
</record>
|
||||
|
||||
<!-- ===== Cleanup cron ============================================ -->
|
||||
<record id="cron_purge_expired_pin_resets" model="ir.cron">
|
||||
<field name="name">Fusion Plating: Purge expired tablet PIN reset codes</field>
|
||||
<field name="model_id" ref="model_fp_tablet_pin_reset"/>
|
||||
<field name="state">code</field>
|
||||
<field name="code">model._cron_purge_expired()</field>
|
||||
<field name="interval_number">1</field>
|
||||
<field name="interval_type">days</field>
|
||||
<field name="active" eval="True"/>
|
||||
</record>
|
||||
|
||||
</odoo>
|
||||
Reference in New Issue
Block a user