CluPilotCloud/app/Mail/InvoiceMail.php

70 lines
2.4 KiB
PHP

<?php
namespace App\Mail;
use App\Mail\Concerns\SendsFromMailbox;
use App\Models\Invoice;
use App\Services\Billing\InvoiceRenderer;
use App\Services\Mail\MailPurpose;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Mail\Mailable;
use Illuminate\Mail\Mailables\Attachment;
use Illuminate\Mail\Mailables\Content;
use Illuminate\Mail\Mailables\Envelope;
use Illuminate\Queue\SerializesModels;
/**
* The invoice, with the invoice attached.
*
* The PDF is rendered when the mail is sent rather than fetched from anywhere,
* because nothing stores it — and rendering from the frozen snapshot means the
* attachment is the document as issued no matter when the queue gets round to
* it, or how often it is retried.
*
* From the BILLING mailbox: a reply to this is a question about money.
*/
class InvoiceMail extends Mailable implements ShouldQueue
{
use Queueable, SendsFromMailbox, SerializesModels;
public function __construct(public Invoice $invoice, public string $name) {}
public function envelope(): Envelope
{
return $this->mailboxEnvelope(
MailPurpose::BILLING,
__('invoice_mail.subject', ['number' => $this->invoice->number]),
);
}
public function content(): Content
{
$meta = (array) ($this->invoice->snapshot['meta'] ?? []);
return new Content(view: 'mail.invoice', with: [
'name' => $this->name,
'number' => $this->invoice->number,
'issuedOn' => $this->invoice->issued_on?->local()->format('d.m.Y'),
'dueOn' => $this->invoice->due_on?->local()->format('d.m.Y'),
'gross' => \App\Services\Billing\InvoiceMath::money((int) $this->invoice->gross_cents),
'currency' => $this->invoice->currency,
'paymentTerms' => (string) ($meta['payment_terms'] ?? ''),
'invoicesUrl' => route('invoices'),
]);
}
/** @return array<int, Attachment> */
public function attachments(): array
{
return [
// fromData, not fromPath: there is no path. The document exists as
// a row and becomes a file only for as long as this mail needs one.
Attachment::fromData(
fn () => app(InvoiceRenderer::class)->forInvoice($this->invoice),
$this->invoice->number.'.pdf',
)->withMime('application/pdf'),
];
}
}