## Ringkasan Melakukan perbaikan pada helper format Rupiah, akses role user, validasi data MIG, serta penyesuaian tampilan laporan dan dokumentasi. ## Perubahan Detail ### 🔧 Helper Function **app/Helpers/Lpj.php**: - Menambahkan parameter opsional `withSymbol` pada fungsi `formatRupiah()` untuk kontrol simbol Rp - Menambahkan handling untuk menghapus titik (.) dari input number sebelum proses - Memperbaiki return value untuk null/empty string sesuai parameter `withSymbol` - Mengganti `str_pad()` dengan `sprintf()` untuk generate random number (lebih efisien) ### 🛠️ Service Layer **app/Services/PreviewLaporanService.php**: - Memperbaiki validasi data MIG dengan menambahkan pengecekan `is_mig` flag - Menambahkan null safety pada property `mig_mst_lpj_tot_nilai_pasar` - Memperbaiki kondisi logic untuk memo dan validasi nilai pasar ### 🎨 View Components **resources/views/component/print-out-dokument.blade.php**: - Memperbaiki syntax Blade dari `@isset` menjadi `isset()` yang lebih proper **resources/views/debitur/components/debitur.blade.php**: - Memperbaiki role checking dari `hasRole()` menjadi `hasAnyRole()` untuk multiple roles **resources/views/debitur/index.blade.php**: - Menambahkan role 'admin' pada kondisi edit dan delete actions - Memperbaiki permission checking untuk administrator dan admin **resources/views/laporan/index.blade.php**: - Menyederhanakan logic tombol laporan dan resume - Menghapus logic role-based yang kompleks untuk tombol laporan - Memperbaiki route URL untuk print-out laporan - Menghapus function `generateLaporanButton()` yang tidak digunakan **resources/views/penilai/components/lpj-sederhana-standar.blade.php**: - Menambahkan role 'penilai' pada permission tombol simpan **resources/views/penilai/components/print-out-sederhana.blade.php**: - Memperbaiki tampilan data dokumen dengan menambahkan kolom nomor dokumen - Mengganti `number_format()` dengan `formatRupiah()` untuk konsistensi format - Menambahkan fallback untuk data tanah dan bangunan ketika `npw_tambahan` tidak tersedia - Memperbaiki perhitungan total nilai pasar wajar dengan proper parsing - Memperbaiki format tampilan nilai likuidasi - Memperbaiki struktur HTML tabel untuk dokumentasi **resources/views/penilai/components/signature-approval.blade.php**: - Memperbaiki route dan parameter untuk approval signature **resources/views/permohonan/index.blade.php**: - Menambahkan role 'admin' pada permission actions
778 lines
26 KiB
PHP
778 lines
26 KiB
PHP
<?php
|
|
declare(strict_types=1);
|
|
|
|
use Illuminate\Support\Facades\Log;
|
|
use Illuminate\Support\Facades\DB;
|
|
|
|
use Carbon\Carbon;
|
|
use Modules\Location\Models\City;
|
|
use Modules\Location\Models\District;
|
|
use Modules\Location\Models\Province;
|
|
use Modules\Location\Models\Village;
|
|
use Modules\Lpj\Models\CustomField;
|
|
use Modules\Lpj\Models\HolidayCalendar;
|
|
use Modules\Lpj\Models\JenisDokumen;
|
|
use Modules\Lpj\Models\Laporan;
|
|
use Modules\Lpj\Models\PenawaranDetailTender;
|
|
use Modules\Lpj\Models\PenawaranTender;
|
|
use Modules\Lpj\Models\Penilaian;
|
|
use Modules\Lpj\Models\TeamsUsers;
|
|
use Modules\Usermanagement\Models\User;
|
|
use Illuminate\Support\Facades\File;
|
|
use Illuminate\Support\Facades\Storage;
|
|
|
|
/**
|
|
* Format tanggal ke dalam format Bahasa Indonesia
|
|
*
|
|
* Mengubah tanggal menjadi format yang lebih mudah dibaca dalam Bahasa Indonesia.
|
|
* Contoh: "15 Januari 2024" atau "15 Januari 2024 pukul 14.30 WIB"
|
|
*
|
|
* @param string|mixed $date Tanggal yang akan diformat (string tanggal atau null)
|
|
* @param bool $time Apakah akan menampilkan waktu juga (default: false)
|
|
* @return string Tanggal yang sudah diformat dalam Bahasa Indonesia
|
|
*
|
|
* @example
|
|
* formatTanggalIndonesia('2024-01-15') // "15 Januari 2024"
|
|
* formatTanggalIndonesia('2024-01-15 14:30:00', true) // "15 Januari 2024 pukul 14.30 WIB"
|
|
* formatTanggalIndonesia(null) // ""
|
|
* formatTanggalIndonesia('invalid-date') // "invalid-date" (return as-is jika error)
|
|
*/
|
|
function formatTanggalIndonesia($date, $time = false): string
|
|
{
|
|
Log::debug('Memulai format tanggal Indonesia', [
|
|
'date' => $date,
|
|
'time' => $time
|
|
]);
|
|
|
|
// Validasi input null atau kosong
|
|
if (empty($date)) {
|
|
Log::debug('Tanggal kosong, return empty string');
|
|
return '';
|
|
}
|
|
|
|
Carbon::setLocale('id');
|
|
|
|
try {
|
|
$waktu = Carbon::parse($date);
|
|
|
|
if (!$time) {
|
|
$result = $waktu->translatedFormat('d F Y');
|
|
Log::debug('Format tanggal berhasil', ['result' => $result]);
|
|
return $result;
|
|
}
|
|
|
|
$result = $waktu->translatedFormat('d F Y') . ' pukul ' . $waktu->format('H.i') . ' WIB';
|
|
Log::debug('Format tanggal dengan waktu berhasil', ['result' => $result]);
|
|
return $result;
|
|
|
|
} catch (Throwable $e) {
|
|
Log::warning('Gagal parse tanggal', [
|
|
'date' => $date,
|
|
'error' => $e->getMessage()
|
|
]);
|
|
// Return input as-is jika gagal parse
|
|
return (string) $date;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Format angka ke dalam format mata uang Rupiah Indonesia
|
|
*
|
|
* Mengubah angka menjadi format mata uang Rupiah dengan pemisah ribuan
|
|
* dan menggunakan koma sebagai pemisah desimal sesuai standar Indonesia.
|
|
*
|
|
* @param int|float|string $number Angka yang akan diformat (bisa negatif)
|
|
* @param int $decimals Jumlah digit desimal (default: 0)
|
|
* @return string Angka yang sudah diformat dalam format Rupiah
|
|
*
|
|
* @example
|
|
* formatRupiah(1500000) // "Rp 1.500.000"
|
|
* formatRupiah(1500000.50, 2) // "Rp 1.500.000,50"
|
|
* formatRupiah(-500000) // "Rp -500.000"
|
|
* formatRupiah(0) // "Rp 0"
|
|
* formatRupiah(null) // "Rp 0"
|
|
*/
|
|
function formatRupiah($number, $decimals = 0, $withSymbol = true): string
|
|
{
|
|
Log::debug('Memulai format Rupiah', [
|
|
'number' => $number,
|
|
'decimals' => $decimals,
|
|
'withSymbol' => $withSymbol
|
|
]);
|
|
|
|
// Handle null atau kosong
|
|
if ($number === null || $number === '') {
|
|
Log::debug('Number null atau kosong, return Rp 0');
|
|
return $withSymbol ? 'Rp 0' : '0';
|
|
}
|
|
|
|
// Remove dots if present
|
|
$number = str_replace('.', '', (string) $number);
|
|
|
|
// Konversi ke float dan handle error
|
|
try {
|
|
$number = (float) $number;
|
|
} catch (Throwable $e) {
|
|
Log::warning('Gagal konversi number ke float', [
|
|
'number' => $number,
|
|
'error' => $e->getMessage()
|
|
]);
|
|
return $withSymbol ? 'Rp 0' : '0';
|
|
}
|
|
|
|
// Validasi decimals
|
|
$decimals = max(0, (int) $decimals);
|
|
|
|
$formatted = number_format($number, $decimals, ',', '.');
|
|
$result = $withSymbol ? 'Rp ' . $formatted : $formatted;
|
|
Log::debug('Format Rupiah berhasil', ['result' => $result]);
|
|
|
|
return $result;
|
|
}
|
|
|
|
function formatAlamat($alamat)
|
|
{
|
|
return ($alamat->address ? $alamat->address . ', ' : '') . (isset($alamat->village) ? $alamat->village->name . ', ' : '') . (isset($alamat->city) ? $alamat->city->name . ', ' : '') . (isset($alamat->province) ? $alamat->province->name . ', ' : '') . ($alamat->village->postal_code ?? '');
|
|
}
|
|
|
|
// andy add
|
|
function checkActiveDateRangePenawaran($id)
|
|
{
|
|
$penawaran = PenawaranTender::find($id);
|
|
|
|
$start_date = strtotime($penawaran->start_date);
|
|
$end_date = strtotime($penawaran->end_date);
|
|
$todays_date = strtotime(now());
|
|
//$todays_date = strtotime("+1 day", strtotime(now()));
|
|
|
|
$allow = true;
|
|
if ($todays_date >= $start_date && $todays_date <= $end_date) {
|
|
//Penawaran dibuka
|
|
$allow = true;
|
|
} else {
|
|
if ($todays_date < $start_date) {
|
|
//Penawaran Belum dibuka
|
|
$allow = true;
|
|
} else {
|
|
//Penawaran sudah ditutup
|
|
$allow = false;
|
|
}
|
|
}
|
|
|
|
return $allow;
|
|
}
|
|
|
|
function checkKelengkapanDetailKJPP($id)
|
|
{
|
|
$allow = true;
|
|
// DB::enableQueryLog();
|
|
// detail_penawaran apakah isian biaya_penawaran, attachment, dokumen_persetujuan sudah lengkap?
|
|
$query = PenawaranDetailTender::select('id')->where('penawaran_id', '=', $id)->where('status', '=', 1)->where(
|
|
function ($query) {
|
|
// no_proposal
|
|
$query->orWhere('no_proposal', '', "");
|
|
$query->orWhereNull('no_proposal');
|
|
|
|
// tgl_proposal
|
|
$query->orWhere('tgl_proposal', '', "");
|
|
$query->orWhereNull('tgl_proposal');
|
|
|
|
$query->orWhere('biaya_penawaran', '', "");
|
|
$query->orWhereNull('biaya_penawaran');
|
|
|
|
$query->orWhere('attachment', '', "");
|
|
$query->orWhereNull('attachment');
|
|
|
|
$query->orWhere('dokumen_persetujuan', '', "");
|
|
$query->orWhereNull('dokumen_persetujuan');
|
|
},
|
|
)->get();
|
|
|
|
if (sizeof($query) > 0) {
|
|
$allow = false;
|
|
}
|
|
|
|
return $allow;
|
|
}
|
|
|
|
// convert
|
|
function convertSlug($slug)
|
|
{
|
|
$words = explode('-', $slug);
|
|
|
|
foreach ($words as $index => $word) {
|
|
$words[$index] = strtoupper($word);
|
|
}
|
|
|
|
return implode(' ', $words);
|
|
}
|
|
|
|
// generate last penawaran.code
|
|
function onLastnumberCodePenawaran()
|
|
: string
|
|
{
|
|
// ambil code terakhir
|
|
$maxCode = PenawaranTender::max('code');
|
|
// chek data penawaran terakhir --> mengurutkan data berdasarkan kolom `created_at` secara DESC
|
|
// $penawaran = PenawaranTender::latest()->first();
|
|
$penawaran = PenawaranTender::where('code', '=', $maxCode)->first();
|
|
$code_penawaran_last = '';
|
|
|
|
// nomor di set 0001
|
|
$noUrutAkhirString = sprintf("%04s", 1);
|
|
if ($penawaran) {
|
|
$isNum = substr($maxCode, 2); // memastikan string ke 3 s/d 8 adalan numiric
|
|
$isNP = substr($maxCode, 0, 2);
|
|
if ((8 == strlen($maxCode)) && ("NP" == $isNP) && (ctype_digit($isNum))) {
|
|
$code_penawaran_last = substr($maxCode, -4);
|
|
$year_penawaran_last = Carbon::parse($penawaran->created_at)->year;
|
|
$year_now = Carbon::now()->year;
|
|
if ($year_now == $year_penawaran_last) {
|
|
$noUrutAkhirString = sprintf("%04s", abs($code_penawaran_last + 1));
|
|
}
|
|
// jika ternyata tahun tdk sama (kurang dari tahun sekarang), maka nomor di set 0001
|
|
}
|
|
|
|
}
|
|
|
|
return 'NP' . Carbon::now()->format('y') . $noUrutAkhirString;
|
|
}
|
|
|
|
// generate last penawaran.no_spk
|
|
function onLastnumberCodePenawaranSPK($jenis_laporan_code)
|
|
: string
|
|
{
|
|
|
|
// 20241124_001 ==> spk_no_core
|
|
// XXX / PJ / JKT / MONTH-ROM / FR|SR / 2024
|
|
// 001 / PJ / JKT / XI / FR / 2024
|
|
$maxCode = PenawaranTender::max('spk_no_core');
|
|
$penawaran = PenawaranTender::where('spk_no_core', '=', $maxCode)->first();
|
|
$no_spk_penawaran_last = '';
|
|
$year_penawaran_last = '';
|
|
$year_now = Carbon::now()->year;
|
|
// nomor di set 001
|
|
$noUrutAkhirString = sprintf("%03s", 1);
|
|
if ($penawaran) {
|
|
$no_spk_penawaran_last = substr($maxCode, -3);
|
|
$year_penawaran_last = substr($maxCode, 0, 4);
|
|
|
|
if ($year_now == $year_penawaran_last) {
|
|
$noUrutAkhirString = sprintf("%03s", abs($no_spk_penawaran_last + 1));
|
|
}
|
|
// jika ternyata tahun tdk sama (kurang dari tahun sekarang), maka nomor di set 001
|
|
}
|
|
|
|
$month = onRomawi(Carbon::now()->month);
|
|
|
|
$lastSPK = $noUrutAkhirString . ' / PJ / JKT / ' . $month . ' / ' . $jenis_laporan_code . ' / ' . $year_now;
|
|
return $lastSPK;
|
|
}
|
|
|
|
function onRomawi(int $bln)
|
|
: string
|
|
{
|
|
return convertToRoman($bln);
|
|
}
|
|
|
|
function penyebut($nilai)
|
|
{
|
|
$nilai = abs($nilai);
|
|
$huruf = [
|
|
"",
|
|
"satu",
|
|
"dua",
|
|
"tiga",
|
|
"empat",
|
|
"lima",
|
|
"enam",
|
|
"tujuh",
|
|
"delapan",
|
|
"sembilan",
|
|
"sepuluh",
|
|
"sebelas"
|
|
];
|
|
$temp = "";
|
|
if ($nilai < 12) {
|
|
$temp = " " . $huruf[$nilai];
|
|
} else if ($nilai < 20) {
|
|
$temp = penyebut($nilai - 10) . " belas";
|
|
} else if ($nilai < 100) {
|
|
$temp = penyebut($nilai / 10) . " puluh" . penyebut($nilai % 10);
|
|
} else if ($nilai < 200) {
|
|
$temp = " seratus" . penyebut($nilai - 100);
|
|
} else if ($nilai < 1000) {
|
|
$temp = penyebut($nilai / 100) . " ratus" . penyebut($nilai % 100);
|
|
} else if ($nilai < 2000) {
|
|
$temp = " seribu" . penyebut($nilai - 1000);
|
|
} else if ($nilai < 1000000) {
|
|
$temp = penyebut($nilai / 1000) . " ribu" . penyebut($nilai % 1000);
|
|
} else if ($nilai < 1000000000) {
|
|
$temp = penyebut($nilai / 1000000) . " juta" . penyebut($nilai % 1000000);
|
|
} else if ($nilai < 1000000000000) {
|
|
$temp = penyebut($nilai / 1000000000) . " milyar" . penyebut(fmod($nilai, 1000000000));
|
|
} else if ($nilai < 1000000000000000) {
|
|
$temp = penyebut($nilai / 1000000000000) . " trilyun" . penyebut(fmod($nilai, 1000000000000));
|
|
}
|
|
return $temp;
|
|
}
|
|
|
|
function terbilang($nilai)
|
|
{
|
|
if ($nilai < 0) {
|
|
$hasil = "minus " . trim(penyebut($nilai));
|
|
} else {
|
|
$hasil = trim(penyebut($nilai));
|
|
}
|
|
return $hasil;
|
|
}
|
|
|
|
function hitungHariKerja($tanggalMulai, $tanggalSelesai)
|
|
{
|
|
$tanggalMulai = Carbon::parse($tanggalMulai)->startOfDay();
|
|
$tanggalSelesai = Carbon::parse($tanggalSelesai)->endOfDay();
|
|
|
|
$hariKerja = 0;
|
|
$tanggalSekarang = $tanggalMulai->copy();
|
|
|
|
while ($tanggalSekarang <= $tanggalSelesai) {
|
|
// Cek apakah hari ini bukan Sabtu atau Minggu dan bukan hari libur
|
|
if (!$tanggalSekarang->isWeekend() && !in_array($tanggalSekarang->format('Y-m-d'), holidays())) {
|
|
$hariKerja++;
|
|
}
|
|
$tanggalSekarang->addDay();
|
|
}
|
|
|
|
return $hariKerja;
|
|
}
|
|
|
|
function countPermohonanForUser($userId)
|
|
{
|
|
$validStatuses = [
|
|
'assign',
|
|
'survey-completed',
|
|
'proses-laporan',
|
|
'paparan',
|
|
'proses-paparan',
|
|
'revisi-laporan',
|
|
'revisi-paparan',
|
|
'survey',
|
|
'proses-survey',
|
|
'request-reschedule',
|
|
'reschedule',
|
|
'rejected-reschedule',
|
|
'approved-reschedule',
|
|
'revisi-survey',
|
|
'revisi-pembayaran'
|
|
];
|
|
|
|
$result = Penilaian::whereHas('userPenilai', function ($query) use ($userId) {
|
|
$query->where('user_id', $userId);
|
|
})
|
|
->whereHas('permohonan', function ($query) use ($validStatuses) {
|
|
$query->whereIn('status', $validStatuses);
|
|
})
|
|
->get()
|
|
->groupBy(function ($item) {
|
|
// Pastikan mengakses properti dari model yang valid
|
|
return $item->userPenilai->first()->user_id . '-' . $item->permohonan->id;
|
|
})
|
|
->map(function ($group) {
|
|
return [
|
|
'statuses' => $group->pluck('permohonan.status')->unique()->values()->all(),
|
|
];
|
|
});
|
|
|
|
return $result->count();
|
|
}
|
|
|
|
|
|
function getMaxFileSize($jenis)
|
|
{
|
|
$jenisDokumen = JenisDokumen::where('name', $jenis)->first();
|
|
if (!$jenisDokumen) {
|
|
return 2048;
|
|
}
|
|
//konversi ke KB (1 MB = 1024 KB)
|
|
$maxSizeInKB = (int) $jenisDokumen->max_size * 1024;
|
|
|
|
return $maxSizeInKB;
|
|
}
|
|
|
|
function getUser($userId)
|
|
{
|
|
return User::find($userId);
|
|
}
|
|
|
|
function generateLpjUniqueCode($randomLength = 6)
|
|
{
|
|
|
|
$year = date('y');
|
|
$month = str_pad(date('m'), 2, '0', STR_PAD_LEFT);
|
|
$day = str_pad(date('d'), 2, '0', STR_PAD_LEFT);
|
|
|
|
// Generate random numbers
|
|
//$randomNumber = str_pad(mt_rand(0, pow(10, $randomLength) - 1), $randomLength, '0', STR_PAD_LEFT);
|
|
$randomNumber = sprintf('%0' . $randomLength . 'd', mt_rand(0, pow(10, $randomLength) - 1));
|
|
|
|
// Concatenate components to create the custom code
|
|
return $year . $month . $day . $randomNumber;
|
|
}
|
|
|
|
function checkRegionUserName($userId)
|
|
{
|
|
$region = TeamsUsers::where('user_id', $userId)->first();
|
|
if ($region) {
|
|
return $region->team->regions->name;
|
|
} else {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
function getNomorLaporan($permohonanId, $documentId, $type = 'nomor_laporan')
|
|
{
|
|
|
|
$laporan = Laporan::where([
|
|
'permohonan_id' => $permohonanId,
|
|
'dokumen_jaminan_id' => $documentId,
|
|
])->first();
|
|
|
|
if (!$laporan) {
|
|
return $type == 'nomor_laporan' ? '-' : null;
|
|
}
|
|
|
|
return $type == 'nomor_laporan' ? $laporan->nomor_laporan : $laporan->created_at;
|
|
}
|
|
|
|
function getCustomField($param)
|
|
{
|
|
if (is_numeric($param)) {
|
|
$field = CustomField::find($param);
|
|
} else {
|
|
$field = CustomField::where(['name' => $param])->first();
|
|
}
|
|
if ($field) {
|
|
return $field;
|
|
} else {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
function getWilayahName($code, $type)
|
|
{
|
|
try {
|
|
$wilayah = null;
|
|
|
|
if (!$code) {
|
|
return null;
|
|
}
|
|
|
|
switch ($type) {
|
|
case 'province':
|
|
$wilayah = Province::where('code', $code)->first();
|
|
return $wilayah ? $wilayah->name : null;
|
|
|
|
case 'city':
|
|
$wilayah = City::where('code', $code)->first();
|
|
return $wilayah ? $wilayah->name : null;
|
|
|
|
case 'district':
|
|
$wilayah = District::where('code', $code)->first();
|
|
return $wilayah ? $wilayah->name : null;
|
|
|
|
case 'village':
|
|
$wilayah = Village::where('code', $code)->first();
|
|
return $wilayah ? $wilayah->name : null;
|
|
|
|
default:
|
|
return null;
|
|
}
|
|
} catch (Exception $e) {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
|
|
function formatLabel($key)
|
|
{
|
|
|
|
static $labelCache = [];
|
|
if (isset($labelCache[$key])) {
|
|
return $labelCache[$key];
|
|
}
|
|
|
|
$customLabel = CustomField::where('name', $key)->first();
|
|
$labelCache[$key] = $customLabel->label ?? ucwords(str_replace('_', ' ', $key));
|
|
|
|
return $labelCache[$key];
|
|
}
|
|
|
|
function calculateSLA($permohonan, $type)
|
|
{
|
|
if (!$type) {
|
|
return null;
|
|
}
|
|
|
|
$nilai_plafond = in_array($permohonan->nilai_plafond_id, [2, 3]);
|
|
$nilai_plafond_2 = in_array($permohonan->nilai_plafond_id, [1]);
|
|
|
|
$slaMap = [
|
|
'resume' => $nilai_plafond ? 2 : null,
|
|
'paparan' => $nilai_plafond ? 2 : null,
|
|
'standard' => $nilai_plafond ? 3 : null,
|
|
'sederhana' => $nilai_plafond ? 2 : null,
|
|
'paparan' => $nilai_plafond_2 ? 3 : null,
|
|
'rap' => 3,
|
|
'memo' => $nilai_plafond ? 1 : null
|
|
];
|
|
|
|
if ($type === 'paparan' && isset($permohonan->tujuanPenilaian->name) && $permohonan->tujuanPenilaian->name === 'rap') {
|
|
return 2;
|
|
}
|
|
|
|
return $slaMap[$type] ?? null;
|
|
}
|
|
|
|
|
|
/**
|
|
* Menghitung total nilai berdasarkan key dan jenis legalitas.
|
|
*
|
|
* @param array $detailsArray
|
|
* @param string $key
|
|
* @param int $jenisLegalitas
|
|
*
|
|
* @return int
|
|
*/
|
|
function calculateTotalLuas($detailsArray, $key, $jenisLegalitas, $defaultJenisLegalitas, $fallbackJenisLegalitas)
|
|
{
|
|
$total = 0;
|
|
|
|
if ($detailsArray) {
|
|
foreach ($detailsArray as $item) {
|
|
if (isset($item->jenis_legalitas_jaminan_id) && $item->jenis_legalitas_jaminan_id === $jenisLegalitas) {
|
|
$details = json_decode($item->details, true);
|
|
|
|
if (is_array($details)) {
|
|
foreach ($details as $detail) {
|
|
if (isset($detail[$key])) {
|
|
$total += (int) $detail[$key];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Jika total masih 0, gunakan jenis jaminan ppjb
|
|
if ($total === 0) {
|
|
foreach ($detailsArray as $item) {
|
|
if (isset($item->jenis_legalitas_jaminan_id) && $item->jenis_legalitas_jaminan_id === $defaultJenisLegalitas) {
|
|
$details = json_decode($item->details, true);
|
|
|
|
if (is_array($details)) {
|
|
foreach ($details as $detail) {
|
|
if (isset($detail[$key]) && $detail[$key] !== null) {
|
|
$total += (int) $detail[$key];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// jika total masih kosong juga maka gunakan ppb
|
|
if ($total === 0 && $fallbackJenisLegalitas !== null) {
|
|
foreach ($detailsArray as $item) {
|
|
if (isset($item->jenis_legalitas_jaminan_id) && $item->jenis_legalitas_jaminan_id === $fallbackJenisLegalitas) {
|
|
$details = json_decode($item->details, true);
|
|
|
|
if (is_array($details)) {
|
|
foreach ($details as $detail) {
|
|
if (isset($detail[$key]) && $detail[$key] !== null) {
|
|
$total += (int) $detail[$key];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return $total > 0 ? $total : 0;
|
|
}
|
|
|
|
|
|
function ubahNomorHp($nomorHp)
|
|
{
|
|
|
|
$nomorHp = preg_replace('/\D/', '', $nomorHp);
|
|
if (strpos($nomorHp, '62') === 0) {
|
|
$nomorBaru = substr($nomorHp, 0, 5) . "xxxxx";
|
|
return '+' . $nomorBaru;
|
|
} else if (strpos($nomorHp, '0') === 0) {
|
|
|
|
$nomorBaru = substr($nomorHp, 0, 5) . "xxxxxx";
|
|
return $nomorBaru;
|
|
} else {
|
|
return "Nomor HP tidak valid";
|
|
}
|
|
}
|
|
|
|
function parsePembandingMigration($keterangan) {
|
|
$keterangan = preg_replace('/[-]{5,}/', '',$keterangan); // Hapus ------
|
|
$keterangan = preg_replace('/[.]{5,}/', '',$keterangan); // Hapus .....
|
|
|
|
$keterangan = preg_replace('/\s+/', ' ',$keterangan);
|
|
$keterangan = preg_replace('/\s*\n\s*/', "\n",$keterangan);
|
|
|
|
// Pecah teks per baris untuk diproses
|
|
$lines = explode("\n",$keterangan);
|
|
$cleaned = [];
|
|
|
|
foreach ($lines as $line) {
|
|
$line = trim($line);
|
|
if (!empty($line)) {
|
|
// Format angka dalam format Rp. 123.456.789
|
|
$line = preg_replace_callback('/Rp\.\s*([\d.,]+)/', function($matches) {
|
|
$angka = str_replace(['.', ','], '', $matches[1]);
|
|
return 'Rp. ' . number_format((int)$angka, 0, ',', '.');
|
|
}, $line);
|
|
|
|
// Jika ada tanda pagar (#), pisahkan menjadi baris baru
|
|
$line = str_replace('#', "\n#", $line);
|
|
|
|
$cleaned[] = $line;
|
|
}
|
|
}
|
|
|
|
return implode("\n", $cleaned);
|
|
}
|
|
|
|
/**
|
|
* get full path to internal storage file or external storage file
|
|
*
|
|
* @param string $path
|
|
* @return string
|
|
*/
|
|
|
|
function getFilePath($path)
|
|
{
|
|
// define base path external storage (use .env) example: 'F:\path\to\storage' in windows
|
|
$externalBase = env('EXTERNAL_STORAGE_BASE_PATH', 'F:LPJ/lpj/LPJ Gambar/001/');
|
|
|
|
$segments = explode('/', $path);
|
|
|
|
if(strtoupper($segments[0]) === 'SURVEYOR'){
|
|
$year = $segments[1];
|
|
$month = ucfirst(strtolower($segments[2]));
|
|
$date = $segments[3];
|
|
$code = $segments[4];
|
|
$file = $segments[5] ?? '';
|
|
|
|
$extenalFullpath = $externalBase . $year . '/' . $month . '/' . $date . '/' . $code . '/' . $file;
|
|
|
|
if(File::exists($extenalFullpath)){
|
|
return $extenalFullpath;
|
|
}
|
|
}
|
|
|
|
// if not found in external storage, try to find in internal storage
|
|
if (Storage::exists($path)) {
|
|
return Storage::url('app/' . $path);
|
|
}
|
|
return $path;
|
|
}
|
|
|
|
|
|
function parseTimestamp(?string $timestamp): ?string
|
|
{
|
|
if (!$timestamp) {
|
|
return null;
|
|
}
|
|
|
|
// Trim whitespace dan normalize
|
|
$timestamp = trim($timestamp);
|
|
|
|
// Log untuk debugging
|
|
Log::info('Mencoba parsing timestamp: "' . $timestamp . '"');
|
|
|
|
// Parsing dengan DateTime native PHP untuk lebih robust
|
|
try {
|
|
// Pattern untuk format d/m/Y H:i:s
|
|
if (preg_match('/^(\d{1,2})\/(\d{1,2})\/(\d{4})\s+(\d{1,2}):(\d{1,2}):(\d{1,2})$/', $timestamp, $matches)) {
|
|
$day = (int) $matches[1];
|
|
$month = (int) $matches[2];
|
|
$year = (int) $matches[3];
|
|
$hour = (int) $matches[4];
|
|
$minute = (int) $matches[5];
|
|
$second = (int) $matches[6];
|
|
|
|
// Validasi nilai
|
|
if ($day >= 1 && $day <= 31 && $month >= 1 && $month <= 12 && $year >= 1900 && $year <= 2100 &&
|
|
$hour >= 0 && $hour <= 23 && $minute >= 0 && $minute <= 59 && $second >= 0 && $second <= 59) {
|
|
|
|
// Buat DateTime object langsung
|
|
$dateTime = new \DateTime();
|
|
$dateTime->setDate($year, $month, $day);
|
|
$dateTime->setTime($hour, $minute, $second);
|
|
|
|
$result = $dateTime->format('Y-m-d H:i:s');
|
|
Log::info('Berhasil parsing dengan DateTime: ' . $timestamp . ' -> ' . $result);
|
|
return $result;
|
|
}
|
|
}
|
|
|
|
// Pattern untuk format d/m/Y tanpa waktu
|
|
if (preg_match('/^(\d{1,2})\/(\d{1,2})\/(\d{4})$/', $timestamp, $matches)) {
|
|
$day = (int) $matches[1];
|
|
$month = (int) $matches[2];
|
|
$year = (int) $matches[3];
|
|
|
|
// Validasi nilai
|
|
if ($day >= 1 && $day <= 31 && $month >= 1 && $month <= 12 && $year >= 1900 && $year <= 2100) {
|
|
|
|
// Buat DateTime object langsung
|
|
$dateTime = new \DateTime();
|
|
$dateTime->setDate($year, $month, $day);
|
|
$dateTime->setTime(0, 0, 0);
|
|
|
|
$result = $dateTime->format('Y-m-d H:i:s');
|
|
Log::info('Berhasil parsing tanpa waktu dengan DateTime: ' . $timestamp . ' -> ' . $result);
|
|
return $result;
|
|
}
|
|
}
|
|
} catch (\Exception $e) {
|
|
Log::error('Gagal parsing dengan DateTime: ' . $timestamp . '. Error: ' . $e->getMessage());
|
|
}
|
|
|
|
// Fallback ke format Carbon standar untuk format lainnya
|
|
$formats = [
|
|
'Y-m-d H:i:s',
|
|
'Y-m-d',
|
|
'd-m-Y H:i:s',
|
|
'd-m-Y',
|
|
'j-n-Y H:i:s',
|
|
'j-n-Y',
|
|
];
|
|
|
|
foreach ($formats as $format) {
|
|
try {
|
|
$carbon = \Carbon\Carbon::createFromFormat($format, $timestamp);
|
|
|
|
if ($carbon && $carbon->format($format) === $timestamp) {
|
|
// Jika format tidak mengandung waktu, set ke awal hari
|
|
if (!str_contains($format, 'H:i:s')) {
|
|
$carbon = $carbon->startOfDay();
|
|
}
|
|
Log::info('Berhasil parsing dengan format ' . $format . ': ' . $timestamp . ' -> ' . $carbon->toDateTimeString());
|
|
return $carbon->toDateTimeString();
|
|
}
|
|
} catch (\Exception $e) {
|
|
// Lanjut ke format berikutnya
|
|
continue;
|
|
}
|
|
}
|
|
|
|
Log::error('Tidak dapat memparsing timestamp dengan format apapun: "' . $timestamp . '"');
|
|
return null;
|
|
}
|