NIM_E31222518/app/Http/Controllers/PesananController.php

377 lines
12 KiB
PHP

<?php
namespace App\Http\Controllers;
use App\Models\Pesanan;
use App\Models\Barang;
use App\Models\Keranjang;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
use App\Models\Transaksi;
class PesananController extends Controller
{
use AuthorizesRequests;
public function __construct()
{
$this->middleware('auth');
}
public function index()
{
$query = Pesanan::with(['user', 'barang'])
->where('user_id', Auth::id());
// Filter berdasarkan tanggal
if (request('start_date')) {
$query->whereDate('created_at', '>=', request('start_date'));
}
if (request('end_date')) {
$query->whereDate('created_at', '<=', request('end_date'));
}
// Filter berdasarkan status
if (request('status')) {
$query->where('status', request('status'));
}
$pesanan = $query->latest()->paginate(10);
return view('pesanan.index', compact('pesanan'));
}
public function create()
{
$barang = Barang::where('stok', '>', 0)->get();
return view('pesanan.create', compact('barang'));
}
public function store(Request $request)
{
$request->validate([
'barang_id' => 'required|exists:barang,id',
'jumlah' => 'required|integer|min:1',
'catatan' => 'nullable|string'
]);
$barang = Barang::findOrFail($request->barang_id);
if ($barang->stok < $request->jumlah) {
return back()->with('error', 'Stok tidak mencukupi');
}
// Cek apakah sudah ada pesanan pending untuk barang yang sama
$existingPesanan = Pesanan::where('user_id', Auth::id())
->where('barang_id', $request->barang_id)
->where('status', 'pending')
->first();
if ($existingPesanan) {
// Update jumlah pesanan yang ada
$newJumlah = $existingPesanan->jumlah + $request->jumlah;
if ($barang->stok < $newJumlah) {
return back()->with('error', 'Stok tidak mencukupi untuk total pesanan');
}
$existingPesanan->update([
'jumlah' => $newJumlah,
'total_harga' => $barang->harga * $newJumlah,
'catatan' => $request->catatan ?? $existingPesanan->catatan
]);
// Kurangi stok barang
$barang->update([
'stok' => $barang->stok - $request->jumlah
]);
return redirect()->route('pesanan.index')->with('success', 'Pesanan berhasil diperbarui');
}
// Jika tidak ada pesanan yang sama, buat pesanan baru
$total_harga = $barang->harga * $request->jumlah;
$pesanan = Pesanan::create([
'user_id' => Auth::id(),
'barang_id' => $request->barang_id,
'jumlah' => $request->jumlah,
'total_harga' => $total_harga,
'status' => 'pending',
'catatan' => $request->catatan
]);
// Kurangi stok barang
$barang->update([
'stok' => $barang->stok - $request->jumlah
]);
return redirect()->route('pesanan.index')->with('success', 'Pesanan berhasil dibuat');
}
public function show(Pesanan $pesanan)
{
$pesanan->load(['user', 'barang', 'items.barang']);
return view('pesanan.show', compact('pesanan'));
}
public function updateStatus(Request $request, Pesanan $pesanan)
{
$request->validate([
'status' => 'required|in:pending,diproses,dikirim,selesai,dibatalkan'
]);
$pesanan->update(['status' => $request->status]);
// Jika pesanan dibatalkan, kembalikan stok
if ($request->status === 'dibatalkan') {
$pesanan->barang->update([
'stok' => $pesanan->barang->stok + $pesanan->jumlah
]);
}
return back()->with('success', 'Status pesanan berhasil diperbarui');
}
public function destroy(Pesanan $pesanan)
{
try {
// Kembalikan stok
$pesanan->barang->update([
'stok' => $pesanan->barang->stok + $pesanan->jumlah
]);
// Hapus pesanan
$pesanan->delete();
return response()->json([
'success' => true,
'message' => 'Pesanan berhasil dibatalkan'
]);
} catch (\Exception $e) {
return response()->json([
'success' => false,
'message' => 'Terjadi kesalahan saat membatalkan pesanan'
], 500);
}
}
public function createFromBarang(Barang $barang)
{
if ($barang->stok <= 0) {
return back()->with('error', 'Maaf, stok barang tidak tersedia');
}
return view('pesanan.create-from-barang', compact('barang'));
}
public function edit(Pesanan $pesanan)
{
// Pastikan user hanya bisa mengedit pesanannya sendiri
if ($pesanan->user_id !== Auth::id()) {
return abort(403, 'Unauthorized action.');
}
// Pastikan hanya pesanan dengan status pending yang bisa diedit
if ($pesanan->status !== 'pending') {
return redirect()->route('pesanan.index')
->with('error', 'Hanya pesanan dengan status pending yang dapat diedit');
}
return view('pesanan.edit', compact('pesanan'));
}
public function update(Request $request, Pesanan $pesanan)
{
// Validasi user
if ($pesanan->user_id !== Auth::id()) {
return abort(403, 'Unauthorized action.');
}
// Validasi status
if ($pesanan->status !== 'pending') {
return redirect()->route('pesanan.index')
->with('error', 'Hanya pesanan dengan status pending yang dapat diubah');
}
$request->validate([
'jumlah' => 'required|integer|min:1',
'catatan' => 'nullable|string'
]);
$barang = $pesanan->barang;
$stokTersedia = $barang->stok + $pesanan->jumlah; // Stok saat ini + jumlah pesanan yang akan diubah
if ($request->jumlah > $stokTersedia) {
return back()->with('error', 'Stok tidak mencukupi');
}
// Hitung selisih stok
$selisihStok = $pesanan->jumlah - $request->jumlah;
// Update pesanan
$pesanan->update([
'jumlah' => $request->jumlah,
'total_harga' => $barang->harga * $request->jumlah,
'catatan' => $request->catatan
]);
// Update stok barang
$barang->update([
'stok' => $barang->stok + $selisihStok
]);
return redirect()->route('pesanan.index')
->with('success', 'Pesanan berhasil diperbarui');
}
public function storeFromCart(Request $request)
{
$request->validate([
'catatan' => 'nullable|string',
'shipping_info' => 'required|json',
'selected_items' => 'required|array'
]);
$shippingInfo = json_decode($request->shipping_info, true);
if (!$shippingInfo) {
return redirect()->route('keranjang.index')
->with('error', 'Informasi pengiriman tidak valid');
}
$query = Keranjang::with('barang')->where('user_id', Auth::id());
// Jika ada item yang dipilih, gunakan hanya item tersebut
if ($request->has('selected_items') && !empty($request->selected_items)) {
$query->whereIn('id', $request->selected_items);
}
$keranjangItems = $query->get();
if ($keranjangItems->isEmpty()) {
return redirect()->route('keranjang.index')
->with('error', 'Keranjang belanja Anda kosong');
}
DB::beginTransaction();
try {
$totalHargaBarang = 0;
$items = [];
foreach ($keranjangItems as $item) {
$barang = $item->barang;
// Verify stock availability
if ($barang->stok < $item->jumlah) {
DB::rollBack();
return redirect()->route('keranjang.index')
->with('error', "Stok {$barang->nama_barang} tidak mencukupi, tersisa {$barang->stok}");
}
$totalHargaBarang += $item->total_harga;
$items[] = [
'barang_id' => $barang->id,
'jumlah' => $item->jumlah,
'harga' => $barang->harga,
'subtotal' => $item->total_harga
];
// Update stock
$barang->update([
'stok' => $barang->stok - $item->jumlah
]);
}
// Buat satu pesanan untuk semua item
$pesanan = Pesanan::create([
'user_id' => Auth::id(),
'barang_id' => $items[0]['barang_id'], // Set barang_id dari item pertama
'jumlah' => $items[0]['jumlah'], // Set jumlah dari item pertama
'total_harga' => $totalHargaBarang + $shippingInfo['cost'],
'status' => 'pending',
'catatan' => $request->catatan,
'shipping_cost' => $shippingInfo['cost'],
'shipping_service' => $shippingInfo['service'],
'shipping_etd' => $shippingInfo['etd'],
'shipping_courier' => $shippingInfo['courier'],
'shipping_province_id' => $shippingInfo['province_id'],
'shipping_city_id' => $shippingInfo['city_id']
]);
// Simpan detail item pesanan
foreach ($items as $item) {
$pesanan->items()->create([
'barang_id' => $item['barang_id'],
'jumlah' => $item['jumlah'],
'harga' => $item['harga'],
'total_harga' => $item['subtotal']
]);
}
// Hapus item dari keranjang
$keranjangItems->each->delete();
DB::commit();
// Buat transaksi Midtrans
try {
// Hitung total harga item
$itemDetails = array_map(function($item) {
return [
'id' => $item['barang_id'],
'price' => $item['harga'],
'quantity' => $item['jumlah'],
'name' => $item['barang']->nama_barang
];
}, $items);
// Tambahkan detail pengiriman sebagai item terpisah
$itemDetails[] = [
'id' => 'shipping',
'price' => $shippingInfo['cost'],
'quantity' => 1,
'name' => 'Ongkos Kirim - ' . strtoupper($shippingInfo['courier']) . ' ' . $shippingInfo['service']
];
$params = [
'transaction_details' => [
'order_id' => 'ORDER-' . $pesanan->id,
'gross_amount' => $pesanan->total_harga,
],
'customer_details' => [
'first_name' => Auth::user()->name,
'email' => Auth::user()->email,
],
'item_details' => $itemDetails
];
// Dapatkan Snap Token
$snapToken = \Midtrans\Snap::getSnapToken($params);
// Simpan transaksi
$transaksi = Transaksi::create([
'pesanan_id' => $pesanan->id,
'user_id' => Auth::id(),
'total_bayar' => $pesanan->total_harga,
'status' => 'pending',
'snap_token' => $snapToken
]);
return redirect()->route('transaksi.show', $transaksi)
->with('success', 'Pesanan berhasil dibuat. Silakan selesaikan pembayaran.');
} catch (\Exception $e) {
\Log::error('Midtrans Error: ' . $e->getMessage());
return redirect()->route('pesanan.index');
}
} catch (\Exception $e) {
DB::rollBack();
return redirect()->route('keranjang.index')
->with('error', 'Terjadi kesalahan saat membuat pesanan: ' . $e->getMessage());
}
}
}