}
    // Delete old user keys from usermeta
    foreach ($api_users as $_user) {
        $user_id = intval($_user->user_id);
        delete_user_meta($user_id, 'woocommerce_api_consumer_key');
        delete_user_meta($user_id, 'woocommerce_api_consumer_secret');
        delete_user_meta($user_id, 'woocommerce_api_key_permissions');
    }
}
/**
 * Webhooks
 * Make sure order.update webhooks get the woocommerce_order_edit_status hook
 */
$order_update_webhooks = get_posts(array('posts_per_page' => -1, 'post_type' => 'shop_webhook', 'meta_key' => '_topic', 'meta_value' => 'order.updated'));
foreach ($order_update_webhooks as $order_update_webhook) {
    $webhook = new WC_Webhook($order_update_webhook->ID);
    $webhook->set_topic('order.updated');
}
/**
 * Refunds for full refunded orders.
 * Update fully refunded orders to ensure they have a refund line item so reports add up.
 */
$refunded_orders = get_posts(array('posts_per_page' => -1, 'post_type' => 'shop_order', 'post_status' => array('wc-refunded')));
foreach ($refunded_orders as $refunded_order) {
    $order_total = get_post_meta($refunded_order->ID, '_order_total', true);
    $refunded_total = $wpdb->get_var($wpdb->prepare("\n\t\tSELECT SUM( postmeta.meta_value )\n\t\tFROM {$wpdb->postmeta} AS postmeta\n\t\tINNER JOIN {$wpdb->posts} AS posts ON ( posts.post_type = 'shop_order_refund' AND posts.post_parent = %d )\n\t\tWHERE postmeta.meta_key = '_refund_amount'\n\t\tAND postmeta.post_id = posts.ID\n\t", $refunded_order->ID));
    if ($order_total > $refunded_total) {
        $refund = wc_create_refund(array('amount' => $order_total - $refunded_total, 'reason' => __('Order Fully Refunded', 'woocommerce'), 'order_id' => $refunded_order->ID, 'line_items' => array(), 'date' => $refunded_order->post_modified));
    }
}
wc_delete_shop_order_transients();
/**
 * When refunding an order, create a refund line item if the partial refunds do not match order total.
 *
 * This is manual; no gateway refund will be performed.
 *
 * @since 2.4
 * @param int $order_id
 */
function wc_order_fully_refunded($order_id)
{
    $order = wc_get_order($order_id);
    $max_refund = wc_format_decimal($order->get_total() - $order->get_total_refunded());
    if (!$max_refund) {
        return;
    }
    // Create the refund object
    $refund = wc_create_refund(array('amount' => $max_refund, 'reason' => __('Order Fully Refunded', 'woocommerce'), 'order_id' => $order_id, 'line_items' => array()));
    wc_delete_shop_order_transients($order_id);
}
Example #3
0
 /**
  * Handle a refund via the edit order screen
  */
 public static function refund_line_items()
 {
     ob_start();
     check_ajax_referer('order-item', 'security');
     if (!current_user_can('edit_shop_orders')) {
         die(-1);
     }
     $order_id = absint($_POST['order_id']);
     $refund_amount = wc_format_decimal(sanitize_text_field($_POST['refund_amount']));
     $refund_reason = sanitize_text_field($_POST['refund_reason']);
     $line_item_qtys = json_decode(sanitize_text_field(stripslashes($_POST['line_item_qtys'])), true);
     $line_item_totals = json_decode(sanitize_text_field(stripslashes($_POST['line_item_totals'])), true);
     $line_item_tax_totals = json_decode(sanitize_text_field(stripslashes($_POST['line_item_tax_totals'])), true);
     $api_refund = $_POST['api_refund'] === 'true' ? true : false;
     $restock_refunded_items = $_POST['restock_refunded_items'] === 'true' ? true : false;
     $refund = false;
     $response_data = array();
     try {
         // Validate that the refund can occur
         $order = wc_get_order($order_id);
         $order_items = $order->get_items();
         $max_refund = wc_format_decimal($order->get_total() - $order->get_total_refunded());
         if (!$refund_amount || $max_refund < $refund_amount || 0 > $refund_amount) {
             throw new exception(__('Invalid refund amount', 'woocommerce'));
         }
         // Prepare line items which we are refunding
         $line_items = array();
         $item_ids = array_unique(array_merge(array_keys($line_item_qtys, $line_item_totals)));
         foreach ($item_ids as $item_id) {
             $line_items[$item_id] = array('qty' => 0, 'refund_total' => 0, 'refund_tax' => array());
         }
         foreach ($line_item_qtys as $item_id => $qty) {
             $line_items[$item_id]['qty'] = max($qty, 0);
         }
         foreach ($line_item_totals as $item_id => $total) {
             $line_items[$item_id]['refund_total'] = wc_format_decimal($total);
         }
         foreach ($line_item_tax_totals as $item_id => $tax_totals) {
             $line_items[$item_id]['refund_tax'] = array_map('wc_format_decimal', $tax_totals);
         }
         // Create the refund object
         $refund = wc_create_refund(array('amount' => $refund_amount, 'reason' => $refund_reason, 'order_id' => $order_id, 'line_items' => $line_items));
         if (is_wp_error($refund)) {
             throw new Exception($refund->get_error_message());
         }
         // Refund via API
         if ($api_refund) {
             if (WC()->payment_gateways()) {
                 $payment_gateways = WC()->payment_gateways->payment_gateways();
             }
             if (isset($payment_gateways[$order->payment_method]) && $payment_gateways[$order->payment_method]->supports('refunds')) {
                 $result = $payment_gateways[$order->payment_method]->process_refund($order_id, $refund_amount, $refund_reason);
                 do_action('woocommerce_refund_processed', $refund, $result);
                 if (is_wp_error($result)) {
                     throw new Exception($result->get_error_message());
                 } elseif (!$result) {
                     throw new Exception(__('Refund failed', 'woocommerce'));
                 }
             }
         }
         // restock items
         foreach ($line_item_qtys as $item_id => $qty) {
             if ($restock_refunded_items && $qty && isset($order_items[$item_id])) {
                 $order_item = $order_items[$item_id];
                 $_product = $order->get_product_from_item($order_item);
                 if ($_product && $_product->exists() && $_product->managing_stock()) {
                     $old_stock = wc_stock_amount($_product->stock);
                     $new_quantity = $_product->increase_stock($qty);
                     $order->add_order_note(sprintf(__('Item #%s stock increased from %s to %s.', 'woocommerce'), $order_item['product_id'], $old_stock, $new_quantity));
                     do_action('woocommerce_restock_refunded_item', $_product->id, $old_stock, $new_quantity, $order);
                 }
             }
         }
         if ($refund_amount == $max_refund) {
             $order->update_status(apply_filters('woocommerce_order_fully_refunded_status', 'refunded', $order_id, $refund->id));
             $response_data['status'] = 'fully_refunded';
         }
         do_action('woocommerce_order_refunded', $order_id, $refund->id);
         // Clear transients
         wc_delete_shop_order_transients($order_id);
         wp_send_json_success($response_data);
     } catch (Exception $e) {
         if ($refund && is_a($refund, 'WC_Order_Refund')) {
             wp_delete_post($refund->id, true);
         }
         wp_send_json_error(array('error' => $e->getMessage()));
     }
 }
Example #4
0
 /**
  * Handle a refund via the edit order screen.
  * Called after wp_ajax_woocommerce_refund_line_items action
  *
  * @use woocommerce_order_refunded action
  * @see woocommerce\includes\class-wc-ajax.php:2295
  */
 public function order_refunded($order_id, $parent_refund_id)
 {
     if (!wp_get_post_parent_id($order_id)) {
         $create_refund = true;
         $refund = false;
         $parent_line_item_refund = 0;
         $refund_amount = wc_format_decimal(sanitize_text_field($_POST['refund_amount']));
         $refund_reason = sanitize_text_field($_POST['refund_reason']);
         $line_item_qtys = json_decode(sanitize_text_field(stripslashes($_POST['line_item_qtys'])), true);
         $line_item_totals = json_decode(sanitize_text_field(stripslashes($_POST['line_item_totals'])), true);
         $line_item_tax_totals = json_decode(sanitize_text_field(stripslashes($_POST['line_item_tax_totals'])), true);
         $api_refund = $_POST['api_refund'] === 'true' ? true : false;
         $restock_refunded_items = $_POST['restock_refunded_items'] === 'true' ? true : false;
         $order = wc_get_order($order_id);
         $parent_order_total = wc_format_decimal($order->get_total());
         $suborder_ids = self::get_suborder($order_id);
         //calculate line items total from parent order
         foreach ($line_item_totals as $item_id => $total) {
             $parent_line_item_refund += wc_format_decimal($total);
         }
         foreach ($suborder_ids as $suborder_id) {
             $suborder = wc_get_order($suborder_id);
             $suborder_items_ids = array_keys($suborder->get_items());
             $suborder_total = wc_format_decimal($suborder->get_total());
             $max_refund = wc_format_decimal($suborder_total - $suborder->get_total_refunded());
             $child_line_item_refund = 0;
             // Prepare line items which we are refunding
             $line_items = array();
             $item_ids = array_unique(array_merge(array_keys($line_item_qtys, $line_item_totals)));
             foreach ($item_ids as $item_id) {
                 $child_item_id = self::get_child_item_id($item_id);
                 if ($child_item_id && in_array($child_item_id, $suborder_items_ids)) {
                     $line_items[$child_item_id] = array('qty' => 0, 'refund_total' => 0, 'refund_tax' => array());
                 }
             }
             foreach ($line_item_qtys as $item_id => $qty) {
                 $child_item_id = self::get_child_item_id($item_id);
                 if ($child_item_id && in_array($child_item_id, $suborder_items_ids)) {
                     $line_items[$child_item_id]['qty'] = max($qty, 0);
                 }
             }
             foreach ($line_item_totals as $item_id => $total) {
                 $child_item_id = self::get_child_item_id($item_id);
                 if ($child_item_id && in_array($child_item_id, $suborder_items_ids)) {
                     $total = wc_format_decimal($total);
                     $child_line_item_refund += $total;
                     $line_items[$child_item_id]['refund_total'] = $total;
                 }
             }
             foreach ($line_item_tax_totals as $item_id => $tax_totals) {
                 $child_item_id = self::get_child_item_id($item_id);
                 if ($child_item_id && in_array($child_item_id, $suborder_items_ids)) {
                     $line_items[$child_item_id]['refund_tax'] = array_map('wc_format_decimal', $tax_totals);
                 }
             }
             //calculate refund amount percentage
             $suborder_refund_amount = ($refund_amount - $parent_line_item_refund) * $suborder_total / $parent_order_total;
             $suborder_total_refund = wc_format_decimal($child_line_item_refund + $suborder_refund_amount);
             if (!$refund_amount || $max_refund < $suborder_total_refund || 0 > $suborder_total_refund) {
                 /**
                  * Invalid refund amount.
                  * Check if suborder total != 0 create a partial refund, exit otherwise
                  */
                 $surplus = wc_format_decimal($suborder_total_refund - $max_refund);
                 $suborder_total_refund = $suborder_total_refund - $surplus;
                 $create_refund = $suborder_total_refund > 0 ? true : false;
             }
             if ($create_refund) {
                 // Create the refund object
                 $refund = wc_create_refund(array('amount' => $suborder_total_refund, 'reason' => $refund_reason, 'order_id' => $suborder->id, 'line_items' => $line_items));
                 add_post_meta($refund->id, '_parent_refund_id', $parent_refund_id);
             }
         }
     }
 }
 /**
  * Create a new order refund for the given order
  *
  * @since 2.2
  * @param string $order_id order ID
  * @param array $data raw request data
  * @param bool $api_refund do refund using a payment gateway API
  * @return WP_Error|array error or created refund response data
  */
 public function create_order_refund($order_id, $data, $api_refund = true)
 {
     try {
         if (!isset($data['order_refund'])) {
             throw new WC_API_Exception('woocommerce_api_missing_order_refund_data', sprintf(__('No %1$s data specified to create %1$s', 'woocommerce'), 'order_refund'), 400);
         }
         $data = $data['order_refund'];
         // Permission check
         if (!current_user_can('publish_shop_orders')) {
             throw new WC_API_Exception('woocommerce_api_user_cannot_create_order_refund', __('You do not have permission to create order refunds', 'woocommerce'), 401);
         }
         $order_id = absint($order_id);
         if (empty($order_id)) {
             throw new WC_API_Exception('woocommerce_api_invalid_order_id', __('Order ID is invalid', 'woocommerce'), 400);
         }
         $data = apply_filters('woocommerce_api_create_order_refund_data', $data, $order_id, $this);
         // Refund amount is required
         if (!isset($data['amount'])) {
             throw new WC_API_Exception('woocommerce_api_invalid_order_refund', __('Refund amount is required', 'woocommerce'), 400);
         } elseif (0 > $data['amount']) {
             throw new WC_API_Exception('woocommerce_api_invalid_order_refund', __('Refund amount must be positive', 'woocommerce'), 400);
         }
         $data['order_id'] = $order_id;
         $data['refund_id'] = 0;
         // Create the refund
         $refund = wc_create_refund($data);
         if (!$refund) {
             throw new WC_API_Exception('woocommerce_api_cannot_create_order_refund', __('Cannot create order refund, please try again', 'woocommerce'), 500);
         }
         // Refund via API
         if ($api_refund) {
             if (WC()->payment_gateways()) {
                 $payment_gateways = WC()->payment_gateways->payment_gateways();
             }
             $order = wc_get_order($order_id);
             if (isset($payment_gateways[$order->get_payment_method()]) && $payment_gateways[$order->get_payment_method()]->supports('refunds')) {
                 $result = $payment_gateways[$order->get_payment_method()]->process_refund($order_id, $refund->get_amount(), $refund->get_reason());
                 if (is_wp_error($result)) {
                     return $result;
                 } elseif (!$result) {
                     throw new WC_API_Exception('woocommerce_api_create_order_refund_api_failed', __('An error occurred while attempting to create the refund using the payment gateway API', 'woocommerce'), 500);
                 }
             }
         }
         // HTTP 201 Created
         $this->server->send_status(201);
         do_action('woocommerce_api_create_order_refund', $refund->id, $order_id, $this);
         return $this->get_order_refund($order_id, $refund->id);
     } catch (WC_Data_Exception $e) {
         return new WP_Error($e->getErrorCode(), $e->getMessage(), array('status' => 400));
     } catch (WC_API_Exception $e) {
         return new WP_Error($e->getErrorCode(), $e->getMessage(), array('status' => $e->getCode()));
     }
 }
Example #6
0
 /**
  * Test: get_remaining_refund_amount
  */
 function test_get_remaining_refund_amount()
 {
     $object = new WC_Order();
     $object->set_total(400);
     $id = $object->save();
     wc_create_refund(array('order_id' => $id, 'amount' => '100', 'line_items' => array()));
     $this->assertEquals(300, $object->get_remaining_refund_amount());
 }
function wc_update_240_refunds()
{
    global $wpdb;
    /**
     * Refunds for full refunded orders.
     * Update fully refunded orders to ensure they have a refund line item so reports add up.
     */
    $refunded_orders = get_posts(array('posts_per_page' => -1, 'post_type' => 'shop_order', 'post_status' => array('wc-refunded')));
    // Ensure emails are disabled during this update routine
    remove_all_actions('woocommerce_order_status_refunded_notification');
    remove_all_actions('woocommerce_order_partially_refunded_notification');
    remove_action('woocommerce_order_status_refunded', array('WC_Emails', 'send_transactional_email'));
    remove_action('woocommerce_order_partially_refunded', array('WC_Emails', 'send_transactional_email'));
    foreach ($refunded_orders as $refunded_order) {
        $order_total = get_post_meta($refunded_order->ID, '_order_total', true);
        $refunded_total = $wpdb->get_var($wpdb->prepare("\n\t\t\tSELECT SUM( postmeta.meta_value )\n\t\t\tFROM {$wpdb->postmeta} AS postmeta\n\t\t\tINNER JOIN {$wpdb->posts} AS posts ON ( posts.post_type = 'shop_order_refund' AND posts.post_parent = %d )\n\t\t\tWHERE postmeta.meta_key = '_refund_amount'\n\t\t\tAND postmeta.post_id = posts.ID\n\t\t", $refunded_order->ID));
        if ($order_total > $refunded_total) {
            wc_create_refund(array('amount' => $order_total - $refunded_total, 'reason' => __('Order fully refunded', 'woocommerce'), 'order_id' => $refunded_order->ID, 'line_items' => array(), 'date' => $refunded_order->post_modified));
        }
    }
    wc_delete_shop_order_transients();
}
 /**
  * Create a single item.
  *
  * @param WP_REST_Request $request Full details about the request.
  * @return WP_Error|WP_REST_Response
  */
 public function create_item($request)
 {
     if (!empty($request['id'])) {
         return new WP_Error("woocommerce_rest_{$this->post_type}_exists", sprintf(__('Cannot create existing %s.', 'woocommerce'), $this->post_type), array('status' => 400));
     }
     $order_data = get_post((int) $request['order_id']);
     if (empty($order_data)) {
         return new WP_Error('woocommerce_rest_invalid_order', __('Order is invalid', 'woocommerce'), 400);
     }
     if (0 > $request['amount']) {
         return new WP_Error('woocommerce_rest_invalid_order_refund', __('Refund amount must be greater than zero.', 'woocommerce'), 400);
     }
     $api_refund = is_bool($request['api_refund']) ? $request['api_refund'] : true;
     $data = array('order_id' => $order_data->ID, 'amount' => $request['amount'], 'line_items' => $request['line_items']);
     // Create the refund.
     $refund = wc_create_refund($data);
     if (!$refund) {
         return new WP_Error('woocommerce_rest_cannot_create_order_refund', __('Cannot create order refund, please try again.', 'woocommerce'), 500);
     }
     // Refund via API.
     if ($api_refund) {
         if (WC()->payment_gateways()) {
             $payment_gateways = WC()->payment_gateways->payment_gateways();
         }
         $order = wc_get_order($order_data);
         if (isset($payment_gateways[$order->payment_method]) && $payment_gateways[$order->payment_method]->supports('refunds')) {
             $result = $payment_gateways[$order->payment_method]->process_refund($order_id, $refund->get_refund_amount(), $refund->get_refund_reason());
             if (is_wp_error($result)) {
                 return $result;
             } elseif (!$result) {
                 return new WP_Error('woocommerce_rest_create_order_refund_api_failed', __('An error occurred while attempting to create the refund using the payment gateway API.', 'woocommerce'), 500);
             }
         }
     }
     $post = get_post($refund->id);
     $this->update_additional_fields_for_object($post, $request);
     /**
      * Fires after a single item is created or updated via the REST API.
      *
      * @param object          $post      Inserted object (not a WP_Post object).
      * @param WP_REST_Request $request   Request object.
      * @param boolean         $creating  True when creating item, false when updating.
      */
     do_action("woocommerce_rest_insert_{$this->post_type}", $post, $request, true);
     $request->set_param('context', 'edit');
     $response = $this->prepare_item_for_response($post, $request);
     $response = rest_ensure_response($response);
     $response->set_status(201);
     $response->header('Location', rest_url(sprintf('/%s/%s/%d', $this->namespace, $this->rest_base, $post->ID)));
     return $response;
 }
 public function import($importData)
 {
     $order_id = $importData['pid'];
     $index = $importData['i'];
     $this->articleData = $importData['articleData'];
     /*
      *
      * Import Order details - status, date
      *
      */
     $order_status = trim($this->data['pmwi_order']['status'][$index]);
     // detect order status by slug or title
     $all_order_statuses = wc_get_order_statuses();
     if (empty($all_order_statuses[$order_status])) {
         $status_founded = false;
         foreach ($all_order_statuses as $key => $value) {
             if (strtolower($value) == strtolower($order_status)) {
                 $order_status = $key;
                 $status_founded = true;
                 break;
             }
         }
         if (!$status_founded) {
             $order_status = 'wc-pending';
         }
     }
     $this->order_data = array('ID' => $order_id, 'post_title' => 'Order &ndash; ' . date_i18n('F j, Y @ h:i A', strtotime($this->data['pmwi_order']['date'][$index])), 'post_content' => '', 'post_date' => $this->data['pmwi_order']['date'][$index], 'post_date_gmt' => get_gmt_from_date($this->data['pmwi_order']['date'][$index]), 'post_status' => $order_status, 'ping_status' => 'closed', 'post_password' => uniqid('order_'), 'post_excerpt' => $this->data['pmwi_order']['customer_provided_note'][$index]);
     $old_status = str_replace("wc-", "", $this->articleData['post_status']);
     $new_status = str_replace("wc-", "", $this->order_data['post_status']);
     if (!empty($this->articleData['ID'])) {
         if ($this->import->options['update_all_data'] == 'no') {
             if (!$this->import->options['is_update_dates']) {
                 // preserve date of already existing article when duplicate is found
                 $this->order_data['post_title'] = 'Order &ndash; ' . date_i18n('F j, Y @ h:i A', strtotime($this->articleData['post_date']));
                 $this->order_data['post_date'] = $this->articleData['post_date'];
                 $this->order_data['post_date_gmt'] = $this->articleData['post_date_gmt'];
             }
             if (!$this->import->options['is_update_status']) {
                 // preserve status and trashed flag
                 $this->order_data['post_status'] = $this->articleData['post_status'];
             }
             if (!$this->import->options['is_update_excerpt']) {
                 // preserve customer's note
                 $this->order_data['post_excerpt'] = $this->articleData['post_excerpt'];
             }
         }
     }
     $order_id = wp_update_post($this->order_data);
     if (is_wp_error($order_id)) {
         return $order_id;
     }
     $order = wc_get_order($order_id);
     /*
      *
      * Import Order billing & shipping details
      *
      */
     $billing_fields = array('billing_first_name', 'billing_last_name', 'billing_company', 'billing_address_1', 'billing_address_2', 'billing_city', 'billing_postcode', 'billing_country', 'billing_state', 'billing_phone', 'billing_email');
     $billing_data = array();
     if (empty($this->articleData['ID']) or $this->import->options['update_all_data'] == 'yes' or $this->import->options['is_update_billing_details']) {
         $this->logger and call_user_func($this->logger, sprintf(__('- Importing billing & shipping information for Order ID `%s`.', 'wpai_woocommerce_addon_plugin'), $order_id));
         // [ Importing billing information ]
         switch ($this->import->options['pmwi_order']['billing_source']) {
             // Load details from existing customer
             case 'existing':
                 $customer = $this->get_existing_customer('billing_source', $index);
                 if ($customer) {
                     $this->logger and call_user_func($this->logger, sprintf(__('- %s Existing customer with ID `%s` founded for Order `%s`.', 'wpai_woocommerce_addon_plugin'), $customer->ID, $order_id));
                     foreach ($billing_fields as $billing_field) {
                         $billing_data[$billing_field] = get_user_meta($customer->ID, $billing_field, true);
                         update_post_meta($order_id, '_' . $billing_field, $billing_data[$billing_field]);
                         $this->logger and call_user_func($this->logger, sprintf(__('- Billing field `%s` has been updated with value `%s` for order `%s` ...', 'wp_all_import_plugin'), $billing_field, $billing_data[$billing_field], $order_id));
                     }
                     update_post_meta($order_id, '_customer_user', $customer->ID);
                 } else {
                     $this->logger and call_user_func($this->logger, sprintf(__('<b>WARNING</b>: Existing customer not found for Order `%s`.', 'wpai_woocommerce_addon_plugin'), $this->order_data['post_title']));
                 }
                 break;
                 // Use guest customer
             // Use guest customer
             default:
                 foreach ($billing_fields as $billing_field) {
                     $billing_data[$billing_field] = $this->data['pmwi_order'][$billing_field][$index];
                     update_post_meta($order_id, '_' . $billing_field, $billing_data[$billing_field]);
                     $this->logger and call_user_func($this->logger, sprintf(__('- Billing field `%s` has been updated with value `%s` for order `%s` ...', 'wp_all_import_plugin'), $billing_field, $this->data['pmwi_order'][$billing_field][$index], $order_id));
                 }
                 update_post_meta($order_id, '_customer_user', '0');
                 break;
         }
     }
     // [\Importing billing information ]
     // [ Importing shipping information ]
     if (empty($this->articleData['ID']) or $this->import->options['update_all_data'] == 'yes' or $this->import->options['is_update_shipping_details']) {
         switch ($this->import->options['pmwi_order']['shipping_source']) {
             // Copy from billing
             case 'copy':
                 $this->logger and call_user_func($this->logger, sprintf(__('- Copying shipping from billing information...', 'wpai_woocommerce_addon_plugin')));
                 if (!empty($billing_data)) {
                     foreach ($billing_data as $key => $value) {
                         $shipping_field = str_replace('billing', 'shipping', $key);
                         update_post_meta($order_id, '_' . $shipping_field, $value);
                         $this->logger and call_user_func($this->logger, sprintf(__('- Shipping field `%s` has been updated with value `%s` for order `%s` ...', 'wp_all_import_plugin'), $shipping_field, $value, $order_id));
                     }
                 }
                 break;
                 // Import shipping address
             // Import shipping address
             default:
                 foreach ($billing_fields as $billing_field) {
                     $shipping_field = str_replace('billing', 'shipping', $billing_field);
                     update_post_meta($order_id, '_' . $shipping_field, $this->data['pmwi_order'][$shipping_field][$index]);
                     $this->logger and call_user_func($this->logger, sprintf(__('- Shipping field `%s` has been updated with value `%s` for order `%s` ...', 'wp_all_import_plugin'), $shipping_field, $this->data['pmwi_order'][$shipping_field][$index], $order_id));
                 }
                 break;
         }
     }
     // [\Importing shipping information ]
     // send notifications on order status changed
     if (!empty($this->articleData['ID']) and $new_status !== $old_status && empty($this->import->options['do_not_send_order_notifications'])) {
         do_action('woocommerce_order_status_' . $old_status . '_to_' . $new_status, $order_id);
         do_action('woocommerce_order_status_changed', $order_id, $old_status, $new_status);
         if ($new_status == 'completed') {
             do_action('woocommerce_order_status_completed', $this->articleData['ID']);
         }
     }
     // send new order notification
     if (empty($this->articleData['ID']) && empty($this->import->options['do_not_send_order_notifications'])) {
         do_action('woocommerce_order_status_' . $new_status, $order_id);
         do_action('woocommerce_order_status_pending_to_' . $new_status, $order_id);
         do_action('woocommerce_before_resend_order_emails', $order);
         // Load mailer
         $mailer = WC()->mailer();
         $email_to_send = 'new_order';
         $mails = $mailer->get_emails();
         if (!empty($mails)) {
             foreach ($mails as $mail) {
                 if ($mail->id == $email_to_send) {
                     $mail->trigger($order_id);
                     $this->logger and call_user_func($this->logger, sprintf(__('- %s email notification has beed sent. ...', 'wp_all_import_plugin'), $mail->title));
                 }
             }
         }
         do_action('woocommerce_after_resend_order_email', $order, $email_to_send);
     }
     // [ Importing payment information ]
     if (empty($this->articleData['ID']) or $this->import->options['update_all_data'] == 'yes' or $this->import->options['is_update_payment']) {
         $payment_method = $this->data['pmwi_order']['payment_method'][$index];
         if (!empty($payment_method)) {
             if (!empty($this->payment_gateways[$payment_method])) {
                 update_post_meta($order_id, '_payment_method', $payment_method);
                 update_post_meta($order_id, '_payment_method_title', $this->payment_gateways[$payment_method]->title);
             } else {
                 $method = false;
                 if (!empty($this->payment_gateways)) {
                     foreach ($this->payment_gateways as $payment_gateway_slug => $payment_gateway) {
                         if (strtolower($payment_gateway->method_title) == strtolower(trim($payment_method))) {
                             $method = $payment_method;
                             break;
                         }
                     }
                 }
                 if ($method) {
                     update_post_meta($order_id, '_payment_method', $payment_method);
                     update_post_meta($order_id, '_payment_method_title', $method->method_title);
                 }
             }
         } else {
             update_post_meta($order_id, '_payment_method', 'N/A');
         }
         update_post_meta($order_id, '_transaction_id', $this->data['pmwi_order']['transaction_id'][$index]);
     }
     // [\Importing payment information ]
     /*
      *
      * Import Order Items
      *
      */
     // Importing product items
     if (empty($this->articleData['ID']) or $this->import->options['update_all_data'] == 'yes' or $this->import->options['is_update_products']) {
         if (!empty($this->articleData['ID']) and ($this->import->options['update_all_data'] == 'yes' or $this->import->options['is_update_products'] and $this->import->options['update_products_logic'] == 'full_update')) {
             $previously_updated_order = get_option('wp_all_import_previously_updated_order_' . $this->import->id, false);
             if (empty($previously_updated_order) or $previously_updated_order != $this->articleData['ID']) {
                 $order->remove_order_items('line_item');
                 global $wpdb;
                 $wpdb->query($wpdb->prepare("DELETE FROM {$wpdb->prefix}pmxi_posts WHERE import_id = %d AND post_id = %d AND unique_key LIKE %s;", $this->import->id, $order_id, '%' . $wpdb->esc_like('line-item') . '%'));
             }
         }
         $this->_import_line_items($order, $order_id, $index);
     }
     // Importing fee items
     if (empty($this->articleData['ID']) or $this->import->options['update_all_data'] == 'yes' or $this->import->options['is_update_fees']) {
         $this->_import_fee_items($order, $order_id, $index);
     }
     // Importing coupons items
     if (empty($this->articleData['ID']) or $this->import->options['update_all_data'] == 'yes' or $this->import->options['is_update_coupons']) {
         $this->_import_coupons_items($order, $order_id, $index);
     }
     // Importing shipping items
     if (empty($this->articleData['ID']) or $this->import->options['update_all_data'] == 'yes' or $this->import->options['is_update_shipping']) {
         $this->_import_shipping_items($order, $order_id, $index);
     }
     // Importing taxes items
     if (empty($this->articleData['ID']) or $this->import->options['update_all_data'] == 'yes' or $this->import->options['is_update_taxes']) {
         $this->_import_taxes_items($order, $order_id, $index);
     }
     /*
      *
      * Import Order Refunds
      *
      */
     if (empty($this->articleData['ID']) or $this->import->options['update_all_data'] == 'yes' or $this->import->options['is_update_refunds']) {
         if (!empty($this->data['pmwi_order']['order_refund_amount'][$index])) {
             $refund_item = new PMXI_Post_Record();
             $refund_item->getBy(array('import_id' => $this->import->id, 'post_id' => $order_id, 'unique_key' => 'refund-item-' . $order_id));
             $args = array('amount' => $this->data['pmwi_order']['order_refund_amount'][$index], 'reason' => $this->data['pmwi_order']['order_refund_reason'][$index], 'order_id' => $order_id, 'refund_id' => 0, 'line_items' => array(), 'date' => $this->data['pmwi_order']['order_refund_date'][$index]);
             if (!$refund_item->isEmpty()) {
                 $args['refund_id'] = str_replace('refund-item-', '', $refund_item->product_key);
             }
             $refund = wc_create_refund($args);
             if ($refund instanceof WC_Order_Refund) {
                 $refund_item->set(array('import_id' => $this->import->id, 'post_id' => $order_id, 'unique_key' => 'refund-item-' . $order_id, 'product_key' => 'refund-item-' . $refund->id, 'iteration' => $this->import->iteration))->save();
                 switch ($this->import->options['pmwi_order']['order_refund_issued_source']) {
                     case 'existing':
                         $customer = $this->get_existing_customer('order_refund_issued', $index);
                         if ($customer) {
                             wp_update_post(array('ID' => $refund->id, 'post_author' => $customer->ID));
                         }
                         break;
                     default:
                         wp_update_post(array('ID' => $refund->id, 'post_author' => 0));
                         break;
                 }
             }
         }
     }
     /*
      *
      * Import Order Total
      *
      */
     if (empty($this->articleData['ID']) or $this->import->options['update_all_data'] == 'yes' or $this->import->options['is_update_total']) {
         if ($this->import->options['pmwi_order']['order_total_logic'] !== 'auto') {
             $order->set_total($this->data['pmwi_order']['order_total_xpath'][$index], 'total');
         } else {
             $order->calculate_totals();
         }
     }
     /*
      *
      * Import Order Notes
      *
      */
     if (empty($this->articleData['ID']) or $this->import->options['update_all_data'] == 'yes' or $this->import->options['is_update_notes']) {
         $this->_import_order_notes($order, $order_id, $index);
     }
     update_post_meta($order_id, '_order_version', WC_VERSION);
 }
 /**
  * Update order data
  *
  * Based on WC_API_Customers::update_customer_data()
  *
  * @since 3.0.0
  * @param \WC_Order $order
  * @param array $data
  * @param array $options
  */
 private function update_order_data(WC_Order $order, $data, $options)
 {
     if (isset($data['date']) && $data['date']) {
         wp_update_post(array('ID' => $order->id, 'post_date' => date('Y-m-d H:i:s', $data['date'])));
     }
     $merging = $options['merge'] && isset($data['id']) && $data['id'];
     $this->process_terms($order->id, $data['terms']);
     // set order addresses
     $order->set_address($data['billing_address'], 'billing');
     $order->set_address($data['shipping_address'], 'shipping');
     // clear any previously set refunded order item ids
     $this->refunded_item_order_ids = array();
     // set order lines
     foreach ($this->line_types as $line_type => $line) {
         // don't set lines if they're empty. This ensures partial updates/merges
         // are supported and won't wipe out order lines
         if (!empty($data[$line]) && is_array($data[$line])) {
             $this->process_items($order, $data[$line], $line_type, $merging);
         }
     }
     // set order currency
     if (isset($data['currency'])) {
         update_post_meta($order->id, '_order_currency', $data['currency']);
     }
     // grant downloadable product permissions
     if (isset($data['download_permissions_granted']) && $data['download_permissions_granted']) {
         wc_downloadable_product_permissions($order->id);
     }
     // set order meta
     if (isset($data['order_meta']) && is_array($data['order_meta'])) {
         $this->set_order_meta($order->id, $data['order_meta']);
     }
     // set the paying customer flag on the user meta if applicable
     $paid_statuses = array('processing', 'completed', 'refunded');
     if ($data['customer_id'] && in_array($data['status'], $paid_statuses)) {
         update_user_meta($data['customer_id'], "paying_customer", 1);
     }
     // process refunds
     if (!empty($data['refunds'])) {
         // remove previous refunds
         foreach ($order->get_refunds() as $refund) {
             wc_delete_shop_order_transients($refund->id);
             wp_delete_post($refund->id, true);
         }
         foreach ($data['refunds'] as $refund_data) {
             // try mapping temp refunded item ids to real order item ids
             if (!empty($refund_data['line_items'])) {
                 foreach ($refund_data['line_items'] as $key => $refunded_item) {
                     if (isset($refunded_item['refunded_item_temp_id'])) {
                         $temp_id = $refunded_item['refunded_item_temp_id'];
                         // get the real order item id for this refunded itme
                         $order_item_id = $this->get_array_key_value($this->refunded_item_order_ids, $temp_id);
                         if ($order_item_id) {
                             $refund_data['line_items'][$order_item_id] = $refunded_item;
                             unset($refund_data['line_items'][$key]);
                         }
                     }
                 }
             }
             wc_create_refund(array('order_id' => $order->id, 'amount' => $refund_data['amount'], 'reason' => $refund_data['reason'], 'line_items' => $refund_data['line_items'], 'date' => $refund_data['date']));
         }
     }
     wc_delete_shop_order_transients($order->id);
     /**
      * Triggered after order data has been updated via CSV
      *
      * This will be triggered for both new and updated orders
      *
      * @since 3.0.0
      * @param int $id Order ID
      * @param array $data Order data
      * @param array $options Import options
      */
     do_action('wc_csv_import_suite_update_order_data', $order->id, $data, $options);
 }