Files
api-btekno/src/Modules/Retribusi/Summary/DailySummaryService.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();
}
}