38929-vm/customer_statement.php
2026-03-03 10:35:21 +00:00

346 lines
14 KiB
PHP

<?php
$title = 'customer_statement';
require_once __DIR__ . '/includes/header.php';
$customer_id = $_GET['id'] ?? null;
if (!$customer_id) {
header('Location: customers.php');
exit;
}
// Fetch customer details
$stmt = db()->prepare("SELECT * FROM customers WHERE id = ?");
$stmt->execute([$customer_id]);
$customer = $stmt->fetch();
if (!$customer) {
header('Location: customers.php');
exit;
}
$from_date = $_GET['from_date'] ?? '';
$to_date = $_GET['to_date'] ?? '';
// Base queries
$orders_sql = "SELECT id, order_number, total_price, created_at FROM orders WHERE customer_id = ?";
$payments_sql = "SELECT p.id, p.amount, p.payment_method, p.created_at, o.order_number
FROM payments p
JOIN orders o ON p.order_id = o.id
WHERE o.customer_id = ?";
$params = [$customer_id];
if ($from_date) {
$orders_sql .= " AND DATE(created_at) >= ?";
$payments_sql .= " AND DATE(p.created_at) >= ?";
$params[] = $from_date;
}
if ($to_date) {
$orders_sql .= " AND DATE(created_at) <= ?";
$payments_sql .= " AND DATE(p.created_at) <= ?";
$params[] = $to_date;
}
$stmt_orders = db()->prepare($orders_sql);
// We need to be careful with params if both filters are set
$orders_params = [$customer_id];
if ($from_date) $orders_params[] = $from_date;
if ($to_date) $orders_params[] = $to_date;
$stmt_orders->execute($orders_params);
$orders = $stmt_orders->fetchAll();
$stmt_payments = db()->prepare($payments_sql);
$payments_params = [$customer_id];
if ($from_date) $payments_params[] = $from_date;
if ($to_date) $payments_params[] = $to_date;
$stmt_payments->execute($payments_params);
$payments = $stmt_payments->fetchAll();
// Combine and sort
$transactions = [];
foreach ($orders as $o) {
$transactions[] = [
'date' => $o['created_at'],
'type' => 'order',
'ref' => $o['order_number'],
'debit' => $o['total_price'],
'credit' => 0,
'description' => __('order') . ' #' . $o['order_number']
];
}
foreach ($payments as $p) {
$transactions[] = [
'date' => $p['created_at'],
'type' => 'payment',
'ref' => $p['order_number'],
'debit' => 0,
'credit' => $p['amount'],
'description' => __('payment') . ' (' . __($p['payment_method']) . ') - ' . __('order') . ' #' . $p['order_number']
];
}
usort($transactions, function($a, $b) {
return strtotime($a['date']) - strtotime($b['date']);
});
$total_debit = 0;
$total_credit = 0;
$balance = 0;
foreach ($transactions as &$t) {
$total_debit += $t['debit'];
$total_credit += $t['credit'];
$balance += ($t['debit'] - $t['credit']);
$t['running_balance'] = $balance;
}
// Fallback values if database is empty
$display_company_name = ($lang === 'ar' ? ($company_info['name_ar'] ?: $company_info['name_en']) : $company_info['name_en']) ?: 'Laundry Brand';
$display_address = ($lang === 'ar' ? ($company_info['address_ar'] ?: $company_info['address_en']) : $company_info['address_en']);
$display_phone = $company_info['phone'];
$display_email = $company_info['email'];
$display_vat = $company_info['vat_no'] ?: $company_info['vat_number'];
$display_ctr = $company_info['ctr_no'];
?>
<div class="d-print-none mb-4">
<nav aria-label="breadcrumb">
<ol class="breadcrumb">
<li class="breadcrumb-item"><a href="customers.php"><?= __('customers') ?></a></li>
<li class="breadcrumb-item active"><?= __('customer_statement') ?></li>
</ol>
</nav>
</div>
<div class="card p-4 border-0 shadow-sm mb-4 d-print-none" style="border-radius: 20px;">
<form action="" method="GET" class="row g-3 align-items-end">
<input type="hidden" name="id" value="<?= $customer_id ?>">
<div class="col-md-4">
<label class="form-label small fw-bold"><?= __('from_date') ?></label>
<input type="date" name="from_date" class="form-control" value="<?= $from_date ?>" style="border-radius: 12px;">
</div>
<div class="col-md-4">
<label class="form-label small fw-bold"><?= __('to_date') ?></label>
<input type="date" name="to_date" class="form-control" value="<?= $to_date ?>" style="border-radius: 12px;">
</div>
<div class="col-md-4 d-flex gap-2">
<button type="submit" class="btn btn-primary px-4 w-100" style="border-radius: 12px;">
<i class="bi bi-filter me-1"></i> <?= __('filter') ?? 'Filter' ?>
</button>
<button type="button" class="btn btn-outline-dark px-4 w-100" style="border-radius: 12px;" onclick="window.print()">
<i class="bi bi-printer me-1"></i> <?= __('print') ?>
</button>
</div>
</form>
</div>
<div id="printableStatement" class="card p-5 border-0 shadow-sm" style="border-radius: 20px;">
<!-- Formal Header for Printing -->
<div class="d-none d-print-block mb-5">
<div class="row align-items-center mb-4">
<div class="col-7">
<?php if (!empty($company_info['logo'])): ?>
<img src="<?= $company_info['logo'] ?>" alt="Logo" style="max-height: 100px;" class="mb-3">
<?php else: ?>
<div class="mb-3 d-flex align-items-center text-primary">
<i class="bi bi-tsunami fs-1 me-2"></i>
<span class="fs-4 fw-bold">Laundry Management</span>
</div>
<?php endif; ?>
<h2 class="fw-bold mb-1"><?= htmlspecialchars($display_company_name) ?></h2>
<div class="mb-0 text-muted small">
<?php if ($display_address): ?>
<?= htmlspecialchars($display_address) ?><br>
<?php endif; ?>
<?php if ($display_phone): ?>
<?= __('phone') ?>: <?= htmlspecialchars($display_phone) ?>
<?php endif; ?>
<?php if ($display_email): ?>
<?= $display_phone ? ' | ' : '' ?><?= __('email') ?>: <?= htmlspecialchars($display_email) ?><br>
<?php elseif($display_phone): ?>
<br>
<?php endif; ?>
<?php if ($display_vat): ?>
<?= __('vat_no') ?>: <?= htmlspecialchars($display_vat) ?>
<?php endif; ?>
<?php if ($display_ctr): ?>
<?= $display_vat ? ' | ' : '' ?><?= __('ctr_no') ?>: <?= htmlspecialchars($display_ctr) ?>
<?php endif; ?>
</div>
</div>
<div class="col-5 text-end">
<h1 class="fw-bold text-uppercase mb-2" style="color: #0d6efd;"><?= __('statement') ?></h1>
<div class="mt-3">
<p class="mb-0 fw-bold"><?= __('date') ?>: <?= date('d/m/Y') ?></p>
<p class="mb-0 text-muted small"><?= __('cashier') ?>: <?= htmlspecialchars($_SESSION['full_name'] ?? 'System Admin') ?></p>
<?php if ($from_date || $to_date): ?>
<p class="mb-0 text-muted small mt-1">
<?= $from_date ? __('from_date') . ': ' . date('d/m/Y', strtotime($from_date)) : '' ?>
<?= $to_date ? ' ' . __('to_date') . ': ' . date('d/m/Y', strtotime($to_date)) : '' ?>
</p>
<?php endif; ?>
</div>
</div>
</div>
<div class="row p-3 bg-light rounded-3 mb-4 mx-0 border">
<div class="col-12">
<h6 class="fw-bold text-muted text-uppercase mb-2 small"><?= __('customer_details') ?></h6>
<h4 class="fw-bold mb-1"><?= $lang === 'ar' ? ($customer['name_ar'] ?: $customer['name_en']) : $customer['name_en'] ?></h4>
<p class="mb-0 text-muted small"><?= $customer['phone'] ?> <?= $customer['email'] ? ' | ' . $customer['email'] : '' ?></p>
</div>
</div>
</div>
<!-- Screen Header -->
<div class="d-print-none mb-4">
<h4 class="fw-bold mb-1"><?= $lang === 'ar' ? ($customer['name_ar'] ?: $customer['name_en']) : $customer['name_en'] ?></h4>
<p class="text-muted mb-0"><?= $customer['phone'] ?> <?= $customer['email'] ? ' | ' . $customer['email'] : '' ?></p>
</div>
<div class="table-responsive">
<table class="table table-striped align-middle mt-4">
<thead class="table-dark">
<tr>
<th><?= __('date') ?></th>
<th><?= __('description') ?></th>
<th class="text-center"><?= __('ref') ?? 'Ref' ?></th>
<th class="text-end"><?= __('debit') ?></th>
<th class="text-end"><?= __('credit') ?></th>
<th class="text-end"><?= __('balance') ?></th>
</tr>
</thead>
<tbody>
<?php if (empty($transactions)): ?>
<tr>
<td colspan="6" class="text-center py-5 text-muted">
<?= __('no_transactions_found') ?? 'No transactions found' ?>
</td>
</tr>
<?php else: ?>
<?php foreach ($transactions as $t): ?>
<tr>
<td class="small"><?= date('d/m/Y H:i', strtotime($t['date'])) ?></td>
<td><?= $t['description'] ?></td>
<td class="text-center"><span class="badge bg-light text-dark border"><?= $t['ref'] ?></span></td>
<td class="text-end"><?= $t['debit'] > 0 ? format_amount($t['debit']) : '-' ?></td>
<td class="text-end"><?= $t['credit'] > 0 ? format_amount($t['credit']) : '-' ?></td>
<td class="text-end fw-bold"><?= format_amount($t['running_balance']) ?></td>
</tr>
<?php endforeach; ?>
<?php endif; ?>
</tbody>
<tfoot class="table-light fw-bold border-top">
<tr>
<td colspan="3" class="text-end"><?= __('total') ?></td>
<td class="text-end"><?= format_amount($total_debit) ?></td>
<td class="text-end"><?= format_amount($total_credit) ?></td>
<td class="text-end text-primary"><?= format_amount($balance) ?></td>
</tr>
</tfoot>
</table>
</div>
<div class="row mt-5">
<div class="col-md-5 ms-auto">
<div class="card bg-white border" style="border-radius: 15px;">
<div class="card-body p-4">
<h5 class="fw-bold mb-4 border-bottom pb-2 small text-uppercase text-muted"><?= __('summary') ?? 'Summary' ?></h5>
<div class="d-flex justify-content-between mb-2">
<span class="text-muted small"><?= __('total_debit') ?>:</span>
<span class="fw-bold small"><?= format_amount($total_debit) ?></span>
</div>
<div class="d-flex justify-content-between mb-2">
<span class="text-muted small"><?= __('total_credit') ?>:</span>
<span class="fw-bold small"><?= format_amount($total_credit) ?></span>
</div>
<div class="d-flex justify-content-between pt-2 mt-2 border-top">
<span class="fw-bold fs-6"><?= __('closing_balance') ?>:</span>
<span class="fw-bold text-primary fs-6"><?= format_amount($balance) ?></span>
</div>
</div>
</div>
</div>
</div>
<!-- Print Footer -->
<div class="d-none d-print-block mt-5 pt-4 border-top">
<div class="row text-center small text-muted">
<div class="col-4">
<div class="mb-4">_______________________</div>
<div><?= __('customer_signature') ?? 'Customer Signature' ?></div>
</div>
<div class="col-4">
<div class="mb-4"><?= date('d/m/Y H:i') ?></div>
<div><?= __('print_date') ?? 'Print Date' ?></div>
</div>
<div class="col-4">
<div class="mb-4">_______________________</div>
<div><?= __('authorized_signature') ?? 'Authorized Signature' ?></div>
</div>
</div>
</div>
</div>
<style>
@media print {
@page {
size: auto;
margin: 10mm 15mm;
}
body {
background-color: white !important;
font-size: 11px;
-webkit-print-color-adjust: exact;
}
.main-content {
padding: 0 !important;
margin: 0 !important;
width: 100% !important;
max-width: 100% !important;
}
header, .sidebar, .d-print-none, .breadcrumb, nav {
display: none !important;
}
.container-fluid, .row, .col-lg-10 {
padding: 0 !important;
margin: 0 !important;
width: 100% !important;
max-width: 100% !important;
flex: 0 0 100% !important;
}
.card {
box-shadow: none !important;
border: none !important;
padding: 0 !important;
margin: 0 !important;
}
#printableStatement {
padding: 0 !important;
}
table {
width: 100% !important;
border-collapse: collapse !important;
}
th, td {
border: 1px solid #dee2e6 !important;
padding: 6px !important;
}
.badge {
border: none !important;
padding: 0 !important;
}
.bg-light {
background-color: #f8f9fa !important;
}
.table-dark {
background-color: #212529 !important;
color: white !important;
}
}
</style>
<?php require_once __DIR__ . '/includes/footer.php'; ?>