Files

308 lines
13 KiB
PHP
Raw Permalink Normal View History

2026-02-08 15:16:35 +07:00
<?php
namespace App\Http\Controllers\Breeding;
use App\Http\Controllers\Controller;
use App\Models\{Matting, Cat, Kitten};
use App\Traits\LogsActivity;
use Illuminate\Http\{Request, RedirectResponse, JsonResponse};
2026-09-23 12:45:02 +07:00
use Illuminate\Support\Facades\{DB, Storage, Gate};
2026-02-08 15:16:35 +07:00
use Illuminate\View\View;
class MattingController extends Controller
{
use LogsActivity;
public function index(): View
{
2026-09-23 12:45:02 +07:00
Gate::authorize('check-access', ['matting', 'read']);
2026-02-08 15:16:35 +07:00
$mattings = Matting::with(['sire', 'dam'])
->withCount('kittens')
->latest()
->paginate(15);
return view('pages.matting.index', compact('mattings'));
}
public function create(): View
{
2026-09-23 12:45:02 +07:00
Gate::authorize('check-access', ['matting', 'create']);
2026-02-08 15:16:35 +07:00
$sires = Cat::where('jenis_kelamin', 'Jantan')->get(['id', 'nama_kucing', 'ras']);
$dams = Cat::where('jenis_kelamin', 'Betina')->get(['id', 'nama_kucing', 'ras']);
return view('pages.matting.create', compact('sires', 'dams'));
}
public function getCatData($id): JsonResponse
{
2026-09-23 12:45:02 +07:00
Gate::authorize('check-access', ['matting', 'read']);
2026-02-08 15:16:35 +07:00
$cat = Cat::find($id);
if (!$cat) return response()->json(['error' => 'Kucing tidak ditemukan'], 404);
return response()->json([
'tgl_lahir' => $cat->tanggal_lahir ? $cat->tanggal_lahir->format('Y-m-d') : '',
'pedigree' => $cat->pedigree ?? '',
'microchip' => $cat->microchip ?? '',
'kode_ems' => $cat->kode_ems ?? '',
]);
}
/**
* STORE: Menyimpan Data Breeding Baru
*/
public function store(Request $request): RedirectResponse
{
2026-09-23 12:45:02 +07:00
Gate::authorize('check-access', ['matting', 'create']);
2026-02-08 15:16:35 +07:00
$this->validateMatting($request);
return DB::transaction(function () use ($request) {
// 1. Sinkronisasi Data Induk (Update profil bapak/ibu di tabel cats)
$this->syncParentData($request);
// 2. Simpan Transaksi Matting
$matting = Matting::create(array_merge($request->except('kittens'), [
'tanggal_kawin' => $request->tgl_kawin_awal,
'user_id' => auth()->id(),
'ems_bapak' => $request->ems_bapak,
'ems_ibu' => $request->ems_ibu,
]));
// 3. Simpan Kittens
if ($request->has('kittens')) {
foreach ($request->kittens as $index => $data) {
$this->saveKittenData($matting, $data, $index, $request);
}
}
$this->logAction('MATTING_CREATED', $matting, "Registrasi Breeding Baru");
return redirect()->route('matting.index')->with('success', 'Data Breeding & Anak berhasil disimpan!');
});
}
/**
* EDIT: Menampilkan Form Edit (Metode yang tadi hilang)
*/
public function edit(Matting $matting): View
{
2026-09-23 12:45:02 +07:00
Gate::authorize('check-access', ['matting', 'update']);
2026-02-08 15:16:35 +07:00
// Load relasi agar data anak muncul di form edit
$matting->load('kittens.cat');
$sires = Cat::where('jenis_kelamin', 'Jantan')->get(['id', 'nama_kucing', 'ras']);
$dams = Cat::where('jenis_kelamin', 'Betina')->get(['id', 'nama_kucing', 'ras']);
return view('pages.matting.edit', compact('matting', 'sires', 'dams'));
}
/**
* UPDATE: Memperbarui Data Breeding & Sinkronisasi Ulang Kittens
*/
public function update(Request $request, Matting $matting): RedirectResponse
{
2026-09-23 12:45:02 +07:00
Gate::authorize('check-access', ['matting', 'update']);
2026-02-08 15:16:35 +07:00
$this->validateMatting($request);
return DB::transaction(function () use ($request, $matting) {
// 1. Update profil Bapak/Ibu di tabel 'cats'
$this->syncParentData($request);
// 2. Update data di tabel 'mattings'
$matting->update(array_merge($request->except('kittens'), [
'tanggal_kawin' => $request->tgl_kawin_awal,
'ems_bapak' => $request->ems_bapak,
'ems_ibu' => $request->ems_ibu,
]));
// 3. Sinkronisasi Kittens (CRUD Logic)
$requestKittenIds = collect($request->kittens)->pluck('id')->filter()->toArray();
// Hapus Kitten yang tidak ada di form lagi
$kittensToDelete = $matting->kittens()->whereNotIn('id', $requestKittenIds)->get();
foreach ($kittensToDelete as $kDelete) {
if ($kDelete->cat_id) Cat::find($kDelete->cat_id)?->delete();
$kDelete->delete();
}
if ($request->has('kittens')) {
foreach ($request->kittens as $index => $data) {
if (isset($data['id']) && !empty($data['id'])) {
$kitten = Kitten::find($data['id']);
if ($kitten) {
// Update profil master anak di tabel 'cats'
Cat::where('id', $kitten->cat_id)->update([
'nama_kucing' => $data['nama'],
'jenis_kelamin' => $data['jenis_kelamin'],
'tanggal_lahir' => $data['tgl_lahir'],
'kode_ems' => $data['kode_ems'] ?? null,
'registry' => $data['registry'] ?? [],
]);
// Update record silsilah di tabel 'kittens'
$kitten->update([
'nama' => $data['nama'],
'tgl_lahir' => $data['tgl_lahir'],
'jenis_kelamin' => $data['jenis_kelamin'],
'kode_ems' => $data['kode_ems'] ?? null,
'is_pedigree' => isset($data['is_pedigree']),
'registry' => $data['registry'] ?? [],
]);
$this->handlePedigreeUploads($kitten, $index, $request);
}
} else {
$this->saveKittenData($matting, $data, $index, $request);
}
}
}
$this->logAction('MATTING_UPDATED', $matting, "Update Breeding Record");
return redirect()->route('matting.index')->with('success', 'Perubahan berhasil disimpan!');
});
}
2026-09-23 13:56:51 +07:00
public function updateStatus(Request $request, Matting $matting): RedirectResponse
{
Gate::authorize('check-access', ['matting', 'update']);
$validated = $request->validate([
'status' => 'required|in:proses,hamil,berhasil,gagal',
'actual_birth_date' => 'nullable|date',
'breeding_notes' => 'nullable|string|max:2000',
]);
if ($validated['status'] === 'hamil' && !$matting->pregnancy_confirmed_at) {
$validated['pregnancy_confirmed_at'] = now()->toDateString();
}
if ($validated['status'] === 'berhasil' && empty($validated['actual_birth_date'])) {
$validated['actual_birth_date'] = $matting->kittens()->min('tgl_lahir') ?: now()->toDateString();
}
$matting->update($validated);
$this->logAction('MATTING_STATUS_UPDATED', $matting, 'Memperbarui tahap pembiakan menjadi ' . $validated['status']);
return back()->with('success', 'Tahap pembiakan berhasil diperbarui.');
}
2026-02-08 15:16:35 +07:00
/**
* SINKRONISASI DATA INDUK (EMS Fix)
*/
private function syncParentData(Request $request)
{
Cat::where('id', $request->sire_id)->update([
'microchip' => $request->no_microchip_bapak,
'tanggal_lahir' => $request->tgl_lahir_sire,
'kode_ems' => $request->ems_bapak // Sinkron EMS Bapak
]);
Cat::where('id', $request->dam_id)->update([
'microchip' => $request->no_microchip_ibu,
'tanggal_lahir' => $request->tgl_lahir_dam,
'kode_ems' => $request->ems_ibu // Sinkron EMS Ibu
]);
}
/**
* SIMPAN DATA KITTEN (EMS & Registry Fix)
*/
private function saveKittenData($matting, $data, $index, $request)
{
$newCat = Cat::create([
'nama_kucing' => $data['nama'],
'ras' => $matting->dam->ras ?? 'Persian',
'jenis_kelamin' => $data['jenis_kelamin'],
'induk_jantan_id' => $matting->sire_id,
'induk_betina_id' => $matting->dam_id,
'status' => 'Kitten',
'tanggal_lahir' => $data['tgl_lahir'],
'kode_ems' => $data['kode_ems'] ?? null,
'registry' => $data['registry'] ?? [],
'pic_id' => auth()->id(),
'lokasi_kandang' => $matting->dam->lokasi_kandang ?? 'Lorong',
]);
$kitten = new Kitten([
'cat_id' => $newCat->id,
'matting_id' => $matting->id,
'nama' => $data['nama'],
'tgl_lahir' => $data['tgl_lahir'],
'jenis_kelamin' => $data['jenis_kelamin'],
'kode_ems' => $data['kode_ems'] ?? null,
'is_pedigree' => isset($data['is_pedigree']),
'registry' => $data['registry'] ?? [],
]);
$this->handlePedigreeUploads($kitten, $index, $request);
$kitten->save();
}
private function handlePedigreeUploads($kitten, $index, $request)
{
for ($i = 1; $i <= 4; $i++) {
$field = "foto_ped_$i";
if ($request->hasFile("kittens.$index.$field")) {
if ($kitten->$field) Storage::disk('public')->delete($kitten->$field);
$kitten->$field = $request->file("kittens.$index.$field")->store('kittens/pedigrees', 'public');
}
}
}
public function destroy(Matting $matting): RedirectResponse
{
2026-09-23 12:45:02 +07:00
Gate::authorize('check-access', ['matting', 'delete']);
2026-02-08 15:16:35 +07:00
return DB::transaction(function () use ($matting) {
try {
$pairName = ($matting->sire->nama_kucing ?? 'Sire') . ' x ' . ($matting->dam->nama_kucing ?? 'Dam');
// 1. Loop setiap data anak yang terhubung
foreach ($matting->kittens as $kitten) {
if ($kitten->cat_id) {
$cat = Cat::find($kitten->cat_id);
if ($cat) {
// Cek apakah anak ini punya data medis atau riwayat berat
$hasMedical = $cat->treatments()->exists();
$hasWeight = $cat->weightHistories()->exists();
if ($hasMedical || $hasWeight) {
// JIKA ADA DATA TERKAIT, BATALKAN DAN BERI INFO
return back()->with('error', "Gagal menghapus! Anak ({$cat->nama_kucing}) sudah memiliki data Rekam Medis/Berat Badan. Hapus data medis anak tersebut terlebih dahulu.");
}
$cat->delete();
}
}
$kitten->delete();
}
// 2. Hapus data Matting utama
$matting->delete();
$this->logAction('MATTING_DELETED', $matting, "Menghapus riwayat breeding: $pairName");
return redirect()->route('matting.index')->with('success', "Riwayat $pairName berhasil dihapus.");
} catch (\Illuminate\Database\QueryException $e) {
// Menangkap error database (Foreign Key Constraint)
return back()->with('error', "Sistem tidak dapat menghapus data ini karena integritas database terganggu. Silakan periksa data anak yang terkait.");
}
});
}
private function validateMatting(Request $request)
{
return $request->validate([
'sire_id' => 'required|exists:cats,id',
'dam_id' => 'required|exists:cats,id',
'tgl_kawin_awal' => 'required|date',
2026-09-23 13:56:51 +07:00
'status' => 'required|in:proses,hamil,berhasil,gagal',
'pregnancy_confirmed_at' => 'nullable|date',
'actual_birth_date' => 'nullable|date',
'breeding_notes' => 'nullable|string|max:2000',
2026-02-08 15:16:35 +07:00
'ems_bapak' => 'nullable|string',
'ems_ibu' => 'nullable|string',
'no_pedigree_bapak' => 'nullable|string',
'no_pedigree_ibu' => 'nullable|string',
'no_microchip_bapak'=> 'nullable|string',
'no_microchip_ibu' => 'nullable|string',
'kittens' => 'nullable|array',
'kittens.*.nama' => 'required_with:kittens|string',
'kittens.*.kode_ems'=> 'nullable|string',
'kittens.*.registry'=> 'nullable|array',
]);
}
}