diff --git a/app/Http/Controllers/AksesFileController.php b/app/Http/Controllers/AksesFileController.php index be85742..5f3dcd1 100644 --- a/app/Http/Controllers/AksesFileController.php +++ b/app/Http/Controllers/AksesFileController.php @@ -3,9 +3,9 @@ namespace App\Http\Controllers; use App\Models\AksesFile; +use App\Models\AksesFileDetail; use App\Models\DataUser; use App\Models\FileDirectory; -use App\Models\MappingUnitKerjaPegawai; use App\Models\UnitKerja; use Carbon\Carbon; use Illuminate\Http\Request; @@ -41,21 +41,25 @@ class AksesFileController extends Controller try { $datas = request('data'); foreach ($datas as $data) { - $pegawai = MappingUnitKerjaPegawai::where(['objectpegawaifk'=> $data['pegawai_id'], 'statusenabled' => true])->first(); $payload = [ 'pegawai_id' => $data['pegawai_id'], 'pegawai_id_entry' => auth()->user()?->dataUser?->id, 'pegawai_nama_entry' => auth()->user()?->dataUser?->namalengkap, 'entry_at' => Carbon::now()->format('Y-m-d H:i:s.u'), + 'all_akses' => $data['akses'] === "all" ? true : false, ]; - if($data['akses'] === "all"){ - $payload['all_akses'] = true; - }else{ - $payload['all_akses'] = false; - $payload['unit_akses'] = $pegawai->objectunitkerjapegawaifk ?? null; - + $af = AksesFile::create($payload); + if($data['akses'] === "unit"){ + $unitIds = collect($data['unit_akses'] ?? [])->filter()->unique()->values(); + foreach ($unitIds as $unitId) { + $payloadDetail = [ + 'akses_file_id' => $af->akses_file_id, + 'statusenabled' => true, + 'id_unit_kerja' => $unitId, + ]; + AksesFileDetail::create($payloadDetail); + } } - AksesFile::create($payload); } DB::connection('dbDirectory')->commit(); return response()->json([ @@ -76,7 +80,55 @@ class AksesFileController extends Controller */ public function show(string $id) { - // + $data = AksesFile::where('akses_file_id', $id)->first(); + if (!$data) { + return response()->json([ + 'status' => false, + 'message' => 'Data tidak ditemukan' + ], 404); + } + + $aksesAll = $data->akses ?? null; + if (is_null($aksesAll)) { + $aksesAll = $data->all_akses ?? null; + } + $aksesType = $aksesAll ? 'all' : 'unit'; + + $units = []; + $detailUnits = AksesFileDetail::where('akses_file_id', $id) + ->where('statusenabled', true) + ->get(); + if ($detailUnits->isNotEmpty()) { + $unitIds = $detailUnits->pluck('id_unit_kerja'); + $units = UnitKerja::whereIn('id', $unitIds) + ->select('id', 'name') + ->get() + ->map(function ($unit) { + return [ + 'id' => $unit->id, + 'text' => $unit->name, + ]; + }) + ->values(); + } elseif (!empty($data->unit_akses)) { + $unit = UnitKerja::where('id', $data->unit_akses)->select('id', 'name')->first(); + if ($unit) { + $units[] = [ + 'id' => $unit->id, + 'text' => $unit->name, + ]; + } + } + + return response()->json([ + 'status' => true, + 'data' => [ + 'akses_type' => $aksesType, + 'pegawai_id' => $data->pegawai_id, + 'pegawai_nama' => $data?->pegawai?->namalengkap, + 'units' => $units, + ] + ], 200); } /** @@ -92,19 +144,40 @@ class AksesFileController extends Controller */ public function update(Request $request, string $id) { + DB::connection('dbDirectory')->beginTransaction(); try { $data = AksesFile::where('akses_file_id', $id)->first(); - $pegawai = MappingUnitKerjaPegawai::where(['objectpegawaifk' => request('pegawai_id'), 'statusenabled' => true])->first(); + if (!$data) { + return response()->json([ + 'status' => false, + 'message' => 'Data tidak ditemukan' + ], 404); + } + $payload = [ 'pegawai_id' => request('pegawai_id'), 'pegawai_id_modified' => auth()->user()?->dataUser?->id, 'pegawai_nama_modified' => auth()->user()?->dataUser?->namalengkap, 'modified_at' => Carbon::now()->format('Y-m-d H:i:s.u'), 'all_akses' => request('akses') === "all" ? true : false, - 'unit_akses' => $pegawai?->objectunitkerjapegawaifk ?? null ]; $data->update($payload); + AksesFileDetail::where('akses_file_id', $id)->delete(); + + if (request('akses') === 'unit') { + $unitIds = collect(request('unit_akses') ?? [])->filter()->unique()->values(); + foreach ($unitIds as $unitId) { + $payloadDetail = [ + 'akses_file_id' => $data->akses_file_id, + 'statusenabled' => true, + 'id_unit_kerja' => $unitId, + ]; + AksesFileDetail::create($payloadDetail); + } + } + + DB::connection('dbDirectory')->commit(); return response()->json([ 'status' => true, 'message' => 'Data berhasil diperbarui', @@ -123,26 +196,43 @@ class AksesFileController extends Controller */ public function destroy(string $id) { - $data = AksesFile::where('akses_file_id', $id)->first(); - if(!$data){ + try { + $data = AksesFile::where('akses_file_id', $id) + ->where('statusenabled', true) + ->first(); + + if (!$data) { + return response()->json([ + 'status' => false, + 'message' => 'Data tidak ditemukan' + ], 404); + } + + DB::transaction(function () use ($id, $data) { + AksesFileDetail::where('akses_file_id', $id) + ->where('statusenabled', true) + ->update(['statusenabled' => false]); + $data->update(['statusenabled' => false]); + }); + + return response()->json([ + 'status' => true, + 'message' => 'Data berhasil dihapus' + ], 200); + + } catch (\Throwable $th) { return response()->json([ 'status' => false, - 'message' => 'Data tidak ditemukan' - ], 404); + 'message' => 'Gagal menghapus data', + ], 500); } - $payload =[ - 'statusenabled' => false - ]; - $data->update($payload); - return response()->json([ - 'status' => true, - 'message' => 'Data berhasil dihapus' - ], 200); } public function datatable(){ - return AksesFile::where('statusenabled', true)->get(); + return AksesFile::with(['details.unit']) + ->where('statusenabled', true) + ->get(); } public function optionPegawai(){ diff --git a/app/Http/Controllers/DashboardController.php b/app/Http/Controllers/DashboardController.php index 55d4e56..3635379 100644 --- a/app/Http/Controllers/DashboardController.php +++ b/app/Http/Controllers/DashboardController.php @@ -3,12 +3,14 @@ namespace App\Http\Controllers; use App\Models\AksesFile; +use App\Models\AksesFileDetail; use App\Models\FileDirectory; use App\Models\LogActivity; use App\Models\MasterKategori; use App\Models\MasterKlasifikasi; use App\Models\SubUnitKerja; use App\Models\UnitKerja; +use Carbon\Carbon; use Illuminate\Http\Request; use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\Storage; @@ -43,19 +45,37 @@ class DashboardController extends Controller public function dataUnitKerja(){ $user = auth()->user()?->dataUser; $akses = AksesFile::where(['pegawai_id' => $user->id, 'statusenabled' => true])->first(); + $aksesAll = $akses?->akses ?? $akses?->all_akses ?? false; + $detailUnitIds = collect(); + if ($akses?->akses_file_id) { + $detailUnitIds = AksesFileDetail::where('akses_file_id', $akses->akses_file_id) + ->where('statusenabled', true) + ->pluck('id_unit_kerja') + ->unique() + ->values(); + } + $allowedUnitIds = null; + if (!$aksesAll) { + if ($detailUnitIds->isNotEmpty()) { + $allowedUnitIds = $detailUnitIds; + } elseif (!empty($akses?->unit_akses)) { + $allowedUnitIds = collect([$akses->unit_akses]); + } + } $kategori = request('kategori'); $filterUnit = request('unitKerja'); $subUnit = request('subUnit'); - $klasifikasi = request('klasifikasi'); $keyword = request('keyword'); $subArray = $subUnit ? explode(',', $subUnit) : []; $katArray = $kategori ? explode(',', $kategori) : []; - $klaArray = $klasifikasi ? explode(',', $klasifikasi) : []; $katDok = MasterKategori::when($katArray, fn($q) => $q->whereIn('master_kategori_directory_id', $katArray))->where('statusenabled', true)->select('master_kategori_directory_id', 'nama_kategori_directory')->get(); - if ($katArray && $filterUnit && $subArray && $klaArray) { + if ($katArray && $filterUnit && $subArray) { /* mode pencarian lengkap */ + if ($allowedUnitIds && !$allowedUnitIds->contains((int) $filterUnit)) { + $unitKerja = collect(); + } else { $unitKerja = UnitKerja::where('statusenabled', true) ->where('id', $filterUnit) ->with(['subUnitKerja' => fn($q) => $q->whereIn('id', $subArray) @@ -63,7 +83,6 @@ class DashboardController extends Controller ->where('id_unit_kerja', $filterUnit) ->when($subArray, fn($q) => $q->whereIn('id_sub_unit_kerja', $subArray)) ->when($katArray, fn($q) => $q->whereIn('master_kategori_directory_id', $katArray)) - ->when($klaArray, fn($q) => $q->whereIn('master_klasifikasi_directory_id', $klaArray)) ->when($keyword, fn($q) => $q->where(function($query) use ($keyword) { $query->where('file', 'ilike', "%{$keyword}%") @@ -74,8 +93,9 @@ class DashboardController extends Controller ]) ->select('id', 'name') ->get(); + } - } elseif ($akses?->all_akses) { + } elseif ($aksesAll) { /* all akses */ $unitKerja = UnitKerja::where('statusenabled', true)->with([ // muat relasi 'subUnitKerja' => fn($q) => $q->with([ // sub-unit @@ -88,9 +108,10 @@ class DashboardController extends Controller ->select('id', 'name') ->get(); - } elseif ($akses?->unit_akses) { - /* akses per unit */ - $unitKerja = UnitKerja::where(['statusenabled' => true, 'id' => $akses->unit_akses]) + } elseif ($allowedUnitIds) { + /* akses per unit (single/multiple) */ + $unitKerja = UnitKerja::where('statusenabled', true) + ->whereIn('id', $allowedUnitIds) ->with([ // muat relasi 'subUnitKerja' => fn($q) => $q->with([ // sub-unit 'fileDirectory' => fn($f) => $f->when($keyword, fn($q) => @@ -378,23 +399,43 @@ class DashboardController extends Controller public function dataDocumentLast(){ $perPage = (int) request('per_page', 10); $authUnitId = auth()->user()->dataUser?->mappingUnitKerjaPegawai[0]?->objectunitkerjapegawaifk; + $user = auth()->user()?->dataUser; + $akses = AksesFile::where(['pegawai_id' => $user->id, 'statusenabled' => true])->first(); $keyword = request('keyword'); - $data = FileDirectory::where('statusenabled', true) - ->where(function ($query) use ($authUnitId) { - $query->where('permission_file', true) - ->orWhere(function ($sub) use ($authUnitId) { - $sub->where('permission_file', false) - ->where('id_unit_kerja', $authUnitId); - }); - }) + $query = FileDirectory::where('statusenabled', true) ->when($keyword, function ($q) use ($keyword) { $q->where(function ($sub) use ($keyword) { $sub->where('file', 'ILIKE', "%{$keyword}%") ->orWhere('no_dokumen', 'ILIKE', "%{$keyword}%"); }); - }) - ->orderBy('entry_at', 'desc') + }); + if($akses){ + if(!$akses->all_akses){ + $aksesFile = AksesFileDetail::where('akses_file_id', $akses->akses_file_id)->pluck('id_unit_kerja'); + $query->where(function ($query) use ($authUnitId, $aksesFile) { + $query->where('permission_file', true) + ->orWhere(function ($sub) use ($authUnitId, $aksesFile) { + $sub->where('permission_file', false) + ->whereIn('id_unit_kerja', $aksesFile); + }); + }); + }else{ + $query; + } + }else{ + $query->where(function ($query) use ($authUnitId) { + $query->where('permission_file', true) + ->orWhere(function ($sub) use ($authUnitId) { + $sub->where('permission_file', false) + ->where('id_unit_kerja', $authUnitId); + }); + }); + } + + + + $data = $query->orderBy('entry_at', 'desc') ->paginate($perPage); $payload = [ @@ -661,8 +702,10 @@ class DashboardController extends Controller foreach ($grouped as $unitName => $folders) { $data = []; foreach ($folders as $folder => $count) { + $sliceText = array_values(array_filter(explode('/', $folder))); $data[] = [ - 'folder'=> $folder, + 'subUnit' => $sliceText[0], + 'folder'=> $sliceText[1], 'count' => $count, ]; } @@ -701,4 +744,161 @@ class DashboardController extends Controller public function recapView(){ return view('dashboard.recap', ['title' => 'Rekap Dokumen']); } + + public function pendingFile(){ + return view('pendingFile.index', ['title' => 'Data Pending']); + } + + public function dataPendingFile(){ + $perPage = (int) request('per_page', 10); + $keyword = request('keyword'); + $start = request('start_date'); + $end = request('end_date'); + + $query = FileDirectory::where('statusenabled', true)->whereNull('status_action')->orderBy('entry_at','desc'); + if($keyword){ + $query->where(function($q) use ($keyword){ + $q->where('file', 'ILIKE', "%{$keyword}%") + ->orWhere('no_dokumen', 'ILIKE', "%{$keyword}%"); + }); + } + if($start){ + $query->whereDate('entry_at','>=',$start); + } + if($end){ + $query->whereDate('entry_at','<=',$end); + } + + $paginated = $query->paginate($perPage); + $data = $paginated->getCollection()->map(function($item){ + $dataSlice = array_values(array_filter(explode('/', $item->file))); + return [ + 'file_directory_id' => $item->file_directory_id, + 'pegawai_nama_entry' => $item->pegawai_nama_entry, + 'part' => $dataSlice[0] . '/' . $dataSlice[1], + 'folder' => $dataSlice[2], + 'fileName' =>$dataSlice[3], + 'file' => $item->file, + 'no_dokumen' => $item->no_dokumen, + 'entry_at' => $item->entry_at, + 'tanggal_terbit' => $item->tanggal_terbit, + 'permission_file' => $item->permission_file, + ]; + }); + return response()->json([ + 'status' => true, + 'data' => $data, + 'pagination' => [ + 'current_page' => $paginated->currentPage(), + 'next_page' => $paginated->hasMorePages() ? $paginated->currentPage() + 1 : null, + 'has_more' => $paginated->hasMorePages(), + 'last_page' => $paginated->lastPage(), + 'per_page' => $paginated->perPage(), + 'total' => $paginated->total(), + ] + ]); + + } + + public function approvePendingFile(string $id){ + try { + $data = FileDirectory::where('file_directory_id', $id)->first(); + if(!$data){ + return response()->json([ + 'status' => false, + 'message' => 'Data tidak ditemukan' + ], 404); + } + $data->update([ + 'status_action' => 'approved', + 'action_at' => Carbon::now(), + 'action_by' => auth()->user()->dataUser->id, + ]); + $payloadLog = [ + 'file_directory_id' => $data->file_directory_id, + 'pegawai_id_entry' => $data->action_by, + 'pegawai_nama_entry' => auth()->user()->dataUser->namalengkap, + 'entry_at' => $data->action_at, + 'action_type' => 'Approval Dokumen', + 'statusenabled' => true, + 'mod_change' => $data->entry_at, + 'id_unit_kerja' => $data->id_unit_kerja, + 'id_sub_unit_kerja' => $data->id_sub_unit_kerja, + 'file' => $data->file, + 'tanggal_terbit' => $data->tanggal_terbit, + 'no_dokumen' => $data->no_dokumen, + 'permission_file' => $data->permission_file, + ]; + LogActivity::create($payloadLog); + return response()->json([ + 'status' => true, + 'message' => 'File berhasil di-approve' + ], 200); + } catch (\Throwable $th) { + return response()->json([ + 'status' => false, + 'message' => $th->getMessage() + ], 500); + } + } + + public function rejectPendingFile(string $id){ + try { + $data = FileDirectory::where('file_directory_id', $id)->first(); + if(!$data){ + return response()->json([ + 'status' => false, + 'message' => 'Data tidak ditemukan' + ], 404); + } + $data->update([ + 'status_action' => 'rejected', + 'action_at' => Carbon::now(), + 'action_by' => auth()->user()->dataUser->id, + ]); + $payloadLog = [ + 'file_directory_id' => $data->file_directory_id, + 'pegawai_id_entry' => $data->action_by, + 'pegawai_nama_entry' => auth()->user()->dataUser->namalengkap, + 'entry_at' => $data->action_at, + 'action_type' => 'Reject Dokumen', + 'statusenabled' => true, + 'mod_change' => $data->entry_at, + 'id_unit_kerja' => $data->id_unit_kerja, + 'id_sub_unit_kerja' => $data->id_sub_unit_kerja, + 'file' => $data->file, + 'tanggal_terbit' => $data->tanggal_terbit, + 'no_dokumen' => $data->no_dokumen, + 'permission_file' => $data->permission_file, + ]; + LogActivity::create($payloadLog); + return response()->json([ + 'status' => true, + 'message' => 'File berhasil di-reject' + ], 200); + } catch (\Throwable $th) { + return response()->json([ + 'status' => false, + 'message' => $th->getMessage() + ], 500); + } + } + + public function countDataPending(){ + try { + $count = FileDirectory::where('statusenabled', true) + ->whereNull('status_action') + ->count(); + return response()->json([ + 'status' => true, + 'count' => $count, + 'message' => 'Berhasil mendapatkan data' + ]); + } catch (\Throwable $th) { + return response()->json([ + 'status' => false, + 'message' => 'Terdapat kesalahan!' + ]); + } + } } diff --git a/app/Http/Controllers/LogActivityController.php b/app/Http/Controllers/LogActivityController.php index b64c7d2..a969c0a 100644 --- a/app/Http/Controllers/LogActivityController.php +++ b/app/Http/Controllers/LogActivityController.php @@ -9,7 +9,7 @@ class LogActivityController extends Controller { public function index(){ $data =[ - 'title' => 'Log Activity' + 'title' => 'Log Aktivitas' ]; return view('logActivity.index', $data); } diff --git a/app/Models/AksesFile.php b/app/Models/AksesFile.php index 065fbe7..7991315 100644 --- a/app/Models/AksesFile.php +++ b/app/Models/AksesFile.php @@ -3,6 +3,7 @@ namespace App\Models; use Illuminate\Database\Eloquent\Model; +use App\Models\AksesFileDetail; class AksesFile extends Model { @@ -21,4 +22,9 @@ class AksesFile extends Model public function akses(){ return $this->belongsTo(UnitKerja::class, 'unit_akses', 'id')->select('id', 'name'); } + + public function details() + { + return $this->hasMany(AksesFileDetail::class, 'akses_file_id', 'akses_file_id'); + } } diff --git a/app/Models/AksesFileDetail.php b/app/Models/AksesFileDetail.php new file mode 100644 index 0000000..2b709ab --- /dev/null +++ b/app/Models/AksesFileDetail.php @@ -0,0 +1,20 @@ +belongsTo(UnitKerja::class, 'id_unit_kerja', 'id')->select('id', 'name'); + } +} diff --git a/public/js/akses/action.js b/public/js/akses/action.js index 299eec3..9c674a3 100644 --- a/public/js/akses/action.js +++ b/public/js/akses/action.js @@ -103,13 +103,36 @@ function editAkses(e){ const data = $(e).data(); new bootstrap.Modal(modalEdit).show(); formEditAkses.attr('action', `/akses/${data.akses_file_id}`) - $("#akses_id_edit").val(data.akses === 1 ? 'all' : 'unit') + $("#unit_akses_edit").empty().trigger('change'); + $("#unit_akses_wrapper_edit").addClass('d-none'); selectOptionPegawaiEdit() + selectOptionUnitKerjaEdit() if (data.pegawai_id) { setOldSelect2Value('#pegawai_id_edit', data.pegawai_id, data.pegawai_nama); } + fetch(`/akses/${data.akses_file_id}`) + .then(async(res) => { + const responseData = await res.json(); + if (!responseData.status) { + throw new Error(responseData.message || 'Gagal memuat data akses.'); + } + const detail = responseData.data; + if (detail?.akses_type === 'all') { + $("#akses_all_edit").prop('checked', true); + } else { + $("#akses_unit_edit").prop('checked', true); + } + toggleUnitAksesEdit(); + if (detail?.akses_type === 'unit' && Array.isArray(detail.units)) { + setOldSelect2Values('#unit_akses_edit', detail.units); + } + }) + .catch(() => { + $("#akses_all_edit").prop('checked', true); + toggleUnitAksesEdit(); + }); } @@ -143,6 +166,46 @@ function selectOptionPegawaiEdit() { }); } +function selectOptionUnitKerjaEdit() { + let selectUnit = $(`#unit_akses_edit`); + if (selectUnit.data('select2')) return; + selectUnit.select2({ + placeholder: '-- Pilih Unit Kerja --', + allowClear:true, + width: '100%', + dropdownParent: selectUnit.parent(), + ajax:{ + url : '/select-unit-kerja', + dataType: 'json', + delay: 250, + data: function(params){ + return { q: params.term } + }, + processResults: function(data){ + return { + results : data?.data.map(item => ({ + id: item.id, + text: item.name, + })) + } + }, + cache: true, + }, + minimumInputLength: 1, + }); +} + +function toggleUnitAksesEdit() { + const wrapper = $("#unit_akses_wrapper_edit"); + const unitSelect = $("#unit_akses_edit"); + const isUnit = $("#akses_unit_edit").is(':checked'); + if (isUnit) { + wrapper.removeClass('d-none'); + } else { + wrapper.addClass('d-none'); + unitSelect.val(null).trigger('change'); + } +} function setOldSelect2Value(selector, id, text) { @@ -151,6 +214,16 @@ function setOldSelect2Value(selector, id, text) { $(selector).append(option).trigger('change') } +function setOldSelect2Values(selector, items) { + if (!Array.isArray(items) || items.length === 0) return; + items.forEach(item => { + if (!item?.id || !item?.text) return; + let option = new Option(item.text, item.id, true, true); + $(selector).append(option); + }); + $(selector).trigger('change') +} + formEditAkses.on('submit', function(e){ e.preventDefault(); diff --git a/public/js/akses/dt.js b/public/js/akses/dt.js index 60b9987..5dc8206 100644 --- a/public/js/akses/dt.js +++ b/public/js/akses/dt.js @@ -25,15 +25,13 @@ ` - buttons += ` ` return ` @@ -50,7 +48,13 @@ { title:"Akses", formatter:function(value, row){ - return row?.all_akses ? 'Semua Akses' : row?.akses?.name; + if (row?.all_akses) return 'Semua Unit'; + const units = (row?.details || []) + .filter(detail => detail?.statusenabled) + .map(detail => detail?.unit?.name) + .filter(Boolean); + if (units.length > 0) return units.join(', '); + return row?.akses?.name || '-'; } } ], diff --git a/public/js/akses/functions.js b/public/js/akses/functions.js index 82cdf88..7471874 100644 --- a/public/js/akses/functions.js +++ b/public/js/akses/functions.js @@ -1,5 +1,6 @@ $(document).ready(function() { selectOptionPegawai(0) + selectOptionUnitKerja(0) }); function selectOptionPegawai(colCount) { @@ -31,6 +32,46 @@ function selectOptionPegawai(colCount) { }); } +function selectOptionUnitKerja(colCount) { + let selectUnit = $(`#unit_akses_${colCount}`); + selectUnit.select2({ + placeholder: '-- Pilih Unit Kerja --', + allowClear: true, + width: '100%', + dropdownParent: selectUnit.parent(), + ajax:{ + url : '/select-unit-kerja', + dataType: 'json', + delay: 250, + data: function(params){ + return { q: params.term } + }, + processResults: function(data){ + return { + results : data?.data.map(item => ({ + id: item.id, + text: item.name, + })) + } + }, + cache: true, + }, + minimumInputLength: 1, + }); +} + +function toggleUnitAkses(colCount) { + const wrapper = $(`#unit_akses_wrapper_${colCount}`); + const unitSelect = $(`#unit_akses_${colCount}`); + const isUnit = $(`#akses_unit_${colCount}`).is(':checked'); + if (isUnit) { + wrapper.removeClass('d-none'); + } else { + wrapper.addClass('d-none'); + unitSelect.val(null).trigger('change'); + } +} + let colCount = 1; @@ -42,18 +83,38 @@ function addForm(){ html += `