withCount('kittens') ->latest() ->paginate(15); return view('pages.matting.index', compact('mattings')); } public function create(): View { Gate::authorize('check-access', ['matting', 'create']); $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 { Gate::authorize('check-access', ['matting', 'read']); $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 { Gate::authorize('check-access', ['matting', 'create']); $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 { Gate::authorize('check-access', ['matting', 'update']); // 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 { Gate::authorize('check-access', ['matting', 'update']); $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!'); }); } /** * 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 { Gate::authorize('check-access', ['matting', 'delete']); 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', 'status' => 'required|in:proses,berhasil,gagal', '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', ]); } }