# ❓ FAQ & TECHNICAL Q&A - OCEANGO

## BAGIAN 1: PERTANYAAN UMUM

### Q1: Apa fungsi utama Oceango?
**A:** 
Oceango adalah sistem booking tiket kapal online yang memungkinkan:
- Pelanggan untuk memesan tiket kapal dengan mudah
- Admin untuk mengelola pemesanan dan tracking perjalanan kapal
- Transparan tracking status kapal real-time

**Use Case:**
- Pengguna buka aplikasi → Register → Pesan tiket → Bayar → Terima konfirmasi
- Admin approve pemesanan → Update status kapal → Pelanggan tracking

---

### Q2: Siapa saja yang bisa menggunakan sistem ini?
**A:**
```
1. PELANGGAN (User)
   - Siapa: Individu yang ingin pesan tiket kapal
   - Akses: Register sendiri, tidak perlu undangan admin
   - Fitur: Pesan tiket, lihat riwayat, tracking, batalkan

2. ADMIN
   - Siapa: Staff perusahaan kapal
   - Akses: Login dengan credential dari admin (dibuat manual)
   - Fitur: Kelola user, booking, progress, statistik
   
3. SUPER ADMIN
   - Siapa: Developer/Owner sistem
   - Akses: Database direct access
   - Fitur: Buat admin baru via seeder
```

---

### Q3: Berapa biaya untuk menggunakan Oceango?
**A:**
Ini adalah aplikasi custom yang sudah dibangun. Biaya tergantung:
- Development sudah selesai ✅
- Hosting: Tergantung server yang dipilih
- Maintenance: Maintenance fee tahunan
- Scaling: Biaya server meningkat sesuai traffic

Ini adalah project TugasAkhir (tugas sekolah), bukan produk komersial resmi.

---

### Q4: Bagaimana data pelanggan dijaga keamanannya?
**A:**
```
🔐 SECURITY LAYERS:

1. PASSWORD
   - Tidak disimpan plain text
   - Di-hash dengan Bcrypt
   - Tidak bisa di-reverse

2. DATABASE
   - Foreign key constraints
   - Cascade delete untuk data integrity
   - Indexed untuk performance

3. AUTHENTICATION
   - Session-based
   - Middleware check setiap route
   - Auto logout setelah inactivity

4. AUTHORIZATION
   - Role-based (User vs Admin)
   - isAdmin middleware
   - Cannot access other users data

5. INPUT VALIDATION
   - Email format validation
   - Password strength check
   - Booking data validation

6. CSRF PROTECTION
   - Token di setiap form
   - Prevent cross-site attacks

7. ENCRYPTION
   - Passwords hashed
   - Sensitive data validated
```

---

### Q5: Bisa digunakan untuk berapa banyak pengguna sekaligus?
**A:**
Tergantung setup server:

```
SMALL BUSINESS (1000-5000 pengguna):
- Single server Laravel
- MySQL default
- Shared hosting OK
- Cost: Rp 500k - Rp 2jt/bulan

MEDIUM BUSINESS (10,000+ pengguna):
- Dedicated server
- MySQL optimization
- Load balancing
- Cost: Rp 5jt - Rp 20jt/bulan

LARGE BUSINESS (100,000+ pengguna):
- Multiple app servers
- Database replication
- CDN untuk media
- Cost: Rp 50jt+/bulan
```

MySQL default bisa handle ribuan concurrent users tanpa masalah.

---

### Q6: Apakah sistem ini bisa di-upgrade/scale-up?
**A:**
**Ya, sangat bisa!** Contoh upgrade:

```
FASE 1 (Current):
- Single server
- MySQL
- Blade templates

FASE 2:
+ Add caching (Redis)
+ Add queue (Background jobs)
+ Email notifications
+ SMS gateway

FASE 3:
+ API REST untuk mobile app
+ Payment gateway (Stripe, iPaymu)
+ Admin reports/analytics
+ Multi-language support

FASE 4:
+ Real-time socket (websocket)
+ Machine learning (price prediction)
+ Blockchain (immutable bookings)
+ Advanced analytics
```

---

## BAGIAN 2: PERTANYAAN TEKNIS

### Q7: Bagaimana booking code di-generate?
**A:**
```php
// Di Model: app/Models/Booking.php

protected static function boot()
{
    parent::boot();
    
    static::creating(function ($model) {
        if (!$model->booking_code) {
            // Generate format: OG-YYYYMMDD-XXXXXX
            $date = now()->format('Ymd');        // 20260602
            $random = strtoupper(Str::random(6)); // ABC123
            $model->booking_code = "OG-{$date}-{$random}";
            
            // Ensure uniqueness
            while (static::where('booking_code', $model->booking_code)->exists()) {
                $random = strtoupper(Str::random(6));
                $model->booking_code = "OG-{$date}-{$random}";
            }
        }
    });
}

RESULT:
OG-20260602-ABC123
OG-20260602-XYZ789
OG-20260603-QWE456
```

**Keuntungan:**
- Unique setiap booking
- Format konsisten
- Human-readable
- Tidak bisa diprediksi

---

### Q8: Bagaimana relasi database antara User, Booking, dan Progress?
**A:**
```
┌─────────┐           ┌─────────┐           ┌──────────┐
│  USERS  │──────────│ BOOKINGS│──────────│ PROGRESS │
└─────────┘ 1    *   └─────────┘ 1    *   └──────────┘

Penjelasan:

1 USER → MANY BOOKINGS
- 1 pengguna bisa punya banyak booking
- Foreign key: bookings.user_id → users.id
- Cascade delete: hapus user → hapus booking

1 BOOKING → MANY PROGRESS
- 1 booking bisa punya banyak update progress
- Foreign key: progress.booking_id → bookings.id
- Cascade delete: hapus booking → hapus progress

EXAMPLE DATA:
```

```sql
-- User
INSERT INTO users VALUES (1, 'Budi', 'budi@mail.com', '***', 'user');

-- Bookings (1 user bisa punya 2 booking)
INSERT INTO bookings VALUES (101, 1, 'OG-20260602-ABC', 'Jakarta', 'Surabaya', ..., 'pending');
INSERT INTO bookings VALUES (102, 1, 'OG-20260603-XYZ', 'Surabaya', 'Bandung', ..., 'confirmed');

-- Progress (1 booking bisa punya 3 update)
INSERT INTO progress VALUES (1, 101, 'Pending', 'Belum berangkat', 'Jakarta', '2026-06-02');
INSERT INTO progress VALUES (2, 101, 'Berangkat', 'Kapal sudah berlayar', 'Laut Jawa', '2026-06-02 08:00');
INSERT INTO progress VALUES (3, 101, 'Tiba', 'Sampai di Surabaya', 'Surabaya', '2026-06-03 10:00');
```

---

### Q9: Bagaimana authentication flow bekerja?
**A:**
```
LOGIN USER:
1. User input email + password di form /login
2. Controller validasi: email exist? password match?
3. Jika valid:
   - Create session dengan user id
   - Set session timeout 120 minutes
   - Redirect ke dashboard
4. Jika invalid:
   - Flash error message
   - Redirect ke login form lagi

AUTHENTICATED USER:
1. User akses /my-bookings (protected route)
2. Middleware 'auth' check: ada session?
3. Jika ada: lanjut ke controller
4. Jika tidak: redirect ke login

ADMIN LOGIN:
1. Sama seperti user tapi route /admin/login
2. Middleware 'auth' + 'isAdmin' check
3. isAdmin: role == 'admin'? YES → lanjut | NO → forbidden

LOGOUT:
1. User klik tombol logout
2. Session destroyed
3. Redirect ke login page
```

**Middleware Code:**
```php
// app/Http/Middleware/isAdmin.php
public function handle(Request $request, Closure $next)
{
    if (auth()->user() && auth()->user()->isAdmin()) {
        return $next($request);
    }
    
    return redirect('/')->with('error', 'Akses ditolak');
}
```

---

### Q10: Apa perbedaan antara Booking Status dan Progress?
**A:**
```
BOOKING STATUS:
- Main status booking
- Berisi: pending, confirmed, completed, cancelled
- 1 nilai per booking
- Digunakan: untuk approval workflow

Progress:
- Detail perjalanan kapal
- Berisi: lokasi, status deskriptif, timestamp
- Bisa multiple entries per booking
- Digunakan: untuk tracking real-time

CONTOH:

Booking #OG-20260602-ABC
├─ Status: CONFIRMED ← booking sudah di-approve
│
└─ Progress History:
   ├─ 06-02 08:00 → Status: Kapal Berangkat, Lokasi: Jakarta
   ├─ 06-02 12:00 → Status: Berlayar, Lokasi: Selat Sunda
   ├─ 06-03 08:00 → Status: Sampai, Lokasi: Surabaya
   └─ 06-03 10:00 → Status: Penumpang Turun, Lokasi: Terminal Surabaya

Jadi:
- Status = Keseluruhan (pending/confirmed/completed)
- Progress = Detail journey (history tracking)
```

---

### Q11: Bagaimana cara admin update progress?
**A:**
```
FLOW:

1. Admin buka /admin/progress
2. Klik booking yang ingin di-update
3. Klik "Tambah Progress"
4. Isi form:
   - Status: "Kapal Berangkat"
   - Deskripsi: "Kapal sudah berlayar dari Jakarta"
   - Lokasi: "Laut Jawa"
   - Waktu: auto filled dengan current time
5. Submit

DATABASE:
INSERT INTO progress VALUES (
    NULL,                          # auto increment
    101,                           # booking_id
    'Kapal Berangkat',            # status
    'Kapal sudah berlayar dari Jakarta',  # description
    'Laut Jawa',                  # location
    '2026-06-02 08:30:00',        # updated_at_status
    '2026-06-02 08:30:00',        # created_at
    '2026-06-02 08:30:00'         # updated_at
);

USER EXPERIENCE:
User buka dashboard → Scroll ke progress booking
Update otomatis muncul dalam 1-2 detik
Timeline progress terlihat jelas
```

---

### Q12: Bagaimana jika user ingin batalkan booking?
**A:**
```
RULE:
- Hanya booking dengan status 'pending' atau 'confirmed' bisa dibatalkan
- Booking 'completed' atau 'cancelled' tidak bisa dibatalkan

FLOW:

1. User lihat booking di /my-bookings/list
2. Klik tombol "Batalkan"
3. Confirmation popup: "Yakin ingin batalkan?"
4. Klik OK

BACKEND:
```php
// UserBookingController.php
public function cancel(Booking $booking)
{
    if (!in_array($booking->status, ['pending', 'confirmed'])) {
        return redirect()->back()->with('error', 'Booking tidak bisa dibatalkan');
    }
    
    $booking->update(['status' => 'cancelled']);
    
    return redirect()->back()->with('success', 'Booking dibatalkan');
}
```

DATABASE:
```sql
-- Before
UPDATE bookings SET status = 'pending' WHERE id = 101;

-- After
UPDATE bookings SET status = 'cancelled', updated_at = NOW() WHERE id = 101;
```

USER NOTIFICATION:
- Flash message: "Booking berhasil dibatalkan"
- Status langsung berubah di list
- Opsi "batalkan" hilang dari button
```

---

## BAGIAN 3: PERFORMANCE & SCALABILITY

### Q13: Bagaimana performance aplikasi untuk jutaan records?
**A:**
```
CURRENT SETUP:
- Single MySQL server
- Indexing di foreign keys
- No caching

POTENTIAL BOTTLENECKS:

1. Query pembacaan (SELECT)
   - Jika users > 100,000 → perlu pagination
   - Solution: Add caching layer (Redis)
   
2. Booking history
   - Jika per user > 10,000 booking → query lambat
   - Solution: Pagination, add indexes
   
3. Progress tracking
   - Jika per booking > 1,000 updates → filter
   - Solution: Archiving old records

OPTIMIZATION TIPS:

1. DATABASE
   - Add indexes di user_id, booking_id, status
   - Enable query caching
   - Use raw queries untuk complex operations

2. BACKEND
   - Add Redis cache untuk frequently accessed data
   - Use queues untuk heavy operations
   - Implement pagination (15-25 items per page)

3. FRONTEND
   - Lazy loading untuk list
   - AJAX untuk infinite scroll
   - Minimize CSS/JS bundle

SCALING APPROACH:

Small → Medium (100K users):
- Add database indexes ✅
- Implement caching (Redis) ✅
- Load balancing (2-3 servers) ✅
- CDN untuk static files ✅

Medium → Large (1M users):
- Database replication (Master-Slave) ✅
- Microservices untuk booking, progress ✅
- Real-time queue system ✅
- Advanced caching strategy ✅

Current system without optimization: ~10,000 QPS (queries per second)
With optimization: ~50,000+ QPS
```

---

## BAGIAN 4: FUTURE FEATURES

### Q14: Fitur apa yang bisa ditambahkan ke depan?
**A:**
```
PHASE 1 (Immediate):
✅ Email notifications untuk booking status
✅ SMS reminders sebelum keberangkatan
✅ PDF invoice untuk booking
✅ Receipt email

PHASE 2 (1-3 months):
✅ Payment gateway integration (Stripe, iPaymu)
✅ QR code ticket generation
✅ Multiple language support (EN, ID, CN)
✅ Dark mode theme

PHASE 3 (3-6 months):
✅ Mobile app (iOS + Android)
✅ REST API untuk 3rd party integration
✅ Loyalty program / rewards
✅ Advanced reporting dashboard
✅ Business intelligence (BI) tools

PHASE 4 (6+ months):
✅ Real-time seat selection (like airline)
✅ Dynamic pricing based on demand
✅ Group booking discounts
✅ Insurance options
✅ Tour packages integration
✅ Virtual tour of cabins
✅ Chat support agent
✅ AI-powered recommendation

LONG TERM:
✅ Blockchain untuk immutable records
✅ IoT integration untuk kapal
✅ Machine learning price optimization
✅ Multivendor marketplace
```

---

## BAGIAN 5: TROUBLESHOOTING SAAT PRESENTASI

### Q15: Apa yang harus dilakukan jika database error?
**A:**
```
ERROR: SQLSTATE[HY000] [2002] Connection refused

SOLUTION CHECKLIST:
✅ 1. MySQL running?
     - Buka Task Manager → Services
     - Cari "MySQL80" atau "MySQL57"
     - Jika berhenti → Start

✅ 2. Check .env file:
   DB_HOST=127.0.0.1
   DB_PORT=3306
   DB_USERNAME=root
   DB_PASSWORD=
   DB_DATABASE=oceangov2

✅ 3. Run migration:
   php artisan migrate

✅ 4. Seed database:
   php artisan db:seed

✅ 5. Test connection:
   php artisan tinker
   > DB::connection()->getPdo()
   # Jika berhasil tidak ada error
```

---

### Q16: Bagaimana jika muncul "500 Internal Server Error"?
**A:**
```
DEBUGGING STEPS:

1. Check log file:
   storage/logs/laravel.log
   - Lihat error message terakhir

2. Enable debug mode di .env:
   APP_DEBUG=true

3. Clear cache:
   php artisan cache:clear
   php artisan config:clear
   php artisan route:clear

4. Check permissions:
   chmod -R 775 storage/
   chmod -R 775 bootstrap/cache/

5. Check dependencies:
   php artisan serve
   # Lihat terminal untuk error details

COMMON ERRORS:
- Undefined variable → typo di view
- Model not found → error di route model binding
- Database error → migration belum jalan
- File permission → write access to storage folder
```

---

Semoga berhasil untuk presentasi! 🎉
