463 lines
15 KiB
PHP
463 lines
15 KiB
PHP
<?php
|
|
require_once __DIR__ . '/includes/app.php';
|
|
$user = require_permission('sales', 'show');
|
|
$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 = current_lang() === 'ar' ? get_setting('company_name_ar', 'حلوى الريامي') : get_setting('company_name_en', 'Al Riyami Sweets');
|
|
$companyAddress = get_setting('company_address', '');
|
|
$companyVat = get_setting('company_vat_number', '300123456789012');
|
|
$companyEmail = 'info@flatlogic.com';
|
|
$companyPhone = get_setting('company_phone', '');
|
|
|
|
require __DIR__ . '/includes/header.php';
|
|
?>
|
|
|
|
<style>
|
|
/* Formal A4 Invoice Styles */
|
|
.invoice-container {
|
|
background: #fff;
|
|
max-width: 210mm; /* A4 width */
|
|
margin: 2rem auto;
|
|
padding: 2cm;
|
|
box-shadow: 0 4px 15px rgba(0,0,0,0.05);
|
|
border: 1px solid #ddd;
|
|
color: #333;
|
|
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
|
|
font-size: 13px; /* Smaller, formal text */
|
|
line-height: 1.5;
|
|
}
|
|
|
|
.invoice-header {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: flex-start;
|
|
border-bottom: 2px solid #333;
|
|
padding-bottom: 1.5rem;
|
|
margin-bottom: 2rem;
|
|
}
|
|
|
|
.company-logo-info {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 1.5rem;
|
|
}
|
|
|
|
.invoice-logo {
|
|
width: 80px;
|
|
height: 80px;
|
|
background: #f8f9fa;
|
|
border: 1px solid #eee;
|
|
border-radius: 4px;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
}
|
|
.invoice-logo svg {
|
|
width: 50px;
|
|
height: 50px;
|
|
fill: none;
|
|
stroke: #333;
|
|
stroke-width: 2;
|
|
}
|
|
|
|
.company-details h2 {
|
|
font-size: 18px;
|
|
font-weight: bold;
|
|
margin: 0 0 5px 0;
|
|
text-transform: uppercase;
|
|
color: #000;
|
|
}
|
|
.company-details p {
|
|
margin: 2px 0;
|
|
color: #555;
|
|
}
|
|
|
|
.invoice-title-meta {
|
|
text-align: <?= current_lang() === 'ar' ? 'left' : 'right' ?>;
|
|
}
|
|
|
|
.invoice-title-meta h1 {
|
|
font-size: 24px;
|
|
font-weight: bold;
|
|
margin: 0 0 15px 0;
|
|
text-transform: uppercase;
|
|
color: #000;
|
|
letter-spacing: 1px;
|
|
}
|
|
|
|
.meta-grid {
|
|
display: grid;
|
|
grid-template-columns: auto auto;
|
|
gap: 5px 15px;
|
|
text-align: <?= current_lang() === 'ar' ? 'right' : 'left' ?>;
|
|
}
|
|
<?php if (current_lang() === 'ar'): ?>
|
|
.meta-grid { direction: rtl; }
|
|
<?php endif; ?>
|
|
|
|
.meta-label {
|
|
font-weight: bold;
|
|
color: #666;
|
|
}
|
|
|
|
.meta-val {
|
|
font-weight: bold;
|
|
color: #000;
|
|
}
|
|
|
|
.invoice-parties {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
margin-bottom: 2rem;
|
|
}
|
|
|
|
.party-box {
|
|
width: 48%;
|
|
}
|
|
|
|
.party-title {
|
|
font-weight: bold;
|
|
border-bottom: 1px solid #ccc;
|
|
padding-bottom: 5px;
|
|
margin-bottom: 10px;
|
|
color: #000;
|
|
text-transform: uppercase;
|
|
}
|
|
|
|
.party-info h4 {
|
|
font-size: 14px;
|
|
font-weight: bold;
|
|
margin: 0 0 5px 0;
|
|
color: #000;
|
|
}
|
|
|
|
.party-info p {
|
|
margin: 0;
|
|
color: #555;
|
|
}
|
|
|
|
.invoice-table-wrapper {
|
|
margin-bottom: 2rem;
|
|
}
|
|
|
|
.formal-table {
|
|
width: 100%;
|
|
border-collapse: collapse;
|
|
}
|
|
|
|
.formal-table th,
|
|
.formal-table td {
|
|
border: 1px solid #ccc;
|
|
padding: 8px 10px;
|
|
vertical-align: top;
|
|
}
|
|
|
|
.formal-table th {
|
|
background-color: #f9f9f9;
|
|
font-weight: bold;
|
|
color: #000;
|
|
text-transform: uppercase;
|
|
}
|
|
|
|
.formal-table th.text-right,
|
|
.formal-table td.text-right {
|
|
text-align: right;
|
|
}
|
|
|
|
.formal-table th.text-center,
|
|
.formal-table td.text-center {
|
|
text-align: center;
|
|
}
|
|
|
|
.item-name {
|
|
font-weight: bold;
|
|
color: #000;
|
|
margin-bottom: 3px;
|
|
}
|
|
|
|
.item-sku {
|
|
color: #666;
|
|
font-size: 11px;
|
|
}
|
|
|
|
.invoice-summary {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: flex-start;
|
|
}
|
|
|
|
.invoice-notes {
|
|
width: 50%;
|
|
font-size: 12px;
|
|
}
|
|
|
|
.notes-title {
|
|
font-weight: bold;
|
|
text-transform: uppercase;
|
|
margin-bottom: 5px;
|
|
}
|
|
|
|
.totals-box {
|
|
width: 40%;
|
|
}
|
|
|
|
.totals-table {
|
|
width: 100%;
|
|
border-collapse: collapse;
|
|
}
|
|
|
|
.totals-table td {
|
|
padding: 6px 10px;
|
|
border-bottom: 1px solid #eee;
|
|
}
|
|
|
|
.totals-table tr:last-child td {
|
|
border-bottom: none;
|
|
}
|
|
|
|
.total-label {
|
|
font-weight: bold;
|
|
color: #666;
|
|
}
|
|
|
|
.total-amount {
|
|
text-align: right;
|
|
font-weight: bold;
|
|
color: #000;
|
|
}
|
|
|
|
.grand-total-row td {
|
|
font-size: 16px;
|
|
border-top: 2px solid #000;
|
|
padding-top: 10px;
|
|
}
|
|
|
|
.grand-total-row .total-label {
|
|
color: #000;
|
|
text-transform: uppercase;
|
|
}
|
|
|
|
.invoice-footer {
|
|
margin-top: 3rem;
|
|
padding-top: 1.5rem;
|
|
border-top: 1px solid #ccc;
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: flex-end;
|
|
font-size: 12px;
|
|
color: #666;
|
|
}
|
|
|
|
.qr-code {
|
|
width: 80px;
|
|
height: 80px;
|
|
background: #fff;
|
|
border: 1px solid #ccc;
|
|
padding: 5px;
|
|
}
|
|
.qr-code img {
|
|
width: 100%;
|
|
height: 100%;
|
|
display: block;
|
|
}
|
|
|
|
.print-actions {
|
|
position: sticky;
|
|
top: 1rem;
|
|
z-index: 100;
|
|
background: rgba(255, 255, 255, 0.95);
|
|
padding: 15px 25px;
|
|
border-radius: 8px;
|
|
box-shadow: 0 4px 15px rgba(0,0,0,0.1);
|
|
border: 1px solid #ddd;
|
|
max-width: 210mm;
|
|
margin: 0 auto 2rem auto;
|
|
}
|
|
|
|
/* Print Styles */
|
|
@media print {
|
|
body { background: #fff; }
|
|
.main-sidebar, .main-header, .print-actions, .alert, .footer-section { display: none !important; }
|
|
.main-content { margin: 0 !important; padding: 0 !important; width: 100% !important; }
|
|
.invoice-container {
|
|
box-shadow: none;
|
|
border: none;
|
|
margin: 0;
|
|
padding: 0;
|
|
max-width: 100%;
|
|
width: 100%;
|
|
}
|
|
@page { size: A4; margin: 15mm; }
|
|
}
|
|
</style>
|
|
|
|
<div class="container-fluid mb-5">
|
|
<?php if ($dbError): ?>
|
|
<div class="alert alert-warning"><?= h($dbError) ?></div>
|
|
<?php elseif (!$sale): ?>
|
|
<div class="alert alert-info text-center mt-4">
|
|
<h4><?= h(tr('الفاتورة غير موجودة', 'Sale not found')) ?></h4>
|
|
<p><?= h(tr('قد تكون الفاتورة خارج صلاحية هذا الحساب أو لم تعد موجودة.', 'The sale may be outside this account scope or no longer exists.')) ?></p>
|
|
<a class="btn btn-outline-secondary mt-3" href="<?= h(url_for('sales.php')) ?>"><?= h(tr('العودة إلى المبيعات', 'Back to sales')) ?></a>
|
|
</div>
|
|
<?php else: ?>
|
|
|
|
<!-- Print Actions -->
|
|
<div class="print-actions d-flex justify-content-between align-items-center">
|
|
<a href="sales.php" class="btn btn-outline-secondary btn-sm">
|
|
<i class="bi bi-arrow-<?= current_lang() === 'ar' ? 'right' : 'left' ?> me-1"></i> <?= h(tr('رجوع للسجل', 'Back to ledger')) ?>
|
|
</a>
|
|
<div>
|
|
<a href="<?= h(url_for('edit_sale.php', ['id' => $sale['id']])) ?>" class="btn btn-outline-primary btn-sm me-2">
|
|
<i class="bi bi-pencil me-1"></i><?= h(tr('تعديل الفاتورة', 'Edit Invoice')) ?>
|
|
</a>
|
|
<button onclick="window.print()" class="btn btn-dark btn-sm px-4">
|
|
<i class="bi bi-printer me-2"></i><?= h(tr('طباعة الفاتورة', 'Print Invoice')) ?>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Formal A4 Invoice -->
|
|
<div class="invoice-container">
|
|
<div class="invoice-header">
|
|
<div class="company-logo-info">
|
|
<div class="invoice-logo">
|
|
<!-- Formal Box Logo Placeholder -->
|
|
<svg viewBox="0 0 24 24"><path d="M12 2L2 7l10 5 10-5-10-5zM2 17l10 5 10-5M2 12l10 5 10-5" stroke-linecap="round" stroke-linejoin="round"/></svg>
|
|
</div>
|
|
<div class="company-details">
|
|
<h2><?= h($companyName) ?></h2>
|
|
<p><?= h($companyAddress) ?></p>
|
|
<p><?= h(tr('الرقم الضريبي:', 'VAT NO:')) ?> <?= h($companyVat) ?></p>
|
|
<p><?= h($companyPhone) ?> | <?= h($companyEmail) ?></p>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="invoice-title-meta">
|
|
<h1><?= ($sale['status'] ?? 'completed') === 'order' ? h(tr('طلب حجز', 'ORDER')) : h(tr('فاتورة ضريبية', 'TAX INVOICE')) ?></h1>
|
|
|
|
<div class="meta-grid">
|
|
<div class="meta-label"><?= h(tr('رقم الفاتورة', 'Invoice No.')) ?>:</div>
|
|
<div class="meta-val">#<?= h($sale['receipt_no']) ?></div>
|
|
|
|
<div class="meta-label"><?= h(tr('تاريخ الإصدار', 'Date Issued')) ?>:</div>
|
|
<div class="meta-val"><?= h(date('Y-m-d H:i', strtotime((string) $sale['sale_date']))) ?></div>
|
|
|
|
<div class="meta-label"><?= h(tr('طريقة الدفع', 'Payment')) ?>:</div>
|
|
<div class="meta-val"><?= h(ucfirst((string) $sale['payment_method'])) ?></div>
|
|
|
|
<div class="meta-label"><?= h(tr('الحالة', 'Status')) ?>:</div>
|
|
<div class="meta-val"><?= ($sale['status'] ?? 'completed') === 'order' ? h(tr('غير مدفوعة', 'Unpaid')) : h(tr('مدفوعة', 'Paid')) ?></div>
|
|
</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>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="party-box">
|
|
<div class="party-title"><?= h(tr('معلومات المتجر', 'Store Details')) ?></div>
|
|
<div class="party-info">
|
|
<p><strong><?= h(tr('الفرع:', 'Branch:')) ?></strong> <?= h(branch_label((string) $sale['branch_code'])) ?></p>
|
|
<p><strong><?= h(tr('بواسطة:', 'Served By:')) ?></strong> <?= h((string) $sale['cashier_name']) ?></p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="invoice-table-wrapper">
|
|
<table class="formal-table">
|
|
<thead>
|
|
<tr>
|
|
<th width="5%" class="text-center">#</th>
|
|
<th width="45%" class="<?= current_lang() === 'ar' ? 'text-right' : 'text-left' ?>"><?= h(tr('وصف الصنف', 'Item Description')) ?></th>
|
|
<th width="15%" class="text-center"><?= h(tr('الكمية', 'Qty')) ?></th>
|
|
<th width="15%" class="text-center"><?= h(tr('سعر الوحدة', 'Unit Price')) ?></th>
|
|
<th width="20%" class="<?= current_lang() === 'ar' ? 'text-left' : 'text-right' ?>"><?= h(tr('الإجمالي', 'Line Total')) ?></th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<?php $i = 1; foreach ($sale['items'] as $item): ?>
|
|
<tr>
|
|
<td class="text-center"><?= $i++ ?></td>
|
|
<td>
|
|
<div class="item-name"><?= h(current_lang() === 'ar' ? ($item['name_ar'] ?? $item['sku']) : ($item['name_en'] ?? $item['sku'])) ?></div>
|
|
<div class="item-sku"><?= h(tr('رمز الصنف:', 'SKU:')) ?> <?= h($item['sku']) ?></div>
|
|
</td>
|
|
<td class="text-center"><?= h((string) ($item['qty'] ?? 0)) ?></td>
|
|
<td class="text-center"><?= h(number_format((float) ($item['price'] ?? 0), 3)) ?></td>
|
|
<td class="<?= current_lang() === 'ar' ? 'text-left' : 'text-right' ?>"><?= h(number_format((float) ($item['line_total'] ?? 0), 3)) ?></td>
|
|
</tr>
|
|
<?php endforeach; ?>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
|
|
<div class="invoice-summary">
|
|
<div class="invoice-notes">
|
|
<?php if (!empty($sale['notes'])): ?>
|
|
<div class="notes-title"><?= h(tr('ملاحظات', 'Notes')) ?></div>
|
|
<p><?= nl2br(h((string) $sale['notes'])) ?></p>
|
|
<?php endif; ?>
|
|
</div>
|
|
|
|
<div class="totals-box">
|
|
<table class="totals-table">
|
|
<tr>
|
|
<td class="total-label"><?= h(tr('المجموع الفرعي', 'Subtotal')) ?></td>
|
|
<td class="total-amount"><?= h(number_format((float) $sale['subtotal'], 3)) ?></td>
|
|
</tr>
|
|
<tr>
|
|
<td class="total-label"><?= h(tr('ضريبة القيمة المضافة (مضافة)', 'VAT (Added)')) ?></td>
|
|
<td class="total-amount"><?= number_format((float)($sale['vat_amount'] ?? 0), 3) ?></td>
|
|
</tr>
|
|
<tr class="grand-total-row">
|
|
<td class="total-label"><?= h(tr('الإجمالي', 'Total')) ?></td>
|
|
<td class="total-amount"><?= h(number_format((float) $sale['total_amount'], 3)) ?> <?= h(tr('ر.ع', 'OMR')) ?></td>
|
|
</tr>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="invoice-footer">
|
|
<div class="footer-text">
|
|
<p style="margin-bottom: 5px; font-weight: bold; color: #000;">
|
|
<?= h(tr('شكراً لتعاملكم معنا!', 'Thank you for your business!')) ?>
|
|
</p>
|
|
<p style="margin: 0;">
|
|
<?= h(tr('هذه الفاتورة معتمدة ضريبياً، يُرجى الاحتفاظ بها لضمان حقوقك.', 'This is a certified tax invoice. Please keep it for your records.')) ?>
|
|
</p>
|
|
</div>
|
|
|
|
<!-- Simple QR code simulation using an inline SVG to keep it formal and clean -->
|
|
<div class="qr-code">
|
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
|
|
<rect width="100" height="100" fill="#fff"/>
|
|
<path d="M10 10h20v20H10zM70 10h20v20H70zM10 70h20v20H10z" fill="#000"/>
|
|
<path d="M15 15h10v10H15zM75 15h10v10H75zM15 75h10v10H15z" fill="#fff"/>
|
|
<path d="M35 10h10v10H35zM50 10h10v10H50zM35 25h10v10H35zM50 25h20v10H50zM75 35h15v10H75zM10 35h20v10H10zM35 40h10v20H35zM50 50h20v20H50zM10 50h15v10H10zM75 60h15v30H75zM35 70h10v20H35zM50 80h10v10H50z" fill="#000"/>
|
|
</svg>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<?php endif; ?>
|
|
</div>
|
|
|
|
<?php require __DIR__ . '/includes/footer.php'; ?>
|