# Akses Rapor Siswa untuk Wali Kelas

## Ringkasan
Sistem ini telah dikonfigurasi sehingga **hanya guru dengan status "Wali Kelas"** yang dapat mengakses rapor siswa di kelas yang mereka bimbing. Admin tetap memiliki akses penuh ke semua rapor.

## Cara Kerja

### 1. Pengecekan Status Wali Kelas
Status wali kelas ditentukan dari field `jabatan` di tabel `gurus`:
- Guru dengan `jabatan = 'wali_kelas'` dapat mengakses rapor siswa
- Admin dapat mengakses semua rapor
- Guru lain tidak dapat mengakses fitur rapor

### 2. Pembatasan Akses Berdasarkan Kelas
Wali kelas hanya dapat:
- Melihat rapor siswa dari kelas yang mereka bimbing (berdasarkan `wali_kelas_id` di tabel `kelas`)
- Membuat rapor untuk siswa di kelas mereka
- Mencetak rapor siswa di kelas mereka
- Menghapus rapor (hanya yang berstatus draft) dari siswa di kelas mereka

## Implementasi Teknis

### Trait WaliKelasAccess
File: `app/Http/Controllers/Simaju/Traits/WaliKelasAccess.php`

Trait ini menyediakan method-method helper:

#### Method `isWaliKelasOrAdmin()`
Mengecek apakah user adalah wali kelas atau admin:
```php
protected function isWaliKelasOrAdmin(): bool
{
    $user = auth()->user();
    
    // Admin dapat akses semua
    if ($user->role === 'admin') {
        return true;
    }
    
    // Cek apakah guru memiliki jabatan wali_kelas
    if ($user->role === 'guru' && $user->guru) {
        return $user->guru->jabatan === 'wali_kelas';
    }
    
    return false;
}
```

#### Method `getWaliKelasClasses()`
Mendapatkan daftar kelas yang dibimbing wali kelas:
```php
protected function getWaliKelasClasses()
{
    $user = auth()->user();
    
    if ($user->role === 'admin') {
        return Kelas::with('jurusan')->get();
    }
    
    if ($user->guru && $user->guru->jabatan === 'wali_kelas') {
        return Kelas::with('jurusan')
            ->where('wali_kelas_id', $user->guru->id)
            ->get();
    }
    
    return collect();
}
```

#### Method `checkWaliKelasAccess()`
Memvalidasi akses dan redirect jika tidak memiliki hak akses:
```php
protected function checkWaliKelasAccess(string $errorMessage = '...')
{
    if (!$this->isWaliKelasOrAdmin()) {
        return redirect()->route('simaju.dashboard')
            ->with('error', $errorMessage);
    }
    
    return null;
}
```

### RaporController
File: `app/Http/Controllers/Simaju/RaporController.php`

Setiap method dalam RaporController mengimplementasikan pengecekan:

#### 1. Index (Daftar Rapor)
```php
public function index(Request $request)
{
    // Cek akses wali kelas
    if ($check = $this->checkWaliKelasAccess('...')) {
        return $check;
    }
    
    // Ambil kelas yang dibimbing
    $kelasList = $this->getWaliKelasClasses();
    
    // Filter rapor hanya dari kelas yang dibimbing
    $kelasIds = $kelasList->pluck('id');
    $query->whereHas('siswa', function($q) use ($kelasIds) {
        $q->whereIn('kelas_id', $kelasIds);
    });
    
    // ... query lainnya
}
```

#### 2. Create (Buat Rapor Baru)
```php
public function create(Request $request)
{
    // Cek akses wali kelas
    if ($check = $this->checkWaliKelasAccess('...')) {
        return $check;
    }
    
    // Hanya tampilkan siswa dari kelas yang dibimbing
    $kelasIds = $kelasList->pluck('id');
    $siswaList = Siswa::whereIn('kelas_id', $kelasIds)->get();
    
    // ...
}
```

#### 3. Store (Simpan Rapor)
```php
public function store(Request $request)
{
    // Cek akses wali kelas
    if ($check = $this->checkWaliKelasAccess()) {
        return $check;
    }
    
    // Verifikasi siswa ada di kelas yang dibimbing
    $siswa = Siswa::findOrFail($request->siswa_id);
    $kelasIds = $this->getWaliKelasClasses()->pluck('id');
    
    if (!$kelasIds->contains($siswa->kelas_id)) {
        return back()->with('error', 'Anda hanya dapat membuat rapor untuk siswa di kelas yang Anda bimbing.');
    }
    
    // ... proses simpan
}
```

#### 4. Show (Lihat Detail Rapor)
```php
public function show(Rapor $rapor)
{
    // Cek akses wali kelas
    if ($check = $this->checkWaliKelasAccess()) {
        return $check;
    }
    
    // Verifikasi siswa ada di kelas yang dibimbing
    $kelasIds = $this->getWaliKelasClasses()->pluck('id');
    if (!$kelasIds->contains($rapor->siswa->kelas_id)) {
        return redirect()->route('simaju.rapor.index')
            ->with('error', 'Anda hanya dapat melihat rapor siswa di kelas yang Anda bimbing.');
    }
    
    // ...
}
```

#### 5. Print (Cetak PDF)
```php
public function print(Rapor $rapor)
{
    // Cek akses wali kelas
    if ($check = $this->checkWaliKelasAccess()) {
        return $check;
    }
    
    // Verifikasi siswa ada di kelas yang dibimbing
    $kelasIds = $this->getWaliKelasClasses()->pluck('id');
    if (!$kelasIds->contains($rapor->siswa->kelas_id)) {
        return redirect()->route('simaju.rapor.index')
            ->with('error', 'Anda hanya dapat mencetak rapor siswa di kelas yang Anda bimbing.');
    }
    
    // ... generate PDF
}
```

#### 6. Destroy (Hapus Rapor)
```php
public function destroy(Rapor $rapor)
{
    // Cek akses wali kelas
    if ($check = $this->checkWaliKelasAccess()) {
        return $check;
    }
    
    // Verifikasi siswa ada di kelas yang dibimbing
    $kelasIds = $this->getWaliKelasClasses()->pluck('id');
    if (!$kelasIds->contains($rapor->siswa->kelas_id)) {
        return back()->with('error', 'Anda hanya dapat menghapus rapor siswa di kelas yang Anda bimbing.');
    }
    
    // Hanya boleh hapus jika status draft
    if ($rapor->status !== 'draft') {
        return back()->with('error', 'Hanya rapor dengan status draft yang dapat dihapus.');
    }
    
    // ...
}
```

## Routing
File: `routes/web.php` (baris 112-117)

```php
// Rapor (Only for Wali Kelas and Admin)
Route::middleware('role:admin,guru')->group(function () {
    Route::resource('rapor', RaporController::class);
    Route::get('rapor/{rapor}/print', [RaporController::class, 'print'])->name('rapor.print');
    Route::put('rapor/{rapor}/update-status', [RaporController::class, 'updateStatus'])->name('rapor.update-status');
});
```

**Catatan:** Route menggunakan middleware `role:admin,guru`, namun pengecekan detail dilakukan di controller untuk memfilter berdasarkan status `jabatan = 'wali_kelas'`.

## Model Relationships

### Guru Model
```php
public function kelas(): HasMany
{
    return $this->hasMany(Kelas::class, 'wali_kelas_id');
}
```

### Kelas Model
```php
public function waliKelas(): BelongsTo
{
    return $this->belongsTo(Guru::class, 'wali_kelas_id');
}
```

### Rapor Model
```php
public function siswa(): BelongsTo
{
    return $this->belongsTo(Siswa::class);
}
```

## Contoh Skenario

### Skenario 1: Guru Wali Kelas Login
1. Guru dengan jabatan `wali_kelas` login
2. Akses menu Rapor
3. Sistem otomatis menampilkan hanya rapor dari siswa di kelas yang dia bimbing
4. Filter kelas hanya menampilkan kelas yang dia bimbing

### Skenario 2: Guru Biasa (Bukan Wali Kelas) Mencoba Akses
1. Guru dengan jabatan `guru_mapel` login
2. Akses menu Rapor
3. Sistem mendeteksi bukan wali kelas
4. User di-redirect ke dashboard dengan pesan error: "Anda tidak memiliki akses. Hanya wali kelas yang dapat mengakses rapor."

### Skenario 3: Admin Login
1. Admin login
2. Akses menu Rapor
3. Dapat melihat semua rapor dari semua kelas
4. Dapat membuat/edit/hapus rapor siswa manapun

### Skenario 4: Wali Kelas Mencoba Akses Rapor Kelas Lain
1. Wali Kelas login (misal: Wali Kelas XII RPL 1)
2. Mencoba akses langsung URL rapor siswa dari kelas lain (misal: XII TKJ 1)
3. Sistem mendeteksi siswa bukan dari kelasnya
4. User di-redirect dengan pesan error: "Anda hanya dapat melihat rapor siswa di kelas yang Anda bimbing."

## Keamanan

### Layer Keamanan
1. **Middleware Level**: Route middleware `role:admin,guru` 
2. **Controller Level**: Method `checkWaliKelasAccess()` di setiap action
3. **Query Level**: Filter data berdasarkan `wali_kelas_id`
4. **Verification Level**: Double-check pada setiap action (show, print, destroy) untuk memastikan siswa berada di kelas yang dibimbing

### Validasi Data
- Setiap operasi memvalidasi bahwa siswa berada di kelas yang dibimbing oleh wali kelas yang login
- Menggunakan relationship `Kelas->waliKelas` untuk mapping
- Admin bypass semua validasi dan dapat akses semua data

## Testing

### Test Case yang Harus Dijalankan

#### Test 1: Wali Kelas Akses Rapor Kelasnya
- **User**: Wali Kelas XII RPL 1
- **Action**: Akses daftar rapor
- **Expected**: Hanya menampilkan rapor siswa XII RPL 1

#### Test 2: Wali Kelas Buat Rapor
- **User**: Wali Kelas XII RPL 1
- **Action**: Buat rapor untuk siswa XII RPL 1
- **Expected**: Berhasil dibuat

#### Test 3: Wali Kelas Akses Rapor Kelas Lain
- **User**: Wali Kelas XII RPL 1
- **Action**: Akses rapor siswa XII TKJ 1 via direct URL
- **Expected**: Redirect dengan error message

#### Test 4: Guru Biasa Akses Rapor
- **User**: Guru Mapel (bukan wali kelas)
- **Action**: Akses menu rapor
- **Expected**: Redirect ke dashboard dengan error message

#### Test 5: Admin Akses Semua Rapor
- **User**: Admin
- **Action**: Akses daftar rapor
- **Expected**: Menampilkan semua rapor dari semua kelas

## Cara Mengatur Wali Kelas

1. Masuk sebagai Admin
2. Menu **Data Guru** > Pilih guru > Edit
3. Pada field **Jabatan**, pilih **"Wali Kelas"**
4. Simpan perubahan
5. Menu **Data Kelas** > Pilih kelas > Edit
6. Pada field **Wali Kelas**, pilih guru yang sudah dijadikan wali kelas
7. Simpan perubahan

Setelah itu, guru tersebut dapat login dan mengakses rapor siswa di kelas yang dibimbingnya.

## Troubleshooting

### Problem: Wali Kelas Tidak Bisa Akses Rapor
**Solusi:**
1. Pastikan field `jabatan` guru = `'wali_kelas'`
2. Pastikan `wali_kelas_id` di tabel kelas terisi dengan ID guru tersebut
3. Cek role user di tabel users adalah `'guru'`

### Problem: Wali Kelas Tidak Melihat Siswa Saat Buat Rapor
**Solusi:**
1. Pastikan siswa sudah terdaftar di kelas
2. Pastikan `kelas_id` siswa sesuai dengan kelas yang dibimbing wali kelas
3. Pastikan relasi `wali_kelas_id` di tabel kelas sudah benar

### Problem: Admin Tidak Bisa Akses Rapor
**Solusi:**
1. Pastikan role user adalah `'admin'`
2. Cek middleware di routes sudah benar

## Kesimpulan

Sistem akses rapor untuk wali kelas telah diimplementasikan dengan lengkap dan aman. Setiap wali kelas hanya dapat mengakses rapor siswa di kelas yang mereka bimbing, sementara admin memiliki akses penuh. Implementasi menggunakan multi-layer security untuk memastikan data rapor terlindungi dengan baik.
