AddExtGState([ 'ca' => $alpha, 'CA' => $alpha, 'BM' => '/' . $blendMode ]); $this->SetExtGState($gs); } protected function AddExtGState(array $parms): int { $n = count($this->extgstates) + 1; $this->extgstates[$n]['parms'] = $parms; return $n; } protected function SetExtGState(int $gs): void { $this->_out(sprintf('/GS%d gs', $gs)); } protected function _putextgstates(): void { foreach ($this->extgstates as $i => $extgstate) { $this->_newobj(); $this->extgstates[$i]['n'] = $this->n; $this->_put('< $v) { $this->_put('/' . $k . ' ' . $v); } $this->_put('>>'); $this->_put('endobj'); } } protected function _putresourcedict(): void { parent::_putresourcedict(); if (empty($this->extgstates)) { return; } $this->_put('/ExtGState <<'); foreach ($this->extgstates as $k => $extgstate) { $this->_put('/GS' . $k . ' ' . $extgstate['n'] . ' 0 R'); } $this->_put('>>'); } protected function _putresources(): void { $this->_putextgstates(); parent::_putresources(); } } class DashboardController extends Controller { // public function index(){ // $katDok = MasterKategori::where('statusenabled', true)->select('master_kategori_directory_id', 'nama_kategori_directory')->get(); // $klasifikasiDok = MasterKlasifikasi::where('statusenabled', true)->select('master_klasifikasi_directory_id', 'nama_klasifikasi_directory')->get(); // $prefillFilter = session()->pull('dashboard_prefill'); // $authMapping = auth()->user()?->dataUser?->mappingUnitKerjaPegawai[0]; // $authUnitKerja = $authMapping->objectunitkerjapegawaifk; // $authSubUnitKerja = $authMapping->objectsubunitkerjapegawaifk; // $allAkses = AksesFile::where(['statusenabled' => true, 'pegawai_id' => auth()->user()?->dataUser->id])->first(); // $payload = [ // 'title' => 'Dashboard', // 'katDok' => $katDok, // 'klasifikasiDok' => $klasifikasiDok, // 'authUnitKerja' => $authUnitKerja, // 'authSubUnitKerja' => $authSubUnitKerja, // 'allAkses' => $allAkses ?? null, // 'prefillFilter' => $prefillFilter // ]; // return view('dashboard.index', $payload); // } public function setDashboardPrefill(Request $request) { $payload = [ 'unitId' => (string) $request->input('unitId', ''), 'subId' => (string) $request->input('subId', ''), 'kategoriId' => (string) $request->input('kategoriId', ''), 'unitName' => (string) $request->input('unitName', ''), 'subName' => (string) $request->input('subName', ''), 'kategoriName' => (string) $request->input('kategoriName', ''), ]; session(['dashboard_prefill' => $payload]); return response()->json([ 'status' => true, 'message' => 'Prefill disimpan' ]); } public function index(){ $katDok = MasterKategori::where('statusenabled', true)->select('master_kategori_directory_id', 'nama_kategori_directory')->get(); $authMapping = auth()->user()?->dataUser?->mappingUnitKerjaPegawai[0]; $authUnitKerja = $authMapping->objectunitkerjapegawaifk; $authSubUnitKerja = $authMapping->objectsubunitkerjapegawaifk; $data = [ 'title' => 'Dashboard', 'katDok' => $katDok, 'authUnitKerja' => $authUnitKerja, 'authSubUnitKerja' => $authSubUnitKerja, ]; return view('dataUnit.index', $data); } public function dataUnitInternal(){ $perPage = (int) request('per_page', 10); // $authUnitId = auth()->user()->dataUser?->mappingUnitKerjaPegawai[0]?->objectunitkerjapegawaifk; $mapping = MappingUnitKerjaPegawai::where('statusenabled', true) ->where('objectpegawaifk', auth()->user()->dataUser->id) ->get(['objectunitkerjapegawaifk', 'objectsubunitkerjapegawaifk']); $unitIds = $mapping->pluck('objectunitkerjapegawaifk') ->filter() // buang null ->unique() ->values() ->all(); $keyword = request('keyword'); $query = FileDirectory::where('statusenabled', true) ->where('status_action', 'approved') ->whereIn('id_unit_kerja', $unitIds) ->when($keyword, function ($q) use ($keyword) { $q->where(function ($sub) use ($keyword) { $sub->where('nama_dokumen', 'ILIKE', "%{$keyword}%") ->orWhere('no_dokumen', 'ILIKE', "%{$keyword}%"); }); }); $data = $query->orderBy('entry_at', 'desc') ->paginate($perPage); $payload = [ 'status' => true, 'message' => 'Berhasil mendapatkan data', 'data' => $data->items(), 'pagination' => [ 'current_page' => $data->currentPage(), 'next_page' => $data->hasMorePages() ? $data->currentPage() + 1 : null, 'has_more' => $data->hasMorePages(), 'last_page' => $data->lastPage(), 'per_page' => $data->perPage(), 'total' => $data->total(), ] ]; return response()->json($payload); } public function downloadDataUnitExcel() { $mapping = MappingUnitKerjaPegawai::where('statusenabled', true) ->where('objectpegawaifk', auth()->user()->dataUser->id) ->get(['objectunitkerjapegawaifk']); $unitIds = $mapping->pluck('objectunitkerjapegawaifk') ->filter() ->unique() ->values() ->all(); $query = FileDirectory::where('statusenabled', true) ->where('status_action', 'approved') ->whereIn('id_unit_kerja', $unitIds) ->orderBy('entry_at', 'desc'); $rows = $query->get(); $spreadsheet = new Spreadsheet(); $sheet = $spreadsheet->getActiveSheet(); $sheet->setCellValue('A1', "List Dokumen Unit"); $sheet->mergeCells('A1:I1'); $sheet->getStyle('A1')->getFont()->setBold(true)->setSize(14); $sheet->getStyle('A1')->getAlignment()->setHorizontal('center'); $headers = [ 'No Dokumen', 'Nama Dokumen', 'Kategori', 'Unit', 'Sub Unit', 'Tanggal Terbit', 'Tanggal Expired', 'Tanggal Upload', 'Pengunggah' ]; $sheet->fromArray($headers, null, 'A4'); $sheet->getStyle('A4:I4')->applyFromArray([ 'font' => ['bold' => true], 'alignment' => ['horizontal' => \PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER], 'borders' => [ 'allBorders' => [ 'borderStyle' => \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_THIN ] ] ]); $sheet->getStyle('A4:I4')->getFont()->setBold(true); $sheet->getStyle('A4:I4')->getAlignment()->setHorizontal('center'); $sheet->getStyle('A4:I4')->getBorders()->getAllBorders()->setBorderStyle(\PhpOffice\PhpSpreadsheet\Style\Border::BORDER_THIN); $rowIdx = 5; foreach ($rows as $item) { $parts = array_values(array_filter(explode('/', (string) $item->file))); $unitName = $parts[0] ?? '-'; $subUnitName = $parts[1] ?? '-'; $kategoriName = $parts[2] ?? '-'; $sheet->fromArray([ $item->no_dokumen ?? '-', $item->nama_dokumen ?? '-', $kategoriName, $unitName, $subUnitName, $item->tanggal_terbit ? Carbon::parse($item->tanggal_terbit)->format('d/m/Y') : '-', $item->tgl_expired ? Carbon::parse($item->tgl_expired)->format('d/m/Y') : '-', $item->entry_at ? Carbon::parse($item->entry_at)->format('d/m/Y') : '-', $item->pegawai_nama_entry ?? '-' ], null, "A{$rowIdx}"); $rowIdx++; } $recapData = $this->buildRecapData($unitIds, ''); if (!empty($recapData)) { $rowIdx += 1; $sheet->setCellValue("E{$rowIdx}", 'Rekap Dokumen'); $sheet->mergeCells("E{$rowIdx}:G{$rowIdx}"); $sheet->getStyle("E{$rowIdx}")->applyFromArray([ 'font' => ['bold' => true, 'size' => 12], ]); $rowIdx++; $sheet->fromArray(['Unit', 'Kategori', 'Jumlah File'], null, "E{$rowIdx}"); $sheet->getStyle("E{$rowIdx}:G{$rowIdx}")->applyFromArray([ 'font' => ['bold' => true], 'alignment' => ['horizontal' => \PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER], 'borders' => [ 'allBorders' => [ 'borderStyle' => \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_THIN ] ] ]); $rowIdx++; foreach ($recapData as $recap) { $unitName = $recap['unit'] ?? '-'; $folders = $recap['data'] ?? []; $unitStartRow = $rowIdx; foreach ($folders as $folderItem) { $sheet->setCellValue("F{$rowIdx}", $folderItem['folder'] ?? '-'); $sheet->setCellValue("G{$rowIdx}", $folderItem['count'] ?? 0); $rowIdx++; } $unitEndRow = max($unitStartRow, $rowIdx - 1); $sheet->setCellValue("E{$unitStartRow}", $unitName); if ($unitEndRow > $unitStartRow) { $sheet->mergeCells("E{$unitStartRow}:E{$unitEndRow}"); } } } foreach(range('A', 'I') as $col){ $sheet->getColumnDimension($col)->setAutoSize(true); } $fileName = 'data-unit-' . now()->format('Ymd-His') . '.xlsx'; $tempPath = storage_path('app/temp'); if (!is_dir($tempPath)) { @mkdir($tempPath, 0777, true); } $fullPath = $tempPath . '/' . $fileName; (new Xlsx($spreadsheet))->save($fullPath); return response()->download($fullPath, $fileName)->deleteFileAfterSend(true); } public function dataUnitKerja(){ $user = auth()->user()?->dataUser; // $entryPegawaiId = auth()->user()?->objectpegawaifk; $authMapping = $user?->mappingUnitKerjaPegawai[0] ?? null; $authUnit = $authMapping?->objectunitkerjapegawaifk; $authSub = $authMapping?->objectsubunitkerjapegawaifk; $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]); } } $limitPrivateToSubUnit = false; if (!$aksesAll && !$allowedUnitIds && $authUnit) { $allowedUnitIds = collect([$authUnit]); $limitPrivateToSubUnit = true; } $kategori = request('kategori'); $filterUnit = request('unitKerja'); $subUnit = request('subUnit'); $keyword = request('keyword'); $hasKeyword = !empty($keyword); $subArray = $subUnit ? explode(',', $subUnit) : []; $katArray = $kategori ? explode(',', $kategori) : []; $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(); $applyFileFilters = function ($q) use ($keyword, $katArray, $subArray, $entryPegawaiId) { $q->where(function($subQuery) use ($entryPegawaiId){ $subQuery->where('status_action', '!=', 'rejected')->whereNotNull('status_action'); }) ->when($subArray, fn($sq) => $sq->whereIn('id_sub_unit_kerja', $subArray)) ->when($katArray, fn($sq) => $sq->whereIn('master_kategori_directory_id', $katArray)) ->when($keyword, fn($sq) => $sq->where(function ($query) use ($keyword) { $query->where('file', 'ilike', "%{$keyword}%"); }) ); }; $applyAccessFilter = function ($q) use ($aksesAll, $allowedUnitIds, $limitPrivateToSubUnit, $authSub) { if ($aksesAll) { return; } $hasPrivateScope = ($allowedUnitIds && $allowedUnitIds->isNotEmpty()) || ($limitPrivateToSubUnit && $authSub); $q->where(function ($query) use ($allowedUnitIds, $limitPrivateToSubUnit, $authSub, $hasPrivateScope) { $query->where('permission_file', true); if ($hasPrivateScope) { $query->orWhere(function ($sub) use ($allowedUnitIds, $limitPrivateToSubUnit, $authSub) { $sub->where('permission_file', false); if ($allowedUnitIds && $allowedUnitIds->isNotEmpty()) { $sub->whereIn('id_unit_kerja', $allowedUnitIds); } if ($limitPrivateToSubUnit && $authSub) { $sub->where('id_sub_unit_kerja', $authSub); } }); } }); }; $applyFileQuery = function ($q) use ($applyFileFilters, $applyAccessFilter) { $applyFileFilters($q); $applyAccessFilter($q); }; if ($katArray && $filterUnit && $subArray) { /* mode pencarian lengkap */ $unitKerja = UnitKerja::where('statusenabled', true) ->where('id', $filterUnit) ->with(['subUnitKerja' => fn($q) => $q->whereIn('id', $subArray) ->whereHas('fileDirectory', fn($f) => $applyFileQuery($f)) ->with(['fileDirectory' => fn($f) => $applyFileQuery($f)]) ]) ->select('id', 'name') ->get(); } elseif ($aksesAll) { /* all akses */ $unitKerja = UnitKerja::where('statusenabled', true) ->when($hasKeyword, fn($q) => $q->whereHas('subUnitKerja.fileDirectory', fn($f) => $applyFileQuery($f))) ->with([ // muat relasi 'subUnitKerja' => fn($q) => $q ->when($hasKeyword, fn($sq) => $sq->whereHas('fileDirectory', fn($f) => $applyFileQuery($f))) ->with([ // sub-unit 'fileDirectory' => fn($f) => $applyFileQuery($f) ]) ]) ->select('id', 'name') ->get(); } elseif ($allowedUnitIds) { $unitKerja = UnitKerja::where('statusenabled', true) ->when($hasKeyword, fn($q) => $q->whereHas('subUnitKerja.fileDirectory', fn($f) => $applyFileQuery($f))) ->where(function ($q) use ($allowedUnitIds, $applyFileQuery) { if ($allowedUnitIds && $allowedUnitIds->isNotEmpty()) { $q->whereIn('id', $allowedUnitIds); } $q->orWhereHas('subUnitKerja.fileDirectory', fn($f) => $applyFileQuery($f)); }) ->with([ 'subUnitKerja' => fn($q) => $q->whereHas('fileDirectory', fn($f) => $applyFileQuery($f)) ->with(['fileDirectory' => fn($f) => $applyFileQuery($f)]) ]) ->select('id', 'name') ->get(); } else { $unitKerja = UnitKerja::where('statusenabled', true) ->when($hasKeyword, fn($q) => $q->whereHas('subUnitKerja.fileDirectory', fn($f) => $applyFileQuery($f))) ->where(function ($q) use ($authUnit, $applyFileQuery) { if ($authUnit) { $q->where('id', $authUnit); } $q->orWhereHas('subUnitKerja.fileDirectory', fn($f) => $applyFileQuery($f)); }) ->with([ // 1. sub-unit milik user 'subUnitKerja' => fn($q) => $q->where(function ($sq) use ($authSub, $applyFileQuery, $hasKeyword) { if ($authSub && !$hasKeyword) { $sq->where('id', $authSub); } $sq->orWhereHas('fileDirectory', fn($f) => $applyFileQuery($f)); }) ->with([ // 2. file-directory + filter keyword 'fileDirectory' => fn($f) => $applyFileQuery($f) ]) ]) ->select('id', 'name') ->get(); } $data = [ 'unitKerja' => $unitKerja ?? null, 'katDok' => $katDok ?? null ]; return response()->json([ 'status' => true, 'data' => $data, ], 200); } public function store(){ DB::connection('dbDirectory')->beginTransaction(); try { $datas = request()->input('data'); $result = []; foreach($datas as $index => $value){ $files = request()->file("data.fileUpload$index"); if(!empty($files)){ foreach ($files['file'] as $file) { list($id_unit_kerja, $nama_unit_kerja) = explode('/', $value['id_unit_kerja'],2); list($id_sub_unit_kerja, $nama_sub_unit_kerja) = explode('/', $value['id_sub_unit_kerja'],2); list($master_kategori_directory_id, $nama_kategori) = explode('/', $value['master_kategori_directory_id'],2); list($klasifikasi, $nama_klasifikasi) = explode('/', $value['klasifikasi'],2); $payload = [ 'master_klasifikasi_directory_id' => $klasifikasi, 'id_unit_kerja' => $id_unit_kerja, 'id_sub_unit_kerja' => $id_sub_unit_kerja, 'master_kategori_directory_id' => $master_kategori_directory_id, 'pegawai_id_entry' => auth()->user()->dataUser->id ?? 1, 'pegawai_nama_entry' => auth()->user()->dataUser->namalengkap ?? 'tes', ]; if($file){ $imageName = $file->getClientOriginalName(); $path = "{$nama_unit_kerja}/{$nama_sub_unit_kerja}/{$nama_kategori}/{$nama_klasifikasi}"; $file->storeAs($path, $imageName, 'file_directory'); $payload['file'] =$path .'/' .$imageName; } $fd = FileDirectory::create($payload); } } } DB::connection('dbDirectory')->commit(); return response()->json([ 'status' => true, 'message' => 'Data berhasil disimpan', 'data' => count($result) == 1 ? $result[0] : $result ], 200); } catch (\Throwable $th) { DB::connection('dbDirectory')->rollBack(); return response()->json([ 'status' => false, 'message' => $th->getMessage() ], 500); } } public function OptionUnitKerja(){ $q = request()->get('q'); $query = UnitKerja::where('statusenabled', true); $data = $query->when($q, function ($query, $q){ $query->where('name', 'ILIKE', '%' .$q . '%'); }) ->select('id', 'name')->get(); return response()->json([ 'status' => true, 'data' => $data ], 200); } public function OptionUnitKerjaByMapping(){ $q = request()->get('q'); $pegawaiId = auth()->user()?->dataUser?->id; $mapping = MappingUnitKerjaPegawai::where('statusenabled', true) ->where('objectpegawaifk', $pegawaiId) ->get(['objectunitkerjapegawaifk', 'objectsubunitkerjapegawaifk']); $unitIds = $mapping->pluck('objectunitkerjapegawaifk')->filter()->unique()->values(); $subIds = $mapping->pluck('objectsubunitkerjapegawaifk')->filter()->unique()->values(); $units = UnitKerja::where('statusenabled', true) ->when($unitIds->isNotEmpty(), fn($q2) => $q2->whereIn('id', $unitIds)) ->when($q, fn($q2) => $q2->where('name', 'ILIKE', '%' . $q . '%')) ->select('id', 'name') ->get(); $subUnits = $subIds->isNotEmpty() ? SubUnitKerja::where('statusenabled', true) ->whereIn('id', $subIds) ->get(['id', 'name', 'objectunitkerjapegawaifk']) : collect(); $subMap = $subUnits->groupBy('objectunitkerjapegawaifk')->map(function($items){ return $items->map(fn($s) => ['id' => $s->id, 'name' => $s->name])->values(); }); $data = $units->map(function($u) use ($subMap){ return [ 'id' => $u->id, 'name' => $u->name, 'sub_unit_kerja' => $subMap[$u->id] ?? [] ]; })->values(); return response()->json([ 'status' => true, 'data' => $data ], 200); } public function deleteFile(string $id){ DB::connection('dbDirectory')->beginTransaction(); try { $mapping = MappingUnitKerjaPegawai::where('statusenabled', true) ->where('objectpegawaifk', auth()->user()?->dataUser?->id) ->first(); $data = FileDirectory::where('file_directory_id', $id)->first(); if(!$data){ return response()->json([ 'success' => false, 'message' => 'File tidak ditemukan' ]); } $oldPath= public_path('file/' . $data->file); $fileInfo = pathinfo($data->file); $newFileName = $fileInfo['filename'] . '_deleted.' . $fileInfo['extension']; $newPath = public_path('file/' . $fileInfo['dirname'] . '/' . $newFileName); if (file_exists($oldPath)) { // pastikan folder tujuan ada if (!is_dir(dirname($newPath))) { mkdir(dirname($newPath), 0777, true); } rename($oldPath, $newPath); } $data->update(['statusenabled' => false, 'file' => $fileInfo['dirname'].'/'. $newFileName]); $uploaderName = auth()->user()?->dataUser?->namalengkap ?? 'Pengguna'; $docNumber = $data->no_dokumen ? 'nomor '. $data->no_dokumen : $data->nama_dokumen; $payloadNotification = [ 'created_at' => now(), 'text_notifikasi' => "Dokumen {$docNumber} . dihapus oleh {$uploaderName}.", 'url' => '/pending-file', 'is_read' => false, 'pegawai_id' => $mapping?->objectatasanlangsungfk, ]; Notifkasi::create($payloadNotification); if($mapping->objectpejabatpenilaifk){ $payloadNotification = [ 'created_at' => now(), 'text_notifikasi' => "Dokumen {$docNumber}. dihapus oleh {$uploaderName}.", 'url' => '/pending-file', 'is_read' => false, 'pegawai_id' => $mapping?->objectpejabatpenilaifk, ]; Notifkasi::create($payloadNotification); } DB::connection('dbDirectory')->commit(); return response()->json([ 'success' => true, 'message' => 'Berhasil menghapus data' ]); } catch (\Throwable $th) { DB::connection('dbDirectory')->rollBack(); return response()->json([ 'success' => false, 'message' => 'Gagal menghapus data' ]); //throw $th; } } public function optionSubUnitKerja(string $id){ $data = SubUnitKerja::where('statusenabled', true)->where('objectunitkerjapegawaifk', $id)->get(); return response()->json([ 'status' => true, 'data' => $data, ]); } public function optionSubUnitKerjaByMapping(string $id){ $pegawaiId = auth()->user()?->dataUser?->id; $subIds = MappingUnitKerjaPegawai::where('statusenabled', true) ->where('objectpegawaifk', $pegawaiId) ->where('objectunitkerjapegawaifk', $id) ->pluck('objectsubunitkerjapegawaifk') ->filter() ->unique() ->values(); $data = SubUnitKerja::where('statusenabled', true) ->where('objectunitkerjapegawaifk', $id) ->when($subIds->isNotEmpty(), fn($q) => $q->whereIn('id', $subIds)) ->get(); return response()->json([ 'status' => true, 'data' => $data, ]); } public function getFile($id_unit_kerja, $id_sub_unit_kerja, $master_kategori_directory_id){ $klasifikasi = request('klasifikasi'); $klaArray = explode(',', $klasifikasi); $data = FileDirectory::where(['statusenabled' => true, 'id_unit_kerja' => $id_unit_kerja, 'id_sub_unit_kerja' => $id_sub_unit_kerja, 'master_kategori_directory_id' => $master_kategori_directory_id])->whereIn('master_klasifikasi_directory_id', $klaArray)->get(); return response()->json([ 'data' => $data, 'status' => true, ]); } public function downloadDataMultiple(){ try { $rows = request('ids', []); // [[file_directory_id=>x] | [sub_unit_id=>y] | "file_directory_id", ...] if (empty($rows)) { return response()->json(['message' => 'Tidak ada data'], 422); } $paths = []; foreach ($rows as $r) { if (is_string($r) || is_numeric($r)) { $file = FileDirectory::where('file_directory_id', $r) ->where('statusenabled', true) ->where('status_action', 'approved') ->value('file'); if ($file) { $paths[] = $file; } continue; } if (!empty($r['file_directory_id'] ?? null)) { $file = FileDirectory::where('file_directory_id', $r['file_directory_id']) ->where('statusenabled', true) ->where('status_action', 'approved') ->value('file'); if ($file) { $paths[] = $file; } continue; } if (!empty($r['file'] ?? null)) { $paths[] = $r['file']; continue; } $subUnitId = $r['sub_unit_id'] ?? $r['id_sub_unit_kerja'] ?? null; if (!empty($subUnitId)) { $files = FileDirectory::where('id_sub_unit_kerja', $subUnitId) ->where('statusenabled', true) ->where('status_action', 'approved') ->pluck('file'); $paths = array_merge($paths, $files->toArray()); } } $paths = array_unique($paths); if (empty($paths)) { return response()->json(['message' => 'File tidak ditemukan'], 404); } $zipName = 'files_' . time() . '.zip'; $zipPath = public_path('zip/' . $zipName); $zip = new ZipArchive; $tempFiles = []; if($zip->open($zipPath, ZipArchive::CREATE) === TRUE){ foreach ($paths as $path) { $fullPath = public_path('file/' . $path); if(!file_exists($fullPath)){ throw new \Exception("File tidak ditemukan: " . $path); } $relativePathInZip = $path; $fileToAdd = $this->prepareFileWithWatermark($fullPath, $tempFiles); $zip->addFile($fileToAdd, $relativePathInZip); } $zip->close(); } $this->cleanupTempFiles($tempFiles); return response()->download(public_path('zip/' . $zipName))->deleteFileAfterSend(true); //code... } catch (\Throwable $th) { return response()->json([ 'message' => 'Terjadi kesalahan', 'error' => $th->getMessage() ], 500); } } public function downloadDataFolder(){ try { $id = request('id'); $type = request('type'); if($type === "unit"){ $data = FileDirectory::where('id_unit_kerja', $id)->where('statusenabled', true)->where('status_action', 'approved')->pluck('file'); }else{ $data = FileDirectory::where('id_sub_unit_kerja', $id)->where('statusenabled', true)->where('status_action', 'approved')->pluck('file'); } if (empty($data)) { return response()->json(['message' => 'File tidak ditemukan'], 404); } $zipName = 'files_' . time() . '.zip'; $zipPath = public_path('zip/' . $zipName); $zip = new ZipArchive; $tempFiles = []; if($zip->open($zipPath, ZipArchive::CREATE) === TRUE){ foreach ($data as $path) { $fullPath = public_path('file/' . $path); if(!file_exists($fullPath)){ throw new \Exception("File tidak ditemukan: " . $path); } $relativePathInZip = $path; $fileToAdd = $this->prepareFileWithWatermark($fullPath, $tempFiles); $zip->addFile($fileToAdd, $relativePathInZip); } $zip->close(); } $this->cleanupTempFiles($tempFiles); return response()->download(public_path('zip/' . $zipName))->deleteFileAfterSend(true); } catch (\Throwable $th) { return response()->json([ 'message' => 'Terjadi kesalahan', 'error' => $th->getMessage() ], 500); } } public function downloadFile(string $id) { $data = FileDirectory::where('file_directory_id', $id) ->where('statusenabled', true) ->first(); if (!$data) { abort(404, 'File tidak ditemukan'); } $filePath = public_path('file/' . $data->file); if (!file_exists($filePath)) { abort(404, 'File tidak ditemukan'); } $user = auth()->user()->dataUser; $mapping = MappingUnitKerjaPegawai::where('statusenabled', true) ->where('objectpegawaifk', $user->id)->where('isprimary', true) ->first(); LogActivity::create([ 'file_directory_id' => $id, 'pegawai_id_entry' => $user->id, 'pegawai_nama_entry' => $user->namalengkap, 'entry_at' => now(), 'action_type' => 'Download Dokumen', 'no_dokumen' => $data->no_dokumen, 'file' => $data->file, 'statusenabled' => true, 'mod_change' => null, 'id_unit_kerja' => $mapping ? $mapping->objectunitkerjapegawaifk : null, 'id_sub_unit_kerja' => $mapping ? $mapping->objectsubunitkerjapegawaifk : null, ]); $tempFiles = []; $fileToSend = $this->prepareFileWithWatermark($filePath, $tempFiles); $downloadName = basename($data->file); $response = response()->download($fileToSend, $downloadName); if ($fileToSend !== $filePath) { $response->deleteFileAfterSend(true); } else { $this->cleanupTempFiles($tempFiles); } return $response; } public function dataUmum(){ $katDok = MasterKategori::where('statusenabled', true)->select('master_kategori_directory_id', 'nama_kategori_directory')->get(); $authMapping = auth()->user()?->dataUser?->mappingUnitKerjaPegawai[0]; $authUnitKerja = $authMapping->objectunitkerjapegawaifk; $authSubUnitKerja = $authMapping->objectsubunitkerjapegawaifk; $data = [ 'title' => 'Dashboard', 'katDok' => $katDok, 'authUnitKerja' => $authUnitKerja, 'authSubUnitKerja' => $authSubUnitKerja, ]; return view('dataUmum.index', $data); } public function datatableDataUmum(){ $perPage = (int) request('per_page', 10); // $authUnitId = auth()->user()->dataUser?->mappingUnitKerjaPegawai[0]?->objectunitkerjapegawaifk; $user = auth()->user()?->dataUser; // $entryPegawaiId = auth()->user()?->objectpegawaifk; $akses = AksesFile::where(['pegawai_id' => $user->id, 'statusenabled' => true])->first(); $keyword = request('keyword'); $mapping = MappingUnitKerjaPegawai::where('statusenabled', true) ->where('objectpegawaifk', $user->id) ->get(['objectunitkerjapegawaifk', 'objectsubunitkerjapegawaifk']); // $unitIds = $mapping->pluck('objectunitkerjapegawaifk') // ->filter() // buang null // ->unique() // ->values() // ->all(); // $subUnitIds = $mapping->pluck('objectsubunitkerjapegawaifk') // ->filter() // ->unique() // ->values() // ->all(); $query = FileDirectory::where('statusenabled', true)->where('status_action', 'approved') ->when($keyword, function ($q) use ($keyword) { $q->where(function ($sub) use ($keyword) { $sub->where('nama_dokumen', 'ILIKE', "%{$keyword}%") ->orWhere('no_dokumen', 'ILIKE', "%{$keyword}%"); }); }); if($akses && $akses->all_akses){ $query; }else{ $query->where('permission_file', true); } $data = $query->orderBy('entry_at', 'desc') ->paginate($perPage); $payload = [ 'status' => true, 'message' => 'Berhasil mendapatkan data', 'data' => $data->items(), 'pagination' => [ 'current_page' => $data->currentPage(), 'next_page' => $data->hasMorePages() ? $data->currentPage() + 1 : null, 'has_more' => $data->hasMorePages(), 'last_page' => $data->lastPage(), 'per_page' => $data->perPage(), 'total' => $data->total(), ] ]; return response()->json($payload); } public function downloadDataUmumExcel() { $rows = FileDirectory::where('statusenabled', true) ->where('status_action', 'approved') ->where('permission_file', true) ->orderBy('entry_at', 'desc')->get(); $spreadsheet = new Spreadsheet(); $sheet = $spreadsheet->getActiveSheet(); $sheet->setCellValue('A1', "List Dokumen Umum"); $sheet->mergeCells('A1:H1'); $sheet->getStyle('A1')->getFont()->setBold(true)->setSize(14); $sheet->getStyle('A1')->getAlignment()->setHorizontal('center'); $headers = [ 'No Dokumen', 'Nama Dokumen', 'Kategori', 'Unit', 'Sub Unit', 'Tanggal Terbit', 'Tanggal Expired', 'Tanggal Upload', ]; $sheet->fromArray($headers, null, 'A4'); $sheet->getStyle('A4:H4')->applyFromArray([ 'font' => ['bold' => true], 'alignment' => ['horizontal' => \PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER], 'borders' => [ 'allBorders' => [ 'borderStyle' => \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_THIN ] ] ]); $sheet->getStyle('A4:H4')->getFont()->setBold(true); $sheet->getStyle('A4:H4')->getAlignment()->setHorizontal('center'); $sheet->getStyle('A4:H4')->getBorders()->getAllBorders()->setBorderStyle(\PhpOffice\PhpSpreadsheet\Style\Border::BORDER_THIN); $rowIdx = 5; foreach ($rows as $item) { $parts = array_values(array_filter(explode('/', (string) $item->file))); $unitName = $parts[0] ?? '-'; $subName = $parts[1] ?? '-'; $kategoriName = $parts[2] ?? '-'; $sheet->fromArray([ $item->no_dokumen ?? '-', $item->nama_dokumen ?? '-', $kategoriName, $unitName, $subName, $item->tanggal_terbit ? Carbon::parse($item->tanggal_terbit)->format('d/m/Y') : '-', $item->tgl_expired ? Carbon::parse($item->tgl_expired)->format('d/m/Y') : '-', $item->entry_at ? Carbon::parse($item->entry_at)->format('d/m/Y') : '-' ], null, "A{$rowIdx}"); $rowIdx++; } foreach(range('A', 'H') as $col){ $sheet->getColumnDimension($col)->setAutoSize(true); } $fileName = 'data-umum-' . now()->format('Ymd-His') . '.xlsx'; $tempPath = storage_path('app/temp'); if (!is_dir($tempPath)) { @mkdir($tempPath, 0777, true); } $fullPath = $tempPath . '/' . $fileName; (new Xlsx($spreadsheet))->save($fullPath); return response()->download($fullPath, $fileName)->deleteFileAfterSend(true); } public function storeVersion2(){ DB::connection('dbDirectory')->beginTransaction(); try { $datas = request('data'); $mapping = MappingUnitKerjaPegawai::where('statusenabled', true) ->where('objectpegawaifk', auth()->user()?->dataUser?->id) ->first(); $isAtasan = MappingUnitKerjaPegawai::where('statusenabled', true)->where(function($q){ $q->where('objectatasanlangsungfk', auth()->user()?->dataUser?->id)->orWhere('objectpejabatpenilaifk', auth()->user()->objectpegawaifk); })->exists(); foreach ($datas as $index => $data) { list($id_unit_kerja, $nama_unit_kerja) = explode('/', $data['id_unit_kerja'],2); list($id_sub_unit_kerja, $nama_sub_unit_kerja) = explode('/', $data['id_sub_unit_kerja'],2); list($master_kategori_directory_id, $nama_kategori) = explode('/', $data['master_kategori_directory_id'],2); $uploadedFile = request()->file("data.$index.file"); if(!$uploadedFile){ throw new \RuntimeException('File wajib diunggah pada baris ke-' . ($index+1)); } // if(auth()->user()->masterPersetujuan){ // $unitPegawaiIds = auth()->user()->masterPersetujuan->details->pluck('unit_pegawai_id')->unique()->toArray(); // $status = in_array($id_unit_kerja, $unitPegawaiIds) // ? 'approved' // : null; $status = $isAtasan ? 'approved' : null; // } $payload = [ 'id_unit_kerja' => $id_unit_kerja, 'id_sub_unit_kerja' => $id_sub_unit_kerja, 'master_kategori_directory_id' => $master_kategori_directory_id, 'pegawai_id_entry' => auth()->user()->dataUser->id ?? 1, 'pegawai_nama_entry' => auth()->user()->dataUser->namalengkap ?? null, 'tanggal_terbit' => $data['date_active'] ?? null, 'no_dokumen' => $data['no_dokumen'] ?? null, 'nama_dokumen' => $data['nama_dokumen'] ?? null, 'tgl_expired' => $data['tgl_expired'] ?? null, 'permission_file' => ($data['is_permission'] ?? null) == "1", 'status_action' => $status, 'action_by' => $status && $status === "approved" ? auth()->user()->objectpegawaifk : null, 'action_at' => $status && $status === "approved" ? now() : null ]; $imageName = $uploadedFile->getClientOriginalName(); $path = "{$nama_unit_kerja}/{$nama_sub_unit_kerja}/{$nama_kategori}"; $uploadedFile->storeAs($path, $imageName, 'file_directory'); $payload['file'] =$path .'/' .$imageName; $fd = FileDirectory::create($payload); if(!$isAtasan){ $uploaderName = auth()->user()?->dataUser?->namalengkap ?? 'Pengguna'; $docNumber = $fd->no_dokumen ? 'nomor '. $fd->no_dokumen : $imageName; $payloadNotification = [ 'created_at' => now(), 'text_notifikasi' => "Dokumen {$docNumber} memerlukan persetujuan. Diunggah oleh {$uploaderName}.", 'url' => '/pending-file', 'is_read' => false, 'pegawai_id' => $mapping?->objectatasanlangsungfk, ]; Notifkasi::create($payloadNotification); if($mapping->objectpejabatpenilaifk){ $payloadNotification = [ 'created_at' => now(), 'text_notifikasi' => "Dokumen {$docNumber} memerlukan persetujuan. Diunggah oleh {$uploaderName}.", 'url' => '/pending-file', 'is_read' => false, 'pegawai_id' => $mapping?->objectpejabatpenilaifk, ]; Notifkasi::create($payloadNotification); } } } DB::connection('dbDirectory')->commit(); return response()->json([ 'status' => true, 'message' => 'Data berhasil disimpan', 'status_action' => $isAtasan ? 'approved' : null ], 200); } catch (\Throwable $th) { DB::connection('dbDirectory')->rollback(); return response()->json([ 'status' => false, 'message' => $th->getMessage() ], 500); } } public function dataPdfV2($id){ $data = FileDirectory::where('file_directory_id', $id)->first(); return view('pdf.index', compact('id'), compact('data')); } public function dataPdf($fileDirectoryId) { $data = FileDirectory::where('file_directory_id', $fileDirectoryId)->first(); $user = auth()->user()->dataUser; $mapping = MappingUnitKerjaPegawai::where('statusenabled', true) ->where('objectpegawaifk', $user->id)->where('isprimary', true) ->first(); $payloadLog = [ 'file_directory_id' => $fileDirectoryId, 'pegawai_id_entry' => auth()->user()->dataUser->id, 'pegawai_nama_entry' => auth()->user()->dataUser->namalengkap, 'entry_at' => now(), 'action_type' => 'Membuka Dokumen', 'no_dokumen' => $data->no_dokumen, 'file' => $data->file, 'statusenabled' => true, 'mod_change' => null, 'id_unit_kerja' => $mapping ? $mapping->objectunitkerjapegawaifk : null, 'id_sub_unit_kerja' => $mapping ? $mapping->objectsubunitkerjapegawaifk : null, ]; LogActivity::create($payloadLog); $filePath = public_path('file/' . $data->file); if (!file_exists($filePath)) { abort(404, 'PDF Tidak ditemukan'); } $stampFile = public_path('assets/copy.png'); if (!file_exists($stampFile)) { // kalau watermark tidak ada, tampilkan file asli return response()->file($filePath, [ 'Content-Type' => 'application/pdf', 'Content-Disposition' => 'inline; filename="preview.pdf"', 'Cache-Control' => 'no-store, no-cache, must-revalidate, max-age=0', ]); } $tempConverted = storage_path('app/temp/' . uniqid('conv_') . '.pdf'); try { // coba watermark langsung return $this->watermarkCenterAndStream($filePath, $stampFile); } catch (\Throwable $e) { // kalau gagal (PDF modern) -> convert dulu // dd($e); $this->convertWithGhostscript($filePath, $tempConverted); $resp = $this->watermarkCenterAndStream($tempConverted, $stampFile); @unlink($tempConverted); return $resp; } } private function watermarkCenterAndStream(string $pdfPath, string $stampFile) { $pdf = new PdfFpdiWithAlpha(); $pageCount = $pdf->setSourceFile($pdfPath); $opacity = $this->getWatermarkOpacity(); for ($pageNo = 1; $pageNo <= $pageCount; $pageNo++) { $tplId = $pdf->importPage($pageNo); $size = $pdf->getTemplateSize($tplId); $pdf->AddPage($size['orientation'], [$size['width'], $size['height']]); $pdf->useTemplate($tplId); // watermark tengah (skala adaptif) $stampW = $size['width'] * 0.60; $stampH = $stampW * 0.75; // sesuaikan rasio gambar kalau perlu $x = ($size['width'] - $stampW) / 2; $y = ($size['height'] - $stampH) / 2; $pdf->SetAlpha($opacity); $pdf->Image($stampFile, $x, $y, $stampW, $stampH); $pdf->SetAlpha(1); } $output = $pdf->Output('S'); return response($output, 200, [ 'Content-Type' => 'application/pdf', 'Content-Disposition' => 'inline; filename="preview.pdf"', 'Cache-Control' => 'no-store, no-cache, must-revalidate, max-age=0', ]); } /** * Generate watermarked PDF to temp file (or return original) for zipping. */ private function prepareFileWithWatermark(string $fullPath, array &$tempFiles = []) { $stampFile = public_path('assets/copy.png'); $ext = strtolower(pathinfo($fullPath, PATHINFO_EXTENSION)); if ($ext !== 'pdf' || !file_exists($stampFile)) { return $fullPath; } $tempDir = storage_path('app/temp'); if (!is_dir($tempDir)) { @mkdir($tempDir, 0777, true); } $tempOut = $tempDir . '/' . uniqid('wm_') . '.pdf'; try { $this->watermarkCenterToFile($fullPath, $stampFile, $tempOut); } catch (\Throwable $e) { // fallback convert then watermark $converted = $tempDir . '/' . uniqid('conv_') . '.pdf'; $this->convertWithGhostscript($fullPath, $converted); $this->watermarkCenterToFile($converted, $stampFile, $tempOut); $tempFiles[] = $converted; } $tempFiles[] = $tempOut; return $tempOut; } private function watermarkCenterToFile(string $pdfPath, string $stampFile, string $outputPath): void { $pdf = new PdfFpdiWithAlpha(); $pageCount = $pdf->setSourceFile($pdfPath); $opacity = $this->getWatermarkOpacity(); for ($pageNo = 1; $pageNo <= $pageCount; $pageNo++) { $tplId = $pdf->importPage($pageNo); $size = $pdf->getTemplateSize($tplId); $pdf->AddPage($size['orientation'], [$size['width'], $size['height']]); $pdf->useTemplate($tplId); $stampW = $size['width'] * 0.60; $stampH = $stampW * 0.75; $x = ($size['width'] - $stampW) / 2; $y = ($size['height'] - $stampH) / 2; $pdf->SetAlpha($opacity); $pdf->Image($stampFile, $x, $y, $stampW, $stampH); $pdf->SetAlpha(1); } $pdf->Output($outputPath, 'F'); } private function getWatermarkOpacity(): float { return 0.2; } private function cleanupTempFiles(array $tempFiles): void { foreach ($tempFiles as $file) { if (is_string($file) && file_exists($file)) { @unlink($file); } } } private function convertWithGhostscript(string $inputPdf, string $outputPdf): void { $gs = config('services.ghostscript.path'); if (!$gs || !file_exists($gs)) { throw new \RuntimeException('Ghostscript tidak ditemukan. Cek GHOSTSCRIPT_PATH di .env'); } $cmd = "\"{$gs}\" -sDEVICE=pdfwrite -dCompatibilityLevel=1.4 -dPDFSETTINGS=/prepress " . "-dNOPAUSE -dBATCH -dQUIET -sOutputFile=\"{$outputPdf}\" \"{$inputPdf}\""; exec($cmd, $out, $code); if ($code !== 0 || !file_exists($outputPdf)) { throw new \RuntimeException('Convert Ghostscript gagal (code=' . $code . ')'); } } public function recapData(){ try { $perPage = (int) request('per_page', 10); $page = max(1, (int) request('page', 1)); $keyword = strtolower(request('keyword', '')); // $authUnit = auth()->user()->masterPersetujuan->details->pluck('unit_pegawai_id')->unique()->toArray(); $user = auth()->user()->dataUser; $mapping = MappingUnitKerjaPegawai::where('statusenabled', true) ->where('objectpegawaifk', $user->id) ->get(['objectunitkerjapegawaifk', 'objectsubunitkerjapegawaifk']); $unitIds = $mapping->pluck('objectunitkerjapegawaifk') ->filter() // buang null ->unique() ->values() ->all(); $result = $this->buildRecapData($unitIds, $keyword); // paginate manually $total = count($result); $chunks = array_chunk($result, $perPage); $currentData = $chunks[$page-1] ?? []; return response()->json([ 'status' => true, 'data' => $currentData, 'message' => 'Berhasil mendapatkan data', 'pagination' => [ 'current_page' => $page, 'per_page' => $perPage, 'total' => $total, 'last_page' => max(1, ceil($total / $perPage)), 'has_more' => $page < max(1, ceil($total / $perPage)), ] ]); } catch (\Throwable $th) { return response()->json([ 'status' => false, 'message' => 'Gagal! mendapatkan data' ]); } } private function buildRecapData(array $unitIds, string $keyword = ''): array { $rows = FileDirectory::where('statusenabled', true) ->whereNotNull('status_action') ->whereIn('id_unit_kerja', $unitIds) ->pluck('file'); $grouped = []; foreach ($rows as $path) { $parts = array_values(array_filter(explode('/', $path))); if (count($parts) < 4) { continue; } $unit = $parts[0]; $folder = $parts[2]; if ($keyword) { $hit = str_contains(strtolower($unit), $keyword) || str_contains(strtolower($folder), $keyword); if (!$hit) { continue; } } if (!isset($grouped[$unit])) { $grouped[$unit] = []; } if (!isset($grouped[$unit][$folder])) { $grouped[$unit][$folder] = 0; } $grouped[$unit][$folder]++; } $result = []; foreach ($grouped as $unitName => $folders) { $data = []; foreach ($folders as $folder => $count) { $data[] = [ 'folder' => $folder, 'count' => $count, ]; } usort($data, fn($a, $b) => $b['count'] <=> $a['count']); $result[] = [ 'unit' => $unitName, 'data' => $data, ]; } return $result; } 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'); $objectpegawaifk = MappingUnitKerjaPegawai::query() ->where('statusenabled', true) ->where(fn($q) => $q->where('objectatasanlangsungfk', auth()->user()->objectpegawaifk) ->orWhere('objectpejabatpenilaifk', auth()->user()->objectpegawaifk) ) ->pluck('objectpegawaifk') ->unique() ->values() ->all(); $keyword = request('keyword'); $query = FileDirectory::where('statusenabled', true) ->where(function($qsa){ $qsa->where('status_action', '!=', 'approved')->orWhereNull('status_action'); }) ->whereIn('pegawai_id_entry', $objectpegawaifk) ->when($keyword, function ($q) use ($keyword) { $q->where(function ($sub) use ($keyword) { $sub->where('nama_dokumen', '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, 'nama_dokumen' => $item->nama_dokumen ?? '-', 'tgl_expired' => $item->tgl_expired, 'no_dokumen' => $item->no_dokumen, 'entry_at' => $item->entry_at, 'tanggal_terbit' => $item->tanggal_terbit, 'permission_file' => $item->permission_file, 'status_action' => $item->status_action ]; }); 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 { DB::connection('dbDirectory')->beginTransaction(); $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' => now(), 'action_by' => auth()->user()->dataUser->id, ]); $parts = array_values(array_filter(explode('/', $data->file))); $actionName = auth()->user()?->dataUser?->namalengkap ?? 'Pengguna'; $docNumber = $data->no_dokumen ? 'nomor '. $data->no_dokumen : end($parts); $payloadNotification = [ 'created_at' => now(), 'text_notifikasi' => "Dokumen {$docNumber} telah disetujui oleh {$actionName}.", 'url' => '/', 'is_read' => false, // 'pegawai_id' => $mapping?->objectatasanlangsungfk, 'pegawai_id' => $data->pegawai_id_entry, ]; Notifkasi::create($payloadNotification); DB::connection('dbDirectory')->commit(); return response()->json([ 'status' => true, 'message' => 'File berhasil di-approve' ], 200); } catch (\Throwable $th) { DB::connection('dbDirectory')->rollBack(); return response()->json([ 'status' => false, 'message' => $th->getMessage() ], 500); } } public function approvePendingFileMultiple(Request $request){ $ids = $request->input('ids', []); if (!is_array($ids) || count($ids) === 0) { return response()->json([ 'status' => false, 'message' => 'Daftar dokumen kosong' ], 422); } $ids = array_values(array_filter(array_map('strval', $ids))); if (count($ids) === 0) { return response()->json([ 'status' => false, 'message' => 'Daftar dokumen kosong' ], 422); } try { $files = FileDirectory::whereIn('file_directory_id', $ids)->get(); if ($files->isEmpty()) { return response()->json([ 'status' => false, 'message' => 'Data tidak ditemukan' ], 404); } DB::connection('dbDirectory')->beginTransaction(); $actionName = auth()->user()?->dataUser?->namalengkap ?? 'Pengguna'; $actionBy = auth()->user()?->dataUser?->id; $updated = 0; foreach ($files as $file) { if ($file->status_action === 'approved') { continue; } $file->update([ 'status_action' => 'approved', 'action_at' => now(), 'action_by' => $actionBy, ]); $parts = array_values(array_filter(explode('/', $file->file))); $docNumber = $file->no_dokumen ? 'nomor '. $file->no_dokumen : end($parts); $payloadNotification = [ 'created_at' => now(), 'text_notifikasi' => "Dokumen {$docNumber} telah disetujui oleh {$actionName}.", 'url' => '/', 'is_read' => false, 'pegawai_id' => $file->pegawai_id_entry, ]; Notifkasi::create($payloadNotification); $updated++; } DB::connection('dbDirectory')->commit(); $message = $updated > 0 ? "{$updated} dokumen berhasil di-approve" : 'Tidak ada dokumen yang diproses'; return response()->json([ 'status' => true, 'message' => $message, 'updated' => $updated ], 200); } catch (\Throwable $th) { DB::connection('dbDirectory')->rollBack(); return response()->json([ 'status' => false, 'message' => $th->getMessage() ], 500); } } public function rejectPendingFile(Request $request, string $id){ try { DB::connection('dbDirectory')->beginTransaction(); $data = FileDirectory::where('file_directory_id', $id)->first(); if(!$data){ return response()->json([ 'status' => false, 'message' => 'Data tidak ditemukan' ], 404); } $revision = trim((string) $request->input('revision', '')); if ($revision === '') { return response()->json([ 'status' => false, 'message' => 'Catatan revisi wajib diisi' ], 422); } $data->update([ 'status_action' => 'rejected', 'action_at' => now(), 'action_by' => auth()->user()->dataUser->id, 'revision' => $revision, ]); $parts = array_values(array_filter(explode('/', $data->file))); $actionName = auth()->user()?->dataUser?->namalengkap ?? 'Pengguna'; $docNumber = $data->no_dokumen ? 'nomor '. $data->no_dokumen : end($parts); $payloadNotification = [ 'created_at' => now(), 'text_notifikasi' => "Dokumen {$docNumber} telah ditolak oleh {$actionName}. ". "Silakan periksa dokumen untuk melakukan perbaikan.", 'url' => '/pengajuan-file', 'is_read' => false, // 'pegawai_id' => $mapping?->objectatasanlangsungfk, 'pegawai_id' => $data->pegawai_id_entry, ]; Notifkasi::create($payloadNotification); DB::connection('dbDirectory')->commit(); return response()->json([ 'status' => true, 'message' => 'File berhasil di-reject' ], 200); } catch (\Throwable $th) { DB::connection('dbDirectory')->rollBack(); return response()->json([ 'status' => false, 'message' => $th->getMessage() ], 500); } } public function countDataPending(){ try { $objectpegawaifk = MappingUnitKerjaPegawai::query() ->where('statusenabled', true) ->where(fn($q) => $q->where('objectatasanlangsungfk', auth()->user()->objectpegawaifk) ->orWhere('objectpejabatpenilaifk', auth()->user()->objectpegawaifk) ) ->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-> return response()->json([ 'status' => true, 'count' => $count, 'message' => 'Berhasil mendapatkan data' ]); } catch (\Throwable $th) { return response()->json([ 'status' => false, 'message' => 'Terdapat kesalahan!' ]); } } public function countRejectedPengajuan() { try { $count = FileDirectory::where('statusenabled', true) ->where('pegawai_id_entry', auth()->user()->objectpegawaifk) ->where('status_action', 'rejected') ->count(); return response()->json([ 'status' => true, 'count' => $count, 'message' => 'Berhasil mendapatkan data' ]); } catch (\Throwable $th) { return response()->json([ 'status' => false, 'message' => 'Terdapat kesalahan!' ]); } } public function notifkasiList() { try { $pegawaiId = auth()->user()?->dataUser?->id; if (!$pegawaiId) { return response()->json([ 'status' => false, 'message' => 'Pegawai tidak ditemukan', 'data' => [], 'unread' => 0 ], 404); } $query = Notifkasi::where('pegawai_id', $pegawaiId); $unread = (clone $query)->where('is_read', false)->count(); $items = $query->orderBy('created_at', 'desc') ->limit(20) ->get(['id', 'text_notifikasi', 'url', 'is_read', 'created_at']); return response()->json([ 'status' => true, 'data' => $items, 'unread' => $unread ]); } catch (\Throwable $th) { return response()->json([ 'status' => false, 'message' => 'Terdapat kesalahan!', 'data' => [], 'unread' => 0 ], 500); } } public function notifkasiMarkRead() { try { $pegawaiId = auth()->user()?->dataUser?->id; if (!$pegawaiId) { return response()->json([ 'status' => false, 'message' => 'Pegawai tidak ditemukan' ], 404); } Notifkasi::where('pegawai_id', $pegawaiId) ->where('is_read', false) ->update(['is_read' => true]); return response()->json([ 'status' => true, 'message' => 'Notifikasi ditandai dibaca' ]); } catch (\Throwable $th) { return response()->json([ 'status' => false, 'message' => 'Terdapat kesalahan!' ], 500); } } public function pengajuanFile(){ $katDok = MasterKategori::where('statusenabled', true) ->select('master_kategori_directory_id', 'nama_kategori_directory') ->get(); return view('pengajuanFile.index', [ 'title' => 'Data Pending', 'katDok' => $katDok ]); } public function dataPengajuanFile(){ $perPage = (int) request('per_page', 10); $keyword = request('keyword'); $start = request('start_date'); $end = request('end_date'); $query = FileDirectory::where('statusenabled', true)->where('pegawai_id_entry', auth()->user()->objectpegawaifk) ->where(function($q){ $q->where('status_action', '!=', 'approved') ->orWhereNull('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, 'nama_dokumen' => $item->nama_dokumen, 'entry_at' => $item->entry_at, 'tanggal_terbit' => $item->tanggal_terbit, 'tgl_expired' => $item->tgl_expired, 'permission_file' => $item->permission_file, 'status_action' => $item->status_action, 'revision' => $item->revision, 'id_unit_kerja' => $item->id_unit_kerja, 'id_sub_unit_kerja' => $item->id_sub_unit_kerja, 'master_kategori_directory_id' => $item->master_kategori_directory_id ]; }); 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 updatePengajuanFile(Request $request, string $id) { DB::connection('dbDirectory')->beginTransaction(); try { $data = FileDirectory::where('file_directory_id', $id) ->where('pegawai_id_entry', auth()->user()->objectpegawaifk) ->first(); if (!$data) { return response()->json([ 'status' => false, 'message' => 'Data tidak ditemukan' ], 404); } $payload = []; $unitName = null; $subName = null; $kategoriName = null; $parseIdName = function ($value) { $value = is_string($value) ? trim($value) : $value; if (!$value) { return [null, null]; } if (is_string($value) && str_contains($value, '/')) { [$idVal, $nameVal] = explode('/', $value, 2); return [trim($idVal), trim($nameVal)]; } return [$value, null]; }; if ($request->has('id_unit_kerja')) { [$unitId, $unitName] = $parseIdName($request->input('id_unit_kerja')); if ($unitId !== null && $unitId !== '') { $payload['id_unit_kerja'] = $unitId; } } if ($request->has('id_sub_unit_kerja')) { [$subId, $subName] = $parseIdName($request->input('id_sub_unit_kerja')); if ($subId !== null && $subId !== '') { $payload['id_sub_unit_kerja'] = $subId; } } if ($request->has('master_kategori_directory_id')) { [$kategoriId, $kategoriName] = $parseIdName($request->input('master_kategori_directory_id')); if ($kategoriId !== null && $kategoriId !== '') { $payload['master_kategori_directory_id'] = $kategoriId; } } if ($request->has('no_dokumen')) { $payload['no_dokumen'] = $request->input('no_dokumen') ?: null; } if ($request->has('nama_dokumen')) { $payload['nama_dokumen'] = $request->input('nama_dokumen') ?: null; } if ($request->has('tanggal_terbit')) { $payload['tanggal_terbit'] = $request->input('tanggal_terbit') ?: null; } if ($request->has('tgl_expired')) { $payload['tgl_expired'] = $request->input('tgl_expired') ?: null; } if ($request->has('permission_file')) { $permVal = $request->input('permission_file'); if ($permVal !== null && $permVal !== '') { $payload['permission_file'] = $permVal === '1' || $permVal === 1 || $permVal === true || $permVal === 'true'; } } if ($request->hasFile('file')) { $uploadedFile = $request->file('file'); $fileInfo = pathinfo($data->file); $folderPath = $fileInfo['dirname'] ?? ''; if ($folderPath === '.' || $folderPath === DIRECTORY_SEPARATOR) { $folderPath = ''; } $existingParts = array_values(array_filter(explode('/', $data->file))); $existingUnit = $existingParts[0] ?? null; $existingSub = $existingParts[1] ?? null; $existingKategori = $existingParts[2] ?? null; $targetUnit = $unitName ?: $existingUnit; $targetSub = $subName ?: $existingSub; $targetKategori = $kategoriName ?: $existingKategori; if ($targetUnit && $targetSub && $targetKategori) { $folderPath = "{$targetUnit}/{$targetSub}/{$targetKategori}"; } $imageName = $uploadedFile->getClientOriginalName(); $path = $folderPath ? "{$folderPath}" : ''; $uploadedFile->storeAs($path, $imageName, 'file_directory'); $payload['file'] = ($path ? $path . '/' : '') . $imageName; } $payload['status_action'] = 'revised'; if (!empty($payload)) { $data->update($payload); } $mapping = MappingUnitKerjaPegawai::where('statusenabled', true) ->where('objectpegawaifk', auth()->user()?->dataUser?->id) ->first(); $parts = array_values(array_filter(explode('/', $data->file))); $uploaderName = auth()->user()?->dataUser?->namalengkap ?? 'Pengguna'; $docNumber = $data->no_dokumen ? 'nomor '. $data->no_dokumen : end($parts);; $payloadNotification = [ 'created_at' => now(), 'text_notifikasi' => "Dokumen {$docNumber} telah direvisi dan memerlukan persetujuan ulang. ". "Direvisi oleh {$uploaderName}.", 'url' => '/pending-file', 'is_read' => false, 'pegawai_id' => $mapping?->objectatasanlangsungfk, ]; Notifkasi::create($payloadNotification); if($mapping->objectpejabatpenilaifk){ $payloadNotification = [ 'created_at' => now(), 'text_notifikasi' => "Dokumen {$docNumber} telah direvisi dan memerlukan persetujuan ulang. ". "Direvisi oleh {$uploaderName}.", 'url' => '/pending-file', 'is_read' => false, 'pegawai_id' => $mapping?->objectpejabatpenilaifk, ]; Notifkasi::create($payloadNotification); } DB::connection('dbDirectory')->commit(); return response()->json([ 'status' => true, 'message' => 'Data berhasil diperbarui' ], 200); } catch (\Throwable $th) { DB::connection('dbDirectory')->rollBack(); return response()->json([ 'status' => false, 'message' => $th->getMessage() ], 500); } } }