Compare commits

...

10 Commits

Author SHA1 Message Date
ninavirgiana dc36c6fa51 perbaikan bug email terkirim 2026-03-28 08:23:29 +07:00
ninavirgiana ece92b25b2 update telur dan perbaikan bug 2026-03-24 19:51:19 +07:00
ninavirgiana 3872207bf0 update ayam 2026-03-24 13:08:15 +07:00
ninavirgiana ff786d572a update pakan 2026-03-24 10:43:42 +07:00
ninavirgiana dedf8458ac Resolve bug edit and delete 2026-03-22 00:01:14 +07:00
ninavirgiana 4332219600 update 19/03 2026-03-19 11:29:22 +07:00
Lutfi Hakim ebf2c6d277 test CI/CD 2026-03-15 20:43:38 +07:00
Lutfi Hakim 844d2e8db2 fix branch in deploy.yml 2026-03-15 20:40:32 +07:00
Lutfi Hakim f1fa09ea0a fix deploy.yml 2026-03-15 20:37:33 +07:00
Lutfi Hakim 16629874c5 Setup CI/CD 2026-03-15 20:32:10 +07:00
14 changed files with 586 additions and 280 deletions

View File

@ -12,24 +12,34 @@ jobs:
steps: steps:
- name: Deployment Logic - name: Deployment Logic
run: | run: |
cd /www/wwwroot/Layerfarm cd /www/wwwroot/LayerFarm
# Ambil ID commit untuk deteksi perubahan # 1. Ambil ID commit lama untuk deteksi perubahan
OLD_COMMIT=$(git rev-parse HEAD) OLD_COMMIT=$(git rev-parse HEAD)
git fetch --all
# 2. Tarik kode terbaru
git remote set-url origin https://x-access-token:${{ secrets.GITHUB_TOKEN }}@github.com/ninavirgiana/LayerFarm.git
git fetch -4 --all
git reset --hard origin/master git reset --hard origin/master
# 3. Ambil ID commit baru
NEW_COMMIT=$(git rev-parse HEAD) NEW_COMMIT=$(git rev-parse HEAD)
# Build dependencies (Container temporary) # 4. Build dependencies (Container temporary)
docker run --rm -v $(pwd):/app -w /app composer:2 install --no-interaction --prefer-dist --optimize-autoloader --ignore-platform-reqs docker run --rm -v $(pwd):/app -w /app composer:2 install --no-interaction --prefer-dist --optimize-autoloader --ignore-platform-reqs
# Perbaikan permission untuk user www/docker (PUID 33) # 5. Perbaikan permission untuk user www/docker (PUID 33)
chown -R 33:33 vendor/ # Sekalian fix untuk storage dan cache biar aman
chown -R 33:33 vendor/ storage/ bootstrap/cache/
chmod -R 775 storage/ bootstrap/cache/
# Refresh cache Laravel # 6. Refresh cache Laravel
docker compose exec -T app php artisan optimize:clear docker compose exec -T layerfarm_php php artisan optimize:clear
# Deteksi otomatis migrasi database # 7. Deteksi otomatis migrasi database
if [ "$OLD_COMMIT" != "$NEW_COMMIT" ] && git diff --name-only $OLD_COMMIT $NEW_COMMIT | grep -q "^database/migrations/"; then if [ "$OLD_COMMIT" != "$NEW_COMMIT" ] && git diff --name-only $OLD_COMMIT $NEW_COMMIT | grep -q "^database/migrations/"; then
docker compose exec -T app php artisan migrate --force echo "🚀 Perubahan database terdeteksi! Menjalankan migrate..."
docker compose exec -T layerfarm_php php artisan migrate --force
else
echo "✅ Tidak ada file migrasi baru. Skip migrate."
fi fi

View File

@ -61,13 +61,14 @@ public function index(Request $request)
return view('inventori-ayam', compact('data', 'kandang')); return view('inventori-ayam', compact('data', 'kandang'));
} }
public function store(Request $request) public function store(Request $request)
{ {
$request->validate([ $request->validate([
'jenis_mutasi' => 'required|in:masuk,mati,afkir,pindah', 'jenis_mutasi' => 'required|in:masuk,mati,afkir,pindah',
'jumlah' => 'required|integer|min:1|max:9999', 'jumlah' => 'required|integer|min:1|max:9999',
'tanggal' => 'required|date|before_or_equal:today', 'tanggal' => 'required|date|before_or_equal:today',
], [ 'keterangan' => 'required_if:jenis_mutasi,masuk,mati,afkir|string|max:255',
], [
'jenis_mutasi.required' => 'Jenis mutasi wajib dipilih.', 'jenis_mutasi.required' => 'Jenis mutasi wajib dipilih.',
'jenis_mutasi.in' => 'Jenis mutasi tidak valid.', 'jenis_mutasi.in' => 'Jenis mutasi tidak valid.',
@ -78,6 +79,10 @@ public function store(Request $request)
'tanggal.required' => 'Tanggal wajib diisi.', 'tanggal.required' => 'Tanggal wajib diisi.',
'tanggal.date' => 'Format tanggal tidak valid.', 'tanggal.date' => 'Format tanggal tidak valid.',
'tanggal.before_or_equal' => 'Tanggal tidak boleh melebihi hari ini.', '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) { DB::transaction(function () use ($request) {
@ -135,7 +140,8 @@ public function store(Request $request)
'jumlah' => $request->jumlah, 'jumlah' => $request->jumlah,
'tanggal' => $request->tanggal, 'tanggal' => $request->tanggal,
'keterangan' => 'Pindahan dari ' . $kandangAsal->nama_kandang, 'keterangan' => 'Pindahan dari ' . $kandangAsal->nama_kandang,
]);} ]);
}
// MUTASI BIASA // MUTASI BIASA
else { else {
@ -192,7 +198,13 @@ public function store(Request $request)
public function update(Request $request, $id) public function update(Request $request, $id)
{ {
$mutasi = MutasiAyam::findOrFail($id); $mutasi = MutasiAyam::findOrFail($id);
// CEGAH EDIT DATA PINDAH
if (
$mutasi->jenis_mutasi === 'pindah' ||
str_contains($mutasi->keterangan, 'Pindahan dari')
) {
abort(403, 'Data hasil pindahan tidak boleh diedit.');
}
/** @var \App\Models\User $user */ /** @var \App\Models\User $user */
$user = Auth::user(); $user = Auth::user();
@ -203,8 +215,10 @@ public function update(Request $request, $id)
$validator = Validator::make($request->all(), [ $validator = Validator::make($request->all(), [
'kandang_id' => 'required|exists:kandang,id', 'kandang_id' => 'required|exists:kandang,id',
'jenis_mutasi' => 'required|in:masuk,mati,afkir', 'jenis_mutasi' => 'required|in:masuk,mati,afkir',
'jumlah' => 'required|integer|min:1', 'jumlah' => 'required|integer|min:1|max:9999',
'tanggal' => 'required|date|before_or_equal:today', 'tanggal' => 'required|date|before_or_equal:today',
'keterangan' => 'required_if:jenis_mutasi,masuk,mati,afkir|string|max:255',
], [ ], [
'kandang_id.required' => 'Nama kandang wajib dipilih.', 'kandang_id.required' => 'Nama kandang wajib dipilih.',
'kandang_id.exists' => 'Kandang tidak ditemukan.', 'kandang_id.exists' => 'Kandang tidak ditemukan.',
@ -216,6 +230,9 @@ public function update(Request $request, $id)
'tanggal.required' => 'Tanggal wajib diisi.', 'tanggal.required' => 'Tanggal wajib diisi.',
'tanggal.date' => 'Format tanggal tidak valid.', 'tanggal.date' => 'Format tanggal tidak valid.',
'tanggal.before_or_equal' => 'Tanggal tidak boleh melebihi hari ini.', '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()) { if ($validator->fails()) {
@ -259,7 +276,7 @@ public function update(Request $request, $id)
} }
} }
// UPDATE DATA // UPDATE DATA
$mutasi->update([ $mutasi->update([
'kandang_id' => $request->kandang_id, 'kandang_id' => $request->kandang_id,
'jenis_mutasi' => $request->jenis_mutasi, 'jenis_mutasi' => $request->jenis_mutasi,
@ -273,15 +290,23 @@ public function update(Request $request, $id)
} }
public function destroy($id) public function destroy($id)
{ {
/** @var \App\Models\User $user */ /** @var \App\Models\User $user */
$user = Auth::user(); $user = Auth::user();
if ($user->isKaryawan()) { if ($user->isKaryawan()) {
abort(403, 'Karyawan tidak boleh menghapus data.'); abort(403, 'Karyawan tidak boleh menghapus data.');
} }
MutasiAyam::findOrFail($id)->delete(); $mutasi = MutasiAyam::findOrFail($id);
if (
$mutasi->jenis_mutasi === 'pindah' ||
str_contains($mutasi->keterangan, 'Pindahan dari')
) {
abort(403, 'Data hasil pindahan tidak boleh dihapus.');
}
$mutasi->delete();
return redirect()->route('ayam') return redirect()->route('ayam')
->with('success', 'Data berhasil dihapus.'); ->with('success', 'Data berhasil dihapus.');
} }

View File

@ -7,6 +7,7 @@
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\Auth;
use App\Models\User; use App\Models\User;
use Illuminate\Support\Facades\Validator;
class HasilController extends Controller class HasilController extends Controller
{ {
@ -47,9 +48,7 @@ public function index(Request $request)
}); });
} }
if ($request->kandang) {
$query->where('kandang_id', $request->kandang);
}
if ($request->bulan) { if ($request->bulan) {
$query->whereMonth('tanggal_produksi', $request->bulan); $query->whereMonth('tanggal_produksi', $request->bulan);
@ -79,7 +78,7 @@ public function index(Request $request)
public function store(Request $request) public function store(Request $request)
{ {
$request->validate([ $validator = Validator::make($request->all(), [
'kandang_id' => 'required|exists:kandang,id', 'kandang_id' => 'required|exists:kandang,id',
'shift' => 'required|in:pagi,sore', 'shift' => 'required|in:pagi,sore',
'berat_telur_layak' => 'required|regex:/^\d{1,6}(\.\d{1,2})?$/', 'berat_telur_layak' => 'required|regex:/^\d{1,6}(\.\d{1,2})?$/',
@ -103,15 +102,23 @@ public function store(Request $request)
'tanggal_produksi.before_or_equal' => 'Tanggal tidak boleh melebihi hari ini.', 'tanggal_produksi.before_or_equal' => 'Tanggal tidak boleh melebihi hari ini.',
]); ]);
if ($validator->fails()) {
return redirect()->route('hasil')
->withErrors($validator)
->withInput()
->with('form', 'tambah');
}
$total = $request->berat_telur_layak + $request->berat_telur_rusak; $layak = (float) $request->berat_telur_layak;
$rusak = (float) $request->berat_telur_rusak;
$total = $layak + $rusak;
ProduksiTelur::create([ ProduksiTelur::create([
'kandang_id' => $request->kandang_id, 'kandang_id' => $request->kandang_id,
'user_id' => Auth::id(), 'user_id' => Auth::id(),
'shift' => $request->shift, 'shift' => $request->shift,
'berat_telur_layak' => $request->berat_telur_layak, 'berat_telur_layak' => $layak,
'berat_telur_rusak' => $request->berat_telur_rusak, 'berat_telur_rusak' => $rusak,
'berat_telur_total' => $total, 'berat_telur_total' => $total,
'tanggal_produksi' => $request->tanggal_produksi, 'tanggal_produksi' => $request->tanggal_produksi,
]); ]);
@ -123,7 +130,7 @@ public function store(Request $request)
public function update(Request $request, $id) public function update(Request $request, $id)
{ {
$request->validate([ $validator = Validator::make($request->all(), [
'kandang_id' => 'required|exists:kandang,id', 'kandang_id' => 'required|exists:kandang,id',
'shift' => 'required|in:pagi,sore', 'shift' => 'required|in:pagi,sore',
'berat_telur_layak' => 'required|regex:/^\d{1,6}(\.\d{1,2})?$/', 'berat_telur_layak' => 'required|regex:/^\d{1,6}(\.\d{1,2})?$/',
@ -150,20 +157,29 @@ public function update(Request $request, $id)
'tanggal_produksi.before_or_equal' => 'Tanggal tidak boleh melebihi hari ini.', 'tanggal_produksi.before_or_equal' => 'Tanggal tidak boleh melebihi hari ini.',
]); ]);
if ($validator->fails()) {
return redirect()->route('hasil')
->withErrors($validator)
->withInput()
->with('form', 'edit')
->with('edit_id', $id);
}
$total = $request->berat_telur_layak + $request->berat_telur_rusak; $layak = (float) $request->berat_telur_layak;
$rusak = (float) $request->berat_telur_rusak;
$total = $layak + $rusak;
ProduksiTelur::findOrFail($id)->update([ ProduksiTelur::findOrFail($id)->update([
'kandang_id' => $request->kandang_id, 'kandang_id' => $request->kandang_id,
'shift' => $request->shift, 'shift' => $request->shift,
'berat_telur_layak' => $request->berat_telur_layak, 'berat_telur_layak' => $layak,
'berat_telur_rusak' => $request->berat_telur_rusak, 'berat_telur_rusak' => $rusak,
'berat_telur_total' => $total, 'berat_telur_total' => $total,
'tanggal_produksi' => $request->tanggal_produksi, 'tanggal_produksi' => $request->tanggal_produksi,
]); ]);
return redirect()->route('hasil') return redirect()->route('hasil')
->with('success', 'Data produksi berhasil diperbarui.'); ->with('success', 'Data berhasil diupdate.');
} }

View File

@ -6,6 +6,7 @@
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\Auth;
use App\Models\User; use App\Models\User;
use Illuminate\Support\Facades\DB;
class PakanController extends Controller class PakanController extends Controller
{ {
@ -87,7 +88,9 @@ public function store(Request $request)
/** @var User $user */ /** @var User $user */
$user = Auth::user(); $user = Auth::user();
$request->merge([ $request->merge([
'harga_satuan' => str_replace('.', '', $request->harga_satuan) 'harga_satuan' => $request->harga_satuan
? str_replace('.', '', $request->harga_satuan)
: null
]); ]);
// karyawan TIDAK BOLEH input barang masuk // karyawan TIDAK BOLEH input barang masuk
@ -98,7 +101,7 @@ public function store(Request $request)
$request->validate([ $request->validate([
'tanggal' => 'required|date|before_or_equal:today', 'tanggal' => 'required|date|before_or_equal:today',
'nama_barang' => 'required|string|max:100', 'nama_barang' => 'required|string|max:100',
'jenis_transaksi' => 'required|in:masuk,keluar', 'jenis_transaksi' => 'required|in:masuk,keluar',
'jumlah' => 'required|numeric|min:1|max:999999', 'jumlah' => 'required|numeric|min:1|max:999999',
// 'satuan' => 'required|string|max:50|in:karung', // 'satuan' => 'required|string|max:50|in:karung',
@ -177,7 +180,9 @@ public function update(Request $request, $id)
/** @var User $user */ /** @var User $user */
$user = Auth::user(); $user = Auth::user();
$request->merge([ $request->merge([
'harga_satuan' => str_replace('.', '', $request->harga_satuan) 'harga_satuan' => $request->harga_satuan
? str_replace('.', '', $request->harga_satuan)
: null
]); ]);
if ($user->isKaryawan()) { if ($user->isKaryawan()) {
abort(403, 'Anda tidak memiliki izin mengedit data.'); abort(403, 'Anda tidak memiliki izin mengedit data.');
@ -185,81 +190,95 @@ public function update(Request $request, $id)
$namaBarang = ucfirst(strtolower(trim($request->nama_barang))); $namaBarang = ucfirst(strtolower(trim($request->nama_barang)));
$request->validate([ $validator = \Illuminate\Support\Facades\Validator::make($request->all(), [
'tanggal' => 'required|date|before_or_equal:today', 'tanggal' => 'required|date|before_or_equal:today',
'nama_barang' => 'required|string|max:100', 'nama_barang' => 'required|string|max:100',
'jenis_transaksi' => 'required|in:masuk,keluar', 'jenis_transaksi' => 'required|in:masuk,keluar',
'jumlah' => 'required|numeric|min:1|max:999999', 'jumlah' => 'required|numeric|min:1|max:999999',
// 'satuan' => 'required|string|max:50|in:karung', 'harga_satuan' => $request->jenis_transaksi === 'masuk'
'harga_satuan' => $request->jenis_transaksi === 'masuk'
? 'required|numeric|min:1|max:999999999' ? 'required|numeric|min:1|max:999999999'
: 'nullable', : 'nullable',
], [ ], [
'tanggal.required' => 'Tanggal wajib diisi.', 'tanggal.required' => 'Tanggal wajib diisi.',
'tanggal.date' => 'Format tanggal tidak valid.', 'tanggal.date' => 'Format tanggal tidak valid.',
'nama_barang.required' => 'Nama barang wajib diisi.', 'nama_barang.required' => 'Nama barang wajib diisi.',
'nama_barang.string' => 'Nama barang harus berupa teks.', 'nama_barang.string' => 'Nama barang harus berupa teks.',
'nama_barang.max' => 'Nama barang maksimal 100 karakter.', 'nama_barang.max' => 'Nama barang maksimal 100 karakter.',
'jenis_transaksi.required' => 'Jenis transaksi wajib dipilih.', 'jenis_transaksi.required' => 'Jenis transaksi wajib dipilih.',
'jenis_transaksi.in' => 'Jenis transaksi tidak valid.', 'jenis_transaksi.in' => 'Jenis transaksi tidak valid.',
'jumlah.required' => 'Jumlah wajib diisi.', 'jumlah.required' => 'Jumlah wajib diisi.',
'jumlah.numeric' => 'Jumlah harus berupa angka.', 'jumlah.numeric' => 'Jumlah harus berupa angka.',
'jumlah.min' => 'Jumlah minimal 1.', 'jumlah.min' => 'Jumlah minimal 1.',
'jumlah.max' => 'Jumlah terlalu besar.', 'jumlah.max' => 'Jumlah terlalu besar.',
// 'satuan.required' => 'Satuan wajib diisi.', 'harga_satuan.required' => 'Harga satuan wajib diisi untuk transaksi masuk.',
// 'satuan.string' => 'Satuan harus berupa teks.', 'harga_satuan.numeric' => 'Harga satuan harus berupa angka.',
// 'satuan.max' => 'Satuan maksimal 50 karakter.', 'harga_satuan.min' => 'Harga satuan minimal 1.',
'harga_satuan.max' => 'Harga satuan terlalu besar.',
'harga_satuan.required' => 'Harga satuan wajib diisi untuk transaksi masuk.',
'harga_satuan.numeric' => 'Harga satuan harus berupa angka.',
'harga_satuan.min' => 'Harga satuan minimal 1.',
'harga_satuan.max' => 'Harga satuan terlalu besar.',
]); ]);
$item = InventoriKandang::findOrFail($id); if ($validator->fails()) {
return back()
$total = null; ->withErrors($validator, 'edit')
->withInput()
if ($request->jenis_transaksi === 'masuk') { ->with('edit_id', $id);
$total = $request->jumlah * $request->harga_satuan;
} }
// CEK STOK JIKA KELUAR try {
if ($request->jenis_transaksi === 'keluar') {
$stokSekarang = InventoriKandang::where('nama_barang', $namaBarang) DB::transaction(function () use ($request, $id, $namaBarang) {
->where('id', '!=', $id)
->selectRaw("
SUM(CASE WHEN jenis_transaksi = 'masuk' THEN jumlah ELSE 0 END)
-
SUM(CASE WHEN jenis_transaksi = 'keluar' THEN jumlah ELSE 0 END)
AS stok
")
->value('stok') ?? 0;
if ($request->jumlah > $stokSekarang) { $item = InventoriKandang::findOrFail($id);
return back()->withErrors([
'jumlah' => 'Stok tidak mencukupi. Sisa stok: ' . $stokSekarang $total = null;
])->withInput();
} if ($request->jenis_transaksi === 'masuk') {
$total = $request->jumlah * $request->harga_satuan;
}
// CEK STOK JIKA KELUAR
if ($request->jenis_transaksi === 'keluar') {
$stokSekarang = InventoriKandang::where('nama_barang', $namaBarang)
->where('id', '!=', $id)
->selectRaw("
SUM(CASE WHEN jenis_transaksi = 'masuk' THEN jumlah ELSE 0 END)
-
SUM(CASE WHEN jenis_transaksi = 'keluar' THEN jumlah ELSE 0 END)
AS stok
")
->value('stok') ?? 0;
if ($request->jumlah > $stokSekarang) {
throw new \Exception('Stok tidak mencukupi. Sisa stok: ' . $stokSekarang);
}
}
$item->update([
'tanggal' => $request->tanggal,
'nama_barang' => $namaBarang,
'jenis_transaksi' => $request->jenis_transaksi,
'jumlah' => $request->jumlah,
'satuan' => 'karung',
'harga_satuan' => $request->jenis_transaksi === 'masuk'
? $request->harga_satuan
: null,
'total_harga' => $total,
]);
});
} catch (\Exception $e) {
return back()
->withErrors([
'jumlah' => $e->getMessage()
], 'edit')
->withInput()
->with('edit_id', $id);
} }
$item->update([
'tanggal' => $request->tanggal,
'nama_barang' => $namaBarang,
'jenis_transaksi' => $request->jenis_transaksi,
'jumlah' => $request->jumlah,
'satuan' => 'karung',
'harga_satuan' => $request->jenis_transaksi === 'masuk'
? $request->harga_satuan
: null,
'total_harga' => $total,
]);
return redirect()->route('pakan')->with('success', 'Transaksi berhasil diupdate'); return redirect()->route('pakan')->with('success', 'Transaksi berhasil diupdate');
} }

View File

@ -9,10 +9,12 @@ class ResetPasswordNotification extends ResetPassword
{ {
public function toMail($notifiable) public function toMail($notifiable)
{ {
$url = url(route('password.reset', [
$url = route('password.reset', [
'token' => $this->token, 'token' => $this->token,
'email' => $notifiable->getEmailForPasswordReset(), 'email' => $notifiable->getEmailForPasswordReset(),
], false)); ]);
return (new MailMessage) return (new MailMessage)
->subject('Reset Kata Sandi Akun Anda') ->subject('Reset Kata Sandi Akun Anda')

View File

@ -5,6 +5,8 @@
use Illuminate\Support\ServiceProvider; use Illuminate\Support\ServiceProvider;
use Illuminate\Pagination\Paginator; use Illuminate\Pagination\Paginator;
use Carbon\Carbon; use Carbon\Carbon;
use Illuminate\Support\Facades\URL;
class AppServiceProvider extends ServiceProvider class AppServiceProvider extends ServiceProvider
{ {
@ -25,5 +27,10 @@ public function boot(): void
// SET BAHASA INDONESIA UNTUK TANGGAL // SET BAHASA INDONESIA UNTUK TANGGAL
Carbon::setLocale('id'); Carbon::setLocale('id');
// PAKSA HTTPS HANYA DI PRODUCTION
if (app()->environment('production')) {
URL::forceScheme('https');
}
} }
} }

View File

@ -3,16 +3,32 @@
use Illuminate\Foundation\Application; use Illuminate\Foundation\Application;
use Illuminate\Foundation\Configuration\Exceptions; use Illuminate\Foundation\Configuration\Exceptions;
use Illuminate\Foundation\Configuration\Middleware; use Illuminate\Foundation\Configuration\Middleware;
use Illuminate\Support\Facades\Auth;
use Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
return Application::configure(basePath: dirname(__DIR__)) return Application::configure(basePath: dirname(__DIR__))
->withRouting( ->withRouting(
web: __DIR__.'/../routes/web.php', web: __DIR__ . '/../routes/web.php',
commands: __DIR__.'/../routes/console.php', commands: __DIR__ . '/../routes/console.php',
health: '/up', health: '/up',
) )
->withMiddleware(function (Middleware $middleware): void { ->withMiddleware(function (Middleware $middleware): void {
// //
}) })
->withExceptions(function (Exceptions $exceptions): void { ->withExceptions(function (Exceptions $exceptions): void {
//
// 405 - Method tidak sesuai
$exceptions->render(function (MethodNotAllowedHttpException $e, $request) {
if (!Auth::check()) {
return redirect()->route('login');
}
});
// 404 - URL tidak ditemukan / diisengi
$exceptions->render(function (NotFoundHttpException $e, $request) {
if (!Auth::check()) {
return redirect()->route('login');
}
});
})->create(); })->create();

View File

@ -6,7 +6,7 @@ class="img-fluid"
style="max-width: 320px; height: auto;"> style="max-width: 320px; height: auto;">
</div> </div>
<div class="mb-4 text-center"> <div class="mb-4 text-center">
<h4 class="fw-bold">Masuk</h4> <h4 class="fw-bold">Login</h4>
<p class="text-muted">Silakan login ke akun Anda</p> <p class="text-muted">Silakan login ke akun Anda</p>
</div> </div>
@ -56,7 +56,7 @@ class="form-control @error('password') is-invalid @enderror"
{{-- Remember + Forgot --}} {{-- Remember + Forgot --}}
<div class="mb-3 d-flex justify-content-between align-items-center"> <div class="mb-3 d-flex justify-content-between align-items-center">
<div class="form-check"> {{-- <div class="form-check">
<input class="form-check-input" <input class="form-check-input"
type="checkbox" type="checkbox"
name="remember" name="remember"
@ -64,7 +64,7 @@ class="form-control @error('password') is-invalid @enderror"
<label class="form-check-label" for="remember"> <label class="form-check-label" for="remember">
Ingat saya Ingat saya
</label> </label>
</div> </div> --}}
@if (Route::has('password.request')) @if (Route::has('password.request'))
<a href="{{ route('password.request') }}" class="text-decoration-none"> <a href="{{ route('password.request') }}" class="text-decoration-none">

View File

@ -11,26 +11,26 @@
<h4 class="mb-1 fw-bold">Populasi Ayam</h4> <h4 class="mb-1 fw-bold">Populasi Ayam</h4>
</div> </div>
<div class="mb-0 row"> <div class="mb-0 row">
@foreach ($kandang as $k) @foreach ($kandang as $k)
<div class="mb-2 col-md-3 col-sm-6"> <div class="mb-2 col-md-3 col-sm-6">
<div class="border-0 shadow-sm card"> <div class="border-0 shadow-sm card">
<div class="py-2 text-center card-body"> <div class="py-2 text-center card-body">
<div class="mb-1 fw-semibold text-dark"> <div class="mb-1 fw-semibold text-dark">
{{ $k->nama_kandang }} {{ $k->nama_kandang }}
</div> </div>
<div class="mt-1 h6 fw-bold text-dark"> <div class="mt-1 h6 fw-bold text-dark">
{{ number_format($k->jumlah_ayam_terakhir, 0, ',', '.') }} {{ number_format($k->jumlah_ayam_terakhir, 0, ',', '.') }}
</div> </div>
</div>
</div>
</div>
@endforeach
</div> </div>
</div>
</div>
@endforeach
</div>
<!-- ===== CARD ===== --> <!-- ===== CARD ===== -->
<div class="shadow-sm card table-card"> <div class="shadow-sm card table-card">
@ -79,12 +79,12 @@ class="form-control form-control-sm" placeholder="Cari kandang/keterangan">
<label class="small text-muted">Tahun</label> <label class="small text-muted">Tahun</label>
<select name="tahun" id="filterTahun" class="form-control form-control-sm"> <select name="tahun" id="filterTahun" class="form-control form-control-sm">
<option value="">Semua</option> <option value="">Semua</option>
@foreach ([2024, 2025, 2026] as $th) @for ($th = now()->year - 2; $th <= now()->year; $th++)
<option value="{{ $th }}" <option value="{{ $th }}"
{{ request('tahun') == $th ? 'selected' : '' }}> {{ request('tahun') == $th ? 'selected' : '' }}>
{{ $th }} {{ $th }}
</option> </option>
@endforeach @endfor
</select> </select>
</div> </div>
@ -140,9 +140,9 @@ class="form-control form-control-sm">
<td>{{ number_format($item->jumlah, 0, ',', '.') }}</td> <td>{{ number_format($item->jumlah, 0, ',', '.') }}</td>
<td> <td>
{{ ucfirst($item->jenis_mutasi ?? '-') }} {{ ucfirst($item->jenis_mutasi ?? '-') }}
</td> </td>
<td>{{ $item->keterangan ?? '-' }}</td> <td>{{ $item->keterangan ?? '-' }}</td>
@ -151,24 +151,43 @@ class="form-control form-control-sm">
</td> </td>
<td class="text-center"> <td class="text-center">
<button class="btn btn-warning btn-sm" data-toggle="modal"
data-target="#modalEdit" data-id="{{ $item->id }}" @php
data-kandang="{{ $item->kandang_id }}" $isPindahan =
$item->jenis_mutasi === 'pindah' ||
str_contains($item->keterangan, 'Pindahan dari');
@endphp
{{-- TOMBOL EDIT --}}
<button
class="btn btn-warning btn-sm {{ $isPindahan ? 'disabled opacity-50' : '' }}"
@if (!$isPindahan) data-toggle="modal"
data-target="#modalEdit" @endif
data-id="{{ $item->id }}" data-kandang="{{ $item->kandang_id }}"
data-jumlah="{{ $item->jumlah }}" data-jumlah="{{ $item->jumlah }}"
data-jenis="{{ $item->jenis_mutasi }}" data-jenis="{{ $item->jenis_mutasi }}"
data-keterangan="{{ $item->keterangan }}" data-keterangan="{{ $item->keterangan }}"
data-tanggal="{{ $item->tanggal }}"> data-tanggal="{{ $item->tanggal }}"
style="{{ $isPindahan ? 'pointer-events: none;' : '' }}"
title="{{ $isPindahan ? 'Data pindahan tidak bisa diedit' : '' }}">
<i class="la la-edit"></i> <i class="la la-edit"></i>
</button> </button>
{{-- TOMBOL HAPUS --}}
@auth @auth
@if (auth()->user()->isAdmin()) @if (auth()->user()->isAdmin())
<button class="btn btn-danger btn-sm" data-toggle="modal" <button
data-target="#modalHapus" data-id="{{ $item->id }}"> class="btn btn-danger btn-sm {{ $isPindahan ? 'disabled opacity-50' : '' }}"
@if (!$isPindahan) data-toggle="modal"
data-target="#modalHapus" @endif
data-id="{{ $item->id }}"
style="{{ $isPindahan ? 'pointer-events: none;' : '' }}"
title="{{ $isPindahan ? 'Data pindahan tidak bisa dihapus' : '' }}">
<i class="la la-trash"></i> <i class="la la-trash"></i>
</button> </button>
@endif @endif
@endauth @endauth
</td> </td>
</tr> </tr>
@ -232,12 +251,19 @@ class="form-control form-control-sm">
<label class="fw-bold">1. Pilih Jenis Mutasi</label> <label class="fw-bold">1. Pilih Jenis Mutasi</label>
<select name="jenis_mutasi" id="jenisMutasi" <select name="jenis_mutasi" id="jenisMutasi"
class="form-control mt-2 @error('jenis_mutasi') is-invalid @enderror"> class="form-control mt-2 @error('jenis_mutasi') is-invalid @enderror">
<option value="">-- Pilih Jenis Mutasi --</option> <option value="">-- Pilih Jenis Mutasi --</option>
<option value="masuk">Masuk (DOC)</option> <option value="masuk" {{ old('jenis_mutasi') == 'masuk' ? 'selected' : '' }}>Masuk (DOC)
<option value="mati">Mati</option> </option>
<option value="afkir">Afkir</option> <option value="mati" {{ old('jenis_mutasi') == 'mati' ? 'selected' : '' }}>Mati</option>
<option value="pindah">Pindah Kandang</option> <option value="afkir" {{ old('jenis_mutasi') == 'afkir' ? 'selected' : '' }}>Afkir
</option>
<option value="pindah" {{ old('jenis_mutasi') == 'pindah' ? 'selected' : '' }}>Pindah
Kandang</option>
</select> </select>
@error('jenis_mutasi')
<small class="text-danger">{{ $message }}</small>
@enderror
</div> </div>
@ -247,15 +273,19 @@ class="form-control mt-2 @error('jenis_mutasi') is-invalid @enderror">
<div class="mt-2 form-group"> <div class="mt-2 form-group">
<label>Nama Kandang</label> <label>Nama Kandang</label>
<select name="kandang_id" class="form-control"> <select name="kandang_id" class="form-control @error('kandang_id') is-invalid @enderror">
<option value="">-- Pilih Kandang --</option> <option value="">-- Pilih Kandang --</option>
@foreach ($kandang as $k) @foreach ($kandang as $k)
<option value="{{ $k->id }}"> <option value="{{ $k->id }}"
{{ old('kandang_id') == $k->id ? 'selected' : '' }}>
{{ $k->nama_kandang }} {{ $k->nama_kandang }}
(Stok: {{ $k->jumlah_ayam_terakhir }}) (Stok: {{ $k->jumlah_ayam_terakhir }})
</option> </option>
@endforeach @endforeach
</select> </select>
@error('kandang_id')
<small class="text-danger">{{ $message }}</small>
@enderror
</div> </div>
</div> </div>
@ -266,25 +296,37 @@ class="form-control mt-2 @error('jenis_mutasi') is-invalid @enderror">
<div class="mt-2 form-group"> <div class="mt-2 form-group">
<label>Kandang Asal</label> <label>Kandang Asal</label>
<select name="kandang_asal_id" class="form-control"> <select name="kandang_asal_id"
class="form-control @error('kandang_asal_id') is-invalid @enderror">
<option value="">-- Pilih Kandang Asal --</option> <option value="">-- Pilih Kandang Asal --</option>
@foreach ($kandang as $k) @foreach ($kandang as $k)
<option value="{{ $k->id }}"> <option value="{{ $k->id }}"
{{ old('kandang_asal_id') == $k->id ? 'selected' : '' }}>
{{ $k->nama_kandang }} {{ $k->nama_kandang }}
(Stok: {{ $k->jumlah_ayam_terakhir }}) (Stok: {{ $k->jumlah_ayam_terakhir }})
</option> </option>
@endforeach @endforeach
</select> </select>
@error('kandang_asal_id')
<small class="text-danger">{{ $message }}</small>
@enderror
</div> </div>
<div class="form-group"> <div class="form-group">
<label>Kandang Tujuan</label> <label>Kandang Tujuan</label>
<select name="kandang_tujuan_id" class="form-control"> <select name="kandang_tujuan_id"
class="form-control @error('kandang_tujuan_id') is-invalid @enderror">
<option value="">-- Pilih Kandang Tujuan --</option> <option value="">-- Pilih Kandang Tujuan --</option>
@foreach ($kandang as $k) @foreach ($kandang as $k)
<option value="{{ $k->id }}">{{ $k->nama_kandang }}</option> <option value="{{ $k->id }}"
{{ old('kandang_tujuan_id') == $k->id ? 'selected' : '' }}>
{{ $k->nama_kandang }}
</option>
@endforeach @endforeach
</select> </select>
@error('kandang_tujuan_id')
<small class="text-danger">{{ $message }}</small>
@enderror
</div> </div>
</div> </div>
@ -295,21 +337,31 @@ class="form-control mt-2 @error('jenis_mutasi') is-invalid @enderror">
<div class="mt-2 form-group"> <div class="mt-2 form-group">
<label>Jumlah Ayam</label> <label>Jumlah Ayam</label>
{{-- <input type="number" name="jumlah" class="form-control"> --}}
<input type="number" name="jumlah" max="9999" min="1" inputmode="numeric" <input type="number" name="jumlah" max="9999" min="1" inputmode="numeric"
oninput="this.value=this.value.replace(/[^0-9]/g,'').slice(0,4)" oninput="this.value=this.value.replace(/[^0-9]/g,'').slice(0,4)"
class="form-control @error('jumlah') is-invalid @enderror" class="form-control @error('jumlah') is-invalid @enderror"
value="{{ old('jumlah') }}"> value="{{ old('jumlah') }}">
@error('jumlah')
<small class="text-danger">{{ $message }}</small>
@enderror
</div> </div>
<div class="form-group"> <div class="form-group">
<label>Tanggal</label> <label>Tanggal</label>
<input type="date" name="tanggal" class="form-control" max="{{ date('Y-m-d') }}"> <input type="date" name="tanggal" value="{{ old('tanggal') }}"
class="form-control @error('tanggal') is-invalid @enderror"
max="{{ date('Y-m-d') }}">
@error('tanggal')
<small class="text-danger">{{ $message }}</small>
@enderror
</div> </div>
<div class="form-group"> <div class="form-group">
<label>Keterangan</label> <label>Keterangan</label>
<textarea name="keterangan" class="form-control" rows="2"></textarea> <textarea name="keterangan" class="form-control @error('keterangan') is-invalid @enderror" rows="2">{{ old('keterangan') }}</textarea>
@error('keterangan')
<small class="text-danger">{{ $message }}</small>
@enderror
</div> </div>
</div> </div>
@ -361,9 +413,7 @@ class="form-control @error('jumlah') is-invalid @enderror"
<div class="form-group"> <div class="form-group">
<label>Jumlah Ayam</label> <label>Jumlah Ayam</label>
{{-- <input type="number" name="jumlah"
value="{{ old('jumlah') }}"
class="form-control @error('jumlah') is-invalid @enderror"> --}}
<input type="number" name="jumlah" max="9999" min="1" inputmode="numeric" <input type="number" name="jumlah" max="9999" min="1" inputmode="numeric"
oninput="this.value=this.value.replace(/[^0-9]/g,'').slice(0,4)" oninput="this.value=this.value.replace(/[^0-9]/g,'').slice(0,4)"
value="{{ old('jumlah') }}" class="form-control @error('jumlah') is-invalid @enderror"> value="{{ old('jumlah') }}" class="form-control @error('jumlah') is-invalid @enderror">
@ -377,9 +427,11 @@ class="form-control @error('jumlah') is-invalid @enderror"> --}}
<label>Jenis Mutasi</label> <label>Jenis Mutasi</label>
<select name="jenis_mutasi" class="form-control @error('jenis_mutasi') is-invalid @enderror"> <select name="jenis_mutasi" class="form-control @error('jenis_mutasi') is-invalid @enderror">
<option value="masuk" {{ old('jenis_mutasi') == 'masuk' ? 'selected' : '' }}>Masuk</option> <option value="masuk" {{ old('jenis_mutasi') == 'masuk' ? 'selected' : '' }}>Masuk
</option>
<option value="mati" {{ old('jenis_mutasi') == 'mati' ? 'selected' : '' }}>Mati</option> <option value="mati" {{ old('jenis_mutasi') == 'mati' ? 'selected' : '' }}>Mati</option>
<option value="afkir" {{ old('jenis_mutasi') == 'afkir' ? 'selected' : '' }}>Afkir</option> <option value="afkir" {{ old('jenis_mutasi') == 'afkir' ? 'selected' : '' }}>Afkir
</option>
</select> </select>
@error('jenis_mutasi') @error('jenis_mutasi')
@ -452,12 +504,11 @@ class="form-control @error('jumlah') is-invalid @enderror"> --}}
@section('scripts') @section('scripts')
<script> <script>
const baseUrl = "{{ url('/ayam') }}"; const baseUrl = "{{ route('ayam') }}";
$(document).ready(function() { $(document).ready(function() {
/* ============================= /* =============================
HANDLE MODAL EDIT NORMAL HANDLE MODAL EDIT NORMAL
============================= */ ============================= */
$('#modalEdit').on('show.bs.modal', function(e) { $('#modalEdit').on('show.bs.modal', function(e) {
// Jika ada error validation (mode old input) // Jika ada error validation (mode old input)

View File

@ -50,12 +50,12 @@ class="form-control form-control-sm">
<label class="small">Tahun</label> <label class="small">Tahun</label>
<select name="tahun" class="form-control form-control-sm"> <select name="tahun" class="form-control form-control-sm">
<option value="">Semua</option> <option value="">Semua</option>
@foreach ([2024, 2025, 2026] as $th) @for ($th = now()->year - 2; $th <= now()->year + 1; $th++)
<option value="{{ $th }}" <option value="{{ $th }}"
{{ request('tahun') == $th ? 'selected' : '' }}> {{ request('tahun') == $th ? 'selected' : '' }}>
{{ $th }} {{ $th }}
</option> </option>
@endforeach @endfor
</select> </select>
</div> </div>
@ -103,11 +103,16 @@ class="form-control form-control-sm">
@endif @endif
@if ($errors->has('delete'))
<div class="alert alert-danger">
{{ $errors->first('delete') }}
</div>
@endif
<!-- TABEL --> <!-- TABEL -->
<div class="p-0 card-body"> <div class="p-0 card-body">
<div class="table-responsive"> <div class="table-responsive">
<table class="table mb-0" style="table-layout:fixed; width:100%;"> <thead class="table-light"> <table class="table mb-0" style="table-layout:fixed; width:100%;">
<thead class="table-light">
<tr> <tr>
<th class="text-center" style="width:60px;">No</th> <th class="text-center" style="width:60px;">No</th>
<th style="width:150px;">Tanggal</th> <th style="width:150px;">Tanggal</th>
@ -165,10 +170,9 @@ class="badge badge-{{ $item->jenis_transaksi == 'masuk' ? 'success' : 'danger' }
data-target="#modalEditTransaksi" data-id="{{ $item->id }}" data-target="#modalEditTransaksi" data-id="{{ $item->id }}"
data-nama="{{ $item->nama_barang }}" data-nama="{{ $item->nama_barang }}"
data-jenis="{{ $item->jenis_transaksi }}" data-jenis="{{ $item->jenis_transaksi }}"
data-jumlah="{{ $item->jumlah }}" data-jumlah="{{ (int) $item->jumlah }}"
data-satuan="{{ $item->satuan }}" data-harga="{{ (int) $item->harga_satuan }}"
data-harga="{{ $item->harga_satuan }}" {{-- data-harga="{{ $item->harga_satuan }}" --}} data-tanggal="{{ $item->tanggal }}">
data-tanggal="{{ $item->tanggal }}">
<i class="la la-edit"></i> <i class="la la-edit"></i>
</button> </button>
@ -275,8 +279,12 @@ class="form-control @error('jenis_transaksi') is-invalid @enderror" required>
</div> </div>
<div class="form-group"> <div class="form-group">
<label>Tanggal</label> <label>Tanggal</label>
<input type="date" name="tanggal" class="form-control" <input type="date" name="tanggal"
class="form-control @error('tanggal') is-invalid @enderror"
value="{{ old('tanggal', date('Y-m-d')) }}" max="{{ date('Y-m-d') }}" required> value="{{ old('tanggal', date('Y-m-d')) }}" max="{{ date('Y-m-d') }}" required>
@error('tanggal')
<small class="text-danger">{{ $message }}</small>
@enderror
</div> </div>
<div class="form-group"> <div class="form-group">
<label>Nama Barang</label> <label>Nama Barang</label>
@ -320,7 +328,7 @@ class="form-control @error('jenis_transaksi') is-invalid @enderror" required>
<div class="form-group"> <div class="form-group">
<label>Jumlah</label> <label>Jumlah</label>
<input type="number" name="jumlah" id="jumlahTambah" max="999999" <input type="number" name="jumlah" id="jumlahTambah" max="999999"
min="1" inputmode="numeric" oninput="this.value=this.value.slice(0,6)" min="1" inputmode="numeric" maxlength="6"
class="form-control @error('jumlah') is-invalid @enderror" class="form-control @error('jumlah') is-invalid @enderror"
value="{{ old('jumlah') }}" required> value="{{ old('jumlah') }}" required>
@ -407,18 +415,23 @@ class="form-control @error('jenis_transaksi') is-invalid @enderror" required>
</select> </select>
@error('jenis_transaksi') @error('jenis_transaksi', 'edit')
<small class="text-danger">{{ $message }}</small> <small class="text-danger">{{ $message }}</small>
@enderror @enderror
</div> </div>
<div class="form-group"> <div class="form-group">
<label>Tanggal</label> <label>Tanggal</label>
<input type="date" name="tanggal" id="tanggalEdit" class="form-control" <input type="date" name="tanggal" id="tanggalEdit"
max="{{ date('Y-m-d') }}" required> class="form-control @error('tanggal') is-invalid @enderror" max="{{ date('Y-m-d') }}"
required>
@error('tanggal', 'edit')
<small class="text-danger">{{ $message }}</small>
@enderror
</div> </div>
<div class="form-group"> <div class="form-group">
<label>Nama Barang</label> <label>Nama Barang</label>
<select name="nama_barang" id="namaEdit" class="form-control" required> <select name="nama_barang" id="namaEdit"
class="form-control @error('nama_barang') is-invalid @enderror" required>
<option value="Jagung">Jagung</option> <option value="Jagung">Jagung</option>
<option value="Katul">Katul</option> <option value="Katul">Katul</option>
@ -427,6 +440,9 @@ class="form-control @error('jenis_transaksi') is-invalid @enderror" required>
<option value="Pakan Starter">Pakan Starter</option> <option value="Pakan Starter">Pakan Starter</option>
</select> </select>
@error('nama_barang', 'edit')
<small class="text-danger">{{ $message }}</small>
@enderror
</div> </div>
<div class="row"> <div class="row">
@ -434,8 +450,11 @@ class="form-control @error('jenis_transaksi') is-invalid @enderror" required>
<div class="form-group"> <div class="form-group">
<label>Jumlah</label> <label>Jumlah</label>
<input type="number" name="jumlah" id="jumlahEdit" max="999999" min="1" <input type="number" name="jumlah" id="jumlahEdit" max="999999" min="1"
inputmode="numeric" oninput="this.value=this.value.slice(0,6)" inputmode="numeric" maxlength="6"
class="form-control" required> class="form-control @error('jumlah') is-invalid @enderror" required>
@error('jumlah', 'edit')
<small class="text-danger">{{ $message }}</small>
@enderror
</div> </div>
</div> </div>
<div class="col-md-4"> <div class="col-md-4">
@ -449,8 +468,12 @@ class="form-control" required>
<div class="col-md-4 harga-edit"> <div class="col-md-4 harga-edit">
<div class="form-group"> <div class="form-group">
<label>Harga Satuan (Rp)</label> <label>Harga Satuan (Rp)</label>
<input type="text" name="harga_satuan" id="hargaEdit" class="form-control" <input type="text" name="harga_satuan" id="hargaEdit"
class="form-control @error('harga_satuan') is-invalid @enderror"
inputmode="numeric" maxlength="12"> inputmode="numeric" maxlength="12">
@error('harga_satuan', 'edit')
<small class="text-danger">{{ $message }}</small>
@enderror
</div> </div>
</div> </div>
</div> </div>
@ -513,54 +536,30 @@ class="form-control" required>
@section('scripts') @section('scripts')
<script> <script>
const baseUrl = "{{ url('/pakan') }}"; const baseUrl = "{{ route('pakan') }}";
/* FORMAT RUPIAH */
function formatRupiah(angka) { function formatRupiah(angka) {
if (!angka) return '';
angka = angka.replace(/[^,\d]/g, '').toString(); angka = angka.toString().replace(/\D/g, '');
let split = angka.split(','); return angka.replace(/\B(?=(\d{3})+(?!\d))/g, ".");
let sisa = split[0].length % 3;
let rupiah = split[0].substr(0, sisa);
let ribuan = split[0].substr(sisa).match(/\d{3}/gi);
if (ribuan) {
let separator = sisa ? '.' : '';
rupiah += separator + ribuan.join('.');
}
return rupiah;
} }
function formatJumlah(angka){
angka = parseFloat(angka);
if(isNaN(angka)) return '';
if(angka === 0) return '0';
return angka.toString().replace(/\.?0+$/, '');
}
/* TAMBAH */ /* TAMBAH */
function hitungTambah() { function hitungTambah() {
let j = $('#jumlahTambah').val() || 0; let j = parseInt($('#jumlahTambah').val()) || 0;
let h = $('#hargaTambah').val().replace(/\./g, '') || 0;
let h = $('#hargaTambah').val().replace(/\D/g, '');
h = parseInt(h) || 0;
$('#totalTambah').val( $('#totalTambah').val(
'Rp ' + (j * h).toLocaleString('id-ID') 'Rp ' + (j * h).toLocaleString('id-ID')
); );
} }
$('#hargaTambah').on('input', function() {
$('#jumlahTambah, #hargaTambah').on('input', hitungTambah); let angka = this.value.replace(/\D/g, '');
/* format harga tambah */
$('#hargaTambah').on('keyup', function() {
let angka = this.value.replace(/\./g, '');
if (angka.length > 9) { if (angka.length > 9) {
angka = angka.slice(0, 9); angka = angka.slice(0, 9);
@ -568,16 +567,22 @@ function hitungTambah() {
this.value = formatRupiah(angka); this.value = formatRupiah(angka);
hitungTambah(); hitungTambah();
}); });
/* format harga tambah */
$('#jumlahTambah').on('input', hitungTambah);
$('#jenisTambah').on('change', function() { $('#jenisTambah').on('change', function() {
if (this.value === 'keluar') { if (this.value === 'keluar') {
$('.harga-tambah').hide(); $('.harga-tambah').hide();
$('#hargaTambah,#totalTambah').val(''); $('#hargaTambah')
.val('')
.prop('disabled', true);
$('#totalTambah').val('');
} else { } else {
$('.harga-tambah').show(); $('.harga-tambah').show();
$('#hargaTambah').prop('disabled', false);
} }
}); });
@ -585,20 +590,21 @@ function hitungTambah() {
/* EDIT */ /* EDIT */
function hitungEdit() { function hitungEdit() {
let j = $('#jumlahEdit').val() || 0; let j = parseInt($('#jumlahEdit').val()) || 0;
let h = $('#hargaEdit').val().replace(/\./g, '') || 0;
let h = $('#hargaEdit').val().replace(/\./g, '');
h = parseInt(h) || 0;
$('#totalEdit').val( $('#totalEdit').val(
'Rp ' + (j * h).toLocaleString('id-ID') j && h ? 'Rp ' + (j * h).toLocaleString('id-ID') : ''
); );
} }
/* realtime hitung */ /* realtime hitung */
$('#jumlahEdit, #hargaEdit').on('input', hitungEdit); $('#jumlahEdit, #hargaEdit').on('input', hitungEdit);
/* format harga edit */ /* format harga edit */
$('#hargaEdit').on('keyup', function() { $('#hargaEdit').on('input', function() {
let angka = this.value.replace(/\./g, ''); let angka = this.value.replace(/\./g, '');
@ -610,7 +616,6 @@ function hitungEdit() {
hitungEdit(); hitungEdit();
}); });
/* perubahan jenis transaksi edit */ /* perubahan jenis transaksi edit */
$('#jenisEdit').on('change', function() { $('#jenisEdit').on('change', function() {
@ -627,28 +632,43 @@ function hitungEdit() {
/* modal edit dibuka */ /* modal edit dibuka */
$('#modalEditTransaksi').on('show.bs.modal', function(e) { $('#modalEditTransaksi').on('show.bs.modal', function(e) {
// CEK: kalau ada error edit, JANGAN override input
let isError = {{ $errors->edit->any() ? 'true' : 'false' }};
if (isError) return; // STOP di sini, biar pakai old()
let btn = $(e.relatedTarget); let btn = $(e.relatedTarget);
let id = btn.data('id');
$('#formEditTransaksi').attr('action', baseUrl + '/' + btn.data('id')); $('#formEditTransaksi').attr('action', baseUrl + '/' + btn.data('id'));
$('#formEditTransaksi [name=nama_barang]').val(btn.data('nama'));
$('#formEditTransaksi [name=jenis_transaksi]').val(btn.data('jenis'));
$('#formEditTransaksi [name=jumlah]').val(
formatJumlah(btn.data('jumlah'))
);
let harga = btn.data('harga');
if (harga !== null && harga !== undefined) { // FIX NAMA BARANG
harga = formatRupiah(harga.toString()); $('#namaEdit').val(''); // RESET DULU
} else {
harga = '';
}
$('#formEditTransaksi [name=harga_satuan]').val(harga); let nama = btn.data('nama');
$('#formEditTransaksi [name=tanggal]').val(btn.data('tanggal')); $('#namaEdit option').each(function() {
if ($(this).val().toLowerCase() === String(nama).toLowerCase()) {
$(this).prop('selected', true);
}
});
// jenis
$('#jenisEdit').val(btn.data('jenis'));
// jumlah (langsung angka asli)
$('#jumlahEdit').val(btn.data('jumlah'));
// harga
let harga = parseInt(btn.data('harga')) || 0;
$('#hargaEdit').val(harga ? formatRupiah(harga.toString()) : '');
// tanggal
$('#tanggalEdit').val(btn.data('tanggal'));
$('#jenisEdit').trigger('change'); $('#jenisEdit').trigger('change');
hitungEdit(); hitungEdit();
}); });
/* HAPUS */ /* HAPUS */
@ -693,15 +713,59 @@ function hitungEdit() {
@endif @endif
@if ($errors->any()) @if ($errors->any() && !$errors->edit->any())
<script> <script>
$(document).ready(function() { $(document).ready(function() {
$('#modalTransaksi').modal('show'); $('#modalTransaksi').modal('show');
hitungTambah();
let jenis = "{{ old('jenis_transaksi') }}";
if (jenis === 'keluar') {
$('.harga-tambah').hide();
$('#hargaTambah').prop('disabled', true);
} else {
$('.harga-tambah').show();
$('#hargaTambah').prop('disabled', false);
}
hitungTambah();
}); });
</script> </script>
@endif @endif
@if ($errors->edit->any())
<script>
$(document).ready(function() {
let id = "{{ session('edit_id') }}";
// SET ACTION WAJIB!
$('#formEditTransaksi').attr('action', "{{ route('pakan') }}/" + id);
$('#modalEditTransaksi').modal('show');
// isi pakai old input
$('#jenisEdit').val("{{ old('jenis_transaksi') }}");
$('#tanggalEdit').val("{{ old('tanggal') }}");
$('#jumlahEdit').val("{{ old('jumlah') }}");
let nama = "{{ old('nama_barang') }}";
$('#namaEdit option').each(function() {
if ($(this).val().toLowerCase() === nama.toLowerCase()) {
$(this).prop('selected', true);
}
});
let harga = "{{ old('harga_satuan') }}";
if (harga) {
$('#hargaEdit').val(formatRupiah(harga));
}
$('#jenisEdit').trigger('change');
hitungEdit();
});
</script>
@endif
@endsection @endsection

View File

@ -288,44 +288,78 @@ class="form-control @error('tanggal_produksi') is-invalid @enderror"
<div class="modal-body"> <div class="modal-body">
<!-- KANDANG -->
<div class="form-group"> <div class="form-group">
<label>Kandang</label> <label>Kandang</label>
<select name="kandang_id" class="form-control"> <select name="kandang_id" class="form-control @error('kandang_id') is-invalid @enderror">
<option value="">-- Pilih Kandang --</option>
@foreach ($kandang as $k) @foreach ($kandang as $k)
<option value="{{ $k->id }}">{{ $k->nama_kandang }}</option> <option value="{{ $k->id }}">
{{ $k->nama_kandang }}
</option>
@endforeach @endforeach
</select> </select>
@error('kandang_id')
<small class="text-danger">{{ $message }}</small>
@enderror
</div> </div>
<!-- SHIFT -->
<div class="form-group"> <div class="form-group">
<label>Shift</label> <label>Shift</label>
<select name="shift" class="form-control"> <select name="shift" class="form-control @error('shift') is-invalid @enderror">
<option value="pagi">Pagi</option> <option value="">-- Pilih Shift --</option>
<option value="sore">Sore</option> <option value="pagi" {{ old('shift') == 'pagi' ? 'selected' : '' }}>Pagi</option>
<option value="sore" {{ old('shift') == 'sore' ? 'selected' : '' }}>Sore</option>
</select> </select>
@error('shift')
<small class="text-danger">{{ $message }}</small>
@enderror
</div> </div>
<!-- BERAT -->
<div class="row"> <div class="row">
<div class="col-md-6"> <div class="col-md-6">
<div class="form-group"> <div class="form-group">
<label>Berat Telur Layak (Kg)</label> <label>Berat Telur Layak (Kg)</label>
<input type="text" name="berat_telur_layak" class="form-control" maxlength="6" inputmode="decimal" <input type="text" name="berat_telur_layak"
class="form-control @error('berat_telur_layak') is-invalid @enderror"
value="{{ old('berat_telur_layak') }}" maxlength="6" inputmode="decimal"
oninput="validasiBerat(this)"> oninput="validasiBerat(this)">
@error('berat_telur_layak')
<small class="text-danger">{{ $message }}</small>
@enderror
</div> </div>
</div> </div>
<div class="col-md-6"> <div class="col-md-6">
<div class="form-group"> <div class="form-group">
<label>Berat Telur Rusak (Kg)</label> <label>Berat Telur Rusak (Kg)</label>
<input type="text" name="berat_telur_rusak" class="form-control" maxlength="6" inputmode="decimal" <input type="text" name="berat_telur_rusak"
class="form-control @error('berat_telur_rusak') is-invalid @enderror"
value="{{ old('berat_telur_rusak') }}" maxlength="6" inputmode="decimal"
oninput="validasiBerat(this)"> oninput="validasiBerat(this)">
@error('berat_telur_rusak')
<small class="text-danger">{{ $message }}</small>
@enderror
</div> </div>
</div> </div>
</div> </div>
<!-- TANGGAL -->
<div class="form-group"> <div class="form-group">
<label>Tanggal Produksi</label> <label>Tanggal Produksi</label>
<input type="date" name="tanggal_produksi" min="2000-01-01" max="{{ date('Y-m-d') }}" <input type="date" name="tanggal_produksi"
class="form-control"> class="form-control @error('tanggal_produksi') is-invalid @enderror"
value="{{ old('tanggal_produksi') }}" min="2000-01-01" max="{{ date('Y-m-d') }}">
@error('tanggal_produksi')
<small class="text-danger">{{ $message }}</small>
@enderror
</div> </div>
</div> </div>
@ -391,28 +425,32 @@ function autoSubmit() {
$('#formFilter').submit(); $('#formFilter').submit();
}); });
function formatBerat(angka) { function formatBerat(angka) {
angka = parseFloat(angka); if (!angka && angka !== 0) return '';
if (isNaN(angka)) return ''; let num = Number(angka);
// jika nilainya 0 tetap tampil 0 if (Number.isInteger(num)) {
if (angka === 0) return '0'; return num.toString(); // contoh: 10 tetap 10
}
// hilangkan .00 atau nol di belakang return num.toFixed(2).replace(/\.?0+$/, ''); // contoh: 10.50 → 10.5
return angka.toString().replace(/\.?0+$/, ''); }
}
/* MODAL EDIT */ /* MODAL EDIT */
const baseUrl = "{{ url('/hasil') }}";
$('#modalEditProduksi').on('show.bs.modal', function(e) { $('#modalEditProduksi').on('show.bs.modal', function(e) {
let btn = $(e.relatedTarget); let btn = $(e.relatedTarget);
let id = btn.data('id');
let url = "{{ route('hasil.update', ':id') }}";
url = url.replace(':id', id);
$('#formEdit').attr('action', url);
$('#formEdit').attr('action', baseUrl + '/' + btn.data('id'));
$('#formEdit [name=kandang_id]').val(btn.data('kandang')); $('#formEdit [name=kandang_id]').val(btn.data('kandang'));
$('#formEdit [name=shift]').val(btn.data('shift')); $('#formEdit [name=shift]').val(btn.data('shift'));
$('#formEdit [name=berat_telur_layak]').val(formatBerat(btn.data('layak') ?? 0)); $('#formEdit [name=berat_telur_layak]').val(formatBerat(btn.data('layak') ?? 0));
$('#formEdit [name=berat_telur_rusak]').val(formatBerat(btn.data('rusak') ?? 0)); $('#formEdit [name=berat_telur_rusak]').val(formatBerat(btn.data('rusak') ?? 0));
$('#formEdit [name=tanggal_produksi]').val(btn.data('tanggal')); $('#formEdit [name=tanggal_produksi]').val(btn.data('tanggal'));
}); });
@ -420,14 +458,40 @@ function formatBerat(angka) {
/* MODAL HAPUS */ /* MODAL HAPUS */
$('#modalHapusProduksi').on('show.bs.modal', function(e) { $('#modalHapusProduksi').on('show.bs.modal', function(e) {
let btn = $(e.relatedTarget); let btn = $(e.relatedTarget);
$('#formHapus').attr('action', baseUrl + '/' + btn.data('id')); let id = btn.data('id');
let url = "{{ route('hasil.destroy', ':id') }}";
url = url.replace(':id', id);
$('#formHapus').attr('action', url);
}); });
/*AUTO OPEN MODAL JIKA ERROR */ /*AUTO OPEN MODAL JIKA ERROR */
@if ($errors->any()) @if ($errors->any())
$(document).ready(function() { $(document).ready(function() {
$('#modalTambahProduksi').modal('show');
let form = "{{ session('form') }}";
if (form === 'edit') {
let editId = "{{ session('edit_id') }}";
$('#modalEditProduksi').modal('show');
// langsung pakai old() untuk isi form
$('#formEdit [name=kandang_id]').val("{{ old('kandang_id') }}");
$('#formEdit [name=shift]').val("{{ old('shift') }}");
$('#formEdit [name=berat_telur_layak]').val("{{ old('berat_telur_layak') }}");
$('#formEdit [name=berat_telur_rusak]').val("{{ old('berat_telur_rusak') }}");
$('#formEdit [name=tanggal_produksi]').val("{{ old('tanggal_produksi') }}");
// set action form edit
let url = "{{ route('hasil.update', ':id') }}".replace(':id', editId);
$('#formEdit').attr('action', url);
} else {
$('#modalTambahProduksi').modal('show');
}
}); });
@endif @endif

View File

@ -386,9 +386,13 @@ function formatJumlah(angka) {
if (isNaN(angka)) return ''; if (isNaN(angka)) return '';
if (angka === 0) return '0'; // kalau bilangan bulat, tampilkan tanpa desimal
if (Number.isInteger(angka)) {
return angka.toString();
}
return angka.toString().replace(/\.?0+$/, ''); // kalau desimal, tampilkan normal (tanpa nol berlebih)
return angka.toString().replace(/(\.\d*?[1-9])0+$/, '$1');
} }
function formatRupiah(angka) { function formatRupiah(angka) {
@ -521,27 +525,52 @@ function hitungTotalTambah() {
// TOTAL OTOMATIS MODAL EDIT // TOTAL OTOMATIS MODAL EDIT
function hitungTotalEdit() { function hitungTotalEdit() {
let jumlah = parseFloat($('#modalEditPenjualan input[name=jumlah]').val()) || 0; let jumlah = parseFloat($('#modalEditPenjualan input[name=jumlah]').val()) || 0;
let harga = parseFloat($('#modalEditPenjualan input[name=harga_satuan]').val()) || 0;
let total = jumlah * harga; let harga = $('#modalEditPenjualan input[name=harga_satuan]').val()
.replace(/\./g, ''); // 🔥 hapus titik dulu
harga = parseFloat(harga) || 0;
let total = jumlah * harga;
$('#totalPreviewEdit').val(
"Rp " + total.toLocaleString('id-ID')
);
}
$('#modalEditPenjualan input[name=harga_satuan]').on('input', function() {
let angka = $(this).val().replace(/\D/g, '');
if (parseInt(angka || 0) > 99999999) {
angka = '99999999';
}
let rupiah = angka.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ".");
$(this).val(rupiah);
hitungTotalEdit();
});
$('#formEdit').on('submit', function() {
let harga = $('#modalEditPenjualan input[name=harga_satuan]')
.val()
.replace(/\./g, '');
$('#modalEditPenjualan input[name=harga_satuan]').val(harga);
});
$('#totalPreviewEdit').val(
"Rp " + total.toLocaleString('id-ID')
);
}
$('#modalEditPenjualan input[name=jumlah], #modalEditPenjualan input[name=harga_satuan]')
.on('input', hitungTotalEdit);
// FORMAT RUPIAH + PEMBATASAN HARGA // FORMAT RUPIAH + PEMBATASAN HARGA
$('#hargaTambah').on('input', function() { $('#hargaTambah').on('input', function() {
let angka = $(this).val().replace(/\D/g, ''); let angka = $(this).val().replace(/\D/g, '');
// BATAS MAKSIMAL // BATAS MAKSIMAL
if (angka > 99999999) { if (parseInt(angka || 0) > 99999999) {
angka = 99999999; angka = '99999999';
} }
// FORMAT RIBUAN // FORMAT RIBUAN
let rupiah = angka.toString().replace(/\B(?=(\d{3})+(?!\d))/g, "."); let rupiah = angka.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ".");
@ -551,11 +580,9 @@ function hitungTotalEdit() {
hitungTotalTambah(); hitungTotalTambah();
}); });
$('form').on('submit', function() { $('#modalTambahPenjualan form').on('submit', function() {
let harga = $('#hargaTambah').val().replace(/\./g, ''); let harga = $('#hargaTambah').val().replace(/\./g, '');
$('#hargaTambah').val(harga); $('#hargaTambah').val(harga);
}); });
}); });
</script> </script>

View File

@ -6,12 +6,12 @@
<link rel="icon" type="image/png" href="{{ asset('assets/img/favicon.png') }}"> <link rel="icon" type="image/png" href="{{ asset('assets/img/favicon.png') }}">
<meta content='width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0, shrink-to-fit=no' <meta content='width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0, shrink-to-fit=no'
name='viewport' /> name='viewport' />
<link rel="stylesheet" href="assets/css/bootstrap.min.css"> <link rel="stylesheet" href="{{ asset('assets/css/bootstrap.min.css') }}">
<link href="https://fonts.googleapis.com/css2?family=Poppins:wght@400;500;600;700&display=swap" rel="stylesheet"> <link href="https://fonts.googleapis.com/css2?family=Poppins:wght@400;500;600;700&display=swap" rel="stylesheet">
<link rel="stylesheet" href="assets/css/ready.css"> <link rel="stylesheet" href="{{ asset('assets/css/ready.css') }}">
<link rel="stylesheet" href="assets/css/demo.css"> <link rel="stylesheet" href="{{ asset('assets/css/demo.css') }}">
<link rel="stylesheet" href="assets/css/custom.css"> <link rel="stylesheet" href="{{ asset('assets/css/custom.css') }}">
<link rel="stylesheet" <link rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/line-awesome/1.3.0/line-awesome/css/line-awesome.min.css"> href="https://cdnjs.cloudflare.com/ajax/libs/line-awesome/1.3.0/line-awesome/css/line-awesome.min.css">
@ -224,19 +224,19 @@ class="d-none d-sm-inline font-weight-bold text-dark">{{ auth()->user()->name }}
@yield('content') @yield('content')
<script src="assets/js/core/jquery.3.2.1.min.js"></script> <script src="{{ asset('assets/js/core/jquery.3.2.1.min.js') }}"></script>
<script src="assets/js/core/popper.min.js"></script> <script src="{{ asset('assets/js/core/popper.min.js') }}"></script>
<script src="assets/js/core/bootstrap.min.js"></script> <script src="{{ asset('assets/js/core/bootstrap.min.js') }}"></script>
<script src="assets/js/plugin/jquery-ui-1.12.1.custom/jquery-ui.min.js"></script> <script src="{{ asset('assets/js/plugin/jquery-ui-1.12.1.custom/jquery-ui.min.js') }}"></script>
<script src="assets/js/plugin/chartist/chartist.min.js"></script> <script src="{{ asset('assets/js/plugin/chartist/chartist.min.js') }}"></script>
<script src="assets/js/plugin/chartist/plugin/chartist-plugin-tooltip.min.js"></script> <script src="{{ asset('assets/js/plugin/chartist/plugin/chartist-plugin-tooltip.min.js') }}"></script>
<script src="assets/js/plugin/bootstrap-notify/bootstrap-notify.min.js"></script> <script src="{{ asset('assets/js/plugin/bootstrap-notify/bootstrap-notify.min.js') }}"></script>
<script src="assets/js/plugin/bootstrap-toggle/bootstrap-toggle.min.js"></script> <script src="{{ asset('assets/js/plugin/bootstrap-toggle/bootstrap-toggle.min.js') }}"></script>
<script src="assets/js/plugin/jquery-mapael/jquery.mapael.min.js"></script> <script src="{{ asset('assets/js/plugin/jquery-mapael/jquery.mapael.min.js') }}"></script>
<script src="assets/js/plugin/jquery-mapael/maps/world_countries.min.js"></script> <script src="{{ asset('assets/js/plugin/jquery-mapael/maps/world_countries.min.js') }}"></script>
<script src="assets/js/plugin/chart-circle/circles.min.js"></script> <script src="{{ asset('assets/js/plugin/chart-circle/circles.min.js') }}"></script>
<script src="assets/js/plugin/jquery-scrollbar/jquery.scrollbar.min.js"></script> <script src="{{ asset('assets/js/plugin/jquery-scrollbar/jquery.scrollbar.min.js') }}"></script>
<script src="assets/js/ready.min.js"></script> <script src="{{ asset('assets/js/ready.min.js') }}"></script>
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script> <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script> <script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>

View File

@ -99,3 +99,8 @@
Route::get('/laporan/export', [LaporanController::class, 'export'])->name('laporan.export'); Route::get('/laporan/export', [LaporanController::class, 'export'])->name('laporan.export');
}); });
}); });
Route::fallback(function () {
return Auth::check()
? abort(404)
: redirect()->route('login');
});