activity_model.php
3 months ago
agent_meta_model.php
3 months ago
agent_model.php
3 months ago
booking_meta_model.php
3 months ago
booking_model.php
21 hours ago
bundle_meta_model.php
3 months ago
bundle_model.php
1 week ago
cart_item_model.php
3 months ago
cart_meta_model.php
3 months ago
cart_model.php
2 weeks ago
connector_model.php
3 months ago
customer_meta_model.php
3 months ago
customer_model.php
1 month ago
invoice_model.php
2 weeks ago
join_bundles_services_model.php
3 months ago
location_category_model.php
3 months ago
location_model.php
3 months ago
meta_model.php
3 months ago
model.php
2 days ago
off_period_model.php
3 months ago
order_intent_meta_model.php
3 months ago
order_intent_model.php
1 week ago
order_item_model.php
3 months ago
order_meta_model.php
3 months ago
order_model.php
1 month ago
otp_model.php
3 months ago
payment_request_model.php
3 months ago
process_job_model.php
3 months ago
process_model.php
1 month ago
recurrence_model.php
3 months ago
service_category_model.php
3 months ago
service_meta_model.php
3 months ago
service_model.php
3 months ago
session_model.php
3 months ago
settings_model.php
3 months ago
step_settings_model.php
3 months ago
transaction_intent_model.php
3 months ago
transaction_model.php
3 months ago
transaction_refund_model.php
3 months ago
work_period_model.php
3 months ago
agent_model.php
499 lines
| 1 | <?php |
| 2 | |
| 3 | /** |
| 4 | * @property string $full_name |
| 5 | */ |
| 6 | class OsAgentModel extends OsModel { |
| 7 | public $id, |
| 8 | $first_name = '', |
| 9 | $last_name = '', |
| 10 | $display_name, |
| 11 | $email, |
| 12 | $phone, |
| 13 | $password, |
| 14 | $avatar_image_id, |
| 15 | $bio_image_id, |
| 16 | $is_custom_price = false, |
| 17 | $is_custom_hours = false, |
| 18 | $is_custom_duration = false, |
| 19 | $custom_hours, |
| 20 | $wp_user_id, |
| 21 | $title, |
| 22 | $bio, |
| 23 | $features, |
| 24 | $extra_emails, |
| 25 | $extra_phones, |
| 26 | $status, |
| 27 | $meta_class = 'OsAgentMetaModel', |
| 28 | $updated_at, |
| 29 | $created_at, |
| 30 | $services_agents_table_name; |
| 31 | |
| 32 | function __construct( $id = false ) { |
| 33 | parent::__construct(); |
| 34 | $this->table_name = LATEPOINT_TABLE_AGENTS; |
| 35 | $this->services_agents_table_name = LATEPOINT_TABLE_AGENTS_SERVICES; |
| 36 | $this->nice_names = array( |
| 37 | 'first_name' => __( 'First Name', 'latepoint' ), |
| 38 | 'password' => __( 'Password', 'latepoint' ), |
| 39 | 'email' => __( 'Email Address', 'latepoint' ), |
| 40 | 'wp_user_id' => __( 'Connected WordPress User', 'latepoint' ), |
| 41 | 'last_name' => __( 'Last Name', 'latepoint' ), |
| 42 | ); |
| 43 | |
| 44 | if ( $id ) { |
| 45 | $this->load_by_id( $id ); |
| 46 | } |
| 47 | } |
| 48 | |
| 49 | |
| 50 | public function get_initials() { |
| 51 | return mb_substr( $this->first_name, 0, 1 ) . mb_substr( $this->last_name, 0, 1 ); |
| 52 | } |
| 53 | |
| 54 | public function get_edit_link() { |
| 55 | return OsRouterHelper::build_link( [ 'agents', 'edit_form' ], [ 'id' => $this->id ] ); |
| 56 | } |
| 57 | |
| 58 | public function generate_data_vars(): array { |
| 59 | return [ |
| 60 | 'id' => $this->id, |
| 61 | 'full_name' => $this->full_name, |
| 62 | 'email' => $this->email, |
| 63 | 'phone' => $this->phone, |
| 64 | ]; |
| 65 | } |
| 66 | |
| 67 | protected function params_to_save( $role = 'admin' ) { |
| 68 | $params_to_save = array( |
| 69 | 'id', |
| 70 | 'first_name', |
| 71 | 'last_name', |
| 72 | 'display_name', |
| 73 | 'email', |
| 74 | 'phone', |
| 75 | 'password', |
| 76 | 'wp_user_id', |
| 77 | 'bio_image_id', |
| 78 | 'title', |
| 79 | 'bio', |
| 80 | 'features', |
| 81 | 'status', |
| 82 | 'extra_emails', |
| 83 | 'extra_phones', |
| 84 | 'avatar_image_id', |
| 85 | 'custom_hours', |
| 86 | ); |
| 87 | return $params_to_save; |
| 88 | } |
| 89 | |
| 90 | protected function allowed_params( $role = 'admin' ) { |
| 91 | $allowed_params = array( |
| 92 | 'id', |
| 93 | 'first_name', |
| 94 | 'last_name', |
| 95 | 'display_name', |
| 96 | 'email', |
| 97 | 'phone', |
| 98 | 'password', |
| 99 | 'wp_user_id', |
| 100 | 'bio_image_id', |
| 101 | 'title', |
| 102 | 'bio', |
| 103 | 'features', |
| 104 | 'extra_emails', |
| 105 | 'extra_phones', |
| 106 | 'status', |
| 107 | 'avatar_image_id', |
| 108 | 'custom_hours', |
| 109 | ); |
| 110 | return $allowed_params; |
| 111 | } |
| 112 | |
| 113 | |
| 114 | protected function properties_to_validate() { |
| 115 | $validations = array( |
| 116 | 'email' => array( 'presence' ), |
| 117 | 'wp_user_id' => array( 'uniqueness' ), |
| 118 | ); |
| 119 | return $validations; |
| 120 | } |
| 121 | |
| 122 | |
| 123 | public function count_number_of_connected_locations( $service_id = false ) { |
| 124 | if ( $this->is_new_record() ) { |
| 125 | return 0; |
| 126 | } |
| 127 | $args = [ 'agent_id' => $this->id ]; |
| 128 | if ( $service_id ) { |
| 129 | $args['service_id'] = $service_id; |
| 130 | } |
| 131 | return OsConnectorHelper::count_connections( $args, 'location_id' ); |
| 132 | } |
| 133 | |
| 134 | public function delete_meta_by_key( $meta_key ) { |
| 135 | if ( $this->is_new_record() ) { |
| 136 | return false; |
| 137 | } |
| 138 | |
| 139 | $meta = new OsAgentMetaModel(); |
| 140 | return $meta->delete_by_key( $meta_key, $this->id ); |
| 141 | } |
| 142 | |
| 143 | public function get_meta_by_key( $meta_key, $default = false ) { |
| 144 | if ( $this->is_new_record() ) { |
| 145 | return $default; |
| 146 | } |
| 147 | |
| 148 | $meta = new OsAgentMetaModel(); |
| 149 | return $meta->get_by_key( $meta_key, $this->id, $default ); |
| 150 | } |
| 151 | |
| 152 | public function save_meta_by_key( $meta_key, $meta_value ) { |
| 153 | if ( $this->is_new_record() ) { |
| 154 | return false; |
| 155 | } |
| 156 | |
| 157 | $meta = new OsAgentMetaModel(); |
| 158 | return $meta->save_by_key( $meta_key, $meta_value, $this->id ); |
| 159 | } |
| 160 | |
| 161 | protected function set_defaults() { |
| 162 | if ( empty( $this->status ) ) { |
| 163 | $this->status = LATEPOINT_AGENT_STATUS_ACTIVE; |
| 164 | } |
| 165 | } |
| 166 | |
| 167 | public function has_location( $location_id ) { |
| 168 | return OsConnectorHelper::has_connection( |
| 169 | [ |
| 170 | 'agent_id' => $this->id, |
| 171 | 'location_id' => $location_id, |
| 172 | ] |
| 173 | ); |
| 174 | } |
| 175 | |
| 176 | |
| 177 | protected function get_total_future_bookings() { |
| 178 | $bookings = new OsBookingModel(); |
| 179 | $total = $bookings->where( [ 'agent_id' => $this->id ] )->should_be_in_future()->count(); |
| 180 | return $total; |
| 181 | } |
| 182 | |
| 183 | protected function get_total_synced_future_bookings() { |
| 184 | $bookings = new OsBookingModel(); |
| 185 | $total = $bookings->where( |
| 186 | [ |
| 187 | 'agent_id' => $this->id, |
| 188 | LATEPOINT_TABLE_BOOKING_META . '.meta_key' => 'google_calendar_event_id', |
| 189 | ] |
| 190 | ) |
| 191 | ->join( LATEPOINT_TABLE_BOOKING_META, [ 'object_id' => LATEPOINT_TABLE_BOOKINGS . '.id' ] ) |
| 192 | ->should_be_in_future() |
| 193 | ->count(); |
| 194 | return $total; |
| 195 | } |
| 196 | |
| 197 | protected function get_future_bookings( $limit = false ) { |
| 198 | $bookings = new OsBookingModel(); |
| 199 | if ( $limit ) { |
| 200 | $bookings = $bookings->set_limit( $limit ); |
| 201 | } |
| 202 | return $bookings->order_by( 'start_date, start_time asc' )->where( [ 'agent_id' => $this->id ] )->should_be_in_future()->get_results_as_models(); |
| 203 | } |
| 204 | |
| 205 | public function should_be_active() { |
| 206 | return $this->where( [ 'status !=' => LATEPOINT_AGENT_STATUS_DISABLED ] ); |
| 207 | } |
| 208 | |
| 209 | public function has_service_and_location( $service_id, $location_id ) { |
| 210 | if ( $this->is_new_record() ) { |
| 211 | return false; |
| 212 | } |
| 213 | return OsConnectorHelper::has_connection( |
| 214 | [ |
| 215 | 'location_id' => $location_id, |
| 216 | 'agent_id' => $this->id, |
| 217 | 'service_id' => $service_id, |
| 218 | ] |
| 219 | ); |
| 220 | } |
| 221 | |
| 222 | public function get_features_arr() { |
| 223 | $features_arr = []; |
| 224 | if ( ! empty( $this->features ) ) { |
| 225 | $features = json_decode( $this->features, true ); |
| 226 | if ( ! empty( $features ) ) { |
| 227 | foreach ( $features as $feature ) { |
| 228 | if ( $feature['value'] && $feature['label'] ) { |
| 229 | $features_arr[] = $feature; |
| 230 | } |
| 231 | } |
| 232 | } |
| 233 | } |
| 234 | return $features_arr; |
| 235 | } |
| 236 | |
| 237 | public function save_custom_schedule( $work_periods, int $location_id = 0 ) { |
| 238 | foreach ( $work_periods as &$work_period ) { |
| 239 | $work_period['agent_id'] = $this->id; |
| 240 | $work_period['location_id'] = $location_id; |
| 241 | } |
| 242 | unset( $work_period ); |
| 243 | OsWorkPeriodsHelper::save_work_periods( $work_periods ); |
| 244 | } |
| 245 | |
| 246 | public function delete_custom_schedule( int $location_id = 0 ) { |
| 247 | $work_periods_model = new OsWorkPeriodModel(); |
| 248 | $work_periods = $work_periods_model->where( |
| 249 | array( |
| 250 | 'agent_id' => $this->id, |
| 251 | 'service_id' => 0, |
| 252 | 'location_id' => $location_id, |
| 253 | 'custom_date' => 'IS NULL', |
| 254 | ) |
| 255 | )->get_results_as_models(); |
| 256 | if ( is_array( $work_periods ) ) { |
| 257 | foreach ( $work_periods as $work_period ) { |
| 258 | $work_period->delete(); |
| 259 | } |
| 260 | } |
| 261 | } |
| 262 | |
| 263 | public function has_service( $service_id ) { |
| 264 | foreach ( $this->services as $service ) { |
| 265 | if ( $service->id == $service_id ) { |
| 266 | return true; |
| 267 | } |
| 268 | } |
| 269 | return false; |
| 270 | } |
| 271 | |
| 272 | |
| 273 | public function save_services() { |
| 274 | foreach ( $this->services as $service ) { |
| 275 | $service_connection_row = $this->db->get_row( $this->db->prepare( 'SELECT id FROM ' . $this->services_agents_table_name . ' WHERE agent_id = %d AND service_id = %d', array( $this->id, $service->id ) ) ); |
| 276 | if ( $service_connection_row ) { |
| 277 | $update_data = array( |
| 278 | 'is_custom_hours' => $service->is_custom_hours, |
| 279 | 'is_custom_price' => $service->is_custom_price, |
| 280 | 'is_custom_duration' => $service->is_custom_duration, |
| 281 | ); |
| 282 | $this->db->update( $this->services_agents_table_name, $update_data, array( 'id' => $service_connection_row->id ) ); |
| 283 | } else { |
| 284 | $insert_data = array( |
| 285 | 'service_id' => $service->id, |
| 286 | 'agent_id' => $this->id, |
| 287 | 'is_custom_hours' => $service->is_custom_hours, |
| 288 | 'is_custom_price' => $service->is_custom_price, |
| 289 | 'is_custom_duration' => $service->is_custom_duration, |
| 290 | ); |
| 291 | if ( $this->db->insert( $this->services_agents_table_name, $insert_data ) ) { |
| 292 | $service_connection_row_id = $this->db->insert_id; |
| 293 | } |
| 294 | } |
| 295 | } |
| 296 | return true; |
| 297 | } |
| 298 | |
| 299 | |
| 300 | public function remove_services_by_ids( $ids_to_remove = array() ) { |
| 301 | if ( $ids_to_remove ) { |
| 302 | $query = $this->db->prepare( 'DELETE FROM %i WHERE agent_id = %d AND service_id IN ' . OsModel::where_in_array_to_string( $ids_to_remove ), [ $this->services_agents_table_name, $this->id ] ); |
| 303 | $this->db->query( $query ); |
| 304 | } |
| 305 | } |
| 306 | |
| 307 | |
| 308 | public function get_service_ids_to_remove( $new_services = array() ) { |
| 309 | $current_service_ids = $this->get_current_service_ids_from_db(); |
| 310 | $new_service_ids = array(); |
| 311 | foreach ( $new_services as $service ) { |
| 312 | if ( $service['connected'] == 'yes' ) { |
| 313 | $new_service_ids[] = $service['id']; |
| 314 | } |
| 315 | } |
| 316 | $service_ids_to_remove = array_diff( $current_service_ids, $new_service_ids ); |
| 317 | return $service_ids_to_remove; |
| 318 | } |
| 319 | |
| 320 | |
| 321 | public function save_locations_and_services( $services ) { |
| 322 | if ( ! $services ) { |
| 323 | return true; |
| 324 | } |
| 325 | $connections_to_save = []; |
| 326 | $connections_to_remove = []; |
| 327 | foreach ( $services as $service_key => $locations ) { |
| 328 | $service_id = str_replace( 'service_', '', $service_key ); |
| 329 | foreach ( $locations as $location_key => $location ) { |
| 330 | $location_id = str_replace( 'location_', '', $location_key ); |
| 331 | $connection = [ |
| 332 | 'service_id' => $service_id, |
| 333 | 'agent_id' => $this->id, |
| 334 | 'location_id' => $location_id, |
| 335 | ]; |
| 336 | if ( $location['connected'] == 'yes' ) { |
| 337 | $connections_to_save[] = $connection; |
| 338 | } else { |
| 339 | $connections_to_remove[] = $connection; |
| 340 | } |
| 341 | } |
| 342 | } |
| 343 | if ( ! empty( $connections_to_save ) ) { |
| 344 | foreach ( $connections_to_save as $connection_to_save ) { |
| 345 | OsConnectorHelper::save_connection( $connection_to_save ); |
| 346 | } |
| 347 | } |
| 348 | if ( ! empty( $connections_to_remove ) ) { |
| 349 | foreach ( $connections_to_remove as $connection_to_remove ) { |
| 350 | OsConnectorHelper::remove_connection( $connection_to_remove ); |
| 351 | } |
| 352 | // Clean up location-specific schedules for fully disconnected locations |
| 353 | $cleaned_location_ids = []; |
| 354 | foreach ( $connections_to_remove as $conn ) { |
| 355 | $loc_id = (int) $conn['location_id']; |
| 356 | if ( $loc_id > 0 && ! in_array( $loc_id, $cleaned_location_ids ) ) { |
| 357 | if ( ! $this->has_location( $loc_id ) ) { |
| 358 | $this->delete_custom_schedule( $loc_id ); |
| 359 | $wp_model = new OsWorkPeriodModel(); |
| 360 | $wp_model->delete_where( |
| 361 | [ |
| 362 | 'agent_id' => $this->id, |
| 363 | 'location_id' => $loc_id, |
| 364 | ] |
| 365 | ); |
| 366 | $cleaned_location_ids[] = $loc_id; |
| 367 | } |
| 368 | } |
| 369 | } |
| 370 | } |
| 371 | return true; |
| 372 | } |
| 373 | |
| 374 | public function set_features( $features ) { |
| 375 | $this->features = wp_json_encode( $features ); |
| 376 | } |
| 377 | |
| 378 | public function get_current_service_ids_from_db() { |
| 379 | $query = $this->db->prepare( 'SELECT service_id FROM ' . $this->services_agents_table_name . ' WHERE agent_id = %d', $this->id ); |
| 380 | $service_rows = $this->db->get_results( $query ); |
| 381 | |
| 382 | $service_ids = array(); |
| 383 | |
| 384 | if ( $service_rows ) { |
| 385 | foreach ( $service_rows as $service_row ) { |
| 386 | $service_ids[] = $service_row->service_id; |
| 387 | } |
| 388 | } |
| 389 | return $service_ids; |
| 390 | } |
| 391 | |
| 392 | |
| 393 | public function get_current_service_ids() { |
| 394 | $service_ids = array(); |
| 395 | foreach ( $this->services as $service ) { |
| 396 | $service_ids[] = $service->id; |
| 397 | } |
| 398 | return $service_ids; |
| 399 | } |
| 400 | |
| 401 | public function set_services( $service_datas ) { |
| 402 | $this->services = array(); |
| 403 | |
| 404 | foreach ( $service_datas as $service_data ) { |
| 405 | if ( $service_data['connected'] == 'yes' ) { |
| 406 | $service = new OsserviceModel(); |
| 407 | $service->id = $service_data['id']; |
| 408 | $service->is_custom_hours = $service_data['is_custom_hours']; |
| 409 | $service->is_custom_price = $service_data['is_custom_price']; |
| 410 | $service->is_custom_duration = $service_data['is_custom_duration']; |
| 411 | $this->services[] = $service; |
| 412 | } |
| 413 | } |
| 414 | return $this; |
| 415 | } |
| 416 | |
| 417 | public function filter_allowed_records(): OsModel { |
| 418 | if ( ! OsRolesHelper::are_all_records_allowed( 'agent' ) ) { |
| 419 | $this->filter_where_conditions( [ 'id' => OsRolesHelper::get_allowed_records( 'agent' ) ] ); |
| 420 | } |
| 421 | return $this; |
| 422 | } |
| 423 | |
| 424 | public function get_services() { |
| 425 | if ( ! isset( $this->services ) ) { |
| 426 | $query = 'SELECT * FROM ' . $this->services_agents_table_name . ' WHERE agent_id = %d GROUP BY service_id'; |
| 427 | $query_args = array( $this->id ); |
| 428 | $services_rows = $this->get_query_results( $query, $query_args ); |
| 429 | |
| 430 | $this->services = array(); |
| 431 | |
| 432 | if ( $services_rows ) { |
| 433 | foreach ( $services_rows as $service_row ) { |
| 434 | $service = new OsServiceModel( $service_row->service_id ); |
| 435 | $service->is_custom_hours = $service_row->is_custom_hours; |
| 436 | $service->is_custom_price = $service_row->is_custom_price; |
| 437 | $service->is_custom_duration = $service_row->is_custom_duration; |
| 438 | $this->services[] = $service; |
| 439 | } |
| 440 | } |
| 441 | } |
| 442 | return $this->services; |
| 443 | } |
| 444 | |
| 445 | |
| 446 | protected function before_create() { |
| 447 | if ( empty( $this->password ) ) { |
| 448 | $this->password = wp_hash_password( bin2hex( openssl_random_pseudo_bytes( 8 ) ) ); |
| 449 | } |
| 450 | } |
| 451 | |
| 452 | protected function before_save() { |
| 453 | } |
| 454 | |
| 455 | public function get_full_name() { |
| 456 | $full_name = trim( join( ' ', array( $this->first_name, $this->last_name ) ) ); |
| 457 | return empty( $full_name ) ? __( 'Agent', 'latepoint' ) : $full_name; |
| 458 | } |
| 459 | |
| 460 | protected function get_name_for_front() { |
| 461 | if ( isset( $this->display_name ) && ! empty( $this->display_name ) ) { |
| 462 | return $this->display_name; |
| 463 | } else { |
| 464 | return $this->get_full_name(); |
| 465 | } |
| 466 | } |
| 467 | |
| 468 | public function get_avatar_url() { |
| 469 | return OsAgentHelper::get_avatar_url( $this ); |
| 470 | } |
| 471 | |
| 472 | public function get_avatar_image() { |
| 473 | return '<img src="' . $this->get_avatar_url() . '"/>'; |
| 474 | } |
| 475 | |
| 476 | public function get_bio_image_url() { |
| 477 | return OsAgentHelper::get_bio_image_url( $this ); |
| 478 | } |
| 479 | |
| 480 | public function get_bio_image() { |
| 481 | return '<img src="' . $this->get_bio_image_url() . '"/>'; |
| 482 | } |
| 483 | |
| 484 | |
| 485 | public function delete( $id = false ) { |
| 486 | if ( ! $id && isset( $this->id ) ) { |
| 487 | $id = $this->id; |
| 488 | } |
| 489 | if ( $id && $this->db->delete( $this->table_name, array( 'id' => $id ), array( '%d' ) ) ) { |
| 490 | $this->db->delete( LATEPOINT_TABLE_AGENTS_SERVICES, array( 'agent_id' => $id ), array( '%d' ) ); |
| 491 | $this->db->delete( LATEPOINT_TABLE_WORK_PERIODS, array( 'agent_id' => $id ), array( '%d' ) ); |
| 492 | $this->db->delete( LATEPOINT_TABLE_AGENT_META, array( 'object_id' => $id ), array( '%d' ) ); |
| 493 | return true; |
| 494 | } else { |
| 495 | return false; |
| 496 | } |
| 497 | } |
| 498 | } |
| 499 |