select('master_kategori_directory_id', 'nama_kategori_directory')->get(); $klasifikasiDok = MasterKlasifikasi::where('statusenabled', true)->select('master_klasifikasi_directory_id', 'nama_klasifikasi_directory')->get(); $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 ]; return view('dashboard.index', $payload); } public function dataUnitKerja(){ $user = auth()->user()?->dataUser; $akses = AksesFile::where(['pegawai_id' => $user->id, 'statusenabled' => true])->first(); $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) { /* mode pencarian lengkap */ $unitKerja = UnitKerja::where('statusenabled', true) ->where('id', $filterUnit) ->with(['subUnitKerja' => fn($q) => $q->whereIn('id', $subArray) ->with(['fileDirectory' => fn($q) => $q ->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}%") ->orWhere('pegawai_nama_entry', 'ilike', "%{$keyword}%"); }) ) ]) ]) ->select('id', 'name') ->get(); } elseif ($akses?->all_akses) { /* all akses */ $unitKerja = UnitKerja::where('statusenabled', true)->with([ // muat relasi 'subUnitKerja' => fn($q) => $q->with([ // sub-unit 'fileDirectory' => fn($f) => $f->when($keyword, fn($q) => $q->where('file', 'ilike', "%{$keyword}%") ->orWhere('pegawai_nama_entry', 'ilike', "%{$keyword}%") ) ]) ]) ->select('id', 'name') ->get(); } elseif ($akses?->unit_akses) { /* akses per unit */ $unitKerja = UnitKerja::where(['statusenabled' => true, 'id' => $akses->unit_akses]) ->with([ // muat relasi 'subUnitKerja' => fn($q) => $q->with([ // sub-unit 'fileDirectory' => fn($f) => $f->when($keyword, fn($q) => $q->where(function($query) use ($keyword) { $query->where('file', 'ilike', "%{$keyword}%") ->orWhere('pegawai_nama_entry', 'ilike', "%{$keyword}%"); }) ) ]) ]) ->select('id', 'name') ->get(); } else { /* default : unit & sub milik sendiri */ $authUnit = $user?->mappingUnitKerjaPegawai[0]?->objectunitkerjapegawaifk; $authSub = $user?->mappingUnitKerjaPegawai[0]?->objectsubunitkerjapegawaifk; $unitKerja = UnitKerja::where('statusenabled', true) ->where('id', $authUnit) ->with([ // 1. sub-unit milik user 'subUnitKerja' => fn($q) => $q->where('id', $authSub) ->with([ // 2. file-directory + filter keyword 'fileDirectory' => fn($f) => $f->when($keyword, fn($q) => $q->where(function($query) use ($keyword) { $query->where('file', 'ilike', "%{$keyword}%") ->orWhere('pegawai_nama_entry', 'ilike', "%{$keyword}%"); }) ) ]) ]) ->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; } 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 deleteFile(string $id){ DB::connection('dbDirectory')->beginTransaction(); try { $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]); $payloadLog = [ 'file_directory_id' => $data->file_directory_id, 'pegawai_id_entry' => $data->pegawai_id_entry, 'pegawai_nama_entry' => $data->pegawai_nama_entry, 'entry_at' => $data->entry_at, 'action_type' => 'Hapus 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); 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 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', []); // [[unit_id=>u, sub_unit_id=>s], ...] if (empty($rows)) { return response()->json(['message' => 'Tidak ada data'], 422); } $paths = []; foreach ($rows as $r) { if(!empty($r['sub_unit_id'])){ $files = FileDirectory::where('id_sub_unit_kerja', $r['sub_unit_id'])->where('statusenabled', true)->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; if($zip->open($zipPath, ZipArchive::CREATE) === TRUE){ foreach ($paths as $path) { $fullPath = public_path('file/' . $path); if(file_exists($fullPath)){ $relativePathInZip = $path; $zip->addFile($fullPath, $relativePathInZip); }else{ throw new \Exception("File tidak ditemukan: " . $path); } } $zip->close(); } 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)->pluck('file'); }else{ $data = FileDirectory::where('id_sub_unit_kerja', $id)->where('statusenabled', true)->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; if($zip->open($zipPath, ZipArchive::CREATE) === TRUE){ foreach ($data as $path) { $fullPath = public_path('file/' . $path); if(file_exists($fullPath)){ $relativePathInZip = $path; $zip->addFile($fullPath, $relativePathInZip); }else{ throw new \Exception("File tidak ditemukan: " . $path); } } $zip->close(); } return response()->download(public_path('zip/' . $zipName))->deleteFileAfterSend(true); } catch (\Throwable $th) { return response()->json([ 'message' => 'Terjadi kesalahan', 'error' => $th->getMessage() ], 500); } } public function dashboardVersion2(){ $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('dashboardV2.index', $data); } public function dataDocumentLast(){ $perPage = request('per_page', 10); $data = FileDirectory::where('statusenabled', true) ->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() ] ]; return response()->json($payload); } public function storeVersion2(){ DB::connection('dbDirectory')->beginTransaction(); try { $datas = request('data'); foreach ($datas as $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); $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, 'permission_file' => $data['is_permission'] === "1" ? true : false, ]; if(!empty($data['file'])){ $file = $data['file']; $imageName = $file->getClientOriginalName(); $path = "{$nama_unit_kerja}/{$nama_sub_unit_kerja}/{$nama_kategori}"; $file->storeAs($path, $imageName, 'file_directory'); $payload['file'] =$path .'/' .$imageName; } $fd = FileDirectory::create($payload); $payloadLog = [ 'file_directory_id' => $fd->file_directory_id, 'pegawai_id_entry' => $fd->pegawai_id_entry, 'pegawai_nama_entry' => $fd->pegawai_nama_entry, 'entry_at' => $fd->entry_at, 'action_type' => 'Upload Dokumen', 'statusenabled' => true, 'mod_change' => $fd->entry_at, 'id_unit_kerja' => $fd->id_unit_kerja, 'id_sub_unit_kerja' => $fd->id_sub_unit_kerja, 'file' => $fd->file, 'tanggal_terbit' => $fd->tanggal_terbit, 'no_dokumen' => $fd->no_dokumen, 'permission_file' => $fd->permission_file, ]; LogActivity::create($payloadLog); } DB::connection('dbDirectory')->commit(); return response()->json([ 'status' => true, 'message' => 'Data berhasil disimpan' ], 200); } catch (\Throwable $th) { DB::connection('dbDirectory')->rollback(); return response()->json([ 'status' => false, 'message' => $th->getMessage() ], 500); } } public function dataPdf($fileDirectoryId) { $data = FileDirectory::where('file_directory_id', $fileDirectoryId)->first(); $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 Fpdi(); $pageCount = $pdf->setSourceFile($pdfPath); 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->Image($stampFile, $x, $y, $stampW, $stampH); } $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', ]); } 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 . ')'); } } }