# -*- coding: utf-8 -*- # Fusion Claims - Professional Email Builder Mixin # Provides consistent, dark/light mode safe email templates across all modules. from odoo import models class FusionEmailBuilderMixin(models.AbstractModel): _name = 'fusion.email.builder.mixin' _description = 'Fusion Email Builder Mixin' # ------------------------------------------------------------------ # Color constants # ------------------------------------------------------------------ _EMAIL_COLORS = { 'info': '#2B6CB0', 'success': '#38a169', 'attention': '#d69e2e', 'urgent': '#c53030', } # ------------------------------------------------------------------ # Public API # ------------------------------------------------------------------ def _email_build( self, title, summary, sections=None, note=None, note_color=None, email_type='info', attachments_note=None, button_url=None, button_text='View Case Details', sender_name=None, extra_html='', ): """Build a complete professional email HTML string. Args: title: Email heading (e.g. "Application Approved") summary: One-sentence summary HTML (may contain tags) sections: list of (heading, rows) where rows is list of (label, value) e.g. [('Case Details', [('Client', 'John'), ('Case', 'S30073')])] note: Optional note/next-steps text (plain or HTML) note_color: Override left-border color for note (default uses email_type) email_type: 'info' | 'success' | 'attention' | 'urgent' attachments_note: Optional string listing attached files button_url: Optional CTA button URL button_text: CTA button label sender_name: Name for sign-off (defaults to current user) extra_html: Any additional HTML to insert before sign-off """ accent = self._EMAIL_COLORS.get(email_type, self._EMAIL_COLORS['info']) company = self._get_company_info() parts = [] # -- Wrapper open + accent bar (no forced bg/color so it adapts to dark/light) parts.append( f'
' f'
' f'
' ) # -- Company name (accent color works in both themes) parts.append( f'

{company["name"]}

' ) # -- Title (inherits text color from container) parts.append( f'

{title}

' ) # -- Summary (muted via opacity) parts.append( f'

{summary}

' ) # -- Sections (details tables) if sections: for heading, rows in sections: parts.append(self._email_section(heading, rows)) # -- Note / Next Steps if note: nc = note_color or accent parts.append(self._email_note(note, nc)) # -- Extra HTML if extra_html: parts.append(extra_html) # -- Attachment note if attachments_note: parts.append(self._email_attachment_note(attachments_note)) # -- CTA Button if button_url: parts.append(self._email_button(button_url, button_text, accent)) # -- Sign-off signer = sender_name or (self.env.user.name if self.env.user else '') parts.append( f'

' f'Best regards,
' f'{signer}
' f'{company["name"]}

' ) # -- Close content card parts.append('
') # -- Footer footer_parts = [company['name']] if company['phone']: footer_parts.append(company['phone']) if company['email']: footer_parts.append(company['email']) footer_text = ' · '.join(footer_parts) parts.append( f'
' f'

' f'{footer_text}
' f'This is an automated notification from the ADP Claims Management System.

' f'
' ) # -- Close wrapper parts.append('
') return ''.join(parts) # ------------------------------------------------------------------ # Building blocks # ------------------------------------------------------------------ def _email_section(self, heading, rows): """Build a labeled details table section. Args: heading: Section title (e.g. "Case Details") rows: list of (label, value) tuples. Value can be plain text or HTML. """ if not rows: return '' html = ( '' f'' ) for label, value in rows: if value is None or value == '' or value is False: continue html += ( f'' f'' f'' f'' ) html += '
{heading}
{label}{value}
' return html def _email_note(self, text, color='#2B6CB0'): """Build a left-border accent note block.""" return ( f'
' f'

{text}

' f'
' ) def _email_button(self, url, text='View Case Details', color='#2B6CB0'): """Build a centered CTA button.""" return ( f'

' f'{text}

' ) def _email_attachment_note(self, description): """Build a dashed-border attachment callout. Args: description: e.g. "ADP Application (PDF), XML Data File" """ return ( f'
' f'

' f'Attached: {description}

' f'
' ) def _email_status_badge(self, label, color='#2B6CB0'): """Return an inline status badge/pill HTML snippet.""" bg_map = { '#38a169': 'rgba(56,161,105,0.12)', '#2B6CB0': 'rgba(43,108,176,0.12)', '#d69e2e': 'rgba(214,158,46,0.12)', '#c53030': 'rgba(197,48,48,0.12)', } bg = bg_map.get(color, 'rgba(43,108,176,0.12)') return ( f'' f'{label}' ) # ------------------------------------------------------------------ # Helpers # ------------------------------------------------------------------ def _get_company_info(self): """Return company name, phone, email for email templates.""" company = getattr(self, 'company_id', None) or self.env.company return { 'name': company.name or 'Our Company', 'phone': company.phone or '', 'email': company.email or '', } def _email_is_enabled(self): """Check if email notifications are enabled in settings.""" ICP = self.env['ir.config_parameter'].sudo() val = ICP.get_param('fusion_claims.enable_email_notifications', 'True') return val.lower() in ('true', '1', 'yes')