PluginProbe ʕ •ᴥ•ʔ
LatePoint – Calendar Booking Plugin for Appointments and Events / 5.5.2
LatePoint – Calendar Booking Plugin for Appointments and Events v5.5.2
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 / bookings_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 2 months ago calendars_controller.php 3 months ago carts_controller.php 3 months ago controller.php 3 months ago customer_cabinet_controller.php 2 months ago customers_controller.php 3 months ago dashboard_controller.php 2 months ago default_agent_controller.php 3 months ago events_controller.php 3 months ago form_fields_controller.php 3 months ago integrations_controller.php 3 months ago invoices_controller.php 2 months 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 3 months ago pro_controller.php 2 months ago process_jobs_controller.php 3 months ago processes_controller.php 3 months ago search_controller.php 3 months ago services_controller.php 3 months ago settings_controller.php 2 months ago steps_controller.php 3 months ago stripe_connect_controller.php 2 months ago support_topics_controller.php 3 months ago todos_controller.php 3 months ago transactions_controller.php 3 months ago wizard_controller.php 2 months ago
bookings_controller.php
454 lines
1 <?php
2 if ( ! defined( 'ABSPATH' ) ) {
3 exit; // Exit if accessed directly.
4 }
5
6
7 if ( ! class_exists( 'OsBookingsController' ) ) :
8
9
10 class OsBookingsController extends OsController {
11
12 private $booking;
13
14 function __construct() {
15 parent::__construct();
16 $this->views_folder = LATEPOINT_VIEWS_ABSPATH . 'bookings/';
17 $this->vars['page_header'] = OsMenuHelper::get_menu_items_by_id( 'appointments' );
18 $this->vars['breadcrumbs'][] = array(
19 'label' => __( 'Appointments', 'latepoint' ),
20 'link' => OsRouterHelper::build_link( [ 'bookings', 'pending_approval' ] ),
21 );
22 }
23
24 public function view_booking_log() {
25 $activities = new OsActivityModel();
26 $activities = $activities->where( [ 'booking_id' => absint( $this->params['booking_id'] ) ] )->order_by( 'id desc' )->get_results_as_models();
27
28 $booking = new OsBookingModel( $this->params['booking_id'] );
29
30 $this->vars['booking'] = $booking;
31 $this->vars['activities'] = $activities;
32
33 $this->format_render( __FUNCTION__ );
34 }
35
36 public function grouped_bookings_quick_view() {
37 if ( ! isset( $this->params['booking_id'] ) ) {
38 return false;
39 }
40
41 $booking = new OsBookingModel( $this->params['booking_id'] );
42 $this->vars['booking'] = $booking;
43
44 $group_bookings = new OsBookingModel();
45 $group_bookings = $group_bookings->where(
46 [
47 'start_time' => $booking->start_time,
48 'start_date' => $booking->start_date,
49 'service_id' => $booking->service_id,
50 'location_id' => $booking->location_id,
51 'agent_id' => $booking->agent_id,
52 ]
53 )->should_not_be_cancelled()->get_results_as_models();
54 $total_attendees = 0;
55 if ( $group_bookings ) {
56 foreach ( $group_bookings as $group_booking ) {
57 $total_attendees = $total_attendees + $group_booking->total_attendees;
58 }
59 }
60 $this->vars['total_attendees'] = $total_attendees;
61 $this->vars['group_bookings'] = $group_bookings;
62 $this->format_render( __FUNCTION__ );
63 }
64
65 public function pending_approval() {
66 $this->vars['page_header'] = __( 'Pending Appointments', 'latepoint' );
67 $this->vars['breadcrumbs'][] = array(
68 'label' => __( 'Pending Appointments', 'latepoint' ),
69 'link' => false,
70 );
71
72 $page_number = isset( $this->params['page_number'] ) ? $this->params['page_number'] : 1;
73 $per_page = OsSettingsHelper::get_number_of_records_per_page();
74 $offset = ( $page_number > 1 ) ? ( ( $page_number - 1 ) * $per_page ) : 0;
75
76 $bookings = new OsBookingModel();
77 $query_args = [ 'status' => OsBookingHelper::get_booking_statuses_for_pending_page() ];
78
79 $bookings->where( $query_args )->filter_allowed_records();
80
81 $count_total_bookings = clone $bookings;
82 $total_bookings = $count_total_bookings->count();
83
84 $this->vars['bookings'] = $bookings->set_limit( $per_page )->set_offset( $offset )->order_by( 'id desc' )->get_results_as_models();
85
86 $total_pages = ceil( $total_bookings / $per_page );
87
88 $this->vars['total_pages'] = $total_pages;
89 $this->vars['total_bookings'] = $total_bookings;
90 $this->vars['per_page'] = $per_page;
91 $this->vars['current_page_number'] = $page_number;
92
93 $this->vars['showing_from'] = ( ( $page_number - 1 ) * $per_page ) ? ( ( $page_number - 1 ) * $per_page ) : 1;
94 $this->vars['showing_to'] = min( $page_number * $per_page, $this->vars['total_bookings'] );
95
96 $this->format_render( __FUNCTION__ );
97 }
98
99 public function customize_table() {
100 $this->vars['selected_columns'] = OsSettingsHelper::get_selected_columns_for_bookings_table();
101 $this->vars['available_columns'] = OsSettingsHelper::get_available_columns_for_bookings_table();
102 $this->vars['ordered_columns'] = OsSettingsHelper::get_ordered_bookings_table_columns();
103
104 $this->format_render( __FUNCTION__ );
105 }
106
107 public function index() {
108
109 $this->vars['page_header'] = false;
110 $this->vars['breadcrumbs'][] = array(
111 'label' => __( 'All', 'latepoint' ),
112 'link' => false,
113 );
114
115 $page_number = isset( $this->params['page_number'] ) ? $this->params['page_number'] : 1;
116 $per_page = OsSettingsHelper::get_number_of_records_per_page();
117 $offset = ( $page_number > 1 ) ? ( ( $page_number - 1 ) * $per_page ) : 0;
118
119 $customer = new OsCustomerModel();
120
121 $bookings = new OsBookingModel();
122 $query_args = [];
123
124 $selected_columns = OsSettingsHelper::get_selected_columns_for_bookings_table();
125 $available_columns = OsSettingsHelper::get_available_columns_for_bookings_table();
126 $ordered_columns = OsSettingsHelper::get_ordered_bookings_table_columns();
127
128 $filter = $this->params['filter'] ?? false;
129
130 $order_by = [
131 'key' => 'booking_id',
132 'direction' => 'desc',
133 'column' => 'id',
134 ];
135
136 // TABLE SEARCH FILTERS
137 if ( $filter ) {
138 if ( ! empty( $filter['records_ordered_by_key'] ) && ! empty( $filter['records_ordered_by_direction'] ) ) {
139 if ( in_array( $filter['records_ordered_by_direction'], [ 'desc', 'asc' ] ) ) {
140 $order_by['direction'] = $filter['records_ordered_by_direction'];
141 }
142 $order_by['key'] = $filter['records_ordered_by_key'];
143 switch ( $filter['records_ordered_by_key'] ) {
144 case 'booking_id':
145 $order_by['column'] = 'id';
146 break;
147 case 'booking_start_datetime':
148 $order_by['column'] = 'start_datetime_utc';
149 break;
150 case 'booking_created_on':
151 $order_by['column'] = 'created_at';
152 break;
153 case 'booking_time_left':
154 $order_by['column'] = 'start_datetime_utc';
155 break;
156 }
157 }
158 if ( ! empty( $filter['service_id'] ) ) {
159 $query_args['service_id'] = $filter['service_id'];
160 }
161 if ( ! empty( $filter['agent_id'] ) ) {
162 $query_args['agent_id'] = $filter['agent_id'];
163 }
164 if ( ! empty( $filter['location_id'] ) ) {
165 $query_args['location_id'] = $filter['location_id'];
166 }
167 if ( ! empty( $filter['time_status'] ) ) {
168 switch ( $filter['time_status'] ) {
169 case 'now':
170 $query_args['start_datetime_utc <='] = OsTimeHelper::now_datetime_utc_in_db_format();
171 $query_args['end_datetime_utc >='] = OsTimeHelper::now_datetime_utc_in_db_format();
172 break;
173 case 'upcoming':
174 $query_args['start_datetime_utc >='] = OsTimeHelper::now_datetime_utc_in_db_format();
175 break;
176 case 'past':
177 $query_args['end_datetime_utc <='] = OsTimeHelper::now_datetime_utc_in_db_format();
178 break;
179 }
180 }
181 if ( ! empty( $filter['status'] ) ) {
182 $query_args[ LATEPOINT_TABLE_BOOKINGS . '.status' ] = $filter['status'];
183 }
184 if ( ! empty( $filter['payment_status'] ) ) {
185 $query_args[ LATEPOINT_TABLE_BOOKINGS . '.payment_status' ] = $filter['payment_status'];
186 }
187 if ( ! empty( $filter['id'] ) ) {
188 $query_args[ LATEPOINT_TABLE_BOOKINGS . '.id' ] = $filter['id'];
189 }
190 if ( ! empty( $filter['created_date_from'] ) && ! empty( $filter['created_date_to'] ) ) {
191 $query_args[ LATEPOINT_TABLE_BOOKINGS . '.created_at >=' ] = $filter['created_date_from'] . ' 00:00:00';
192 $query_args[ LATEPOINT_TABLE_BOOKINGS . '.created_at <=' ] = $filter['created_date_to'] . ' 23:59:59';
193 }
194 if ( ! empty( $filter['booking_date_from'] ) && ! empty( $filter['booking_date_to'] ) ) {
195 $query_args[ LATEPOINT_TABLE_BOOKINGS . '.start_date >=' ] = $filter['booking_date_from'];
196 $query_args[ LATEPOINT_TABLE_BOOKINGS . '.start_date <=' ] = $filter['booking_date_to'];
197 }
198
199 $selected_columns = OsSettingsHelper::get_selected_columns_for_bookings_table();
200 if ( ! empty( $filter['order'] ) ) {
201 $bookings->select( LATEPOINT_TABLE_BOOKINGS . '.*' );
202 $bookings->join( LATEPOINT_TABLE_ORDER_ITEMS, [ 'id' => LATEPOINT_TABLE_BOOKINGS . '.order_item_id' ] );
203 $bookings->join( LATEPOINT_TABLE_ORDERS, [ 'id' => LATEPOINT_TABLE_ORDER_ITEMS . '.order_id' ] );
204 if ( ! empty( $filter['order']['payment_status'] ) ) {
205 $bookings->select( LATEPOINT_TABLE_ORDERS . '.payment_status' );
206 $query_args[ LATEPOINT_TABLE_ORDERS . '.payment_status' ] = $filter['order']['payment_status'];
207 }
208 }
209 if ( ! empty( $filter['customer'] ) ) {
210 $bookings->select( LATEPOINT_TABLE_BOOKINGS . '.*' );
211 if ( ! empty( $filter['customer']['full_name'] ) ) {
212 $bookings->select( LATEPOINT_TABLE_CUSTOMERS . '.first_name, ' . LATEPOINT_TABLE_CUSTOMERS . '.last_name' );
213 $query_args[ 'concat_ws(" ", ' . LATEPOINT_TABLE_CUSTOMERS . '.first_name,' . LATEPOINT_TABLE_CUSTOMERS . '.last_name) LIKE' ] = '%' . $filter['customer']['full_name'] . '%';
214 $this->vars['customer_name_query'] = $filter['customer']['full_name'];
215 }
216 $bookings->join( LATEPOINT_TABLE_CUSTOMERS, [ 'id' => LATEPOINT_TABLE_BOOKINGS . '.customer_id' ] );
217
218
219 if ( ! empty( $selected_columns['customer'] ) ) {
220 $meta_filter = [];
221 foreach ( $selected_columns['customer'] as $customer_column_key ) {
222
223 if ( isset( $available_columns['customer'][ $customer_column_key ] ) && ! empty( $filter['customer'][ $customer_column_key ] ) ) {
224
225 if ( in_array( $customer_column_key, $customer->get_params_to_save() ) ) {
226 // native field
227 $bookings->select( LATEPOINT_TABLE_CUSTOMERS . '.' . $customer_column_key );
228 $query_args[ LATEPOINT_TABLE_CUSTOMERS . '.' . $customer_column_key . ' LIKE' ] = '%' . $filter['customer'][ $customer_column_key ] . '%';
229 } else {
230 // meta field
231 $meta_filter[ $customer_column_key ] = $filter['customer'][ $customer_column_key ];
232 }
233 }
234 }
235 if ( count( $meta_filter ) ) {
236 $customers_ids = OsMetaHelper::get_customers_by_filter( $meta_filter ) ?: [ - 1 ];
237 $query_args[ LATEPOINT_TABLE_CUSTOMERS . '.id IN' ] = $customers_ids;
238 }
239 }
240 }
241 // filters for custom selected columns, only related to booking fields
242 if ( ! empty( $selected_columns['booking'] ) ) {
243 foreach ( $selected_columns['booking'] as $booking_column_key ) {
244 if ( ! empty( $available_columns['booking'][ $booking_column_key ] ) && ! empty( $filter[ $booking_column_key ] ) ) {
245 $query_args[ $booking_column_key . ' LIKE' ] = '%' . $filter[ $booking_column_key ] . '%';
246 }
247 }
248 }
249 }
250
251 $this->vars['agents_list'] = OsAgentHelper::get_agents_list( true );
252 $this->vars['locations_list'] = OsLocationHelper::get_locations_list( true );
253 $this->vars['services_list'] = OsServiceHelper::get_services_list( true );
254
255 $this->vars['selected_columns'] = $selected_columns;
256 $this->vars['available_columns'] = $available_columns;
257 $this->vars['ordered_columns'] = $ordered_columns;
258
259 $this->vars['records_ordered_by_key'] = $order_by['key'];
260 $this->vars['records_ordered_by_direction'] = $order_by['direction'];
261
262 // OUTPUT CSV IF REQUESTED
263 if ( isset( $this->params['download'] ) && $this->params['download'] == 'csv' ) {
264 $csv_filename = 'all_bookings_' . OsUtilHelper::random_text() . '.csv';
265
266 header( 'Content-Type: text/csv' );
267 header( "Content-Disposition: attachment; filename={$csv_filename}" );
268
269 $labels_row = [
270 __( 'ID', 'latepoint' ),
271 __( 'Service', 'latepoint' ),
272 __( 'Start Date & Time', 'latepoint' ),
273 __( 'Duration', 'latepoint' ),
274 __( 'Customer', 'latepoint' ),
275 __( 'Customer Phone', 'latepoint' ),
276 __( 'Customer Email', 'latepoint' ),
277 __( 'Agent', 'latepoint' ),
278 __( 'Agent Phone', 'latepoint' ),
279 __( 'Agent Email', 'latepoint' ),
280 __( 'Status', 'latepoint' ),
281 __( 'Price', 'latepoint' ),
282 __( 'Booked On', 'latepoint' ),
283 ];
284
285
286 $bookings_data = [];
287 $bookings_data[] = $labels_row;
288
289
290 $bookings_arr = $bookings->where( $query_args )->filter_allowed_records()->order_by( $order_by['column'] . ' ' . $order_by['direction'] )->get_results_as_models();
291
292 if ( $bookings_arr ) {
293 foreach ( $bookings_arr as $booking ) {
294 $order_item = new OsOrderItemModel( $booking->order_item_id );
295 $values_row = [
296 $booking->id,
297 $booking->service->name,
298 $booking->nice_start_datetime,
299 $booking->get_total_duration(),
300 $booking->customer->full_name,
301 $booking->customer->phone,
302 $booking->customer->email,
303 $booking->agent->full_name,
304 $booking->agent->phone,
305 $booking->agent->email,
306 $booking->nice_status,
307 OsMoneyHelper::format_price( $order_item->get_total(), true, false ),
308 $booking->nice_created_at,
309 ];
310 $values_row = apply_filters( 'latepoint_booking_row_for_csv_export', $values_row, $booking, $this->params );
311 $bookings_data[] = $values_row;
312 }
313 }
314
315 $bookings_data = apply_filters( 'latepoint_bookings_data_for_csv_export', $bookings_data, $this->params );
316 OsCSVHelper::array_to_csv( $bookings_data );
317
318 return;
319 }
320
321 $query_args = OsRolesHelper::filter_allowed_records_from_arguments_or_filter( $query_args );
322 $bookings->where( $query_args )->filter_allowed_records();
323 $count_total_bookings = clone $bookings;
324 $total_bookings = $count_total_bookings->count();
325
326 $this->vars['bookings'] = $bookings->set_limit( $per_page )->set_offset( $offset )->order_by( $order_by['column'] . ' ' . $order_by['direction'] )->get_results_as_models();
327 $this->vars['total_bookings'] = $total_bookings;
328 $total_pages = ceil( $total_bookings / $per_page );
329
330 $this->vars['total_pages'] = $total_pages;
331 $this->vars['per_page'] = $per_page;
332 $this->vars['current_page_number'] = $page_number;
333 $this->vars['total_records'] = $total_bookings;
334
335 $this->vars['showing_from'] = ( ( $page_number - 1 ) * $per_page ) ? ( ( $page_number - 1 ) * $per_page ) : 1;
336 $this->vars['showing_to'] = min( $page_number * $per_page, $this->vars['total_bookings'] );
337
338 $this->format_render(
339 [
340 'json_view_name' => '_table_body',
341 'html_view_name' => __FUNCTION__,
342 ],
343 [],
344 [
345 'total_pages' => $total_pages,
346 'showing_from' => $this->vars['showing_from'],
347 'showing_to' => $this->vars['showing_to'],
348 'total_records' => $total_bookings,
349 ]
350 );
351 }
352
353 function quick_availability() {
354
355 $trigger_form_booking_id = $this->params['trigger_form_booking_id'];
356 $trigger_form_order_item_id = $this->params['trigger_form_order_item_id'];
357
358 $booking = OsOrdersHelper::create_booking_object_from_booking_data_form( $this->params['order_items'][ $trigger_form_order_item_id ]['bookings'][ $trigger_form_booking_id ] );
359
360 $calendar_start_date = isset( $this->params['start_date'] ) ? new OsWpDateTime( $this->params['start_date'] ) : new OsWpDateTime( $booking->start_date );
361 // show one more day before so the current selection does not look weird
362 if ( isset( $this->params['previous_days'] ) ) {
363 $calendar_end_date = clone $calendar_start_date;
364 $calendar_start_date->modify( '-60 days' );
365 } else {
366 if ( ! isset( $this->params['show_days_only'] ) ) {
367 $calendar_start_date->modify( '-1 day' );
368 }
369 $calendar_end_date = clone $calendar_start_date;
370 $calendar_end_date->modify( '+60 days' );
371 }
372
373 if ( OsAuthHelper::get_current_user()->is_single_record_allowed( 'agent' ) ) {
374 $booking->agent_id = OsRolesHelper::get_allowed_records( 'agent' )[0];
375 }
376
377 $work_periods = OsWorkPeriodsHelper::get_work_periods(
378 new \LatePoint\Misc\Filter(
379 [
380 'date_from' => $calendar_start_date->format( 'Y-m-d' ),
381 'date_to' => $calendar_end_date->format( 'Y-m-d' ),
382 'service_id' => $booking->service_id,
383 'agent_id' => $booking->agent_id,
384 'location_id' => $booking->location_id,
385 ]
386 )
387 );
388 $work_start_end = OsWorkPeriodsHelper::get_work_start_end_time( $work_periods );
389
390 $booking_request = \LatePoint\Misc\BookingRequest::create_from_booking_model( $booking );
391 $settings = [];
392 $settings['accessed_from_backend'] = true;
393 if ( ! $booking->is_new_record() ) {
394 $settings['exclude_booking_ids'] = [ $booking->id ];
395 }
396 $resources = OsResourceHelper::get_resources_grouped_by_day( $booking_request, $calendar_start_date, $calendar_end_date, $settings );
397 $work_boundaries = OsResourceHelper::get_work_boundaries_for_groups_of_resources( $resources );
398
399 $this->vars['trigger_form_booking_id'] = $trigger_form_booking_id;
400 $this->vars['trigger_form_order_item_id'] = $trigger_form_order_item_id;
401
402 $this->vars['booking'] = $booking;
403 $this->vars['work_boundaries'] = $work_boundaries;
404 $this->vars['show_days_only'] = isset( $this->params['show_days_only'] ) ? true : false;
405
406 $this->vars['timeblock_interval'] = $booking->service->get_timeblock_interval();
407 $this->vars['calendar_start_date'] = $calendar_start_date;
408 $this->vars['calendar_end_date'] = $calendar_end_date;
409 $this->vars['booking_request'] = $booking_request;
410 $this->vars['resources'] = $resources;
411
412 $agents = new OsAgentModel();
413 $this->vars['agents'] = $agents->filter_allowed_records()->get_results_as_models();
414
415 $this->format_render( __FUNCTION__ );
416 }
417
418
419 function change_status() {
420
421 if ( filter_var( $this->params['id'], FILTER_VALIDATE_INT ) ) {
422 $this->check_nonce( 'change_status_booking_' . $this->params['id'] );
423 $booking_id = $this->params['id'];
424 $new_status = $this->params['status'];
425 $booking = new OsBookingModel( $booking_id );
426 if ( ! OsRolesHelper::can_user_make_action_on_model_record( $booking, 'edit' ) ) {
427 exit;
428 }
429
430 if ( $booking->update_status( $new_status ) ) {
431 $status = LATEPOINT_STATUS_SUCCESS;
432 $response_html = __( 'Appointment Status Updated', 'latepoint' );
433 } else {
434 $status = LATEPOINT_STATUS_ERROR;
435 $response_html = __( 'Error Updating Booking Status!', 'latepoint' ) . ' ' . implode( ',', $booking->get_error_messages() );
436 }
437 } else {
438 $status = LATEPOINT_STATUS_ERROR;
439 $response_html = __( 'Error Updating Booking Status! Invalid ID', 'latepoint' );
440 }
441
442 if ( $this->get_return_format() == 'json' ) {
443 $this->send_json(
444 array(
445 'status' => $status,
446 'message' => $response_html,
447 )
448 );
449 }
450 }
451 }
452
453 endif;
454