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(); } }