Update Koperasi

This commit is contained in:
2026-11-06 22:38:45 +07:00
parent 6232b28e11
commit cb36682d9e
79 changed files with 4639 additions and 1378 deletions
@@ -0,0 +1,198 @@
<?php
namespace App\Services\Koperasi;
use App\Enums\Koperasi\FokusKomoditasKoperasi;
use App\Enums\Koperasi\JenisKoperasi;
use App\Enums\Koperasi\LayananKoperasi;
use App\Enums\Koperasi\StatusAdArtKoperasi;
use App\Enums\Koperasi\UrutanKoperasi;
use App\Enums\Role;
use App\Models\Koperasi\PengurusKoperasi;
use Illuminate\Support\Collection;
class PengurusKoperasiService
{
public function __construct(private WilayahKoperasiService $wilayah) {}
public const RUPIAH_FIELDS = [
'shu_2025', 'shu_2024', 'shu_2023', 'simpanan_terbesar', 'harga_premium_rupiah',
'harga_segar_sekarang', 'harga_segar_1_tahun', 'harga_segar_2_tahun',
'harga_basah_sekarang', 'harga_basah_1_tahun', 'harga_basah_2_tahun',
'harga_kering_sekarang', 'harga_kering_1_tahun', 'harga_kering_2_tahun',
'harga_fermentasi_sekarang', 'harga_fermentasi_1_tahun', 'harga_fermentasi_2_tahun',
];
public function indexData(array $validated): array
{
$filters = [
'search' => $validated['search'] ?? '',
'kabupaten_kota_id' => $validated['kabupaten_kota_id'] ?? ($this->wilayah->available() ? $this->wilayah->defaultKabupaten()?->id : ''),
'kecamatan_id' => $validated['kecamatan_id'] ?? '', 'desa_kelurahan_id' => $validated['desa_kelurahan_id'] ?? '',
'jenis_koperasi' => $validated['jenis_koperasi'] ?? '',
'layanan' => $validated['layanan'] ?? '', 'ad_art' => $validated['ad_art'] ?? '',
'sort_by' => $validated['sort_by'] ?? UrutanKoperasi::TERBARU->value,
];
$query = PengurusKoperasi::query()->with('creator:id,name')
->when(filled($filters['jenis_koperasi']), function ($query) use ($filters) {
if ($filters['jenis_koperasi'] === JenisKoperasi::LAINNYA->value) {
$standard = array_map(fn ($jenis) => $jenis->value, array_filter(JenisKoperasi::cases(), fn ($jenis) => $jenis !== JenisKoperasi::LAINNYA));
return $query->whereNotIn('jenis_koperasi', $standard);
}
return $query->where('jenis_koperasi', $filters['jenis_koperasi']);
})
->when(filled($filters['layanan']), fn ($query) => $query->whereJsonContains('layanan_koperasi', $filters['layanan']))
->when(filled($filters['ad_art']), fn ($query) => $query->where('ad_art', $filters['ad_art']))
->when(filled($filters['search']), function ($query) use ($filters) {
$query->where(function ($query) use ($filters) {
foreach (['nama_koperasi', 'alamat_koperasi', 'jenis_koperasi', 'nama_lengkap'] as $field) {
$query->orWhereLike($field, '%'.$filters['search'].'%');
}
});
});
$this->wilayah->applyFilters($query, $filters);
$order = UrutanKoperasi::from($filters['sort_by']);
match ($order) {
UrutanKoperasi::NAMA_ASC, UrutanKoperasi::NAMA_DESC => $query->orderByRaw('LOWER(nama_koperasi) '.($order === UrutanKoperasi::NAMA_ASC ? 'asc' : 'desc')),
UrutanKoperasi::ANGGOTA_ASC, UrutanKoperasi::ANGGOTA_DESC => $query
->orderByRaw('CASE WHEN jumlah_anggota_dewasa IS NULL OR jumlah_anggota_anak IS NULL THEN 1 ELSE 0 END')
->orderByRaw('(jumlah_anggota_dewasa + jumlah_anggota_anak) '.($order === UrutanKoperasi::ANGGOTA_ASC ? 'asc' : 'desc')),
UrutanKoperasi::TERBARU => $query->latest(),
};
$koperasi = $query->orderByDesc('id')->paginate((int) ($validated['per_page'] ?? 10))->withQueryString();
$ringkasanKoperasi = $koperasi->getCollection()->mapWithKeys(fn (PengurusKoperasi $item) => [$item->id => $this->profileSummary($item)]);
$jenisTerdata = PengurusKoperasi::whereNotNull('jenis_koperasi')->where('jenis_koperasi', '!=', '')
->distinct()->orderBy('jenis_koperasi')->pluck('jenis_koperasi');
$jenisKoperasiOptions = collect(JenisKoperasi::cases())->map(fn ($jenis) => $jenis->value)
->merge($jenisTerdata)->unique()->values();
return [
'koperasi' => $koperasi,
'ringkasanKoperasi' => $ringkasanKoperasi,
'filters' => $filters,
'jenisKoperasiOptions' => $jenisKoperasiOptions,
...$this->wilayah->filterOptions($filters),
'showEnumerator' => in_array(auth()->user()?->role, [Role::SUPER_ADMIN, Role::ADMIN], true),
'totalKoperasi' => PengurusKoperasi::count(),
'totalJenisKoperasi' => $jenisTerdata->count(),
'totalDokumenLengkap' => PengurusKoperasi::where('ad_art', StatusAdArtKoperasi::LENGKAP->value)->count(),
];
}
public function profileViewData(?PengurusKoperasi $pengurus = null): array
{
return [
'pengurus' => $pengurus ?? new PengurusKoperasi,
'ringkasanProfil' => $this->profileSummary($pengurus),
...$this->wilayah->profileOptions($pengurus, session()->getOldInput()),
];
}
public function profileSummary(?PengurusKoperasi $pengurus = null): array
{
$empty = 'Belum terisi';
$dewasa = $pengurus?->jumlah_anggota_dewasa;
$anak = $pengurus?->jumlah_anggota_anak;
$count = fn ($value) => filled($value) ? number_format((int) $value, 0, ',', '.') : $empty;
$layanan = collect($pengurus?->layanan_koperasi ?? [])->map(function (LayananKoperasi $item) use ($pengurus) {
return $item === LayananKoperasi::LAINNYA && filled($pengurus->layanan_lainnya)
? $item->label().': '.$pengurus->layanan_lainnya : $item->label();
})->unique()->values()->all();
return [
'judul' => filled($pengurus?->nama_koperasi) ? $pengurus->nama_koperasi : 'Nama Koperasi',
'jenis' => filled($pengurus?->jenis_koperasi) ? $pengurus->jenis_koperasi : $empty,
'alamat' => filled($pengurus?->alamat_koperasi) ? $pengurus->alamat_koperasi : $empty,
'tahun_berdiri' => $pengurus?->tahun_berdiri ?? $empty,
'anggota' => filled($dewasa) && filled($anak) ? $count((int) $dewasa + (int) $anak) : $empty,
'anggota_rincian' => filled($dewasa) || filled($anak) ? 'Dewasa: '.$count($dewasa).' · Anak: '.$count($anak) : null,
'pengurus' => $count($pengurus?->jumlah_pengurus),
'layanan' => $layanan,
'responden' => filled($pengurus?->nama_lengkap) ? $pengurus->nama_lengkap : $empty,
'jabatan' => $pengurus?->posisi_dalam_koperasi?->value ?? $empty,
'kontak' => filled($pengurus?->no_hp) ? $pengurus->no_hp : $empty,
'diperbarui' => $pengurus?->updated_at ?? $pengurus?->created_at,
'tersimpan' => $pengurus?->exists ?? false,
];
}
public static function normalizeRupiah(mixed $value): mixed
{
if (is_string($value) && preg_match('/^-?\d{1,3}(?:\.\d{3})+$/D', $value)) {
return str_replace('.', '', $value);
}
return $value;
}
public static function formatRupiah(mixed $value): string
{
$value = (string) self::normalizeRupiah($value);
return preg_match('/^-?\d+$/D', $value)
? preg_replace('/\B(?=(\d{3})+(?!\d))/', '.', $value)
: $value;
}
public static function hasSelection(mixed $value, string $selection): bool
{
if ($value instanceof Collection) {
$value = $value->all();
}
if ($value instanceof \BackedEnum) {
$value = $value->value;
}
if (is_array($value)) {
return in_array($selection, array_map(fn ($item) => $item instanceof \BackedEnum ? $item->value : $item, $value), true);
}
$decoded = json_decode((string) $value, true);
return is_array($decoded)
? in_array($selection, $decoded, true)
: str_contains((string) $value, $selection);
}
public function profileData(array $data): array
{
unset($data['provinsi_id'], $data['kabupaten_kota_id'], $data['kecamatan_id'], $data['created_by']);
if (! $this->wilayah->available()) {
unset($data['desa_kelurahan_id']);
}
if ($data['jenis_koperasi'] === JenisKoperasi::LAINNYA->value && ! empty($data['jenis_koperasi_lainnya'])) {
$data['jenis_koperasi'] = $data['jenis_koperasi_lainnya'];
}
unset($data['jenis_koperasi_lainnya']);
if (array_key_exists('fokus_komoditas', $data) && $data['fokus_komoditas'] !== FokusKomoditasKoperasi::YA->value) {
$data['detail_fokus_komoditas'] = null;
}
return $data;
}
public function createProfile(array $data, int $creatorId): PengurusKoperasi
{
$data = $this->profileData($data);
if ($this->wilayah->available()) {
$data['created_by'] = $creatorId;
}
return PengurusKoperasi::create($data);
}
public function tabData(array $data): array
{
$model = new PengurusKoperasi;
foreach ($data as $field => $value) {
if (is_array($value) && ! $model->hasCast($field)) {
$data[$field] = json_encode($value, JSON_UNESCAPED_UNICODE | JSON_THROW_ON_ERROR);
}
}
return $data;
}
}