205 lines
15 KiB
PHP
205 lines
15 KiB
PHP
<?php
|
|
// Shared Sales/Purchases list view extracted from index.php to keep the main router thinner.
|
|
?>
|
|
<div class="card p-4">
|
|
<!-- Print Header -->
|
|
<div class="print-only mb-4">
|
|
<div class="row align-items-center">
|
|
<div class="col-6">
|
|
<?php if (!empty($data['settings']['company_logo'])): ?>
|
|
<img src="<?= htmlspecialchars($data['settings']['company_logo']) ?>" alt="Logo" style="max-height: 80px;" class="mb-2">
|
|
<?php endif; ?>
|
|
<h3 class="mb-1 fw-bold"><?= htmlspecialchars($data['settings']['company_name'] ?? 'Accounting System') ?></h3>
|
|
<p class="text-muted small mb-0"><?= nl2br(htmlspecialchars($data['settings']['company_address'] ?? '')) ?></p>
|
|
<p class="text-muted small mb-0">VAT: <?= htmlspecialchars($data['settings']['vat_number'] ?? '') ?></p>
|
|
</div>
|
|
<div class="col-6 text-end">
|
|
<h2 class="text-uppercase text-muted"><?= $currTitle['en'] ?> Report</h2>
|
|
<p class="mb-0">Date: <?= date('Y-m-d') ?></p>
|
|
<?php if (!empty($_GET['start_date']) || !empty($_GET['end_date']) || !empty($_GET['customer_id'])): ?>
|
|
<p class="small text-muted mb-0">
|
|
<?php if (!empty($_GET['customer_id'])): ?>
|
|
<strong><?= $page === 'sales' ? 'Customer' : 'Supplier' ?>:</strong>
|
|
<?php
|
|
foreach ($data['customers_list'] as $c) {
|
|
if ($c['id'] == $_GET['customer_id']) {
|
|
echo htmlspecialchars($c['name']);
|
|
break;
|
|
}
|
|
}
|
|
?> |
|
|
<?php endif; ?>
|
|
<strong>Period:</strong> <?= !empty($_GET['start_date']) ? $_GET['start_date'] : 'All' ?> to <?= !empty($_GET['end_date']) ? $_GET['end_date'] : 'All' ?>
|
|
</p>
|
|
<?php endif; ?>
|
|
</div>
|
|
</div>
|
|
<hr>
|
|
</div>
|
|
|
|
<div class="d-flex justify-content-between align-items-center mb-4 d-print-none">
|
|
<h5 class="m-0" data-en="<?= $currTitle['en'] ?>" data-ar="<?= $currTitle['ar'] ?>"><?= $currTitle['en'] ?></h5>
|
|
<div class="d-flex gap-2">
|
|
<a href="index.php?<?= http_build_query(array_merge($_GET, ['page' => 'export', 'type' => $page, 'format' => 'excel'])) ?>" class="btn btn-outline-success">
|
|
<i class="bi bi-file-earmark-excel"></i> <span data-en="Export to Excel" data-ar="تصدير إلى اكسل">Export to Excel</span>
|
|
</a>
|
|
<?php if (can($page . '_add')): ?>
|
|
<button class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#addInvoiceModal">
|
|
<i class="bi bi-plus-lg"></i> <span data-en="Create New Tax Invoice" data-ar="إنشاء فاتورة ضريبية جديدة">Create New Tax Invoice</span>
|
|
</button>
|
|
<?php endif; ?>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Filters Section -->
|
|
<div class="bg-light p-3 rounded mb-4 d-print-none">
|
|
<form method="GET" class="documents-filter">
|
|
<input type="hidden" name="page" value="<?= $page ?>">
|
|
<input type="hidden" name="limit" value="<?= (int)($_GET['limit'] ?? 20) ?>">
|
|
<div class="documents-filter__field documents-filter__field--search">
|
|
<label class="form-label small fw-bold" data-en="Search" data-ar="بحث">Search</label>
|
|
<input type="text" name="search" class="form-control form-control-sm" value="<?= htmlspecialchars($_GET['search'] ?? '') ?>" placeholder="<?= $page === 'sales' ? 'Invoice #, transaction # or customer...' : 'Purchase # or supplier...' ?>">
|
|
</div>
|
|
<div class="documents-filter__field documents-filter__field--party">
|
|
<label class="form-label small fw-bold" data-en="<?= $page === 'sales' ? 'Customer' : 'Supplier' ?>" data-ar="<?= $page === 'sales' ? 'العميل' : 'المورد' ?>"><?= $page === 'sales' ? 'Customer' : 'Supplier' ?></label>
|
|
<select name="customer_id" class="form-select form-select-sm">
|
|
<option value="" data-en="All" data-ar="الكل">All</option>
|
|
<?php foreach ($data['customers_list'] as $c): ?>
|
|
<option value="<?= $c['id'] ?>" <?= (($_GET['customer_id'] ?? '') == $c['id']) ? 'selected' : '' ?>><?= htmlspecialchars($c['name']) ?></option>
|
|
<?php endforeach; ?>
|
|
</select>
|
|
</div>
|
|
<div class="documents-filter__field documents-filter__field--date">
|
|
<label class="form-label small fw-bold" data-en="Start Date" data-ar="من تاريخ">Start Date</label>
|
|
<input type="date" name="start_date" class="form-control form-control-sm" value="<?= htmlspecialchars($_GET['start_date'] ?? '') ?>">
|
|
</div>
|
|
<div class="documents-filter__field documents-filter__field--date">
|
|
<label class="form-label small fw-bold" data-en="End Date" data-ar="إلى تاريخ">End Date</label>
|
|
<input type="date" name="end_date" class="form-control form-control-sm" value="<?= htmlspecialchars($_GET['end_date'] ?? '') ?>">
|
|
</div>
|
|
<div class="documents-filter__actions">
|
|
<button type="submit" class="btn btn-primary btn-sm">
|
|
<i class="bi bi-filter"></i> <span data-en="Filter" data-ar="تصفية">Filter</span>
|
|
</button>
|
|
<div class="dropdown d-inline-block">
|
|
<button class="btn btn-success btn-sm dropdown-toggle" type="button" data-bs-toggle="dropdown">
|
|
<i class="bi bi-download"></i> <span data-en="Export" data-ar="تصدير">Export</span>
|
|
</button>
|
|
<ul class="dropdown-menu dropdown-menu-end">
|
|
<li><a class="dropdown-item" href="index.php?<?= http_build_query(array_merge($_GET, ['page' => 'export', 'type' => $page, 'format' => 'csv'])) ?>"><i class="bi bi-filetype-csv me-2"></i> CSV</a></li>
|
|
<li><a class="dropdown-item" href="index.php?<?= http_build_query(array_merge($_GET, ['page' => 'export', 'type' => $page, 'format' => 'excel'])) ?>"><i class="bi bi-file-earmark-excel me-2"></i> Excel</a></li>
|
|
</ul>
|
|
</div>
|
|
<button type="button" class="btn btn-outline-primary btn-sm" onclick="window.print()">
|
|
<i class="bi bi-printer"></i> <span data-en="Print" data-ar="طباعة">Print</span>
|
|
</button>
|
|
<a href="index.php?page=<?= $page ?>" class="btn btn-outline-secondary btn-sm">
|
|
<i class="bi bi-x-circle"></i> <span data-en="Clear" data-ar="مسح">Clear</span>
|
|
</a>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
<div class="table-responsive">
|
|
<table class="table table-hover align-middle documents-table">
|
|
<thead>
|
|
<tr>
|
|
<th data-en="Invoice #" data-ar="رقم الفاتورة">Invoice #</th>
|
|
<th data-en="<?= $page === 'sales' ? 'Customer' : 'Supplier' ?>" data-ar="<?= $page === 'sales' ? 'العميل' : 'المورد' ?>"><?= $page === 'sales' ? 'Customer' : 'Supplier' ?></th>
|
|
<th data-en="Dates" data-ar="التواريخ">Dates</th>
|
|
<th data-en="Payment" data-ar="الدفع">Payment</th>
|
|
<th data-en="Status" data-ar="الحالة">Status</th>
|
|
<th data-en="Total" data-ar="الإجمالي" class="text-end">Total</th>
|
|
<th data-en="Paid" data-ar="المدفوع" class="text-end">Paid</th>
|
|
<th data-en="Balance" data-ar="المتبقي" class="text-end">Balance</th>
|
|
<th data-en="Actions" data-ar="الإجراءات" class="text-end d-print-none">Actions</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<?php
|
|
$itemTable = ($page === 'purchases') ? 'purchase_items' : 'invoice_items';
|
|
$fkCol = ($page === 'purchases') ? 'purchase_id' : 'invoice_id';
|
|
$total_all = 0; $total_paid = 0; $total_balance = 0;
|
|
foreach ($data['invoices'] as $inv):
|
|
$total_all += (float)$inv['total_with_vat'];
|
|
$total_paid += (float)$inv['paid_amount'];
|
|
$total_balance += (float)$inv['balance_amount'];
|
|
$items = db()->prepare("SELECT ii.*, i.name_en, i.name_ar, i.vat_rate
|
|
FROM $itemTable ii
|
|
JOIN stock_items i ON ii.item_id = i.id
|
|
WHERE ii.$fkCol = ?");
|
|
$items->execute([$inv['id']]);
|
|
$inv['items'] = $items->fetchAll(PDO::FETCH_ASSOC);
|
|
$isOverdue = !empty($inv['due_date']) && strtotime((string)$inv['due_date']) < time() && ($inv['status'] ?? '') !== 'paid';
|
|
?>
|
|
<tr>
|
|
<td class="fw-semibold"><?= htmlspecialchars($inv['document_no']) ?></td>
|
|
<td class="documents-table__party">
|
|
<div class="fw-semibold text-dark"><?= htmlspecialchars($inv['party_name']) ?></div>
|
|
<?php if (!empty($inv['customer_phone'])): ?>
|
|
<div class="small text-muted"><?= htmlspecialchars($inv['customer_phone']) ?></div>
|
|
<?php endif; ?>
|
|
</td>
|
|
<td class="documents-table__dates">
|
|
<div class="small text-nowrap"><i class="bi bi-calendar-event text-muted me-1"></i><?= htmlspecialchars($inv['invoice_date'] ?? '---') ?></div>
|
|
<div class="small text-nowrap">
|
|
<i class="bi bi-hourglass-split text-muted me-1"></i>
|
|
<span class="<?= $isOverdue ? 'text-danger fw-bold' : '' ?>">
|
|
<?= htmlspecialchars($inv['due_date'] ?: '---') ?>
|
|
<?php if ($isOverdue): ?>
|
|
<i class="bi bi-exclamation-triangle-fill ms-1" title="Overdue"></i>
|
|
<?php endif; ?>
|
|
</span>
|
|
</div>
|
|
</td>
|
|
<td><span class="badge bg-light text-dark border"><?= htmlspecialchars($inv['payment_type_label']) ?></span></td>
|
|
<td>
|
|
<?php
|
|
$statusClass = 'bg-secondary';
|
|
if ($inv['status'] === 'paid') $statusClass = 'bg-success';
|
|
elseif ($inv['status'] === 'unpaid') $statusClass = 'bg-danger';
|
|
elseif ($inv['status'] === 'partially_paid') $statusClass = 'bg-warning text-dark';
|
|
?>
|
|
<span class="badge text-uppercase <?= $statusClass ?>"><?= htmlspecialchars(str_replace('_', ' ', $inv['status'])) ?></span>
|
|
</td>
|
|
<td class="text-end fw-bold">OMR <?= number_format((float)$inv['total_with_vat'], 3) ?></td>
|
|
<td class="text-end text-success">OMR <?= number_format((float)$inv['paid_amount'], 3) ?></td>
|
|
<td class="text-end text-danger fw-bold">OMR <?= number_format((float)$inv['balance_amount'], 3) ?></td>
|
|
<td class="text-end d-print-none">
|
|
<div class="btn-group btn-group-sm">
|
|
<button class="btn btn-outline-info view-invoice-btn" data-json="<?= htmlspecialchars(json_encode($inv)) ?>" title="View"><i class="bi bi-eye"></i></button>
|
|
<button class="btn btn-outline-warning return-invoice-btn" data-id="<?= $inv['id'] ?>" data-bs-toggle="modal" data-bs-target="<?= $page === 'sales' ? '#addSalesReturnModal' : '#addPurchaseReturnModal' ?>" title="Return"><i class="bi bi-arrow-return-left"></i></button>
|
|
<button class="btn btn-outline-primary edit-invoice-btn" data-json="<?= htmlspecialchars(json_encode($inv)) ?>" data-bs-toggle="modal" data-bs-target="#editInvoiceModal" title="Edit"><i class="bi bi-pencil"></i></button>
|
|
<?php if ($inv['status'] !== 'paid'): ?>
|
|
<button class="btn btn-outline-success pay-invoice-btn" data-id="<?= $inv['id'] ?>" data-total="<?= $inv['total_with_vat'] ?>" data-paid="<?= $inv['paid_amount'] ?>" data-bs-toggle="modal" data-bs-target="#payInvoiceModal" title="Payment"><i class="bi bi-cash-coin"></i></button>
|
|
<?php endif; ?>
|
|
<button class="btn btn-outline-secondary print-a4-btn" data-json="<?= htmlspecialchars(json_encode($inv)) ?>" title="Print A4 Invoice"><i class="bi bi-printer"></i></button>
|
|
<form method="POST" class="d-inline" onsubmit="return confirm('Are you sure you want to delete this invoice?')">
|
|
<input type="hidden" name="id" value="<?= $inv['id'] ?>">
|
|
<button type="submit" name="delete_invoice" class="btn btn-outline-danger" title="Delete"><i class="bi bi-trash"></i></button>
|
|
</form>
|
|
</div>
|
|
</td>
|
|
</tr>
|
|
<?php endforeach; ?>
|
|
<?php if (empty($data['invoices'])): ?>
|
|
<tr>
|
|
<td colspan="9" class="text-center py-4 text-muted" data-en="No invoices found" data-ar="لا توجد فواتير">No invoices found</td>
|
|
</tr>
|
|
<?php endif; ?>
|
|
</tbody>
|
|
<tfoot>
|
|
<tr class="fw-bold bg-light">
|
|
<td colspan="5" class="text-end" data-en="Totals" data-ar="الإجمالي">Totals</td>
|
|
<td class="text-end">OMR <?= number_format((float)$total_all, 3) ?></td>
|
|
<td class="text-end text-success">OMR <?= number_format((float)$total_paid, 3) ?></td>
|
|
<td class="text-end text-danger">OMR <?= number_format((float)$total_balance, 3) ?></td>
|
|
<td class="d-print-none"></td>
|
|
</tr>
|
|
</tfoot>
|
|
</table>
|
|
</div>
|
|
<?= renderPagination($data['current_page'] ?? 1, $data['total_pages'] ?? 1) ?>
|
|
|
|
|
|
</div>
|