/** * Create or update a line item * * @since 2.5.0 * @param WC_Order $order * @param array $item line item data * @param string $action 'create' to add line item or 'update' to update it * @throws WC_CLI_Exception invalid data, server error */ protected function set_line_item($order, $item, $action) { $creating = 'create' === $action; // product is always required if (!isset($item['product_id']) && !isset($item['sku'])) { throw new WC_CLI_Exception('woocommerce_cli_invalid_product_id', __('Product ID or SKU is required', 'woocommerce')); } // when updating, ensure product ID provided matches if ('update' === $action) { $item_product_id = wc_get_order_item_meta($item['id'], '_product_id'); $item_variation_id = wc_get_order_item_meta($item['id'], '_variation_id'); if ($item['product_id'] != $item_product_id && $item['product_id'] != $item_variation_id) { throw new WC_CLI_Exception('woocommerce_cli_invalid_product_id', __('Product ID provided does not match this line item', 'woocommerce')); } } if (isset($item['product_id'])) { $product_id = $item['product_id']; } elseif (isset($item['sku'])) { $product_id = wc_get_product_id_by_sku($item['sku']); } // variations must each have a key & value $variation_id = 0; if (isset($item['variations']) && is_array($item['variations'])) { foreach ($item['variations'] as $key => $value) { if (!$key || !$value) { throw new WC_CLI_Exception('woocommerce_cli_invalid_product_variation', __('The product variation is invalid', 'woocommerce')); } } $item_args['variation'] = $item['variations']; $variation_id = $this->get_variation_id(wc_get_product($product_id), $item_args['variation']); } $product = wc_get_product($variation_id ? $variation_id : $product_id); // must be a valid WC_Product if (!is_object($product)) { throw new WC_CLI_Exception('woocommerce_cli_invalid_product', __('Product is invalid', 'woocommerce')); } // quantity must be positive float if (isset($item['quantity']) && floatval($item['quantity']) <= 0) { throw new WC_CLI_Exception('woocommerce_cli_invalid_product_quantity', __('Product quantity must be a positive float', 'woocommerce')); } // quantity is required when creating if ($creating && !isset($item['quantity'])) { throw new WC_CLI_Exception('woocommerce_cli_invalid_product_quantity', __('Product quantity is required', 'woocommerce')); } $item_args = array(); // quantity if (isset($item['quantity'])) { $item_args['qty'] = $item['quantity']; } // total if (isset($item['total'])) { $item_args['totals']['total'] = floatval($item['total']); } // total tax if (isset($item['total_tax'])) { $item_args['totals']['tax'] = floatval($item['total_tax']); } // subtotal if (isset($item['subtotal'])) { $item_args['totals']['subtotal'] = floatval($item['subtotal']); } // subtotal tax if (isset($item['subtotal_tax'])) { $item_args['totals']['subtotal_tax'] = floatval($item['subtotal_tax']); } if ($creating) { $item_id = $order->add_product($product, $item_args['qty'], $item_args); if (!$item_id) { throw new WC_CLI_Exception('woocommerce_cannot_create_line_item', __('Cannot create line item, try again', 'woocommerce')); } } else { $item_id = $order->update_product($item['id'], $product, $item_args); if (!$item_id) { throw new WC_CLI_Exception('woocommerce_cannot_update_line_item', __('Cannot update line item, try again', 'woocommerce')); } } }
/** * Test: has_free_item */ function test_has_free_item() { $object = new WC_Order(); $object->add_product(WC_Helper_Product::create_simple_product(), 4); $this->assertFalse($object->has_free_item()); $free_product = WC_Helper_Product::create_simple_product(); $free_product->set_price(0); $object->add_product($free_product, 4); $this->assertTrue($object->has_free_item()); }
/** * Add an item to the provided order * * @since 3.0.0 * @param \WC_Order $order * @param array $item Parsed item data from CSV * @param string $type Line item type * @return int|false ID of the inserted order item, false on failure */ private function add_order_item(WC_Order $order, $item, $type) { $result = false; switch ($type) { case 'line_item': $product = $this->get_product_for_item($item); $args = $this->prepare_product_args($item); $result = $order->add_product($product, $args['qty'], $args); if (!$result) { wc_csv_import_suite()->log(sprintf(__('> > Warning: cannot add order item "%s".', 'woocommerce-csv-import-suite'), esc_html($identifier))); } break; case 'shipping': $args = array('order_item_name' => $item['method_title'], 'order_item_type' => 'shipping'); // we're using wc_add_order_item instead of $order->add_shipping because // we do not want the order total to be recalculated $result = wc_add_order_item($order->id, $args); if (!$result) { wc_csv_import_suite()->log(sprintf(__('> > Warning: cannot add shipping method "%s".', 'woocommerce-csv-import-suite'), esc_html($item['title']))); } break; case 'tax': $args = array('order_item_name' => $item['code'], 'order_item_type' => 'tax'); $result = wc_add_order_item($order->id, $args); if (!$result) { wc_csv_import_suite()->log(sprintf(__('> > Warning: cannot add tax "%s".', 'woocommerce-csv-import-suite'), esc_html($item['label']))); } break; case 'coupon': $result = $order->add_coupon($item['code'], $item['amount']); if (!$result) { wc_csv_import_suite()->log(sprintf(__('> > Warning: cannot add coupon "%s".', 'woocommerce-csv-import-suite'), esc_html($item['code']))); } break; case 'fee': $order_fee = new stdClass(); $order_fee->id = sanitize_title($item['title']); $order_fee->name = $item['title']; $order_fee->amount = isset($item['total']) ? floatval($item['total']) : 0; $order_fee->taxable = false; $order_fee->tax = 0; $order_fee->tax_data = array(); $order_fee->tax_class = ''; // if taxable, tax class and total are required if (isset($item['taxable']) && $item['taxable']) { $order_fee->taxable = true; $order_fee->tax_class = $item['tax_class']; if (isset($item['total_tax'])) { $order_fee->tax = isset($item['total_tax']) ? wc_format_refund_total($item['total_tax']) : 0; } if (isset($item['tax_data'])) { $tax_data = isset($item['tax_data']['total']) ? $item['tax_data']['total'] : $item['tax_data']; $order_fee->tax = wc_format_refund_total(array_sum($tax_data)); $order_fee->tax_data = array_map('wc_format_refund_total', $tax_data); } } $result = $order->add_fee($order_fee); if (!$result) { wc_csv_import_suite()->log(sprintf(__('> > Warning: cannot add fee "%s".', 'woocommerce-csv-import-suite'), esc_html($item['title']))); } break; } // store original order item ID if ($result && isset($item['order_item_id']) && $item['order_item_id'] > 0) { wc_update_order_item_meta($result, '_original_order_item_id', $item['order_item_id']); } return $result; }
/** * Create or update a line item. * * @param WC_Order $order Order data. * @param array $item Line item data. * @param string $action 'create' to add line item or 'update' to update it. * @throws WC_REST_Exception Invalid data, server error. */ protected function set_line_item($order, $item, $action = 'create') { $creating = 'create' === $action; $item_args = array(); // Product is always required. if (empty($item['product_id']) && empty($item['sku']) && empty($item['variation_id'])) { throw new WC_REST_Exception('woocommerce_rest_required_product_reference', __('Product ID or SKU is required.', 'woocommerce'), 400); } if (!empty($item['sku'])) { $product_id = (int) wc_get_product_id_by_sku($item['sku']); } elseif (!empty($item['product_id']) && empty($item['variation_id'])) { $product_id = (int) $item['product_id']; } elseif (!empty($item['variation_id'])) { $product_id = (int) $item['variation_id']; } // When updating, ensure product ID provided matches. if ('update' === $action && !empty($item['id'])) { $item_product_id = (int) wc_get_order_item_meta($item['id'], '_product_id'); $item_variation_id = (int) wc_get_order_item_meta($item['id'], '_variation_id'); if ($product_id !== $item_product_id && $product_id !== $item_variation_id) { throw new WC_REST_Exception('woocommerce_rest_required_product_reference', __('Product ID or variation ID provided does not match this line item.', 'woocommerce'), 400); } } $product = wc_get_product($product_id); // Must be a valid WC_Product. if (!is_object($product)) { throw new WC_REST_Exception('woocommerce_rest_invalid_product', __('Product is invalid.', 'woocommerce'), 400); } // Quantity must be positive float. if (isset($item['quantity']) && 0 >= floatval($item['quantity'])) { throw new WC_REST_Exception('woocommerce_rest_invalid_product_quantity', __('Product quantity must be a positive float.', 'woocommerce'), 400); } // Quantity is required when creating. if ($creating && !isset($item['quantity'])) { throw new WC_REST_Exception('woocommerce_rest_invalid_product_quantity', __('Product quantity is required.', 'woocommerce'), 400); } // Get variation attributes. if (method_exists($product, 'get_variation_attributes')) { $item_args['variation'] = $product->get_variation_attributes(); } // Quantity. if (isset($item['quantity'])) { $item_args['qty'] = $item['quantity']; } // Total. if (isset($item['total'])) { $item_args['totals']['total'] = floatval($item['total']); } // Total tax. if (isset($item['total_tax'])) { $item_args['totals']['tax'] = floatval($item['total_tax']); } // Subtotal. if (isset($item['subtotal'])) { $item_args['totals']['subtotal'] = floatval($item['subtotal']); } // Subtotal tax. if (isset($item['subtotal_tax'])) { $item_args['totals']['subtotal_tax'] = floatval($item['subtotal_tax']); } if ($creating) { $item_id = $order->add_product($product, $item_args['qty'], $item_args); if (!$item_id) { throw new WC_REST_Exception('woocommerce_rest_cannot_create_line_item', __('Cannot create line item, try again.', 'woocommerce'), 500); } } else { $item_id = $order->update_product($item['id'], $product, $item_args); if (!$item_id) { throw new WC_REST_Exception('woocommerce_rest_cannot_update_line_item', __('Cannot update line item, try again.', 'woocommerce'), 500); } } }