diff --git a/app/Exports/CustomFieldExport.php b/app/Exports/CustomFieldExport.php new file mode 100644 index 0000000..5158d70 --- /dev/null +++ b/app/Exports/CustomFieldExport.php @@ -0,0 +1,49 @@ +id, + $row->name, + $row->type, + $row->created_at, + $row->updated_at, + ]; + } + + public function headings(): array + { + return [ + 'ID', + 'Name', + 'Type', + 'Created At', + 'Updated At', + ]; + } + + public function columnFormats(): array + { + return [ + 'A' => NumberFormat::FORMAT_NUMBER, + 'D' => NumberFormat::FORMAT_DATE_DDMMYYYY, + 'E' => NumberFormat::FORMAT_DATE_DDMMYYYY, + ]; + } +} diff --git a/app/Helpers/Lpj.php b/app/Helpers/Lpj.php index 6a778a0..222460c 100644 --- a/app/Helpers/Lpj.php +++ b/app/Helpers/Lpj.php @@ -2,7 +2,8 @@ use Carbon\Carbon; use Illuminate\Support\Facades\DB; -use Modules\Lpj\Models\HolidayCalendar; + use Modules\Lpj\Models\CustomField; + use Modules\Lpj\Models\HolidayCalendar; use Modules\Lpj\Models\PenawaranDetailTender; use Modules\Lpj\Models\PenawaranTender; use Modules\Lpj\Models\Penilaian; @@ -359,3 +360,16 @@ function getNomorLaporan($permohonanId, $documentId){ ])->first(); return $laporan->nomor_laporan ?? null; } + +function getCustomField($param){ + if(is_numeric($param)){ + $field = CustomField::find($param); + } else { + $field = CustomField::where(['name' => $param])->first(); + } + if($field){ + return $field; + } else { + return null; + } +} diff --git a/app/Http/Controllers/CustomFieldController.php b/app/Http/Controllers/CustomFieldController.php new file mode 100644 index 0000000..b42ab89 --- /dev/null +++ b/app/Http/Controllers/CustomFieldController.php @@ -0,0 +1,153 @@ +validated(); + + if ($validate) { + try { + // Save to database + CustomField::create($validate); + return redirect() + ->route('basicdata.custom-field.index') + ->with('success', 'Custom Field created successfully'); + } catch (Exception $e) { + return redirect() + ->route('basicdata.custom-field.create') + ->with('error', $e->getMessage()); + } + } + } + + public function create() + { + $urutan_prioritas = CustomField::max('urutan_prioritas')+1; + return view('lpj::custom_fields.create', compact('urutan_prioritas')); + } + + public function edit($id) + { + $customField = CustomField::find($id); + $urutan_prioritas = $customField->urutan_prioritas ?? CustomField::max('urutan_prioritas')+1; + return view('lpj::custom_fields.create', compact('customField', 'urutan_prioritas' )); + } + + public function update(CustomFieldRequest $request, $id) + { + $validate = $request->validated(); + + if ($validate) { + try { + // Update in database + $customField = CustomField::find($id); + $customField->update($validate); + return redirect() + ->route('basicdata.custom-field.index') + ->with('success', 'Custom Field updated successfully'); + } catch (Exception $e) { + return redirect() + ->route('basicdata.custom-field.edit', $id) + ->with('error', 'Failed to update custom field'); + } + } + } + + public function destroy($id) + { + try { + // Delete from database + $customField = CustomField::find($id); + $customField->delete(); + + echo json_encode(['success' => true, 'message' => 'Custom Field deleted successfully']); + } catch (Exception $e) { + echo json_encode(['success' => false, 'message' => 'Failed to delete custom field']); + } + } + + public function dataForDatatables(Request $request) + { + if (is_null($this->user) || !$this->user->can('custom_fields.view')) { + //abort(403, 'Sorry! You are not allowed to view custom fields.'); + } + + // Retrieve data from the database + $query = CustomField::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('name', 'LIKE', "%$search%"); + $q->orWhere('label', 'LIKE', "%$search%"); + $q->orWhere('type', '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(); + + // Calculate the page count + $pageCount = ceil($totalRecords / $request->get('size')); + + // Calculate the current page number + $currentPage = 0 + 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' => $data, + ]); + } + + public function export() + { + return Excel::download(new CustomFieldExport, 'custom_fields.xlsx'); + } + } diff --git a/app/Http/Controllers/DokumenJaminanController.php b/app/Http/Controllers/DokumenJaminanController.php index 78a11c2..e86f22a 100644 --- a/app/Http/Controllers/DokumenJaminanController.php +++ b/app/Http/Controllers/DokumenJaminanController.php @@ -14,6 +14,7 @@ use Modules\Location\Models\Province; use Modules\Location\Models\Village; use Modules\Lpj\Http\Requests\DokumenJaminanRequest; + use Modules\Lpj\Models\CustomField; use Modules\Lpj\Models\Debiture; use Modules\Lpj\Models\DetailDokumenJaminan; use Modules\Lpj\Models\DokumenJaminan; @@ -88,7 +89,7 @@ 'jenis_legalitas_jaminan_id' => $value, 'name' => $request->name[$key], 'keterangan' => $request->keterangan[$key], - 'details' => isset($request->custom_field[$key]) ? json_encode($request->custom_field[$key]) : '' + 'details' => isset($request->custom_field[$value]) ? json_encode($request->custom_field[$value]) : '' ]; $dokumenJaminan = []; @@ -247,7 +248,7 @@ 'jenis_legalitas_jaminan_id' => $value, 'name' => $request->name[$key], 'keterangan' => $request->keterangan[$key], - 'details' => isset($request->custom_field[$key]) ? json_encode($request->custom_field[$key]) : '' + 'details' => isset($request->custom_field[$value]) ? json_encode($request->custom_field[$value]) : '' ]; $dokumenJaminan = []; @@ -496,6 +497,12 @@ foreach ($document->detail as $detail) { // Only include existing legalitas if its id is in the new set if (in_array($detail->jenis_legalitas_jaminan_id, $newLegalitasIds)) { + $customFields = []; + if($detail->jenisLegalitasJaminan->custom_fields) { + $customFields = CustomField::whereIn('id', $detail->jenisLegalitasJaminan->custom_fields) + ->get(); + } + $existingLegalitas[] = [ 'id' => $detail->id, 'jenis_legalitas_jaminan_id' => $detail->jenis_legalitas_jaminan_id, @@ -507,6 +514,7 @@ $detail->dokumen_nomor, ) ?? $detail->dokumen_nomor, 'custom_field' => $detail->jenisLegalitasJaminan->custom_field, + 'custom_fields' => $customFields, 'custom_field_type' => $detail->jenisLegalitasJaminan->custom_field_type, 'details' => $detail->details, 'keterangan' => $detail->keterangan, diff --git a/app/Http/Controllers/JenisLegalitasJaminanController.php b/app/Http/Controllers/JenisLegalitasJaminanController.php index 9c6f4e9..b087589 100644 --- a/app/Http/Controllers/JenisLegalitasJaminanController.php +++ b/app/Http/Controllers/JenisLegalitasJaminanController.php @@ -8,6 +8,7 @@ use Maatwebsite\Excel\Facades\Excel; use Modules\Lpj\Exports\JenisLegalitasJaminanExport; use Modules\Lpj\Http\Requests\JenisLegalitasJaminanRequest; + use Modules\Lpj\Models\CustomField; use Modules\Lpj\Models\JenisLegalitasJaminan; class JenisLegalitasJaminanController extends Controller @@ -40,13 +41,15 @@ public function create() { - return view('lpj::jenis_legalitas_jaminan.create'); + $customFields = CustomField::orderBy('urutan_prioritas', 'asc')->get(); + return view('lpj::jenis_legalitas_jaminan.create',compact('customFields')); } public function edit($id) { $jenisLegalitasJaminan = JenisLegalitasJaminan::find($id); - return view('lpj::jenis_legalitas_jaminan.create', compact('jenisLegalitasJaminan')); + $customFields = CustomField::orderBy('urutan_prioritas', 'asc')->get(); + return view('lpj::jenis_legalitas_jaminan.create', compact('jenisLegalitasJaminan', 'customFields')); } public function update(JenisLegalitasJaminanRequest $request, $id) diff --git a/app/Http/Requests/CustomFieldRequest.php b/app/Http/Requests/CustomFieldRequest.php new file mode 100644 index 0000000..9c8730c --- /dev/null +++ b/app/Http/Requests/CustomFieldRequest.php @@ -0,0 +1,58 @@ + 'required|max:255', + 'type' => 'required|in:text,select,radio,checkbox', + 'label' => 'nullable|max:255', + 'urutan_prioritas' => [ + 'nullable', + 'integer', + Rule::unique('custom_fields')->ignore($this->route('custom_field')), + ], + ]; + } + + /** + * Determine if the user is authorized to make this request. + */ + public function authorize(): bool + { + return true; + } + + public function prepareValidationData($data){ + if(!$this->type){ + $this->merge(['type' => 'text']); + } + + if (!$this->urutan_prioritas) { + $maxPrioritas = CustomField::max('urutan_prioritas') ?? 0; + $this->merge(['urutan_prioritas' => $maxPrioritas + 1]); + } + } + + /** + * Get custom messages for validator errors. + * + * @return array + */ + public function messages() + { + return [ + 'urutan_prioritas.unique' => 'Urutan prioritas sudah digunakan. Silakan pilih nomor lain.', + ]; + } +} diff --git a/app/Http/Requests/JenisLegalitasJaminanRequest.php b/app/Http/Requests/JenisLegalitasJaminanRequest.php index 82fb205..b6ca8a1 100644 --- a/app/Http/Requests/JenisLegalitasJaminanRequest.php +++ b/app/Http/Requests/JenisLegalitasJaminanRequest.php @@ -20,6 +20,8 @@ 'slug' => 'required|max:255', 'custom_field' => 'nullable|max:255', 'custom_field_type' => 'nullable|max:255', + 'custom_fields' => 'nullable|array', + 'custom_fields.*' => 'required|string|max:255', ]; } @@ -46,5 +48,10 @@ 'slug' => Str::slug($this->name), ]); } + + // Ensure custom_fields is always an array + if (!is_array($this->custom_fields)) { + $this->merge(['custom_fields' => []]); + } } } diff --git a/app/Models/CustomField.php b/app/Models/CustomField.php new file mode 100644 index 0000000..8dd41e5 --- /dev/null +++ b/app/Models/CustomField.php @@ -0,0 +1,26 @@ + 'array', + ]; + + public function customFields() + { + return $this->hasMany(CustomField::class); + } } diff --git a/database/migrations/2025_01_30_082943_create_custom_fields_table.php b/database/migrations/2025_01_30_082943_create_custom_fields_table.php new file mode 100644 index 0000000..b8eb922 --- /dev/null +++ b/database/migrations/2025_01_30_082943_create_custom_fields_table.php @@ -0,0 +1,34 @@ +id(); + $table->string('name'); + $table->string('type'); + $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('custom_fields'); + } +}; diff --git a/database/migrations/2025_01_30_085835_add_urutan_prioritas_to_custom_fields_table.php b/database/migrations/2025_01_30_085835_add_urutan_prioritas_to_custom_fields_table.php new file mode 100644 index 0000000..f4250e3 --- /dev/null +++ b/database/migrations/2025_01_30_085835_add_urutan_prioritas_to_custom_fields_table.php @@ -0,0 +1,28 @@ +integer('urutan_prioritas')->nullable()->after('type'); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('custom_fields', function (Blueprint $table) { + $table->dropColumn('urutan_prioritas'); + }); + } +}; diff --git a/database/migrations/2025_01_30_091021_add_label_to_custom_fields_table.php b/database/migrations/2025_01_30_091021_add_label_to_custom_fields_table.php new file mode 100644 index 0000000..39f8b30 --- /dev/null +++ b/database/migrations/2025_01_30_091021_add_label_to_custom_fields_table.php @@ -0,0 +1,28 @@ +string('label')->nullable()->after('name'); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('custom_fields', function (Blueprint $table) { + $table->dropColumn('label'); + }); + } +}; diff --git a/database/migrations/2025_01_30_091713_add_custom_fields_to_jenis_legalitas_jaminan_table.php b/database/migrations/2025_01_30_091713_add_custom_fields_to_jenis_legalitas_jaminan_table.php new file mode 100644 index 0000000..b4ba94b --- /dev/null +++ b/database/migrations/2025_01_30_091713_add_custom_fields_to_jenis_legalitas_jaminan_table.php @@ -0,0 +1,28 @@ +string('custom_fields')->nullable(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('jenis_legalitas_jaminan', function (Blueprint $table) { + $table->dropColumn('custom_fields'); + }); + } +}; diff --git a/module.json b/module.json index 4d52030..8eb0128 100644 --- a/module.json +++ b/module.json @@ -851,6 +851,17 @@ "administrator", "admin" ] + }, + { + "title": "Custom Field", + "path": "basicdata.custom-field", + "classes": "", + "attributes": [], + "permission": "", + "roles": [ + "administrator", + "admin" + ] } ] } diff --git a/resources/views/custom_fields/create.blade.php b/resources/views/custom_fields/create.blade.php new file mode 100644 index 0000000..448cdb2 --- /dev/null +++ b/resources/views/custom_fields/create.blade.php @@ -0,0 +1,89 @@ +@php + $route = explode('.', Route::currentRouteName()); +@endphp + +@extends('layouts.main') + +@section('breadcrumbs') + {{ Breadcrumbs::render(request()->route()->getName()) }} +@endsection + +@section('content') +
| + + | ++ Custom Field + + | ++ Type + + | ++ Urutan Prioritas + + | +Action | +
|---|
- {{ $permohonan->nomor_registrasi ?? "-" }} -
-+ {{ $permohonan->nomor_registrasi ?? "-" }} +
- {{ $permohonan->user->name }} -
-+ {{ $permohonan->user->name }} +
+