MIF_E31220412/app/Http/Controllers/PaketController.php

401 lines
13 KiB
PHP

<?php
namespace App\Http\Controllers;
use App\Models\Paket;
use App\Models\StockModel;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Str;
class PaketController extends Controller
{
public function __construct()
{
$this->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
]);
}
}
}
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
]);
}
}
}
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')->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());
}
}
}