BuiltEmail workspace

Invoice-discounting request — internal

Source: App\Mail\InvoiceDiscountRequestMail, app/Mail/InvoiceDiscountRequestMail.php; resources/views/emails/InvoiceDiscountRequest.blade.php using mail::message. Subject: Invoice discounting request from {{business_name}} for invoice {{invoice_number}} (existing exact pattern). Suggested preheader: the same source-derived request summary.

Required values and conditional values

TokenExisting source / derivationHandling
{{business_name}}business.nameRequired escaped business label and native subject component.
{{business_address}}business.address ?? 'Not available'Required row. Null fallback only; preserve supplied empty string/0.
{{business_phone}}business.phone_number ?? 'Not available'Same null-only fallback.
{{customer_name}}request.customer_name (InvoiceDiscount)Required escaped supplied customer name.
{{customer_phone}}request.customer_phone_numberRequired escaped original value; not business/owner phone.
{{customer_email}}request.customer_emailRequired escaped body text, not this email's recipient.
{{request_amount}}invoice.fx_currency . number_format(request.amount, 2)Required complete original formatted display. Not separate FundRequest.request_amount, which this repository sets to 0.
{{invoice_amount_due}}invoice.fx_currency . number_format(invoice.amount_due, 2)Required original amount_due; do not subtract amount_paid or reinterpret as outstanding balance.
{{invoice_number}}invoice.invoice_numberRequired display and subject component, distinct from ID/UUID.
{{request_note}}request.note, converted to reviewed readable textRequired row even when empty or 0. Original raw {!! !!} is not trusted HTML. Preserve paragraphs and meaningful anchor destinations during conversion, then escape the resulting text.
{{invoice_url}}invoice.linkConditional complete source URL; preserve only when original link is PHP-truthy. Do not rebuild from UUID/enc_id or a different print route.
{{attachment_url}}config('app.url') . request.attachment_urlConditional complete source download URL. Evaluate original path truthiness before prefixing. This is a link, not a MIME attachment/PDF.
{{wallet_number}}wallet.numberConditional on Wallet model existence. Preserve string/leading zeros.
{{wallet_balance}}wallet.currency . number_format(wallet.balance, 2)Same object condition; preserve zero and sign, independent of invoice currency.
{{app_name}}config('app.name')Required original Thanks sign-off.
{{preheader}}Source business/invoice summary aboveRequired escaped text, no approval/discount guarantee.

Default logo/optional {{logo_url}} and common PNG/CID/HTTPS policy: [shared-footer](../shared-footer.md). Required missing business/invoice/request/customer data needs a consuming-project decision, not invented values. All formatted money displays are supplied strings derived in Laravel, not browser arithmetic.

Optional-section predicates

Portable HTML/text mark three independent sections. Optional invoice review is retained only if original invoice.link is PHP-truthy, with View invoice and its visible fallback using the same complete URL. Optional supporting file is retained only if original request.attachment_url is PHP-truthy. Null, empty and literal string 0 remove those whole sections; a prefixed URL for original 0 must not become visible merely because config(app.url) made the concatenation truthy.

Optional wallet is retained only if the Wallet object exists, not if its balance is nonzero. Remove its caption/table and text block completely when absent; a zero-balance wallet still renders. Preview invoice_link_visible, attachment_visible and wallet_visible are adapter flags, not printed tokens or new source fields. Do not decide visibility from arbitrary preformatted placeholders.

Note is unconditional in the source. Keep blank or 0 as supplied, without treating it like a PHP-truthy optional message. For raw merchant HTML, choose reviewed text conversion that retains link labels/destinations and line breaks, or a separately approved narrowly sanitized rich section. This portable draft supports escaped text only. Plain strip_tags alone can destroy necessary URLs. Never insert untrusted raw HTML or evaluate inserted token-shaped strings again.

Caller, recipient, headers and distinct links

invoicesController::RequestDiscount at :3815–3841 validates required amount/invoice/service/customer values, stores an optional upload under public/invoices/discounts/attachments via Storage::url, assigns current business_id and calls InvoiceRepository::requestDiscount. Route POST invoice/discount: routes/api.php:808. Do not infer per-email validation, additional ownership guards or upload type restrictions that are not established by this method.

InvoiceRepository::requestDiscount (:242–301) saves InvoiceDiscount, creates a separate FundRequest and PartnerBusinessReference, resolves Business/Invoice, looks up business.owner_id's User, finds the first Wallet by business_id, and sends this email to its fixed internal recipient. The view's request is InvoiceDiscount, not the new FundRequest or the inbound HTTP request. Preserve all record creation/lookup/order and native send() behavior.

Reply-To uses the resolved business owner's user.email, not customer_email or the initiating user's request field. From is native configured sender with no override. Preserve exact subject and internal To; no CC/BCC override is added by this Mailable. Underlying mail transport/outbox remains separate.

The separate FundRequest.request_details.print_link uses route('printInvoice', invoice.enc_id); it is not the source email's invoice.link. Keep the existing invoice_url and concatenated file URL as separate purposes; neither should be replaced by that other print_link. No actual attach()/attachData() or PDF exists here. There are no independent legacy duplicate link fields beyond the newly repeated invoice button/fallback value.

Native integration and validation

Use the existing Mailable with a complete HTML Blade view and proposed plain-text alternative. Portable {{placeholder_name}} values are not automatically Blade. Use native predicates and explicit aliases; no new framework. Escape all text/attributes; validate invoice/attachment/image HTTPS hosts and paths separately, preserve existing complete values and use one pass for string replacement. CID assets must be genuinely embedded or replaced with approved absolute HTTPS assets.

Eight fictional states cover all optionals, each independently absent, all absent, null-only business fallback, zero/empty/note fields, original attachment 0 and long values. Files: public/ready/invoice-discount-request.html/.txt and previews/invoice-discount-request-*.html/.txt. No separate project-owned text source found. Browser checks do not establish financing approval, file/portal authorization, actual email-client compatibility, embedded-image delivery or current production delivery.