BuiltEmail workspace

Invoice payment receipt contract

Implementation: App\Mail\Receipt, app/Mail/Receipt.php. Baseline view: resources/views/emails/invoice/Receipt.blade.php, using mail::message. Referenced calls are static usage evidence, not proof of current production delivery.

Suggested subject: Receipt_#{{invoice_number}}.pdf (existing exact pattern).

Suggested preheader: Receipt from {{business_name}} for invoice {{invoice_number}}.

Placeholder contract

TokenExisting source / derivationHandling
{{logo_url}}Original Built app_name PNGOptional deployment override; a concrete approved HTTPS logo already exists in ready HTML. Use approved absolute HTTPS or a real matching CID.
{{preheader}}Suggested existing business/reference summary aboveRequired escaped text; no new payment, settlement or delivery claim.
{{business_name}}$business->name passed/resolved by the existing MailableRequired escaped merchant identity; not the customer, sender email or owner name.
{{invoice_number}}$invoice->invoice_numberRequired escaped source reference. Used in the original header subject and PDF filename.
{{invoice_paid_total}}$invoice->fx_currency . number_format($invoice->amount_paid, 2)Required complete formatted display. This is the supplied invoice’s cumulative recorded paid amount, not constructor $amount or payment.amount. Do not use business base currency, reformat the currency prefix, recalculate payments or replace it with invoice.amount_due. Preserve supplied zero and signed amounts.
{{payment_method}}$payment->method (also exposed as $data[method])Required escaped method for the associated payment. Do not infer it from the invoice total or expose a bank/account number.
{{payment_date}}Illuminate\Support\Carbon::parse($payment->date_paid)->format("l d F, Y")Required existing formatted date, e.g. Tuesday 03 November, 2026. Retain source timezone/locale/date semantics. It is not the invoice issue date or today.
{{business_phone}}$business->phone_numberOptional; original PHP truthiness predicate. Remove the entire marked row when falsy, including string 0. Preserve supplied text, leading + and zeroes; no numeric conversion or new tel: URL.
{{business_address}}$business->addressOptional; original PHP truthiness predicate. Escape multiline text and remove the complete row when falsy.
{{business_email}}$business->emailOptional visible text under original PHP truthiness predicate. This is the merchant contact, not customer.business_email or the owner fallback. Remove the whole row when falsy; do not invent a mailto: link.
{{receipt_url}}$data[link] = config('app.url') . '/invoicereciept/' . $invoice->uuidRequired complete server-generated HTTPS URL. Preserve the legacy invoicereciept spelling and UUID; button/fallback share this one value. Validate scheme/host/path separately and escape attributes. No new signed link, expiry or payment URL.

Usage, recipients, values and attachments

From uses config(mail.from.address) with business.name. Reply-To uses business.email ?? business owner.email, with business.name as display name. Preserve null-coalescing semantics (an empty string differs from null), owner lookup and exact source headers. The body’s optional business email is not automatically replaced by the owner’s Reply-To address. No recipient/CC/BCC, queue or attachment change is authorized by this design.

Integration and safe handling

Portable {{placeholder_name}} tokens are not automatically Laravel Blade variables. Prefer the existing Mailable with a complete HTML Blade view and a separate plain-text view using explicit mapped values; do not nest this full document inside mail::message or introduce another templating framework. Keep native header, queue, business authorization, PDF and recipient behavior. Follow docs/integration/laravel.md.

Escape all dynamic text/attributes: identifiers, names, amounts, methods, dates and contacts. Validate the complete receipt URL’s HTTPS scheme, approved application host and exact existing path separately; preserve encrypted/UUID components without decoding/rebuilding in the template. Bind the same receipt_url to the button and visible fallback. There is one source link, not separate legacy duplicate action fields. Browser preview URLs are local inert explanations and must not enter production.

If using one-pass string replacement, escape text first and validate URL values separately, then replace only original tokens once. Inserted token-looking text must remain text, not be evaluated again; no dynamic value is trusted raw HTML. Optional blocks must be controlled explicitly by the integration adapter rather than leaving empty/unresolved tokens. Required missing/invalid amount/date/reference/URL needs an explicit integration decision, not an invented fallback or silently dropped content.

Ready HTML has the approved concrete https://built-storage.ams3.cdn.digitaloceanspaces.com/Built/app_name.png logo with descriptive Built alt text and proportional white-backed rendering. Retain assets/brand/built-logo.png. Deploy on accessible approved absolute HTTPS hosting or attach the original PNG and reference a real matching CID. Preview-relative assets are local fixtures only. Remote-image blocking, rounded corners and native dark styling vary by email client.

Alternatives and open decisions

public/ready/invoice-receipt.html and .txt are portable extracts; public/previews/invoice-receipt-*.html/.txt contain fictional sample data. No separate project-owned text alternative was found for the Markdown source, so the .txt is a proposed equivalent and must be registered in the consuming Mailable explicitly.

Legacy resources/views/mails/receipt.blade.php and mails/salesreciept.blade.php are separate unresolved-dispatch surfaces with different historical bindings. Do not migrate them merely because their names resemble these referenced Mailables. This batch does not include payment-link receipts, deposit receipts, waybills, SMS or externally authored CRM content.

Open integration decisions: native Blade/text registration, image hosting/CID, client approval, treatment of invalid required source values and explicit review of the documented amount-label semantics. Existing amounts, filenames and routes are preserved. No real recipients, live tokens, emails, payment actions or PDFs are generated here. Browser rendering does not prove Gmail, Outlook, iOS Mail compatibility, PDF correctness or actual payment/delivery status.