191 lines
5.4 KiB
PHP
191 lines
5.4 KiB
PHP
<?php
|
|
|
|
namespace App\Mail;
|
|
|
|
use App\Models\PackagePurchase;
|
|
use Illuminate\Bus\Queueable;
|
|
use Illuminate\Mail\Mailable;
|
|
use Illuminate\Mail\Mailables\Content;
|
|
use Illuminate\Mail\Mailables\Envelope;
|
|
use Illuminate\Queue\SerializesModels;
|
|
|
|
class PurchaseConfirmation extends Mailable
|
|
{
|
|
use Queueable, SerializesModels;
|
|
|
|
public function __construct(public PackagePurchase $purchase)
|
|
{
|
|
//
|
|
}
|
|
|
|
public function envelope(): Envelope
|
|
{
|
|
return new Envelope(
|
|
subject: __('emails.purchase.subject', ['package' => $this->localizedPackageName()]),
|
|
);
|
|
}
|
|
|
|
public function content(): Content
|
|
{
|
|
return new Content(
|
|
view: 'emails.purchase',
|
|
with: [
|
|
'purchase' => $this->purchase,
|
|
'user' => $this->purchase->tenant->user,
|
|
'package' => $this->purchase->package,
|
|
'packageName' => $this->localizedPackageName(),
|
|
'priceFormatted' => $this->formattedTotal(),
|
|
'purchaseDate' => $this->formattedPurchaseDate(),
|
|
'providerLabel' => $this->providerLabel(),
|
|
'orderId' => $this->purchase->provider_id,
|
|
'packageTypeLabel' => $this->packageTypeLabel(),
|
|
'limits' => $this->packageLimits(),
|
|
'invoiceUrl' => $this->resolveInvoiceUrl(),
|
|
'ctaUrl' => route('tenant.admin.dashboard'),
|
|
],
|
|
);
|
|
}
|
|
|
|
public function attachments(): array
|
|
{
|
|
return [];
|
|
}
|
|
|
|
private function localizedPackageName(): string
|
|
{
|
|
$locale = $this->locale ?? app()->getLocale();
|
|
|
|
return optional($this->purchase->package)->getNameForLocale($locale) ?? '';
|
|
}
|
|
|
|
private function formattedTotal(): string
|
|
{
|
|
$totals = $this->purchase->metadata['paddle_totals'] ?? [];
|
|
$currency = $totals['currency']
|
|
?? $this->purchase->metadata['currency']
|
|
?? $this->purchase->package?->currency
|
|
?? 'EUR';
|
|
$amount = array_key_exists('total', $totals) ? (float) $totals['total'] : (float) $this->purchase->price;
|
|
|
|
$locale = $this->locale ?? app()->getLocale();
|
|
$formatter = class_exists(\NumberFormatter::class)
|
|
? new \NumberFormatter($this->mapLocale($locale), \NumberFormatter::CURRENCY)
|
|
: null;
|
|
|
|
if ($formatter) {
|
|
$formatted = $formatter->formatCurrency($amount, $currency);
|
|
if ($formatted !== false) {
|
|
return $formatted;
|
|
}
|
|
}
|
|
|
|
$symbol = match ($currency) {
|
|
'EUR' => '€',
|
|
'USD' => '$',
|
|
default => $currency,
|
|
};
|
|
|
|
return number_format($amount, 2, ',', '.').' '.$symbol;
|
|
}
|
|
|
|
private function formattedPurchaseDate(): string
|
|
{
|
|
$locale = $this->locale ?? app()->getLocale();
|
|
$date = $this->purchase->purchased_at ?? now();
|
|
|
|
if (str_starts_with($locale, 'en')) {
|
|
return $date->translatedFormat('F j, Y');
|
|
}
|
|
|
|
return $date->translatedFormat('d. F Y');
|
|
}
|
|
|
|
private function mapLocale(string $locale): string
|
|
{
|
|
$normalized = strtolower(str_replace('_', '-', $locale));
|
|
|
|
return match (true) {
|
|
str_starts_with($normalized, 'de') => 'de_DE',
|
|
str_starts_with($normalized, 'en') => 'en_US',
|
|
default => 'de_DE',
|
|
};
|
|
}
|
|
|
|
private function providerLabel(): string
|
|
{
|
|
$provider = $this->purchase->provider ?? 'paddle';
|
|
$labelKey = 'emails.purchase.provider.'.$provider;
|
|
$label = __($labelKey);
|
|
|
|
if ($label === $labelKey) {
|
|
return ucfirst((string) $provider);
|
|
}
|
|
|
|
return $label;
|
|
}
|
|
|
|
private function packageTypeLabel(): string
|
|
{
|
|
$type = $this->purchase->package?->type ?? 'endcustomer';
|
|
$labelKey = 'emails.purchase.package_type.'.$type;
|
|
$label = __($labelKey);
|
|
|
|
if ($label === $labelKey) {
|
|
return ucfirst((string) $type);
|
|
}
|
|
|
|
return $label;
|
|
}
|
|
|
|
/**
|
|
* @return array<int, array{label: string, value: string}>
|
|
*/
|
|
private function packageLimits(): array
|
|
{
|
|
$package = $this->purchase->package;
|
|
if (! $package) {
|
|
return [];
|
|
}
|
|
|
|
$limits = [
|
|
'max_photos' => $package->max_photos,
|
|
'max_guests' => $package->max_guests,
|
|
'gallery_days' => $package->gallery_days,
|
|
'max_tasks' => $package->max_tasks,
|
|
'max_events_per_year' => $package->max_events_per_year,
|
|
];
|
|
|
|
$result = [];
|
|
|
|
foreach ($limits as $key => $value) {
|
|
if (! is_numeric($value) || (int) $value <= 0) {
|
|
continue;
|
|
}
|
|
|
|
$result[] = [
|
|
'label' => __('emails.purchase.limits.'.$key),
|
|
'value' => number_format((int) $value, 0, ',', '.'),
|
|
];
|
|
}
|
|
|
|
return $result;
|
|
}
|
|
|
|
private function resolveInvoiceUrl(): ?string
|
|
{
|
|
$payload = $this->purchase->metadata['payload'] ?? [];
|
|
|
|
$invoiceUrl = $payload['invoice_url'] ?? null;
|
|
if (is_string($invoiceUrl) && $invoiceUrl !== '') {
|
|
return $invoiceUrl;
|
|
}
|
|
|
|
$receiptUrl = $payload['receipt_url'] ?? null;
|
|
if (is_string($receiptUrl) && $receiptUrl !== '') {
|
|
return $receiptUrl;
|
|
}
|
|
|
|
return null;
|
|
}
|
|
}
|