validate([ 'cat_id' => 'required|exists:cats,id', 'type' => 'required|string', 'date_given' => 'required|date', 'next_schedule' => 'nullable|date|after_or_equal:date_given', 'medicines' => 'nullable|array', ]); try { return DB::transaction(function () use ($request) { $type = $request->type; $medicines = $request->input('medicines', []); if ($type === 'Grooming') { $this->createRecord($request->cat_id, $type, 'Routine Grooming', null, 'SESSION', $request); } else { foreach ($medicines as $med) { if (empty($med['name'])) continue; $doseValue = $this->parseFraction($med['dosage']); // Pengecekan Stok Sebelum Potong $item = Medicine::where('nama_obat', $med['name'])->first(); if ($item) { if ($item->qty < $doseValue) { throw new Exception("Stok obat '{$med['name']}' tidak mencukupi. Sisa: {$item->qty}"); } $item->decrement('qty', $doseValue); } $this->createRecord($request->cat_id, $type, $med['name'], $med['dosage'], $med['unit'], $request); } } // Update pengingat di tabel cats $this->updateCatReminder($request->cat_id, $type, $request->next_schedule); return back()->with('success', 'Medical Ledger berhasil dicatat dan jadwal otomatis diperbarui.'); }); } catch (Exception $e) { return back()->with('error', 'Gagal mencatat rekam medis: ' . $e->getMessage())->withInput(); } } /** * Tampilkan form Bulk Treatment */ /** * Tampilkan form Bulk Treatment */ public function bulkCreate() { Gate::authorize('check-access', ['cats', 'update']); // Mengambil kucing yang Sehat (2) maupun yang sedang Treatment (1) $cats = Cat::whereIn('treatment_status', [1, 2]) ->orderBy('nama_kucing', 'asc') ->get(); // Mengambil obat dengan stok yang valid (qty > 0) $availableMedicines = Medicine::where('qty', '>', 0)->orderBy('nama_obat')->get(); return view('pages.cats.medical-bulk', compact('cats', 'availableMedicines')); } /** * Simpan Bulk Treatment (Massal) */ public function bulkStore(Request $request) { Gate::authorize('check-access', ['cats', 'update']); $request->validate([ 'cat_ids' => 'required|array|min:1', 'type' => 'required', 'date_given' => 'required|date', 'next_schedule' => 'nullable|date|after_or_equal:date_given', ]); try { return DB::transaction(function () use ($request) { $catIds = $request->cat_ids; $medicines = $request->input('medicines', []); $totalCats = count($catIds); foreach ($catIds as $catId) { if ($request->type === 'Grooming') { $this->createRecord($catId, $request->type, 'Routine Grooming', null, 'SESSION', $request); } else { foreach ($medicines as $med) { if (empty($med['name'])) continue; $doseValue = $this->parseFraction($med['dosage']); // Validasi stok untuk bulk (kebutuhan = dosis * jumlah kucing) $item = Medicine::where('nama_obat', $med['name'])->first(); if ($item) { if ($item->qty < $doseValue) { throw new Exception("Stok '{$med['name']}' tidak cukup untuk pemrosesan massal."); } $item->decrement('qty', $doseValue); } $this->createRecord($catId, $request->type, $med['name'], $med['dosage'], $med['unit'], $request); } } $this->updateCatReminder($catId, $request->type, $request->next_schedule); } return redirect()->route('cats.index')->with('success', "Bulk Treatment berhasil diterapkan pada $totalCats kucing."); }); } catch (Exception $e) { return back()->with('error', 'Gagal memproses bulk treatment: ' . $e->getMessage())->withInput(); } } /** * Helper: Simpan data ke tabel medical_records */ /** * Helper: Simpan data ke tabel medical_records */ private function createRecord($catId, $type, $name, $dosage, $unit, $request) { return MedicalRecord::create([ 'cat_id' => $catId, 'user_id' => auth()->id(), // Ini adalah kolom yang benar sesuai migration kita 'type' => $type, 'treatment_name' => $name, 'dosage' => $this->parseFraction($dosage), 'unit' => $unit, 'date_given' => $request->date_given, 'next_schedule' => $request->next_schedule, 'notes' => $request->notes // HAPUS baris 'performed_by' di sini ]); } /** * Helper: Update kolom jadwal di tabel cats */ private function updateCatReminder($catId, $type, $nextDate) { if (!$nextDate) return; $mapping = [ 'Vaccine' => 'jadwal_vaksin', 'Deworming' => 'jadwal_obat_cacing', 'Flea Treatment' => 'jadwal_obat_kutu', 'Grooming' => 'jadwal_grooming', ]; if (isset($mapping[$type])) { Cat::where('id', $catId)->update([$mapping[$type] => $nextDate]); } } /** * Helper: Konversi pecahan (1/2) ke desimal (0.5) */ private function parseFraction($fraction) { if (is_null($fraction)) return 0; $fraction = str_replace(' ', '', $fraction); // Hapus spasi jika ada if (str_contains($fraction, '/')) { list($numerator, $denominator) = explode('/', $fraction); return $denominator > 0 ? (float)$numerator / (float)$denominator : 0; } return (float)$fraction; } public function create(Cat $cat) { Gate::authorize('check-access', ['cats', 'update']); $availableMedicines = Medicine::where('qty', '>', 0)->orderBy('nama_obat')->get(); return view('pages.cats.medical-ledger-create', compact('cat', 'availableMedicines')); } }