PluginProbe ʕ •ᴥ•ʔ
CommerceBird – AI Command Center, ERP Integrations & B2B for WooCommerce (Zoho, Exact Online). / 2.7.5
CommerceBird – AI Command Center, ERP Integrations & B2B for WooCommerce (Zoho, Exact Online). v2.7.5
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 / includes / classes / zoho-inventory / class-product.php
commercebird / includes / classes / zoho-inventory Last commit date
class-cmbird-categories-zi.php 7 months ago class-cmbird-image-zi.php 5 months ago class-import-items.php 4 months ago class-import-price-list.php 9 months ago class-multi-currency.php 7 months ago class-order-sync.php 4 months ago class-product.php 4 months ago class-users-contact.php 4 months ago index.php 1 year ago
class-product.php
1136 lines
1 <?php
2
3 if ( ! defined( 'ABSPATH' ) ) {
4 exit;
5 }
6
7 /**
8 * Handles export and synchronization of WooCommerce products with Zoho Inventory.
9 *
10 * Provides methods for syncing simple, variable, and bundle products, as well as updating product data between WooCommerce and Zoho Inventory.
11 */
12 class CMBIRD_Products_ZI_Export {
13
14 /**
15 * Configuration options for Zoho Inventory and plugin settings.
16 *
17 * @var array
18 */
19 private $config;
20
21 /**
22 * Constructor for CMBIRD_Products_ZI_Export.
23 *
24 * Initializes configuration options for Zoho Inventory and plugin settings.
25 */
26 public function __construct() {
27 $this->config = array(
28 'ProductZI' => array(
29 'OID' => get_option( 'cmbird_zoho_inventory_oid' ),
30 'APIURL' => get_option( 'cmbird_zoho_inventory_url' ),
31 'Domain' => get_option( 'cmbird_zoho_inventory_domain' ),
32 ),
33 'Settings' => array(
34 'disable_description' => get_option( 'cmbird_zoho_disable_description_sync_status' ),
35 'disable_name' => get_option( 'cmbird_zoho_disable_name_sync_status' ),
36 'disable_price' => get_option( 'cmbird_zoho_disable_price_sync_status' ),
37 'disable_stock' => get_option( 'cmbird_zoho_disable_stock_sync_status' ),
38 'enable_accounting_stock' => get_option( 'cmbird_zoho_enable_accounting_stock_status' ),
39 'enable_location_stock' => get_option( 'cmbird_zoho_enable_locationstock_status' ),
40 'zoho_location_id' => get_option( 'cmbird_zoho_location_id_status' ),
41 'disable_image' => get_option( 'cmbird_zoho_disable_image_sync_status' ),
42 ),
43 );
44 }
45
46 /**
47 * Prepares products for Zoho Inventory sync.
48 *
49 * @param array $product_ids List of WooCommerce product IDs to sync.
50 *
51 * @return void
52 */
53 public function cmbird_zi_products_prepare_sync( $product_ids ) {
54 $rate_limit = get_option( 'cmbird_zoho_rate_limit_exceeded' );
55 if ( is_array( $product_ids ) ) {
56 // schedule the unsynced products for tomorrow via action scheduler.
57 if ( $rate_limit ) {
58 $timestamp = strtotime( 'tomorrow' );
59 // set the zoho rate limit option exceeded to false tomorrow if not scheduled yet.
60 if ( ! wp_next_scheduled( 'cmbird_common' ) ) {
61 wp_schedule_single_event( $timestamp, 'cmbird_common' );
62 }
63 // Get all scheduled actions with the specific hook name.
64 $action_ids = as_get_scheduled_actions(
65 array(
66 'hook' => 'sync_zi_product_cron',
67 'status' => ActionScheduler_Store::STATUS_PENDING,
68 'per_page' => -1,
69 )
70 );
71 // Loop through each action and reschedule it.
72 if ( ! empty( $action_ids ) ) {
73 foreach ( $action_ids as $action_id ) {
74 // Fetch the action by ID.
75 $action = as_get_scheduled_action( $action_id );
76 // If the action is valid and exists, reschedule it.
77 if ( $action ) {
78 // Reschedule the action to run tomorrow.
79 as_schedule_single_action( $timestamp, 'sync_zi_product_cron', $action->get_args(), 'ActionScheduler' );
80 // Cancel the old action to avoid duplicates.
81 as_unschedule_action( 'sync_zi_product_cron', $action->get_args(), $action_id );
82 }
83 }
84 }
85 } else {
86 foreach ( $product_ids as $product_id ) {
87 $this->cmbird_zi_product_sync( $product_id );
88 }
89 }
90 }
91 }
92
93 /**
94 * Starting point to sync Product to Zoho Inventory. If product type is other than simple, pass the product_id to different function
95 *
96 * @param integer $post_id - Product id.
97 * @return string|void - item_id of Zoho Inventory.
98 */
99 public function cmbird_zi_product_sync( $post_id ) {
100
101 // $fd = fopen( __DIR__ . '/product_class.txt', 'a+' );
102 $item_id = '';
103
104 if ( is_array( $post_id ) ) {
105 $product_id = intval( $post_id['0'] );
106 $post_id = $product_id;
107 }
108
109 if ( 'draft' === get_post_status( $post_id ) ) {
110 return;
111 }
112
113 $product = wc_get_product( $post_id );
114 if ( ! $product ) {
115 return;
116 }
117 if ( $product->is_type( 'bundle' ) ) {
118 // fwrite($fd,PHP_EOL.'Inside bundle: ');
119 $item_id = $this->zi_bundle_product_to_zoho( $post_id );
120 return $item_id;
121 } elseif ( $product->is_type( 'variable' ) ) {
122 // fwrite( $fd, PHP_EOL . 'Inside variable: ' );
123 $this->cmbird_zi_variation_product_to_zoho( $post_id );
124 } elseif ( $product->is_type( 'variation' ) ) {
125 return;
126 } else {
127 // fwrite($fd,PHP_EOL.'Inside Regular: ');
128 // Simple product.
129 $rate = $product->get_regular_price();
130 $pre_name = $product->get_name();
131 $name = preg_replace( "/[>\"''<`]/", '', $pre_name );
132
133 $sku = $product->get_sku();
134 $stock_quantity = $product->get_stock_quantity();
135 $in_stock = ( $stock_quantity > 0 ) ? $stock_quantity : 0;
136 // fwrite($fd,PHP_EOL.'$product->get_stock_quantity() : '.$product->get_stock_quantity());
137 $in_stock_rate = $in_stock * (int) $rate;
138
139 $tax_rates = WC_Tax::get_base_tax_rates( $product->get_tax_class() );
140 $tax_id_key = '';
141 foreach ( $tax_rates as $tax_key => $tax_value ) {
142 $tax_id_key = $tax_key;
143 break;
144 }
145 $tax_option = get_option( 'cmbird_zoho_inventory_tax_rate_' . $tax_id_key );
146 $tax_id = explode( '##', $tax_option )[0];
147
148 $zi_status = ( 'publish' === get_post_status( $post_id ) ) ? 'active' : 'inactive';
149 // request data for adding/updating value to zoho.
150 $zi_disable_item_name_sync = get_option( 'cmbird_zoho_disable_name_sync_status' );
151 $zoho_item_id = get_post_meta( $post_id, 'zi_item_id', true );
152
153 $zidata = '';
154 if ( empty( $zoho_item_id ) || 'true' !== $zi_disable_item_name_sync ) {
155 $zidata .= '"name" : "' . $name . '",';
156 }
157
158 if ( $product->is_virtual( 'yes' ) ) {
159 $zidata .= '"product_type" : "service",';
160 $zidata .= '"item_type" : "sales",';
161 } else {
162 $zidata .= '"product_type" : "goods",';
163 $zidata .= '"item_type" : "inventory",';
164 }
165
166 $zidata .= '"sku" : "' . $sku . '",';
167 // $zidata .= '"unit" : "pcs",';
168 $zidata .= '"status" : "' . $zi_status . '",';
169 // Initial stock update only if item sync for first time.
170 if ( empty( $zoho_item_id ) ) {
171 $zidata .= '"initial_stock" : ' . $in_stock . ',';
172 $zidata .= '"initial_stock_rate" : "' . $in_stock_rate . '",';
173 }
174 $zidata .= '"rate" : "' . $rate . '",';
175 $domain = isset( $this->config['ProductZI']['Domain'] ) ? $this->config['ProductZI']['Domain'] : '';
176 if ( 'in' !== strtolower( $domain ) && $tax_id ) {
177 $zidata .= '"tax_id" : "' . $tax_id . '",';
178 } elseif ( 'in' === strtolower( $domain ) ) {
179 // For India domain, find GST and IGST tax IDs dynamically, but only if tax rate > 0%.
180 $intra_tax_id = ''; // For SGST&CGST (intra-state).
181 $inter_tax_id = ''; // For IGST (inter-state).
182 $has_non_zero_rate = false;
183 $tax_rate_percent = 0;
184
185 // First, check if we have any non-zero tax rates and get the rate percentage.
186 foreach ( $tax_rates as $tax_key => $tax_value ) {
187 if ( isset( $tax_value['rate'] ) && floatval( $tax_value['rate'] ) > 0 ) {
188 $has_non_zero_rate = true;
189 $tax_rate_percent = floatval( $tax_value['rate'] );
190 break; // Use the first non-zero rate found.
191 }
192 }
193
194 // If we have non-zero rates, find the corresponding Zoho tax IDs for the same rate.
195 if ( $has_non_zero_rate ) {
196 // Look for tax options that match this rate percentage.
197 global $wpdb;
198 $all_tax_options = $wpdb->get_results(
199 "SELECT option_name, option_value
200 FROM {$wpdb->options}
201 WHERE option_name LIKE 'cmbird_zoho_inventory_tax_rate_%'"
202 );
203
204 foreach ( $all_tax_options as $option ) {
205 $option_str = $option->option_value;
206 // Example: "2946885000000035251##SGST&CGST12##tax_group##12".
207 $parts = explode( '##', $option_str );
208 if ( isset( $parts[1] ) && isset( $parts[3] ) ) {
209 $option_rate = floatval( $parts[3] );
210
211 // Only consider options with the same tax rate percentage.
212 if ( $option_rate === $tax_rate_percent ) {
213 // Check for intra-state tax (SGST&CGST combined):
214 // Look for "GST" without "IGST", or explicit "SGST" and "CGST" mentions.
215 if ( ( false !== stripos( $parts[1], 'GST' ) && false === stripos( $parts[1], 'IGST' ) ) ||
216 ( false !== stripos( $parts[1], 'SGST' ) && false !== stripos( $parts[1], 'CGST' ) ) ) {
217 $intra_tax_id = $parts[0];
218 }
219 // Check for IGST (inter-state) - contains "IGST".
220 if ( false !== stripos( $parts[1], 'IGST' ) ) {
221 $inter_tax_id = $parts[0];
222 }
223 }
224 }
225 }
226
227 // Add both intra and inter tax preferences if we found the tax IDs.
228 $item_tax_preferences = array();
229 if ( ! empty( $intra_tax_id ) ) {
230 $item_tax_preferences[] = array(
231 'tax_id' => $intra_tax_id,
232 'tax_specification' => 'intra',
233 );
234 }
235 if ( ! empty( $inter_tax_id ) ) {
236 $item_tax_preferences[] = array(
237 'tax_id' => $inter_tax_id,
238 'tax_specification' => 'inter',
239 );
240 }
241 if ( ! empty( $item_tax_preferences ) ) {
242 $zidata .= '"item_tax_preferences" : ' . wp_json_encode( $item_tax_preferences ) . ',';
243 }
244 } else {
245 $zidata .= '"is_taxable" : false,';
246 $zidata .= '"tax_exemption_code" : "exempt",';
247 }
248 }
249 // $zidata .= '"image_name" : "' . $image . '",';
250
251 // Get cost_price from meta data.
252 $cost_price = $product->get_meta( '_cogs_total_value' );
253 if ( ! empty( $cost_price ) && is_numeric( $cost_price ) ) {
254 $zidata .= '"purchase_rate" : "' . $cost_price . '",';
255 }
256
257 $dimensions = (object) array();
258 $dimensions->length = $product->get_length();
259 $dimensions->width = $product->get_width();
260 $dimensions->height = $product->get_height();
261 $dimensions->weight = $product->get_weight();
262 $zidata .= '"package_details" : ' . wp_json_encode( $dimensions ) . '';
263
264 // Send category only if category ID available.
265 $zi_category_id = $this->cmbird_zi_get_prod_updated_category( $post_id );
266 if ( $zi_category_id ) {
267 $zidata .= ',"category_id" : "' . $zi_category_id . '"';
268 }
269
270 // save the request body for debugging purposes.
271 $zi_body_request = '{' . $zidata . '}';
272 update_post_meta( $post_id, 'zi_product_body_request', $zi_body_request );
273
274 // $zidata .= '"image_type" : "' . $ext . '"';
275 if ( ! empty( $zoho_item_id ) && ctype_digit( $zoho_item_id ) ) {
276 // fwrite($fd,PHP_EOL.'Inside Update: ');
277 $this->cmbird_zi_product_put( $post_id, $zoho_item_id, $zidata );
278 } else {
279 // fwrite($fd,PHP_EOL.'Inside Create ');
280 $zoho_inventory_oid = $this->config['ProductZI']['OID'];
281 $zoho_inventory_url = $this->config['ProductZI']['APIURL'];
282
283 $data = array(
284 'JSONString' => '{' . $zidata . '}',
285 'organization_id' => $zoho_inventory_oid,
286 );
287 $url = $zoho_inventory_url . 'inventory/v1/items';
288
289 $execute_curl_call_handle = new CMBIRD_API_Handler_Zoho();
290 $json = $execute_curl_call_handle->execute_curl_call_post( $url, $data );
291
292 $errmsg = $json->message;
293 update_post_meta( $post_id, 'zi_product_errmsg', $errmsg );
294
295 $code = $json->code;
296 // fwrite($fd,PHP_EOL.'JSON Response : '.print_r($json,true));
297 // Check if the the given sku has product at zoho inventory.
298 if ( '1001' === $code || 1001 === $code ) {
299 // fwrite($fd,PHP_EOL.'Inside SKU Check');
300 $sku_check = str_replace( ' ', '+', $sku );
301 $url = $zoho_inventory_url . 'inventory/v1/items?search_text=' . $sku_check . '&organization_id=' . $zoho_inventory_oid;
302 $get_request = $execute_curl_call_handle->execute_curl_call_get( $url );
303
304 if ( '0' === $get_request->code || 0 === $get_request->code ) {
305 $item_id = '';
306 $matching_item = null;
307
308 foreach ( $get_request->items as $zoho_item ) {
309 if ( $zoho_item->sku === $sku ) {
310 // SKU matched.
311 $matching_item = $zoho_item;
312 break;
313 }
314 }
315
316 // If SKU check didn't find a match, perform name check.
317 if ( ! $matching_item ) {
318 $item_name_check = str_replace( ' ', '+', $name );
319 $url = $zoho_inventory_url . 'inventory/v1/items?search_text=' . $item_name_check . '&organization_id=' . $zoho_inventory_oid;
320 $get_request = $execute_curl_call_handle->execute_curl_call_get( $url );
321
322 if ( '0' === $get_request->code || 0 === $get_request->code ) {
323 foreach ( $get_request->items as $zoho_item ) {
324 if ( $zoho_item->name === $name ) {
325 // Name matched.
326 $matching_item = $zoho_item;
327 break;
328 }
329 }
330 }
331 }
332
333 if ( $matching_item ) {
334 $code = 0;
335 $json->item = $matching_item;
336 update_post_meta( $post_id, 'zi_product_errmsg', 'Product "' . $matching_item->name . '" is mapped successfully with Zoho' );
337 }
338 }
339 }
340 // fwrite($fd,PHP_EOL.'After SKU Check : code '.$code);
341 if ( '0' === $code || 0 === $code ) {
342 foreach ( $json->item as $key => $value ) {
343 if ( 'item_id' === $key ) {
344 $item_id = $value;
345 }
346 if ( 'purchase_account_id' === $key ) {
347 $purchase_account_id = $value;
348 }
349 if ( 'account_id' === $key ) {
350 $account_id = $value;
351 }
352 if ( 'account_name' === $key ) {
353 $account_name = $value;
354 }
355 if ( 'inventory_account_id' === $key ) {
356 $inventory_account_id = $value;
357 }
358 if ( 'category_id' === $key && ! empty( $value ) ) {
359 update_post_meta( $post_id, 'zi_category_id', $value );
360 }
361 }
362 update_post_meta( $post_id, 'zi_item_id', $item_id );
363 update_post_meta( $post_id, 'zi_purchase_account_id', $purchase_account_id );
364 update_post_meta( $post_id, 'zi_account_id', $account_id );
365 update_post_meta( $post_id, 'zi_account_name', $account_name );
366 update_post_meta( $post_id, 'zi_inventory_account_id', $inventory_account_id );
367 }
368 }
369 }
370 return $item_id;
371 }
372
373 /**
374 * Function to update zoho item if already exists.
375 *
376 * @param number $proid - product number.
377 * @param number $item_id - zoho item id.
378 * @param mixed $pdt3 - Zoho item object for post request.
379 * @return string
380 */
381 public function cmbird_zi_product_put( $proid, $item_id, $pdt3 = '' ) {
382 // $fd = fopen(__DIR__.'/product_class.txt','a+');
383 // fwrite($fd,PHP_EOL.'Inside update : ');
384 $errmsg = '';
385 $zoho_inventory_oid = $this->config['ProductZI']['OID'];
386 $zoho_inventory_url = $this->config['ProductZI']['APIURL'];
387
388 $url = $zoho_inventory_url . 'inventory/v1/items/' . $item_id;
389 // fwrite($fd,PHP_EOL.'JSON Data : '.'{' . $pdt3 . '}');
390 $data = array(
391 'JSONString' => '{' . $pdt3 . '}',
392 'organization_id' => $zoho_inventory_oid,
393 );
394
395 // if pdt3 is empty then do GET call, else do PUT call.
396 if ( empty( $pdt3 ) ) {
397 $execute_curl_call_handle = new CMBIRD_API_Handler_Zoho();
398 $json = $execute_curl_call_handle->execute_curl_call_get( $url );
399 $code = $json->code;
400 $errmsg = $json->message;
401 } else {
402 $execute_curl_call_handle = new CMBIRD_API_Handler_Zoho();
403 $json = $execute_curl_call_handle->execute_curl_call_put( $url, $data );
404 $code = $json->code;
405 $errmsg = $json->message;
406 }
407
408 if ( 0 === $code || '0' === $code ) {
409 $product = wc_get_product( $proid );
410 // if type is not simple then return.
411 if ( ! $product->is_type( 'simple' ) ) {
412 return $errmsg;
413 }
414 $item = $json->item;
415 // update price.
416 $zi_disable_itemprice_sync = $this->config['Settings']['disable_price'];
417 if ( ! empty( $item->rate ) && ! $zi_disable_itemprice_sync ) {
418 $product->set_regular_price( $item->rate );
419 $sale_price = $product->get_sale_price();
420 if ( empty( $sale_price ) ) {
421 $product->set_price( $item->rate );
422 }
423 }
424 // To check status of stock sync option.
425 $zi_disable_stock_sync = $this->config['Settings']['disable_stock'];
426 if ( ! $zi_disable_stock_sync && isset( $item->available_for_sale_stock ) ) {
427 $stock = '';
428 // Update stock.
429 $accounting_stock = $this->config['Settings']['enable_accounting_stock'];
430 // Sync from specific location check.
431 $zi_enable_locationstock = $this->config['Settings']['enable_location_stock'];
432 if ( $zi_enable_locationstock && isset( $item->locations ) ) {
433 $locations = $item->locations;
434 $location_id = $this->config['Settings']['zoho_location_id'];
435 foreach ( $locations as $location ) {
436 if ( $location->location_id === $location_id ) {
437 if ( $accounting_stock ) {
438 $stock = $location->location_available_for_sale_stock;
439 } else {
440 $stock = $location->location_actual_available_for_sale_stock;
441 }
442 }
443 }
444 } elseif ( $accounting_stock ) {
445 $stock = $item->available_for_sale_stock;
446 } else {
447 $stock = $item->actual_available_for_sale_stock;
448 }
449
450 if ( is_numeric( $stock ) ) {
451 $product->set_manage_stock( true );
452 $product->set_stock_quantity( number_format( $stock, 0, '.', '' ) );
453 if ( $stock > 0 ) {
454 $product->set_stock_status( 'instock' );
455 } else {
456 $backorder_status = $product->backorders_allowed();
457 $status = ( 'yes' === $backorder_status ) ? 'onbackorder' : 'outofstock';
458 $product->set_stock_status( $status );
459 }
460 }
461 }
462 $product->save();
463 update_post_meta( $proid, 'zi_product_errmsg', $errmsg );
464 } else {
465 update_post_meta( $proid, 'zi_product_errmsg', $errmsg );
466 }
467 // fclose($fd);
468 return $errmsg;
469 }
470
471 protected function cmbird_zi_bundle_product_data_zoho( $bundle_id ) {
472 // $fd = fopen(__DIR__ . '/cmbird_zi_bundle_product_data_zoho.txt', 'w+');
473
474 $bundled_product = new WC_Product_Bundle( $bundle_id );
475 $bundle_childs = $bundled_product->get_bundled_items();
476
477 // Allow Bundle Product.
478 $child_array = array();
479 foreach ( $bundle_childs as $child ) {
480 $parent_product = $child->product;
481 $child_id = $child->product_id;
482 $meta_value = WC_PB_DB::get_bundled_item_meta( $child_id, 'quantity_max' );
483 $zi_child_ids = array(); // Array to store zi_child_ids.
484
485 if ( $parent_product->is_type( 'variable' ) ) {
486 $meta_data = WC_PB_DB::get_bundled_item_meta( $child_id, 'allowed_variations' );
487
488 foreach ( $meta_data as $meta ) {
489 if ( $meta->meta_key === 'allowed_variations' ) {
490 $serialized_value = $meta->meta_value;
491 $deserialized_value = maybe_unserialize( $serialized_value );
492
493 if ( is_array( $deserialized_value ) ) {
494 foreach ( $deserialized_value as $variation_id ) {
495 $zi_variation_id = get_post_meta( $variation_id, 'zi_item_id', true );
496 if ( $zi_variation_id ) {
497 $zi_child_ids[] = $zi_variation_id;
498 }
499 }
500 }
501 }
502 }
503 } else {
504 $zi_child_id = get_post_meta( $child_id, 'zi_item_id', true );
505 if ( $zi_child_id ) {
506 $zi_child_ids[] = $zi_child_id;
507 }
508 }
509
510 foreach ( $zi_child_ids as $zi_child_id ) {
511 $json_child = (object) array(
512 'item_id' => $zi_child_id,
513 'quantity' => $meta_value[0]->meta_value,
514 );
515 array_push( $child_array, $json_child );
516 }
517 }
518 $child_items = $child_array;
519
520 // fclose($fd);
521 return $child_items;
522 }
523
524 /**
525 * Create a bundle product on Zoho Inventory.
526 *
527 * @param int $post_id The ID of the product to be created on Zoho Inventory.
528 *
529 * @return string The item ID of the created bundle product on Zoho Inventory.
530 */
531 protected function zi_bundle_product_to_zoho( $post_id ) {
532 // $fd = fopen(__DIR__ . '/zi_bundle_product_to_zoho.txt', 'w+');
533
534 $item = wc_get_product( $post_id );
535 if ( $item->is_type( 'bundle' ) ) {
536
537 $child_items = $this->cmbird_zi_bundle_product_data_zoho( $post_id );
538 }
539
540 $price_r = $item->get_regular_price();
541 $price_s = $item->get_sale_price();
542
543 if ( $price_s ) {
544 $rate = round( $price_s, 2 );
545 } else {
546 $rate = round( $price_r, 2 );
547 }
548 // $rate = 500;
549 // $proid = $item->ID;
550 $pre_name = $item->get_name();
551 $name = preg_replace( "/[>\"''<`]/", '', $pre_name );
552 $sku = $item->get_sku();
553 $stock_quantity = $item->get_stock_quantity();
554 $in_stock = ( $stock_quantity > 0 ) ? $stock_quantity : 0;
555 $in_stock_rate = ( $in_stock * $rate );
556
557 $product_type = 'goods';
558 $item_type = 'inventory';
559 $tax_rates = WC_Tax::get_base_tax_rates( $item->get_tax_class() );
560 $tax_id_key = '';
561 foreach ( $tax_rates as $tax_key => $tax_value ) {
562 $tax_id_key = $tax_key;
563 break;
564 }
565 $tax_option = get_option( 'cmbird_zoho_inventory_tax_rate_' . $tax_id_key );
566 $tax_id = explode( '##', $tax_option )[0];
567 if ( ! empty( $tax_rates ) ) {
568 $tax_rate = reset( $tax_rates );
569 }
570
571 $pdt1 = '"name" : "' . $name . '","mapped_items":' . wp_json_encode( $child_items ) . ', "product_type" : "' . $product_type . '","tax_id" : "' . $tax_id . '","rate" : "' . $rate . '","sku" : "' . $sku . '","item_type" : "' . $item_type . '"';
572 // If zoho category id is not mapped to product, then assign mapped product category with zoho.
573
574 // $zi_category_id = $this->cmbird_zi_get_prod_updated_category($post_id);
575 // if ($zi_category_id) {.
576 // $pdt1 .= ',"category_id" : "' . $zi_category_id . '"';
577 // }.
578
579 $zoho_item_id = get_post_meta( $post_id, 'zi_item_id', true );
580 if ( empty( $zoho_item_id ) ) {
581 $pdt1 .= ',"initial_stock" : ' . $in_stock . ',';
582 $pdt1 .= '"initial_stock_rate" : "' . $in_stock_rate . '"';
583 }
584
585 // Dimensions data append to update call.
586 $dimensions = (object) array();
587 $dimensions->length = $item->get_length();
588 $dimensions->width = $item->get_width();
589 $dimensions->height = $item->get_height();
590 $dimensions->weight = $item->get_weight();
591 $pdt1 .= ',"package_details" : ' . wp_json_encode( $dimensions ) . ',';
592
593 // save the request body for debugging purposes.
594 $zi_body_request = '{' . $pdt1 . '}';
595 update_post_meta( $post_id, 'zi_product_body_request', $zi_body_request );
596
597 $zoho_inventory_oid = $this->config['ProductZI']['OID'];
598 $zoho_inventory_url = $this->config['ProductZI']['APIURL'];
599
600 if ( $zoho_item_id && ctype_digit( $zoho_item_id ) ) {
601 $url_p = $zoho_inventory_url . 'inventory/v1/compositeitems/' . $zoho_item_id;
602 } else {
603 $url_p = $zoho_inventory_url . 'inventory/v1/compositeitems';
604 }
605
606 $data_p = array(
607 'JSONString' => '{' . $pdt1 . '}',
608 'organization_id' => $zoho_inventory_oid,
609 );
610
611 // fwrite($fd, PHP_EOL . 'data_p : ' . print_r($data_p, true));
612
613 $execute_curl_call_handle = new CMBIRD_API_Handler_Zoho();
614
615 if ( $zoho_item_id && ctype_digit( $zoho_item_id ) ) {
616
617 $json = $execute_curl_call_handle->execute_curl_call_put( $url_p, $data_p );
618 $errmsg = $json->message;
619 update_post_meta( $post_id, 'zi_product_errmsg', $errmsg );
620 } else {
621
622 $json = $execute_curl_call_handle->execute_curl_call_post( $url_p, $data_p );
623
624 $code = $json->code;
625 $errmsg = $json->message;
626 update_post_meta( $post_id, 'zi_product_errmsg', $errmsg );
627 if ( '1001' == $code || 1001 == $code ) {
628 $sku_check = str_replace( ' ', '+', $sku );
629 $url = $zoho_inventory_url . 'inventory/v1/compositeitems/?search_text=' . $sku_check . '&organization_id=' . $zoho_inventory_oid;
630 $get_request = $execute_curl_call_handle->execute_curl_call_get( $url );
631 if ( '0' === $get_request->code || 0 === $get_request->code ) {
632 $item_id = '';
633 foreach ( $get_request->composite_items as $zoho_composite ) {
634 // fwrite($fd,PHP_EOL.'ZOHO Item : '.print_r($zoho_item, true));
635 if ( $zoho_composite->sku === $sku ) {
636 $code = 0;
637 $json->composite_item = $zoho_composite;
638 update_post_meta( $post_id, 'zi_product_errmsg', 'Product "' . $zoho_composite->name . '" is mapped successfully with Zoho' );
639 break;
640 }
641 }
642 }
643 }
644 if ( '0' === $code || 0 === $code ) {
645 foreach ( $json->composite_item as $key => $value ) {
646
647 if ( 'composite_item_id' === $key ) {
648 $item_id = $value;
649 }
650 if ( 'purchase_account_id' === $key ) {
651 $purchase_account_id = $value;
652 }
653 if ( 'account_id' === $key ) {
654 $account_id = $value;
655 }
656 if ( 'account_name' === $key ) {
657 $account_name = $value;
658 }
659 if ( 'inventory_account_id' === $key ) {
660 $inventory_account_id = $value;
661 }
662 if ( 'category_id' === $key && ! empty( $value ) ) {
663 update_post_meta( $post_id, 'zi_category_id', $value );
664 }
665 }
666 update_post_meta( $post_id, 'zi_item_id', $item_id );
667 update_post_meta( $post_id, 'zi_purchase_account_id', $purchase_account_id );
668 update_post_meta( $post_id, 'zi_account_id', $account_id );
669 update_post_meta( $post_id, 'zi_account_name', $account_name );
670 update_post_meta( $post_id, 'zi_inventory_account_id', $inventory_account_id );
671 }
672 }
673 // fclose($fd);
674 return $item_id;
675 }
676
677 /**
678 * Pushes the variation product to Zoho Inventory.
679 *
680 * @param int $post_id The post ID of the product.
681 *
682 * @return void
683 */
684 protected function cmbird_zi_variation_product_to_zoho( $post_id ) {
685 // $fd = fopen( __DIR__ . '/cmbird_zi_variation_product_to_zoho.txt', 'a+' );
686
687 $product = wc_get_product( $post_id );
688 if ( ! $product ) {
689 return;
690 }
691 $zoho_group_id = $product->get_meta( 'zi_item_id', true );
692 if ( ! empty( $zoho_group_id ) ) {
693 return;
694 }
695
696 // Check if the the given sku has product in zoho inventory.
697 $sku = $product->get_sku();
698 // use the product name if sku is empty, as Zoho search can match on name as well.
699 if ( empty( $sku ) ) {
700 $sku = $product->get_name();
701 }
702 $zoho_inventory_oid = $this->config['ProductZI']['OID'];
703 $zoho_inventory_url = $this->config['ProductZI']['APIURL'];
704 $sku_check = str_replace( ' ', '+', $sku );
705 $url = $zoho_inventory_url . 'inventory/v1/items?search_text=' . $sku_check . '&filter_by=Status.Active&organization_id=' . $zoho_inventory_oid;
706 $execute_curl_call_handle = new CMBIRD_API_Handler_Zoho();
707 $get_request = $execute_curl_call_handle->execute_curl_call_get( $url );
708
709 // Guard against transport/errors and ensure Zoho returned a successful response with items.
710 if ( ! is_wp_error( $get_request ) && 0 === (int) $get_request->code && isset( $get_request->items ) && is_array( $get_request->items ) ) {
711 // build lookups keyed by SKU for quick matching.
712 // A Zoho item may carry the SKU in either the `sku` field or the `name` field.
713 $zoho_items_by_sku = array();
714 $zoho_group_by_sku = array();
715 foreach ( $get_request->items as $zi_item ) {
716 // Collect candidate SKU values: prefer explicit sku field, fall back to name.
717 $candidates = array();
718 if ( ! empty( $zi_item->sku ) ) {
719 $candidates[] = $zi_item->sku;
720 }
721 if ( ! empty( $zi_item->name ) ) {
722 $candidates[] = $zi_item->name;
723 }
724 foreach ( $candidates as $candidate ) {
725 $sku_lc = strtolower( trim( $candidate ) );
726 $zoho_items_by_sku[ $sku_lc ] = $zi_item->item_id;
727 if ( ! empty( $zi_item->group_id ) ) {
728 $zoho_group_by_sku[ $sku_lc ] = (int) $zi_item->group_id;
729 }
730 }
731 }
732 // Match each Woo variation's SKU to a Zoho item. Save item_id on the variation and,
733 // from the first match, capture the group_id to save on the parent product.
734 $child_ids = $product->get_children();
735 $matched_group_id = null;
736 foreach ( $child_ids as $child_id ) {
737 $variation = wc_get_product( $child_id );
738 if ( ! $variation ) {
739 continue;
740 }
741 $var_sku_lc = strtolower( trim( (string) $variation->get_sku() ) );
742 if ( $var_sku_lc && isset( $zoho_items_by_sku[ $var_sku_lc ] ) ) {
743 $variation->update_meta_data( 'zi_item_id', $zoho_items_by_sku[ $var_sku_lc ] );
744 $variation->save();
745 // Capture group_id from the first matched item to store on the parent.
746 if ( null === $matched_group_id && isset( $zoho_group_by_sku[ $var_sku_lc ] ) ) {
747 $matched_group_id = $zoho_group_by_sku[ $var_sku_lc ];
748 }
749 }
750 }
751 if ( $matched_group_id ) {
752 $product->update_meta_data( 'zi_item_id', $matched_group_id );
753 $product->update_meta_data( 'zi_product_errmsg', 'Variation products are mapped with Zoho item group successfully' );
754 $product->save();
755 return;
756 }
757 }
758
759 $pre_name = $product->get_title();
760 $name = preg_replace( "/[>\"''<`]/", '', $pre_name );
761
762 $tax_rates = WC_Tax::get_base_tax_rates( $product->get_tax_class() );
763 $tax_id_key = '';
764 foreach ( $tax_rates as $tax_key => $tax_value ) {
765 $tax_id_key = $tax_key;
766 break;
767 }
768 $tax_option = get_option( 'cmbird_zoho_inventory_tax_rate_' . $tax_id_key );
769 $tax_id = explode( '##', $tax_option )[0];
770 $zi_category_id = $this->cmbird_zi_get_prod_updated_category( $post_id );
771
772 $zidata = '"group_name" : "' . $name . '", "tax_id" : "' . $tax_id . '","category_id" : "' . $zi_category_id . '",';
773
774 // attributes.
775 $attributes = $product->get_attributes();
776 // fwrite($fd, PHP_EOL . 'ATTRIBUTES : ' . print_r($attributes, true));
777
778 $attribute_name1 = '';
779 $attribute_name2 = '';
780 $attribute_name3 = '';
781 foreach ( $attributes as $attribute ) {
782 if ( ! empty( $attribute ) ) {
783 $attrname1 = $attribute->get_name();
784 $attrname = str_replace( '"', '', $attrname1 );
785 if ( ! empty( $attrname ) && $attribute['variation'] ) {
786 if ( empty( $attribute_name1 ) ) {
787 $attribute_name1 = $attrname;
788 } elseif ( empty( $attribute_name2 ) ) {
789 $attribute_name2 = $attrname;
790 } elseif ( empty( $attribute_name3 ) ) {
791 $attribute_name3 = $attrname;
792 }
793 }
794 }
795 }
796 if ( ! empty( $attribute_name1 ) ) {
797 $zidata .= '"attribute_name1": "' . $attribute_name1 . '",';
798 }
799 if ( ! empty( $attribute_name2 ) ) {
800 $zidata .= '"attribute_name2": "' . $attribute_name2 . '",';
801 }
802 if ( ! empty( $attribute_name3 ) ) {
803 $zidata .= '"attribute_name3": "' . $attribute_name3 . '",';
804 }
805
806 $available_variations = $product->get_children();
807 // If there is attributes variations then append that data to server.
808 $items = array();
809 if ( count( $available_variations ) > 0 ) {
810 foreach ( $available_variations as $child_id ) {
811
812 $product_variable = wc_get_product( $child_id );
813 $items[] = $this->cmbird_zi_variants_products( $product_variable, $child_id, $attribute_name1, $attribute_name2, $attribute_name3 );
814 }
815 }
816
817 // get category id.
818 // $zi_category_id = $this->cmbird_zi_get_prod_updated_category($post_id);
819 // if ($zi_category_id) {.
820 // $zidata .= '"category_id" : "' . $zi_category_id . '",';
821 // }.
822
823 $zidata .= '"items" :[' . implode( ',', $items ) . ']';
824 // save the request body for debugging purposes.
825 $zi_body_request = rtrim( $zidata, ',' );
826 $product->update_meta_data( 'zi_product_body_request', '{' . $zi_body_request . '}' );
827 $product->save();
828
829 $data = array(
830 'JSONString' => '{' . $zidata . '}',
831 );
832
833 // fwrite($fd, PHP_EOL . 'ZI Data JSON : ' . '{' . print_r($data, true) . '}');
834 // fclose($fd);
835
836 $zoho_inventory_oid = $this->config['ProductZI']['OID'];
837 $zoho_inventory_url = $this->config['ProductZI']['APIURL'];
838
839 if ( ! empty( $zoho_inventory_oid ) ) {
840 $url = $zoho_inventory_url . 'inventory/v1/itemgroups?organization_id=' . $zoho_inventory_oid;
841
842 $execute_curl_call_handle = new CMBIRD_API_Handler_Zoho();
843 $json = $execute_curl_call_handle->execute_curl_call_post( $url, $data );
844
845 $errmsg = $json->message;
846 $product->update_meta_data( 'zi_product_errmsg', $errmsg );
847 $product->save();
848 $code = $json->code;
849 if ( '0' === $code || 0 === $code ) {
850
851 // This item will keep the copy of zoho item_id with respect to product.
852 // name as key synced to zoho.
853 $child_items = array();
854 foreach ( $json->item_group as $key => $value ) {
855 if ( 'group_id' === $key ) {
856 $group_id = $value;
857 }
858
859 if ( 'items' === $key ) {
860 foreach ( $value as $key2 => $val2 ) {
861 // Only map child items by SKU — skip entries without SKU.
862 if ( ! empty( $val2->sku ) ) {
863 $child_items[ strtolower( trim( $val2->sku ) ) ] = $val2->item_id;
864 }
865 }
866 }
867 }
868 if ( ! empty( $group_id ) ) {
869 $product->update_meta_data( 'zi_item_id', $group_id );
870 $product->save();
871 }
872
873 foreach ( $available_variations as $child_id ) {
874 $product_variable = wc_get_product( $child_id );
875
876 $var_sku = trim( (string) $product_variable->get_sku() );
877 if ( $var_sku && isset( $child_items[ strtolower( $var_sku ) ] ) ) {
878 $variation = wc_get_product( $child_id );
879 if ( $variation ) {
880 $variation->update_meta_data( 'zi_item_id', $child_items[ strtolower( $var_sku ) ] );
881 $variation->save();
882 }
883 }
884 }
885 }
886 }
887 // End New Variable Product.
888 }
889
890 /**
891 * Function to sync variations of a product.
892 *
893 * @param object $product_variable - WooCommerce product object of a variation.
894 * @param int $post_id - Post ID of a variation product.
895 * @param string $attr1 - Attribute 1 name.
896 * @param string $attr2 - Attribute 2 name.
897 * @param string $attr3 - Attribute 3 name.
898 * @return string $item_id - Zoho item id of a variation product.
899 */
900 protected function cmbird_zi_variants_products( $product_variable, $post_id, $attr1 = '', $attr2 = '', $attr3 = '' ) {
901 // $fd = fopen(__DIR__.'/variations_products.txt','a+');
902 // fwrite($fd,PHP_EOL.'-------------------------------');
903 // fwrite($fd,PHP_EOL.'$attr1 : '.$attr1.' | $attr2 : '.$attr2.' | $attr3 : '.$attr3.' $post_id : '.$post_id);
904 // Sync Attributes of Variable Products.
905
906 $attributes = $product_variable->get_variation_attributes();
907 // fwrite($fd,PHP_EOL.'$variation_attributes : '.print_r($attributes,true));
908 $arrtibute_string = '';
909 if ( ! empty( $attr1 ) ) {
910 $attr_key = strtolower( $attr1 );
911 $attr_key = 'attribute_' . str_replace( ' ', '-', $attr_key );
912 $arrtibute_string .= '"attribute_option_name1": "' . str_replace( '"', '', $attributes[ $attr_key ] ) . '",';
913 }
914 if ( ! empty( $attr2 ) ) {
915 $attr_key = strtolower( $attr2 );
916 $attr_key = 'attribute_' . str_replace( ' ', '-', $attr_key );
917 $arrtibute_string .= '"attribute_option_name2": "' . str_replace( '"', '', $attributes[ $attr_key ] ) . '",';
918 }
919 if ( ! empty( $attr3 ) ) {
920 $attr_key = strtolower( $attr3 );
921 $attr_key = 'attribute_' . str_replace( ' ', '-', $attr_key );
922 $arrtibute_string .= '"attribute_option_name3": "' . str_replace( '"', '', $attributes[ $attr_key ] ) . '",';
923 }
924 // fwrite($fd,PHP_EOL.'$arrtibute_string : '.$arrtibute_string);
925 // fclose($fd);
926 // Use product object meta accessor instead of direct postmeta.
927 $zoho_item_id = $product_variable->get_meta( 'zi_item_id', true );
928
929 // $product_variable = wc_get_product($post_id);
930 $pname = '';
931 foreach ( $product_variable->get_variation_attributes() as $taxonomy => $terms_slug ) {
932
933 $pname .= $terms_slug;
934 }
935
936 $vname = $product_variable->get_name();
937 $name = wp_strip_all_tags( $vname );
938 $name = preg_replace( '/[^\w\s\-]/', '', $name );
939 $rate = $product_variable->get_regular_price();
940 // $rateS = $product_variable->get_sale_price();
941 if ( $product_variable->is_virtual( 'yes' ) ) {
942 $product_type = 'service';
943 $item_type = 'sales';
944 } else {
945 $product_type = 'goods';
946 $item_type = 'inventory';
947 }
948
949 $sku = $product_variable->get_sku();
950 $stock_quantity = $product_variable->get_stock_quantity();
951 $in_stock = ( $stock_quantity > 0 ) ? $stock_quantity : 0;
952 // Get Tax ID.
953 $tax_rates = WC_Tax::get_base_tax_rates( $product_variable->get_tax_class() );
954 $tax_id_key = '';
955 foreach ( $tax_rates as $tax_key => $tax_value ) {
956 $tax_id_key = $tax_key;
957 break;
958 }
959 $tax_option = get_option( 'cmbird_zoho_inventory_tax_rate_' . $tax_id_key );
960 $tax_id = explode( '##', $tax_option )[0];
961
962 $zi_status = ( 'publish' === get_post_status( $post_id ) ) ? 'active' : 'inactive';
963 // request data for adding/updating value to zoho.
964 $zidata = '';
965 if ( ! empty( $arrtibute_string ) ) {
966 $zidata .= $arrtibute_string;
967 }
968 $zidata .= '"name" : "' . $name . '",';
969 $zidata .= '"product_type" : "' . $product_type . '",';
970 $zidata .= '"sku" : "' . $sku . '",';
971 $zidata .= '"item_type" : "' . $item_type . '",';
972 // $zidata .= '"unit" : "pcs",';
973 $zidata .= '"status" : "' . $zi_status . '",';
974 if ( empty( $zoho_item_id ) && $in_stock > 0 ) {
975 $zidata .= '"initial_stock" : ' . $in_stock . ',';
976 $zidata .= '"initial_stock_rate" : ' . $in_stock . ',';
977 }
978 $zidata .= '"rate" : "' . $rate . '",';
979 $zidata .= '"tax_id" : "' . $tax_id . '",';
980 // Get cost_price from product meta using the WC product object.
981 $cost_price = $product_variable->get_meta( '_cogs_total_value', true );
982 if ( ! empty( $cost_price ) && is_numeric( $cost_price ) ) {
983 $zidata .= '"purchase_rate" : "' . $cost_price . '",';
984 }
985
986 $dimensions = (object) array();
987 $dimensions->length = $product_variable->get_length();
988 $dimensions->width = $product_variable->get_width();
989 $dimensions->height = $product_variable->get_height();
990 $dimensions->weight = $product_variable->get_weight();
991 if ( ! empty( $dimensions ) ) {
992 $zidata .= '"package_details" : ' . wp_json_encode( $dimensions );
993 }
994
995 // $fd = fopen(__DIR__ . '/variations.txt', 'a+');
996 // fwrite($fd,PHP_EOL.'Get data for $post_id '.$post_id);
997 if ( ctype_digit( $zoho_item_id ) && ! empty( $zoho_item_id ) ) {
998 // fwrite($fd, PHP_EOL . 'Update Item');
999 $update_error_msg = $this->cmbird_zi_product_put( $post_id, $zoho_item_id, $zidata );
1000 $zidataa = '';
1001 // fwrite($fd, PHP_EOL . '{' . $zidata . '}');
1002 return $zidataa .= '{' . $zidata . '}';
1003 } else {
1004 // fwrite($fd, PHP_EOL . 'Create Item');
1005 // Check if the the given sku has product in zoho inventory.
1006 $zoho_inventory_oid = $this->config['ProductZI']['OID'];
1007 $zoho_inventory_url = $this->config['ProductZI']['APIURL'];
1008 $sku_check = str_replace( ' ', '+', $sku );
1009 $url = $zoho_inventory_url . 'inventory/v1/items?search_text=' . $sku_check . '&filter_by=Status.Active&organization_id=' . $zoho_inventory_oid;
1010 $execute_curl_call_handle = new CMBIRD_API_Handler_Zoho();
1011 $get_request = $execute_curl_call_handle->execute_curl_call_get( $url );
1012 $var_item_id = '';
1013 $groupitem_id = '';
1014
1015 // Guard against transport/errors and ensure Zoho returned a successful response with items.
1016 if ( ! is_wp_error( $get_request ) && property_exists( $get_request, 'code' ) && (int) $get_request->code === 0 && property_exists( $get_request, 'items' ) && is_array( $get_request->items ) ) {
1017 foreach ( $get_request->items as $zoho_item ) {
1018 // match SKU exactly (trimmed) to avoid false positives from Zoho's "contains" search
1019 if ( isset( $zoho_item->sku ) && trim( (string) $zoho_item->sku ) === trim( (string) $sku ) ) {
1020 // prefer active items only
1021 if ( ! isset( $zoho_item->status ) || 'active' === $zoho_item->status ) {
1022 $var_item_id = $zoho_item->item_id ?? '';
1023 $groupitem_id = $zoho_item->group_id ?? '';
1024 break;
1025 }
1026 }
1027 }
1028 }
1029
1030 $zidataa = '';
1031 if ( $var_item_id ) {
1032 // Persist mapping on the variation using WC_Product API.
1033 $product_variable->update_meta_data( 'zi_item_id', $var_item_id );
1034 $product_variable->save();
1035 }
1036 if ( $groupitem_id ) {
1037 $parent_product_id = wp_get_post_parent_id( $post_id );
1038 if ( $parent_product_id ) {
1039 $parent_product = wc_get_product( $parent_product_id );
1040 if ( $parent_product ) {
1041 $parent_product->update_meta_data( 'zi_item_id', $groupitem_id );
1042 $parent_product->save();
1043 }
1044 }
1045 }
1046 // fwrite($fd, PHP_EOL . '$var_item_id : ' . $var_item_id);
1047 // fclose($fd);
1048 return $zidataa .= '{' . $zidata . '}';
1049 }
1050 }
1051
1052 /**
1053 * Check if category already exists and return updated one
1054 */
1055 protected function cmbird_zi_get_prod_updated_category( $product_id ) {
1056 // Check if product category already synced.
1057 $terms = get_the_terms( $product_id, 'product_cat' );
1058 if ( $terms ) {
1059 foreach ( $terms as $term ) {
1060 $product_cat_id = $term->term_id;
1061 $zoho_cat_id = get_option( "cmbird_zoho_id_for_term_id_{$product_cat_id}" );
1062 if ( $zoho_cat_id ) {
1063 break;
1064 }
1065 }
1066 }
1067 // Check if product has already mapped category.
1068 if ( empty( $zoho_cat_id ) ) {
1069 $zoho_cat_id = get_post_meta( $product_id, 'zi_category_id', true );
1070 }
1071
1072 if ( $zoho_cat_id ) {
1073 return $zoho_cat_id;
1074 } else {
1075 return false;
1076 }
1077 }
1078
1079 /**
1080 * Function for adding Simple product from Zoho to woocommerce.
1081 *
1082 * @param $prod - Product object for adding new product in woocommerce.
1083 * @param $user_id - Current Active user Id
1084 * @param string $type - product is composite item or not (composite)
1085 */
1086 public function cmbird_zi_product_to_woocommerce( $item, $item_stock = '', $type = '' ) {
1087 // $fd = fopen( __DIR__ . '/cmbird_zi_product_to_woocommerce.txt', 'a+' );
1088 try {
1089 if ( 'active' !== $item['status'] ) {
1090 return;
1091 }
1092 $product = new WC_Product();
1093
1094 $allow_backorders = get_option( 'woocommerce_allow_backorders' );
1095 $zi_disable_stock_sync = get_option( 'cmbird_zoho_disable_stock_sync_status' );
1096
1097 // Set the product data.
1098 $product->set_status( 'publish' );
1099 $product->set_name( $item['name'] );
1100 $product->set_regular_price( $item['rate'] );
1101 $product->set_short_description( $item['description'] );
1102 $product->set_sku( $item['sku'] );
1103
1104 // Set the stock management properties.
1105 if ( ! empty( $item_stock ) && ! $zi_disable_stock_sync ) {
1106 $product->set_manage_stock( true );
1107 $product->set_stock_quantity( $item_stock );
1108
1109 if ( $item_stock > 0 ) {
1110 $product->set_stock_status( 'instock' );
1111 } elseif ( $item_stock < 0 && 'yes' === $allow_backorders ) {
1112 $product->set_stock_status( 'onbackorder' );
1113 } else {
1114 $product->set_stock_status( 'outofstock' );
1115 }
1116 }
1117
1118 // Save the product.
1119 $product_id = $product->save();
1120
1121 // Map composite items metadata to convert product as a bundle product.
1122 if ( 'composite' === $type ) {
1123 update_post_meta( $product_id, '_wc_pb_layout_style', 'default' );
1124 update_post_meta( $product_id, '_wc_pb_add_to_cart_form_location', 'default' );
1125 wp_set_object_terms( $product_id, 'bundle', 'product_type' );
1126 }
1127
1128 return $product_id;
1129 } catch ( Exception $e ) {
1130 // Handle the exception, log it, or perform any necessary actions.
1131 return new WP_Error( 'Error creating WooCommerce product: ' . $e->getMessage() );
1132 }
1133 }
1134 }
1135 $cmbird_products_zi_export = new CMBIRD_Products_ZI_Export();
1136