🔧(services): Selaraskan fallback path foto pada PreviewLaporanService dan tambah logging

- Menyelaraskan resolusi path file foto di PreviewLaporanService dengan logika fallback seperti pada komponen foto:
  - Menggunakan `originalPath = $path['path']` sebagai path utama
  - Jika `statusLpj == 1` dan file asli tidak ditemukan, maka:
    - Ekstrak dua bagian terakhir dari path (contoh: `251051/251051_2_2.png`)
    - Bangun `fallbackPath` dengan pola `surveyor/001/{lastTwoParts}`
  - Tentukan `pathToUse`:
    - Apabila `fallbackPath` ada dan file fallback ditemukan, gunakan `fallbackPath`
    - Jika tidak, tetap gunakan `originalPath`
  - Resolusi final: `storage_path('app/public/' . $pathToUse)`

- Menambahkan logging untuk setiap operasi penting dan setiap titik pengembalian:
  - `Log::warning` saat path kosong terdeteksi dalam daftar paths
  - `Log::info` saat fallback kandidat dibangun dari `originalPath`
  - `Log::warning` saat file tidak ditemukan pada original maupun fallback (dengan menyertakan ketiganya: original, fallback, resolved)
  - `Log::info` saat file berhasil ditambahkan ke daftar unduhan
  - `Log::warning` saat tidak ada file valid setelah resolusi path
  - `Log::info` saat mengunduh single file
  - `Log::info` saat zip file berhasil dibuat (dengan jumlah file)
  - `Log::error` saat zip file gagal dibuat

- Memindahkan logika resolusi path di dalam loop pengolahan `$paths` untuk setiap item:
  - Mengganti setting langsung `storage_path('app/public/' . $path['path'])` dengan resolusi path yang bisa fallback
  - Menjaga struktur kontrol dengan `continue` jika file final tetap tidak ditemukan

- Menambahkan komentar level-fungsi (docblock) pada `previewLaporan`:
  - Menjelaskan tanggung jawab fungsi dalam menghasilkan PDF atau unduhan foto
  - Menjelaskan skenario fallback path dan tujuan mengurangi gambar hilang
  - Mendokumentasikan parameter dan bentuk nilai kembali respons
This commit is contained in:
Daeng Deni Mardaeni
2025-11-07 10:57:46 +07:00
parent a442f879b7
commit 45cebcf325

View File

@@ -75,6 +75,20 @@ use Modules\Lpj\Http\Requests\FormSurveyorRequest;
class PreviewLaporanService
{
/**
* Preview Laporan dan unduh foto terkait dengan logika fallback path.
*
* Menghasilkan PDF atau paket unduhan foto berdasarkan status laporan.
* Jika file foto asli tidak ditemukan dan status LPJ adalah 1, maka
* sistem akan mencoba menggunakan fallback path dengan pola
* `surveyor/001/{lastTwoParts}` untuk meminimalisir gambar hilang.
*
* @param int $permohonan_id ID Permohonan
* @param int $dokumen_id ID Dokumen
* @param int $jaminan_id ID Jaminan
* @param string $back URL atau rute kembali
* @return \Symfony\Component\HttpFoundation\Response
*/
public function previewLaporan($permohonan_id, $dokumen_id, $jaminan_id, $back)
{
$permohonan = $this->getPermohonanJaminanId(
@@ -140,6 +154,8 @@ class PreviewLaporanService
$tipeLaporanResponse = $this->checkPrintOutLaporan($permohonan_id, $document_id);
$tipeLaporan = $tipeLaporanResponse->getData();
//dd($permohonan_id, $document_id, $tipeLaporan);
if (!$tipeLaporan->status) {
//return redirect()->back()->with('error', 'Laporan tidak valid');
}
@@ -206,48 +222,91 @@ class PreviewLaporanService
$mig_permohonan = json_decode($permohonan->mig_permohonan);
if(($tipeLaporan->status === 'memo' && $permohonan->mig_permohonan) || $mig_permohonan->mig_mst_lpj_tot_nilai_pasar < 1){
$paths = $formFoto['upload_foto'] ?? null;
$paths = $formFoto['upload_foto'] ?? null;
if (!is_array($paths) || empty($paths)) {
return response()->json(['error' => 'No files to download'], 404);
}
$files = [];
foreach ($paths as $path) {
if (!$path['path']) {
continue;
if (!is_array($paths) || empty($paths)) {
return response()->json(['error' => 'No files to download'], 404);
}
$fullPath = storage_path('app/public/' . $path['path']);
if (!file_exists($fullPath)) {
continue;
$files = [];
foreach ($paths as $path) {
if (!$path['path']) {
Log::warning('PreviewLaporanService: Path kosong terdeteksi dalam daftar paths.');
continue;
}
// Logika fallback untuk path file
$originalPath = $path['path'];
$fallbackPath = null;
// Jika file asli tidak ditemukan, buat fallback path
if ($statusLpj == 1) {
$fullOriginalPath = storage_path('app/public/' . $originalPath);
if (!file_exists($fullOriginalPath)) {
// Ekstrak bagian akhir path (contoh: 251051/251051_2_2.png)
$pathParts = explode('/', $originalPath);
if (count($pathParts) >= 2) {
$lastTwoParts = array_slice($pathParts, -2);
$fallbackPath = 'surveyor/001/' . implode('/', $lastTwoParts);
Log::info('PreviewLaporanService: Menggunakan fallback path kandidat.', [
'original' => $originalPath,
'fallback' => $fallbackPath,
]);
}
}
}
// Tentukan path yang akan digunakan
$pathToUse = ($fallbackPath && $statusLpj == 1 && file_exists(storage_path('app/public/' . $fallbackPath)))
? $fallbackPath
: $originalPath;
$fullPath = storage_path('app/public/' . $pathToUse);
if (!file_exists($fullPath)) {
Log::warning('PreviewLaporanService: File tidak ditemukan untuk original maupun fallback.', [
'original' => $originalPath,
'fallback' => $fallbackPath,
'resolved' => $pathToUse,
]);
continue;
}
Log::info('PreviewLaporanService: Menambahkan file untuk diunduh.', [
'resolved' => $pathToUse,
'fullPath' => $fullPath,
]);
$files[] = $fullPath;
}
$files[] = $fullPath;
}
if (empty($files)) {
return response()->json(['error' => 'No valid files found'], 404);
}
// For single file, download directly
if (count($files) === 1) {
return response()->download($files[0]);
}
// For multiple files, create zip and download
$zipName = 'photos_' . time() . '.zip';
$zipPath = storage_path('app/public/' . $zipName);
$zip = new \ZipArchive();
if ($zip->open($zipPath, \ZipArchive::CREATE) === true) {
foreach ($files as $file) {
$zip->addFile($file, basename($file));
if (empty($files)) {
Log::warning('PreviewLaporanService: Tidak ada file valid ditemukan setelah resolusi path.');
return response()->json(['error' => 'No valid files found'], 404);
}
$zip->close();
return response()->download($zipPath)->deleteFileAfterSend(true);
}
return response()->json(['error' => 'Failed to create zip file'], 500);
}
// For single file, download directly
if (count($files) === 1) {
Log::info('PreviewLaporanService: Mengunduh single file.', ['file' => $files[0]]);
return response()->download($files[0]);
}
// For multiple files, create zip and download
$zipName = 'photos_' . time() . '.zip';
$zipPath = storage_path('app/public/' . $zipName);
$zip = new \ZipArchive();
if ($zip->open($zipPath, \ZipArchive::CREATE) === true) {
foreach ($files as $file) {
$zip->addFile($file, basename($file));
}
$zip->close();
Log::info('PreviewLaporanService: Zip file berhasil dibuat.', ['zip' => $zipPath, 'count' => count($files)]);
return response()->download($zipPath)->deleteFileAfterSend(true);
}
Log::error('PreviewLaporanService: Gagal membuat zip file.');
return response()->json(['error' => 'Failed to create zip file'], 500);
}
try {
$pdf = $this->generatePDF($viewLaporan, compact(
'permohonan',
@@ -280,6 +339,8 @@ class PreviewLaporanService
private function generatePDF(string $viewLaporan, array $data)
{
//return view('lpj::' . $viewLaporan, $data);
$pdf = PDF::loadView('lpj::' . $viewLaporan, $data);
$pdf->setPaper('A4', 'portrait');
$pdf->set_option('isHtml5ParserEnabled', true);
@@ -349,6 +410,7 @@ class PreviewLaporanService
// Ambil data JSON dari statusLpj
$data = json_decode($statusLpj->memo, true) ?? [];
$validationRules = [
'memo' => [
'kepada',