project_directory/app/Http/Controllers/DashboardController.php
2026-02-02 15:16:09 +07:00

1838 lines
74 KiB
PHP

<?php
namespace App\Http\Controllers;
use App\Models\AksesFile;
use App\Models\AksesFileDetail;
use App\Models\FileDirectory;
use App\Models\LogActivity;
use App\Models\MappingUnitKerjaPegawai;
use App\Models\MasterKategori;
use App\Models\MasterKlasifikasi;
use App\Models\Notifkasi;
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;
use Illuminate\Support\Str;
use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Writer\Xlsx;
use setasign\Fpdi\Fpdi;
use ZipArchive;
use function PHPUnit\Framework\isEmpty;
class PdfFpdiWithAlpha extends Fpdi
{
protected array $extgstates = [];
public function SetAlpha(float $alpha, string $blendMode = 'Normal'): void
{
$alpha = max(0.0, min(1.0, $alpha));
$gs = $this->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('<</Type /ExtGState');
foreach ($extgstate['parms'] as $k => $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");
$sheet->mergeCells('A1:F1');
$sheet->getStyle('A1')->getFont()->setBold(true)->setSize(14);
$sheet->getStyle('A1')->getAlignment()->setHorizontal('center');
$headers = [
'No Dokumen',
'Nama Dokumen',
'Kategori',
'Unit',
'Sub Unit',
'Tanggal Upload',
'Pengunggah'
];
$sheet->fromArray($headers, null, 'A4');
$sheet->getStyle('A4:G4')->applyFromArray([
'font' => ['bold' => true],
'alignment' => ['horizontal' => \PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER],
'borders' => [
'allBorders' => [
'borderStyle' => \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_THIN
]
]
]);
$sheet->getStyle('A4:G4')->getFont()->setBold(true);
$sheet->getStyle('A4:G4')->getAlignment()->setHorizontal('center');
$sheet->getStyle('A4:G4')->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->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', 'G') 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 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 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()
{
$user = auth()->user()?->dataUser;
$akses = AksesFile::where(['pegawai_id' => $user->id, 'statusenabled' => true])->first();
$keyword = request('keyword');
$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->where('permission_file', true);
}
$rows = $query->orderBy('entry_at', 'desc')->get();
$spreadsheet = new Spreadsheet();
$sheet = $spreadsheet->getActiveSheet();
$headers = [
'No Dokumen',
'Nama Dokumen',
'Kategori',
'Unit',
'Sub Unit',
'Tanggal Terbit',
'Tanggal Upload',
'Pengunggah',
'Akses'
];
$sheet->fromArray($headers, null, 'A1');
$rowIdx = 2;
foreach ($rows as $item) {
$parts = array_values(array_filter(explode('/', (string) $item->file)));
$unitName = $parts[0] ?? '-';
$subName = $parts[1] ?? '-';
$kategoriName = $parts[2] ?? '-';
$aksesLabel = $item->permission_file ? 'Umum' : 'Internal Unit';
$sheet->fromArray([
$item->no_dokumen ?? '-',
$item->nama_dokumen ?? '-',
$kategoriName,
$unitName,
$subName,
$item->tanggal_terbit ? Carbon::parse($item->tanggal_terbit)->format('d/m/Y') : '-',
$item->entry_at ? Carbon::parse($item->entry_at)->format('d/m/Y H:i') : '-',
$item->pegawai_nama_entry ?? '-',
$aksesLabel
], null, "A{$rowIdx}");
$rowIdx++;
}
$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);
}
}
}