Files
portal-api/resources/views/pdf/invoice.blade.php
T
baodev0 6bb4a47bfb Add stubs for various Laravel components and scaffolding
- Created stubs for JavaScript and SASS assets.
- Added stubs for channel, command, component, controller, event, factory, job, listener, mail, middleware, migration, model, notification, observer, policy, request, resource, route provider, seeder, and validation rule.
- Implemented scaffolding for configuration, service provider, and Vite integration.
- Included example views for module structure.
- Introduced a module loader for Vite to handle asset paths dynamically.
2026-05-29 09:28:08 +07:00

318 lines
12 KiB
PHP

@php
$companyLogo = $companyLogo ?? '';
$companyName = $companyName ?? '';
$companyAddress = $companyAddress ?? '';
$companyPhone = $companyPhone ?? '';
$companyEmail = $companyEmail ?? '';
$companyTaxCode = $companyTaxCode ?? '';
$brandColor = $brandColor ?? '#1a56db';
$cfg = array_merge([
'accent_color' => $brandColor,
'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ố.',
], $cfg ?? []);
@endphp
<!DOCTYPE html>
<html lang="vi">
<head>
<meta charset="UTF-8"/>
<title>Hóa đơn #{{ $invoice->invoice_number }}</title>
<style>
@page {
size: A4;
margin: 17mm 18mm;
}
* { box-sizing: border-box; margin: 0; padding: 0; }
html, body {
width: 100%;
}
body {
font-family: "DejaVu Sans", "Times New Roman", serif;
color: #000;
font-size: 11px;
line-height: 1.45;
background: #fff;
}
.page {
width: 100%;
}
/* Header */
.top-table { width: 100%; border-collapse: collapse; margin-bottom: 7px; table-layout: fixed; }
.top-table td { vertical-align: top; }
.logo-cell { width: 31mm; }
.logo-cell img { width: 29mm; max-height: 15mm; }
.title-cell { text-align: center; padding: 0 10px; }
.title-cell h1 { font-size: 16px; font-weight: bold; text-transform: uppercase; letter-spacing: .4px; margin-bottom: 2px; }
.title-cell h2 { font-size: 11px; font-style: italic; font-weight: normal; margin-bottom: 3px; }
.title-cell .date-line { font-size: 11px; }
.meta-cell { width: 43mm; font-size: 10px; line-height: 1.45; vertical-align: top; padding-top: 1px; }
.meta-table { width: 100%; border-collapse: collapse; table-layout: fixed; }
.meta-table td { padding: 2px 0 2px 3px; vertical-align: top; }
.meta-table .meta-label { width: 22mm; font-weight: bold; }
.meta-table .meta-value { word-wrap: break-word; }
.divider { border: none; border-top: 1px solid #999; margin: 7px 0; }
/* Company */
.company-table { width: 100%; border-collapse: collapse; }
.company-main { vertical-align: top; padding: 2px 8px 2px 0; }
.company-main h3 { font-size: 13px; text-transform: uppercase; font-weight: bold; margin-bottom: 5px; }
.company-qr { width: 22mm; vertical-align: top; text-align: right; padding: 2px 0 2px 8px; }
.qr-box { width: 20mm; height: 20mm; border: 1px solid #ccc; background: #f9f9f9; }
.info-line { margin-bottom: 4px; font-size: 11px; line-height: 1.45; }
.lbl { font-weight: bold; }
/* Buyer */
.buyer-section { margin-top: 8px; padding: 1px 0; }
.payment-table { width: 100%; border-collapse: collapse; }
.payment-table td { vertical-align: top; padding: 2px 8px 2px 0; }
/* Items table */
.items-table { width: 100%; border-collapse: collapse; margin-top: 9px; font-size: 10px; line-height: 1.4; table-layout: fixed; page-break-inside: auto; }
.items-table th, .items-table td { border: 1px solid #333; padding: 6px 7px; vertical-align: top; overflow-wrap: break-word; word-wrap: break-word; }
.items-table thead th { font-weight: bold; text-align: center; }
.items-table tr { page-break-inside: avoid; page-break-after: auto; }
.items-table td.center { text-align: center; }
.items-table td.right { text-align: right; }
.items-table tr.sum td { font-weight: bold; }
.items-table tr.total-row td { font-weight: bold; font-size: 11px; background: #fafafa; }
/* Amount words */
.amount-words {
border: 1px solid #333; border-top: none;
padding: 7px 9px; font-size: 11px; line-height: 1.45;
}
/* Signature */
.sign-table { width: 100%; border-collapse: collapse; margin-top: 11mm; text-align: center; page-break-inside: avoid; }
.sign-table td { vertical-align: top; padding: 0 10px; }
.sign-table h4 { font-size: 11px; margin-bottom: 2px; }
.sign-table p { font-size: 10px; font-style: italic; color: #555; }
.sign-spacer { height: 24px; }
/* Note */
.note-box { margin-top: 8px; border-left: 3px solid #e6a817; background: #fefce8; padding: 7px 10px; font-size: 10px; line-height: 1.45; page-break-inside: avoid; }
/* Footer */
.footer { margin-top: 10px; text-align: center; font-size: 10px; line-height: 1.5; color: #444; border-top: 1px solid #ddd; padding-top: 7px; page-break-inside: avoid; }
.status-paid { color: #065f46; font-weight: bold; }
.status-unpaid { color: #991b1b; font-weight: bold; }
.status-cancelled { color: #6b7280; font-weight: bold; }
.accent { color: {{ $cfg['accent_color'] ?? '#1a56db' }}; }
.items-table thead th { background: {{ $cfg['accent_color'] ?? '#1a56db' }}; color: #fff; }
</style>
</head>
<body>
<div class="page">
{{-- ══ HEADER ══ --}}
<table class="top-table">
<tr>
<td class="logo-cell">
@if(($cfg['show_logo'] ?? true) && $companyLogo)
<img src="{{ $companyLogo }}" alt="{{ $companyName }}"/>
@endif
</td>
<td class="title-cell">
<h1>HÓA ĐƠN ĐẶT HÀNG</h1>
<h2>(INVOICE ORDER)</h2>
<div class="date-line">
Ngày <strong>{{ $invoice->created_at?->format('d') ?? '—' }}</strong>
tháng <strong>{{ $invoice->created_at?->format('m') ?? '—' }}</strong>
năm <strong>{{ $invoice->created_at?->format('Y') ?? '—' }}</strong>
</div>
</td>
<td class="meta-cell">
<table class="meta-table">
<tr>
<td class="meta-label">Mã hóa đơn:</td>
<td class="meta-value">{{ $invoice->invoice_number }}</td>
</tr>
@if($order)
<tr>
<td class="meta-label">Mã đơn hàng:</td>
<td class="meta-value">{{ $order->order_num }}</td>
</tr>
@endif
<tr>
<td class="meta-label">Hạn thanh toán:</td>
<td class="meta-value">{{ $invoice->due_date ? \Carbon\Carbon::parse($invoice->due_date)->format('d/m/Y') : '—' }}</td>
</tr>
<tr>
<td class="meta-label">Trạng thái:</td>
<td class="meta-value">
@if($invoice->status == 2)<span class="status-paid">Đã thanh toán</span>
@elseif($invoice->status == 1)<span class="status-unpaid">Chưa thanh toán</span>
@else<span class="status-cancelled">Đã hủy</span>@endif
</td>
</tr>
</table>
</td>
</tr>
</table>
<hr class="divider"/>
{{-- ══ COMPANY ══ --}}
@if($cfg['show_company_info'] ?? true)
<table class="company-table">
<tr>
<td class="company-main">
<h3>{{ $companyName }}</h3>
@if($companyTaxCode)
<div class="info-line"><span class="lbl">Mã số thuế (Tax code):</span> {{ $companyTaxCode }}</div>
@endif
@if($companyAddress)
<div class="info-line"><span class="lbl">Địa chỉ (Address):</span> {{ $companyAddress }}</div>
@endif
@if($companyPhone)
<div class="info-line"><span class="lbl">Điện thoại (Tel):</span> {{ $companyPhone }}</div>
@endif
@if($companyEmail)
<div class="info-line"><span class="lbl">Email:</span> {{ $companyEmail }}</div>
@endif
</td>
<td class="company-qr"><div class="qr-box"></div></td>
</tr>
</table>
<hr class="divider"/>
@endif
{{-- ══ BUYER ══ --}}
@if($cfg['show_customer_info'] ?? true)
<div class="buyer-section">
<div class="info-line">
<span class="lbl">Họ tên người mua hàng (Buyer):</span> {{ $customer?->fullname ?? '—' }}
</div>
@if($customer?->company)
<div class="info-line"><span class="lbl">Tên đơn vị:</span> {{ $customer->company }}</div>
@endif
@if($customer?->identity_number)
<div class="info-line"><span class="lbl">MST / CMND:</span> {{ $customer->identity_number }}</div>
@endif
@if($customer?->address)
<div class="info-line"><span class="lbl">Địa chỉ (Address):</span> {{ $customer->address }}</div>
@endif
<table class="payment-table">
<tr>
<td style="width:55%">
<div class="info-line">
<span class="lbl">Hình thức thanh toán:</span>
{{ $invoice->payment_method ? strtoupper($invoice->payment_method) : 'TM/CK' }}
</div>
</td>
<td>
<div class="info-line"><span class="lbl">Email:</span> {{ $customer?->email ?? '—' }}</div>
</td>
</tr>
</table>
</div>
@endif
{{-- ══ ITEMS TABLE ══ --}}
@if($cfg['show_items_table'] ?? true)
<table class="items-table">
<thead>
<tr>
<th style="width:9mm">STT</th>
<th>Tên hàng hóa, dịch vụ</th>
<th style="width:19mm">Đơn vị tính</th>
<th style="width:17mm">Số lượng</th>
<th style="width:27mm">Đơn giá (đ)</th>
<th style="width:29mm">Thành tiền (đ)</th>
</tr>
</thead>
<tbody>
@foreach($invoiceItems as $i => $item)
<tr>
<td class="center">{{ $i + 1 }}</td>
<td>{{ $item->description ?? ($item->product?->name ?? 'Dịch vụ') }}</td>
<td class="center">{{ ($item->months && $item->months > 0) ? 'Tháng' : 'Lần' }}</td>
<td class="center">{{ number_format($item->quantity ?? 1, 2, ',', '.') }}</td>
<td class="right">{{ number_format($item->unit_price, 0, ',', '.') }}</td>
<td class="right">{{ number_format($item->total_price, 0, ',', '.') }}</td>
</tr>
@endforeach
@if($cfg['show_summary'] ?? true)
{{-- Sub-total --}}
<tr class="sum">
<td colspan="5" class="right">Cộng tiền hàng (Total amount excl. VAT)</td>
<td class="right">{{ number_format($invoice->sub_total, 0, ',', '.') }}</td>
</tr>
@if($invoice->discount_amount > 0)
<tr class="sum">
<td colspan="5" class="right">Giảm giá (Discount)</td>
<td class="right">-{{ number_format($invoice->discount_amount, 0, ',', '.') }}</td>
</tr>
@endif
@php $taxRate = ($invoice->total > 0 && $invoice->tax > 0) ? round($invoice->tax / ($invoice->total - $invoice->tax) * 100) : 0; @endphp
<tr class="sum">
<td colspan="3">Thuế suất GTGT (VAT rate): {{ $taxRate > 0 ? $taxRate.'%' : 'Không áp dụng' }}</td>
<td colspan="2" class="right">Tiền thuế GTGT (VAT amount)</td>
<td class="right">{{ number_format($invoice->tax, 0, ',', '.') }}</td>
</tr>
<tr class="sum total-row">
<td colspan="5" class="right">Tổng tiền thanh toán (Total amount)</td>
<td class="right">{{ number_format($invoice->total, 0, ',', '.') }}</td>
</tr>
@endif
</tbody>
</table>
<div class="amount-words">
<strong>Số tiền viết bằng chữ (Total amount in words):</strong>
{{ \App\Helpers\NumberToWords::convert((int) $invoice->total) }}.
</div>
@endif
{{-- ══ NOTE ══ --}}
@if(($cfg['show_note'] ?? true) && $invoice->note)
<div class="note-box"><strong>Ghi chú:</strong> {{ $invoice->note }}</div>
@endif
{{-- ══ SIGNATURE ══ --}}
<table class="sign-table">
<tr>
<td>
<h4>Người mua hàng<br/><em style="font-size:11px">(Buyer's signature)</em></h4>
<p>Ký, ghi rõ họ tên</p>
<div class="sign-spacer"></div>
<p>{{ $customer?->fullname ?? '' }}</p>
</td>
<td></td>
<td>
<h4>Người bán hàng<br/><em style="font-size:11px">(Seller's signature)</em></h4>
<p>Ký, đóng dấu, ghi rõ họ tên</p>
<div class="sign-spacer"></div>
<p>{{ $companyName }}</p>
</td>
</tr>
</table>
{{-- ══ FOOTER ══ --}}
<div class="footer">
@if($cfg['footer_text'] ?? ''){{ $cfg['footer_text'] }}<br/>@endif
@if($cfg['footer_note'] ?? ''){{ $cfg['footer_note'] }}<br/>@endif
Mã tra cứu: <strong>{{ $invoice->invoice_number }}</strong>
</div>
</div>
</body>
</html>