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_awaiting_issuance', 'Cert Awaiting Issuance'),
|
||||||
('cert_voided_re_notify', 'Cert Voided — Please Re-Issue'),
|
('cert_voided_re_notify', 'Cert Voided — Please Re-Issue'),
|
||||||
('job_shipped', 'Job Shipped (manual mark)'),
|
('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
|
# Sub 6 — map each trigger event to a communication stream. Contacts on
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
{
|
{
|
||||||
'name': 'Fusion Plating — Shop Floor',
|
'name': 'Fusion Plating — Shop Floor',
|
||||||
'version': '19.0.34.2.0',
|
'version': '19.0.35.0.0',
|
||||||
'category': 'Manufacturing/Plating',
|
'category': 'Manufacturing/Plating',
|
||||||
'summary': 'Shop-floor tablet stations, QR scanning, bake window enforcer.',
|
'summary': 'Shop-floor tablet stations, QR scanning, bake window enforcer.',
|
||||||
'description': """
|
'description': """
|
||||||
@@ -59,6 +59,7 @@ Copyright (c) 2026 Nexa Systems Inc. All rights reserved.
|
|||||||
],
|
],
|
||||||
'demo': [
|
'demo': [
|
||||||
'data/fp_demo_shopfloor_data.xml',
|
'data/fp_demo_shopfloor_data.xml',
|
||||||
|
'data/fp_tablet_pin_reset_template.xml',
|
||||||
],
|
],
|
||||||
'assets': {
|
'assets': {
|
||||||
'web.assets_backend': [
|
'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