class-api-for-cmbird.php
7 months ago
class-api-for-exact-webhooks.php
5 months ago
class-api-for-product-webhook.php
5 months ago
class-api-for-shipping-status.php
9 months ago
class-api-for-woo-order.php
4 months ago
class-api-for-zoho-inventory.php
9 months ago
class-commercebird-list-items-api-controller.php
10 months ago
class-commercebird-media-api-controller.php
10 months ago
class-commercebird-metadata-controller.php
5 months ago
index.php
1 year ago
trait-api-permission.php
7 months ago
class-api-for-woo-order.php
562 lines
| 1 | <?php |
| 2 | |
| 3 | namespace CommerceBird\API; |
| 4 | |
| 5 | if ( ! defined( 'ABSPATH' ) ) { |
| 6 | exit; |
| 7 | } |
| 8 | |
| 9 | use CommerceBird\Admin\Traits\LogWriter; |
| 10 | use WC_Coupon; |
| 11 | use WC_Customer; |
| 12 | use WP_REST_Response; |
| 13 | |
| 14 | class CreateOrderWebhook { |
| 15 | |
| 16 | use Api; |
| 17 | use LogWriter; |
| 18 | |
| 19 | private static string $endpoint = 'create-woo-order'; |
| 20 | |
| 21 | |
| 22 | public function __construct() { |
| 23 | register_rest_route( |
| 24 | self::$namespace, |
| 25 | self::$endpoint, |
| 26 | array( |
| 27 | 'methods' => 'POST', |
| 28 | 'callback' => array( $this, 'handle' ), |
| 29 | 'permission_callback' => array( $this, 'permission_check' ), |
| 30 | ) |
| 31 | ); |
| 32 | } |
| 33 | |
| 34 | /** |
| 35 | * @param $address |
| 36 | * |
| 37 | * @return array |
| 38 | */ |
| 39 | public function format_address( $address ): array { |
| 40 | if ( array_key_exists( 'attention', $address ) ) { |
| 41 | $names = explode( ' ', $address['attention'] ); |
| 42 | $first_name = $names[0] ?? ''; |
| 43 | $last_name = $names[1] ?? ''; |
| 44 | } |
| 45 | return array( |
| 46 | 'first_name' => $first_name ?? '', |
| 47 | 'last_name' => $last_name ?? '', |
| 48 | 'address_1' => $address['address'] ?? '', |
| 49 | 'address_2' => $address['street2'] ?? '', |
| 50 | 'city' => $address['city'] ?? '', |
| 51 | 'state' => $address['state_code'] ?? '', |
| 52 | 'postcode' => $address['zip'] ?? '', |
| 53 | 'country' => $address['country_code'] ?? '', |
| 54 | 'phone' => $address['phone'] ?? '', |
| 55 | ); |
| 56 | } |
| 57 | |
| 58 | private function process( array $order_data ): WP_REST_Response { |
| 59 | $response = new WP_REST_Response(); |
| 60 | |
| 61 | // Check if the order data is valid. |
| 62 | if ( empty( $order_data ) || empty( $order_data['salesorder'] ) ) { |
| 63 | $response->set_data( $this->empty_response ); |
| 64 | $response->set_status( 404 ); |
| 65 | return $response; |
| 66 | } |
| 67 | |
| 68 | // Validate salesorder_id exists. |
| 69 | if ( ! isset( $order_data['salesorder']['salesorder_id'] ) || empty( $order_data['salesorder']['salesorder_id'] ) ) { |
| 70 | $message = sprintf( __( 'Zoho order could not be created in your store %1$s because of missing order ID.', 'commercebird' ), get_bloginfo( 'name' ) ); |
| 71 | $common_class = new \CMBIRD_Common_Functions(); |
| 72 | $common_class->send_email( __( 'Zoho Order Sync', 'commercebird' ), $message ); |
| 73 | $response->set_status( 500 ); |
| 74 | $response->set_data( $message ); |
| 75 | return $response; |
| 76 | } |
| 77 | |
| 78 | $allowed_keys = array( |
| 79 | 'salesorder_id', |
| 80 | 'salesorder_number', |
| 81 | 'customer_id', |
| 82 | 'billing_address', |
| 83 | 'shipping_address', |
| 84 | 'delivery_method', |
| 85 | 'currency_code', |
| 86 | 'line_items', |
| 87 | 'contact_person_details', |
| 88 | 'shipping_charge', |
| 89 | 'order_status', |
| 90 | 'paid_status', |
| 91 | 'invoiced_status', |
| 92 | 'discount', |
| 93 | 'discount_percent', |
| 94 | 'notes', |
| 95 | 'salesperson_name', |
| 96 | ); |
| 97 | |
| 98 | $order_data = array_intersect_key( $order_data['salesorder'], array_flip( $allowed_keys ) ); |
| 99 | $billing_address = $this->format_address( $order_data['billing_address'] ); |
| 100 | $shipping_address = $this->format_address( $order_data['shipping_address'] ); |
| 101 | |
| 102 | // Handle customer creation/update. |
| 103 | $customer = null; |
| 104 | if ( isset( $order_data['contact_person_details'][0]['email'] ) ) { |
| 105 | $customer_data = $order_data['contact_person_details'][0]; |
| 106 | $customer_mail = $customer_data['email']; |
| 107 | $customer = get_user_by( 'email', $customer_mail ); |
| 108 | if ( empty( $customer ) ) { |
| 109 | $customer_id = wc_create_new_customer( $customer_mail ); |
| 110 | $wc_customer = new \WC_Customer( $customer_id ); |
| 111 | // Set billing details. |
| 112 | $wc_customer->set_billing_first_name( $billing_address['first_name'] ); |
| 113 | $wc_customer->set_billing_last_name( $billing_address['last_name'] ); |
| 114 | $wc_customer->set_billing_address_1( $billing_address['address_1'] ); |
| 115 | $wc_customer->set_billing_address_2( $billing_address['address_2'] ); |
| 116 | $wc_customer->set_billing_city( $billing_address['city'] ); |
| 117 | $wc_customer->set_billing_postcode( $billing_address['postcode'] ); |
| 118 | $wc_customer->set_billing_country( $billing_address['country'] ); |
| 119 | $wc_customer->set_billing_state( $billing_address['state'] ); |
| 120 | $wc_customer->set_billing_email( $customer_mail ); |
| 121 | $wc_customer->set_billing_phone( $billing_address['phone'] ); |
| 122 | // Set shipping details. |
| 123 | $wc_customer->set_shipping_first_name( $shipping_address['first_name'] ); |
| 124 | $wc_customer->set_shipping_last_name( $shipping_address['last_name'] ); |
| 125 | $wc_customer->set_shipping_address_1( $shipping_address['address_1'] ); |
| 126 | $wc_customer->set_shipping_address_2( $shipping_address['address_2'] ); |
| 127 | $wc_customer->set_shipping_city( $shipping_address['city'] ); |
| 128 | $wc_customer->set_shipping_postcode( $shipping_address['postcode'] ); |
| 129 | $wc_customer->set_shipping_country( $shipping_address['country'] ); |
| 130 | $wc_customer->set_shipping_state( $shipping_address['state'] ); |
| 131 | $wc_customer->save(); |
| 132 | $customer = get_user_by( 'id', $customer_id ); |
| 133 | } else { |
| 134 | $wc_customer = new \WC_Customer( $customer->ID ); |
| 135 | // Set billing details. |
| 136 | $wc_customer->set_billing_first_name( $billing_address['first_name'] ); |
| 137 | $wc_customer->set_billing_last_name( $billing_address['last_name'] ); |
| 138 | $wc_customer->set_billing_address_1( $billing_address['address_1'] ); |
| 139 | $wc_customer->set_billing_address_2( $billing_address['address_2'] ); |
| 140 | $wc_customer->set_billing_city( $billing_address['city'] ); |
| 141 | $wc_customer->set_billing_postcode( $billing_address['postcode'] ); |
| 142 | $wc_customer->set_billing_country( $billing_address['country'] ); |
| 143 | $wc_customer->set_billing_state( $billing_address['state'] ); |
| 144 | $wc_customer->set_billing_email( $customer_mail ); |
| 145 | $wc_customer->set_billing_phone( $billing_address['phone'] ); |
| 146 | // Set shipping details. |
| 147 | $wc_customer->set_shipping_first_name( $shipping_address['first_name'] ); |
| 148 | $wc_customer->set_shipping_last_name( $shipping_address['last_name'] ); |
| 149 | $wc_customer->set_shipping_address_1( $shipping_address['address_1'] ); |
| 150 | $wc_customer->set_shipping_address_2( $shipping_address['address_2'] ); |
| 151 | $wc_customer->set_shipping_city( $shipping_address['city'] ); |
| 152 | $wc_customer->set_shipping_postcode( $shipping_address['postcode'] ); |
| 153 | $wc_customer->set_shipping_country( $shipping_address['country'] ); |
| 154 | $wc_customer->set_shipping_state( $shipping_address['state'] ); |
| 155 | $wc_customer->save(); |
| 156 | } |
| 157 | } |
| 158 | |
| 159 | // Validate line items exist. |
| 160 | if ( empty( $order_data['line_items'] ) ) { |
| 161 | // translators: 1: order number, 2: Store name. |
| 162 | $message = sprintf( __( 'Zoho order #%1$s could not be created in your store %2$s because of missing line items.', 'commercebird' ), $order_data['salesorder_number'], get_bloginfo( 'name' ) ); |
| 163 | $common_class = new \CMBIRD_Common_Functions(); |
| 164 | $common_class->send_email( __( 'Zoho Order Sync', 'commercebird' ), $message ); |
| 165 | $response->set_status( 500 ); |
| 166 | $response->set_data( $message ); |
| 167 | return $response; |
| 168 | } |
| 169 | |
| 170 | $line_items = $this->get_items( $order_data['line_items'] ); |
| 171 | |
| 172 | if ( ! empty( $line_items['not_found'] ) ) { |
| 173 | // translators: 1: order number, 2: Store name, 3: missing items. |
| 174 | $message = sprintf( __( 'Zoho order #%1$s could not be created in your store %2$s because of missing items: %3$s', 'commercebird' ), $order_data['salesorder_number'], get_bloginfo( 'name' ), implode( ', ', $line_items['not_found'] ) ); |
| 175 | $common_class = new \CMBIRD_Common_Functions(); |
| 176 | $common_class->send_email( __( 'Zoho Order Sync', 'commercebird' ), $message ); |
| 177 | $response->set_status( 500 ); |
| 178 | $response->set_data( $message ); |
| 179 | return $response; |
| 180 | } |
| 181 | |
| 182 | $discount_percent = $order_data['discount_percent'] ?? ''; |
| 183 | if ( ! empty( $discount_percent ) && $discount_percent > 0 ) { |
| 184 | $coupon_code = $this->get_coupon_code( $order_data ); |
| 185 | } |
| 186 | |
| 187 | // Check if order already exists. |
| 188 | $orders = wc_get_orders( |
| 189 | array( |
| 190 | 'limit' => 1, |
| 191 | 'meta_key' => 'zi_salesorder_id', |
| 192 | 'meta_value' => $order_data['salesorder_id'], |
| 193 | 'meta_compare' => '=', |
| 194 | 'return' => 'ids', |
| 195 | ) |
| 196 | ); |
| 197 | if ( ! empty( $orders ) ) { |
| 198 | $existing_order = wc_get_order( $orders[0] ); |
| 199 | } |
| 200 | |
| 201 | // Update existing order. |
| 202 | if ( ! empty( $existing_order ) && empty( $line_items['not_found'] ) ) { |
| 203 | // if order status is completed or processing, do not update the order and return error response. |
| 204 | if ( in_array( $existing_order->get_status(), array( 'completed', 'processing' ), true ) ) { |
| 205 | $message = sprintf( __( 'Zoho order #%1$s could not be updated in your store %2$s because the order is already in %3$s status.', 'commercebird' ), $order_data['salesorder_number'], get_bloginfo( 'name' ), $existing_order->get_status() ); |
| 206 | $common_class = new \CMBIRD_Common_Functions(); |
| 207 | $common_class->send_email( __( 'Zoho Order Sync', 'commercebird' ), $message ); |
| 208 | $response->set_status( 200 ); |
| 209 | $response->set_data( $message ); |
| 210 | return $response; |
| 211 | } |
| 212 | |
| 213 | $existing_order->set_address( $billing_address, 'billing' ); |
| 214 | $existing_order->set_address( $shipping_address, 'shipping' ); |
| 215 | // Remove existing order items. |
| 216 | $existing_order->remove_order_items( 'line_item' ); |
| 217 | // Get all applied coupons and remove them. |
| 218 | $applied_coupons = $existing_order->get_coupon_codes(); |
| 219 | foreach ( $applied_coupons as $coupon_code_old ) { |
| 220 | $existing_order->remove_coupon( $coupon_code_old ); |
| 221 | } |
| 222 | // Add products to the order. |
| 223 | foreach ( $line_items as $line_item ) { |
| 224 | $product_id = $line_item['id']; |
| 225 | $quantity = $line_item['quantity']; |
| 226 | $rate = $line_item['rate'] ?? null; |
| 227 | if ( ! empty( $product_id ) ) { |
| 228 | $product = wc_get_product( $product_id ); |
| 229 | if ( $product && $product->is_type( 'variation' ) ) { |
| 230 | // Get variation object. |
| 231 | $variation = wc_get_product_object( 'variation', $product_id ); |
| 232 | if ( $variation ) { |
| 233 | $item_id = $existing_order->add_product( $variation, $quantity ); |
| 234 | if ( null !== $rate && $item_id ) { |
| 235 | $item = $existing_order->get_item( $item_id ); |
| 236 | $line_total = $rate * $quantity; |
| 237 | $item->set_subtotal( $line_total ); |
| 238 | $item->set_total( $line_total ); |
| 239 | $item->save(); |
| 240 | } |
| 241 | } |
| 242 | } else { |
| 243 | $item_id = $existing_order->add_product( $product, $quantity ); |
| 244 | if ( null !== $rate && $item_id ) { |
| 245 | $item = $existing_order->get_item( $item_id ); |
| 246 | $line_total = $rate * $quantity; |
| 247 | $item->set_subtotal( $line_total ); |
| 248 | $item->set_total( $line_total ); |
| 249 | $item->save(); |
| 250 | } |
| 251 | } |
| 252 | } |
| 253 | } |
| 254 | |
| 255 | // Set order details. |
| 256 | $existing_order->set_customer_note( isset( $order_data['notes'] ) ? $order_data['notes'] : '' ); |
| 257 | $existing_order->update_status( $this->map_status( $order_data['paid_status'], $order_data['invoiced_status'] ?? '' ) ); |
| 258 | |
| 259 | // Handle shipping. |
| 260 | // Remove existing shipping items first. |
| 261 | foreach ( $existing_order->get_items( 'shipping' ) as $item_id => $item ) { |
| 262 | $existing_order->remove_item( $item_id ); |
| 263 | } |
| 264 | |
| 265 | if ( isset( $order_data['shipping_charge'] ) && $order_data['shipping_charge'] > 0 ) { |
| 266 | $shipping = new \WC_Order_Item_Shipping(); |
| 267 | $shipping->set_method_title( $order_data['delivery_method'] ?? 'Flat Rate' ); |
| 268 | $shipping->set_method_id( 'flat_rate' ); |
| 269 | $shipping->set_total( $order_data['shipping_charge'] ); |
| 270 | $existing_order->add_item( $shipping ); |
| 271 | } |
| 272 | |
| 273 | $existing_order->calculate_totals(); |
| 274 | $existing_order->save(); |
| 275 | $note = 'Updated in Zoho Inventory'; |
| 276 | if ( ! empty( $order_data['salesperson_name'] ) ) { |
| 277 | $note .= ' by ' . $order_data['salesperson_name']; |
| 278 | } |
| 279 | $existing_order->add_order_note( $note ); |
| 280 | // get new order object and calculate totals again. |
| 281 | $updated_order = wc_get_order( $existing_order->get_id() ); |
| 282 | $updated_order->calculate_totals(); |
| 283 | $updated_order->save(); |
| 284 | |
| 285 | $response->set_data( |
| 286 | array( |
| 287 | 'order_id' => $existing_order->get_id(), |
| 288 | 'total' => $existing_order->get_total(), |
| 289 | 'status' => $existing_order->get_status(), |
| 290 | ) |
| 291 | ); |
| 292 | $response->set_status( 200 ); |
| 293 | } elseif ( empty( $line_items['not_found'] ) ) { |
| 294 | // Create new order. |
| 295 | $order = wc_create_order(); |
| 296 | if ( $customer ) { |
| 297 | $order->set_customer_id( $customer->ID ); |
| 298 | } |
| 299 | // Add products to the order. |
| 300 | foreach ( $line_items as $line_item ) { |
| 301 | $product_id = $line_item['id']; |
| 302 | $quantity = $line_item['quantity']; |
| 303 | $rate = $line_item['rate'] ?? null; |
| 304 | if ( ! empty( $product_id ) ) { |
| 305 | $product = wc_get_product( $product_id ); |
| 306 | if ( $product && $product->is_type( 'variation' ) ) { |
| 307 | // Get variation object. |
| 308 | $variation = wc_get_product_object( 'variation', $product_id ); |
| 309 | if ( $variation ) { |
| 310 | $item_id = $order->add_product( $variation, $quantity ); |
| 311 | if ( null !== $rate && $item_id ) { |
| 312 | $item = $order->get_item( $item_id ); |
| 313 | $line_total = $rate * $quantity; |
| 314 | $item->set_subtotal( $line_total ); |
| 315 | $item->set_total( $line_total ); |
| 316 | $item->save(); |
| 317 | } |
| 318 | } |
| 319 | } else { |
| 320 | $item_id = $order->add_product( $product, $quantity ); |
| 321 | if ( null !== $rate && $item_id ) { |
| 322 | $item = $order->get_item( $item_id ); |
| 323 | $line_total = $rate * $quantity; |
| 324 | $item->set_subtotal( $line_total ); |
| 325 | $item->set_total( $line_total ); |
| 326 | $item->save(); |
| 327 | } |
| 328 | } |
| 329 | } |
| 330 | } |
| 331 | |
| 332 | $order->set_address( $billing_address, 'billing' ); |
| 333 | $order->set_address( $shipping_address, 'shipping' ); |
| 334 | $order->set_currency( $order_data['currency_code'] ); |
| 335 | $order->set_status( $this->map_status( $order_data['paid_status'], $order_data['invoiced_status'] ?? '' ) ); |
| 336 | // Handle shipping. |
| 337 | if ( isset( $order_data['shipping_charge'] ) && $order_data['shipping_charge'] > 0 ) { |
| 338 | $shipping = new \WC_Order_Item_Shipping(); |
| 339 | $shipping->set_method_title( $order_data['delivery_method'] ?? 'Flat Rate' ); |
| 340 | $shipping->set_method_id( 'flat_rate' ); |
| 341 | $shipping->set_total( $order_data['shipping_charge'] ); |
| 342 | $order->add_item( $shipping ); |
| 343 | } |
| 344 | |
| 345 | // Apply coupon if discount exists. |
| 346 | if ( isset( $coupon_code ) && ! empty( $coupon_code ) ) { |
| 347 | $order->apply_coupon( $coupon_code ); |
| 348 | } |
| 349 | $order->calculate_totals(); |
| 350 | $order->set_customer_note( $order_data['notes'] ?? '' ); |
| 351 | $order->save(); |
| 352 | $order->update_meta_data( 'zi_salesorder_id', $order_data['salesorder_id'] ); |
| 353 | $order->save(); |
| 354 | $note = 'Synced in Zoho Inventory'; |
| 355 | if ( ! empty( $order_data['salesperson_name'] ) ) { |
| 356 | $note .= ' by ' . $order_data['salesperson_name']; |
| 357 | } |
| 358 | $order->add_order_note( $note ); |
| 359 | |
| 360 | // Update Zoho sales order with WooCommerce order ID as reference number. |
| 361 | $this->update_zoho_reference_number( $order, $order_data['salesorder_id'] ); |
| 362 | |
| 363 | $response->set_data( |
| 364 | array( |
| 365 | 'order_id' => $order->get_id(), |
| 366 | 'status' => $order->get_status(), |
| 367 | ) |
| 368 | ); |
| 369 | $response->set_status( 200 ); |
| 370 | } else { |
| 371 | $response->set_data( |
| 372 | array( |
| 373 | 'status' => 'Something went wrong. Please try again.', |
| 374 | ) |
| 375 | ); |
| 376 | $response->set_status( 500 ); |
| 377 | } |
| 378 | |
| 379 | return $response; |
| 380 | } |
| 381 | |
| 382 | |
| 383 | private function map_status( $paid_status, $invoiced_status = '' ): string { |
| 384 | // If invoiced, status must be processing. |
| 385 | if ( 'invoiced' === $invoiced_status ) { |
| 386 | return 'wc-processing'; |
| 387 | } |
| 388 | |
| 389 | // Otherwise check paid status. |
| 390 | switch ( $paid_status ) { |
| 391 | case 'paid': |
| 392 | return 'wc-completed'; |
| 393 | default: |
| 394 | return 'wc-pending'; |
| 395 | } |
| 396 | } |
| 397 | |
| 398 | |
| 399 | /** |
| 400 | * Update Zoho sales order reference number with WooCommerce order ID. |
| 401 | * |
| 402 | * @param \WC_Order $order WooCommerce order object. |
| 403 | * @param string $salesorder_id Zoho sales order ID. |
| 404 | * @return void |
| 405 | */ |
| 406 | private function update_zoho_reference_number( $order, $salesorder_id ): void { |
| 407 | // Get Zoho Inventory configuration. |
| 408 | $zoho_inventory_url = get_option( 'cmbird_zoho_inventory_url' ); |
| 409 | $zoho_inventory_oid = get_option( 'cmbird_zoho_inventory_oid' ); |
| 410 | |
| 411 | if ( empty( $zoho_inventory_url ) || empty( $zoho_inventory_oid ) || empty( $salesorder_id ) ) { |
| 412 | return; |
| 413 | } |
| 414 | |
| 415 | // Prepare reference number using the same logic as order sync. |
| 416 | $transaction_id = $order->get_transaction_id(); |
| 417 | if ( empty( $transaction_id ) ) { |
| 418 | $transaction_id = $order->get_meta( '_order_number', true ); |
| 419 | } |
| 420 | |
| 421 | $order_prefix = get_option( 'cmbird_zoho_order_prefix_status' ); |
| 422 | $reference_number = ''; |
| 423 | |
| 424 | if ( class_exists( 'WCJ_Order_Numbers' ) || class_exists( 'WC_Seq_Order_Number_Pro' ) ) { |
| 425 | $reference_number = $order_prefix . $transaction_id; |
| 426 | } elseif ( ! empty( $order_prefix ) ) { |
| 427 | $reference_number = $order_prefix . '-' . $order->get_id(); |
| 428 | } else { |
| 429 | $reference_number = $order->get_id(); |
| 430 | } |
| 431 | |
| 432 | // Build the API URL. |
| 433 | $url = $zoho_inventory_url . 'inventory/v1/salesorders/' . $salesorder_id . '?organization_id=' . $zoho_inventory_oid; |
| 434 | |
| 435 | // Prepare data for update. |
| 436 | $data = array( |
| 437 | 'JSONString' => wp_json_encode( |
| 438 | array( |
| 439 | 'reference_number' => $reference_number, |
| 440 | ) |
| 441 | ), |
| 442 | ); |
| 443 | |
| 444 | // Make the API call to update Zoho sales order. |
| 445 | $api_handler = new \CMBIRD_API_Handler_Zoho(); |
| 446 | $response = $api_handler->execute_curl_call_put( $url, $data ); |
| 447 | |
| 448 | // Log any errors. |
| 449 | $logger = wc_get_logger(); |
| 450 | if ( is_wp_error( $response ) ) { |
| 451 | $logger->error( |
| 452 | 'Error updating Zoho reference number: ' . $response->get_error_message(), |
| 453 | array( |
| 454 | 'source' => 'commercebird', |
| 455 | 'order_id' => $order->get_id(), |
| 456 | 'salesorder_id' => $salesorder_id, |
| 457 | ) |
| 458 | ); |
| 459 | } elseif ( isset( $response->code ) && 0 !== $response->code ) { |
| 460 | $error_message = isset( $response->message ) ? $response->message : 'Unknown error'; |
| 461 | $logger->error( |
| 462 | 'Error updating Zoho reference number: ' . $error_message, |
| 463 | array( |
| 464 | 'source' => 'commercebird', |
| 465 | 'order_id' => $order->get_id(), |
| 466 | 'salesorder_id' => $salesorder_id, |
| 467 | ) |
| 468 | ); |
| 469 | } else { |
| 470 | $order->add_order_note( 'Updated Zoho reference number to: ' . $reference_number ); |
| 471 | } |
| 472 | } |
| 473 | |
| 474 | |
| 475 | /** |
| 476 | * Find the product ids from the line items from Zoho Inventory. |
| 477 | * |
| 478 | * @param mixed $line_items Line items from the salesorder. |
| 479 | * @return array |
| 480 | */ |
| 481 | private function get_items( $line_items ): array { |
| 482 | $product_ids = array(); |
| 483 | $not_found = array(); |
| 484 | |
| 485 | foreach ( $line_items as $item ) { |
| 486 | // Check if the sku key is present (case-insensitive check). |
| 487 | $sku = isset( $item['sku'] ) ? $item['sku'] : ( isset( $item['SKU'] ) ? $item['SKU'] : null ); |
| 488 | $quantity = $item['quantity'] ?? 1; |
| 489 | $rate = $item['rate'] ?? null; |
| 490 | |
| 491 | if ( null !== $sku ) { |
| 492 | $product_id = wc_get_product_id_by_sku( $sku ); |
| 493 | if ( $product_id ) { |
| 494 | // Append to product_ids instead of overwriting. |
| 495 | $product_ids[] = array( |
| 496 | 'id' => $product_id, |
| 497 | 'quantity' => $quantity, |
| 498 | 'rate' => $rate, |
| 499 | ); |
| 500 | } else { |
| 501 | $not_found[] = $sku; |
| 502 | } |
| 503 | } else { |
| 504 | $not_found[] = 'Unknown SKU'; |
| 505 | } |
| 506 | } |
| 507 | |
| 508 | if ( ! empty( $not_found ) ) { |
| 509 | return array( 'not_found' => $not_found ); |
| 510 | } |
| 511 | |
| 512 | return $product_ids; |
| 513 | } |
| 514 | |
| 515 | /** |
| 516 | * Find the coupon code based on Discount or create the coupon code and return it. |
| 517 | * @param mixed $order_data The order data from salesforce. |
| 518 | * @return string The coupon code. |
| 519 | */ |
| 520 | private function get_coupon_code( $order_data ): string { |
| 521 | if ( isset( $order_data['discount_percent'] ) && ! empty( $order_data['discount_percent'] ) ) { |
| 522 | $fixed_cart_amount = $order_data['discount_percent']; |
| 523 | // Search for an existing coupon by fixed cart amount |
| 524 | $existing_coupon = get_posts( |
| 525 | array( |
| 526 | 'post_type' => 'shop_coupon', |
| 527 | 'post_status' => 'publish', |
| 528 | 'post_per_page' => -1, |
| 529 | 'meta_query' => array( |
| 530 | 'relation' => 'AND', |
| 531 | array( |
| 532 | 'key' => 'discount_type', |
| 533 | 'value' => 'percent', |
| 534 | ), |
| 535 | array( |
| 536 | 'key' => 'coupon_amount', |
| 537 | 'value' => $fixed_cart_amount, |
| 538 | 'compare' => '=', |
| 539 | ), |
| 540 | ), |
| 541 | ) |
| 542 | ); |
| 543 | |
| 544 | if ( $existing_coupon ) { |
| 545 | $coupon_code = $existing_coupon[0]->post_title; |
| 546 | return $coupon_code; |
| 547 | } else { |
| 548 | // If not found, create a new coupon with a random code |
| 549 | $coupon_code = 'AUTO_' . wp_generate_password( 8, false ); |
| 550 | $coupon = new \WC_Coupon(); |
| 551 | $coupon->set_code( $coupon_code ); |
| 552 | $coupon->set_description( 'Auto-generated coupon.' ); |
| 553 | $coupon->set_discount_type( 'percent' ); |
| 554 | $coupon->set_amount( $fixed_cart_amount ); |
| 555 | $coupon->save(); |
| 556 | return $coupon_code; |
| 557 | } |
| 558 | } |
| 559 | return ''; |
| 560 | } |
| 561 | } |
| 562 |