emailr_
Tous les articles
usecase·8 min

E-mails de factures et de reçus : quoi inclure

billingtransactionalreceipts

Les e-mails de factures et de reçus ont des fonctions juridiques, comptables et de service client. Voici comment les concevoir efficacement.

Reçu vs facture

  • Reçu : Confirme que le paiement a été reçu
  • Facture : Demande un paiement (peut être prépayée)

Les deux nécessitent des informations similaires, mais ont des finalités différentes.

Éléments essentiels

E-mail de reçu

interface ReceiptEmail {
  customer: {
    name: string;
    email: string;
    billingAddress?: Address;
  };
  transaction: {
    id: string;
    date: Date;
    paymentMethod: string;
    last4?: string;
  };
  items: Array<{
    description: string;
    quantity: number;
    unitPrice: number;
    total: number;
  }>;
  totals: {
    subtotal: number;
    tax: number;
    discount?: number;
    total: number;
    currency: string;
  };
  business: {
    name: string;
    address: string;
    taxId?: string;
  };
}


await sendEmail({
  to: customer.email,
  subject: `Receipt for your purchase - $${totals.total}`,
  template: 'receipt',
  data: receipt,
  attachments: [
    {
      filename: `receipt-${transaction.id}.pdf`,
      content: await generateReceiptPDF(receipt)
    }
  ]
});

E-mail de facture

interface InvoiceEmail {
  customer: {
    name: string;
    email: string;
    billingAddress: Address;
  };
  invoice: {
    number: string;
    issueDate: Date;
    dueDate: Date;
    status: 'draft' | 'sent' | 'paid' | 'overdue';
  };
  items: InvoiceItem[];
  totals: {
    subtotal: number;
    tax: number;
    total: number;
    currency: string;
    amountDue: number;
  };
  paymentOptions: PaymentOption[];
}

await sendEmail({
  to: customer.email,
  subject: `Invoice #${invoice.number} - $${totals.amountDue} due ${formatDate(invoice.dueDate)}`,
  template: 'invoice',
  data: invoiceData,
  attachments: [
    {
      filename: `invoice-${invoice.number}.pdf`,
      content: await generateInvoicePDF(invoiceData)
    }
  ]
});

Rappels de paiement

Échéance à venir

const reminderSequence = [
  { daysBefore: 7, template: 'invoice-reminder-7d' },
  { daysBefore: 3, template: 'invoice-reminder-3d' },
  { daysBefore: 1, template: 'invoice-reminder-1d' },
  { daysAfter: 1, template: 'invoice-overdue-1d' },
  { daysAfter: 7, template: 'invoice-overdue-7d' }
];

async function sendInvoiceReminder(invoice: Invoice, reminder: Reminder) {
  await sendEmail({
    to: invoice.customer.email,
    subject: reminder.daysBefore 
      ? `Invoice #${invoice.number} due in ${reminder.daysBefore} days`
      : `Invoice #${invoice.number} is overdue`,
    template: reminder.template,
    data: {
      invoice,
      payNowUrl: `${baseUrl}/invoices/${invoice.id}/pay`,
      amountDue: invoice.amountDue
    }
  });
}

Bonnes pratiques de formatage

Affichage des devises

function formatMoney(amount: number, currency: string, locale: string): string {
  return new Intl.NumberFormat(locale, {
    style: 'currency',
    currency: currency
  }).format(amount);
}

// $1,234.56 (en-US, USD)
// €1.234,56 (de-DE, EUR)
// ¥1,235 (ja-JP, JPY)

Tableau des lignes d’articles

<table>
  <thead>
    <tr>
      <th>Description</th>
      <th>Qty</th>
      <th>Unit Price</th>
      <th>Total</th>
    </tr>
  </thead>
  <tbody>
    &#123;&#123;#each items&#125;&#125;
    <tr>
      <td>&#123;&#123;this.description&#125;&#125;</td>
      <td>&#123;&#123;this.quantity&#125;&#125;</td>
      <td>&#123;&#123;formatMoney this.unitPrice&#125;&#125;</td>
      <td>&#123;&#123;formatMoney this.total&#125;&#125;</td>
    </tr>
    &#123;&#123;/each&#125;&#125;
  </tbody>
  <tfoot>
    <tr>
      <td colspan="3">Subtotal</td>
      <td>&#123;&#123;formatMoney totals.subtotal&#125;&#125;</td>
    </tr>
    <tr>
      <td colspan="3">Tax</td>
      <td>&#123;&#123;formatMoney totals.tax&#125;&#125;</td>
    </tr>
    <tr>
      <td colspan="3"><strong>Total</strong></td>
      <td><strong>&#123;&#123;formatMoney totals.total&#125;&#125;</strong></td>
    </tr>
  </tfoot>
</table>

Exigences légales

Éléments requis

const requiredReceiptElements = {
  business: ['name', 'address', 'taxId'],
  transaction: ['date', 'id', 'paymentMethod'],
  items: ['description', 'quantity', 'price'],
  totals: ['subtotal', 'tax', 'total']
};

// Validate before sending
function validateReceipt(receipt: ReceiptEmail): boolean {
  // Check all required fields present
  for (const [section, fields] of Object.entries(requiredReceiptElements)) {
    for (const field of fields) {
      if (!receipt[section]?.[field]) {
        throw new Error(`Missing required field: ${section}.${field}`);
      }
    }
  }
  return true;
}

Bonnes pratiques

  1. Joindre un PDF - Les clients ont besoin de justificatifs imprimables
  2. Totaux clairs - Détailler le sous-total, les taxes, les remises
  3. Informations de paiement - Indiquer comment ils ont payé ou comment payer
  4. Coordonnées de l’entreprise - Dénomination légale, adresse, numéro d’identification fiscale
  5. Identifiants uniques - Numéros de facture/de reçu pour référence
  6. Compatible mobile - Des tableaux qui fonctionnent sur petits écrans

Les e-mails de factures et de reçus sont des documents juridiques. Bien les concevoir réduira les questions comptables et renforcera la confiance.

e_

Écrit par l'équipe emailr

Nous construisons l'infrastructure email pour les développeurs

Prêt à commencer à envoyer ?

Obtenez votre clé API et envoyez votre premier email en moins de 5 minutes. Aucune carte de crédit requise.