This commit is contained in:
2026-06-08 10:09:54 +07:00
160 changed files with 11667 additions and 1688 deletions
+31
View File
@@ -0,0 +1,31 @@
<?php
namespace App\Enums;
enum LayoutForm: string
{
case ROW = 'form-row';
case COLUMN = 'form-column';
case VALUE = 'form-value';
case SECTION = 'form-section';
case HR_LINE = 'form-hr-line';
public function label(): string
{
return match($this) {
self::ROW => 'Row',
self::COLUMN => 'Column',
self::VALUE => 'Value',
self::SECTION => 'Section',
self::HR_LINE => 'HR Line',
};
}
public static function options(): array
{
return collect(self::cases())->map(fn ($case) => [
'value' => $case->value,
'label' => $case->label(),
])->toArray();
}
}
@@ -0,0 +1,59 @@
<?php
namespace App\Http\Controllers\Api\Core;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\AnonymousResourceCollection;
use App\Models\Core\Program;
use App\Http\Resources\Core\ProgramResource;
class ProgramController extends Controller
{
/**
* Display a listing of the resource.
*/
public function index(Request $request): AnonymousResourceCollection
{
$perPage = $request->query('per_page', 10);
$search = $request->query('search', '');
$program = Program::where('nama', 'like', "%$search%")
->paginate($perPage);
return ProgramResource::collection($program);
}
/**
* Store a newly created resource in storage.
*/
public function store(Request $request)
{
//
}
/**
* Display the specified resource.
*/
public function show(string $id): ProgramResource
{
$program = Program::findOrFail($id);
return new ProgramResource($program);
}
/**
* Update the specified resource in storage.
*/
public function update(Request $request, string $id)
{
//
}
/**
* Remove the specified resource from storage.
*/
public function destroy(string $id)
{
//
}
}
@@ -0,0 +1,140 @@
<?php
namespace App\Http\Controllers\Api\Ekosistem;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Illuminate\Http\JsonResponse;
use Illuminate\Support\Facades\Gate;
use Illuminate\Support\Facades\DB;
use App\Models\Ekosistem\TabelBasisData;
use App\Models\Ekosistem\KolomBasisData;
use App\Models\Core\Program;
class FormBasisDataController extends Controller
{
/**
* Display a listing of the resource.
*/
public function index(Request $request, string $tabelId): JsonResponse
{
if (!Gate::any(['super_admin', 'admin', 'fasilitator'])) {
abort(403);
}
$tabel = TabelBasisData::with('kolom')
->whereHas('kolom', function ($query) {
$query->where('is_active', true);
})->find($tabelId);
if (!$tabel) {
abort(404, 'Data tabel tidak ditemukan.');
}
$kolom = KolomBasisData::where('tabel_id', $tabelId)
->where('is_active', true)->get();
if ($kolom->isEmpty()) {
abort(404, 'Data kolom tidak ditemukan untuk tabel ini.');
}
$program = null;
if (app()->has('SystemProgram')) {
$program = app('SystemProgram');
} else {
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.');
}
$method = $request->query('method', 'add');
$list_relasi = null;
if ($method == 'add' || $method == 'edit') {
$list_relasi = [];
foreach ($kolom as $k) {
if ($k->tipe == 'foreign_key') {
$relasi['kolom_id'] = $k->id;
try {
$options_kolom = DB::table($k->relasi_tabel)->selectRaw($k->relasi_kolom_label . ' as label, ' . $k->relasi_kolom_id . ' as value')->whereNull('deleted_at');
$relasi['options'] = $options_kolom->get();
$relasi['sql'] = $options_kolom->toSql();
} catch (\Throwable $th) {
$relasi['options'] = [];
}
$list_relasi[] = $relasi;
}
}
$list_relasi = collect($list_relasi);
} elseif ($method == 'view') {
$id = $request->query('value_id');
if (!$id) {
abort(400, 'value_id query parameter diperlukan untuk view method.');
}
$values = ValueBasisData::query()
->where('tabel_id', $tabelId)
->where('value_id', $id)
->where('program_id', $program->id)
->get();
if ($values->isEmpty()) {
abort(404, 'Data tidak ditemukan.');
}
foreach ($values as $v) {
$k = $kolom->where('id', $v->kolom_id)->first();
if ($k->tipe == 'foreign_key') {
$v->value_relasi_label = DB::table($k->relasi_tabel)->where($k->relasi_kolom_id, $v->value_relasi)->value($k->relasi_kolom_label);
} else if ($k->tipe == 'enum') {
$opsi = collect($k->enum_opsi);
$found = $opsi->first(function ($item) use ($v) {
return (string) $item['value'] === (string) $v->value_enum;
});
$v->value_enum_label = $found['label'] ?? null;
}
}
$value_id = $id;
}
$errors = $request->query('errors', null);
return response()->json($tabel->renderHtml($method, $errors, $list_relasi));
}
/**
* Store a newly created resource in storage.
*/
public function store(Request $request)
{
//
}
/**
* Display the specified resource.
*/
public function show(string $id)
{
//
}
/**
* Update the specified resource in storage.
*/
public function update(Request $request, string $id)
{
//
}
/**
* Remove the specified resource from storage.
*/
public function destroy(string $id)
{
//
}
}
@@ -0,0 +1,78 @@
<?php
namespace App\Http\Controllers\Api\Ekosistem;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Gate;
use Illuminate\Http\Resources\Json\AnonymousResourceCollection;
use Illuminate\Http\JsonResponse;
use App\Models\Ekosistem\TabelBasisData;
use App\Http\Resources\Ekosistem\TabelBasisDataResource;
class TabelBasisDataController extends Controller
{
/**
* Display a listing of the resource.
*/
public function index(Request $request): AnonymousResourceCollection
{
if (!Gate::any(['super_admin', 'admin', 'fasilitator'])) {
abort(403);
}
$perPage = $request->query('per_page', 10);
$search = strtolower($request->query('search', ''));
$tabel = TabelBasisData::with('kolom')
->whereHas('kolom', function ($query) {
$query->where('is_active', true);
})
->whereRaw('lower(tabel) LIKE ?', ["%$search%"])
->paginate($perPage);
return TabelBasisDataResource::collection($tabel);
}
/**
* Store a newly created resource in storage.
*/
public function store(Request $request)
{
//
}
/**
* Display the specified resource.
*/
public function show(Request $request, string $id): JsonResponse
{
if (!Gate::any(['super_admin', 'admin', 'fasilitator'])) {
abort(403);
}
$tabel = TabelBasisData::with('kolom', 'form', 'form.form', 'form.form.form', 'form.form.form.kolom')->findOrFail($id);
return (new TabelBasisDataResource($tabel))
->response();
}
/**
* Update the specified resource in storage.
*/
public function update(Request $request, string $id)
{
//
}
/**
* Remove the specified resource from storage.
*/
public function destroy(string $id)
{
//
}
}
@@ -0,0 +1,368 @@
<?php
namespace App\Http\Controllers\Api\Ekosistem;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\AnonymousResourceCollection;
use Illuminate\Http\JsonResponse;
use Illuminate\Support\Facades\Gate;
use Illuminate\Support\Facades\DB;
use App\Models\Ekosistem\TabelBasisData;
use App\Models\Ekosistem\KolomBasisData;
use App\Models\Ekosistem\ValueBasisData;
use App\Models\Core\Program;
class ValueBasisDataController extends Controller
{
/**
* Display a listing of the resource.
*/
public function index(Request $request, string $tabelId): JsonResponse
{
if (!Gate::any(['super_admin', 'admin', 'fasilitator'])) {
abort(403);
}
$perPage = $request->query('per_page', 10);
$search = strtolower($request->query('search', ''));
$program = null;
$programList = Program::get();
if (app()->has('SystemProgram')) {
$program = app('SystemProgram');
} else {
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.');
}
}
}
$tabel = TabelBasisData::with('kolom')
->whereHas('kolom', function ($query) {
$query->where('is_active', true);
})
->find($tabelId);
if (!$tabel) {
abort(404, 'Data tabel tidak ditemukan.');
}
$kolom = KolomBasisData::where('tabel_id', $tabelId)
->where('is_active', true)
->when('is_browse', function ($q) {
$q->where('is_browse', true);
})
->orderBy('urutan', 'asc')
->get();
if ($kolom->isEmpty()) {
abort(404, 'Data kolom tidak ditemukan untuk tabel ini.');
}
$selects = [];
foreach ($kolom as $k) {
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}\"
";
} elseif ($k->tipe == 'foreign_key') {
$selects[] = "
MAX(
CASE
WHEN kolom_id = {$k->id}
THEN (select {$k->relasi_kolom_label} from {$k->relasi_tabel} where {$k->relasi_kolom_id} = value_relasi)
ELSE NULL
END
) AS \"{$k->kolom}\"
";
} elseif ($k->tipe == 'enum') {
$selects[] = "
MAX(
CASE
WHEN kolom_id = {$k->id}
AND value_enum IS NOT NULL
THEN (
SELECT elem->>'label'
FROM ekosistem_basis_data_kolom k,
jsonb_array_elements(k.enum_opsi::jsonb) AS elem
WHERE k.id = kolom_id
AND elem->>'value' = value_enum
LIMIT 1
)
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("
core_program.id AS program_id,
core_program.nama AS program_nama,
tabel_id,
value_id,
" . implode(",\n", $selects) . "
")
->groupBy('core_program.id', 'core_program.nama', 'tabel_id', 'value_id')
->orderBy('value_id', 'asc');
$values = DB::query()->fromSub($base, 'pivot')
->when($search, function ($query) use ($search, $kolom) {
$query->where(function ($q) use ($search, $kolom) {
foreach ($kolom as $k) {
if ($k->tipe == 'text' || $k->tipe == 'varchar') {
$q->orWhereRaw("lower({$k->kolom}) LIKE ?", ["%$search%"]);
}
}
});
})
->paginate($perPage);
return response()->json($values);
}
/**
* Store a newly created resource in storage.
*/
public function store(Request $request, string $tabelId): JsonResponse
{
if (!Gate::any(['super_admin', 'admin', 'fasilitator'])) {
abort(403);
}
$tabel = TabelBasisData::whereHas('kolom', function ($query) {
$query->where('is_active', true);
})->find($tabelId);
if (!$tabel) {
abort(404, 'Data tabel tidak ditemukan.');
}
$kolom = KolomBasisData::where('tabel_id', $tabelId)
->where('is_active', true)->get();
if ($kolom->isEmpty()) {
abort(404, 'Data kolom tidak ditemukan untuk tabel ini.');
}
if (app()->has('SystemProgram')) {
$program = app('SystemProgram');
} else {
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.');
}
}
$validationRules = [];
foreach ($kolom as $k) {
if ($k->validasi && is_array($k->validasi)) {
$validationRules[$k->kolom] = $k->validasi;
} else {
$validationRules[$k->kolom] = ['nullable'];
}
}
$validated = $request->validate($validationRules);
DB::transaction(function () use ($program, $tabelId, $validated, $kolom) {
$maxId = ValueBasisData::where('tabel_id', $tabelId)
->where('program_id', $program->id)
->whereNotNull('value_id')
->max('value_id');
foreach ($kolom as $k) {
$values = [
'program_id' => $program->id,
'tabel_id' => (int)$tabelId,
'kolom_id' => $k->id,
'value_id' => ($maxId ?? 0) + 1,
'created_by' => auth()->id(),
'updated_by' => auth()->id(),
];
if ($k->tipe == 'foreign_key') {
$values['value_relasi'] = $validated[$k->kolom] ?? null;
} else {
$values['value_' . $k->tipe] = $validated[$k->kolom] ?? null;
}
ValueBasisData::create($values);
}
});
return response()->json(['message' => 'Data berhasil disimpan.']);
}
/**
* Display the specified resource.
*/
public function show(string $id)
{
//
}
/**
* Update the specified resource in storage.
*/
public function update(Request $request, string $tabelId, string $id): JsonResponse
{
if (!Gate::any(['super_admin', 'admin', 'fasilitator'])) {
abort(403);
}
$tabel = TabelBasisData::whereHas('kolom', function ($query) {
$query->where('is_active', true);
})->find($tabelId);
if (!$tabel) {
abort(404, 'Data tabel tidak ditemukan.');
}
$kolom = KolomBasisData::where('tabel_id', $tabelId)
->where('is_active', true)->get();
if ($kolom->isEmpty()) {
abort(404, 'Data kolom tidak ditemukan untuk tabel ini.');
}
if (app()->has('SystemProgram')) {
$program = app('SystemProgram');
} else {
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.');
}
}
$values = ValueBasisData::query()
->where('tabel_id', $tabelId)
->where('value_id', $id)
->where('program_id', $program->id)
->get();
if ($values->isEmpty()) {
abort(404, 'Data tidak ditemukan.');
}
$validationRules = [];
foreach ($kolom as $k) {
if ($k->validasi && is_array($k->validasi)) {
$validationRules[$k->kolom] = $k->validasi;
} else {
$validationRules[$k->kolom] = ['nullable'];
}
}
$validated = $request->validate($validationRules);
DB::transaction(function () use ($program, $tabelId, $validated, $kolom, $id, $values) {
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(),
];
if ($k->tipe == 'foreign_key') {
$vals['value_relasi'] = $validated[$k->kolom] ?? null;
} else {
$vals['value_' . $k->tipe] = $validated[$k->kolom] ?? null;
}
ValueBasisData::create($vals);
} else {
$v->update([
'value_' . ($k->tipe == 'foreign_key' ? 'relasi' : $k->tipe) => $val,
'updated_by' => auth()->id(),
]);
}
}
});
return response()->json(['message' => 'Data berhasil diperbarui.']);
}
/**
* Remove the specified resource from storage.
*/
public function destroy(Request $request, string $tabelId, string $id): JsonResponse
{
if (!Gate::any(['super_admin', 'admin', 'fasilitator'])) {
abort(403);
}
$tabel = TabelBasisData::whereHas('kolom', function ($query) {
$query->where('is_active', true);
})->find($tabelId);
if (!$tabel) {
abort(404, 'Data tabel tidak ditemukan.');
}
$kolom = KolomBasisData::where('tabel_id', $tabelId)->get();
if ($kolom->isEmpty()) {
abort(404, 'Data kolom tidak ditemukan untuk tabel ini.');
}
if (app()->has('SystemProgram')) {
$program = app('SystemProgram');
} else {
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.');
}
}
$values = ValueBasisData::query()
->where('tabel_id', $tabelId)
->where('value_id', $id)
->where('program_id', $program->id)
->get();
if ($values->isEmpty()) {
abort(404, 'Data tidak ditemukan.');
}
ValueBasisData::query()
->where('tabel_id', $tabelId)
->where('value_id', $id)
->where('program_id', $program->id)
->delete();
return response()->json(['message' => 'Data berhasil dihapus.']);
}
}
@@ -1,16 +1,14 @@
<?php
namespace App\Http\Controllers\Api;
namespace App\Http\Controllers\Api\Konfigurasi;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Http\JsonResponse;
use Illuminate\Support\Facades\Hash;
use App\Models\User;
use App\Models\Profile;
use App\Http\Resources\UserResource;
class AuthController extends Controller
@@ -45,20 +43,25 @@ class AuthController extends Controller
'name' => ['required', 'string', 'max:255'],
'email' => ['required', 'email', 'max:255', 'unique:users'],
'password' => ['required', 'string', 'min:8', 'confirmed'],
'username' => ['required', 'string', 'max:255'],
'role' => ['string'],
'uid' => ['required','string', 'unique:users'],
]);
$user = User::create([
'name' => $credentials['name'],
'email' => $credentials['email'],
'password' => Hash::make($credentials['password']),
'username' => $credentials['username'],
'role' => $credentials['role'],
'uid' => $credentials['uid'],
]);
$profile = Profile::create([
'nama' => $credentials['name'],
'email' => $credentials['email'],
'role' => $credentials['role'],
'user_uid' => $credentials['uid'],
'user_id' => $user->id,
'created_by' => $user->id,
'updated_by' => $user->id,
@@ -1,6 +1,6 @@
<?php
namespace App\Http\Controllers\Api;
namespace App\Http\Controllers\Api\Master;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
@@ -1,6 +1,6 @@
<?php
namespace App\Http\Controllers\Api;
namespace App\Http\Controllers\Api\Master;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
@@ -0,0 +1,141 @@
<?php
namespace App\Http\Controllers\Api\Master;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Illuminate\Http\JsonResponse;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Gate;
use Illuminate\Http\Resources\Json\AnonymousResourceCollection;
use Illuminate\Validation\Rule;
use App\Http\Resources\Pertanian\JenisKomoditasResource;
use App\Models\Pertanian\JenisKomoditas;
class JenisKomoditasController extends Controller
{
/**
* Display a listing of the resource.
*/
public function index(Request $request): AnonymousResourceCollection
{
if (!Gate::any(['petani', 'fasilitator', 'super_admin'])) {
abort(403);
}
$size = $request->integer('size') ?: 10;
$jenisKomoditasList = JenisKomoditas::when($request->search, function ($q, $search) {
$search = strtolower($search);
$q->whereRaw('lower(nama) like ?', ["%{$search}%"]);
})
->when($request->kode, fn($q, $v) => $q->where('kode', $v));
if ($request->filled('sort')) {
$dir = str_starts_with($request->sort, '-') ? 'desc' : 'asc';
$column = ltrim($request->sort, '-');
$allowed = ['id', 'nama', 'kode'];
if (in_array($column, $allowed)) {
$jenisKomoditasList->orderBy($column, $dir);
}
} else {
$jenisKomoditasList->orderBy('nama', 'asc');
}
$jenisKomoditasList = $jenisKomoditasList->paginate($size);
return JenisKomoditasResource::collection($jenisKomoditasList);
}
/**
* Show the form for creating a new resource.
*/
public function create()
{
//
}
/**
* Store a newly created resource in storage.
*/
public function store(Request $request): JsonResponse
{
if (!Gate::any(['petani', 'fasilitator', 'super_admin'])) {
abort(403);
}
$validated = $request->validate([
'nama' => ['required', 'string', 'max:255'],
'kode' => ['required', 'string', 'max:50', 'unique:jenis_komoditas,kode'],
'keterangan' => ['nullable', 'string'],
]);
$jenisKomoditas = JenisKomoditas::create($validated);
return (new JenisKomoditasResource($jenisKomoditas))
->response()
->setStatusCode(201);
}
/**
* Display the specified resource.
*/
public function show(string $id): JsonResponse
{
if (!Gate::any(['petani', 'fasilitator', 'super_admin'])) {
abort(403);
}
$jenisKomoditas = JenisKomoditas::findOrFail($id);
return (new JenisKomoditasResource($jenisKomoditas))->response();
}
/**
* Show the form for editing the specified resource.
*/
public function edit(string $id)
{
//
}
/**
* Update the specified resource in storage.
*/
public function update(Request $request, string $id): JsonResponse
{
if (!Gate::any(['petani', 'fasilitator', 'super_admin'])) {
abort(403);
}
$jenisKomoditas = JenisKomoditas::findOrFail($id);
$validated = $request->validate([
'nama' => ['required', 'string', 'max:255'],
'kode' => ['required', 'string', 'max:50', Rule::unique('jenis_komoditas', 'kode')->ignore($jenisKomoditas->id)],
'keterangan' => ['nullable', 'string'],
]);
$jenisKomoditas->update($validated);
return (new JenisKomoditasResource($jenisKomoditas))->response();
}
/**
* Remove the specified resource from storage.
*/
public function destroy(string $id): JsonResponse
{
if (!Gate::any(['petani', 'fasilitator', 'super_admin'])) {
abort(403);
}
$jenisKomoditas = JenisKomoditas::findOrFail($id);
$jenisKomoditas->delete();
return response()->json(null, 204);
}
}
@@ -1,6 +1,6 @@
<?php
namespace App\Http\Controllers\Api;
namespace App\Http\Controllers\Api\Master;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
@@ -1,6 +1,6 @@
<?php
namespace App\Http\Controllers\Api;
namespace App\Http\Controllers\Api\Master;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
@@ -1,6 +1,6 @@
<?php
namespace App\Http\Controllers\Api;
namespace App\Http\Controllers\Api\Master;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
@@ -1,6 +1,6 @@
<?php
namespace App\Http\Controllers\Api;
namespace App\Http\Controllers\Api\Master;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
@@ -1,6 +1,6 @@
<?php
namespace App\Http\Controllers\Api;
namespace App\Http\Controllers\Api\Produktivitas;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
@@ -1,6 +1,6 @@
<?php
namespace App\Http\Controllers\Api;
namespace App\Http\Controllers\Api\Produktivitas;
use App\Http\Controllers\Controller;
use App\Models\Map\InsLahan;
@@ -1,5 +1,5 @@
<?php
namespace App\Http\Controllers\Api;
namespace App\Http\Controllers\Api\Produktivitas;
use App\Http\Controllers\Controller;
use App\Models\Map\Inspeksi;
@@ -1,6 +1,6 @@
<?php
namespace App\Http\Controllers\Api;
namespace App\Http\Controllers\Api\Produktivitas;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
@@ -87,7 +87,10 @@ class LahanController extends Controller
if (!$profile) {
abort(404, 'Profile tidak ditemukan');
}
if ($request->has('profile_id')) {
$request->merge(['profile_id' => (int) $request->profile_id]);
}
$profileRule = $user->role === 'fasilitator' ? ['required', 'numeric', 'exists:profiles,id'] : ['nullable'];
$validated = $request->validate([
@@ -97,6 +100,7 @@ class LahanController extends Controller
'path' => ['nullable', 'array'],
'path.*' => ['array'],
'luas_lahan' => ['nullable', 'numeric'],
'uid' => ['required', 'string'],
'profile_id' => $profileRule,
]);
@@ -1,6 +1,6 @@
<?php
namespace App\Http\Controllers\Api;
namespace App\Http\Controllers\Api\Produktivitas;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
@@ -1,6 +1,6 @@
<?php
namespace App\Http\Controllers\Api;
namespace App\Http\Controllers\Api\Produktivitas;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
@@ -1,6 +1,6 @@
<?php
namespace App\Http\Controllers\Api;
namespace App\Http\Controllers\Api\Produktivitas;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
@@ -0,0 +1,210 @@
<?php
namespace App\Http\Controllers\Api\Produktivitas;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Illuminate\Http\JsonResponse;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Gate;
use Illuminate\Http\Resources\Json\AnonymousResourceCollection;
use Illuminate\Validation\Rules\Enum;
use Illuminate\Validation\Rule;
use App\Http\Resources\Pertanian\TanamanResource;
use App\Models\Pertanian\Tanaman;
use App\Enums\KondisiTanaman;
class TanamanController extends Controller
{
/**
* Display a listing of the resource.
*/
public function index(Request $request): AnonymousResourceCollection
{
if (!Gate::any(['petani', 'fasilitator','super_admin'])) {
abort(403);
}
$user = Auth::user();
$profile = $user->profile;
$profileId = $user->role === 'petani' ? $profile->id : $request->profile_id;
$size = $request->integer('size') ?: 10;
$tanamanList = Tanaman::when($request->search, function ($q, $search) {
$search = strtolower($search);
$q->whereRaw('lower(nama) like ?', ["%{$search}%"]);
})
->when($profileId, fn($q,$v) => $q->where('profile_id',$v))
->when($request->status_kepemilikan, fn($q,$v) => $q->where('status_kepemilikan',$v))
->when($request->lahan_id, fn($q,$v) => $q->where('lahan_id',$v))
->when($request->komoditas_id, fn($q,$v) => $q->where('komoditas_id',$v))
->when($request->desa_kelurahan_id, fn($q,$v) =>
$q->whereHas('lahan', fn($k)
=> $k->where('desa_kelurahan_id',$v)
)
)
->when($request->kecamatan_id, fn ($q, $v) =>
$q->whereHas('lahan.desaKelurahan', fn ($k) =>
$k->where('kecamatan_id', $v)
)
)
->when($request->kabupaten_kota_id, fn ($q, $v) =>
$q->whereHas('lahan.desaKelurahan.kecamatan', fn ($k) =>
$k->where('kabupaten_kota_id', $v)
)
)
->when($request->provinsi_id, fn ($q, $v) =>
$q->whereHas('lahan.desaKelurahan.kecamatan.kabupatenkota', fn ($k) =>
$k->where('provinsi_id', $v)
)
);
if ($request->filled('sort')) {
$dir = str_starts_with($request->sort, '-') ? 'desc' : 'asc';
$column = ltrim($request->sort, '-');
$allowed = ['id', 'nama'];
if (in_array($column, $allowed)) {
$tanamanList->orderBy($column, $dir);
}
} else {
$tanamanList->orderBy('nama', 'asc');
}
$tanamanList = $tanamanList->paginate($size);
return TanamanResource::collection($tanamanList);
}
/**
* Show the form for creating a new resource.
*/
public function create()
{
//
}
/**
* Store a newly created resource in storage.
*/
public function store(Request $request): JsonResponse
{
if (!Gate::any(['petani', 'fasilitator','super_admin'])) {
abort(403);
}
$user = Auth::user();
$profile = $user->profile;
$profileId = $user->role === 'petani' ? $profile->id : $request->profile_id;
$request->merge([
'komoditas_id' => $request->input('komoditas.id') ?? $request->input('komoditas_id'),
'lahan_id' => $request->input('lahan.id') ?? $request->input('lahan_id'),
'profile_id' => $profileId,
]);
$validated = $request->validate([
'nama' => ['required', 'string', 'max:255'],
'komoditas_id' => ['required', 'exists:master_komoditas,id'],
'lahan_id' => [
'required',
Rule::exists('map_lahan', 'id')->where(function ($query) use ($profileId) {
$query->where('profile_id', $profileId)
->whereNull('deleted_at');
}),
],
'latitude' => ['nullable', 'numeric', 'between:-90,90', 'required_with:longitude'],
'longitude' => ['nullable', 'numeric', 'between:-180,180', 'required_with:latitude'],
'kondisi_tanaman' => ['nullable', 'string', new Enum(KondisiTanaman::class)],
]);
$tanaman = Tanaman::create([
...$validated,
'profile_id' => $profile->id,
]);
return (new TanamanResource($tanaman))
->response()
->setStatusCode(201);
}
/**
* Display the specified resource.
*/
public function show(string $id): JsonResponse
{
if (!Gate::any(['petani', 'fasilitator','super_admin'])) {
abort(403);
}
$tanaman = Tanaman::findOrFail($id);
if ($tanaman->profile_id !== Auth::user()->profile->id) {
return response()->json(['message' => 'Unauthorized'], 403);
}
return (new TanamanResource($tanaman))->response();
}
/**
* Show the form for editing the specified resource.
*/
public function edit(string $id)
{
//
}
/**
* Update the specified resource in storage.
*/
public function update(Request $request, string $id): JsonResponse
{
if (!Gate::any(['petani', 'fasilitator','super_admin'])) {
abort(403);
}
$tanaman = Tanaman::findOrFail($id);
if ($tanaman->profile_id !== Auth::user()->profile->id) {
return response()->json(['message' => 'Unauthorized'], 403);
}
$profile = Auth::user()->profile;
$validated = $request->validate([
'nama' => ['required', 'string', 'max:255'],
'komoditas_id' => ['required', 'exists:master_komoditas,id'],
'lahan_id' => [
'required',
Rule::exists('map_lahan', 'id')->where(function ($query) use ($profile) {
$query->where('profile_id', $profile->id)
->whereNull('deleted_at');
}),
],
'latitude' => ['nullable', 'numeric', 'between:-90,90', 'required_with:longitude'],
'longitude' => ['nullable', 'numeric', 'between:-180,180', 'required_with:latitude'],
'kondisi_tanaman' => ['nullable', 'string', new Enum(KondisiTanaman::class)],
]);
$tanaman->update($validated);
return (new TanamanResource($tanaman))->response();
}
/**
* Remove the specified resource from storage.
*/
public function destroy(string $id): JsonResponse
{
if (!Gate::any(['petani', 'fasilitator','super_admin'])) {
abort(403);
}
$tanaman = Tanaman::findOrFail($id);
if ($tanaman->profile_id !== Auth::user()->profile->id) {
return response()->json(['message' => 'Unauthorized'], 403);
}
$tanaman->delete();
return response()->json(null, 204);
}
}
+19 -4
View File
@@ -94,26 +94,41 @@ class TanamanController extends Controller
if (!Gate::any(['petani', 'fasilitator','super_admin'])) {
abort(403);
}
$profile = Auth::user()->profile;
$user = Auth::user();
$profile = $user->profile;
$profileId = $user->role === 'petani' ? $profile->id : $request->profile_id;
$request->merge([
'komoditas_id' => $request->input('komoditas.id') ?? $request->input('komoditas_id'),
'lahan_id' => $request->input('lahan.id') ?? $request->input('lahan_id'),
'profile_id' => $profileId,
]);
$validated = $request->validate([
'nama' => ['required', 'string', 'max:255'],
'komoditas_id' => ['required', 'exists:master_komoditas,id'],
'lahan_id' => [
'required',
Rule::exists('map_lahan', 'id')->where(function ($query) use ($profile) {
$query->where('profile_id', $profile->id)
Rule::exists('map_lahan', 'id')->where(function ($query) use ($profileId) {
$query->where('profile_id', $profileId)
->whereNull('deleted_at');
}),
],
'latitude' => ['nullable', 'numeric', 'between:-90,90', 'required_with:longitude'],
'longitude' => ['nullable', 'numeric', 'between:-180,180', 'required_with:latitude'],
'longitude' => ['nullable ', 'numeric', 'between:-180,180', 'required_with:latitude'],
'kondisi_tanaman' => ['nullable', 'string', new Enum(KondisiTanaman::class)],
'uid' => ['required', 'string'],
'jenis_komoditas_id' => ['nullable', 'exists:jenis_komoditas,id'],
'komoditas_kode' => ['nullable', 'string', 'max:255'],
]);
$tanaman = Tanaman::create([
...$validated,
'profile_id' => $profile->id,
'uid' => $validated['uid'] ?? $request->input('uid'),
'komoditas_kode' => $validated['komoditas_kode'] ?? $request->input('komoditas_kode'),
'jenis_komoditas_id' => $validated['jenis_komoditas_id'] ?? $request->input('jenis_komoditas_id'),
]);
return (new TanamanResource($tanaman))
@@ -4,13 +4,8 @@ namespace App\Http\Controllers\Web\Dashboard;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use App\Models\Profile;
use App\Models\Wilayah\Provinsi;
use App\Models\wilayah\KabupatenKota;
use App\Models\Wilayah\Kecamatan;
use App\Models\Wilayah\DesaKelurahan;
use App\Models\Pertanian\Lahan;
use Illuminate\Support\Facades\Gate;
class SummaryController extends Controller
{
public function index()
@@ -21,128 +16,4 @@ class SummaryController extends Controller
$title = 'Summary Dashboard';
return view('dashboard.summary', compact('title'));
}
public function produktivitasBackup(Request $request)
{
if (!Gate::allows('super_admin') && !Gate::allows('admin')) {
abort(403);
}
$title = 'Produktivitas Dashboard';
$luasTotal = Lahan::whereNotNull('path')->sum('luas_lahan');
$totalpetani = Profile::where('role', 'petani')->count();
$totallahan = Lahan::whereNotNull('path')->count();
$petaniList = Profile::where('role', 'petani')
->with(['lahan.tanaman.komoditas', 'desaKelurahan'])
->paginate(20);
$allLahan = Lahan::whereNotNull('path')
->with(['profile', 'tanaman.komoditas', 'desaKelurahan.kecamatan.kabupatenKota.provinsi'])
->get()
->map(function($lahan) {
return [
'id' => $lahan->id,
'polygon' => $lahan->path,
'nama_petani' => $lahan->profile->nama ?? 'N/A',
'luas' => $lahan->luas_lahan,
'tanaman' => $lahan->tanaman->map(fn($t) => $t->komoditas->nama ?? null)->filter()->unique()->values()
];
});
return view('dashboard.produktivitas', compact('title', 'petaniList', 'allLahan', 'totalpetani', 'totallahan', 'luasTotal'));
}
public function produktivitas(Request $request)
{
if (!Gate::allows('super_admin') && !Gate::allows('admin')) {
abort(403);
}
$title = 'Produktivitas Dashboard';
$luasTotal = Lahan::whereNotNull('path')->sum('luas_lahan');
$totalpetani = Profile::where('role', 'petani')->count();
$totallahan = Lahan::whereNotNull('path')->count();
$petaniList = Profile::where('role', 'petani')
->with(['lahan.tanaman.komoditas', 'desaKelurahan'])
->paginate(20);
$allLahan = Lahan::whereNotNull('path')
->with(['profile', 'tanaman.komoditas', 'desaKelurahan.kecamatan.kabupatenKota.provinsi'])
->get();
// Penampung data per level (menggunakan ID sebagai key agar unique)
$geoProvinsi = [];
$geoKabupaten = [];
$geoKecamatan = [];
$geoDesa = [];
$geoLahan = [];
foreach ($allLahan as $lahan) {
$desa = $lahan->desaKelurahan;
$kec = $desa ? $desa->kecamatan : null;
$kab = $kec ? $kec->kabupatenKota : null;
$prov = $kab ? $kab->provinsi : null;
// --- Akumulasi Provinsi ---
if ($prov && $prov->path) {
if (!isset($geoProvinsi[$prov->id])) {
$geoProvinsi[$prov->id] = ['id' => $prov->id, 'nama' => $prov->nama, 'polygon' => $prov->path, 'total_lahan' => 0, 'total_luas' => 0];
}
$geoProvinsi[$prov->id]['total_lahan']++;
$geoProvinsi[$prov->id]['total_luas'] += $lahan->luas_lahan;
}
// --- Akumulasi Kabupaten ---
if ($kab && $kab->path) {
if (!isset($geoKabupaten[$kab->id])) {
$geoKabupaten[$kab->id] = ['id' => $kab->id, 'parent_id' => $prov->id ?? null, 'nama' => $kab->nama, 'polygon' => $kab->path, 'total_lahan' => 0, 'total_luas' => 0];
}
$geoKabupaten[$kab->id]['total_lahan']++;
$geoKabupaten[$kab->id]['total_luas'] += $lahan->luas_lahan;
}
// --- Akumulasi Kecamatan ---
if ($kec && $kec->path) {
if (!isset($geoKecamatan[$kec->id])) {
$geoKecamatan[$kec->id] = ['id' => $kec->id, 'parent_id' => $kab->id ?? null, 'nama' => $kec->nama, 'polygon' => $kec->path, 'total_lahan' => 0, 'total_luas' => 0];
}
$geoKecamatan[$kec->id]['total_lahan']++;
$geoKecamatan[$kec->id]['total_luas'] += $lahan->luas_lahan;
}
// --- Akumulasi Desa ---
if ($desa && $desa->path) {
if (!isset($geoDesa[$desa->id])) {
$geoDesa[$desa->id] = ['id' => $desa->id, 'parent_id' => $kec->id ?? null, 'nama' => $desa->nama, 'polygon' => $desa->path, 'total_lahan' => 0, 'total_luas' => 0];
}
$geoDesa[$desa->id]['total_lahan']++;
$geoDesa[$desa->id]['total_luas'] += $lahan->luas_lahan;
}
// Data Lahan Tetap
$geoLahan[] = [
'id' => $lahan->id,
'parent_id' => $desa->id ?? null,
'polygon' => $lahan->path,
'nama_petani' => $lahan->profile->nama ?? 'N/A',
'luas' => $lahan->luas_lahan,
'tanaman' => $lahan->tanaman->map(fn($t) => $t->komoditas->nama ?? null)->filter()->unique()->values()
];
}
return view('dashboard.produktivitas', [
'title' => $title,
'petaniList' => $petaniList,
'totalpetani' => $totalpetani,
'totallahan' => $totallahan,
'luasTotal' => $luasTotal,
// Reset key array agar menjadi format list normal untuk JSON
'geoProvinsi' => array_values($geoProvinsi),
'geoKabupaten' => array_values($geoKabupaten),
'geoKecamatan' => array_values($geoKecamatan),
'geoDesa' => array_values($geoDesa),
'geoLahan' => $geoLahan
]);
}
}
@@ -0,0 +1,296 @@
<?php
namespace App\Http\Controllers\Web\Ekosistem;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Gate;
use Illuminate\View\View;
use Illuminate\Http\JsonResponse;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rule;
use Illuminate\Http\RedirectResponse;
use App\Models\Ekosistem\TabelBasisData;
use App\Models\Ekosistem\FormBasisData;
use App\Enums\LayoutForm;
class FormBasisDataController extends Controller
{
public function index(Request $request, string $tabelId): View
{
Gate::authorize('super_admin');
$tabel = TabelBasisData::find($tabelId);
if (!$tabel) {
return response()->json([
'status' => 'error',
'message' => 'Data tabel tidak ditemukan.'
], 404);
}
$listEnum = LayoutForm::options();
$tab = $request->tab ?? 'form';
$tabel->state = 'preview';
return view('ekosistem.form-basis-data.index', compact('tabel', 'listEnum', 'tab'));
}
public function create()
{
//
}
public function store(Request $request, string $tabelId): JsonResponse
{
Gate::authorize('super_admin');
$tabel = TabelBasisData::find($tabelId);
if (!$tabel) {
return response()->json([
'status' => 'error',
'message' => 'Data tabel tidak ditemukan.'
], 404);
}
$validated = $request->validate([
'parent_id' => ['nullable', 'exists:ekosistem_basis_data_form,id'],
'tipe' => ['required', Rule::enum(LayoutForm::class)],
'column_width' => [
Rule::requiredIf($request->tipe === LayoutForm::COLUMN->value),
'nullable', 'integer', 'min:1', 'max:12'],
'kolom_id' => [
Rule::requiredIf($request->tipe === LayoutForm::VALUE->value),
'nullable', 'exists:ekosistem_basis_data_kolom,id'],
'section_label' => [
Rule::requiredIf($request->tipe === LayoutForm::SECTION->value),
'nullable', 'string'],
]);
FormBasisData::create([...$validated,
'tabel_id' => $tabelId,
'created_by' => auth()->user()->id,
'updated_by' => auth()->user()->id
]);
return response()->json([
'status' => 'success',
'message' => 'Form basis data berhasil ditambahkan.'
], 201);
}
public function show(string $tabelId, string $id): JsonResponse
{
Gate::authorize('super_admin');
$form = FormBasisData::where('tabel_id', $tabelId)->find($id);
if (!$form) {
return response()->json([
'status' => 'error',
'message' => 'Data formulir basis data tidak ditemukan.'
], 404);
}
return response()->json([
'status' => 'success',
'data' => $form
], 200);
}
public function edit(string $id)
{
//
}
public function update(Request $request, string $tabelId, string $id)
{
Gate::authorize('super_admin');
$form = FormBasisData::where('tabel_id', $tabelId)->find($id);
if (!$form) {
return response()->json([
'status' => 'error',
'message' => 'Data formulir basis data tidak ditemukan.'
], 404);
}
$validated = $request->validate([
'parent_id' => ['nullable', 'exists:ekosistem_basis_data_form,id'],
'tipe' => ['required', Rule::enum(LayoutForm::class)],
'column_width' => [
Rule::requiredIf($request->tipe === LayoutForm::COLUMN->value),
'nullable', 'integer', 'min:1', 'max:12'],
'kolom_id' => [
Rule::requiredIf($request->tipe === LayoutForm::VALUE->value),
'nullable', 'exists:ekosistem_basis_data_kolom,id'],
'section_label' => [
Rule::requiredIf($request->tipe === LayoutForm::SECTION->value),
'nullable', 'string'],
]);
$form->update([...$validated,
'updated_by' => auth()->user()->id
]);
return response()->json([
'status' => 'success',
'message' => 'Form basis data berhasil diubah.'
]);
}
public function destroy(string $tabelId, string $id): JsonResponse
{
Gate::authorize('super_admin');
$form = FormBasisData::where('tabel_id', $tabelId)->find($id);
if (!$form) {
return response()->json([
'status' => 'error',
'message' => 'Data form basis data tidak ditemukan.'
], 404);
}
if ($form->form->count() > 0) {
return response()->json([
'status' => 'error',
'message' => 'Tidak dapat menghapus formulir basis data yang memiliki formulir.'
], 400);
}
$form->update([
'deleted_by' => auth()->user()->id
]);
$form->delete();
return response()->json([
'status' => 'success',
'message' => 'Form basis data berhasil dihapus.'
], 200);
}
public function generate(Request $request, string $tabelId): RedirectResponse
{
Gate::authorize('super_admin');
$tabel = TabelBasisData::find($tabelId);
if (!$tabel) {
return redirect()->route('tabel.formulir.index', $tabelId)->with('error', 'Tabel basis data tidak ditemukan.');
}
DB::transaction(function () use ($tabel) {
FormBasisData::where('tabel_id', $tabel->id)->delete();
FormBasisData::create([
'tabel_id' => $tabel->id,
'tipe' => LayoutForm::SECTION,
'section_label' => $tabel->label,
'created_by' => auth()->user()->id,
'updated_by' => auth()->user()->id
]);
FormBasisData::create([
'tabel_id' => $tabel->id,
'tipe' => LayoutForm::HR_LINE,
'created_by' => auth()->user()->id,
'updated_by' => auth()->user()->id
]);
$chunks = $tabel->kolom->chunk(4);
foreach ($chunks as $chunk) {
$row = FormBasisData::create([
'tabel_id' => $tabel->id,
'tipe' => LayoutForm::ROW,
'created_by' => auth()->user()->id,
'updated_by' => auth()->user()->id
]);
foreach ($chunk as $kolom) {
$column = FormBasisData::create([
'tabel_id' => $tabel->id,
'tipe' => LayoutForm::COLUMN,
'column_width' => 3,
'parent_id' => $row->id,
'created_by' => auth()->user()->id,
'updated_by' => auth()->user()->id
]);
FormBasisData::create([
'tabel_id' => $tabel->id,
'tipe' => LayoutForm::VALUE,
'parent_id' => $column->id,
'kolom_id' => $kolom->id,
'created_by' => auth()->user()->id,
'updated_by' => auth()->user()->id
]);
}
}
});
return redirect()->route('tabel.formulir.index', $tabelId)->with('success', 'Formulir berhasil dibuat.');
}
public function moveUp(Request $request, string $tabelId, string $id): JsonResponse
{
Gate::authorize('super_admin');
$current = FormBasisData::where('tabel_id', $tabelId)->find($id);
if (!$current) {
return response()->json([
'status' => 'error',
'message' => 'Data formulir tidak ditemukan.'
], 404);
}
$prev = FormBasisData::where('tabel_id', $tabelId)
->where('urutan', '<', $current->urutan)
->where('parent_id', $current->parent_id)
->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' => 'Formulir basis data berhasil diperbarui.'
], 200);
}
public function moveDown(Request $request, string $tabelId, string $id): JsonResponse
{
Gate::authorize('super_admin');
$current = FormBasisData::where('tabel_id', $tabelId)->find($id);
if (!$current) {
return response()->json([
'status' => 'error',
'message' => 'Data formulir tidak ditemukan.'
], 404);
}
$next = FormBasisData::where('tabel_id', $tabelId)
->where('urutan', '>', $current->urutan)
->where('parent_id', $current->parent_id)
->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' => 'Formulir basis data berhasil diperbarui.'
], 200);
}
}
@@ -145,6 +145,13 @@ class KolomBasisDataController extends Controller
'is_browse' => ['nullable', 'boolean'],
]);
if (!empty($validated['enum_opsi'])) {
$validated['enum_opsi'] = json_decode($validated['enum_opsi'], true);
}
if (!empty($validated['validasi'])) {
$validated['validasi'] = json_decode($validated['validasi'], true);
}
$kolom->update([...$validated,
'updated_by' => auth()->id(),
]);
@@ -188,7 +195,7 @@ class KolomBasisDataController extends Controller
], 404);
}
$prev = KolomBasisData::where('tabel_id', $current->tabel_id)
$prev = KolomBasisData::where('tabel_id', $tabelId)
->where('urutan', '<', $current->urutan)
->orderBy('urutan', 'desc')
->first();
@@ -218,7 +225,7 @@ class KolomBasisDataController extends Controller
], 404);
}
$next = KolomBasisData::where('tabel_id', $current->tabel_id)
$next = KolomBasisData::where('tabel_id', $tabelId)
->where('urutan', '>', $current->urutan)
->orderBy('urutan', 'asc')
->first();
@@ -8,6 +8,13 @@ use Illuminate\Support\Facades\Gate;
use Illuminate\View\View;
use Illuminate\Http\RedirectResponse;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Validator;
use Illuminate\Http\JsonResponse;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Str;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\Hash;
use Illuminate\Validation\Rule;
use App\Models\Ekosistem\TabelBasisData;
use App\Models\Ekosistem\KolomBasisData;
@@ -17,9 +24,16 @@ use App\Models\Core\Program;
class ValueBasisDataController extends Controller
{
private $tableModelClassMap = [
'master_provinsi' => \App\Models\Wilayah\Provinsi::class,
'master_kabupaten_kota' => \App\Models\Wilayah\KabupatenKota::class,
'master_kecamatan' => \App\Models\Wilayah\Kecamatan::class,
'master_desa_kelurahan' => \App\Models\Wilayah\DesaKelurahan::class,
];
public function index(Request $request, string $tabelId): View
{
if (!Gate::any(['super_admin', 'admin'])) {
if (!Gate::any(['super_admin', 'admin', 'fasilitator'])) {
abort(403);
}
@@ -40,13 +54,15 @@ class ValueBasisDataController extends Controller
}
}
$tabel = TabelBasisData::find($tabelId);
$tabel = TabelBasisData::with('kolom')
->whereHas('kolom', function ($query) {
$query->where('is_active', true);
})->find($tabelId);
if (!$tabel) {
abort(404, 'Data tabel tidak ditemukan.');
}
$kolom = KolomBasisData::where('tabel_id', $tabelId)
$kolom = KolomBasisData::where('tabel_id', $tabel->id)
->where('is_active', true)
->where('is_browse', true)
->get();
if ($kolom->isEmpty()) {
abort(404, 'Data kolom tidak ditemukan untuk tabel ini.');
@@ -83,6 +99,7 @@ class ValueBasisDataController extends Controller
MAX(
CASE
WHEN kolom_id = {$k->id}
AND value_enum IS NOT NULL
THEN (
SELECT elem->>'label'
FROM ekosistem_basis_data_kolom k,
@@ -160,8 +177,11 @@ class ValueBasisDataController extends Controller
if (!Gate::any(['super_admin', 'admin'])) {
abort(403);
}
$tabel = TabelBasisData::find($tabelId);
$tabel = TabelBasisData::with('kolom')
->whereHas('kolom', function ($query) {
$query->where('is_active', true);
})->find($tabelId);
if (!$tabel) {
abort(404, 'Data tabel tidak ditemukan.');
}
@@ -189,7 +209,12 @@ class ValueBasisDataController extends Controller
if ($k->tipe == 'foreign_key') {
$relasi['kolom_id'] = $k->id;
try {
$options_kolom = DB::table($k->relasi_tabel)->selectRaw($k->relasi_kolom_label . ' as label, ' . $k->relasi_kolom_id . ' as value')->whereNull('deleted_at');
$modelClass = Arr::get($this->tableModelClassMap, $k->relasi_tabel);
if ($modelClass) {
$options_kolom = $modelClass::select($k->relasi_kolom_label . ' as label', $k->relasi_kolom_id . ' as value')->limit(10000);
} else {
$options_kolom = DB::table($k->relasi_tabel)->selectRaw($k->relasi_kolom_label . ' as label, ' . $k->relasi_kolom_id . ' as value')->whereNull('deleted_at')->limit(10000);
}
$relasi['options'] = $options_kolom->get();
$relasi['sql'] = $options_kolom->toSql();
} catch (\Throwable $th) {
@@ -199,18 +224,84 @@ class ValueBasisDataController extends Controller
}
}
$list_relasi = collect($list_relasi);
// dd($kolom->where('tipe', 'enum')->first()?->enum_opsi);
return view('ekosistem.value-basis-data.add', compact('tabel', 'kolom', 'program', 'list_relasi'));
}
private function prepareValidationRules($kolom)
{
$rules = [];
foreach ($kolom as $k) {
if ($k->validasi && is_array($k->validasi)) {
$rules[$k->kolom] = $k->validasi;
if (!in_array('required', $k->validasi) && !in_array('nullable', $k->validasi)) {
$rules[$k->kolom][] = 'nullable';
}
if (!in_array('string', $k->validasi) && ($k->tipe == 'varchar' || $k->tipe == 'text')) {
$rules[$k->kolom][] = 'string';
}
if (!in_array('size', $k->validasi) && ($k->tipe == 'varchar')) {
$rules[$k->kolom][] = 'size:255';
}
if (!in_array('integer', $k->validasi) && $k->tipe == 'integer') {
$rules[$k->kolom][] = 'integer';
}
if (!in_array('boolean', $k->validasi) && $k->tipe == 'boolean') {
$rules[$k->kolom][] = 'boolean';
}
if (!in_array('date', $k->validasi) && ($k->tipe == 'date' || $k->tipe == 'datetime')) {
$rules[$k->kolom][] = 'date';
}
if ($k->tipe == 'foreign_key') {
$rules[$k->kolom][] = 'exists:' . $k->relasi_tabel . ',' . $k->relasi_kolom_id;
}
if ($k->tipe == 'enum') {
$enumValues = collect($k->enum_opsi)->pluck('value')->toArray();
$rules[$k->kolom][] = Rule::in($enumValues);
}
} else {
$rules[$k->kolom] = ['nullable'];
if ($k->tipe == 'varchar' || $k->tipe == 'text') {
$rules[$k->kolom][] = 'string';
}
if ($k->tipe == 'varchar') {
$rules[$k->kolom][] = 'size:255';
}
if ($k->tipe == 'integer') {
$rules[$k->kolom][] = 'integer';
}
if ($k->tipe == 'boolean') {
$rules[$k->kolom][] = 'boolean';
}
if ($k->tipe == 'date' || $k->tipe == 'datetime') {
$rules[$k->kolom][] = 'date';
}
if ($k->tipe == 'foreign_key') {
$rules[$k->kolom][] = 'exists:' . $k->relasi_tabel . ',' . $k->relasi_kolom_id;
}
if ($k->tipe == 'enum') {
$enumValues = collect($k->enum_opsi)->pluck('value')->toArray();
$rules[$k->kolom][] = Rule::in($enumValues);
}
}
}
return $rules;
}
public function store(Request $request, string $tabelId): RedirectResponse
{
if (!Gate::any(['super_admin', 'admin'])) {
abort(403);
}
$tabel = TabelBasisData::find($tabelId);
$tabel = TabelBasisData::with('kolom')
->whereHas('kolom', function ($query) {
$query->where('is_active', true);
})->find($tabelId);
if (!$tabel) {
abort(404, 'Data tabel tidak ditemukan.');
}
@@ -233,15 +324,7 @@ class ValueBasisDataController extends Controller
}
}
$validationRules = [];
foreach ($kolom as $k) {
if ($k->validasi && is_array($k->validasi)) {
$validationRules[$k->kolom] = $k->validasi;
} else {
$validationRules[$k->kolom] = ['nullable'];
}
}
$validated = $request->validate($validationRules);
$validated = $request->validate($this->prepareValidationRules($kolom));
DB::transaction(function () use ($program, $tabelId, $validated, $kolom) {
$maxId = ValueBasisData::where('tabel_id', $tabelId)
@@ -270,16 +353,16 @@ class ValueBasisDataController extends Controller
return redirect()->route('tabel.data.index', [$tabelId, 'program_id' => $program->id])->with('success', 'Data berhasil ditambahkan.');
}
/**
* Display the specified resource.
*/
public function show(Request $request, string $tabelId, string $id): View
{
if (!Gate::any(['super_admin', 'admin'])) {
abort(403);
}
$tabel = TabelBasisData::find($tabelId);
$tabel = TabelBasisData::with('kolom')
->whereHas('kolom', function ($query) {
$query->where('is_active', true);
})->find($tabelId);
if (!$tabel) {
abort(404, 'Data tabel tidak ditemukan.');
}
@@ -315,7 +398,9 @@ class ValueBasisDataController extends Controller
foreach ($values as $v) {
$k = $kolom->where('id', $v->kolom_id)->first();
if ($k->tipe == 'foreign_key') {
$v->value_relasi_label = DB::table($k->relasi_tabel)->where($k->relasi_kolom_id, $v->value_relasi)->value($k->relasi_kolom_label);
$v->value_relasi_label = DB::table($k->relasi_tabel)
->where($k->relasi_kolom_id, $v->value_relasi)
->value($k->relasi_kolom_label);
} else if ($k->tipe == 'enum') {
$opsi = collect($k->enum_opsi);
$found = $opsi->first(function ($item) use ($v) {
@@ -336,7 +421,10 @@ class ValueBasisDataController extends Controller
abort(403);
}
$tabel = TabelBasisData::find($tabelId);
$tabel = TabelBasisData::with('kolom')
->whereHas('kolom', function ($query) {
$query->where('is_active', true);
})->find($tabelId);
if (!$tabel) {
abort(404, 'Data tabel tidak ditemukan.');
}
@@ -376,7 +464,12 @@ class ValueBasisDataController extends Controller
if ($k->tipe == 'foreign_key') {
$relasi['kolom_id'] = $k->id;
try {
$options_kolom = DB::table($k->relasi_tabel)->selectRaw($k->relasi_kolom_label . ' as label, ' . $k->relasi_kolom_id . ' as value')->whereNull('deleted_at');
$modelClass = Arr::get($this->tableModelClassMap, 'master_desa_kelurahan');
if ($modelClass) {
$options_kolom = $modelClass::select($k->relasi_kolom_label . ' as label', $k->relasi_kolom_id . ' as value')->limit(10000);
} else {
$options_kolom = DB::table($k->relasi_tabel)->selectRaw($k->relasi_kolom_label . ' as label, ' . $k->relasi_kolom_id . ' as value')->whereNull('deleted_at')->limit(10000);
}
$relasi['options'] = $options_kolom->get();
$relasi['sql'] = $options_kolom->toSql();
} catch (\Throwable $th) {
@@ -390,16 +483,16 @@ class ValueBasisDataController extends Controller
return view('ekosistem.value-basis-data.edit', compact('tabel', 'kolom', 'program', 'values', 'value_id', 'list_relasi'));
}
/**
* Update the specified resource in storage.
*/
public function update(Request $request, string $tabelId, string $id): RedirectResponse
{
if (!Gate::any(['super_admin', 'admin'])) {
abort(403);
}
$tabel = TabelBasisData::find($tabelId);
$tabel = TabelBasisData::with('kolom')
->whereHas('kolom', function ($query) {
$query->where('is_active', true);
})->find($tabelId);
if (!$tabel) {
abort(404, 'Data tabel tidak ditemukan.');
}
@@ -431,15 +524,7 @@ class ValueBasisDataController extends Controller
abort(404, 'Data tidak ditemukan.');
}
$validationRules = [];
foreach ($kolom as $k) {
if ($k->validasi && is_array($k->validasi)) {
$validationRules[$k->kolom] = $k->validasi;
} else {
$validationRules[$k->kolom] = ['nullable'];
}
}
$validated = $request->validate($validationRules);
$validated = $request->validate($this->prepareValidationRules($kolom));
DB::transaction(function () use ($program, $tabelId, $validated, $kolom, $id, $values) {
foreach ($validated as $kol => $val) {
@@ -15,13 +15,13 @@ class AuthController extends Controller
public function login()
{
$title = 'Login';
return view('konfigurasi.auth.login', compact('title'));
return view('auth.login', compact('title'));
}
public function register()
{
$title = 'Register';
return view('konfigurasi.auth.register', compact('title'));
return view('auth.register', compact('title'));
}
public function createAccount(Request $request)
@@ -42,7 +42,7 @@ class AuthController extends Controller
'deleted_by' => null,
]);
return redirect()->route('konfigurasi.auth.login')->with('success', 'Account created successfully. Please login.');
return redirect()->route('auth.login')->with('success', 'Account created successfully. Please login.');
}
public function verify(User $user)
@@ -10,6 +10,7 @@ use App\Enums\Role;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Validator;
use Illuminate\Support\Str;
class UserController extends Controller
{
@@ -70,6 +71,7 @@ class UserController extends Controller
public function store(Request $request)
{
$validator = Validator::make($request->all(), [
'username' => ['required', 'string', 'max:255', 'unique:users,name'],
'name' => ['required', 'string', 'max:255'],
'email' => ['required', 'string', 'email', 'max:255', 'unique:users'],
'password' => ['required', 'string', 'min:8', 'confirmed'],
@@ -90,14 +92,17 @@ class UserController extends Controller
$user = User::create([
'name' => $request->name,
'username' => $request->username,
'email' => $request->email,
'password' => Hash::make($request->password),
'role' => $request->role,
'uid' => Str::random(10),
'created_by' => auth()->id(),
]);
Profile::create([
'user_id' => $user->id,
'user_uid' => $user->uid,
'role' => $request->role,
'nama' => $request->name,
'email' => $request->email,
@@ -0,0 +1,228 @@
<?php
namespace App\Http\Controllers\Web\Master;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use App\Models\Master\JenisKomoditas;
use App\Models\Pertanian\Komoditas;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Validator;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Str;
use Illuminate\Validation\Rule;
class JenisKomoditasController extends Controller
{
public function index(Request $request)
{
$perPage = $request->get('per_page', 10);
$search = $request->get('search');
$jenisKomoditas = JenisKomoditas::with('komoditas')
->when($search, function ($query) use ($search) {
$query->where(function ($q) use ($search) {
$q->where('nama', 'ILIKE', "%{$search}%")
->orWhere('path', 'ILIKE', "%{$search}%")
->orWhereHas('komoditas', function ($komoditasQuery) use ($search) {
$komoditasQuery->where('nama', 'ILIKE', "%{$search}%");
});
});
})
->latest()
->paginate($perPage);
$komoditas = Komoditas::orderBy('nama', 'asc')->get();
return view('master.jeniskomoditas.index', compact(
'jenisKomoditas',
'komoditas'
));
}
public function getByKomoditas($komoditas_id)
{
$jenisKomoditas = JenisKomoditas::where('komoditas_id', $komoditas_id)
->orderBy('nama', 'asc')
->get(['id', 'nama']);
return response()->json([
'status' => 'success',
'data' => $jenisKomoditas,
]);
}
/**
* Store a newly created resource in storage.
*/
public function store(Request $request)
{
$validated = $request->validate([
'komoditas_id' => [
'required',
'integer',
'exists:master_komoditas,id',
],
'nama' => [
'required',
'string',
'max:255',
Rule::unique('jenis_komoditas', 'nama')
->where('komoditas_id', $request->komoditas_id),
],
], [
'komoditas_id.required' => 'Komoditas wajib dipilih.',
'komoditas_id.exists' => 'Komoditas yang dipilih tidak valid.',
'nama.required' => 'Nama jenis komoditas wajib diisi.',
'nama.unique' => 'Nama jenis komoditas sudah tersedia pada komoditas ini.',
]);
try {
DB::beginTransaction();
$jenisKomoditas = JenisKomoditas::create([
'komoditas_id' => $validated['komoditas_id'],
'nama' => $validated['nama'],
'created_by' => auth()->id(),
'updated_by' => auth()->id(),
]);
DB::commit();
return response()->json([
'status' => 'success',
'message' => 'Data jenis komoditas berhasil disimpan.',
'data' => $jenisKomoditas,
]);
} catch (\Throwable $e) {
DB::rollBack();
Log::error('Gagal menyimpan jenis komoditas', [
'error' => $e->getMessage(),
'request' => $request->all(),
]);
return response()->json([
'status' => 'error',
'message' => 'Gagal menyimpan data: ' . $e->getMessage(),
], 500);
}
}
/**
* Display the specified resource.
*/
public function show(string $id)
{
try {
$jenisKomoditas = JenisKomoditas::with('komoditas')->findOrFail($id);
return response()->json([
'status' => 'success',
'data' => $jenisKomoditas,
]);
} catch (\Throwable $e) {
return response()->json([
'status' => 'error',
'message' => 'Data jenis komoditas tidak ditemukan.',
], 404);
}
}
/**
* Update the specified resource in storage.
*/
public function update(Request $request, string $id)
{
$jenisKomoditas = JenisKomoditas::findOrFail($id);
$validated = $request->validate([
'komoditas_id' => [
'required',
'integer',
'exists:master_komoditas,id',
],
'nama' => [
'required',
'string',
'max:255',
Rule::unique('jenis_komoditas', 'nama')
->where('komoditas_id', $request->komoditas_id)
->ignore($jenisKomoditas->id),
],
'path' => [
'nullable',
'string',
],
], [
'komoditas_id.required' => 'Komoditas wajib dipilih.',
'komoditas_id.exists' => 'Komoditas yang dipilih tidak valid.',
'nama.required' => 'Nama jenis komoditas wajib diisi.',
'nama.unique' => 'Nama jenis komoditas sudah tersedia pada komoditas ini.',
]);
try {
DB::beginTransaction();
$jenisKomoditas->update([
'komoditas_id' => $validated['komoditas_id'],
'nama' => $validated['nama'],
'updated_by' => auth()->id(),
]);
DB::commit();
return response()->json([
'status' => 'success',
'message' => 'Data jenis komoditas berhasil diperbarui.',
'data' => $jenisKomoditas->fresh('komoditas'),
]);
} catch (\Throwable $e) {
DB::rollBack();
Log::error('Gagal update jenis komoditas', [
'error' => $e->getMessage(),
'id' => $id,
'request' => $request->all(),
]);
return response()->json([
'status' => 'error',
'message' => 'Gagal mengupdate data: ' . $e->getMessage(),
], 500);
}
}
/**
* Remove the specified resource from storage.
*/
public function destroy(string $id)
{
try {
DB::beginTransaction();
$jenisKomoditas = JenisKomoditas::findOrFail($id);
$jenisKomoditas->update(['deleted_by' => auth()->id()]);
$jenisKomoditas->delete();
DB::commit();
return response()->json([
'status' => 'success',
'message' => 'Data jenis komoditas berhasil dihapus.',
]);
} catch (\Throwable $e) {
DB::rollBack();
Log::error('Gagal hapus jenis komoditas', [
'error' => $e->getMessage(),
'id' => $id,
]);
return response()->json([
'status' => 'error',
'message' => 'Gagal menghapus data: ' . $e->getMessage(),
], 500);
}
}
}
@@ -17,9 +17,12 @@ class ProvinsiController extends Controller
$perPage = $request->query('per_page', 10);
$search = $request->query('search', '');
$provinsi = Provinsi::where('nama', 'like', "%$search%")
->orWhere('kode', 'like', "%$search%")
->orWhere('iso', 'like', "%$search%")
$provinsi = Provinsi::withCount('kabupatenKota')
->where(function($query) use ($search) {
$query->where('nama', 'like', "%$search%")
->orWhere('kode', 'like', "%$search%")
->orWhere('iso', 'like', "%$search%");
})
->paginate($perPage);
return view('master.provinsi.index', compact('title', 'provinsi'));
@@ -0,0 +1,236 @@
<?php
namespace App\Http\Controllers\Web\Master;
use App\Http\Controllers\Controller;
use App\Models\Master\Varietas;
use App\Models\Pertanian\Komoditas;
use App\Models\Master\JenisKomoditas;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Str;
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rule;
use Illuminate\Http\Request;
class VarietasController extends Controller
{
public function index(Request $request)
{
$perPage = $request->get('per_page', 10);
$search = $request->get('search');
$varietas = Varietas::with(['komoditas', 'jenisKomoditas'])
->when($search, function ($query) use ($search) {
$query->where(function ($q) use ($search) {
$q->where('nama', 'ILIKE', "%{$search}%")
->orWhere('path', 'ILIKE', "%{$search}%")
->orWhereHas('komoditas', function ($komoditasQuery) use ($search) {
$komoditasQuery->where('nama', 'ILIKE', "%{$search}%");
})
->orWhereHas('jenisKomoditas', function ($jenisQuery) use ($search) {
$jenisQuery->where('nama', 'ILIKE', "%{$search}%");
});
});
})
->latest()
->paginate($perPage);
$komoditas = Komoditas::orderBy('nama', 'asc')->get();
return view('master.varietas.index', compact(
'varietas',
'komoditas'
));
}
public function getByJenisKomoditas($jenisKomoditasId)
{
$varietas = Varietas::where('jenis_komoditas_id', $jenisKomoditasId)->get();
return response()->json([
'status' => 'success',
'data' => $varietas,
]);
}
public function store(Request $request)
{
$komoditasTable = (new Komoditas)->getTable();
$jenisKomoditasTable = (new JenisKomoditas)->getTable();
$varietasTable = (new Varietas)->getTable();
$validated = $request->validate([
'komoditas_id' => [
'required',
'integer',
Rule::exists($komoditasTable, 'id'),
],
'jenis_komoditas_id' => [
'required',
'integer',
Rule::exists($jenisKomoditasTable, 'id')
->where('komoditas_id', $request->komoditas_id),
],
'nama' => [
'required',
'string',
'max:255',
Rule::unique($varietasTable, 'nama')
->where('komoditas_id', $request->komoditas_id)
->where('jenis_komoditas_id', $request->jenis_komoditas_id),
],
'deskripsi' => [
'nullable',
'string',
],
]);
try {
DB::beginTransaction();
$varietas = Varietas::create([
'komoditas_id' => $validated['komoditas_id'],
'jenis_komoditas_id' => $validated['jenis_komoditas_id'],
'nama' => $validated['nama'],
'deskripsi' => $validated['deskripsi'] ?? null,
'created_by' => auth()->id(),
'updated_by' => auth()->id(),
]);
DB::commit();
return response()->json([
'status' => 'success',
'message' => 'Data varietas berhasil disimpan.',
'data' => $varietas,
]);
} catch (\Throwable $e) {
DB::rollBack();
Log::error('Gagal menyimpan varietas', [
'error' => $e->getMessage(),
'request' => $request->all(),
]);
return response()->json([
'status' => 'error',
'message' => 'Gagal menyimpan data: ' . $e->getMessage(),
], 500);
}
}
public function show(string $id)
{
try {
$varietas = Varietas::with(['komoditas', 'jenisKomoditas'])->findOrFail($id);
return response()->json([
'status' => 'success',
'data' => $varietas,
]);
} catch (\Throwable $e) {
return response()->json([
'status' => 'error',
'message' => 'Data varietas tidak ditemukan.',
], 404);
}
}
public function update(Request $request, string $id)
{
$komoditasTable = (new Komoditas)->getTable();
$jenisKomoditasTable = (new JenisKomoditas)->getTable();
$varietasTable = (new Varietas)->getTable();
$validated = $request->validate([
'komoditas_id' => [
'required',
'integer',
Rule::exists($komoditasTable, 'id'),
],
'jenis_komoditas_id' => [
'required',
'integer',
Rule::exists($jenisKomoditasTable, 'id')
->where('komoditas_id', $request->komoditas_id),
],
'nama' => [
'required',
'string',
'max:255',
Rule::unique($varietasTable, 'nama')
->where('komoditas_id', $request->komoditas_id)
->where('jenis_komoditas_id', $request->jenis_komoditas_id),
],
'deskripsi' => [
'nullable',
'string',
],
]);
try {
DB::beginTransaction();
$varietas = Varietas::findOrFail($id);
$varietas->update([
'komoditas_id' => $validated['komoditas_id'],
'jenis_komoditas_id' => $validated['jenis_komoditas_id'],
'nama' => $validated['nama'],
'deskripsi' => $validated['deskripsi'] ?? null,
'updated_by' => auth()->id(),
]);
DB::commit();
return response()->json([
'status' => 'success',
'message' => 'Data varietas berhasil diperbarui.',
'data' => $varietas->fresh(['komoditas', 'jenisKomoditas']),
]);
} catch (\Throwable $e) {
DB::rollBack();
Log::error('Gagal update varietas', [
'error' => $e->getMessage(),
'id' => $id,
'request' => $request->all(),
]);
return response()->json([
'status' => 'error',
'message' => 'Gagal mengupdate data: ' . $e->getMessage(),
], 500);
}
}
public function destroy(string $id)
{
try {
DB::beginTransaction();
$varietas = Varietas::findOrFail($id);
$varietas->update(['deleted_by' => auth()->id()]);
$varietas->delete();
DB::commit();
return response()->json([
'status' => 'success',
'message' => 'Data varietas berhasil dihapus.',
]);
} catch (\Throwable $e) {
DB::rollBack();
Log::error('Gagal hapus varietas', [
'error' => $e->getMessage(),
'id' => $id,
]);
return response()->json([
'status' => 'error',
'message' => 'Gagal menghapus data: ' . $e->getMessage(),
], 500);
}
}
}
@@ -10,6 +10,7 @@ use App\Models\Pertanian\Adat;
use App\Models\Wilayah\Provinsi;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Facades\Validator;
use Illuminate\Support\Str;
class LahanController extends Controller
{
@@ -76,6 +77,25 @@ class LahanController extends Controller
return view('produktivitas.lahan.index', compact('lahan', 'provinsi', 'profiles', 'adat', 'kabupaten', 'kecamatan', 'desa'));
}
public function getByProfile(Request $request, $profileId)
{
$desaKelurahanId = $request->get('desa_kelurahan_id');
$lahan = Lahan::with('profile')
->where('profile_id', $profileId)
->when($desaKelurahanId, function ($query) use ($desaKelurahanId) {
$query->where('desa_kelurahan_id', $desaKelurahanId);
})
->orderBy('created_at', 'desc')
->get(['id', 'nama', 'path', 'profile_id', 'desa_kelurahan_id']);
return response()->json([
'status' => 'success',
'data' => $lahan,
]);
}
public function create()
{
$provinsi = Provinsi::orderBy('nama', 'asc')->get();
@@ -112,8 +132,12 @@ class LahanController extends Controller
return response()->json(['status' => 'error', 'message' => 'Format koordinat (path) bukan JSON array yang valid.'], 422);
}
}
$userUID = Profile::where('id', $request->profile_id)->value('user_uid');
$userUID = substr($userUID, 2);
Lahan::create([
'uid' => 'LH' . $userUID . '-' . strtoupper(Str::random(10)),
'nama' => $request->nama,
'status_kepemilikan' => $request->status_kepemilikan,
'profile_id' => $request->profile_id,
@@ -0,0 +1,421 @@
<?php
namespace App\Http\Controllers\Web\Produktivitas;
use App\Http\Controllers\Controller;
use App\Models\Pertanian\Tanaman;
use App\Models\Profile;
use App\Models\Pertanian\Komoditas;
use App\Models\Master\JenisKomoditas;
use App\Models\Master\Varietas;
use App\Models\Pertanian\Lahan;
use App\Models\Wilayah\Provinsi;
use App\Models\Wilayah\KabupatenKota;
use App\Models\Wilayah\Kecamatan;
use App\Models\Wilayah\DesaKelurahan;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Str;
use Illuminate\Validation\Rule;
class MapTanamanController extends Controller
{
public function index(Request $request)
{
$perPage = $request->get('per_page', 10);
$search = $request->get('search');
$tanaman = Tanaman::query()
->select([
DB::raw('MIN(id) as id'),
'profile_id',
'lahan_id',
'komoditas_id',
'jenis_komoditas_id',
'varietas_id',
DB::raw('COUNT(*) as total_tanaman'),
DB::raw("SUM(CASE WHEN kondisi_tanaman = 'sehat' THEN 1 ELSE 0 END) as total_sehat"),
DB::raw("SUM(CASE WHEN kondisi_tanaman = 'sakit' THEN 1 ELSE 0 END) as total_sakit"),
DB::raw("SUM(CASE WHEN kondisi_tanaman = 'mati' THEN 1 ELSE 0 END) as total_mati"),
DB::raw('MAX(created_at) as max_created_at'),
])
->with([
'profile',
'lahan.desaKelurahan.kecamatan.kabupatenkota.provinsi',
'komoditas',
'jenisKomoditas',
'varietas',
])
->when($search, function ($query) use ($search) {
$query->where(function ($q) use ($search) {
$q->whereHas('profile', fn ($q) => $q->where('nama', 'ILIKE', "%{$search}%"))
->orWhereHas('lahan', fn ($q) => $q->where('nama', 'ILIKE', "%{$search}%"))
->orWhereHas('komoditas', fn ($q) => $q->where('nama', 'ILIKE', "%{$search}%"))
->orWhereHas('jenisKomoditas', fn ($q) => $q->where('nama', 'ILIKE', "%{$search}%"))
->orWhereHas('varietas', fn ($q) => $q->where('nama', 'ILIKE', "%{$search}%"))
->orWhereHas('lahan.desaKelurahan', fn ($q) => $q->where('nama', 'ILIKE', "%{$search}%"))
->orWhereHas('lahan.desaKelurahan.kecamatan', fn ($q) => $q->where('nama', 'ILIKE', "%{$search}%"))
->orWhereHas('lahan.desaKelurahan.kecamatan.kabupatenkota', fn ($q) => $q->where('nama', 'ILIKE', "%{$search}%"))
->orWhereHas('lahan.desaKelurahan.kecamatan.kabupatenkota.provinsi', fn ($q) => $q->where('nama', 'ILIKE', "%{$search}%"));
});
})
->groupBy([
'profile_id',
'lahan_id',
'komoditas_id',
'jenis_komoditas_id',
'varietas_id',
])
->orderByDesc('max_created_at')
->paginate($perPage);
return view('produktivitas.mapTanaman.index', compact('tanaman'));
}
private function getTanamanGroupByRepresentativeId($id)
{
$representative = Tanaman::findOrFail($id);
$points = Tanaman::with([
'profile',
'lahan.desaKelurahan.kecamatan.kabupatenkota.provinsi',
'komoditas',
'jenisKomoditas',
'varietas',
])
->where('profile_id', $representative->profile_id)
->where('lahan_id', $representative->lahan_id)
->where('komoditas_id', $representative->komoditas_id)
->where('jenis_komoditas_id', $representative->jenis_komoditas_id)
->where('varietas_id', $representative->varietas_id)
->orderBy('id')
->get();
return [
'representative' => $representative,
'points' => $points,
];
}
public function create()
{
$provinsi = Provinsi::select('id', 'nama', 'path')
->orderBy('nama')
->get();
$komoditas = Komoditas::orderBy('nama')->get();
$profiles = Profile::orderBy('nama')->get();
return view('produktivitas.mapTanaman.add', compact(
'provinsi',
'komoditas',
'profiles'
));
}
public function store(Request $request)
{
$desaKelurahanTable = (new DesaKelurahan)->getTable();
$profileTable = (new Profile)->getTable();
$lahanTable = (new Lahan)->getTable();
$komoditasTable = (new Komoditas)->getTable();
$jenisKomoditasTable = (new JenisKomoditas)->getTable();
$varietasTable = (new Varietas)->getTable();
$validated = $request->validate([
'desa_kelurahan_id' => [
'required',
'integer',
Rule::exists($desaKelurahanTable, 'id'),
],
'profile_id' => [
'required',
'integer',
Rule::exists($profileTable, 'id'),
],
'lahan_id' => [
'required',
'integer',
Rule::exists($lahanTable, 'id')
->where('profile_id', $request->profile_id)
->where('desa_kelurahan_id', $request->desa_kelurahan_id),
],
'komoditas_id' => [
'required',
'integer',
Rule::exists($komoditasTable, 'id'),
],
'jenis_komoditas_id' => [
'required',
'integer',
Rule::exists($jenisKomoditasTable, 'id')
->where('komoditas_id', $request->komoditas_id),
],
'varietas_id' => [
'required',
'integer',
Rule::exists($varietasTable, 'id')
->where('jenis_komoditas_id', $request->jenis_komoditas_id),
],
'points' => [
'required',
'array',
'min:1',
],
'points.*.latitude' => [
'required',
'numeric',
],
'points.*.longitude' => [
'required',
'numeric',
],
'points.*.kondisi_tanaman' => [
'required',
Rule::in(['sehat', 'sakit', 'mati']),
],
'metode_pengumpulan' => [
'nullable',
'string',
'max:50',
],
'deskripsi' => [
'nullable',
'string',
],
], [
'points.required' => 'Minimal tambahkan satu titik tanaman pada peta.',
'points.min' => 'Minimal tambahkan satu titik tanaman pada peta.',
'points.*.latitude.required' => 'Latitude titik tanaman wajib ada.',
'points.*.longitude.required' => 'Longitude titik tanaman wajib ada.',
'points.*.kondisi_tanaman.required' => 'Kondisi tanaman wajib dipilih.',
]);
try {
DB::beginTransaction();
$lahan = Lahan::findOrFail($validated['lahan_id']);
$komoditas = Komoditas::findOrFail($validated['komoditas_id']);
$profile = Profile::findOrFail($validated['profile_id']);
if (!$lahan->uid) {
throw new \Exception('UID lahan tidak ditemukan.');
}
$profileName = str_replace(' ', '', $profile->nama);
$lahanUidPart = substr($lahan->uid, 2);
$existingCount = Tanaman::where('lahan_id', $validated['lahan_id'])
->where('komoditas_id', $validated['komoditas_id'])
->where('jenis_komoditas_id', $validated['jenis_komoditas_id'])
->where('varietas_id', $validated['varietas_id'])
->count();
$createdTanaman = [];
foreach ($validated['points'] as $index => $point) {
$number = $existingCount + $index + 1;
$createdTanaman[] = Tanaman::create([
'uid' => 'TM' . $lahanUidPart . '-' . strtoupper(Str::random(10)),
'nama' => $komoditas->nama . ' - ' . $profileName . ' - ' . $number,
'desa_kelurahan_id' => $validated['desa_kelurahan_id'],
'profile_id' => $validated['profile_id'],
'lahan_id' => $validated['lahan_id'],
'komoditas_id' => $validated['komoditas_id'],
'jenis_komoditas_id' => $validated['jenis_komoditas_id'],
'varietas_id' => $validated['varietas_id'],
'latitude' => $point['latitude'],
'longitude' => $point['longitude'],
'kondisi_tanaman' => $point['kondisi_tanaman'],
'metode_pengumpulan' => $validated['metode_pengumpulan'] ?? 'manual',
'deskripsi' => $validated['deskripsi'] ?? null,
'created_by' => auth()->id(),
'updated_by' => auth()->id(),
]);
}
DB::commit();
return response()->json([
'status' => 'success',
'message' => count($createdTanaman) . ' data tanaman berhasil disimpan.',
'redirect' => route('map-tanaman.index'),
'data' => $createdTanaman,
]);
} catch (\Throwable $e) {
DB::rollBack();
Log::error('Gagal menyimpan tanaman bulk', [
'error' => $e->getMessage(),
'request' => $request->all(),
]);
return response()->json([
'status' => 'error',
'message' => 'Gagal menyimpan data: ' . $e->getMessage(),
], 500);
}
}
public function show(string $id)
{
$group = $this->getTanamanGroupByRepresentativeId($id);
$tanaman = $group['representative']->load([
'profile',
'lahan.desaKelurahan.kecamatan.kabupatenkota.provinsi',
'komoditas',
'jenisKomoditas',
'varietas',
]);
$points = $group['points'];
return view('produktivitas.mapTanaman.view', compact(
'tanaman',
'points'
));
}
public function edit(string $id)
{
$group = $this->getTanamanGroupByRepresentativeId($id);
$tanaman = $group['representative']->load([
'profile',
'lahan.desaKelurahan.kecamatan.kabupatenkota.provinsi',
'komoditas',
'jenisKomoditas',
'varietas',
]);
$points = $group['points'];
return view('produktivitas.mapTanaman.edit', compact(
'tanaman',
'points'
));
}
public function update(Request $request, string $id)
{
$group = $this->getTanamanGroupByRepresentativeId($id);
$representative = $group['representative'];
$validated = $request->validate([
'points' => ['required', 'array', 'min:1'],
'points.*.id' => ['nullable', 'integer', 'exists:map_tanaman,id'],
'points.*.latitude' => ['required', 'numeric'],
'points.*.longitude' => ['required', 'numeric'],
'points.*.kondisi_tanaman' => [
'required',
Rule::in(['sehat', 'sakit', 'mati']),
],
'points.*._delete' => ['nullable'],
]);
try {
DB::beginTransaction();
foreach ($validated['points'] as $point) {
if (!empty($point['_delete']) && !empty($point['id'])) {
$tanaman = Tanaman::where('id', $point['id'])
->where('profile_id', $representative->profile_id)
->where('lahan_id', $representative->lahan_id)
->where('komoditas_id', $representative->komoditas_id)
->where('jenis_komoditas_id', $representative->jenis_komoditas_id)
->where('varietas_id', $representative->varietas_id)
->first();
if ($tanaman) {
$tanaman->deleted_by = auth()->id();
$tanaman->save();
$tanaman->delete();
}
continue;
}
if (!empty($point['id'])) {
$tanaman = Tanaman::where('id', $point['id'])
->where('profile_id', $representative->profile_id)
->where('lahan_id', $representative->lahan_id)
->where('komoditas_id', $representative->komoditas_id)
->where('jenis_komoditas_id', $representative->jenis_komoditas_id)
->where('varietas_id', $representative->varietas_id)
->firstOrFail();
$tanaman->update([
'latitude' => $point['latitude'],
'longitude' => $point['longitude'],
'kondisi_tanaman' => $point['kondisi_tanaman'],
'updated_by' => auth()->id(),
]);
}
}
DB::commit();
return response()->json([
'status' => 'success',
'message' => 'Data titik tanaman berhasil diperbarui.',
'redirect' => route('map-tanaman.index'),
]);
} catch (\Throwable $e) {
DB::rollBack();
return response()->json([
'status' => 'error',
'message' => 'Gagal memperbarui data: ' . $e->getMessage(),
], 500);
}
}
public function destroy(string $id)
{
try {
DB::beginTransaction();
$group = $this->getTanamanGroupByRepresentativeId($id);
$points = $group['points'];
foreach ($points as $point) {
$point->update([
'deleted_by' => auth()->id(),
]);
$point->delete();
}
DB::commit();
return response()->json([
'status' => 'success',
'message' => $points->count() . ' titik tanaman berhasil dihapus.',
]);
} catch (\Throwable $e) {
DB::rollBack();
return response()->json([
'status' => 'error',
'message' => 'Gagal menghapus data: ' . $e->getMessage(),
], 500);
}
}
}
@@ -35,6 +35,25 @@ class ProfileController extends Controller
return view('master.profile.index', compact('profiles', 'provinsi'));
}
public function getByDesaKelurahan($desaId)
{
try {
$profiles = Profile::where('desa_kelurahan_id', $desaId)
->orderBy('nama', 'asc')
->get(['id', 'nama']);
return response()->json([
'status' => 'success',
'data' => $profiles,
]);
} catch (\Throwable $e) {
return response()->json([
'status' => 'error',
'message' => $e->getMessage(),
], 500);
}
}
public function create()
{
$provinsi = Provinsi::orderBy('nama', 'asc')->get();
@@ -54,6 +54,9 @@ class AktivitasController extends Controller
'jenis_aktivitas' => ['required','string','max:255', Rule::in(['tujuan', 'aktivitas']),],
'indikator' => ['required','string'],
'deskripsi' => ['required','string'],
'parent_id' => [
Rule::requiredIf($request->jenis_aktivitas === 'aktivitas'),
'nullable','exists:program_aktivitas,id',],
]);
Aktivitas::create([...$validated,
@@ -125,6 +128,9 @@ class AktivitasController extends Controller
'jenis_aktivitas' => ['required','string','max:255', Rule::in(['tujuan', 'aktivitas']),],
'indikator' => ['required','string'],
'deskripsi' => ['required','string'],
'parent_id' => [
Rule::requiredIf($request->jenis_aktivitas === 'aktivitas'),
'nullable','exists:program_aktivitas,id'],
]);
$aktivitas->update([...$validated,
@@ -102,7 +102,8 @@ class FrameworkController extends Controller
abort(403);
}
$framework = Framework::findOrFail($id);
$framework = Framework::with('transformasi')->with('transformasi.tujuan')
->findOrFail($id);
$program = Program::all();
return view('program.framework.edit', compact('framework', 'program'));
@@ -0,0 +1,208 @@
<?php
namespace App\Http\Controllers\Web\Program;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Gate;
use Illuminate\View\View;
use Illuminate\Http\JsonResponse;
use Illuminate\Support\Facades\DB;
use App\Models\Program\Framework;
use App\Models\Program\Realisasi;
class RealisasiController extends Controller
{
public function index(Request $request): View
{
if (!Gate::any(['super_admin', 'admin'])) {
abort(403);
}
$framework = Framework::when($request->has('frameworkid'), function ($query) use ($request) {
$query->where('id', $request->frameworkid);
})->latest()->first();
if ($framework == null) {
abort(404);
}
$ringkasanIsiRealisasi = DB::select('select count(pt.id) count_target, sum(case when rl.id > 0 then 1 else 0 end) count_realisasi
from program_target pt
inner join program_aktivitas pa on pt.aktivitas_id = pa.id
inner join program_transformasi ptr on pa.transformasi_id = ptr.id
inner join program_framework pf on ptr.framework_id = pf.id
left join
(select target_id, max(id) id from program_realisasi pr
group by target_id) rl on pt.id = rl.target_id
where
pt.deleted_at is null
and pa.deleted_at is null
and ptr.deleted_at is null
and pf.id = ?
', [$framework->id]);
$ringkasanIsiRealisasi = collect($ringkasanIsiRealisasi)->map(function ($item) {
$item->persentase = $item->count_target > 0 ? round(($item->count_realisasi / $item->count_target) * 100, 2) : 0;
return $item;
})->first();
$ringkasanCapaianRealisasi = DB::select("select round(avg(percent_realisasi)::numeric * 100, 2) persentase,
sum(case when percent_realisasi >= 0.8 then 1 else 0 end) capaian_80,
sum(case when percent_realisasi >= 0.5 and percent_realisasi < 0.8 then 1 else 0 end) capaian_50_80,
sum(case when percent_realisasi < 0.5 then 1 else 0 end) capaian_50
from
(select pt.id target_id, pr.id realisasi_id,
pt.tipe,
case
when pt.tipe = 'integer' then pt.target_integer
when pt.tipe = 'float' then pt.target_float
when pt.tipe = 'boolean' then pt.target_boolean::integer
end target,
case
when pt.tipe = 'integer' then pr.realisasi_integer
when pt.tipe = 'float' then pr.realisasi_float
when pt.tipe = 'boolean' then pr.realisasi_boolean::integer
end realisasi,
case
when pt.tipe = 'integer' then pr.realisasi_integer::float / pt.target_integer::float
when pt.tipe = 'float' then pr.realisasi_float / pt.target_float
when pt.tipe = 'boolean' then pr.realisasi_boolean::integer / pt.target_boolean::integer
end percent_realisasi
from program_target pt
inner join program_aktivitas pa on pt.aktivitas_id = pa.id
inner join program_transformasi ptr on pa.transformasi_id = ptr.id
inner join program_framework pf on ptr.framework_id = pf.id
left join
(select target_id, max(id) id from program_realisasi pr
group by target_id) rl on pt.id = rl.target_id
left join program_realisasi pr on rl.id = pr.id and pr.target_id = pt.id
where
pt.deleted_at is null
and pa.deleted_at is null
and ptr.deleted_at is null
and pf.id = ?) v",
[$framework->id]);
$ringkasanCapaianRealisasi = collect($ringkasanCapaianRealisasi)->first();
$ringkasanVerifikasi = DB::select("select count(pt.id) count_target,
sum(case when count_verifikasi > 0 then 1 else 0 end) count_verifikasi,
sum(case when count_verifikasi = 0 or count_verifikasi is null then 1 else 0 end) count_unverifikasi
from program_target pt
inner join program_aktivitas pa on pt.aktivitas_id = pa.id
inner join program_transformasi ptr on pa.transformasi_id = ptr.id
inner join program_framework pf on ptr.framework_id = pf.id
left join
(select target_id, max(id) id from program_realisasi pr
group by target_id) rl on pt.id = rl.target_id
left join
(select realisasi_id, count(pv.id) count_verifikasi from program_verifikasi pv
group by realisasi_id) rv
on rv.realisasi_id = rl.id
where
pt.deleted_at is null
and pa.deleted_at is null
and ptr.deleted_at is null
and pf.id = ?",
[$framework->id]);
$ringkasanVerifikasi = collect($ringkasanVerifikasi)->map(function ($item) {
$item->persentase = $item->count_target > 0 ? round(($item->count_verifikasi / $item->count_target) * 100, 2) : 0;
return $item;
})->first();
return view('program.realisasi.index', compact('framework', 'ringkasanIsiRealisasi', 'ringkasanCapaianRealisasi', 'ringkasanVerifikasi'));
}
public function create()
{
//
}
public function store(Request $request): JsonResponse
{
if (!Gate::any(['super_admin', 'admin'])) {
abort(403);
}
$validated = $request->validate([
'target_id' => ['required', 'integer', 'exists:program_target,id'],
'realisasi_integer' => ['nullable', 'integer'],
'realisasi_float' => ['nullable', 'numeric'],
'realisasi_boolean' => ['nullable', 'boolean'],
]);
$realisasi = Realisasi::create([...$validated,
'created_by' => auth()->id(),
'updated_by' => auth()->id()
]);
return response()->json([
'status' => 'success',
'message' => 'Target berhasil ditambahkan.'
], 201);
}
public function show(string $id)
{
if (!Gate::any(['super_admin', 'admin'])) {
abort(403);
}
$realisasi = Realisasi::with('target', 'target.aktivitas', 'target.aktivitas.transformasi', 'verifikasi')
->find($id);
if (!$realisasi) {
return response()->json([
'status' => 'error',
'message' => 'Data realisasi tidak ditemukan.'
], 404);
}
return response()->json([
'status' => 'success',
'data' => $realisasi
]);
}
public function edit(string $id)
{
//
}
public function update(Request $request, string $id): JsonResponse
{
if (!Gate::any(['super_admin', 'admin'])) {
abort(403);
}
$realisasi = Realisasi::find($id);
if (!$realisasi) {
return response()->json([
'status' => 'error',
'message' => 'Data realisasi tidak ditemukan.'
], 404);
}
$validated = $request->validate([
'target_id' => ['required', 'integer', 'exists:program_target,id'],
'realisasi_integer' => ['nullable', 'integer'],
'realisasi_float' => ['nullable', 'numeric'],
'realisasi_boolean' => ['nullable', 'boolean'],
]);
$realisasi->update([...$validated,
'updated_by' => auth()->id(),
]);
return response()->json([
'status' => 'success',
'message' => 'Target berhasil diperbarui.'
], 200);
}
/**
* Remove the specified resource from storage.
*/
public function destroy(string $id)
{
//
}
}
@@ -69,6 +69,16 @@ class TargetController extends Controller
'nullable',
'boolean'
],
'tipe_realisasi' => [
'nullable',
'string',
Rule::in(['manual', 'referensi'])
],
'value_query' => [
Rule::requiredIf($request->tipe_realisasi === 'referensi'),
'nullable',
'string'
]
]);
}
@@ -77,9 +87,6 @@ class TargetController extends Controller
}
/**
* Store a newly created resource in storage.
*/
public function store(Request $request, string $frameworkId, string $transformasiId, string $aktivitasId): JsonResponse
{
if (!Gate::any(['super_admin', 'admin'])) {
@@ -109,12 +116,32 @@ class TargetController extends Controller
], 201);
}
/**
* Display the specified resource.
*/
public function show(string $id)
public function show(string $frameworkId, string $transformasiId, string $aktivitasId, string $id)
{
//
if (!Gate::any(['super_admin', 'admin'])) {
abort(403);
}
$target = Target::with('realisasi', 'latestRealisasi')
->whereHas('aktivitas.transformasi', function ($query) use ($frameworkId) {
$query->where('framework_id', $frameworkId);
})
->whereHas('aktivitas', function ($query) use ($transformasiId) {
$query->where('transformasi_id', $transformasiId);
})
->where('aktivitas_id', $aktivitasId)->find($id);
if (!$target) {
return response()->json([
'status' => 'error',
'message' => 'Data target tidak ditemukan.'
], 404);
}
return response()->json([
'status' => 'success',
'data' => $target
]);
}
/**
@@ -128,16 +155,67 @@ class TargetController extends Controller
/**
* Update the specified resource in storage.
*/
public function update(Request $request, string $id)
public function update(Request $request, string $frameworkId, string $transformasiId, string $aktivitasId, string $id)
{
//
if (!Gate::any(['super_admin', 'admin'])) {
abort(403);
}
$target = Target::whereHas('aktivitas.transformasi', function ($query) use ($frameworkId) {
$query->where('framework_id', $frameworkId);
})
->whereHas('aktivitas', function ($query) use ($transformasiId) {
$query->where('transformasi_id', $transformasiId);
})
->where('aktivitas_id', $aktivitasId)->find($id);
if (!$target) {
return response()->json([
'status' => 'error',
'message' => 'Data target tidak ditemukan.'
], 404);
}
$validated = $this->validated($request);
$target->update([...$validated,
'updated_by' => auth()->id(),
]);
return response()->json([
'status' => 'success',
'message' => 'Target berhasil diperbarui.'
], 200);
}
/**
* Remove the specified resource from storage.
*/
public function destroy(string $id)
public function destroy(string $frameworkId, string $transformasiId, string $aktivitasId, string $id)
{
//
if (!Gate::any(['super_admin', 'admin'])) {
abort(403);
}
$target = Target::whereHas('aktivitas.transformasi', function ($query) use ($frameworkId) {
$query->where('framework_id', $frameworkId);
})
->whereHas('aktivitas', function ($query) use ($transformasiId) {
$query->where('transformasi_id', $transformasiId);
})
->where('aktivitas_id', $aktivitasId)->find($id);
if (!$target) {
return response()->json([
'status' => 'error',
'message' => 'Data target tidak ditemukan.'
], 404);
}
$target->update([
'deleted_by' => auth()->id(),
]);
$target->delete();
return response()->json([
'status' => 'success',
'message' => 'Target berhasil dihapus.'
], 200);
}
}
@@ -0,0 +1,107 @@
<?php
namespace App\Http\Controllers\Web\Program;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Gate;
use Illuminate\View\View;
use Illuminate\Http\JsonResponse;
use App\Models\Program\Framework;
use App\Models\Program\Realisasi;
use App\Models\Program\Verifikasi;
class VerifikasiController extends Controller
{
/**
* Display a listing of the resource.
*/
public function index(Request $request): JsonResponse
{
}
/**
* Show the form for creating a new resource.
*/
public function create()
{
//
}
/**
* Store a newly created resource in storage.
*/
public function store(Request $request): JsonResponse
{
if (!Gate::any(['super_admin', 'admin'])) {
abort(403);
}
$validated = $request->validate([
'realisasi_id' => ['required', 'integer', 'exists:program_realisasi,id'],
'dokumen' => ['required', 'string'],
'link_dokumen' => ['required', 'url'],
]);
$verifikasi = Verifikasi::create([...$validated,
'created_by' => auth()->id(),
'updated_by' => auth()->id()
]);
return response()->json([
'status' => 'success',
'message' => 'Dokumen bukti berhasil ditambahkan.'
], 201);
}
/**
* Display the specified resource.
*/
public function show(string $id): JsonResponse
{
//
}
/**
* Show the form for editing the specified resource.
*/
public function edit(string $id)
{
//
}
/**
* Update the specified resource in storage.
*/
public function update(Request $request, string $id)
{
//
}
/**
* Remove the specified resource from storage.
*/
public function destroy(string $id): JsonResponse
{
if (!Gate::any(['super_admin', 'admin'])) {
abort(403);
}
$verifikasi = Verifikasi::find($id);
if (!$verifikasi) {
return response()->json([
'status' => 'error',
'message' => 'Data verifikasi tidak ditemukan.'
], 404);
}
$verifikasi->update(['updated_by' => auth()->id()]);
$verifikasi->delete();
return response()->json([
'status' => 'success',
'message' => 'Dokumen bukti berhasil dihapus.'
]);
}
}
@@ -49,6 +49,7 @@ class ProgramController extends Controller
'sub_domain' => ['required', Rule::unique(Program::class, 'sub_domain')],
'tahun' => ['required', 'integer'],
'instansi' => ['nullable', 'string'],
'nama_singkat' => ['required', 'string'],
]);
if ($validator->fails()) {
@@ -94,6 +95,9 @@ class ProgramController extends Controller
$validator = Validator::make($request->all(), [
'nama' => ['required'],
'sub_domain' => ['required', Rule::unique(Program::class, 'sub_domain')->ignore($id)],
'tahun' => ['required', 'integer'],
'instansi' => ['nullable', 'string'],
'nama_singkat' => ['required', 'string'],
]);
if ($validator->fails()) {
@@ -106,9 +110,7 @@ class ProgramController extends Controller
return redirect()->route('program.index')->with('error', 'Data program tidak ditemukan!');
}
$program->update([
'nama' => $request->nama,
'sub_domain' => $request->sub_domain,
$program->update([...$validator->validated(),
'updated_by' => auth()->id(),
]);
@@ -0,0 +1,27 @@
<?php
namespace App\Http\Resources\Core;
use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\JsonResource;
use App\Http\Resources\Pertanian\KomoditasResource;
class ProgramKomoditasResource extends JsonResource
{
/**
* Transform the resource into an array.
*
* @return array<string, mixed>
*/
public function toArray(Request $request): array
{
return [
'id' => $this->id,
'program_id' => $this->program_id,
'komoditas_id' => $this->komoditas_id,
'default' => $this->default,
'komoditas' => $this->komoditas ? new KomoditasResource($this->komoditas) : null,
];
}
}
@@ -0,0 +1,36 @@
<?php
namespace App\Http\Resources\Core;
use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\JsonResource;
use App\Http\Resources\Wilayah\ProvinsiResource;
use App\Http\Resources\Wilayah\KabupatenKotaResource;
use App\Http\Resources\Wilayah\KecamatanResource;
use App\Http\Resources\Wilayah\DesaKelurahanResource;
class ProgramLokasiResource extends JsonResource
{
/**
* Transform the resource into an array.
*
* @return array<string, mixed>
*/
public function toArray(Request $request): array
{
return [
'id' => $this->id,
'program_id' => $this->program_id,
'provinsi_id' => $this->provinsi_id,
'kabupaten_kota_id' => $this->kabupaten_kota_id,
'kecamatan_id' => $this->kecamatan_id,
'desa_kelurahan_id' => $this->desa_kelurahan_id,
'default' => $this->default,
'provinsi' => $this->provinsi ? new ProvinsiResource($this->provinsi) : null,
'kabupatenKota' => $this->kabupatenKota ? new KabupatenKotaResource($this->kabupatenKota) : null,
'kecamatan' => $this->kecamatan ? new KecamatanResource($this->kecamatan) : null,
'desaKelurahan' => $this->desaKelurahan ? new DesaKelurahanResource($this->desaKelurahan) : null,
];
}
}
@@ -0,0 +1,34 @@
<?php
namespace App\Http\Resources\Core;
use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\JsonResource;
use App\Http\Resources\Core\ProgramKomoditasResource;
use App\Http\Resources\Core\ProgramLokasiResource;
class ProgramResource extends JsonResource
{
/**
* Transform the resource into an array.
*
* @return array<string, mixed>
*/
public function toArray(Request $request): array
{
return [
'id' => $this->id,
'nama' => $this->nama,
'sub_domain' => $this->sub_domain,
'tahun' => $this->tahun,
'instansi' => $this->instansi,
'nama_singkat' => $this->nama_singkat,
'komoditas' => $this->komoditas()->with('komoditas')->get()->map(function ($item) {
return new ProgramKomoditasResource($item);
}),
'lokasi' => $this->lokasi()->with(['provinsi', 'kabupatenKota', 'kecamatan', 'desaKelurahan'])->get()->map(function ($item) {
return new ProgramLokasiResource($item);
}),
];
}
}
@@ -0,0 +1,32 @@
<?php
namespace App\Http\Resources\Ekosistem;
use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\JsonResource;
use App\Http\Resources\Ekosistem\KolomBasisDataResource;
class FormBasisDataResource extends JsonResource
{
/**
* Transform the resource into an array.
*
* @return array<string, mixed>
*/
public function toArray(Request $request): array
{
return [
'id' => $this->id,
'tabel_id' => $this->tabel_id,
'parent_id' => $this->parent_id,
'tipe' => $this->tipe,
'column_width' => $this->column_width,
'kolom_id' => $this->kolom_id,
'section_label' => $this->section_label,
'urutan' => $this->urutan,
'kolom' => new KolomBasisDataResource($this->whenLoaded('kolom')),
'form' => FormBasisDataResource::collection($this->whenLoaded('form')),
];
}
}
@@ -0,0 +1,32 @@
<?php
namespace App\Http\Resources\Ekosistem;
use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\JsonResource;
class KolomBasisDataResource extends JsonResource
{
/**
* Transform the resource into an array.
*
* @return array<string, mixed>
*/
public function toArray(Request $request): array
{
return [
'id' => $this->id,
'label' => $this->label,
'kolom' => $this->kolom,
'tipe' => $this->tipe,
'validasi' => $this->validasi,
'urutan' => $this->urutan,
'relasi_tabel' => $this->relasi_tabel,
'relasi_kolom_id' => $this->relasi_kolom_id,
'relasi_kolom_label' => $this->relasi_kolom_label,
'enum_opsi' => $this->enum_opsi,
'is_active' => $this->is_active,
'is_browse' => $this->is_browse,
];
}
}
@@ -0,0 +1,35 @@
<?php
namespace App\Http\Resources\Ekosistem;
use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\JsonResource;
use App\Models\Ekosistem\TabelBasisData;
use App\Models\Ekosistem\KolomBasisData;
use App\Http\Resources\Ekosistem\KolomBasisDataResource;
class TabelBasisDataResource extends JsonResource
{
/**
* Transform the resource into an array.
*
* @return array<string, mixed>
*/
public function toArray(Request $request): array
{
return [
'id' => $this->id,
'tabel' => $this->tabel,
'label' => $this->label,
'menu' => $this->menu,
'deskripsi' => $this->deskripsi,
// 'group_id' => $this->group_id,
'urutan' => $this->urutan,
// 'group' => new GroupBasisDataResource($this->whenLoaded('group')),
'kolom' => KolomBasisDataResource::collection($this->whenLoaded('kolom')),
//'ringkasan' => RingkasanBasisDataResource::collection($this->whenLoaded('ringkasan')),
'form' => FormBasisDataResource::collection($this->whenLoaded('form')),
];
}
}
@@ -0,0 +1,34 @@
<?php
namespace App\Http\Resources\Ekosistem;
use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\JsonResource;
class ValueBasisDataResource extends JsonResource
{
/**
* Transform the resource into an array.
*
* @return array<string, mixed>
*/
public function toArray(Request $request): array
{
return [
'id' => $this->id,
'program_id' => $this->program_id,
'tabel_id' => $this->tabel_id,
'kolom_id' => $this->kolom_id,
'value_id' => $this->value_id,
'value_varchar' => $this->value_varchar,
'value_integer' => $this->value_integer,
'value_float' => $this->value_float,
'value_boolean' => $this->value_boolean,
'value_date' => $this->value_date,
'value_datetime' => $this->value_datetime,
'value_text' => $this->value_text,
'value_relasi' => $this->value_relasi,
'value_enum' => $this->value_enum,
];
}
}
@@ -0,0 +1,26 @@
<?php
namespace App\Http\Resources\Pertanian;
use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\JsonResource;
class JenisKomoditasResource extends JsonResource
{
/**
* Transform the resource into an array.
*
* @return array<string, mixed>
*/
public function toArray(Request $request): array
{
return [
'id' => $this->id,
'nama' => $this->nama,
'kode' => $this->kode,
'keterangan' => $this->keterangan,
'created_at' => $this->created_at?->toIso8601String(),
'updated_at' => $this->updated_at?->toIso8601String(),
];
}
}
@@ -25,6 +25,7 @@ class LahanResource extends JsonResource
'luas_lahan' => $this->luas_lahan,
'keluarga_pengelola_id' => $this->keluarga_pengelola_id,
'adat_pemilik_id' => $this->adat_pemilik_id,
'uid' => $this->uid,
];
}
}
@@ -24,6 +24,7 @@ class TanamanResource extends JsonResource
'latitude' => $this->latitude,
'longitude' => $this->longitude,
'kondisi_tanaman' => $this->kondisi_tanaman,
'uid' => $this->uid,
];
}
}
+2
View File
@@ -7,6 +7,7 @@ use Illuminate\Http\Resources\Json\JsonResource;
use App\Http\Resources\Wilayah\DesaKelurahanResource;
use App\Http\Resources\UserResource;
use phpDocumentor\Reflection\Types\This;
class ProfileResource extends JsonResource
{
@@ -31,6 +32,7 @@ class ProfileResource extends JsonResource
'desa_kelurahan_id' => $this->desa_kelurahan_id,
'desa_kelurahan' => $this->desaKelurahan ? new DesaKelurahanResource($this->desaKelurahan) : null,
'user' => $this->user ? new UserResource($this->user) : null,
'user_uid' => $this->user_uid,
];
}
}
+1
View File
@@ -20,6 +20,7 @@ class UserResource extends JsonResource
'email' => $this->email,
'email_verified_at' => $this->email_verified_at,
'role' => $this->role,
'uid' => $this->uid,
];
}
}
+1
View File
@@ -20,6 +20,7 @@ class Program extends Model
"sub_domain",
"tahun",
"instansi",
"nama_singkat",
];
public function komoditas(): HasMany
+383
View File
@@ -0,0 +1,383 @@
<?php
namespace App\Models\Ekosistem;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Casts\Attribute;
use Illuminate\Support\Str;
use App\Models\Ekosistem\TabelBasisData;
use App\Enums\LayoutForm;
class FormBasisData extends Model
{
use SoftDeletes;
protected $table = 'ekosistem_basis_data_form';
protected $fillable = [
'tabel_id',
'parent_id',
'tipe',
'column_width',
'kolom_id',
'section_label',
'urutan',
'created_by',
'updated_by',
'deleted_by',
];
protected $casts = [
'tipe' => LayoutForm::class
];
protected static function booted()
{
static::creating(function ($model) {
$max = self::where('tabel_id', $model->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');
}
public function form(): HasMany
{
return $this->hasMany(FormBasisData::class, 'parent_id')
->with('form')
->orderBy('urutan');
}
public function kolom(): BelongsTo
{
return $this->belongsTo(KolomBasisData::class, 'kolom_id');
}
public function renderHtml(string $state, $errors = null, $optionsFK = null, $values = null, $framework = 'bootstrap'): string
{
if ($framework == 'tailwind') {
return match ($this->tipe) {
LayoutForm::COLUMN => '<div className="space-y-2 form-control-validation">'
.$this->childHtml($state, $errors, $optionsFK, $values, $framework).'</div>',
LayoutForm::VALUE => $this->value($state, $errors, $optionsFK, $values, $framework),
LayoutForm::SECTION => '<h3 className="font-semibold text-lg text-slate-900">'.$this->section_label.'</h3>',
LayoutForm::ROW => '<div className="grid grid-cols-1 gap-5">'.$this->childHtml($state, $errors, $optionsFK, $values, $framework).'</div>',
LayoutForm::HR_LINE => '<hr/>',
default => ''
};
} else {
return match ($this->tipe) {
LayoutForm::COLUMN => '<div class="col-'.($this->column_width ?? 3).' mb-4 form-control-validation">'
.$this->childHtml($state, $errors, $optionsFK, $values, $framework).'</div>',
LayoutForm::VALUE => $this->value($state, $errors, $optionsFK, $values, $framework),
LayoutForm::SECTION => '<h6 class="mb-3">'.$this->section_label.'</h6>',
LayoutForm::ROW => '<div class="row">'.$this->childHtml($state, $errors, $optionsFK, $values, $framework).'</div>',
LayoutForm::HR_LINE => '<hr/>',
default => ''
};
}
}
private function childHtml(string $state, $errors = null, $optionsFK = null, $values = null, $framework = 'bootstrap'): string
{
$html = '';
foreach ($this->form as $form) {
$html .= $form->renderHtml($state, $errors, $optionsFK, $values, $framework);
}
return $html;
}
private function value(string $state, $errors = null, $optionsFK = null, $values = null, $framework = 'bootstrap'): string
{
$html = '';
if ($this->kolom) {
$k = $this->kolom;
$value = $values ? $values->where('kolom_id', $k->id)->first() : null;
$oldValue = old($k->kolom);
if ($framework == 'tailwind') {
$html .= '<Label htmlFor="label" className="text-sm font-medium text-slate-700">kolom_required'.$this->kolom->label;
$html .= '</Label>';
} else {
$html .= '<label class="form-label" for="value-data-kolom_name">kolom_required'.$this->kolom->label;
$html .= '</label>';
}
if($k->tipe == 'varchar') {
if ($framework == 'tailwind') {
$html .= '<Input className="form-control kolom_error h-11" id="value-data-kolom_name" readonly
name="kolom_name" value="kolom_value" />';
} else {
$html .= '<input type="text" class="form-control kolom_error" id="value-data-kolom_name" readonly
name="kolom_name" value="kolom_value" />';
}
}
elseif($k->tipe == 'text') {
if ($framework == 'tailwind') {
$html .= '<Textarea className="form-control kolom_error h-11" id="value-data-kolom_name" readonly
name="kolom_name">kolom_value</Textarea>';
} else {
$html .= '<textarea class="form-control kolom_error" id="value-data-kolom_name" readonly
name="kolom_name">kolom_value</textarea>';
}
}
elseif($k->tipe == 'integer') {
if ($framework == 'tailwind') {
$html .= '<Input type="number" className="form-control kolom_error h-11" id="value-data-kolom_name" readonly
name="kolom_name" step="1" value="kolom_value" />';
} else {
$html .= '<input type="number" class="form-control" id="value-data-kolom_name" readonly
name="kolom_name" step="1" value="kolom_value" />';
}
}
elseif($k->tipe == 'float') {
if ($framework == 'tailwind') {
$html .= '<Input className="form-control kolom_error h-11" id="value-data-kolom_name" readonly
name="kolom_name" value="kolom_value" step="any" />';
} else {
$html .= '<input type="number" class="form-control kolom_error" id="add-data-kolom_name" readonly
name="kolom_name" value="kolom_value" step="any" />';
}
}
elseif($k->tipe == 'date') {
if ($framework == 'tailwind') {
$html .= '<Input type="date" className="form-control kolom_error h-11" id="value-data-kolom_name" readonly
name="kolom_name" value="kolom_value" />';
} else {
$html .= '<input type="date" class="form-control kolom_error" id="value-data-kolom_name" readonly
name="kolom_name" value="kolom_value" />';
}
}
elseif($k->tipe == 'datetime'){
if ($framework == 'tailwind') {
$html .= '<Input type="datetime-local" className="form-control kolom_error h-11" id="value-data-kolom_name" readonly
name="kolom_name" value="kolom_value" />';
} else {
$html .= '<input type="datetime-local" class="form-control kolom_error" id="value-data-kolom_name" readonly
name="kolom_name" value="kolom_value" />';
}
}
elseif($k->tipe == 'boolean') {
if ($state == 'preview' || $state == 'view') {
if ($framework == 'tailwind') {
$html .= '<Input type="text" className="form-control kolom_error h-11" id="value-data-kolom_name" readonly
name="kolom_name" value="kolom_value" />';
} else {
$html .= '<input type="text" class="form-control kolom_error" id="value-data-kolom_name" readonly
name="kolom_name" value="kolom_value" />';
}
} elseif ($state == 'add') {
if ($framework == 'tailwind') {
$html .= '<Select value="kolom_value">
<SelectTrigger className="border-slate-200 focus:ring-emerald-500 rounded-xl h-11 bg-white text-left">
<SelectValue />
</SelectTrigger>
<SelectContent className="rounded-xl">
<SelectItem value="1" className="rounded-lg">Ya</SelectItem>
<SelectItem value="0" className="rounded-lg">Tidak</SelectItem>
</SelectContent>
</Select>';
} else {
$html .= '<select class="form-select tipe-boolean kolom_error" id="value-data-kolom_name" name="kolom_name">
<option value="1" '. (old($k->kolom) == 1 ? 'selected' : '') .'>Ya</option>
<option value="0" '. (old($k->kolom) == 0 ? 'selected' : '') .'>Tidak</option>
</select>';
}
} elseif ($state == 'edit') {
if ($framework == 'tailwind') {
$html .= '<Select value="kolom_value">
<SelectTrigger className="border-slate-200 focus:ring-emerald-500 rounded-xl h-11 bg-white text-left">
<SelectValue />
</SelectTrigger>
<SelectContent className="rounded-xl">
<SelectItem value="1" className="rounded-lg">Ya</SelectItem>
<SelectItem value="0" className="rounded-lg">Tidak</SelectItem>
</SelectContent>
</Select>';
} else {
$html .= '<select class="form-select tipe-boolean kolom_error" id="value-data-kolom_name" name="kolom_name">
<option value="1" '. ((old($k->kolom) ?? (($value ? $value['value_'.$k->tipe] : null) ?? null) == 1) ? 'selected' : '') .'>Ya</option>
<option value="0" '. ((old($k->kolom) ?? (($value ? $value['value_'.$k->tipe] : null) ?? null) == 0) ? 'selected' : '') .'>Tidak</option>
</select>';
}
}
}
elseif($k->tipe == 'foreign_key') {
if ($state == 'preview' || $state == 'view') {
if ($framework == 'tailwind') {
$html .= '<Input type="text" className="form-control kolom_error h-11" id="value-data-kolom_name" readonly
name="kolom_name" value="kolom_value" />';
} else {
$html .= '<input type="text" class="form-control kolom_error" id="value-data-kolom_name" readonly
name="kolom_name" value="kolom_value" />';
}
} elseif ($state == 'add') {
if ($framework == 'tailwind') {
$html .= '<Select value="kolom_value" id="value-data-kolom_name" name="kolom_name" className="form-select tipe-foreign_key kolom_error">
<SelectTrigger className="border-slate-200 focus:ring-emerald-500 rounded-xl h-11 bg-white text-left">
<SelectValue />
</SelectTrigger>';
if ($optionsFK && $optionsFK->where('kolom_id', $k->id)->first() != null) {
foreach ($optionsFK->where('kolom_id', $k->id)->first()['options'] as $option) {
$html .= '<SelectContent className="rounded-xl">
<SelectItem value="'.$option->value.'" className="rounded-lg">'.$option->label.'</SelectItem>
</SelectContent>';
}
}
$html .= '</Select>';
} else {
$html .= '<select class="form-select tipe-foreign_key kolom_error" id="value-data-kolom_name" name="kolom_name">';
if ($optionsFK && $optionsFK->where('kolom_id', $k->id)->first() != null) {
foreach ($optionsFK->where('kolom_id', $k->id)->first()['options'] as $option) {
$html .= '<option value="'.$option->value.'" '.(old($k->kolom) == $option->value ? 'selected' : '').'>'.$option->label.'</option>';
}
}
$html .= '</select>';
}
} elseif ($state == 'edit') {
if ($framework == 'tailwind') {
$html .= '<Select value="kolom_value" id="value-data-kolom_name" name="kolom_name" className="form-select tipe-foreign_key kolom_error">
<SelectTrigger className="border-slate-200 focus:ring-emerald-500 rounded-xl h-11 bg-white text-left">
<SelectValue />
</SelectTrigger>';
if ($optionsFK && $optionsFK->where('kolom_id', $k->id)->first() != null) {
foreach ($optionsFK->where('kolom_id', $k->id)->first()['options'] as $option) {
$html .= '<SelectContent className="rounded-xl">
<SelectItem value="'.$option->value.'" className="rounded-lg" '.(old($k->kolom) ?? ($value ? ($value['value_relasi'] == $option->value) : null) ? 'selected' : '') .'>'.$option->label.'</SelectItem>
</SelectContent>';
}
}
$html .= '</Select>';
} else {
$html .= '<select class="form-select tipe-foreign_key kolom_error" id="value-data-kolom_name" name="kolom_name">';
if ($optionsFK && $optionsFK->where('kolom_id', $k->id)->first() != null) {
foreach ($optionsFK->where('kolom_id', $k->id)->first()['options'] as $option) {
$html .= '<option value="'.$option->value.'" '.(old($k->kolom) ?? ($value ? $value['value_relasi'] : null) == $option->value ? 'selected' : '').'>'.$option->label.'</option>';
}
}
$html .= '</select>';
}
}
}
elseif($k->tipe == 'enum') {
if ($state == 'preview' || $state == 'view') {
if ($framework == 'tailwind') {
$html .= '<Input type="text" className="form-control kolom_error h-11" id="value-data-kolom_name" readonly
name="kolom_name" value="kolom_value" />';
} else {
$html .= '<input type="text" class="form-control kolom_error" id="value-data-kolom_name" readonly
name="kolom_name" value="kolom_value" />';
}
} elseif ($state == 'add') {
if ($framework == 'tailwind') {
$html .= '<Select value="kolom_value" id="value-data-kolom_name" name="kolom_name" className="form-select tipe-enum kolom_error">
<SelectTrigger className="border-slate-200 focus:ring-emerald-500 rounded-xl h-11 bg-white text-left">
<SelectValue />
</SelectTrigger>';
foreach($k->enum_opsi as $opsi) {
$html .= '<SelectContent className="rounded-xl">
<SelectItem value="'.$opsi['value'].'" className="rounded-lg">'.$opsi['label'].'</SelectItem>
</SelectContent>';
}
$html .= '</Select>';
} else {
$html .= '<select class="form-select tipe-enum kolom_error" id="value-data-kolom_name" name="kolom_name">';
foreach($k->enum_opsi as $opsi) {
$html .= '<option value="' .$opsi['value']. '" ' .(old($k->kolom) == $opsi['value'] ? 'selected' : ''). '>' .$opsi['label']. '</option>';
}
$html .= '</select>';
}
} elseif ($state == 'edit') {
if ($framework == 'tailwind') {
$html .= '<Select value="kolom_value" id="value-data-kolom_name" name="kolom_name" className="form-select tipe-enum kolom_error">
<SelectTrigger className="border-slate-200 focus:ring-emerald-500 rounded-xl h-11 bg-white text-left">
<SelectValue />
</SelectTrigger>';
foreach($k->enum_opsi as $opsi) {
$html .= '<SelectContent className="rounded-xl">
<SelectItem value="'.$opsi['value'].'" className="rounded-lg">'.$opsi['label'].'</SelectItem>
</SelectContent>';
}
$html .= '</Select>';
} else {
$html .= '<select class="form-select tipe-enum kolom_error" id="value-data-kolom_name" name="kolom_name">';
foreach($k->enum_opsi as $opsi) {
$html .= '<option value="' .$opsi['value']. '" ' .(old($k->kolom) ?? ($value ? $value['value_'.$k->tipe] : null) == $opsi['value'] ? 'selected' : ''). '>' .$opsi['label']. '</option>';
}
$html .= '</select>';
}
}
}
else {
if ($framework == 'tailwind') {
$html .= '<Input type="text" className="form-control kolom_error h-11" id="value-data-kolom_name" readonly
name="kolom_name" value="kolom_value" />';
} else {
$html .= '<input type="text" class="form-control kolom_error" id="value-data-kolom_name" readonly
name="kolom_name" value="kolom_value" />';
}
}
$errorClass = $errors && $errors->has($k->kolom)
? 'is-invalid'
: '';
if ($state == 'preview') {
$html = Str::of($html)
->replace('kolom_value', '')
->replace('kolom_name', $k->kolom)
->replace('kolom_error', '')
->replace('kolom_required', '');
} elseif ($state == 'add') {
$html = Str::of($html)
->replace('kolom_value', e($oldValue))
->replace('kolom_name', $k->kolom)
->replace('kolom_error', $errorClass)
->replace('kolom_required', '')
->replace('readonly', '');
} elseif ($state == 'edit') {
$html = Str::of($html)
->replace('kolom_value', e($oldValue ?? ($value ? ($value['value_'.$k->tipe]) : null)))
->replace('kolom_name', $k->kolom)
->replace('kolom_error', $errorClass)
->replace('kolom_required', '')
->replace('readonly', '');
} elseif ($state == 'view') {
$html = Str::of($html)
->replace('kolom_name', $k->kolom)
->replace('kolom_error', '')
->replace('kolom_required', '');
if ($k->tipe == 'boolean') {
$html = Str::of($html)
->replace('kolom_value', e($value ? ($value['value_'.$k->tipe] == 1 ? 'Ya' : 'Tidak') : null));
} elseif($k->tipe == 'foreign_key') {
$html = Str::of($html)
->replace('kolom_value', e($value ? $value['value_relasi_label'] : null));
} elseif($k->tipe == 'enum') {
$html = Str::of($html)
->replace('kolom_value', e($value ? $value['value_enum_label'] : null));
} else {
$html = Str::of($html)
->replace('kolom_value', e($value ? $value['value_'.$k->tipe] : null));
}
}
}
return $html;
}
}
+20
View File
@@ -7,10 +7,14 @@ use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasOne;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Casts\Attribute;
use App\Models\Ekosistem\KolomBasisData;
use App\Models\Ekosistem\GroupBasisData;
use App\Models\Ekosistem\RingkasanBasisData;
use App\Models\Ekosistem\FormBasisData;
class TabelBasisData extends Model
{
@@ -53,4 +57,20 @@ class TabelBasisData extends Model
{
return $this->hasMany(RingkasanBasisData::class, 'tabel_id')->orderBy('urutan');
}
public function form(): HasMany
{
return $this->hasMany(FormBasisData::class, 'tabel_id')
->whereNull('parent_id')
->orderBy('urutan');
}
public function renderHtml(string $state, $errors = null, $optionsFK = null, $values = null): string
{
$html = '';
foreach ($this->form as $form) {
$html .= $form->renderHtml($state, $errors, $optionsFK, $values);
}
return $html;
}
}
+1
View File
@@ -17,6 +17,7 @@ class Lahan extends Model
'status_kepemilikan',
'profile_id',
'desa_kelurahan_id',
'uid',
'path',
'luas_lahan',
'created_by',
+33
View File
@@ -0,0 +1,33 @@
<?php
namespace App\Models\Master;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\SoftDeletes;
use App\Models\Pertanian\Komoditas;
class JenisKomoditas extends Model
{
use HasFactory, SoftDeletes;
protected $table = 'jenis_komoditas';
protected $fillable = [
'nama',
'komoditas_id',
'created_by',
'updated_by',
'deleted_by',
];
public function komoditas()
{
return $this->belongsTo(Komoditas::class, 'komoditas_id');
}
public function varietas()
{
return $this->hasMany(Varietas::class, 'jenis_komoditas_id');
}
}
+33
View File
@@ -0,0 +1,33 @@
<?php
namespace App\Models\Master;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\SoftDeletes;
use App\Models\Pertanian\Komoditas;
use App\Models\Master\JenisKomoditas;
class Varietas extends Model
{
protected $table = 'master_varietas';
protected $fillable = [
'komoditas_id',
'jenis_komoditas_id',
'nama',
'deskripsi',
'created_by',
'updated_by',
];
public function jenisKomoditas()
{
return $this->belongsTo(JenisKomoditas::class, 'jenis_komoditas_id');
}
public function komoditas()
{
return $this->belongsTo(Komoditas::class, 'komoditas_id');
}
}
+52
View File
@@ -0,0 +1,52 @@
<?php
namespace App\Models\Pertanian;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Database\Eloquent\Relations\HasMany;
class JenisKomoditas extends Model
{
use HasFactory, SoftDeletes;
/**
* Nama tabel yang terkait dengan model ini.
* Un-comment baris di bawah jika nama tabel di database tidak jamak (plural).
*
* @var string
*/
protected $table = 'jenis_komoditas';
/**
* Atribut yang dapat diisi secara massal (mass assignable).
*
* @var array<int, string>
*/
protected $fillable = [
'nama',
'kode',
'keterangan',
];
/**
* Atribut yang harus dikonversi ke tipe data lain (casting).
*
* @var array<string, string>
*/
protected $casts = [
'created_at' => 'datetime',
'updated_at' => 'datetime',
'deleted_at' => 'datetime',
];
/**
* Relasi ke model Komoditas atau Tanaman (jika ada).
* Contoh: Satu Jenis Komoditas memiliki banyak data Tanaman/Komoditas turunannya.
*/
public function tanaman(): HasMany
{
return $this->hasMany(Tanaman::class, 'jenis_komoditas_id', 'id');
}
}
+12
View File
@@ -5,6 +5,8 @@ namespace App\Models\Pertanian;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Database\Eloquent\Builder;
use App\Models\Master\JenisKomoditas;
use App\Models\Master\Varietas;
class Komoditas extends Model
{
@@ -30,4 +32,14 @@ class Komoditas extends Model
$builder->whereIn('id', app('SystemProgram')->komoditas()->pluck('id'));
});
}
public function jenisKomoditas()
{
return $this->hasMany(JenisKomoditas::class, 'komoditas_id');
}
public function varietas()
{
return $this->hasMany(Varietas::class, 'komoditas_id');
}
}
+5 -4
View File
@@ -19,6 +19,7 @@ class Lahan extends Model
protected $table = 'map_lahan';
protected $fillable = [
'uid',
'nama',
'status_kepemilikan',
'profile_id',
@@ -37,22 +38,22 @@ class Lahan extends Model
'path' => 'array',
];
public function profile()
public function profile(): BelongsTo
{
return $this->belongsTo(Profile::class, 'profile_id');
}
public function desaKelurahan()
public function desaKelurahan(): BelongsTo
{
return $this->belongsTo(DesaKelurahan::class, 'desa_kelurahan_id');
}
public function adat()
public function adat(): BelongsTo
{
return $this->belongsTo(Adat::class, 'adat_pemilik_id');
}
public function tanaman()
public function tanaman(): HasMany
{
return $this->hasMany(Tanaman::class, 'lahan_id');
}
+19 -5
View File
@@ -4,12 +4,11 @@ namespace App\Models\Pertanian;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
use App\Models\Pertanian\Komoditas;
use App\Models\Pertanian\Lahan;
use App\Models\Profile;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use App\Models\Pertanian\Lahan;
use App\Models\Pertanian\Komoditas;
use App\Models\Master\JenisKomoditas;
use App\Models\Master\Varietas;
class Tanaman extends Model
{
@@ -18,13 +17,18 @@ class Tanaman extends Model
protected $table = 'map_tanaman';
protected $fillable = [
'uid',
'nama',
'jenis_komoditas_id',
'varietas_id',
'komoditas_id',
'profile_id',
'lahan_id',
'latitude',
'longitude',
'kondisi_tanaman',
'metode_pengumpulan',
'deskripsi',
'created_by',
'updated_by',
'deleted_by',
@@ -35,6 +39,16 @@ class Tanaman extends Model
return $this->belongsTo(Komoditas::class, 'komoditas_id');
}
public function jenisKomoditas()
{
return $this->belongsTo(JenisKomoditas::class, 'jenis_komoditas_id');
}
public function varietas()
{
return $this->belongsTo(Varietas::class, 'varietas_id');
}
public function profile()
{
return $this->belongsTo(Profile::class, 'profile_id');
+3 -9
View File
@@ -4,11 +4,9 @@ namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
use App\Models\User;
use App\Models\Pertanian\Lahan;
use App\Models\Wilayah\DesaKelurahan;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
class Profile extends Model
{
@@ -17,13 +15,14 @@ class Profile extends Model
protected $fillable = [
'user_id',
'role',
'user_uid',
'nama',
'email',
'telepon',
'alamat',
'kk',
'ktp',
'uid',
'desa_kelurahan_id',
'path_kk',
'file_kk',
@@ -44,9 +43,4 @@ class Profile extends Model
{
return $this->belongsTo(User::class, 'user_id');
}
public function lahan(): HasMany
{
return $this->hasMany(Lahan::class, 'profile_id');
}
}
+18 -1
View File
@@ -23,6 +23,9 @@ class Aktivitas extends Model
"indikator",
"deskripsi",
"transformasi_id",
"parent_id",
"created_by",
"updated_by"
];
public function transformasi(): BelongsTo
@@ -32,6 +35,20 @@ class Aktivitas extends Model
public function target(): HasMany
{
return $this->hasMany(Target::class, 'aktivitas_id', 'id');
return $this->hasMany(Target::class, 'aktivitas_id', 'id')
->orderBy('id', 'asc');
}
public function parent(): BelongsTo
{
return $this->belongsTo(Aktivitas::class, 'parent_id', 'id');
}
public function aktivitas(): HasMany
{
return $this->hasMany(Aktivitas::class, 'parent_id', 'id')
->where('jenis_aktivitas', 'aktivitas')
->orderBy('kode', 'asc')
->orderBy('id', 'asc');
}
}
+5 -1
View File
@@ -20,6 +20,8 @@ class Framework extends Model
"nama",
"tahun",
"program_id",
"created_by",
"updated_by",
];
public function program(): BelongsTo
@@ -29,6 +31,8 @@ class Framework extends Model
public function transformasi(): HasMany
{
return $this->hasMany(Transformasi::class, 'framework_id', 'id');
return $this->hasMany(Transformasi::class, 'framework_id', 'id')
->orderBy('kode', 'asc')
->orderBy('id', 'asc');
}
}
+37
View File
@@ -0,0 +1,37 @@
<?php
namespace App\Models\Program;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany;
use App\Models\Program\Target;
class Realisasi extends Model
{
use SoftDeletes;
protected $table = 'program_realisasi';
protected $fillable = [
"target_id",
"realisasi_integer",
"realisasi_float",
"realisasi_boolean",
"created_by",
"updated_by",
"deleted_by",
];
public function target(): BelongsTo
{
return $this->belongsTo(Target::class, 'target_id', 'id');
}
public function verifikasi(): HasMany
{
return $this->hasMany(Verifikasi::class, 'realisasi_id', 'id')->oldest();
}
}
+17
View File
@@ -5,6 +5,8 @@ namespace App\Models\Program;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Relations\HasOne;
use App\Models\Program\Aktivitas;
@@ -27,10 +29,25 @@ class Target extends Model
"realisasi_float",
"realisasi_boolean",
"aktivitas_id",
"tipe_realisasi",
"value_query",
"created_by",
"updated_by",
"deleted_by",
];
public function aktivitas(): BelongsTo
{
return $this->belongsTo(Aktivitas::class, 'aktivitas_id', 'id');
}
public function realisasi(): HasMany
{
return $this->hasMany(Realisasi::class, 'target_id', 'id')->latest();
}
public function latestRealisasi(): HasOne
{
return $this->hasOne(Realisasi::class, 'target_id', 'id')->latest();
}
}
+6 -2
View File
@@ -27,8 +27,12 @@ class Transformasi extends Model
return $this->belongsTo(Framework::class, 'framework_id', 'id');
}
public function aktivitas(): HasMany
public function tujuan(): HasMany
{
return $this->hasMany(Aktivitas::class, 'transformasi_id', 'id');
return $this->hasMany(Aktivitas::class, 'transformasi_id', 'id')
->whereNull('parent_id')
->where('jenis_aktivitas', 'tujuan')
->orderBy('kode', 'asc')
->orderBy('id', 'asc');
}
}
+30
View File
@@ -0,0 +1,30 @@
<?php
namespace App\Models\Program;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use App\Models\Program\Realisasi;
class Verifikasi extends Model
{
use SoftDeletes;
protected $table = 'program_verifikasi';
protected $fillable = [
"realisasi_id",
"dokumen",
"link_dokumen",
"created_by",
"updated_by",
"deleted_by",
];
public function realisasi(): BelongsTo
{
return $this->belongsTo(Realisasi::class, 'realisasi_id', 'id');
}
}
+2
View File
@@ -21,6 +21,8 @@ class User extends Authenticatable
'password',
'email_verified_at',
'role',
'username',
'uid'
];
protected $hidden = [
+1 -1
View File
@@ -1,6 +1,6 @@
<?php
namespace App\Models\wilayah;
namespace App\Models\Wilayah;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
+3 -1
View File
@@ -67,7 +67,9 @@ class AppServiceProvider extends ServiceProvider
});
View::composer('*', function ($view) {
$tabel_menu = TabelBasisData::has('kolom')->get();
$tabel_menu = TabelBasisData::whereHas('kolom', function ($query) {
$query->where('is_active', true);
})->get();
$view->with('tabel_menu', $tabel_menu);
});
+70
View File
@@ -0,0 +1,70 @@
<?php
namespace App\View\Components;
use Closure;
use Illuminate\Contracts\View\View;
use Illuminate\View\Component;
use App\Models\Wilayah\Provinsi;
use App\Models\Wilayah\KabupatenKota;
use App\Models\Wilayah\Kecamatan;
use App\Models\Wilayah\DesaKelurahan;
class WilayahDashboard extends Component
{
public function render(): View|Closure|string
{
$kodeJawa = ['31', '32', '33', '34', '35', '36'];
$totalProvinsi = Provinsi::count();
$totalKabKota = KabupatenKota::count();
$totalKecamatan = Kecamatan::count();
$totalDesaKelurahan = DesaKelurahan::count();
$provinsiAktif = Provinsi::has('kabupatenKota')->count();
$provinsiKosong = $totalProvinsi - $provinsiAktif;
$totalKabupaten = KabupatenKota::whereRaw("SUBSTRING(kode, 3, 2) < '70'")->count();
$totalKota = KabupatenKota::whereRaw("SUBSTRING(kode, 3, 2) >= '70'")->count();
if ($totalKabupaten == 0 && $totalKota == 0 && $totalKabKota > 0) {
$totalKabupaten = $totalKabKota;
}
$kecamatanPerdesaan = Kecamatan::whereHas('kabupatenKota', function($query) {
$query->whereRaw("SUBSTRING(kode, 3, 2) < '70'");
})->count();
$kecamatanPerkotaan = max(0, $totalKecamatan - $kecamatanPerdesaan);
$terpetakan = DesaKelurahan::whereNotNull('path')->count();
$belumTerpetakan = max(0, $totalDesaKelurahan - $terpetakan);
$totalDesa = DesaKelurahan::where('nama', 'like', 'DESA%')->count() ?: $totalDesaKelurahan;
$totalKelurahan = DesaKelurahan::where('nama', 'like', 'KEL%')->count();
$data = [
'totalProvinsi' => $totalProvinsi,
'provinsiAktif' => $provinsiAktif,
'provinsiKosong' => $provinsiKosong,
'totalKabKota' => $totalKabKota,
'totalKabupaten' => $totalKabupaten,
'totalKota' => $totalKota,
'totalKecamatan' => $totalKecamatan,
'kecamatanPerdesaan' => $kecamatanPerdesaan,
'kecamatanPerkotaan' => $kecamatanPerkotaan,
'totalDesaKelurahan' => $totalDesaKelurahan,
'totalDesa' => $totalDesa,
'totalKelurahan' => $totalKelurahan,
'terpetakan' => $terpetakan,
'belumTerpetakan' => $belumTerpetakan,
];
return view('components.wilayah-dashboard', $data);
}
}