feat(noc): tambah fitur penyelesaian dan memo penyelesaian NOC
- Menambahkan relasi `noc` pada data laporan. - Memperbarui logika `update` NOC untuk memproses memo penyelesaian. - Menambahkan tombol "Penyelesaian" pada halaman laporan jika data NOC belum selesai. - Memperbaiki pengecekan keberadaan file memo dengan disk publik. - Mengimplementasikan view dan form baru untuk input memo penyelesaian pada NOC. - Menambahkan routing dan breadcrumbs untuk proses penyelesaian memo NOC. - Menambahkan validasi dan penyimpanan file memo penyelesaian. Signed-off-by: Daeng Deni Mardaeni <ddeni05@gmail.com>
This commit is contained in:
@@ -123,7 +123,7 @@ class LaporanController extends Controller
|
|||||||
$filteredRecords = $query->count();
|
$filteredRecords = $query->count();
|
||||||
|
|
||||||
// Get the data for the current page
|
// Get the data for the current page
|
||||||
$data = $query->with(['user', 'debiture', 'branch', 'tujuanPenilaian', 'penilaian','jenisFasilitasKredit', 'documents.inspeksi','penilai','documents.detail'])->get();
|
$data = $query->with(['user', 'debiture', 'branch', 'tujuanPenilaian', 'penilaian','jenisFasilitasKredit', 'documents.inspeksi','penilai','documents.detail','noc'])->get();
|
||||||
|
|
||||||
// Calculate the page count
|
// Calculate the page count
|
||||||
$pageCount = ceil($totalRecords / $size);
|
$pageCount = ceil($totalRecords / $size);
|
||||||
|
|||||||
@@ -100,6 +100,27 @@
|
|||||||
public function update(NocRequest $request, PersetujuanPenawaran $persetujuanPenawaran)
|
public function update(NocRequest $request, PersetujuanPenawaran $persetujuanPenawaran)
|
||||||
{
|
{
|
||||||
$validated = $request->validated();
|
$validated = $request->validated();
|
||||||
|
|
||||||
|
if($request->get('is_memo')){
|
||||||
|
|
||||||
|
$memo = Noc::find($request->get('is_memo'));
|
||||||
|
|
||||||
|
$folderPath = 'noc/' . request()->get('persetujuan_penawaran_id') . '/memo_penyelesaian/';
|
||||||
|
|
||||||
|
if ($request->hasFile('memo_penyelesaian')) {
|
||||||
|
$memo->memo_penyelesaian = $request->file('memo_penyelesaian')->store(
|
||||||
|
$folderPath,
|
||||||
|
'public',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
$memo->catatan_noc = $validated['catatan_noc'];
|
||||||
|
$memo->save();
|
||||||
|
|
||||||
|
|
||||||
|
return redirect()
|
||||||
|
->route('laporan.index')->with('success', 'Memo Penyelesaian updated successfully');
|
||||||
|
}
|
||||||
$dataNoc = [
|
$dataNoc = [
|
||||||
'nominal_penyelesaian' => $validated['nominal_penyelesaian'],
|
'nominal_penyelesaian' => $validated['nominal_penyelesaian'],
|
||||||
'tanggal_penyelesaian' => $validated['tanggal_penyelesaian'] ?? date('Y-m-d'),
|
'tanggal_penyelesaian' => $validated['tanggal_penyelesaian'] ?? date('Y-m-d'),
|
||||||
@@ -142,7 +163,11 @@
|
|||||||
/**
|
/**
|
||||||
* Display the specified resource.
|
* Display the specified resource.
|
||||||
*/
|
*/
|
||||||
public function show($id) {}
|
public function show(Request $request) {
|
||||||
|
$noc = Noc::find($request->get('id'));
|
||||||
|
|
||||||
|
return view('lpj::noc.memo', compact('noc'));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Show the form for editing the specified resource.
|
* Show the form for editing the specified resource.
|
||||||
|
|||||||
@@ -237,8 +237,17 @@
|
|||||||
const type = data.penilai?.type || '';
|
const type = data.penilai?.type || '';
|
||||||
let laporanButton = '';
|
let laporanButton = '';
|
||||||
let resumeButton = '';
|
let resumeButton = '';
|
||||||
|
let penyelesaian = '';
|
||||||
|
|
||||||
|
|
||||||
|
if(data.noc) {
|
||||||
|
if (!data.noc?.tanggal_penyelesaian && !data.noc?.memo_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">
|
||||||
|
Penyelesaian
|
||||||
|
</a>`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if(data.penilai.resume) {
|
if(data.penilai.resume) {
|
||||||
resumeButton = `
|
resumeButton = `
|
||||||
@@ -270,7 +279,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return `<div class="flex flex-wrap justify-end gap-1.5"> ${resumeButton} ${laporanButton} </div>`;
|
return `<div class="flex flex-wrap justify-end gap-1.5"> ${penyelesaian} ${resumeButton} ${laporanButton} </div>`;
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
$hasMemo = false;
|
$hasMemo = false;
|
||||||
try {
|
try {
|
||||||
$memoPath = $persetujuanPenawaran->noc->memo_penyelesaian ?? null;
|
$memoPath = $persetujuanPenawaran->noc->memo_penyelesaian ?? null;
|
||||||
$hasMemo = isset($memoPath) && !empty($memoPath) && Storage::exists($memoPath);
|
$hasMemo = isset($memoPath) && !empty($memoPath) && Storage::disk('public')->exists($memoPath);
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
// Jika terjadi error, $hasMemo tetap false
|
// Jika terjadi error, $hasMemo tetap false
|
||||||
}
|
}
|
||||||
@@ -19,7 +19,7 @@
|
|||||||
<div class="card border border-agi-100 pb-2.5">
|
<div class="card border border-agi-100 pb-2.5">
|
||||||
<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="card-title flex flex-row gap-1.5">
|
||||||
NOC
|
{{ $hasMemo ? 'Proses Penyelesaian NOC' : 'NOC' }}
|
||||||
</div>
|
</div>
|
||||||
<div class="flex items-center gap-2">
|
<div class="flex items-center gap-2">
|
||||||
<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>
|
||||||
@@ -28,7 +28,7 @@
|
|||||||
<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" value="{{ $persetujuanPenawaran->penawaran_id ?? old('penawaran_id') }}">
|
||||||
|
|||||||
163
resources/views/noc/memo.blade.php
Normal file
163
resources/views/noc/memo.blade.php
Normal file
@@ -0,0 +1,163 @@
|
|||||||
|
@extends('layouts.main')
|
||||||
|
|
||||||
|
@section('breadcrumbs')
|
||||||
|
{{ Breadcrumbs::render(request()->route()->getName()) }}
|
||||||
|
@endsection
|
||||||
|
@section('content')
|
||||||
|
<div class="w-full grid gap-5 lg:gap-7.5 mx-auto">
|
||||||
|
<div class="card border border-agi-100 pb-2.5">
|
||||||
|
<div class="card-header bg-agi-50" id="basic_settings">
|
||||||
|
<div class="card-title flex flex-row gap-1.5">
|
||||||
|
Memo Penyelesaian NOC
|
||||||
|
</div>
|
||||||
|
<div class="flex items-center gap-2">
|
||||||
|
<a href="{{ route('noc.index') }}" class="btn btn-xs btn-info"><i class="ki-filled ki-exit-left"></i> Back</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="card-body">
|
||||||
|
<form action="{{ route('noc.update',$noc) }}" method="POST" class="grid gap-5" enctype="multipart/form-data">
|
||||||
|
@csrf
|
||||||
|
@method('PUT')
|
||||||
|
|
||||||
|
<input type="hidden" name="persetujuan_penawaran_id" value="{{ $noc->persetujuan_penawaran_id }}">
|
||||||
|
<input type="hidden" name="permohonan_id" value="{{ $noc->permohonan_id }}">
|
||||||
|
|
||||||
|
<div class="flex items-baseline flex-wrap lg:flex-nowrap gap-2.5">
|
||||||
|
<label class="form-label max-w-56">
|
||||||
|
Status Bayar
|
||||||
|
</label>
|
||||||
|
<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" disabled>
|
||||||
|
<option value="">Pilih Status Bayar</option>
|
||||||
|
<option value="sudah_bayar" {{ (old('status_pembayar') == 'sudah_bayar') || ($noc?->permohonan?->status_bayar == 'sudah_bayar') ? 'selected' : '' }}>Sudah Bayar</option>
|
||||||
|
<option value="belum_bayar" {{ (old('status_pembayar') == 'belum_bayar') || ($noc?->permohonan?->status_bayar == 'belum_bayar') ? 'selected' : '' }}>Belum Bayar</option>
|
||||||
|
</select>
|
||||||
|
@error('status_bayar')
|
||||||
|
<em class="alert text-danger text-sm">{{ $message }}</em>
|
||||||
|
@enderror
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="flex items-baseline flex-wrap lg:flex-nowrap gap-2.5">
|
||||||
|
<label class="form-label max-w-56">
|
||||||
|
Bukti Pembayaran
|
||||||
|
</label>
|
||||||
|
<div class="flex flex-wrap items-baseline w-full">
|
||||||
|
@if(!empty($noc->persetujuanPenawaran->bukti_bayar))
|
||||||
|
<div class="mt-2 flex items-center">
|
||||||
|
<a href="{{ Storage::url($noc->persetujuanPenawaran->bukti_bayar) }}" target="_blank" class="badge badge-sm badge-outline badge-warning">
|
||||||
|
<i class="ki-filled ki-eye mr-2"></i> Lihat File
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
@endif
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="flex items-baseline flex-wrap lg:flex-nowrap gap-2.5">
|
||||||
|
<label class="form-label max-w-56">
|
||||||
|
Nominal Bayar
|
||||||
|
</label>
|
||||||
|
<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', $noc->nominal_bayar ?? '') }}" readonly>
|
||||||
|
@error('total_harus_bayar')
|
||||||
|
<em class="alert text-danger text-sm">{{ $message }}</em>
|
||||||
|
@enderror
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="flex items-baseline flex-wrap lg:flex-nowrap gap-2.5">
|
||||||
|
<label class="form-label max-w-56">
|
||||||
|
Nominal Diterima
|
||||||
|
</label>
|
||||||
|
<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', $noc->nominal_bayar ?? '') }}" placeholder="Masukkan nominal bayar" readonly>
|
||||||
|
@error('nominal_bayar')
|
||||||
|
<em class="alert text-danger text-sm">{{ $message }}</em>
|
||||||
|
@enderror
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="flex items-baseline flex-wrap lg:flex-nowrap gap-2.5">
|
||||||
|
<label class="form-label max-w-56">
|
||||||
|
Tanggal Pembayaran
|
||||||
|
</label>
|
||||||
|
<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($noc->tanggal_pembayaran) ? date('Y-m-d', strtotime($noc->tanggal_pembayaran)) : '') }}" readonly>
|
||||||
|
@error('tanggal_pembayaran')
|
||||||
|
<em class="alert text-danger text-sm">{{ $message }}</em>
|
||||||
|
@enderror
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div class="flex items-baseline flex-wrap lg:flex-nowrap gap-2.5">
|
||||||
|
<label class="form-label max-w-56">
|
||||||
|
Bukti KSL
|
||||||
|
</label>
|
||||||
|
<div class="flex flex-wrap items-baseline w-full">
|
||||||
|
@if(isset($noc->bukti_ksl) && !empty($noc->bukti_ksl))
|
||||||
|
<div class="mt-2 flex items-center">
|
||||||
|
<a href="{{ Storage::url($noc->bukti_ksl) }}" target="_blank" class="badge badge-sm badge-outline badge-warning">
|
||||||
|
<i class="ki-filled ki-eye mr-2"></i> Lihat File
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
@endif
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="flex items-baseline flex-wrap lg:flex-nowrap gap-2.5">
|
||||||
|
<label class="form-label max-w-56">
|
||||||
|
Memo Penyelesaian
|
||||||
|
</label>
|
||||||
|
<div class="flex flex-wrap items-baseline w-full">
|
||||||
|
<input type="hidden" name="is_memo" value="{{ $noc->id }}">
|
||||||
|
<input type="file" name="memo_penyelesaian" id="memo_penyelesaian" class="file-input w-full @error('memo_penyelesaian') border-danger bg-danger-light @enderror" accept=".pdf,.jpg,.jpeg,.png">
|
||||||
|
@error('memo_penyelesaian')
|
||||||
|
<em class="alert text-danger text-sm">{{ $message }}</em>
|
||||||
|
@enderror
|
||||||
|
|
||||||
|
@if(isset($noc->memo_penyelesaian) && !empty($noc->memo_penyelesaian))
|
||||||
|
<div class="mt-2 flex items-center">
|
||||||
|
<a href="{{ Storage::url($noc->memo_penyelesaian) }}" target="_blank" class="badge badge-sm badge-outline badge-warning">
|
||||||
|
<i class="ki-filled ki-eye mr-2"></i> Lihat File
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
@endif
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div class="flex items-baseline flex-wrap lg:flex-nowrap gap-2.5">
|
||||||
|
<label class="form-label max-w-56">
|
||||||
|
Catatan
|
||||||
|
</label>
|
||||||
|
<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', $noc->catatan ?? '') }}</textarea>
|
||||||
|
@error('catatan')
|
||||||
|
<em class="alert text-danger text-sm">{{ $message }}</em>
|
||||||
|
@enderror
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="flex items-baseline flex-wrap lg:flex-nowrap gap-2.5">
|
||||||
|
<label class="form-label max-w-56">
|
||||||
|
Catatan NOC
|
||||||
|
</label>
|
||||||
|
<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', $noc->catatan_noc ?? '') }}</textarea>
|
||||||
|
@error('catatan_noc')
|
||||||
|
<em class="alert text-danger text-sm">{{ $message }}</em>
|
||||||
|
@enderror
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="flex justify-end">
|
||||||
|
<button type="submit" class="btn btn-primary">
|
||||||
|
Proses
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
@endsection
|
||||||
@@ -678,6 +678,11 @@ Breadcrumbs::for('noc.edit', function (BreadcrumbTrail $trail) {
|
|||||||
$trail->push('Proses NOC');
|
$trail->push('Proses NOC');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Breadcrumbs::for('noc.penyelesaian', function (BreadcrumbTrail $trail) {
|
||||||
|
$trail->parent('noc');
|
||||||
|
$trail->push('Proses Memo Penyelesaian NOC');
|
||||||
|
});
|
||||||
|
|
||||||
Breadcrumbs::for('laporan-external', function (BreadcrumbTrail $trail) {
|
Breadcrumbs::for('laporan-external', function (BreadcrumbTrail $trail) {
|
||||||
$trail->push('Laporan External', route('laporan-external.index'));
|
$trail->push('Laporan External', route('laporan-external.index'));
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -654,6 +654,9 @@ Route::middleware(['auth'])->group(function () {
|
|||||||
|
|
||||||
Route::get('noc/datatables', [NocController::class, 'dataForDatatables'])
|
Route::get('noc/datatables', [NocController::class, 'dataForDatatables'])
|
||||||
->name('noc.datatables');
|
->name('noc.datatables');
|
||||||
|
Route::get('noc/penyelesaian',[NocController::class, 'show'])->name('noc.penyelesaian');
|
||||||
|
Route::post('noc/penyelesaian',[NocController::class, 'penyelesaian'])->name('noc.store.penyelesaian');
|
||||||
|
|
||||||
|
|
||||||
Route::resource('noc', NocController::class);
|
Route::resource('noc', NocController::class);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user