/**
* Add Italian translations for client-facing email templates
*
* Translates authentication, ticketing, and billing email templates to Italian
* for client portal users.
*/
exports.up = async function(knex) {
console.log('Adding Italian email templates...');
// Get notification subtypes
const subtypes = await knex('notification_subtypes')
.select('id', 'name')
.whereIn('name', [
'email-verification',
'password-reset',
'portal-invitation',
'tenant-recovery',
'no-account-found',
'Ticket Assigned',
'Ticket Created',
'Ticket Updated',
'Ticket Closed',
'Ticket Comment Added',
'Invoice Generated',
'Payment Received',
'Payment Overdue'
]);
const getSubtypeId = (name) => {
const subtype = subtypes.find(s => s.name === name);
if (!subtype) {
throw new Error(`Notification subtype '${name}' not found`);
}
return subtype.id;
};
// Insert Italian templates
await knex('system_email_templates').insert([
// Authentication templates
// NOTE: email-verification template is managed in migration 20251029100000
{
name: 'password-reset',
language_code: 'it',
subject: 'Richiesta di reimpostazione della password',
notification_subtype_id: getSubtypeId('password-reset'),
html_content: `
Richiesta di reimpostazione della password
Ciao {{userName}},
Abbiamo ricevuto una richiesta di reimpostazione della password per l'account associato a {{email}}.
🔐 Verifica di sicurezza dell'account
Richiesta: Poco fa
Email dell'account: {{email}}
Valido per: {{expirationTime}}
Per creare una nuova password per il tuo account, fai clic sul pulsante qui sotto:
Oppure copia e incolla questo link nel tuo browser:
{{resetLink}}
⚠️ Informazioni di sicurezza importanti
- Questo link di reimpostazione scadrà tra {{expirationTime}}
- Per motivi di sicurezza questo link può essere utilizzato una sola volta
- Se non hai richiesto questo ripristino, ignora questa email
- La tua password non verrà modificata finché non ne imposterai una nuova
Cosa succede adesso?
- Fai clic sul pulsante di reimpostazione oppure usa il link fornito
- Crea una password sicura e unica per il tuo account
- Verrai autenticato automaticamente dopo il ripristino
- Tutte le sessioni esistenti verranno chiuse per sicurezza
- Valuta l'attivazione dell'autenticazione a due fattori per maggiore protezione
Hai bisogno di aiuto?
Se riscontri problemi nel reimpostare la password, il nostro team di supporto è a tua disposizione.
Contatta il supporto: {{supportEmail}}
`,
text_content: `Richiesta di reimpostazione della password
Ciao {{userName}},
Abbiamo ricevuto una richiesta di reimpostazione della password per l'account associato a {{email}}.
VERIFICA DI SICUREZZA DELL'ACCOUNT
- Richiesta: Poco fa
- Email dell'account: {{email}}
- Valido per: {{expirationTime}}
Per creare una nuova password, visita il seguente link:
{{resetLink}}
INFORMAZIONI IMPORTANTI:
- Questo link scadrà tra {{expirationTime}}
- Può essere utilizzato una sola volta
- Se non hai richiesto questa operazione, ignora questa email
- La tua password non verrà modificata finché non ne imposterai una nuova
Cosa succede adesso?
1. Usa il link fornito qui sopra
2. Crea una password sicura e unica
3. Verrai autenticato automaticamente
4. Tutte le sessioni esistenti verranno chiuse
5. Valuta l'autenticazione a due fattori
Hai bisogno di aiuto?
Contatta il supporto: {{supportEmail}}
---
Questa è un'email di sicurezza automatica inviata a {{email}}.
© {{currentYear}} {{clientName}}. Tutti i diritti riservati.`
},
// NOTE: portal-invitation template is managed in migration 20251029100000
{
name: 'tenant-recovery',
language_code: 'it',
subject: '{{platformName}} - I tuoi link di accesso',
notification_subtype_id: getSubtypeId('tenant-recovery'),
html_content: `
{{platformName}}
Ciao,
Hai richiesto l'accesso al tuo{{#if isMultiple}}i{{/if}} portale{{#if isMultiple}}i{{/if}} clienti.
{{#if isMultiple}}Abbiamo trovato {{tenantCount}} organizzazioni associate al tuo indirizzo email.{{else}}Ecco il tuo link di accesso:{{/if}}
Nota di sicurezza: Se non hai richiesto questi link di accesso, puoi ignorare questa email in tutta sicurezza. Il tuo account rimane protetto.
Se hai domande o hai bisogno di assistenza, contatta il team di supporto della tua organizzazione.
© {{currentYear}} {{platformName}}. Tutti i diritti riservati.
Questo è un messaggio automatico. Non rispondere a questa email.
`,
text_content: `{{platformName}} - I tuoi link di accesso
Ciao,
Hai richiesto l'accesso al tuo{{#if isMultiple}}i{{/if}} portale{{#if isMultiple}}i{{/if}} clienti.
{{#if isMultiple}}Abbiamo trovato {{tenantCount}} organizzazioni associate al tuo indirizzo email.{{else}}Ecco il tuo link di accesso:{{/if}}
I tuoi link di accesso:
{{tenantLinksText}}
Nota di sicurezza: Se non hai richiesto questi link di accesso, puoi ignorare questa email in tutta sicurezza.
Se hai domande o hai bisogno di assistenza, contatta il team di supporto della tua organizzazione.
---
© {{currentYear}} {{platformName}}. Tutti i diritti riservati.
Questo è un messaggio automatico. Non rispondere a questa email.`
},
{
name: 'no-account-found',
language_code: 'it',
subject: '{{platformName}} - Richiesta di accesso',
notification_subtype_id: getSubtypeId('no-account-found'),
html_content: `
{{platformName}}
Ciao,
Abbiamo ricevuto una richiesta di accesso al portale clienti utilizzando questo indirizzo email.
Se hai un account con noi, dovresti aver ricevuto un'email separata con i tuoi link di accesso.
Se non hai ricevuto l'email di accesso, potrebbe significare:
- Questo indirizzo email non è associato a un account del portale clienti
- Il tuo account potrebbe essere inattivo
- L'email potrebbe essere stata filtrata nella cartella spam
Hai bisogno di aiuto?
Se ritieni di dover avere accesso a un portale clienti, contatta il team di supporto del tuo provider di servizi per assistenza.
Nota di sicurezza: Se non hai richiesto l'accesso, puoi ignorare questa email in tutta sicurezza.
© {{currentYear}} {{platformName}}. Tutti i diritti riservati.
Questo è un messaggio automatico. Non rispondere a questa email.
`,
text_content: `{{platformName}} - Richiesta di accesso
Ciao,
Abbiamo ricevuto una richiesta di accesso al portale clienti utilizzando questo indirizzo email.
Se hai un account con noi, dovresti aver ricevuto un'email separata con i tuoi link di accesso.
Se non hai ricevuto l'email di accesso, potrebbe significare:
- Questo indirizzo email non è associato a un account del portale clienti
- Il tuo account potrebbe essere inattivo
- L'email potrebbe essere stata filtrata nella cartella spam
Hai bisogno di aiuto?
Se ritieni di dover avere accesso a un portale clienti, contatta il team di supporto del tuo provider di servizi per assistenza.
Nota di sicurezza: Se non hai richiesto l'accesso, puoi ignorare questa email in tutta sicurezza.
---
© {{currentYear}} {{platformName}}. Tutti i diritti riservati.
Questo è un messaggio automatico. Non rispondere a questa email.`
},
// Ticketing templates
{
name: 'ticket-assigned',
language_code: 'it',
subject: 'Ticket assegnato • {{ticket.title}} ({{ticket.priority}})',
notification_subtype_id: getSubtypeId('Ticket Assigned'),
html_content: `
|
Ticket assegnato
{{ticket.title}}
{{ticket.metaLine}}
|
|
Ti è stato assegnato un ticket per {{ticket.clientName}}. Consulta i dettagli qui sotto e procedi con le attività necessarie.
| Priorità |
{{ticket.priority}}
|
| Stato |
{{ticket.status}} |
| Assegnato da |
{{ticket.assignedBy}} |
| Assegnato a |
{{ticket.assignedToName}}
{{ticket.assignedToEmail}}
|
| Richiedente |
{{ticket.requesterName}}
{{ticket.requesterContact}}
|
| Board |
{{ticket.board}} |
| Categoria |
{{ticket.categoryDetails}} |
| Sede |
{{ticket.locationSummary}} |
Descrizione
{{ticket.description}}
Apri ticket
|
| Powered by Alga PSA • Manteniamo i team allineati |
|
`,
text_content: `
Ticket assegnato a te
{{ticket.metaLine}}
Assegnato da: {{ticket.assignedBy}}
Priorità: {{ticket.priority}}
Stato: {{ticket.status}}
Assegnato a: {{ticket.assignedDetails}}
Richiedente: {{ticket.requesterDetails}}
Board: {{ticket.board}}
Categoria: {{ticket.categoryDetails}}
Sede: {{ticket.locationSummary}}
Descrizione:
{{ticket.description}}
Apri ticket: {{ticket.url}}
`
},
{
name: 'ticket-created',
language_code: 'it',
subject: 'Nuovo ticket • {{ticket.title}} ({{ticket.priority}})',
notification_subtype_id: getSubtypeId('Ticket Created'),
html_content: `
|
Nuovo ticket Creato
{{ticket.title}}
{{ticket.metaLine}}
|
|
È stato registrato un nuovo ticket per {{ticket.clientName}}. Consulta il riepilogo qui sotto e utilizza il link per intervenire.
| Priorità |
{{ticket.priority}}
|
| Stato |
{{ticket.status}} |
| Creato |
{{ticket.createdAt}} · {{ticket.createdBy}} |
| Assegnato a |
{{ticket.assignedToName}}
{{ticket.assignedToEmail}}
|
| Richiedente |
{{ticket.requesterName}}
{{ticket.requesterContact}}
|
| Board |
{{ticket.board}} |
| Categoria |
{{ticket.categoryDetails}} |
| Sede |
{{ticket.locationSummary}} |
Descrizione
{{ticket.description}}
Apri ticket
|
| Powered by Alga PSA • Manteniamo i team allineati |
|
`,
text_content: `
Nuovo ticket creato per {{ticket.clientName}}
{{ticket.metaLine}}
Creato: {{ticket.createdAt}} · {{ticket.createdBy}}
Priorità: {{ticket.priority}}
Stato: {{ticket.status}}
Assegnato a: {{ticket.assignedDetails}}
Richiedente: {{ticket.requesterDetails}}
Board: {{ticket.board}}
Categoria: {{ticket.categoryDetails}}
Sede: {{ticket.locationSummary}}
Descrizione:
{{ticket.description}}
Apri ticket: {{ticket.url}}
`
},
{
name: 'ticket-updated',
language_code: 'it',
subject: 'Ticket aggiornato • {{ticket.title}} ({{ticket.priority}})',
notification_subtype_id: getSubtypeId('Ticket Updated'),
html_content: `
|
Ticket aggiornato
{{ticket.title}}
{{ticket.metaLine}}
|
|
È stato aggiornato un ticket per {{ticket.clientName}}. Consulta le modifiche riportate qui sotto.
| Priorità |
{{ticket.priority}}
|
| Stato |
{{ticket.status}} |
| Aggiornato da |
{{ticket.updatedBy}} |
| Assegnato a |
{{ticket.assignedToName}}
{{ticket.assignedToEmail}}
|
| Richiedente |
{{ticket.requesterName}}
{{ticket.requesterContact}}
|
| Board |
{{ticket.board}} |
| Categoria |
{{ticket.categoryDetails}} |
| Sede |
{{ticket.locationSummary}} |
Modifiche effettuate
{{ticket.changes}}
Apri ticket
|
| Powered by Alga PSA • Manteniamo i team allineati |
|
`,
text_content: `
Ticket aggiornato
{{ticket.metaLine}}
Aggiornato da: {{ticket.updatedBy}}
Priorità: {{ticket.priority}}
Stato: {{ticket.status}}
Assegnato a: {{ticket.assignedDetails}}
Richiedente: {{ticket.requesterDetails}}
Board: {{ticket.board}}
Categoria: {{ticket.categoryDetails}}
Sede: {{ticket.locationSummary}}
Modifiche effettuate:
{{ticket.changes}}
Apri ticket: {{ticket.url}}
`
},
{
name: 'ticket-closed',
language_code: 'it',
subject: 'Ticket chiuso • {{ticket.title}}',
notification_subtype_id: getSubtypeId('Ticket Closed'),
html_content: `
|
Ticket chiuso
{{ticket.title}}
{{ticket.metaLine}}
|
|
È stato risolto e chiuso un ticket per {{ticket.clientName}}. Consulta i dettagli della risoluzione di seguito.
| Stato |
Chiuso
|
| Chiuso da |
{{ticket.closedBy}} |
| Assegnato a |
{{ticket.assignedToName}}
{{ticket.assignedToEmail}}
|
| Richiedente |
{{ticket.requesterName}}
{{ticket.requesterContact}}
|
| Board |
{{ticket.board}} |
| Categoria |
{{ticket.categoryDetails}} |
| Sede |
{{ticket.locationSummary}} |
Risoluzione
{{ticket.resolution}}
Apri ticket
|
| Powered by Alga PSA • Manteniamo i team allineati |
|
`,
text_content: `
Ticket chiuso
{{ticket.metaLine}}
Chiuso da: {{ticket.closedBy}}
Stato: Chiuso
Assegnato a: {{ticket.assignedDetails}}
Richiedente: {{ticket.requesterDetails}}
Board: {{ticket.board}}
Categoria: {{ticket.categoryDetails}}
Sede: {{ticket.locationSummary}}
Risoluzione:
{{ticket.resolution}}
Apri ticket: {{ticket.url}}
`
},
{
name: 'ticket-comment-added',
language_code: 'it',
subject: 'Nuovo commento • {{ticket.title}}',
notification_subtype_id: getSubtypeId('Ticket Comment Added'),
html_content: `
|
Nuovo commento aggiunto
{{ticket.title}}
{{ticket.metaLine}}
|
|
È stato aggiunto un nuovo commento a un ticket per {{ticket.clientName}}.
| Priorità |
{{ticket.priority}}
|
| Stato |
{{ticket.status}} |
| Commento di |
{{comment.author}} |
| Assegnato a |
{{ticket.assignedToName}}
{{ticket.assignedToEmail}}
|
| Richiedente |
{{ticket.requesterName}}
{{ticket.requesterContact}}
|
| Board |
{{ticket.board}} |
| Categoria |
{{ticket.categoryDetails}} |
| Sede |
{{ticket.locationSummary}} |
💬 Commento
{{comment.content}}
Apri ticket
|
| Powered by Alga PSA • Manteniamo i team allineati |
|
`,
text_content: `
Nuovo commento aggiunto
{{ticket.metaLine}}
Commento di: {{comment.author}}
Priorità: {{ticket.priority}}
Stato: {{ticket.status}}
Assegnato a: {{ticket.assignedDetails}}
Richiedente: {{ticket.requesterDetails}}
Board: {{ticket.board}}
Categoria: {{ticket.categoryDetails}}
Sede: {{ticket.locationSummary}}
Commento:
{{comment.content}}
Apri ticket: {{ticket.url}}
`
},
// Billing templates
{
name: 'invoice-generated',
language_code: 'it',
subject: 'Nuova fattura #{{invoice.number}}',
notification_subtype_id: getSubtypeId('Invoice Generated'),
html_content: `
Fattura {{invoice.number}}
È stata generata una nuova fattura da esaminare:
Numero fattura: {{invoice.number}}
Importo: {{invoice.amount}}
Data di scadenza: {{invoice.dueDate}}
Cliente: {{invoice.clientName}}
Apri la fattura
`,
text_content: `
Fattura {{invoice.number}}
È stata generata una nuova fattura da esaminare:
Numero fattura: {{invoice.number}}
Importo: {{invoice.amount}}
Data di scadenza: {{invoice.dueDate}}
Cliente: {{invoice.clientName}}
Apri la fattura: {{invoice.url}}
`
},
{
name: 'payment-received',
language_code: 'it',
subject: 'Pagamento ricevuto: Fattura #{{invoice.number}}',
notification_subtype_id: getSubtypeId('Payment Received'),
html_content: `
Pagamento ricevuto
È stato ricevuto il pagamento della fattura #{{invoice.number}}:
Numero fattura: {{invoice.number}}
Importo pagato: {{invoice.amountPaid}}
Data del pagamento: {{invoice.paymentDate}}
Metodo di pagamento: {{invoice.paymentMethod}}
Apri la fattura
`,
text_content: `
Pagamento ricevuto
È stato ricevuto il pagamento della fattura #{{invoice.number}}:
Numero fattura: {{invoice.number}}
Importo pagato: {{invoice.amountPaid}}
Data del pagamento: {{invoice.paymentDate}}
Metodo di pagamento: {{invoice.paymentMethod}}
Apri la fattura: {{invoice.url}}
`
},
{
name: 'payment-overdue',
language_code: 'it',
subject: 'Pagamento in ritardo: Fattura #{{invoice.number}}',
notification_subtype_id: getSubtypeId('Payment Overdue'),
html_content: `
Pagamento in ritardo
Il pagamento della fattura #{{invoice.number}} è in ritardo:
Numero fattura: {{invoice.number}}
Importo dovuto: {{invoice.amountDue}}
Data di scadenza: {{invoice.dueDate}}
Giorni di ritardo: {{invoice.daysOverdue}}
Apri la fattura
`,
text_content: `
Pagamento in ritardo
Il pagamento della fattura #{{invoice.number}} è in ritardo:
Numero fattura: {{invoice.number}}
Importo dovuto: {{invoice.amountDue}}
Data di scadenza: {{invoice.dueDate}}
Giorni di ritardo: {{invoice.daysOverdue}}
Apri la fattura: {{invoice.url}}
`
}
]).onConflict(['name', 'language_code']).merge({
subject: knex.raw('excluded.subject'),
html_content: knex.raw('excluded.html_content'),
text_content: knex.raw('excluded.text_content'),
notification_subtype_id: knex.raw('excluded.notification_subtype_id')
});
console.log('✓ Italian email templates added (auth + notifications)');
};
exports.down = async function(knex) {
// Remove Italian email templates
// NOTE: email-verification and portal-invitation are NOT removed as they're managed by other migrations
await knex('system_email_templates')
.where({ language_code: 'it' })
.whereIn('name', [
'password-reset',
'tenant-recovery',
'no-account-found',
'ticket-assigned',
'ticket-created',
'ticket-updated',
'ticket-closed',
'ticket-comment-added',
'invoice-generated',
'payment-received',
'payment-overdue'
])
.del();
console.log('Italian email templates removed');
};