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
- User goes to Settings → Invoices.
- List of all successful payments appears with invoice number, date, description, amount, status, and action buttons.
- Click View to open a themed HTML invoice preview in a new tab (no browser PDF viewer chrome).
- From the preview page, click Download PDF to get the rendered PDF, or Print to use the browser print dialog.
- 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:
- Admin → Payments.
- Each succeeded payment row shows the invoice number in bold + View and PDF buttons next to the Refund button.
- View opens the themed HTML preview; PDF downloads the file.
- 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, andbilling_emailare copied from their user profile onto thepaymentstable 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.