Invoicing & PDFs

EU-compliant invoicing with auto-generated invoice numbers, themed HTML previews, downloadable PDFs, and complete tax-breakdown details on every payment.

Invoice Numbers

Every successful payment gets an invoice number in the format INV-YYYYMM-NNNN (e.g. INV-202605-0001). The counter resets monthly and is sequential with no gaps within a month. Numbers are assigned at the moment a payment succeeds (or on first invoice preview / download for legacy payments).

The counter is stored in system_settings under key invoice_counter_YYYYMM. A DB transaction protects against duplicate numbers when two payments succeed at the same instant.

User flow — downloading an invoice

  1. User goes to Settings → Invoices.
  2. List of all successful payments appears with invoice number, date, description, amount, status, and action buttons.
  3. Click View to open a themed HTML invoice preview in a new tab (no browser PDF viewer chrome).
  4. From the preview page, click Download PDF to get the rendered PDF, or Print to use the browser print dialog.
  5. Alternatively, click the PDF button directly from the list to download without previewing first.

Admin flow

Admins can pull any customer's invoice for support purposes:

  1. Admin → Payments.
  2. Each succeeded payment row shows the invoice number in bold + View and PDF buttons next to the Refund button.
  3. View opens the themed HTML preview; PDF downloads the file.
  4. Auth bypass: InvoiceController::authorizePayment() lets admins through unconditionally so they can fetch invoices for any workspace.

What appears on every invoice

The invoice template shows:

  • Header — your company brand mark (initial in a brand-colored square) + company name + website.
  • Document meta — invoice number, issue date, payment method, status pill (Paid / Pending / Refunded).
  • From card — seller details from Admin → Settings → Company tab (company name, address, Tax ID, VAT number).
  • Bill To card — buyer billing snapshot frozen at purchase time (company, address, Tax ID, VAT, email).
  • Line item — description (typically “{Plan name} (monthly/yearly) subscription”) + amount.
  • Totals card — subtotal, discount (if coupon applied), tax (if enabled, e.g. “VAT (19%)”), grand total in brand color.
  • Payment details footer (if bank details configured in Company tab).
  • Thank-you footer with brand name and website.

EU compliance — frozen buyer snapshot

EU invoicing law requires that historical invoices reflect the customer's billing details as of the purchase date. If the customer updates their VAT number or address two months later, the old invoice must still show the original values.

MailTrixy handles this with a snapshot:

  • At checkout, the customer's billing_company, billing_tax_id, billing_vat_number, billing_address, and billing_email are copied from their user profile onto the payments table row.
  • The invoice PDF reads from the Payment row, never from the live user profile.
  • Later profile edits never affect past invoices.
  • Seller info (your company) is NOT frozen — it's always read fresh from Admin Settings, because if YOU change your VAT number you typically want all reprints to show the new one (your company is “always current”).

Tax breakdown on invoices

When Tax / VAT is enabled (Admin → Settings → Tax tab), the invoice automatically shows the tax line with the configured label (VAT, GST, Sales Tax, etc.) and rate. See the Tax / VAT Configuration page for full details on how the math works.

The tax breakdown is snapshotted onto the Payment row at checkout time, so the invoice always reflects the rate that was in effect when the customer paid — not the current rate.

Customising the invoice look

  • HTML preview respects Theme Studio — uses your --color-brand, --color-surface, etc. live. Change your theme → invoice preview matches.
  • PDF uses static colors based on the brand defaults (DomPDF doesn't support CSS variables). To customise the PDF style, edit resources/views/invoices/template.blade.php.
  • Brand name on both invoice preview and PDF is pulled from Admin → Settings → General → Site Name.
  • Bank details textarea in Admin → Settings → Company appears as a separate panel at the bottom of every invoice PDF (free-form text, newlines preserved).

PDF storage

Generated PDFs are cached at storage/app/invoices/{invoice_number}.pdf. Subsequent downloads stream the cached file directly — no regeneration. The path is recorded on the Payment row's invoice_pdf_path column.

If you change company branding details and want fresh PDFs, you can either delete the cached files from storage (they'll regenerate on next request) or just rely on the HTML preview which always renders live.

Last updated 28/05/2026