Files
linumiq-invoice/app/services/invoice/emailTemplates.ts
T
Gerhard Scheikl ff5c435bd4 feat(email): split invoice email into paid/unpaid variants
Persist paymentStatus on the Invoice at generation time and use it at send
time to pick the default email body. Paid orders (paid/refunded/voided) now
get a body without the bank-transfer reference hint; outstanding orders keep
it. Custom merchant templates still override the defaults for both cases.

- Add Invoice.paymentStatus column + migration
- Split DEFAULT_EMAIL_BODY_{DE,EN} into _PAID/_UNPAID variants
- Persist paymentStatus in generateInvoice; select default in email.server
- Document behaviour on the settings page
- Add email-templates test (paid omits hint, unpaid keeps it)
2026-08-24 16:16:17 +02:00

93 lines
4.0 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* Default invoice email templates per language and per payment state. Used
* when the user hasn't customised them in settings. Variables
* ({{invoiceNumber}}, etc.) are substituted by `renderTemplate` at send time.
*
* There are two body variants per language:
* - "unpaid": includes the bank-transfer payment-reference hint.
* - "paid": identical but with the bank-transfer hint removed (the order
* is already settled, so asking for a transfer reference would
* be confusing).
*
* The shop logo is rendered as an inline attachment with content-id
* `invoice-logo`; the email sender attaches the logo bytes automatically
* when the template (or any custom template) references that cid.
*/
const DE_HEAD = `\
<h2 style="margin:0 0 8px;font-family:Arial,Helvetica,sans-serif;"><span style="color:#0883DA">{{companyName}}</span></h2>
<h3 style="margin:0 0 16px;font-family:Arial,Helvetica,sans-serif;"><span style="color:#0883DA">Danke für deinen Einkauf!</span></h3>
<p style="font-family:Arial,Helvetica,sans-serif;font-size:14px;line-height:1.5;">
Die Rechnung befindet sich im Anhang.
</p>`;
const DE_FOOT = `\
<p style="margin-top:24px;">
<img src="cid:invoice-logo" alt="{{companyName}}" style="max-height:48px;">
</p>
<p style="font-family:Arial,Helvetica,sans-serif;font-size:13px;line-height:1.6;color:#0883DA;">
✉ <a href="mailto:{{shopEmail}}" style="color:#0883DA;">Kontakt</a><br>
🌐 <a href="{{shopWebsite}}" style="color:#0883DA;">{{shopWebsite}}</a>
</p>`;
const DE_PAYMENT_HINT = `\
<p style="font-family:Arial,Helvetica,sans-serif;font-size:14px;line-height:1.5;">
Bei Überweisung bitte die Rechnungs-Nummer als Referenz verwenden:
<strong>{{invoiceNumber}}</strong><br>
Besten Dank!
</p>`;
const DE_PAID_NOTE = `\
<p style="font-family:Arial,Helvetica,sans-serif;font-size:14px;line-height:1.5;">
Besten Dank!
</p>`;
const EN_HEAD = `\
<h2 style="margin:0 0 8px;font-family:Arial,Helvetica,sans-serif;"><span style="color:#0883DA">{{companyName}}</span></h2>
<h3 style="margin:0 0 16px;font-family:Arial,Helvetica,sans-serif;"><span style="color:#0883DA">Thank you for your purchase!</span></h3>
<p style="font-family:Arial,Helvetica,sans-serif;font-size:14px;line-height:1.5;">
Please find the invoice attached.
</p>`;
const EN_FOOT = `\
<p style="margin-top:24px;">
<img src="cid:invoice-logo" alt="{{companyName}}" style="max-height:48px;">
</p>
<p style="font-family:Arial,Helvetica,sans-serif;font-size:13px;line-height:1.6;color:#0883DA;">
✉ <a href="mailto:{{shopEmail}}" style="color:#0883DA;">Contact</a><br>
🌐 <a href="{{shopWebsite}}" style="color:#0883DA;">{{shopWebsite}}</a>
</p>`;
const EN_PAYMENT_HINT = `\
<p style="font-family:Arial,Helvetica,sans-serif;font-size:14px;line-height:1.5;">
When paying by bank transfer, please use the invoice number as the reference:
<strong>{{invoiceNumber}}</strong><br>
Thanks a lot!
</p>`;
const EN_PAID_NOTE = `\
<p style="font-family:Arial,Helvetica,sans-serif;font-size:14px;line-height:1.5;">
Thanks a lot!
</p>`;
// Unpaid (outstanding) bodies — keep the bank-transfer reference hint.
const DE_HTML_UNPAID = `${DE_HEAD}\n${DE_PAYMENT_HINT}\n${DE_FOOT}`;
const EN_HTML_UNPAID = `${EN_HEAD}\n${EN_PAYMENT_HINT}\n${EN_FOOT}`;
// Paid bodies — bank-transfer hint removed.
const DE_HTML_PAID = `${DE_HEAD}\n${DE_PAID_NOTE}\n${DE_FOOT}`;
const EN_HTML_PAID = `${EN_HEAD}\n${EN_PAID_NOTE}\n${EN_FOOT}`;
export const DEFAULT_EMAIL_SUBJECT_DE = "Rechnung {{invoiceNumber}} – {{companyName}}";
export const DEFAULT_EMAIL_SUBJECT_EN = "Invoice {{invoiceNumber}} – {{companyName}}";
// Backwards-compatible aliases (these are the "unpaid" variants, matching the
// historical single-template behaviour).
export const DEFAULT_EMAIL_BODY_DE = DE_HTML_UNPAID;
export const DEFAULT_EMAIL_BODY_EN = EN_HTML_UNPAID;
export const DEFAULT_EMAIL_BODY_DE_UNPAID = DE_HTML_UNPAID;
export const DEFAULT_EMAIL_BODY_EN_UNPAID = EN_HTML_UNPAID;
export const DEFAULT_EMAIL_BODY_DE_PAID = DE_HTML_PAID;
export const DEFAULT_EMAIL_BODY_EN_PAID = EN_HTML_PAID;