From 69d09e74e2ecb70addb5dcdb580f1b7b1bd0befe Mon Sep 17 00:00:00 2001 From: Irwan Cahyono Date: Mon, 4 May 2026 15:07:56 +0700 Subject: [PATCH] ringkasan dan summary petani Co-authored-by: Copilot --- .../Ekosistem/KolomBasisDataController.php | 1 - .../RingkasanBasisDataController.php | 191 ++++++++++++++++++ .../Ekosistem/ValueBasisDataController.php | 109 +++++++--- .../Web/SummaryDashboardController copy.php | 19 ++ app/Models/Ekosistem/RingkasanBasisData.php | 46 +++++ app/Models/Ekosistem/TabelBasisData.php | 7 + app/Models/Ekosistem/ValueBasisData.php | 3 + app/Rules/ValidSql.php | 62 ++++++ ...2152_create_ringkasan_basis_data_table.php | 40 ++++ .../ekosistem/petani-cpm/index.blade.php | 96 ++++++++- .../ringkasan-basis-data/add.blade.php | 87 ++++++++ .../ringkasan-basis-data/edit.blade.php | 108 ++++++++++ .../ekosistem/tabel-basis-data/view.blade.php | 123 +++++++++++ .../ekosistem/value-basis-data/add.blade.php | 5 +- .../ekosistem/value-basis-data/edit.blade.php | 19 +- .../value-basis-data/index.blade.php | 50 ++++- routes/web.php | 5 + 17 files changed, 933 insertions(+), 38 deletions(-) create mode 100644 app/Http/Controllers/Web/Ekosistem/RingkasanBasisDataController.php create mode 100644 app/Http/Controllers/Web/SummaryDashboardController copy.php create mode 100644 app/Models/Ekosistem/RingkasanBasisData.php create mode 100644 app/Rules/ValidSql.php create mode 100644 database/migrations/2026_05_04_092152_create_ringkasan_basis_data_table.php create mode 100644 resources/views/ekosistem/ringkasan-basis-data/add.blade.php create mode 100644 resources/views/ekosistem/ringkasan-basis-data/edit.blade.php diff --git a/app/Http/Controllers/Web/Ekosistem/KolomBasisDataController.php b/app/Http/Controllers/Web/Ekosistem/KolomBasisDataController.php index 0a55575..9c76681 100644 --- a/app/Http/Controllers/Web/Ekosistem/KolomBasisDataController.php +++ b/app/Http/Controllers/Web/Ekosistem/KolomBasisDataController.php @@ -125,7 +125,6 @@ class KolomBasisDataController extends Controller ]); $kolom->update([...$validated, - 'created_by' => auth()->id(), 'updated_by' => auth()->id(), ]); diff --git a/app/Http/Controllers/Web/Ekosistem/RingkasanBasisDataController.php b/app/Http/Controllers/Web/Ekosistem/RingkasanBasisDataController.php new file mode 100644 index 0000000..16f5001 --- /dev/null +++ b/app/Http/Controllers/Web/Ekosistem/RingkasanBasisDataController.php @@ -0,0 +1,191 @@ +json([ + 'status' => 'error', + 'message' => 'Data tabel tidak ditemukan.' + ], 404); + } + + $validated = $request->validate([ + 'heading' => ['required', 'string'], + 'subheading' => ['required', 'string'], + 'query_ringkasan' => ['required', 'string', new ValidSql()], + ]); + + RingkasanBasisData::create([ + 'tabel_id' => $tabelId, + 'heading' => $validated['heading'], + 'subheading' => $validated['subheading'], + 'query_ringkasan' => $validated['query_ringkasan'], + ]); + + return response()->json([ + 'status' => 'success', + 'message' => 'Ringkasan basis data berhasil ditambahkan.' + ], 201); + } + + public function show(string $tabelId, string $id): JsonResponse + { + Gate::authorize('super_admin'); + + $ringkasan = RingkasanBasisData::where('tabel_id', $tabelId)->find($id); + if (!$ringkasan) { + return response()->json([ + 'status' => 'error', + 'message' => 'Data ringkasan tidak ditemukan.' + ], 404); + } + + return response()->json(['data' => $ringkasan, 'status' => 'success']); + } + + public function edit(string $id) + { + // + } + + public function update(Request $request, string $id) + { + Gate::authorize('super_admin'); + + $ringkasan = RingkasanBasisData::find($id); + if (!$ringkasan) { + return response()->json([ + 'status' => 'error', + 'message' => 'Data ringkasan tidak ditemukan.' + ], 404); + } + + $validated = $request->validate([ + 'heading' => ['required', 'string'], + 'subheading' => ['required', 'string'], + 'query_ringkasan' => ['required', 'string', new ValidSql()], + ]); + + $ringkasan->update([...$validated, + 'updated_by' => auth()->id(), + ]); + + return response()->json([ + 'status' => 'success', + 'message' => 'Ringkasan basis data berhasil diperbarui.' + ], 200); + } + + public function destroy(string $id) + { + Gate::authorize('super_admin'); + + $ringkasan = RingkasanBasisData::find($id); + if (!$ringkasan) { + return response()->json([ + 'status' => 'error', + 'message' => 'Data ringkasan tidak ditemukan.' + ], 404); + } + + $ringkasan->update([ + 'deleted_by' => auth()->id(), + ]); + $ringkasan->delete(); + + return response()->json([ + 'status' => 'success', + 'message' => 'Ringkasan basis data berhasil dihapus.' + ], 200); + } + + public function moveUp(Request $request, string $tabelId, string $id): JsonResponse + { + Gate::authorize('super_admin'); + + $current = RingkasanBasisData::where('tabel_id', $tabelId)->find($id); + if (!$current) { + return response()->json([ + 'status' => 'error', + 'message' => 'Data ringkasan tidak ditemukan.' + ], 404); + } + + $prev = RingkasanBasisData::where('tabel_id', $current->tabel_id) + ->where('urutan', '<', $current->urutan) + ->orderBy('urutan', 'desc') + ->first(); + + if ($prev) { + // swap + [$current->urutan, $prev->urutan] = [$prev->urutan, $current->urutan]; + $current->save(); + $prev->save(); + } + + return response()->json([ + 'status' => 'success', + 'message' => 'Ringkasan basis data berhasil diperbarui.' + ], 200); + } + + public function moveDown(Request $request, string $tabelId, string $id): JsonResponse + { + Gate::authorize('super_admin'); + + $current = RingkasanBasisData::where('tabel_id', $tabelId)->find($id); + if (!$current) { + return response()->json([ + 'status' => 'error', + 'message' => 'Data ringkasan tidak ditemukan.' + ], 404); + } + + $next = RingkasanBasisData::where('tabel_id', $current->tabel_id) + ->where('urutan', '>', $current->urutan) + ->orderBy('urutan', 'asc') + ->first(); + + if ($next) { + // swap + [$current->urutan, $next->urutan] = [$next->urutan, $current->urutan]; + $current->save(); + $next->save(); + } + + return response()->json([ + 'status' => 'success', + 'message' => 'Ringkasan basis data berhasil diperbarui.' + ], 200); + } +} diff --git a/app/Http/Controllers/Web/Ekosistem/ValueBasisDataController.php b/app/Http/Controllers/Web/Ekosistem/ValueBasisDataController.php index a1f832a..07510f2 100644 --- a/app/Http/Controllers/Web/Ekosistem/ValueBasisDataController.php +++ b/app/Http/Controllers/Web/Ekosistem/ValueBasisDataController.php @@ -12,6 +12,7 @@ use Illuminate\Support\Facades\DB; use App\Models\Ekosistem\TabelBasisData; use App\Models\Ekosistem\KolomBasisData; use App\Models\Ekosistem\ValueBasisData; +use App\Models\Ekosistem\RingkasanBasisData; use App\Models\Core\Program; class ValueBasisDataController extends Controller @@ -53,29 +54,47 @@ class ValueBasisDataController extends Controller $selects = []; foreach ($kolom as $k) { - $selects[] = " - MAX( - CASE - WHEN kolom_id = {$k->id} - THEN value_{$k->tipe} - ELSE NULL - END - ) AS \"{$k->kolom}\" - "; + if ($k->tipe == 'boolean') { + $selects[] = " + MAX( + CASE + WHEN kolom_id = {$k->id} + THEN CASE + WHEN value_boolean = true THEN 'Ya' + WHEN value_boolean = false THEN 'Tidak' + ELSE NULL + END + ELSE NULL + END + ) AS \"{$k->kolom}\" + "; + } else { + $selects[] = " + MAX( + CASE + WHEN kolom_id = {$k->id} + THEN value_{$k->tipe} + ELSE NULL + END + ) AS \"{$k->kolom}\" + "; + } } $base = ValueBasisData::query() + ->join('core_program', 'core_program.id', '=', 'ekosistem_basis_data_value.program_id') ->where('tabel_id', $tabelId) ->when($program, function ($query) use ($program) { $query->where('program_id', $program->id); }) ->selectRaw(" - program_id, + core_program.id AS program_id, + core_program.nama AS program_nama, tabel_id, value_id, " . implode(",\n", $selects) . " ") - ->groupBy('program_id', 'tabel_id', 'value_id') + ->groupBy('core_program.id', 'core_program.nama', 'tabel_id', 'value_id') ->orderBy('value_id', 'asc'); $values = DB::query()->fromSub($base, 'pivot') @@ -90,7 +109,23 @@ class ValueBasisDataController extends Controller }) ->paginate($perPage); - return view('ekosistem.value-basis-data.index', compact('programList', 'program', 'tabel', 'kolom', 'values')); + $ringkasan = RingkasanBasisData::where('tabel_id', $tabelId)->get(); + $baseSql = $base->toSql(); + if ($ringkasan->isNotEmpty()) { + foreach ($ringkasan as $r) { + $q = str_replace($tabel->tabel, "(" . $baseSql . ") as " . $tabel->tabel, $r->query_ringkasan); + $result_q = DB::select($q, $base->getBindings()); + if (!empty($result_q)) { + $row = (array) $result_q[0]; // object → array + $r->nilai = array_values($row)[0] ?? 0; // ambil value pertama + } else { + $r->nilai = 0; + } + $r->hasil_ringkasan = $result_q; + } + } + + return view('ekosistem.value-basis-data.index', compact('programList', 'program', 'tabel', 'kolom', 'values', 'ringkasan')); } /** @@ -117,13 +152,11 @@ class ValueBasisDataController extends Controller if ($request->has('program_id') && $request->query('program_id')) { $programId = $request->query('program_id'); $program = Program::find($programId); - if (!$program) { - abort(400, 'Program tidak ditemukan.'); - } - } else { - abort(400, 'Program tidak ditemukan.'); } } + if (!$program) { + abort(400, 'Program tidak ditemukan.'); + } return view('ekosistem.value-basis-data.add', compact('tabel', 'kolom', 'program')); } @@ -188,7 +221,7 @@ class ValueBasisDataController extends Controller } }); - return redirect()->route('tabel.data.index', [$tabelId, 'program' => $program->id])->with('success', 'Data berhasil ditambahkan.'); + return redirect()->route('tabel.data.index', [$tabelId, 'program_id' => $program->id])->with('success', 'Data berhasil ditambahkan.'); } /** @@ -296,16 +329,40 @@ class ValueBasisDataController extends Controller $validated = $request->validate($validationRules); DB::transaction(function () use ($program, $tabelId, $validated, $kolom, $id, $values) { - foreach ($values as $v) { - $k = $kolom->where('id', $v->kolom_id)->first(); - $v->update([ - 'value_' . $k->tipe => $validated[$k->kolom] ?? null, - 'updated_by' => auth()->id(), - ]); + foreach ($validated as $kol => $val) { + $k = $kolom->where('kolom', $kol)->first(); + if (!$k) { + continue; + } + $v = $values->where('kolom_id', $k->id)->first(); + if (!$v) { + $vals = [ + 'program_id' => $program->id, + 'tabel_id' => (int)$tabelId, + 'kolom_id' => $k->id, + 'value_id' => $id, + 'created_by' => auth()->id(), + 'updated_by' => auth()->id(), + ]; + $vals['value_' . $k->tipe] = $validated[$k->kolom] ?? null; + ValueBasisData::create($vals); + } else { + $v->update([ + 'value_' . $k->tipe => $val, + 'updated_by' => auth()->id(), + ]); + } } + // foreach ($values as $v) { + // $k = $kolom->where('id', $v->kolom_id)->first(); + // $v->update([ + // 'value_' . $k->tipe => $validated[$k->kolom] ?? null, + // 'updated_by' => auth()->id(), + // ]); + // } }); - return redirect()->route('tabel.data.index', [$tabelId, 'program' => $program->id])->with('success', 'Data berhasil diperbarui.'); + return redirect()->route('tabel.data.index', [$tabelId, 'program_id' => $program->id])->with('success', 'Data berhasil diperbarui.'); } /** @@ -354,6 +411,6 @@ class ValueBasisDataController extends Controller ->where('program_id', $program->id) ->delete(); - return redirect()->route('tabel.data.index', [$tabelId, 'program' => $program->id])->with('success', 'Data berhasil dihapus.'); + return redirect()->route('tabel.data.index', [$tabelId, 'program_id' => $program->id])->with('success', 'Data berhasil dihapus.'); } } diff --git a/app/Http/Controllers/Web/SummaryDashboardController copy.php b/app/Http/Controllers/Web/SummaryDashboardController copy.php new file mode 100644 index 0000000..e5e20b2 --- /dev/null +++ b/app/Http/Controllers/Web/SummaryDashboardController copy.php @@ -0,0 +1,19 @@ +tabel_id)->max('urutan'); + $model->urutan = ($max ?? 0) + 1; + }); + static::addGlobalScope('order', function (Builder $builder) { + $builder->orderBy('urutan'); + }); + } + + public function tabel(): BelongsTo + { + return $this->belongsTo(TabelBasisData::class, 'tabel_id'); + } +} diff --git a/app/Models/Ekosistem/TabelBasisData.php b/app/Models/Ekosistem/TabelBasisData.php index 9eb67b1..b238269 100644 --- a/app/Models/Ekosistem/TabelBasisData.php +++ b/app/Models/Ekosistem/TabelBasisData.php @@ -9,6 +9,8 @@ use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Relations\BelongsTo; use App\Models\Ekosistem\KolomBasisData; +use App\Models\Ekosistem\GroupBasisData; +use App\Models\Ekosistem\RingkasanBasisData; class TabelBasisData extends Model { @@ -46,4 +48,9 @@ class TabelBasisData extends Model { return $this->belongsTo(GroupBasisData::class, 'group_id'); } + + public function ringkasan(): HasMany + { + return $this->hasMany(RingkasanBasisData::class, 'tabel_id')->orderBy('urutan'); + } } diff --git a/app/Models/Ekosistem/ValueBasisData.php b/app/Models/Ekosistem/ValueBasisData.php index feee72c..33075c1 100644 --- a/app/Models/Ekosistem/ValueBasisData.php +++ b/app/Models/Ekosistem/ValueBasisData.php @@ -27,6 +27,9 @@ class ValueBasisData extends Model 'value_date', 'value_datetime', 'value_text', + 'created_by', + 'updated_by', + 'deleted_by', ]; public function tabel(): BelongsTo diff --git a/app/Rules/ValidSql.php b/app/Rules/ValidSql.php new file mode 100644 index 0000000..bf01db8 --- /dev/null +++ b/app/Rules/ValidSql.php @@ -0,0 +1,62 @@ +getMessage()); + // } + } +} diff --git a/database/migrations/2026_05_04_092152_create_ringkasan_basis_data_table.php b/database/migrations/2026_05_04_092152_create_ringkasan_basis_data_table.php new file mode 100644 index 0000000..f52ff1f --- /dev/null +++ b/database/migrations/2026_05_04_092152_create_ringkasan_basis_data_table.php @@ -0,0 +1,40 @@ +id(); + + $table->foreignId('tabel_id')->constrained('ekosistem_basis_data_tabel')->restrictOnDelete(); + + $table->string('heading'); + $table->string('subheading'); + $table->text('query_ringkasan'); + $table->integer('urutan')->default(0); + + $table->foreignId('created_by')->nullable()->constrained('users')->onDelete('set null'); + $table->foreignId('updated_by')->nullable()->constrained('users')->onDelete('set null'); + $table->foreignId('deleted_by')->nullable()->constrained('users')->onDelete('set null'); + + $table->timestamps(); + $table->softDeletes(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('ekosistem_basis_data_ringkasan'); + } +}; diff --git a/resources/views/ekosistem/petani-cpm/index.blade.php b/resources/views/ekosistem/petani-cpm/index.blade.php index 56238f2..d7e6005 100644 --- a/resources/views/ekosistem/petani-cpm/index.blade.php +++ b/resources/views/ekosistem/petani-cpm/index.blade.php @@ -2,8 +2,75 @@ @section('content')
+
+
+
+
+
+
+ Jumlah +
+

12

+
+ 2 Laki-laki | 5 Perempuan +
+
+ + + +
+
+
+
+
+
+
+
+
+
+ Usia +
+

30.5 (rata-rata)

+
+ 20-45 (mayoritas) +
+
+ + + +
+
+
+
+
+
+
+
+
+
+ Pendidikan Terakhir +
+

SD (mayoritas)

+
+ SMA (tertinggi) +
+
+ + + +
+
+
+
+
+
+
-
+
+
Data Petani (CPCL)
+
+ +
@@ -108,6 +175,33 @@ } }); }); + + $.ajax({ + url: "{{ route('petani-cpm.summary', 'jenis_kelamin') }}", + type: 'GET', + success: function (data) { + $('#jumlah_petani').text(data.total); + $('#jenis_kelamin_petani').text(`${data.laki_laki} Laki-laki | ${data.perempuan} Perempuan`); + } + }); + + $.ajax({ + url: "{{ route('petani-cpm.summary', 'usia') }}", + type: 'GET', + success: function (data) { + $('#usia_rata_rata').text(`${data.usia_rata_rata} (rata-rata)`); + $('#usia_mayoritas').text(`${data.usia_mayoritas} (mayoritas)`); + } + }); + + $.ajax({ + url: "{{ route('petani-cpm.summary', 'pendidikan') }}", + type: 'GET', + success: function (data) { + $('#pendidikan_mayoritas').text(`${data.pendidikan_mayoritas} (mayoritas)`); + $('#pendidikan_tertinggi').text(`${data.pendidikan_tertinggi} (tertinggi)`); + } + }); }); @endpush \ No newline at end of file diff --git a/resources/views/ekosistem/ringkasan-basis-data/add.blade.php b/resources/views/ekosistem/ringkasan-basis-data/add.blade.php new file mode 100644 index 0000000..a9d3f8f --- /dev/null +++ b/resources/views/ekosistem/ringkasan-basis-data/add.blade.php @@ -0,0 +1,87 @@ +
+
+
Tambah Ringkasan
+ +
+
+ + @csrf + +
+ + +
+
+ + +
+
+ + +
+ + + + +
+
+ +@push('scripts') + +@endpush \ No newline at end of file diff --git a/resources/views/ekosistem/ringkasan-basis-data/edit.blade.php b/resources/views/ekosistem/ringkasan-basis-data/edit.blade.php new file mode 100644 index 0000000..f5316dd --- /dev/null +++ b/resources/views/ekosistem/ringkasan-basis-data/edit.blade.php @@ -0,0 +1,108 @@ +
+
+
Edit Ringkasan
+ +
+
+
+ @csrf + @method('PUT') + +
+ + +
+
+ + +
+
+ + +
+ + + +
+
+
+ +@push('scripts') + +@endpush \ No newline at end of file diff --git a/resources/views/ekosistem/tabel-basis-data/view.blade.php b/resources/views/ekosistem/tabel-basis-data/view.blade.php index a842c32..3eb64f1 100644 --- a/resources/views/ekosistem/tabel-basis-data/view.blade.php +++ b/resources/views/ekosistem/tabel-basis-data/view.blade.php @@ -95,6 +95,70 @@
+
Informasi Ringkasan Tabel
+ +
+
+
+ +
+
+
+
+ +
+ + + + + + + + + + + @forelse($tabel->ringkasan as $index => $ringkasan) + + + + + + + @empty + + + + @endforelse + +
NoHeading / SubheadingQueryAksi
{{ $loop->iteration }} + {{ $ringkasan->heading }}
+ {{ $ringkasan->subheading }} +
{{ $ringkasan->query_ringkasan }} +
+ @if (!$loop->first) + + @endif + @if (!$loop->last) + + @endif + + +
+
Tidak ada ringkasan ditemukan.
+
+
+
+ @@ -103,6 +167,8 @@
@include('ekosistem.kolom-basis-data.add') @include('ekosistem.kolom-basis-data.edit') + @include('ekosistem.ringkasan-basis-data.add') + @include('ekosistem.ringkasan-basis-data.edit')
@endsection @@ -168,6 +234,63 @@ }); }); + $(".move-up-ringkasan").click(function (e) { + e.preventDefault(); + let id = $(this).data('id'); + + $.post("{{ route('tabel.ringkasan.move-up', [$tabel->id, ':id']) }}".replace(':id', id), { + _token: '{{ csrf_token() }}', + _method: 'PUT' + }, function (res) { + if (res.status === 'success') { + location.reload(); + } + }); + }); + + $(".move-down-ringkasan").click(function (e) { + e.preventDefault(); + let id = $(this).data('id'); + + $.post("{{ route('tabel.ringkasan.move-down', [$tabel->id, ':id']) }}".replace(':id', id), { + _token: '{{ csrf_token() }}', + _method: 'PUT' + }, function (res) { + if (res.status === 'success') { + location.reload(); + } + }); + }); + + $(".delete-ringkasan").click(function (e) { + e.preventDefault(); + const id = $(this).data('id'); + const name = $(this).data('nama'); + + Swal.fire({ + title: 'Hapus?', + text: `Ringkasan ${name} akan dihapus!`, + icon: 'warning', + showCancelButton: true, + confirmButtonText: 'Ya, Hapus!', + customClass: { confirmButton: 'btn btn-danger me-3', cancelButton: 'btn btn-label-secondary' }, + buttonsStyling: false + }).then(function (result) { + if (result.value) { + $.ajax({ + url: "{{ route('tabel.ringkasan.destroy', [$tabel->id, ':id']) }}".replace(':id', id), + type: 'DELETE', + data: { + _token: '{{ csrf_token() }}' + }, + success: function () { + Swal.fire({ icon: 'success', title: 'Terhapus!', showConfirmButton: false, timer: 1500 }) + .then(() => window.location.reload()); + } + }); + } + }); + }); }); @endpush \ No newline at end of file diff --git a/resources/views/ekosistem/value-basis-data/add.blade.php b/resources/views/ekosistem/value-basis-data/add.blade.php index a644617..0e6ac62 100644 --- a/resources/views/ekosistem/value-basis-data/add.blade.php +++ b/resources/views/ekosistem/value-basis-data/add.blade.php @@ -35,7 +35,7 @@ @elseif($k->tipe == 'boolean') - @@ -50,7 +50,7 @@
- Kembali + Kembali
@@ -63,6 +63,7 @@