184 lines
6.7 KiB
PHP
184 lines
6.7 KiB
PHP
|
|
<?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',
|
||
|
|
]);
|
||
|
|
}
|
||
|
|
}
|