{{-- Order Type Indicator --}} @if($orderTypeId)
@lang('modules.settings.orderType'): {{ \App\Models\OrderType::find($orderTypeId)?->order_type_name ?? ucfirst($orderType) }} @if($orderTypeSlug === 'delivery' && $selectedDeliveryApp) Platform: @if($selectedDeliveryApp === 'default') Default @else {{ \App\Models\DeliveryPlatform::find($selectedDeliveryApp)?->name ?? 'Unknown' }} @endif @endif
@endif
{{-- Customer info section (shown when customer exists) --}}
{{ $customer->name ?? '' }}
@if(user_can('Update Order')) @endif
{{-- Add customer section (shown when no customer) --}}
@if(!isOrderPrefixEnabled()) @lang('modules.order.orderNumber') #{{ $orderNumber }} @else {{ $formattedOrderNumber }} @endif
@if ($orderType == 'dine_in')
{{-- @if (!auth()->user()->roles->pluck('display_name')->contains('Waiter')) --}}
{{ $tableNo }} @if (user_can('Update Order')) @endif
@lang('modules.order.setTable')
@lang('modules.order.mergeTables') {{-- @endif --}}
@endif
@if ($orderType == 'dine_in')
@lang('modules.order.noOfPax')
@if ($orderNote) @endif
@if ($isWaiterLocked) {{ $waiterName }} @else @foreach ($users as $item) @endforeach @endif
@endif @if ($orderType == 'delivery')
@foreach ($deliveryExecutives as $item) @endforeach
@endif @if(module_enabled('Hotel') && in_array('Hotel', restaurant_modules())) @include('hotel::pos.room-service') @endif @if ($orderType == 'pickup') @php $timeFormat = restaurant()->time_format ?? 'h:i A'; $currentDate = $pickupDate ?? now()->format(restaurant()->date_format); $currentTime = $pickupTime ?? now()->format('H:i'); @endphp
@endif
@forelse ($orderItemList as $key => $item) @php // Initialize variables - START WITH FALSE $isFreeItem = false; $hasStampDiscount = false; $stampDiscountAmount = 0; $originalAmount = 0; $itemFoundInDatabase = false; // CRITICAL: Track if we found item in DB // For existing orders, check both kot_items and order_items tables for stamp data // PRIORITY: Database values ALWAYS override key patterns if (isset($orderID) && $orderID && isset($orderDetail) && $orderDetail) { // Check if this is a KOT item (key format: "kot_{kot_id}_{item_id}") if (strpos($key, 'kot_') !== false) { $keyParts = explode('_', trim($key, '"')); if (count($keyParts) >= 3 && $keyParts[0] === 'kot') { $kotItemId = (int)($keyParts[2] ?? 0); $kotId = (int)($keyParts[1] ?? 0); if ($kotItemId > 0 && $kotId > 0) { try { // Load kot items if not already loaded if (!$orderDetail->relationLoaded('kot')) { $orderDetail->load('kot.items'); } // Find the kot and kot_item $kot = $orderDetail->kot->firstWhere('id', $kotId); if ($kot) { if (!$kot->relationLoaded('items')) { $kot->load('items'); } $kotItem = $kot->items->firstWhere('id', $kotItemId); if ($kotItem) { $itemFoundInDatabase = true; // Found in database // STRICT CHECK: Only true if database value is exactly 1, true, or '1' // Explicitly check for 0, false, null, '0', '' and set to false $dbFreeValue = $kotItem->getAttribute('is_free_item_from_stamp') ?? $kotItem->is_free_item_from_stamp ?? null; // Explicitly check: if value is 0, false, null, '0', or empty string, it's NOT free if ($dbFreeValue === 0 || $dbFreeValue === false || $dbFreeValue === null || $dbFreeValue === '0' || $dbFreeValue === '') { $isFreeItem = false; } else { // Only mark as free if value is exactly 1, true, or '1' $isFreeItem = ($dbFreeValue === 1 || $dbFreeValue === true || $dbFreeValue === '1'); } // Check for discount from stamp in kot_items $discountAmount = (float)($kotItem->getAttribute('discount_amount') ?? $kotItem->discount_amount ?? 0); $isDiscounted = (bool)($kotItem->getAttribute('is_discounted') ?? $kotItem->is_discounted ?? false); $hasStampDiscount = $discountAmount > 0 || $isDiscounted || !is_null($kotItem->stamp_rule_id); // SAFEGUARD: treat item as free only when its amount is actually zero (or nearly zero) $currentAmount = (float)($kotItem->amount ?? 0); if ($isFreeItem && $currentAmount > 0.0001) { $isFreeItem = false; } if ($hasStampDiscount && $discountAmount > 0) { $stampDiscountAmount = $discountAmount; $originalAmount = (float)($kotItem->amount ?? 0) + $discountAmount; } elseif ($isFreeItem) { // For free items, calculate original amount from price $basePrice = (float)($kotItem->getAttribute('price') ?? $kotItem->price ?? 0); $modifierPrice = isset($orderItemModifiersPrice[$key]) ? (float)$orderItemModifiersPrice[$key] : 0; $qty = isset($orderItemQty[$key]) ? (int)$orderItemQty[$key] : 1; $originalAmount = ($basePrice + $modifierPrice) * $qty; } } } } catch (\Exception $e) { // Silently fail if error } } } } // Check if this is an order_item (key format: "order_item_{id}") // Only check if we haven't found it as a KOT item and it's not already marked as free if (!$itemFoundInDatabase && strpos($key, 'order_item_') !== false) { $keyParts = explode('_', trim($key, '"')); if (count($keyParts) >= 3 && $keyParts[0] === 'order' && $keyParts[1] === 'item') { $orderItemId = (int)($keyParts[2] ?? 0); if ($orderItemId > 0) { try { // Load order items if not already loaded if (!$orderDetail->relationLoaded('items')) { $orderDetail->load('items'); } // Find the order_item from the loaded relationship $orderItem = $orderDetail->items->firstWhere('id', $orderItemId); if ($orderItem) { $itemFoundInDatabase = true; // Found in database // STRICT CHECK: Only true if database value is exactly 1, true, or '1' // Explicitly check for 0, false, null, '0', '' and set to false $dbFreeValue = $orderItem->is_free_item_from_stamp ?? null; // Explicitly check: if value is 0, false, null, '0', or empty string, it's NOT free if ($dbFreeValue === 0 || $dbFreeValue === false || $dbFreeValue === null || $dbFreeValue === '0' || $dbFreeValue === '') { $isFreeItem = false; } else { // Only mark as free if value is exactly 1, true, or '1' $isFreeItem = ($dbFreeValue === 1 || $dbFreeValue === true || $dbFreeValue === '1'); } // Check for discount from stamp // Note: order_items table only has 'stamp_rule_id' and 'is_free_item_from_stamp' columns if (!$hasStampDiscount) { $hasStampDiscount = !is_null($orderItem->stamp_rule_id) && !$isFreeItem; } // SAFEGUARD: treat item as free only when its amount is actually zero (or nearly zero) $currentAmount = (float)($orderItem->amount ?? 0); if ($isFreeItem && $currentAmount > 0.0001) { $isFreeItem = false; } // For items with stamp discounts, we can't calculate exact discount per item from order_items // The discount is already deducted from amount field if ($hasStampDiscount && $stampDiscountAmount == 0) { // Try to estimate original amount from price field (if available) $basePrice = $orderItem->price ?? 0; $modifierPrice = isset($orderItemModifiersPrice[$key]) ? $orderItemModifiersPrice[$key] : 0; $qty = $orderItemQty[$key] ?? $orderItem->quantity ?? 1; $estimatedOriginalAmount = ($basePrice + $modifierPrice) * $qty; // If current amount is less than estimated, there's a discount $currentAmount = (float)($orderItem->amount ?? 0); if ($estimatedOriginalAmount > $currentAmount) { $stampDiscountAmount = $estimatedOriginalAmount - $currentAmount; $originalAmount = $estimatedOriginalAmount; } } elseif ($isFreeItem && $originalAmount == 0) { // For free items, calculate original amount from price $basePrice = $orderItem->price ?? 0; $modifierPrice = isset($orderItemModifiersPrice[$key]) ? $orderItemModifiersPrice[$key] : 0; $originalAmount = ($basePrice + $modifierPrice) * ($orderItemQty[$key] ?? 1); } } } catch (\Exception $e) { // Silently fail if error } } } } } // FALLBACK: Only use key pattern or notes if item was NOT found in database // This is ONLY for draft orders or items not yet saved to database // CRITICAL: Only check fallback if we didn't find the item in database // IMPORTANT: If item was found in database, NEVER use fallback - database value is final if (!$itemFoundInDatabase) { // Only check key pattern for draft orders (when orderID might not be set or order is draft) $isDraftOrder = !isset($orderID) || !$orderID || (isset($orderDetail) && $orderDetail && $orderDetail->status === 'draft'); if ($isDraftOrder) { // Only check key pattern if not already set from database // Reset to false first to ensure clean state $isFreeItem = false; $isFreeItem = strpos($key, 'free_stamp_') === 0 || (isset($itemNotes[$key]) && str_contains($itemNotes[$key] ?? '', __('loyalty::app.freeItemFromStamp'))); // SAFEGUARD: for draft items, consider them free only if their current amount is zero (or nearly zero) $draftAmount = (float)($orderItemAmount[$key] ?? 0); if ($isFreeItem && $draftAmount > 0.0001) { $isFreeItem = false; } } else { // For non-draft orders, if item not found in DB, it's definitely NOT free $isFreeItem = false; } } // FINAL SAFEGUARD: If item was found in database, $isFreeItem is already set correctly above - do NOT override // If item was NOT found and it's not a draft order, ensure it's false if ($itemFoundInDatabase && !$isFreeItem) { // Explicitly ensure it stays false - database said it's not free $isFreeItem = false; } @endphp
{{ $item->item_name }} @if ($isFreeItem) @lang('app.freeItem') @elseif($hasStampDiscount) @lang('app.stampDiscount') @if($stampDiscountAmount > 0) (-{{ currency_format($stampDiscountAmount, restaurant()->currency_id) }}) @endif @endif
@if (isset($orderItemVariation[$key]) && $orderItemVariation[$key]) • {{ $orderItemVariation[$key]->variation }} @endif @if (!empty($itemModifiersSelected[$key]))
@foreach ($itemModifiersSelected[$key] as $modifierOptionId)
{{ isset($modifierOptions[$modifierOptionId]) ? $modifierOptions[$modifierOptionId]->name : '' }} {{ isset($modifierOptions[$modifierOptionId]) ? currency_format($modifierOptions[$modifierOptionId]->price, $restaurant->currency_id) : '' }}
@endforeach
@endif
@php // Livewire method leftover guard: compute display price directly for Blade/AJAX POS. // Base price = variation price (if any) else item price; then add modifiers' total price. $basePrice = 0; if (isset($orderItemVariation[$key]) && $orderItemVariation[$key]) { $basePrice = (float) ($orderItemVariation[$key]->price ?? 0); } else { $basePrice = (float) ($item->price ?? 0); } $modifierPrice = (float) ($orderItemModifiersPrice[$key] ?? 0); $displayPrice = $basePrice + $modifierPrice; // Prefer component amount (reflects live qty changes); fallback to DB if not available $totalAmount = $orderItemAmount[$key] ?? (isset($orderItem) && $orderItem ? (float)($orderItem->amount ?? 0) : 0); @endphp
@if ($isFreeItem)
{{ currency_format(0, restaurant()->currency_id) }}
@if($originalAmount > 0)
{{ currency_format($originalAmount, restaurant()->currency_id) }}
@endif
@elseif($hasStampDiscount)
{{ currency_format($totalAmount, restaurant()->currency_id) }}
@if($originalAmount > 0 && $originalAmount > $totalAmount)
{{ currency_format($originalAmount, restaurant()->currency_id) }}
@endif
@else
{{ currency_format($displayPrice, restaurant()->currency_id) }}
{{ currency_format($totalAmount, restaurant()->currency_id) }}
@endif
@if (!$isFreeItem)
@else
@lang('app.qty') {{ $orderItemQty[$key] ?? 1 }}
@endif {{-- Item Note Button/Display --}}
@if(isset($itemNotes[$key]) && !empty($itemNotes[$key])) {{-- Show note preview when note exists --}} @else {{-- Show "Add Note" button when no note exists --}} @endif
@empty
@lang('messages.noItemAdded')
@endforelse
@if (user_can('Add Discount on POS'))
@lang('modules.order.addDiscount')
@endif
@lang('modules.order.totalItem')
{{ count($orderItemList) }}
@lang('modules.order.subTotal') @php // Get stamp discount amount from component property or order detail $displayStampDiscountAmount = (float)($stampDiscountAmount ?? 0); $hasFreeStampItems = false; $isOrderPlaced = false; // Check if order is placed (not draft) if ($orderID && $orderDetail) { $isOrderPlaced = $orderDetail->status !== 'draft'; // For existing orders, use orderDetail $displayStampDiscountAmount = (float)($orderDetail->stamp_discount_amount ?? $displayStampDiscountAmount); $hasFreeStampItems = $orderDetail->items()->where('is_free_item_from_stamp', true)->exists(); } elseif ($orderID) { // Load order if orderID exists but orderDetail doesn't try { $order = \App\Models\Order::find($orderID); if ($order) { $displayStampDiscountAmount = (float)($order->stamp_discount_amount ?? $displayStampDiscountAmount); $hasFreeStampItems = $order->items()->where('is_free_item_from_stamp', true)->exists(); } } catch (\Exception $e) { // Silently fail } } else { // For new orders, detect free stamp items by key, payload flag, or note token. foreach ($orderItemList as $key => $item) { $note = $itemNotes[$key] ?? ''; $rawFreeFlag = is_array($item) ? ($item['is_free_item_from_stamp'] ?? false) : ($item->is_free_item_from_stamp ?? false); $isFlaggedFree = in_array($rawFreeFlag, [true, 1, '1', 'true'], true); if ( str_starts_with((string)$key, 'free_stamp_') || $isFlaggedFree || str_contains((string)$note, __('loyalty::app.freeItemFromStamp')) || str_starts_with(strtolower(trim((string)$note)), 'free') ) { $hasFreeStampItems = true; break; } } } @endphp @lang('app.stampDiscount') @if($displayStampDiscountAmount > 0) (-{{ currency_format($displayStampDiscountAmount, $restaurant->currency_id) }}) @elseif($hasFreeStampItems) (@lang('app.freeItem')) @endif
{{ currency_format($subTotal, $restaurant->currency_id) }}
@if(function_exists('module_enabled') && module_enabled('Loyalty')) @php // On the dedicated New KOT page, when there are no new KOT items yet, // the loyalty section should start from 0 (do not show main order points). $isNewKotPage = isset($orderDetail) && $orderDetail && $orderDetail->status === 'kot' && request()->routeIs('pos.kot'); $hasNewKotItems = isset($orderItemList) && count($orderItemList) > 0; $loyaltyPointsForDisplay = ($isNewKotPage && !$hasNewKotItems) ? 0 : ($loyaltyPointsRedeemed ?? 0); $loyaltyDiscountForDisplay = ($isNewKotPage && !$hasNewKotItems) ? 0.0 : ($loyaltyDiscountAmount ?? 0.0); @endphp
@include('loyalty::components.loyalty-discount-display', [ 'loyaltyPointsRedeemed' => $loyaltyPointsForDisplay, 'loyaltyDiscountAmount' => $loyaltyDiscountForDisplay, 'currencyId' => $restaurant->currency_id, 'showEditIcon' => true, 'customer' => $customer ?? null ])
{{-- JS-updatable row (shown when loyalty applied in session; updated by updateTotalsDisplay) --}} @endif
@lang('modules.order.discount') @if ($discountType == 'percent') ({{ $discountValue }}%) @endif @if(user_can('Add Discount on POS') && user_can('Update Order')) @endif
-{{ currency_format($discountAmount, $restaurant->currency_id) }}
@if ($orderType === 'delivery')
@lang('modules.delivery.deliveryFee') @if($deliveryFee == 0) (@lang('modules.delivery.freeDelivery')) @endif
@endif
@if (count($orderItemList) > 0 && $extraCharges) @foreach ($extraCharges as $charge)
{{ $charge->charge_name }} @if ($charge->charge_type == 'percent') ({{ $charge->charge_value }}%) @endif @if (user_can('Update Order')) @endif
{{ currency_format($charge->getAmount($discountedTotal), $restaurant->currency_id) }}
@endforeach @elseif($orderID && count($orderItemList) > 0 && $extraCharges) @foreach ($extraCharges as $newKotCharge)
{{ $newKotCharge->charge_name }} @if ($newKotCharge->charge_type == 'percent') ({{ $newKotCharge->charge_value }}%) @endif
{{ currency_format($newKotCharge->getAmount($discountedTotal), $restaurant->currency_id) }}
@endforeach @endif
@if ($taxMode == 'order')
@foreach ($taxes as $item)
{{ $item->tax_name }} ({{ $item->tax_percent }}%)
{{ currency_format(($item->tax_percent / 100) * $taxBase, $restaurant->currency_id) }}
@endforeach
@else
@php // Show item-wise tax breakdown above total tax $taxTotals = []; $isInclusive = $restaurant->tax_inclusive ?? false; foreach ($orderItemTaxDetails as $item) { $qty = $item['qty'] ?? 1; if (!empty($item['tax_breakup'])) { foreach ($item['tax_breakup'] as $taxName => $taxInfo) { if (!isset($taxTotals[$taxName])) { $taxTotals[$taxName] = [ 'percent' => $taxInfo['percent'], 'amount' => 0, ]; } $taxTotals[$taxName]['amount'] += $taxInfo['amount'] * $qty; } } } @endphp @if (!empty($taxTotals)) @foreach ($taxTotals as $taxName => $taxInfo)
{{ $taxName }} ({{ $taxInfo['percent'] }}%)
{{ currency_format($taxInfo['amount'], $restaurant->currency_id) }}
@endforeach
@lang('modules.order.totalTax') @if ($isInclusive) (@lang('modules.settings.taxInclusive')) @else (@lang('modules.settings.taxExclusive')) @endif
{{ currency_format($totalTaxAmount, $restaurant->currency_id) }}
@endif
@endif
@lang('modules.order.total')
{{ currency_format($total, $restaurant->currency_id) }}
@php $isNewKotPage = $orderDetail && $orderDetail->status === 'kot' && !request()->boolean('show-order-detail'); @endphp @if ((!$orderID || ($orderID && $orderDetail && $orderDetail->status !== 'draft')) && !$isNewKotPage)
@endif @if (in_array('KOT', restaurant_modules()))
@endif @if (!$orderID || ($orderID && $orderDetail && $orderDetail->status == 'draft'))
@endif