158 lines
4.4 KiB
PHP
158 lines
4.4 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Modules\Retribusi\Summary;
|
|
|
|
use PDO;
|
|
use PDOException;
|
|
|
|
class DailySummaryService
|
|
{
|
|
private PDO $db;
|
|
|
|
public function __construct(PDO $db)
|
|
{
|
|
$this->db = $db;
|
|
}
|
|
|
|
/**
|
|
* Aggregate daily summary for a specific date
|
|
*
|
|
* @param string $date Format: Y-m-d
|
|
* @return array ['rows_processed' => int, 'date' => string]
|
|
* @throws PDOException
|
|
*/
|
|
public function aggregateForDate(string $date): array
|
|
{
|
|
// Validate date format
|
|
$dateTime = \DateTime::createFromFormat('Y-m-d', $date);
|
|
if ($dateTime === false || $dateTime->format('Y-m-d') !== $date) {
|
|
throw new \InvalidArgumentException('Invalid date format. Expected Y-m-d');
|
|
}
|
|
|
|
$this->db->beginTransaction();
|
|
|
|
try {
|
|
// Aggregate from entry_events
|
|
// Only count events from active locations, gates, and tariffs
|
|
$sql = "
|
|
SELECT
|
|
DATE(e.event_time) as summary_date,
|
|
e.location_code,
|
|
e.gate_code,
|
|
e.category,
|
|
COUNT(*) as total_count,
|
|
COALESCE(t.amount, 0) as tariff_amount
|
|
FROM entry_events e
|
|
INNER JOIN locations l ON e.location_code = l.code AND l.is_active = 1
|
|
INNER JOIN gates g ON e.location_code = g.location_code
|
|
AND e.gate_code = g.gate_code
|
|
AND g.is_active = 1
|
|
LEFT JOIN tariffs t ON e.location_code = t.location_code
|
|
AND e.gate_code = t.gate_code
|
|
AND e.category = t.category
|
|
WHERE DATE(e.event_time) = ?
|
|
GROUP BY
|
|
DATE(e.event_time),
|
|
e.location_code,
|
|
e.gate_code,
|
|
e.category,
|
|
COALESCE(t.amount, 0)
|
|
";
|
|
|
|
$stmt = $this->db->prepare($sql);
|
|
$stmt->execute([$date]);
|
|
$aggregated = $stmt->fetchAll();
|
|
|
|
$rowsProcessed = 0;
|
|
|
|
// Upsert to daily_summary
|
|
$upsertSql = "
|
|
INSERT INTO daily_summary
|
|
(summary_date, location_code, gate_code, category, total_count, total_amount, created_at, updated_at)
|
|
VALUES (?, ?, ?, ?, ?, ?, NOW(), NOW())
|
|
ON DUPLICATE KEY UPDATE
|
|
total_count = VALUES(total_count),
|
|
total_amount = VALUES(total_amount),
|
|
updated_at = NOW()
|
|
";
|
|
|
|
$upsertStmt = $this->db->prepare($upsertSql);
|
|
|
|
foreach ($aggregated as $row) {
|
|
$totalAmount = (int) $row['total_count'] * (int) $row['tariff_amount'];
|
|
|
|
$upsertStmt->execute([
|
|
$row['summary_date'],
|
|
$row['location_code'],
|
|
$row['gate_code'],
|
|
$row['category'],
|
|
(int) $row['total_count'],
|
|
$totalAmount
|
|
]);
|
|
|
|
$rowsProcessed++;
|
|
}
|
|
|
|
$this->db->commit();
|
|
|
|
return [
|
|
'rows_processed' => $rowsProcessed,
|
|
'date' => $date
|
|
];
|
|
|
|
} catch (PDOException $e) {
|
|
$this->db->rollBack();
|
|
throw $e;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get daily summary data
|
|
*
|
|
* @param string $date
|
|
* @param string|null $locationCode
|
|
* @param string|null $gateCode
|
|
* @return array
|
|
* @throws PDOException
|
|
*/
|
|
public function getDailySummary(
|
|
string $date,
|
|
?string $locationCode = null,
|
|
?string $gateCode = null
|
|
): array {
|
|
$sql = "
|
|
SELECT
|
|
summary_date,
|
|
location_code,
|
|
gate_code,
|
|
category,
|
|
total_count,
|
|
total_amount
|
|
FROM daily_summary
|
|
WHERE summary_date = ?
|
|
";
|
|
|
|
$params = [$date];
|
|
|
|
if ($locationCode !== null) {
|
|
$sql .= " AND location_code = ?";
|
|
$params[] = $locationCode;
|
|
}
|
|
|
|
if ($gateCode !== null) {
|
|
$sql .= " AND gate_code = ?";
|
|
$params[] = $gateCode;
|
|
}
|
|
|
|
$sql .= " ORDER BY location_code, gate_code, category";
|
|
|
|
$stmt = $this->db->prepare($sql);
|
|
$stmt->execute($params);
|
|
|
|
return $stmt->fetchAll();
|
|
}
|
|
}
|
|
|