PluginProbe ʕ •ᴥ•ʔ
LatePoint – Calendar Booking Plugin for Appointments and Events / trunk
LatePoint – Calendar Booking Plugin for Appointments and Events vtrunk
5.6.5 5.6.4 5.6.3 5.6.2 5.6.1 5.6.0 5.5.2 5.5.1 5.5.0 5.4.2 trunk 5.1.0 5.1.1 5.1.2 5.1.3 5.1.4 5.1.5 5.1.6 5.1.7 5.1.8 5.1.9 5.1.91 5.1.92 5.1.93 5.1.94 5.2.0 5.2.1 5.2.10 5.2.11 5.2.2 5.2.3 5.2.4 5.2.5 5.2.6 5.2.7 5.2.8 5.2.9 5.3.0 5.3.1 5.3.2 5.4.0 5.4.1
latepoint / lib / controllers / dashboard_controller.php
latepoint / lib / controllers Last commit date
activities_controller.php 1 month ago auth_controller.php 3 months ago booking_form_settings_controller.php 3 months ago bookings_controller.php 14 hours ago calendars_controller.php 3 months ago carts_controller.php 14 hours ago controller.php 3 months ago customer_cabinet_controller.php 2 months ago customers_controller.php 14 hours ago dashboard_controller.php 2 months ago default_agent_controller.php 3 months ago events_controller.php 3 months ago form_fields_controller.php 1 week ago integrations_controller.php 3 months ago invoices_controller.php 14 hours ago manage_booking_by_key_controller.php 3 months ago manage_order_by_key_controller.php 3 months ago notifications_controller.php 3 months ago orders_controller.php 14 hours ago pro_controller.php 2 weeks ago process_jobs_controller.php 3 months ago processes_controller.php 1 month ago razorpay_connect_controller.php 1 week ago search_controller.php 3 months ago services_controller.php 3 months ago settings_controller.php 2 months ago steps_controller.php 2 weeks ago stripe_connect_controller.php 1 week ago support_topics_controller.php 3 months ago todos_controller.php 3 months ago transactions_controller.php 14 hours ago wizard_controller.php 1 week ago
dashboard_controller.php
318 lines
1 <?php
2 if ( ! defined( 'ABSPATH' ) ) {
3 exit; // Exit if accessed directly.
4 }
5
6
7 if ( ! class_exists( 'OsDashboardController' ) ) :
8
9
10 class OsDashboardController extends OsController {
11
12 private $booking;
13
14
15 function __construct() {
16 parent::__construct();
17
18 $this->views_folder = LATEPOINT_VIEWS_ABSPATH . 'dashboard/';
19 $this->vars['page_header'] = __( 'Dashboard', 'latepoint' );
20 }
21
22
23 public function pro_agents() {
24 }
25
26 /*
27 Index
28 */
29
30 public function index() {
31 $this->vars['page_header'] = false;
32
33 ob_start();
34 $this->widget_bookings_and_availability_timeline();
35 $this->vars['widget_bookings_and_availability_timeline'] = ob_get_clean();
36
37 ob_start();
38 $this->widget_daily_bookings_chart();
39 $this->vars['widget_daily_bookings_chart'] = ob_get_clean();
40
41 ob_start();
42 $this->widget_upcoming_appointments( 3 );
43 $this->vars['widget_upcoming_appointments'] = ob_get_clean();
44
45 $this->set_layout( 'admin' );
46 $this->format_render( __FUNCTION__ );
47 }
48
49 public function widget_upcoming_appointments( $limit = 3 ) {
50 $agents = new OsAgentModel();
51 $services = new OsServiceModel();
52 $bookings = new OsBookingModel();
53 $locations = new OsLocationModel();
54
55 $selected_agent_id = isset( $this->params['agent_id'] ) ? OsAuthHelper::get_current_user()->check_if_allowed_record_id( $this->params['agent_id'], 'agent' ) : false;
56 $selected_service_id = isset( $this->params['service_id'] ) ? OsAuthHelper::get_current_user()->check_if_allowed_record_id( $this->params['service_id'], 'service' ) : false;
57 $selected_location_id = isset( $this->params['location_id'] ) ? OsAuthHelper::get_current_user()->check_if_allowed_record_id( $this->params['location_id'], 'location' ) : false;
58
59 $this->vars['upcoming_bookings'] = $bookings->get_upcoming_bookings( $selected_agent_id, false, $selected_service_id, $selected_location_id, $limit );
60
61 $this->vars['agents'] = $agents->should_be_active()->filter_allowed_records()->get_results_as_models();
62 $this->vars['services'] = $services->should_be_active()->filter_allowed_records()->get_results_as_models();
63 $this->vars['locations'] = $locations->should_be_active()->filter_allowed_records()->get_results_as_models();
64
65 $this->vars['selected_agent_id'] = $selected_agent_id;
66 $this->vars['selected_service_id'] = $selected_service_id;
67 $this->vars['selected_location_id'] = $selected_location_id;
68
69
70 $this->set_layout( 'none' );
71 $this->format_render( __FUNCTION__ );
72 }
73
74
75
76 public function widget_daily_bookings_chart( $date_from = false, $date_to = false ) {
77 if ( $date_from == false ) {
78 $date_from = isset( $this->params['date_from'] ) ? OsWpDateTime::os_createFromFormat( 'Y-m-d', $this->params['date_from'] ) : new OsWpDateTime( '-1 week' );
79 }
80 if ( $date_to == false ) {
81 $date_to = isset( $this->params['date_to'] ) ? OsWpDateTime::os_createFromFormat( 'Y-m-d', $this->params['date_to'] ) : new OsWpDateTime( 'now' );
82 }
83
84
85 $filter = new \LatePoint\Misc\Filter();
86 $filter = OsRolesHelper::filter_allowed_records_from_arguments_or_filter( $filter );
87
88 if ( ! empty( $this->params['agent_id'] ) ) {
89 $filter->agent_id = $this->params['agent_id'];
90 }
91 if ( ! empty( $this->params['service_id'] ) ) {
92 $filter->service_id = $this->params['service_id'];
93 }
94 if ( ! empty( $this->params['location_id'] ) ) {
95 $filter->location_id = $this->params['location_id'];
96 }
97
98 if ( ! OsRolesHelper::are_all_records_allowed() ) {
99 if ( ! OsRolesHelper::are_all_records_allowed( 'agent' ) ) {
100 $agent_id = OsRolesHelper::get_allowed_records( 'agent' );
101 }
102 }
103
104
105
106 $daily_bookings = OsBookingHelper::get_total_bookings_per_day_for_period( $date_from->format( 'Y-m-d' ), $date_to->format( 'Y-m-d' ), $filter );
107
108 $daily_chart_data = [];
109 // fill data array with all the days
110 for ( $day_date = clone $date_from; $day_date <= $date_to; $day_date->modify( '+1 day' ) ) {
111 $daily_chart_data[ OsTimeHelper::get_nice_date_with_optional_year( $day_date->format( 'Y-m-d' ), false, true ) ] = 0;
112 }
113 // update the days with count of bookings
114 foreach ( $daily_bookings as $bookings_for_day ) {
115 $daily_chart_data[ OsTimeHelper::get_nice_date_with_optional_year( gmdate( 'Y-m-d', strtotime( $bookings_for_day->start_date ) ), false, true ) ] = $bookings_for_day->bookings_per_day;
116 }
117
118 $this->vars['total_bookings'] = OsBookingHelper::get_stat_for_period( 'bookings', $date_from->format( 'Y-m-d' ), $date_to->format( 'Y-m-d' ), $filter );
119 $this->vars['total_price'] = OsBookingHelper::get_stat_for_period( 'price', $date_from->format( 'Y-m-d' ), $date_to->format( 'Y-m-d' ), $filter );
120 $this->vars['total_duration'] = OsBookingHelper::get_stat_for_period( 'duration', $date_from->format( 'Y-m-d' ), $date_to->format( 'Y-m-d' ), $filter );
121 $this->vars['total_new_customers'] = OsBookingHelper::get_new_customer_stat_for_period( $date_from, $date_to, $filter );
122
123 $day_difference = $date_from->diff( $date_to );
124 $day_difference = ( $day_difference->d > 0 ) ? $day_difference->d : 1;
125
126 $prev_date_from = clone $date_from;
127 $prev_date_from->modify( '-' . $day_difference . ' days' );
128 $prev_date_to = clone $date_to;
129 $prev_date_to->modify( '-' . $day_difference . ' days' );
130
131 $this->vars['prev_total_bookings'] = OsBookingHelper::get_stat_for_period( 'bookings', $prev_date_from->format( 'Y-m-d' ), $prev_date_to->format( 'Y-m-d' ), $filter );
132 $this->vars['prev_total_price'] = OsBookingHelper::get_stat_for_period( 'price', $prev_date_from->format( 'Y-m-d' ), $prev_date_to->format( 'Y-m-d' ), $filter );
133 $this->vars['prev_total_duration'] = OsBookingHelper::get_stat_for_period( 'duration', $prev_date_from->format( 'Y-m-d' ), $prev_date_to->format( 'Y-m-d' ), $filter );
134 $this->vars['prev_total_new_customers'] = OsBookingHelper::get_new_customer_stat_for_period( $prev_date_from, $prev_date_to, $filter );
135
136
137 $agents = new OsAgentModel();
138 $services = new OsServiceModel();
139 $locations = new OsLocationModel();
140
141 $this->vars['agents'] = $agents->should_be_active()->filter_allowed_records()->get_results_as_models();
142 $this->vars['services'] = $services->should_be_active()->filter_allowed_records()->get_results_as_models();
143 $this->vars['locations'] = $locations->should_be_active()->filter_allowed_records()->get_results_as_models();
144
145 $this->vars['filter'] = $filter;
146
147 $this->vars['date_from'] = $date_from->format( 'Y-m-d' );
148 $this->vars['date_to'] = $date_to->format( 'Y-m-d' );
149
150 $this->vars['daily_bookings_chart_labels_string'] = implode( ',', array_keys( $daily_chart_data ) );
151 $this->vars['daily_bookings_chart_data_values_string'] = implode( ',', array_values( $daily_chart_data ) );
152
153 $pie_labels = [];
154 $pie_colors = [];
155 $pie_values = [];
156 $pie_chart_data = OsBookingHelper::get_stat_for_period( 'bookings', $date_from->format( 'Y-m-d' ), $date_to->format( 'Y-m-d' ), $filter, 'service_id' );
157 foreach ( $pie_chart_data as $pie_data ) {
158 $service = new OsServiceModel( $pie_data['service_id'] );
159 $pie_labels[] = $service->name;
160 $pie_colors[] = $service->bg_color;
161 $pie_values[] = $pie_data['stat'];
162 }
163
164 $this->vars['pie_chart_data'] = [
165 'labels' => $pie_labels,
166 'colors' => $pie_colors,
167 'values' => $pie_values,
168 ];
169
170 $this->vars['date_period_string'] = OsTimeHelper::format_date_with_locale( OsSettingsHelper::get_readable_date_format( true, true ), $date_from ) . ' - ' . OsTimeHelper::format_date_with_locale( OsSettingsHelper::get_readable_date_format( true, true ), $date_to );
171
172 $this->set_layout( 'none' );
173 $this->format_render( __FUNCTION__ );
174 }
175
176
177
178 public function widget_bookings_and_availability_timeline() {
179 $target_date = isset( $this->params['date_from'] ) ? OsWpDateTime::os_createFromFormat( 'Y-m-d', $this->params['date_from'] ) : new OsWpDateTime( 'now' );
180
181 $services = new OsServiceModel();
182 $agents = new OsAgentModel();
183 $locations = new OsLocationModel();
184
185 $agents_models = $agents->should_be_active()->filter_allowed_records()->get_results_as_models();
186 $services_models = $services->should_be_active()->filter_allowed_records()->get_results_as_models();
187 $locations_models = $locations->should_be_active()->filter_allowed_records()->get_results_as_models();
188
189 $this->vars['services'] = $services_models;
190 $this->vars['locations'] = $locations_models;
191 $this->vars['agents'] = $agents_models;
192
193 if ( $services_models && ! empty( $this->params['service_id'] ) ) {
194 $selected_service = $services->load_by_id( $this->params['service_id'] );
195 } else {
196 $selected_service = false;
197 }
198
199
200 if ( $locations_models ) {
201 // show all locations option if agent can only be present at one place - because it means he does not have overlapping appointments on the calendar
202 $default_location_id = OsSettingsHelper::is_on( 'one_location_at_time' ) ? false : $locations_models[0]->id;
203 $selected_location_id = ! empty( $this->params['location_id'] ) ? $this->params['location_id'] : $default_location_id;
204 } else {
205 $selected_location_id = false;
206 }
207
208 $this->vars['selected_location'] = $selected_location_id ? new OsLocationModel( $selected_location_id ) : false;
209 $this->vars['selected_location_id'] = $selected_location_id;
210
211 $timeblock_interval = OsSettingsHelper::get_default_timeblock_interval();
212 $selected_service_id = ( $selected_service ) ? $selected_service->id : false;
213
214 $this->vars['selected_service'] = $selected_service;
215 $this->vars['selected_service_id'] = $selected_service_id;
216
217
218
219 // we are using two separate booking requests because the calendar on top has to generate availability timeline,
220 // which can only be generated if we know service to check for. The second booking request is used to retrieve
221 // shared resources for all services and locations (unless specific location is selected)
222 $availability_booking_request = new \LatePoint\Misc\BookingRequest( [ 'start_date' => $target_date->format( 'Y-m-d' ) ] );
223 $general_booking_request = new \LatePoint\Misc\BookingRequest( [ 'start_date' => $target_date->format( 'Y-m-d' ) ] );
224 if ( $selected_location_id ) {
225 $availability_booking_request->location_id = $selected_location_id;
226 $general_booking_request->location_id = $selected_location_id;
227 }
228 if ( $selected_service ) {
229 $availability_booking_request->service_id = $selected_service->id;
230 // TODO add capacity and duration select box and POST params if multiple durations in a service
231 $availability_booking_request->duration = $selected_service->duration;
232 $timeblock_interval = $selected_service->get_timeblock_interval();
233 }
234
235 if ( count( $agents_models ) == 1 ) {
236 $availability_booking_request->agent_id = $agents_models[0]->id;
237 $general_booking_request->agent_id = $agents_models[0]->id;
238 }
239
240 $settings = [ 'accessed_from_backend' => true ];
241 $resources = OsResourceHelper::get_resources_grouped_by_day( $general_booking_request, $target_date, $target_date, $settings );
242 $availability_resources = OsResourceHelper::get_resources_grouped_by_day( $availability_booking_request, $target_date, $target_date, $settings );
243 $work_boundaries = OsResourceHelper::get_work_boundaries_for_resources( $resources[ $target_date->format( 'Y-m-d' ) ] );
244 $work_total_minutes = $work_boundaries->end_time - $work_boundaries->start_time;
245
246 $this->vars['timeblock_interval'] = $timeblock_interval;
247
248 $bookings = [];
249 $agent_work_time_periods = [];
250 if ( $agents_models ) {
251 foreach ( $agents_models as $agent ) {
252 $agent_work_time_periods[ $agent->id ] = [];
253 $args = [ 'agent_id' => $agent->id ];
254 if ( $selected_location_id ) {
255 $args['location_id'] = $selected_location_id;
256 }
257 $args['status'] = OsCalendarHelper::get_booking_statuses_to_display_on_calendar();
258 $args = OsRolesHelper::filter_allowed_records_from_arguments_or_filter( $args );
259 $bookings[ $agent->id ] = OsBookingHelper::get_bookings_for_date( $target_date->format( 'Y-m-d' ), $args );
260 }
261 foreach ( $availability_resources[ $target_date->format( 'Y-m-d' ) ] as $resource ) {
262 if ( isset( $agent_work_time_periods[ $resource->agent_id ] ) ) {
263 $agent_work_time_periods[ $resource->agent_id ] = array_merge( $agent_work_time_periods[ $resource->agent_id ], $resource->work_time_periods );
264 }
265 }
266 }
267
268
269 $this->vars['agent_work_time_periods'] = $agent_work_time_periods;
270
271 $this->vars['availability_booking_request'] = $availability_booking_request;
272 $this->vars['general_booking_request'] = $general_booking_request;
273
274 $agents_resources = [];
275 foreach ( $agents_models as $agent ) {
276 $agent_booking_request = clone $availability_booking_request;
277 $agent_booking_request->agent_id = $agent->id;
278 $daily_resources = OsResourceHelper::get_resources_grouped_by_day( $agent_booking_request, $target_date, null, $settings );
279 $agents_resources[ 'agent_' . $agent->id ] = $daily_resources[ $target_date->format( 'Y-m-d' ) ];
280 }
281 $this->vars['agents_resources'] = $agents_resources;
282 $this->vars['timeline_boundaries'] = OsResourceHelper::get_work_boundaries_for_groups_of_resources( $agents_resources );
283
284 $this->vars['work_total_minutes'] = $work_total_minutes;
285 $this->vars['work_boundaries'] = $work_boundaries;
286 $this->vars['show_day_info'] = OsAuthHelper::is_admin_logged_in();
287 $this->vars['target_date_obj'] = $target_date;
288 $this->vars['target_date'] = $target_date->format( 'Y-m-d' );
289 $this->vars['target_date_string'] = OsTimeHelper::get_readable_date( $target_date );
290
291 $this->vars['what_to_show'] = isset( $this->params['what_to_show'] ) ? $this->params['what_to_show'] : 'appointments';
292
293
294 $today_date = new OsWpDateTime( 'today' );
295
296 if ( $target_date->format( 'Y-m-d' ) == $today_date->format( 'Y-m-d' ) ) {
297 $time_now = OsTimeHelper::now_datetime_object();
298 $time_now_in_minutes = OsTimeHelper::convert_datetime_to_minutes( $time_now );
299 if ( ( $time_now_in_minutes <= $work_boundaries->end_time && $time_now_in_minutes >= $work_boundaries->start_time ) && $work_total_minutes > 0 ) {
300 $this->vars['time_now_label'] = $time_now->format( OsTimeHelper::get_time_format() );
301 // agents row with avatars and margin below - offset that needs to be accounted for when calculating "time now" indicator position
302 $this->vars['time_now_indicator_left_offset'] = ( $time_now_in_minutes - $work_boundaries->start_time ) / $work_total_minutes * 100;
303 $this->vars['show_today_indicator'] = true;
304 } else {
305 $this->vars['show_today_indicator'] = false;
306 }
307 } else {
308 $this->vars['show_today_indicator'] = false;
309 }
310
311 $this->set_layout( 'none' );
312
313 $this->format_render( __FUNCTION__ );
314 }
315 }
316
317 endif;
318