39728-vm/sale.php
2026-04-19 04:15:39 +00:00

333 lines
13 KiB
PHP

<?php
require_once __DIR__ . '/includes/app.php';
$user = require_roles(['owner', 'manager', 'cashier']);
$pageTitle = tr('تفاصيل الفاتورة الضريبية', 'Tax Invoice Details');
$activeNav = 'sales';
$id = (int) ($_GET['id'] ?? 0);
$sale = null;
$dbError = null;
if ($id > 0) {
try {
$sale = fetch_sale($id);
} catch (Throwable $e) {
$dbError = $e->getMessage();
}
}
// Company Info for Invoice
$companyName = tr('متجر فلات لوجيك', 'Flatlogic Store');
$companyAddress = tr('شارع الملك فهد، الرياض، المملكة العربية السعودية', 'King Fahd Road, Riyadh, KSA');
$companyVat = '300123456789012';
$companyEmail = 'info@flatlogic.com';
$companyPhone = '920000000';
require __DIR__ . '/includes/header.php';
?>
<style>
/* Full Page Borderless Invoice */
.invoice-page {
background: #fff;
min-height: 80vh;
max-width: 900px; margin: 0 auto; border-radius: 12px; box-shadow: 0 10px 40px rgba(0,0,0,0.08); overflow: hidden;
padding: 4rem 3rem;
position: relative;
}
.invoice-ribbon {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 12px;
background: linear-gradient(90deg, #212529, #6c757d);
}
.invoice-header {
display: flex;
justify-content: space-between;
align-items: flex-start;
margin-bottom: 4rem;
}
.company-details h2 {
font-weight: 800;
color: #212529;
font-size: 2.5rem;
letter-spacing: -1px;
margin-bottom: 0.5rem;
}
.company-details p {
color: #adb5bd;
margin-bottom: 0.25rem;
font-size: 1rem;
}
.invoice-meta {
text-align: <?= current_lang() === 'ar' ? 'left' : 'right' ?>;
}
.invoice-meta h1 {
font-size: 4rem;
font-weight: 900;
color: #f8f9fa;
text-transform: uppercase;
letter-spacing: 2px;
line-height: 1;
margin-bottom: 1rem;
}
.meta-box-row {
display: flex;
justify-content: <?= current_lang() === 'ar' ? 'flex-start' : 'flex-end' ?>;
gap: 2rem;
margin-bottom: 0.5rem;
}
.meta-label {
color: #adb5bd;
font-size: 0.9rem;
font-weight: 600;
text-transform: uppercase;
letter-spacing: 1px;
}
.meta-val {
font-weight: 700;
color: #212529;
font-size: 1.1rem;
}
.invoice-parties {
display: flex;
justify-content: space-between;
margin-bottom: 4rem;
padding-top: 3rem;
border-top: 1px dashed #dee2e6;
}
.party-box {
flex: 1;
}
.party-title {
font-size: 0.85rem;
color: #adb5bd;
font-weight: 700;
text-transform: uppercase;
margin-bottom: 1rem;
letter-spacing: 1px;
}
.party-info h4 {
font-weight: 800;
font-size: 1.5rem;
margin-bottom: 0.5rem;
color: #212529;
}
.party-info p {
color: #6c757d;
margin-bottom: 0;
font-size: 1.1rem;
}
.invoice-table {
width: 100%;
margin-bottom: 4rem;
border-collapse: collapse;
}
.invoice-table th {
color: #adb5bd;
font-weight: 600;
padding: 1rem 0;
border-bottom: 2px solid #212529;
text-transform: uppercase;
font-size: 0.85rem;
letter-spacing: 1px;
}
.invoice-table td {
padding: 1.5rem 0;
border-bottom: 1px solid #f8f9fa;
vertical-align: middle;
}
.invoice-table tr:last-child td { border-bottom: 1px solid #dee2e6; }
.totals-section {
display: flex;
justify-content: flex-end;
margin-bottom: 4rem;
}
.totals-box {
width: 100%;
max-width: 400px;
}
.totals-row {
display: flex;
justify-content: space-between;
margin-bottom: 1rem;
font-size: 1.2rem;
color: #6c757d;
}
.totals-row.grand-total {
font-size: 2.5rem;
font-weight: 900;
color: #212529;
margin-top: 1.5rem;
padding-top: 1.5rem;
border-top: 2px solid #212529;
margin-bottom: 0;
line-height: 1.2;
}
.invoice-footer {
display: flex;
justify-content: space-between;
align-items: flex-end;
color: #adb5bd;
font-size: 0.95rem;
border-top: 1px dashed #dee2e6;
padding-top: 3rem;
}
.qr-placeholder {
width: 120px;
height: 120px;
background: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"><rect width="100" height="100" fill="%23f8f9fa"/><path d="M20 20h20v20H20zM60 20h20v20H60zM20 60h20v20H20zM50 50h10v10H50zM70 60h10v10H70zM60 70h10v10H60z" fill="%23dee2e6"/></svg>') center/cover;
}
.print-actions {
position: sticky;
top: 1rem;
z-index: 100;
background: rgba(255, 255, 255, 0.9);
backdrop-filter: blur(10px);
padding: 1rem;
border-radius: 100px;
box-shadow: 0 10px 30px rgba(0,0,0,0.05);
}
/* Print Styles */
@media print {
body { background: #fff; margin: 0; padding: 0; }
.main-sidebar, .main-header, .print-actions, .alert { display: none !important; }
.main-content { margin: 0 !important; padding: 0 !important; width: 100% !important; }
.invoice-page { padding: 0; margin: 0; min-height: auto; }
@page { size: A4; margin: 1.5cm; }
}
</style>
<div class="container-fluid mb-5">
<?php if ($dbError): ?>
<div class="alert alert-warning"><?= h($dbError) ?></div>
<?php elseif (!$sale): ?>
<div class="empty-state bg-white rounded-4 shadow-sm p-5 text-center">
<i class="bi bi-file-earmark-x fs-1 text-muted d-block mb-3"></i>
<h4><?= h(tr('الفاتورة غير موجودة', 'Sale not found')) ?></h4>
<p class="text-muted"><?= h(tr('قد تكون الفاتورة خارج صلاحية هذا الحساب أو لم تعد موجودة.', 'The sale may be outside this account scope or no longer exists.')) ?></p>
<a class="btn btn-outline-secondary mt-3 rounded-pill px-4" href="<?= h(url_for('sales.php')) ?>"><?= h(tr('العودة إلى المبيعات', 'Back to sales')) ?></a>
</div>
<?php else: ?>
<!-- Print Actions (Hidden when printing) -->
<div class="print-actions d-flex justify-content-between align-items-center mb-4 mx-auto" style="max-width: 800px;">
<a href="sales.php" class="btn btn-link text-muted text-decoration-none">
<i class="bi bi-arrow-<?= current_lang() === 'ar' ? 'right' : 'left' ?> me-1"></i> <?= h(tr('رجوع للسجل', 'Back to ledger')) ?>
</a>
<button onclick="window.print()" class="btn btn-dark rounded-pill px-4 shadow-sm fs-6">
<i class="bi bi-printer me-2"></i><?= h(tr('طباعة الفاتورة (A4)', 'Print Invoice (A4)')) ?>
</button>
</div>
<!-- Invoice A4 Document -->
<div class="invoice-page">
<div class="invoice-ribbon"></div>
<div class="invoice-header flex-column flex-md-row">
<div class="company-details mb-4 mb-md-0">
<h2><?= h($companyName) ?></h2>
<p><?= h($companyAddress) ?></p>
<p>VAT NO: <?= h($companyVat) ?></p>
<p><?= h($companyEmail) ?> &nbsp;&bull;&nbsp; <?= h($companyPhone) ?></p>
</div>
<div class="invoice-meta">
<h1><?= ($sale['status'] ?? 'completed') === 'order' ? h(tr('طلب حجز', 'ORDER')) : h(tr('فاتورة ضريبية', 'TAX INVOICE')) ?></h1>
<div class="meta-box-row">
<span class="meta-label"><?= h(tr('رقم الفاتورة', 'Invoice No.')) ?></span>
<span class="meta-val">#<?= h($sale['receipt_no']) ?></span>
</div>
<div class="meta-box-row">
<span class="meta-label"><?= h(tr('تاريخ الإصدار', 'Date Issued')) ?></span>
<span class="meta-val"><?= h(date('Y-m-d', strtotime((string) $sale['sale_date']))) ?></span>
</div>
<div class="meta-box-row">
<span class="meta-label"><?= h(tr('طريقة الدفع', 'Payment')) ?></span>
<span class="meta-val"><?= h(ucfirst((string) $sale['payment_method'])) ?></span>
</div>
<div class="meta-box-row">
<span class="meta-label"><?= h(tr('الحالة', 'Status')) ?></span>
<span class="meta-val"><?= ($sale['status'] ?? 'completed') === 'order' ? h(tr('طلب حجز (غير مدفوع)\", 'Order (Unpaid)\")) : h(tr('مدفوعة', 'Paid')) ?></span>
</div>
</div>
</div>
<div class="invoice-parties">
<div class="party-box">
<div class="party-title"><?= h(tr('فاتورة إلى', 'Invoice To')) ?></div>
<div class="party-info">
<h4><?= h((string) ($sale['customer_name'] ?: tr('عميل نقدي', 'Walk-in Customer'))) ?></h4>
<p><?= h(tr('الفرع:', 'Branch:')) ?> <?= h(branch_label((string) $sale['branch_code'])) ?></p>
</div>
</div>
<div class="party-box text-<?= current_lang() === 'ar' ? 'left' : 'right' ?>">
<div class="party-title"><?= h(tr('بواسطة', 'Served By')) ?></div>
<div class="party-info">
<h4><?= h((string) $sale['cashier_name']) ?></h4>
<p><?= h(tr('موظف مبيعات', 'Sales Rep')) ?></p>
</div>
</div>
</div>
<table class="invoice-table">
<thead>
<tr>
<th width="50%" class="text-<?= current_lang() === 'ar' ? 'right' : 'left' ?>"><?= h(tr('وصف الصنف', 'Item Description')) ?></th>
<th width="15%" class="text-center"><?= h(tr('السعر', 'Price')) ?></th>
<th width="15%" class="text-center"><?= h(tr('الكمية', 'Qty')) ?></th>
<th width="20%" class="text-<?= current_lang() === 'ar' ? 'left' : 'right' ?>"><?= h(tr('الإجمالي', 'Line Total')) ?></th>
</tr>
</thead>
<tbody>
<?php foreach ($sale['items'] as $item): ?>
<tr>
<td>
<div class="fw-bold fs-5 text-dark"><?= h(current_lang() === 'ar' ? ($item['name_ar'] ?? $item['sku']) : ($item['name_en'] ?? $item['sku'])) ?></div>
<div class="text-muted">SKU: <?= h($item['sku']) ?></div>
</td>
<td class="text-center fs-5"><?= h(number_format((float) ($item['price'] ?? 0), 3)) ?></td>
<td class="text-center fs-5 fw-bold"><?= h((string) ($item['qty'] ?? 0)) ?></td>
<td class="text-<?= current_lang() === 'ar' ? 'left' : 'right' ?> fs-4 fw-bold text-dark"><?= h(number_format((float) ($item['line_total'] ?? 0), 3)) ?></td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
<div class="totals-section">
<div class="totals-box">
<div class="totals-row">
<span><?= h(tr('المجموع الفرعي', 'Subtotal')) ?></span>
<span class="text-dark fw-bold"><?= h(number_format((float) $sale['subtotal'], 3)) ?></span>
</div>
<div class="totals-row">
<span><?= h(tr('ضريبة القيمة المضافة (15%)', 'VAT (15%)')) ?></span>
<span class="text-success"><?= h(tr('شامل', 'Inclusive')) ?></span>
</div>
<div class="totals-row grand-total">
<span><?= h(tr('الإجمالي', 'Total')) ?></span>
<span><?= h(number_format((float) $sale['total_amount'], 3)) ?> <small class="fs-5 text-muted"><?= h(tr('ر.ع', 'OMR')) ?></small></span>
</div>
</div>
</div>
<?php if (!empty($sale['notes'])): ?>
<div class="mb-5 px-4 py-3 bg-light" style="border-left: 4px solid #dee2e6;">
<strong class="text-uppercase text-muted fs-6 d-block mb-1"><?= h(tr('ملاحظات', 'Notes')) ?></strong>
<span class="fs-5 text-dark"><?= h((string) $sale['notes']) ?></span>
</div>
<?php endif; ?>
<div class="invoice-footer">
<div>
<h5 class="fw-bold text-dark mb-1"><?= h(tr('شكراً لتعاملكم معنا!', 'Thank you for your business!')) ?></h5>
<p class="mb-0"><?= h(tr('هذه الفاتورة معتمدة ضريبياً، يُرجى الاحتفاظ بها لضمان حقوقك.', 'This is a certified tax invoice. Please keep it for your records.')) ?></p>
</div>
<div class="qr-placeholder"></div>
</div>
</div>
<?php endif; ?>
</div>
<?php require __DIR__ . '/includes/footer.php'; ?>