327 lines
13 KiB
PHP
327 lines
13 KiB
PHP
<?php
|
|
|
|
namespace App\Http\Controllers;
|
|
|
|
use App\Models\MutasiAyam;
|
|
use App\Models\JenisMutasi;
|
|
use App\Models\Kandang;
|
|
use Illuminate\Http\Request;
|
|
use Illuminate\Support\Facades\DB;
|
|
use Illuminate\Support\Facades\Auth;
|
|
use Illuminate\Support\Facades\Validator;
|
|
|
|
class AyamController extends Controller
|
|
{
|
|
public function index(Request $request)
|
|
{
|
|
$query = MutasiAyam::with(['kandang', 'jenisMutasi']);
|
|
$jenisMutasi = JenisMutasi::all();
|
|
|
|
/** @var \App\Models\User $user */
|
|
$user = Auth::user();
|
|
if ($user->isKaryawan()) {
|
|
$query->where('user_id', $user->id);
|
|
}
|
|
|
|
if ($request->search) {
|
|
$query->where(function ($q) use ($request) {
|
|
$q->whereHas('kandang', function ($k) use ($request) {
|
|
$k->where('nama_kandang', 'like', '%' . $request->search . '%');
|
|
})->orWhere('keterangan', 'like', '%' . $request->search . '%');
|
|
});
|
|
}
|
|
|
|
if ($request->kandang) $query->where('kandang_id', $request->kandang);
|
|
if ($request->bulan) $query->whereMonth('tanggal', $request->bulan);
|
|
if ($request->tahun) $query->whereYear('tanggal', $request->tahun);
|
|
|
|
$perPage = $request->perPage ?? 10;
|
|
$data = $query
|
|
->orderBy('tanggal', 'desc') // tanggal terbaru dulu
|
|
->orderBy('id', 'desc') // jika tanggal sama, yang terakhir ditambah tetap di atas
|
|
->paginate($perPage)
|
|
->withQueryString();
|
|
|
|
// jumlah ayam terakhir per kandang
|
|
$kandang = Kandang::query()
|
|
->select('id', 'nama_kandang')
|
|
->selectSub(function ($q) {
|
|
$q->from('mutasi_ayam')
|
|
->join('jenis_mutasi', 'mutasi_ayam.jenis_mutasi_id', '=', 'jenis_mutasi.id')
|
|
->whereColumn('mutasi_ayam.kandang_id', 'kandang.id')
|
|
->selectRaw("
|
|
COALESCE(SUM(
|
|
CASE
|
|
WHEN jenis_mutasi.tipe = 'tambah' THEN jumlah
|
|
WHEN jenis_mutasi.tipe = 'kurang' THEN -jumlah
|
|
WHEN jenis_mutasi.tipe = 'transfer' THEN -jumlah
|
|
ELSE 0
|
|
END
|
|
),0)
|
|
");
|
|
}, 'jumlah_ayam_terakhir')
|
|
->get();
|
|
return view('inventori-ayam', compact('data', 'kandang', 'jenisMutasi'));
|
|
}
|
|
|
|
public function store(Request $request)
|
|
{
|
|
$request->validate([
|
|
'jenis_mutasi_id' => 'required|exists:jenis_mutasi,id',
|
|
'jumlah' => 'required|integer|min:1|max:9999',
|
|
'tanggal' => 'required|date|before_or_equal:today',
|
|
'keterangan' => 'nullable|string|max:255',
|
|
], [
|
|
'jenis_mutasi_id.required' => 'Jenis mutasi wajib dipilih.',
|
|
'jenis_mutasi_id.exists' => 'Jenis mutasi tidak valid.',
|
|
|
|
'jumlah.required' => 'Jumlah ayam wajib diisi.',
|
|
'jumlah.integer' => 'Jumlah ayam harus berupa angka.',
|
|
'jumlah.min' => 'Jumlah ayam minimal 1 ekor.',
|
|
|
|
'tanggal.required' => 'Tanggal wajib diisi.',
|
|
'tanggal.date' => 'Format tanggal tidak valid.',
|
|
'tanggal.before_or_equal' => 'Tanggal tidak boleh melebihi hari ini.',
|
|
|
|
'keterangan.required_if' => 'Keterangan wajib diisi.',
|
|
'keterangan.string' => 'Keterangan harus berupa teks.',
|
|
'keterangan.max' => 'Keterangan maksimal 255 karakter.',
|
|
]);
|
|
|
|
DB::transaction(function () use ($request) {
|
|
|
|
// ✅ ambil jenis mutasi dari tabel master
|
|
$jenisPindah = JenisMutasi::where('nama', 'pindah')->first();
|
|
$jenisMasuk = JenisMutasi::where('nama', 'masuk')->first();
|
|
|
|
// PINDAH
|
|
$jenis = JenisMutasi::findOrFail($request->jenis_mutasi_id);
|
|
|
|
if ($jenis->nama === 'pindah'){ $request->validate([
|
|
'kandang_asal_id' => 'required|exists:kandang,id|different:kandang_tujuan_id',
|
|
'kandang_tujuan_id' => 'required|exists:kandang,id',
|
|
], [
|
|
'kandang_asal_id.required' => 'Kandang asal wajib dipilih.',
|
|
'kandang_asal_id.different' => 'Kandang asal dan tujuan tidak boleh sama.',
|
|
'kandang_tujuan_id.required' => 'Kandang tujuan wajib dipilih.',
|
|
]);
|
|
|
|
$kandangAsal = Kandang::findOrFail($request->kandang_asal_id);
|
|
$kandangTujuan = Kandang::findOrFail($request->kandang_tujuan_id);
|
|
|
|
$stokAsal = $kandangAsal->mutasiAyam()
|
|
->join('jenis_mutasi', 'mutasi_ayam.jenis_mutasi_id', '=', 'jenis_mutasi.id')
|
|
->selectRaw("
|
|
COALESCE(SUM(
|
|
CASE
|
|
WHEN jenis_mutasi.tipe = 'tambah' THEN jumlah
|
|
WHEN jenis_mutasi.tipe IN ('kurang','transfer') THEN -jumlah
|
|
ELSE 0
|
|
END
|
|
),0) as stok
|
|
")
|
|
->value('stok');
|
|
|
|
if ($stokAsal <= 0) {
|
|
throw \Illuminate\Validation\ValidationException::withMessages([
|
|
'jumlah' => 'Stok kandang asal sudah habis.'
|
|
]);
|
|
}
|
|
|
|
if ($request->jumlah > $stokAsal) {
|
|
throw \Illuminate\Validation\ValidationException::withMessages([
|
|
'jumlah' => "Stok kandang asal hanya $stokAsal ekor."
|
|
]);
|
|
}
|
|
|
|
MutasiAyam::create([
|
|
'kandang_id' => $request->kandang_asal_id,
|
|
'user_id' => Auth::id(),
|
|
'jenis_mutasi_id' => $jenisPindah->id,
|
|
'jumlah' => $request->jumlah,
|
|
'tanggal' => $request->tanggal,
|
|
'keterangan' => 'Pindah ke ' . $kandangTujuan->nama_kandang,
|
|
]);
|
|
|
|
MutasiAyam::create([
|
|
'kandang_id' => $request->kandang_tujuan_id,
|
|
'user_id' => Auth::id(),
|
|
'jenis_mutasi_id' => $jenisMasuk->id,
|
|
'jumlah' => $request->jumlah,
|
|
'tanggal' => $request->tanggal,
|
|
'keterangan' => 'Pindahan dari ' . $kandangAsal->nama_kandang,
|
|
]);
|
|
}
|
|
|
|
// MUTASI BIASA
|
|
else {
|
|
|
|
$request->validate([
|
|
'kandang_id' => 'required|exists:kandang,id',
|
|
], [
|
|
'kandang_id.required' => 'Nama kandang wajib dipilih.',
|
|
'kandang_id.exists' => 'Kandang tidak ditemukan.',
|
|
]);
|
|
$kandang = Kandang::findOrFail($request->kandang_id);
|
|
|
|
$stok = $kandang->mutasiAyam()
|
|
->join('jenis_mutasi', 'mutasi_ayam.jenis_mutasi_id', '=', 'jenis_mutasi.id')
|
|
->selectRaw("
|
|
COALESCE(SUM(
|
|
CASE
|
|
WHEN jenis_mutasi.tipe = 'tambah' THEN jumlah
|
|
WHEN jenis_mutasi.tipe IN ('kurang','transfer') THEN -jumlah
|
|
ELSE 0
|
|
END
|
|
),0) as stok
|
|
")
|
|
->value('stok'); // ← WAJIB
|
|
$jenis = JenisMutasi::findOrFail($request->jenis_mutasi_id);
|
|
// Kalau mutasi keluar/mati/afkir → cek stok
|
|
if (in_array($jenis->nama, ['mati', 'afkir'])) {
|
|
if ($stok <= 0) {
|
|
throw \Illuminate\Validation\ValidationException::withMessages([
|
|
'jumlah' => 'Stok ayam di kandang ini sudah habis.'
|
|
]);
|
|
}
|
|
|
|
if ($request->jumlah > $stok) {
|
|
throw \Illuminate\Validation\ValidationException::withMessages([
|
|
'jumlah' => "Stok hanya tersisa $stok ekor."
|
|
]);
|
|
}
|
|
}
|
|
|
|
MutasiAyam::create([
|
|
'kandang_id' => $request->kandang_id,
|
|
'user_id' => Auth::id(),
|
|
'jenis_mutasi_id' => $request->jenis_mutasi_id,
|
|
'jumlah' => $request->jumlah,
|
|
'tanggal' => $request->tanggal,
|
|
'keterangan' => $request->keterangan,
|
|
]);
|
|
}
|
|
});
|
|
|
|
return redirect()->route('ayam')
|
|
->with('success', 'Data mutasi berhasil disimpan.');
|
|
}
|
|
|
|
public function update(Request $request, $id)
|
|
{
|
|
$mutasi = MutasiAyam::findOrFail($id);
|
|
// CEGAH EDIT DATA PINDAH
|
|
if (
|
|
$mutasi->jenisMutasi->nama === 'pindah' ||
|
|
str_contains($mutasi->keterangan, 'Pindahan dari')
|
|
) {
|
|
abort(403, 'Data hasil pindahan tidak boleh diedit.');
|
|
}
|
|
/** @var \App\Models\User $user */
|
|
$user = Auth::user();
|
|
|
|
if ($user->isKaryawan() && $mutasi->user_id !== $user->id) {
|
|
abort(403, 'Tidak diizinkan mengedit data ini.');
|
|
}
|
|
// VALIDASI MANUAL
|
|
$validator = Validator::make($request->all(), [
|
|
'kandang_id' => 'required|exists:kandang,id',
|
|
'jenis_mutasi_id' => 'required|exists:jenis_mutasi,id',
|
|
'jumlah' => 'required|integer|min:1|max:9999',
|
|
'tanggal' => 'required|date|before_or_equal:today',
|
|
'keterangan' => 'nullable|string|max:255',
|
|
|
|
], [
|
|
'kandang_id.required' => 'Nama kandang wajib dipilih.',
|
|
'kandang_id.exists' => 'Kandang tidak ditemukan.',
|
|
'jenis_mutasi_id.required' => 'Jenis mutasi wajib dipilih.',
|
|
'jenis_mutasi_id.exists' => 'Jenis mutasi tidak valid.',
|
|
'jumlah.required' => 'Jumlah ayam wajib diisi.',
|
|
'jumlah.integer' => 'Jumlah ayam harus berupa angka.',
|
|
'jumlah.min' => 'Jumlah ayam minimal 1 ekor.',
|
|
'tanggal.required' => 'Tanggal wajib diisi.',
|
|
'tanggal.date' => 'Format tanggal tidak valid.',
|
|
'tanggal.before_or_equal' => 'Tanggal tidak boleh melebihi hari ini.',
|
|
'keterangan.required_if' => 'Keterangan wajib diisi.',
|
|
'keterangan.string' => 'Keterangan harus berupa teks.',
|
|
'keterangan.max' => 'Keterangan maksimal 255 karakter.',
|
|
]);
|
|
|
|
if ($validator->fails()) {
|
|
return back()
|
|
->withErrors($validator)
|
|
->withInput()
|
|
->with('edit_id', $mutasi->id);
|
|
}
|
|
$jenis = JenisMutasi::findOrFail($request->jenis_mutasi_id);
|
|
// HITUNG STOK
|
|
$kandang = Kandang::findOrFail($request->kandang_id);
|
|
|
|
$stok = $kandang->mutasiAyam()
|
|
->join('jenis_mutasi', 'mutasi_ayam.jenis_mutasi_id', '=', 'jenis_mutasi.id')
|
|
->selectRaw("
|
|
COALESCE(SUM(
|
|
CASE
|
|
WHEN jenis_mutasi.tipe = 'tambah' THEN jumlah
|
|
WHEN jenis_mutasi.tipe IN ('kurang','transfer') THEN -jumlah
|
|
ELSE 0
|
|
END
|
|
),0) as stok
|
|
")
|
|
->value('stok'); // ✅ WAJIB
|
|
|
|
// kembalikan stok lama jika mutasi lama adalah pengurang
|
|
if (in_array($mutasi->jenisMutasi->nama, ['mati', 'afkir', 'pindah'])) {
|
|
$stok += $mutasi->jumlah;
|
|
}
|
|
// CEK STOK
|
|
if (in_array($jenis->nama, ['mati', 'afkir'])) {
|
|
if ($stok <= 0) {
|
|
throw \Illuminate\Validation\ValidationException::withMessages([
|
|
'jumlah' => 'Stok ayam di kandang ini sudah habis.'
|
|
]);
|
|
}
|
|
|
|
if ($request->jumlah > $stok) {
|
|
throw \Illuminate\Validation\ValidationException::withMessages([
|
|
'jumlah' => "Stok hanya tersisa $stok ekor."
|
|
]);
|
|
}
|
|
}
|
|
|
|
// UPDATE DATA
|
|
$mutasi->update([
|
|
'kandang_id' => $request->kandang_id,
|
|
'jenis_mutasi_id' => $request->jenis_mutasi_id,
|
|
'jumlah' => $request->jumlah,
|
|
'tanggal' => $request->tanggal,
|
|
'keterangan' => $request->keterangan,
|
|
]);
|
|
|
|
return redirect()->route('ayam')
|
|
->with('success', 'Data berhasil diperbarui.');
|
|
}
|
|
public function destroy($id)
|
|
{
|
|
/** @var \App\Models\User $user */
|
|
$user = Auth::user();
|
|
|
|
if ($user->isKaryawan()) {
|
|
abort(403, 'Karyawan tidak boleh menghapus data.');
|
|
}
|
|
|
|
$mutasi = MutasiAyam::findOrFail($id);
|
|
|
|
if (
|
|
$mutasi->jenisMutasi->nama === 'pindah'||
|
|
str_contains($mutasi->keterangan, 'Pindahan dari')
|
|
) {
|
|
abort(403, 'Data hasil pindahan tidak boleh dihapus.');
|
|
}
|
|
|
|
$mutasi->delete();
|
|
return redirect()->route('ayam')
|
|
->with('success', 'Data berhasil dihapus.');
|
|
}
|
|
}
|