Ringkas: perluas akses untuk peran admin , rapikan alur status permohonan/pembayaran/SPK, pindahkan sumber LPJ ke relasi penilai, perbaiki parsing/formatting rupiah, dan tambah konten cetak “Catatan yang Perlu Diperhatikan”. - Perizinan & akses - Izinkan admin melewati filter cabang pada listing Debitur dan Permohonan. - Tambah peran admin pada konfigurasi module.json di beberapa menu/fitur. - Izinkan admin membuat Debitur dan mengakses aksi yang sebelumnya eksklusif untuk administrator dan pemohon-ao . - Alur bisnis & status - Ubah status setelah proses pembatalan/penanganan pembayaran dari done menjadi proses-laporan agar konsisten dengan alur pelaporan. - Nonaktifkan blokir navigasi saat status proses-laporan di PenilaiController (redirect/JSON error dikomentari) agar proses lanjutan tetap bisa diakses bila diperlukan. - Setelah generate SPK, set Permohonan.status dan PenawaranTender.status menjadi registrasi-final untuk menandai finalisasi registrasi. - Pada pembuatan permohonan, jika pengguna admin , tetapkan status = preregister untuk proses pra-registrasi. - Hapus set default branch_id dari PermohonanRequest sehingga pengisian cabang dilakukan eksplisit melalui form (terutama untuk admin). - Data LPJ & referensi relasi - Sumber data LPJ dipindah dari permohonan->penilaian->lpj ke permohonan->penilai->lpj baik di controller ( PenilaianController ) maupun view ( penilaian/otorisator/show.blade.php ) untuk menyesuaikan struktur relasi terbaru. - Dokumen pembayaran - Ubah cara deteksi “Bukti Bayar” dari documents menjadi dokumenjaminan dan ambil detail berdasarkan name = 'Bukti Bayar' , lalu gunakan dokumen_jaminan yang terenkode JSON sebagai sumber pemrosesan berikutnya. - Pada UI approval pembayaran, benahi rendering nominal_bayar (hindari pemutusan baris) dan tampilkan tombol otorisator jika status_bayar !== 'sudah_bayar' || !approve_bayar . - UI & formatting rupiah - Perbaiki fungsi calculateTotal() pada form-penilai.blade.php agar parsing angka mendukung pemisah ribuan titik dan desimal koma, serta formatting konsisten dengan id-ID . - Aktifkan kembali fallback tampilan status utama di penilai/index.blade.php . - Tambahkan blok “Catatan yang Perlu Diperhatikan” pada print-out-sederhana.blade.php , mendukung input string/array dan memformat poin dengan awalan “- ”. Perubahan berkas (ringkas): - app/Http/Controllers/DebitureController.php : tambah peran admin pada pengecualian filter cabang. - app/Http/Controllers/PembayaranController.php : set status = 'proses-laporan' dalam proses terkait pembayaran. - app/Http/Controllers/PenilaiController.php : longgarkan blokir saat proses-laporan (redirect/JSON error dikomentari). - app/Http/Controllers/PenilaianController.php : gunakan permohonan->penilai->lpj untuk menghitung NPW. - app/Http/Controllers/PermohonanController.php : - set status = 'preregister' untuk user admin saat create, - tambah peran admin pada pengecualian filter cabang, - ubah pencarian “Bukti Bayar” ke dokumenjaminan dan gunakan dokumen_jaminan (JSON). - app/Http/Controllers/SpkController.php : set status = 'registrasi-final' pada Permohonan dan PenawaranTender setelah generate SPK. - app/Http/Requests/PermohonanRequest.php : hilangkan set default branch_id . - module.json : tambahkan admin pada beberapa daftar roles . - resources/views/component/form-penilai.blade.php : dukungan parsing/formatting rupiah dengan pemisah lokal. - resources/views/debitur/components/debitur.blade.php : perluas akses cabang untuk admin di form Debitur. - resources/views/debitur/index.blade.php : izinkan admin membuat Debitur. - resources/views/pembayaran/approval.blade.php : perbaiki render nominal dan visibilitas tombol otorisator. - resources/views/penilai/components/print-out-sederhana.blade.php : tambah bagian “Catatan yang Perlu Diperhatikan”. - resources/views/penilai/index.blade.php : gunakan data.status sebagai fallback tampilan status. - resources/views/penilaian/otorisator/show.blade.php : konsisten gunakan permohonan->penilai->lpj . - resources/views/permohonan/form.blade.php : penataan ulang kelas Tailwind dan penambahan field Cabang untuk administrator / admin .
347 lines
16 KiB
PHP
347 lines
16 KiB
PHP
<form action="{{ isset($debitur->id) ? route('debitur.update', $debitur->id) : route('debitur.store') }}" method="POST" id="debitur-form" class="grid gap-5">
|
|
@if(isset($debitur->id))
|
|
<input type="hidden" name="id" value="{{ $debitur->id }}">
|
|
@method('PUT')
|
|
@endif
|
|
@csrf
|
|
<div class="flex flex-wrap gap-2.5 items-baseline lg:flex-nowrap">
|
|
<label class="gap-1 form-label max-w-56">
|
|
Cabang
|
|
<span class="text-danger">*</span>
|
|
</label>
|
|
<div class="flex flex-wrap items-baseline w-full">
|
|
@if(auth()->user()->hasRole('administrator','admin'))
|
|
<select class="input tomselect w-full @error('branch_id') border-danger bg-danger-light @enderror" name="branch_id" id="branch_id">
|
|
<option value="">Pilih Cabang</option>
|
|
@foreach($branches as $branch)
|
|
<option value="{{ $branch->id }}" {{ (isset($debitur) && $branch->id == $debitur->branch_id) || (old('branch_id') == $branch->id) ? 'selected' : '' }}>
|
|
{{ $branch->name }}
|
|
</option>
|
|
@endforeach
|
|
</select>
|
|
@else
|
|
<input type="hidden" name="branch_id" value="{{ auth()->user()->branch_id }}">
|
|
<input type="text" class="w-full input" value="{{ auth()->user()->branch->name }}" readonly>
|
|
@endif
|
|
@error('branch_id')
|
|
<em class="text-sm alert text-danger">{{ $message }}</em>
|
|
@enderror
|
|
</div>
|
|
</div>
|
|
<div class="flex flex-wrap gap-2.5 items-baseline lg:flex-nowrap">
|
|
<label class="gap-1 form-label max-w-56">
|
|
CIF
|
|
<span class="text-danger">
|
|
*
|
|
</span>
|
|
</label>
|
|
<div class="flex flex-wrap items-baseline w-full">
|
|
<input class="input @error('cif') border-danger bg-danger-light @enderror" type="number" id="cif" name="cif" value="{{ $debitur->cif ?? '0000000000' }}">
|
|
@error('cif')
|
|
<em class="text-sm alert text-danger">{{ $message }}</em>
|
|
@enderror
|
|
</div>
|
|
</div>
|
|
<div class="flex flex-wrap gap-2.5 items-baseline lg:flex-nowrap">
|
|
<label class="form-label max-w-56">
|
|
Nomor Rekening
|
|
</label>
|
|
<div class="flex flex-wrap items-baseline w-full">
|
|
<input class="input @error('nomor_rekening') border-danger bg-danger-light @enderror" type="number" name="nomor_rekening" value="{{ $debitur->nomor_rekening ?? '' }}">
|
|
@error('nomor_rekening')
|
|
<em class="text-sm alert text-danger">{{ $message }}</em>
|
|
@enderror
|
|
</div>
|
|
</div>
|
|
<div class="flex flex-wrap gap-2.5 items-baseline lg:flex-nowrap">
|
|
<label class="gap-1 form-label max-w-56">
|
|
Nama Debitur
|
|
<span class="text-danger">
|
|
*
|
|
</span>
|
|
</label>
|
|
<div class="flex flex-wrap items-baseline w-full">
|
|
<input required class="input @error('name') border-danger bg-danger-light @enderror" type="text" name="name" value="{{ $debitur->name ?? '' }}">
|
|
@error('name')
|
|
<em class="text-sm alert text-danger">{{ $message }}</em>
|
|
@enderror
|
|
</div>
|
|
</div>
|
|
<div class="flex flex-wrap gap-2.5 items-baseline lg:flex-nowrap">
|
|
<label class="form-label max-w-56">
|
|
NPWP
|
|
</label>
|
|
<div class="flex flex-wrap items-baseline w-full">
|
|
<input class="input @error('npwp') border-danger bg-danger-light @enderror" type="number" name="npwp" value="{{ $debitur->npwp ?? '' }}">
|
|
@error('npwp')
|
|
<em class="text-sm alert text-danger">{{ $message }}</em>
|
|
@enderror
|
|
</div>
|
|
</div>
|
|
<div class="flex flex-wrap gap-2.5 items-baseline lg:flex-nowrap">
|
|
<label class="form-label max-w-56">
|
|
Email
|
|
</label>
|
|
<div class="flex flex-wrap items-baseline w-full">
|
|
<input class="input @error('email') border-danger bg-danger-light @enderror" type="email" name="email" value="{{ $debitur->email ?? '' }}">
|
|
@error('email')
|
|
<em class="text-sm alert text-danger">{{ $message }}</em>
|
|
@enderror
|
|
</div>
|
|
</div>
|
|
<div class="flex flex-wrap gap-2.5 items-baseline lg:flex-nowrap">
|
|
<label class="form-label max-w-56">
|
|
No Handphone
|
|
</label>
|
|
<div class="flex flex-wrap items-baseline w-full">
|
|
<input class="input @error('phone') border-danger bg-danger-light @enderror" type="number" name="phone" value="{{ $debitur->phone ?? '' }}">
|
|
@error('phone')
|
|
<em class="text-sm alert text-danger">{{ $message }}</em>
|
|
@enderror
|
|
</div>
|
|
</div>
|
|
<div class="flex flex-wrap gap-2.5 items-baseline lg:flex-nowrap">
|
|
<label class="gap-1 form-label max-w-56">
|
|
Alamat
|
|
<span class="text-danger">
|
|
*
|
|
</span>
|
|
</label>
|
|
<div class="flex flex-wrap items-baseline w-full">
|
|
<div class="flex flex-col gap-2 w-full lg:flex-row">
|
|
<div class="flex flex-wrap items-baseline w-full">
|
|
<select required id="province_code" name="province_code" class="select w-full @error('province_code') border-danger bg-danger-light @enderror">
|
|
<option value="">Select Province</option>
|
|
@foreach($provinces as $province)
|
|
@if(isset($debitur))
|
|
<option value="{{ $province->code }}" {{ isset($debitur->province_code) && $debitur->province_code == $province->code?'selected' : '' }}>
|
|
{{ $province->name }}
|
|
</option>
|
|
@else
|
|
<option value="{{ $province->code }}">
|
|
{{ $province->name }}
|
|
</option>
|
|
@endif
|
|
@endforeach
|
|
</select>
|
|
@error('province_code')
|
|
<em class="text-sm alert text-danger">{{ $message }}</em>
|
|
@enderror
|
|
</div>
|
|
<div class="flex flex-wrap items-baseline w-full">
|
|
<select required id="city_code" name="city_code" class="select w-full @error('city_code') border-danger bg-danger-light @enderror">
|
|
<option value="">Select City</option>
|
|
@if(isset($cities))
|
|
@foreach($cities as $city)
|
|
@if(isset($debitur))
|
|
<option value="{{ $city->code }}" {{ isset($debitur->city_code) && $debitur->city_code == $city->code?'selected' : '' }}>
|
|
{{ $city->name }}
|
|
</option>
|
|
@else
|
|
<option value="{{ $city->code }}">
|
|
{{ $city->name }}
|
|
</option>
|
|
@endif
|
|
@endforeach
|
|
|
|
@endif
|
|
</select>
|
|
@error('city_code')
|
|
<em class="text-sm alert text-danger">{{ $message }}</em>
|
|
@enderror
|
|
</div>
|
|
</div>
|
|
<div class="flex flex-col gap-2 mt-2 w-full lg:flex-row lg:mt-5">
|
|
<div class="flex flex-wrap items-baseline w-full">
|
|
<select required id="district_code" name="district_code" class="select w-full @error('district_code') border-danger bg-danger-light @enderror">
|
|
<option value="">Select District</option>
|
|
@if(isset($districts))
|
|
@foreach($districts as $district)
|
|
@if(isset($debitur))
|
|
<option value="{{ $district->code }}" {{ isset($debitur->district_code) && $debitur->district_code == $district->code?'selected' : '' }}>
|
|
{{ $district->name }}
|
|
</option>
|
|
@else
|
|
<option value="{{ $district->code }}">
|
|
{{ $district->name }}
|
|
</option>
|
|
@endif
|
|
@endforeach
|
|
|
|
@endif
|
|
</select>
|
|
@error('district_code')
|
|
<em class="text-sm alert text-danger">{{ $message }}</em>
|
|
@enderror
|
|
</div>
|
|
<div class="flex flex-wrap items-baseline w-full">
|
|
<select required id="village_code" name="village_code" class="select w-full @error('district_code') border-danger bg-danger-light @enderror">
|
|
<option value="">Select Village</option>
|
|
@if(isset($villages))
|
|
@foreach($villages as $village)
|
|
@if(isset($debitur))
|
|
<option value="{{ $village->code }}" {{ isset($debitur->village_code) && $debitur->village_code == $village->code?'selected' : '' }}>
|
|
{{ $village->name }}
|
|
</option>
|
|
@else
|
|
<option value="{{ $village->code }}">
|
|
{{ $village->name }}
|
|
</option>
|
|
@endif
|
|
@endforeach
|
|
|
|
@endif
|
|
</select>
|
|
@error('district_code')
|
|
<em class="text-sm alert text-danger">{{ $message }}</em>
|
|
@enderror
|
|
</div>
|
|
<div class="flex flex-wrap items-baseline w-full">
|
|
<input required class="input @error('postal_code') border-danger bg-danger-light @enderror" type="number" id="postal_code" name="postal_code" value="{{ $debitur->postal_code ?? '' }}" placeholder="Postal Code">
|
|
@error('postal_code')
|
|
<em class="text-sm alert text-danger">{{ $message }}</em>
|
|
@enderror
|
|
</div>
|
|
</div>
|
|
<div class="flex flex-row mt-2 w-full lg:mt-5">
|
|
<textarea required class="textarea @error('address') border-danger bg-danger-light @enderror" rows="3" id="address" name="address" placeholder="Alamat Lengkap">{{ $debitur->address ?? '' }}</textarea>
|
|
@error('address')
|
|
<em class="text-sm alert text-danger">{{ $message }}</em>
|
|
@enderror
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="flex justify-end">
|
|
<button type="submit" class="btn btn-primary" id="submit">
|
|
Save
|
|
</button>
|
|
</div>
|
|
</form>
|
|
@push('scripts')
|
|
<script>
|
|
document.addEventListener('DOMContentLoaded', function () {
|
|
const form = document.getElementById('debitur-form');
|
|
const nameInput = form.querySelector('input[name="name"]');
|
|
const provinceSelect = form.querySelector('#province_code');
|
|
const citySelect = form.querySelector('#city_code');
|
|
const districtSelect = form.querySelector('#district_code');
|
|
const villageSelect = form.querySelector('#village_code');
|
|
const postalCodeInput = form.querySelector('#postal_code');
|
|
const addressTextarea = form.querySelector('#address');
|
|
const branchSelect = document.getElementById('branch_id');
|
|
const cifInput = document.getElementById('cif');
|
|
const submitButton = document.getElementById('submit');
|
|
|
|
function validateField(field, errorMessage) {
|
|
const value = field.value.trim();
|
|
if (value.length === 0) {
|
|
field.classList.add('border-danger', 'bg-danger-light');
|
|
const existingError = field.parentElement.querySelector('.alert.text-danger');
|
|
if (!existingError) {
|
|
const em = document.createElement('em');
|
|
em.className = 'alert text-danger text-sm';
|
|
em.textContent = errorMessage;
|
|
field.parentElement.appendChild(em);
|
|
}
|
|
return false;
|
|
} else {
|
|
field.classList.remove('border-danger', 'bg-danger-light');
|
|
const existingError = field.parentElement.querySelector('.alert.text-danger');
|
|
if (existingError) {
|
|
existingError.remove();
|
|
}
|
|
return true;
|
|
}
|
|
}
|
|
|
|
function validateBranch() {
|
|
return validateField(branchSelect, 'Cabang is required');
|
|
}
|
|
|
|
function validateCIF() {
|
|
return validateField(cifInput, 'CIF is required');
|
|
}
|
|
|
|
function validateName() {
|
|
return validateField(nameInput, 'Nama Debitur is required');
|
|
}
|
|
|
|
function validateProvince() {
|
|
return validateField(provinceSelect, 'Province is required');
|
|
}
|
|
|
|
function validateCity() {
|
|
return validateField(citySelect, 'City is required');
|
|
}
|
|
|
|
function validateDistrict() {
|
|
return validateField(districtSelect, 'District is required');
|
|
}
|
|
|
|
function validateVillage() {
|
|
return validateField(villageSelect, 'Village is required');
|
|
}
|
|
|
|
function validatePostalCode() {
|
|
return validateField(postalCodeInput, 'Postal Code is required');
|
|
}
|
|
|
|
function validateAddress() {
|
|
return validateField(addressTextarea, 'Address is required');
|
|
}
|
|
|
|
nameInput.addEventListener('blur', validateName);
|
|
nameInput.addEventListener('input', validateName);
|
|
provinceSelect.addEventListener('change', validateProvince);
|
|
citySelect.addEventListener('change', validateCity);
|
|
districtSelect.addEventListener('change', validateDistrict);
|
|
villageSelect.addEventListener('change', validateVillage);
|
|
postalCodeInput.addEventListener('blur', validatePostalCode);
|
|
postalCodeInput.addEventListener('input', validatePostalCode);
|
|
addressTextarea.addEventListener('blur', validateAddress);
|
|
addressTextarea.addEventListener('input', validateAddress);
|
|
branchSelect.addEventListener('change', validateVillage);
|
|
cifInput.addEventListener('blur', validateCIF);
|
|
cifInput.addEventListener('input', validateName);
|
|
|
|
function validateAllFields() {
|
|
const isValid =
|
|
validateBranch() &&
|
|
validateCIF() &&
|
|
validateName() &&
|
|
validateProvince() &&
|
|
validateCity() &&
|
|
validateDistrict() &&
|
|
validateVillage() &&
|
|
validatePostalCode() &&
|
|
validateAddress();
|
|
|
|
return isValid;
|
|
}
|
|
|
|
form.addEventListener('submit', function (event) {
|
|
const isValid =
|
|
validateBranch() &&
|
|
validateCIF() &&
|
|
validateName() &&
|
|
validateProvince() &&
|
|
validateCity() &&
|
|
validateDistrict() &&
|
|
validateVillage() &&
|
|
validatePostalCode() &&
|
|
validateAddress();
|
|
|
|
if (!isValid) {
|
|
event.preventDefault();
|
|
}
|
|
});
|
|
|
|
submitButton.addEventListener('click', function (event) {
|
|
if (!validateAllFields()) {
|
|
event.preventDefault();
|
|
}
|
|
});
|
|
});
|
|
</script>
|
|
@endpush
|