PluginProbe ʕ •ᴥ•ʔ
CommerceBird – AI Command Center, ERP Integrations & B2B for WooCommerce (Zoho, Exact Online). / 2.3.14
CommerceBird – AI Command Center, ERP Integrations & B2B for WooCommerce (Zoho, Exact Online). v2.3.14
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-categories.php 1 year ago class-import-image.php 11 months ago class-import-items.php 11 months ago class-import-price-list.php 1 year ago class-multi-currency.php 1 year ago class-order-sync.php 11 months ago class-product.php 1 year ago class-users-contact.php 1 year ago index.php 1 year ago
class-product.php
938 lines
1 <?php
2
3 /**
4 * Class for All Product Data from Woo To Zoho
5 *
6 * @package WooZo Inventory
7 */
8 if ( ! defined( 'ABSPATH' ) ) {
9 exit;
10 }
11 class CMBIRD_Products_ZI_Export {
12
13 private $config;
14
15 public function __construct() {
16 $this->config = array(
17 'ProductZI' => array(
18 'OID' => get_option( 'cmbird_zoho_inventory_oid' ),
19 'APIURL' => get_option( 'cmbird_zoho_inventory_url' ),
20 ),
21 'Settings' => array(
22 'disable_description' => get_option( 'cmbird_zoho_disable_description_sync_status' ),
23 'disable_name' => get_option( 'cmbird_zoho_disable_name_sync_status' ),
24 'disable_price' => get_option( 'cmbird_zoho_disable_price_sync_status' ),
25 'disable_stock' => get_option( 'cmbird_zoho_disable_stock_sync_status' ),
26 'enable_accounting_stock' => get_option( 'cmbird_zoho_enable_accounting_stock_status' ),
27 'enable_location_stock' => get_option( 'cmbird_zoho_enable_locationstock_status' ),
28 'zoho_location_id' => get_option( 'cmbird_zoho_location_id_status' ),
29 'disable_image' => get_option( 'cmbird_zoho_disable_image_sync_status' ),
30 ),
31 );
32 }
33
34 public function cmbird_zi_products_prepare_sync( $product_ids ) {
35 $rate_limit = get_option( 'cmbird_zoho_rate_limit_exceeded' );
36 if ( is_array( $product_ids ) ) {
37 // schedule the unsynced products for tomorrow via action scheduler
38 if ( $rate_limit ) {
39 $timestamp = strtotime( 'tomorrow' );
40 // set the zoho rate limit option exceeded to false tomorrow if not scheduled yet.
41 if ( ! wp_next_scheduled( 'cmbird_common' ) ) {
42 wp_schedule_single_event( $timestamp, 'cmbird_common' );
43 }
44 // Get all scheduled actions with the specific hook name
45 $action_ids = as_get_scheduled_actions(
46 array(
47 'hook' => 'sync_zi_product_cron',
48 'status' => ActionScheduler_Store::STATUS_PENDING,
49 'per_page' => -1,
50 )
51 );
52 // Loop through each action and reschedule it
53 if ( ! empty( $action_ids ) ) {
54 foreach ( $action_ids as $action_id ) {
55 // Fetch the action by ID
56 $action = as_get_scheduled_action( $action_id );
57 // If the action is valid and exists, reschedule it
58 if ( $action ) {
59 // Reschedule the action to run tomorrow
60 as_schedule_single_action( $timestamp, 'sync_zi_product_cron', $action->get_args(), 'ActionScheduler' );
61 // Cancel the old action to avoid duplicates
62 as_unschedule_action( 'sync_zi_product_cron', $action->get_args(), $action_id );
63 }
64 }
65 }
66 } else {
67 foreach ( $product_ids as $product_id ) {
68 $this->cmbird_zi_product_sync( $product_id );
69 }
70 }
71 }
72 }
73
74 /**
75 * Starting point to sync Product to Zoho Inventory. If product type is other than simple, pass the product_id to different function
76 *
77 * @param [type] $post_id
78 * @return string - item_id of Zoho Inventory
79 */
80 public function cmbird_zi_product_sync( $post_id ) {
81
82 // $fd = fopen(__DIR__.'/product_class.txt','a+');
83 $item_id = '';
84
85 if ( is_array( $post_id ) ) {
86 $product_id = intval( $post_id['0'] );
87 $post_id = $product_id;
88 }
89
90 if ( 'publish' !== get_post_status( $post_id ) ) {
91 return $item_id;
92 }
93
94 $product = wc_get_product( $post_id );
95 if ( $product->is_type( 'bundle' ) ) {
96 // fwrite($fd,PHP_EOL.'Inside bundle: ');
97 $item_id = $this->zi_bundle_product_to_zoho( $post_id );
98 return $item_id;
99 } elseif ( $product->is_type( 'variable' ) ) {
100 // fwrite($fd,PHP_EOL.'Inside variable: ');
101 $this->cmbird_zi_variation_product_to_zoho( $post_id );
102 } else {
103 // fwrite($fd,PHP_EOL.'Inside Regular: ');
104 // Simple product.
105 $rate = $product->get_regular_price();
106 $pre_name = $product->get_name();
107 $name = preg_replace( "/[>\"''<`]/", '', $pre_name );
108
109 $sku = $product->get_sku();
110 $stock_quantity = $product->get_stock_quantity();
111 $in_stock = ( $stock_quantity > 0 ) ? $stock_quantity : 0;
112 // fwrite($fd,PHP_EOL.'$product->get_stock_quantity() : '.$product->get_stock_quantity());
113 $in_stock_rate = $in_stock * (int) $rate;
114
115 $tax_rates = WC_Tax::get_base_tax_rates( $product->get_tax_class() );
116 $tax_id_key = '';
117 foreach ( $tax_rates as $tax_key => $tax_value ) {
118 $tax_id_key = $tax_key;
119 break;
120 }
121 $tax_option = get_option( 'cmbird_zoho_inventory_tax_rate_' . $tax_id_key );
122 $tax_id = explode( '##', $tax_option )[0];
123
124 $zi_status = ( 'publish' === get_post_status( $post_id ) ) ? 'active' : 'inactive';
125 // request data for adding/updating value to zoho.
126 $zi_disable_itemname_sync = get_option( 'cmbird_zoho_disable_name_sync_status' );
127 $zoho_item_id = get_post_meta( $post_id, 'zi_item_id', true );
128
129 $zidata = '';
130 if ( empty( $zoho_item_id ) || 'true' != $zi_disable_itemname_sync ) {
131 $zidata .= '"name" : "' . $name . '",';
132 }
133
134 if ( $product->is_virtual( 'yes' ) ) {
135 $zidata .= '"product_type" : "service",';
136 $zidata .= '"item_type" : "sales",';
137 } else {
138 $zidata .= '"product_type" : "goods",';
139 $zidata .= '"item_type" : "inventory",';
140 }
141
142 $zidata .= '"sku" : "' . $sku . '",';
143 // $zidata .= '"unit" : "pcs",';
144 $zidata .= '"status" : "' . $zi_status . '",';
145 // Initial stock update only if item sync for first time.
146 if ( empty( $zoho_item_id ) ) {
147 $zidata .= '"initial_stock" : ' . $in_stock . ',';
148 $zidata .= '"initial_stock_rate" : "' . $in_stock_rate . '",';
149 }
150 $zidata .= '"rate" : "' . $rate . '",';
151 if ( $tax_id ) {
152 $zidata .= '"tax_id" : "' . $tax_id . '",';
153 }
154 //$zidata .= '"image_name" : "' . $image . '",';
155
156 // Get cost_price from meta data.
157 $cost_price = $product->get_meta( '_cost_price' );
158 if ( ! empty( $cost_price ) && is_numeric( $cost_price ) ) {
159 $zidata .= '"purchase_rate" : "' . $cost_price . '",';
160 }
161
162 $dimensions = (object) array();
163 $dimensions->length = $product->get_length();
164 $dimensions->width = $product->get_width();
165 $dimensions->height = $product->get_height();
166 $dimensions->weight = $product->get_weight();
167 $zidata .= '"package_details" : ' . wp_json_encode( $dimensions ) . ',';
168
169 // Send category only if category ID available.
170 $zi_category_id = $this->cmbird_zi_get_prod_updated_category( $post_id );
171 if ( $zi_category_id ) {
172 $zidata .= '"category_id" : "' . $zi_category_id . '"';
173 }
174
175 // $zidata .= '"image_type" : "' . $ext . '"';
176 if ( ! empty( $zoho_item_id ) && ctype_digit( $zoho_item_id ) ) {
177 // fwrite($fd,PHP_EOL.'Inside Update: ');
178 $this->cmbird_zi_product_put( $post_id, $zoho_item_id, $zidata );
179 } else {
180 // fwrite($fd,PHP_EOL.'Inside Create ');
181 $zoho_inventory_oid = $this->config['ProductZI']['OID'];
182 $zoho_inventory_url = $this->config['ProductZI']['APIURL'];
183
184 $data = array(
185 'JSONString' => '{' . $zidata . '}',
186 'organization_id' => $zoho_inventory_oid,
187 );
188 $url = $zoho_inventory_url . 'inventory/v1/items';
189
190 $execute_curl_call_handle = new CMBIRD_API_Handler_Zoho();
191 $json = $execute_curl_call_handle->execute_curl_call_post( $url, $data );
192
193 $errmsg = $json->message;
194 update_post_meta( $post_id, 'zi_product_errmsg', $errmsg );
195
196 $code = $json->code;
197 // fwrite($fd,PHP_EOL.'JSON Response : '.print_r($json,true));
198 // Check if the the given sku has product at zoho inventory.
199 if ( '1001' === $code || 1001 === $code ) {
200 // fwrite($fd,PHP_EOL.'Inside SKU Check');
201 $sku_check = str_replace( ' ', '+', $sku );
202 $url = $zoho_inventory_url . 'inventory/v1/items?search_text=' . $sku_check . '&organization_id=' . $zoho_inventory_oid;
203 $get_request = $execute_curl_call_handle->execute_curl_call_get( $url );
204
205 if ( '0' === $get_request->code || 0 === $get_request->code ) {
206 $item_id = '';
207 $matching_item = null;
208
209 foreach ( $get_request->items as $zoho_item ) {
210 if ( $zoho_item->sku === $sku ) {
211 // SKU matched
212 $matching_item = $zoho_item;
213 break;
214 }
215 }
216
217 // If SKU check didn't find a match, perform name check
218 if ( ! $matching_item ) {
219 $item_name_check = str_replace( ' ', '+', $name );
220 $url = $zoho_inventory_url . 'inventory/v1/items?search_text=' . $item_name_check . '&organization_id=' . $zoho_inventory_oid;
221 $get_request = $execute_curl_call_handle->execute_curl_call_get( $url );
222
223 if ( '0' === $get_request->code || 0 === $get_request->code ) {
224 foreach ( $get_request->items as $zoho_item ) {
225 if ( $zoho_item->name === $name ) {
226 // Name matched
227 $matching_item = $zoho_item;
228 break;
229 }
230 }
231 }
232 }
233
234 if ( $matching_item ) {
235 $code = 0;
236 $json->item = $matching_item;
237 update_post_meta( $post_id, 'zi_product_errmsg', 'Product "' . $matching_item->name . '" is mapped successfully with Zoho' );
238 }
239 }
240 }
241 // fwrite($fd,PHP_EOL.'After SKU Check : code '.$code);
242 if ( '0' === $code || 0 === $code ) {
243 foreach ( $json->item as $key => $value ) {
244 if ( 'item_id' === $key ) {
245 $item_id = $value;
246 }
247 if ( 'purchase_account_id' === $key ) {
248 $purchase_account_id = $value;
249 }
250 if ( 'account_id' === $key ) {
251 $account_id = $value;
252 }
253 if ( 'account_name' === $key ) {
254 $account_name = $value;
255 }
256 if ( 'inventory_account_id' === $key ) {
257 $inventory_account_id = $value;
258 }
259 if ( 'category_id' === $key && ! empty( $value ) ) {
260 update_post_meta( $post_id, 'zi_category_id', $value );
261 }
262 }
263 update_post_meta( $post_id, 'zi_item_id', $item_id );
264 update_post_meta( $post_id, 'zi_purchase_account_id', $purchase_account_id );
265 update_post_meta( $post_id, 'zi_account_id', $account_id );
266 update_post_meta( $post_id, 'zi_account_name', $account_name );
267 update_post_meta( $post_id, 'zi_inventory_account_id', $inventory_account_id );
268 }
269 }
270 } // loop end
271 // fclose($fd);
272 return $item_id;
273 }
274
275 /**
276 * Function to update zoho item if already exists.
277 *
278 * @param number $proid - product number.
279 * @param number $item_id - zoho item id.
280 * @param mixed $pdt3 - Zoho item object for post request.
281 * @return string
282 */
283 public function cmbird_zi_product_put( $proid, $item_id, $pdt3 = '' ) {
284 // $fd = fopen(__DIR__.'/product_class.txt','a+');
285 // fwrite($fd,PHP_EOL.'Inside update : ');
286 $errmsg = '';
287 $zoho_inventory_oid = $this->config['ProductZI']['OID'];
288 $zoho_inventory_url = $this->config['ProductZI']['APIURL'];
289
290 $url = $zoho_inventory_url . 'inventory/v1/items/' . $item_id;
291 // fwrite($fd,PHP_EOL.'JSON Data : '.'{' . $pdt3 . '}');
292 $data = array(
293 'JSONString' => '{' . $pdt3 . '}',
294 'organization_id' => $zoho_inventory_oid,
295 );
296
297 // if pdt3 is empty then do GET call, else do PUT call
298 if ( empty( $pdt3 ) ) {
299 $execute_curl_call_handle = new CMBIRD_API_Handler_Zoho();
300 $json = $execute_curl_call_handle->execute_curl_call_get( $url );
301 $code = $json->code;
302 $errmsg = $json->message;
303 } else {
304 $execute_curl_call_handle = new CMBIRD_API_Handler_Zoho();
305 $json = $execute_curl_call_handle->execute_curl_call_put( $url, $data );
306 $code = $json->code;
307 $errmsg = $json->message;
308 }
309
310 if ( 0 === $code || '0' === $code ) {
311 $product = wc_get_product( $proid );
312 // if type is not simple then return.
313 if ( ! $product->is_type( 'simple' ) ) {
314 return $errmsg;
315 }
316 $item = $json->item;
317 // update price
318 $zi_disable_itemprice_sync = $this->config['Settings']['disable_price'];
319 if ( ! empty( $item->rate ) && ! $zi_disable_itemprice_sync ) {
320 $product->set_regular_price( $item->rate );
321 $sale_price = $product->get_sale_price();
322 if ( empty( $sale_price ) ) {
323 $product->set_price( $item->rate );
324 }
325 }
326 // To check status of stock sync option.
327 $zi_disable_stock_sync = $this->config['Settings']['disable_stock'];
328 if ( ! $zi_disable_stock_sync && isset( $item->available_for_sale_stock ) ) {
329 $stock = '';
330 // Update stock
331 $accounting_stock = $this->config['Settings']['enable_accounting_stock'];
332 // Sync from specific location check
333 $zi_enable_locationstock = $this->config['Settings']['enable_location_stock'];
334 if ( $zi_enable_locationstock && isset( $item->locations ) ) {
335 $locations = $item->locations;
336 $location_id = $this->config['Settings']['zoho_location_id'];
337 foreach ( $locations as $location ) {
338 if ( $location->location_id === $location_id ) {
339 if ( $accounting_stock ) {
340 $stock = $location->location_available_for_sale_stock;
341 } else {
342 $stock = $location->location_actual_available_for_sale_stock;
343 }
344 }
345 }
346 } elseif ( $accounting_stock ) {
347 $stock = $item->available_for_sale_stock;
348 } else {
349 $stock = $item->actual_available_for_sale_stock;
350 }
351
352 if ( is_numeric( $stock ) ) {
353 $product->set_manage_stock( true );
354 $product->set_stock_quantity( number_format( $stock, 0, '.', '' ) );
355 if ( $stock > 0 ) {
356 $product->set_stock_status( 'instock' );
357 } else {
358 $backorder_status = $product->backorders_allowed();
359 $status = ( 'yes' === $backorder_status ) ? 'onbackorder' : 'outofstock';
360 $product->set_stock_status( $status );
361 }
362 }
363 }
364 $product->save();
365 update_post_meta( $proid, 'zi_product_errmsg', $errmsg );
366 } else {
367 update_post_meta( $proid, 'zi_product_errmsg', $errmsg );
368 }
369 // fclose($fd);
370 return $errmsg;
371 }
372
373 protected function cmbird_zi_bundle_product_data_zoho( $bundle_id ) {
374 // $fd = fopen(__DIR__ . '/cmbird_zi_bundle_product_data_zoho.txt', 'w+');
375
376 $bundled_product = new WC_Product_Bundle( $bundle_id );
377 $bundle_childs = $bundled_product->get_bundled_items();
378
379 // Allow Bundle Product
380 $child_array = array();
381 foreach ( $bundle_childs as $child ) {
382 $parent_product = $child->product;
383 $child_id = $child->product_id;
384 $meta_value = WC_PB_DB::get_bundled_item_meta( $child_id, 'quantity_max' );
385 $zi_child_ids = array(); // Array to store zi_child_ids
386
387 if ( $parent_product->is_type( 'variable' ) ) {
388 $meta_data = WC_PB_DB::get_bundled_item_meta( $child_id, 'allowed_variations' );
389
390 foreach ( $meta_data as $meta ) {
391 if ( $meta->meta_key === 'allowed_variations' ) {
392 $serialized_value = $meta->meta_value;
393 $deserialized_value = maybe_unserialize( $serialized_value );
394
395 if ( is_array( $deserialized_value ) ) {
396 foreach ( $deserialized_value as $variation_id ) {
397 $zi_variation_id = get_post_meta( $variation_id, 'zi_item_id', true );
398 if ( $zi_variation_id ) {
399 $zi_child_ids[] = $zi_variation_id;
400 }
401 }
402 }
403 }
404 }
405 } else {
406 $zi_child_id = get_post_meta( $child_id, 'zi_item_id', true );
407 if ( $zi_child_id ) {
408 $zi_child_ids[] = $zi_child_id;
409 }
410 }
411
412 foreach ( $zi_child_ids as $zi_child_id ) {
413 $json_child = (object) array(
414 'item_id' => $zi_child_id,
415 'quantity' => $meta_value[0]->meta_value,
416 );
417 array_push( $child_array, $json_child );
418 }
419 }
420 $child_items = $child_array;
421
422 // fclose($fd);
423 return $child_items;
424 }
425
426 protected function zi_bundle_product_to_zoho( $post_id ) {
427 // $fd = fopen(__DIR__ . '/zi_bundle_product_to_zoho.txt', 'w+');
428
429 $item = wc_get_product( $post_id );
430 if ( $item->is_type( 'bundle' ) ) {
431
432 $child_items = $this->cmbird_zi_bundle_product_data_zoho( $post_id );
433 }
434
435 $price_r = $item->get_regular_price();
436 $price_s = $item->get_sale_price();
437
438 if ( $price_s ) {
439 $rate = round( $price_s, 2 );
440 } else {
441 $rate = round( $price_r, 2 );
442 }
443 //$rate = 500;
444 // $proid = $item->ID;
445 $pre_name = $item->get_name();
446 $name = preg_replace( "/[>\"''<`]/", '', $pre_name );
447 $sku = $item->get_sku();
448 $stock_quantity = $item->get_stock_quantity();
449 $in_stock = ( $stock_quantity > 0 ) ? $stock_quantity : 0;
450 $in_stock_rate = ( $in_stock * $rate );
451
452 $product_type = 'goods';
453 $item_type = 'inventory';
454 $tax_rates = WC_Tax::get_base_tax_rates( $item->get_tax_class() );
455 $tax_id_key = '';
456 foreach ( $tax_rates as $tax_key => $tax_value ) {
457 $tax_id_key = $tax_key;
458 break;
459 }
460 $tax_option = get_option( 'cmbird_zoho_inventory_tax_rate_' . $tax_id_key );
461 $tax_id = explode( '##', $tax_option )[0];
462 if ( ! empty( $tax_rates ) ) {
463 $tax_rate = reset( $tax_rates );
464 }
465
466 $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 . '"';
467 // If zoho category id is not mapped to product, then assign mapped product category with zoho.
468
469 // $zi_category_id = $this->cmbird_zi_get_prod_updated_category($post_id);
470 // if ($zi_category_id) {
471 // $pdt1 .= ',"category_id" : "' . $zi_category_id . '"';
472 // }
473
474 $zoho_item_id = get_post_meta( $post_id, 'zi_item_id', true );
475 if ( empty( $zoho_item_id ) ) {
476 $pdt1 .= ',"initial_stock" : ' . $in_stock . ',';
477 $pdt1 .= '"initial_stock_rate" : "' . $in_stock_rate . '"';
478 }
479
480 // Dimensions data append to update call.
481 $dimensions = (object) array();
482 $dimensions->length = $item->get_length();
483 $dimensions->width = $item->get_width();
484 $dimensions->height = $item->get_height();
485 $dimensions->weight = $item->get_weight();
486 $pdt1 .= ',"package_details" : ' . wp_json_encode( $dimensions ) . ',';
487
488 $zoho_inventory_oid = $this->config['ProductZI']['OID'];
489 $zoho_inventory_url = $this->config['ProductZI']['APIURL'];
490
491 if ( $zoho_item_id && ctype_digit( $zoho_item_id ) ) {
492 $url_p = $zoho_inventory_url . 'inventory/v1/compositeitems/' . $zoho_item_id;
493 } else {
494 $url_p = $zoho_inventory_url . 'inventory/v1/compositeitems';
495 }
496
497 $data_p = array(
498 'JSONString' => '{' . $pdt1 . '}',
499 'organization_id' => $zoho_inventory_oid,
500 );
501
502 // fwrite($fd, PHP_EOL . 'data_p : ' . print_r($data_p, true));
503
504 $execute_curl_call_handle = new CMBIRD_API_Handler_Zoho();
505
506 if ( $zoho_item_id && ctype_digit( $zoho_item_id ) ) {
507
508 $json = $execute_curl_call_handle->execute_curl_call_put( $url_p, $data_p );
509 $errmsg = $json->message;
510 update_post_meta( $post_id, 'zi_product_errmsg', $errmsg );
511 } else {
512
513 $json = $execute_curl_call_handle->execute_curl_call_post( $url_p, $data_p );
514
515 $code = $json->code;
516 $errmsg = $json->message;
517 update_post_meta( $post_id, 'zi_product_errmsg', $errmsg );
518 if ( $code == '1001' || $code == 1001 ) {
519 $sku_check = str_replace( ' ', '+', $sku );
520 $url = $zoho_inventory_url . 'inventory/v1/compositeitems/?search_text=' . $sku_check . '&organization_id=' . $zoho_inventory_oid;
521 $get_request = $execute_curl_call_handle->execute_curl_call_get( $url );
522 if ( $get_request->code === '0' || $get_request->code === 0 ) {
523 $item_id = '';
524 foreach ( $get_request->composite_items as $zoho_composite ) {
525 // fwrite($fd,PHP_EOL.'ZOHO Item : '.print_r($zoho_item, true));
526 if ( $zoho_composite->sku === $sku ) {
527 $code = 0;
528 $json->composite_item = $zoho_composite;
529 update_post_meta( $post_id, 'zi_product_errmsg', 'Product "' . $zoho_composite->name . '" is mapped successfully with Zoho' );
530 break;
531 }
532 }
533 }
534 }
535 if ( '0' === $code || 0 === $code ) {
536 foreach ( $json->composite_item as $key => $value ) {
537
538 if ( $key === 'composite_item_id' ) {
539 $item_id = $value;
540 }
541 if ( $key === 'purchase_account_id' ) {
542 $purchase_account_id = $value;
543 }
544 if ( $key === 'account_id' ) {
545 $account_id = $value;
546 }
547 if ( $key === 'account_name' ) {
548 $account_name = $value;
549 }
550 if ( $key === 'inventory_account_id' ) {
551 $inventory_account_id = $value;
552 }
553 if ( $key === 'category_id' && ! empty( $value ) ) {
554 update_post_meta( $post_id, 'zi_category_id', $value );
555 }
556 }
557 update_post_meta( $post_id, 'zi_item_id', $item_id );
558 update_post_meta( $post_id, 'zi_purchase_account_id', $purchase_account_id );
559 update_post_meta( $post_id, 'zi_account_id', $account_id );
560 update_post_meta( $post_id, 'zi_account_name', $account_name );
561 update_post_meta( $post_id, 'zi_inventory_account_id', $inventory_account_id );
562 }
563 }
564 // fclose($fd);
565 }
566
567 //variation product post zoho start
568
569 protected function cmbird_zi_variation_product_to_zoho( $post_id ) {
570 // $fd = fopen(__DIR__ . '/cmbird_zi_variation_product_to_zoho.txt', 'w+');
571
572 $product = wc_get_product( $post_id );
573
574 $pre_name = $product->get_title();
575 $name = preg_replace( "/[>\"''<`]/", '', $pre_name );
576
577 $tax_rates = WC_Tax::get_base_tax_rates( $product->get_tax_class() );
578 $tax_id_key = '';
579 foreach ( $tax_rates as $tax_key => $tax_value ) {
580 $tax_id_key = $tax_key;
581 break;
582 }
583 $tax_option = get_option( 'cmbird_zoho_inventory_tax_rate_' . $tax_id_key );
584 $tax_id = explode( '##', $tax_option )[0];
585 $zi_category_id = $this->cmbird_zi_get_prod_updated_category( $post_id );
586
587 $zidata = '"group_name" : "' . $name . '", "tax_id" : "' . $tax_id . '","category_id" : "' . $zi_category_id . '",';
588
589 // attributes
590 $attributes = $product->get_attributes();
591 // fwrite($fd, PHP_EOL . 'ATTRIBUTES : ' . print_r($attributes, true));
592
593 $attribute_name1 = '';
594 $attribute_name2 = '';
595 $attribute_name3 = '';
596 foreach ( $attributes as $attribute ) {
597 if ( ! empty( $attribute ) ) {
598 $attrname1 = $attribute->get_name();
599 $attrname = str_replace( '"', '', $attrname1 );
600 if ( ! empty( $attrname ) && $attribute['variation'] ) {
601 if ( empty( $attribute_name1 ) ) {
602 $attribute_name1 = $attrname;
603 } elseif ( empty( $attribute_name2 ) ) {
604 $attribute_name2 = $attrname;
605 } elseif ( empty( $attribute_name3 ) ) {
606 $attribute_name3 = $attrname;
607 }
608 }
609 }
610 }
611 if ( ! empty( $attribute_name1 ) ) {
612 $zidata .= '"attribute_name1": "' . $attribute_name1 . '",';
613 }
614 if ( ! empty( $attribute_name2 ) ) {
615 $zidata .= '"attribute_name2": "' . $attribute_name2 . '",';
616 }
617 if ( ! empty( $attribute_name3 ) ) {
618 $zidata .= '"attribute_name3": "' . $attribute_name3 . '",';
619 }
620
621 $available_variations = $product->get_available_variations();
622 // If there is attributes variations then append that data to server.
623 $items = array();
624 if ( count( $available_variations ) > 0 ) {
625 foreach ( $available_variations as $child_data ) {
626
627 $product_variable = wc_get_product( $child_data['variation_id'] );
628 $items[] = $this->cmbird_zi_variants_products( $product_variable, $child_data['variation_id'], $attribute_name1, $attribute_name2, $attribute_name3 );
629 }
630 }
631
632 // get category id
633 // $zi_category_id = $this->cmbird_zi_get_prod_updated_category($post_id);
634 // if ($zi_category_id) {
635 // $zidata .= '"category_id" : "' . $zi_category_id . '",';
636 // }
637
638 $zidata .= '"items" :[' . implode( ',', $items ) . ']';
639 $data = array(
640 'JSONString' => '{' . $zidata . '}',
641 );
642
643 // fwrite($fd, PHP_EOL . 'ZI Data JSON : ' . '{' . print_r($data, true) . '}');
644 // fclose($fd);
645
646 $zoho_inventory_oid = $this->config['ProductZI']['OID'];
647 $zoho_inventory_url = $this->config['ProductZI']['APIURL'];
648 $zoho_group_id = get_post_meta( $post_id, 'zi_item_id', true );
649
650 if ( ! empty( $zoho_group_id ) ) {
651 $url = $zoho_inventory_url . 'inventory/v1/itemgroups/' . $zoho_group_id . '?organization_id=' . $zoho_inventory_oid;
652 $execute_curl_call_handle = new CMBIRD_API_Handler_Zoho();
653 $json_p = $execute_curl_call_handle->execute_curl_call_put( $url, $data );
654 $code = $json_p->code;
655 $errmsg = $json_p->message;
656 update_post_meta( $post_id, 'zi_product_errmsg', $errmsg );
657 } else {
658 $url = $zoho_inventory_url . 'inventory/v1/itemgroups?organization_id=' . $zoho_inventory_oid;
659
660 $execute_curl_call_handle = new CMBIRD_API_Handler_Zoho();
661 $json = $execute_curl_call_handle->execute_curl_call_post( $url, $data );
662
663 $errmsg = $json->message;
664 update_post_meta( $post_id, 'zi_product_errmsg', $errmsg );
665 $code = $json->code;
666 if ( '0' === $code || 0 === $code ) {
667
668 // This item will keep the copy of zoho item_id with respect to product.
669 // name as key synced to zoho.
670 $child_items = array();
671 foreach ( $json->item_group as $key => $value ) {
672 if ( $key == 'group_id' ) {
673 $group_id = $value;
674 }
675
676 if ( $key === 'items' ) {
677 foreach ( $value as $key2 => $val2 ) {
678 $zi_name = str_replace( ' ', '-', $val2->name );
679 // echo '<br>';
680 $zi_name = $val2->name;
681 $child_items[ $zi_name ] = $val2->item_id;
682 }
683 }
684 }
685 if ( ! empty( $group_id ) ) {
686 update_post_meta( $post_id, 'zi_item_id', $group_id );
687 }
688
689 foreach ( $available_variations as $child_data ) {
690 $product_variable = wc_get_product( $child_data['variation_id'] );
691
692 $pname = '';
693 foreach ( $product_variable->get_variation_attributes() as $taxonomy => $terms_slug ) {
694
695 $pname .= $terms_slug;
696 }
697
698 $vname = $product_variable->get_name();
699 $product_key = $vname . '-' . $pname;
700 update_post_meta( $child_data['variation_id'], 'zi_item_id', $child_items[ $product_key ] );
701 }
702 }
703 }
704 // End New Variable Product
705 }
706
707 /**
708 * Function to sync variations of a product.
709 *
710 * @param $post_id - variation product_id.
711 * @param $zi_category_id - Zoho category id of parent of a variation.
712 * @return void
713 */
714 protected function cmbird_zi_variants_products( $product_variable, $post_id, $attr1 = '', $attr2 = '', $attr3 = '' ) {
715 // $fd = fopen(__DIR__.'/variations_products.txt','a+');
716 // fwrite($fd,PHP_EOL.'-------------------------------');
717 // fwrite($fd,PHP_EOL.'$attr1 : '.$attr1.' | $attr2 : '.$attr2.' | $attr3 : '.$attr3.' $post_id : '.$post_id);
718 // Sync Attributes of Variable Products
719
720 $attributes = $product_variable->get_variation_attributes();
721 // fwrite($fd,PHP_EOL.'$variation_attributes : '.print_r($attributes,true));
722 $arrtibute_string = '';
723 if ( ! empty( $attr1 ) ) {
724 $attr_key = strtolower( $attr1 );
725 $attr_key = 'attribute_' . str_replace( ' ', '-', $attr_key );
726 $arrtibute_string .= '"attribute_option_name1": "' . str_replace( '"', '', $attributes[ $attr_key ] ) . '",';
727 }
728 if ( ! empty( $attr2 ) ) {
729 $attr_key = strtolower( $attr2 );
730 $attr_key = 'attribute_' . str_replace( ' ', '-', $attr_key );
731 $arrtibute_string .= '"attribute_option_name2": "' . str_replace( '"', '', $attributes[ $attr_key ] ) . '",';
732 }
733 if ( ! empty( $attr3 ) ) {
734 $attr_key = strtolower( $attr3 );
735 $attr_key = 'attribute_' . str_replace( ' ', '-', $attr_key );
736 $arrtibute_string .= '"attribute_option_name3": "' . str_replace( '"', '', $attributes[ $attr_key ] ) . '",';
737 }
738 // fwrite($fd,PHP_EOL.'$arrtibute_string : '.$arrtibute_string);
739 // fclose($fd);
740 $zoho_item_id = get_post_meta( $post_id, 'zi_item_id', true );
741
742 // $product_variable = wc_get_product($post_id);
743 $pname = '';
744 foreach ( $product_variable->get_variation_attributes() as $taxonomy => $terms_slug ) {
745
746 $pname .= $terms_slug;
747 }
748
749 $vname = $product_variable->get_name();
750 $name = str_replace( '"', '', $vname );
751 $rate = $product_variable->get_regular_price();
752 // $rateS = $product_variable->get_sale_price();
753 if ( $product_variable->is_virtual( 'yes' ) ) {
754 $product_type = 'service';
755 $item_type = 'sales';
756 } else {
757 $product_type = 'goods';
758 $item_type = 'inventory';
759 }
760
761 $sku = $product_variable->get_sku();
762 $stock_quantity = $product_variable->get_stock_quantity();
763 $in_stock = ( $stock_quantity > 0 ) ? $stock_quantity : 0;
764 // Get Tax ID
765 $tax_rates = WC_Tax::get_base_tax_rates( $product_variable->get_tax_class() );
766 $tax_id_key = '';
767 foreach ( $tax_rates as $tax_key => $tax_value ) {
768 $tax_id_key = $tax_key;
769 break;
770 }
771 $tax_option = get_option( 'cmbird_zoho_inventory_tax_rate_' . $tax_id_key );
772 $tax_id = explode( '##', $tax_option )[0];
773
774 $zi_status = ( 'publish' === get_post_status( $post_id ) ) ? 'active' : 'inactive';
775 // request data for adding/updating value to zoho.
776 $zidata = '';
777 if ( ! empty( $arrtibute_string ) ) {
778 $zidata .= $arrtibute_string;
779 }
780 $zidata .= '"name" : "' . $name . '",';
781 $zidata .= '"product_type" : "' . $product_type . '",';
782 $zidata .= '"sku" : "' . $sku . '",';
783 $zidata .= '"item_type" : "' . $item_type . '",';
784 // $zidata .= '"unit" : "pcs",';
785 $zidata .= '"status" : "' . $zi_status . '",';
786 if ( empty( $zoho_item_id ) && $in_stock > 0 ) {
787 $zidata .= '"initial_stock" : ' . $in_stock . ',';
788 $zidata .= '"initial_stock_rate" : ' . $in_stock . ',';
789 }
790 $zidata .= '"rate" : "' . $rate . '",';
791 $zidata .= '"tax_id" : "' . $tax_id . '",';
792 // Get cost_price from meta data.
793 $cost_price = get_post_meta( $post_id, '_cost_price', true );
794 if ( ! empty( $cost_price ) && is_numeric( $cost_price ) ) {
795 $zidata .= '"purchase_rate" : "' . $cost_price . '",';
796 }
797
798 $dimensions = (object) array();
799 $dimensions->length = $product_variable->get_length();
800 $dimensions->width = $product_variable->get_width();
801 $dimensions->height = $product_variable->get_height();
802 $dimensions->weight = $product_variable->get_weight();
803 if ( ! empty( $dimensions ) ) {
804 $zidata .= '"package_details" : ' . wp_json_encode( $dimensions );
805 }
806
807 // $fd = fopen(__DIR__ . '/variations.txt', 'a+');
808 // fwrite($fd,PHP_EOL.'Get data for $post_id '.$post_id);
809 if ( ctype_digit( $zoho_item_id ) ) {
810 // fwrite($fd, PHP_EOL . 'Update Item');
811 $update_error_msg = $this->cmbird_zi_product_put( $post_id, $zoho_item_id, $zidata );
812 $zidataa = '';
813 // fwrite($fd, PHP_EOL . '{' . $zidata . '}');
814 return $zidataa .= '{' . $zidata . '}';
815 } else {
816 // fwrite($fd, PHP_EOL . 'Create Item');
817 // Check if the the given sku has product in zoho inventory.
818 $zoho_inventory_oid = $this->config['ProductZI']['OID'];
819 $zoho_inventory_url = $this->config['ProductZI']['APIURL'];
820 $sku_check = str_replace( ' ', '+', $sku );
821 $url = $zoho_inventory_url . 'inventory/v1/items?search_text=' . $sku_check . '&organization_id=' . $zoho_inventory_oid;
822 $execute_curl_call_handle = new CMBIRD_API_Handler_Zoho();
823 $get_request = $execute_curl_call_handle->execute_curl_call_get( $url );
824 $var_item_id = '';
825 $groupitem_id = '';
826 // fwrite($fd, PHP_EOL . '$get_request->code : ' . $get_request->code);
827 if ( $get_request->code === '0' || $get_request->code === 0 ) {
828 foreach ( $get_request->items as $zoho_item ) {
829 // fwrite($fd, PHP_EOL . '$zoho_item->sku : ' . $zoho_item->sku);
830 if ( $zoho_item->sku === $sku ) {
831 // fwrite($fd, PHP_EOL . 'Product found with same sku $zoho_item : ' . print_r($zoho_item, true));
832 $var_item_id = $zoho_item->item_id;
833 $groupitem_id = $zoho_item->group_id;
834 // Item sku is matched
835 // Assign matched zoho item to json so fields can be mapped.
836 break;
837 }
838 }
839 }
840 $zidataa = '';
841 if ( $var_item_id ) {
842 update_post_meta( $post_id, 'zi_item_id', $var_item_id );
843 }
844 if ( $groupitem_id ) {
845 $parent_product_id = wp_get_post_parent_id( $post_id );
846 update_post_meta( $parent_product_id, 'zi_item_id', $groupitem_id );
847 }
848 // fwrite($fd, PHP_EOL . '$var_item_id : ' . $var_item_id);
849 // fclose($fd);
850 return $zidataa .= '{' . $zidata . '}';
851 }
852 }
853
854 /**
855 * Check if category already exists and return updated one
856 */
857 protected function cmbird_zi_get_prod_updated_category( $product_id ) {
858 // Check if product category already synced.
859 $terms = get_the_terms( $product_id, 'product_cat' );
860 if ( $terms ) {
861 foreach ( $terms as $term ) {
862 $product_cat_id = $term->term_id;
863 $zoho_cat_id = get_option( "zoho_id_for_term_id_{$product_cat_id}" );
864 if ( $zoho_cat_id ) {
865 break;
866 }
867 }
868 }
869 // Check if product has already mapped category.
870 if ( empty( $zoho_cat_id ) ) {
871 $zoho_cat_id = get_post_meta( $product_id, 'zi_category_id', true );
872 }
873
874 if ( $zoho_cat_id ) {
875 return $zoho_cat_id;
876 } else {
877 return false;
878 }
879 }
880
881 /**
882 * Function for adding Simple product from Zoho to woocommerce.
883 *
884 * @param $prod - Product object for adding new product in woocommerce.
885 * @param $user_id - Current Active user Id
886 * @param string $type - product is composite item or not (composite)
887 */
888 public function cmbird_zi_product_to_woocommerce( $item, $item_stock = '', $type = '' ) {
889 // $fd = fopen( __DIR__ . '/cmbird_zi_product_to_woocommerce.txt', 'a+' );
890 try {
891 if ( 'active' !== $item['status'] ) {
892 return;
893 }
894 $product = new WC_Product();
895
896 $allow_backorders = get_option( 'woocommerce_allow_backorders' );
897 $zi_disable_stock_sync = get_option( 'cmbird_zoho_disable_stock_sync_status' );
898
899 // Set the product data
900 $product->set_status( 'publish' );
901 $product->set_name( $item['name'] );
902 $product->set_regular_price( $item['rate'] );
903 $product->set_short_description( $item['description'] );
904 $product->set_sku( $item['sku'] );
905
906 // Set the stock management properties
907 if ( ! empty( $item_stock ) && ! $zi_disable_stock_sync ) {
908 $product->set_manage_stock( true );
909 $product->set_stock_quantity( $item_stock );
910
911 if ( $item_stock > 0 ) {
912 $product->set_stock_status( 'instock' );
913 } elseif ( $item_stock < 0 && $allow_backorders === 'yes' ) {
914 $product->set_stock_status( 'onbackorder' );
915 } else {
916 $product->set_stock_status( 'outofstock' );
917 }
918 }
919
920 // Save the product
921 $product_id = $product->save();
922
923 // Map composite items metadata to convert product as a bundle product.
924 if ( 'composite' === $type ) {
925 update_post_meta( $product_id, '_wc_pb_layout_style', 'default' );
926 update_post_meta( $product_id, '_wc_pb_add_to_cart_form_location', 'default' );
927 wp_set_object_terms( $product_id, 'bundle', 'product_type' );
928 }
929
930 return $product_id;
931 } catch ( Exception $e ) {
932 // Handle the exception, log it, or perform any necessary actions.
933 return new WP_Error( 'Error creating WooCommerce product: ' . $e->getMessage() );
934 }
935 }
936 }
937 $cmbird_products_zi_export = new CMBIRD_Products_ZI_Export();
938