where('invoice_number', $invoiceNumber) ->where('status', '!=', InvoiceStatus::CANCELLED->value) ->first(); if (!$invoice || !hash_equals((string) $invoice->lookup_code, strtoupper(trim($lookupCode)))) { return null; } return $invoice; } public static function emailRow(Invoice $invoice): string { return $invoice->lookup_code ? EmailTemplateShell::row('Mã tra cứu', '' . e($invoice->lookup_code) . '') : ''; } public static function emailNote(Invoice $invoice): string { if (!$invoice->lookup_code) { return ''; } $url = MailGlobals::frontendUrl() . '/tra-cuu-hoa-don'; return EmailTemplateShell::paragraph( 'Quý khách có thể tra cứu và tải hoá đơn tại ' . e($url) . ' bằng số hoá đơn ' . e($invoice->invoice_number) . ' và mã tra cứu ' . e($invoice->lookup_code) . '.' ); } public static function payload(Invoice $invoice): array { $invoice->loadMissing(['invoiceItems', 'customer']); $buyer = InvoiceBuyer::forInvoice($invoice); return [ 'invoice_number' => $invoice->invoice_number, 'vat_serial' => $invoice->vat_serial, 'vat_number' => $invoice->vat_number, 'vat_issued_at' => $invoice->vat_issued_at?->toDateString(), 'date' => $invoice->date?->toDateString(), 'status' => $invoice->status, 'status_text' => $invoice->status_label, 'sub_total' => (int) $invoice->sub_total, 'discount_amount' => (int) $invoice->discount_amount, 'tax' => (int) $invoice->tax, 'total' => (int) $invoice->total, 'buyer' => [ 'company' => $buyer['company'], 'tax_code' => $buyer['tax_code'], ], 'items' => $invoice->invoiceItems->map(fn ($item) => [ 'description' => $item->description, 'quantity' => (float) ($item->quantity ?? 1), 'unit_price' => (int) $item->unit_price, 'total_price' => (int) $item->total_price, ])->values(), ]; } }