292 lines
14 KiB
PHP
292 lines
14 KiB
PHP
<?php
|
|
declare(strict_types=1);
|
|
|
|
require_once __DIR__ . '/includes/layout.php'; require_role('admin');
|
|
|
|
// Check permission
|
|
if (!has_permission('view_reports') && !has_permission('manage_shippers')) {
|
|
render_header(t('shippers_statements'), 'reports_shippers');
|
|
echo '<div class="container py-5"><div class="alert alert-danger">Access Denied. You do not have permission to view reports.</div></div>';
|
|
render_footer();
|
|
exit;
|
|
}
|
|
|
|
$shipperId = (int)($_GET['shipper_id'] ?? 0);
|
|
$startDate = $_GET['start_date'] ?? '';
|
|
$endDate = $_GET['end_date'] ?? '';
|
|
|
|
$shipper = null;
|
|
$shipments = [];
|
|
$totalAmount = 0.00;
|
|
|
|
// Fetch all shippers for the dropdown
|
|
$allShippers = db()->query("
|
|
SELECT u.id, u.full_name, p.company_name
|
|
FROM users u
|
|
LEFT JOIN shipper_profiles p ON u.id = p.user_id
|
|
WHERE u.role = 'shipper'
|
|
ORDER BY u.full_name ASC
|
|
")->fetchAll();
|
|
|
|
if ($shipperId) {
|
|
// Fetch selected shipper details
|
|
$stmt = db()->prepare("
|
|
SELECT u.id, u.full_name, u.email, p.company_name, p.phone, p.address_line,
|
|
c.name_en as country, ci.name_en as city
|
|
FROM users u
|
|
LEFT JOIN shipper_profiles p ON u.id = p.user_id
|
|
LEFT JOIN countries c ON p.country_id = c.id
|
|
LEFT JOIN cities ci ON p.city_id = ci.id
|
|
WHERE u.id = ? AND u.role = 'shipper'
|
|
");
|
|
$stmt->execute([$shipperId]);
|
|
$shipper = $stmt->fetch();
|
|
|
|
if ($shipper) {
|
|
// Build Query with Date Filter
|
|
$sql = "SELECT *
|
|
FROM shipments
|
|
WHERE shipper_id = ?
|
|
AND status IN ('confirmed', 'in_transit', 'delivered')";
|
|
$params = [$shipperId];
|
|
|
|
if (!empty($startDate)) {
|
|
$sql .= " AND created_at >= ?";
|
|
$params[] = $startDate . ' 00:00:00';
|
|
}
|
|
|
|
if (!empty($endDate)) {
|
|
$sql .= " AND created_at <= ?";
|
|
$params[] = $endDate . ' 23:59:59';
|
|
}
|
|
|
|
$sql .= " ORDER BY created_at DESC";
|
|
|
|
$stmt = db()->prepare($sql);
|
|
$stmt->execute($params);
|
|
$shipments = $stmt->fetchAll();
|
|
|
|
foreach ($shipments as $s) {
|
|
$totalAmount += (float)($s['total_price'] ?? 0);
|
|
}
|
|
}
|
|
}
|
|
|
|
render_header(t('shippers_statements'), 'reports_shippers', true);
|
|
?>
|
|
|
|
<!-- Select2 CSS -->
|
|
<link href="https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/css/select2.min.css" rel="stylesheet" />
|
|
|
|
<style>
|
|
/* Select2 Bootstrap 5 Fixes */
|
|
.select2-container .select2-selection--single { height: 38px !important; border: 1px solid #dee2e6 !important; padding: 5px 0; }
|
|
.select2-container--default .select2-selection--single .select2-selection__arrow { height: 36px !important; }
|
|
.select2-container--default .select2-selection--single .select2-selection__rendered { line-height: 26px !important; color: #212529; }
|
|
|
|
@media print {
|
|
@page { size: A4; margin: 1cm; }
|
|
body { background: white !important; font-family: 'Times New Roman', serif; -webkit-print-color-adjust: exact; }
|
|
.no-print, .admin-sidebar, nav, footer, .btn, form.filter-form { display: none !important; }
|
|
.col-md-2 { display: none !important; }
|
|
.col-md-10 { width: 100% !important; flex: 0 0 100% !important; max-width: 100% !important; padding: 0 !important; margin: 0 !important; }
|
|
.row { display: flex !important; flex-wrap: wrap !important; margin: 0 !important; }
|
|
.col-6 { width: 50% !important; flex: 0 0 50% !important; max-width: 50% !important; }
|
|
.panel { border: none !important; box-shadow: none !important; padding: 0 !important; }
|
|
|
|
/* Compact Header */
|
|
.print-header { display: flex !important; justify-content: space-between !important; align-items: flex-start !important; margin-bottom: 10px !important; border-bottom: 2px solid #000 !important; padding-bottom: 5px !important; }
|
|
.print-header-left { text-align: left; }
|
|
.print-header-right { text-align: right; }
|
|
.print-header h1 { font-size: 14pt; font-weight: bold; margin: 0; text-transform: uppercase; }
|
|
.print-header h2 { font-size: 12pt; margin: 0; font-weight: normal; }
|
|
.print-header p { margin: 0; font-size: 9pt; color: #555; }
|
|
|
|
/* Compact Info Section */
|
|
.statement-info { margin-bottom: 10px !important; display: flex !important; justify-content: space-between !important; border-bottom: 1px solid #ddd !important; padding-bottom: 5px !important; }
|
|
.statement-info h5 { margin: 0 0 2px 0; font-size: 9pt; color: #777; text-transform: uppercase; font-weight: bold; }
|
|
.statement-info h4 { margin: 0; font-size: 11pt; font-weight: bold; }
|
|
.statement-info .small { font-size: 9pt; margin-top: 2px; }
|
|
|
|
.table-responsive { overflow: visible !important; }
|
|
table { width: 100% !important; border-collapse: collapse !important; font-size: 9pt; }
|
|
th, td { border: 1px solid #ddd !important; padding: 4px 6px !important; text-align: left; }
|
|
th { background-color: #f8f9fa !important; font-weight: bold; text-transform: uppercase; color: #000 !important; font-size: 8pt; }
|
|
.text-end { text-align: right !important; }
|
|
.total-row td { background-color: #eee !important; font-weight: bold; font-size: 10pt; border-top: 2px solid #000 !important; }
|
|
.print-footer { display: block !important; margin-top: 20px; text-align: center; font-size: 8pt; color: #777; border-top: 1px solid #ddd; padding-top: 5px; }
|
|
|
|
/* Arabic Support */
|
|
[dir="rtl"] body { font-family: 'Traditional Arabic', serif; }
|
|
[dir="rtl"] th, [dir="rtl"] td { text-align: right; }
|
|
[dir="rtl"] .text-end { text-align: left !important; }
|
|
}
|
|
.print-header, .print-footer { display: none; }
|
|
</style>
|
|
|
|
<div class="row g-0">
|
|
<div class="col-md-2 bg-white border-end min-vh-100 no-print">
|
|
<?php render_admin_sidebar('reports_shippers'); ?>
|
|
</div>
|
|
<div class="col-md-10 p-4">
|
|
<!-- Screen Only Header -->
|
|
<div class="page-intro d-flex justify-content-between align-items-center mb-4 no-print">
|
|
<div>
|
|
<h1 class="section-title mb-1"><?= e(t('shippers_statements')) ?></h1>
|
|
<p class="muted mb-0"><?= e(t('view_print_statements')) ?></p>
|
|
</div>
|
|
<?php if ($shipper): ?>
|
|
<button onclick="window.print()" class="btn btn-dark">
|
|
<i class="bi bi-printer me-2"></i><?= e(t('print_formal_statement')) ?>
|
|
</button>
|
|
<?php endif; ?>
|
|
</div>
|
|
|
|
<!-- Filter Form -->
|
|
<div class="panel p-4 mb-4 no-print filter-form">
|
|
<form method="get" class="row g-3 align-items-end">
|
|
<div class="col-md-4">
|
|
<label class="form-label small text-muted"><?= e(t('select_shipper')) ?></label>
|
|
<select name="shipper_id" id="shipperSelect" class="form-select" onchange="this.form.submit()">
|
|
<option value=""><?= e(t('choose_shipper')) ?></option>
|
|
<?php foreach ($allShippers as $s): ?>
|
|
<option value="<?= $s['id'] ?>" <?= $shipperId == $s['id'] ? 'selected' : '' ?>>
|
|
<?= e($s['full_name']) ?> (<?= e($s['company_name'] ?: 'No Company') ?>)
|
|
</option>
|
|
<?php endforeach; ?>
|
|
</select>
|
|
</div>
|
|
<div class="col-md-3">
|
|
<label class="form-label small text-muted"><?= e(t('start_date')) ?></label>
|
|
<input type="date" name="start_date" class="form-control" value="<?= e($startDate) ?>">
|
|
</div>
|
|
<div class="col-md-3">
|
|
<label class="form-label small text-muted"><?= e(t('end_date')) ?></label>
|
|
<input type="date" name="end_date" class="form-control" value="<?= e($endDate) ?>">
|
|
</div>
|
|
<div class="col-md-2">
|
|
<button type="submit" class="btn btn-primary w-100"><?= e(t('filter')) ?></button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
|
|
<?php if ($shipperId && !$shipper): ?>
|
|
<div class="alert alert-warning"><?= e(t('shipper_not_found')) ?></div>
|
|
<?php elseif ($shipper): ?>
|
|
<div class="panel p-5 bg-white">
|
|
<!-- Print Header (Compact) -->
|
|
<div class="print-header">
|
|
<div class="print-header-left">
|
|
<h2 style="font-size: 14pt; margin: 0; font-weight: bold;"><?= e(get_setting('company_name', 'Logistics Platform')) ?></h2>
|
|
<p class="mt-1"><?= date('F j, Y') ?></p>
|
|
</div>
|
|
<div class="print-header-right">
|
|
<h1><?= e(t('statement_of_account')) ?></h1>
|
|
<h2 style="font-size: 12pt; margin: 0; font-weight: normal;">كشف حساب</h2>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Info Section (Compact) -->
|
|
<div class="statement-info row">
|
|
<div class="col-6">
|
|
<h5><?= e(t('billed_to')) ?> / إلى السيد</h5>
|
|
<h4><?= e($shipper['full_name']) ?></h4>
|
|
<div class="small text-muted">
|
|
<?= e($shipper['company_name'] ?: '-') ?><br>
|
|
<?= e($shipper['address_line'] ?: '') ?><br>
|
|
<?= e($shipper['city'] ?: '') ?>, <?= e($shipper['country'] ?: '') ?><br>
|
|
<?= e($shipper['phone'] ?: '') ?>
|
|
</div>
|
|
</div>
|
|
<div class="col-6 text-end">
|
|
<h5><?= e(t('summary')) ?> / ملخص</h5>
|
|
<div class="small">
|
|
<div><strong>Date:</strong> <?= date('Y-m-d') ?></div>
|
|
<?php if ($startDate || $endDate): ?>
|
|
<div><strong><?= e(t('period')) ?>:</strong> <?= e($startDate ?: 'Start') ?> to <?= e($endDate ?: 'Now') ?></div>
|
|
<?php else: ?>
|
|
<div><strong><?= e(t('period')) ?>:</strong> <?= e(t('all_time')) ?></div>
|
|
<?php endif; ?>
|
|
<div><strong><?= e(t('total_count')) ?>:</strong> <?= count($shipments) ?></div>
|
|
<div class="fs-5 fw-bold text-primary mt-1">
|
|
<?= format_currency($totalAmount) ?>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Table -->
|
|
<div class="table-responsive">
|
|
<table class="table table-bordered align-middle">
|
|
<thead>
|
|
<tr>
|
|
<th>Date <br> <span class="fw-normal text-muted">التاريخ</span></th>
|
|
<th>Ref # <br> <span class="fw-normal text-muted">رقم الشحنة</span></th>
|
|
<th><?= e(t('route')) ?> <br> <span class="fw-normal text-muted">المسار</span></th>
|
|
<th><?= e(t('status')) ?> <br> <span class="fw-normal text-muted">الحالة</span></th>
|
|
<th class="text-end"><?= e(t('amount')) ?> <br> <span class="fw-normal text-muted">المبلغ</span></th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<?php if (empty($shipments)): ?>
|
|
<tr><td colspan="5" class="text-center py-4 text-muted"><?= e(t('no_completed_shipments')) ?></td></tr>
|
|
<?php else: ?>
|
|
<?php foreach ($shipments as $row): ?>
|
|
<tr>
|
|
<td><?= date('Y-m-d', strtotime($row['created_at'])) ?></td>
|
|
<td><span class="font-monospace">#<?= $row['id'] ?></span></td>
|
|
<td>
|
|
<?= e($row['origin_city']) ?> <i class="bi bi-arrow-right small text-muted mx-1"></i> <?= e($row['destination_city']) ?>
|
|
<div class="small text-muted"><?= e($row['cargo_description']) ?></div>
|
|
</td>
|
|
<td>
|
|
<?= e(status_label($row['status'])) ?>
|
|
</td>
|
|
<td class="text-end fw-bold">
|
|
<?= format_currency((float)$row['total_price']) ?>
|
|
</td>
|
|
</tr>
|
|
<?php endforeach; ?>
|
|
<?php endif; ?>
|
|
</tbody>
|
|
<tfoot>
|
|
<tr class="total-row table-active">
|
|
<td colspan="4" class="text-end text-uppercase"><?= e(t('total_balance')) ?> / الإجمالي</td>
|
|
<td class="text-end text-dark"><?= format_currency($totalAmount) ?></td>
|
|
</tr>
|
|
</tfoot>
|
|
</table>
|
|
</div>
|
|
|
|
<!-- Print Footer -->
|
|
<div class="print-footer">
|
|
<div class="row">
|
|
<div class="col-6 text-start">
|
|
<?= e(t('authorized_signature')) ?><br>
|
|
_______________________
|
|
</div>
|
|
<div class="col-6 text-end">
|
|
<?= e(t('printed_on')) ?> <?= date('Y-m-d H:i') ?><br>
|
|
<?= e(t('generated_doc')) ?>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<?php endif; ?>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- jQuery and Select2 JS -->
|
|
<script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
|
|
<script src="https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/js/select2.min.js"></script>
|
|
<script>
|
|
$(document).ready(function() {
|
|
$('#shipperSelect').select2({
|
|
width: '100%',
|
|
placeholder: '<?= e(t('choose_shipper')) ?>',
|
|
allowClear: true
|
|
});
|
|
});
|
|
</script>
|
|
|
|
<?php render_footer(); ?>
|