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' ,
]);
}
}