From bffdb4bef315856505e80c6b243a06dc82ba4708 Mon Sep 17 00:00:00 2001 From: jouel88 Date: Thu, 19 Mar 2026 22:30:01 +0700 Subject: [PATCH] Roles Kantor --- QA_GUIDE.md | 70 ++++++++++++ README.md | 5 + app/Http/Controllers/JadwalController.php | 100 +++++++++++++++--- .../Controllers/PengajuanIzinController.php | 24 ++++- app/Http/Controllers/PresensiController.php | 77 ++++++++++++-- app/Http/Controllers/SuratIzinController.php | 55 ++++++---- 6 files changed, 285 insertions(+), 46 deletions(-) create mode 100644 QA_GUIDE.md diff --git a/QA_GUIDE.md b/QA_GUIDE.md new file mode 100644 index 00000000..34b54da4 --- /dev/null +++ b/QA_GUIDE.md @@ -0,0 +1,70 @@ +# 🛡️ QA & System Testing Guide - MPG HRIS + +Dokumen ini disusun untuk membantu tim Quality Assurance (QA) memahami alur bisnis, aturan validasi, dan skenario pengujian untuk ekosistem MPG HRIS (Web & Mobile). + +--- + +## 👥 1. Matriks Peran & Izin (RBAC) + +Sistem ini menggunakan Role-Based Access Control yang ketat. Berikut adalah daftar akun uji coba default: + +| Role | Email | Password | Cakupan Akses | +| :--- | :--- | :--- | :--- | +| **Super Admin** | `superadmin@mpg.co.id` | `password` | Seluruh data & seluruh kantor (Global). | +| **Admin** | `admin@mpg.co.id` | `admin123` | Manajemen data master & operasional (Global). | +| **Manajer** | (Sesuai User) | `Mpg123!` | Approval Izin & Koreksi Presensi (**Hanya Kantor Sendiri**). | +| **Supervisor** | (Sesuai User) | `Mpg123!` | Management Jadwal Pegawai (**Hanya Kantor Sendiri**). | +| **Pegawai** | `budi@mpg.co.id` | `Mpg123!` | Presensi & Pengajuan Izin via Mobile. | + +--- + +## 🏢 2. Isolasi Data Per Kantor (Feature Highlight) + +Fitur ini memastikan Manajer dan Supervisor **tidak bisa** melihat atau memproses data dari kantor lain. + +**Skenario Test QA:** +1. Login sebagai Manajer Kantor A. +2. Pastikan di Dashboard/Laporan tidak muncul nama pegawai dari Kantor B. +3. Coba akses ID Izin/Presensi dari Kantor B via URL langsung (ID di URL). +4. **Expected Result**: Muncul error 403 (Forbidden) atau redirect kembali dengan pesan error. + +--- + +## 📱 3. Skenario Pengujian Mobile (Pegawai) + +### A. Presensi Real-time +1. **Validasi Radius**: Gunakan Mock Location. Coba absen di luar radius (misal > 100m dari titik kantor). + - **Expected**: Status presensi menjadi "Pending" (menunggu validasi admin) dan muncul peringatan "Di Luar Radius". +2. **Face Recognition**: + - Absen dengan wajah yang sudah terdaftar -> **Lolos**. + - Absen dengan wajah orang lain/foto -> **Gagal/Pending verifikasi**. +3. **Shift Kerja**: Absen sesuai jam shift. Jika lewat toleransi 15 menit, status otomatis "Terlambat". + +### B. Pengajuan Izin/Cuti +1. **Aturan Cuti**: Coba ajukan cuti kurang dari 7 hari dari tanggal mulai (H-7). + - **Expected**: Muncul error "Pengajuan Cuti minimal H-7". +2. **Signature**: Pastikan tanda tangan tersimpan dengan jelas dan muncul di PDF/Web Panel. + +--- + +## 💻 4. Skenario Pengujian Web (Manajer/Admin) + +### A. Alur Persetujuan Izin (Workflow) +1. **Flow**: Pegawai (Mobile) -> Manajer (Approve) -> HRD/Admin (Approve). +2. **Dampak Data**: Setelah disetujui HRD (Final), cek tabel Presensi pegawai tersebut. + - **Expected**: Data presensi otomatis terisi sesuai jenis izin (Cuti/Sakit) pada rentang tanggal tersebut. + +### B. Penjadwalan (Scheduling) +1. **Bulk Create**: Buat jadwal untuk 10 pegawai sekaligus untuk 1 bulan. +2. **Conflict Detect**: Buat jadwal pada tanggal di mana pegawai sudah mengajukan Cuti. + - **Expected**: Muncul peringatan konflik penggunaan poin/cuti. + +--- + +## 🛠️ 5. Prasyarat Teknis QA +- **Web**: Laravel 12, MySQL 8, npm installed. +- **Mobile**: Flutter SDK, Dio, Google ML Kit (Face Detection). +- **Environment**: Pastikan `BASE_URL` di mobile `.env` sudah mengarah ke IP/Domain server Laravel. + +--- +*Dibuat oleh Tim Development MPG* diff --git a/README.md b/README.md index 37ca69f6..0c1a3b12 100644 --- a/README.md +++ b/README.md @@ -61,6 +61,11 @@ ## 📜 Aturan Pengembangan (Project Rules) - `` & ``: Tombol aksi. - ``: Untuk CRUD Data Master sederhana. +## 🛡️ Quality Assurance (QA) & Testing + +Untuk tim QA, silakan merujuk ke dokumen panduan pengujian komprehensif di: +👉 **[QA_GUIDE.md](file:///c:/xampp/htdocs/mpg-hris/QA_GUIDE.md)** + ## 🔑 Akun Default (Seeder) - **Super Admin**: `superadmin@mpg.co.id` / `password` diff --git a/app/Http/Controllers/JadwalController.php b/app/Http/Controllers/JadwalController.php index 485d7fd5..54e54f00 100644 --- a/app/Http/Controllers/JadwalController.php +++ b/app/Http/Controllers/JadwalController.php @@ -17,14 +17,21 @@ class JadwalController extends Controller { public function index() { - $kantor = Kantor::all(); + $user = Auth::user(); + $isGlobalAdmin = $user->isGlobalAdmin(); + + $kantor = $isGlobalAdmin ? Kantor::all() : Kantor::where('id_kantor', $user->id_kantor)->get(); $divisi = Divisi::all(); $shifts = ShiftKerja::all()->map(function ($s) { $s->color = $this->getShiftColor($s->nama_shift); return $s; }); - $pegawai = User::where('status_aktif', 1)->orderBy('nama_lengkap', 'asc')->get(); + $pegawaiQuery = User::where('status_aktif', 1); + if (!$isGlobalAdmin) { + $pegawaiQuery->where('id_kantor', $user->id_kantor); + } + $pegawai = $pegawaiQuery->orderBy('nama_lengkap', 'asc')->get(); return view('jadwal.index', compact('kantor', 'divisi', 'shifts', 'pegawai')); } @@ -34,16 +41,32 @@ public function getEvents(Request $request) $start = Carbon::parse($request->start)->format('Y-m-d'); $end = Carbon::parse($request->end)->format('Y-m-d'); + $user = Auth::user(); + $isGlobalAdmin = $user->isGlobalAdmin(); + $query = JadwalKerja::with(['user.kantor', 'user.jabatan', 'shift']) ->whereDate('tanggal', '>=', $start) ->whereDate('tanggal', '<=', $end); - if ($request->filled('filter_kantor') && $request->filter_kantor != "") { - $query->whereHas('user', function ($q) use ($request) { - $q->where('id_kantor', $request->filter_kantor); + if (!$isGlobalAdmin) { + $query->whereHas('user', function ($q) use ($user) { + $q->where('id_kantor', $user->id_kantor); }); } + if ($request->filled('filter_kantor') && $request->filter_kantor != "") { + // Jika bukan admin, pastikan filter_kantor sesuai dengan kantornya + if (!$isGlobalAdmin && $request->filter_kantor != $user->id_kantor) { + $query->whereHas('user', function ($q) use ($user) { + $q->where('id_kantor', $user->id_kantor); + }); + } else { + $query->whereHas('user', function ($q) use ($request) { + $q->where('id_kantor', $request->filter_kantor); + }); + } + } + if ($request->filled('filter_divisi') && $request->filter_divisi != "") { $query->whereHas('user', function ($q) use ($request) { $q->where('id_divisi', $request->filter_divisi); @@ -129,12 +152,12 @@ public function getEvents(Request $request) $hariLibursQuery = \App\Models\HariLibur::whereBetween('tanggal', [$start, $end]); if ($request->filled('filter_kantor') && $request->filter_kantor != "") { - $hariLibursQuery->where(function($q) use ($request) { + $hariLibursQuery->where(function ($q) use ($request) { $q->whereNull('id_kantor')->orWhere('id_kantor', $request->filter_kantor); }); } $hariLiburs = $hariLibursQuery->get(); - + foreach ($hariLiburs as $hl) { $events[] = [ 'id' => 'libur-' . $hl->id, @@ -173,14 +196,18 @@ private function getShiftColor($namaShift) public function create() { + $user = Auth::user(); + $isGlobalAdmin = $user->isGlobalAdmin(); + $shifts = ShiftKerja::all(); - $kantor = Kantor::all(); + $kantor = $isGlobalAdmin ? Kantor::all() : Kantor::where('id_kantor', $user->id_kantor)->get(); $divisi = Divisi::all(); - $pegawai = User::where('status_aktif', 1) - ->with(['kantor', 'jabatan']) - ->orderBy('nama_lengkap', 'asc') - ->get(); + $pegawaiQuery = User::where('status_aktif', 1)->with(['kantor', 'jabatan']); + if (!$isGlobalAdmin) { + $pegawaiQuery->where('id_kantor', $user->id_kantor); + } + $pegawai = $pegawaiQuery->orderBy('nama_lengkap', 'asc')->get(); return view('jadwal.create', compact('shifts', 'pegawai', 'kantor', 'divisi')); } @@ -195,6 +222,20 @@ public function store(Request $request) 'user_ids.*' => 'exists:users,id', ]); + $user = Auth::user(); + $isGlobalAdmin = $user->isGlobalAdmin(); + + // Validasi Kantor (Security Check) + if (!$isGlobalAdmin) { + $invalidUsers = User::whereIn('id', $request->user_ids) + ->where('id_kantor', '!=', $user->id_kantor) + ->exists(); + + if ($invalidUsers) { + return redirect()->back()->with('error', 'Anda tidak diizinkan membuat jadwal untuk karyawan di luar kantor Anda.'); + } + } + $startDate = Carbon::parse($request->tanggal_mulai); $endDate = Carbon::parse($request->tanggal_selesai); $period = \Carbon\CarbonPeriod::create($startDate, $endDate); @@ -216,10 +257,10 @@ public function store(Request $request) foreach ($userIds as $userId) { $user = $usersData->get($userId); - $isLibur = $libursDate->contains(function($libur) use ($user) { - return is_null($libur->id_kantor) || ($user && $libur->id_kantor == $user->id_kantor); + $isLibur = $libursDate->contains(function ($libur) use ($user) { + return is_null($libur->id_kantor) || ($user && $libur->id_kantor == $user->id_kantor); }); - + if ($isLibur) { continue; } @@ -249,7 +290,6 @@ public function store(Request $request) } return redirect()->route('jadwal.index')->with('success', $message); - } catch (\Exception $e) { return redirect()->back()->with('error', 'Terjadi kesalahan: ' . $e->getMessage()); } @@ -262,6 +302,13 @@ public function update(Request $request, $id) ]); $jadwal = JadwalKerja::findOrFail($id); + $user = Auth::user(); + + // Security Check + if (!$user->isGlobalAdmin() && $jadwal->user->id_kantor != $user->id_kantor) { + return response()->json(['success' => false, 'message' => 'Anda tidak diizinkan mengubah jadwal karyawan di luar kantor Anda.'], 403); + } + $warningMsg = null; try { @@ -284,7 +331,6 @@ public function update(Request $request, $id) 'success' => true, 'message' => $warningMsg ?? 'Jadwal berhasil diperbarui' ]); - } catch (\Exception $e) { return response()->json(['success' => false, 'message' => $e->getMessage()], 500); } @@ -293,6 +339,13 @@ public function update(Request $request, $id) public function destroy($id) { $jadwal = JadwalKerja::findOrFail($id); + $user = Auth::user(); + + // Security Check + if (!$user->isGlobalAdmin() && $jadwal->user->id_kantor != $user->id_kantor) { + return response()->json(['success' => false, 'message' => 'Anda tidak diizinkan menghapus jadwal karyawan di luar kantor Anda.'], 403); + } + $jadwal->delete(); return response()->json(['success' => true, 'message' => 'Jadwal berhasil dihapus']); @@ -307,6 +360,19 @@ public function bulkDestroy(Request $request) 'user_ids.*' => 'exists:users,id', ]); + $user = Auth::user(); + $isGlobalAdmin = $user->isGlobalAdmin(); + + if (!$isGlobalAdmin) { + $invalidUsers = User::whereIn('id', $request->user_ids) + ->where('id_kantor', '!=', $user->id_kantor) + ->exists(); + + if ($invalidUsers) { + return redirect()->back()->with('error', 'Anda tidak diizinkan menghapus jadwal karyawan di luar kantor Anda.'); + } + } + try { DB::transaction(function () use ($request) { JadwalKerja::whereIn('id_user', $request->user_ids) diff --git a/app/Http/Controllers/PengajuanIzinController.php b/app/Http/Controllers/PengajuanIzinController.php index 63a34cd0..9649dff6 100644 --- a/app/Http/Controllers/PengajuanIzinController.php +++ b/app/Http/Controllers/PengajuanIzinController.php @@ -19,9 +19,17 @@ class PengajuanIzinController extends Controller public function index(Request $request) { $statusId = $request->get('status'); + $user = Auth::user(); + $isGlobalAdmin = $user->isGlobalAdmin(); $query = PengajuanIzin::with(['user', 'jenisIzin', 'statusPengajuan', 'suratIzin']); + if (!$isGlobalAdmin) { + $query->whereHas('user', function ($q) use ($user) { + $q->where('id_kantor', $user->id_kantor); + }); + } + if ($statusId) { $query->where('id_status', $statusId); } @@ -121,7 +129,13 @@ public function approve($id) try { DB::beginTransaction(); - $izin = PengajuanIzin::with('jenisIzin')->findOrFail($id); + $izin = PengajuanIzin::with(['jenisIzin', 'user'])->findOrFail($id); + $user = Auth::user(); + + // Security Check + if (!$user->isGlobalAdmin() && $izin->user->id_kantor != $user->id_kantor) { + return redirect()->back()->with('error', 'Anda tidak diizinkan menyetujui pengajuan dari kantor lain.'); + } if ($izin->id_status !== 1) { return redirect()->back()->with('error', 'Pengajuan ini sudah diproses sebelumnya.'); @@ -178,7 +192,13 @@ public function approve($id) public function reject(Request $request, $id) { - $izin = PengajuanIzin::findOrFail($id); + $izin = PengajuanIzin::with('user')->findOrFail($id); + $user = Auth::user(); + + // Security Check + if (!$user->isGlobalAdmin() && $izin->user->id_kantor != $user->id_kantor) { + return redirect()->back()->with('error', 'Anda tidak diizinkan menolak pengajuan dari kantor lain.'); + } if ($izin->id_status !== 1) { return redirect()->back()->with('error', 'Pengajuan ini sudah diproses sebelumnya.'); diff --git a/app/Http/Controllers/PresensiController.php b/app/Http/Controllers/PresensiController.php index b4995d67..3aad89bd 100644 --- a/app/Http/Controllers/PresensiController.php +++ b/app/Http/Controllers/PresensiController.php @@ -17,11 +17,20 @@ class PresensiController extends Controller { public function index(Request $request) { + $user = Auth::user(); + $isGlobalAdmin = $user->isGlobalAdmin(); + $tanggal = $request->get('tanggal', Carbon::today()->format('Y-m-d')); $divisiId = $request->get('divisi_id'); - $pendingDates = Presensi::where('id_validasi', 2) - ->selectRaw('DATE(tanggal) as tgl, COUNT(*) as jumlah') + $pendingQuery = Presensi::where('id_validasi', 2); + if (!$isGlobalAdmin) { + $pendingQuery->whereHas('user', function ($q) use ($user) { + $q->where('id_kantor', $user->id_kantor); + }); + } + + $pendingDates = $pendingQuery->selectRaw('DATE(tanggal) as tgl, COUNT(*) as jumlah') ->groupBy('tgl') ->orderBy('tgl', 'desc') ->get(); @@ -29,6 +38,12 @@ public function index(Request $request) $query = Presensi::with(['user.jabatan', 'user.kantor']) ->whereDate('tanggal', $tanggal); + if (!$isGlobalAdmin) { + $query->whereHas('user', function ($q) use ($user) { + $q->where('id_kantor', $user->id_kantor); + }); + } + if ($divisiId) { $query->whereHas('user', function ($q) use ($divisiId) { $q->where('id_divisi', $divisiId); @@ -109,7 +124,7 @@ public function index(Request $request) $item->jarak_masuk = null; if ($item->user && $item->user->kantor && $item->lat_masuk && $item->lon_masuk) { - $item->jarak_masuk = app(self::class)->calculateDistance( + $item->jarak_masuk = $this->calculateDistance( $item->lat_masuk, $item->lon_masuk, $item->user->kantor->latitude, @@ -131,7 +146,13 @@ public function index(Request $request) public function approve($id) { - $presensi = Presensi::findOrFail($id); + $presensi = Presensi::with('user')->findOrFail($id); + $user = Auth::user(); + + if (!$user->isGlobalAdmin() && $presensi->user->id_kantor != $user->id_kantor) { + return redirect()->back()->with('error', 'Anda tidak diizinkan menyetujui presensi dari kantor lain.'); + } + $presensi->update(['id_validasi' => 1]); return redirect()->back()->with('success', 'Presensi berhasil disetujui.'); @@ -139,7 +160,13 @@ public function approve($id) public function reject($id) { - $presensi = Presensi::findOrFail($id); + $presensi = Presensi::with('user')->findOrFail($id); + $user = Auth::user(); + + if (!$user->isGlobalAdmin() && $presensi->user->id_kantor != $user->id_kantor) { + return redirect()->back()->with('error', 'Anda tidak diizinkan menolak presensi dari kantor lain.'); + } + $presensi->update(['id_validasi' => 3]); return redirect()->back()->with('success', 'Presensi berhasil ditolak.'); @@ -152,6 +179,19 @@ public function bulkAction(Request $request) 'action' => 'required|in:approve,reject' ]); + $user = Auth::user(); + if (!$user->isGlobalAdmin()) { + $invalidCount = Presensi::whereIn('id_presensi', $request->presensi_ids) + ->whereHas('user', function ($q) use ($user) { + $q->where('id_kantor', '!=', $user->id_kantor); + }) + ->count(); + + if ($invalidCount > 0) { + return redirect()->back()->with('error', 'Terdapat data dari kantor lain dalam pilihan Anda.'); + } + } + $statusValidasi = $request->action == 'approve' ? 1 : 3; Presensi::whereIn('id_presensi', $request->presensi_ids) @@ -164,9 +204,17 @@ public function bulkAction(Request $request) public function create() { - $pegawai = \App\Models\User::with('divisi') - ->orderBy('nama_lengkap', 'asc') - ->get(); + $user = Auth::user(); + $isGlobalAdmin = $user->isGlobalAdmin(); + + $pegawaiQuery = \App\Models\User::with('divisi') + ->orderBy('nama_lengkap', 'asc'); + + if (!$isGlobalAdmin) { + $pegawaiQuery->where('id_kantor', $user->id_kantor); + } + + $pegawai = $pegawaiQuery->get(); $statuses = \Illuminate\Support\Facades\DB::table('status_presensi')->get(); @@ -213,6 +261,12 @@ public function storeManual(StoreManualPresensiRequest $request) public function edit($id) { $presensi = Presensi::with('user.divisi')->findOrFail($id); + $user = Auth::user(); + + if (!$user->isGlobalAdmin() && $presensi->user->id_kantor != $user->id_kantor) { + abort(403, 'Anda tidak diizinkan mengedit presensi dari kantor lain.'); + } + $statuses = \Illuminate\Support\Facades\DB::table('status_presensi')->get(); return view('presensi.edit', compact('presensi', 'statuses')); @@ -220,6 +274,13 @@ public function edit($id) public function updateManual(Request $request, $id) { + $presensi = Presensi::with('user')->findOrFail($id); + $user = Auth::user(); + + if (!$user->isGlobalAdmin() && $presensi->user->id_kantor != $user->id_kantor) { + return redirect()->back()->with('error', 'Anda tidak diizinkan mengoreksi presensi dari kantor lain.'); + } + $request->validate([ 'id_status' => 'required|exists:status_presensi,id_status', 'jam_masuk' => [ diff --git a/app/Http/Controllers/SuratIzinController.php b/app/Http/Controllers/SuratIzinController.php index 49f04487..74314346 100644 --- a/app/Http/Controllers/SuratIzinController.php +++ b/app/Http/Controllers/SuratIzinController.php @@ -15,8 +15,17 @@ class SuratIzinController extends Controller { public function index(Request $request) { + $user = Auth::user(); + $isGlobalAdmin = $user->isGlobalAdmin(); + $query = SuratIzin::with(['user', 'pengajuanIzin.jenisIzin', 'approvals.approver']); + if (!$isGlobalAdmin) { + $query->whereHas('user', function ($q) use ($user) { + $q->where('id_kantor', $user->id_kantor); + }); + } + if ($request->filled('status')) { $query->where('status_surat', $request->status); } @@ -44,17 +53,19 @@ public function show($id) ])->findOrFail($id); $user = Auth::user(); + $isGlobalAdmin = $user->isGlobalAdmin(); + + // Security Check: Office Isolation + if (!$isGlobalAdmin && $surat->user->id_kantor != $user->id_kantor) { + abort(403, 'Anda tidak diizinkan mengakses data dari kantor lain.'); + } + $canApprove = false; - $tahapApproval = null; - $isSuperAdmin = $user->roles->contains(function ($role) { - return in_array(strtolower($role->nama_role), ['admin', 'super admin', 'super_admin']); - }); - - if ($surat->status_surat === 'menunggu_manajer' && ($user->roles->contains('nama_role', 'manajer') || $isSuperAdmin)) { + if ($surat->status_surat === 'menunggu_manajer' && ($user->roles->contains('nama_role', 'manajer') || $isGlobalAdmin)) { $canApprove = true; $tahapApproval = 1; - } elseif ($surat->status_surat === 'menunggu_hrd' && ($user->roles->contains('nama_role', 'hrd') || $isSuperAdmin)) { + } elseif ($surat->status_surat === 'menunggu_hrd' && ($user->roles->contains('nama_role', 'hrd') || $isGlobalAdmin)) { $canApprove = true; $tahapApproval = 2; } @@ -67,21 +78,24 @@ public function show($id) public function approve(Request $request, $id) { try { - $surat = SuratIzin::findOrFail($id); + $surat = SuratIzin::with('user')->findOrFail($id); $user = Auth::user(); + $isGlobalAdmin = $user->isGlobalAdmin(); + + // Security Check + if (!$isGlobalAdmin && $surat->user->id_kantor != $user->id_kantor) { + return redirect()->back()->with('error', 'Anda tidak diizinkan menyetujui surat dari karyawan kantor lain.'); + } if (in_array($surat->status_surat, ['disetujui', 'ditolak'])) { return redirect()->back()->with('error', 'Surat ini sudah diproses sebelumnya.'); } $tahap = null; - $isSuperAdmin = $user->roles->contains(function ($role) { - return in_array(strtolower($role->nama_role), ['admin', 'super admin', 'super_admin']); - }); - if ($surat->status_surat === 'menunggu_manajer' && ($user->roles->contains('nama_role', 'manajer') || $isSuperAdmin)) { + if ($surat->status_surat === 'menunggu_manajer' && ($user->roles->contains('nama_role', 'manajer') || $isGlobalAdmin)) { $tahap = 1; - } elseif ($surat->status_surat === 'menunggu_hrd' && ($user->roles->contains('nama_role', 'hrd') || $isSuperAdmin)) { + } elseif ($surat->status_surat === 'menunggu_hrd' && ($user->roles->contains('nama_role', 'hrd') || $isGlobalAdmin)) { $tahap = 2; } @@ -126,21 +140,24 @@ public function approve(Request $request, $id) public function reject(Request $request, $id) { try { - $surat = SuratIzin::findOrFail($id); + $surat = SuratIzin::with('user')->findOrFail($id); $user = Auth::user(); + $isGlobalAdmin = $user->isGlobalAdmin(); + + // Security Check + if (!$isGlobalAdmin && $surat->user->id_kantor != $user->id_kantor) { + return redirect()->back()->with('error', 'Anda tidak diizinkan menolak surat dari karyawan kantor lain.'); + } if (in_array($surat->status_surat, ['disetujui', 'ditolak'])) { return redirect()->back()->with('error', 'Surat ini sudah diproses sebelumnya.'); } $tahap = null; - $isSuperAdmin = $user->roles->contains(function ($role) { - return in_array(strtolower($role->nama_role), ['admin', 'super admin', 'super_admin']); - }); - if ($surat->status_surat === 'menunggu_manajer' && ($user->roles->contains('nama_role', 'manajer') || $isSuperAdmin)) { + if ($surat->status_surat === 'menunggu_manajer' && ($user->roles->contains('nama_role', 'manajer') || $isGlobalAdmin)) { $tahap = 1; - } elseif ($surat->status_surat === 'menunggu_hrd' && ($user->roles->contains('nama_role', 'hrd') || $isSuperAdmin)) { + } elseif ($surat->status_surat === 'menunggu_hrd' && ($user->roles->contains('nama_role', 'hrd') || $isGlobalAdmin)) { $tahap = 2; }