/** * create_order function. * * @access public * @return void */ public function create_order() { global $woocommerce, $wpdb; // Give plugins the opportunity to create an order themselves $order_id = apply_filters('woocommerce_create_order', null, $this); if (is_numeric($order_id)) { return $order_id; } // Create Order (send cart variable so we can record items and reduce inventory). Only create if this is a new order, not if the payment was rejected. $order_data = apply_filters('woocommerce_new_order_data', array('post_type' => 'shop_order', 'post_title' => sprintf(__('Order – %s', 'woocommerce'), strftime(_x('%b %d, %Y @ %I:%M %p', 'Order date parsed by strftime', 'woocommerce'))), 'post_status' => 'publish', 'ping_status' => 'closed', 'post_excerpt' => isset($this->posted['order_comments']) ? $this->posted['order_comments'] : '', 'post_author' => 1, 'post_password' => uniqid('order_'))); // Insert or update the post data $create_new_order = true; if ($woocommerce->session->order_awaiting_payment > 0) { $order_id = absint($woocommerce->session->order_awaiting_payment); /* Check order is unpaid by getting its status */ $terms = wp_get_object_terms($order_id, 'shop_order_status', array('fields' => 'slugs')); $order_status = isset($terms[0]) ? $terms[0] : 'pending'; // Resume the unpaid order if its pending if ($order_status == 'pending' || $order_status == 'failed') { // Update the existing order as we are resuming it $create_new_order = false; $order_data['ID'] = $order_id; wp_update_post($order_data); // Clear the old line items - we'll add these again in case they changed $wpdb->query($wpdb->prepare("DELETE FROM {$wpdb->prefix}woocommerce_order_itemmeta WHERE order_item_id IN ( SELECT order_item_id FROM {$wpdb->prefix}woocommerce_order_items WHERE order_id = %d )", $order_id)); $wpdb->query($wpdb->prepare("DELETE FROM {$wpdb->prefix}woocommerce_order_items WHERE order_id = %d", $order_id)); // Trigger an action for the resumed order do_action('woocommerce_resume_order', $order_id); } } if ($create_new_order) { $order_id = wp_insert_post($order_data); if (is_wp_error($order_id)) { throw new MyException('Error: Unable to create order. Please try again.'); } else { do_action('woocommerce_new_order', $order_id); } } // Store user data if ($this->checkout_fields['billing']) { foreach ($this->checkout_fields['billing'] as $key => $field) { update_post_meta($order_id, '_' . $key, $this->posted[$key]); // User if ($this->customer_id && !empty($this->posted[$key])) { update_user_meta($this->customer_id, $key, $this->posted[$key]); // Special fields switch ($key) { case "billing_email": if (!email_exists($this->posted[$key])) { wp_update_user(array('ID' => $this->customer_id, 'user_email' => $this->posted[$key])); } break; case "billing_first_name": wp_update_user(array('ID' => $this->customer_id, 'first_name' => $this->posted[$key])); break; case "billing_last_name": wp_update_user(array('ID' => $this->customer_id, 'last_name' => $this->posted[$key])); break; } } } } if ($this->checkout_fields['shipping'] && ($woocommerce->cart->needs_shipping() || get_option('woocommerce_require_shipping_address') == 'yes')) { foreach ($this->checkout_fields['shipping'] as $key => $field) { $postvalue = false; if ($this->posted['shiptobilling']) { if (isset($this->posted[str_replace('shipping_', 'billing_', $key)])) { $postvalue = $this->posted[str_replace('shipping_', 'billing_', $key)]; update_post_meta($order_id, '_' . $key, $postvalue); } } else { $postvalue = $this->posted[$key]; update_post_meta($order_id, '_' . $key, $postvalue); } // User if ($postvalue && $this->customer_id) { update_user_meta($this->customer_id, $key, $postvalue); } } } // Save any other user meta if ($this->customer_id) { do_action('woocommerce_checkout_update_user_meta', $this->customer_id, $this->posted); } // Store the line items to the new/resumed order foreach ($woocommerce->cart->get_cart() as $cart_item_key => $values) { $_product = $values['data']; // Add line item $item_id = woocommerce_add_order_item($order_id, array('order_item_name' => $_product->get_title(), 'order_item_type' => 'line_item')); // Add line item meta if ($item_id) { woocommerce_add_order_item_meta($item_id, '_qty', apply_filters('woocommerce_stock_amount', $values['quantity'])); woocommerce_add_order_item_meta($item_id, '_tax_class', $_product->get_tax_class()); woocommerce_add_order_item_meta($item_id, '_product_id', $values['product_id']); woocommerce_add_order_item_meta($item_id, '_variation_id', $values['variation_id']); woocommerce_add_order_item_meta($item_id, '_line_subtotal', woocommerce_format_decimal($values['line_subtotal'], 4)); woocommerce_add_order_item_meta($item_id, '_line_total', woocommerce_format_decimal($values['line_total'], 4)); woocommerce_add_order_item_meta($item_id, '_line_tax', woocommerce_format_decimal($values['line_tax'], 4)); woocommerce_add_order_item_meta($item_id, '_line_subtotal_tax', woocommerce_format_decimal($values['line_subtotal_tax'], 4)); // Store variation data in meta so admin can view it if ($values['variation'] && is_array($values['variation'])) { foreach ($values['variation'] as $key => $value) { woocommerce_add_order_item_meta($item_id, esc_attr(str_replace('attribute_', '', $key)), $value); } } // Add line item meta for backorder status if ($_product->backorders_require_notification() && $_product->is_on_backorder($values['quantity'])) { woocommerce_add_order_item_meta($item_id, apply_filters('woocommerce_backordered_item_meta_name', __('Backordered', 'woocommerce'), $cart_item_key, $order_id), $values['quantity'] - max(0, $_product->get_total_stock())); } // Allow plugins to add order item meta do_action('woocommerce_add_order_item_meta', $item_id, $values); } } // Store fees foreach ($woocommerce->cart->get_fees() as $fee) { $item_id = woocommerce_add_order_item($order_id, array('order_item_name' => $fee->name, 'order_item_type' => 'fee')); if ($fee->taxable) { woocommerce_add_order_item_meta($item_id, '_tax_class', $fee->tax_class); } else { woocommerce_add_order_item_meta($item_id, '_tax_class', '0'); } woocommerce_add_order_item_meta($item_id, '_line_total', woocommerce_format_decimal($fee->amount)); woocommerce_add_order_item_meta($item_id, '_line_tax', woocommerce_format_decimal($fee->tax)); } // Store tax rows foreach (array_keys($woocommerce->cart->taxes + $woocommerce->cart->shipping_taxes) as $key) { $item_id = woocommerce_add_order_item($order_id, array('order_item_name' => $woocommerce->cart->tax->get_rate_code($key), 'order_item_type' => 'tax')); // Add line item meta if ($item_id) { woocommerce_add_order_item_meta($item_id, 'rate_id', $key); woocommerce_add_order_item_meta($item_id, 'label', $woocommerce->cart->tax->get_rate_label($key)); woocommerce_add_order_item_meta($item_id, 'compound', absint($woocommerce->cart->tax->is_compound($key) ? 1 : 0)); woocommerce_add_order_item_meta($item_id, 'tax_amount', woocommerce_clean(isset($woocommerce->cart->taxes[$key]) ? $woocommerce->cart->taxes[$key] : 0)); woocommerce_add_order_item_meta($item_id, 'shipping_tax_amount', woocommerce_clean(isset($woocommerce->cart->shipping_taxes[$key]) ? $woocommerce->cart->shipping_taxes[$key] : 0)); } } // Store coupons if ($applied_coupons = $woocommerce->cart->get_applied_coupons()) { foreach ($applied_coupons as $code) { $item_id = woocommerce_add_order_item($order_id, array('order_item_name' => $code, 'order_item_type' => 'coupon')); // Add line item meta if ($item_id) { woocommerce_add_order_item_meta($item_id, 'discount_amount', isset($woocommerce->cart->coupon_discount_amounts[$code]) ? $woocommerce->cart->coupon_discount_amounts[$code] : 0); } } } // Store meta if ($this->shipping_method) { update_post_meta($order_id, '_shipping_method', $this->shipping_method->id); update_post_meta($order_id, '_shipping_method_title', $this->shipping_method->label); } if ($this->payment_method) { update_post_meta($order_id, '_payment_method', $this->payment_method->id); update_post_meta($order_id, '_payment_method_title', $this->payment_method->get_title()); } update_post_meta($order_id, '_order_shipping', woocommerce_format_total($woocommerce->cart->shipping_total)); update_post_meta($order_id, '_order_discount', woocommerce_format_total($woocommerce->cart->get_order_discount_total())); update_post_meta($order_id, '_cart_discount', woocommerce_format_total($woocommerce->cart->get_cart_discount_total())); update_post_meta($order_id, '_order_tax', woocommerce_clean($woocommerce->cart->tax_total)); update_post_meta($order_id, '_order_shipping_tax', woocommerce_clean($woocommerce->cart->shipping_tax_total)); update_post_meta($order_id, '_order_total', woocommerce_format_total($woocommerce->cart->total)); update_post_meta($order_id, '_order_key', apply_filters('woocommerce_generate_order_key', uniqid('order_'))); update_post_meta($order_id, '_customer_user', absint($this->customer_id)); update_post_meta($order_id, '_order_currency', get_woocommerce_currency()); update_post_meta($order_id, '_prices_include_tax', get_option('woocommerce_prices_include_tax')); update_post_meta($order_id, '_customer_ip_address', isset($_SERVER['HTTP_X_FORWARDED_FOR']) ? $_SERVER['HTTP_X_FORWARDED_FOR'] : $_SERVER['REMOTE_ADDR']); update_post_meta($order_id, '_customer_user_agent', isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : ''); // Let plugins add meta do_action('woocommerce_checkout_update_order_meta', $order_id, $this->posted); // Order status wp_set_object_terms($order_id, 'pending', 'shop_order_status'); return $order_id; }
$wpdb->query($wpdb->prepare("\r\n\t\t\t\tUPDATE {$wpdb->postmeta}\r\n\t\t\t\tSET meta_key = '_order_items_old'\r\n\t\t\t\tWHERE meta_key = '_order_items'\r\n\t\t\t\tAND post_id = %d\r\n\t\t\t", $order_item_row->post_id)); } unset($meta_rows, $item_id, $order_item); } } // Do the same kind of update for order_taxes - move to lines // Reverse with UPDATE `wpwc_postmeta` SET meta_key = '_order_taxes' WHERE meta_key = '_order_taxes_old' $order_tax_rows = $wpdb->get_results("\r\n\tSELECT * FROM {$wpdb->postmeta}\r\n\tWHERE meta_key = '_order_taxes'\r\n"); foreach ($order_tax_rows as $order_tax_row) { $order_taxes = (array) maybe_unserialize($order_tax_row->meta_value); if ($order_taxes) { foreach ($order_taxes as $order_tax) { if (!isset($order_tax['label']) || !isset($order_tax['cart_tax']) || !isset($order_tax['shipping_tax'])) { continue; } $item_id = woocommerce_add_order_item($order_tax_row->post_id, array('order_item_name' => $order_tax['label'], 'order_item_type' => 'tax')); // Add line item meta if ($item_id) { woocommerce_add_order_item_meta($item_id, 'compound', absint(isset($order_tax['compound']) ? $order_tax['compound'] : 0)); woocommerce_add_order_item_meta($item_id, 'tax_amount', woocommerce_clean($order_tax['cart_tax'])); woocommerce_add_order_item_meta($item_id, 'shipping_tax_amount', woocommerce_clean($order_tax['shipping_tax'])); } // Delete from DB (rename) $wpdb->query($wpdb->prepare("\r\n\t\t\t\tUPDATE {$wpdb->postmeta}\r\n\t\t\t\tSET meta_key = '_order_taxes_old'\r\n\t\t\t\tWHERE meta_key = '_order_taxes'\r\n\t\t\t\tAND post_id = %d\r\n\t\t\t", $order_tax_row->post_id)); unset($tax_amount); } } } // Grab the pre 2.0 Image options and use to populate the new image options settings, // cleaning up afterwards like nice people do foreach (array('catalog', 'single', 'thumbnail') as $value) {
function woocommerce_etsyi_submenu_page_callback() { global $wpdb, $oscdb, $import_cat_counter, $import_prod_counter; if (!empty($_POST)) { $oscdb = new wpdb(trim($_POST['store_user']), trim($_POST['store_pass']), trim($_POST['store_dbname']), trim($_POST['store_host'])); if ($oscdb->ready) { echo '<p>Starting...<em>(If the page stops loading or shows a timeout error, then just refresh the page and the importer will continue where it left off. If you are using a shared server and are importing a lot of products you may need to refresh several times)</p>'; // Do customer import if ($_POST['dtype']['customers'] == 1) { $country_data = $oscdb->get_results("SELECT * FROM countries", ARRAY_A); $countries_id = array(); foreach ($country_data as $cdata) { $countries_id[$cdata['countries_id']] = $cdata; } $zones = array(); $zone_data = $oscdb->get_results("SELECT zone_id, zone_code FROM zones", ARRAY_A); foreach ($zone_data as $z) { $zones[$z['zone_id']] = $z['zone_code']; } if ($customers = $oscdb->get_results("SELECT c.customers_id, c.customers_firstname, c.customers_lastname, c.customers_telephone, c.customers_email_address, ab.entry_country_id, ab.entry_lastname, ab.entry_firstname, ab.entry_street_address, ab.entry_suburb, ab.entry_postcode, ab.entry_city, ab.entry_state, ab.entry_zone_id FROM customers c, address_book ab WHERE c.customers_id=ab.customers_id AND c.customers_default_address_id=ab.address_book_id", ARRAY_A)) { foreach ($customers as $customer) { if (!email_exists($customer['customers_email_address'])) { $original = strtolower(preg_replace("/[^A-Za-z0-9]/", '', $customer['customers_firstname'] . $customer['customers_lastname'])); $user_name = $original; $i = 1; while ($user_id = username_exists($user_name)) { $user_name = $original . $i; $i++; } $random_password = wp_generate_password(); $user_id = wp_create_user($user_name, $random_password, $customer['customers_email_address']); $data = array('first_name' => $customer['customers_firstname'], 'last_name' => $customer['customers_lastname'], 'billing_country' => $countries_id[$customer['entry_country_id']]['countries_iso_code_2'], 'billing_first_name' => $customer['entry_firstname'], 'billing_last_name' => $customer['entry_lastname'], 'billing_address_1' => $customer['entry_street_address'], 'billing_address_2' => $customer['entry_suburb'], 'billing_city' => $customer['entry_city'], 'billing_state' => $customer['entry_state'] != '' ? $customer['entry_state'] : $zones[$customer['entry_zone_id']], 'billing_postcode' => $customer['entry_postcode'], 'billing_email' => $customer['customers_email_address'], 'billing_phone' => $customer['customers_telephone'], 'shipping_country' => $countries_id[$customer['entry_country_id']]['countries_iso_code_2'], 'shipping_first_name' => $customer['entry_firstname'], 'shipping_last_name' => $customer['entry_lastname'], 'shipping_address_1' => $customer['entry_street_address'], 'shipping_address_2' => $customer['entry_suburb'], 'shipping_city' => $customer['entry_city'], 'shipping_state' => $customer['entry_state'] != '' ? $customer['entry_state'] : $zones[$customer['entry_zone_id']], 'shipping_postcode' => $customer['entry_postcode'], 'osc_id' => $customer['customers_id']); foreach ($data as $k => $v) { update_user_meta($user_id, $k, $v); } if ($user_id > 1) { wp_update_user(array('ID' => $user_id, 'role' => 'customer')); } $import_customer_counter++; } } } } if ($_POST['dtype']['products'] == 1) { woocommerce_osc_run_cats(); // Get all categories by OSC cat ID $categories = array(); $terms = get_terms('product_cat', array('hide_empty' => 0)); foreach ($terms as $term) { $o = get_woocommerce_term_meta($term->term_id, 'osc_id', true); $categories[$o] = (int) $term->term_id; } // Import the products if ($products = $oscdb->get_results("SELECT p.*, pd.*, p2c.categories_id FROM products p, products_description pd, products_to_categories p2c WHERE p.products_id=pd.products_id AND pd.language_id=1 AND p.products_id=p2c.products_id GROUP BY p.products_id", ARRAY_A)) { foreach ($products as $product) { $existing_product = get_posts(array('post_type' => 'product', 'posts_per_page' => 1, 'post_status' => 'any', 'meta_query' => array(array('key' => 'osc_id', 'value' => $product['products_id'])))); if (empty($existing_product)) { $product_id = wp_insert_post(array('post_title' => $product['products_name'], 'post_content' => $product['products_description'], 'post_status' => 'publish', 'post_type' => 'product', 'post_author' => 1)); update_post_meta($product_id, 'osc_id', $product['products_id']); wp_set_object_terms($product_id, 'simple', 'product_type'); wp_set_object_terms($product_id, (int) $categories[$product['categories_id']], 'product_cat'); update_post_meta($product_id, '_sku', $product['products_model']); update_post_meta($product_id, '_regular_price', $product['products_price']); update_post_meta($product_id, '_price', $product['products_price']); update_post_meta($product_id, '_visibility', 'visible'); update_post_meta($product_id, '_stock_status', $product['products_status'] ? 'instock' : 'outofstock'); update_post_meta($product_id, '_manage_stock', '1'); update_post_meta($product_id, '_stock', $product['products_quantity']); $import_prod_counter++; if ($special = $oscdb->get_row("SELECT specials_new_products_price, expires_date FROM specials WHERE status=1 AND products_id='" . $product_id . "' LIMIT 1", ARRAY_A)) { update_post_meta($product_id, '_sale_price', $special['specials_new_products_price']); $special['expires_date'] = strtotime($special['expires_date']); if ($special['expires_date'] > time()) { update_post_meta($product_id, '_sale_price_dates_to', date("Y-m-d", $special['expires_date'])); update_post_meta($product_id, '_sale_price_dates_from', date("Y-m-d")); } } $attach_id = 0; if ($product['products_image'] != '') { $url = rtrim($_POST['store_url'], '/') . '/images/' . urlencode($product['products_image']); $attach_id = woocommerce_osc_import_image($url); } if ($attach_id > 0) { set_post_thumbnail($product_id, $attach_id); } // Handle attributes if ($attributes = $oscdb->get_results("SELECT po.products_options_name, pov.products_options_values_name FROM products_attributes pa, products_options po, products_options_values pov WHERE pa.products_id='" . $product['products_id'] . "' AND pov.products_options_values_id = pa.options_values_id AND pov.language_id=po.language_id AND po.language_id=1 AND pa.options_id=products_options_id", ARRAY_A)) { wp_set_object_terms($product_id, 'variable', 'product_type'); $attrib_array = array(); $attrib_combo = array(); $max_price = $product['products_price']; $min_price = $product['products_price']; foreach ($attributes as $attribute) { $slug = sanitize_title($attribute['products_options_name']); $attrib_array[$slug] = array('name' => $attribute['products_options_name'], 'value' => ltrim($attrib_array[$slug]['value'] . ' | ' . $attribute['products_options_values_name'], ' | '), 'position' => 0, 'is_visible' => 1, 'is_variation' => 1, 'is_taxonomy' => 0); $attrib_combo[$slug][] = array($attribute['products_options_values_name'], ($attribute['price_prefix'] == '-' ? '-' : '') . $attribute['options_values_price']); } // Now it gets tricky... $combos = woocommerce_osc_cartesian_product($attrib_combo); foreach ($combos as $combo) { $variation_id = wp_insert_post(array('post_title' => 'Product ' . $product_id . ' Variation', 'post_content' => '', 'post_status' => 'publish', 'post_type' => 'product_variation', 'post_author' => 1, 'post_parent' => $product_id)); $opt_price = $product['products_price']; $special_price = $special['specials_new_products_price']; foreach ($combo as $k => $v) { update_post_meta($variation_id, 'attribute_' . $k, $v[0]); $opt_price += $v[1]; $special_price += $v[1]; } update_post_meta($variation_id, '_sku', $product['products_model']); update_post_meta($variation_id, '_regular_price', $opt_price); update_post_meta($variation_id, '_price', $opt_price); update_post_meta($variation_id, '_thumbnail_id', 0); update_post_meta($variation_id, '_stock', $product['products_quantity']); if ($special) { update_post_meta($variation_id, '_sale_price', $special_price); if ($special['expires_date'] > time()) { update_post_meta($variation_id, '_sale_price_dates_to', date("Y-m-d", $special['expires_date'])); update_post_meta($variation_id, '_sale_price_dates_from', date("Y-m-d")); } } if ($opt_price > $max_price) { $max_price = $opt_price; } if ($opt_price < $min_price) { $min_price = $opt_price; } } update_post_meta($product_id, '_product_attributes', $attrib_array); update_post_meta($product_id, '_max_variation_regular_price', $max_price); update_post_meta($product_id, '_min_variation_regular_price', $min_price); update_post_meta($product_id, '_max_variation_price', $max_price); update_post_meta($product_id, '_min_variation_price', $min_price); } } } } } if ($_POST['dtype']['orders'] == 1) { $customers = $wpdb->get_results("SELECT ID FROM {$wpdb->users}", ARRAY_A); $customer_id = array(); foreach ($customers as $c) { $osc_id = get_user_meta($c['ID'], 'osc_id', true); $customer_id[$osc_id] = $c['ID']; } $product_id = array(); $products_query = $wpdb->get_results("SELECT ID FROM {$wpdb->posts} WHERE post_type='product'", ARRAY_A); foreach ($products_query as $p) { $osc_id = get_post_meta($p['ID'], 'osc_id', true); $product_id[$osc_id] = $p['ID']; } $country_data = $oscdb->get_results("SELECT * FROM countries", ARRAY_A); $countries_name = array(); foreach ($country_data as $cdata) { $countries_name[$cdata['countries_name']] = $cdata; } if ($orders = $oscdb->get_results("SELECT * FROM orders ORDER BY orders_id", ARRAY_A)) { foreach ($orders as $order) { $existing_order = get_posts(array('post_type' => 'shop_order', 'posts_per_page' => 1, 'post_status' => 'any', 'meta_query' => array(array('key' => 'osc_id', 'value' => $order['orders_id'])))); if (empty($existing_order)) { $totals = array(); if ($total_query = $oscdb->get_results("SELECT * FROM orders_total WHERE orders_id='" . $order['orders_id'] . "'", ARRAY_A)) { foreach ($total_query as $t) { $totals[$t['class']] = $t; } } $order_key = 'order_' . wp_generate_password(13); $data = array('post_type' => 'shop_order', 'post_date' => $order['date_purchased'], 'post_author' => $customer_id[$order['customers_id']], 'post_password' => $order_key, 'post_title' => 'Order – ' . date("M d, Y @ h:i A", strtotime($order['date_purchased'])), 'post_status' => 'publish'); $order_id = wp_insert_post($data); $billing_namebits = explode(' ', $order['billing_name']); $billing_firstname = $billing_namebits[0]; $billing_lastname = trim(str_replace($billing_namebits[0], '', $order['billing_name'])); $shipping_namebits = explode(' ', $order['delivery_name']); $shipping_firstname = $shipping_namebits[0]; $shipping_lastname = trim(str_replace($shipping_namebits[0], '', $order['delivery_name'])); $meta_data = array('_billing_address_1' => $order['billing_street_address'], '_billing_address_2' => $order['billing_suburb'], '_wpas_done_all' => 1, '_billing_country' => $countries_name[$order['billing_country']]['countries_iso_code_2'], '_billing_first_name' => $billing_firstname, '_billing_last_name' => $billing_lastname, '_billing_company' => $order['billing_company'], '_billing_city' => $order['billing_city'], '_billing_state' => $order['billing_state'], '_billing_postcode' => $order['billing_postcode'], '_billing_phone' => $order['customers_telephone'], '_billing_email' => $order['customers_email_address'], '_shipping_country' => $countries_name[$order['delivery_country']]['countries_iso_code_2'], '_shipping_first_name' => $shipping_firstname, '_shipping_last_name' => $shipping_lastname, '_shipping_company' => $order['delivery_company'], '_shipping_address_1' => $order['delivery_street_address'], '_shipping_address_2' => $order['delivery_suburb'], '_shipping_city' => $order['delivery_city'], '_shipping_state' => $order['delivery_state'], '_shipping_postcode' => $order['delivery_postcode'], '_shipping_method_title' => $totals['ot_shipping']['title'], '_payment_method_title' => $order['payment_method'], '_order_shipping' => $totals['ot_shipping']['value'], '_order_discount' => $totals['ot_coupon']['value'] + $totals['ot_discount']['value'], '_order_tax' => $totals['ot_tax']['value'], '_order_shipping_tax' => 0, '_order_total' => $totals['ot_total']['value'], '_order_key' => $order_key, '_customer_user' => $customer_id[$order['customers_id']], '_order_currency' => $order['currency'], '_prices_include_tax' => 'no', 'osc_id' => $order['orders_id']); foreach ($meta_data as $k => $v) { update_post_meta($order_id, $k, $v); } $order_import_counter++; if ($order_products = $oscdb->get_results("SELECT * FROM orders_products WHERE orders_id='" . $order['orders_id'] . "'", ARRAY_A)) { foreach ($order_products as $product) { $item_id = woocommerce_add_order_item($order_id, array('order_item_name' => $product['products_name'], 'order_item_type' => 'line_item')); if ($item_id) { $item_meta = array('_qty' => $product['products_quantity'], '_product_id' => $product_id[$product['products_id']], '_line_subtotal' => $product['final_price'] * $product['products_quantity'], '_line_total' => $product['final_price'] * $product['products_quantity']); foreach ($item_meta as $k => $v) { woocommerce_add_order_item_meta($item_id, $k, $v); } } } } } } } } if ($_POST['dtype']['pages'] == 1) { $page_import_counter = 0; if ($information_table = $oscdb->get_results("SHOW TABLES LIKE 'information'", ARRAY_A)) { if ($information_pages = $oscdb->get_results("SELECT * FROM information WHERE language_id=1", ARRAY_A)) { foreach ($information_pages as $information) { $existing_page = $wpdb->get_results("SELECT ID FROM {$wpdb->posts} WHERE post_type='page' AND LOWER(post_title)='" . strtolower(esc_sql($information['information_title'])) . "'", ARRAY_A); if (!$existing_page) { $existing_page = get_posts(array('post_type' => 'page', 'posts_per_page' => 1, 'post_status' => 'any', 'meta_query' => array(array('key' => 'osc_id', 'value' => $information['information_id'])))); if (!$existing_page) { $data = array('post_type' => 'page', 'post_title' => $information['information_title'], 'post_content' => $information['information_description'], 'post_status' => 'publish'); $page_id = wp_insert_post($data); update_post_meta($page_id, 'osc_id', $information['information_id']); $page_import_counter++; } } } } } else { echo '<p class="notice">The information (pages) table does not exist in this osCommerce installation.</p>'; } } $success = true; } else { echo '<p class="notice">Could not connect to the osCommerce database</p>'; } } if ($success) { echo '<h3>The oscommerce data was successfully imported</h3>'; if ($_POST['dtype']['customers'] == 1) { echo '<p><strong>Customers Imported: ' . $import_customer_counter . '</p>'; } if ($_POST['dtype']['orders'] == 1) { echo '<p><strong>Orders Imported: ' . $order_import_counter . '</p>'; } if ($_POST['dtype']['products'] == 1) { echo '<p><strong>Categories Imported: ' . $import_cat_counter . '</p>'; echo '<p><strong>Products Imported: ' . $import_prod_counter . '</p>'; } if ($_POST['dtype']['pages'] == 1) { echo '<p><strong>Pages Imported: ' . $page_import_counter . '</p>'; } } else { ?> <form action="<?php echo $_SERVER['REQUEST_URI']; ?> " method="post"> <h3>Import data from osCommerce</h3> <p> Enter your oscommerce database information (you will need remote access to your oscommerce database) </p> <p> <label>osCommerce store URL: <input type="text" name="store_url" value="<?php echo $_POST['store_url']; ?> "></label> </p> <p> <label>osCommerce Database Host: <input type="text" name="store_host" value="localhost"></label></p> <p> <label>osCommerce Database User: <input type="text" name="store_user" value="<?php echo $_POST['store_user']; ?> "></label> </p> <p> <label>osCommerce Database Password: <input type="text" name="store_pass" value="<?php echo $_POST['store_pass']; ?> "></label> </p> <p> <label>osCommerce Database Name: <input type="text" name="store_dbname" value="<?php echo $_POST['store_dbname']; ?> "></label> </p> <p> Data to Import:<br> <label><input type="checkbox" name="dtype[customers]" value="1"> Customers (passwords will not be transferred)</label> <br> <label><input type="checkbox" name="dtype[orders]" value="1"> Orders</label> <br> <label><input type="checkbox" name="dtype[products]" value="1"> Categories/Products</label> <br> <label><input type="checkbox" name="dtype[pages]" value="1"> Information Pages</label> </p> <p> <input type="submit" value="Import Data" class="button button-primary button-large"> </p> </form> <?php } }
/** * woocommerce_add_line_tax function. * * @access public * @return void */ function woocommerce_add_line_tax() { global $woocommerce, $wpdb; check_ajax_referer('calc-totals', 'security'); $order_id = absint($_POST['order_id']); $order = new WC_Order($order_id); // Get tax rates $rates = $wpdb->get_results("SELECT tax_rate_id, tax_rate_country, tax_rate_state, tax_rate_name, tax_rate_priority FROM {$wpdb->prefix}woocommerce_tax_rates ORDER BY tax_rate_name"); $tax_codes = array(); foreach ($rates as $rate) { $code = array(); $code[] = $rate->tax_rate_country; $code[] = $rate->tax_rate_state; $code[] = $rate->tax_rate_name ? sanitize_title($rate->tax_rate_name) : 'TAX'; $code[] = absint($rate->tax_rate_priority); $tax_codes[$rate->tax_rate_id] = strtoupper(implode('-', array_filter($code))); } // Add line item $item_id = woocommerce_add_order_item($order_id, array('order_item_name' => '', 'order_item_type' => 'tax')); // Add line item meta if ($item_id) { woocommerce_add_order_item_meta($item_id, 'rate_id', ''); woocommerce_add_order_item_meta($item_id, 'label', ''); woocommerce_add_order_item_meta($item_id, 'compound', ''); woocommerce_add_order_item_meta($item_id, 'tax_amount', ''); woocommerce_add_order_item_meta($item_id, 'shipping_tax_amount', ''); } include 'admin/post-types/writepanels/order-tax-html.php'; // Quit out die; }
/** * Creates a new order for renewing a subscription product based on the details of a previous order. * * No trial periods or sign up fees are applied to the renewal order. However, if the order has failed * payments and the store manager has set failed payments to be added to renewal orders, then the * orders totals will be set to include the outstanding balance. * * If the $args['new_order_role'] flag is set to 'parent', then the renewal order will supersede the existing * order. The existing order and subscription associated with it will be cancelled. A new order and * subscription will be created. * * If the $args['new_order_role'] flag is 'child', the $original_order will remain the master order for the * subscription and the new order is just for accepting a recurring payment on the subscription. * * Renewal orders have the same meta data as the original order. If the renewal order is set to be a 'child' * then any subscription related meta data will not be stored on the new order. This is to keep subscription * meta data associated only with the one master order for the subscription. * * @param WC_Order|int $order The WC_Order object or ID of the order for which the a new order should be created. * @param string $product_id The ID of the subscription product in the order which needs to be added to the new order. * @param array $args (optional) An array of name => value flags: * 'new_order_role' string A flag to indicate whether the new order should become the master order for the subscription. Accepts either 'parent' or 'child'. Defaults to 'parent' - replace the existing order. * 'checkout_renewal' bool Indicates if invoked from an interactive cart/checkout session. Default false. * 'failed_order_id' int For checkout_renewal true, indicates order id being replaced * @since 1.2 */ public static function generate_renewal_order($original_order, $product_id, $args = array()) { global $wpdb, $woocommerce; if (!is_object($original_order)) { $original_order = new WC_Order($original_order); } if (!WC_Subscriptions_Order::order_contains_subscription($original_order) || !WC_Subscriptions_Order::is_item_subscription($original_order, $product_id)) { return false; } if (self::is_renewal($original_order, array('order_role' => 'child'))) { $original_order = self::get_parent_order($original_order); } if (!is_array($args)) { _deprecated_argument(__CLASS__ . '::' . __FUNCTION__, '1.3', __('Third parameter is now an array of name => value pairs. Use array( "new_order_role" => "parent" ) instead.', WC_Subscriptions::$text_domain)); $args = array('new_order_role' => $args); } $args = wp_parse_args($args, array('new_order_role' => 'parent', 'checkout_renewal' => false)); $renewal_order_key = uniqid('order_'); // Create the new order $renewal_order_data = array('post_type' => 'shop_order', 'post_title' => sprintf(__('Subscription Renewal Order – %s', WC_Subscriptions::$text_domain), strftime(_x('%b %d, %Y @ %I:%M %p', 'Order date parsed by strftime', WC_Subscriptions::$text_domain))), 'post_status' => 'publish', 'ping_status' => 'closed', 'post_excerpt' => $original_order->customer_note, 'post_author' => 1, 'post_password' => $renewal_order_key); $create_new_order = true; if ('child' == $args['new_order_role']) { $renewal_order_data['post_parent'] = $original_order->id; } if (true === $args['checkout_renewal']) { $renewal_order_id = null; if ($woocommerce->session->order_awaiting_payment > 0) { $renewal_order_id = absint($woocommerce->session->order_awaiting_payment); } elseif (isset($args['failed_order_id'])) { $failed_order_id = $args['failed_order_id']; /* Check order is unpaid by getting its status */ $terms = wp_get_object_terms($failed_order_id, 'shop_order_status', array('fields' => 'slugs')); $order_status = isset($terms[0]) ? $terms[0] : 'pending'; /* If paying on a pending order, we are resuming */ if ($order_status == 'pending') { $renewal_order_id = $failed_order_id; } } if ($renewal_order_id) { /* Check order is unpaid by getting its status */ $terms = wp_get_object_terms($renewal_order_id, 'shop_order_status', array('fields' => 'slugs')); $order_status = isset($terms[0]) ? $terms[0] : 'pending'; // Resume the unpaid order if its pending if ($order_status == 'pending' || $order_status == 'failed') { // Update the existing order as we are resuming it $create_new_order = false; $renewal_order_data['ID'] = $renewal_order_id; wp_update_post($renewal_order_data); // Clear the old line items - we'll add these again in case they changed $wpdb->query($wpdb->prepare("DELETE FROM {$wpdb->prefix}woocommerce_order_itemmeta WHERE order_item_id IN ( SELECT order_item_id FROM {$wpdb->prefix}woocommerce_order_items WHERE order_id = %d )", $renewal_order_id)); $wpdb->query($wpdb->prepare("DELETE FROM {$wpdb->prefix}woocommerce_order_items WHERE order_id = %d", $renewal_order_id)); } } } if ($create_new_order) { $renewal_order_id = wp_insert_post($renewal_order_data); } // Set the order as pending wp_set_object_terms($renewal_order_id, 'pending', 'shop_order_status'); // Set a unique key for this order update_post_meta($renewal_order_id, '_order_key', $renewal_order_key); if (true === $args['checkout_renewal']) { $checkout_object = $woocommerce->checkout; $customer_id = $original_order->customer_user; // Save posted billing fields to both renewal and original order if ($checkout_object->checkout_fields['billing']) { foreach ($checkout_object->checkout_fields['billing'] as $key => $field) { update_post_meta($renewal_order_id, '_' . $key, $checkout_object->posted[$key]); update_post_meta($original_order->id, '_' . $key, $checkout_object->posted[$key]); // User if ($customer_id && !empty($checkout_object->posted[$key])) { update_user_meta($customer_id, $key, $checkout_object->posted[$key]); // Special fields switch ($key) { case "billing_email": if (!email_exists($checkout_object->posted[$key])) { wp_update_user(array('ID' => $customer_id, 'user_email' => $checkout_object->posted[$key])); } break; case "billing_first_name": wp_update_user(array('ID' => $customer_id, 'first_name' => $checkout_object->posted[$key])); break; case "billing_last_name": wp_update_user(array('ID' => $customer_id, 'last_name' => $checkout_object->posted[$key])); break; } } } } // Save posted shipping fields to both renewal and original order if ($checkout_object->checkout_fields['shipping'] && ($woocommerce->cart->needs_shipping() || get_option('woocommerce_require_shipping_address') == 'yes')) { foreach ($checkout_object->checkout_fields['shipping'] as $key => $field) { $postvalue = false; if ($checkout_object->posted['shiptobilling']) { if (isset($checkout_object->posted[str_replace('shipping_', 'billing_', $key)])) { $postvalue = $checkout_object->posted[str_replace('shipping_', 'billing_', $key)]; update_post_meta($renewal_order_id, '_' . $key, $postvalue); update_post_meta($original_order->id, '_' . $key, $postvalue); } } else { $postvalue = $checkout_object->posted[$key]; update_post_meta($renewal_order_id, '_' . $key, $postvalue); update_post_meta($original_order->id, '_' . $key, $postvalue); } // User if ($postvalue && $customer_id) { update_user_meta($customer_id, $key, $postvalue); } } } } $order_meta_query = "SELECT `meta_key`, `meta_value`\n\t\t\t\t\t\t\t FROM {$wpdb->postmeta}\n\t\t\t\t\t\t\t WHERE `post_id` = {$original_order->id}\n\t\t\t\t\t\t\t AND `meta_key` NOT IN ('_paid_date', '_completed_date', '_order_key', '_edit_lock', '_original_order')"; // Superseding existing order so don't carry over payment details if ('parent' == $args['new_order_role'] || true === $args['checkout_renewal']) { $order_meta_query .= " AND `meta_key` NOT IN ('_payment_method', '_payment_method_title', '_recurring_payment_method', '_recurring_payment_method_title', '_shipping_method', '_shipping_method_title', '_recurring_shipping_method', '_recurring_shipping_method_title')"; } else { $order_meta_query .= " AND `meta_key` NOT LIKE '_order_recurring_%' AND `meta_key` NOT IN ('_payment_method', '_payment_method_title', '_recurring_payment_method', '_recurring_payment_method_title', '_shipping_method', '_shipping_method_title', '_recurring_shipping_method', '_recurring_shipping_method_title')"; } // Allow extensions to add/remove order meta $order_meta_query = apply_filters('woocommerce_subscriptions_renewal_order_meta_query', $order_meta_query, $original_order->id, $renewal_order_id, $args['new_order_role']); // Carry all the required meta from the old order over to the new order $order_meta = $wpdb->get_results($order_meta_query, 'ARRAY_A'); $order_meta = apply_filters('woocommerce_subscriptions_renewal_order_meta', $order_meta, $original_order->id, $renewal_order_id, $args['new_order_role']); foreach ($order_meta as $meta_item) { add_post_meta($renewal_order_id, $meta_item['meta_key'], maybe_unserialize($meta_item['meta_value']), true); } $outstanding_balance = WC_Subscriptions_Order::get_outstanding_balance($original_order, $product_id); if (true === $args['checkout_renewal']) { $failed_payment_multiplier = 1; update_post_meta($renewal_order_id, '_order_shipping', woocommerce_format_total($woocommerce->cart->shipping_total)); update_post_meta($renewal_order_id, '_order_discount', woocommerce_format_total($woocommerce->cart->get_order_discount_total())); update_post_meta($renewal_order_id, '_cart_discount', woocommerce_format_total($woocommerce->cart->get_cart_discount_total())); update_post_meta($renewal_order_id, '_order_tax', woocommerce_format_total($woocommerce->cart->tax_total)); update_post_meta($renewal_order_id, '_order_shipping_tax', woocommerce_format_total($woocommerce->cart->shipping_tax_total)); update_post_meta($renewal_order_id, '_order_total', woocommerce_format_total($woocommerce->cart->total)); update_post_meta($renewal_order_id, '_checkout_renewal', 'yes'); } else { // If there are outstanding payment amounts, add them to the order, otherwise set the order details to the values of the recurring totals if ($outstanding_balance > 0 && 'yes' == get_option(WC_Subscriptions_Admin::$option_prefix . '_add_outstanding_balance', 'no')) { $failed_payment_multiplier = WC_Subscriptions_Order::get_failed_payment_count($original_order, $product_id); } else { $failed_payment_multiplier = 1; } // Set order totals based on recurring totals from the original order $cart_discount = $failed_payment_multiplier * get_post_meta($original_order->id, '_order_recurring_discount_cart', true); $order_discount = $failed_payment_multiplier * get_post_meta($original_order->id, '_order_recurring_discount_total', true); $order_shipping_tax = $failed_payment_multiplier * get_post_meta($original_order->id, '_order_recurring_shipping_tax_total', true); $order_shipping = $failed_payment_multiplier * get_post_meta($original_order->id, '_order_recurring_shipping_total', true); $order_tax = $failed_payment_multiplier * get_post_meta($original_order->id, '_order_recurring_tax_total', true); $order_total = $failed_payment_multiplier * get_post_meta($original_order->id, '_order_recurring_total', true); update_post_meta($renewal_order_id, '_cart_discount', $cart_discount); update_post_meta($renewal_order_id, '_order_discount', $order_discount); update_post_meta($renewal_order_id, '_order_shipping_tax', $order_shipping_tax); update_post_meta($renewal_order_id, '_order_shipping', $order_shipping); update_post_meta($renewal_order_id, '_order_tax', $order_tax); update_post_meta($renewal_order_id, '_order_total', $order_total); update_post_meta($renewal_order_id, '_shipping_method', $original_order->recurring_shipping_method); update_post_meta($renewal_order_id, '_shipping_method_title', $original_order->recurring_shipping_method_title); // Apply the recurring shipping & payment methods to child renewal orders if ('child' == $args['new_order_role']) { update_post_meta($renewal_order_id, '_payment_method', $original_order->recurring_payment_method); update_post_meta($renewal_order_id, '_payment_method_title', $original_order->recurring_payment_method_title); } } // Set order taxes based on recurring taxes from the original order $recurring_order_taxes = WC_Subscriptions_Order::get_recurring_taxes($original_order); foreach ($recurring_order_taxes as $index => $recurring_order_tax) { if (function_exists('woocommerce_update_order_item_meta')) { // WC 2.0+ $item_ids = array(); $item_ids[] = woocommerce_add_order_item($renewal_order_id, array('order_item_name' => $recurring_order_tax['name'], 'order_item_type' => 'tax')); // Also set recurring taxes on parent renewal orders if ('parent' == $args['new_order_role']) { $item_ids[] = woocommerce_add_order_item($renewal_order_id, array('order_item_name' => $recurring_order_tax['name'], 'order_item_type' => 'recurring_tax')); } // Add line item meta foreach ($item_ids as $item_id) { woocommerce_add_order_item_meta($item_id, 'compound', absint(isset($recurring_order_tax['compound']) ? $recurring_order_tax['compound'] : 0)); woocommerce_add_order_item_meta($item_id, 'tax_amount', woocommerce_clean($failed_payment_multiplier * $recurring_order_tax['tax_amount'])); woocommerce_add_order_item_meta($item_id, 'shipping_tax_amount', woocommerce_clean($failed_payment_multiplier * $recurring_order_tax['shipping_tax_amount'])); if (isset($recurring_order_tax['rate_id'])) { woocommerce_add_order_item_meta($item_id, 'rate_id', $recurring_order_tax['rate_id']); } if (isset($recurring_order_tax['label'])) { woocommerce_add_order_item_meta($item_id, 'label', $recurring_order_tax['label']); } } } else { // WC 1.x if (isset($recurring_order_tax['cart_tax']) && $recurring_order_tax['cart_tax'] > 0) { $recurring_order_taxes[$index]['cart_tax'] = $failed_payment_multiplier * $recurring_order_tax['cart_tax']; } else { $recurring_order_taxes[$index]['cart_tax'] = 0; } if (isset($recurring_order_tax['shipping_tax']) && $recurring_order_tax['shipping_tax'] > 0) { $recurring_order_taxes[$index]['shipping_tax'] = $failed_payment_multiplier * $recurring_order_tax['shipping_tax']; } else { $recurring_order_taxes[$index]['shipping_tax'] = 0; } // Inefficient but keeps WC 1.x code grouped together update_post_meta($renewal_order_id, '_order_taxes', $recurring_order_taxes); } } // Set line totals to be recurring line totals and remove the subscription/recurring related item meta from each order item $order_items = WC_Subscriptions_Order::get_recurring_items($original_order); // Allow extensions to add/remove items or item meta $order_items = apply_filters('woocommerce_subscriptions_renewal_order_items', $order_items, $original_order->id, $renewal_order_id, $product_id, $args['new_order_role']); foreach ($order_items as $item_index => $order_item) { $item_meta = new WC_Order_Item_Meta($order_item['item_meta']); // WC 2.0+ order item structure - as of WC 2.0 item_meta is stored as $key => meta pairs, not 'meta_name'/'meta_value' if (function_exists('woocommerce_add_order_item_meta')) { if ('child' == $args['new_order_role']) { $renewal_order_item_name = sprintf(__('Renewal of "%s" purchased in Order %s', WC_Subscriptions::$text_domain), $order_item['name'], $original_order->get_order_number()); } else { $renewal_order_item_name = $order_item['name']; } // Create order line item on the renewal order $recurring_item_id = woocommerce_add_order_item($renewal_order_id, array('order_item_name' => $renewal_order_item_name, 'order_item_type' => 'line_item')); // Remove recurring line items and set item totals based on recurring line totals foreach ($item_meta->meta as $meta_key => $meta) { // $meta is an array, so the item needs to be extracted from $meta[0] (just like order meta on a WC Order) $meta_value = $meta[0]; // Map line item totals based on recurring line totals switch ($meta_key) { case '_recurring_line_total': woocommerce_delete_order_item_meta($recurring_item_id, '_line_total'); woocommerce_add_order_item_meta($recurring_item_id, '_line_total', woocommerce_format_decimal($failed_payment_multiplier * $meta_value)); break; case '_recurring_line_tax': woocommerce_delete_order_item_meta($recurring_item_id, '_line_tax'); woocommerce_add_order_item_meta($recurring_item_id, '_line_tax', woocommerce_format_decimal($failed_payment_multiplier * $meta_value)); break; case '_recurring_line_subtotal': woocommerce_delete_order_item_meta($recurring_item_id, '_line_subtotal'); woocommerce_add_order_item_meta($recurring_item_id, '_line_subtotal', woocommerce_format_decimal($failed_payment_multiplier * $meta_value)); break; case '_recurring_line_subtotal_tax': woocommerce_delete_order_item_meta($recurring_item_id, '_line_subtotal_tax'); woocommerce_add_order_item_meta($recurring_item_id, '_line_subtotal_tax', woocommerce_format_decimal($failed_payment_multiplier * $meta_value)); break; default: break; } // Copy over line item meta data, with some parent/child role based exceptions for recurring amounts $copy_to_renewal_item = true; switch ($meta_key) { case '_recurring_line_total': case '_recurring_line_tax': case '_recurring_line_subtotal': case '_recurring_line_subtotal_tax': case '_subscription_recurring_amount': case '_subscription_sign_up_fee': case '_subscription_period': case '_subscription_interval': case '_subscription_length': case '_subscription_trial_period': case '_subscription_end_date': case '_subscription_expiry_date': case '_subscription_start_date': case '_subscription_status': case '_subscription_completed_payments': if ('child' == $args['new_order_role']) { $copy_to_renewal_item = false; } break; case '_subscription_trial_length': // We never want to duplicate free trials on renewal orders $copy_to_renewal_item = false; break; case '_subscription_suspension_count': // We want to reset some values for the new order // We want to reset some values for the new order case '_subscription_trial_expiry_date': case '_subscription_failed_payments': $copy_to_renewal_item = false; $meta_value = 0; break; default: break; } // Copy existing item over to new recurring order item if ($copy_to_renewal_item) { woocommerce_add_order_item_meta($recurring_item_id, $meta_key, $meta_value); } } } else { // WC 1.x order item structure foreach ($item_meta->meta as $meta_index => $meta_item) { switch ($meta_item['meta_name']) { case '_recurring_line_total': $order_items[$item_index]['line_total'] = $failed_payment_multiplier * $meta_item['meta_value']; case '_recurring_line_tax': $order_items[$item_index]['line_tax'] = $failed_payment_multiplier * $meta_item['meta_value']; case '_recurring_line_subtotal': $order_items[$item_index]['line_subtotal'] = $failed_payment_multiplier * $meta_item['meta_value']; case '_recurring_line_subtotal_tax': $order_items[$item_index]['line_subtotal_tax'] = $failed_payment_multiplier * $meta_item['meta_value']; case '_recurring_line_total': case '_recurring_line_tax': case '_recurring_line_subtotal': case '_recurring_line_subtotal_tax': case '_recurring_line_subtotal_tax': case '_subscription_recurring_amount': case '_subscription_sign_up_fee': case '_subscription_period': case '_subscription_interval': case '_subscription_length': case '_subscription_trial_length': case '_subscription_trial_period': if ('child' == $args['new_order_role']) { unset($item_meta->meta[$meta_index]); } break; case '_subscription_trial_length': // We never want to duplicate free trials on renewal orders if ('child' == $args['new_order_role']) { unset($item_meta->meta[$meta_index]); } else { $item_meta->meta[$meta_index] = 0; } break; } if ('child' == $args['new_order_role']) { $order_items[$item_index]['name'] = sprintf(__('Renewal of "%s" purchased in Order %s', WC_Subscriptions::$text_domain), $order_item['name'], $original_order->get_order_number()); } $order_items[$item_index]['item_meta'] = $item_meta->meta; } // Save the item meta on the new order update_post_meta($renewal_order_id, '_order_items', $order_items); } } // Keep a record of the original order's ID on the renewal order update_post_meta($renewal_order_id, '_original_order', $original_order->id, true); $renewal_order = new WC_Order($renewal_order_id); if ('parent' == $args['new_order_role']) { WC_Subscriptions_Manager::process_subscriptions_on_checkout($renewal_order_id); $original_order->add_order_note(sprintf(__('Order superseded by Renewal Order %s.', WC_Subscriptions::$text_domain), $renewal_order->get_order_number())); } do_action('woocommerce_subscriptions_renewal_order_created', $renewal_order, $original_order, $product_id, $args['new_order_role']); return apply_filters('woocommerce_subscriptions_renewal_order_id', $renewal_order_id, $original_order, $product_id, $args['new_order_role']); }
/** * Output the form */ public function output() { $this->errors = array(); $step = 1; try { if (!empty($_POST) && !check_admin_referer('create_booking_notification')) { throw new Exception(__('Error - please try again', 'woocommerce-bookings')); } if (!empty($_POST['create_booking'])) { $customer_id = absint($_POST['customer_id']); $bookable_product_id = absint($_POST['bookable_product_id']); $booking_order = wc_clean($_POST['booking_order']); if (!$bookable_product_id) { throw new Exception(__('Please choose a bookable product', 'woocommerce-bookings')); } if ($booking_order === 'existing') { $order_id = absint($_POST['booking_order_id']); $booking_order = $order_id; if (!$booking_order || get_post_type($booking_order) !== 'shop_order') { throw new Exception(__('Invalid order ID provided', 'woocommerce-bookings')); } } $step++; $product = get_product($bookable_product_id); $booking_form = new WC_Booking_Form($product); } elseif (!empty($_POST['create_booking_2'])) { $customer_id = absint($_POST['customer_id']); $bookable_product_id = absint($_POST['bookable_product_id']); $booking_order = wc_clean($_POST['booking_order']); $product = get_product($bookable_product_id); $booking_form = new WC_Booking_Form($product); $booking_data = $booking_form->get_posted_data($_POST); $booking_cost = ($cost = $booking_form->calculate_booking_cost($_POST)) && !is_wp_error($cost) ? number_format($cost, 2, '.', '') : 0; $create_order = false; if ('yes' === get_option('woocommerce_prices_include_tax')) { if (version_compare(WOOCOMMERCE_VERSION, '2.3', '<')) { $base_tax_rates = WC_Tax::get_shop_base_rate($product->tax_class); } else { $base_tax_rates = WC_Tax::get_base_tax_rates($product->tax_class); } $base_taxes = WC_Tax::calc_tax($booking_cost, $base_tax_rates, true); $booking_cost = round($booking_cost - array_sum($base_taxes), absint(get_option('woocommerce_price_num_decimals'))); } // Data to go into the booking $new_booking_data = array('user_id' => $customer_id, 'product_id' => $product->id, 'resource_id' => isset($booking_data['_resource_id']) ? $booking_data['_resource_id'] : '', 'persons' => $booking_data['_persons'], 'cost' => $booking_cost, 'start_date' => $booking_data['_start_date'], 'end_date' => $booking_data['_end_date'], 'all_day' => $booking_data['_all_day'] ? 1 : 0); // Create order if ($booking_order === 'new') { $create_order = true; $order_id = $this->create_order($booking_cost, $customer_id); if (!$order_id) { throw new Exception(__('Error: Could not create order', 'woocommerce-bookings')); } } elseif ($booking_order > 0) { $order_id = absint($booking_order); if (!$order_id || get_post_type($order_id) !== 'shop_order') { throw new Exception(__('Invalid order ID provided', 'woocommerce-bookings')); } $order = new WC_Order($order_id); update_post_meta($order_id, '_order_total', $order->get_total() + $booking_cost); update_post_meta($order_id, '_booking_order', '1'); } else { $order_id = 0; } if ($order_id) { $item_id = woocommerce_add_order_item($order_id, array('order_item_name' => $product->get_title(), 'order_item_type' => 'line_item')); if (!$item_id) { throw new Exception(__('Error: Could not create item', 'woocommerce-bookings')); } // Add line item meta woocommerce_add_order_item_meta($item_id, '_qty', 1); woocommerce_add_order_item_meta($item_id, '_tax_class', $product->get_tax_class()); woocommerce_add_order_item_meta($item_id, '_product_id', $product->id); woocommerce_add_order_item_meta($item_id, '_variation_id', ''); woocommerce_add_order_item_meta($item_id, '_line_subtotal', $booking_cost); woocommerce_add_order_item_meta($item_id, '_line_total', $booking_cost); woocommerce_add_order_item_meta($item_id, '_line_tax', 0); woocommerce_add_order_item_meta($item_id, '_line_subtotal_tax', 0); // We have an item id $new_booking_data['order_item_id'] = $item_id; // Add line item data foreach ($booking_data as $key => $value) { if (strpos($key, '_') !== 0) { woocommerce_add_order_item_meta($item_id, get_wc_booking_data_label($key, $product), $value); } } } // Create the booking itself $new_booking = get_wc_booking($new_booking_data); $new_booking->create($create_order ? 'unpaid' : 'pending-confirmation'); wp_safe_redirect(admin_url('post.php?post=' . ($create_order ? $order_id : $new_booking->id) . '&action=edit')); exit; } } catch (Exception $e) { $this->errors[] = $e->getMessage(); } switch ($step) { case 1: include 'views/html-create-booking-page.php'; break; case 2: include 'views/html-create-booking-page-2.php'; break; } }
/** * Create new orders based on the parsed data */ private function process_orders() { global $wpdb; $this->imported = $this->merged = 0; // peforming a dry run? $dry_run = isset($_POST['dry_run']) && $_POST['dry_run'] ? true : false; $this->log->add('---'); $this->log->add(__('Processing orders.', WC_Customer_CSV_Import_Suite::TEXT_DOMAIN)); foreach ($this->posts as $post) { // orders with custom order order numbers can be checked for existance, otherwise there's not much we can do if (!empty($post['order_number_formatted']) && isset($this->processed_posts[$post['order_number_formatted']])) { $this->skipped++; $this->log->add(sprintf(__('> Order %s already processed. Skipping.', WC_Customer_CSV_Import_Suite::TEXT_DOMAIN), $post['order_number_formatted']), true); continue; } // see class-wc-checkout.php for reference $order_data = array('post_date' => date('Y-m-d H:i:s', $post['date']), 'post_type' => 'shop_order', 'post_title' => 'Order – ' . date('F j, Y @ h:i A', $post['date']), 'post_status' => 'publish', 'ping_status' => 'closed', 'post_excerpt' => $post['order_comments'], 'post_author' => 1, 'post_password' => uniqid('order_')); if (!$dry_run) { // track whether download permissions need to be granted $add_download_permissions = false; $order_id = wp_insert_post($order_data); if (is_wp_error($order_id)) { $this->errored++; $this->log->add(sprintf(__('> Error inserting %s: %s', WC_Customer_CSV_Import_Suite::TEXT_DOMAIN), $post['order_number_formatted'], $order_id->get_error_message()), true); } // empty update to bump up the post_modified date to today's date (otherwise it would match the post_date, which isn't quite right) wp_update_post(array('ID' => $order_id)); // set order status wp_set_object_terms($order_id, $post['status'], 'shop_order_status'); // handle special meta fields update_post_meta($order_id, '_order_key', apply_filters('woocommerce_generate_order_key', uniqid('order_'))); update_post_meta($order_id, '_order_currency', get_woocommerce_currency()); // TODO: fine to use store default? if (!SV_WC_Plugin_Compatibility::is_wc_version_gte_2_1()) { update_post_meta($order_id, '_order_taxes', array()); // pre-2.1 } update_post_meta($order_id, '_prices_include_tax', get_option('woocommerce_prices_include_tax')); // add order postmeta foreach ($post['postmeta'] as $meta) { $meta_processed = false; // we don't set the "download permissions granted" meta, we call the woocommerce function to take care of this for us if (('Download Permissions Granted' == $meta['key'] || '_download_permissions_granted' == $meta['key']) && $meta['value']) { $add_download_permissions = true; $meta_processed = true; } if (!$meta_processed) { update_post_meta($order_id, $meta['key'], $meta['value']); } // set the paying customer flag on the user meta if applicable if ('_customer_user' == $meta['key'] && $meta['value'] && in_array($post['status'], array('processing', 'completed', 'refunded'))) { update_user_meta($meta['value'], "paying_customer", 1); } } // handle order items $order_items = array(); $order_item_meta = null; foreach ($post['order_items'] as $item) { $product = null; $variation_item_meta = array(); // if there's a product_id then we've already determined during parsing that this product exists if ($item['product_id']) { $product = get_product($item['product_id']); // handle variations if (($product->is_type('variable') || $product->is_type('variation') || $product->is_type('subscription_variation')) && method_exists($product, 'get_variation_id')) { foreach ($product->get_variation_attributes() as $key => $value) { $variation_item_meta[] = array('meta_name' => esc_attr(substr($key, 10)), 'meta_value' => $value); // remove the leading 'attribute_' from the name to get 'pa_color' for instance } } } // order item $order_items[] = array('order_item_name' => $product ? $product->get_title() : __('Unknown Product', WC_Customer_CSV_Import_Suite::TEXT_DOMAIN), 'order_item_type' => 'line_item'); // standard order item meta $_order_item_meta = array('_qty' => (int) $item['qty'], '_tax_class' => '', '_product_id' => $item['product_id'], '_variation_id' => $product && method_exists($product, 'get_variation_id') ? $product->get_variation_id() : 0, '_line_subtotal' => number_format((double) $item['total'], 2, '.', ''), '_line_subtotal_tax' => 0, '_line_total' => number_format((double) $item['total'], 2, '.', ''), '_line_tax' => 0); // add any product variation meta foreach ($variation_item_meta as $meta) { $_order_item_meta[$meta['meta_name']] = $meta['meta_value']; } // include any arbitrary order item meta $_order_item_meta = array_merge($_order_item_meta, $item['meta']); $order_item_meta[] = $_order_item_meta; } foreach ($order_items as $key => $order_item) { $order_item_id = woocommerce_add_order_item($order_id, $order_item); if ($order_item_id) { foreach ($order_item_meta[$key] as $meta_key => $meta_value) { if (strpos($meta_value, ':{i')) { $meta_value = unserialize(stripslashes($meta_value)); //'a:1:{i:0;s:19:"2014-05-01 08:00:00";}'; } woocommerce_add_order_item_meta($order_item_id, $meta_key, $meta_value); } } } // create the shipping order items (WC 2.1+) foreach ($post['order_shipping'] as $order_shipping) { $shipping_order_item = array('order_item_name' => $order_shipping['title'], 'order_item_type' => 'shipping'); $shipping_order_item_id = woocommerce_add_order_item($order_id, $shipping_order_item); if ($shipping_order_item_id) { woocommerce_add_order_item_meta($shipping_order_item_id, 'method_id', $order_shipping['method_id']); woocommerce_add_order_item_meta($shipping_order_item_id, 'cost', $order_shipping['cost']); } } // create the tax order items (WC 2.1+) foreach ($post['tax_items'] as $tax_item) { $tax_order_item = array('order_item_name' => $tax_item['title'], 'order_item_type' => 'tax'); $tax_order_item_id = woocommerce_add_order_item($order_id, $tax_order_item); if ($tax_order_item_id) { woocommerce_add_order_item_meta($tax_order_item_id, 'rate_id', $tax_item['rate_id']); woocommerce_add_order_item_meta($tax_order_item_id, 'label', $tax_item['label']); woocommerce_add_order_item_meta($tax_order_item_id, 'compound', $tax_item['compound']); woocommerce_add_order_item_meta($tax_order_item_id, 'tax_amount', $tax_item['tax_amount']); woocommerce_add_order_item_meta($tax_order_item_id, 'shipping_tax_amount', $tax_item['shipping_tax_amount']); } } // Grant downloadalbe product permissions if ($add_download_permissions) { woocommerce_downloadable_product_permissions($order_id); } // add order notes $order = new WC_Order($order_id); foreach ($post['notes'] as $order_note) { $order->add_order_note($order_note); } // record the product sales $order->record_product_sales(); } // ! dry run // was an original order number provided? if (!empty($post['order_number_formatted'])) { if (!$dry_run) { // do our best to provide some custom order number functionality while also allowing 3rd party plugins to provide their own custom order number facilities do_action('woocommerce_set_order_number', $order, $post['order_number'], $post['order_number_formatted']); $order->add_order_note(sprintf(__("Original order #%s", WC_Customer_CSV_Import_Suite::TEXT_DOMAIN), $post['order_number_formatted'])); // get the order so we can display the correct order number $order = new WC_Order($order_id); } $this->processed_posts[$post['order_number_formatted']] = $post['order_number_formatted']; } $this->imported++; $this->log->add(sprintf(__('> Finished importing order %s', WC_Customer_CSV_Import_Suite::TEXT_DOMAIN), $dry_run ? "" : $order->get_order_number())); } $this->log->add(__('Finished processing orders.', WC_Customer_CSV_Import_Suite::TEXT_DOMAIN)); unset($this->posts); }
/** * When a new order is inserted, add subscriptions related order meta. * * @since 1.0 */ public static function add_order_meta($order_id, $posted) { global $woocommerce; if (!WC_Subscriptions_Cart::cart_contains_subscription_renewal('child') && WC_Subscriptions_Order::order_contains_subscription($order_id)) { // This works because the 'woocommerce_add_order_item_meta' runs before the 'woocommerce_checkout_update_order_meta' hook // Set the recurring totals so totals display correctly on order page update_post_meta($order_id, '_order_recurring_discount_cart', WC_Subscriptions_Cart::get_recurring_discount_cart()); update_post_meta($order_id, '_order_recurring_discount_cart_tax', WC_Subscriptions_Cart::get_recurring_discount_cart_tax()); update_post_meta($order_id, '_order_recurring_discount_total', WC_Subscriptions_Cart::get_recurring_discount_total()); update_post_meta($order_id, '_order_recurring_shipping_tax_total', WC_Subscriptions_Cart::get_recurring_shipping_tax_total()); update_post_meta($order_id, '_order_recurring_shipping_total', WC_Subscriptions_Cart::get_recurring_shipping_total()); update_post_meta($order_id, '_order_recurring_tax_total', WC_Subscriptions_Cart::get_recurring_total_tax()); update_post_meta($order_id, '_order_recurring_total', WC_Subscriptions_Cart::get_recurring_total()); // Set the recurring payment method - it starts out the same as the original by may change later update_post_meta($order_id, '_recurring_payment_method', get_post_meta($order_id, '_payment_method', true)); update_post_meta($order_id, '_recurring_payment_method_title', get_post_meta($order_id, '_payment_method_title', true)); $order = new WC_Order($order_id); $order_fees = $order->get_fees(); // the fee order items have already been set, we just need to to add the recurring total meta $cart_fees = $woocommerce->cart->get_fees(); foreach ($order->get_fees() as $item_id => $order_fee) { // Find the matching fee in the cart foreach ($cart_fees as $fee_index => $cart_fee) { if (sanitize_title($order_fee['name']) == $cart_fee->id) { woocommerce_add_order_item_meta($item_id, '_recurring_line_total', wc_format_decimal($cart_fee->recurring_amount)); woocommerce_add_order_item_meta($item_id, '_recurring_line_tax', wc_format_decimal($cart_fee->recurring_tax)); unset($cart_fees[$fee_index]); break; } } } // Get recurring taxes into same format as _order_taxes $order_recurring_taxes = array(); foreach (WC_Subscriptions_Cart::get_recurring_taxes() as $tax_key => $tax_amount) { $item_id = woocommerce_add_order_item($order_id, array('order_item_name' => WC_Tax::get_rate_code($tax_key), 'order_item_type' => 'recurring_tax')); if ($item_id) { wc_add_order_item_meta($item_id, 'rate_id', $tax_key); wc_add_order_item_meta($item_id, 'label', WC_Tax::get_rate_label($tax_key)); wc_add_order_item_meta($item_id, 'compound', absint(WC_Tax::is_compound($tax_key) ? 1 : 0)); wc_add_order_item_meta($item_id, 'tax_amount', wc_format_decimal(isset(WC()->cart->recurring_taxes[$tax_key]) ? WC()->cart->recurring_taxes[$tax_key] : 0)); wc_add_order_item_meta($item_id, 'shipping_tax_amount', wc_format_decimal(isset(WC()->cart->recurring_shipping_taxes[$tax_key]) ? WC()->cart->recurring_shipping_taxes[$tax_key] : 0)); } } $payment_gateways = $woocommerce->payment_gateways->payment_gateways(); if ('yes' == get_option(WC_Subscriptions_Admin::$option_prefix . '_turn_off_automatic_payments', 'no')) { update_post_meta($order_id, '_wcs_requires_manual_renewal', 'true'); } elseif (isset($payment_gateways[$posted['payment_method']]) && !$payment_gateways[$posted['payment_method']]->supports('subscriptions')) { update_post_meta($order_id, '_wcs_requires_manual_renewal', 'true'); } $cart_item = WC_Subscriptions_Cart::cart_contains_subscription_renewal(); if (isset($cart_item['subscription_renewal']) && 'parent' == $cart_item['subscription_renewal']['role']) { update_post_meta($order_id, '_original_order', $cart_item['subscription_renewal']['original_order']); } // WC 2.1+ if (!WC_Subscriptions::is_woocommerce_pre('2.1')) { // Recurring coupons if ($applied_coupons = $woocommerce->cart->get_coupons()) { foreach ($applied_coupons as $code => $coupon) { if (!isset($woocommerce->cart->recurring_coupon_discount_amounts[$code])) { continue; } $item_id = woocommerce_add_order_item($order_id, array('order_item_name' => $code, 'order_item_type' => 'recurring_coupon')); // Add line item meta if ($item_id) { woocommerce_add_order_item_meta($item_id, 'discount_amount', isset($woocommerce->cart->recurring_coupon_discount_amounts[$code]) ? $woocommerce->cart->recurring_coupon_discount_amounts[$code] : 0); } } } // Add recurring shipping order items if (WC_Subscriptions_Cart::cart_contains_subscriptions_needing_shipping()) { $packages = $woocommerce->shipping->get_packages(); $checkout = $woocommerce->checkout(); foreach ($packages as $i => $package) { if (isset($package['rates'][$checkout->shipping_methods[$i]])) { $method = $package['rates'][$checkout->shipping_methods[$i]]; $item_id = woocommerce_add_order_item($order_id, array('order_item_name' => $method->label, 'order_item_type' => 'recurring_shipping')); if ($item_id) { woocommerce_add_order_item_meta($item_id, 'method_id', $method->id); woocommerce_add_order_item_meta($item_id, 'cost', WC_Subscriptions::format_total($method->cost)); woocommerce_add_order_item_meta($item_id, 'taxes', array_map('wc_format_decimal', $method->taxes)); do_action('woocommerce_subscriptions_add_recurring_shipping_order_item', $order_id, $item_id, $i); } } } } // Remove shipping on original order if it was added but is not required if (!WC_Subscriptions_Cart::charge_shipping_up_front()) { foreach ($order->get_shipping_methods() as $order_item_id => $shipping_method) { woocommerce_update_order_item_meta($order_item_id, 'cost', WC_Subscriptions::format_total(0)); } } } else { update_post_meta($order_id, '_recurring_shipping_method', get_post_meta($order_id, '_shipping_method', true), true); update_post_meta($order_id, '_recurring_shipping_method_title', get_post_meta($order_id, '_shipping_method_title', true), true); } } }
/** * Update recurring line taxes via AJAX * @see WC_Subscriptions_Order::calculate_recurring_line_taxes() * * @since 4.4 * @return JSON object with updated tax data */ public static function ajax_update_recurring_tax() { global $wpdb; $woo_22_plus = version_compare(WOOCOMMERCE_VERSION, '2.2', '>='); check_ajax_referer('woocommerce-subscriptions', 'security'); $order_id = absint($_POST['order_id']); $country = strtoupper(esc_attr($_POST['country'])); // Step out of the way if the customer is not located in the US if ($country != 'US') { return; } $shipping = $_POST['shipping']; $line_subtotal = isset($_POST['line_subtotal']) ? esc_attr($_POST['line_subtotal']) : 0; $line_total = isset($_POST['line_total']) ? esc_attr($_POST['line_total']) : 0; // Set up WC_WooTax_Order object $order = self::get_order($order_id); // We only need to instantiate a WC_Tax object if we are using WooCommerce < 2.3 if (!$woo_22_plus) { $tax = new WC_Tax(); } $taxes = $shipping_taxes = array(); $return = array(); $item_data = array(); $type_array = array(); $product_id = ''; if (isset($_POST['order_item_id'])) { $product_id = woocommerce_get_order_item_meta($_POST['order_item_id'], '_product_id'); } elseif (isset($_POST['product_id'])) { $product_id = esc_attr($_POST['product_id']); } if (!empty($product_id) && WC_Subscriptions_Product::is_subscription($product_id)) { // Get product details $product = WC_Subscriptions::get_product($product_id); // Add product to items array $tic = get_post_meta($product->id, 'wootax_tic', true); $item_info = array('Index' => '', 'ItemID' => isset($_POST['order_item_id']) ? $_POST['order_item_id'] : $product_id, 'Qty' => 1, 'Price' => $line_subtotal > 0 ? $line_subtotal : $product->get_price(), 'Type' => 'cart'); if (!empty($tic) && $tic) { $item_info['TIC'] = $tic; } $item_data[] = $item_info; $type_array[$_POST['order_item_id']] = 'cart'; // Add shipping to items array if ($shipping > 0) { $item_data[] = array('Index' => '', 'ItemID' => WT_SHIPPING_ITEM, 'TIC' => WT_SHIPPING_TIC, 'Qty' => 1, 'Price' => $shipping, 'Type' => 'shipping'); $type_array[WT_SHIPPING_ITEM] = 'shipping'; } // Issue Lookup request $res = $order->do_lookup($item_data, $type_array, true); if (is_array($res)) { $return['recurring_shipping_tax'] = 0; $return['recurring_line_subtotal_tax'] = 0; $return['recurring_line_tax'] = 0; foreach ($res as $item) { $item_id = $item->ItemID; $item_tax = $item->TaxAmount; if ($item_id == WT_SHIPPING_ITEM) { $return['recurring_shipping_tax'] += $item_tax; } else { $return['recurring_line_subtotal_tax'] += $item_tax; $return['recurring_line_tax'] += $item_tax; } } $taxes[WT_RATE_ID] = $return['recurring_line_tax']; $shipping_taxes[WT_RATE_ID] = $return['recurring_shipping_tax']; // Get tax rates $tax_codes = array(WT_RATE_ID => apply_filters('wootax_rate_code', 'WOOTAX-RATE-DO-NOT-REMOVE')); // Remove old tax rows $wpdb->query($wpdb->prepare("DELETE FROM {$wpdb->prefix}woocommerce_order_itemmeta WHERE order_item_id IN ( SELECT order_item_id FROM {$wpdb->prefix}woocommerce_order_items WHERE order_id = %d AND order_item_type = 'recurring_tax' )", $order_id)); $wpdb->query($wpdb->prepare("DELETE FROM {$wpdb->prefix}woocommerce_order_items WHERE order_id = %d AND order_item_type = 'recurring_tax'", $order_id)); // Now merge to keep tax rows ob_start(); foreach (array_keys($taxes + $shipping_taxes) as $key) { $item = array(); $item['rate_id'] = $key; $item['name'] = $tax_codes[$key]; $item['label'] = $woo_22_plus ? WC_Tax::get_rate_label($key) : $tax->get_rate_label($key); $item['compound'] = $woo_22_plus ? WC_Tax::is_compound($key) : $tax->is_compound($key) ? 1 : 0; $item['tax_amount'] = wc_round_tax_total(isset($taxes[$key]) ? $taxes[$key] : 0); $item['shipping_tax_amount'] = wc_round_tax_total(isset($shipping_taxes[$key]) ? $shipping_taxes[$key] : 0); if (!$item['label']) { $item['label'] = WC()->countries->tax_or_vat(); } // Add line item $item_id = woocommerce_add_order_item($order_id, array('order_item_name' => $item['name'], 'order_item_type' => 'recurring_tax')); // Add line item meta if ($item_id) { woocommerce_add_order_item_meta($item_id, 'rate_id', $item['rate_id']); woocommerce_add_order_item_meta($item_id, 'label', $item['label']); woocommerce_add_order_item_meta($item_id, 'compound', $item['compound']); woocommerce_add_order_item_meta($item_id, 'tax_amount', $item['tax_amount']); woocommerce_add_order_item_meta($item_id, 'shipping_tax_amount', $item['shipping_tax_amount']); } include plugin_dir_path(WC_Subscriptions::$plugin_file) . 'templates/admin/post-types/writepanels/order-tax-html.php'; } $return['tax_row_html'] = ob_get_clean(); echo json_encode($return); } } die; }
/** * Output the form */ public function output() { global $woocommerce; $this->errors = array(); $step = 1; try { if (!empty($_POST) && !check_admin_referer('create_booking_notification')) { throw new Exception(__('Error - please try again', 'woocommerce-bookings')); } if (!empty($_POST['create_booking'])) { $customer_id = absint($_POST['customer_id']); $bookable_product_id = absint($_POST['bookable_product_id']); $create_order = isset($_POST['create_order']) ? 1 : 0; if (!$bookable_product_id) { throw new Exception(__('Please choose a bookable product', 'woocommerce-bookings')); } $step++; $product = get_product($bookable_product_id); $booking_form = new WC_Booking_Form($product); } elseif (!empty($_POST['create_booking_2'])) { $customer_id = absint($_POST['customer_id']); $bookable_product_id = absint($_POST['bookable_product_id']); $create_order = absint($_POST['create_order']); $product = get_product($bookable_product_id); $booking_form = new WC_Booking_Form($product); $booking_data = $booking_form->get_posted_data($_POST); $booking_cost = number_format($booking_form->calculate_booking_cost($_POST), 2, '.', ''); // Data to go into the booking $new_booking_data = array('product_id' => $product->id, 'resource_id' => isset($booking_data['_resource_id']) ? $booking_data['_resource_id'] : '', 'persons' => $booking_data['_persons'], 'cost' => $booking_cost, 'start_date' => $booking_data['_start_date'], 'end_date' => $booking_data['_end_date'], 'all_day' => $booking_data['_all_day'] ? 1 : 0); // Create order if ($create_order) { $order_id = $this->create_order($booking_cost, $customer_id); if (!$order_id) { throw new Exception(__('Error: Could not create order', 'woocommerce-bookings')); } $item_id = woocommerce_add_order_item($order_id, array('order_item_name' => $product->get_title(), 'order_item_type' => 'line_item')); if (!$item_id) { throw new Exception(__('Error: Could not create item', 'woocommerce-bookings')); } // Add line item meta woocommerce_add_order_item_meta($item_id, '_qty', 1); woocommerce_add_order_item_meta($item_id, '_tax_class', $product->get_tax_class()); woocommerce_add_order_item_meta($item_id, '_product_id', $product->id); woocommerce_add_order_item_meta($item_id, '_variation_id', ''); woocommerce_add_order_item_meta($item_id, '_line_subtotal', $booking_cost); woocommerce_add_order_item_meta($item_id, '_line_total', $booking_cost); woocommerce_add_order_item_meta($item_id, '_line_tax', 0); woocommerce_add_order_item_meta($item_id, '_line_subtotal_tax', 0); // We have an item id $new_booking_data['order_item_id'] = $item_id; // Add line item data foreach ($booking_data as $key => $value) { if (strpos($key, '_') !== 0) { woocommerce_add_order_item_meta($item_id, get_wc_booking_data_label($key, $product), $value); } } } // Create the booking itself $new_booking = get_wc_booking($new_booking_data); $new_booking->create($create_order ? 'unpaid' : 'pending'); wp_safe_redirect(admin_url('post.php?post=' . ($create_order ? $order_id : $new_booking->id) . '&action=edit')); exit; } } catch (Exception $e) { $this->errors[] = $e->getMessage(); } switch ($step) { case 1: include 'views/html-create-booking-page.php'; break; case 2: include 'views/html-create-booking-page-2.php'; break; } }
/** * Runs necessary database updates for working with WooCommerce updates. This function should be called * immediately after WooCommerce has run it's own updates. * * @since 1.2.5 */ public static function upgrade_to_latest_wc() { global $wpdb; // Update recurring tax structure to 2.0 format - item meta if ('true' != self::$updated_to_wc_2_0) { $upgraded_orders = $wpdb->get_col("SELECT post_id FROM {$wpdb->postmeta} WHERE meta_key = '_order_recurring_taxes_old'"); $query = "SELECT * FROM {$wpdb->postmeta} WHERE meta_key = '_order_recurring_taxes'"; if (!empty($upgraded_orders)) { $query .= "AND post_id NOT IN (" . implode(',', $upgraded_orders) . ")"; } $order_tax_rows = $wpdb->get_results($query); foreach ($order_tax_rows as $order_tax_row) { $order_taxes = (array) maybe_unserialize($order_tax_row->meta_value); if ($order_taxes) { foreach ($order_taxes as $order_tax) { if (!isset($order_tax['label']) || !isset($order_tax['cart_tax']) || !isset($order_tax['shipping_tax'])) { continue; } $item_id = woocommerce_add_order_item($order_tax_row->post_id, array('order_item_name' => $order_tax['label'], 'order_item_type' => 'recurring_tax')); // Add line item meta if ($item_id) { woocommerce_add_order_item_meta($item_id, 'compound', absint(isset($order_tax['compound']) ? $order_tax['compound'] : 0)); woocommerce_add_order_item_meta($item_id, 'tax_amount', woocommerce_clean($order_tax['cart_tax'])); woocommerce_add_order_item_meta($item_id, 'shipping_tax_amount', woocommerce_clean($order_tax['shipping_tax'])); } // Delete from DB (rename) $wpdb->query($wpdb->prepare("\n\t\t\t\t\t\t\tUPDATE {$wpdb->postmeta}\n\t\t\t\t\t\t\tSET meta_key = '_order_recurring_taxes_old'\n\t\t\t\t\t\t\tWHERE meta_key = '_order_recurring_taxes'\n\t\t\t\t\t\t\tAND post_id = %d\n\t\t\t\t\t\t", $order_tax_row->post_id)); } } } // Maybe add the "Variable Subscriptions" product type if it wasn't added in the v1.3 upgrade if (!get_term_by('slug', 'variable-subscription', 'product_type')) { wp_insert_term(__('Variable Subscription', 'woocommerce-subscriptions'), 'product_type'); } update_option('wcs_updated_to_wc_2_0', 'true'); } }
/** * When a new order is inserted, add subscriptions related order meta. * * @since 1.0 */ public static function add_order_meta($order_id, $posted) { global $woocommerce; if (!WC_Subscriptions_Cart::cart_contains_subscription_renewal('child') && WC_Subscriptions_Order::order_contains_subscription($order_id)) { // This works because the 'woocommerce_add_order_item_meta' runs before the 'woocommerce_checkout_update_order_meta' hook // Set the recurring totals so totals display correctly on order page update_post_meta($order_id, '_order_recurring_discount_cart', WC_Subscriptions_Cart::get_recurring_discount_cart()); update_post_meta($order_id, '_order_recurring_discount_total', WC_Subscriptions_Cart::get_recurring_discount_total()); update_post_meta($order_id, '_order_recurring_shipping_tax_total', WC_Subscriptions_Cart::get_recurring_shipping_tax_total()); update_post_meta($order_id, '_order_recurring_tax_total', WC_Subscriptions_Cart::get_recurring_total_tax()); update_post_meta($order_id, '_order_recurring_total', WC_Subscriptions_Cart::get_recurring_total()); // Get recurring taxes into same format as _order_taxes $order_recurring_taxes = array(); foreach (WC_Subscriptions_Cart::get_recurring_taxes() as $tax_key => $tax_amount) { $is_compound = $woocommerce->cart->tax->is_compound($tax_key) ? 1 : 0; if (isset($woocommerce->cart->taxes[$tax_key])) { $cart_tax = $tax_amount; $shipping_tax = 0; } else { $cart_tax = 0; $shipping_tax = $tax_amount; } if (function_exists('woocommerce_add_order_item_meta')) { // WC 2.0+ $item_id = woocommerce_add_order_item($order_id, array('order_item_name' => $woocommerce->cart->tax->get_rate_code($tax_key), 'order_item_type' => 'recurring_tax')); if ($item_id) { woocommerce_add_order_item_meta($item_id, 'rate_id', $tax_key); woocommerce_add_order_item_meta($item_id, 'label', $woocommerce->cart->tax->get_rate_label($tax_key)); woocommerce_add_order_item_meta($item_id, 'compound', $is_compound); woocommerce_add_order_item_meta($item_id, 'tax_amount', woocommerce_clean($cart_tax)); woocommerce_add_order_item_meta($item_id, 'shipping_tax_amount', woocommerce_clean($shipping_tax)); } } else { // WC 1.x $order_recurring_taxes[] = array('label' => $woocommerce->cart->tax->get_rate_label($tax_key), 'compound' => $is_compound, 'cart_tax' => woocommerce_format_total($cart_tax), 'shipping_tax' => woocommerce_format_total($shipping_tax)); // Inefficient but keeps WC 1.x code grouped together update_post_meta($order_id, '_order_recurring_taxes', $order_recurring_taxes); } } $payment_gateways = $woocommerce->payment_gateways->payment_gateways(); if ('yes' == get_option(WC_Subscriptions_Admin::$option_prefix . '_turn_off_automatic_payments', 'no')) { update_post_meta($order_id, '_wcs_requires_manual_renewal', 'true'); } elseif (isset($payment_gateways[$posted['payment_method']]) && !$payment_gateways[$posted['payment_method']]->supports('subscriptions')) { update_post_meta($order_id, '_wcs_requires_manual_renewal', 'true'); } $cart_item = WC_Subscriptions_Cart::cart_contains_subscription_renewal(); if (isset($cart_item['subscription_renewal']) && 'parent' == $cart_item['subscription_renewal']['role']) { update_post_meta($order_id, '_original_order', $cart_item['subscription_renewal']['original_order']); } } }
/** * Adds a line tax item from an order by ID. Hooked to * an Ajax call from the "Edit Order" page and mirrors the * @see woocommerce_add_line_tax() function. * * @return void */ public static function add_line_tax() { global $woocommerce, $wpdb; check_ajax_referer(WC_Subscriptions::$text_domain, 'security'); if (function_exists('woocommerce_add_order_item_meta')) { $order_id = absint($_POST['order_id']); $order = new WC_Order($order_id); // Get tax rates $rates = $wpdb->get_results("SELECT tax_rate_id, tax_rate_country, tax_rate_state, tax_rate_name, tax_rate_priority FROM {$wpdb->prefix}woocommerce_tax_rates ORDER BY tax_rate_name"); $tax_codes = array(); foreach ($rates as $rate) { $code = array(); $code[] = $rate->tax_rate_country; $code[] = $rate->tax_rate_state; $code[] = $rate->tax_rate_name ? sanitize_title($rate->tax_rate_name) : 'TAX'; $code[] = absint($rate->tax_rate_priority); $tax_codes[$rate->tax_rate_id] = strtoupper(implode('-', array_filter($code))); } // Add line item $item_id = woocommerce_add_order_item($order_id, array('order_item_name' => '', 'order_item_type' => 'recurring_tax')); // Add line item meta if ($item_id) { woocommerce_add_order_item_meta($item_id, 'rate_id', ''); woocommerce_add_order_item_meta($item_id, 'label', ''); woocommerce_add_order_item_meta($item_id, 'compound', ''); woocommerce_add_order_item_meta($item_id, 'tax_amount', ''); woocommerce_add_order_item_meta($item_id, 'shipping_tax_amount', ''); } include plugin_dir_path(WC_Subscriptions::$plugin_file) . 'templates/admin/post-types/writepanels/order-tax-html.php'; } else { // WC 1.x $size = absint($_POST['size']); ?> <div class="tax_row"> <p class="first"> <label><?php _e('Recurring Tax Label:', WC_Subscriptions::$text_domain); ?> </label> <input type="text" name="_order_recurring_taxes[<?php echo $size; ?> ][label]" placeholder="<?php echo $woocommerce->countries->tax_or_vat(); ?> " value="" /> </p> <p class="last"> <label><?php _e('Compound:', WC_Subscriptions::$text_domain); ?> <input type="checkbox" name="_order_recurring_taxes[<?php echo $size; ?> ][compound]" /></label> </p> <p class="first"> <label><?php _e('Recurring Cart Tax:', WC_Subscriptions::$text_domain); ?> </label> <input type="text" name="_order_recurring_taxes[<?php echo $size; ?> ][cart_tax]" placeholder="0.00" value="" /> </p> <p class="last"> <label><?php _e('Shipping Tax:', WC_Subscriptions::$text_domain); ?> </label> <input type="text" name="_order_recurring_taxes[<?php echo $size; ?> ][shipping_tax]" placeholder="0.00" value="" /> </p> <a href="#" class="delete_tax_row">×</a> <div class="clear"></div> </div> <?php } die; }
function woocommerce_ajax_add_order_item() { check_ajax_referer('order-item', 'security'); $item_to_add = sanitize_text_field($_POST['item_to_add']); $order_id = absint($_POST['order_id']); // Find the item if (!is_numeric($item_to_add)) { die; } $post = get_post($item_to_add); if (!$post || $post->post_type !== 'product' && $post->post_type !== 'product_variation') { die; } $_product = get_product($post->ID); $order = new WC_Order($order_id); $class = 'new_row'; // Set values $item = array(); $item['product_id'] = $_product->id; $item['variation_id'] = isset($_product->variation_id) ? $_product->variation_id : ''; $item['name'] = $_product->get_title(); $item['tax_class'] = $_product->get_tax_class(); $item['qty'] = 1; $item['line_subtotal'] = number_format((double) $_product->get_price_excluding_tax(), 2, '.', ''); $item['line_subtotal_tax'] = ''; $item['line_total'] = number_format((double) $_product->get_price_excluding_tax(), 2, '.', ''); $item['line_tax'] = ''; $item = apply_filters('woocommerce_ajax_before_add_order_item', $item, $_product, $order); // Add line item $item_id = woocommerce_add_order_item($order_id, array('order_item_name' => $item['name'], 'order_item_type' => 'line_item')); $class = apply_filters('woocommerce_admin_order_items_class', $class, $item, $order); // Add line item meta if ($item_id) { woocommerce_add_order_item_meta($item_id, '_qty', $item['qty']); woocommerce_add_order_item_meta($item_id, '_tax_class', $item['tax_class']); woocommerce_add_order_item_meta($item_id, '_product_id', $item['product_id']); woocommerce_add_order_item_meta($item_id, '_variation_id', $item['variation_id']); woocommerce_add_order_item_meta($item_id, '_line_subtotal', $item['line_subtotal']); woocommerce_add_order_item_meta($item_id, '_line_subtotal_tax', $item['line_subtotal_tax']); woocommerce_add_order_item_meta($item_id, '_line_total', $item['line_total']); woocommerce_add_order_item_meta($item_id, '_line_tax', $item['line_tax']); } do_action('woocommerce_ajax_add_order_item_meta', $item_id, $item); //include( 'admin/post-types/writepanels/order-item-html.php' ); include apply_filters('qsot-woo-template', 'post-types/meta-boxes/views/html-order-item.php', 'admin'); // Quit out die; }
/** * Creates a new order for renewing a subscription product based on the details of a previous order. * * No trial periods or sign up fees are applied to the renewal order. However, if the order has failed * payments and the store manager has set failed payments to be added to renewal orders, then the * orders totals will be set to include the outstanding balance. * * If the $args['new_order_role'] flag is set to 'parent', then the renewal order will supersede the existing * order. The existing order and subscription associated with it will be cancelled. A new order and * subscription will be created. * * If the $args['new_order_role'] flag is 'child', the $original_order will remain the master order for the * subscription and the new order is just for accepting a recurring payment on the subscription. * * Renewal orders have the same meta data as the original order. If the renewal order is set to be a 'child' * then any subscription related meta data will not be stored on the new order. This is to keep subscription * meta data associated only with the one master order for the subscription. * * @param WC_Order|int $order The WC_Order object or ID of the order for which the a new order should be created. * @param string $product_id The ID of the subscription product in the order which needs to be added to the new order. * @param array $args (optional) An array of name => value flags: * 'new_order_role' string A flag to indicate whether the new order should become the master order for the subscription. Accepts either 'parent' or 'child'. Defaults to 'parent' - replace the existing order. * 'checkout_renewal' bool Indicates if invoked from an interactive cart/checkout session and certain order items are not set, like taxes, shipping as they need to be set in teh calling function, like @see WC_Subscriptions_Checkout::filter_woocommerce_create_order(). Default false. * 'failed_order_id' int For checkout_renewal true, indicates order id being replaced * @since 1.2 */ public static function generate_renewal_order($original_order, $product_id, $args = array()) { global $wpdb, $woocommerce; if (!is_object($original_order)) { $original_order = new WC_Order($original_order); } if (!WC_Subscriptions_Order::order_contains_subscription($original_order) || !WC_Subscriptions_Order::is_item_subscription($original_order, $product_id)) { return false; } if (self::is_renewal($original_order, array('order_role' => 'child'))) { $original_order = self::get_parent_order($original_order); } if (!is_array($args)) { _deprecated_argument(__CLASS__ . '::' . __FUNCTION__, '1.3', __('Third parameter is now an array of name => value pairs. Use array( "new_order_role" => "parent" ) instead.', 'woocommerce-subscriptions')); $args = array('new_order_role' => $args); } $args = wp_parse_args($args, array('new_order_role' => 'parent', 'checkout_renewal' => false)); $renewal_order_key = uniqid('order_'); // Create the new order $renewal_order_data = array('post_type' => 'shop_order', 'post_title' => sprintf(__('Subscription Renewal Order – %s', 'woocommerce-subscriptions'), strftime(_x('%b %d, %Y @ %I:%M %p', 'Order date parsed by strftime', 'woocommerce-subscriptions'))), 'ping_status' => 'closed', 'post_excerpt' => $original_order->customer_note, 'post_author' => 1, 'post_password' => $renewal_order_key); $create_new_order = true; if (!WC_Subscriptions::is_woocommerce_pre_2_2()) { // WC 2.2 order status $renewal_order_data['post_status'] = 'wc-pending'; } else { $renewal_order_data['post_status'] = 'publish'; } if ('child' == $args['new_order_role']) { $renewal_order_data['post_parent'] = $original_order->id; } if (true === $args['checkout_renewal']) { $renewal_order_id = null; if ($woocommerce->session->order_awaiting_payment > 0) { $renewal_order_id = absint($woocommerce->session->order_awaiting_payment); } elseif (isset($args['failed_order_id'])) { $failed_order_id = $args['failed_order_id']; if (WC_Subscriptions::is_woocommerce_pre_2_2()) { // WC 2.1 - need to use taxonomy /* Check order is unpaid by getting its status */ $terms = wp_get_object_terms($failed_order_id, 'shop_order_status', array('fields' => 'slugs')); $order_status = isset($terms[0]) ? $terms[0] : 'pending'; } else { // WC 2.2+ $failed_order = wc_get_order($failed_order_id); $order_status = $failed_order->get_status(); } /* If paying on a pending order, we are resuming */ if ($order_status == 'pending') { $renewal_order_id = $failed_order_id; } } if ($renewal_order_id) { if (WC_Subscriptions::is_woocommerce_pre_2_2()) { // WC 2.1 - need to use taxonomy /* Check order is unpaid by getting its status */ $terms = wp_get_object_terms($renewal_order_id, 'shop_order_status', array('fields' => 'slugs')); $order_status = isset($terms[0]) ? $terms[0] : 'pending'; } else { // WC 2.2+ $existing_order = wc_get_order($renewal_order_id); $order_status = $existing_order->get_status(); } // Resume the unpaid order if its pending if ($order_status == 'pending' || $order_status == 'failed') { // Update the existing order as we are resuming it $create_new_order = false; $renewal_order_data['ID'] = $renewal_order_id; wp_update_post($renewal_order_data); // Clear the old line items - we'll add these again in case they changed $wpdb->query($wpdb->prepare("DELETE FROM {$wpdb->prefix}woocommerce_order_itemmeta WHERE order_item_id IN ( SELECT order_item_id FROM {$wpdb->prefix}woocommerce_order_items WHERE order_id = %d )", $renewal_order_id)); $wpdb->query($wpdb->prepare("DELETE FROM {$wpdb->prefix}woocommerce_order_items WHERE order_id = %d", $renewal_order_id)); } } } if ($create_new_order) { $renewal_order_id = wp_insert_post($renewal_order_data); } if (WC_Subscriptions::is_woocommerce_pre_2_2()) { // WC 2.1 order status // Set the order as pending wp_set_object_terms($renewal_order_id, 'pending', 'shop_order_status'); } // Set a unique key for this order update_post_meta($renewal_order_id, '_order_key', $renewal_order_key); $order_meta_query = "SELECT `meta_key`, `meta_value`\n\t\t\t\t\t\t\t FROM {$wpdb->postmeta}\n\t\t\t\t\t\t\t WHERE `post_id` = {$original_order->id}\n\t\t\t\t\t\t\t AND `meta_key` NOT IN ('_paid_date', '_completed_date', '_order_key', '_edit_lock', '_original_order', '_wc_points_earned', '_transaction_id')"; // Superseding existing order so don't carry over payment details if ('parent' == $args['new_order_role'] || true === $args['checkout_renewal']) { $order_meta_query .= " AND `meta_key` NOT IN ('_payment_method', '_payment_method_title', '_recurring_payment_method', '_recurring_payment_method_title', '_shipping_method', '_shipping_method_title', '_recurring_shipping_method', '_recurring_shipping_method_title')"; } else { $order_meta_query .= " AND `meta_key` NOT LIKE '_order_recurring_%' AND `meta_key` NOT IN ('_payment_method', '_payment_method_title', '_recurring_payment_method', '_recurring_payment_method_title', '_shipping_method', '_shipping_method_title', '_recurring_shipping_method', '_recurring_shipping_method_title')"; } // Allow extensions to add/remove order meta $order_meta_query = apply_filters('woocommerce_subscriptions_renewal_order_meta_query', $order_meta_query, $original_order->id, $renewal_order_id, $args['new_order_role']); // Carry all the required meta from the old order over to the new order $order_meta = $wpdb->get_results($order_meta_query, 'ARRAY_A'); $order_meta = apply_filters('woocommerce_subscriptions_renewal_order_meta', $order_meta, $original_order->id, $renewal_order_id, $args['new_order_role']); foreach ($order_meta as $meta_item) { add_post_meta($renewal_order_id, $meta_item['meta_key'], maybe_unserialize($meta_item['meta_value']), true); } $outstanding_balance = WC_Subscriptions_Order::get_outstanding_balance($original_order, $product_id); $failed_payment_multiplier = 1; if (false == $args['checkout_renewal']) { // If there are outstanding payment amounts, add them to the order, otherwise set the order details to the values of the recurring totals if ($outstanding_balance > 0 && 'yes' == get_option(WC_Subscriptions_Admin::$option_prefix . '_add_outstanding_balance', 'no')) { $failed_payment_multiplier = WC_Subscriptions_Order::get_failed_payment_count($original_order, $product_id); } // Set order totals based on recurring totals from the original order $cart_discount = $failed_payment_multiplier * wc_format_decimal(get_post_meta($original_order->id, '_order_recurring_discount_cart', true)); $order_discount = $failed_payment_multiplier * wc_format_decimal(get_post_meta($original_order->id, '_order_recurring_discount_total', true)); $order_shipping_tax = $failed_payment_multiplier * wc_format_decimal(get_post_meta($original_order->id, '_order_recurring_shipping_tax_total', true)); $order_shipping = $failed_payment_multiplier * wc_format_decimal(get_post_meta($original_order->id, '_order_recurring_shipping_total', true)); $order_tax = $failed_payment_multiplier * wc_format_decimal(get_post_meta($original_order->id, '_order_recurring_tax_total', true)); $order_total = $failed_payment_multiplier * wc_format_decimal(get_post_meta($original_order->id, '_order_recurring_total', true)); update_post_meta($renewal_order_id, '_cart_discount', $cart_discount); update_post_meta($renewal_order_id, '_order_discount', $order_discount); update_post_meta($renewal_order_id, '_order_shipping_tax', $order_shipping_tax); update_post_meta($renewal_order_id, '_order_shipping', $order_shipping); update_post_meta($renewal_order_id, '_order_tax', $order_tax); update_post_meta($renewal_order_id, '_order_total', $order_total); // Set shipping for orders created with WC 2.0.n (or when we are using WC 2.0.n) if (WC_Subscriptions::is_woocommerce_pre_2_1() || isset($original_order->recurring_shipping_method)) { update_post_meta($renewal_order_id, '_shipping_method', $original_order->recurring_shipping_method); update_post_meta($renewal_order_id, '_shipping_method_title', $original_order->recurring_shipping_method_title); // Also set recurring shipping as it's a parent renewal order if ('parent' == $args['new_order_role']) { update_post_meta($renewal_order_id, '_recurring_shipping_method', $original_order->recurring_shipping_method); update_post_meta($renewal_order_id, '_recurring_shipping_method_title', $original_order->recurring_shipping_method_title); } } // Apply the recurring shipping & payment methods to child renewal orders if ('child' == $args['new_order_role']) { update_post_meta($renewal_order_id, '_payment_method', $original_order->recurring_payment_method); update_post_meta($renewal_order_id, '_payment_method_title', $original_order->recurring_payment_method_title); } // Set order taxes based on recurring taxes from the original order $recurring_order_taxes = WC_Subscriptions_Order::get_recurring_taxes($original_order); foreach ($recurring_order_taxes as $index => $recurring_order_tax) { $item_ids = array(); $item_ids[] = woocommerce_add_order_item($renewal_order_id, array('order_item_name' => $recurring_order_tax['name'], 'order_item_type' => 'tax')); // Also set recurring taxes on parent renewal orders if ('parent' == $args['new_order_role']) { $item_ids[] = woocommerce_add_order_item($renewal_order_id, array('order_item_name' => $recurring_order_tax['name'], 'order_item_type' => 'recurring_tax')); } // Add line item meta foreach ($item_ids as $item_id) { woocommerce_add_order_item_meta($item_id, 'compound', absint(isset($recurring_order_tax['compound']) ? $recurring_order_tax['compound'] : 0)); woocommerce_add_order_item_meta($item_id, 'tax_amount', $failed_payment_multiplier * WC_Subscriptions::format_total($recurring_order_tax['tax_amount'])); woocommerce_add_order_item_meta($item_id, 'shipping_tax_amount', $failed_payment_multiplier * WC_Subscriptions::format_total($recurring_order_tax['shipping_tax_amount'])); if (isset($recurring_order_tax['rate_id'])) { woocommerce_add_order_item_meta($item_id, 'rate_id', $recurring_order_tax['rate_id']); } if (isset($recurring_order_tax['label'])) { woocommerce_add_order_item_meta($item_id, 'label', $recurring_order_tax['label']); } } } // Set up shipping items on renewal order $recurring_shipping_items = WC_Subscriptions_Order::get_recurring_shipping_methods($original_order); foreach ($recurring_shipping_items as $recurring_shipping_item_id => $recurring_shipping_item) { $item_ids = array(); $item_ids[] = woocommerce_add_order_item($renewal_order_id, array('order_item_name' => $recurring_shipping_item['name'], 'order_item_type' => 'shipping')); // Also set recurring shipping as it's a parent renewal order if ('parent' == $args['new_order_role']) { $item_ids[] = woocommerce_add_order_item($renewal_order_id, array('order_item_name' => $recurring_shipping_item['name'], 'order_item_type' => 'recurring_shipping')); } // Add shipping item meta foreach ($item_ids as $item_id) { woocommerce_add_order_item_meta($item_id, 'method_id', $recurring_shipping_item['method_id']); woocommerce_add_order_item_meta($item_id, 'cost', $failed_payment_multiplier * WC_Subscriptions::format_total($recurring_shipping_item['cost'])); // Set line taxes for shipping if (isset($recurring_shipping_item['taxes'])) { $taxes = maybe_unserialize($recurring_shipping_item['taxes']); } else { // try to determine recurring shipping taxes from original order's shipping taxes $taxes = array(); foreach ($original_order->get_shipping_methods() as $original_shipping_item_id => $original_shipping_item) { // We need to use the amount of the same shipping method as this one if ($recurring_shipping_item['method_id'] != $original_shipping_item['method_id']) { continue; } // If we don't have taxes on the matching shipping item, there's nothing we can do if (!isset($original_shipping_item['taxes'])) { break; } $original_shipping_item['taxes'] = maybe_unserialize($original_shipping_item['taxes']); // Make sure we account for any amount on the original original shipping not applied to renewals by determining what proportion of the initial amount the recurring total represents if (0 != $original_shipping_item['cost'] && $recurring_shipping_item['cost'] != $original_shipping_item['cost']) { $recurring_ratio = $recurring_shipping_item['cost'] / $original_shipping_item['cost']; foreach ($original_shipping_item['taxes'] as $tax_id => $tax_amount) { $original_shipping_item['taxes'][$tax_id] = $recurring_ratio * $tax_amount; } } foreach ($original_shipping_item['taxes'] as $tax_id => $tax_amount) { $taxes[$tax_id] = WC_Subscriptions::format_total($failed_payment_multiplier * $tax_amount); } } } woocommerce_add_order_item_meta($item_id, 'taxes', $taxes); } } } // Set line totals to be recurring line totals and remove the subscription/recurring related item meta from each order item $order_items = WC_Subscriptions_Order::get_recurring_items($original_order); // Allow extensions to add/remove items or item meta $order_items = apply_filters('woocommerce_subscriptions_renewal_order_items', $order_items, $original_order->id, $renewal_order_id, $product_id, $args['new_order_role']); if (true === $args['checkout_renewal']) { $cart_items = $woocommerce->cart->get_cart(); } foreach ($order_items as $item_index => $order_item) { $renewal_order_item_name = apply_filters('woocommerce_subscriptions_renewal_order_item_name', $order_item['name'], $order_item, $original_order); // Create order line item on the renewal order $recurring_item_id = woocommerce_add_order_item($renewal_order_id, array('order_item_name' => $renewal_order_item_name, 'order_item_type' => 'line_item')); if (true === $args['checkout_renewal']) { $cart_item = array(); foreach ($cart_items as $item) { if ($item['product_id'] == $order_item['product_id'] && (empty($order_item['variation_id']) || $item['variation_id'] == $order_item['variation_id'])) { $cart_item = $item; } } if (!empty($cart_item)) { woocommerce_update_order_item_meta($recurring_item_id, '_line_total', woocommerce_format_decimal($cart_item['line_total'])); woocommerce_update_order_item_meta($recurring_item_id, '_line_tax', woocommerce_format_decimal($cart_item['line_tax'])); woocommerce_update_order_item_meta($recurring_item_id, '_line_subtotal', woocommerce_format_decimal($cart_item['line_subtotal'])); woocommerce_update_order_item_meta($recurring_item_id, '_line_subtotal_tax', woocommerce_format_decimal($cart_item['line_subtotal_tax'])); if (is_object($cart_item['data'])) { woocommerce_update_order_item_meta($recurring_item_id, '_tax_class', $cart_item['data']->get_tax_class()); } } $cart_items = $woocommerce->cart->get_cart(); } $item_meta = new WC_Order_Item_Meta($order_item['item_meta']); // Remove recurring line items and set item totals based on recurring line totals foreach ($item_meta->meta as $meta_key => $meta) { // $meta is an array, so the item needs to be extracted from $meta[0] (just like order meta on a WC Order) $meta_value = maybe_unserialize($meta[0]); if (false === $args['checkout_renewal']) { // Already set earlier // Map line item totals based on recurring line totals switch ($meta_key) { case '_recurring_line_total': woocommerce_update_order_item_meta($recurring_item_id, '_line_total', $failed_payment_multiplier * woocommerce_format_decimal($meta_value)); break; case '_recurring_line_tax': woocommerce_update_order_item_meta($recurring_item_id, '_line_tax', $failed_payment_multiplier * woocommerce_format_decimal($meta_value)); break; case '_recurring_line_subtotal': woocommerce_update_order_item_meta($recurring_item_id, '_line_subtotal', $failed_payment_multiplier * woocommerce_format_decimal($meta_value)); break; case '_recurring_line_subtotal_tax': woocommerce_update_order_item_meta($recurring_item_id, '_line_subtotal_tax', $failed_payment_multiplier * woocommerce_format_decimal($meta_value)); break; case '_line_tax_data': // Copy line tax data if the order doesn't have a _recurring_line_tax_data (for backward compatibility) if (!array_key_exists('_recurring_line_tax_data', $item_meta->meta)) { $line_total = $item_meta->meta['_line_total'][0]; $recurring_line_total = $item_meta->meta['_recurring_line_total'][0]; // There will only be recurring tax data if the recurring amount is > 0 and we can only retroactively calculate recurring amount from initial amoutn if it is > 0 if ($line_total > 0 && $recurring_line_total > 0) { // Make sure we account for any sign-up fees by determining what proportion of the initial amount the recurring total represents $recurring_ratio = $recurring_line_total / $line_total; $recurring_tax_data = array(); $tax_data_keys = array('total', 'subtotal'); foreach ($tax_data_keys as $tax_data_key) { foreach ($meta_value[$tax_data_key] as $tax_index => $tax_value) { // Use total tax amount for both total and subtotal because we don't want any initial discounts to be applied to recurring amounts $total_tax_amount = $meta_value['total'][$tax_index]; $recurring_tax_data[$tax_data_key][$tax_index] = woocommerce_format_decimal($failed_payment_multiplier * ($recurring_ratio * $total_tax_amount)); } } } else { $recurring_tax_data = array('total' => array(), 'subtotal' => array()); } woocommerce_update_order_item_meta($recurring_item_id, '_line_tax_data', $recurring_tax_data); } break; case '_recurring_line_tax_data': $recurring_tax_data = array(); $tax_data_keys = array('total', 'subtotal'); foreach ($tax_data_keys as $tax_data_key) { foreach ($meta_value[$tax_data_key] as $tax_index => $tax_value) { $recurring_tax_data[$tax_data_key][$tax_index] = woocommerce_format_decimal($failed_payment_multiplier * $tax_value); } } woocommerce_update_order_item_meta($recurring_item_id, '_line_tax_data', $recurring_tax_data); break; default: break; } } // Copy over line item meta data, with some parent/child role based exceptions for recurring amounts $copy_to_renewal_item = true; switch ($meta_key) { case '_recurring_line_total': case '_recurring_line_tax': case '_recurring_line_subtotal': case '_recurring_line_subtotal_tax': case '_recurring_line_tax_data': case '_line_tax_data': case '_subscription_recurring_amount': case '_subscription_sign_up_fee': case '_subscription_period': case '_subscription_interval': case '_subscription_length': case '_subscription_trial_period': case '_subscription_end_date': case '_subscription_expiry_date': case '_subscription_start_date': case '_subscription_status': case '_subscription_completed_payments': if ('child' == $args['new_order_role']) { $copy_to_renewal_item = false; } break; case '_subscription_trial_length': // We never want to duplicate free trials on renewal orders $copy_to_renewal_item = false; break; case '_subscription_suspension_count': // We want to reset some values for the new order // We want to reset some values for the new order case '_subscription_trial_expiry_date': case '_subscription_failed_payments': $copy_to_renewal_item = false; $meta_value = 0; break; default: break; } // Copy existing item over to new recurring order item if ($copy_to_renewal_item) { woocommerce_add_order_item_meta($recurring_item_id, $meta_key, $meta_value); } } } if (false == $args['checkout_renewal']) { // Add fees foreach ($original_order->get_fees() as $item_id => $order_fee) { if (!isset($order_fee['recurring_line_total'])) { continue; } $item_id = woocommerce_add_order_item($renewal_order_id, array('order_item_name' => $order_fee['name'], 'order_item_type' => 'fee')); woocommerce_add_order_item_meta($item_id, '_tax_class', $order_fee['tax_class']); woocommerce_add_order_item_meta($item_id, '_line_total', WC_Subscriptions::format_total($order_fee['recurring_line_total'])); woocommerce_add_order_item_meta($item_id, '_line_tax', WC_Subscriptions::format_total($order_fee['recurring_line_tax'])); } } // Keep a record of the original order's ID on the renewal order update_post_meta($renewal_order_id, '_original_order', $original_order->id, true); $renewal_order = new WC_Order($renewal_order_id); if ('parent' == $args['new_order_role']) { WC_Subscriptions_Manager::process_subscriptions_on_checkout($renewal_order_id); $original_order->add_order_note(sprintf(__('Order superseded by Renewal Order %s.', 'woocommerce-subscriptions'), $renewal_order->get_order_number())); } do_action('woocommerce_subscriptions_renewal_order_created', $renewal_order, $original_order, $product_id, $args['new_order_role']); return apply_filters('woocommerce_subscriptions_renewal_order_id', $renewal_order_id, $original_order, $product_id, $args['new_order_role']); }