Merge branch 'feature/senior-officer' into lpj-db-migratio

This commit is contained in:
majid
2025-07-21 10:17:51 +07:00
9 changed files with 393 additions and 392 deletions

View File

@@ -15,6 +15,8 @@
use Modules\Lpj\Models\Penilaian; use Modules\Lpj\Models\Penilaian;
use Modules\Lpj\Models\TeamsUsers; use Modules\Lpj\Models\TeamsUsers;
use Modules\Usermanagement\Models\User; use Modules\Usermanagement\Models\User;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Facades\Storage;
function formatTanggalIndonesia($date, $time = false) function formatTanggalIndonesia($date, $time = false)
{ {
@@ -557,3 +559,37 @@ function parsePembandingMigration($keterangan) {
return implode("\n", $cleaned); 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;
}

View File

@@ -20,7 +20,7 @@
*/ */
public function index() public function index()
{ {
return redirect()->route('noc.pembayaran'); return redirect()->route('noc.pembayaran.index');
} }
public function pembayaran() public function pembayaran()
@@ -80,7 +80,7 @@
} }
$noc->save(); $noc->save();
// Update the status of the related permohonan to 'spk' /* Update the status of the related permohonan to 'spk'
$permohonan = Permohonan::find(request()->get('permohonan_id')); $permohonan = Permohonan::find(request()->get('permohonan_id'));
if ($permohonan) { if ($permohonan) {
$permohonan->status_bayar = request()->get('status_pembayar'); $permohonan->status_bayar = request()->get('status_pembayar');
@@ -99,7 +99,7 @@
]); ]);
} }
// andy add, update status penawaran.status='spk' // andy add, update status penawaran.status='spk'
} }*/
return redirect() return redirect()
->route('noc.index')->with('success', 'NOC berhasil disimpan.'); ->route('noc.index')->with('success', 'NOC berhasil disimpan.');
@@ -175,9 +175,7 @@
/** /**
* Display the specified resource. * Display the specified resource.
*/ */
public function show(Request $request) { public function show(Noc $noc) {
$noc = Noc::find($request->get('id'));
return view('lpj::noc.memo', compact('noc')); return view('lpj::noc.memo', compact('noc'));
} }

View File

@@ -1,8 +1,10 @@
<?php <?php
namespace Modules\Lpj\Services; namespace Modules\Lpj\Services;
use Modules\Lpj\Models\Permohonan; use Modules\Lpj\Models\Permohonan;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Modules\Usermanagement\Models\User;
class LaporanUserService class LaporanUserService
{ {
@@ -25,36 +27,15 @@ class LaporanUserService
{ {
// Retrieve data from the database // Retrieve data from the database
$query = Permohonan::query(); $query = User::query();
$query = $query->where('status', 'done');
// Apply search filter if provided // Apply search filter if provided
if ($request->has('search') && !empty($request->get('search'))) { if ($request->has('search') && !empty($request->get('search'))) {
$search = json_decode($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->user_id) && !empty($search->user_id)) {
$query->where('user_id', $search->user_id);
}
if (isset($search->search)) { if (isset($search->search)) {
$query->where(function ($q) use ($search) { $query->where(function ($q) use ($search) {
$q->where('nomor_registrasi', 'LIKE', '%' . $search->search . '%'); $q->whereRaw('LOWER(name) LIKE ?', ['%' . strtolower($search) . '%']);
$q->orWhere('tanggal_permohonan', 'LIKE', '%' . $search->search . '%'); $q->where('nik', '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 . '%');
}); });
} }
} }
@@ -82,28 +63,16 @@ class LaporanUserService
$filteredRecords = $query->count(); $filteredRecords = $query->count();
// Get the data for the current page // Get the data for the current page
$data = $query->with(['debiture.branch'])->get(); $data = $query->with(['branch', 'roles'])->get();
$data = $data->map(function ($permohonan) { $data = $data->map(function ($user) {
$npw = 0;
if (isset($permohonan->penilai->lpj)) {
$lpj = json_decode($permohonan->penilai->lpj, true);
$npw = str_replace('.', '', $lpj['total_nilai_pasar_wajar'] ?? 0);
}
return [ return [
'id' => $permohonan->id, 'id' => $user->id,
'nomor_registrasi' => $permohonan->nomor_registrasi, 'nik' => $user->nik,
'branch' => $permohonan->debiture->branch?->name, 'name' => $user->name,
'name' => $permohonan->debiture?->name, 'level' => $user->roles->pluck('name')->implode(', '),
'pemohon' => $permohonan->creator?->name, 'approval_limit' => 0,
'tanggal_permohonan' => $permohonan->tanggal_permohonan,
'nama_penilai' => $permohonan->penilaian?->_user_penilai?->userPenilaiTeam?->name,
'tanggal_laporan' => $permohonan->approval_dd_at ?? $permohonan->approval_eo_at ?? '',
'nilai_pasar_wajar' => formatRupiah($npw, 2)
]; ];
}); });

View File

@@ -268,7 +268,7 @@
return ` return `
<div class="flex flex-nowrap justify-center"> <div class="flex flex-nowrap justify-center">
<a class="btn btn-sm btn-icon btn-clear btn-warning" href="activity/${data.id}/show" title="Lihat Detail"> <a class="btn btn-sm btn-icon ${status === 'freeze' ? 'btn-light' : 'btn-warning btn-clear'}" href="activity/${data.id}/show" title="Lihat Detail">
<i class="ki-outline ki-eye"></i> <i class="ki-outline ki-eye"></i>
</a> </a>
${ ${
@@ -284,14 +284,44 @@
</div> </div>
`; `;
}, },
}, },
} }
}; };
let dataTable = new KTDataTable(element, dataTableOptions); let dataTable = new KTDataTable(element, dataTableOptions);
function highlightFreezeRows() {
const table = document.querySelector('#permohonan-table table[data-datatable-table="true"]');
if (!table) return;
const rows = table.querySelectorAll('tbody tr');
rows.forEach(row => {
const statusCell = row.cells[7];
if (!statusCell) return;
const statusText = statusCell.textContent.trim().toLowerCase();
if (statusText === 'freeze') {
row.classList.add('bg-red-400', 'text-white');
} else {
row.classList.remove('bg-red-400', 'text-white');
}
});
}
// Polling setiap 1 detik untuk sementara
setInterval(() => {
highlightFreezeRows();
}, 500);
searchInput.addEventListener('input', function() { searchInput.addEventListener('input', function() {
const searchValue = this.value.trim(); const searchValue = this.value.trim();
dataTable.search(searchValue, true); dataTable.search(searchValue, true);

View File

@@ -6,63 +6,27 @@
@section('content') @section('content')
<div class="w-full grid gap-5 lg:gap-7.5 mx-auto"> <div class="w-full grid gap-5 lg:gap-7.5 mx-auto">
<!-- Filter Card -->
<div class="card border border-agi-100"> <!-- Data Table Card -->
<div class="card-header bg-agi-50 py-5"> <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-user-table" data-api-url="{{ route('laporan-user.datatables') }}">
<h3 class="card-title"> Laporan User Penilai</h3> <div class="card-header bg-agi-50 py-5 flex-wrap">
</div>
<div class="card-body grid gap-4"> <h3 class="card-title">
<!-- Search field at the top, full width --> Laporan User
<div class="flex flex-col w-full"> </h3>
<label class="text-sm font-medium mb-1">Pencarian</label> <div class="flex flex-wrap gap-2 lg:gap-5">
<div class="flex flex-wrap gap-2 lg:gap-5">
<label class="input input-sm"> <label class="input input-sm">
<i class="ki-filled ki-magnifier"></i> <i class="ki-filled ki-magnifier"></i>
<input placeholder="Search Laporan User" id="search" type="text" value=""> <input placeholder="Search Laporan User" id="search" type="text" value="">
</label> </label>
</div> </div>
<!-- Other filter fields in grid layout -->
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
<div class="flex flex-col">
<label class="text-base font-medium mb-1">Tanggal Awal</label>
<label class="input">
<input placeholder="Tanggal Awal" id="start_date" type="date">
</label>
</div>
<div class="flex flex-col">
<label class="text-base font-medium mb-1">Tanggal Akhir</label>
<label class="input">
<input placeholder="Tanggal Akhir" id="end_date" type="date">
</label>
</div>
<div class="flex flex-col">
<label class="text-base font-medium mb-1">User</label>
<select class="select tomselect" id="user_id" name="user_id">
</select>
</div>
</div>
<!-- Buttons row at the bottom -->
<div class="grid grid-cols-1 md:grid-cols-2 gap-4 mt-2">
<button class="btn btn-sm btn-primary" id="filter_tanggal">
<i class="ki-outline ki-filter fs-2 me-1"></i>
Terapkan Filter
</button>
<a class="btn btn-sm btn-light" href="{{ route('laporan-user.export') }}" id="export-btn"> <a class="btn btn-sm btn-light" href="{{ route('laporan-user.export') }}" id="export-btn">
<i class="ki-outline ki-file-down fs-2 me-1"></i> <i class="ki-outline ki-file-down fs-2 me-1"></i>
Export to Excel Export to Excel
</a> </a>
</div> </div>
</div>
</div>
<!-- Data Table Card -->
<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-user-table" data-api-url="{{ route('laporan-user.datatables') }}">
<div class="card-header bg-agi-50 py-5 flex-wrap">
<h3 class="card-title">
Laporan User Pemohon
</h3>
</div> </div>
<div class="card-body"> <div class="card-body">
@@ -73,41 +37,20 @@
<th class="w-14"> <th class="w-14">
<input class="checkbox checkbox-sm" data-datatable-check="true" type="checkbox"/> <input class="checkbox checkbox-sm" data-datatable-check="true" type="checkbox"/>
</th> </th>
<th class="min-w-[150px]" data-datatable-column="nomor_registrasi"> <th class="min-w-[150px]" data-datatable-column="nik">
<span class="sort"> <span class="sort-label"> Nomor Registrasi </span> <span class="sort"> <span class="sort-label"> NIK</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> <span class="sort-icon"> </span> </span>
</th> </th>
<th class="min-w-[150px]" data-datatable-column="name"> <th class="min-w-[150px]" data-datatable-column="name">
<span class="sort"> <span class="sort-label"> Nama Debitur </span> <span class="sort"> <span class="sort-label"> Nama User</span>
<span class="sort-icon"> </span> </span> <span class="sort-icon"> </span> </span>
</th> </th>
<th class="min-w-[150px]" data-datatable-column="pemohon"> <th class="min-w-[150px]" data-datatable-column="level">
<span class="sort"> <span class="sort-label"> Pemohon </span> <span class="sort"> <span class="sort-label"> Level Group </span>
<span class="sort-icon"> </span> </span> <span class="sort-icon"> </span> </span>
</th> </th>
<th class="min-w-[150px]" data-datatable-column="approval_limit">
<span class="sort"> <span class="sort-label"> Approval Limit </span>
<th class="min-w-[150px]" data-datatable-column="jenis_penilaian">
<span class="sort"> <span class="sort-label"> Tgl Terima </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"> Penilai </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"> Tgl Laporan </span>
<span class="sort-icon"> </span> </span>
</th>
<th class="min-w-[150px]" data-datatable-column="catatan">
<span class="sort"> <span class="sort-label"> Nilai Pasar Wajar </span>
<span class="sort-icon"> </span> </span> <span class="sort-icon"> </span> </span>
</th> </th>
</tr> </tr>
@@ -155,40 +98,21 @@
return checkbox.outerHTML.trim(); return checkbox.outerHTML.trim();
}, },
}, },
nomor_registrasi: { nik: {
title: 'Nomor Registrasi', title: 'Nomor Registrasi',
},
branch: {
title: 'Cabang',
}, },
name: { name: {
title: 'Nama Debitur', title: 'Nama',
}, },
pemohon: { level: {
title: 'Pemohon', title: 'level',
}, },
tanggal_permohonan: { approval_limit: {
title: 'Tanggal Permohonan', title: 'Approval Limit',
render: (item, data) => { render: (item, data) => {
return data.tanggal_permohonan ? window.formatTanggalIndonesia(data.tanggal_permohonan) : '-'; return data.tanggal_permohonan ? window.formatTanggalIndonesia(data.tanggal_permohonan) : '-';
}, },
}, },
nama_penilai: {
title: 'Nama Penilai',
},
tanggal_laporan: {
title: 'Tanggal Dokumen Diterima',
render: (item, data) => {
return data.tanggal_laporan ? window.formatTanggalIndonesia(data.tanggal_laporan) : '-';
},
},
nilai_pasar_wajar: {
title: 'Nilai Pasar Wajar',
render: (item, data) => {
return data.nilai_pasar_wajar ?? '-';
},
}
} }
}; };
@@ -209,7 +133,6 @@
if (startDate) { if (startDate) {
filters.start_date = startDate; filters.start_date = startDate;
} }
if (endDate) { if (endDate) {
filters.end_date = endDate; filters.end_date = endDate;
} }
@@ -219,7 +142,6 @@
} }
dataTable.search(filters); dataTable.search(filters);
} }

View File

@@ -6,10 +6,10 @@
@section('content') @section('content')
<div class="w-full grid gap-5 lg:gap-7.5 mx-auto"> <div class="grid gap-5 mx-auto w-full lg:gap-7.5">
<div class="card border border-agi-100 card-grid min-w-full" data-datatable="false" data-datatable-page-size="10" <div class="min-w-full border card border-agi-100 card-grid" data-datatable="false" data-datatable-page-size="10"
data-datatable-state-save="false" id="laporan-table" data-api-url="{{ route('laporan.datatables') }}"> data-datatable-state-save="false" id="laporan-table" data-api-url="{{ route('laporan.datatables') }}">
<div class="card-header bg-agi-50 py-5 flex-wrap"> <div class="flex-wrap py-5 card-header bg-agi-50">
<h3 class="card-title"> <h3 class="card-title">
Laporan Laporan
</h3> </h3>
@@ -28,7 +28,7 @@
<div class="card-body"> <div class="card-body">
<div class="scrollable-x-auto"> <div class="scrollable-x-auto">
<table class="table table-auto table-border align-middle text-gray-700 font-medium text-sm" <table class="table text-sm font-medium text-gray-700 align-middle table-auto table-border"
data-datatable-table="true"> data-datatable-table="true">
<thead> <thead>
<tr> <tr>
@@ -74,13 +74,13 @@
</table> </table>
</div> </div>
<div <div
class="card-footer justify-center md:justify-between flex-col md:flex-row gap-3 text-gray-600 text-2sm font-medium"> class="flex-col gap-3 justify-center font-medium text-gray-600 card-footer md:justify-between md:flex-row text-2sm">
<div class="flex items-center gap-2"> <div class="flex gap-2 items-center">
Show Show
<select class="select select-sm w-16" data-datatable-size="true" name="perpage"> </select> per <select class="w-16 select select-sm" data-datatable-size="true" name="perpage"> </select> per
page page
</div> </div>
<div class="flex items-center gap-4"> <div class="flex gap-4 items-center">
<span data-datatable-info="true"> </span> <span data-datatable-info="true"> </span>
<div class="pagination" data-datatable-pagination="true"> <div class="pagination" data-datatable-pagination="true">
</div> </div>
@@ -186,7 +186,7 @@
tanggal_survei: { tanggal_survei: {
title: 'Tanggal Survei', title: 'Tanggal Survei',
render: (item, data) => { render: (item, data) => {
if(data.penilaian.waktu_penilaian){ if (data.penilaian.waktu_penilaian) {
return `${formatDate(new Date(data.penilaian.waktu_penilaian))}`; return `${formatDate(new Date(data.penilaian.waktu_penilaian))}`;
} }
return `${formatDate(new Date(data.penilaian.created_at))}`; return `${formatDate(new Date(data.penilaian.created_at))}`;
@@ -199,19 +199,19 @@
const tipe_laporan = data.penilai?.type; const tipe_laporan = data.penilai?.type;
const nilai_plafond = data.penilaian.nilaiPlafond?.name; const nilai_plafond = data.penilaian.nilaiPlafond?.name;
let waktu_penilaian = new Date(data.penilaian.created_at); let waktu_penilaian = new Date(data.penilaian.created_at);
if(data.penilaian.waktu_penilaian){ if (data.penilaian.waktu_penilaian) {
waktu_penilaian = new Date(data.penilaian.waktu_penilaian); waktu_penilaian = new Date(data.penilaian.waktu_penilaian);
} }
if(tujuan_penilaian.name==="RAP"){ if (tujuan_penilaian.name === "RAP") {
waktu_penilaian.setDate(waktu_penilaian.getDate() + 3); waktu_penilaian.setDate(waktu_penilaian.getDate() + 3);
} else { } else {
if(tipe_laporan==="sederhana"){ if (tipe_laporan === "sederhana") {
waktu_penilaian.setDate(waktu_penilaian.getDate() + 2); waktu_penilaian.setDate(waktu_penilaian.getDate() + 2);
} else if(tipe_laporan==="standar"){ } else if (tipe_laporan === "standar") {
if(nilai_plafond==="2 M - 5 M"){ if (nilai_plafond === "2 M - 5 M") {
waktu_penilaian.setDate(waktu_penilaian.getDate() + 3); waktu_penilaian.setDate(waktu_penilaian.getDate() + 3);
} else if(nilai_plafond==="< 2M"){ } else if (nilai_plafond === "< 2M") {
waktu_penilaian.setDate(waktu_penilaian.getDate() + 3); waktu_penilaian.setDate(waktu_penilaian.getDate() + 3);
} else { } else {
waktu_penilaian.setDate(waktu_penilaian.getDate() + 5); waktu_penilaian.setDate(waktu_penilaian.getDate() + 5);
@@ -224,7 +224,7 @@
status: { status: {
title: 'Status', title: 'Status',
render: (item, data) => { render: (item, data) => {
return `<span class="badge badge-sm badge-default uppercase flex justify-center">${data.status}</span>`; return `<span class="flex justify-center uppercase badge badge-sm badge-default">${data.status}</span>`;
} }
}, },
actions: { actions: {
@@ -240,31 +240,32 @@
let penyelesaian = ''; let penyelesaian = '';
if(data.noc) { if (data.noc) {
if (!data.noc?.tanggal_penyelesaian && !data.noc?.memo_penyelesaian) { if (!data.noc?.memo_penyelesaian) {
penyelesaian = ` penyelesaian = `
<a href="{{ route('noc.penyelesaian') }}?id=${data.noc.id}&permohonanId=${data.noc.permohonan_id}&persetujuanPenawaranId=${data.noc.persetujuan_penawaran_id}" class="btn btn-sm btn-warning"> <a href="{{ route('noc.index') }}/${data.noc.id}" class="btn btn-sm btn-warning">
Penyelesaian Penyelesaian
</a>`; </a>`;
} }
} }
if(data.penilai.resume) { if (data.penilai.resume) {
resumeButton = ` resumeButton = `
<a href="penilai/print-out-laporan/${data.id}/${dokumenID}/${jenisJaminanID}" class="btn btn-sm btn-success"> <a href="penilai/print-out-laporan/${data.id}/${dokumenID}/${jenisJaminanID}" class="btn btn-sm btn-success">
Resume Resume
</a>`; </a>`;
} }
if(data.nilai_liquidasi==null) { if (data.nilai_liquidasi == null) {
laporanButton = ` laporanButton = `
<a href="laporan/${data.id}" class="btn btn-sm btn-primary"> <a href="laporan/${data.id}" class="btn btn-sm btn-primary">
Laporan Laporan
</a>`; </a>`;
} }
if((data.status_bayar=="sudah_bayar" || data.status_bayar=="tidak_bayar") && data.nilai_liquidasi >0) { if ((data.status_bayar == "sudah_bayar" || data.status_bayar == "tidak_bayar") && data
if(data.penilai.type_penilai=='resume' && !data.penilai.resume){ .nilai_liquidasi > 0) {
if (data.penilai.type_penilai == 'resume' && !data.penilai.resume) {
laporanButton = ` laporanButton = `
<a href="penilai/print-out-laporan/${data.id}/${dokumenID}/${jenisJaminanID}" class="btn btn-sm btn-primary"> <a href="penilai/print-out-laporan/${data.id}/${dokumenID}/${jenisJaminanID}" class="btn btn-sm btn-primary">
Laporan Laporan
@@ -279,7 +280,7 @@
} }
return `<div class="flex flex-wrap justify-end gap-1.5"> ${penyelesaian} ${resumeButton} ${laporanButton} </div>`; return `<div class="flex flex-wrap gap-1.5 justify-end"> ${penyelesaian} ${resumeButton} ${laporanButton} </div>`;
}, },
} }
}, },

View File

@@ -15,197 +15,236 @@
@endphp @endphp
@section('content') @section('content')
<div class="w-full grid gap-5 lg:gap-7.5 mx-auto"> <div class="grid gap-5 mx-auto w-full lg:gap-7.5">
<div class="card border border-agi-100 pb-2.5"> <div class="pb-2.5 border card border-agi-100">
<div class="card-header bg-agi-50" id="basic_settings"> <div class="card-header bg-agi-50" id="basic_settings">
<div class="card-title flex flex-row gap-1.5"> <div class="flex flex-row gap-1.5 card-title">
{{ $hasMemo ? 'Proses Penyelesaian NOC' : 'NOC' }} {{ $hasMemo ? 'Proses Penyelesaian NOC' : 'NOC' }}
</div> </div>
<div class="flex items-center gap-2"> <div class="flex gap-2 items-center">
<a href="{{ route('noc.index') }}" class="btn btn-xs btn-info"><i class="ki-filled ki-exit-left"></i> Back</a> <a href="{{ route('noc.index') }}" class="btn btn-xs btn-info"><i class="ki-filled ki-exit-left"></i>
Back</a>
</div> </div>
</div> </div>
<div class="card-body"> <div class="card-body">
<form action="{{ !$hasMemo ? route('noc.store') : route('noc.update',$persetujuanPenawaran) }}" method="POST" class="grid gap-5" enctype="multipart/form-data"> <form action="{{ !$hasMemo ? route('noc.store') : route('noc.update', $persetujuanPenawaran) }}"
method="POST" class="grid gap-5" enctype="multipart/form-data">
@csrf @csrf
@if($hasMemo) @if ($hasMemo)
@method('PUT') @method('PUT')
@endif @endif
<input type="hidden" name="penawaran_id" value="{{ $persetujuanPenawaran->penawaran_id ?? old('penawaran_id') }}"> <input type="hidden" name="penawaran_id"
<input type="hidden" name="persetujuan_penawaran_id" value="{{ $persetujuanPenawaran->id ?? old('persetujuan_penawaran_id') }}"> value="{{ $persetujuanPenawaran->penawaran_id ?? old('penawaran_id') }}">
<input type="hidden" name="permohonan_id" value="{{ $persetujuanPenawaran->penawaran->permohonan->id ?? $persetujuanPenawaran->permohonan->id }}"> <input type="hidden" name="persetujuan_penawaran_id"
value="{{ $persetujuanPenawaran->id ?? old('persetujuan_penawaran_id') }}">
<input type="hidden" name="permohonan_id"
value="{{ $persetujuanPenawaran->penawaran->permohonan->id ?? $persetujuanPenawaran->permohonan->id }}">
<div class="flex items-baseline flex-wrap lg:flex-nowrap gap-2.5"> <div class="flex flex-wrap gap-2.5 items-baseline lg:flex-nowrap">
<label class="form-label max-w-56"> <label class="form-label max-w-56">
Status Bayar Status Bayar
</label> </label>
<div class="flex flex-wrap items-baseline w-full"> <div class="flex flex-wrap items-baseline w-full">
<select class="input tomselect w-full @error('status_pembayar') border-danger bg-danger-light @enderror" name="status_pembayar" id="status_pembayar" {{ $hasMemo ? 'disabled' : '' }}> <select
class="input tomselect w-full @error('status_pembayar') border-danger bg-danger-light @enderror"
name="status_pembayar" id="status_pembayar" {{ $hasMemo ? 'disabled' : '' }}>
<option value="">Pilih Status Bayar</option> <option value="">Pilih Status Bayar</option>
<option value="sudah_bayar" {{ (old('status_pembayar') == 'sudah_bayar') || ($persetujuanPenawaran?->penawaran?->permohonan?->status_bayar == 'sudah_bayar') ? 'selected' : '' }}>Sudah Bayar</option> <option value="sudah_bayar"
<option value="belum_bayar" {{ (old('status_pembayar') == 'belum_bayar') || ($persetujuanPenawaran?->penawaran?->permohonan?->status_bayar == 'belum_bayar') ? 'selected' : '' }}>Belum Bayar</option> {{ old('status_pembayar') == 'sudah_bayar' || $persetujuanPenawaran?->penawaran?->permohonan?->status_bayar == 'sudah_bayar' ? 'selected' : '' }}>
Sudah Bayar</option>
<option value="belum_bayar"
{{ old('status_pembayar') == 'belum_bayar' || $persetujuanPenawaran?->penawaran?->permohonan?->status_bayar == 'belum_bayar' ? 'selected' : '' }}>
Belum Bayar</option>
</select> </select>
@error('status_bayar') @error('status_bayar')
<em class="alert text-danger text-sm">{{ $message }}</em> <em class="text-sm alert text-danger">{{ $message }}</em>
@enderror @enderror
</div> </div>
</div> </div>
<div class="flex items-baseline flex-wrap lg:flex-nowrap gap-2.5"> <div class="flex flex-wrap gap-2.5 items-baseline lg:flex-nowrap">
<label class="form-label max-w-56"> <label class="form-label max-w-56">
Bukti Pembayaran Bukti Pembayaran
</label> </label>
<div class="flex flex-wrap items-baseline w-full"> <div class="flex flex-wrap items-baseline w-full">
@if(!empty($persetujuanPenawaran->bukti_bayar)) @if (!empty($persetujuanPenawaran->bukti_bayar))
<div class="mt-2 flex items-center"> <div class="flex items-center mt-2">
<a href="{{ Storage::url($persetujuanPenawaran->bukti_bayar) }}" target="_blank" class="badge badge-sm badge-outline badge-warning"> <a href="{{ Storage::url($persetujuanPenawaran->bukti_bayar) }}" target="_blank"
<i class="ki-filled ki-eye mr-2"></i> Lihat File class="badge badge-sm badge-outline badge-warning">
<i class="mr-2 ki-filled ki-eye"></i> Lihat File
</a> </a>
</div> </div>
@endif @endif
</div> </div>
</div> </div>
<div class="flex items-baseline flex-wrap lg:flex-nowrap gap-2.5"> <div class="flex flex-wrap gap-2.5 items-baseline lg:flex-nowrap">
<label class="form-label max-w-56"> <label class="form-label max-w-56">
Nominal Bayar Nominal Bayar
</label> </label>
<div class="flex flex-wrap items-baseline w-full"> <div class="flex flex-wrap items-baseline w-full">
<input type="number" name="total_harus_bayar" id="total_harus_bayar" class="input w-full @error('total_harus_bayar') border-danger bg-danger-light @enderror" value="{{ old('total_harus_bayar', $persetujuanPenawaran->nominal_bayar ?? '') }}" readonly> <input type="number" name="total_harus_bayar" id="total_harus_bayar"
class="input w-full @error('total_harus_bayar') border-danger bg-danger-light @enderror"
value="{{ old('total_harus_bayar', $persetujuanPenawaran->nominal_bayar ?? '') }}"
readonly>
@error('total_harus_bayar') @error('total_harus_bayar')
<em class="alert text-danger text-sm">{{ $message }}</em> <em class="text-sm alert text-danger">{{ $message }}</em>
@enderror @enderror
</div> </div>
</div> </div>
<div class="flex items-baseline flex-wrap lg:flex-nowrap gap-2.5"> <div class="flex flex-wrap gap-2.5 items-baseline lg:flex-nowrap">
<label class="form-label max-w-56"> <label class="form-label max-w-56">
Nominal Diterima Nominal Diterima
</label> </label>
<div class="flex flex-wrap items-baseline w-full"> <div class="flex flex-wrap items-baseline w-full">
<input type="number" name="nominal_bayar" id="nominal_bayar" class="input w-full @error('nominal_bayar') border-danger bg-danger-light @enderror" value="{{ old('nominal_bayar', $persetujuanPenawaran->noc->nominal_bayar ?? '') }}" placeholder="Masukkan nominal bayar" {{ $hasMemo ? 'readonly' : '' }}> <input type="number" name="nominal_bayar" id="nominal_bayar"
class="input w-full @error('nominal_bayar') border-danger bg-danger-light @enderror"
value="{{ old('nominal_bayar', $persetujuanPenawaran->noc->nominal_bayar ?? '') }}"
placeholder="Masukkan nominal bayar" {{ $hasMemo ? 'readonly' : '' }}>
@error('nominal_bayar') @error('nominal_bayar')
<em class="alert text-danger text-sm">{{ $message }}</em> <em class="text-sm alert text-danger">{{ $message }}</em>
@enderror @enderror
</div> </div>
</div> </div>
<div class="flex items-baseline flex-wrap lg:flex-nowrap gap-2.5"> <div class="flex flex-wrap gap-2.5 items-baseline lg:flex-nowrap">
<label class="form-label max-w-56"> <label class="form-label max-w-56">
Tanggal Pembayaran Tanggal Pembayaran
</label> </label>
<div class="flex flex-wrap items-baseline w-full"> <div class="flex flex-wrap items-baseline w-full">
<input type="date" name="tanggal_pembayaran" id="tanggal_pembayaran" class="input w-full @error('tanggal_pembayaran') border-danger bg-danger-light @enderror" value="{{ old('tanggal_pembayaran', isset($persetujuanPenawaran->noc->tanggal_pembayaran) ? date('Y-m-d', strtotime($persetujuanPenawaran->noc->tanggal_pembayaran)) : '') }}" {{ $hasMemo ? 'readonly' : '' }}> <input type="date" name="tanggal_pembayaran" id="tanggal_pembayaran"
class="input w-full @error('tanggal_pembayaran') border-danger bg-danger-light @enderror"
value="{{ old('tanggal_pembayaran', isset($persetujuanPenawaran->noc->tanggal_pembayaran) ? date('Y-m-d', strtotime($persetujuanPenawaran->noc->tanggal_pembayaran)) : '') }}"
{{ $hasMemo ? 'readonly' : '' }}>
@error('tanggal_pembayaran') @error('tanggal_pembayaran')
<em class="alert text-danger text-sm">{{ $message }}</em> <em class="text-sm alert text-danger">{{ $message }}</em>
@enderror @enderror
</div> </div>
</div> </div>
<div class="flex items-baseline flex-wrap lg:flex-nowrap gap-2.5"> <div class="flex flex-wrap gap-2.5 items-baseline lg:flex-nowrap">
<label class="form-label max-w-56"> <label class="form-label max-w-56">
Bukti KSL Bukti KSL
</label> </label>
<div class="flex flex-wrap items-baseline w-full"> <div class="flex flex-wrap items-baseline w-full">
@if(!$hasMemo) @if (!$hasMemo)
<input type="file" name="bukti_ksl" id="bukti_ksl" class="file-input w-full @error('bukti_ksl') border-danger bg-danger-light @enderror" accept=".pdf,.jpg,.jpeg,.png"> <input type="file" name="bukti_ksl" id="bukti_ksl"
class="file-input w-full @error('bukti_ksl') border-danger bg-danger-light @enderror"
accept=".pdf,.jpg,.jpeg,.png">
@error('bukti_ksl') @error('bukti_ksl')
<em class="alert text-danger text-sm">{{ $message }}</em> <em class="text-sm alert text-danger">{{ $message }}</em>
@enderror @enderror
@endif @endif
@if(isset($persetujuanPenawaran->noc->bukti_ksl) && !empty($persetujuanPenawaran->noc->bukti_ksl)) @if (isset($persetujuanPenawaran->noc->bukti_ksl) && !empty($persetujuanPenawaran->noc->bukti_ksl))
<div class="mt-2 flex items-center"> <div class="flex items-center mt-2">
<a href="{{ Storage::url($persetujuanPenawaran->noc->bukti_ksl) }}" target="_blank" class="badge badge-sm badge-outline badge-warning"> <a href="{{ Storage::url($persetujuanPenawaran->noc->bukti_ksl) }}" target="_blank"
<i class="ki-filled ki-eye mr-2"></i> Lihat File class="badge badge-sm badge-outline badge-warning">
<i class="mr-2 ki-filled ki-eye"></i> Lihat File
</a> </a>
</div> </div>
@endif @endif
</div> </div>
</div> </div>
@if($hasMemo) @if ($hasMemo)
<div class="flex items-baseline flex-wrap lg:flex-nowrap gap-2.5"> <div class="flex flex-wrap gap-2.5 items-baseline lg:flex-nowrap">
<label class="form-label max-w-56"> <label class="form-label max-w-56">
Memo Penyelesaian Memo Penyelesaian
</label> </label>
<div class="flex flex-wrap items-baseline w-full"> <div class="flex flex-wrap items-baseline w-full">
<div class="flex items-center"> <div class="flex items-center">
<a href="{{ Storage::url($persetujuanPenawaran->noc->memo_penyelesaian) }}" target="_blank" class="badge badge-sm badge-outline badge-warning"> <a href="{{ Storage::url($persetujuanPenawaran->noc->memo_penyelesaian) }}"
<i class="ki-filled ki-eye mr-2"></i> Lihat File target="_blank" class="badge badge-sm badge-outline badge-warning">
<i class="mr-2 ki-filled ki-eye"></i> Lihat File
</a> </a>
<input type="hidden" name="memo_penyelesaian_existing" value="{{ $persetujuanPenawaran->noc->memo_penyelesaian }}"> <input type="hidden" name="memo_penyelesaian_existing"
value="{{ $persetujuanPenawaran->noc->memo_penyelesaian }}">
</div> </div>
</div> </div>
</div> </div>
<div class="flex items-baseline flex-wrap lg:flex-nowrap gap-2.5"> <div class="flex flex-wrap gap-2.5 items-baseline lg:flex-nowrap">
<label class="form-label max-w-56"> <label class="form-label max-w-56">
Bukti Penyelesaian Bukti Penyelesaian
</label> </label>
<div class="flex flex-wrap items-baseline w-full"> <div class="flex flex-wrap items-baseline w-full">
<input type="file" name="bukti_penyelesaian" id="bukti_penyelesaian" class="file-input w-full @error('bukti_penyelesaian') border-danger bg-danger-light @enderror" accept=".pdf,.jpg,.jpeg,.png"> <input type="file" name="bukti_penyelesaian" id="bukti_penyelesaian"
class="file-input w-full @error('bukti_penyelesaian') border-danger bg-danger-light @enderror"
accept=".pdf,.jpg,.jpeg,.png">
@error('bukti_penyelesaian') @error('bukti_penyelesaian')
<em class="alert text-danger text-sm">{{ $message }}</em> <em class="text-sm alert text-danger">{{ $message }}</em>
@enderror @enderror
@if(isset($persetujuanPenawaran->noc->bukti_penyelesaian) && !empty($persetujuanPenawaran->noc->bukti_penyelesaian)) @if (isset($persetujuanPenawaran->noc->bukti_penyelesaian) && !empty($persetujuanPenawaran->noc->bukti_penyelesaian))
<div class="mt-2 flex items-center"> <div class="flex items-center mt-2">
<a href="{{ Storage::url($persetujuanPenawaran->noc->bukti_penyelesaian) }}" target="_blank" class="badge badge-sm badge-outline badge-warning"> <a href="{{ Storage::url($persetujuanPenawaran->noc->bukti_penyelesaian) }}"
<i class="ki-filled ki-eye mr-2"></i> Lihat File target="_blank" class="badge badge-sm badge-outline badge-warning">
<i class="mr-2 ki-filled ki-eye"></i> Lihat File
</a> </a>
<input type="hidden" name="bukti_penyelesaian_existing" value="{{ $persetujuanPenawaran->noc->bukti_penyelesaian }}"> <input type="hidden" name="bukti_penyelesaian_existing"
value="{{ $persetujuanPenawaran->noc->bukti_penyelesaian }}">
</div> </div>
@endif @endif
</div> </div>
</div> </div>
<div class="flex items-baseline flex-wrap lg:flex-nowrap gap-2.5"> <div class="flex flex-wrap gap-2.5 items-baseline lg:flex-nowrap">
<label class="form-label max-w-56"> <label class="form-label max-w-56">
Nominal Penyelesaian Nominal Penyelesaian
</label> </label>
<div class="flex flex-wrap items-baseline w-full"> <div class="flex flex-wrap items-baseline w-full">
<input type="number" name="nominal_penyelesaian" id="nominal_penyelesaian" class="input w-full @error('nominal_penyelesaian') border-danger bg-danger-light @enderror" value="{{ old('nominal_penyelesaian', $persetujuanPenawaran->noc->nominal_penyelesaian ?? '') }}" placeholder="Masukkan nominal penyelesaian"> <input type="number" name="nominal_penyelesaian" id="nominal_penyelesaian"
class="input w-full @error('nominal_penyelesaian') border-danger bg-danger-light @enderror"
value="{{ old('nominal_penyelesaian', $persetujuanPenawaran->noc->nominal_penyelesaian ?? '') }}"
placeholder="Masukkan nominal penyelesaian">
@error('nominal_penyelesaian') @error('nominal_penyelesaian')
<em class="alert text-danger text-sm">{{ $message }}</em> <em class="text-sm alert text-danger">{{ $message }}</em>
@enderror @enderror
</div> </div>
</div> </div>
<div class="flex items-baseline flex-wrap lg:flex-nowrap gap-2.5"> <div class="flex flex-wrap gap-2.5 items-baseline lg:flex-nowrap">
<label class="form-label max-w-56"> <label class="form-label max-w-56">
Tanggal Penyelesaian Tanggal Penyelesaian
</label> </label>
<div class="flex flex-wrap items-baseline w-full"> <div class="flex flex-wrap items-baseline w-full">
<input type="date" name="tanggal_penyelesaian" id="tanggal_penyelesaian" class="input w-full @error('tanggal_penyelesaian') border-danger bg-danger-light @enderror" value="{{ old('tanggal_penyelesaian', isset($persetujuanPenawaran->noc->tanggal_penyelesaian) ? date('Y-m-d', strtotime($persetujuanPenawaran->noc->tanggal_penyelesaian)) : '') }}"> <input type="date" name="tanggal_penyelesaian" id="tanggal_penyelesaian"
class="input w-full @error('tanggal_penyelesaian') border-danger bg-danger-light @enderror"
value="{{ old('tanggal_penyelesaian', isset($persetujuanPenawaran->noc->tanggal_penyelesaian) ? date('Y-m-d', strtotime($persetujuanPenawaran->noc->tanggal_penyelesaian)) : '') }}">
@error('tanggal_penyelesaian') @error('tanggal_penyelesaian')
<em class="alert text-danger text-sm">{{ $message }}</em> <em class="text-sm alert text-danger">{{ $message }}</em>
@enderror @enderror
</div> </div>
</div> </div>
@endif @endif
<div class="flex items-baseline flex-wrap lg:flex-nowrap gap-2.5"> <div class="flex flex-wrap gap-2.5 items-baseline lg:flex-nowrap">
<label class="form-label max-w-56"> <label class="form-label max-w-56">
Catatan Catatan
</label> </label>
<div class="flex flex-wrap items-baseline w-full"> <div class="flex flex-wrap items-baseline w-full">
<textarea name="catatan" id="catatan" rows="4" class="textarea w-full @error('catatan') border-danger bg-danger-light @enderror" readonly placeholder="Masukkan catatan">{{ old('catatan', $persetujuanPenawaran->catatan ?? '') }}</textarea> <textarea name="catatan" id="catatan" rows="4"
class="textarea w-full @error('catatan') border-danger bg-danger-light @enderror" readonly
placeholder="Masukkan catatan">{{ old('catatan', $persetujuanPenawaran->catatan ?? '') }}</textarea>
@error('catatan') @error('catatan')
<em class="alert text-danger text-sm">{{ $message }}</em> <em class="text-sm alert text-danger">{{ $message }}</em>
@enderror @enderror
</div> </div>
</div> </div>
<div class="flex items-baseline flex-wrap lg:flex-nowrap gap-2.5"> <div class="flex flex-wrap gap-2.5 items-baseline lg:flex-nowrap">
<label class="form-label max-w-56"> <label class="form-label max-w-56">
Catatan NOC Catatan NOC
</label> </label>
<div class="flex flex-wrap items-baseline w-full"> <div class="flex flex-wrap items-baseline w-full">
<textarea name="catatan_noc" id="catatan_noc" rows="4" class="textarea w-full @error('catatan_noc') border-danger bg-danger-light @enderror" placeholder="Masukkan catatan noc">{{ old('catatan_noc', $persetujuanPenawaran->noc->catatan_noc ?? '') }}</textarea> <textarea name="catatan_noc" id="catatan_noc" rows="4"
class="textarea w-full @error('catatan_noc') border-danger bg-danger-light @enderror"
placeholder="Masukkan catatan noc">{{ old('catatan_noc', $persetujuanPenawaran->noc->catatan_noc ?? '') }}</textarea>
@error('catatan_noc') @error('catatan_noc')
<em class="alert text-danger text-sm">{{ $message }}</em> <em class="text-sm alert text-danger">{{ $message }}</em>
@enderror @enderror
</div> </div>
</div> </div>

View File

@@ -5,9 +5,10 @@
@endsection @endsection
@section('content') @section('content')
<div class="w-full grid gap-5 lg:gap-7.5 mx-auto"> <div class="grid gap-5 mx-auto w-full lg:gap-7.5">
<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="noc-table" data-api-url="{{ route('noc.datatables.pembayaran') }}"> <div class="min-w-full border card border-agi-100 card-grid" data-datatable="false" data-datatable-page-size="10"
<div class="card-header bg-agi-50 py-5 flex-wrap"> data-datatable-state-save="false" id="noc-table" data-api-url="{{ route('noc.datatables.pembayaran') }}">
<div class="flex-wrap py-5 card-header bg-agi-50">
<h3 class="card-title"> <h3 class="card-title">
Daftar NOC Pembayaran Daftar NOC Pembayaran
</h3> </h3>
@@ -27,11 +28,12 @@
<div class="card-body"> <div class="card-body">
<div class="scrollable-x-auto"> <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"> <table class="table text-sm font-medium text-gray-700 align-middle table-auto table-border"
data-datatable-table="true">
<thead> <thead>
<tr> <tr>
<th class="w-14"> <th class="w-14">
<input class="checkbox checkbox-sm" data-datatable-check="true" type="checkbox"/> <input class="checkbox checkbox-sm" data-datatable-check="true" type="checkbox" />
</th> </th>
<th class="min-w-[150px]" data-datatable-column="nomor_registrasi"> <th class="min-w-[150px]" data-datatable-column="nomor_registrasi">
<span class="sort"> <span class="sort-label"> Nomor Registrasi </span> <span class="sort"> <span class="sort-label"> Nomor Registrasi </span>
@@ -75,13 +77,13 @@
</table> </table>
</div> </div>
<div <div
class="card-footer justify-center md:justify-between flex-col md:flex-row gap-3 text-gray-600 text-2sm font-medium"> class="flex-col gap-3 justify-center font-medium text-gray-600 card-footer md:justify-between md:flex-row text-2sm">
<div class="flex items-center gap-2"> <div class="flex gap-2 items-center">
Show Show
<select class="select select-sm w-16" data-datatable-size="true" name="perpage"> </select> per <select class="w-16 select select-sm" data-datatable-size="true" name="perpage"> </select> per
page page
</div> </div>
<div class="flex items-center gap-4"> <div class="flex gap-4 items-center">
<span data-datatable-info="true"> </span> <span data-datatable-info="true"> </span>
<div class="pagination" data-datatable-pagination="true"> <div class="pagination" data-datatable-pagination="true">
</div> </div>
@@ -140,7 +142,7 @@
title: 'Cabang', title: 'Cabang',
}, },
tanggal_setor: { tanggal_setor: {
title: 'Tanggal Setor', title: 'Tanggal KSL',
}, },
nominal_bayar: { nominal_bayar: {
title: 'Nominal Bayar', title: 'Nominal Bayar',
@@ -190,7 +192,7 @@
let dataTable = new KTDataTable(element, dataTableOptions); let dataTable = new KTDataTable(element, dataTableOptions);
// Custom search functionality // Custom search functionality
searchInput.addEventListener('input', function () { searchInput.addEventListener('input', function() {
const searchValue = this.value.trim(); const searchValue = this.value.trim();
dataTable.search(searchValue, true); dataTable.search(searchValue, true);
}); });

View File

@@ -673,6 +673,10 @@ Breadcrumbs::for('noc', function (BreadcrumbTrail $trail) {
$trail->push('NOC', route('noc.index')); $trail->push('NOC', route('noc.index'));
}); });
Breadcrumbs::for('noc.show', function (BreadcrumbTrail $trail) {
$trail->push('NOC', route('noc.index'));
});
Breadcrumbs::for('noc.pembayaran', function (BreadcrumbTrail $trail) { Breadcrumbs::for('noc.pembayaran', function (BreadcrumbTrail $trail) {
$trail->push('NOC Pembayaran', route('noc.pembayaran.index')); $trail->push('NOC Pembayaran', route('noc.pembayaran.index'));
}); });