Update Status kelengkapan data
This commit is contained in:
@@ -21,6 +21,10 @@ class PetaniStatusController extends Controller
|
|||||||
|
|
||||||
$validated = $request->validate([
|
$validated = $request->validate([
|
||||||
'status' => ['required', Rule::in([StatusDataPetani::LENGKAP->value, StatusDataPetani::DRAFT->value])],
|
'status' => ['required', Rule::in([StatusDataPetani::LENGKAP->value, StatusDataPetani::DRAFT->value])],
|
||||||
|
// Enumerator wajib menyetujui pernyataan kelengkapan saat menandai lengkap.
|
||||||
|
'pernyataan' => ['exclude_unless:status,' . StatusDataPetani::LENGKAP->value, 'accepted'],
|
||||||
|
], [
|
||||||
|
'pernyataan.accepted' => 'Centang pernyataan kelengkapan data terlebih dahulu.',
|
||||||
]);
|
]);
|
||||||
$tujuan = StatusDataPetani::from($validated['status']);
|
$tujuan = StatusDataPetani::from($validated['status']);
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,85 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Models\Concerns;
|
||||||
|
|
||||||
|
use App\Enums\StatusDataPetani;
|
||||||
|
use App\Models\Pertanian\Petani;
|
||||||
|
use Closure;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Data petani yang sudah ditandai "Lengkap" lalu diubah/ditambah/dihapus
|
||||||
|
* otomatis kembali ke "Draf", supaya enumerator menandai lengkap lagi setelah selesai.
|
||||||
|
*
|
||||||
|
* Dipasang di semua model yang menyimpan data profil petani (web maupun API).
|
||||||
|
* Model yang tidak punya kolom petani_id meng-override petaniIdUntukStatus().
|
||||||
|
*/
|
||||||
|
trait KembalikanStatusPetaniKeDraf
|
||||||
|
{
|
||||||
|
// Kolom otomatis/audit yang tidak dihitung sebagai perubahan data.
|
||||||
|
private static array $kolomBukanPerubahanData = [
|
||||||
|
'created_at', 'updated_at', 'deleted_at', 'created_by', 'updated_by', 'deleted_by', 'status',
|
||||||
|
];
|
||||||
|
|
||||||
|
public static function bootKembalikanStatusPetaniKeDraf(): void
|
||||||
|
{
|
||||||
|
static::saved(function ($model) {
|
||||||
|
$kolomBerubah = array_diff(array_keys($model->getChanges()), self::$kolomBukanPerubahanData);
|
||||||
|
|
||||||
|
if ($model->wasRecentlyCreated || $kolomBerubah) {
|
||||||
|
$model->kembalikanStatusPetaniKeDraf();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
static::deleted(fn ($model) => $model->kembalikanStatusPetaniKeDraf());
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function petaniIdUntukStatus(): ?int
|
||||||
|
{
|
||||||
|
return $this->petani_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function kembalikanStatusPetaniKeDraf(): void
|
||||||
|
{
|
||||||
|
$petaniId = $this->petaniIdUntukStatus();
|
||||||
|
if (! $petaniId) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Satu simpan bisa memicu ratusan baris (mis. sinkron jenis hama ke semua tanaman).
|
||||||
|
// Cukup sekali per petani per request: setelah dicek, status pasti bukan "Lengkap" lagi.
|
||||||
|
self::ingatPerRequest('status_petani.dicek', $petaniId, function () use ($petaniId) {
|
||||||
|
// Query langsung (tanpa event model) supaya tidak memicu hook lain / berulang.
|
||||||
|
$diubah = Petani::withoutGlobalScopes()
|
||||||
|
->whereKey($petaniId)
|
||||||
|
->where('status', StatusDataPetani::LENGKAP->value)
|
||||||
|
->update(['status' => StatusDataPetani::DRAFT->value]);
|
||||||
|
|
||||||
|
if ($diubah && request()->hasSession()) {
|
||||||
|
request()->session()->flash('status_petani_info', 'Data petani diubah, status kembali ke Draf. Tandai lengkap lagi setelah selesai.');
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Simpan hasil $ambil() selama satu request web, per $kunci + $id.
|
||||||
|
* Di console/queue tidak disimpan (proses berjalan lama, data bisa berubah antar-job).
|
||||||
|
*/
|
||||||
|
protected static function ingatPerRequest(string $kunci, int|string|null $id, Closure $ambil): mixed
|
||||||
|
{
|
||||||
|
if ($id === null || app()->runningInConsole()) {
|
||||||
|
return $ambil();
|
||||||
|
}
|
||||||
|
|
||||||
|
$bag = request()->attributes;
|
||||||
|
$cache = $bag->get($kunci, []);
|
||||||
|
|
||||||
|
if (! array_key_exists($id, $cache)) {
|
||||||
|
$cache[$id] = $ambil();
|
||||||
|
$bag->set($kunci, $cache);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $cache[$id];
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
namespace App\Models\Pertanian;
|
namespace App\Models\Pertanian;
|
||||||
|
|
||||||
|
use App\Models\Concerns\KembalikanStatusPetaniKeDraf;
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||||
use Illuminate\Support\Str;
|
use Illuminate\Support\Str;
|
||||||
@@ -15,7 +16,7 @@ use App\Enums\AksesPasar\SkorKesadaranPremium;
|
|||||||
|
|
||||||
class AksesPasar extends Model
|
class AksesPasar extends Model
|
||||||
{
|
{
|
||||||
use SoftDeletes;
|
use SoftDeletes, KembalikanStatusPetaniKeDraf;
|
||||||
|
|
||||||
protected $table = 'akses_pasar';
|
protected $table = 'akses_pasar';
|
||||||
|
|
||||||
@@ -77,7 +78,7 @@ class AksesPasar extends Model
|
|||||||
$skor->update([
|
$skor->update([
|
||||||
'skor_d6_k1_6_pengalaman_menjual_ke_saluran_berbeda' => $aksesPasar->skor_pengalaman,
|
'skor_d6_k1_6_pengalaman_menjual_ke_saluran_berbeda' => $aksesPasar->skor_pengalaman,
|
||||||
'skor_d6_k4_1_kesadaran_akses_pasar_premium' => $aksesPasar->skor_kesadaran_premium,
|
'skor_d6_k4_1_kesadaran_akses_pasar_premium' => $aksesPasar->skor_kesadaran_premium,
|
||||||
'skor_d6_k5_1_hambatan_mutu' => $aksesPasar->skor_kepercayaan_responden
|
// skor_d6_k5_1_hambatan_mutu diisi dari SurveyPanen (tingkat hasil panen ditolak).
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,12 +2,15 @@
|
|||||||
|
|
||||||
namespace App\Models\Pertanian;
|
namespace App\Models\Pertanian;
|
||||||
|
|
||||||
|
use App\Models\Concerns\KembalikanStatusPetaniKeDraf;
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
use App\Models\Pertanian\Petani;
|
use App\Models\Pertanian\Petani;
|
||||||
|
|
||||||
class HargaJualPanen extends Model
|
class HargaJualPanen extends Model
|
||||||
{
|
{
|
||||||
|
use KembalikanStatusPetaniKeDraf;
|
||||||
|
|
||||||
protected $table = 'harga_jual_panen';
|
protected $table = 'harga_jual_panen';
|
||||||
|
|
||||||
protected $fillable = [
|
protected $fillable = [
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
namespace App\Models\Pertanian;
|
namespace App\Models\Pertanian;
|
||||||
|
|
||||||
|
use App\Models\Concerns\KembalikanStatusPetaniKeDraf;
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||||
use App\Models\Wilayah\DesaKelurahan;
|
use App\Models\Wilayah\DesaKelurahan;
|
||||||
@@ -22,7 +23,7 @@ use App\Models\Pertanian\Petani;
|
|||||||
|
|
||||||
class Lahan extends Model
|
class Lahan extends Model
|
||||||
{
|
{
|
||||||
use SoftDeletes;
|
use SoftDeletes, KembalikanStatusPetaniKeDraf;
|
||||||
|
|
||||||
protected $table = 'map_lahan';
|
protected $table = 'map_lahan';
|
||||||
|
|
||||||
|
|||||||
@@ -2,11 +2,14 @@
|
|||||||
|
|
||||||
namespace App\Models\Pertanian;
|
namespace App\Models\Pertanian;
|
||||||
|
|
||||||
|
use App\Models\Concerns\KembalikanStatusPetaniKeDraf;
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||||
|
|
||||||
class PendapatanKomoditas extends Model
|
class PendapatanKomoditas extends Model
|
||||||
{
|
{
|
||||||
|
use KembalikanStatusPetaniKeDraf;
|
||||||
|
|
||||||
protected $table = 'pendapatan_komoditas';
|
protected $table = 'pendapatan_komoditas';
|
||||||
|
|
||||||
protected $fillable = [
|
protected $fillable = [
|
||||||
@@ -29,4 +32,11 @@ class PendapatanKomoditas extends Model
|
|||||||
{
|
{
|
||||||
return $this->belongsTo(SosialEkonomi::class, 'sosial_ekonomi_id');
|
return $this->belongsTo(SosialEkonomi::class, 'sosial_ekonomi_id');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Untuk trait KembalikanStatusPetaniKeDraf: petani diambil dari data sosial ekonomi.
|
||||||
|
protected function petaniIdUntukStatus(): ?int
|
||||||
|
{
|
||||||
|
return self::ingatPerRequest('status_petani.sosial_ekonomi', $this->sosial_ekonomi_id,
|
||||||
|
fn () => SosialEkonomi::withoutGlobalScopes()->whereKey($this->sosial_ekonomi_id)->value('petani_id'));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,11 +2,14 @@
|
|||||||
|
|
||||||
namespace App\Models\Pertanian;
|
namespace App\Models\Pertanian;
|
||||||
|
|
||||||
|
use App\Models\Concerns\KembalikanStatusPetaniKeDraf;
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||||
|
|
||||||
class PendapatanLuarPertanian extends Model
|
class PendapatanLuarPertanian extends Model
|
||||||
{
|
{
|
||||||
|
use KembalikanStatusPetaniKeDraf;
|
||||||
|
|
||||||
protected $table = 'pendapatan_luar_pertanian';
|
protected $table = 'pendapatan_luar_pertanian';
|
||||||
|
|
||||||
protected $fillable = [
|
protected $fillable = [
|
||||||
@@ -27,4 +30,11 @@ class PendapatanLuarPertanian extends Model
|
|||||||
{
|
{
|
||||||
return $this->belongsTo(SosialEkonomi::class, 'sosial_ekonomi_id');
|
return $this->belongsTo(SosialEkonomi::class, 'sosial_ekonomi_id');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Untuk trait KembalikanStatusPetaniKeDraf: petani diambil dari data sosial ekonomi.
|
||||||
|
protected function petaniIdUntukStatus(): ?int
|
||||||
|
{
|
||||||
|
return self::ingatPerRequest('status_petani.sosial_ekonomi', $this->sosial_ekonomi_id,
|
||||||
|
fn () => SosialEkonomi::withoutGlobalScopes()->whereKey($this->sosial_ekonomi_id)->value('petani_id'));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
namespace App\Models\Pertanian;
|
namespace App\Models\Pertanian;
|
||||||
|
|
||||||
|
use App\Models\Concerns\KembalikanStatusPetaniKeDraf;
|
||||||
use App\Enums\Pendidikan;
|
use App\Enums\Pendidikan;
|
||||||
use App\Enums\Pernikahan;
|
use App\Enums\Pernikahan;
|
||||||
use App\Enums\Role;
|
use App\Enums\Role;
|
||||||
@@ -30,7 +31,7 @@ use Illuminate\Support\Str;
|
|||||||
|
|
||||||
class Petani extends Model
|
class Petani extends Model
|
||||||
{
|
{
|
||||||
use SoftDeletes;
|
use SoftDeletes, KembalikanStatusPetaniKeDraf;
|
||||||
|
|
||||||
protected $table = 'petani';
|
protected $table = 'petani';
|
||||||
|
|
||||||
@@ -420,4 +421,10 @@ class Petani extends Model
|
|||||||
{
|
{
|
||||||
return $this->belongsTo(User::class, 'created_by');
|
return $this->belongsTo(User::class, 'created_by');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Untuk trait KembalikanStatusPetaniKeDraf: petani ini sendiri.
|
||||||
|
protected function petaniIdUntukStatus(): ?int
|
||||||
|
{
|
||||||
|
return $this->id;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
namespace App\Models\Pertanian;
|
namespace App\Models\Pertanian;
|
||||||
|
|
||||||
|
use App\Models\Concerns\KembalikanStatusPetaniKeDraf;
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
@@ -18,7 +19,7 @@ use App\Models\Pertanian\Lahan;
|
|||||||
|
|
||||||
class PraktikBudidaya extends Model
|
class PraktikBudidaya extends Model
|
||||||
{
|
{
|
||||||
use SoftDeletes;
|
use SoftDeletes, KembalikanStatusPetaniKeDraf;
|
||||||
|
|
||||||
protected $table = 'praktik_budidaya';
|
protected $table = 'praktik_budidaya';
|
||||||
|
|
||||||
@@ -101,27 +102,11 @@ class PraktikBudidaya extends Model
|
|||||||
$jenisHama = $praktikBudidaya->jenis_hama ?? [];
|
$jenisHama = $praktikBudidaya->jenis_hama ?? [];
|
||||||
$jenisPenyakit = $praktikBudidaya->jenis_penyakit ?? [];
|
$jenisPenyakit = $praktikBudidaya->jenis_penyakit ?? [];
|
||||||
|
|
||||||
if (Schema::hasColumn((new Lahan)->getTable(), 'jenis_hama')
|
// Salin jenis hama/penyakit ke semua lahan & tanaman petani: satu query per tabel
|
||||||
&& Schema::hasColumn((new Lahan)->getTable(), 'jenis_penyakit')) {
|
// (sebelumnya satu query per baris; petani bisa punya ratusan titik tanaman).
|
||||||
Lahan::where('petani_id', $praktikBudidaya->petani_id)->get()->each(function (Lahan $lahan) use ($jenisHama, $jenisPenyakit, $praktikBudidaya) {
|
// Hanya baris yang isinya berbeda yang diubah, supaya updated_at baris lain tidak ikut berubah.
|
||||||
$lahan->update([
|
self::sinkronHamaPenyakit(new Lahan, $praktikBudidaya, $jenisHama, $jenisPenyakit);
|
||||||
'jenis_hama' => $jenisHama,
|
self::sinkronHamaPenyakit(new Tanaman, $praktikBudidaya, $jenisHama, $jenisPenyakit);
|
||||||
'jenis_penyakit' => $jenisPenyakit,
|
|
||||||
'updated_by' => $praktikBudidaya->updated_by,
|
|
||||||
]);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Schema::hasColumn((new Tanaman)->getTable(), 'jenis_hama')
|
|
||||||
&& Schema::hasColumn((new Tanaman)->getTable(), 'jenis_penyakit')) {
|
|
||||||
Tanaman::where('petani_id', $praktikBudidaya->petani_id)->get()->each(function (Tanaman $tanaman) use ($jenisHama, $jenisPenyakit, $praktikBudidaya) {
|
|
||||||
$tanaman->update([
|
|
||||||
'jenis_hama' => $jenisHama,
|
|
||||||
'jenis_penyakit' => $jenisPenyakit,
|
|
||||||
'updated_by' => $praktikBudidaya->updated_by,
|
|
||||||
]);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($kebiasaan == 0) {
|
if ($kebiasaan == 0) {
|
||||||
$skor_konservasi_tanah = 1;
|
$skor_konservasi_tanah = 1;
|
||||||
@@ -146,6 +131,37 @@ class PraktikBudidaya extends Model
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @var array<string, bool> hasil cek kolom per tabel (cukup sekali per proses) */
|
||||||
|
private static array $punyaKolomHama = [];
|
||||||
|
|
||||||
|
private static function sinkronHamaPenyakit(Model $model, PraktikBudidaya $praktikBudidaya, array $jenisHama, array $jenisPenyakit): void
|
||||||
|
{
|
||||||
|
$tabel = $model->getTable();
|
||||||
|
$ada = self::$punyaKolomHama[$tabel] ??= Schema::hasColumns($tabel, ['jenis_hama', 'jenis_penyakit']);
|
||||||
|
if (! $ada) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Format JSON sama dengan cast 'array' di model Lahan/Tanaman.
|
||||||
|
$hama = json_encode($jenisHama);
|
||||||
|
$penyakit = json_encode($jenisPenyakit);
|
||||||
|
|
||||||
|
// Query builder: tidak memicu event per baris. Status petani sudah dikembalikan ke Draf
|
||||||
|
// oleh event PraktikBudidaya sendiri (trait KembalikanStatusPetaniKeDraf).
|
||||||
|
$model->newQuery()
|
||||||
|
->where('petani_id', $praktikBudidaya->petani_id)
|
||||||
|
// Kolom jsonb: dibandingkan sebagai jsonb (bukan teks) karena PostgreSQL menormalkan formatnya.
|
||||||
|
->where(fn ($q) => $q
|
||||||
|
->whereRaw('jenis_hama::jsonb IS DISTINCT FROM ?::jsonb', [$hama])
|
||||||
|
->orWhereRaw('jenis_penyakit::jsonb IS DISTINCT FROM ?::jsonb', [$penyakit]))
|
||||||
|
->update([
|
||||||
|
'jenis_hama' => $hama,
|
||||||
|
'jenis_penyakit' => $penyakit,
|
||||||
|
'updated_by' => $praktikBudidaya->updated_by,
|
||||||
|
'updated_at' => now(),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
public function petani(): BelongsTo
|
public function petani(): BelongsTo
|
||||||
{
|
{
|
||||||
return $this->belongsTo(Petani::class, 'petani_id');
|
return $this->belongsTo(Petani::class, 'petani_id');
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
namespace App\Models\Pertanian;
|
namespace App\Models\Pertanian;
|
||||||
|
|
||||||
|
use App\Models\Concerns\KembalikanStatusPetaniKeDraf;
|
||||||
use App\Enums\SosialEkonomi\AlasanKreditDitolak;
|
use App\Enums\SosialEkonomi\AlasanKreditDitolak;
|
||||||
use App\Enums\SosialEkonomi\BisaBeliPupukBersubsidi;
|
use App\Enums\SosialEkonomi\BisaBeliPupukBersubsidi;
|
||||||
use App\Enums\SosialEkonomi\JenisAsetProduktif;
|
use App\Enums\SosialEkonomi\JenisAsetProduktif;
|
||||||
@@ -51,7 +52,7 @@ use Illuminate\Support\Str;
|
|||||||
|
|
||||||
class SosialEkonomi extends Model
|
class SosialEkonomi extends Model
|
||||||
{
|
{
|
||||||
use SoftDeletes;
|
use SoftDeletes, KembalikanStatusPetaniKeDraf;
|
||||||
|
|
||||||
protected $table = 'sosial_ekonomi';
|
protected $table = 'sosial_ekonomi';
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
namespace App\Models\Pertanian;
|
namespace App\Models\Pertanian;
|
||||||
|
|
||||||
|
use App\Models\Concerns\KembalikanStatusPetaniKeDraf;
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
@@ -11,7 +12,7 @@ use App\Models\Pertanian\Petani;
|
|||||||
|
|
||||||
class SurveyPanen extends Model
|
class SurveyPanen extends Model
|
||||||
{
|
{
|
||||||
use SoftDeletes;
|
use SoftDeletes, KembalikanStatusPetaniKeDraf;
|
||||||
|
|
||||||
protected $table = 'survey_panen';
|
protected $table = 'survey_panen';
|
||||||
|
|
||||||
@@ -64,6 +65,9 @@ class SurveyPanen extends Model
|
|||||||
$skor->update([
|
$skor->update([
|
||||||
'skor_d2_k3_1_penentuan_pematangan' => $survey->dasar_penentuan_panen,
|
'skor_d2_k3_1_penentuan_pematangan' => $survey->dasar_penentuan_panen,
|
||||||
'skor_d2_k3_5_sortasi_awal_pemisahan_kualitas' => $survey->praktik_sortasi,
|
'skor_d2_k3_5_sortasi_awal_pemisahan_kualitas' => $survey->praktik_sortasi,
|
||||||
|
// Hambatan mutu = "Tingkat hasil panen ditolak pembeli" (TingkatPanenReject, 1–5).
|
||||||
|
// Kolomnya bernama hasil_panen_reject, tetapi isinya tingkat reject.
|
||||||
|
'skor_d6_k5_1_hambatan_mutu' => $survey->hasil_panen_reject,
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
namespace App\Models\Pertanian;
|
namespace App\Models\Pertanian;
|
||||||
|
|
||||||
|
use App\Models\Concerns\KembalikanStatusPetaniKeDraf;
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||||
@@ -11,7 +12,7 @@ use App\Models\Pertanian\Petani;
|
|||||||
|
|
||||||
class SurveyPelatihan extends Model
|
class SurveyPelatihan extends Model
|
||||||
{
|
{
|
||||||
use HasFactory, SoftDeletes;
|
use HasFactory, SoftDeletes, KembalikanStatusPetaniKeDraf;
|
||||||
|
|
||||||
protected $table = 'survey_pelatihan';
|
protected $table = 'survey_pelatihan';
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
namespace App\Models\Pertanian;
|
namespace App\Models\Pertanian;
|
||||||
|
|
||||||
|
use App\Models\Concerns\KembalikanStatusPetaniKeDraf;
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
@@ -9,7 +10,7 @@ use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
|||||||
|
|
||||||
class SurveyProduktivitas extends Model
|
class SurveyProduktivitas extends Model
|
||||||
{
|
{
|
||||||
use SoftDeletes;
|
use SoftDeletes, KembalikanStatusPetaniKeDraf;
|
||||||
|
|
||||||
protected $table = 'survey_produktivitas';
|
protected $table = 'survey_produktivitas';
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
namespace App\Models\Pertanian;
|
namespace App\Models\Pertanian;
|
||||||
|
|
||||||
|
use App\Models\Concerns\KembalikanStatusPetaniKeDraf;
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||||
@@ -9,7 +10,7 @@ use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
|||||||
|
|
||||||
class SurveySertifikasi extends Model
|
class SurveySertifikasi extends Model
|
||||||
{
|
{
|
||||||
use HasFactory, SoftDeletes;
|
use HasFactory, SoftDeletes, KembalikanStatusPetaniKeDraf;
|
||||||
|
|
||||||
protected $table = 'survey_sertifikasi';
|
protected $table = 'survey_sertifikasi';
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
namespace App\Models\Pertanian;
|
namespace App\Models\Pertanian;
|
||||||
|
|
||||||
|
use App\Models\Concerns\KembalikanStatusPetaniKeDraf;
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||||
use App\Models\Profile;
|
use App\Models\Profile;
|
||||||
@@ -17,7 +18,7 @@ use App\Enums\KeparahanSerangan;
|
|||||||
|
|
||||||
class Tanaman extends Model
|
class Tanaman extends Model
|
||||||
{
|
{
|
||||||
use SoftDeletes;
|
use SoftDeletes, KembalikanStatusPetaniKeDraf;
|
||||||
|
|
||||||
protected $table = 'map_tanaman';
|
protected $table = 'map_tanaman';
|
||||||
|
|
||||||
@@ -80,4 +81,11 @@ class Tanaman extends Model
|
|||||||
{
|
{
|
||||||
return $this->belongsTo(Lahan::class, 'lahan_id');
|
return $this->belongsTo(Lahan::class, 'lahan_id');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Untuk trait KembalikanStatusPetaniKeDraf: petani diambil dari lahannya.
|
||||||
|
protected function petaniIdUntukStatus(): ?int
|
||||||
|
{
|
||||||
|
return $this->petani_id ?? self::ingatPerRequest('status_petani.lahan', $this->lahan_id,
|
||||||
|
fn () => Lahan::withoutGlobalScopes()->whereKey($this->lahan_id)->value('petani_id'));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ class KelengkapanPetani
|
|||||||
private const KONSERVASI_TIDAK_ADA = 'Tidak ada yang seperti itu di kebun saya';
|
private const KONSERVASI_TIDAK_ADA = 'Tidak ada yang seperti itu di kebun saya';
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Seluruh isian Profil Petani (total 209 untuk 1 lahan), per tabel.
|
* Seluruh isian Profil Petani (total 207 untuk 1 lahan), per tabel.
|
||||||
* Aturan hitung: satu pertanyaan = satu isian; kolom repeater dihitung sekali per kolom;
|
* Aturan hitung: satu pertanyaan = satu isian; kolom repeater dihitung sekali per kolom;
|
||||||
* teks "Lainnya" tidak dihitung; provinsi/kabupaten/kecamatan ikut terisi bila desa terisi.
|
* teks "Lainnya" tidak dihitung; provinsi/kabupaten/kecamatan ikut terisi bila desa terisi.
|
||||||
*/
|
*/
|
||||||
@@ -46,9 +46,9 @@ class KelengkapanPetani
|
|||||||
'komoditas_id', 'desa_kelurahan_id',
|
'komoditas_id', 'desa_kelurahan_id',
|
||||||
];
|
];
|
||||||
|
|
||||||
private const ISIAN_LAHAN = [ // 18 + 3 wilayah = 21, per lahan
|
private const ISIAN_LAHAN = [ // 16 + 3 wilayah = 19, per lahan
|
||||||
'desa_kelurahan_id', 'path', 'luas_lahan', 'komoditas_id', 'jenis_komoditas_id', 'varietas_id',
|
'desa_kelurahan_id', 'path', 'luas_lahan', 'komoditas_id', 'jenis_komoditas_id', 'varietas_id',
|
||||||
'jumlah_tanaman', 'kondisi_tanaman', 'serangan_hama', 'penyakit_tanaman', 'keparahan_serangan',
|
'jumlah_tanaman', 'kondisi_tanaman', 'keparahan_serangan',
|
||||||
'jenis_hama', 'jenis_penyakit', 'umur_tanaman', 'umur_lahan', 'komoditas_lain', 'tanaman_penaung', 'foto',
|
'jenis_hama', 'jenis_penyakit', 'umur_tanaman', 'umur_lahan', 'komoditas_lain', 'tanaman_penaung', 'foto',
|
||||||
];
|
];
|
||||||
|
|
||||||
@@ -153,7 +153,7 @@ class KelengkapanPetani
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Hitungan seluruh isian: terisi, total (209 untuk 1 lahan; +21 per lahan tambahan),
|
* Hitungan seluruh isian: terisi, total (207 untuk 1 lahan; +19 per lahan tambahan),
|
||||||
* tidak_berlaku (pertanyaan lanjutan yang tidak perlu dijawab), berlaku, persen.
|
* tidak_berlaku (pertanyaan lanjutan yang tidak perlu dijawab), berlaku, persen.
|
||||||
*/
|
*/
|
||||||
public function hitungIsian(): array
|
public function hitungIsian(): array
|
||||||
@@ -349,7 +349,9 @@ class KelengkapanPetani
|
|||||||
'lahan_id' => $l->id,
|
'lahan_id' => $l->id,
|
||||||
'url' => route('petani.lahan-tanaman.edit', [$this->petani->id, $l->id]),
|
'url' => route('petani.lahan-tanaman.edit', [$this->petani->id, $l->id]),
|
||||||
];
|
];
|
||||||
$adaSerangan = self::terisi($l->serangan_hama) || self::terisi($l->penyakit_tanaman);
|
// Jenis hama/penyakit lahan terisi otomatis dari Praktik Budidaya; kolom lama serangan_hama/penyakit_tanaman ikut dicek untuk data lama.
|
||||||
|
$adaSerangan = self::terisi($l->jenis_hama) || self::terisi($l->jenis_penyakit)
|
||||||
|
|| self::terisi($l->serangan_hama) || self::terisi($l->penyakit_tanaman);
|
||||||
|
|
||||||
return array_filter([
|
return array_filter([
|
||||||
$this->item('Luas lahan', self::PERLU, 'luas_lahan', $l->luas_lahan, $tambahan),
|
$this->item('Luas lahan', self::PERLU, 'luas_lahan', $l->luas_lahan, $tambahan),
|
||||||
@@ -358,8 +360,6 @@ class KelengkapanPetani
|
|||||||
$this->item('Umur tanaman', self::PERLU, 'umur_tanaman', $l->umur_tanaman, $tambahan),
|
$this->item('Umur tanaman', self::PERLU, 'umur_tanaman', $l->umur_tanaman, $tambahan),
|
||||||
$this->item('Jumlah tanaman', self::PERLU, 'jumlah_tanaman', $l->jumlah_tanaman, $tambahan),
|
$this->item('Jumlah tanaman', self::PERLU, 'jumlah_tanaman', $l->jumlah_tanaman, $tambahan),
|
||||||
$this->item('Kondisi tanaman', self::PERLU, 'kondisi_tanaman', $l->kondisi_tanaman, $tambahan),
|
$this->item('Kondisi tanaman', self::PERLU, 'kondisi_tanaman', $l->kondisi_tanaman, $tambahan),
|
||||||
$this->item('Serangan hama', self::PERLU, 'serangan_hama', $l->serangan_hama, $tambahan),
|
|
||||||
$this->item('Penyakit tanaman', self::PERLU, 'penyakit_tanaman', $l->penyakit_tanaman, $tambahan),
|
|
||||||
$adaSerangan
|
$adaSerangan
|
||||||
? $this->item('Keparahan serangan', self::PERLU, 'keparahan_serangan', $l->keparahan_serangan, $tambahan)
|
? $this->item('Keparahan serangan', self::PERLU, 'keparahan_serangan', $l->keparahan_serangan, $tambahan)
|
||||||
: null,
|
: null,
|
||||||
@@ -396,6 +396,7 @@ class KelengkapanPetani
|
|||||||
$this->item('Dasar penentuan panen', self::WAJIB, 'dasar_penentuan_panen', $panen?->dasar_penentuan_panen),
|
$this->item('Dasar penentuan panen', self::WAJIB, 'dasar_penentuan_panen', $panen?->dasar_penentuan_panen),
|
||||||
$this->item('Hasil komoditas utama per musim', self::PERLU, 'hasil_komoditas_utama_permusim', $panen?->hasil_komoditas_utama_permusim),
|
$this->item('Hasil komoditas utama per musim', self::PERLU, 'hasil_komoditas_utama_permusim', $panen?->hasil_komoditas_utama_permusim),
|
||||||
$this->item('Praktik sortasi', self::WAJIB, 'praktik_sortasi', $panen?->praktik_sortasi),
|
$this->item('Praktik sortasi', self::WAJIB, 'praktik_sortasi', $panen?->praktik_sortasi),
|
||||||
|
$this->item('Tingkat hasil panen ditolak pembeli', self::WAJIB, 'tingkat_reject', $panen?->hasil_panen_reject),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -181,7 +181,7 @@
|
|||||||
|
|
||||||
if (!sorot(btn.dataset.input)) {
|
if (!sorot(btn.dataset.input)) {
|
||||||
const pesan = 'Kolom ini belum tampil di halaman ini. Simpan bagian yang sudah ada terlebih dahulu, atau periksa jawaban pertanyaan sebelumnya.';
|
const pesan = 'Kolom ini belum tampil di halaman ini. Simpan bagian yang sudah ada terlebih dahulu, atau periksa jawaban pertanyaan sebelumnya.';
|
||||||
window.Swal ? Swal.fire({ icon: 'info', text: pesan }) : alert(pesan);
|
window.Swal ? Swal.fire({ icon: 'info', text: pesan, buttonsStyling: false, customClass: { confirmButton: 'btn btn-primary' } }) : alert(pesan);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
{{--
|
{{--
|
||||||
Kelengkapan data (terisi X dari 209) + status Draf/Lengkap/Terverifikasi di kartu Profil Petani.
|
Kelengkapan data (terisi X dari total isian) + status Draf/Lengkap/Terverifikasi di kartu Profil Petani.
|
||||||
Tombol "Tandai Lengkap" hanya untuk enumerator penginput, dan nonaktif selama isian wajib masih kosong.
|
Tombol "Tandai Lengkap" hanya untuk enumerator penginput, dan nonaktif selama isian wajib masih kosong.
|
||||||
--}}
|
--}}
|
||||||
@props(['petani'])
|
@props(['petani'])
|
||||||
@@ -42,11 +42,15 @@
|
|||||||
|
|
||||||
@if ($bisaTandai && $status === StatusDataPetani::DRAFT)
|
@if ($bisaTandai && $status === StatusDataPetani::DRAFT)
|
||||||
<form method="POST" action="{{ route('petani.status.update', $petani->id) }}" class="form-status-petani mt-2"
|
<form method="POST" action="{{ route('petani.status.update', $petani->id) }}" class="form-status-petani mt-2"
|
||||||
data-konfirmasi="Tandai data petani ini sudah lengkap? Koordinator akan memverifikasinya.">
|
data-judul="Pernyataan Kelengkapan Data"
|
||||||
|
data-konfirmasi="Setelah ditandai lengkap, data akan diteruskan ke koordinator untuk diverifikasi."
|
||||||
|
data-pernyataan="Saya menyatakan bahwa data petani {{ $petani->nama }} telah saya periksa, sudah lengkap, dan sesuai dengan hasil survei bersama pihak terkait di lapangan. Saya bertanggung jawab atas kebenaran data ini."
|
||||||
|
data-tombol="Ya, Tandai Lengkap">
|
||||||
@csrf
|
@csrf
|
||||||
@method('PUT')
|
@method('PUT')
|
||||||
<input type="hidden" name="status" value="{{ StatusDataPetani::LENGKAP->value }}">
|
<input type="hidden" name="status" value="{{ StatusDataPetani::LENGKAP->value }}">
|
||||||
<button type="submit" class="btn btn-sm btn-success w-100" @disabled($wajibKosong > 0)
|
<input type="hidden" name="pernyataan" value="0">
|
||||||
|
<button type="submit" class="btn btn-sm btn-primary w-100" @disabled($wajibKosong > 0)
|
||||||
@if ($wajibKosong) title="Lengkapi {{ $wajibKosong }} isian wajib terlebih dahulu" @endif>
|
@if ($wajibKosong) title="Lengkapi {{ $wajibKosong }} isian wajib terlebih dahulu" @endif>
|
||||||
<i class="icon-base ti tabler-checks icon-sm me-1"></i>Tandai Sudah Lengkap
|
<i class="icon-base ti tabler-checks icon-sm me-1"></i>Tandai Sudah Lengkap
|
||||||
</button>
|
</button>
|
||||||
@@ -61,6 +65,7 @@
|
|||||||
<i class="icon-base ti tabler-arrow-back-up icon-sm me-1"></i>Batalkan Tanda Lengkap
|
<i class="icon-base ti tabler-arrow-back-up icon-sm me-1"></i>Batalkan Tanda Lengkap
|
||||||
</button>
|
</button>
|
||||||
</form>
|
</form>
|
||||||
|
<p class="mb-0 mt-1 text-muted fst-italic" style="font-size: 0.7rem;">Mengubah data petani akan mengembalikan status ke Draf.</p>
|
||||||
@elseif ($status === StatusDataPetani::DRAFT)
|
@elseif ($status === StatusDataPetani::DRAFT)
|
||||||
<p class="mb-0 mt-1 text-muted fst-italic" style="font-size: 0.7rem;">Hanya enumerator penginput yang dapat menandai lengkap.</p>
|
<p class="mb-0 mt-1 text-muted fst-italic" style="font-size: 0.7rem;">Hanya enumerator penginput yang dapat menandai lengkap.</p>
|
||||||
@elseif ($status === StatusDataPetani::LENGKAP)
|
@elseif ($status === StatusDataPetani::LENGKAP)
|
||||||
@@ -70,31 +75,64 @@
|
|||||||
@once
|
@once
|
||||||
@push('scripts')
|
@push('scripts')
|
||||||
<script>
|
<script>
|
||||||
|
// Tombol popup mengikuti warna tombol aplikasi (bukan ungu bawaan SweetAlert).
|
||||||
|
const gayaTombolSwal = () => ({
|
||||||
|
buttonsStyling: false,
|
||||||
|
customClass: { confirmButton: 'btn btn-primary me-2', cancelButton: 'btn btn-label-secondary' },
|
||||||
|
});
|
||||||
|
|
||||||
document.addEventListener('submit', function (e) {
|
document.addEventListener('submit', function (e) {
|
||||||
const form = e.target.closest('.form-status-petani');
|
const form = e.target.closest('.form-status-petani');
|
||||||
if (!form || form.dataset.terkonfirmasi) return;
|
if (!form || form.dataset.terkonfirmasi) return;
|
||||||
|
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
const kirim = () => { form.dataset.terkonfirmasi = '1'; form.submit(); };
|
const pernyataan = form.dataset.pernyataan;
|
||||||
|
const kirim = () => {
|
||||||
|
if (pernyataan) form.querySelector('input[name="pernyataan"]').value = '1';
|
||||||
|
form.dataset.terkonfirmasi = '1';
|
||||||
|
form.submit();
|
||||||
|
};
|
||||||
|
|
||||||
if (!window.Swal) {
|
if (!window.Swal) {
|
||||||
if (confirm(form.dataset.konfirmasi)) kirim();
|
if (confirm((pernyataan ? pernyataan + '\n\n' : '') + form.dataset.konfirmasi)) kirim();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Swal.fire({
|
|
||||||
icon: 'question',
|
const opsi = {
|
||||||
|
icon: pernyataan ? 'warning' : 'question',
|
||||||
|
title: form.dataset.judul || undefined,
|
||||||
text: form.dataset.konfirmasi,
|
text: form.dataset.konfirmasi,
|
||||||
showCancelButton: true,
|
showCancelButton: true,
|
||||||
confirmButtonText: 'Ya',
|
confirmButtonText: form.dataset.tombol || 'Ya',
|
||||||
cancelButtonText: 'Batal',
|
cancelButtonText: 'Batal',
|
||||||
}).then((r) => { if (r.isConfirmed) kirim(); });
|
...gayaTombolSwal(),
|
||||||
|
};
|
||||||
|
|
||||||
|
// Tandai Lengkap: wajib mencentang pernyataan sebelum bisa lanjut.
|
||||||
|
if (pernyataan) {
|
||||||
|
opsi.input = 'checkbox';
|
||||||
|
opsi.inputValue = 0;
|
||||||
|
opsi.inputPlaceholder = pernyataan;
|
||||||
|
opsi.inputValidator = (dicentang) => !dicentang && 'Centang pernyataan terlebih dahulu.';
|
||||||
|
opsi.customClass.input = 'text-start small';
|
||||||
|
}
|
||||||
|
|
||||||
|
Swal.fire(opsi).then((r) => { if (r.isConfirmed) kirim(); });
|
||||||
});
|
});
|
||||||
|
|
||||||
@if (session('status_petani_success') || session('status_petani_error'))
|
@if (session('status_petani_info'))
|
||||||
|
// Data diubah setelah ditandai lengkap → status kembali ke Draf (KembalikanStatusPetaniKeDraf).
|
||||||
window.addEventListener('load', function () {
|
window.addEventListener('load', function () {
|
||||||
const pesan = @json(session('status_petani_success') ?? session('status_petani_error'));
|
const pesan = @json(session('status_petani_info'));
|
||||||
|
window.Swal ? Swal.fire({ icon: 'info', title: 'Status kembali ke Draf', text: pesan, ...gayaTombolSwal() }) : alert(pesan);
|
||||||
|
});
|
||||||
|
@endif
|
||||||
|
|
||||||
|
@if (session('status_petani_success') || session('status_petani_error') || $errors->has('pernyataan'))
|
||||||
|
window.addEventListener('load', function () {
|
||||||
|
const pesan = @json(session('status_petani_success') ?? session('status_petani_error') ?? $errors->first('pernyataan'));
|
||||||
const ikon = @json(session('status_petani_success') ? 'success' : 'error');
|
const ikon = @json(session('status_petani_success') ? 'success' : 'error');
|
||||||
window.Swal ? Swal.fire({ icon: ikon, text: pesan }) : alert(pesan);
|
window.Swal ? Swal.fire({ icon: ikon, text: pesan, ...gayaTombolSwal() }) : alert(pesan);
|
||||||
});
|
});
|
||||||
@endif
|
@endif
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
Reference in New Issue
Block a user