diff --git a/app/Http/Controllers/DashboardController.php b/app/Http/Controllers/DashboardController.php index 156d526..887c577 100644 --- a/app/Http/Controllers/DashboardController.php +++ b/app/Http/Controllers/DashboardController.php @@ -1349,7 +1349,7 @@ class DashboardController extends Controller $id_unit_kerja = $data['id_unit_kerja']; } list($id_sub_unit_kerja, $nama_sub_unit_kerja) = explode('/', $data['id_sub_unit_kerja'],2); - if($data['master_kategori_directory_id']){ + if(isset($data['master_kategori_directory_id'])){ list($master_kategori_directory_id, $nama_kategori) = explode('/', $data['master_kategori_directory_id'],2); } if(isset($data['akre'])){ @@ -1372,10 +1372,7 @@ class DashboardController extends Controller $requiresTurtApproval = !empty($master_kategori_directory_id); $mutuStatus = $isKomiteMutu && $requiresMutuApproval ? 'approved' : null; $turtStatus = $isTurt && $requiresTurtApproval ? 'approved' : null; - $finalApproved = $isAtasan - && (!$requiresMutuApproval || $mutuStatus === 'approved') - && (!$requiresTurtApproval || $turtStatus === 'approved'); - $status = $finalApproved ? 'approved' : null; + $status = $isAtasan ? 'approved' : null; $payload = [ 'id_unit_kerja' => $id_unit_kerja, 'id_sub_unit_kerja' => $id_sub_unit_kerja, @@ -1401,18 +1398,18 @@ class DashboardController extends Controller ]; $fd = FileDirectory::create($payload); - // $disk = Storage::disk('s3'); + $disk = Storage::disk('s3'); $imageName = $this->buildStoredFileName( $fd->nama_dokumen ?? null, $fd->file_directory_id, $uploadedFile->getClientOriginalExtension() ); - // $disk->putFileAs( - // $path, - // $uploadedFile, - // $imageName, - // ['visibility' => 'private'] - // ); + $disk->putFileAs( + $path, + $uploadedFile, + $imageName, + ['visibility' => 'private'] + ); $fd->update([ 'file' => $path . '/' . $imageName ]); @@ -1446,7 +1443,7 @@ class DashboardController extends Controller $payloadNotificationMutu = [ 'created_at' => now(), 'text_notifikasi' => "Dokumen {$docNumber} memerlukan persetujuan. Diunggah oleh " . auth()->user()->dataUser->namalengkap, - 'url' => '/pengajuan-file', + 'url' => '/pending-file', 'is_read' => false, 'unit_id' => 51, ]; @@ -1457,7 +1454,7 @@ class DashboardController extends Controller $payloadNotificationTurt = [ 'created_at' => now(), 'text_notifikasi' => "Dokumen {$docNumber} memerlukan persetujuan. Diunggah oleh " . auth()->user()->dataUser->namalengkap, - 'url' => '/pengajuan-file', + 'url' => '/pending-file', 'is_read' => false, 'unit_id' => 22, ]; @@ -1474,7 +1471,6 @@ class DashboardController extends Controller 'status_action' => $status ], 200); } catch (\Throwable $th) { - dd($th); DB::connection('dbDirectory')->rollback(); return response()->json([ 'status' => false, @@ -1896,19 +1892,23 @@ class DashboardController extends Controller $keyword = request('keyword'); $start = request('start_date'); $end = request('end_date'); + $pegawaiId = auth()->user()->objectpegawaifk; $objectpegawaifk = MappingUnitKerjaPegawai::query() ->where('statusenabled', true) ->where(fn($q) => - $q->where('objectatasanlangsungfk', auth()->user()->objectpegawaifk) - ->orWhere('objectpejabatpenilaifk', auth()->user()->objectpegawaifk) + $q->where('objectatasanlangsungfk', $pegawaiId) + ->orWhere('objectpejabatpenilaifk', $pegawaiId) ) ->pluck('objectpegawaifk') ->unique() ->values() ->all(); + if (!in_array($pegawaiId, $objectpegawaifk, true)) { + $objectpegawaifk[] = $pegawaiId; + } $objectUnit = MappingUnitKerjaPegawai::query() ->where('statusenabled', true) - ->where('objectpegawaifk', auth()->user()->objectpegawaifk) + ->where('objectpegawaifk', $pegawaiId) ->pluck('objectunitkerjapegawaifk') ->unique() ->values() @@ -1916,71 +1916,73 @@ class DashboardController extends Controller $keyword = request('keyword'); $isKomiteMutu = in_array(51, $objectUnit); $isTurt = in_array(22, $objectUnit); + $hasAtasanScope = !empty($objectpegawaifk); // 51 / Komite Mutu // 22 / turt $query = FileDirectory::where('statusenabled', true); - - if ($isKomiteMutu || $isTurt) { - $query->where('status_action', 'approved') - ->where(function ($q) use ($isKomiteMutu, $isTurt) { - if ($isTurt) { - $q->where(function ($sub) { - $sub->whereNotNull('master_kategori_directory_id') - ->where(function ($pendingTurt) { - $pendingTurt->whereNull('status_turt') - ->orWhere('status_turt', 'rejected'); + $query->where(function ($root) use ($isKomiteMutu, $isTurt, $hasAtasanScope, $objectpegawaifk) { + if ($hasAtasanScope) { + $root->where(function ($atasanQuery) use ($objectpegawaifk, $hasAtasanScope) { + $atasanQuery->whereIn('pegawai_id_entry', $objectpegawaifk)->where(function ($qsa) { + $qsa->where('status_action', '!=', 'approved') + ->orWhereNull('status_action') + ->orWhere(function ($approvedButPending) { + $approvedButPending->where(function ($needFurtherApproval) { + $needFurtherApproval + ->where(function ($needTurt) { + $needTurt->whereNotNull('master_kategori_directory_id') + ->where(function ($pendingTurt) { + $pendingTurt->whereNull('status_turt') + ->orWhere('status_turt', 'rejected'); + }); + }) + ->orWhere(function ($needMutu) { + $needMutu->where('is_akre', true) + ->where(function ($pendingMutu) { + $pendingMutu->whereNull('status_mutu') + ->orWhere('status_mutu', 'rejected'); + }); + }); + }); }); }); - } - if ($isKomiteMutu) { - $method = $isTurt ? 'orWhere' : 'where'; - $q->{$method}(function ($sub) { - $sub->where('is_akre', true) - ->where(function ($pendingMutu) { - $pendingMutu->whereNull('status_mutu') - ->orWhere('status_mutu', 'rejected'); - }); - }); - } }); - } else { - $query->where(function ($qsa) { - $qsa->where('status_action', '!=', 'approved') - ->orWhereNull('status_action') - ->orWhere(function ($approvedButPending) { - $approvedButPending->where('status_action', 'approved') - ->where(function ($needFurtherApproval) { - $needFurtherApproval - ->where(function ($needTurt) { - $needTurt->whereNotNull('master_kategori_directory_id') - ->where(function ($pendingTurt) { - $pendingTurt->whereNull('status_turt') - ->orWhere('status_turt', 'rejected'); - }); - }) - ->orWhere(function ($needMutu) { - $needMutu->where('is_akre', true) - ->where(function ($pendingMutu) { - $pendingMutu->whereNull('status_mutu') - ->orWhere('status_mutu', 'rejected'); - }); - }); - }); - }); - }); - } + } + + if ($isKomiteMutu || $isTurt) { + $method = $hasAtasanScope ? 'orWhere' : 'where'; + $root->{$method}(function ($roleQuery) use ($isKomiteMutu, $isTurt) { + $roleQuery->where('status_action', 'approved') + ->where(function ($q) use ($isKomiteMutu, $isTurt) { + if ($isTurt) { + $q->where(function ($sub) { + $sub->whereNotNull('master_kategori_directory_id') + ->where(function ($pendingTurt) { + $pendingTurt->whereNull('status_turt') + ->orWhere('status_turt', 'rejected'); + }); + }); + } + if ($isKomiteMutu) { + $innerMethod = $isTurt ? 'orWhere' : 'where'; + $q->{$innerMethod}(function ($sub) { + $sub->where('is_akre', true) + ->where(function ($pendingMutu) { + $pendingMutu->whereNull('status_mutu') + ->orWhere('status_mutu', 'rejected'); + }); + }); + } + }); + }); + } + }); $query->when($keyword, function ($q) use ($keyword) { $q->where(function ($sub) use ($keyword) { $sub->where('nama_dokumen', 'ILIKE', "%{$keyword}%") ->orWhere('no_dokumen', 'ILIKE', "%{$keyword}%"); }); }); - if(!empty($objectpegawaifk) && !$isKomiteMutu && !$isTurt){ - $query->whereIn('pegawai_id_entry', $objectpegawaifk); - } - - - if($start){ $query->whereDate('entry_at','>=',$start); } @@ -1989,7 +1991,7 @@ class DashboardController extends Controller } $paginated = $query->paginate($perPage); - $data = $paginated->getCollection()->map(function($item){ + $data = $paginated->getCollection()->map(function($item) use($objectpegawaifk){ $dataSlice = array_values(array_filter(explode('/', $item->file))); return [ 'file_directory_id' => $item->file_directory_id, @@ -2013,6 +2015,9 @@ class DashboardController extends Controller 'id_sub_unit_kerja' => $item->id_sub_unit_kerja, 'master_kategori_directory_id' => $item->master_kategori_directory_id, 'is_akre' => $item->is_akre, + 'can_approve_atasan' => in_array($item->pegawai_id_entry, $objectpegawaifk), + 'can_edit_submission' => (int) $item->pegawai_id_entry === (int) $pegawaiId, + 'revision' => $item->revision, ]; }); return response()->json([ @@ -2040,10 +2045,29 @@ class DashboardController extends Controller 'message' => 'Data tidak ditemukan' ], 404); } + $objectUnit = MappingUnitKerjaPegawai::query() + ->where('statusenabled', true) + ->where('objectpegawaifk', auth()->user()->objectpegawaifk) + ->pluck('objectunitkerjapegawaifk') + ->unique() + ->values() + ->all(); + $requiresMutuApproval = $data->is_akre; + $requiresTurtApproval = $data->master_kategori_directory_id; + $isKomiteMutu = in_array(51, $objectUnit); + $isTurt = in_array(22, $objectUnit); + $mutuStatus = $isKomiteMutu && $requiresMutuApproval ? 'approved' : null; + $turtStatus = $isTurt && $requiresTurtApproval ? 'approved' : null; $data->update([ 'status_action' => 'approved', 'action_at' => now(), 'action_by' => auth()->user()->dataUser->id, + 'status_mutu' => $mutuStatus, + 'action_mutu_at' => $mutuStatus === 'approved' ? now() : null, + 'action_mutu_by' => $mutuStatus === 'approved' ? auth()->user()->objectpegawaifk : null, + 'status_turt' => $turtStatus, + 'action_turt_at' => $turtStatus === 'approved' ? now() : null, + 'action_turt_by' => $turtStatus === 'approved' ? auth()->user()->objectpegawaifk : null, ]); $parts = array_values(array_filter(explode('/', $data->file))); @@ -2318,23 +2342,77 @@ class DashboardController extends Controller public function countDataPending(){ try { + $pegawaiId = auth()->user()->objectpegawaifk; $objectpegawaifk = MappingUnitKerjaPegawai::query() ->where('statusenabled', true) ->where(fn($q) => - $q->where('objectatasanlangsungfk', auth()->user()->objectpegawaifk) - ->orWhere('objectpejabatpenilaifk', auth()->user()->objectpegawaifk) + $q->where('objectatasanlangsungfk', $pegawaiId) + ->orWhere('objectpejabatpenilaifk', $pegawaiId) ) ->pluck('objectpegawaifk') ->unique() ->values() ->all(); - $count = FileDirectory::where('statusenabled', true)->whereIn('pegawai_id_entry', $objectpegawaifk) - ->where(function($q){ - $q->whereNotIn('status_action', ['approved', 'rejected'])->orWhereNull('status_action'); - })->count(); - // $authUnit = auth()->user()->masterPersetujuan->details->pluck('unit_pegawai_id')->unique()->toArray(); - // $count= $query->whereIn('id_unit_kerja', $authUnit)->count(); - // $count = $query-> + if (!in_array($pegawaiId, $objectpegawaifk, true)) { + $objectpegawaifk[] = $pegawaiId; + } + $objectUnit = MappingUnitKerjaPegawai::query() + ->where('statusenabled', true) + ->where('objectpegawaifk', $pegawaiId) + ->pluck('objectunitkerjapegawaifk') + ->unique() + ->values() + ->all(); + $isKomiteMutu = in_array(51, $objectUnit); + $isTurt = in_array(22, $objectUnit); + $hasAtasanScope = !empty($objectpegawaifk); + + $query = FileDirectory::where('statusenabled', true); + $query->where(function ($root) use ($isKomiteMutu, $isTurt, $hasAtasanScope, $objectpegawaifk) { + if ($hasAtasanScope) { + $root->where(function ($atasanQuery) use ($objectpegawaifk) { + $atasanQuery->whereIn('pegawai_id_entry', $objectpegawaifk) + ->where(function ($qsa) { + $qsa->where('status_action', '!=', 'approved') + ->where(function ($notRejected) { + $notRejected->where('status_action', '!=', 'rejected') + ->orWhereNull('status_action'); + }) + ->orWhereNull('status_action'); + }); + }); + } + + if ($isKomiteMutu || $isTurt) { + $method = $hasAtasanScope ? 'orWhere' : 'where'; + $root->{$method}(function ($roleQuery) use ($isKomiteMutu, $isTurt) { + $roleQuery->where('status_action', 'approved') + ->where(function ($q) use ($isKomiteMutu, $isTurt) { + if ($isTurt) { + $q->where(function ($sub) { + $sub->whereNotNull('master_kategori_directory_id') + ->where(function ($pendingTurt) { + $pendingTurt->whereNull('status_turt') + ->orWhere('status_turt', 'rejected'); + }); + }); + } + if ($isKomiteMutu) { + $innerMethod = $isTurt ? 'orWhere' : 'where'; + $q->{$innerMethod}(function ($sub) { + $sub->where('is_akre', true) + ->where(function ($pendingMutu) { + $pendingMutu->whereNull('status_mutu') + ->orWhere('status_mutu', 'rejected'); + }); + }); + } + }); + }); + } + }); + + $count = $query->count(); return response()->json([ 'status' => true, 'count' => $count, @@ -2401,7 +2479,8 @@ class DashboardController extends Controller $query = Notifkasi::query(); $query->where(function($q) use($pegawaiId, $objectUnit, $isKomiteMutu, $isTurt){ if($isKomiteMutu || $isTurt){ - $q->orWhere(function($sub) use($objectUnit){ + $q->where('pegawai_id', $pegawaiId) + ->orWhere(function($sub) use($objectUnit){ $sub->whereNull('pegawai_id')->whereIn('unit_id', $objectUnit); }); }else{ @@ -2438,7 +2517,7 @@ class DashboardController extends Controller ]); } - $pegawaiId = auth()->user()?->dataUser?->id; + $pegawaiId = auth()->user()?->objectpegawaifk; $objectUnit = MappingUnitKerjaPegawai::query() ->where('statusenabled', true) ->where('objectpegawaifk', auth()->user()->objectpegawaifk) @@ -2458,7 +2537,8 @@ class DashboardController extends Controller $query = Notifkasi::query(); $query->where(function($q) use($pegawaiId, $isKomiteMutu, $isTurt, $objectUnit){ if($isKomiteMutu || $isTurt){ - $q->orWhere(function($sub) use($objectUnit){ + $q->where('pegawai_id', $pegawaiId) + ->orWhere(function($sub) use($objectUnit){ $sub->whereNull('pegawai_id')->whereIn('unit_id', $objectUnit); }); }else{ @@ -2705,20 +2785,29 @@ class DashboardController extends Controller $katDok = MasterKategori::where('statusenabled', true) ->select('master_kategori_directory_id', 'nama_kategori_directory') ->get(); + $pegawaiId = auth()->user()->objectpegawaifk; $objectUnit = MappingUnitKerjaPegawai::query() ->where('statusenabled', true) - ->where('objectpegawaifk', auth()->user()->objectpegawaifk) + ->where('objectpegawaifk', $pegawaiId) ->pluck('objectunitkerjapegawaifk') ->unique() ->values() ->all(); $isKomiteMutu = in_array(51, $objectUnit); $isTurt = in_array(22, $objectUnit); + $isAtasan = MappingUnitKerjaPegawai::query() + ->where('statusenabled', true) + ->where(function ($q) use ($pegawaiId) { + $q->where('objectatasanlangsungfk', $pegawaiId) + ->orWhere('objectpejabatpenilaifk', $pegawaiId); + }) + ->exists(); return view('pengajuanFile.index', [ 'title' => 'Data Persetujuan', 'katDok' => $katDok, 'isKomiteMutu' => $isKomiteMutu, - 'isTurt' => $isTurt + 'isTurt' => $isTurt, + 'isAtasan' => $isAtasan, ]); } @@ -2739,29 +2828,65 @@ class DashboardController extends Controller ->all(); $isKomiteMutu = in_array(51, $objectUnit); $isTurt = in_array(22, $objectUnit); + $isAtasan = MappingUnitKerjaPegawai::query() + ->where('statusenabled', true) + ->where(function ($q) use ($pegawaiId) { + $q->where('objectatasanlangsungfk', $pegawaiId) + ->orWhere('objectpejabatpenilaifk', $pegawaiId); + }) + ->exists(); $query = FileDirectory::with('kategori')->where('statusenabled', true); - if ($mode === 'persetujuan' && ($isKomiteMutu || $isTurt)) { - $query->where(function ($q) use ($isKomiteMutu, $isTurt) { - if ($isTurt) { - $q->whereNotNull('master_kategori_directory_id') - ->where(function ($pendingTurt) { - $pendingTurt->whereNull('status_turt') - ->orWhere('status_turt', 'rejected'); - }); + if ($mode === 'persetujuan' && ($isKomiteMutu || $isTurt || $isAtasan)) { + $query->where(function ($root) use ($isKomiteMutu, $isTurt, $isAtasan, $pegawaiId) { + if ($isKomiteMutu || $isTurt) { + $root->where(function ($q) use ($isKomiteMutu, $isTurt) { + if ($isTurt) { + $q->whereNotNull('master_kategori_directory_id') + ->where(function ($pendingTurt) { + $pendingTurt->whereNull('status_turt') + ->orWhere('status_turt', 'rejected'); + }); + } + if ($isKomiteMutu) { + $method = $isTurt ? 'orWhere' : 'where'; + $q->{$method}(function ($sub) { + $sub->where('is_akre', true) + ->where(function ($pendingMutu) { + $pendingMutu->whereNull('status_mutu') + ->orWhere('status_mutu', 'rejected'); + }); + }); + } + })->where('status_action', 'approved'); } - if ($isKomiteMutu) { - $method = $isTurt ? 'orWhere' : 'where'; - $q->{$method}(function ($sub) { - $sub->where('is_akre', true) - ->where(function ($pendingMutu) { - $pendingMutu->whereNull('status_mutu') - ->orWhere('status_mutu', 'rejected'); + + if ($isAtasan) { + $method = ($isKomiteMutu || $isTurt) ? 'orWhere' : 'where'; + $root->{$method}(function ($ownSubmission) use ($pegawaiId) { + $ownSubmission->where('pegawai_id_entry', $pegawaiId) + ->where('status_action', 'approved') + ->where(function ($needFurtherApproval) { + $needFurtherApproval + ->where(function ($needTurt) { + $needTurt->whereNotNull('master_kategori_directory_id') + ->where(function ($pendingTurt) { + $pendingTurt->whereNull('status_turt') + ->orWhere('status_turt', 'rejected'); + }); + }) + ->orWhere(function ($needMutu) { + $needMutu->where('is_akre', true) + ->where(function ($pendingMutu) { + $pendingMutu->whereNull('status_mutu') + ->orWhere('status_mutu', 'rejected'); + }); + }); }); }); } - })->where('status_action', 'approved'); + }); } else { $query->where('pegawai_id_entry', $pegawaiId) ->when($isHistory, function($q){ @@ -3001,9 +3126,10 @@ class DashboardController extends Controller $targetRoleNotifications = []; $resetMutuApproval = $data->status_mutu === 'rejected'; $resetTurtApproval = $data->status_turt === 'rejected'; + $resetAtasanApproval = $data->status_action === 'rejected'; if ($resetMutuApproval) { - $payload['status_mutu'] = null; + $payload['status_mutu'] = 'revised Mutu'; $payload['mutu_revision'] = null; $payload['action_mutu_at'] = null; $payload['action_mutu_by'] = null; @@ -3011,17 +3137,19 @@ class DashboardController extends Controller } if ($resetTurtApproval) { - $payload['status_turt'] = null; + $payload['status_turt'] = 'revised TURT'; $payload['turt_revision'] = null; $payload['action_turt_at'] = null; $payload['action_turt_by'] = null; $targetRoleNotifications[] = 22; } + if($resetAtasanApproval){ + $payload['revision'] = null; + $payload['status_action'] = 'revised'; + $payload['action_at'] = null; + $payload['action_by'] = null; + } - $payload['revision'] = null; - $payload['status_action'] = 'revised'; - $payload['action_at'] = null; - $payload['action_by'] = null; if (!empty($payload)) { @@ -3073,7 +3201,6 @@ class DashboardController extends Controller 'statusenabled' => true, 'nama_dokumen' => $data->nama_dokumen ?? null, 'no_dokumen' => $data->no_dokumen ?? null, - 'mod_change' => 'Reset approval: ' . (!empty($targetRoleNotifications) ? implode(',', $targetRoleNotifications) : 'atasan'), 'id_unit_kerja' => $data ? $data->id_unit_kerja : null, 'id_sub_unit_kerja' => $data ? $data->id_sub_unit_kerja : null, 'action_type' => 'Revisi Dokumen', @@ -3231,6 +3358,7 @@ class DashboardController extends Controller public function dataTableAkreditasi(Request $request) { $keyword = $request->query('keyword'); + $page = max(1, (int) $request->query('page', 1)); $perPage = (int) $request->query('per_page', 10); $perPage = max(1, min(100, $perPage)); @@ -3266,28 +3394,131 @@ class DashboardController extends Controller ->orWhere('file', 'ILIKE', "%{$keyword}%"); // Cari juga berdasarkan nama file di path }); }); - $data = $query - ->orderBy('entry_at', 'desc') - ->paginate($perPage); + $items = $query->get(); + $sortedItems = $this->sortAkreditasiRowsByJffOrder($items->all()); + $total = count($sortedItems); + $offset = ($page - 1) * $perPage; + $pageItems = array_slice($sortedItems, $offset, $perPage); + $lastPage = max(1, (int) ceil($total / $perPage)); return response()->json([ 'status' => true, 'message' => 'Berhasil mendapatkan data', - 'data' => $data->items(), + 'data' => array_values($pageItems), 'pagination' => [ - 'current_page' => $data->currentPage(), - 'next_page' => $data->hasMorePages() ? $data->currentPage() + 1 : null, - 'prev_page' => $data->currentPage() > 1 ? $data->currentPage() - 1 : null, - 'total' => $data->total(), - 'per_page' => $data->perPage(), - 'last_page' => $data->lastPage(), - 'has_more' => $data->hasMorePages(), - 'from' => $data->firstItem(), - 'to' => $data->lastItem(), + 'current_page' => $page, + 'next_page' => $page < $lastPage ? $page + 1 : null, + 'prev_page' => $page > 1 ? $page - 1 : null, + 'total' => $total, + 'per_page' => $perPage, + 'last_page' => $lastPage, + 'has_more' => $page < $lastPage, + 'from' => $total > 0 ? $offset + 1 : 0, + 'to' => $offset + count($pageItems), ] ]); } + private function sortAkreditasiRowsByJffOrder(array $items): array + { + $orderMap = $this->buildAkreditasiOrderMap(); + + usort($items, function ($left, $right) use ($orderMap) { + $leftPath = $this->getAkreditasiFolderPathFromFile($left->file ?? ''); + $rightPath = $this->getAkreditasiFolderPathFromFile($right->file ?? ''); + + $pathCompare = $this->compareAkreditasiPaths($leftPath, $rightPath, $orderMap); + if ($pathCompare !== 0) { + return $pathCompare; + } + + $leftName = Str::lower((string) ($left->nama_dokumen ?? $left->file ?? '')); + $rightName = Str::lower((string) ($right->nama_dokumen ?? $right->file ?? '')); + + return strnatcasecmp($leftName, $rightName); + }); + + return $items; + } + + private function buildAkreditasiOrderMap(): array + { + $path = public_path('json/akreditasi.jff'); + if (!is_file($path)) { + return []; + } + + $raw = @file_get_contents($path); + $data = json_decode($raw ?: '[]', true); + if (!is_array($data)) { + return []; + } + + $orderMap = []; + foreach ($data as $typeIndex => $typeItem) { + $typeName = trim((string) ($typeItem['name'] ?? '')); + if ($typeName === '') { + continue; + } + $orderMap[$typeName] = [$typeIndex, -1, -1]; + + $segments = isset($typeItem['segment']) && is_array($typeItem['segment']) + ? $typeItem['segment'] + : []; + + foreach ($segments as $segmentIndex => $segmentItem) { + $segmentName = trim((string) ($segmentItem['name'] ?? '')); + if ($segmentName === '') { + continue; + } + + $segmentPath = $typeName . '/' . $segmentName; + $orderMap[$segmentPath] = [$typeIndex, $segmentIndex, -1]; + + $children = isset($segmentItem['turunan']) && is_array($segmentItem['turunan']) + ? $segmentItem['turunan'] + : []; + + foreach ($children as $childIndex => $childItem) { + $childName = trim((string) ($childItem['name'] ?? '')); + if ($childName === '') { + continue; + } + + $orderMap[$segmentPath . '/' . $childName] = [$typeIndex, $segmentIndex, $childIndex]; + } + } + } + + return $orderMap; + } + + private function getAkreditasiFolderPathFromFile(?string $filePath): string + { + $parts = array_values(array_filter(explode('/', (string) $filePath))); + if (count($parts) <= 1) { + return ''; + } + + array_pop($parts); + return implode('/', $parts); + } + + private function compareAkreditasiPaths(string $leftPath, string $rightPath, array $orderMap): int + { + $fallback = [PHP_INT_MAX, PHP_INT_MAX, PHP_INT_MAX]; + $leftOrder = $orderMap[$leftPath] ?? $fallback; + $rightOrder = $orderMap[$rightPath] ?? $fallback; + + for ($i = 0; $i < 3; $i++) { + if ($leftOrder[$i] !== $rightOrder[$i]) { + return $leftOrder[$i] <=> $rightOrder[$i]; + } + } + + return strnatcasecmp($leftPath, $rightPath); + } + public function expDokumen(){ $katDok = MasterKategori::where('statusenabled', true)->select('master_kategori_directory_id', 'nama_kategori_directory')->get(); $authMapping = auth()->user()?->dataUser?->mappingUnitKerjaPegawai[0]; @@ -3818,7 +4049,7 @@ class DashboardController extends Controller 'statusenabled' => true, 'nama_dokumen' => $data->nama_dokumen ?? null, 'no_dokumen' => $data->no_dokumen ?? null, - 'mod_change' => $revision, + 'mod_change' => null, 'id_unit_kerja' => $data ? $data->id_unit_kerja : null, 'id_sub_unit_kerja' => $data ? $data->id_sub_unit_kerja : null, 'action_type' => 'Rejected Dokumen Turt', diff --git a/public/js/pendingFile/index.js b/public/js/pendingFile/index.js index b4cabc0..dad946e 100644 --- a/public/js/pendingFile/index.js +++ b/public/js/pendingFile/index.js @@ -115,15 +115,23 @@ document.addEventListener('DOMContentLoaded', () => { return item?.status_action === 'approved'; } + function canApproveAsAtasan(item){ + return item?.can_approve_atasan === true || item?.can_approve_atasan === 1 || item?.can_approve_atasan === '1'; + } + + function canEditSubmission(item){ + return item?.can_edit_submission === true || item?.can_edit_submission === 1 || item?.can_edit_submission === '1'; + } + function getSelectableIdsOnPage(){ return (tableState.data || []) - .filter((item) => !isRejected(item) && !isAtasanApproved(item)) + .filter((item) => !isRejected(item) && !isAtasanApproved(item) && canApproveAsAtasan(item)) .map((item) => String(item.file_directory_id)); } function updateSelectAllState(){ if (!selectAllCheckbox) return; - if (tableState.mode === 'history' || isKomiteMutu || isTurt) { + if (tableState.mode === 'history') { selectAllCheckbox.checked = false; selectAllCheckbox.indeterminate = false; selectAllCheckbox.disabled = true; @@ -145,9 +153,11 @@ document.addEventListener('DOMContentLoaded', () => { function updateSelectionUI(){ const count = selectedIds.size; + const selectableIds = getSelectableIdsOnPage(); + const canBulkApprove = tableState.mode !== 'history' && selectableIds.length > 0; if (selectedCountEl) selectedCountEl.textContent = String(count); - if (bulkApproveBtn) bulkApproveBtn.disabled = count === 0 || tableState.mode === 'history' || isKomiteMutu || isTurt; - if (clearSelectionBtn) clearSelectionBtn.disabled = count === 0 || tableState.mode === 'history' || isKomiteMutu || isTurt; + if (bulkApproveBtn) bulkApproveBtn.disabled = count === 0 || !canBulkApprove; + if (clearSelectionBtn) clearSelectionBtn.disabled = count === 0 || !canBulkApprove; updateSelectAllState(); } @@ -158,6 +168,7 @@ document.addEventListener('DOMContentLoaded', () => { const id = String(item.file_directory_id); const rejected = isRejected(item); const atasanApproved = isAtasanApproved(item); + const canAtasanApprove = canApproveAsAtasan(item); const checked = selectedIds.has(id); const actions = [ ``); + actions.push(``); + } + if (atasanApproved && isKomiteMutu && item.is_akre && item.status_mutu !== 'approved') { actions.push(``); actions.push(``); } - if (isTurt && item.status_turt !== 'approved') { + if (atasanApproved && isTurt && item.master_kategori_directory_id && item.status_turt !== 'approved') { actions.push(``); actions.push(``); } @@ -193,6 +208,14 @@ document.addEventListener('DOMContentLoaded', () => { } } + if (rejected) { + actions.length = 1; + actions.push(``); + if (canEditSubmission(item)) { + actions.push(``); + } + } + const statusContent = (isKomiteMutu || isTurt) ? getWorkflowStatusBadges(item).join(' ') : getWorkflowStatusBadges(item).join(' '); @@ -203,9 +226,9 @@ document.addEventListener('DOMContentLoaded', () => { class="form-check-input row-select" data-id="${id}" ${checked ? 'checked' : ''} - ${(rejected || atasanApproved || isKomiteMutu || isTurt) ? 'disabled' : ''}> + ${(rejected || atasanApproved || !canAtasanApprove) ? 'disabled' : ''}> - ${rejected ? '' : `
${actions.join('')}
`} +
${actions.join('')}
${safeText(item.no_dokumen)} ${statusContent} ${aksesBadge(item?.permission_file)} @@ -454,7 +477,7 @@ document.addEventListener('DOMContentLoaded', () => { showConfirmButton: false }); selectedIds.delete(String(id)); - countData(); + if (typeof window.refreshPendingCount === 'function') window.refreshPendingCount(); fetchData(); }).catch((err) => { Swal.fire({ @@ -511,7 +534,7 @@ document.addEventListener('DOMContentLoaded', () => { showConfirmButton: false }); selectedIds.delete(String(id)); - countData(); + if (typeof window.refreshPendingCount === 'function') window.refreshPendingCount(); fetchData(); }).catch((err) => { Swal.fire({ @@ -532,6 +555,33 @@ document.addEventListener('DOMContentLoaded', () => { }); } + window.infoRejectPending = function(id){ + const item = getItemById(id); + const notes = []; + if (item?.revision) { + notes.push(`Atasan: ${String(item.revision)}`); + } + if (item?.mutu_revision) { + notes.push(`Komite Mutu: ${String(item.mutu_revision)}`); + } + if (item?.turt_revision) { + notes.push(`TURT: ${String(item.turt_revision)}`); + } + + Swal.fire({ + title: 'Catatan Revisi', + text: notes.length ? notes.join('\n\n') : 'Tidak ada catatan revisi.', + icon: 'info', + confirmButtonText: 'Tutup' + }); + } + + window.editRejectedFromPending = function(id){ + const targetUrl = new URL('/pengajuan-file', window.location.origin); + targetUrl.searchParams.set('edit', id); + window.location.href = targetUrl.toString(); + } + window.approvePendingRole = function(type, id, fileName){ const endpoint = type === 'mutu' ? `/pending-file/${id}/approve-mutu` @@ -565,6 +615,7 @@ document.addEventListener('DOMContentLoaded', () => { timer: 1500, showConfirmButton: false }); + if (typeof window.refreshPendingCount === 'function') window.refreshPendingCount(); fetchData(); }).catch((err) => { Swal.fire({ @@ -623,6 +674,7 @@ document.addEventListener('DOMContentLoaded', () => { timer: 1500, showConfirmButton: false }); + if (typeof window.refreshPendingCount === 'function') window.refreshPendingCount(); fetchData(); }).catch((err) => { Swal.fire({ @@ -733,7 +785,7 @@ document.addEventListener('DOMContentLoaded', () => { timer: 1500, showConfirmButton: false }); - countData(); + if (typeof window.refreshPendingCount === 'function') window.refreshPendingCount(); fetchData(); }).catch((err) => { Swal.fire({ diff --git a/public/js/pengajuanFile/index.js b/public/js/pengajuanFile/index.js index 98b3b44..aad39a9 100644 --- a/public/js/pengajuanFile/index.js +++ b/public/js/pengajuanFile/index.js @@ -29,6 +29,7 @@ document.addEventListener('DOMContentLoaded', () => { const selectedIds = new Set(); const isKomiteMutu = !!window.isKomiteMutu; const isTurt = !!window.isTurt; + let editFromQueryId = new URLSearchParams(window.location.search).get('edit'); if (pageSizeSelect) { const initialSize = parseInt(pageSizeSelect.value); @@ -254,8 +255,8 @@ document.addEventListener('DOMContentLoaded', () => { return ` - - -
${actions.join('')}
+ +
${actions.join('')}
${item.no_dokumen || '-'}
${statusParts.join('')}
${aksesBadge(item?.permission_file)} @@ -422,6 +423,19 @@ document.addEventListener('DOMContentLoaded', () => { renderPagination(activeState.lastPage || 1); updateSelectionUI(); + maybeOpenEditFromQuery(); + } + + function maybeOpenEditFromQuery(){ + if (!editFromQueryId || tableState.mode !== 'pengajuan') return; + const item = getItemById(editFromQueryId); + if (!item) return; + const cleanUrl = new URL(window.location.href); + cleanUrl.searchParams.delete('edit'); + window.history.replaceState({}, '', cleanUrl.toString()); + const pendingId = editFromQueryId; + editFromQueryId = null; + window.editFileReject(pendingId); } let searchDebounce; @@ -640,6 +654,7 @@ document.addEventListener('DOMContentLoaded', () => { timer: 1500, showConfirmButton: false }); + if (typeof window.refreshPendingCount === 'function') window.refreshPendingCount(); fetchData(); }).catch((err) => { Swal.fire({ @@ -700,6 +715,7 @@ document.addEventListener('DOMContentLoaded', () => { timer: 1500, showConfirmButton: false }); + if (typeof window.refreshPendingCount === 'function') window.refreshPendingCount(); fetchData(); }).catch((err) => { Swal.fire({ @@ -1120,6 +1136,7 @@ document.addEventListener('DOMContentLoaded', () => { showConfirmButton: false }); $("#modalEditPengajuanFile").modal('hide'); + if (typeof window.refreshPendingCount === 'function') window.refreshPendingCount(); fetchData(); }).catch((err) => { Swal.fire({ @@ -1548,6 +1565,7 @@ document.addEventListener('DOMContentLoaded', () => { const modalInstance = bootstrap.Modal.getInstance(modalCreate); modalInstance?.hide(); resetCreateForm(); + if (typeof window.refreshPendingCount === 'function') window.refreshPendingCount(); fetchData(); if(responseData.status_action === null || responseData.status_action === undefined){ Swal.fire({ diff --git a/resources/views/layout/partials/sidenav.blade.php b/resources/views/layout/partials/sidenav.blade.php index bed5a92..7f2a4a3 100644 --- a/resources/views/layout/partials/sidenav.blade.php +++ b/resources/views/layout/partials/sidenav.blade.php @@ -52,9 +52,21 @@ {{-- AKTIVITAS --}} @php - $isAtasan = \App\Models\MappingUnitKerjaPegawai::where('statusenabled', true)->where('objectatasanlangsungfk', auth()->user()->objectpegawaifk)->exists(); + $pegawaiId = auth()->user()->objectpegawaifk; + $userUnitIds = auth()->user()->dataUser->mappingUnitKerjaPegawai() + ->where('statusenabled', true) + ->pluck('objectunitkerjapegawaifk') + ->unique() + ->values() + ->all(); + $isAtasan = \App\Models\MappingUnitKerjaPegawai::where('statusenabled', true) + ->where(function ($q) use ($pegawaiId) { + $q->where('objectatasanlangsungfk', $pegawaiId) + ->orWhere('objectpejabatpenilaifk', $pegawaiId); + })->exists(); + $isRoleApprover = in_array(51, $userUnitIds, true) || in_array(22, $userUnitIds, true); @endphp - @if($isAtasan) + @if($isAtasan || $isRoleApprover) @if(!Auth::guard('admin')->check()) - @if($isKomiteMutu || $isTurt) + @if($isKomiteMutu || $isTurt || $isAtasan) @@ -158,6 +158,7 @@ window.katDok = @json($katDok); window.isKomiteMutu = @json($isKomiteMutu); window.isTurt = @json($isTurt); + window.isAtasan = @json($isAtasan); @endsection