Merge branch 'staging' of https://git.putrakuningan.com/daengdeni/lpj into tender

This commit is contained in:
2025-04-23 10:42:37 +07:00
12 changed files with 1203 additions and 547 deletions

View File

@@ -0,0 +1,126 @@
<?php
namespace Modules\Lpj\Exports;
use Maatwebsite\Excel\Concerns\FromCollection;
use Maatwebsite\Excel\Concerns\WithHeadings;
use Maatwebsite\Excel\Concerns\WithMapping;
use Modules\Lpj\Models\Permohonan;
use Illuminate\Support\Facades\Auth;
class LaporanPenilaianJaminanExport implements FromCollection, WithHeadings, WithMapping
{
protected $request;
public function __construct($request)
{
$this->request = $request;
}
public function collection()
{
$query = Permohonan::query();
$query = $query->where('status', 'done');
// Apply date range filter if provided
if ($this->request->has('start_date') || $this->request->has('end_date')) {
$query->whereBetween('tanggal_permohonan', [
$this->request->start_date ?? '1900-01-01',
$this->request->end_date ?? now()->toDateString()
]);
}
// Apply branch filter if provided
if ($this->request->has('branch_id') && !empty($this->request->branch_id)) {
$query->where('branch_id', $this->request->branch_id);
}
// Apply search filter if provided
if ($this->request->has('search') && !empty($this->request->search)) {
$search = $this->request->search;
$query->where(function ($q) use ($search) {
$q->where('nomor_registrasi', 'LIKE', '%' . $search . '%');
$q->orWhere('tanggal_permohonan', 'LIKE', '%' . $search . '%');
$q->orWhereRelation('user', 'name', 'LIKE', '%' . $search . '%');
$q->orWhereRelation('tujuanPenilaian', 'name', 'LIKE', '%' . $search . '%');
$q->orWhereRelation('branch', 'name', 'LIKE', '%' . $search . '%');
$q->orWhereRelation('jenisFasilitasKredit', 'name', 'LIKE', '%' . $search . '%');
$q->orWhereRelation('jenisPenilaian', 'name', 'LIKE', '%' . $search . '%');
$q->orWhere('status', 'LIKE', '%' . $search . '%');
});
}
// Default ordering
$query->orderBy('nomor_registrasi', 'asc');
return $query->with(['debiture.branch'])->get();
}
public function map($permohonan): array
{
$luas_tanah = 0;
$luas_bangunan = 0;
$nilai_tanah = 0;
$nilai_bangunan = 0;
$npw = 0;
$nilai_liquidasi = 0;
if (isset($permohonan->penilai->lpj)) {
$lpj = json_decode($permohonan->penilai->lpj, true);
$npw = str_replace('.', '', $lpj['total_nilai_pasar_wajar'] ?? 0);
$luas_tanah = $lpj['luas_tanah'] ?? 0;
$luas_bangunan = $lpj['luas_bangunan'] ?? 0;
$nilai_tanah = str_replace('.', '', $lpj['nilai_tanah_2'] ?? 0);
$nilai_bangunan = str_replace('.', '', $lpj['nilai_bangunan_2'] ?? 0);
$nilai_liquidasi = str_replace('.', '', $lpj['likuidasi_nilai_2'] ?? 0);
}
return [
$permohonan->id,
$permohonan->nomor_registrasi,
$permohonan->tanggal_permohonan,
$permohonan->debiture->branch->name,
$permohonan->debiture->name,
$permohonan->creator->name,
$permohonan->tujuanPenilaian->name,
$permohonan->documents->pluck('jenisJaminan.name')->unique()->implode(', '),
$permohonan->documents->map(function ($document) {
return formatAlamat($document);
})->unique()->implode(', '),
$luas_tanah . ' m²',
formatRupiah($nilai_tanah, 2),
$luas_bangunan . ' m²',
formatRupiah($nilai_bangunan, 2),
'', // tanggal_laporan
'', // tanggal_review
formatRupiah($npw, 2),
formatRupiah($nilai_liquidasi, 2),
$permohonan->penilaian->_user_penilai->userPenilaiTeam->name,
];
}
public function headings(): array
{
return [
'ID',
'Nomor Registrasi',
'Tanggal Permohonan',
'Cabang',
'Nama Debitur',
'Pemohon',
'Tujuan Penilaian',
'Jenis Agunan',
'Alamat Agunan',
'Luas Tanah',
'Nilai Tanah',
'Luas Bangunan',
'Nilai Bangunan',
'Tanggal Laporan',
'Tanggal Review',
'Nilai Pasar Wajar',
'Nilai Likuidasi',
'Nama Penilai',
];
}
}

View File

@@ -19,8 +19,7 @@
public function collection() public function collection()
{ {
$query = Permohonan::with(['user', 'branch', 'tujuanPenilaian', 'jenisFasilitasKredit', 'jenisPenilaian']) $query = Permohonan::query();
->select('permohonan.*');
// Apply role-based filtering // Apply role-based filtering
if (!Auth::user()->hasAnyRole(['administrator'])) { if (!Auth::user()->hasAnyRole(['administrator'])) {

View File

@@ -1,23 +1,23 @@
<?php <?php
use Carbon\Carbon; use Carbon\Carbon;
use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\DB;
use Modules\Lpj\Models\CustomField; use Modules\Location\Models\City;
use Modules\Lpj\Models\HolidayCalendar; use Modules\Location\Models\District;
use Modules\Lpj\Models\PenawaranDetailTender; use Modules\Location\Models\Province;
use Modules\Lpj\Models\PenawaranTender; use Modules\Location\Models\Village;
use Modules\Lpj\Models\Penilaian; use Modules\Lpj\Models\CustomField;
use Modules\Lpj\Models\JenisDokumen; use Modules\Lpj\Models\HolidayCalendar;
use Modules\Lpj\Models\TeamsUsers; use Modules\Lpj\Models\JenisDokumen;
use Modules\Lpj\Models\Laporan; use Modules\Lpj\Models\Laporan;
use Modules\Usermanagement\Models\User; use Modules\Lpj\Models\PenawaranDetailTender;
use Modules\Location\Models\Province; use Modules\Lpj\Models\PenawaranTender;
use Modules\Location\Models\City; use Modules\Lpj\Models\Penilaian;
use Modules\Location\Models\District; use Modules\Lpj\Models\TeamsUsers;
use Modules\Location\Models\Village; use Modules\Usermanagement\Models\User;
function formatTanggalIndonesia($date, $time = false) function formatTanggalIndonesia($date, $time = false)
{ {
Carbon::setLocale('id'); Carbon::setLocale('id');
try { try {
$waktu = Carbon::parse($date); $waktu = Carbon::parse($date);
@@ -25,28 +25,28 @@ function formatTanggalIndonesia($date, $time = false)
return $waktu->translatedFormat('d F Y'); return $waktu->translatedFormat('d F Y');
} }
return $waktu->translatedFormat('d F Y') . ' pukul ' . $waktu->format('H.i') . ' WIB'; return $waktu->translatedFormat('d F Y') . ' pukul ' . $waktu->format('H.i') . ' WIB';
} catch (\Throwable $e) { } catch (Throwable $e) {
return $date; return $date;
} }
} }
function formatRupiah($number,$decimals = 0) function formatRupiah($number, $decimals = 0)
{ {
$number = (float) $number; $number = (float) $number;
return 'Rp ' . number_format($number, $decimals, ',', '.'); return 'Rp ' . number_format($number, $decimals, ',', '.');
} }
function formatAlamat($alamat) 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 ?? ''); 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 // andy add
function checkActiveDateRangePenawaran($id) function checkActiveDateRangePenawaran($id)
{ {
$penawaran = PenawaranTender::find($id); $penawaran = PenawaranTender::find($id);
$start_date = strtotime($penawaran->start_date); $start_date = strtotime($penawaran->start_date);
@@ -69,10 +69,10 @@ function checkActiveDateRangePenawaran($id)
} }
return $allow; return $allow;
} }
function checkKelengkapanDetailKJPP($id) function checkKelengkapanDetailKJPP($id)
{ {
$allow = true; $allow = true;
// DB::enableQueryLog(); // DB::enableQueryLog();
// detail_penawaran apakah isian biaya_penawaran, attachment, dokumen_persetujuan sudah lengkap? // detail_penawaran apakah isian biaya_penawaran, attachment, dokumen_persetujuan sudah lengkap?
@@ -104,11 +104,11 @@ function checkKelengkapanDetailKJPP($id)
} }
return $allow; return $allow;
} }
// convert // convert
function convertSlug($slug) function convertSlug($slug)
{ {
$words = explode('-', $slug); $words = explode('-', $slug);
foreach ($words as $index => $word) { foreach ($words as $index => $word) {
@@ -116,11 +116,12 @@ function convertSlug($slug)
} }
return implode(' ', $words); return implode(' ', $words);
} }
// generate last penawaran.code // generate last penawaran.code
function onLastnumberCodePenawaran(): string function onLastnumberCodePenawaran()
{ : string
{
// ambil code terakhir // ambil code terakhir
$maxCode = PenawaranTender::max('code'); $maxCode = PenawaranTender::max('code');
// chek data penawaran terakhir --> mengurutkan data berdasarkan kolom `created_at` secara DESC // chek data penawaran terakhir --> mengurutkan data berdasarkan kolom `created_at` secara DESC
@@ -146,16 +147,17 @@ function onLastnumberCodePenawaran(): string
} }
return 'NP' . Carbon::now()->format('y') . $noUrutAkhirString; return 'NP' . Carbon::now()->format('y') . $noUrutAkhirString;
} }
function isNumeric($str) function isNumeric($str)
{ {
return ctype_digit($str); return ctype_digit($str);
} }
// generate last penawaran.no_spk // generate last penawaran.no_spk
function onLastnumberCodePenawaranSPK($jenis_laporan_code): string function onLastnumberCodePenawaranSPK($jenis_laporan_code)
{ : string
{
// 20241124_001 ==> spk_no_core // 20241124_001 ==> spk_no_core
// XXX / PJ / JKT / MONTH-ROM / FR|SR / 2024 // XXX / PJ / JKT / MONTH-ROM / FR|SR / 2024
@@ -179,12 +181,13 @@ function onLastnumberCodePenawaranSPK($jenis_laporan_code): string
$month = onRomawi(Carbon::now()->month); $month = onRomawi(Carbon::now()->month);
$lastSPK = $noUrutAkhirString.' / PJ / JKT / '. $month .' / ' .$jenis_laporan_code.' / '.$year_now; $lastSPK = $noUrutAkhirString . ' / PJ / JKT / ' . $month . ' / ' . $jenis_laporan_code . ' / ' . $year_now;
return $lastSPK; return $lastSPK;
} }
function onRomawi(int $bln): string function onRomawi(int $bln)
{ : string
{
switch ($bln) { switch ($bln) {
case 1: case 1:
return "I"; return "I";
@@ -225,51 +228,65 @@ function onRomawi(int $bln): string
} }
} }
function penyebut($nilai) function penyebut($nilai)
{ {
$nilai = abs($nilai); $nilai = abs($nilai);
$huruf = array("", "satu", "dua", "tiga", "empat", "lima", "enam", "tujuh", "delapan", "sembilan", "sepuluh", "sebelas"); $huruf = [
"",
"satu",
"dua",
"tiga",
"empat",
"lima",
"enam",
"tujuh",
"delapan",
"sembilan",
"sepuluh",
"sebelas"
];
$temp = ""; $temp = "";
if ($nilai < 12) { if ($nilai < 12) {
$temp = " ". $huruf[$nilai]; $temp = " " . $huruf[$nilai];
} elseif ($nilai < 20) { } else if ($nilai < 20) {
$temp = penyebut($nilai - 10). " belas"; $temp = penyebut($nilai - 10) . " belas";
} elseif ($nilai < 100) { } else if ($nilai < 100) {
$temp = penyebut($nilai / 10)." puluh". penyebut($nilai % 10); $temp = penyebut($nilai / 10) . " puluh" . penyebut($nilai % 10);
} elseif ($nilai < 200) { } else if ($nilai < 200) {
$temp = " seratus" . penyebut($nilai - 100); $temp = " seratus" . penyebut($nilai - 100);
} elseif ($nilai < 1000) { } else if ($nilai < 1000) {
$temp = penyebut($nilai / 100) . " ratus" . penyebut($nilai % 100); $temp = penyebut($nilai / 100) . " ratus" . penyebut($nilai % 100);
} elseif ($nilai < 2000) { } else if ($nilai < 2000) {
$temp = " seribu" . penyebut($nilai - 1000); $temp = " seribu" . penyebut($nilai - 1000);
} elseif ($nilai < 1000000) { } else if ($nilai < 1000000) {
$temp = penyebut($nilai / 1000) . " ribu" . penyebut($nilai % 1000); $temp = penyebut($nilai / 1000) . " ribu" . penyebut($nilai % 1000);
} elseif ($nilai < 1000000000) { } else if ($nilai < 1000000000) {
$temp = penyebut($nilai / 1000000) . " juta" . penyebut($nilai % 1000000); $temp = penyebut($nilai / 1000000) . " juta" . penyebut($nilai % 1000000);
} elseif ($nilai < 1000000000000) { } else if ($nilai < 1000000000000) {
$temp = penyebut($nilai / 1000000000) . " milyar" . penyebut(fmod($nilai, 1000000000)); $temp = penyebut($nilai / 1000000000) . " milyar" . penyebut(fmod($nilai, 1000000000));
} elseif ($nilai < 1000000000000000) { } else if ($nilai < 1000000000000000) {
$temp = penyebut($nilai / 1000000000000) . " trilyun" . penyebut(fmod($nilai, 1000000000000)); $temp = penyebut($nilai / 1000000000000) . " trilyun" . penyebut(fmod($nilai, 1000000000000));
} }
return $temp; return $temp;
} }
function terbilang($nilai) function terbilang($nilai)
{ {
if ($nilai < 0) { if ($nilai < 0) {
$hasil = "minus ". trim(penyebut($nilai)); $hasil = "minus " . trim(penyebut($nilai));
} else { } else {
$hasil = trim(penyebut($nilai)); $hasil = trim(penyebut($nilai));
} }
return $hasil; return $hasil;
} }
// andy add
// andy add
function hitungHariKerja($tanggalMulai, $tanggalSelesai) function hitungHariKerja($tanggalMulai, $tanggalSelesai)
{ {
$tanggalMulai = Carbon::parse($tanggalMulai)->startOfDay(); $tanggalMulai = Carbon::parse($tanggalMulai)->startOfDay();
$tanggalSelesai = Carbon::parse($tanggalSelesai)->endOfDay(); $tanggalSelesai = Carbon::parse($tanggalSelesai)->endOfDay();
@@ -285,19 +302,19 @@ function hitungHariKerja($tanggalMulai, $tanggalSelesai)
} }
return $hariKerja; return $hariKerja;
} }
function holidays() function holidays()
{ {
return HolidayCalendar::pluck('date')->map( return HolidayCalendar::pluck('date')->map(
function ($item) { function ($item) {
return Carbon::parse($item)->format('Y-m-d'); return Carbon::parse($item)->format('Y-m-d');
}, },
)->toArray(); )->toArray();
} }
function countPermohonanForUser($userId) function countPermohonanForUser($userId)
{ {
$validStatuses = [ $validStatuses = [
'assign', 'assign',
'survey-completed', 'survey-completed',
@@ -334,11 +351,11 @@ function countPermohonanForUser($userId)
}); });
return $result->count(); return $result->count();
} }
function getMaxFileSize($jenis) function getMaxFileSize($jenis)
{ {
$jenisDokumen = JenisDokumen::where('name', $jenis)->first(); $jenisDokumen = JenisDokumen::where('name', $jenis)->first();
if (!$jenisDokumen) { if (!$jenisDokumen) {
return 2048; return 2048;
@@ -347,15 +364,15 @@ function getMaxFileSize($jenis)
$maxSizeInKB = (int) $jenisDokumen->max_size * 1024; $maxSizeInKB = (int) $jenisDokumen->max_size * 1024;
return $maxSizeInKB; return $maxSizeInKB;
} }
function getUser($userId) function getUser($userId)
{ {
return User::find($userId); return User::find($userId);
} }
function generateLpjUniqueCode($randomLength = 6) function generateLpjUniqueCode($randomLength = 6)
{ {
$year = date('y'); $year = date('y');
$month = str_pad(date('m'), 2, '0', STR_PAD_LEFT); $month = str_pad(date('m'), 2, '0', STR_PAD_LEFT);
@@ -366,20 +383,20 @@ function generateLpjUniqueCode($randomLength = 6)
// Concatenate components to create the custom code // Concatenate components to create the custom code
return $year . $month . $day . $randomNumber; return $year . $month . $day . $randomNumber;
} }
function checkRegionUserName($userId) function checkRegionUserName($userId)
{ {
$region = TeamsUsers::where('user_id', $userId)->first(); $region = TeamsUsers::where('user_id', $userId)->first();
if ($region) { if ($region) {
return $region->team->regions->name; return $region->team->regions->name;
} else { } else {
return null; return null;
} }
} }
function getNomorLaporan($permohonanId, $documentId, $type = 'nomor_laporan') function getNomorLaporan($permohonanId, $documentId, $type = 'nomor_laporan')
{ {
$laporan = Laporan::where([ $laporan = Laporan::where([
'permohonan_id' => $permohonanId, 'permohonan_id' => $permohonanId,
@@ -391,10 +408,10 @@ function getNomorLaporan($permohonanId, $documentId, $type = 'nomor_laporan')
} }
return $type == 'nomor_laporan' ? $laporan->nomor_laporan : $laporan->created_at; return $type == 'nomor_laporan' ? $laporan->nomor_laporan : $laporan->created_at;
} }
function getCustomField($param) function getCustomField($param)
{ {
if (is_numeric($param)) { if (is_numeric($param)) {
$field = CustomField::find($param); $field = CustomField::find($param);
} else { } else {
@@ -405,9 +422,10 @@ function getCustomField($param)
} else { } else {
return null; return null;
} }
} }
function getWilayahName($code, $type)
{ function getWilayahName($code, $type)
{
try { try {
$wilayah = null; $wilayah = null;
@@ -435,14 +453,14 @@ function getWilayahName($code, $type)
default: default:
return null; return null;
} }
} catch (\Exception $e) { } catch (Exception $e) {
return null; return null;
} }
} }
function formatLabel($key) function formatLabel($key)
{ {
static $labelCache = []; static $labelCache = [];
if (isset($labelCache[$key])) { if (isset($labelCache[$key])) {
@@ -453,10 +471,10 @@ function formatLabel($key)
$labelCache[$key] = $customLabel->label ?? ucwords(str_replace('_', ' ', $key)); $labelCache[$key] = $customLabel->label ?? ucwords(str_replace('_', ' ', $key));
return $labelCache[$key]; return $labelCache[$key];
} }
function calculateSLA($permohonan, $type) function calculateSLA($permohonan, $type)
{ {
if (!$type) { if (!$type) {
return null; return null;
} }
@@ -479,19 +497,20 @@ function calculateSLA($permohonan, $type)
} }
return $slaMap[$type] ?? null; return $slaMap[$type] ?? null;
} }
/** /**
* Menghitung total nilai berdasarkan key dan jenis legalitas. * Menghitung total nilai berdasarkan key dan jenis legalitas.
* *
* @param array $detailsArray * @param array $detailsArray
* @param string $key * @param string $key
* @param int $jenisLegalitas * @param int $jenisLegalitas
*
* @return int * @return int
*/ */
function calculateTotalLuas($detailsArray, $key, $jenisLegalitas, $defaultJenisLegalitas, $fallbackJenisLegalitas) function calculateTotalLuas($detailsArray, $key, $jenisLegalitas, $defaultJenisLegalitas, $fallbackJenisLegalitas)
{ {
$total = 0; $total = 0;
if ($detailsArray) { if ($detailsArray) {
@@ -545,30 +564,33 @@ function calculateTotalLuas($detailsArray, $key, $jenisLegalitas, $defaultJenisL
} }
return $total > 0 ? $total : 0; return $total > 0 ? $total : 0;
} }
function ubahNomorHp($nomorHp) { function ubahNomorHp($nomorHp)
{
$nomorHp = preg_replace('/\D/', '', $nomorHp); $nomorHp = preg_replace('/\D/', '', $nomorHp);
if (strpos($nomorHp, '62') === 0) { if (strpos($nomorHp, '62') === 0) {
$nomorBaru = substr($nomorHp, 0, 5) . "xxxxx"; $nomorBaru = substr($nomorHp, 0, 5) . "xxxxx";
return '+' . $nomorBaru; return '+' . $nomorBaru;
} elseif (strpos($nomorHp, '0') === 0) { } else if (strpos($nomorHp, '0') === 0) {
$nomorBaru = substr($nomorHp, 0, 5) . "xxxxxx"; $nomorBaru = substr($nomorHp, 0, 5) . "xxxxxx";
return $nomorBaru; return $nomorBaru;
} else { } else {
return "Nomor HP tidak valid"; return "Nomor HP tidak valid";
} }
} }
function formatNotifikasi($data){ function formatNotifikasi($notifikasi)
$data = json_decode(json_encode($data->data)); {
$data = json_decode(json_encode($notifikasi->data));
$message = $data->message;
$data = $data->data; $data = $data->data;
$notifikasi = [ $notifikasi = [
'title'=> 'Permohonan : '.$data->nomor_registrasi, 'title' => 'Permohonan : ' . $data->nomor_registrasi,
'message'=> 'Status : '.str_replace(['-','_'],' ',ucwords($data->status)) 'message' => $message,
]; ];
return $notifikasi; return $notifikasi;
} }

View File

@@ -19,12 +19,7 @@
*/ */
public function index() public function index()
{ {
$permohonan = Permohonan::with([ $permohonan = Permohonan::where(['status' => 'done'])->get();
'documents.jenisJaminan',
'penilaian._user_penilai',
'penilai',
'documents.detail.jenisLegalitasJaminan'
])->where(['status' => 'done'])->get();
foreach ($permohonan as $_permohonan) { foreach ($permohonan as $_permohonan) {
$npw = 0; $npw = 0;
if (isset($_permohonan->penilai->lpj)) { if (isset($_permohonan->penilai->lpj)) {

View File

@@ -0,0 +1,155 @@
<?php
namespace Modules\Lpj\Http\Controllers;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Modules\Lpj\Exports\LaporanPenilaianJaminanExport;
use Modules\Lpj\Models\Permohonan;
use Maatwebsite\Excel\Facades\Excel;
class LaporanPenilaianJaminanController extends Controller
{
public $user;
/**
* Display a listing of the resource.
*/
public function index()
{
return view('lpj::laporan_penilaian_jaminan.index');
}
public function dataForDatatables(Request $request)
{
if (is_null($this->user) || !$this->user->can('laporan-admin-kredit.view')) {
//abort(403, 'Sorry! You are not allowed to view laporan admin kredit.');
}
// Retrieve data from the database
$query = Permohonan::query();
$query = $query->where('status', 'done');
// Apply search filter if provided
if ($request->has('search') && !empty($request->get('search'))) {
$search = json_decode($request->get('search'));
if (isset($search->start_date) || isset($search->end_date)) {
$query->whereBetween('tanggal_permohonan', [
$search->start_date ?? '1900-01-01',
$search->end_date ?? now()->toDateString()
]);
}
// Filter by branch if provided
if (isset($search->branch_id) && !empty($search->branch_id)) {
$query->where('branch_id', $search->branch_id);
}
if (isset($search->search)) {
$query->where(function ($q) use ($search) {
$q->where('nomor_registrasi', 'LIKE', '%' . $search->search . '%');
$q->orWhere('tanggal_permohonan', 'LIKE', '%' . $search->search . '%');
$q->orWhereRelation('user', 'name', 'LIKE', '%' . $search->search . '%');
$q->orWhereRelation('tujuanPenilaian', 'name', 'LIKE', '%' . $search->search . '%');
$q->orWhereRelation('branch', 'name', 'LIKE', '%' . $search->search . '%');
$q->orWhereRelation('jenisFasilitasKredit', 'name', 'LIKE', '%' . $search->search . '%');
$q->orWhereRelation('jenisPenilaian', 'name', 'LIKE', '%' . $search->search . '%');
$q->orWhere('status', 'LIKE', '%' . $search->search . '%');
});
}
}
// Apply sorting if provided
if ($request->has('sortOrder') && !empty($request->get('sortOrder'))) {
$order = $request->get('sortOrder');
$column = $request->get('sortField');
$query->orderBy($column, $order);
}
// Get the total count of records
$totalRecords = $query->count();
// Apply pagination if provided
if ($request->has('page') && $request->has('size')) {
$page = $request->get('page');
$size = $request->get('size');
$offset = ($page - 1) * $size; // Calculate the offset
$query->skip($offset)->take($size);
}
// Get the filtered count of records
$filteredRecords = $query->count();
// Get the data for the current page
$data = $query->with(['debiture.branch'])->get();
$data = $data->map(function ($permohonan) {
$luas_tanah = 0;
$luas_bangunan = 0;
$nilai_tanah = 0;
$nilai_bangunan = 0;
$npw = 0;
$nilai_liquidasi = 0;
if (isset($permohonan->penilai->lpj)) {
$lpj = json_decode($permohonan->penilai->lpj, true);
$npw = str_replace('.', '', $lpj['total_nilai_pasar_wajar'] ?? 0);
$luas_tanah = $lpj['luas_tanah'] ?? 0;
$luas_bangunan = $lpj['luas_bangunan'] ?? 0;
// Calculate nilai_tanah dynamically by looking for all keys that start with 'nilai_tanah_'
$nilai_tanah = str_replace('.', '', $lpj['nilai_tanah_2'] ?? 0);
$nilai_bangunan = str_replace('.', '', $lpj['nilai_bangunan_2'] ?? 0);
$nilai_liquidasi = str_replace('.', '', $lpj['likuidasi_nilai_2'] ?? 0);
}
return [
'id' => $permohonan->id,
'nomor_registrasi' => $permohonan->nomor_registrasi,
'tanggal_permohonan' => $permohonan->tanggal_permohonan,
'branch' => $permohonan->debiture->branch->name,
'name' => $permohonan->debiture->name,
'pemohon' => $permohonan->creator->name,
'tujuan_penilaian' => $permohonan->tujuanPenilaian->name,
'jenis_agunan' => $permohonan->documents->pluck('jenisJaminan.name')->unique()->implode(', '),
'alamat_agunan' => $permohonan->documents->map(function ($document) {
return formatAlamat($document);
})->unique()->implode(', '),
'luas_tanah' => $luas_tanah . ' m²',
'nilai_tanah' => formatRupiah($nilai_tanah,2),
'luas_bangunan' => $luas_bangunan . ' m²',
'nilai_bangunan' => formatRupiah($nilai_bangunan,2),
'tanggal_laporan' => '',
'tanggal_review' => '',
'nilai_pasar_wajar' => formatRupiah($npw,2),
'nilai_likuidasi' => formatRupiah($nilai_liquidasi,2),
'nama_penilai' => $permohonan->penilaian->_user_penilai->userPenilaiTeam->name,
];
});
// Calculate the page count
$pageCount = ceil($totalRecords / $request->get('size'));
// Calculate the current page number
$currentPage = $request->get('page', 1);
// Return the response data as a JSON object
return response()->json([
'draw' => $request->get('draw'),
'recordsTotal' => $totalRecords,
'recordsFiltered' => $filteredRecords,
'pageCount' => $pageCount,
'page' => $currentPage,
'totalCount' => $totalRecords,
'data' => $data,
]);
}
public function export(Request $request)
{
return Excel::download(new LaporanPenilaianJaminanExport($request), 'laporan_penilaian_jaminan.xlsx');
}
}

View File

@@ -65,10 +65,6 @@ class PermohonanController extends Controller
// Save to database // Save to database
$permohonan = Permohonan::create($validate); $permohonan = Permohonan::create($validate);
$user_ = User::find($permohonan->created_by);
$user_->notify(new PermohonanNotif($permohonan));
// Create history // Create history
$this->historyService->createHistory( $this->historyService->createHistory(
$permohonan, $permohonan,

View File

@@ -1,36 +1,42 @@
<?php <?php
namespace Modules\Lpj\Notifications; namespace Modules\Lpj\Notifications;
use Illuminate\Bus\Queueable; use Illuminate\Bus\Queueable;
use Illuminate\Notifications\Notification; use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Notifications\Messages\MailMessage; use Illuminate\Notifications\Notification;
class PermohonanNotif extends Notification class PermohonanNotif extends Notification
{ {
use Queueable; use Queueable;
protected $permohonan; protected $permohonan;
protected $message;
/** /**
* Create a new notification instance. * Create a new notification instance.
*/ */
public function __construct($permohonan) public function __construct($permohonan, $message)
{ {
$this->permohonan = $permohonan; $this->permohonan = $permohonan;
$this->message = $message;
} }
/** /**
* Get the notification's delivery channels. * Get the notification's delivery channels.
*/ */
public function via($notifiable): array public function via($notifiable)
: array
{ {
return ['mail','database']; return ['mail', 'database'];
} }
/** /**
* Get the mail representation of the notification. * Get the mail representation of the notification.
*/ */
public function toMail($notifiable): MailMessage public function toMail($notifiable)
: MailMessage
{ {
return (new MailMessage) return (new MailMessage)
->line('The introduction to the notification.') ->line('The introduction to the notification.')
@@ -41,10 +47,12 @@ class PermohonanNotif extends Notification
/** /**
* Get the array representation of the notification. * Get the array representation of the notification.
*/ */
public function toArray($notifiable): array public function toArray($notifiable)
: array
{ {
return [ return [
'data' => $this->permohonan, 'data' => $this->permohonan,
'message' => $this->message,
]; ];
} }
} }

View File

@@ -4,6 +4,8 @@ namespace Modules\Lpj\Services;
use Modules\Lpj\Models\Permohonan; use Modules\Lpj\Models\Permohonan;
use Modules\Lpj\Models\PermohonanHistory; use Modules\Lpj\Models\PermohonanHistory;
use Modules\Lpj\Notifications\PermohonanNotif;
use Modules\Usermanagement\Models\User;
class PermohonanHistoryService class PermohonanHistoryService
{ {
@@ -21,6 +23,8 @@ class PermohonanHistoryService
'user_id' => auth()->id(), 'user_id' => auth()->id(),
]); ]);
$this->createNotification($permohonan, $status, $beforeRequest, $afterRequest);
} catch (\Exception $e) { } catch (\Exception $e) {
// Log the error // Log the error
\Log::error('Error creating PermohonanHistory: ' . $e->getMessage()); \Log::error('Error creating PermohonanHistory: ' . $e->getMessage());
@@ -34,4 +38,25 @@ class PermohonanHistoryService
throw new \Exception('Failed to create PermohonanHistory: ' . $e->getMessage()); throw new \Exception('Failed to create PermohonanHistory: ' . $e->getMessage());
} }
} }
private function createNotification(Permohonan $permohonan, string $status, array $beforeRequest, array $afterRequest)
{
$beforeStatus = '';
if(!empty($beforeRequest)){
$beforeStatus = $beforeRequest['status'] ?? '';
}
if($beforeStatus !== $status){
if($status === 'order'){
$users = User::where(['branch_id' => $permohonan->branch_id])->whereHas('roles',function($q){
$q->where('name', 'pemohon-eo');
})->get();
foreach ($users as $user) {
$message = "telah diorder oleh {$permohonan->creator->name}, Mohon Lakukan konfirmasi";
$user->notify(new PermohonanNotif($permohonan,$message));
}
}
}
}
} }

View File

@@ -0,0 +1,311 @@
@extends('layouts.main')
@section('breadcrumbs')
{{ Breadcrumbs::render('laporan-penilaian-jaminan') }}
@endsection
@section('content')
<div class="w-full grid gap-5 lg:gap-7.5 mx-auto">
<div class="card border border-agi-100 card-grid min-w-full" data-datatable="false" data-datatable-page-size="10" data-datatable-state-save="false" id="laporan-penilaian-jaminan-table" data-api-url="{{ route('laporan-penilaian-jaminan.data') }}">
<div class="card-header bg-agi-50 py-5 flex-wrap">
<h3 class="card-title">
Laporan Penilaian Jaminan
</h3>
<div class="flex flex-wrap gap-2 lg:gap-5">
<div class="flex">
<label class="input input-sm">
<input placeholder="Tanggal Awal" id="start_date" type="date">
</label>
</div>
<div class="flex">
<label class="input input-sm">
<input placeholder="Tanggal Akhir" id="end_date" type="date">
</label>
</div>
<div class="flex">
<select class="select select-sm" id="branch_filter">
<option value="">Semua Cabang</option>
@foreach(\Modules\Basicdata\Models\Branch::where('status', 1)->get() as $branch)
<option value="{{ $branch->id }}">{{ $branch->name }}</option>
@endforeach
</select>
</div>
<div class="flex">
<button class="btn btn-sm btn-primary" id="filter_tanggal">Filter</button>
</div>
<div class="flex">
<label class="input input-sm"> <i class="ki-filled ki-magnifier"> </i>
<input placeholder="Search Laporan Penilaian Jaminan" id="search" type="text" value="">
</label>
</div>
<div class="flex flex-wrap gap-2.5">
<div class="h-[24px] border border-r-gray-200"></div>
<a class="btn btn-sm btn-light" href="{{ route('laporan-penilaian-jaminan.export') }}" id="export-btn"> Export to Excel </a>
</div>
</div>
</div>
<div class="card-body">
<div class="scrollable-x-auto">
<table class="table table-auto table-border align-middle text-gray-700 font-medium text-sm" data-datatable-table="true">
<thead>
<tr>
<th class="w-14">
<input class="checkbox checkbox-sm" data-datatable-check="true" type="checkbox"/>
</th>
<th class="min-w-[150px]" data-datatable-column="nomor_registrasi">
<span class="sort"> <span class="sort-label"> Nomor Registrasi </span>
<span class="sort-icon"> </span> </span>
</th>
<th class="min-w-[150px]" data-datatable-column="tanggal_permohonan">
<span class="sort"> <span class="sort-label"> Tanggal Permohonan </span>
<span class="sort-icon"> </span> </span>
</th>
<th class="min-w-[150px]" data-datatable-column="branch">
<span class="sort"> <span class="sort-label"> Cabang </span>
<span class="sort-icon"> </span> </span>
</th>
<th class="min-w-[150px]" data-datatable-column="pemohon">
<span class="sort"> <span class="sort-label"> Pemohon </span>
<span class="sort-icon"> </span> </span>
</th>
<th class="min-w-[150px]" data-datatable-column="name">
<span class="sort"> <span class="sort-label"> Nama Debitur </span>
<span class="sort-icon"> </span> </span>
</th>
<th class="min-w-[150px]" data-datatable-column="tujuan_penilaian">
<span class="sort"> <span class="sort-label"> Tujuan Penilaian </span>
<span class="sort-icon"> </span> </span>
</th>
<th class="min-w-[150px]" data-datatable-column="jenis_agunan">
<span class="sort"> <span class="sort-label"> Jenis Agunan </span>
<span class="sort-icon"> </span> </span>
</th>
<th class="min-w-[150px]" data-datatable-column="alamat_agunan">
<span class="sort"> <span class="sort-label"> Alamat Agunan </span>
<span class="sort-icon"> </span> </span>
</th>
<th class="min-w-[150px]" data-datatable-column="luas_tanah">
<span class="sort"> <span class="sort-label"> Luas Tanah </span>
<span class="sort-icon"> </span> </span>
</th>
<th class="min-w-[150px]" data-datatable-column="nilai_tanah">
<span class="sort"> <span class="sort-label"> Nilai Tanah </span>
<span class="sort-icon"> </span> </span>
</th>
<th class="min-w-[150px]" data-datatable-column="luas_bangunan">
<span class="sort"> <span class="sort-label"> Luas Bangunan </span>
<span class="sort-icon"> </span> </span>
</th>
<th class="min-w-[150px]" data-datatable-column="nilai_bangunan">
<span class="sort"> <span class="sort-label"> Nilai Bangunan </span>
<span class="sort-icon"> </span> </span>
</th>
<th class="min-w-[150px]" data-datatable-column="tanggal_laporan">
<span class="sort"> <span class="sort-label"> Tanggal Laporan </span>
<span class="sort-icon"> </span> </span>
</th>
<th class="min-w-[150px]" data-datatable-column="tanggal_review">
<span class="sort"> <span class="sort-label"> Tanggal Review </span>
<span class="sort-icon"> </span> </span>
</th>
<th class="min-w-[150px]" data-datatable-column="nilai_pasar_wajar">
<span class="sort"> <span class="sort-label"> Nilai Pasar Wajar </span>
<span class="sort-icon"> </span> </span>
</th>
<th class="min-w-[150px]" data-datatable-column="nilai_likuidasi">
<span class="sort"> <span class="sort-label"> Nilai Likuidasi </span>
<span class="sort-icon"> </span> </span>
</th>
<th class="min-w-[150px]" data-datatable-column="nama_penilai">
<span class="sort"> <span class="sort-label"> Nama Penilai </span>
<span class="sort-icon"> </span> </span>
</th>
</tr>
</thead>
</table>
</div>
<div class="card-footer justify-center md:justify-between flex-col md:flex-row gap-3 text-gray-600 text-2sm font-medium">
<div class="flex items-center gap-2">
Show
<select class="select select-sm w-16" data-datatable-size="true" name="perpage"> </select> per
page
</div>
<div class="flex items-center gap-4">
<span data-datatable-info="true"> </span>
<div class="pagination" data-datatable-pagination="true">
</div>
</div>
</div>
</div>
</div>
</div>
@endsection
@push('scripts')
<script type="module">
const element = document.querySelector('#laporan-penilaian-jaminan-table');
const searchInput = document.getElementById('search');
const startDateInput = document.getElementById('start_date');
const endDateInput = document.getElementById('end_date');
const branchFilter = document.getElementById('branch_filter');
const filterTanggalButton = document.getElementById('filter_tanggal');
const exportBtn = document.getElementById('export-btn');
const apiUrl = element.getAttribute('data-api-url');
const dataTableOptions = {
apiEndpoint: apiUrl,
pageSize: 5,
columns: {
select: {
render: (item, data, context) => {
const checkbox = document.createElement('input');
checkbox.className = 'checkbox checkbox-sm';
checkbox.type = 'checkbox';
checkbox.value = data.id.toString();
checkbox.setAttribute('data-datatable-row-check', 'true');
return checkbox.outerHTML.trim();
},
},
nomor_registrasi: {
title: 'Nomor Registrasi',
},
tanggal_permohonan: {
title: 'Tanggal Permohonan',
render: (item, data) => {
return data.tanggal_permohonan ? window.formatTanggalIndonesia(data.tanggal_permohonan) : '-';
},
},
branch: {
title: 'Cabang',
},
name: {
title: 'Nama Debitur',
},
pemohon: {
title: 'Pemohon',
},
tujuan_penilaian: {
title: 'Tujuan Penilaian',
},
jenis_agunan: {
title: 'Jenis Agunan',
},
alamat_agunan: {
title: 'Alamat Agunan',
},
luas_tanah: {
title: 'Luas Tanah',
},
nilai_tanah: {
title: 'Nilai Tanah',
},
luas_bangunan: {
title: 'Luas Bangunan',
},
nilai_bangunan: {
title: 'Nilai Bangunan',
},
tanggal_laporan: {
title: 'Tanggal Laporan',
render: (item, data) => {
return data.tanggal_laporan ? window.formatTanggalIndonesia(data.tanggal_laporan) : '-';
},
},
tanggal_review: {
title: 'Tanggal Review',
render: (item, data) => {
return data.tanggal_review ? window.formatTanggalIndonesia(data.tanggal_review) : '-';
},
},
nilai_pasar_wajar: {
title: 'Nilai Pasar Wajar',
render: (item, data) => {
return data.nilai_pasar_wajar;
},
},
nilai_likuidasi: {
title: 'Nilai Likuidasi',
},
nama_penilai: {
title: 'Nama Penilai',
}
}
};
let dataTable = new KTDataTable(element, dataTableOptions);
// Function to apply all filters
function applyFilters() {
let filters = {};
const startDate = startDateInput.value;
const endDate = endDateInput.value;
const branch = branchFilter.value;
if (searchInput.value) {
filters.search = searchInput.value;
}
if (startDate) {
filters.start_date = startDate;
}
if (endDate) {
filters.end_date = endDate;
}
if (branch) {
filters.branch_id = branch;
}
dataTable.search(filters);
}
// Update export URL with filters
function updateExportUrl() {
let url = new URL(exportBtn.href);
if (startDateInput.value) {
url.searchParams.set('start_date', startDateInput.value);
} else {
url.searchParams.delete('start_date');
}
if (endDateInput.value) {
url.searchParams.set('end_date', endDateInput.value);
} else {
url.searchParams.delete('end_date');
}
if (branchFilter.value) {
url.searchParams.set('branch_id', branchFilter.value);
} else {
url.searchParams.delete('branch_id');
}
if (searchInput.value) {
url.searchParams.set('search', searchInput.value);
} else {
url.searchParams.delete('search');
}
exportBtn.href = url.toString();
}
// Add event listeners for all inputs
searchInput.addEventListener('input', () => {
applyFilters();
updateExportUrl();
});
filterTanggalButton.addEventListener('click', () => {
applyFilters();
updateExportUrl();
});
// Initial update of export URL
updateExportUrl();
</script>
@endpush

View File

@@ -1,7 +1,7 @@
@extends('layouts.main') @extends('layouts.main')
@section('breadcrumbs') @section('breadcrumbs')
{{-- {{ Breadcrumbs::render('laporan-permohonan') }}--}} {{ Breadcrumbs::render('laporan-permohonan') }}
@endsection @endsection
@section('content') @section('content')

View File

@@ -572,7 +572,7 @@ Breadcrumbs::for('otorisator.show', function (BreadcrumbTrail $trail, $id, $type
Breadcrumbs::for('laporan', function (BreadcrumbTrail $trail) { Breadcrumbs::for('laporan', function (BreadcrumbTrail $trail) {
$trail->push('Laporan', route('laporan.sederhana.index')); $trail->push('Laporan','');
}); });
Breadcrumbs::for('laporan.sederhana.index', function (BreadcrumbTrail $trail) { Breadcrumbs::for('laporan.sederhana.index', function (BreadcrumbTrail $trail) {
@@ -728,9 +728,21 @@ Breadcrumbs::for('laporan-admin-kredit', function ($trail) {
Breadcrumbs::for('bank-data', function ($trail) { Breadcrumbs::for('bank-data', function ($trail) {
$trail->push('Bank Data', route('bank-data.index')); $trail->push('Bank Data', route('bank-data.index'));
}); });
Breadcrumbs::for('laporan-penilai-jaminan', function ($trail) { Breadcrumbs::for('laporan-penilai-jaminan', function ($trail) {
$trail->parent('laporan');
$trail->push('Laporan Penilai Jaminan', route('laporan-penilai-jaminan.index')); $trail->push('Laporan Penilai Jaminan', route('laporan-penilai-jaminan.index'));
}); });
Breadcrumbs::for('laporan-permohonan', function ($trail) {
$trail->parent('laporan');
$trail->push('Laporan Permohnan', route('laporan-permohonan.index'));
});
Breadcrumbs::for('laporan-penilaian-jaminan', function ($trail) {
$trail->parent('laporan');
$trail->push('Laporan Penilaian Jaminan', route('laporan-penilaian-jaminan.index'));
});
// add andy // add andy
require __DIR__ . '/breadcrumbs_registrasi.php'; require __DIR__ . '/breadcrumbs_registrasi.php';

View File

@@ -23,6 +23,7 @@ use Modules\Lpj\Http\Controllers\LaporanAdminKreditController;
use Modules\Lpj\Http\Controllers\LaporanController; use Modules\Lpj\Http\Controllers\LaporanController;
use Modules\Lpj\Http\Controllers\LaporanExternalController; use Modules\Lpj\Http\Controllers\LaporanExternalController;
use Modules\Lpj\Http\Controllers\LaporanPembatalanController; use Modules\Lpj\Http\Controllers\LaporanPembatalanController;
use Modules\Lpj\Http\Controllers\LaporanPenilaianJaminanController;
use Modules\Lpj\Http\Controllers\LaporanPermohonanController; use Modules\Lpj\Http\Controllers\LaporanPermohonanController;
use Modules\Lpj\Http\Controllers\NilaiPlafondController; use Modules\Lpj\Http\Controllers\NilaiPlafondController;
use Modules\Lpj\Http\Controllers\NocController; use Modules\Lpj\Http\Controllers\NocController;
@@ -700,6 +701,12 @@ Route::middleware(['auth'])->group(function () {
Route::get('/export', [LaporanPembatalanController::class, 'export'])->name('export'); Route::get('/export', [LaporanPembatalanController::class, 'export'])->name('export');
}); });
Route::prefix('laporan-penilaian-jaminan')->name('laporan-penilaian-jaminan.')->group(function() {
Route::get('datatables', [LaporanPenilaianJaminanController::class, 'dataForDatatables'])->name('data');
Route::get('export', [LaporanPenilaianJaminanController::class, 'export'])->name('export');
Route::get('/', [LaporanPenilaianJaminanController::class, 'index'])->name('index');
});
}); });
require __DIR__ . '/registrasi.php'; require __DIR__ . '/registrasi.php';