project_directory/app/Http/Controllers/DashboardController.php
2026-03-06 03:58:39 +07:00

2422 lines
100 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');
$kategori = request('kategori');
$kategoriHeader = request('kategori_header');
$unitFilter = request('unit');
$kategoriValues = is_array($kategori)
? array_values(array_filter($kategori))
: array_values(array_filter(explode(',', (string) $kategori)));
$kategoriHeaderValues = is_array($kategoriHeader)
? array_values(array_filter($kategoriHeader))
: array_values(array_filter(explode(',', (string) $kategoriHeader)));
$allKategoriValues = array_values(array_filter(array_merge($kategoriValues, $kategoriHeaderValues)));
$kategoriTypes = [];
$kategoriIds = [];
foreach ($allKategoriValues as $val) {
$lower = strtolower(trim((string) $val));
if (in_array($lower, ['akreditasi', 'akre'], true)) {
$kategoriTypes[] = 'akreditasi';
continue;
}
if ($lower === 'hukum') {
$kategoriTypes[] = 'hukum';
continue;
}
if ($lower === 'lainnya') {
$kategoriTypes[] = 'lainnya';
continue;
}
$kategoriIds[] = $val;
}
$unitFilterIds = is_array($unitFilter)
? array_values(array_filter($unitFilter))
: array_values(array_filter(explode(',', (string) $unitFilter)));
if (!empty($unitFilterIds)) {
$unitIds = array_values(array_intersect($unitIds, $unitFilterIds));
}
$baseQuery = FileDirectory::with('kategori')
->where('statusenabled', true)
->where('status_action', 'approved')
->whereIn('id_unit_kerja', $unitIds);
$query = (clone $baseQuery)
->when(!empty($kategoriIds) || !empty($kategoriTypes), function ($q) use ($kategoriIds, $kategoriTypes) {
$q->where(function ($sub) use ($kategoriIds, $kategoriTypes) {
$hasClause = false;
if (!empty($kategoriIds)) {
$sub->whereIn('master_kategori_directory_id', $kategoriIds);
$hasClause = true;
}
if (in_array('akreditasi', $kategoriTypes, true)) {
$sub->where('is_akre', true);
$hasClause = true;
}
if (in_array('hukum', $kategoriTypes, true)) {
$hasClause ? $sub->orWhereNotNull('kategori_hukum') : $sub->whereNotNull('kategori_hukum');
$hasClause = true;
}
if (in_array('lainnya', $kategoriTypes, true)) {
$hasClause ? $sub->orWhereNotNull('master_kategori_directory_id') : $sub->whereNotNull('master_kategori_directory_id');
}
});
})
->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);
$items = collect($data->items())->map(function($item){
$item->nama_kategori = $item->kategori->nama_kategori_directory ?? $item->kategori_hukum ?? null;
return $item;
});
$kategoriList = (clone $baseQuery)->get()->map(function($item){
if ($item->is_akre) {
return ['id' => 'akreditasi', 'label' => 'Kategori Akreditasi'];
}
if (!empty($item->kategori_hukum)) {
return ['id' => 'hukum', 'label' => 'Kategori Hukum'];
}
$label = $item->kategori->nama_kategori_directory ?? $item->nama_kategori_directory ?? 'Kategori';
$id = $item->master_kategori_directory_id ?? $label;
return ['id' => (string) $id, 'label' => $label];
})->unique('id')->values();
$payload = [
'status' => true,
'message' => 'Berhasil mendapatkan data',
'data' => $items,
'kategori_list' => $kategoriList,
'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('master_kategori_directory_id', '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 Kedaluwarsa Dokumen',
'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++;
$grandTotal = 0;
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);
$grandTotal += (int) ($folderItem['count'] ?? 0);
$rowIdx++;
}
$unitEndRow = max($unitStartRow, $rowIdx - 1);
$sheet->setCellValue("E{$unitStartRow}", $unitName);
if ($unitEndRow > $unitStartRow) {
$sheet->mergeCells("E{$unitStartRow}:E{$unitEndRow}");
}
}
$sheet->setCellValue("F{$rowIdx}", 'Total File');
$sheet->setCellValue("G{$rowIdx}", $grandTotal);
$sheet->getStyle("F{$rowIdx}:G{$rowIdx}")->applyFromArray([
'font' => ['bold' => true],
'borders' => [
'allBorders' => [
'borderStyle' => \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_THIN
]
]
]);
}
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) {
$q->where(function($subQuery){
$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'
]);
}
$fileInfo = pathinfo($data->file);
$newFileName = $fileInfo['filename'] . '_deleted.' . ($fileInfo['extension'] ?? '');
$dirName = $fileInfo['dirname'] ?? '';
$newPath = ($dirName && $dirName !== '.') ? ($dirName . '/' . $newFileName) : $newFileName;
$disk = Storage::disk('s3');
if ($disk->exists($data->file)) {
// S3 tidak bisa rename langsung, jadi copy lalu delete
$disk->copy($data->file, $newPath);
$disk->delete($data->file);
}
$data->update([
'statusenabled' => false,
'file' => $newPath
]);
$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);
}
$payloadLog = [
'file_directory_id' => $data->file_directory_id,
'pegawai_id_entry' => $data->pegawai_id_entry,
'pegawai_nama_entry' => $data->pegawai_nama_entry,
'entry_at' => now(),
'file' => $data->file,
'statusenabled' => true,
'nama_dokumen' => $data->nama_dokumen ?? null,
'no_dokumen' => $data->no_dokumen ?? null,
'mod_change' => null,
'id_unit_kerja' => $data ? $data->id_unit_kerja : null,
'id_sub_unit_kerja' => $data ? $data->id_sub_unit_kerja : null,
'action_type' => 'Menghapus Dokumen',
];
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'
]);
}
}
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 = [];
$tempDownloads = [];
$disk = Storage::disk('s3');
$tempDir = storage_path('app/temp');
if (!is_dir($tempDir)) {
@mkdir($tempDir, 0777, true);
}
if (!is_dir(public_path('zip'))) {
@mkdir(public_path('zip'), 0777, true);
}
if($zip->open($zipPath, ZipArchive::CREATE) === TRUE){
foreach ($paths as $path) {
if(!$disk->exists($path)){
throw new \Exception("File tidak ditemukan: " . $path);
}
$relativePathInZip = $path;
$ext = pathinfo($path, PATHINFO_EXTENSION);
$ext = $ext ? strtolower($ext) : 'bin';
$localPath = $tempDir . '/' . uniqid('s3_') . '.' . $ext;
file_put_contents($localPath, $disk->get($path));
$tempDownloads[] = $localPath;
$fileToAdd = $this->prepareFileWithWatermark($localPath, $tempFiles);
$zip->addFile($fileToAdd, $relativePathInZip);
}
$zip->close();
}
$this->cleanupTempFiles($tempFiles);
$this->cleanupTempFiles($tempDownloads);
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');
}
$disk = Storage::disk('s3');
if (!$data->file || !$disk->exists($data->file)) {
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,
]);
$tempDir = storage_path('app/temp');
if (!is_dir($tempDir)) {
@mkdir($tempDir, 0777, true);
}
$ext = pathinfo((string) $data->file, PATHINFO_EXTENSION);
$ext = $ext ? strtolower($ext) : 'bin';
$localPath = $tempDir . '/' . uniqid('s3_') . '.' . $ext;
file_put_contents($localPath, $disk->get($data->file));
$tempFiles = [];
$fileToSend = $this->prepareFileWithWatermark($localPath, $tempFiles);
$downloadName = basename($data->file);
$response = response()->download($fileToSend, $downloadName);
$response->deleteFileAfterSend(true);
$cleanup = array_merge($tempFiles, [$localPath]);
$cleanup = array_values(array_unique(array_filter($cleanup)));
// cleanup after response is sent
register_shutdown_function(function () use ($cleanup, $fileToSend) {
foreach ($cleanup as $file) {
if ($file === $fileToSend) {
continue;
}
if (is_string($file) && $file !== '' && file_exists($file)) {
@unlink($file);
}
}
});
return $response;
}
public function dataUmum(){
$katDok = MasterKategori::where('statusenabled', true)->select('master_kategori_directory_id', 'nama_kategori_directory')->get();
$unitKerja = UnitKerja::where('statusenabled', true)->select('id', 'name')->orderBy('name')->get();
$authMapping = auth()->user()?->dataUser?->mappingUnitKerjaPegawai[0];
$authUnitKerja = $authMapping->objectunitkerjapegawaifk;
$authSubUnitKerja = $authMapping->objectsubunitkerjapegawaifk;
$data = [
'title' => 'Dashboard',
'katDok' => $katDok,
'unitKerja' => $unitKerja,
'authUnitKerja' => $authUnitKerja,
'authSubUnitKerja' => $authSubUnitKerja,
];
return view('dataUmum.index', $data);
}
public function datatableDataUmum(){
$perPage = (int) request('per_page', 10);
$user = auth()->user()?->dataUser;
$akses = AksesFile::where(['pegawai_id' => $user->id, 'statusenabled' => true])->first();
$keyword = request('keyword');
$unitId = request('unit');
$kategori = request('kategori');
$kategoriHeader = request('kategori_header');
$unitIds = is_array($unitId)
? array_values(array_filter($unitId))
: array_values(array_filter(explode(',', (string) $unitId)));
$kategoriValues = is_array($kategori)
? array_values(array_filter($kategori))
: array_values(array_filter(explode(',', (string) $kategori)));
$kategoriHeaderValues = is_array($kategoriHeader)
? array_values(array_filter($kategoriHeader))
: array_values(array_filter(explode(',', (string) $kategoriHeader)));
$allKategoriValues = array_values(array_filter(array_merge($kategoriValues, $kategoriHeaderValues)));
$kategoriTypes = [];
$kategoriIds = [];
foreach ($allKategoriValues as $val) {
$lower = strtolower(trim((string) $val));
if (in_array($lower, ['akreditasi', 'akre'], true)) {
$kategoriTypes[] = 'akreditasi';
continue;
}
if ($lower === 'hukum') {
$kategoriTypes[] = 'hukum';
continue;
}
if ($lower === 'lainnya') {
$kategoriTypes[] = 'lainnya';
continue;
}
$kategoriIds[] = $val;
}
$baseQuery = FileDirectory::with('kategori')
->where('statusenabled', true)->where('status_action', 'approved')
->when(!empty($unitIds), function ($q) use ($unitIds) {
$q->whereIn('id_unit_kerja', $unitIds);
});
$query = (clone $baseQuery)
->when(!empty($kategoriIds) || !empty($kategoriTypes), function ($q) use ($kategoriIds, $kategoriTypes) {
$q->where(function ($sub) use ($kategoriIds, $kategoriTypes) {
$hasClause = false;
if (!empty($kategoriIds)) {
$sub->whereIn('master_kategori_directory_id', $kategoriIds);
$hasClause = true;
}
if (in_array('akreditasi', $kategoriTypes, true)) {
$hasClause ? $sub->orWhere('is_akre', true) : $sub->where('is_akre', true);
$hasClause = true;
}
if (in_array('hukum', $kategoriTypes, true)) {
$hasClause ? $sub->orWhereNotNull('kategori_hukum') : $sub->whereNotNull('kategori_hukum');
$hasClause = true;
}
if (in_array('lainnya', $kategoriTypes, true)) {
$hasClause ? $sub->orWhereNotNull('master_kategori_directory_id') : $sub->whereNotNull('master_kategori_directory_id');
}
});
})
->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);
$items = collect($data->items())->map(function($item){
$item->nama_kategori = $item->kategori->nama_kategori_directory ?? $item->kategori_hukum ?? null;
return $item;
});
$kategoriList = (clone $baseQuery)->get()->map(function($item){
if ($item->is_akre) {
return ['id' => 'akreditasi', 'label' => 'Kategori Akreditasi'];
}
if (!empty($item->kategori_hukum)) {
return ['id' => 'hukum', 'label' => 'Kategori Hukum'];
}
$label = $item->kategori->nama_kategori_directory ?? $item->nama_kategori_directory ?? 'Kategori';
$id = $item->master_kategori_directory_id ?? $label;
return ['id' => (string) $id, 'label' => $label];
})->unique('id')->values();
$payload = [
'status' => true,
'message' => 'Berhasil mendapatkan data',
'data' => $items,
'kategori_list' => $kategoriList,
'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 Kedaluwarsa Dokumen',
'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');
$maxUploadBytes = 10 * 1024 * 1024;
$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);
if(isset($data['akre'])){
$path = $data['akre'];
}else{
if(isset($data['master_kategori_directory_id'])){
list($master_kategori_directory_id, $nama_kategori) = explode('/', $data['master_kategori_directory_id'],2);
$path = "{$nama_unit_kerja}/{$nama_sub_unit_kerja}/{$nama_kategori}";
}else{
$path = "{$nama_unit_kerja}/{$nama_sub_unit_kerja}";
}
}
$uploadedFile = request()->file("data.$index.file");
if(!$uploadedFile){
throw new \RuntimeException('File wajib diunggah pada segment ke-' . ($index+1));
}
if (!$uploadedFile->isValid()) {
throw new \RuntimeException('Upload file gagal pada segment ke-' . ($index+1));
}
$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 ?? null,
'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,
'is_akre' => isset($data['akre']),
'kategori_hukum' => isset($data['kategori_hukum']) ? $data['kategori_hukum'] : null
];
$fd = FileDirectory::create($payload);
$disk = Storage::disk('s3');
$imageName = $this->buildStoredFileName(
$fd->nama_dokumen ?? null,
$fd->file_directory_id,
$uploadedFile->getClientOriginalExtension()
);
$disk->putFileAs(
$path,
$uploadedFile,
$imageName,
['visibility' => 'private']
);
$fd->update([
'file' => $path . '/' . $imageName
]);
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) {
// dd($th);
DB::connection('dbDirectory')->rollback();
return response()->json([
'status' => false,
'message' => $th->getMessage()
], 500);
}
}
public function dataPdfV2($id){
// dd(auth()->user()->dataUser->mappingUnitKerjaPegawai->pluck('objectunitkerjapegawaifk'));
$file = FileDirectory::findOrFail($id);
// kalau file umum → bebas akses
if ($file->permission_file === true) {
return view('pdf.index', [
'id' => $id,
'data' => $file
]);
}
$userUnitIds = auth()->user()
->dataUser
->mappingUnitKerjaPegawai
->pluck('objectunitkerjapegawaifk');
// cek apakah unit file termasuk unit user
if ($userUnitIds->contains($file->id_unit_kerja)) {
return view('pdf.index', [
'id' => $id,
'data' => $file
]);
}
abort(403, 'Anda tidak memiliki akses ke dokumen ini');
// $akses = FileDirectory::findOrFail($id);
// dd($akses->where('permission_file', false)->first());
// $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();
if (!$data) {
abort(404, 'PDF Tidak ditemukan');
}
$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);
$fileInfo = get_file_s3($data->file);
if (!$fileInfo || empty($fileInfo['file'])) {
abort(404, 'PDF Tidak ditemukan');
}
$mime = $fileInfo['mime'] ?? 'application/pdf';
$tempDir = storage_path('app/temp');
if (!is_dir($tempDir)) {
@mkdir($tempDir, 0777, true);
}
$ext = pathinfo((string) $data->file, PATHINFO_EXTENSION);
$ext = $ext ? strtolower($ext) : 'pdf';
$localPath = $tempDir . '/' . uniqid('s3_') . '.' . $ext;
file_put_contents($localPath, $fileInfo['file']);
$stampFile = public_path('assets/copy.png');
$tempConverted = $tempDir . '/' . uniqid('conv_') . '.pdf';
$resp = null;
try {
if (!file_exists($stampFile)) {
// kalau watermark tidak ada, tampilkan file asli
$resp = response($fileInfo['file'], 200, [
'Content-Type' => $mime,
'Content-Disposition' => 'inline; filename="preview.pdf"',
'Cache-Control' => 'no-store, no-cache, must-revalidate, max-age=0',
]);
} else {
try {
// coba watermark langsung
$resp = $this->watermarkCenterAndStream($localPath, $stampFile);
} catch (\Throwable $e) {
// kalau gagal (PDF modern) -> convert dulu
$this->convertWithGhostscript($localPath, $tempConverted);
$resp = $this->watermarkCenterAndStream($tempConverted, $stampFile);
}
}
} finally {
@unlink($localPath);
if (file_exists($tempConverted)) {
@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')->where('status_action', 'approved')
->where('is_akre')
->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 Persetujuan']);
}
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],
'folder' => $dataSlice[2],
'fileName' => isset($dataSlice[3]) ? $dataSlice[3] : null,
'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,
'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 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);
$payloadLog = [
'file_directory_id' => $data->file_directory_id,
'pegawai_id_entry' => $data->pegawai_id_entry,
'pegawai_nama_entry' => $data->pegawai_nama_entry,
'entry_at' => now(),
'file' => $data->file,
'statusenabled' => true,
'nama_dokumen' => $data->nama_dokumen ?? null,
'no_dokumen' => $data->no_dokumen ?? null,
'mod_change' => null,
'id_unit_kerja' => $data ? $data->id_unit_kerja : null,
'id_sub_unit_kerja' => $data ? $data->id_sub_unit_kerja : null,
'action_type' => 'Approved Dokumen',
];
LogActivity::create($payloadLog);
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);
$payloadLog = [
'file_directory_id' => $data->file_directory_id,
'pegawai_id_entry' => $data->pegawai_id_entry,
'pegawai_nama_entry' => $data->pegawai_nama_entry,
'entry_at' => now(),
'file' => $data->file,
'statusenabled' => true,
'nama_dokumen' => $data->nama_dokumen ?? null,
'no_dokumen' => $data->no_dokumen ?? null,
'mod_change' => null,
'id_unit_kerja' => $data ? $data->id_unit_kerja : null,
'id_sub_unit_kerja' => $data ? $data->id_sub_unit_kerja : null,
'action_type' => 'Rejected Dokumen',
];
LogActivity::create($payloadLog);
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 Persetujuan',
'katDok' => $katDok
]);
}
public function dataPengajuanFile(){
$perPage = (int) request('per_page', 10);
$keyword = request('keyword');
$start = request('start_date');
$end = request('end_date');
$isHistory = filter_var(request('history'), FILTER_VALIDATE_BOOLEAN);
$query = FileDirectory::where('statusenabled', true)
->where('pegawai_id_entry', auth()->user()->objectpegawaifk)
->when($isHistory, function($q){
$q->where('status_action', 'approved');
}, function($q){
$q->where(function($sub){
$sub->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],
'folder' => $dataSlice[2],
'fileName' => isset($dataSlice[3]) ? $dataSlice[3] : null,
'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,
'is_akre' => $item->is_akre,
'kategori_hukum' => $item->kategori_hukum
];
});
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}";
}
$namaDokumenForFile = array_key_exists('nama_dokumen', $payload)
? $payload['nama_dokumen']
: $data->nama_dokumen;
$imageName = $this->buildStoredFileName(
$namaDokumenForFile,
$data->file_directory_id,
$uploadedFile->getClientOriginalExtension()
);
$path = $folderPath ? "{$folderPath}" : '';
$disk = Storage::disk('s3');
$oldFile = $data->file;
$disk->putFileAs(
$path,
$uploadedFile,
$imageName,
['visibility' => 'private']
);
$payload['file'] = ($path ? $path . '/' : '') . $imageName;
if ($oldFile && $oldFile !== $payload['file'] && $disk->exists($oldFile)) {
$disk->delete($oldFile);
}
} elseif (array_key_exists('nama_dokumen', $payload)) {
$oldFile = (string) $data->file;
$fileInfo = pathinfo($oldFile);
$folderPath = $fileInfo['dirname'] ?? '';
if ($folderPath === '.' || $folderPath === DIRECTORY_SEPARATOR) {
$folderPath = '';
}
$currentExt = $fileInfo['extension'] ?? null;
$newFileName = $this->buildStoredFileName(
$payload['nama_dokumen'],
$data->file_directory_id,
$currentExt
);
$newFilePath = ($folderPath ? $folderPath . '/' : '') . $newFileName;
if ($oldFile !== '' && $oldFile !== $newFilePath) {
$disk = Storage::disk('s3');
if ($disk->exists($oldFile)) {
if ($disk->exists($newFilePath)) {
$disk->delete($newFilePath);
}
$disk->copy($oldFile, $newFilePath);
$disk->delete($oldFile);
$payload['file'] = $newFilePath;
}
}
}
$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);
}
$payloadLog = [
'file_directory_id' => $data->file_directory_id,
'pegawai_id_entry' => $data->pegawai_id_entry,
'pegawai_nama_entry' => $data->pegawai_nama_entry,
'entry_at' => now(),
'file' => $data->file,
'statusenabled' => true,
'nama_dokumen' => $data->nama_dokumen ?? null,
'no_dokumen' => $data->no_dokumen ?? null,
'mod_change' => null,
'id_unit_kerja' => $data ? $data->id_unit_kerja : null,
'id_sub_unit_kerja' => $data ? $data->id_sub_unit_kerja : null,
'action_type' => 'Revisi Dokumen',
];
LogActivity::create($payloadLog);
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);
}
}
private function buildStoredFileName(?string $namaDokumen, $fileDirectoryId, ?string $extension = null): string
{
$id = trim((string) $fileDirectoryId);
$rawNama = trim((string) ($namaDokumen ?? ''));
if ($rawNama !== '') {
$safeNama = preg_replace('/[^A-Za-z0-9_-]+/', '_', $rawNama);
$safeNama = trim((string) $safeNama, '_');
$baseName = ($safeNama !== '' ? $safeNama : $id) . '_' . $id;
} else {
$baseName = $id;
}
$ext = strtolower(trim((string) ($extension ?? '')));
return $ext !== '' ? "{$baseName}.{$ext}" : $baseName;
}
// public function historyPengajuan(){
// $data = FileDirectory::where('statusenabled', true)->where('pegawai_id_entry', auth()->user()->objectpegawaifk)->get();
// return $data;
// }
public function logDokumen()
{
$perPage = (int) request('per_page', 10);
$keyword = request('keyword');
$start = request('start_date');
$end = request('end_date');
$queryIsAtasan = MappingUnitKerjaPegawai::where('statusenabled', true)
->where(function ($q) {
$q->where('objectatasanlangsungfk', auth()->user()?->dataUser?->id)
->orWhere('objectpejabatpenilaifk', auth()->user()->objectpegawaifk);
});
$isAtasan = $queryIsAtasan->exists();
$query = LogActivity::query()
->from('logging.log_activity_file_directory as log')
->leftJoin('public.file_directory as fd', 'fd.file_directory_id', '=', 'log.file_directory_id')
->where('log.statusenabled', true)
->whereNotIn('log.action_type', ['Membuka Dokumen', 'Download Dokumen'])
->select([
'log.file_directory_id',
'log.pegawai_nama_entry',
'log.file',
'log.no_dokumen',
'log.nama_dokumen',
'log.entry_at',
'log.action_type',
'log.id_unit_kerja',
'log.id_sub_unit_kerja',
'fd.permission_file',
'fd.tanggal_terbit',
'fd.tgl_expired',
]);
if ($isAtasan) {
$unitIds = $queryIsAtasan
->get(['objectunitkerjapegawaifk'])
->pluck('objectunitkerjapegawaifk')
->filter()
->unique()
->values()
->all();
if (!empty($unitIds)) {
$query->whereIn('log.id_unit_kerja', $unitIds);
} else {
$query->whereRaw('1 = 0');
}
} else {
$query->where('log.pegawai_id_entry', auth()->user()->objectpegawaifk);
}
if ($keyword) {
$query->where(function ($q) use ($keyword) {
$q->where('log.file', 'ILIKE', "%{$keyword}%")
->orWhere('log.no_dokumen', 'ILIKE', "%{$keyword}%")
->orWhere('log.nama_dokumen', 'ILIKE', "%{$keyword}%")
->orWhere('log.action_type', 'ILIKE', "%{$keyword}%");
});
}
if ($start) {
$query->whereDate('log.entry_at', '>=', $start);
}
if ($end) {
$query->whereDate('log.entry_at', '<=', $end);
}
$paginated = $query->orderBy('log.entry_at', 'desc')->paginate($perPage);
$data = $paginated->getCollection()->map(function ($item) {
$parts = array_values(array_filter(explode('/', (string) $item->file)));
return [
'file_directory_id' => $item->file_directory_id,
'pegawai_nama_entry' => $item->pegawai_nama_entry,
'part' => $parts[0] ?? '-',
'folder' => $parts[2] ?? '-',
'fileName' => $parts[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,
'action_type' => $item->action_type,
];
});
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 dataAkreditasi(){
$katDok = MasterKategori::where('statusenabled', true)
->select('master_kategori_directory_id', 'nama_kategori_directory')
->get();
$data = [
'title' => 'Akreditasi',
'katDok' => $katDok
];
return view('dataAkreditasi.index', $data);
}
public function dataTableAkreditasi(Request $request)
{
$keyword = $request->query('keyword');
$perPage = (int) $request->query('per_page', 10);
$query = FileDirectory::withOut('unit')
->where('statusenabled', true)
->where('status_action', 'approved')
->where('is_akre', true);
// Logic Pencarian
$query->when($keyword, function ($q) use ($keyword) {
$q->where(function ($sub) use ($keyword) {
$sub->where('nama_dokumen', 'ILIKE', "%{$keyword}%")
->orWhere('no_dokumen', 'ILIKE', "%{$keyword}%")
->orWhere('file', 'ILIKE', "%{$keyword}%"); // Cari juga berdasarkan nama file di path
});
});
$data = $query->orderBy('entry_at', 'desc')->paginate($perPage);
return response()->json([
'status' => true,
'message' => 'Berhasil mendapatkan data',
'data' => $data->items(),
'pagination' => [
'current_page' => $data->currentPage(),
'total' => $data->total(),
'per_page' => $data->perPage(),
'last_page' => $data->lastPage(),
'has_more' => $data->hasMorePages(),
]
]);
}
}