feat(noc): tambah fitur penyelesaian NOC

- Tambah atribut baru: `tanggal_pembayaran`, `memo_penyelesaian`, `bukti_penyelesaian`, dan `nominal_penyelesaian`.
- Update logika penyimpanan dan update data NOC dengan atribut baru.
- Tambah validasi dan handling untuk memproses pembayaran dan penyelesaian NOC.
- Update form NOC untuk mendukung input penyelesaian, termasuk file memo dan bukti penyelesaian.
- Update tampilan tabel data untuk menampilkan atribut baru di halaman index NOC.
- Tambah logika untuk memeriksa keberadaan memo penyelesaian di view form NOC.
- Penyesuaian endpoint dan logika dalam controller untuk mendukung penyelesaian data NOC.

Signed-off-by: Daeng Deni Mardaeni <ddeni05@gmail.com>
This commit is contained in:
Daeng Deni Mardaeni
2025-05-06 13:41:36 +07:00
parent 5e8067ad72
commit eea49b7943
3 changed files with 186 additions and 35 deletions

View File

@@ -4,6 +4,16 @@
{{ Breadcrumbs::render(request()->route()->getName()) }}
@endsection
@php
$hasMemo = false;
try {
$memoPath = $persetujuanPenawaran->noc->memo_penyelesaian ?? null;
$hasMemo = isset($memoPath) && !empty($memoPath) && Storage::exists($memoPath);
} catch (Exception $e) {
// Jika terjadi error, $hasMemo tetap false
}
@endphp
@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">
@@ -16,8 +26,11 @@
</div>
</div>
<div class="card-body">
<form action="{{ route('noc.store') }}" 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
@if($hasMemo)
@method('PUT')
@endif
<input type="hidden" name="penawaran_id" value="{{ $persetujuanPenawaran->penawaran_id ?? old('penawaran_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 }}">
@@ -27,7 +40,7 @@
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">
<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="sudah_bayar" {{ (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>
@@ -55,41 +68,109 @@
Nominal Bayar
</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', $persetujuanPenawaran->noc->nominal_bayar ?? '') }}" placeholder="Masukkan nominal bayar">
<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')
<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($persetujuanPenawaran->noc->tanggal_pembayaran) ? date('Y-m-d', strtotime($persetujuanPenawaran->noc->tanggal_pembayaran)) : '') }}" {{ $hasMemo ? '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">
<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')
<em class="alert text-danger text-sm">{{ $message }}</em>
@enderror
@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">
@error('bukti_ksl')
<em class="alert text-danger text-sm">{{ $message }}</em>
@enderror
@endif
@if(isset($persetujuanPenawaran->noc->bukti_ksl) && !empty($persetujuanPenawaran->noc->bukti_ksl))
<div class="mt-2 flex items-center">
<span class="text-sm text-gray-600 mr-2">File yang sudah diupload:</span>
<a href="{{ asset('storage/' . $persetujuanPenawaran->noc->bukti_ksl) }}"
target="_blank" class="text-blue-600 hover:text-blue-800 underline flex items-center">
<svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4 mr-1" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z" />
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M2.458 12C3.732 7.943 7.523 5 12 5c4.478 0 8.268 2.943 9.542 7-1.274 4.057-5.064 7-9.542 7-4.477 0-8.268-2.943-9.542-7z" />
</svg>
Lihat File
<a href="{{ Storage::url($persetujuanPenawaran->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>
@if($hasMemo)
<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">
<div class="flex items-center">
<a href="{{ Storage::url($persetujuanPenawaran->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>
<input type="hidden" name="memo_penyelesaian_existing" value="{{ $persetujuanPenawaran->noc->memo_penyelesaian }}">
</div>
</div>
</div>
<div class="flex items-baseline flex-wrap lg:flex-nowrap gap-2.5">
<label class="form-label max-w-56">
Bukti Penyelesaian
</label>
<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">
@error('bukti_penyelesaian')
<em class="alert text-danger text-sm">{{ $message }}</em>
@enderror
@if(isset($persetujuanPenawaran->noc->bukti_penyelesaian) && !empty($persetujuanPenawaran->noc->bukti_penyelesaian))
<div class="mt-2 flex items-center">
<a href="{{ Storage::url($persetujuanPenawaran->noc->bukti_penyelesaian) }}" target="_blank" class="badge badge-sm badge-outline badge-warning">
<i class="ki-filled ki-eye mr-2"></i> Lihat File
</a>
<input type="hidden" name="bukti_penyelesaian_existing" value="{{ $persetujuanPenawaran->noc->bukti_penyelesaian }}">
</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 Penyelesaian
</label>
<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">
@error('nominal_penyelesaian')
<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 Penyelesaian
</label>
<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)) : '') }}">
@error('tanggal_penyelesaian')
<em class="alert text-danger text-sm">{{ $message }}</em>
@enderror
</div>
</div>
@endif
<div class="flex items-baseline flex-wrap lg:flex-nowrap gap-2.5">
<label class="form-label max-w-56">
Catatan

View File

@@ -57,6 +57,22 @@
<span class="sort"> <span class="sort-label"> Bukti KSL </span>
<span class="sort-icon"> </span> </span>
</th>
<th class="min-w-[150px]" data-datatable-column="tanggal_pembayaran">
<span class="sort"> <span class="sort-label"> Tanggal Pembayaran </span>
<span class="sort-icon"> </span> </span>
</th>
<th class="min-w-[150px]" data-datatable-column="memo_penyelesaian">
<span class="sort"> <span class="sort-label"> Memo Penyelesaian </span>
<span class="sort-icon"> </span> </span>
</th>
<th class="min-w-[150px]" data-datatable-column="bukti_penyelesaian">
<span class="sort"> <span class="sort-label"> Bukti Penyelesaian </span>
<span class="sort-icon"> </span> </span>
</th>
<th class="min-w-[150px]" data-datatable-column="nominal_penyelesaian">
<span class="sort"> <span class="sort-label"> Nominal Penyelesaian </span>
<span class="sort-icon"> </span> </span>
</th>
<th class="min-w-[150px]" data-datatable-column="tanggal_penyelesaian">
<span class="sort"> <span class="sort-label"> Tanggal Penyelesaian </span>
<span class="sort-icon"> </span> </span>
@@ -149,6 +165,36 @@
}
},
},
tanggal_pembayaran: {
title: 'Tanggal Pembayaran',
},
memo_penyelesaian: {
title: 'Memo Penyelesaian',
render: (item, data) => {
if (data.memo_penyelesaian) {
return `<a href="storage/${data.memo_penyelesaian}" download="storage/${data.memo_penyelesaian}" target="_blank" class="badge badge-sm badge-outline">
Download <i class="ki-filled ki-cloud-download"></i>
</a>`;
} else {
return '-';
}
},
},
bukti_penyelesaian: {
title: 'Bukti Penyelesaian',
render: (item, data) => {
if (data.bukti_penyelesaian) {
return `<a href="storage/${data.bukti_penyelesaian}" download="storage/${data.bukti_penyelesaian}" target="_blank" class="badge badge-sm badge-outline">
Download <i class="ki-filled ki-cloud-download"></i>
</a>`;
} else {
return '-';
}
},
},
nominal_penyelesaian: {
title: 'Nominal Penyelesaian',
},
tanggal_penyelesaian: {
title: 'Tanggal Penyelesaian',
},