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)
{
$scopeByUser = !PermissionManager::userCanSeeAllBookings();
$scopeToUser = function ($query) {
$query->whereHas('hosts', function ($hostQuery) {
$hostQuery->where('user_id', get_current_user_id());
});
};
$createdBetween = function ($start, $end) use ($scopeByUser, $scopeToUser) {
return Booking::whereBetween('created_at', [$start, $end])
->when($scopeByUser, $scopeToUser);
};
$endTimeBetween = function ($start, $end) use ($scopeByUser, $scopeToUser) {
return Booking::whereBetween('end_time', [$start, $end])
->when($scopeByUser, $scopeToUser);
};
// Bookings and guests based on 'created_at'
$totalBookedCurrentMonth = $createdBetween($currentMonthStart, $currentMonthEnd)->count();
$totalBookedLastMonth = $createdBetween($lastMonthStart, $lastMonthEnd)->count();
$totalGuestsCurrentMonth = $createdBetween($currentMonthStart, $currentMonthEnd)->distinct()->count('email');
$totalGuestsLastMonth = $createdBetween($lastMonthStart, $lastMonthEnd)->distinct()->count('email');
// Completed and cancelled based on 'end_time'
$bookingCompletedCurrentMonth = $endTimeBetween($currentMonthStart, $currentMonthEnd)->where('status', 'completed')->count();
$bookingCompletedLastMonth = $endTimeBetween($lastMonthStart, $lastMonthEnd)->where('status', 'completed')->count();
$bookingCancelledCurrentMonth = $endTimeBetween($currentMonthStart, $currentMonthEnd)->where('status', 'cancelled')->count();
$bookingCancelledLastMonth = $endTimeBetween($lastMonthStart, $lastMonthEnd)->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)
{
$scopeByUser = !PermissionManager::userCanSeeAllBookings();
$scopeToUser = function ($query) {
$query->whereHas('hosts', function ($hostQuery) {
$hostQuery->where('user_id', get_current_user_id());
});
};
$createdBetween = function () use ($startTime, $endTime, $scopeByUser, $scopeToUser) {
return Booking::whereBetween('created_at', [$startTime, $endTime])
->when($scopeByUser, $scopeToUser);
};
$endTimeBetween = function () use ($startTime, $endTime, $scopeByUser, $scopeToUser) {
return Booking::whereBetween('end_time', [$startTime, $endTime])
->when($scopeByUser, $scopeToUser);
};
$totalBooked = $createdBetween()->count();
$totalGuests = $createdBetween()->distinct()->count('email');
$bookingCompleted = $endTimeBetween()->where('status', 'completed')->count();
$bookingCancelled = $endTimeBetween()->where('status', 'cancelled')->count();
return [
'totalBooked' => $totalBooked,
'totalGuests' => $totalGuests,
'bookingCompleted' => $bookingCompleted,
'bookingCancelled' => $bookingCancelled
];
}
private function getAllBookingWidgetNumbers()
{
$scopeByUser = !PermissionManager::userCanSeeAllBookings();
$userId = get_current_user_id();
$totalBooked = Booking::when($scopeByUser, function($q) use ($userId) {
$q->whereHas('hosts', function ($hostQuery) use ($userId) {
$hostQuery->where('user_id', $userId);
});
})->count();
$bookingCompleted = Booking::where('status', 'completed')
->when($scopeByUser, function($q) use ($userId) {
$q->whereHas('hosts', function ($hostQuery) use ($userId) {
$hostQuery->where('user_id', $userId);
});
})->count();
$bookingCancelled = Booking::where('status', 'cancelled')
->when($scopeByUser, function($q) use ($userId) {
$q->whereHas('hosts', function ($hostQuery) use ($userId) {
$hostQuery->where('user_id', $userId);
});
})->count();
$totalGuests = Booking::distinct()
->when($scopeByUser, function($q) use ($userId) {
$q->whereHas('hosts', function ($hostQuery) use ($userId) {
$hostQuery->where('user_id', $userId);
});
})->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(['manage_all_data', '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')
->upcoming()
->orderBy('start_time', 'ASC');
if (!PermissionManager::userCanSeeAllBookings()) {
$bookingQuery->whereHas('calendar', function ($q) {
$q->where('user_id', get_current_user_id());
});
}
$nextMeetings = $bookingQuery->limit(50)->get()
->unique('group_id')
->take(5)
->values();
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
];
}
}