PluginProbe ʕ •ᴥ•ʔ
CommerceBird – AI Command Center, ERP Integrations & B2B for WooCommerce (Zoho, Exact Online). / 2.5.1
CommerceBird – AI Command Center, ERP Integrations & B2B for WooCommerce (Zoho, Exact Online). v2.5.1
3.0.3 3.0.2 3.0.1 trunk 2.2.14 2.2.15 2.2.16 2.2.17 2.2.18 2.2.19 2.3.0 2.3.1 2.3.10 2.3.11 2.3.12 2.3.13 2.3.14 2.3.2 2.3.3 2.3.4 2.3.5 2.3.6 2.3.7 2.3.8 2.3.9 2.4.0 2.4.1 2.4.2 2.4.3 2.4.4 2.4.5 2.4.6 2.5.0 2.5.1 2.5.2 2.6.0 2.6.1 2.6.2 2.6.3 2.6.4 2.6.5 2.7.0 2.7.1 2.7.2 2.7.3 2.7.4 2.7.5 2.7.6 2.7.7 2.7.8 2.7.9 2.7.91 2.7.92 2.7.93 2.8.0 2.8.1 2.8.2 2.8.3 2.8.4 2.8.5 2.9.0 2.9.1 2.9.2 2.9.3 3.0.0
commercebird / admin / includes / Actions / Ajax / ZohoInventoryAjax.php
commercebird / admin / includes / Actions / Ajax Last commit date
AcfAjax.php 11 months ago ExactOnlineAjax.php 11 months ago SettingsAjax.php 11 months ago ZohoCRMAjax.php 11 months ago ZohoInventoryAjax.php 11 months ago index.php 1 year ago
ZohoInventoryAjax.php
847 lines
1 <?php
2
3 namespace CommerceBird\Admin\Actions\Ajax;
4
5 use CMBIRD_Auth_Zoho;
6 use CMBIRD_API_Handler_Zoho;
7 use CMBIRD_Pricelist_ZI;
8 use CMBIRD_Categories_ZI;
9 use CommerceBird\Admin\Template;
10 use CommerceBird\Admin\Traits\AjaxRequest;
11 use CommerceBird\Admin\Traits\OptionStatus;
12 use CommerceBird\Admin\Traits\Singleton;
13 use CommerceBird\Admin\Traits\LogWriter;
14 use Throwable;
15 use WC_Tax;
16 use function gettype;
17
18 if ( ! defined( 'ABSPATH' ) ) {
19 exit;
20 }
21 final class ZohoInventoryAjax {
22
23
24 use Singleton;
25 use AjaxRequest;
26 use OptionStatus;
27 use LogWriter;
28
29 private const FORMS = array(
30 'tax' => array(
31 'selectedTaxRates',
32 ),
33 'product' => array(
34 'item_from_zoho',
35 'disable_stock_sync',
36 'disable_product_sync',
37 'enable_accounting_stock',
38 ),
39 'cron' => array(
40 'form',
41 'categories',
42 ),
43 'order' => array(
44 'disable_sync',
45 'enable_auto_number',
46 'enable_order_status',
47 'order_prefix',
48 'location_id',
49 'enable_locationstock',
50 ),
51 'contact' => array(
52 'enable_cron',
53 ),
54 'price' => array(
55 'wp_user_role',
56 'zoho_inventory_pricelist',
57 'wcb2b',
58 ),
59 );
60
61 private const ACTIONS = array(
62 'get_zoho_connect' => 'connection_get',
63 'save_zoho_connect' => 'connection_set',
64 'reset_zoho_connect' => 'connection_reset',
65 'get_zoho_tax' => 'tax_get',
66 'save_zoho_tax' => 'tax_set',
67 'reset_zoho_tax' => 'tax_reset',
68 'get_zoho_product' => 'product_get',
69 'save_zoho_product' => 'product_set',
70 'reset_zoho_product' => 'product_reset',
71 'get_zoho_cron' => 'cron_get',
72 'save_zoho_cron' => 'cron_set',
73 'reset_zoho_cron' => 'cron_reset',
74 'get_zoho_order' => 'order_get',
75 'save_zoho_order' => 'order_set',
76 'reset_zoho_order' => 'order_reset',
77 'get_zoho_contact' => 'contact_get',
78 'save_zoho_contact' => 'contact_set',
79 'reset_zoho_contact' => 'contact_reset',
80 'get_zoho_price' => 'price_get',
81 'save_zoho_price' => 'price_set',
82 'reset_zoho_price' => 'price_reset',
83 'get_zoho_fields' => 'fields_get',
84 'save_zoho_fields' => 'fields_set',
85 'reset_zoho_fields' => 'fields_reset',
86 'is_connected' => 'connection_done',
87 'get_wc_taxes' => 'wc_tax_collect',
88 'get_zoho_taxes' => 'zoho_tax_rates_collect',
89 'get_zoho_categories' => 'zoho_categories_collect',
90 'get_zoho_locations' => 'zoho_locations_collect',
91 'get_zoho_prices' => 'zoho_prices_collect',
92 'get_all_custom_fields' => 'wc_custom_fields_collect',
93 'get_zoho_webhooks' => 'get_zoho_webhooks',
94 'handle_code' => 'handle_code',
95 'convert_guest' => 'convert_guest',
96 );
97
98 private const SOURCE = 'zoho';
99
100 /**
101 * ZohoInventoryAjax constructor.
102 */
103 public function __construct() {
104 $this->load_actions();
105 }
106
107 /**
108 * Collects custom checkout fields for WooCommerce.
109 *
110 * This function verifies the request and collects custom fields from the
111 * THWCFD_Utils::get_checkout_fields() function if the THWCFD class exists.
112 *
113 * @return void
114 */
115 public function wc_custom_fields_collect(): void {
116 $this->verify();
117 $types = array( 'billing', 'shipping', 'additional' );
118 $all_fields = array();
119 $custom_fields = array();
120 // Get all the fields.
121 foreach ( $types as $type ) {
122 // Skip if an unsupported type.
123 if (
124 ! in_array(
125 $type,
126 array(
127 'billing',
128 'shipping',
129 'additional',
130 ),
131 true,
132 )
133 ) {
134 continue;
135 }
136
137 $temp_fields = get_option( 'wc_fields_' . $type );
138 if ( false !== $temp_fields ) {
139 $all_fields = array_merge( $all_fields, $temp_fields );
140 }
141 }
142 // Loop through each field to see if it is a custom field.
143 foreach ( $all_fields as $name => $options ) {
144 if ( isset( $options['custom'] ) && $options['custom'] ) {
145 $label = trim( $options['label'] );
146 $custom_fields[ $name ] = empty( $label ) ? __( 'Please set label', 'commercebird' ) : $label;
147 }
148 }
149
150 $this->response = $custom_fields;
151
152 $this->serve();
153 }
154
155 /**
156 * Retrieves the connection details.
157 *
158 * @return void
159 */
160 public function connection_get(): void {
161 $this->verify();
162 $this->response['account_domain'] = get_option( 'cmbird_zoho_inventory_domain' );
163 $this->response['organization_id'] = get_option( 'cmbird_zoho_inventory_oid' );
164 $this->response['client_id'] = get_option( 'cmbird_zoho_inventory_cid' );
165 $this->response['client_secret'] = get_option( 'cmbird_zoho_inventory_cs' );
166 $this->response['inventory_url'] = get_option( 'cmbird_zoho_inventory_url' );
167 $this->response['redirect_uri'] = get_option( 'cmbird_authorization_redirect_uri' );
168 $this->serve();
169 }
170
171 /**
172 * Retrieves the fields and serves the response.
173 *
174 * @return void
175 */
176 public function fields_get(): void {
177 $this->verify();
178 $this->response['form'] = get_option( 'cmbird_wootozoho_custom_fields', array() );
179 $this->serve();
180 }
181
182 /**
183 * Sets the custom fields for the form.
184 *
185 * @return void
186 */
187 public function fields_set(): void {
188 $this->verify( array( 'form' ) );
189 try {
190 update_option( 'cmbird_wootozoho_custom_fields', $this->data['form'] );
191 $this->response = array( 'message' => 'saved' );
192 } catch ( Throwable $throwable ) {
193 $this->errors = array( 'message' => $throwable->getMessage() );
194 }
195 $this->serve();
196 }
197
198 /**
199 * Resets the fields.
200 *
201 * @return void
202 */
203 public function fields_reset(): void {
204 $this->verify();
205 delete_option( 'cmbird_wootozoho_custom_fields' );
206 $this->response = array( 'message' => 'Reset successfully!' );
207 $this->serve();
208 }
209
210 /**
211 * Resets the price.
212 *
213 * @return void
214 */
215 public function price_reset(): void {
216 $this->verify();
217 delete_option( 'cmbird_zoho_pricelist_id' );
218 delete_option( 'cmbird_zoho_pricelist_role' );
219 delete_option( 'cmbird_zoho_pricelist_wcb2b_groups' );
220 $this->response = array( 'message' => 'Reset successfully!' );
221 $this->serve();
222 }
223
224 /**
225 * Retrieves the price information.
226 *
227 * @return void
228 */
229 public function price_get(): void {
230 $this->verify();
231 $this->response['zoho_inventory_pricelist'] = get_option( 'cmbird_zoho_pricelist_id' );
232 $this->response['wp_user_role'] = get_option( 'cmbird_zoho_pricelist_role' );
233 if ( class_exists( 'WooCommerceB2B' ) ) {
234 $this->response['wcb2b'] = get_option( 'cmbird_zoho_pricelist_wcb2b_groups' );
235 }
236 $this->serve();
237 }
238
239 /**
240 * Sets the price and saves the pricelist.
241 */
242 public function price_set(): void {
243 $this->verify( self::FORMS['price'] );
244 try {
245 $import_pricelist = new CMBIRD_Pricelist_ZI();
246 $success = $import_pricelist->save_price_list( $this->data );
247 if ( class_exists( 'Addify_B2B_Plugin' ) ) {
248 update_option( 'cmbird_zoho_pricelist_role', $this->data['wp_user_role'] );
249 } else {
250 update_option( 'cmbird_zoho_pricelist_wcb2b_groups', $this->data['wcb2b'] );
251 }
252 if ( $success ) {
253 $this->response = array( 'message' => 'Saved' );
254 if ( class_exists( 'WooCommerceB2B' ) ) {
255 $this->response['wcb2b'] = $this->data['wcb2b'];
256 }
257 } else {
258 $this->errors = array( 'message' => 'Failed to save' );
259 }
260 } catch ( Throwable $throwable ) {
261 $this->errors = array( 'message' => $throwable->getMessage() );
262 $this->write_log(
263 array(
264 'message' => $throwable->getMessage(),
265 'files' => wp_list_pluck( $throwable->getTrace(), 'file', 'line' ),
266 ),
267 'zoho-ajax-error'
268 );
269 }
270
271 $this->serve();
272 }
273
274 /**
275 * Collects Zoho prices.
276 *
277 * @return void
278 */
279 public function zoho_prices_collect(): void {
280 $this->verify();
281 $price_list_class = new CMBIRD_Pricelist_ZI();
282 $prices = $price_list_class->zi_get_all_pricelist();
283 $this->response = wp_list_pluck( $prices, 'name', 'pricebook_id' );
284 $this->serve();
285 }
286
287 /**
288 * Retrieves the contact details.
289 *
290 * @return void
291 */
292 public function contact_get() {
293 $this->verify();
294 $this->response = $this->option_status_get( self::FORMS['contact'], self::SOURCE );
295 $this->serve();
296 }
297 /**
298 * Sets the contact and updates the status.
299 *
300 * @return void
301 */
302 public function contact_set() {
303 $this->verify( self::FORMS['contact'] );
304 $this->option_status_update( $this->data, self::SOURCE );
305 if ( isset( $this->data['enable'] ) && ! empty( $this->data['enable'] ) ) {
306 if ( ! wp_next_scheduled( 'zoho_contact_sync' ) ) {
307 wp_schedule_event( time(), 'daily', 'zoho_contact_sync' );
308 }
309 } else {
310 wp_clear_scheduled_hook( 'zoho_contact_sync' );
311 }
312 $this->response = array( 'message' => 'Saved!' );
313 $this->serve();
314 }
315 /**
316 * Resets the contact.
317 *
318 * @return void
319 */
320 public function contact_reset() {
321 $this->verify();
322 $this->option_status_remove( self::FORMS['contact'], self::SOURCE );
323 $this->response = array( 'message' => 'Reset successfully!' );
324 $this->serve();
325 }
326
327 /**
328 * Sets the order and updates the status.
329 *
330 * @return void
331 */
332 public function order_set(): void {
333 $this->verify( self::FORMS['order'] );
334 $this->option_status_update( $this->data, self::SOURCE );
335 $this->response = array( 'message' => 'Saved!' );
336 $this->serve();
337 }
338
339 /**
340 * Retrieves the order.
341 *
342 * @return void
343 */
344 public function order_get(): void {
345 $this->verify();
346 $this->response = $this->option_status_get( self::FORMS['order'], self::SOURCE );
347 $this->serve();
348 }
349
350 /**
351 * Resets the order.
352 *
353 * @return void
354 */
355 public function order_reset(): void {
356 $this->verify();
357 $this->option_status_remove( self::FORMS['order'], self::SOURCE );
358 $this->response = array( 'message' => 'Reset successfully!' );
359 $this->serve();
360 }
361
362 /**
363 * Collects Zoho locations.
364 *
365 * This function verifies the request, retrieves the Zoho inventory
366 * organization ID and URL from the options, constructs the URL
367 * for the API call, and executes the cURL call to retrieve the
368 * locations. The response is then processed to extract the
369 * location names and IDs, and stored in the class property.
370 *
371 * @return void
372 */
373 public function zoho_locations_collect(): void {
374 // $fd = fopen( __DIR__ . '/zoho_locations.txt', 'w+' );
375 $this->verify();
376 $zoho_inventory_oid = get_option( 'cmbird_zoho_inventory_oid' );
377 $zoho_inventory_url = get_option( 'cmbird_zoho_inventory_url' );
378 $url = $zoho_inventory_url . 'inventory/v1/locations?organization_id=' . $zoho_inventory_oid;
379 $execute_curl_call_handle = new CMBIRD_API_Handler_Zoho();
380 $json = $execute_curl_call_handle->execute_curl_call_get( $url );
381 // save the first location id to the database of the first object of json.
382 if ( ! empty( $json->locations ) && is_array( $json->locations ) && array_key_exists( 0, $json->locations ) ) {
383 $location_id = $json->locations[0]->location_id;
384 update_option( 'cmbird_zoho_parent_location_id_status', $location_id );
385 }
386 $this->response = wp_list_pluck( $json->locations, 'location_name', 'location_id' );
387 $this->serve();
388 }
389
390 /**
391 * Sets the cron for the class.
392 */
393 public function cron_set(): void {
394 $this->verify( self::FORMS['cron'] );
395 if ( array_key_exists( 'form', $this->data ) ) {
396 $decode = json_decode( $this->data['form'], true );
397 update_option( 'zi_cron_interval', $decode['zi_cron_interval'] );
398 unset( $decode['zi_cron_interval'] );
399 $this->option_status_update( $decode, self::SOURCE );
400 }
401 if ( array_key_exists( 'categories', $this->data ) ) {
402 $decode = json_decode( $this->data['categories'] );
403 update_option( 'cmbird_zoho_item_category', serialize( $decode ) );
404 }
405 $this->response = array( 'message' => 'Saved' );
406 // also set the cron job to sync categories.
407 if ( ! wp_next_scheduled( 'cmbird_zi_category_cron' ) ) {
408 wp_schedule_event( time(), 'daily', 'cmbird_zi_category_cron' );
409 }
410 $this->serve();
411 }
412
413 /**
414 * Executes the cron_get function.
415 *
416 * This function verifies the form status and retrieves the form options
417 * for syncing name, price, image, and description. It also retrieves
418 * the cron interval and the Zoho item categories.
419 *
420 * @return void
421 */
422 public function cron_get(): void {
423 $this->verify();
424 $this->response = array();
425 $this->response['form'] = $this->option_status_get(
426 array(
427 'disable_name_sync',
428 'disable_price_sync',
429 'disable_image_sync',
430 'disable_description_sync',
431 ),
432 self::SOURCE,
433 );
434 $this->response['form']['zi_cron_interval'] = get_option( 'zi_cron_interval', 'none' );
435 $categories = get_option( 'cmbird_zoho_item_category', '' );
436 $this->response['categories'] = maybe_unserialize( $categories );
437 $this->serve();
438 }
439
440 /**
441 * Resets the cron job.
442 *
443 * This function verifies the cron job, removes the specified options,
444 * deletes the 'zoho_item_category' option, and serves the cron job.
445 *
446 * @return void
447 */
448 public function cron_reset(): void {
449 $this->verify();
450 $this->option_status_remove(
451 array(
452 'disable_name_sync',
453 'disable_price_sync',
454 'disable_image_sync',
455 'disable_description_sync',
456 ),
457 self::SOURCE,
458 );
459 delete_option( 'cmbird_zoho_item_category' );
460 // delete all options that contain 'zoho_id_for_term_id_'.
461 global $wpdb;
462 $wpdb->query( "DELETE FROM $wpdb->options WHERE option_name LIKE 'zoho_id_for_term_id_%'" );
463 $this->response = array( 'message' => 'Reset successfully!' );
464 $this->serve();
465 }
466
467 /**
468 * Collects Zoho categories.
469 *
470 * This function verifies the data and retrieves the Zoho item categories.
471 * If the categories are successfully retrieved, it filters the data to
472 * include only the 'name' and 'category_id' fields, and removes the
473 * category with ID -1. Finally, it sets the response with the filtered
474 * categories and serves the response.
475 */
476 public function zoho_categories_collect(): void {
477 $this->verify();
478 $category_class = new CMBIRD_Categories_ZI();
479 $categories = $category_class->cmbird_get_zoho_item_categories();
480 if ( gettype( $categories ) === 'array' ) {
481 // $filtered = wp_list_pluck( $categories, 'name', 'category_id' );
482 // unset( $filtered[ -1 ] );
483 $this->response = $categories;
484 }
485 $this->serve();
486 }
487
488 /**
489 * Executes the connection process and handles the response.
490 */
491 public function connection_done(): void {
492 $this->verify();
493 $zoho_inventory_url = get_option( 'cmbird_zoho_inventory_url' );
494 $zoho_inventory_oid = get_option( 'cmbird_zoho_inventory_oid' );
495 $url = $zoho_inventory_url . 'inventory/v1/apiusagereport/dashboard?version=all&organization_id=' . $zoho_inventory_oid;
496
497 $execute_curl_call_handle = new CMBIRD_API_Handler_Zoho();
498 $json = $execute_curl_call_handle->execute_curl_call_get( $url );
499
500 if ( is_wp_error( $json ) ) {
501 $this->errors = array( 'message' => $json->get_error_message() );
502 return;
503 }
504
505 if ( empty( $json ) || empty( $json->data ) || empty( $json->data->api_usage ) ) {
506 $this->errors = array( 'message' => 'We lost connection with Zoho. Please refresh the page.' );
507 return;
508 }
509 $api_usage = $json->data->api_usage;
510 // Debug JSON encoding.
511 $encoded_api_usage = wp_json_encode( $api_usage );
512 // Ensure it's not null.
513 $this->response = json_decode( $encoded_api_usage, true ) ?? array();
514 $this->serve();
515 }
516
517 /**
518 * Executes the product_set function.
519 */
520 public function product_set(): void {
521 $this->verify( self::FORMS['product'] );
522 if ( ! empty( $this->data ) ) {
523 $this->option_status_update( $this->data, self::SOURCE );
524 }
525 $this->response = array( 'message' => 'Saved!' );
526 $this->serve();
527 }
528
529 /**
530 * Retrieves the product data.
531 *
532 * @return void
533 */
534 public function product_get(): void {
535 $this->verify();
536 $this->response = $this->option_status_get( self::FORMS['product'], self::SOURCE );
537 $this->serve();
538 }
539
540 /**
541 * Resets the product.
542 *
543 * @return void
544 */
545 public function product_reset(): void {
546 $this->verify();
547 $this->option_status_remove( self::FORMS['product'], self::SOURCE );
548 $this->response = array( 'message' => 'Reset successfully!' );
549 $this->serve();
550 }
551
552 /**
553 * Retrieves the tax information.
554 *
555 * @return void
556 */
557 public function tax_get(): void {
558 $this->verify();
559 $this->response = array();
560 foreach ( $this->wc_taxes() as $tax ) {
561 $this->response['selectedTaxRates'][] = $tax['id'] . '^^' . get_option( 'cmbird_zoho_inventory_tax_rate_' . $tax['id'] );
562 }
563 $this->serve();
564 }
565
566 /**
567 * Retrieves an array of all tax rates from WooCommerce.
568 *
569 * @return array An array of all tax rates.
570 */
571 public function wc_taxes(): array {
572 $wc_tax_array = array();
573 $tax_classes = WC_Tax::get_tax_classes(); // Retrieve all tax classes.
574 if ( ! in_array( '', $tax_classes ) ) { // Make sure "Standard rate" (empty class name) is present.
575 array_unshift( $tax_classes, '' );
576 }
577
578 foreach ( $tax_classes as $tax_class ) { // For each tax class, get all rates.
579 $taxes = WC_Tax::get_rates_for_tax_class( $tax_class );
580
581 foreach ( $taxes as $key => $tax ) {
582 $taxarray = (array) $tax;
583 $taxarray['id'] = $key;
584 $wc_tax_array[] = $taxarray;
585 }
586 }
587
588 return $wc_tax_array;
589 }
590
591 /**
592 * Resets the tax settings.
593 *
594 * This function verifies the tax settings and then deletes the options
595 * related to the tax rates
596 *
597 * @return void
598 */
599 public function tax_reset(): void {
600 $this->verify();
601 foreach ( $this->wc_taxes() as $tax ) {
602 delete_option( 'cmbird_zoho_inventory_tax_rate_' . $tax['id'] );
603 }
604 $this->response = array( 'message' => 'Reset successfully!' );
605 $this->serve();
606 }
607
608 /**
609 * Saves tax rates to the database.
610 */
611 public function tax_set(): void {
612 $this->verify( self::FORMS['tax'] );
613 $rates = array_filter( $this->data['selectedTaxRates'] );
614 try {
615 foreach ( $rates as $value ) {
616 $valarray = explode( '^^', $value );
617 update_option( 'cmbird_zoho_inventory_tax_rate_' . $valarray[0], $valarray[1] );
618 }
619 $this->response = array( 'message' => 'Saved' );
620 } catch ( Throwable $throwable ) {
621 $this->errors = array( 'message' => $throwable->getMessage() );
622 }
623
624 $this->serve();
625 }
626
627 /**
628 * Sets the connection for the Zoho Inventory API.
629 */
630 public function connection_set(): void {
631 $this->verify(
632 array(
633 'account_domain',
634 'organization_id',
635 'client_id',
636 'client_secret',
637 'redirect_uri',
638 ),
639 );
640 try {
641 $inventory = sprintf( 'https://www.zohoapis.%s/', $this->data['account_domain'] );
642 update_option( 'cmbird_zoho_inventory_domain', $this->data['account_domain'] );
643 update_option( 'cmbird_zoho_inventory_oid', $this->data['organization_id'] );
644 update_option( 'cmbird_zoho_inventory_cid', $this->data['client_id'] );
645 update_option( 'cmbird_zoho_inventory_cs', $this->data['client_secret'] );
646 update_option( 'cmbird_zoho_inventory_url', $inventory );
647 update_option( 'cmbird_authorization_redirect_uri', $this->data['redirect_uri'] );
648 $redirect = esc_url_raw( 'https://accounts.zoho.' . $this->data['account_domain'] . '/oauth/v2/auth?response_type=code&client_id=' . $this->data['client_id'] . '&scope=ZohoInventory.FullAccess.all&redirect_uri=' . $this->data['redirect_uri'] . '&prompt=consent&access_type=offline&state=' . wp_create_nonce( Template::NAME ) );
649 $this->response = array(
650 'redirect' => $redirect,
651 'message' => 'We are redirecting you to zoho. please wait...',
652 );
653 } catch ( Throwable $throwable ) {
654 $this->errors = array( 'message' => $throwable->getMessage() );
655 }
656
657 $this->serve();
658 }
659
660 /**
661 * Resets the connection by deleting specific options from the database.
662 */
663 public function connection_reset(): void {
664 $this->verify();
665 try {
666 // Check if resetAll is true (sent from Vue).
667 $reset_all = isset( $this->data['reset'] ) && $this->data['reset'] == 1;
668 if ( ! $reset_all ) {
669 $options = array(
670 'cmbird_zoho_inventory_domain',
671 'cmbird_zoho_inventory_oid',
672 'cmbird_zoho_inventory_cid',
673 'cmbird_zoho_inventory_cs',
674 'cmbird_zoho_inventory_url',
675 'cmbird_zoho_inventory_access_token',
676 );
677 foreach ( $options as $zi_option ) {
678 delete_option( $zi_option );
679 }
680 $this->response = array( 'message' => 'Reset successfully!' );
681 } else {
682 global $wpdb;
683 // Delete all product and customer meta keys.
684 $wpdb->query( "DELETE FROM {$wpdb->prefix}postmeta WHERE meta_key IN ('zi_item_id', 'zi_category_id')" );
685 $wpdb->query( "DELETE FROM {$wpdb->prefix}usermeta WHERE meta_key IN ('zi_contact_id', 'zi_primary_contact_id', 'zi_billing_address_id', 'zi_shipping_address_id', 'zi_contact_persons_id')" );
686 // reset every option that starts with cmbird_.
687 $wpdb->query( "DELETE FROM {$wpdb->prefix}options WHERE option_name LIKE 'cmbird_zoho_%'" );
688 $this->response['message'] = __( 'All settings are reset successfully', 'commercebird' );
689 }
690 } catch ( Throwable $throwable ) {
691 $this->errors = array( 'message' => $throwable->getMessage() );
692 }
693
694 $this->serve();
695 }
696
697 /**
698 * Retrieves the Zoho tax rates for the organization.
699 *
700 * This function verifies the request, retrieves the organization ID and URL
701 * from the options, constructs the URL for the API request, and executes
702 * the cURL call to fetch the tax rates. If the response contains the
703 * 'taxes' key, it sets the response to the tax rates. Otherwise, it sets
704 * the errors to a default message.
705 */
706 public function zoho_tax_rates_collect(): void {
707 $this->verify();
708 $zoho_inventory_oid = get_option( 'cmbird_zoho_inventory_oid' );
709 $zoho_inventory_url = get_option( 'cmbird_zoho_inventory_url' );
710 $url = $zoho_inventory_url . 'inventory/v1/settings/taxes?organization_id=' . $zoho_inventory_oid;
711 try {
712 $execute_curl_call_handle = new CMBIRD_API_Handler_Zoho();
713 $json = (array) $execute_curl_call_handle->execute_curl_call_get( $url );
714 if ( array_key_exists( 'taxes', $json ) ) {
715 $this->response = $json['taxes'];
716 } else {
717 $this->errors = array( 'message' => 'Something went wrong!' );
718 }
719 } catch ( Throwable $throwable ) {
720 $this->errors = array( 'message' => $throwable->getMessage() );
721 }
722
723 $this->serve();
724 }
725
726 /**
727 * Executes the wc_tax_collect function.
728 *
729 * This function verifies the current state, retrieves the taxes using the
730 * wc_taxes method, and serves the response.
731 */
732 public function wc_tax_collect(): void {
733 $this->verify();
734 $this->response = $this->wc_taxes();
735 $this->serve();
736 }
737
738 /**
739 * Handles the oAuth code.
740 */
741 public function handle_code(): void {
742 $this->verify();
743 if ( array_key_exists( 'code', $this->request ) ) {
744 $class_functions = new CMBIRD_Auth_Zoho();
745 $code = $this->request['code'];
746 try {
747 $access_token = $class_functions->get_zoho_access_token( $code, 'zoho_inventory' );
748 if ( array_key_exists( 'access_token', $access_token ) ) {
749 update_option( 'cmbird_zoho_inventory_auth_code', $code );
750 update_option( 'cmbird_zoho_inventory_access_token', $access_token['access_token'] );
751 update_option( 'cmbird_zoho_inventory_refresh_token', $access_token['refresh_token'] );
752 update_option( 'cmbird_zoho_inventory_timestamp', strtotime( gmdate( 'Y-m-d H:i:s' ) ) + $access_token['expires_in'] );
753 $this->response = (array) $access_token;
754 } else {
755 $this->errors = (array) $access_token;
756 }
757 } catch ( Throwable $throwable ) {
758 $this->errors = array( 'message' => $throwable->getMessage() );
759 }
760 }
761 $this->serve();
762 }
763
764 /**
765 * Converts all guest users to a registered users.
766 *
767 * This function verifies the request, retrieves all guest orders
768 *
769 * @return void
770 */
771 public function convert_guest(): void {
772 $this->verify();
773 $args = array(
774 'status' => array( 'wc-processing', 'wc-completed' ),
775 'return' => 'ids',
776 'customer' => 0, // Only guest orders.
777 'limit' => -1, // Retrieve all guest orders.
778 );
779
780 $orders = wc_get_orders( $args );
781 if ( empty( $orders ) ) {
782 $this->response = array( 'message' => __( 'No guest orders found.', 'commercebird' ) );
783 $this->serve();
784 return;
785 }
786 $count = count( $orders );
787 foreach ( $orders as $order_id ) {
788 $order = wc_get_order( $order_id );
789 $email = $order->get_billing_email();
790
791 if ( email_exists( $email ) === false ) {
792 $username = strstr( $email, '@', true );
793 $password = wp_generate_password();
794 $user_id = wc_create_new_customer( $email, $username, $password );
795
796 if ( ! is_wp_error( $user_id ) ) {
797 // use update_meta to set the user ID for the order.
798 $order->set_customer_id( $user_id );
799 $order->save();
800 }
801 } else {
802 // If the email already exists, we can still update the order to the existing user.
803 $user = get_user_by( 'email', $email );
804 if ( $user ) {
805 $order->set_customer_id( $user->ID );
806 $order->save();
807 }
808 }
809 }
810 $this->response['message'] = sprintf( __( 'Successfully converted %d guest orders to registered users.', 'commercebird' ), $count );
811 $this->serve();
812 }
813
814 /**
815 * Fetches webhooks from Zoho Inventory API.
816 *
817 * @return void
818 */
819 public function get_zoho_webhooks(): void {
820 $this->verify();
821 $zoho_inventory_oid = get_option( 'cmbird_zoho_inventory_oid' );
822 $zoho_inventory_url = get_option( 'cmbird_zoho_inventory_url' );
823 if ( ! $zoho_inventory_oid || ! $zoho_inventory_url ) {
824 $this->errors = array( 'message' => 'Missing Zoho organization ID or domain.' );
825 $this->serve();
826 return;
827 }
828 $url = $zoho_inventory_url . 'inventory/v1/settings/webhooks?page=1&per_page=50&usestate=false&organization_id=' . $zoho_inventory_oid;
829 try {
830 $execute_curl_call_handle = new \CMBIRD_API_Handler_Zoho();
831 $json = $execute_curl_call_handle->execute_curl_call_get( $url );
832
833 // Check if the response is a WP_Error object.
834 if ( is_wp_error( $json ) ) {
835 $this->errors = array( 'message' => $json->get_error_message() );
836 } elseif ( isset( $json->webhooks ) && is_array( $json->webhooks ) ) {
837 $this->response = $json->webhooks;
838 } else {
839 $this->errors = array( 'message' => 'Failed to fetch webhooks or no webhooks found.' );
840 }
841 } catch ( \Throwable $throwable ) {
842 $this->errors = array( 'message' => $throwable->getMessage() );
843 }
844 $this->serve();
845 }
846 }
847