39038-vm/admin_reports_summary.php
2026-03-14 13:13:28 +00:00

287 lines
12 KiB
PHP

<?php
declare(strict_types=1);
require_once __DIR__ . '/includes/layout.php'; require_role('admin');
// Helper to validate date
function validate_date($date, $format = 'Y-m-d') {
$d = DateTime::createFromFormat($format, $date);
return $d && $d->format($format) === $date;
}
// Params
$reportType = $_GET['type'] ?? 'countries_origin'; // countries_origin, countries_dest, cities_origin, cities_dest, shippers
$startDate = $_GET['start_date'] ?? date('Y-m-01'); // Default to first day of current month
$endDate = $_GET['end_date'] ?? date('Y-m-t'); // Default to last day of current month
$export = $_GET['export'] ?? null;
if (!validate_date($startDate)) $startDate = date('Y-m-01');
if (!validate_date($endDate)) $endDate = date('Y-m-t');
// Build Query
$where = "s.payment_status = 'paid' AND DATE(s.created_at) BETWEEN ? AND ?";
$params = [$startDate, $endDate];
$groupBy = '';
$selectName = '';
$join = '';
$orderBy = 'total_amount DESC';
$pageTitle = t('shipments_by_origin_country');
switch ($reportType) {
case 'countries_origin':
$selectName = "COALESCE(co.name_en, 'Unknown') as name";
$join = "LEFT JOIN cities c ON s.origin_city = c.name_en
LEFT JOIN countries co ON c.country_id = co.id";
$groupBy = "co.name_en";
$pageTitle = t('shipments_by_origin_country');
break;
case 'countries_dest':
$selectName = "COALESCE(co.name_en, 'Unknown') as name";
$join = "LEFT JOIN cities c ON s.destination_city = c.name_en
LEFT JOIN countries co ON c.country_id = co.id";
$groupBy = "co.name_en";
$pageTitle = t('shipments_by_dest_country');
break;
case 'cities_origin':
$selectName = "s.origin_city as name";
$groupBy = "s.origin_city";
$pageTitle = t('shipments_by_origin_city');
break;
case 'cities_dest':
$selectName = "s.destination_city as name";
$groupBy = "s.destination_city";
$pageTitle = t('shipments_by_dest_city');
break;
case 'shippers':
$selectName = "s.shipper_name as name"; // simplified, could join users table
$groupBy = "s.shipper_name";
$pageTitle = t('shipments_by_shipper');
break;
default:
$reportType = 'countries_origin';
$selectName = "COALESCE(co.name_en, 'Unknown') as name";
$join = "LEFT JOIN cities c ON s.origin_city = c.name_en
LEFT JOIN countries co ON c.country_id = co.id";
$groupBy = "co.name_en";
$pageTitle = t('shipments_by_origin_country');
break;
}
$sql = "
SELECT
$selectName,
COUNT(s.id) as shipment_count,
SUM(s.total_price) as total_amount,
SUM(s.platform_fee) as total_profit
FROM shipments s
$join
WHERE $where
GROUP BY $groupBy
ORDER BY $orderBy
";
try {
$stmt = db()->prepare($sql);
$stmt->execute($params);
$results = $stmt->fetchAll();
} catch (PDOException $e) {
$results = [];
$error = "Database error: " . $e->getMessage();
}
// Calculate totals
$totalShipments = 0;
$grandTotalAmount = 0.0;
$grandTotalProfit = 0.0;
foreach ($results as $row) {
$totalShipments += $row['shipment_count'];
$grandTotalAmount += $row['total_amount'];
$grandTotalProfit += $row['total_profit'];
}
// Handle CSV Export
if ($export === 'csv') {
header('Content-Type: text/csv');
header('Content-Disposition: attachment; filename="report_' . $reportType . '_' . date('Ymd') . '.csv"');
$out = fopen('php://output', 'w');
// Header
fputcsv($out, ['Name', 'Shipments', 'Total Amount', 'Profit']);
// Rows
foreach ($results as $row) {
fputcsv($out, [
$row['name'],
$row['shipment_count'],
number_format((float)$row['total_amount'], 2, '.', ''),
number_format((float)$row['total_profit'], 2, '.', '')
]);
}
// Footer
fputcsv($out, ['Total', $totalShipments, number_format($grandTotalAmount, 2, '.', ''), number_format($grandTotalProfit, 2, '.', '')]);
fclose($out);
exit;
}
render_header(t('summary_report'), 'reports_summary', true);
?>
<div class="row g-0">
<div class="col-md-2 bg-white border-end min-vh-100 d-print-none">
<?php render_admin_sidebar('reports_summary'); ?>
</div>
<div class="col-md-10 p-4">
<!-- Print Header -->
<div class="d-none d-print-block mb-4">
<div class="row align-items-center mb-4">
<div class="col-6">
<?php
$logoPath = get_setting('logo_path');
if ($logoPath): ?>
<img src="<?= e($logoPath) ?>" alt="Company Logo" style="max-height: 80px; width: auto;">
<?php else: ?>
<h2 class="fw-bold mb-0 text-dark"><?= e(get_setting('company_name', 'CargoLink')) ?></h2>
<?php endif; ?>
</div>
<div class="col-6 text-end">
<h3 class="mb-1 text-dark fw-bold"><?= e(t('summary_report')) ?></h3>
<p class="mb-0 text-muted small">
<?= e(get_setting('company_address')) ?><br>
<?= e(get_setting('company_email')) ?> | <?= e(get_setting('company_phone')) ?>
</p>
<p class="mb-0 text-muted small mt-2">
<?= e(t('generated')) ?>: <?= date('d M Y, H:i') ?>
</p>
</div>
</div>
<div class="row mb-4">
<div class="col-12">
<div class="border p-3 rounded bg-light">
<div class="row">
<div class="col-6">
<strong class="text-muted d-block small text-uppercase"><?= e(t('report_type')) ?></strong>
<span class="fs-5 fw-bold text-dark"><?= e($pageTitle) ?></span>
</div>
<div class="col-6 text-end">
<strong class="text-muted d-block small text-uppercase"><?= e(t('period')) ?></strong>
<span class="fs-5 fw-bold text-dark"><?= e($startDate) ?> &mdash; <?= e($endDate) ?></span>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="d-flex justify-content-between align-items-center mb-4 d-print-none">
<div>
<h1 class="section-title mb-1"><?= e(t('summary_report')) ?></h1>
<p class="muted mb-0"><?= e(t('analyze_performance')) ?></p>
</div>
<div>
<a href="?type=<?= e($reportType) ?>&start_date=<?= e($startDate) ?>&end_date=<?= e($endDate) ?>&export=csv" class="btn btn-outline-primary btn-sm me-2">
<i class="bi bi-download me-2"></i><?= e(t('export_csv')) ?>
</a>
<button class="btn btn-outline-secondary btn-sm" onclick="window.print()">
<i class="bi bi-printer me-2"></i><?= e(t('print')) ?>
</button>
</div>
</div>
<div class="panel p-4 mb-4 d-print-none">
<form method="get" class="row g-3 align-items-end">
<div class="col-md-3">
<label class="form-label small text-muted"><?= e(t('report_type')) ?></label>
<select name="type" class="form-select" onchange="this.form.submit()">
<option value="countries_origin" <?= $reportType === 'countries_origin' ? 'selected' : '' ?>><?= e(t('shipments_by_origin_country')) ?></option>
<option value="countries_dest" <?= $reportType === 'countries_dest' ? 'selected' : '' ?>><?= e(t('shipments_by_dest_country')) ?></option>
<option value="cities_origin" <?= $reportType === 'cities_origin' ? 'selected' : '' ?>><?= e(t('shipments_by_origin_city')) ?></option>
<option value="cities_dest" <?= $reportType === 'cities_dest' ? 'selected' : '' ?>><?= e(t('shipments_by_dest_city')) ?></option>
<option value="shippers" <?= $reportType === 'shippers' ? 'selected' : '' ?>><?= e(t('shipments_by_shipper')) ?></option>
</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('apply_filter')) ?></button>
</div>
</form>
</div>
<div class="panel p-0 print-no-shadow">
<div class="p-3 border-bottom bg-light d-flex justify-content-between align-items-center d-print-none">
<h5 class="mb-0 fw-bold"><?= e($pageTitle) ?></h5>
<span class="badge bg-secondary"><?= e($startDate) ?> to <?= e($endDate) ?></span>
</div>
<?php if (empty($results)): ?>
<div class="p-5 text-center text-muted">
<i class="bi bi-bar-chart fs-1 mb-3 d-block"></i>
<p class="mb-0"><?= e(t('no_paid_shipments')) ?></p>
</div>
<?php else: ?>
<div class="table-responsive">
<table class="table table-hover mb-0 align-middle">
<thead>
<tr>
<th class="ps-4"><?= e(t('name')) ?></th>
<th class="text-center"><?= e(t('stats_shipments')) ?></th>
<th class="text-end"><?= e(t('total_amount')) ?></th>
<th class="text-end pe-4"><?= e(t('profit')) ?></th>
</tr>
</thead>
<tbody>
<?php foreach ($results as $row): ?>
<tr>
<td class="ps-4 fw-medium"><?= e($row['name']) ?></td>
<td class="text-center"><?= number_format((int)$row['shipment_count']) ?></td>
<td class="text-end text-dark"><?= format_currency((float)$row['total_amount']) ?></td>
<td class="text-end pe-4 text-success fw-bold"><?= format_currency((float)$row['total_profit']) ?></td>
</tr>
<?php endforeach; ?>
</tbody>
<tfoot class="table-light fw-bold border-top">
<tr>
<td class="ps-4"><?= e(t('total_label')) ?></td>
<td class="text-center"><?= number_format($totalShipments) ?></td>
<td class="text-end"><?= format_currency($grandTotalAmount) ?></td>
<td class="text-end pe-4 text-success"><?= format_currency($grandTotalProfit) ?></td>
</tr>
</tfoot>
</table>
</div>
<?php endif; ?>
<!-- Print Footer -->
<div class="d-none d-print-block print-footer border-top pt-2">
<div class="row text-muted small">
<div class="col-6">
<?= e(t('printed_by')) ?>: <?= e($_SESSION['user_name'] ?? 'Admin') ?>
</div>
<div class="col-6 text-end">
<?= e(t('generated')) ?>: <?= date('d M Y H:i') ?>
</div>
</div>
</div>
</div>
</div>
</div>
<?php render_footer(); ?>