Reservasi-Cafe/app/Http/Controllers/ReservasiController.php

306 lines
10 KiB
PHP

<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Session;
use Illuminate\Support\Facades\Log;
use App\Models\Reservasi;
use App\Models\Meja;
use App\Models\Transaksi;
use Illuminate\Support\Facades\DB;
use Carbon\Carbon;
use App\Models\Cart;
use App\Models\TransaksiItem;
class ReservasiController extends Controller
{
// Tampilkan formulir reservasi
public function index()
{
try {
$mejaId = session('selected_meja');
$meja = $mejaId ? Meja::findOrFail($mejaId) : null;
$cartItems = auth()->check() ? Cart::where('user_id', auth()->id())->with('menu')->get() : collect();
$totals = [
'subtotal' => 0
];
if ($cartItems->count() > 0) {
$subtotal = $cartItems->sum(function ($item) {
return $item->quantity * $item->menu->price;
});
$totals = [
'subtotal' => $subtotal
];
}
return view('reservasi', compact('meja', 'cartItems', 'totals'));
} catch (\Exception $e) {
Log::error('Error in ReservasiController@index: ' . $e->getMessage());
return redirect()->route('menu.index')->with('error', 'Terjadi kesalahan. Silakan coba lagi.');
}
}
// Simpan data reservasi
public function store(Request $request)
{
DB::beginTransaction();
try {
// Validasi input
$request->validate([
'tanggal' => 'required|date|after_or_equal:today',
'start_time' => 'required'
]);
$mejaId = session('selected_meja');
if (!$mejaId) {
throw new \Exception('Silakan pilih meja terlebih dahulu');
}
// Cek ketersediaan meja
$meja = Meja::findOrFail($mejaId);
if ($meja->status === 'tidak_tersedia') {
throw new \Exception('Meja tidak tersedia');
}
// Ambil items dari cart
$cartItems = Cart::where('user_id', auth()->id())
->with('menu')
->get();
if ($cartItems->isEmpty()) {
throw new \Exception('Keranjang belanja kosong');
}
// Hitung total harga
$totalHarga = $cartItems->sum(function($item) {
return $item->quantity * $item->menu->price;
});
// Final amount sama dengan total harga karena tidak ada tax dan service charge
$finalAmount = $totalHarga;
// Buat reservasi
$reservasi = Reservasi::create([
'meja_id' => $mejaId,
'user_id' => auth()->id(),
'date' => $request->tanggal,
'start_time' => $request->start_time,
'status' => 'pending',
'name' => auth()->user()->name,
'phone' => auth()->user()->phone ?? '',
'total_harga' => $totalHarga
]);
// Generate kode transaksi
$transactionCode = 'TRX-' . date('Ymd') . '-' . strtoupper(uniqid());
// Buat transaksi
$transaksi = Transaksi::create([
'transaction_code' => $transactionCode,
'user_id' => auth()->id(),
'reservasi_id' => $reservasi->id,
'total_amount' => $totalHarga,
'final_amount' => $finalAmount,
'status' => 'pending'
]);
// Simpan item transaksi
foreach ($cartItems as $item) {
TransaksiItem::create([
'transaksi_id' => $transaksi->id,
'menu_id' => $item->menu_id,
'menu_name' => $item->menu->name,
'quantity' => $item->quantity,
'price' => $item->menu->price,
'subtotal' => $item->quantity * $item->menu->price
]);
}
// Update status meja jika reservasi untuk hari ini
if ($request->tanggal === date('Y-m-d')) {
$meja->status = 'dipesan';
$meja->save();
}
// Hapus cart items
Cart::where('user_id', auth()->id())->delete();
// Clear session meja
session()->forget('selected_meja');
DB::commit();
// Redirect ke halaman detail transaksi
return redirect()->route('transaksi.detail', $transaksi->id)
->with('success', 'Reservasi berhasil dibuat, silakan lakukan pembayaran');
} catch (\Exception $e) {
DB::rollback();
Log::error('Error creating reservation and transaction: ' . $e->getMessage());
return back()->with('error', 'Terjadi kesalahan saat membuat reservasi: ' . $e->getMessage());
}
}
public function success($id)
{
$reservasi = Reservasi::with('meja')->findOrFail($id);
return view('reservasi.success', compact('reservasi'));
}
public function checkAvailability(Request $request)
{
$request->validate([
'tanggal' => 'required|date',
'meja_id' => 'required|exists:mejas,id'
]);
$reservasi = Reservasi::where('meja_id', $request->meja_id)
->where('tanggal', $request->tanggal)
->get();
$bookedHours = [];
foreach ($reservasi as $r) {
$startTime = Carbon::parse($r->jam);
for ($i = 0; $i < $r->durasi; $i++) {
$bookedHours[] = $startTime->copy()->addHours($i)->format('H:i');
}
}
$availableHours = [];
$start = Carbon::parse('10:00');
$end = Carbon::parse('22:00');
while ($start <= $end) {
if (!in_array($start->format('H:i'), $bookedHours)) {
$availableHours[] = $start->format('H:i');
}
$start->addHour();
}
return response()->json($availableHours);
}
public function getSchedule(Request $request, Meja $meja)
{
$date = $request->date;
$reservations = Reservasi::where('meja_id', $meja->id)
->where('date', $date)
->where('status', '!=', 'cancelled')
->get(['start_time', 'end_time']);
return response()->json([
'success' => true,
'reservations' => $reservations
]);
}
public function getAvailableSlots(Request $request)
{
try {
$date = $request->date;
$mejaId = session('selected_meja');
if (!$date || !$mejaId) {
return response()->json([
'status' => 'error',
'error' => 'Data tidak lengkap'
], 400);
}
$meja = Meja::findOrFail($mejaId);
$availableSlots = $meja->getAvailableTimeSlots($date);
// Jika tanggal hari ini, filter slot yang sudah lewat
if ($date === date('Y-m-d')) {
$currentTime = Carbon::now();
$availableSlots = array_filter($availableSlots, function($slot) use ($currentTime) {
return Carbon::parse($slot)->gt($currentTime);
});
}
return response()->json([
'status' => 'success',
'data' => array_values($availableSlots)
]);
} catch (\Exception $e) {
Log::error('Error in getAvailableSlots: ' . $e->getMessage());
return response()->json([
'status' => 'error',
'error' => 'Terjadi kesalahan saat memuat slot waktu'
], 500);
}
}
/**
* Handle Midtrans payment notification
*/
public function handlePaymentNotification(Request $request)
{
try {
$notification = json_decode($request->getContent(), true);
// Get transaction
$transaction = Transaksi::where('transaction_code', $notification['order_id'])->firstOrFail();
$reservasi = $transaction->reservasi;
// Update payment method based on Midtrans payment type
$paymentType = $notification['payment_type'];
switch ($paymentType) {
case 'credit_card':
$paymentMethod = 'credit_card';
break;
case 'bank_transfer':
$vaNumbers = $notification['va_numbers'][0] ?? null;
if ($vaNumbers) {
$bank = strtolower($vaNumbers['bank']);
$paymentMethod = $bank . '_va';
} else {
$paymentMethod = 'other_va';
}
break;
case 'gopay':
$paymentMethod = 'gopay';
break;
case 'shopeepay':
$paymentMethod = 'shopeepay';
break;
case 'qris':
$paymentMethod = 'qris';
break;
case 'cstore':
$store = strtolower($notification['store']);
$paymentMethod = $store;
break;
default:
$paymentMethod = $paymentType;
}
// Update reservation payment method
$reservasi->update([
'payment_method' => $paymentMethod
]);
// Handle transaction status
if ($notification['transaction_status'] == 'capture' || $notification['transaction_status'] == 'settlement') {
$transaction->update(['status' => 'paid']);
$reservasi->update(['status' => 'confirmed']);
} elseif ($notification['transaction_status'] == 'cancel' || $notification['transaction_status'] == 'deny' || $notification['transaction_status'] == 'expire') {
$transaction->update(['status' => 'cancelled']);
$reservasi->update(['status' => 'cancelled']);
}
return response()->json(['status' => 'success']);
} catch (\Exception $e) {
Log::error('Error handling Midtrans notification: ' . $e->getMessage());
return response()->json(['status' => 'error'], 500);
}
}
}