get('startTime'); $endTime = $request->get('endTime'); if ($startTime && $endTime) { $timeZone = DateTimeHelper::getTimeZone(); $startTime = DateTimeHelper::convertToUtc($startTime, $timeZone); $endTime = DateTimeHelper::convertToUtc($endTime, $timeZone); $bookingWidgetNumbers = $this->getBookingWidgetNumbers($startTime, $endTime); } else { $startTime = gmdate('Y-m-d H:i:s', strtotime('-30 days')); // phpcs:ignore WordPress.DateTime.RestrictedFunctions.date_date $endTime = gmdate('Y-m-d H:i:s', strtotime('now UTC')); // phpcs:ignore WordPress.DateTime.RestrictedFunctions.date_date $bookingWidgetNumbers = $this->getAllBookingWidgetNumbers(); } $bookingWidgetStats = $this->getBookingWidgetStats($startTime, $endTime); $paymentWidget = $this->getPaymentWidgets($startTime, $endTime); $widgets = [ [ 'title' => __('Total Bookings', 'fluent-booking'), 'period' => 'all', 'number' => $bookingWidgetNumbers['totalBooked'], 'content' => $bookingWidgetStats['bookedComparison'], 'icon' => ' ', 'stat' => $bookingWidgetStats['bookedStat'] ], [ 'title' => __('Completed Bookings', 'fluent-booking'), 'period' => 'completed', 'number' => $bookingWidgetNumbers['bookingCompleted'], 'content' => $bookingWidgetStats['completedComparison'], 'icon' => ' ', 'stat' => $bookingWidgetStats['completedStat'] ] ]; $totalPaymentWidget = apply_filters('fluent_booking/total_payment_widget', [], $paymentWidget); $widgets[] = $totalPaymentWidget ?: [ 'title' => __('Cancelled Bookings', 'fluent-booking'), 'period' => 'cancelled', 'number' => $bookingWidgetNumbers['bookingCancelled'], 'content' => $bookingWidgetStats['cancelledComparison'], 'icon' => ' ', 'stat' => $bookingWidgetStats['cancelledStat'] ]; $widgets[] = [ 'title' => __('Total Guests', 'fluent-booking'), 'number' => $bookingWidgetNumbers['totalGuests'], 'content' => $bookingWidgetStats['guestComparison'], 'icon' => ' ', 'stat' => $bookingWidgetStats['guestStat'] ]; apply_filters('fluent_booking/dashboard_widgets', $widgets); return [ 'overview' => $widgets, 'latest_books' => $this->getLatestBooks(), 'next_meetings' => $this->getNextMeetings() ]; } /** * @return array */ public function getGraphReports(Request $request) { list($startDate, $endDate) = $request->get('date_range') ?: ['', '']; $period = $this->makeDatePeriod( $from = $this->makeFromDate($startDate), $to = $this->makeToDate($endDate), $frequency = $this->getFrequency($from, $to) ); list($groupBy, $orderBy) = $this->getGroupAndOrder($frequency); // Define a function to fetch booking data based on status $fetchBookingsByStatus = function ($status) use ($period, $groupBy, $orderBy, $frequency, $from, $to) { if (!PermissionManager::userCanSeeAllBookings()) { return Booking::select($this->prepareSelect($frequency)) ->where('status', $status) ->whereBetween('created_at', [$from->format('Y-m-d'), $to->format('Y-m-d')]) ->where('host_user_id', get_current_user_id()) ->groupBy($groupBy) ->orderBy($orderBy, 'ASC') ->get(); } return Booking::select($this->prepareSelect($frequency)) ->where('status', $status) ->whereBetween('created_at', [$from->format('Y-m-d'), $to->format('Y-m-d')]) ->groupBy($groupBy) ->orderBy($orderBy, 'ASC') ->get(); }; // Fetch bookings for different statuses $totalBooked = $fetchBookingsByStatus('scheduled'); $totalCompleted = $fetchBookingsByStatus('completed'); $totalCancelled = $fetchBookingsByStatus('cancelled'); return [ 'booked_stats' => $this->getResult($period, $totalBooked), 'completed_stats' => $this->getResult($period, $totalCompleted), 'cancelled_stats' => $this->getResult($period, $totalCancelled) ]; } private function getBookingWidgetStats($startTime, $endTime) { $startTimeStamp = strtotime($startTime); $endTimeStamp = strtotime($endTime); $differenceInDays = ($endTimeStamp - $startTimeStamp) / (60 * 60 * 24); $lastMonthStartTime = gmdate('Y-m-d H:i:s', strtotime("$startTime - $differenceInDays days")); // phpcs:ignore WordPress.DateTime.RestrictedFunctions.date_date $bookingStats = $this->getBookingStats($startTime, $endTime, $lastMonthStartTime, $startTime); $bookingStats['bookedComparison'] = $this->getComparisonMessage($bookingStats['bookedStat']); $bookingStats['completedComparison'] = $this->getComparisonMessage($bookingStats['completedStat']); $bookingStats['cancelledComparison'] = $this->getComparisonMessage($bookingStats['cancelledStat']); $bookingStats['guestComparison'] = $this->getComparisonMessage($bookingStats['guestStat']); return $bookingStats; } private function getBookingStats($currentMonthStart, $currentMonthEnd, $lastMonthStart, $lastMonthEnd) { // Get booking query by created_at and end_time $currentMonthBookings = Booking::whereBetween('created_at', [$currentMonthStart, $currentMonthEnd])->get(); $lastMonthBookings = Booking::whereBetween('created_at', [$lastMonthStart, $lastMonthEnd])->get(); $currentMonthStartBookings = Booking::whereBetween('end_time', [$currentMonthStart, $currentMonthEnd])->get(); $lastMonthStartBookings = Booking::whereBetween('end_time', [$lastMonthStart, $lastMonthEnd])->get(); // Calculate bookings and guests based on 'created_at' $totalBookedCurrentMonth = $currentMonthBookings->count(); $totalBookedLastMonth = $lastMonthBookings->count(); $totalGuestsCurrentMonth = $currentMonthBookings->pluck('email')->unique()->count(); $totalGuestsLastMonth = $lastMonthBookings->pluck('email')->unique()->count(); // Calculate completed and cancelled based on 'end_time' $bookingCompletedCurrentMonth = $currentMonthStartBookings->where('status', 'completed')->count(); $bookingCompletedLastMonth = $lastMonthStartBookings->where('status', 'completed')->count(); $bookingCancelledCurrentMonth = $lastMonthStartBookings->where('status', 'cancelled')->count(); $bookingCancelledLastMonth = $currentMonthStartBookings->where('status', 'cancelled')->count(); $bookingStats['bookedStat'] = $this->getPercentage($totalBookedCurrentMonth, $totalBookedLastMonth); $bookingStats['completedStat'] = $this->getPercentage($bookingCompletedCurrentMonth, $bookingCompletedLastMonth); $bookingStats['cancelledStat'] = $this->getPercentage($bookingCancelledCurrentMonth, $bookingCancelledLastMonth); $bookingStats['guestStat'] = $this->getPercentage($totalGuestsCurrentMonth, $totalGuestsLastMonth); return $bookingStats; } private function getPercentage($currentMonthTotal, $lastMonthTotal) { if ($lastMonthTotal > 0) { return round((($currentMonthTotal - $lastMonthTotal) / $lastMonthTotal) * 100, 2); } else if (!$lastMonthTotal) { return 100; } return 0; } private function getBookingWidgetNumbers($startTime, $endTime) { $statusQuery = Booking::whereBetween('end_time', [$startTime, $endTime])->get(); $bookedQuery = Booking::whereBetween('created_at', [$startTime, $endTime])->get(); $totalBooked = $bookedQuery->count(); $totalGuests = $bookedQuery->pluck('email')->unique()->count(); $bookingCompleted = $statusQuery->where('status', 'completed')->count(); $bookingCancelled = $statusQuery->where('status', 'cancelled')->count(); return [ 'totalBooked' => $totalBooked, 'totalGuests' => $totalGuests, 'bookingCompleted' => $bookingCompleted, 'bookingCancelled' => $bookingCancelled ]; } private function getAllBookingWidgetNumbers() { $permissionAccess = PermissionManager::userCan(['read_all_bookings', 'manage_all_bookings', 'read_other_calendars', 'manage_other_calendars']); if ($permissionAccess) { $totalBooked = Booking::count(); $bookingCompleted = Booking::where('status', 'completed')->count(); $bookingCancelled = Booking::where('status', 'cancelled')->count(); $totalGuests = Booking::distinct()->count('email'); } else { $totalBooked = Booking::where('host_user_id', get_current_user_id())->count(); $bookingCompleted = Booking::where('status', 'completed')->where('host_user_id', get_current_user_id())->count(); $bookingCancelled = Booking::where('status', 'cancelled')->where('host_user_id', get_current_user_id())->count(); $totalGuests = Booking::distinct()->where('host_user_id', get_current_user_id())->count('email'); } return [ 'totalBooked' => $totalBooked, 'totalGuests' => $totalGuests, 'bookingCompleted' => $bookingCompleted, 'bookingCancelled' => $bookingCancelled ]; } private function getComparisonMessage($change) { if ($change > 0) { return __('More than last month', 'fluent-booking'); } if ($change < 0) { return __('Less than last month', 'fluent-booking'); } return __('Same as last month', 'fluent-booking'); } private function getPaymentWidgets($startTime, $endTime) { if (!defined('FLUENT_BOOKING_PRO_DIR_FILE')) { return []; } $stripSettings = get_option('fluent_booking_payment_settings_stripe'); $isActive = Arr::get($stripSettings, 'is_active'); if ($isActive == 'no') { return []; } $startTimeStamp = strtotime($startTime); $endTimeStamp = strtotime($endTime); $differenceInDays = ($endTimeStamp - $startTimeStamp) / (60 * 60 * 24); $lastMonthStartTime = gmdate('Y-m-d H:i:s', strtotime("$startTime - $differenceInDays days")); // phpcs:ignore WordPress.DateTime.RestrictedFunctions.date_date $current_user_email = null; $cantSeeTotal = PermissionManager::userCan(['read_all_bookings', 'manage_all_bookings', 'read_other_calendars', 'manage_other_calendars']); if (!$cantSeeTotal) { $current_user_email = wp_get_current_user()->user_email; } $currentMonthTotal = \FluentBookingPro\App\Models\Order::where('status', 'paid') ->whereBetween('created_at', [$startTime, $endTime]) ->when($current_user_email, function ($query, $email) { return $query->whereHas('booking', function ($query) use ($email) { $query->where('email', $email); }); }) ->selectRaw('SUM(total_amount / 100) as total') ->first() ->total; $lastMonthTotal = \FluentBookingPro\App\Models\Order::where('status', 'paid') ->whereBetween('created_at', [$lastMonthStartTime, $startTime]) ->when($current_user_email, function ($query, $email) { return $query->whereHas('booking', function ($query) use ($email) { $query->where('email', $email); }); }) ->selectRaw('SUM(total_amount / 100) as total') ->first() ->total; $paymentPercentage = $this->getPercentage($currentMonthTotal, $lastMonthTotal); $paymentComparison = $this->getComparisonMessage($paymentPercentage); $paymentStats['totalPayment'] = intval($currentMonthTotal); $paymentStats['paymentComparison'] = $paymentComparison; $paymentStats['paymentStat'] = $paymentPercentage; return $paymentStats; } public function getNextMeetings() { $bookingQuery = Booking::with(['slot']) ->where('status', 'scheduled') ->orderBy('start_time', 'ASC') ->upcoming(); if (!PermissionManager::userCanSeeAllBookings()) { $bookingQuery->whereHas('calendar', function ($q) { $q->where('user_id', get_current_user_id()); }); } $nextMeetings = $bookingQuery->groupBy('group_id')->latest()->take(5)->get(); foreach ($nextMeetings as $meeting) { if (!$meeting->slot) { $meeting->author = [ 'name' => 'unknown' ]; $meeting->slot = (object)[]; } else { $meeting->author = $meeting->slot->getAuthorProfile(false); } $meeting->title = $meeting->getBookingTitle(true); if ($meeting->isMultiGuestBooking()) { $meeting->booked_count = Booking::where('group_id', $meeting->group_id) ->whereIn('status', ['scheduled', 'completed'])->count(); } } return $nextMeetings; } public function getLatestBooks() { $bookingQuery = Booking::whereIn('status', ['pending', 'scheduled', 'completed']); if (!PermissionManager::userCanSeeAllBookings()) { $bookingQuery->whereHas('calendar', function ($q) { $q->where('user_id', get_current_user_id()); }); } return $bookingQuery->latest()->take(5)->get(); } public function getActivities() { $activityQuery = BookingActivity::query(); if (!PermissionManager::userCanSeeAllBookings()) { $activityQuery->whereHas('booking.calendar', function ($q) { $q->where('user_id', get_current_user_id()); }); } $activities = $activityQuery->latest()->take(100)->get(); return [ 'activities' => $activities ]; } }