Reservasi-Cafe/app/Models/Reservasi.php

192 lines
5.7 KiB
PHP

<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasOne;
use Illuminate\Database\Eloquent\Relations\HasManyThrough;
use Carbon\Carbon;
class Reservasi extends Model
{
use HasFactory;
protected $table = 'reservasi';
protected $fillable = [
'user_id',
'meja_id',
'name',
'phone',
'date',
'start_time',
'status',
'notes',
'total_harga',
'payment_method'
];
protected $casts = [
'date' => 'date',
'start_time' => 'datetime:H:i',
];
const STATUS_PENDING = 'pending';
const STATUS_CONFIRMED = 'confirmed';
const STATUS_COMPLETED = 'completed';
const STATUS_CANCELLED = 'cancelled';
/**
* Get the user that owns the reservation.
*/
public function user(): BelongsTo
{
return $this->belongsTo(User::class);
}
/**
* Get the table that is reserved.
*/
public function meja(): BelongsTo
{
return $this->belongsTo(Meja::class, 'meja_id');
}
/**
* Get the transaction associated with the reservation.
*/
public function transaksi(): HasOne
{
return $this->hasOne(Transaksi::class);
}
/**
* Get the transaction items through the transaction.
*/
public function detailPesanan(): HasManyThrough
{
return $this->hasManyThrough(
TransaksiItem::class,
Transaksi::class,
'reservasi_id', // Foreign key on transaksi table...
'transaksi_id', // Foreign key on transaksi_items table...
'id', // Local key on reservasi table...
'id' // Local key on transaksi table...
);
}
/**
* Check if a time slot is available for a specific table.
*/
public static function isTimeSlotAvailable($mejaId, $date, $startTime): bool
{
// Convert times to Carbon instances for comparison
$start = Carbon::parse($startTime);
$requestedDate = Carbon::parse($date);
// Check if the requested date and time is in the past
if ($requestedDate->isPast() && $requestedDate->isToday() && $start->isPast()) {
return false;
}
// Check for existing reservations at the same time slot
$conflictingReservations = self::where('meja_id', $mejaId)
->whereDate('date', $date)
->whereNotIn('status', [self::STATUS_CANCELLED])
->where('start_time', $startTime)
->exists();
return !$conflictingReservations;
}
/**
* Get all available time slots for a specific table and date
*/
public static function getAvailableTimeSlots($mejaId, $date)
{
// Get all reservations for this table on this date
$reservations = self::where('meja_id', $mejaId)
->whereDate('date', $date)
->whereNotIn('status', [self::STATUS_CANCELLED])
->get(['start_time']);
$timeSlots = [];
$startHour = 10; // 10:00
$endHour = 22; // 22:00
$interval = 30; // 30 minutes interval
for ($hour = $startHour; $hour < $endHour; $hour++) {
for ($minute = 0; $minute < 60; $minute += $interval) {
$currentTime = sprintf('%02d:%02d', $hour, $minute);
// Check if this time slot is available
if (self::isTimeSlotAvailable($mejaId, $date, $currentTime)) {
$timeSlots[] = [
'start_time' => $currentTime,
'is_available' => true
];
}
}
}
// If date is today, remove past time slots
if ($date == Carbon::today()->format('Y-m-d')) {
$currentTime = Carbon::now();
$timeSlots = array_filter($timeSlots, function($slot) use ($currentTime) {
return Carbon::parse($slot['start_time'])->gt($currentTime);
});
}
return array_values($timeSlots);
}
/**
* Update table status based on reservation status
*/
public function updateTableStatus()
{
if ($this->date == now()->format('Y-m-d')) {
$status = match($this->status) {
self::STATUS_CONFIRMED => 'dipesan',
self::STATUS_COMPLETED, self::STATUS_CANCELLED => 'tersedia',
default => null
};
if ($status) {
$this->meja()->update(['status' => $status]);
}
}
}
/**
* Get payment method display name
*/
public function getPaymentMethodDisplayAttribute()
{
$methods = [
'credit_card' => 'Kartu Kredit',
'mandiri_clickpay' => 'Mandiri Clickpay',
'cimb_clicks' => 'CIMB Clicks',
'bca_klikbca' => 'BCA KlikBCA',
'bca_klikpay' => 'BCA KlikPay',
'bri_epay' => 'BRI e-Pay',
'echannel' => 'Mandiri Bill Payment',
'permata_va' => 'Permata Virtual Account',
'bca_va' => 'BCA Virtual Account',
'bni_va' => 'BNI Virtual Account',
'bri_va' => 'BRI Virtual Account',
'other_va' => 'Virtual Account Bank Lain',
'gopay' => 'GoPay',
'shopeepay' => 'ShopeePay',
'qris' => 'QRIS',
'indomaret' => 'Indomaret',
'alfamart' => 'Alfamart',
'danamon_online' => 'Danamon Online Banking',
'akulaku' => 'Akulaku'
];
return $methods[$this->payment_method] ?? $this->payment_method;
}
}