# Analisis Mendalam Codebase: KP-ASOY + Laravel_KP

> Dibuat: 2026-05-19 | Tujuan: Mempersiapkan integrasi penuh Frontend (KP-ASOY) ↔ Backend (Laravel_KP)

---

## 1. Gambaran Umum Arsitektur

Sistem ini terdiri dari **dua proyek Laravel terpisah** yang dirancang untuk berkomunikasi via HTTP API:

| Aspek | KP-ASOY (Frontend) | Laravel_KP (Backend) |
|---|---|---|
| **Peran** | UI / Presentasi Layer | API / Business Logic / Database |
| **Port** | `8001` | `8000` |
| **Laravel** | ^13.0 (PHP ^8.3) | ^12.0 (PHP ^8.2) |
| **Auth** | Session-based (dari API token) | Laravel Sanctum Token |
| **Database** | `database_monitoring` (sama) | `database_monitoring` |
| **Env: Backend URL** | `BACKEND_API_URL=http://127.0.0.1:8000/api` | — |

> **Catatan Kritis**: Kedua proyek masih mengarah ke **database yang sama**. Ini membuat banyak controller di KP-ASOY masih query langsung ke DB, padahal seharusnya semua data diambil via API dari Laravel_KP.

---

## 2. Struktur Direktori Lengkap

### 2.1 Laravel_KP (Backend API)

```
Laravel_KP/
├── app/
│   ├── Exports/
│   │   └── PenugasanExport.php          # Export Excel (Maatwebsite)
│   ├── Http/
│   │   ├── Controllers/
│   │   │   ├── AuthController.php        # Login, Logout, Register, Me, UpdateProfile
│   │   │   ├── PegawaiController.php     # CRUD Pegawai (TIDAK ada route-nya di api.php!)
│   │   │   ├── UnitKerjaController.php   # Index Unit Kerja
│   │   │   └── Api/
│   │   │       └── PenugasanController.php  # Dashboard, CRUD Penugasan, Export
│   │   └── Middleware/
│   │       └── CheckRole.php             # Role check via Auth::user() untuk Sanctum
│   └── Models/
│       ├── User.php        # HasApiTokens, relasi ke Pegawai & Penugasan
│       ├── Pegawai.php     # NIP, Nama, Jabatan, user_id → belonsgToMany Penugasan
│       ├── Penugasan.php   # SoftDeletes, pivot ke Pegawai via penugasan_pegawai
│       └── UnitKerja.php
├── database/
│   └── migrations/
│       ├── 000...create_users_table.php         # users, password_reset_tokens, sessions
│       ├── 000...create_cache_table.php          # cache
│       ├── 000...create_jobs_table.php           # jobs queue
│       ├── 2026_04_21_create_pegawai_table.php   # pegawai + softDeletes
│       ├── 2026_04_21_create_penugasan_table.php # penugasan + penugasan_pegawai pivot
│       ├── 2026_04_21_create_unit_kerjas_table.php
│       └── 2026_04_28_create_personal_access_tokens_table.php  # Sanctum
├── routes/
│   ├── api.php    # Semua endpoint REST API
│   └── web.php    # Hanya redirect ke login (minimal)
└── .env
    # APP_URL=http://127.0.0.1:8000
    # DB_DATABASE=database_monitoring
    # CORS_ALLOWED_ORIGINS=http://localhost:8001,http://127.0.0.1:8001
```

### 2.2 KP-ASOY (Frontend)

```
KP-ASOY/
├── app/
│   ├── Http/
│   │   ├── Controllers/
│   │   │   ├── UserLoginController.php       # Login/Logout/Settings/User CRUD via API
│   │   │   ├── ActivityController.php        # CRUD Activity — MASIH query DB lokal!
│   │   │   └── Admin/
│   │   │       ├── ActivityController.php    # Monitor kegiatan Admin — MASIH DB lokal!
│   │   │       └── SuperAdminController.php  # Dashboard SuperAdmin — MASIH DB lokal!
│   │   └── Middleware/
│   │       └── RoleMiddleware.php            # Cek role dari session('user')
│   └── Models/
│       ├── User.php      # Tanpa HasApiTokens, relasi hasMany Activity
│       └── Activity.php  # SoftDeletes; fillable: nama_kegiatan, keterangan, status, user_id
├── resources/views/
│   ├── login-user.blade.php
│   ├── welcome.blade.php
│   ├── user/
│   │   ├── dashboard.blade.php
│   │   ├── activity-list.blade.php
│   │   ├── activity-detail.blade.php
│   │   ├── activity-edit.blade.php
│   │   ├── input-activity.blade.php
│   │   └── settings.blade.php
│   ├── admin/
│   │   ├── dashboard.blade.php
│   │   ├── users.blade.php
│   │   ├── create-user.blade.php
│   │   └── kegiatan/
│   └── superadmin/
│       ├── dashboard.blade.php
│       └── user/
├── routes/
│   └── web.php    # Routing web dengan middleware role
└── .env
    # APP_URL=http://127.0.0.1:8001
    # DB_DATABASE=database_monitoring
    # BACKEND_API_URL=http://127.0.0.1:8000/api
```

---

## 3. Alur Autentikasi (Sudah Terintegrasi)

```
[Browser] → POST /login-user (KP-ASOY:8001)
         → UserLoginController::login()
         → Http::post('http://127.0.0.1:8000/api/login', [username, password])
         → Laravel_KP: AuthController::login()
             - Cek username/email di tabel users
             - Hash::check password
             - Hapus token lama
             - createToken('kp-asoy-token') → Sanctum
         → Response JSON: { token, user:{id,name,username,email,role,jabatan} }
         → KP-ASOY: session(['api_token', 'user', 'role', 'user_id', 'user_name', 'username'])
         → Redirect by role:
             - 'admin'      → /admin/dashboard
             - 'superadmin' → /superadmin/dashboard
             - 'user'       → /user/dashboard
```

---

## 4. Semua Endpoint API Backend (Laravel_KP)

### Public (tanpa token)
| Method | Endpoint | Controller | Fungsi |
|--------|----------|------------|--------|
| POST | `/api/login` | AuthController@login | Login, return Sanctum token |

### Protected — auth:sanctum
| Method | Endpoint | Controller | Fungsi |
|--------|----------|------------|--------|
| POST | `/api/logout` | AuthController@logout | Hapus token aktif |
| GET | `/api/me` | AuthController@me | Data user yang login |
| PUT | `/api/profile/update` | AuthController@updateProfile | Update email/password |
| POST | `/api/register` | AuthController@register | Buat user baru |
| GET | `/api/users` | Closure inline | List semua user (semua role) |
| GET | `/api/pegawai` | Closure inline | List user dengan role='user' |
| GET | `/api/dashboard` | PenugasanController@dashboard | Stats + 5 aktivitas terbaru |
| GET | `/api/penugasan` | PenugasanController@index | List semua penugasan |
| POST | `/api/penugasan` | PenugasanController@store | Buat penugasan baru |
| GET | `/api/penugasan/{id}` | PenugasanController@show | **METHOD TIDAK ADA** |
| PUT | `/api/penugasan/{id}` | PenugasanController@update | **METHOD TIDAK ADA** |
| POST | `/api/penugasan/{id}/update-status` | PenugasanController@updateStatus | Ubah status penugasan |
| POST | `/api/penugasan/{id}/delete` | PenugasanController@destroy | Batalkan penugasan |
| GET | `/api/notifications` | PenugasanController@notifications | **METHOD TIDAK ADA** |
| GET | `/api/unit-kerja` | UnitKerjaController@index | List unit kerja |
| GET | `/api/export-penugasan` | PenugasanController@export | Download Excel |

---

## 5. Skema Database Lengkap

### Tabel `users`
| Kolom | Tipe | Keterangan |
|-------|------|------------|
| id | bigint PK | |
| name | string | Nama lengkap |
| username | string UNIQUE | Login identifier |
| email | string UNIQUE | |
| password | string | bcrypt hashed |
| role | enum | **Migration: `superadmin,admin,pegawai`** tapi kode pakai `user` |
| jabatan | string nullable | |
| created_at / updated_at | timestamp | |

### Tabel `pegawai`
| Kolom | Tipe | Keterangan |
|-------|------|------------|
| id | bigint PK | |
| nip | string UNIQUE | |
| nama | string | |
| jabatan | string | |
| user_id | FK → users | |
| deleted_at | timestamp | SoftDeletes |

### Tabel `penugasan`
| Kolom | Tipe | Keterangan |
|-------|------|------------|
| id | bigint PK | |
| nomor_surat | string nullable UNIQUE | |
| kegiatan | string | Nama kegiatan |
| tanggal_mulai | date | |
| tanggal_selesai | date nullable | |
| status | enum | `proses`, `selesai`, `telah_ditinjau` |
| created_by | FK → users | Admin yang membuat |
| approved_by | FK → users nullable | SuperAdmin penyetuju |
| approved_at | timestamp nullable | |
| alasan_hapus | text nullable | Alasan pembatalan |
| deleted_at | timestamp | SoftDeletes |

### Tabel `penugasan_pegawai` (Pivot)
| Kolom | Tipe | Keterangan |
|-------|------|------------|
| id | bigint PK | |
| penugasan_id | FK → penugasan | |
| pegawai_id | FK → pegawai | |

### Tabel `activities` (KP-ASOY Lokal — TIDAK ADA di Backend)
| Kolom | Tipe | Keterangan |
|-------|------|------------|
| id | bigint PK | |
| user_id | FK → users | |
| nama_kegiatan | string | |
| keterangan | text nullable | |
| status | string | `on_progres`, `selesai` |
| deleted_at | timestamp | SoftDeletes |

---

## 6. Relasi Antar Model

### Laravel_KP (Backend)
```
User ─── hasOne ──────────── Pegawai
User ─── hasMany ─────────── Penugasan (as created_by)
User ─── hasMany ─────────── Penugasan (as approved_by)
Pegawai ─ belongsToMany ──── Penugasan (via penugasan_pegawai)
Penugasan ─ belongsToMany ── Pegawai (via penugasan_pegawai)
Penugasan ─ belongsTo ────── User (pembuat)
Penugasan ─ belongsTo ────── User (penyetuju)
```

### KP-ASOY (Frontend)
```
User ─── hasMany ─────────── Activity
Activity ─ belongsTo ──────── User
```

---

## 7. Analisis Controller per Controller

### 7.1 `UserLoginController` (KP-ASOY) — SUDAH TERINTEGRASI ✅
Semua method sudah menggunakan `Http::withToken(session('api_token'))`:
- `login()` → POST `/api/login`
- `logout()` → POST `/api/logout`
- `updateSettings()` → PUT `/api/profile/update`
- `userList()` → GET `/api/users`
- `storeUser()` → POST `/api/register`
- `destroyUser()` → DELETE `/api/users/{id}` *(endpoint backend belum ada!)*

**Kekurangan**: `editUser()` dan `updateUser()` hanya return view tanpa data dari API.

### 7.2 `ActivityController` (KP-ASOY) — BELUM TERINTEGRASI ❌
Semua method masih pakai `Auth::id()` dan model `Activity::` langsung:
- `index()` → query `Activity::where('user_id', Auth::id())`
- `store()` → `Activity::create([...])`
- `list()`, `show()`, `edit()`, `update()`, `selesai()`

> **Target**: Semua operasi ini harus diganti dengan HTTP call ke backend menggunakan `session('api_token')` dan memetakan `Activity` ke entitas `Penugasan` di backend.

### 7.3 `Admin/ActivityController` (KP-ASOY) — BELUM TERINTEGRASI ❌
- `dashboard()` → query `Activity::`, `User::` langsung ke DB
- `index()` → query dengan filter search/status/bulan langsung ke DB
- `show()`, `edit()`, `update()`, `destroy()` → langsung ke DB

### 7.4 `Admin/SuperAdminController` (KP-ASOY) — BELUM TERINTEGRASI ❌
- `index()` → query `Activity::`, `User::withCount('activities')` langsung ke DB
- `approve()` → `Activity::findOrFail($id)->update(['status' => 'selesai'])` langsung ke DB
- `destroy()` → SoftDelete langsung ke DB
- `userIndex()`, `editUser()`, `updateUser()`, `destroyUser()` → langsung ke DB

### 7.5 `AuthController` (Laravel_KP) — BAIK ✅
Full implementasi login, register, me, logout, updateProfile. Semua return JSON.

### 7.6 `PenugasanController` (Laravel_KP) — PARTIAL ⚠️
- ✅ `dashboard()` → return JSON stats
- ✅ `index()` → return JSON list
- ❌ `store()` → **return redirect(), bukan JSON** (fatal untuk API)
- ❌ `show()` → **method tidak ada**
- ❌ `update()` → **method tidak ada**
- ✅ `updateStatus()` → return JSON
- ✅ `destroy()` → return JSON (tapi method hapus = batalkan, bukan delete)
- ✅ `export()` → return Excel download
- ❌ `notifications()` → **method tidak ada**

### 7.7 `PegawaiController` (Laravel_KP) — TIDAK DI-ROUTE ❌
Full CRUD tersedia (index, store, show, update, destroy, trash, restore) tapi **tidak ada satupun route** di `api.php` yang mengarah ke controller ini.

---

## 8. Middleware & Keamanan

### Backend: `CheckRole` Middleware
```php
// Membaca dari Auth::user() (Sanctum)
if (!$request->user() || !in_array($request->user()->role, $roles)) {
    return response()->json(['status' => false, 'message' => 'Akses ditolak'], 403);
}
```
> **Catatan**: Middleware ini terdaftar tapi tidak digunakan di route manapun di `api.php`.

### Frontend: `RoleMiddleware`
```php
// Membaca dari session('user') yang tersimpan saat login
$user = session('user');
if (!in_array($user['role'], $roles)) { abort(403); }
```
> Ini sudah tepat untuk frontend yang menggunakan session.

---

## 9. GAP INTEGRASI — Daftar Lengkap

### GAP-01: Dua Entitas Data Yang Berbeda (KRITIS)
- Backend punya `Penugasan` = penugasan dari admin ke pegawai (top-down)
- Frontend punya `Activity` = kegiatan yang diinput sendiri user (bottom-up)
- **Keputusan diperlukan**: Apakah `Activity` frontend = `Penugasan` backend? Atau keduanya berbeda?
- Jika disamakan: field tidak cocok (Activity: `nama_kegiatan, tanggal, lokasi, deskripsi` vs Penugasan: `nomor_surat, kegiatan, tanggal_mulai, tanggal_selesai`)

### GAP-02: Inkonsistensi Nilai Role (KRITIS)
- Migration users: enum `['superadmin', 'admin', 'pegawai']`
- Kode backend (AuthController, api.php): menggunakan string `'user'`
- Kode frontend (web.php, RoleMiddleware): menggunakan `'user'`, `'admin'`, `'superadmin'`
- **Harus dipilih satu**: gunakan `user` atau `pegawai` secara konsisten

### GAP-03: Method Hilang di PenugasanController
- `show($id)` → terdaftar di route, method tidak ada
- `update(Request, $id)` → terdaftar di route, method tidak ada
- `notifications()` → terdaftar di route, method tidak ada

### GAP-04: `store()` Return Redirect Bukan JSON
```php
// SALAH (ini web controller, bukan API):
return redirect()->back()->with('success', '...');

// BENAR (untuk API):
return response()->json(['success' => true, 'data' => $penugasan], 201);
```

### GAP-05: PegawaiController Tidak Di-Route
- Full CRUD tersedia namun tidak ada satupun endpoint di `api.php`
- Frontend tidak bisa mengakses data pegawai terpisah dari users

### GAP-06: DELETE `/api/users/{id}` Tidak Ada di Backend
- `UserLoginController::destroyUser()` di frontend memanggil `DELETE /api/users/{id}`
- Route ini tidak terdaftar di backend → HTTP 404

### GAP-07: ActivityController Masih Pakai DB Lokal
- Semua CRUD Activity di frontend (user, admin, superadmin) query langsung ke database
- Padahal database = database yang sama dengan backend, yang idealnya hanya diakses backend

### GAP-08: Activity Model Fillable Tidak Lengkap
```php
// Saat ini:
protected $fillable = ['nama_kegiatan', 'keterangan', 'status', 'user_id'];

// Tapi controller menyimpan:
Activity::create([..., 'tanggal' => ..., 'lokasi' => ...]);
// Field 'tanggal' dan 'lokasi' tidak ada di fillable → Mass Assignment Error!
```

### GAP-09: CORS Belum Dipastikan Terkonfigurasi
- Backend `.env` sudah ada `CORS_ALLOWED_ORIGINS=http://localhost:8001,http://127.0.0.1:8001`
- Perlu verifikasi `config/cors.php` membaca env ini dengan benar

### GAP-10: Session vs Token Auth Tidak Sinkron untuk SuperAdmin
- SuperAdmin di KP-ASOY masih menggunakan `Auth::user()` dan Eloquent langsung
- Harus diubah menggunakan `session('api_token')` untuk semua request ke backend

---

## 10. Peta Alur Integrasi Target

```
KP-ASOY (FE :8001)                          Laravel_KP (BE :8000)
─────────────────────────────────────────────────────────────────────
[LOGIN]
POST /login-user ──────────────────────────► POST /api/login
                 ◄────────────────────────── {token, user}

[USER — Input Kegiatan]
POST /activities/store ────────────────────► POST /api/penugasan
   Http::withToken($token)->post(...)        PenugasanController@store
                 ◄────────────────────────── {success, data}

[USER — List Kegiatan]
GET /activity-list ────────────────────────► GET /api/penugasan?user_id={id}
                 ◄────────────────────────── {success, data:[...]}

[USER — Update Kegiatan]
POST /activity/{id}/update ────────────────► PUT /api/penugasan/{id}
                 ◄────────────────────────── {success, data}

[ADMIN — Dashboard]
GET /admin/dashboard ──────────────────────► GET /api/dashboard
                 ◄────────────────────────── {stats, recent_activities}

[ADMIN — Tinjau Kegiatan]
POST /admin/kegiatan/{id}/update ──────────► POST /api/penugasan/{id}/update-status
   {status: 'telah_ditinjau'}               PenugasanController@updateStatus

[SUPERADMIN — Approve]
POST /superadmin/kegiatan/{id}/approve ───► POST /api/penugasan/{id}/update-status
   {status: 'selesai'}                      PenugasanController@updateStatus

[SUPERADMIN — Export]
GET /superadmin/export ────────────────────► GET /api/export-penugasan
                 ◄────────────────────────── file: Laporan_Kegiatan.xlsx

[ADMIN — Tambah User]
POST /admin/users/store ───────────────────► POST /api/register
                 ◄────────────────────────── {message, user}

[ADMIN — Hapus User]
DELETE /admin/users/{id} ──────────────────► DELETE /api/users/{id}  [BELUM ADA!]
```

---

## 11. Status Integrasi Per Fitur

| # | Fitur | FE Controller | BE Endpoint | Status |
|---|-------|--------------|-------------|--------|
| 1 | Login | UserLoginController@login | POST /api/login | ✅ Terintegrasi |
| 2 | Logout | UserLoginController@logout | POST /api/logout | ✅ Terintegrasi |
| 3 | Update Profil | UserLoginController@updateSettings | PUT /api/profile/update | ✅ Terintegrasi |
| 4 | Tambah User (Admin) | UserLoginController@storeUser | POST /api/register | ✅ Terintegrasi |
| 5 | List User (Admin) | UserLoginController@userList | GET /api/users | ✅ Terintegrasi |
| 6 | Hapus User (Admin) | UserLoginController@destroyUser | ❌ Route belum ada | ❌ Belum |
| 7 | Input Kegiatan (User) | ActivityController@store | POST /api/penugasan | ❌ FE masih DB lokal |
| 8 | List Kegiatan (User) | ActivityController@list | GET /api/penugasan | ❌ FE masih DB lokal |
| 9 | Detail Kegiatan (User) | ActivityController@show | ❌ Method belum ada | ❌ Belum |
| 10 | Edit Kegiatan (User) | ActivityController@update | ❌ Method belum ada | ❌ Belum |
| 11 | Selesaikan Kegiatan | ActivityController@selesai | POST /api/penugasan/{id}/update-status | ❌ FE masih DB lokal |
| 12 | Dashboard Admin | Admin/ActivityController@dashboard | GET /api/dashboard | ❌ FE masih DB lokal |
| 13 | Monitor Kegiatan (Admin) | Admin/ActivityController@index | GET /api/penugasan | ❌ FE masih DB lokal |
| 14 | Tinjau Kegiatan (Admin) | Admin/ActivityController@update | POST /api/penugasan/{id}/update-status | ❌ FE masih DB lokal |
| 15 | Dashboard SuperAdmin | SuperAdminController@index | GET /api/dashboard | ❌ FE masih DB lokal |
| 16 | Approve Kegiatan (SA) | SuperAdminController@approve | POST /api/penugasan/{id}/update-status | ❌ FE masih DB lokal |
| 17 | Hapus Kegiatan (SA) | SuperAdminController@destroy | POST /api/penugasan/{id}/delete | ❌ FE masih DB lokal |
| 18 | Manajemen User (SA) | SuperAdminController@userIndex | GET /api/users | ❌ FE masih DB lokal |
| 19 | Export Laporan | SuperAdminController@export | GET /api/export-penugasan | ❌ FE hanya redirect error |
| 20 | Notifikasi User | ActivityController (statis) | ❌ Method belum ada | ❌ Belum |
| 21 | CRUD Pegawai | ❌ Tidak ada di FE | ❌ Tidak di-route | ❌ Belum |

**Ringkasan**: 5 dari 21 fitur (24%) sudah terintegrasi. 16 fitur (76%) belum terintegrasi.

---

## 12. Prioritas Perbaikan

### 🔴 Prioritas 1 — Perbaiki Backend (Harus Selesai Dulu)

1. **Seragamkan role value** → ubah migration/kode dari `pegawai` ke `user` secara konsisten
2. **Implementasi method hilang** di `PenugasanController`:
   - `show($id)` → return JSON detail penugasan + petugas
   - `update(Request, $id)` → update data penugasan, return JSON
   - `notifications()` → return list penugasan yang sudah `telah_ditinjau` untuk user tertentu
3. **Perbaiki `store()`** → ganti `redirect()->back()` dengan `response()->json(201)`
4. **Tambah route di api.php**:
   - `DELETE /api/users/{id}` → untuk hapus user
   - Route lengkap `PegawaiController` (index, store, show, update, destroy, trash, restore)
5. **Tambah filter by user** di `GET /api/penugasan` → user hanya boleh lihat tugasnya sendiri

### 🟡 Prioritas 2 — Refactor Frontend Controllers

6. **Refactor `ActivityController`** → ganti semua `Activity::` dan `Auth::id()` dengan `Http::withToken(session('api_token'))->...`
7. **Refactor `Admin/ActivityController`** → semua operasi via API backend
8. **Refactor `SuperAdminController`** → gunakan endpoint API, bukan query DB langsung
9. **Perbaiki `Activity` model fillable** → tambahkan `tanggal`, `lokasi`, `deskripsi`

### 🟢 Prioritas 3 — Penyempurnaan

10. **Verifikasi konfigurasi CORS** di `config/cors.php` backend
11. **Hapus koneksi DB dari KP-ASOY** (kecuali sessions/cache)
12. **Implementasi notifikasi real** berdasarkan status perubahan penugasan
13. **Tambah endpoint edit/delete user** untuk SuperAdmin di backend
14. **Implementasi `editUser()` dan `updateUser()`** di `UserLoginController` KP-ASOY

---

## 13. Kesimpulan

Secara arsitektur, rancangan pemisahan frontend (KP-ASOY) dan backend (Laravel_KP) **sudah benar dan tepat**. Fondasi integrasi sudah ada: autentikasi via Sanctum sudah berjalan, `BACKEND_API_URL` sudah dikonfigurasi, dan pattern `Http::withToken()` sudah digunakan di `UserLoginController`.

**Masalah utama** adalah sebagian besar fitur di KP-ASOY (terutama semua yang berhubungan dengan Activity/Kegiatan dan Dashboard) masih bypass API dan langsung mengakses database. Ini terjadi kemungkinan karena pengembangan dilakukan secara bertahap: login terintegrasi lebih dulu, sementara fitur-fitur lainnya masih dalam proses refactoring.

**Langkah terpenting** sebelum integrasi penuh:
1. Putuskan apakah `Activity` (KP-ASOY) = `Penugasan` (Laravel_KP) atau dua entitas berbeda
2. Perbaiki method-method yang hilang di backend
3. Seragamkan nilai role di seluruh codebase
4. Refactor semua controller frontend untuk menggunakan API
