load(['invoiceItems.product', 'customer', 'order.orderItems']); $setting = Setting::where('key', 'setting')->first(); $settingValue = $setting ? json_decode((string) $setting->value) : null; $data = [ 'invoice' => $invoice, 'invoiceItems' => $invoice->invoiceItems, 'customer' => $invoice->customer, 'buyer' => InvoiceBuyer::forInvoice($invoice), 'order' => $invoice->order, 'companyName' => $settingValue->company ?? 'Thế Giới Số', 'companyAddress' => $settingValue->address ?? '', 'companyPhone' => $settingValue->hotline ?? ($settingValue->tel ?? ''), 'companyEmail' => $settingValue->email ?? '', 'companyLogo' => $this->resolvePdfImagePath($settingValue->logo ?? ''), 'companyTaxCode' => $settingValue->tax ?? '', 'brandColor' => $settingValue->brand_color ?? '#1a56db', 'cfg' => [ 'accent_color' => $settingValue->brand_color ?? '#1a56db', 'show_logo' => true, 'show_company_info' => true, 'show_customer_info' => true, 'show_order_info' => true, 'show_items_table' => true, 'show_summary' => true, 'show_note' => true, 'footer_text' => 'Cảm ơn quý khách đã sử dụng dịch vụ.', 'footer_note' => 'Đây là hóa đơn điện tử được tạo tự động, không cần chữ ký số.', ], ]; return Pdf::loadView('pdf.invoice', $data) ->setPaper('a4', 'portrait') ->output(); } public function vatFileName(Invoice $invoice): string { return 'Hoa-don-VAT-' . $invoice->vat_serial . '-' . $invoice->vat_number . '.pdf'; } /** @return array{pdf: string, file_name: string}|null */ public function attachment(?int $invoiceId): ?array { if (!$invoiceId) { return null; } try { $invoice = Invoice::find($invoiceId); return $invoice ? ['pdf' => $this->generate($invoice), 'file_name' => $this->generateFileName($invoice)] : null; } catch (\Throwable $e) { Log::warning('InvoicePdfService: PDF generation failed, sending without attachment', [ 'invoice_id' => $invoiceId, 'error' => $e->getMessage(), ]); return null; } } public function generateFileName(Invoice $invoice): string { return 'Hoa-don-' . $invoice->invoice_number . '.pdf'; } private function resolvePdfImagePath(?string $path): string { if (!$path) { return ''; } $urlPath = parse_url($path, PHP_URL_PATH) ?: $path; if (str_starts_with($urlPath, '/storage/')) { $localPath = storage_path('app/public/' . ltrim(substr($urlPath, strlen('/storage/')), '/')); return file_exists($localPath) ? $localPath : $path; } if (str_starts_with($path, 'storage/')) { $localPath = storage_path('app/public/' . substr($path, strlen('storage/'))); return file_exists($localPath) ? $localPath : $path; } return $path; } }