Files
api-btekno/UPSERT_BEHAVIOR.md

187 lines
4.4 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Penjelasan Behavior Upsert di Hourly Summary
## Jawaban Singkat
**Data DIGANTI (REPLACE), bukan ditambah.**
## Detail Penjelasan
### Query Upsert yang Digunakan
```sql
INSERT INTO hourly_summary
(summary_date, summary_hour, location_code, gate_code, category, total_count, total_amount)
VALUES (?, ?, ?, ?, ?, ?, ?)
ON DUPLICATE KEY UPDATE
total_count = VALUES(total_count),
total_amount = VALUES(total_amount)
```
### Primary Key
```sql
PRIMARY KEY (summary_date, summary_hour, location_code, gate_code, category)
```
### Behavior: ON DUPLICATE KEY UPDATE
**Jika row BELUM ADA:**
-**INSERT** → Tambah row baru
**Jika row SUDAH ADA:**
-**UPDATE** → Ganti `total_count` dan `total_amount` dengan nilai baru
-**BUKAN** tambah ke nilai lama
## Contoh Skenario
### Skenario 1: Cron Pertama Kali (Row Belum Ada)
**Jam 2:00, cron jalan untuk update jam 1:00:**
```
1. Query entry_events untuk jam 1:00:
- location_code: kerkof_01
- gate_code: gate01
- category: motor
- COUNT: 10 events
- total_amount: 10 × 2000 = 20000
2. INSERT ke hourly_summary:
✅ Row baru dibuat:
summary_date: 2025-12-17
summary_hour: 1
location_code: kerkof_01
gate_code: gate01
category: motor
total_count: 10
total_amount: 20000
```
### Skenario 2: Cron Kedua Kali (Row Sudah Ada)
**Jam 2:30, ada event baru masuk (terlambat):**
- Event jam 1:00 masuk di jam 2:30 (terlambat)
**Jam 3:00, cron jalan lagi untuk update jam 1:00:**
```
1. Query entry_events untuk jam 1:00 (SEKARANG):
- location_code: kerkof_01
- gate_code: gate01
- category: motor
- COUNT: 11 events (termasuk yang terlambat)
- total_amount: 11 × 2000 = 22000
2. ON DUPLICATE KEY UPDATE:
✅ Row LAMA diganti:
- total_count: 10 → 11 (DIGANTI, bukan 10 + 11 = 21)
- total_amount: 20000 → 22000 (DIGANTI, bukan 20000 + 22000 = 42000)
```
## Mengapa Diganti, Bukan Ditambah?
### 1. **Akurasi Data**
- Summary harus selalu mencerminkan data aktual di `entry_events`
- Jika ditambah, data akan double-count jika cron jalan berulang
### 2. **Idempotent**
- Cron bisa jalan berulang tanpa merusak data
- Hasil selalu sama, tidak peduli berapa kali dijalankan
### 3. **Event Terlambat**
- Jika ada event yang masuk terlambat, akan otomatis terhitung saat rekap ulang
- Tidak perlu manual correction
## Contoh Timeline Lengkap
### Hari: 2025-12-17
**Jam 1:00 - 1:59:**
```
Event masuk ke entry_events:
- 1:05 → motor (kerkof_01, gate01)
- 1:15 → motor (kerkof_01, gate01)
- 1:30 → motor (kerkof_01, gate01)
Total: 3 events
```
**Jam 2:00 - Cron jalan:**
```
1. Query entry_events untuk jam 1:00:
→ COUNT: 3 events
→ total_amount: 3 × 2000 = 6000
2. INSERT ke hourly_summary:
✅ Row baru: total_count = 3, total_amount = 6000
```
**Jam 2:30 - Event terlambat masuk:**
```
Event masuk ke entry_events (terlambat):
- 2:30 → motor (kerkof_01, gate01) dengan event_time = 1:45
Total sekarang: 4 events untuk jam 1:00
```
**Jam 3:00 - Cron jalan lagi (opsional, jika rekap ulang):**
```
1. Query entry_events untuk jam 1:00 (SEKARANG):
→ COUNT: 4 events (termasuk yang terlambat)
→ total_amount: 4 × 2000 = 8000
2. ON DUPLICATE KEY UPDATE:
✅ Row LAMA diganti:
- total_count: 3 → 4 (DIGANTI)
- total_amount: 6000 → 8000 (DIGANTI)
```
## Verifikasi di Database
### Cek Data Sebelum Cron:
```sql
SELECT * FROM hourly_summary
WHERE summary_date = '2025-12-17'
AND summary_hour = 1
AND location_code = 'kerkof_01'
AND gate_code = 'gate01'
AND category = 'motor';
-- Hasil:
-- total_count: 3
-- total_amount: 6000
```
### Jalankan Cron:
```bash
php bin/hourly_summary.php today 1
```
### Cek Data Setelah Cron:
```sql
SELECT * FROM hourly_summary
WHERE summary_date = '2025-12-17'
AND summary_hour = 1
AND location_code = 'kerkof_01'
AND gate_code = 'gate01'
AND category = 'motor';
-- Hasil (jika ada event baru):
-- total_count: 4 (DIGANTI dari 3, bukan 3 + 4 = 7)
-- total_amount: 8000 (DIGANTI dari 6000, bukan 6000 + 8000 = 14000)
```
## Kesimpulan
| Aspek | Behavior |
|-------|----------|
| **Jika row belum ada** | ✅ INSERT (tambah baru) |
| **Jika row sudah ada** | ✅ UPDATE (ganti nilai) |
| **Apakah ditambah?** | ❌ TIDAK, diganti |
| **Apakah diganti?** | ✅ YA, diganti dengan nilai baru |
| **Nilai lama** | ❌ Tidak dipertahankan, diganti dengan hasil rekap ulang |
**Intinya:** Data selalu di-rekap ulang dari `entry_events`, bukan ditambah ke nilai lama. Ini memastikan akurasi dan konsistensi data summary.