PluginProbe ʕ •ᴥ•ʔ
LatePoint – Calendar Booking Plugin for Appointments and Events / 5.6.2
LatePoint – Calendar Booking Plugin for Appointments and Events v5.6.2
5.6.7 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 2 months ago auth_controller.php 3 months ago booking_form_settings_controller.php 3 months ago bookings_controller.php 3 weeks 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 1 month 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 weeks ago pro_controller.php 3 weeks ago process_jobs_controller.php 3 months ago processes_controller.php 1 month ago razorpay_connect_controller.php 1 month ago search_controller.php 3 months ago services_controller.php 3 months ago settings_controller.php 2 months ago steps_controller.php 3 weeks 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
614 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 $this->vars['can_bulk_delete'] = OsRolesHelper::can_user_perform_model_action( 'OsBookingModel', 'delete' );
263
264 // OUTPUT CSV IF REQUESTED
265 if ( isset( $this->params['download'] ) && $this->params['download'] == 'csv' ) {
266 $csv_filename = 'all_bookings_' . OsUtilHelper::random_text() . '.csv';
267
268 header( 'Content-Type: text/csv' );
269 header( "Content-Disposition: attachment; filename={$csv_filename}" );
270
271 $labels_row = [
272 __( 'ID', 'latepoint' ),
273 __( 'Service', 'latepoint' ),
274 __( 'Start Date & Time', 'latepoint' ),
275 __( 'Duration', 'latepoint' ),
276 __( 'Customer', 'latepoint' ),
277 __( 'Customer Phone', 'latepoint' ),
278 __( 'Customer Email', 'latepoint' ),
279 __( 'Agent', 'latepoint' ),
280 __( 'Agent Phone', 'latepoint' ),
281 __( 'Agent Email', 'latepoint' ),
282 __( 'Status', 'latepoint' ),
283 __( 'Price', 'latepoint' ),
284 __( 'Booked On', 'latepoint' ),
285 ];
286
287
288 $bookings_data = [];
289 $bookings_data[] = $labels_row;
290
291
292 $bookings_arr = $bookings->where( $query_args )->filter_allowed_records()->order_by( $order_by['column'] . ' ' . $order_by['direction'] )->get_results_as_models();
293
294 if ( $bookings_arr ) {
295 foreach ( $bookings_arr as $booking ) {
296 $order_item = new OsOrderItemModel( $booking->order_item_id );
297 $values_row = [
298 $booking->id,
299 $booking->service->name,
300 $booking->nice_start_datetime,
301 $booking->get_total_duration(),
302 $booking->customer->full_name,
303 $booking->customer->phone,
304 $booking->customer->email,
305 $booking->agent->full_name,
306 $booking->agent->phone,
307 $booking->agent->email,
308 $booking->nice_status,
309 OsMoneyHelper::format_price( $order_item->get_total(), true, false ),
310 $booking->nice_created_at,
311 ];
312 $values_row = apply_filters( 'latepoint_booking_row_for_csv_export', $values_row, $booking, $this->params );
313 $bookings_data[] = $values_row;
314 }
315 }
316
317 $bookings_data = apply_filters( 'latepoint_bookings_data_for_csv_export', $bookings_data, $this->params );
318 OsCSVHelper::array_to_csv( $bookings_data );
319
320 return;
321 }
322
323 $query_args = OsRolesHelper::filter_allowed_records_from_arguments_or_filter( $query_args );
324 $bookings->where( $query_args )->filter_allowed_records();
325 $count_total_bookings = clone $bookings;
326 $total_bookings = $count_total_bookings->count();
327
328 $this->vars['bookings'] = $bookings->set_limit( $per_page )->set_offset( $offset )->order_by( $order_by['column'] . ' ' . $order_by['direction'] )->get_results_as_models();
329 $this->vars['total_bookings'] = $total_bookings;
330 $total_pages = ceil( $total_bookings / $per_page );
331
332 $this->vars['total_pages'] = $total_pages;
333 $this->vars['per_page'] = $per_page;
334 $this->vars['current_page_number'] = $page_number;
335 $this->vars['total_records'] = $total_bookings;
336
337 $this->vars['showing_from'] = ( ( $page_number - 1 ) * $per_page ) ? ( ( $page_number - 1 ) * $per_page ) : 1;
338 $this->vars['showing_to'] = min( $page_number * $per_page, $this->vars['total_bookings'] );
339
340 $this->format_render(
341 [
342 'json_view_name' => '_table_body',
343 'html_view_name' => __FUNCTION__,
344 ],
345 [],
346 [
347 'total_pages' => $total_pages,
348 'showing_from' => $this->vars['showing_from'],
349 'showing_to' => $this->vars['showing_to'],
350 'total_records' => $total_bookings,
351 ]
352 );
353 }
354
355 function quick_availability() {
356
357 $trigger_form_booking_id = $this->params['trigger_form_booking_id'];
358 $trigger_form_order_item_id = $this->params['trigger_form_order_item_id'];
359
360 $booking = OsOrdersHelper::create_booking_object_from_booking_data_form( $this->params['order_items'][ $trigger_form_order_item_id ]['bookings'][ $trigger_form_booking_id ] );
361
362 $calendar_start_date = isset( $this->params['start_date'] ) ? new OsWpDateTime( $this->params['start_date'] ) : new OsWpDateTime( $booking->start_date );
363 // show one more day before so the current selection does not look weird
364 if ( isset( $this->params['previous_days'] ) ) {
365 $calendar_end_date = clone $calendar_start_date;
366 $calendar_start_date->modify( '-60 days' );
367 } else {
368 if ( ! isset( $this->params['show_days_only'] ) ) {
369 $calendar_start_date->modify( '-1 day' );
370 }
371 $calendar_end_date = clone $calendar_start_date;
372 $calendar_end_date->modify( '+60 days' );
373 }
374
375 if ( OsAuthHelper::get_current_user()->is_single_record_allowed( 'agent' ) ) {
376 $booking->agent_id = OsRolesHelper::get_allowed_records( 'agent' )[0];
377 }
378
379 $work_periods = OsWorkPeriodsHelper::get_work_periods(
380 new \LatePoint\Misc\Filter(
381 [
382 'date_from' => $calendar_start_date->format( 'Y-m-d' ),
383 'date_to' => $calendar_end_date->format( 'Y-m-d' ),
384 'service_id' => $booking->service_id,
385 'agent_id' => $booking->agent_id,
386 'location_id' => $booking->location_id,
387 ]
388 )
389 );
390 $work_start_end = OsWorkPeriodsHelper::get_work_start_end_time( $work_periods );
391
392 $booking_request = \LatePoint\Misc\BookingRequest::create_from_booking_model( $booking );
393 $settings = [];
394 $settings['accessed_from_backend'] = true;
395 if ( ! $booking->is_new_record() ) {
396 $settings['exclude_booking_ids'] = [ $booking->id ];
397 }
398 $resources = OsResourceHelper::get_resources_grouped_by_day( $booking_request, $calendar_start_date, $calendar_end_date, $settings );
399 $work_boundaries = OsResourceHelper::get_work_boundaries_for_groups_of_resources( $resources );
400
401 $this->vars['trigger_form_booking_id'] = $trigger_form_booking_id;
402 $this->vars['trigger_form_order_item_id'] = $trigger_form_order_item_id;
403
404 $this->vars['booking'] = $booking;
405 $this->vars['work_boundaries'] = $work_boundaries;
406 $this->vars['show_days_only'] = isset( $this->params['show_days_only'] ) ? true : false;
407
408 $this->vars['timeblock_interval'] = $booking->service->get_timeblock_interval();
409 $this->vars['calendar_start_date'] = $calendar_start_date;
410 $this->vars['calendar_end_date'] = $calendar_end_date;
411 $this->vars['booking_request'] = $booking_request;
412 $this->vars['resources'] = $resources;
413
414 $agents = new OsAgentModel();
415 $this->vars['agents'] = $agents->filter_allowed_records()->get_results_as_models();
416
417 $this->format_render( __FUNCTION__ );
418 }
419
420
421 /**
422 * Maximum number of appointments accepted in a single bulk-delete request.
423 * Acts as a guard against accidental or malicious oversized payloads.
424 */
425 const BULK_DESTROY_MAX_IDS = 100;
426
427 /**
428 * Bulk-delete appointments by ID.
429 *
430 * Expects POST params:
431 * - _wpnonce: nonce for action 'bulk_destroy_bookings'.
432 * - ids: array of booking IDs (or comma-separated string).
433 *
434 * Verifies the user can delete bookings, validates input, then attempts to
435 * delete each ID after a per-record capability check. Fires the standard
436 * latepoint_booking_will_be_deleted / latepoint_booking_deleted hooks per
437 * successful deletion and logs activity.
438 *
439 * Responds with JSON containing status, message, deleted_ids, failed_ids,
440 * deleted_count and failed_count.
441 *
442 * @return void
443 */
444 public function bulk_destroy() {
445 $this->check_nonce( 'bulk_destroy_bookings' );
446
447 if ( ! OsRolesHelper::can_user_perform_model_action( 'OsBookingModel', 'delete' ) ) {
448 $this->send_json(
449 array(
450 'status' => LATEPOINT_STATUS_ERROR,
451 'message' => __( 'You do not have permission to delete appointments.', 'latepoint' ),
452 )
453 );
454 return;
455 }
456
457 $raw_ids = $this->params['ids'] ?? array();
458 if ( ! is_array( $raw_ids ) ) {
459 $raw_ids = explode( ',', (string) $raw_ids );
460 }
461
462 $ids = array();
463 foreach ( $raw_ids as $raw_id ) {
464 $id = absint( $raw_id );
465 if ( $id ) {
466 $ids[ $id ] = $id;
467 }
468 }
469
470 if ( empty( $ids ) ) {
471 $this->send_json(
472 array(
473 'status' => LATEPOINT_STATUS_ERROR,
474 'message' => __( 'No appointments selected.', 'latepoint' ),
475 )
476 );
477 return;
478 }
479
480 if ( count( $ids ) > self::BULK_DESTROY_MAX_IDS ) {
481 $this->send_json(
482 array(
483 'status' => LATEPOINT_STATUS_ERROR,
484 'message' => sprintf(
485 /* translators: %d: maximum number of appointments allowed in a single bulk action */
486 __( 'Too many appointments selected. Please delete in batches of %d or fewer.', 'latepoint' ),
487 self::BULK_DESTROY_MAX_IDS
488 ),
489 )
490 );
491 return;
492 }
493
494 ignore_user_abort( true );
495 if ( function_exists( 'set_time_limit' ) ) {
496 // phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged
497 @set_time_limit( 0 );
498 }
499
500 $deleted_ids = array();
501 $failed_ids = array();
502
503 foreach ( $ids as $id ) {
504 $booking = new OsBookingModel( $id );
505 if ( $booking->is_new_record() ) {
506 $failed_ids[] = $id;
507 continue;
508 }
509 if ( ! OsRolesHelper::can_user_make_action_on_model_record( $booking, 'delete' ) ) {
510 $failed_ids[] = $id;
511 continue;
512 }
513
514 /**
515 * Fires right before a booking is about to be deleted via bulk delete.
516 *
517 * @param {integer} $booking_id ID of the booking that will be deleted.
518 * @since 5.2.0
519 * @hook latepoint_booking_will_be_deleted
520 */
521 do_action( 'latepoint_booking_will_be_deleted', $id );
522
523 if ( $booking->delete() ) {
524 /**
525 * Fires right after a booking has been deleted via bulk delete.
526 *
527 * @param {integer} $booking_id ID of the booking that was deleted.
528 * @since 5.2.0
529 * @hook latepoint_booking_deleted
530 */
531 do_action( 'latepoint_booking_deleted', $id );
532 OsActivitiesHelper::log_booking_deleted( $booking );
533 $deleted_ids[] = $id;
534 } else {
535 $failed_ids[] = $id;
536 }
537 }
538
539 $deleted_count = count( $deleted_ids );
540 $failed_count = count( $failed_ids );
541
542 if ( $deleted_count && ! $failed_count ) {
543 $status = LATEPOINT_STATUS_SUCCESS;
544 $message = sprintf(
545 /* translators: %d: number of appointments deleted */
546 _n( '%d appointment deleted successfully.', '%d appointments deleted successfully.', $deleted_count, 'latepoint' ),
547 $deleted_count
548 );
549 } elseif ( $deleted_count && $failed_count ) {
550 $status = LATEPOINT_STATUS_SUCCESS;
551 $message = sprintf(
552 /* translators: 1: number of appointments deleted, 2: number of appointments that could not be deleted */
553 __( '%1$d appointment(s) deleted. %2$d could not be deleted.', 'latepoint' ),
554 $deleted_count,
555 $failed_count
556 );
557 } else {
558 $status = LATEPOINT_STATUS_ERROR;
559 $message = sprintf(
560 /* translators: %d: number of appointments that could not be deleted */
561 _n( '%d appointment could not be deleted.', '%d appointments could not be deleted.', $failed_count, 'latepoint' ),
562 $failed_count
563 );
564 }
565
566 $this->send_json(
567 array(
568 'status' => $status,
569 'message' => $message,
570 'deleted_ids' => $deleted_ids,
571 'failed_ids' => $failed_ids,
572 'deleted_count' => $deleted_count,
573 'failed_count' => $failed_count,
574 )
575 );
576 }
577
578
579 function change_status() {
580
581 if ( filter_var( $this->params['id'], FILTER_VALIDATE_INT ) ) {
582 $this->check_nonce( 'change_status_booking_' . $this->params['id'] );
583 $booking_id = $this->params['id'];
584 $new_status = $this->params['status'];
585 $booking = new OsBookingModel( $booking_id );
586 if ( ! OsRolesHelper::can_user_make_action_on_model_record( $booking, 'edit' ) ) {
587 exit;
588 }
589
590 if ( $booking->update_status( $new_status ) ) {
591 $status = LATEPOINT_STATUS_SUCCESS;
592 $response_html = __( 'Appointment Status Updated', 'latepoint' );
593 } else {
594 $status = LATEPOINT_STATUS_ERROR;
595 $response_html = __( 'Error Updating Booking Status!', 'latepoint' ) . ' ' . implode( ',', $booking->get_error_messages() );
596 }
597 } else {
598 $status = LATEPOINT_STATUS_ERROR;
599 $response_html = __( 'Error Updating Booking Status! Invalid ID', 'latepoint' );
600 }
601
602 if ( $this->get_return_format() == 'json' ) {
603 $this->send_json(
604 array(
605 'status' => $status,
606 'message' => $response_html,
607 )
608 );
609 }
610 }
611 }
612
613 endif;
614