/** * Update fee for order * * Note this does not update order totals * * @since 2.2 * @param int $item_id * @param array $args * @return bool */ public function update_fee($item_id, $args) { if (!$item_id) { return false; } // name if (isset($args['name'])) { wc_update_order_item($item_id, array('order_item_name' => $args['name'])); } // tax class if (isset($args['tax_class'])) { wc_update_order_item_meta($item_id, '_tax_class', $args['tax_class']); } // total if (isset($args['line_total'])) { wc_update_order_item_meta($item_id, '_line_total', wc_format_decimal($args['line_total'])); } // total tax if (isset($args['line_tax'])) { wc_update_order_item_meta($item_id, '_line_tax', wc_format_decimal($args['line_tax'])); } do_action('woocommerce_order_update_fee', $this->id, $item_id, $args); return true; }
/** * Opportunity to change title and add line_item meta * @param $order_id * @param $item_id * @param $product * @param $qty * @param $args */ public function order_add_product($order_id, $item_id, $product, $qty, $args) { $id = isset($product->id) ? $product->id : false; $id = isset($product->variation_id) ? $product->variation_id : $id; if ($id) { $data = $this->get_line_item($id); // update title if (isset($data['title'])) { wc_update_order_item($item_id, array('order_item_name' => sanitize_text_field($data['title']))); } // update meta if (isset($data['meta']) && !empty($data['meta'])) { $this->add_product_meta($item_id, $data['meta']); } } }
/** * Create a scheduled order * @param string $payment_date * @param int $original_order_id */ public static function create_order($payment_date, $original_order_id, $payment_number, $item, $status = '') { $original_order = wc_get_order($original_order_id); $new_order = wc_create_order(array('status' => $status, 'customer_id' => $original_order->get_user_id(), 'customer_note' => $original_order->customer_note, 'created_via' => 'wc_deposits')); if (is_wp_error($new_order)) { $original_order->add_order_note(sprintf(__('Error: Unable to create follow up payment (%s)', 'woocommerce-deposits'), $scheduled_order->get_error_message())); } else { $new_order->set_address(array('first_name' => $original_order->billing_first_name, 'last_name' => $original_order->billing_last_name, 'company' => $original_order->billing_company, 'address_1' => $original_order->billing_address_1, 'address_2' => $original_order->billing_address_2, 'city' => $original_order->billing_city, 'state' => $original_order->billing_state, 'postcode' => $original_order->billing_postcode, 'country' => $original_order->billing_country, 'email' => $original_order->billing_email, 'phone' => $original_order->billing_phone), 'billing'); $new_order->set_address(array('first_name' => $original_order->shipping_first_name, 'last_name' => $original_order->shipping_last_name, 'company' => $original_order->shipping_company, 'address_1' => $original_order->shipping_address_1, 'address_2' => $original_order->shipping_address_2, 'city' => $original_order->shipping_city, 'state' => $original_order->shipping_state, 'postcode' => $original_order->shipping_postcode, 'country' => $original_order->shipping_country), 'shipping'); // Handle items $item_id = $new_order->add_product($item['product'], $item['qty'], array('totals' => array('subtotal' => $item['amount'], 'total' => $item['amount'], 'subtotal_tax' => 0, 'tax' => 0))); woocommerce_add_order_item_meta($item_id, '_original_order_id', $original_order_id); wc_update_order_item($item_id, array('order_item_name' => sprintf(__('Payment #%d for %s'), $payment_number, $item['product']->get_title()))); $new_order->calculate_totals(wc_tax_enabled()); // Set future date and parent $new_order_post = array('ID' => $new_order->id, 'post_date' => date('Y-m-d H:i:s', $payment_date), 'post_parent' => $original_order_id); wp_update_post($new_order_post); do_action('woocommerce_deposits_create_order', $new_order->id); return $new_order->id; } }
/** * Update shipping method on the subscription if the order changed anything * * @param WC_Order $order The new order * @param WC_Subscription $subscription The original subscription * @param WC_Cart $recurring_cart A recurring cart */ public static function update_shipping_methods($subscription, $recurring_cart) { // First, archive all the shipping methods foreach ($subscription->get_shipping_methods() as $shipping_method_id => $shipping_method) { wc_update_order_item($shipping_method_id, array('order_item_type' => 'shipping_switched')); } // Then zero the order_shipping total so we have a clean slate to add to $subscription->order_shipping = 0; WC_Subscriptions_Checkout::add_shipping($subscription, $recurring_cart); // Now update subscription object order_shipping to reflect updated values so it doesn't stay 0 $subscription->order_shipping = get_post_meta($subscription->id, '_order_shipping', true); }
protected function _import_line_items(&$order, $order_id, $index) { $is_product_founded = false; switch ($this->import->options['pmwi_order']['products_source']) { // Get data from existing products case 'existing': foreach ($this->data['pmwi_order']['products'][$index] as $productIndex => $productItem) { if (empty($productItem['sku'])) { continue; } $args = array('post_type' => 'product', 'meta_key' => '_sku', 'meta_value' => $productItem['sku'], 'meta_compare' => '='); $product = false; $query = new WP_Query($args); while ($query->have_posts()) { $query->the_post(); $product = WC()->product_factory->get_product($query->post->ID); break; } wp_reset_postdata(); if (empty($product)) { $args['post_type'] = 'product_variation'; $query = new WP_Query($args); while ($query->have_posts()) { $query->the_post(); $product = WC()->product_factory->get_product($query->post->ID); break; } wp_reset_postdata(); } if ($product) { $is_product_founded = true; $item_price = $product->get_price(); $item_qty = empty($productItem['qty']) ? 1 : $productItem['qty']; $item_subtotal = $item_price * $item_qty; $item_subtotal_tax = 0; $line_taxes = array(); foreach ($productItem['tax_rates'] as $key => $tax_rate) { if (empty($tax_rate['code'])) { continue; } $tax_rate_codes = explode("|", $tax_rate['code']); $percentage_value = explode("|", $tax_rate['percentage_value']); $amount_per_unit = explode("|", $tax_rate['amount_per_unit']); foreach ($tax_rate_codes as $rate_key => $tax_rate_code) { if ($tax_rate_code == 'standard') { $tax_rate_code = ''; } $line_tax = 0; switch ($tax_rate['calculate_logic']) { case 'percentage': if (!empty($percentage_value[$rate_key]) and is_numeric($percentage_value[$rate_key])) { $line_tax = WC_Tax::round($item_subtotal / 100 * $percentage_value[$rate_key]); $item_subtotal_tax += $line_tax; } if (!empty($this->tax_rates)) { foreach ($this->tax_rates as $rate_id => $rate) { if ($rate->tax_rate_name == $tax_rate_code) { $line_taxes[$rate->tax_rate_id] = $line_tax; break; } } } break; case 'per_unit': if (!empty($amount_per_unit[$rate_key]) and is_numeric($amount_per_unit[$rate_key])) { $line_tax = WC_Tax::round($amount_per_unit[$rate_key] * $item_qty); $item_subtotal_tax += $line_tax; } if (!empty($this->tax_rates)) { foreach ($this->tax_rates as $rate_id => $rate) { if ($rate->tax_rate_name == $tax_rate_code) { $line_taxes[$rate->tax_rate_id] = $line_tax; break; } } } break; // Look up tax rate code // Look up tax rate code default: $found_rates = WC_Tax::get_rates_for_tax_class($tax_rate_code); if (!empty($found_rates)) { $found_priority = array(); foreach ($found_rates as $found_rate) { $matched_tax_rates = array(); if (in_array($found_rate->tax_rate_priority, $found_priority)) { continue; } $matched_tax_rates[$found_rate->tax_rate_id] = array('rate' => $found_rate->tax_rate, 'label' => $found_rate->tax_rate_name, 'shipping' => $found_rate->tax_rate_shipping ? 'yes' : 'no', 'compound' => $found_rate->tax_rate_compound ? 'yes' : 'no'); $line_tax = array_sum(WC_Tax::calc_tax($item_subtotal, $matched_tax_rates, $this->prices_include_tax)); $item_subtotal_tax += $line_tax; $line_taxes[$found_rate->tax_rate_id] = $line_tax; $found_priority[] = $found_rate->tax_rate_priority; } } break; } } } $variation = array(); $variation_str = ''; if ($product instanceof WC_Product_Variation) { $variation = $product->get_variation_attributes(); if (!empty($variation)) { foreach ($variation as $key => $value) { $variation_str .= $key . '-' . $value; } } } $product_item = new PMXI_Post_Record(); $product_item->getBy(array('import_id' => $this->import->id, 'post_id' => $order_id, 'unique_key' => 'line-item-' . $product->id . '-' . $variation_str)); if ($product_item->isEmpty()) { $item_id = false; // in case when this is new order just add new line items if (!$item_id) { $item_id = $order->add_product($product, $item_qty, array('variation' => $variation, 'totals' => array('subtotal' => $item_subtotal, 'subtotal_tax' => $item_subtotal_tax, 'total' => $item_subtotal, 'tax' => $item_subtotal_tax, 'tax_data' => array('total' => $line_taxes, 'subtotal' => array())))); } if (!$item_id) { $this->logger and call_user_func($this->logger, __('- <b>WARNING</b> Unable to create order line product.', 'wp_all_import_plugin')); } else { $product_item->set(array('import_id' => $this->import->id, 'post_id' => $order_id, 'unique_key' => 'line-item-' . $product->id . '-' . $variation_str, 'product_key' => 'line-item-' . $item_id, 'iteration' => $this->import->iteration))->save(); } } else { $item_id = str_replace('line-item-', '', $product_item->product_key); $is_updated = $order->update_product($item_id, $product, array('qty' => $item_qty, 'tax_class' => $product->get_tax_class(), 'totals' => array('subtotal' => $item_subtotal, 'subtotal_tax' => $item_subtotal_tax, 'total' => $item_subtotal, 'tax' => $item_subtotal_tax, 'tax_data' => array('total' => $line_taxes, 'subtotal' => array())), 'variation' => $variation)); if ($is_updated) { $product_item->set(array('iteration' => $this->import->iteration))->save(); } } } } break; // Manually import product order data and do not try to match to existing products // Manually import product order data and do not try to match to existing products default: $is_product_founded = true; foreach ($this->data['pmwi_order']['manual_products'][$index] as $productIndex => $productItem) { $item_price = $productItem['price_per_unit']; $item_qty = empty($productItem['qty']) ? 1 : $productItem['qty']; $item_subtotal = $item_price * $item_qty; $item_subtotal_tax = 0; $line_taxes = array(); foreach ($productItem['tax_rates'] as $key => $tax_rate) { if (empty($tax_rate['code'])) { continue; } $line_tax = 0; switch ($tax_rate['calculate_logic']) { case 'percentage': if (!empty($tax_rate['percentage_value']) and is_numeric($tax_rate['percentage_value'])) { $line_tax = WC_Tax::round($item_subtotal / 100 * $tax_rate['percentage_value']); $item_subtotal_tax += $line_tax; } break; case 'per_unit': if (!empty($tax_rate['amount_per_unit']) and is_numeric($tax_rate['amount_per_unit'])) { $line_tax = WC_Tax::round($tax_rate['amount_per_unit'] * $item_qty); $item_subtotal_tax += $line_tax; } break; // Look up tax rate code // Look up tax rate code default: $found_rates = WC_Tax::get_rates_for_tax_class($tax_rate['code']); if (!empty($found_rates)) { $matched_tax_rates = array(); $found_priority = array(); foreach ($found_rates as $found_rate) { if (in_array($found_rate->tax_rate_priority, $found_priority)) { continue; } $matched_tax_rates[$found_rate->tax_rate_id] = array('rate' => $found_rate->tax_rate, 'label' => $found_rate->tax_rate_name, 'shipping' => $found_rate->tax_rate_shipping ? 'yes' : 'no', 'compound' => $found_rate->tax_rate_compound ? 'yes' : 'no'); $found_priority[] = $found_rate->tax_rate_priority; } $line_tax = array_sum(WC_Tax::calc_tax($item_subtotal, $matched_tax_rates, true)); $item_subtotal_tax += $line_tax; } break; } if (!empty($this->tax_rates)) { foreach ($this->tax_rates as $rate_id => $rate) { $line_taxes[$rate->tax_rate_id] = $line_tax; break; } } } $variation = array(); $product_item = new PMXI_Post_Record(); $product_item->getBy(array('import_id' => $this->import->id, 'post_id' => $order_id, 'unique_key' => 'manual-line-item-' . $productIndex . '-' . $productItem['sku'])); if ($product_item->isEmpty()) { $item_id = wc_add_order_item($order_id, array('order_item_name' => $productItem['sku'], 'order_item_type' => 'line_item')); if (!$item_id) { $this->logger and call_user_func($this->logger, __('- <b>WARNING</b> Unable to create order line product.', 'wp_all_import_plugin')); } else { wc_add_order_item_meta($item_id, '_qty', wc_stock_amount($item_qty)); wc_add_order_item_meta($item_id, '_tax_class', ''); wc_add_order_item_meta($item_id, '_line_subtotal', wc_format_decimal($item_subtotal)); wc_add_order_item_meta($item_id, '_line_total', wc_format_decimal($item_subtotal)); wc_add_order_item_meta($item_id, '_line_subtotal_tax', wc_format_decimal($item_subtotal_tax)); wc_add_order_item_meta($item_id, '_line_tax', wc_format_decimal($item_subtotal_tax)); wc_add_order_item_meta($item_id, '_line_tax_data', array('total' => $line_taxes, 'subtotal' => array())); if (!empty($productItem['meta_name'])) { foreach ($productItem['meta_name'] as $key => $meta_name) { wc_add_order_item_meta($item_id, $meta_name, isset($productItem['meta_value'][$key]) ? $productItem['meta_value'][$key] : ''); } } $product_item->set(array('import_id' => $this->import->id, 'post_id' => $order_id, 'unique_key' => 'manual-line-item-' . $productIndex . '-' . $productItem['sku'], 'product_key' => 'manual-line-item-' . $item_id, 'iteration' => $this->import->iteration))->save(); } } else { $item_id = str_replace('manual-line-item-', '', $product_item->product_key); if (is_numeric($item_id)) { wc_update_order_item($item_id, array('order_item_name' => $productItem['sku'], 'order_item_type' => 'line_item')); wc_update_order_item_meta($item_id, '_qty', wc_stock_amount($item_qty)); wc_update_order_item_meta($item_id, '_tax_class', ''); wc_update_order_item_meta($item_id, '_line_subtotal', wc_format_decimal($item_subtotal)); wc_update_order_item_meta($item_id, '_line_total', wc_format_decimal($item_subtotal)); wc_update_order_item_meta($item_id, '_line_subtotal_tax', wc_format_decimal($item_subtotal_tax)); wc_update_order_item_meta($item_id, '_line_tax', wc_format_decimal($item_subtotal_tax)); wc_update_order_item_meta($item_id, '_line_tax_data', array('total' => $line_taxes, 'subtotal' => array())); if (!empty($productItem['meta_name'])) { foreach ($productItem['meta_name'] as $key => $meta_name) { wc_update_order_item_meta($item_id, $meta_name, isset($productItem['meta_value'][$key]) ? $productItem['meta_value'][$key] : ''); } } $product_item->set(array('iteration' => $this->import->iteration))->save(); } } } break; } return $is_product_founded; }
/** * Update shipping method on the subscription if the order changed anything * * @param WC_Order $order The new order * @param WC_Subscription $subscription The original subscription * @param WC_Cart $recurring_cart A recurring cart */ public static function update_shipping_methods($subscription, $recurring_cart) { // First, archive all the shipping methods foreach ($subscription->get_shipping_methods() as $shipping_method_id => $shipping_method) { wc_update_order_item($shipping_method_id, array('order_item_type' => 'shipping_switched')); } WC_Subscriptions_Checkout::add_shipping($subscription, $recurring_cart); }
/** * Update an order item * * @since 3.0.0 * @param \WC_Order $order WC_Order instance * @param int $order_item_id Order item ID to update * @param array $item Parsed item data from CSV * @param string $type Line item type * @return int|false ID of the updated order item, false on failure */ private function update_order_item(WC_Order $order, $order_item_id, $item, $type) { $result = false; switch ($type) { case 'line_item': $product = $this->get_product_for_item($item); $args = $this->prepare_product_args($item); $result = $order->update_product($order_item_id, $product, $args); if (!$result) { wc_csv_import_suite()->log(sprintf(__('> > Warning: cannot update order item %d.', 'woocommerce-csv-import-suite'), $order_item_id)); } break; case 'shipping': $args = array('order_item_name' => $item['method_title']); $result = wc_update_order_item($order_item_id, $args); if (!$result) { wc_csv_import_suite()->log(sprintf(__('> > Warning: cannot update shipping method "%s".', 'woocommerce-csv-import-suite'), esc_html($item['title']))); } break; case 'tax': $args = array('order_item_name' => $item['code']); $result = wc_update_order_item($order_item_id, $args); if (!$result) { wc_csv_import_suite()->log(sprintf(__('> > Warning: cannot update tax "%s".', 'woocommerce-csv-import-suite'), esc_html($item['label']))); } break; case 'coupon': $args = array('code' => $item['code'], 'discount_amount' => $item['amount']); $result = $order->update_coupon($order_item_id, $args); if (!$result) { wc_csv_import_suite()->log(sprintf(__('> > Warning: cannot merge coupon "%s".', 'woocommerce-csv-import-suite'), esc_html($item['code']))); } break; case 'fee': $args = array('name' => $item['title'], 'line_total' => $item['total'], 'line_tax' => $item['total_tax'], 'tax_class' => isset($item['tax_class']) ? $item['tax_class'] : ''); $result = $order->update_fee($order_item_id, $args); if (!$result) { wc_csv_import_suite()->log(sprintf(__('> > Warning: cannot merge fee "%s".', 'woocommerce-csv-import-suite'), esc_html($item['title']))); } break; } return $result; }
/** * Process the remove or re-add a line item from a subscription request. * * @since 2.0 */ public static function maybe_remove_or_add_item_to_subscription() { if (isset($_GET['subscription_id']) && (isset($_GET['remove_item']) || isset($_GET['undo_remove_item'])) && isset($_GET['_wpnonce'])) { $subscription = wcs_is_subscription($_GET['subscription_id']) ? wcs_get_subscription($_GET['subscription_id']) : false; $undo_request = isset($_GET['undo_remove_item']) ? true : false; $item_id = $undo_request ? $_GET['undo_remove_item'] : $_GET['remove_item']; if (false === $subscription) { wc_add_notice(sprintf(_x('Subscription #%d does not exist.', 'hash before subscription ID', 'woocommerce-subscriptions'), $_GET['subscription_id']), 'error'); wp_safe_redirect(wc_get_page_permalink('myaccount')); exit; } if (self::validate_remove_items_request($subscription, $item_id, $undo_request)) { if ($undo_request) { // handle undo request $removed_item = WC()->session->get('removed_subscription_items', array()); if (!empty($removed_item[$item_id]) && $subscription->id == $removed_item[$item_id]) { // restore the item wc_update_order_item($item_id, array('order_item_type' => 'line_item')); unset($removed_item[$item_id]); WC()->session->set('removed_subscription_items', $removed_item); // restore download permissions for this item $line_items = $subscription->get_items(); $line_item = $line_items[$item_id]; $_product = $subscription->get_product_from_item($line_item); $product_id = wcs_get_canonical_product_id($line_item); if ($_product && $_product->exists() && $_product->is_downloadable()) { $downloads = $_product->get_files(); foreach (array_keys($downloads) as $download_id) { wc_downloadable_file_permission($download_id, $product_id, $subscription, $line_item['qty']); } } // translators: 1$: product name, 2$: product id $subscription->add_order_note(sprintf(_x('Customer added "%1$s" (Product ID: #%2$d) via the My Account page.', 'used in order note', 'woocommerce-subscriptions'), wcs_get_line_item_name($line_item), $product_id)); } else { wc_add_notice(__('Your request to undo your previous action was unsuccessful.', 'woocommerce-subscriptions')); } } else { // handle remove item requests WC()->session->set('removed_subscription_items', array($item_id => $subscription->id)); // remove download access for the item $line_items = $subscription->get_items(); $line_item = $line_items[$item_id]; $product_id = wcs_get_canonical_product_id($line_item); WCS_Download_Handler::revoke_downloadable_file_permission($product_id, $subscription->id, $subscription->get_user_id()); // remove the line item from subscription but preserve its data in the DB wc_update_order_item($item_id, array('order_item_type' => 'line_item_removed')); // translators: 1$: product name, 2$: product id $subscription->add_order_note(sprintf(_x('Customer removed "%1$s" (Product ID: #%2$d) via the My Account page.', 'used in order note', 'woocommerce-subscriptions'), wcs_get_line_item_name($line_item), $product_id)); // translators: placeholders are 1$: item name, and, 2$: opening and, 3$: closing link tags wc_add_notice(sprintf(__('You have successfully removed "%1$s" from your subscription. %2$sUndo?%3$s', 'woocommerce-subscriptions'), $line_item['name'], '<a href="' . esc_url(self::get_undo_remove_url($subscription->id, $item_id, $subscription->get_view_order_url())) . '" >', '</a>')); } } $subscription->calculate_totals(); wp_safe_redirect($subscription->get_view_order_url()); exit; } }