@include('Partials.sidebar')
@include('Partials.header')

Booking Report

  1. Reports
  2. Bookings
{{-- Filter bar --}}
@if($from || $to) Showing {{ $totals['total'] }} of {{ $allTimeCount }} total bookings @if($totals['total'] < $allTimeCount)  — clear filter to see all @endif @else Showing all {{ $allTimeCount }} bookings (no date filter) @endif
{{-- KPI Cards --}}
@foreach([ ['Total', $totals['total'], '#64748b','fa-list'], ['Confirmed', $totals['confirmed'], '#22c55e','fa-check-circle'], ['Pending', $totals['pending'], '#f59e0b','fa-clock'], ['Cancelled', $totals['cancelled'], '#ef4444','fa-times-circle'], ['Total Value', $currency.$totals['value'], '#c9a96e','fa-rupee-sign'], ['Collected', $currency.$totals['collected'], '#3b82f6','fa-wallet'], ] as [$label,$val,$color,$icon])
{{ $label }}
{{ $val }}
@endforeach
{{-- By plot type --}}
🏠 Confirmed by Plot Type
@if($byType->isNotEmpty())
@foreach($byType as $t)
{{ $t->plot_type ?: 'Unknown' }} {{ $t->count }} • {{ $currency }}{{ $t->value }}
@endforeach
@else
No confirmed bookings in this range.
@endif
{{-- Status donut --}}
📊 Status Breakdown
{{-- Daily trend --}}
📅 Daily Trend
@if(count($dailyTrend) > 0) @else
No data for selected range.
@endif
{{-- Bookings list --}}
All Bookings ({{ $bookingsList->total() }})
@forelse($bookingsList as $b) @php $statusColors = [ 'confirmed' => 'success', 'pending' => 'warning', 'cancelled' => 'danger', ]; $sc = $statusColors[$b->booking_status] ?? 'secondary'; $txn = $b->transactions->first(); $isInstant = $txn && in_array($txn->mode, ['cash', 'manual']); $isOnline = $txn && $txn->mode === 'online'; // ── FIX: Calculate paid/balance from booking_milestones ── $hasMilestones = $b->milestones->isNotEmpty(); $paidMilestones = $b->milestones->where('status', 'paid'); $paidAmt = $paidMilestones->sum('total_with_tax'); $totalAmt = (float) $b->total_amount; // If no milestone data, fall back to transaction amount or down_payment_amount if (!$hasMilestones || $paidAmt == 0) { $paidAmt = $txn?->total_with_tax ?? (float) $b->down_payment_amount; } $balanceAmt = max(0, $totalAmt - $paidAmt); $isFullyPaid = $hasMilestones && $b->milestones->where('status', '!=', 'paid')->where('status', '!=', 'waived')->isEmpty(); @endphp {{-- Payment Plan + Milestone Progress --}} {{-- FIX: Paid column now uses milestone paid sum --}} {{-- Balance due --}} @empty @endforelse
# Date Client Unit Type Source / Payment Payment Plan Booking Status Total Amount Paid Balance
#{{ $b->id }} {{ $b->created_at->format('d M Y') }}
{{ $b->created_at->format('H:i') }}
{{ $b->client_name ?: $b->user?->name ?: '—' }}
{{ $b->client_phone ?: $b->user?->phone }}
Unit {{ $b->plot_number }} {{ $b->plot_type }} @if($isInstant) Walk-in
{{ ucfirst($txn->mode) }} @if($txn->gateway && !in_array($txn->gateway,['cash','manual'])) • {{ ucfirst($txn->gateway) }} @endif
@elseif($isOnline) {{ ucfirst($txn->gateway) }}
Online
@elseif($b->gateway_order_id) Gateway ref
{{ Str::limit($b->gateway_order_id, 20) }}
@else — No payment yet @endif
@if($b->paymentPlan) {{ $b->paymentPlan->name }} @if($hasMilestones)
@php $total_ms = $b->milestones->count(); $paid_ms = $paidMilestones->count(); $pct = $total_ms > 0 ? ($paid_ms / $total_ms) * 100 : 0; $overdue_ms = $b->milestones->where('status','overdue')->count(); @endphp {{-- Progress bar --}}
{{ $paid_ms }}/{{ $total_ms }} paid @if($overdue_ms > 0) • {{ $overdue_ms }} overdue @endif
{{-- Milestone rows (collapsible via toggle) --}}
@endif @else Full payment @endif
{{ ucfirst($b->booking_status) }} {{ $currency }}{{ $b->total_amount }} @if($paidAmt > 0) {{ $currency }}{{ $paidAmt }} @if($isFullyPaid)
✓ Fully paid
@elseif($hasMilestones && $paidMilestones->count() > 0)
{{ $paidMilestones->count() }} milestone{{ $paidMilestones->count() > 1 ? 's' : '' }}
@endif @if($txn?->paid_at)
{{ $txn->paid_at->format('d M Y') }}
@endif @else @endif
@if($b->booking_status === 'confirmed' && $balanceAmt > 0) {{ $currency }}{{ $balanceAmt }} @php $nextDue = $b->milestones->whereIn('status', ['pending','overdue'])->first(); @endphp @if($nextDue?->due_date)
{{ $nextDue->status === 'overdue' ? '⚠ ' : '' }}Due {{ \Carbon\Carbon::parse($nextDue->due_date)->format('d M') }}
@endif @elseif($b->booking_status === 'confirmed' && $balanceAmt <= 0 && $paidAmt > 0) ✓ Clear @else @endif
No bookings found. @if($from || $to)
Clear date filter to see all bookings @endif
@if($bookingsList->hasPages()) @endif
@include('Partials.footer')