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