Merge branch 'fix/save-penilai' into feature/senior-officer

This commit is contained in:
majid
2025-03-18 14:34:01 +07:00
16 changed files with 1819 additions and 45 deletions

View File

@@ -0,0 +1,128 @@
<?php
namespace Modules\Lpj\Exports;
use Maatwebsite\Excel\Concerns\FromQuery;
use Maatwebsite\Excel\Concerns\WithHeadings;
use Maatwebsite\Excel\Concerns\WithMapping;
use Maatwebsite\Excel\Concerns\ShouldAutoSize;
use Illuminate\Database\Eloquent\Builder;
use PhpOffice\PhpSpreadsheet\Style\NumberFormat;
use Modules\Lpj\Models\Debiture;
use Modules\Lpj\Models\Permohonan;
class LaporanPenilaiJaminanExport implements FromQuery, WithHeadings, WithMapping, ShouldAutoSize
{
protected $tanggalAwal;
protected $tanggalAkhir;
protected $status;
protected $selectedIds;
public function __construct($tanggalAwal = null, $tanggalAkhir = null, $status = null, $selectedIds = null)
{
$this->tanggalAwal = $tanggalAwal;
$this->tanggalAkhir = $tanggalAkhir;
$this->status = $status;
$this->selectedIds = $selectedIds;
}
public function query()
{
$query = Permohonan::query()
->with(['user', 'debiture', 'branch', 'tujuanPenilaian', 'penilaian', 'dokumenjaminan.jenisJaminan','nilaiPlafond', 'penilai']);
// Filter by date range if provided
if ($this->tanggalAwal && $this->tanggalAkhir) {
$query->whereBetween('tanggal_permohonan', [$this->tanggalAwal, $this->tanggalAkhir]);
}
$query->where('status', 'done');
// Filter by status if provided
if ($this->status) {
$types = is_array($this->status) ? $this->status : [$this->status];
$query->whereHas('penilai', function (Builder $query) use ($types) {
$query->whereIn('type_penilai', $types);
});
}
// Filter by selected IDs if provided
if ($this->selectedIds) {
$selectedIds = is_array($this->selectedIds) ? $this->selectedIds : explode(',', $this->selectedIds);
$query->whereIn('id', $selectedIds);
}
return $query;
}
public function map($row): array
{
$fieldPenilai = ['sederhana', 'standar', 'resume', 'memo', 'rap', 'call-report'];
$penilaiCek = null;
// Find the first available field in the array
foreach ($fieldPenilai as $value) {
if (!empty($row->penilai->$value)) {
$penilaiCek = $row->penilai->$value;
break;
}
}
$decodePenilai = json_decode($penilaiCek, true) ?? [];
return [
$row->id,
$row->nomor_registrasi,
$row->user->name,
$row->branch->name,
$row->tujuanPenilaian->name,
$row->debiture->name,
$row->penilai->type_penilai ?? '-',
'-',
$decodePenilai['luas_tanah'] ?? 0,
$decodePenilai['luas_bangunan'] ?? 0,
$decodePenilai['nilai_tanah_1'] ?? 0,
$decodePenilai['nilai_bangunan_1'] ?? 0,
$decodePenilai['total_nilai_pasar_wajar'] ?? 0,
$decodePenilai['likuidasi'] ?? 0,
$row->authorized_at,
$row->authorized_status ?? '-',
$row->authorized_by ?? '-',
$row->created_at,
];
}
public function headings(): array
{
return [
'ID',
'Nomor Registrasi',
'User Pemohon',
'Branch Pemohon',
'Tujuan Penilaian',
'Debitur',
'Jenis Laporan',
'Lokasi Jaminan',
'Luas Tanah',
'Luas Bangunan',
'Harga Tanah',
'Harga Bangunan',
'Nilai Pasar Wajar',
'Likuidasi',
'Tanggal Laporan',
'Nama Penilai',
'Nik Penilai',
];
}
public function columnFormats(): array
{
return [
'A' => NumberFormat::FORMAT_NUMBER,
'C' => NumberFormat::FORMAT_DATE_DATETIME,
'K' => NumberFormat::FORMAT_DATE_DATETIME,
'N' => NumberFormat::FORMAT_DATE_DATETIME
];
}
}

View File

@@ -41,7 +41,7 @@ function formatRupiah($number,$decimals = 0)
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->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

View File

@@ -0,0 +1,173 @@
<?php
namespace Modules\Lpj\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Routing\Controller;
use Modules\Lpj\Http\Requests\BankDataRequest;
use Modules\Lpj\Models\BankData;
use Modules\Lpj\Models\JenisJaminan;
use Modules\Lpj\Services\BankDataService;
use Modules\Location\Models\Province;
class BankDataController extends Controller
{
protected $bankDataService;
protected $user;
public function __construct(BankDataService $bankDataService)
{
$this->bankDataService = $bankDataService;
}
public function index(Request $request)
{
$provinces = Province::all();
$jenisJaminan = JenisJaminan::all();
return view('lpj::bank-data.index', compact('provinces', 'jenisJaminan' ));
}
public function create()
{
return view('lpj::bank-data.create');
}
public function store(BankDataRequest $request)
{
$data = $request->validated();
$bankData = $this->bankDataService->createBankData($data);
return redirect()->route('lpj.bank-data.show', $bankData->id)->with('success', 'Bank data created successfully.');
}
public function show($id)
{
$bankData = $this->bankDataService->findBankData($id);
return view('lpj::bank-data.show', compact('bankData'));
}
public function edit($id)
{
$bankData = $this->bankDataService->findBankData($id);
return view('lpj::bank-data.edit', compact('bankData'));
}
public function update(BankDataRequest $request, $id)
{
$data = $request->validated();
$bankData = $this->bankDataService->updateBankData($id, $data);
return redirect()->route('lpj.bank-data.show', $bankData->id)->with('success', 'Bank data updated successfully.');
}
public function destroy($id)
{
$this->bankDataService->deleteBankData($id);
return redirect()->route('lpj.bank-data.index')->with('success', 'Bank data deleted successfully.');
}
public function dataForDatatables(Request $request)
{
if (is_null($this->user) || !$this->user->can('bank-data.view')) {
//abort(403, 'Sorry! You are not allowed to view bank data.');
}
// Retrieve data from the database
$query = BankData::query();
// Apply search filter if provided
if ($request->has('search') && !empty($request->get('search'))) {
$search = $request->get('search');
$search = json_decode($search, true);
if (is_array($search)) {
if ($search['province_code']) {
$query->ofProvince($search['province_code']);
}
if ($search['city_code']) {
$query->ofCity($search['city_code']);
}
if ($search['district_code']) {
$query->ofDistrict($search['district_code']);
}
if ($search['village_code']) {
$query->ofVillage($search['village_code']);
}
if ($search['jenis_asset']) {
$query->ofAssetType($search['jenis_asset']);
}
if ($search['start_date'] && $search['end_date']) {
$query->betweenDates($request->start_date, $search['end_date']);
}
} else{
$search = $request->get('search');
$query->where(function ($q) use ($search) {
$q->where('jenis_aset', 'LIKE', '%' . $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->get();
// Format the data as needed
$formattedData = $data->map(function ($item) {
return [
'id' => $item->id,
'jenis_aset' => $item->jenis_aset,
'tanggal' => $item->tanggal->format('d-m-Y'),
'tahun' => $item->tahun,
'luas_tanah' => $item->luas_tanah,
'luas_bangunan' => $item->luas_bangunan,
'harga' => $item->harga,
'nilai_pasar' => $item->nilai_pasar,
'location' => $item->kordinat_lat . ', ' . $item->kordinat_lng,
'address' => formatAlamat($item)
// Add more fields as needed
];
});
// 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' => $formattedData,
]);
}
}

View File

@@ -21,6 +21,7 @@
{
$permohonan = Permohonan::with(['documents.jenisJaminan','penilaian._user_penilai','penilai','documents.detail.jenisLegalitasJaminan'])->where(['status'=>'done'])->get();
foreach($permohonan as $_permohonan){
$npw = 0;
if(isset($_permohonan->penilai->lpj)){
$npw = json_decode($_permohonan->penilai->lpj, true);
$npw = $npw['total_nilai_pasar_wajar'] ?? 0;
@@ -38,7 +39,9 @@
'nilai_pasar_wajar' => str_replace('.', '', $npw),
'bukti_kepemilikan' => $_permohonan->documents->flatMap(function ($document) {
return $document->detail->map(function ($detail) {
return $detail->jenisLegalitasJaminan->name ?? null;
return (!empty($detail->dokumen_nomor) && is_array($detail->dokumen_nomor))
? ($detail->jenisLegalitasJaminan->name ?? '') . "\n" . implode(', ', $detail->dokumen_nomor)
: null;
});
})->filter()->unique()->implode(', '),
];

View File

@@ -0,0 +1,192 @@
<?php
namespace Modules\Lpj\Http\Controllers;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Modules\Lpj\Models\Permohonan;
use Modules\Lpj\Models\StatusPermohonan;
use Modules\Lpj\Exports\LaporanPenilaiJaminanExport;
use Maatwebsite\Excel\Facades\Excel;
class LaporanPenilaiJaminanController extends Controller
{
public $user;
/**
* Display a listing of the resource.
*/
public function index()
{
$status_permohonan = StatusPermohonan::all();
return view('lpj::laporan-penilai-jaminan.index', compact('status_permohonan'));
}
/**
* Show the form for creating a new resource.
*/
public function create()
{
return view('lpj::create');
}
/**
* Store a newly created resource in storage.
*/
public function store(Request $request)
{
//
}
/**
* Show the specified resource.
*/
public function show($id)
{
return view('lpj::laporan-penilai-jaminan.show');
}
/**
* Show the form for editing the specified resource.
*/
public function edit($id)
{
return view('lpj::edit');
}
/**
* Update the specified resource in storage.
*/
public function update(Request $request, $id)
{
//
}
/**
* Remove the specified resource from storage.
*/
public function destroy($id)
{
//
}
public function dataForDatatables(Request $request)
{
$user = auth()->user();
// Check permissions
if (is_null($this->user) || !$this->user->can('debitur.view')) {
// abort(403, 'Sorry! You are not allowed to view users.');
}
$userRole = $user->roles->pluck('name')->first();
$regionId = null;
// If user is senior-officer, get their regionId
if ($userRole === 'senior-officer') {
$userTeam = TeamsUsers::with('team')->firstWhere('user_id', $user->id);
$regionId = $userTeam?->team->regions_id;
}
// Retrieve data from the database
$query = Permohonan::query();
// Apply search filter if provided
if ($request->has('search') && !empty($request->get('search'))) {
$search = $request->get('search');
$query->where(function ($q) use ($search) {
$q->where('nomor_registrasi', 'LIKE', '%' . $search . '%')
->orWhere('tanggal_permohonan', 'LIKE', '%' . $search . '%')
->orWhereRelation('user', 'name', 'LIKE', '%' . $search . '%')
->orWhereRelation('debiture', 'name', 'LIKE', '%' . $search . '%')
->orWhereRelation('tujuanPenilaian', 'name', 'LIKE', '%' . $search . '%')
->orWhereRelation('branch', 'name', 'LIKE', '%' . $search . '%');
// Split search term by comma to allow multiple statuses
$statusKeywords = explode(',', $search);
foreach ($statusKeywords as $keyword) {
$q->orWhere('status', 'LIKE', '%' . trim($keyword) . '%');
}
});
}
$query->where('status', 'done');
// Default sorting if no sort provided
if ($request->has('sortOrder') && !empty($request->get('sortOrder'))) {
$order = $request->get('sortOrder');
$column = $request->get('sortField');
$query->orderBy($column, $order);
} else {
$query->orderBy('nomor_registrasi', 'asc');
}
// Get total count of records before pagination
$totalRecords = $query->count();
// Pagination
if ($request->has('page') && $request->has('size')) {
$page = (int) $request->get('page', 1);
$size = (int) $request->get('size', 10);
$offset = ($page - 1) * $size;
$query->skip($offset)->take($size);
}
// Get filtered count
$filteredRecords = $query->count();
$totalRecords = $query->count();
// Pagination
if ($request->has('page') && $request->has('size')) {
$page = (int) $request->get('page', 1);
$size = (int) $request->get('size', 10);
$offset = ($page - 1) * $size;
$query->skip($offset)->take($size);
}
// Get filtered count
$filteredRecords = $query->count();
// Get data with necessary relationships
$data = $query->with(['user', 'debiture', 'branch', 'tujuanPenilaian', 'penilaian', 'dokumenjaminan.jenisJaminan','nilaiPlafond', 'penilai'])->get();
// Calculate total pages
$pageCount = ceil($totalRecords / $request->get('size', 10));
// Calculate total pages
$pageCount = ceil($totalRecords / $request->get('size', 10));
return response()->json([
'draw' => $request->get('draw'),
'recordsTotal' => $totalRecords,
'recordsFiltered' => $filteredRecords,
'pageCount' => $pageCount,
'page' => $request->get('page', 1),
'totalCount' => $totalRecords,
'data' => $data,
]);
}
public function export(Request $request)
{
$tanggalAwal = $request->input('tanggal_awal');
$tanggalAkhir = $request->input('tanggal_akhir');
$status = $request->input('status');
$selectedIds = $request->input('selected_ids');
$filename = 'laporan_penilai_jaminan_' . date('YmdHis') . '.xlsx';
return Excel::download(
new LaporanPenilaiJaminanExport($tanggalAwal, $tanggalAkhir, $status, $selectedIds),
$filename
);
}
}

View File

@@ -0,0 +1,57 @@
<?php
namespace Modules\Lpj\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class BankDataRequest extends FormRequest
{
public function authorize()
{
return true; // Adjust this based on your authorization logic
}
public function rules()
{
return [
'address' => 'nullable|string|max:255',
'village_code' => 'nullable|string|max:20',
'district_code' => 'nullable|string|max:20',
'city_code' => 'nullable|string|max:20',
'province_code' => 'nullable|string|max:20',
'tahun' => 'nullable|integer',
'luas_tanah' => 'nullable|numeric',
'luas_bangunan' => 'nullable|numeric',
'tahun_bangunan' => 'nullable|integer',
'status_nara_sumber' => 'nullable|string|max:50',
'harga' => 'nullable|numeric',
'harga_diskon' => 'nullable|numeric',
'diskon' => 'nullable|numeric',
'total' => 'nullable|numeric',
'nama_nara_sumber' => 'nullable|string|max:100',
'peruntukan' => 'nullable|string|max:100',
'penawaran' => 'nullable|string|max:50',
'telepon' => 'nullable|string|max:20',
'hak_properti' => 'nullable|string|max:50',
'kordinat_lat' => 'nullable|numeric',
'kordinat_lng' => 'nullable|numeric',
'jenis_aset' => 'nullable|string|max:50',
'foto_objek' => 'nullable|image|max:2048',
'tanggal' => 'nullable|date',
'harga_penawaran' => 'nullable|numeric',
'nomor_laporan' => 'nullable|string|max:50',
'tgl_final_laporan' => 'nullable|date',
'nilai_pasar' => 'nullable|numeric',
'indikasi_nilai_likuidasi' => 'nullable|numeric',
'indikasi_nilai_pasar_tanah' => 'nullable|numeric',
'estimasi_harga_tanah' => 'nullable|numeric',
'estimasi_harga_bangunan' => 'nullable|numeric',
'indikasi_nilai_pasar_bangunan' => 'nullable|numeric',
'indikasi_nilai_pasar_sarana_pelengkap' => 'nullable|numeric',
'indikasi_nilai_pasar_mesin' => 'nullable|numeric',
'indikasi_nilai_pasar_kendaraan_alat_berat' => 'nullable|numeric',
'photos' => 'nullable|array',
'photos.*' => 'nullable|image|max:2048',
];
}
}

104
app/Models/BankData.php Normal file
View File

@@ -0,0 +1,104 @@
<?php
namespace Modules\Lpj\Models;
use Modules\Location\Models\City;
use Modules\Location\Models\District;
use Modules\Location\Models\Province;
use Modules\Location\Models\Village;
class BankData extends Base
{
protected $table = 'bank_data';
protected $guarded = ['id'];
protected $casts = [
'tahun' => 'integer',
'luas_tanah' => 'decimal:2',
'luas_bangunan' => 'decimal:2',
'tahun_bangunan' => 'integer',
'harga' => 'decimal:2',
'harga_diskon' => 'decimal:2',
'diskon' => 'decimal:2',
'total' => 'decimal:2',
'kordinat_lat' => 'decimal:8',
'kordinat_lng' => 'decimal:8',
'harga_penawaran' => 'decimal:2',
'tanggal' => 'date',
'tgl_final_laporan' => 'date',
'nilai_pasar' => 'decimal:2',
'indikasi_nilai_likuidasi' => 'decimal:2',
'indikasi_nilai_pasar_tanah' => 'decimal:2',
'estimasi_harga_tanah' => 'decimal:2',
'estimasi_harga_bangunan' => 'decimal:2',
'indikasi_nilai_pasar_bangunan' => 'decimal:2',
'indikasi_nilai_pasar_sarana_pelengkap' => 'decimal:2',
'indikasi_nilai_pasar_mesin' => 'decimal:2',
'indikasi_nilai_pasar_kendaraan_alat_berat' => 'decimal:2',
'photos' => 'array'
];
// Scope for filtering by asset type
public function scopeOfAssetType($query, $assetType)
{
return $query->where('jenis_aset', $assetType);
}
// Scope for filtering by village
public function scopeOfVillage($query, $villageCode)
{
return $query->where('village_code', $villageCode);
}
// Scope for filtering by district
public function scopeOfDistrict($query, $districtCode)
{
return $query->where('district_code', $districtCode);
}
// Scope for filtering by city
public function scopeOfCity($query, $cityCode)
{
return $query->where('city_code', $cityCode);
}
// Scope for filtering by province
public function scopeOfProvince($query, $provinceCode)
{
return $query->where('province_code', $provinceCode);
}
// Scope for filtering by date
public function scopeOfDate($query, $date)
{
return $query->whereDate('tanggal', $date);
}
// Scope for filtering by date range
public function scopeBetweenDates($query, $startDate, $endDate)
{
return $query->whereBetween('tanggal', [$startDate, $endDate]);
}
public function village()
{
return $this->belongsTo(Village::class, 'village_code', 'code');
}
public function district()
{
return $this->belongsTo(District::class, 'district_code', 'code');
}
public function city()
{
return $this->belongsTo(City::class, 'city_code', 'code');
}
public function province()
{
return $this->belongsTo(Province::class, 'province_code', 'code');
}
}

View File

@@ -4,6 +4,8 @@
use Illuminate\Support\Facades\Blade;
use Illuminate\Support\ServiceProvider;
use Modules\Lpj\Models\BankData;
use Modules\Lpj\Services\BankDataService;
class LpjServiceProvider extends ServiceProvider
{
@@ -118,6 +120,9 @@
{
$this->app->register(EventServiceProvider::class);
$this->app->register(RouteServiceProvider::class);
$this->app->bind(BankDataService::class, function ($app){
return new BankDataService($app->make(BankData::class));
});
}
/**

View File

@@ -0,0 +1,116 @@
<?php
namespace Modules\Lpj\Services;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Pagination\LengthAwarePaginator;
use Modules\Lpj\Models\BankData;
class BankDataService
{
protected $bankData;
public function __construct(BankData $bankData)
{
$this->bankData = $bankData;
}
/**
* Get all bank data with optional filtering and pagination
*
* @param array $filters
* @param int|null $perPage
*
* @return Collection|LengthAwarePaginator
*/
public function getAllBankData(array $filters = [], ?int $perPage = null)
{
$query = $this->bankData->newQuery();
// Apply filters
if (isset($filters['village_code'])) {
$query->ofVillage($filters['village_code']);
}
if (isset($filters['district_code'])) {
$query->ofDistrict($filters['district_code']);
}
if (isset($filters['city_code'])) {
$query->ofCity($filters['city_code']);
}
if (isset($filters['province_code'])) {
$query->ofProvince($filters['province_code']);
}
if (isset($filters['date'])) {
$query->ofDate($filters['date']);
}
if (isset($filters['start_date']) && isset($filters['end_date'])) {
$query->betweenDates($filters['start_date'], $filters['end_date']);
}
if (isset($filters['year'])) {
$query->ofYear($filters['year']);
}
if (isset($filters['asset_type'])) {
$query->ofAssetType($filters['asset_type']);
}
// Add more filters as needed
return $perPage ? $query->paginate($perPage) : $query->get();
}
/**
* Create a new bank data entry
*
* @param array $data
*
* @return BankData
*/
public function createBankData(array $data)
: BankData
{
return $this->bankData->create($data);
}
/**
* Update an existing bank data entry
*
* @param int $id
* @param array $data
*
* @return BankData
*/
public function updateBankData(int $id, array $data)
: BankData
{
$bankData = $this->bankData->findOrFail($id);
$bankData->update($data);
return $bankData;
}
/**
* Delete a bank data entry
*
* @param int $id
*
* @return bool
*/
public function deleteBankData(int $id)
: bool
{
$bankData = $this->bankData->findOrFail($id);
return $bankData->delete();
}
/**
* Find a bank data entry by ID
*
* @param int $id
*
* @return BankData|null
*/
public function findBankData(int $id)
: ?BankData
{
return $this->bankData->find($id);
}
}

View File

@@ -0,0 +1,69 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('bank_data', function (Blueprint $table) {
$table->id();
$table->text('address')->nullable();
$table->string('village_code')->nullable();
$table->string('district_code')->nullable();
$table->string('city_code')->nullable();
$table->string('province_code')->nullable();
$table->integer('tahun')->nullable();
$table->decimal('luas_tanah', 15, 2)->nullable();
$table->decimal('luas_bangunan', 15, 2)->nullable();
$table->integer('tahun_bangunan')->nullable();
$table->string('status_nara_sumber')->nullable();
$table->decimal('harga', 15, 2)->nullable();
$table->decimal('harga_diskon', 15, 2)->nullable();
$table->decimal('diskon', 5, 2)->nullable();
$table->decimal('total', 15, 2)->nullable();
$table->string('nama_nara_sumber')->nullable();
$table->string('peruntukan')->nullable();
$table->string('penawaran')->nullable();
$table->string('telepon')->nullable();
$table->string('hak_properti')->nullable();
$table->decimal('kordinat_lat', 10, 8)->nullable();
$table->decimal('kordinat_lng', 11, 8)->nullable();
$table->string('jenis_aset')->nullable();
$table->string('foto_objek')->nullable();
$table->date('tanggal')->nullable();
$table->decimal('harga_penawaran', 15, 2)->nullable();
$table->string('nomor_laporan')->nullable();
$table->date('tgl_final_laporan')->nullable();
$table->decimal('nilai_pasar', 15, 2)->nullable();
$table->decimal('indikasi_nilai_likuidasi', 15, 2)->nullable();
$table->decimal('indikasi_nilai_pasar_tanah', 15, 2)->nullable();
$table->decimal('estimasi_harga_tanah', 15, 2)->nullable();
$table->decimal('estimasi_harga_bangunan', 15, 2)->nullable();
$table->decimal('indikasi_nilai_pasar_bangunan', 15, 2)->nullable();
$table->decimal('indikasi_nilai_pasar_sarana_pelengkap', 15, 2)->nullable();
$table->decimal('indikasi_nilai_pasar_mesin', 15, 2)->nullable();
$table->decimal('indikasi_nilai_pasar_kendaraan_alat_berat', 15, 2)->nullable();
$table->json('photos')->nullable();
$table->timestamps();
$table->softDeletes();
$table->unsignedBigInteger('created_by')->nullable();
$table->unsignedBigInteger('updated_by')->nullable();
$table->unsignedBigInteger('deleted_by')->nullable();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('bank_data');
}
};

View File

@@ -109,6 +109,17 @@
}
],
"main": [
{
"title": "Bank Data",
"path": "bank-data",
"icon": "ki-filled ki-questionnaire-tablet text-lg text-primary",
"classes": "",
"attributes": [],
"permission": "",
"roles": [
"administrator"
]
},
{
"title": "Permohonan",
"path": "permohonan",
@@ -366,6 +377,23 @@
"EO Appraisal",
"senior-officer"
]
},
{
"title": "Laporan Penilai Jaminan",
"path": "laporan-penilai-jaminan",
"icon": "ki-filled ki-filter-tablet text-lg text-primary",
"classes": "",
"attributes": [],
"permission": "",
"roles": [
"administrator",
"pemohon-ao",
"pemohon-eo",
"admin",
"DD Appraisal",
"EO Appraisal",
"senior-officer"
]
}
],
"master": [

View File

@@ -0,0 +1,469 @@
@extends('layouts.main')
@section('breadcrumbs')
{{ Breadcrumbs::render('bank-data') }}
@endsection
@section('content')
<div class="grid grid-cols-1 lg:grid-cols-4 gap-5 lg:gap-7.5 mb-10">
<div class="col-span-1">
<div class="card border border-agi-100 card-grid min-w-full">
<div class="card-header bg-agi-50 py-5 flex-wrap">
<h3 class="card-title">
Filter
</h3>
</div>
<div class="card-body px-5">
<form id="filter-form">
<div class="grid gap-4 w-full p-5">
<div>
<label for="jenis_asset" class="block text-sm font-medium text-gray-700">Jenis Asset</label>
<select id="jenis_asset" name="jenis_asset" class="select tomselect w-full @error('jenis_asset') border-danger bg-danger-light @enderror">
<option value="">Select Asset Type</option>
@foreach($jenisJaminan as $jenis)
<option value="{{ $jenis->name }}">{{ $jenis->name }}</option>
@endforeach
</select>
</div>
<div>
<label for="province_code" class="block text-sm font-medium text-gray-700">Province</label>
<select 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)
<option value="{{ $province->code }}">{{ $province->name }}</option>
@endforeach
<!-- Add province options here -->
</select>
</div>
<div>
<label for="city_code" class="block text-sm font-medium text-gray-700">City</label>
<select id="city_code" name="city_code" class="select w-full @error('city_code') border-danger bg-danger-light @enderror">
<option value="">Select City</option>
<!-- Add city options here -->
</select>
</div>
<div>
<label for="district_code" class="block text-sm font-medium text-gray-700">District</label>
<select id="district_code" name="district_code" class="select w-full @error('district_code') border-danger bg-danger-light @enderror">
<option value="">Select District</option>
<!-- Add district options here -->
</select>
</div>
<div>
<label for="village_code" class="block text-sm font-medium text-gray-700">Village</label>
<select id="village_code" name="village_code" class="select w-full @error('village_code') border-danger bg-danger-light @enderror">
<option value="">Select Village</option>
<!-- Add village options here -->
</select>
</div>
<div>
<label for="start_date" class="block text-sm font-medium text-gray-700">Start Date</label>
<input type="date" id="start_date" name="start_date" class="mt-1 block w-full py-2 px-3 border border-gray-300 bg-white rounded-md shadow-sm focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm">
</div>
<div>
<label for="end_date" class="block text-sm font-medium text-gray-700">End Date</label>
<input type="date" id="end_date" name="end_date" class="mt-1 block w-full py-2 px-3 border border-gray-300 bg-white rounded-md shadow-sm focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm">
</div>
<div>
<button type="submit" class="w-full inline-flex justify-center py-2 px-4 border border-transparent shadow-sm text-sm font-medium rounded-md text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500">
Apply Filters
</button>
</div>
</div>
</form>
</div>
</div>
</div>
<div class="col-span-3">
<div class="card border border-agi-100 card-grid min-w-full">
<div class="card-header bg-agi-50 py-5 flex-wrap">
<h3 class="card-title">
Maps
</h3>
</div>
<div class="card-body px-5">
<div id="map" style="height: 700px; width: 100%;"></div>
</div>
</div>
</div>
</div>
<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="bank-data-table" data-api-url="{{ route('bank-data.datatables') }}">
<div class="card-header bg-agi-50 py-5 flex-wrap">
<h3 class="card-title">
Daftar Bank Data
</h3>
<div class="flex flex-wrap gap-2 lg:gap-5">
<div class="flex">
<label class="input input-sm"> <i class="ki-filled ki-magnifier"> </i>
<input placeholder="Search Bank Data" 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="#"> 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="jenis_aset">
<span class="sort"> <span class="sort-label"> Jenis Aset </span>
<span class="sort-icon"> </span> </span>
</th>
<th class="min-w-[150px]" data-datatable-column="tanggal">
<span class="sort"> <span class="sort-label"> Tanggal </span>
<span class="sort-icon"> </span> </span>
</th>
<th class="min-w-[150px]" data-datatable-column="tahun">
<span class="sort"> <span class="sort-label"> Tahun </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="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="harga">
<span class="sort"> <span class="sort-label"> Harga </span>
<span class="sort-icon"> </span> </span>
</th>
<th class="min-w-[150px]" data-datatable-column="nilai_pasar">
<span class="sort"> <span class="sort-label"> Nilai Pasar </span>
<span class="sort-icon"> </span> </span>
</th>
<th class="min-w-[150px]" data-datatable-column="location">
<span class="sort"> <span class="sort-label"> Location </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 src="https://maps.googleapis.com/maps/api/js?key=AIzaSyDQTNRxyr0w7kXHsO2hmarDTa9-1LyLmS8&callback=initMap" async defer></script>
<script>
let map;
let markers = [];
let infoWindows = [];
let dataTable;
function initMap() {
map = new google.maps.Map(document.getElementById('map'), {
center: {lat: -6.200000, lng: 106.816666}, // Jakarta coordinates
zoom: 10
});
}
function updateMapMarkers(data) {
// Clear existing markers
markers.forEach(marker => marker.setMap(null));
infoWindows.forEach(infoWindow => infoWindow.close());
markers = [];
infoWindows = [];
// Add new markers
data.forEach(item => {
if (item.location) {
let lat, lng;
// Check if item.location is a string containing comma-separated coordinates
if (typeof item.location === 'string' && item.location.includes(',')) {
[lat, lng] = item.location.split(',').map(coord => parseFloat(coord.trim()));
}
// Check if item.location is an object with lat and lng properties
else if (typeof item.location === 'object' && item.location.lat && item.location.lng) {
lat = parseFloat(item.location.lat);
lng = parseFloat(item.location.lng);
}
// Check if item.location is an array with two elements
else if (Array.isArray(item.location) && item.location.length === 2) {
[lat, lng] = item.location.map(coord => parseFloat(coord));
}
if (lat && lng) {
const marker = new google.maps.Marker({
position: {lat: lat, lng: lng},
map: map,
title: item.jenis_aset
});
// Create info window content
const contentString = `
<div id='content' style='width: 500px; max-width: 100%;'>
<div id='siteNotice'></div>
<h2 class='card-title mb-5'>
${item.jenis_aset}
</h2>
<div class="grid gap-3">
<div class='flex items-center justify-between flex-wrap gap-1.5'>
<div class='flex items-center gap-1.5'>
<span class='text-sm font-normal text-gray-900'>
Tanggal Penilaian
</span>
</div>
<div class='flex items-center text-sm font-medium text-gray-800 gap-6'>
<span class='lg:text-right'>
${window.formatTanggalIndonesia(item.tanggal)}
</span>
</div>
</div>
<div class="border-t border-gray-300 border-dashed"></div>
<div class='flex items-center justify-between flex-wrap gap-1.5'>
<div class='flex items-center gap-1.5'>
<span class='text-sm font-normal text-gray-900'>
Tahun
</span>
</div>
<div class='flex items-center text-sm font-medium text-gray-800 gap-6'>
<span class='lg:text-right'>
${item.tahun}
</span>
</div>
</div>
<div class="border-t border-gray-300 border-dashed"></div>
<div class='flex items-center justify-between flex-wrap gap-1.5'>
<div class='flex items-center gap-1.5'>
<span class='text-sm font-normal text-gray-900'>
Luas Tanah
</span>
</div>
<div class='flex items-center text-sm font-medium text-gray-800 gap-6'>
<span class='lg:text-right'>
${item.luas_tanah} m²
</span>
</div>
</div>
<div class="border-t border-gray-300 border-dashed"></div>
<div class='flex items-center justify-between flex-wrap gap-1.5'>
<div class='flex items-center gap-1.5'>
<span class='text-sm font-normal text-gray-900'>
Luas Bangunan
</span>
</div>
<div class='flex items-center text-sm font-medium text-gray-800 gap-6'>
<span class='lg:text-right'>
${item.luas_bangunan} m²
</span>
</div>
</div>
<div class="border-t border-gray-300 border-dashed"></div>
<div class='flex items-center justify-between flex-wrap gap-1.5'>
<div class='flex items-center gap-1.5'>
<span class='text-sm font-normal text-gray-900'>
Harga
</span>
</div>
<div class='flex items-center text-sm font-medium text-gray-800 gap-6'>
<span class='lg:text-right'>
${window.formatRupiah(item.harga)}
</span>
</div>
</div>
<div class="border-t border-gray-300 border-dashed"></div>
<div class='flex items-center justify-between flex-wrap gap-1.5'>
<div class='flex items-center gap-1.5'>
<span class='text-sm font-normal text-gray-900'>
Nilai Pasar
</span>
</div>
<div class='flex items-center text-sm font-medium text-gray-800 gap-6'>
<span class='lg:text-right'>
${window.formatRupiah(item.nilai_pasar)}
</span>
</div>
</div>
<div class="border-t border-gray-300 border-dashed"></div>
<div class='flex items-start justify-between flex-wrap gap-1.5'>
<div class='flex items-start gap-1.5'>
<span class='text-sm font-normal text-gray-900'>
Location
</span>
</div>
<div class='flex items-center text-sm font-medium text-gray-800 gap-6'>
<span class='text-right whitespace-normal break-words'>
${item.address.split(' ').reduce((acc, word, index, array) => {
if (index > 0 && index % 7 === 0) {
acc += '<br>';
}
acc += word + (index < array.length - 1 ? ' ' : '');
return acc;
}, '')}
</span>
</div>
</div>
</div>
</div>
`;
// Create info window
const infoWindow = new google.maps.InfoWindow({
content: contentString
});
// Add click event to marker
marker.addListener('click', () => {
// Close all open info windows
infoWindows.forEach(window => window.close());
// Open this marker's info window
infoWindow.open(map, marker);
});
markers.push(marker);
infoWindows.push(infoWindow);
} else {
console.error('Invalid location format for item:', item);
}
}
});
// Adjust map bounds to fit all markers
if (markers.length > 0) {
const bounds = new google.maps.LatLngBounds();
markers.forEach(marker => bounds.extend(marker.getPosition()));
map.fitBounds(bounds);
}
}
function initializeDataTable() {
const element = document.querySelector('#bank-data-table');
const searchInput = document.getElementById('search');
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();
},
},
jenis_aset: {
title: 'Jenis Aset'
},
tanggal: {
title: 'Tanggal',
render: (item, data) => {
return data.tanggal;
},
},
tahun: {
title: 'Tahun',
render: (item, data) => {
return data.tahun;
},
},
luas_tanah: {
title: 'Luas Tanah',
render: (item, data) => {
return `${data.luas_tanah} m²`;
},
},
luas_bangunan: {
title: 'Luas Bangunan',
render: (item, data) => {
return `${data.luas_bangunan} m²`;
},
},
harga: {
title: 'Harga',
render: (item, data) => {
return window.formatRupiah(data.harga);
},
},
nilai_pasar: {
title: 'Nilai Pasar',
render: (item, data) => {
return window.formatRupiah(data.nilai_pasar);
},
},
location: {
title: 'Location'
}
},
};
dataTable = new KTDataTable(element, dataTableOptions);
dataTable.on('draw', () => {
const data = dataTable._data;
updateMapMarkers(data);
})
// Custom search functionality
searchInput.addEventListener('input', function () {
const searchValue = this.value.trim();
dataTable.search(searchValue, true);
});
}
const filterForm = document.getElementById('filter-form');
filterForm.addEventListener('submit', function (e) {
e.preventDefault();
const formData = new FormData(this);
const filters = Object.fromEntries(formData.entries());
// Apply the new search/filter
if (filters) {
dataTable.search(filters, true);
}
// Reload the table to apply the new filters
dataTable.reload();
});
function initializeEverything() {
initMap();
initializeDataTable();
dataTable.on('draw', () => {
console.log("Table redrawn");
});
}
// Check if Google Maps API is loaded
function checkGoogleMapsLoaded() {
if (window.google && window.google.maps) {
initializeEverything();
} else {
setTimeout(checkGoogleMapsLoaded, 100);
}
}
// Start checking if Google Maps is loaded
checkGoogleMapsLoaded();
</script>
@endpush

View File

@@ -0,0 +1,410 @@
@extends('layouts.main')
@section('breadcrumbs')
{{ Breadcrumbs::render('laporan-penilai-jaminan') }}
@endsection
@section('content')
@push('styles')
<style>
.dropdown {
position: relative;
display: inline-block;
}
.dropdowns-content {
display: none;
position: absolute;
background-color: white;
min-width: 224px;
box-shadow: 0px 8px 16px 0px rgba(0, 0, 0, 0.2);
z-index: 1;
margin-top: 0;
/* Hilangkan jarak antara tombol dan dropdown */
}
.dropdown:hover .dropdowns-content {
display: block;
}
/* Tambahkan hover untuk elemen dropdown agar tidak hilang */
.dropdowns-content:hover {
display: block;
}
.dropdowns-content a {
color: black;
padding: 12px 16px;
text-decoration: none;
display: block;
}
.dropdowns-content a:hover {
background-color: #f1f1f1;
}
</style>
@endpush
<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-penilai-jaminan-table"
data-api-url="{{ route('laporan-penilai-jaminan.datatables') }}">
<div class="card-header bg-agi-50 py-5 flex-wrap">
<h3 class="card-title">
Daftar Laporan Penilai Jaminan
</h3>
<div class="flex flex-wrap gap-2 lg:gap-5">
<div class="flex">
<label class="input">
Start Date
<input placeholder="Tanggal Awal" id="tanggal_awal" type="date">
</label>
</div>
<div class="flex">
<label class="input">
End Date
<input placeholder="Tanggal Akhir" id="tanggal_akhir" type="date">
</label>
</div>
<div class="flex">
<button class="btn btn-primary" id="filter_tanggal">Filter</button>
</div>
<div class="flex">
<label class="input "> <i class="ki-filled ki-magnifier"> </i>
<input placeholder="Search Laporan" id="search" type="text" value="">
</label>
</div>
<div class="flex">
<!-- Custom dropdown for status filter -->
<div class="dropdown" data-dropdown="true" data-dropdown-trigger="click">
<button
class="dropdowns-toggle btn btn-light inline-flex justify-between w-full items-center">
Pilih Status
<i class="ki-outline ki-down dropdown-open:hidden">
</i>
<i class="ki-outline ki-up hidden dropdown-open:block">
</i>
</button>
<div
class="dropdowns-content w-full max-w-56 py-2 absolute mt-2 origin-top-right z-50 bg-white rounded-md shadow-lg ring-1 ring-black ring-opacity-5">
<div class="menu menu-default flex flex-col w-full">
<!-- Checkbox untuk All Status -->
<div class="menu-item">
<label class="menu-link flex items-center px-4 py-2 text-sm text-gray-700">
<input id="select-all" type="checkbox"
class="form-checkbox h-4 w-4 text-blue-600">
<span class="ml-2">All Status</span>
</label>
</div>
<!-- Dinamis Status dari Backend -->
@php
$status_laporan = ['Standar', 'Sederhana', 'Memo', 'Resume', 'Call Report', 'RAP'];
@endphp
@foreach ($status_laporan as $item)
<div class="menu-item">
<label class="menu-link flex items-center px-4 py-2 text-sm text-gray-700">
<input type="checkbox"
class="form-checkbox status-checkbox h-4 w-4 text-blue-600"
value="{{ strtolower($item) }}">
<span class="ml-2">{{ $item }}</span>
</label>
</div>
@endforeach
</div>
</div>
</div>
</div>
<div class="flex flex-wrap gap-2.5">
<div class="h-[24px] border border-r-gray-200"></div>
<button class="btn btn-light" id="export-button">
Export Excel
</button>
</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="user_id">
<span class="sort"><span class="sort-label">User Pemohon</span>
<span class="sort-icon"></span>
</span>
</th>
<th class="min-w-[150px]" data-datatable-column="debitur_id">
<span class="sort"><span class="sort-label">Debitur</span>
<span class="sort-icon"></span>
</span>
</th>
<th class="min-w-[150px]" data-datatable-column="tujuan_penilaian_id">
<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="tujuan_penilaian_id">
<span class="sort"><span class="sort-label">Jenis Jaminan</span>
<span class="sort-icon"></span>
</span>
</th>
<th class="min-w-[150px]" data-datatable-column="laporan">
<span class="sort"><span class="sort-label">Laporan</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>
<!-- Form tersembunyi untuk export -->
<form id="export-form" action="{{ route('laporan-penilai-jaminan.export') }}" method="GET" class="hidden">
<input type="hidden" name="tanggal_awal" id="export_tanggal_awal">
<input type="hidden" name="tanggal_akhir" id="export_tanggal_akhir">
<input type="hidden" name="status" id="export_status">
<input type="hidden" name="selected_ids" id="export_selected_ids">
<input type="hidden" name="export_type" id="export_type" value="all">
</form>
@endsection
@push('scripts')
<script type="module">
const element = document.querySelector('#laporan-penilai-jaminan-table');
const searchInput = document.getElementById('search');
const tanggalAwalInput = document.getElementById('tanggal_awal');
const tanggalAkhirInput = document.getElementById('tanggal_akhir');
const filterTanggalButton = document.getElementById('filter_tanggal');
const selectAllCheckbox = document.getElementById('select-all');
const statusCheckboxes = document.querySelectorAll('.status-checkbox');
// Export elements
const exportForm = document.getElementById('export-form');
const exportButton = document.getElementById('export-button');
const exportTanggalAwal = document.getElementById('export_tanggal_awal');
const exportTanggalAkhir = document.getElementById('export_tanggal_akhir');
const exportStatus = document.getElementById('export_status');
const exportSelectedIds = document.getElementById('export_selected_ids');
const exportType = document.getElementById('export_type');
const apiUrl = element.getAttribute('data-api-url');
const dataTableOptions = {
apiEndpoint: apiUrl,
pageSize: 5,
order: [{
column: 'nomor_registrasi',
dir: 'asc'
}],
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',
},
user_id: {
title: 'User Pemohon',
render: (item, data) => {
return data.user && data.user.name ? `${data.user.name}` : '-';
},
},
debitur_id: {
title: 'Debitur',
render: (item, data) => {
return data.debiture && data.debiture.name ? `${data.debiture.name}` : '-';
},
},
tujuan_penilaian_id: {
title: 'Tujuan Penilaian',
render: (item, data) => {
return data.tujuan_penilaian && data.tujuan_penilaian.name ?
`${data.tujuan_penilaian.name}` : '-';
},
},
jenis_jaminan_id: {
title: 'Jenis Jaminan',
render: (item, data) => {
const jenisJaminan = data.dokumenjaminan.map(d => d.jenis_jaminan.name).join(', ');
return jenisJaminan || '-';
}
},
laporan: {
title: 'Status',
render: (item, data) => {
let badgeClass = '';
const statusLaporan = data.penilai?.type_penilai || '-';
switch (statusLaporan.toLowerCase()) {
case 'standar':
badgeClass = 'badge badge-pill badge-outline badge-warning';
break;
case 'sederhana':
badgeClass = 'badge badge-pill badge-outline badge-info';
break;
case 'memo':
badgeClass = 'badge badge-pill badge-outline badge-success';
break;
case 'resume':
badgeClass = 'badge badge-pill badge-outline badge-primary';
break;
case 'call-report':
badgeClass = 'badge badge-pill badge-outline badge-dark';
break;
default:
badgeClass = 'badge badge-pill badge-outline';
}
return `<span class="badge ${badgeClass}">${statusLaporan}</span>`;
},
},
}
};
let dataTable = new KTDataTable(element, dataTableOptions);
// Search functionality
searchInput.addEventListener('input', function() {
const searchValue = this.value.trim();
dataTable.search(searchValue, true);
});
// Filter by date range
filterTanggalButton.addEventListener('click', function() {
applyDateFilter();
});
function applyDateFilter() {
const tanggalAwal = tanggalAwalInput.value;
const tanggalAkhir = tanggalAkhirInput.value;
if (tanggalAwal && tanggalAkhir) {
// Reload the table with date filters
dataTable.setParameter('tanggal_awal', tanggalAwal);
dataTable.setParameter('tanggal_akhir', tanggalAkhir);
dataTable.reload();
} else {
alert('Mohon isi tanggal awal dan tanggal akhir');
}
}
// Status filter functionality
statusCheckboxes.forEach(checkbox => {
checkbox.addEventListener('change', applyStatusFilter);
});
// Select All functionality
selectAllCheckbox.addEventListener('change', function() {
const isChecked = this.checked;
statusCheckboxes.forEach(checkbox => {
checkbox.checked = isChecked;
});
applyStatusFilter();
});
function applyStatusFilter() {
const selectedStatuses = Array.from(statusCheckboxes)
.filter(checkbox => checkbox.checked)
.map(checkbox => checkbox.value);
if (selectedStatuses.length === 0) {
dataTable.setParameter('status', null);
} else {
dataTable.setParameter('status', selectedStatuses);
}
dataTable.reload();
// Update "Select All" checkbox state
const allChecked = Array.from(statusCheckboxes).every(cb => cb.checked);
selectAllCheckbox.checked = allChecked;
}
// Single export button functionality
exportButton.addEventListener('click', function(e) {
e.preventDefault();
// Check if any rows are selected
const selectedIds = getSelectedRowIds();
// Determine export type based on context
if (selectedIds.length > 0) {
// If rows are selected, export those
exportData({
selected_ids: selectedIds,
export_type: 'selected'
});
} else if (tanggalAwalInput.value && tanggalAkhirInput.value || getSelectedStatuses().length > 0) {
// If filters are applied but no rows selected, export filtered data
exportData({
tanggal_awal: tanggalAwalInput.value,
tanggal_akhir: tanggalAkhirInput.value,
status: getSelectedStatuses(),
export_type: 'filtered'
});
} else {
// If no selection and no filters, export all
exportData({
export_type: 'all'
});
}
});
function exportData(filters = {}) {
// Set filter values in the hidden form
exportTanggalAwal.value = filters.tanggal_awal || '';
exportTanggalAkhir.value = filters.tanggal_akhir || '';
exportStatus.value = filters.status ? filters.status.join(',') : '';
exportSelectedIds.value = filters.selected_ids ? filters.selected_ids.join(',') : '';
exportType.value = filters.export_type || 'all';
// Submit the form
exportForm.submit();
}
function getSelectedStatuses() {
return Array.from(statusCheckboxes)
.filter(checkbox => checkbox.checked)
.map(checkbox => checkbox.value);
}
function getSelectedRowIds() {
const checkboxes = document.querySelectorAll('[data-datatable-row-check="true"]:checked');
return Array.from(checkboxes).map(checkbox => checkbox.value);
}
</script>
@endpush

View File

@@ -142,7 +142,6 @@
@endsection
@push('scripts')
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>
<script type="text/javascript">
function deleteData(data) {
Swal.fire({

View File

@@ -673,51 +673,58 @@ Breadcrumbs::for('noc', function (BreadcrumbTrail $trail) {
$trail->push('NOC', route('noc.index'));
});
Breadcrumbs::for('noc.edit', function (BreadcrumbTrail $trail) {
$trail->parent('noc');
$trail->push('Proses NOC');
});
Breadcrumbs::for('noc.edit', function (BreadcrumbTrail $trail) {
$trail->parent('noc');
$trail->push('Proses NOC');
});
Breadcrumbs::for('laporan-external', function (BreadcrumbTrail $trail) {
$trail->push('Laporan External', route('laporan-external.index'));
});
Breadcrumbs::for('laporan-external', function (BreadcrumbTrail $trail) {
$trail->push('Laporan External', route('laporan-external.index'));
});
Breadcrumbs::for('laporan-external.show', function (BreadcrumbTrail $trail) {
$trail->parent('laporan-external');
$trail->push('Show Laporan External');
});
Breadcrumbs::for('laporan-external.show', function (BreadcrumbTrail $trail) {
$trail->parent('laporan-external');
$trail->push('Show Laporan External');
});
Breadcrumbs::for('laporan-external.create', function (BreadcrumbTrail $trail) {
$trail->parent('laporan-external');
$trail->push('Tambah Laporan External', route('laporan-external.create'));
});
Breadcrumbs::for('laporan-external.create', function (BreadcrumbTrail $trail) {
$trail->parent('laporan-external');
$trail->push('Tambah Laporan External', route('laporan-external.create'));
});
Breadcrumbs::for('laporan-external.edit', function (BreadcrumbTrail $trail) {
$trail->parent('laporan-external');
$trail->push('Data Laporan External');
});
Breadcrumbs::for('laporan-external.edit', function (BreadcrumbTrail $trail) {
$trail->parent('laporan-external');
$trail->push('Data Laporan External');
});
Breadcrumbs::for('basicdata.jenis-lampiran', function (BreadcrumbTrail $trail) {
$trail->parent('basicdata');
$trail->push('Jenis Lampiran', route('basicdata.jenis-lampiran.index'));
});
Breadcrumbs::for('basicdata.jenis-lampiran', function (BreadcrumbTrail $trail) {
$trail->parent('basicdata');
$trail->push('Jenis Lampiran', route('basicdata.jenis-lampiran.index'));
});
Breadcrumbs::for('basicdata.jenis-lampiran.create', function (BreadcrumbTrail $trail) {
$trail->parent('basicdata.jenis-lampiran');
$trail->push('Tambah Jenis Lampiran', route('basicdata.jenis-lampiran.create'));
});
Breadcrumbs::for('basicdata.jenis-lampiran.create', function (BreadcrumbTrail $trail) {
$trail->parent('basicdata.jenis-lampiran');
$trail->push('Tambah Jenis Lampiran', route('basicdata.jenis-lampiran.create'));
});
Breadcrumbs::for('basicdata.jenis-lampiran.edit', function (BreadcrumbTrail $trail, $id) {
$trail->parent('basicdata.jenis-lampiran');
$trail->push('Edit Jenis Lampiran', route('basicdata.jenis-lampiran.edit', $id));
});
Breadcrumbs::for('basicdata.jenis-lampiran.edit', function (BreadcrumbTrail $trail, $id) {
$trail->parent('basicdata.jenis-lampiran');
$trail->push('Edit Jenis Lampiran', route('basicdata.jenis-lampiran.edit', $id));
});
// Laporan Admin Kredit
Breadcrumbs::for('laporan-admin-kredit', function ($trail) {
$trail->push('Laporan Admin Kredit', route('laporan-admin-kredit.index'));
});
// Laporan Admin Kredit
Breadcrumbs::for('laporan-admin-kredit', function ($trail) {
$trail->push('Laporan Admin Kredit', route('laporan-admin-kredit.index'));
});
Breadcrumbs::for('bank-data', function ($trail) {
$trail->push('Bank Data', route('bank-data.index'));
});
Breadcrumbs::for('laporan-penilai-jaminan', function ($trail) {
$trail->push('Laporan Penilai Jaminan', route('laporan-penilai-jaminan.index'));
});
// add andy
require __DIR__ . '/breadcrumbs_registrasi.php';

View File

@@ -3,6 +3,7 @@
use Illuminate\Support\Facades\Route;
use Modules\Lpj\Http\Controllers\ActivityController;
use Modules\Lpj\Http\Controllers\ArahMataAnginController;
use Modules\Lpj\Http\Controllers\BankDataController;
use Modules\Lpj\Http\Controllers\CustomFieldController;
use Modules\Lpj\Http\Controllers\DebitureController;
use Modules\Lpj\Http\Controllers\DokumenJaminanController;
@@ -12,16 +13,16 @@ use Modules\Lpj\Http\Controllers\IjinUsahaController;
use Modules\Lpj\Http\Controllers\JenisDokumenController;
use Modules\Lpj\Http\Controllers\JenisFasilitasKreditController;
use Modules\Lpj\Http\Controllers\JenisJaminanController;
use Modules\Lpj\Http\Controllers\JenisLampiranController;
use Modules\Lpj\Http\Controllers\JenisLaporanController;
use Modules\Lpj\Http\Controllers\JenisLampiranController;
use Modules\Lpj\Http\Controllers\JenisLaporanController;
use Modules\Lpj\Http\Controllers\JenisLegalitasJaminanController;
use Modules\Lpj\Http\Controllers\JenisPenilaianController;
use Modules\Lpj\Http\Controllers\KJPPController;
use Modules\Lpj\Http\Controllers\LampiranDokumenController;
use Modules\Lpj\Http\Controllers\LaporanAdminKreditController;
use Modules\Lpj\Http\Controllers\LaporanController;
use Modules\Lpj\Http\Controllers\LaporanExternalController;
use Modules\Lpj\Http\Controllers\NilaiPlafondController;
use Modules\Lpj\Http\Controllers\LampiranDokumenController;
use Modules\Lpj\Http\Controllers\LaporanAdminKreditController;
use Modules\Lpj\Http\Controllers\LaporanController;
use Modules\Lpj\Http\Controllers\LaporanExternalController;
use Modules\Lpj\Http\Controllers\NilaiPlafondController;
use Modules\Lpj\Http\Controllers\NocController;
use Modules\Lpj\Http\Controllers\PembatalanController;
use Modules\Lpj\Http\Controllers\PemilikJaminanController;
@@ -38,6 +39,7 @@ use Modules\Lpj\Http\Controllers\TeamsController;
use Modules\Lpj\Http\Controllers\TenderController;
use Modules\Lpj\Http\Controllers\TujuanPenilaianController;
use Modules\Lpj\Http\Controllers\TujuanPenilaianKJPPController;
use Modules\Lpj\Http\Controllers\LaporanPenilaiJaminanController;
// use Modules\Lpj\Http\Controllers\ActivityController;
@@ -665,6 +667,18 @@ Route::middleware(['auth'])->group(function () {
Route::get('export', [LaporanAdminKreditController::class, 'export'])->name('export');
});
Route::name('bank-data.')->prefix('bank-data')->group(function () {
Route::get('datatables', [BankDataController::class, 'dataForDatatables'])->name('datatables');
});
Route::resource('bank-data', BankDataController::class);
Route::name('laporan-penilai-jaminan.')->prefix('laporan-penilai-jaminan')->group(function () {
Route::get('/', [LaporanPenilaiJaminanController::class, 'index'])->name('index');
Route::get('datatables', [LaporanPenilaiJaminanController::class, 'dataForDatatables'])->name('datatables');
Route::get('export', [LaporanPenilaiJaminanController::class, 'export'])->name('export');
});
});
require __DIR__ . '/registrasi.php';