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 / customers_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 18 hours ago calendars_controller.php 3 months ago carts_controller.php 18 hours ago controller.php 3 months ago customer_cabinet_controller.php 2 months ago customers_controller.php 18 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 18 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 18 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 18 hours ago wizard_controller.php 1 week ago
customers_controller.php
624 lines
1 <?php
2 if ( ! defined( 'ABSPATH' ) ) {
3 exit; // Exit if accessed directly.
4 }
5
6
7 if ( ! class_exists( 'OsCustomersController' ) ) :
8
9
10 class OsCustomersController extends OsController {
11
12 function __construct() {
13 parent::__construct();
14
15
16 $this->views_folder = LATEPOINT_VIEWS_ABSPATH . 'customers/';
17 $this->vars['page_header'] = OsMenuHelper::get_menu_items_by_id( 'customers' );
18 $this->vars['breadcrumbs'][] = array(
19 'label' => __( 'Customers', 'latepoint' ),
20 'link' => OsRouterHelper::build_link( OsRouterHelper::build_route_name( 'customers', 'index' ) ),
21 );
22 }
23
24 public function destroy() {
25 if ( filter_var( $this->params['id'], FILTER_VALIDATE_INT ) ) {
26 $this->check_nonce( 'destroy_customer_' . $this->params['id'] );
27 $customer = new OsCustomerModel( $this->params['id'] );
28 if ( ! OsRolesHelper::can_user_make_action_on_model_record( $customer, 'delete' ) ) {
29 $status = LATEPOINT_STATUS_ERROR;
30 $response_html = __( 'Not Allowed', 'latepoint' );
31 } elseif ( $customer->delete() ) {
32 $status = LATEPOINT_STATUS_SUCCESS;
33 $response_html = __( 'Customer Removed', 'latepoint' );
34 } else {
35 $status = LATEPOINT_STATUS_ERROR;
36 $response_html = __( 'Error Removing Customer', 'latepoint' );
37 }
38 } else {
39 $status = LATEPOINT_STATUS_ERROR;
40 $response_html = __( 'Error Removing Customer', 'latepoint' );
41 }
42
43 if ( $this->get_return_format() == 'json' ) {
44 $this->send_json(
45 array(
46 'status' => $status,
47 'message' => $response_html,
48 )
49 );
50 }
51 }
52
53
54 public function view_customer_log() {
55
56 $customer = new OsCustomerModel( $this->params['customer_id'] );
57 if ( ! OsRolesHelper::can_user_make_action_on_model_record( $customer, 'view' ) ) {
58 $this->access_not_allowed();
59 return;
60 }
61
62 $activities = new OsActivityModel();
63 $activities = $activities->where( [ 'customer_id' => absint( $this->params['customer_id'] ) ] )->order_by( 'id desc' )->get_results_as_models();
64
65 $this->vars['customer'] = $customer;
66 $this->vars['activities'] = $activities;
67
68 $this->format_render( __FUNCTION__ );
69 }
70
71
72 public function quick_new() {
73 $customer = new OsCustomerModel();
74
75 $this->vars['customer'] = $customer;
76
77 $this->format_render( 'quick_edit' );
78 }
79
80 public function quick_edit() {
81 if ( ! filter_var( $this->params['customer_id'], FILTER_VALIDATE_INT ) ) {
82 $this->access_not_allowed();
83 }
84 $customer = new OsCustomerModel( $this->params['customer_id'] );
85 if ( ! OsRolesHelper::can_user_make_action_on_model_record( $customer, 'edit' ) ) {
86 $this->send_json(
87 array(
88 'status' => LATEPOINT_STATUS_ERROR,
89 'message' => __( 'Not Allowed', 'latepoint' ),
90 )
91 );
92 }
93
94 $this->vars['customer'] = $customer;
95
96 $this->format_render( __FUNCTION__ );
97 }
98
99
100 public function inline_edit_form() {
101 $selected_customer = new OsCustomerModel();
102 if ( isset( $this->params['customer_id'] ) ) {
103 $selected_customer->load_by_id( $this->params['customer_id'] );
104 }
105 $this->vars['default_fields_for_customer'] = OsSettingsHelper::get_default_fields_for_customer();
106 $this->vars['selected_customer'] = $selected_customer;
107 $this->format_render( __FUNCTION__ );
108 }
109
110 public function set_as_guest() {
111 // CSRF protection
112 $this->check_nonce( 'set_customer_as_guest_' . $this->params['id'] );
113
114 if ( filter_var( $this->params['id'], FILTER_VALIDATE_INT ) ) {
115 $customer = new OsCustomerModel( $this->params['id'] );
116 if ( ! OsRolesHelper::can_user_make_action_on_model_record( $customer, 'edit' ) ) {
117 $status = LATEPOINT_STATUS_ERROR;
118 $response_html = __( 'Not Allowed', 'latepoint' );
119 } elseif ( $customer->update_attributes( [ 'is_guest' => true ] ) ) {
120 $status = LATEPOINT_STATUS_SUCCESS;
121 $response_html = __( 'Customer is now allowed to book without password', 'latepoint' );
122 } else {
123 $status = LATEPOINT_STATUS_ERROR;
124 $response_html = $customer->get_error_messages();
125 }
126 } else {
127 $status = LATEPOINT_STATUS_ERROR;
128 $response_html = __( 'Error setting customer as guest', 'latepoint' );
129 }
130
131 if ( $this->get_return_format() == 'json' ) {
132 $this->send_json(
133 array(
134 'status' => $status,
135 'message' => $response_html,
136 )
137 );
138 }
139 }
140
141 /*
142 Edit customer
143 */
144
145 public function edit_form() {
146 $this->vars['page_header'] = __( 'Edit Customer', 'latepoint' );
147 $this->vars['breadcrumbs'][] = array(
148 'label' => __( 'Edit Customer', 'latepoint' ),
149 'link' => false,
150 );
151
152 if ( filter_var( $this->params['id'], FILTER_VALIDATE_INT ) ) {
153 // check if allowed to access
154 $customer = new OsCustomerModel();
155 $customer = $customer->where( [ LATEPOINT_TABLE_CUSTOMERS . '.id' => absint( $this->params['id'] ) ] )->filter_allowed_records()->set_limit( 1 )->get_results_as_models();
156 $this->vars['customer'] = $customer;
157 $this->vars['wp_users_for_select'] = OsWpUserHelper::get_wp_users_for_select();
158 }
159
160 $this->format_render( __FUNCTION__ );
161 }
162
163
164 public function query_for_booking_form() {
165 $query = trim( $this->params['query'] );
166 $sql_query = '%' . $query . '%';
167 $query = $this->params['query'];
168 $customers = new OsCustomerModel();
169 $this->vars['query'] = $query;
170 $this->vars['customers'] = $customers->where(
171 array(
172 'OR' => array(
173 'CONCAT (first_name, " ", last_name) LIKE ' => $sql_query,
174 'email LIKE' => $sql_query,
175 'phone LIKE' => $sql_query,
176 ),
177 )
178 )->set_limit( 20 )->order_by( 'first_name asc, last_name asc' )->get_results_as_models();
179
180 $this->format_render( __FUNCTION__ );
181 }
182
183
184 /*
185 Create customer
186 */
187
188 public function create() {
189 $this->check_nonce( 'new_customer' );
190 $customer = new OsCustomerModel();
191 // Security fix: Prevent mass assignment of wordpress_user_id by non-admin users.
192 // Use admin scope for backend panel users (admin, agent, custom roles), otherwise restrict to public fields.
193 $customer->set_data( $this->params['customer'], OsAuthHelper::get_current_user()->has_backend_access() ? LATEPOINT_PARAMS_SCOPE_ADMIN : LATEPOINT_PARAMS_SCOPE_PUBLIC );
194 if ( $customer->save() ) {
195 // translators: %s is the html of a customer edit link
196 $response_html = sprintf( __( 'Customer Created ID: %s', 'latepoint' ), '<span class="os-notification-link" ' . OsCustomerHelper::quick_customer_btn_html( $customer->id ) . '>' . $customer->id . '</span>' );
197 $status = LATEPOINT_STATUS_SUCCESS;
198 do_action( 'latepoint_customer_created', $customer );
199 } else {
200 $response_html = $customer->get_error_messages();
201 $status = LATEPOINT_STATUS_ERROR;
202 }
203 if ( $this->get_return_format() == 'json' ) {
204 $this->send_json(
205 array(
206 'status' => $status,
207 'message' => $response_html,
208 )
209 );
210 }
211 }
212
213
214 /*
215 Update customer
216 */
217
218 public function update() {
219 if ( isset( $this->params['customer']['id'] ) && filter_var( $this->params['customer']['id'], FILTER_VALIDATE_INT ) ) {
220 $this->check_nonce( 'edit_customer_' . $this->params['customer']['id'] );
221 $customer = new OsCustomerModel( $this->params['customer']['id'] );
222 if ( ! $customer || ! OsRolesHelper::can_user_make_action_on_model_record( $customer, 'edit' ) ) {
223 $response_html = __( 'Access Restricted', 'latepoint' );
224 $status = LATEPOINT_STATUS_ERROR;
225 } else {
226 $old_customer_data = $customer->get_data_vars();
227 // Security fix: Prevent mass assignment of wordpress_user_id by non-admin users.
228 // Use admin scope for backend panel users (admin, agent, custom roles), otherwise restrict to public fields.
229 $customer->set_data( $this->params['customer'], OsAuthHelper::get_current_user()->has_backend_access() ? LATEPOINT_PARAMS_SCOPE_ADMIN : LATEPOINT_PARAMS_SCOPE_PUBLIC );
230 if ( $customer->save() ) {
231 // translators: %s is the html of a customer edit link
232 $response_html = sprintf( __( 'Customer Updated ID: %s', 'latepoint' ), '<span class="os-notification-link" ' . OsCustomerHelper::quick_customer_btn_html( $customer->id ) . '>' . $customer->id . '</span>' );
233 $status = LATEPOINT_STATUS_SUCCESS;
234 do_action( 'latepoint_customer_updated', $customer, $old_customer_data );
235 } else {
236 $response_html = $customer->get_error_messages();
237 $status = LATEPOINT_STATUS_ERROR;
238 }
239 }
240 } else {
241 $response_html = __( 'Invalid customer ID', 'latepoint' );
242 $status = LATEPOINT_STATUS_ERROR;
243 }
244 if ( $this->get_return_format() == 'json' ) {
245 $this->send_json(
246 array(
247 'status' => $status,
248 'message' => $response_html,
249 )
250 );
251 }
252 }
253
254 public function mini_profile() {
255 if ( filter_var( $this->params['customer_id'], FILTER_VALIDATE_INT ) ) {
256 $customer = new OsCustomerModel( $this->params['customer_id'] );
257 $this->vars['upcoming_booking'] = $customer->get_future_bookings( 1, true );
258 $this->vars['customer'] = $customer;
259
260
261 $pie_labels = [];
262 $pie_colors = [];
263 $pie_values = [];
264 $pie_chart_data = OsBookingHelper::get_stat(
265 'bookings',
266 [
267 'group_by' => 'status',
268 'customer_id' => $customer->id,
269 ]
270 );
271 $colors = [ '#2752E4', '#C066F1', '#26B7DD', '#E8C634', '#19CED6', '#2FEAA3', '#252a3e', '#8d87a5', '#b9b784' ];
272 $status_colors = [
273 LATEPOINT_BOOKING_STATUS_APPROVED => '#35d893',
274 LATEPOINT_BOOKING_STATUS_PENDING => '#e6b935',
275 LATEPOINT_BOOKING_STATUS_PAYMENT_PENDING => '#4ca4ef',
276 LATEPOINT_BOOKING_STATUS_CANCELLED => '#f1585d',
277 ];
278 $i = 0;
279 foreach ( $pie_chart_data as $pie_data ) {
280 $pie_labels[] = $pie_data['status'];
281 $pie_colors[] = isset( $status_colors[ $pie_data['status'] ] ) ? $status_colors[ $pie_data['status'] ] : $colors[ $i ];
282 $pie_values[] = $pie_data['stat'];
283 $i++;
284 }
285
286 $this->vars['pie_chart_data'] = [
287 'labels' => $pie_labels,
288 'colors' => $pie_colors,
289 'values' => $pie_values,
290 ];
291
292
293 $this->set_layout( 'none' );
294 $response_html = $this->format_render_return( __FUNCTION__ );
295 } else {
296 $status = LATEPOINT_STATUS_ERROR;
297 $response_html = __( 'Error Accessing Customer', 'latepoint' );
298 }
299
300 if ( $this->get_return_format() == 'json' ) {
301 $this->send_json(
302 array(
303 'status' => $status,
304 'message' => $response_html,
305 )
306 );
307 }
308 }
309
310 public function connect_all_to_wp_users() {
311 // CSRF protection
312 $this->check_nonce( 'connect_all_customers_to_wp_users' );
313
314 $customers = new OsCustomerModel();
315 $customers = $customers->where( [ 'wordpress_user_id' => [ 'OR' => [ 0, 'IS NULL' ] ] ] )->get_results_as_models();
316 if ( $customers ) {
317 foreach ( $customers as $customer ) {
318 $wp_user_id = OsCustomerHelper::create_wp_user_for_customer( $customer );
319 if ( $wp_user_id ) {
320 //check if wp user already connected to another customer
321 $connected_customer = new OsCustomerModel();
322 $connected_customer = $connected_customer->where( [ 'wordpress_user_id' => $wp_user_id ] )->set_limit( 1 )->get_results_as_models();
323 if ( ! $connected_customer ) {
324 $customer->update_attributes( [ 'wordpress_user_id' => $wp_user_id ] );
325 }
326 }
327 }
328 }
329
330 if ( $this->get_return_format() == 'json' ) {
331 $this->send_json(
332 array(
333 'status' => LATEPOINT_STATUS_SUCCESS,
334 'message' => __( 'Customers Connected', 'latepoint' ),
335 )
336 );
337 }
338 }
339
340 public function disconnect_from_wp_user() {
341 // CSRF protection
342 $this->check_nonce( 'disconnect_customer_from_wp_user_' . $this->params['customer_id'] );
343
344 $customer_id = $this->params['customer_id'];
345 $customer = new OsCustomerModel();
346 $customer = $customer->where( [ 'id' => $customer_id ] )->set_limit( 1 )->get_results_as_models();
347 if ( $customer ) {
348 if ( ! OsRolesHelper::can_user_make_action_on_model_record( $customer, 'edit' ) ) {
349 $this->send_json(
350 array(
351 'status' => LATEPOINT_STATUS_ERROR,
352 'message' => __( 'Not Allowed', 'latepoint' ),
353 )
354 );
355 }
356 $customer->update_attributes( [ 'wordpress_user_id' => null ] );
357 }
358 if ( $this->get_return_format() == 'json' ) {
359 $this->send_json(
360 array(
361 'status' => LATEPOINT_STATUS_SUCCESS,
362 'message' => __( 'Customer Disconnected', 'latepoint' ),
363 )
364 );
365 }
366 }
367
368 public function connect_to_wp_user() {
369 // CSRF protection
370 $this->check_nonce( 'connect_customer_to_wp_user_' . $this->params['customer_id'] );
371
372 $customer_id = $this->params['customer_id'];
373 $customer = new OsCustomerModel();
374 $customer = $customer->where( [ 'id' => $customer_id ] )->set_limit( 1 )->get_results_as_models();
375 if ( $customer ) {
376 if ( ! OsRolesHelper::can_user_make_action_on_model_record( $customer, 'edit' ) ) {
377 $this->send_json(
378 array(
379 'status' => LATEPOINT_STATUS_ERROR,
380 'message' => __( 'Not Allowed', 'latepoint' ),
381 )
382 );
383 }
384 if ( ! $customer->wordpress_user_id ) {
385 $wp_user = OsCustomerHelper::create_wp_user_for_customer( $customer );
386 }
387 }
388 if ( $this->get_return_format() == 'json' ) {
389 $this->send_json(
390 array(
391 'status' => LATEPOINT_STATUS_SUCCESS,
392 'message' => __( 'Customer Connected', 'latepoint' ),
393 )
394 );
395 }
396 }
397
398
399 public function index() {
400 $this->vars['page_header'] = false;
401 $page_number = isset( $this->params['page_number'] ) ? $this->params['page_number'] : 1;
402 $per_page = OsSettingsHelper::get_number_of_records_per_page();
403 $offset = ( $page_number > 1 ) ? ( ( $page_number - 1 ) * $per_page ) : 0;
404
405
406 $customers = new OsCustomerModel();
407 $query_args = [];
408
409 $filter = isset( $this->params['filter'] ) ? $this->params['filter'] : false;
410
411 // TABLE SEARCH FILTERS
412 if ( $filter ) {
413 if ( $filter['id'] ) {
414 $query_args['id'] = $filter['id'];
415 }
416 if ( $filter['registration_date_from'] && $filter['registration_date_to'] ) {
417 $query_args[ LATEPOINT_TABLE_CUSTOMERS . '.created_at >=' ] = $filter['registration_date_from'];
418 $query_args[ LATEPOINT_TABLE_CUSTOMERS . '.created_at <=' ] = $filter['registration_date_to'];
419 }
420 if ( $filter['customer'] ) {
421 $query_args[ 'concat_ws(" ", ' . LATEPOINT_TABLE_CUSTOMERS . '.first_name,' . LATEPOINT_TABLE_CUSTOMERS . '.last_name) LIKE' ] = '%' . $filter['customer'] . '%';
422 $this->vars['customer_name_query'] = $filter['customer'];
423 }
424 if ( $filter['phone'] ) {
425 $query_args['phone LIKE'] = '%' . $filter['phone'] . '%';
426 $this->vars['phone_query'] = $filter['phone'];
427 }
428 if ( $filter['email'] ) {
429 $query_args['email LIKE'] = '%' . $filter['email'] . '%';
430 $this->vars['email_query'] = $filter['email'];
431 }
432 }
433
434
435 // OUTPUT CSV IF REQUESTED
436 if ( isset( $this->params['download'] ) && $this->params['download'] == 'csv' ) {
437 // CSRF protection
438 $this->check_nonce( 'customers_csv_export' );
439
440 $csv_filename = 'customers_' . OsUtilHelper::random_text();
441
442 header( 'Content-Type: text/csv' );
443 header( "Content-Disposition: attachment; filename={$csv_filename}.csv" );
444
445 $labels_row = [
446 __( 'ID', 'latepoint' ),
447 __( 'Name', 'latepoint' ),
448 __( 'Phone', 'latepoint' ),
449 __( 'Email', 'latepoint' ),
450 __( 'Total Appointments', 'latepoint' ),
451 __( 'Next Appointment', 'latepoint' ),
452 __( 'Registered On', 'latepoint' ),
453 ];
454
455
456 $customers_data = [];
457 $customers_data[] = $labels_row;
458
459
460 $customers_arr = $customers->where( $query_args )->filter_allowed_records()->order_by( 'id desc' )->get_results_as_models();
461 if ( $customers_arr ) {
462 foreach ( $customers_arr as $customer ) {
463 $next_booking = $customer->get_future_bookings( 1, true );
464 $values_row = [
465 $customer->id,
466 $customer->full_name,
467 $customer->phone,
468 $customer->email,
469 $customer->total_bookings_count,
470 $next_booking ? $next_booking->nice_start_datetime : 'n/a',
471 $customer->formatted_created_date(),
472 ];
473 $values_row = apply_filters( 'latepoint_customer_row_for_csv_export', $values_row, $customer, $this->params );
474 $customers_data[] = $values_row;
475 }
476 }
477 $customers_data = apply_filters( 'latepoint_customers_data_for_csv_export', $customers_data, $this->params );
478 OsCSVHelper::array_to_csv( $customers_data );
479
480 return;
481 }
482
483 $customers->where( $query_args )->filter_allowed_records();
484 $count_total_customers = clone $customers;
485
486 $total_customers = $count_total_customers->count();
487 $total_pages = ceil( $total_customers / $per_page );
488
489
490 $this->vars['customers_violating_auth_rules'] = OsAuthHelper::count_total_customers_violating_auth_rules();
491
492 $this->vars['customers'] = $customers->set_limit( $per_page )->set_offset( $offset )->order_by( 'id desc' )->get_results_as_models();
493 $this->vars['total_customers'] = $total_customers;
494
495 $this->vars['total_pages'] = ceil( $total_customers / $per_page );
496 $this->vars['per_page'] = $per_page;
497 $this->vars['current_page_number'] = $page_number;
498
499 $this->vars['showing_from'] = ( ( $page_number - 1 ) * $per_page ) ? ( ( $page_number - 1 ) * $per_page ) : 1;
500 $this->vars['showing_to'] = min( $page_number * $per_page, $this->vars['total_customers'] );
501
502 $this->format_render(
503 [
504 'json_view_name' => '_table_body',
505 'html_view_name' => __FUNCTION__,
506 ],
507 [],
508 [
509 'total_pages' => $total_pages,
510 'showing_from' => $this->vars['showing_from'],
511 'showing_to' => $this->vars['showing_to'],
512 'total_records' => $total_customers,
513 ]
514 );
515 }
516
517
518 public function import_csv_modal() {
519 $current_step = $this->params['step'] ?? 'upload_csv';
520 $steps = [
521 'upload_csv' => [ 'next_step' => 'mapping' ],
522 'mapping' => [ 'next_step' => 'importing' ],
523 ];
524 $this->vars['current_step'] = $current_step;
525 $this->vars['next_step'] = array_key_exists( $current_step, $steps ) ? $steps[ $current_step ]['next_step'] : 'upload_csv';
526 $this->format_render( __FUNCTION__ );
527 }
528
529 public function import_load_step() {
530 $this->check_nonce( 'import_customers_csv' );
531 $current_step = $this->params['step'] ?? 'upload_csv';
532 $status = LATEPOINT_STATUS_SUCCESS;
533
534 try {
535 switch ( $current_step ) {
536 case 'upload_csv':
537 $response_html = $this->_handle_upload_step();
538 break;
539
540 case 'mapping':
541 $response_html = $this->_handle_mapping_step();
542 break;
543
544 case 'confirmation':
545 $response_html = $this->_handleConfirmationStep();
546 break;
547
548 default:
549 throw new Exception( 'Invalid step provided' );
550 }
551 } catch ( Exception $e ) {
552 $response_html = $e->getMessage();
553 $status = LATEPOINT_STATUS_ERROR;
554 }
555
556 $this->send_json(
557 array(
558 'status' => $status,
559 'message' => $response_html,
560 )
561 );
562 }
563
564 private function _handle_upload_step(): string {
565 $file_path = OsCSVHelper::upload_csv_file( $this->files, 'latepoint_customers_csv' );
566 $csv_data = OsCSVHelper::get_csv_data( $file_path, 1 );
567
568 return $this->render(
569 $this->views_folder . 'import_steps/step_mapping.php',
570 'none',
571 [
572 'csv_data' => $csv_data,
573 ]
574 );
575 }
576
577 private function _handle_mapping_step(): string {
578 $columnMapping = $this->params['latepoint_column_mapping'] ?? [];
579
580 if ( ! OsCustomerImportHelper::validate_import_mapping( $columnMapping ) ) {
581 throw new Exception( esc_html__( 'Email field is required', 'latepoint' ) );
582 }
583
584 $csv_data = OsCSVHelper::get_csv_data( OsCustomerImportHelper::get_import_tmp_filepath() );
585 $validation_result = OsCustomerImportHelper::validate_csv_data( $csv_data, $columnMapping );
586
587 return $this->render(
588 $this->views_folder . 'import_steps/step_confirmation.php',
589 'none',
590 [
591 'conflicts' => $validation_result['conflicts'],
592 'can_be_imported' => $validation_result['importable_count'],
593 'latepoint_column_mapping' => $columnMapping,
594 ]
595 );
596 }
597
598
599 private function _handleConfirmationStep(): string {
600 $update_existing_customers = ! empty( $this->params['latepoint_update_customers_acknowledgement'] ) && OsUtilHelper::is_on( $this->params['latepoint_update_customers_acknowledgement'] );
601 $column_mapping = ! empty( $this->params['latepoint_column_mapping'] ) ? json_decode( $this->params['latepoint_column_mapping'], true ) : [];
602
603 $file_path = OsCustomerImportHelper::get_import_tmp_filepath();
604 $csv_data = OsCSVHelper::get_csv_data( $file_path );
605
606 $importResult = OsCustomerImportHelper::import_customers( $csv_data, $column_mapping, $update_existing_customers );
607
608 // Cleanup after successful import
609 OsCustomerImportHelper::cleanup_stored_file();
610
611 return $this->render(
612 $this->views_folder . 'import_steps/step_done.php',
613 'none',
614 [
615 'skipped_records' => $importResult['skipped_count'],
616 'updated_records' => $importResult['updated_count'],
617 ]
618 );
619 }
620 }
621
622
623 endif;
624