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