/** * Mini interpolateur Mustache-like utilisé pour les sujets/corps des * emails de relance. Supporte les chemins pointés (`{{client.name}}`). * * Volontairement simple : pas d'expressions, pas de conditions, pas de * boucles. Si un chemin manque, retourne "" (silencieux — l'utilisateur * verra un blanc, pas une exception). */ export function renderTemplate(template: string, vars: Record): string { return template.replace(/\{\{\s*([\w.]+)\s*\}\}/g, (_, path: string) => { const parts = path.split('.') let val: unknown = vars for (const p of parts) { if (val == null || typeof val !== 'object') return '' val = (val as Record)[p] } return val == null ? '' : String(val) }) } /** * Helper d'affichage montant : 12400 → "124,00 €". */ export function formatAmountFr(cents: number): string { return new Intl.NumberFormat('fr-FR', { style: 'currency', currency: 'EUR', }).format(cents / 100) } /** * Helper d'affichage date : ISO/Date → "15/04/2026". */ export function formatDateFr(d: Date | string): string { const date = typeof d === 'string' ? new Date(d) : d return new Intl.DateTimeFormat('fr-FR').format(date) }