big update base struktur tahap 1
This commit is contained in:
@@ -0,0 +1,203 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Wilayah;
|
||||
|
||||
use App\Models\WilayahDesa;
|
||||
use App\Models\WilayahKabupaten;
|
||||
use App\Models\WilayahKecamatan;
|
||||
use App\Models\WilayahProvinsi;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Validation\ValidationException;
|
||||
|
||||
class WilayahService
|
||||
{
|
||||
private const MODELS = [
|
||||
'provinsi' => WilayahProvinsi::class,
|
||||
'kabupaten' => WilayahKabupaten::class,
|
||||
'kecamatan' => WilayahKecamatan::class,
|
||||
'desa' => WilayahDesa::class,
|
||||
];
|
||||
|
||||
private const PARENTS = [
|
||||
'kabupaten' => 'provinsi_id',
|
||||
'kecamatan' => 'kabupaten_id',
|
||||
'desa' => 'kecamatan_id',
|
||||
];
|
||||
|
||||
private const RELATIONS = [
|
||||
'provinsi' => [],
|
||||
'kabupaten' => ['provinsi'],
|
||||
'kecamatan' => ['kabupaten.provinsi'],
|
||||
'desa' => ['kecamatan.kabupaten.provinsi'],
|
||||
];
|
||||
|
||||
public function list(string $tingkat, array $filters = [])
|
||||
{
|
||||
$model = $this->model($tingkat);
|
||||
|
||||
return $model::query()
|
||||
->with(self::RELATIONS[$tingkat])
|
||||
->when($filters['search'] ?? null, function ($query, $search) {
|
||||
$value = mb_strtolower($search);
|
||||
$query->where(function ($scope) use ($value) {
|
||||
$scope->whereRaw('LOWER(kode) LIKE ?', ["%{$value}%"])
|
||||
->orWhereRaw('LOWER(nama) LIKE ?', ["%{$value}%"]);
|
||||
});
|
||||
})
|
||||
->when(
|
||||
isset(self::PARENTS[$tingkat]) && ! empty($filters[self::PARENTS[$tingkat]]),
|
||||
fn ($query) => $query->where(
|
||||
self::PARENTS[$tingkat],
|
||||
$filters[self::PARENTS[$tingkat]]
|
||||
)
|
||||
)
|
||||
->orderBy(
|
||||
$filters['sort_by'] ?? 'nama',
|
||||
$filters['sort_direction'] ?? 'asc'
|
||||
)
|
||||
->paginate($filters['per_page'] ?? 10);
|
||||
}
|
||||
|
||||
public function options(string $tingkat, array $filters = [], ?int $parentId = null)
|
||||
{
|
||||
$model = $this->model($tingkat);
|
||||
$parentColumn = self::PARENTS[$tingkat] ?? null;
|
||||
|
||||
return $model::query()
|
||||
->select(['id', 'kode', 'nama'])
|
||||
->when(
|
||||
$parentColumn && $parentId,
|
||||
fn ($query) => $query->where($parentColumn, $parentId)
|
||||
)
|
||||
->when($filters['search'] ?? null, function ($query, $search) {
|
||||
$value = mb_strtolower($search);
|
||||
$query->where(function ($scope) use ($value) {
|
||||
$scope->whereRaw('LOWER(kode) LIKE ?', ["%{$value}%"])
|
||||
->orWhereRaw('LOWER(nama) LIKE ?', ["%{$value}%"]);
|
||||
});
|
||||
})
|
||||
->orderBy('nama')
|
||||
->get();
|
||||
}
|
||||
|
||||
public function create(string $tingkat, array $data): Model
|
||||
{
|
||||
$model = $this->model($tingkat);
|
||||
|
||||
return $model::create($this->payload($tingkat, $data))
|
||||
->load(self::RELATIONS[$tingkat]);
|
||||
}
|
||||
|
||||
public function find(string $tingkat, int $id): Model
|
||||
{
|
||||
$model = $this->model($tingkat);
|
||||
|
||||
return $model::with(self::RELATIONS[$tingkat])->findOrFail($id);
|
||||
}
|
||||
|
||||
public function update(string $tingkat, int $id, array $data): Model
|
||||
{
|
||||
$wilayah = $this->find($tingkat, $id);
|
||||
$wilayah->update($this->payload($tingkat, $data));
|
||||
|
||||
return $wilayah->fresh(self::RELATIONS[$tingkat]);
|
||||
}
|
||||
|
||||
public function delete(string $tingkat, int $id): void
|
||||
{
|
||||
$wilayah = $this->find($tingkat, $id);
|
||||
$childRelation = match ($tingkat) {
|
||||
'provinsi' => 'kabupaten',
|
||||
'kabupaten' => 'kecamatan',
|
||||
'kecamatan' => 'desa',
|
||||
default => null,
|
||||
};
|
||||
|
||||
if ($childRelation && $wilayah->{$childRelation}()->exists()) {
|
||||
throw ValidationException::withMessages([
|
||||
'wilayah' => "Wilayah {$tingkat} tidak dapat dihapus karena masih memiliki data di bawahnya.",
|
||||
]);
|
||||
}
|
||||
|
||||
$wilayah->delete();
|
||||
}
|
||||
|
||||
public function alamatLengkap(array $filters): array
|
||||
{
|
||||
if (! empty($filters['desa_id'])) {
|
||||
$desa = WilayahDesa::with('kecamatan.kabupaten.provinsi')->findOrFail($filters['desa_id']);
|
||||
|
||||
return $this->addressPayload(
|
||||
$desa->kecamatan?->kabupaten?->provinsi,
|
||||
$desa->kecamatan?->kabupaten,
|
||||
$desa->kecamatan,
|
||||
$desa
|
||||
);
|
||||
}
|
||||
|
||||
if (! empty($filters['kecamatan_id'])) {
|
||||
$kecamatan = WilayahKecamatan::with('kabupaten.provinsi')->findOrFail($filters['kecamatan_id']);
|
||||
|
||||
return $this->addressPayload(
|
||||
$kecamatan->kabupaten?->provinsi,
|
||||
$kecamatan->kabupaten,
|
||||
$kecamatan
|
||||
);
|
||||
}
|
||||
|
||||
if (! empty($filters['kabupaten_id'])) {
|
||||
$kabupaten = WilayahKabupaten::with('provinsi')->findOrFail($filters['kabupaten_id']);
|
||||
|
||||
return $this->addressPayload($kabupaten->provinsi, $kabupaten);
|
||||
}
|
||||
|
||||
$provinsi = WilayahProvinsi::findOrFail($filters['provinsi_id']);
|
||||
|
||||
return $this->addressPayload($provinsi);
|
||||
}
|
||||
|
||||
private function model(string $tingkat): string
|
||||
{
|
||||
abort_unless(isset(self::MODELS[$tingkat]), 404, 'Tingkat wilayah tidak ditemukan.');
|
||||
|
||||
return self::MODELS[$tingkat];
|
||||
}
|
||||
|
||||
private function payload(string $tingkat, array $data): array
|
||||
{
|
||||
$fields = ['kode', 'nama'];
|
||||
if (isset(self::PARENTS[$tingkat])) {
|
||||
$fields[] = self::PARENTS[$tingkat];
|
||||
}
|
||||
|
||||
return collect($data)->only($fields)->all();
|
||||
}
|
||||
|
||||
private function addressPayload(
|
||||
?WilayahProvinsi $provinsi,
|
||||
?WilayahKabupaten $kabupaten = null,
|
||||
?WilayahKecamatan $kecamatan = null,
|
||||
?WilayahDesa $desa = null
|
||||
): array {
|
||||
$node = fn ($item) => $item ? [
|
||||
'id' => $item->id,
|
||||
'kode' => $item->kode,
|
||||
'nama' => $item->nama,
|
||||
] : null;
|
||||
|
||||
$parts = array_filter([
|
||||
$desa ? "Desa/Kelurahan {$desa->nama}" : null,
|
||||
$kecamatan ? "Kecamatan {$kecamatan->nama}" : null,
|
||||
$kabupaten?->nama,
|
||||
$provinsi ? $provinsi->nama : null,
|
||||
]);
|
||||
|
||||
return [
|
||||
'desa' => $node($desa),
|
||||
'kecamatan' => $node($kecamatan),
|
||||
'kabupaten' => $node($kabupaten),
|
||||
'provinsi' => $node($provinsi),
|
||||
'alamat_wilayah' => implode(', ', $parts),
|
||||
];
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user