diff --git a/TROUBLESHOOTING.md b/TROUBLESHOOTING.md new file mode 100644 index 0000000..0d3b410 --- /dev/null +++ b/TROUBLESHOOTING.md @@ -0,0 +1,195 @@ +# Troubleshooting Guide + +## Error: "Unknown column 't.amount' in 'SELECT'" + +### Kemungkinan Penyebab: +1. **OPcache belum di-clear** - PHP masih menggunakan file lama +2. **Struktur database berbeda** - Kolom `amount` mungkin tidak ada atau nama berbeda +3. **File belum ter-update** - Meskipun sudah `git pull`, file mungkin belum benar-benar ter-update + +--- + +## Solusi di Production + +### Step 1: Clear OPcache +```bash +# Di production server +cd /www/wwwroot/api.btekno.cloud/api + +# Clear OPcache via PHP CLI +php -r "opcache_reset();" + +# Atau restart PHP-FPM +systemctl restart php-fpm +# atau +/www/server/php/83/bin/php-fpm restart +``` + +### Step 2: Verify File Sudah Ter-update +```bash +# Cek apakah file sudah benar-benar ter-update +grep -n "COALESCE(t.amount, 0)" src/Modules/Retribusi/Summary/DailySummaryService.php + +# Harus muncul di line 46 dan 61 +# Line 46: COALESCE(t.amount, 0) as tariff_amount +# Line 61: COALESCE(t.amount, 0) +``` + +### Step 3: Verify Struktur Database +```bash +# Login ke MySQL +mysql -u sql_retribusi -p sql_retribusi + +# Cek struktur tabel tariffs +DESCRIBE tariffs; + +# Harus ada kolom: +# - location_code +# - gate_code +# - category +# - amount <-- INI HARUS ADA! +``` + +### Step 4: Test Query Manual +```bash +# Di MySQL client +mysql -u sql_retribusi -p sql_retribusi < bin/verify_query.sql + +# Atau jalankan query ini manual: +``` + +```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) = CURDATE() +GROUP BY + DATE(e.event_time), + e.location_code, + e.gate_code, + e.category, + COALESCE(t.amount, 0) +LIMIT 5; +``` + +### Step 5: Test Script Lagi +```bash +cd /www/wwwroot/api.btekno.cloud/api +php bin/daily_summary.php 2025-12-16 +``` + +--- + +## Cek Database Lokal + +### Step 1: Setup .env (jika belum) +```bash +# Copy .env.example ke .env +cp .env.example .env + +# Edit .env, isi dengan database lokal: +DB_HOST=localhost +DB_NAME=sql_retribusi +DB_USER=sql_retribusi +DB_PASS=your_password_here +``` + +### Step 2: Jalankan Script Check Database +```bash +php bin/check_database.php +``` + +### Step 3: Verify Query di Lokal +```bash +# Via MySQL client +mysql -u sql_retribusi -p sql_retribusi < bin/verify_query.sql +``` + +### Step 4: Test Daily Summary di Lokal +```bash +php bin/daily_summary.php 2025-12-16 +``` + +--- + +## Apply Migrations + +### Migration yang Tersedia: +1. `001_create_audit_logs.sql` - Tabel audit_logs +2. `002_create_hourly_summary.sql` - Tabel hourly_summary +3. `003_create_realtime_events.sql` - Tabel realtime_events + +### Cara Apply (Lokal): +```bash +# Via MySQL command line +mysql -u sql_retribusi -p sql_retribusi < migrations/001_create_audit_logs.sql +mysql -u sql_retribusi -p sql_retribusi < migrations/002_create_hourly_summary.sql +mysql -u sql_retribusi -p sql_retribusi < migrations/003_create_realtime_events.sql +``` + +### Cara Apply (Production): +```bash +# Di production server +cd /www/wwwroot/api.btekno.cloud/api + +# Backup dulu! +mysqldump -u sql_retribusi -p sql_retribusi > backup_$(date +%Y%m%d_%H%M%S).sql + +# Apply migration +mysql -u sql_retribusi -p sql_retribusi < migrations/001_create_audit_logs.sql +mysql -u sql_retribusi -p sql_retribusi < migrations/002_create_hourly_summary.sql +mysql -u sql_retribusi -p sql_retribusi < migrations/003_create_realtime_events.sql +``` + +--- + +## Jika Masih Error + +### Cek Log Error Detail: +```bash +# Di production +cd /www/wwwroot/api.btekno.cloud/api +php bin/daily_summary.php 2025-12-16 2>&1 | tee error.log +``` + +### Cek Apakah Tabel Tariffs Ada: +```sql +-- Di MySQL +SHOW TABLES LIKE 'tariffs'; +SELECT COUNT(*) FROM tariffs; +``` + +### Cek Apakah Ada Data di Entry Events: +```sql +-- Di MySQL +SELECT COUNT(*) FROM entry_events WHERE DATE(event_time) = CURDATE(); +``` + +--- + +## Quick Fix (Jika OPcache Issue) + +```bash +# Di production, restart PHP-FPM +systemctl restart php-fpm + +# Atau via aaPanel +# PHP → PHP-FPM → Restart + +# Lalu test lagi +cd /www/wwwroot/api.btekno.cloud/api +php bin/daily_summary.php 2025-12-16 +``` + diff --git a/bin/check_database.php b/bin/check_database.php new file mode 100644 index 0000000..62c7eaa --- /dev/null +++ b/bin/check_database.php @@ -0,0 +1,133 @@ +query("DESCRIBE tariffs"); + $columns = $stmt->fetchAll(PDO::FETCH_ASSOC); + + if (empty($columns)) { + echo " ❌ Table 'tariffs' does not exist!\n"; + } else { + echo " ✅ Table 'tariffs' exists with columns:\n"; + foreach ($columns as $col) { + echo " - {$col['Field']} ({$col['Type']})\n"; + } + } + + echo "\n2. Checking locations table structure:\n"; + $stmt = $db->query("DESCRIBE locations"); + $columns = $stmt->fetchAll(PDO::FETCH_ASSOC); + + if (empty($columns)) { + echo " ❌ Table 'locations' does not exist!\n"; + } else { + echo " ✅ Table 'locations' exists with columns:\n"; + foreach ($columns as $col) { + echo " - {$col['Field']} ({$col['Type']})\n"; + } + } + + echo "\n3. Checking gates table structure:\n"; + $stmt = $db->query("DESCRIBE gates"); + $columns = $stmt->fetchAll(PDO::FETCH_ASSOC); + + if (empty($columns)) { + echo " ❌ Table 'gates' does not exist!\n"; + } else { + echo " ✅ Table 'gates' exists with columns:\n"; + foreach ($columns as $col) { + echo " - {$col['Field']} ({$col['Type']})\n"; + } + } + + echo "\n4. Checking entry_events table structure:\n"; + $stmt = $db->query("DESCRIBE entry_events"); + $columns = $stmt->fetchAll(PDO::FETCH_ASSOC); + + if (empty($columns)) { + echo " ❌ Table 'entry_events' does not exist!\n"; + } else { + echo " ✅ Table 'entry_events' exists with columns:\n"; + foreach ($columns as $col) { + echo " - {$col['Field']} ({$col['Type']})\n"; + } + } + + echo "\n5. Testing query (similar to DailySummaryService):\n"; + $testSql = " + 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) = CURDATE() + GROUP BY + DATE(e.event_time), + e.location_code, + e.gate_code, + e.category, + COALESCE(t.amount, 0) + LIMIT 1 + "; + + try { + $stmt = $db->query($testSql); + $result = $stmt->fetch(PDO::FETCH_ASSOC); + echo " ✅ Query executed successfully!\n"; + if ($result) { + echo " Sample result: " . json_encode($result, JSON_PRETTY_PRINT) . "\n"; + } else { + echo " No data found for today.\n"; + } + } catch (PDOException $e) { + echo " ❌ Query failed: " . $e->getMessage() . "\n"; + } + + echo "\n=== Check Complete ===\n"; + +} catch (PDOException $e) { + echo "Database Error: " . $e->getMessage() . "\n"; + exit(1); +} +