middleware('auth'); // Terapkan middleware admin hanya untuk method yang membutuhkan akses admin $this->middleware('admin')->only([ 'create', 'store', 'edit', 'update', 'destroy', 'activate', 'tambahBarang', 'updateJumlah' ]); } /** * Menampilkan daftar paket */ public function index() { $pakets = Paket::with('barangs')->get(); return view('paket', compact('pakets')); } /** * Menampilkan form untuk membuat paket baru */ public function create() { // Ambil data barang yang masih ada stoknya $barangs = StockModel::where('stok', '>', 0)->get(); return view('tambah-paket', compact('barangs')); } /** * Menyimpan paket baru */ public function store(Request $request) { $request->validate([ 'nama_paket' => 'required|string|max:255', 'jenis_paket' => 'required|in:wedding,seminar,outdoor,custom', 'harga' => 'required|numeric|min:0', 'stok' => 'required|integer|min:1', 'keterangan' => 'nullable|string', 'image' => 'nullable|image|mimes:jpeg,png,jpg,gif|max:2048', 'ongkir.*.nama_kota' => 'nullable|string|max:255', 'ongkir.*.biaya_ongkir' => 'nullable|numeric|min:0', ]); try { DB::beginTransaction(); // Upload gambar jika ada $imagePath = null; if ($request->hasFile('image')) { $imagePath = $request->file('image')->store('paket-images', 'public'); } // Simpan data paket $paket = Paket::create([ 'nama_paket' => $request->nama_paket, 'jenis_paket' => $request->jenis_paket, 'harga' => $request->harga, 'stok' => $request->stok, 'keterangan' => $request->keterangan, 'image' => $imagePath, 'status' => 'aktif' ]); // Simpan data ongkir kota if ($request->has('ongkir')) { foreach ($request->ongkir as $ongkir) { if (!empty($ongkir['nama_kota']) && !empty($ongkir['biaya_ongkir'])) { $paket->ongkirKota()->create([ 'nama_kota' => $ongkir['nama_kota'], 'biaya_ongkir' => $ongkir['biaya_ongkir'], 'status' => true ]); } } } // Tambahkan detail_barang (array barang yang dipilih) $detailBarang = []; if ($request->has('barang_ids')) { foreach ($request->barang_ids as $barangId) { $jumlah = $request->input('jumlah_' . $barangId, 1); $barang = StockModel::find($barangId); if ($barang) { $detailBarang[] = [ 'id' => $barang->id, 'nama_barang' => $barang->nama_barang, 'kode_barang' => $barang->kode_barang, 'kategori' => $barang->kategori, 'harga_sewa' => $barang->harga_sewa, 'jumlah' => $jumlah, 'deskripsi' => $barang->deskripsi, ]; } } $paket->detail_barang = $detailBarang; $paket->save(); } DB::commit(); return redirect()->route('paket.index')->with('success', 'Paket berhasil ditambahkan'); } catch (\Exception $e) { DB::rollback(); return back()->with('error', 'Terjadi kesalahan: ' . $e->getMessage())->withInput(); } } /** * Menampilkan form untuk mengedit paket */ public function edit($id) { $paket = Paket::with(['barangs', 'ongkirKota'])->findOrFail($id); $barangs = StockModel::all(); return view('edit-paket', compact('paket', 'barangs')); } /** * Update data paket */ public function update(Request $request, $id) { $request->validate([ 'nama_paket' => 'required|string|max:255', 'jenis_paket' => 'required|string|in:wedding,seminar,outdoor,custom', 'harga' => 'required|numeric|min:0', 'image' => 'nullable|image|mimes:jpeg,png,jpg,gif|max:2048', 'keterangan' => 'nullable|string', 'stok' => 'required|integer|min:0', 'ongkir.*.nama_kota' => 'nullable|string|max:255', 'ongkir.*.biaya_ongkir' => 'nullable|numeric|min:0', ]); try { DB::beginTransaction(); $paket = Paket::findOrFail($id); // Upload gambar jika ada if ($request->hasFile('image')) { // Hapus gambar lama if ($paket->image) { Storage::disk('public')->delete($paket->image); } $imagePath = $request->file('image')->store('pakets', 'public'); $paket->image = $imagePath; } $paket->update([ 'nama_paket' => $request->nama_paket, 'jenis_paket' => $request->jenis_paket, 'harga' => $request->harga, 'keterangan' => $request->keterangan, 'stok' => $request->stok ]); // Update ongkir kota if ($request->has('ongkir')) { // Hapus data ongkir yang lama $paket->ongkirKota()->delete(); // Tambah data ongkir yang baru foreach ($request->ongkir as $ongkir) { if (!empty($ongkir['nama_kota']) && !empty($ongkir['biaya_ongkir'])) { $paket->ongkirKota()->create([ 'nama_kota' => $ongkir['nama_kota'], 'biaya_ongkir' => $ongkir['biaya_ongkir'], 'status' => true ]); } } } // Update detail_barang (array barang yang dipilih) $detailBarang = []; if ($request->has('barang_ids')) { foreach ($request->barang_ids as $barangId) { $jumlah = $request->input('jumlah_' . $barangId, 1); $barang = StockModel::find($barangId); if ($barang) { $detailBarang[] = [ 'id' => $barang->id, 'nama_barang' => $barang->nama_barang, 'kode_barang' => $barang->kode_barang, 'kategori' => $barang->kategori, 'harga_sewa' => $barang->harga_sewa, 'jumlah' => $jumlah, 'deskripsi' => $barang->deskripsi, ]; } } $paket->detail_barang = $detailBarang; $paket->save(); } DB::commit(); return redirect()->route('paket')->with('success', 'Paket berhasil diperbarui!'); } catch (\Exception $e) { DB::rollback(); return back()->with('error', 'Terjadi kesalahan: ' . $e->getMessage())->withInput(); } } /** * Hapus paket */ public function destroy($id) { try { DB::beginTransaction(); $paket = Paket::findOrFail($id); // Hapus gambar jika ada if ($paket->image) { Storage::disk('public')->delete($paket->image); } // Kembalikan stok barang foreach ($paket->barangs as $barang) { $jumlah = $barang->pivot->jumlah; $barang->increment('stok', $jumlah); } $paket->delete(); DB::commit(); return redirect()->route('paket.index')->with('success', 'Paket berhasil dihapus!'); } catch (\Exception $e) { DB::rollback(); return back()->with('error', 'Terjadi kesalahan: ' . $e->getMessage()); } } /** * Mendapatkan daftar barang dalam paket */ public function getBarang($id) { try { $paket = Paket::with('barangs')->findOrFail($id); $result = []; foreach ($paket->barangs as $barang) { $result[] = [ 'id' => $barang->pivot->id, 'barang_id' => $barang->id, 'nama_barang' => $barang->nama_barang, 'kode_barang' => $barang->kode_barang, 'kategori' => $barang->kategori, 'harga_sewa' => $barang->harga_sewa, 'stok' => $barang->stok, 'jumlah' => $barang->pivot->jumlah, 'image_url' => $barang->image_url ]; } return response()->json([ 'success' => true, 'data' => $result ]); } catch (\Exception $e) { return response()->json([ 'success' => false, 'message' => 'Terjadi kesalahan: ' . $e->getMessage() ], 500); } } /** * Menambahkan barang ke paket */ public function tambahBarang(Request $request, $id) { $request->validate([ 'barang_id' => 'required|exists:barangs,id', 'jumlah' => 'required|integer|min:1', ]); try { DB::beginTransaction(); $paket = Paket::findOrFail($id); $barang = StockModel::findOrFail($request->barang_id); // Validasi stok if ($barang->stok < $request->jumlah) { throw new \Exception("Stok barang {$barang->nama_barang} tidak mencukupi"); } // Cek apakah barang sudah ada dalam paket $existing = $paket->barangs()->where('barang_id', $request->barang_id)->first(); if ($existing) { // Update jumlah jika sudah ada $oldJumlah = $existing->pivot->jumlah; $selisih = $request->jumlah - $oldJumlah; if ($selisih > 0 && $barang->stok < $selisih) { throw new \Exception("Stok barang {$barang->nama_barang} tidak mencukupi"); } $paket->barangs()->updateExistingPivot($request->barang_id, [ 'jumlah' => $request->jumlah ]); // Update stok barang $barang->decrement('stok', $selisih); } else { // Tambahkan baru jika belum ada $paket->barangs()->attach($request->barang_id, [ 'jumlah' => $request->jumlah ]); // Kurangi stok barang $barang->decrement('stok', $request->jumlah); } DB::commit(); return response()->json([ 'success' => true, 'message' => 'Barang berhasil ditambahkan ke paket', 'data' => [ 'nama_barang' => $barang->nama_barang, 'jumlah' => $request->jumlah, 'stok_tersisa' => $barang->stok ] ]); } catch (\Exception $e) { DB::rollback(); return response()->json([ 'success' => false, 'message' => 'Terjadi kesalahan: ' . $e->getMessage() ], 500); } } public function updateJumlah(Request $request, $id) { try { $paket = Paket::findOrFail($id); $request->validate([ 'jumlah' => 'required|integer|min:1' ]); // Update detail_barang dengan jumlah baru if ($paket->detail_barang) { $detail_barang = $paket->detail_barang; foreach ($detail_barang as &$barang) { $barang['jumlah'] = $request->jumlah; } $paket->detail_barang = $detail_barang; $paket->save(); } return response()->json([ 'success' => true, 'message' => 'Jumlah berhasil diperbarui' ]); } catch (\Exception $e) { return response()->json([ 'success' => false, 'message' => 'Gagal memperbarui jumlah: ' . $e->getMessage() ], 500); } } /** * Mengaktifkan satu unit paket yang sedang disewa */ public function activate($id) { try { DB::beginTransaction(); $paket = Paket::findOrFail($id); // Ambil sewa yang paling lama (terlama) untuk diaktifkan $oldestSewa = $paket->sewas() ->whereIn('status', ['confirmed', 'ongoing']) ->orderBy('tanggal_mulai', 'asc') ->first(); if (!$oldestSewa) { return redirect()->route('paket')->with('error', 'Tidak ada penyewaan aktif yang dapat diselesaikan.'); } // Update status sewa menjadi completed hanya untuk sewa terlama $oldestSewa->update(['status' => 'completed']); DB::commit(); return redirect()->route('paket')->with('success', 'Satu unit paket berhasil diaktifkan kembali.'); } catch (\Exception $e) { DB::rollback(); return redirect()->route('paket')->with('error', 'Terjadi kesalahan: ' . $e->getMessage()); } } /** * Mengaktifkan semua unit paket yang sedang disewa */ public function activateAll($id) { try { DB::beginTransaction(); $paket = Paket::findOrFail($id); // Update status semua sewa yang masih aktif menjadi completed $count = $paket->sewas() ->whereIn('status', ['confirmed', 'ongoing']) ->update(['status' => 'completed']); if ($count === 0) { return redirect()->route('paket')->with('error', 'Tidak ada penyewaan aktif yang dapat diselesaikan.'); } DB::commit(); return redirect()->route('paket')->with('success', 'Semua unit paket berhasil diaktifkan kembali.'); } catch (\Exception $e) { DB::rollback(); return redirect()->route('paket')->with('error', 'Terjadi kesalahan: ' . $e->getMessage()); } } /** * Menampilkan detail paket untuk modal */ public function detail($id) { try { $paket = Paket::findOrFail($id); $detailBarang = $paket->detail_barang ?? []; $barangs = []; foreach ($detailBarang as $barang) { $barangs[] = [ 'nama_barang' => $barang['nama_barang'] ?? '', 'pivot' => [ 'jumlah' => $barang['jumlah'] ?? 0 ] ]; } return response()->json([ 'id' => $paket->id, 'nama_paket' => $paket->nama_paket, 'jenis_paket' => $paket->jenis_paket, 'harga' => $paket->harga, 'stok' => $paket->stok, 'minimum_order' => $paket->minimum_order, 'keterangan' => $paket->keterangan, 'image' => $paket->image, 'barangs' => $barangs ]); } catch (\Exception $e) { return response()->json(['error' => 'Paket tidak ditemukan'], 404); } } }