306 lines
10 KiB
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);
|
|
}
|
|
}
|
|
}
|