Files
ilycats/app/Http/Controllers/TreatmentController.php
T

184 lines
6.7 KiB
PHP
Raw Normal View History

2026-02-08 15:16:35 +07:00
<?php
namespace App\Http\Controllers;
use App\Models\Cat;
use App\Models\Treatment;
use App\Models\Medicine;
use App\Traits\LogsActivity;
use Illuminate\Http\Request;
use Illuminate\View\View;
use Illuminate\Http\RedirectResponse;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Storage;
use Exception;
class TreatmentController extends Controller
{
use LogsActivity;
/**
* Menampilkan daftar rekam medis dengan optimasi Eager Loading.
*/
public function index(): View
{
$treatments = Treatment::with([
'cat:id,nama_kucing,foto',
'medicine:id,nama_obat,unit',
'user:id,name'
])
->latest('tanggal')
->paginate(15);
return view('pages.treatments.index', compact('treatments'));
}
/**
* Form tambah rekam medis.
*/
public function create(Request $request): View
{
$selectedCat = $request->filled('cat_id') ? Cat::findOrFail($request->cat_id) : null;
$cats = Cat::select('id', 'nama_kucing', 'ras')->get();
$medicines = Medicine::where('qty', '>', 0)->get();
return view('pages.treatments.create', compact('selectedCat', 'cats', 'medicines'));
}
/**
* Simpan rekam medis baru & potong stok (mendukung desimal).
*/
public function store(Request $request): RedirectResponse
{
$validated = $this->validateTreatment($request);
try {
DB::transaction(function () use ($request, &$validated) {
$medicine = Medicine::findOrFail($request->medicine_id);
// Validasi kecukupan stok desimal
if ($medicine->qty < $request->qty_used) {
throw new Exception("Stok {$medicine->nama_obat} tidak mencukupi (Sisa: {$medicine->qty} {$medicine->unit}).");
}
if ($request->hasFile('foto_bukti')) {
$validated['foto_bukti'] = $request->file('foto_bukti')->store('treatments', 'public');
}
// Otomatisasi data sistem
$validated['user_id'] = auth()->id();
$validated['nama_obat'] = $medicine->nama_obat;
$treatment = Treatment::create($validated);
// Potong stok (decrement mendukung nilai float/decimal)
$medicine->decrement('qty', $request->qty_used);
$this->logAction('TREATED', $treatment, "Mencatat pengobatan oleh " . auth()->user()->name);
});
return redirect()->route('cats.show', $request->cat_id)
->with('success', 'Rekam medis berhasil dicatat dengan presisi.');
} catch (Exception $e) {
if (isset($validated['foto_bukti'])) {
Storage::disk('public')->delete($validated['foto_bukti']);
}
return back()->withInput()->with('error', 'Gagal menyimpan: ' . $e->getMessage());
}
}
/**
* Form edit rekam medis.
*/
public function edit(Treatment $treatment): View
{
$cats = Cat::select('id', 'nama_kucing', 'ras')->get();
$medicines = Medicine::all();
return view('pages.treatments.edit', compact('treatment', 'cats', 'medicines'));
}
/**
* Update rekam medis & sinkronisasi ulang stok desimal.
*/
public function update(Request $request, Treatment $treatment): RedirectResponse
{
$validated = $this->validateTreatment($request);
try {
DB::transaction(function () use ($request, $treatment, &$validated) {
// 1. Kembalikan stok lama (Desimal Revert)
$oldMedicine = Medicine::find($treatment->medicine_id);
if ($oldMedicine) {
$oldMedicine->increment('qty', $treatment->qty_used);
}
// 2. Potong stok baru
$newMedicine = Medicine::findOrFail($request->medicine_id);
if ($newMedicine->qty < $request->qty_used) {
throw new Exception("Stok {$newMedicine->nama_obat} tidak mencukupi untuk perubahan ini.");
}
$newMedicine->decrement('qty', $request->qty_used);
// 3. Kelola Foto
if ($request->hasFile('foto_bukti')) {
if ($treatment->foto_bukti) Storage::disk('public')->delete($treatment->foto_bukti);
$validated['foto_bukti'] = $request->file('foto_bukti')->store('treatments', 'public');
}
// 4. Update data sistem
$validated['user_id'] = auth()->id();
$validated['nama_obat'] = $newMedicine->nama_obat;
$treatment->update($validated);
$this->logAction('UPDATED_TREATMENT', $treatment, "Diperbarui oleh " . auth()->user()->name);
});
return redirect()->route('cats.show', $request->cat_id)->with('success', 'Rekam medis & inventori berhasil di-sinkronisasi.');
} catch (Exception $e) {
return back()->withInput()->with('error', 'Gagal memperbarui: ' . $e->getMessage());
}
}
/**
* Hapus rekam medis & kembalikan stok.
*/
public function destroy(Treatment $treatment): RedirectResponse
{
try {
DB::transaction(function () use ($treatment) {
if ($treatment->medicine_id) {
Medicine::where('id', $treatment->medicine_id)->increment('qty', $treatment->qty_used);
}
if ($treatment->foto_bukti) Storage::disk('public')->delete($treatment->foto_bukti);
$this->logAction('DELETED_TREATMENT', $treatment, "Menghapus catatan medis kucing: {$treatment->cat->nama_kucing}");
$treatment->delete();
});
return back()->with('success', 'Data rekam medis dihapus dan stok dikembalikan.');
} catch (Exception $e) {
return back()->with('error', 'Gagal menghapus data.');
}
}
/**
* Helper Validasi: Terpusat untuk Clean Code & Mendukung Desimal.
*/
private function validateTreatment(Request $request)
{
return $request->validate([
'cat_id' => 'required|exists:cats,id',
'medicine_id' => 'required|exists:medicines,id',
// 'numeric' mengizinkan input desimal (koma)
'qty_used' => 'required|numeric|min:0.01',
'tanggal' => 'required|date',
'keluhan' => 'required|string|max:255',
'diagnosa' => 'required|string',
'dosis' => 'required|string',
'keterangan' => 'nullable|string',
'foto_bukti' => 'nullable|image|max:2048',
]);
}
}