/** * Get tax row amounts with or without compound taxes includes. * * @return float price */ public function get_taxes_total($compound = true) { $total = 0; foreach ($this->taxes as $key => $tax) { if (!$compound && $this->tax->is_compound($key)) { continue; } $total += $tax; } foreach ($this->shipping_taxes as $key => $tax) { if (!$compound && $this->tax->is_compound($key)) { continue; } $total += $tax; } return $total; }
/** * Get tax row amounts with or without compound taxes includes. * * @param boolean $compound True if getting compound taxes * @param boolean $display True if getting total to display * @return float price */ public function get_taxes_total($compound = true, $display = true) { $total = 0; foreach ($this->taxes as $key => $tax) { if (!$compound && $this->tax->is_compound($key)) { continue; } $total += $tax; } foreach ($this->shipping_taxes as $key => $tax) { if (!$compound && $this->tax->is_compound($key)) { continue; } $total += $tax; } if ($display) { $total = wc_round_tax_total($total); } return apply_filters('woocommerce_cart_taxes_total', $total, $compound, $display, $this); }
/** * Get tax row amounts with or without compound taxes includes. * @param boolean $compound True if getting compound taxes * @param boolean $display True if getting total to display * @return float price */ public function get_taxes_total($compound = true, $display = true) { $total = 0; foreach ($this->taxes as $key => $tax) { if (!$compound && $this->tax->is_compound($key)) { continue; } $total += $tax; } foreach ($this->shipping_taxes as $key => $tax) { if (!$compound && $this->tax->is_compound($key)) { continue; } $total += $tax; } if ($display) { return wc_round_tax_total($total); } else { return $total; } }
/** * Add a tax row to the order * * @since 2.2 * @param int tax_rate_id * @return int|bool Item ID or false */ public function add_tax($tax_rate_id, $tax_amount = 0, $shipping_tax_amount = 0) { $code = WC_Tax::get_rate_code($tax_rate_id); if (!$code) { return false; } $item_id = wc_add_order_item($this->id, array('order_item_name' => $code, 'order_item_type' => 'tax')); if (!$item_id) { return false; } wc_add_order_item_meta($item_id, 'rate_id', $tax_rate_id); wc_add_order_item_meta($item_id, 'label', WC_Tax::get_rate_label($tax_rate_id)); wc_add_order_item_meta($item_id, 'compound', WC_Tax::is_compound($tax_rate_id) ? 1 : 0); wc_add_order_item_meta($item_id, 'tax_amount', wc_format_decimal($tax_amount)); wc_add_order_item_meta($item_id, 'shipping_tax_amount', wc_format_decimal($shipping_tax_amount)); do_action('woocommerce_order_add_tax', $this->id, $item_id, $tax_rate_id, $tax_amount, $shipping_tax_amount); return $item_id; }
/** * Calc line tax * * @access public * @return void */ function woocommerce_calc_line_taxes() { global $woocommerce, $wpdb; check_ajax_referer('calc-totals', 'security'); header('Content-Type: application/json; charset=utf-8'); $tax = new WC_Tax(); $taxes = $tax_rows = $item_taxes = $shipping_taxes = array(); $order_id = absint($_POST['order_id']); $country = strtoupper(esc_attr($_POST['country'])); $state = strtoupper(esc_attr($_POST['state'])); $postcode = strtoupper(esc_attr($_POST['postcode'])); $city = sanitize_title(esc_attr($_POST['city'])); $items = $_POST['items']; $shipping = $_POST['shipping']; $item_tax = 0; // Calculate sales tax first if (sizeof($items) > 0) { foreach ($items as $item_id => $item) { $item_id = absint($item_id); $line_subtotal = isset($item['line_subtotal']) ? esc_attr($item['line_subtotal']) : ''; $line_total = esc_attr($item['line_total']); $tax_class = esc_attr($item['tax_class']); if (!$item_id || $tax_class == '0') { continue; } // Get product details if (get_post_type($item_id) == 'product') { $_product = get_product($item_id); $item_tax_status = $_product->get_tax_status(); } else { $item_tax_status = 'taxable'; } // Only calc if taxable if ($item_tax_status == 'taxable') { $tax_rates = $tax->find_rates(array('country' => $country, 'state' => $state, 'postcode' => $postcode, 'city' => $city, 'tax_class' => $tax_class)); $line_subtotal_taxes = $tax->calc_tax($line_subtotal, $tax_rates, false); $line_taxes = $tax->calc_tax($line_total, $tax_rates, false); $line_subtotal_tax = $tax->round(array_sum($line_subtotal_taxes)); $line_tax = $tax->round(array_sum($line_taxes)); //$line_subtotal_tax = rtrim( rtrim( number_format( array_sum( $line_subtotal_taxes ), 4, '.', '' ), '0' ), '.' ); //$line_tax = rtrim( rtrim( number_format( array_sum( $line_taxes ), 4, '.', '' ), '0' ), '.' ); if ($line_subtotal_tax < 0) { $line_subtotal_tax = 0; } if ($line_tax < 0) { $line_tax = 0; } $item_taxes[$item_id] = array('line_subtotal_tax' => $line_subtotal_tax, 'line_tax' => $line_tax); $item_tax += $line_tax; // Sum the item taxes foreach (array_keys($taxes + $line_taxes) as $key) { $taxes[$key] = (isset($line_taxes[$key]) ? $line_taxes[$key] : 0) + (isset($taxes[$key]) ? $taxes[$key] : 0); } } } } // Now calculate shipping tax $matched_tax_rates = array(); $tax_rates = $tax->find_rates(array('country' => $country, 'state' => $state, 'postcode' => $postcode, 'city' => $city, 'tax_class' => '')); if ($tax_rates) { foreach ($tax_rates as $key => $rate) { if (isset($rate['shipping']) && $rate['shipping'] == 'yes') { $matched_tax_rates[$key] = $rate; } } } $shipping_taxes = $tax->calc_shipping_tax($shipping, $matched_tax_rates); //$shipping_tax = rtrim( rtrim( number_format( array_sum( $shipping_taxes ), 2, '.', '' ), '0' ), '.' ); $shipping_tax = $tax->round(array_sum($shipping_taxes)); // 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 = 'tax' )", $order_id)); $wpdb->query($wpdb->prepare("DELETE FROM {$wpdb->prefix}woocommerce_order_items WHERE order_id = %d AND order_item_type = 'tax'", $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))); } // 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'] = $tax->get_rate_label($key); $item['compound'] = $tax->is_compound($key) ? 1 : 0; $item['tax_amount'] = $tax->round(isset($taxes[$key]) ? $taxes[$key] : 0); $item['shipping_tax_amount'] = $tax->round(isset($shipping_taxes[$key]) ? $shipping_taxes[$key] : 0); if (!$item['label']) { $item['label'] = $woocommerce->countries->tax_or_vat(); } // Add line item $item_id = woocommerce_add_order_item($order_id, array('order_item_name' => $item['name'], 'order_item_type' => '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 'admin/post-types/writepanels/order-tax-html.php'; } $tax_row_html = ob_get_clean(); // Return echo json_encode(array('item_tax' => $item_tax, 'item_taxes' => $item_taxes, 'shipping_tax' => $shipping_tax, 'tax_row_html' => $tax_row_html)); // Quit out die; }
/** * Add tax lines to the order. * * @param WC_Order $order */ protected function create_order_tax_lines(&$order) { foreach (array_keys(WC()->cart->taxes + WC()->cart->shipping_taxes) as $tax_rate_id) { if ($tax_rate_id && apply_filters('woocommerce_cart_remove_taxes_zero_rate_id', 'zero-rated') !== $tax_rate_id) { $item = new WC_Order_Item_Tax(); $item->set_props(array('rate_id' => $tax_rate_id, 'tax_total' => WC()->cart->get_tax_amount($tax_rate_id), 'shipping_tax_total' => WC()->cart->get_shipping_tax_amount($tax_rate_id), 'rate_code' => WC_Tax::get_rate_code($tax_rate_id), 'label' => WC_Tax::get_rate_label($tax_rate_id), 'compound' => WC_Tax::is_compound($tax_rate_id))); $order->add_item($item); } } }
/** * Create an order. Error codes: * 520 - Cannot insert order into the database. * 521 - Cannot get order after creation. * 522 - Cannot update order. * 525 - Cannot create line item. * 526 - Cannot create fee item. * 527 - Cannot create shipping item. * 528 - Cannot create tax item. * 529 - Cannot create coupon item. * @throws Exception * @return int|WP_ERROR */ public function create_order() { global $wpdb; // Give plugins the opportunity to create an order themselves if ($order_id = apply_filters('woocommerce_create_order', null, $this)) { return $order_id; } try { // Start transaction if available wc_transaction_query('start'); // Insert or update the post data $order_id = absint(WC()->session->order_awaiting_payment); $cart_hash = md5(json_encode(wc_clean(WC()->cart->get_cart_for_session())) . WC()->cart->total); /** * If there is an order pending payment, we can resume it here so * long as it has not changed. If the order has changed, i.e. * different items or cost, create a new order. We use a hash to * detect changes which is based on cart items + order total. */ if ($order_id && ($order = wc_get_order($order_id)) && $order->has_cart_hash($cart_hash) && $order->has_status(array('pending', 'failed'))) { // Action for 3rd parties. do_action('woocommerce_resume_order', $order_id); // Remove all items - we will re-add them later. $order->remove_order_items(); /** * Not resuming - lets create a new order object. */ } else { $order = new WC_Order(); } $order->set_created_via('checkout'); $order->set_cart_hash($cart_hash); $order->set_customer_id($this->customer_id); $order->set_currency(get_woocommerce_currency()); $order->set_prices_include_tax('yes' === get_option('woocommerce_prices_include_tax')); $order->set_customer_ip_address(WC_Geolocation::get_ip_address()); $order->set_customer_user_agent(wc_get_user_agent()); $order->set_customer_note(isset($this->posted['order_comments']) ? $this->posted['order_comments'] : ''); $order->set_payment_method($this->payment_method); $order->set_shipping_total(WC()->cart->shipping_total); $order->set_discount_total(WC()->cart->get_cart_discount_total()); $order->set_discount_tax(WC()->cart->get_cart_discount_tax_total()); $order->set_cart_tax(WC()->cart->tax_total); $order->set_shipping_tax(WC()->cart->shipping_tax_total); $order->set_total(WC()->cart->total); // Billing and shipping addresses if ($address_keys = array_merge(array_keys($this->checkout_fields['billing']), array_keys($this->checkout_fields['shipping']))) { foreach ($address_keys as $key) { if (is_callable(array($order, "set_{$key}"))) { $order->{"set_{$key}"}($this->get_posted_address_data(str_replace(array('billing_', 'shipping_'), '', $key), strstr($key, 'billing_') ? 'billing' : 'shipping')); } } } // Add line items. foreach (WC()->cart->get_cart() as $cart_item_key => $values) { $product = $values['data']; $item = new WC_Order_Item_Product(array('quantity' => $values['quantity'], 'name' => $product ? $product->get_title() : '', 'tax_class' => $product ? $product->get_tax_class() : '', 'product_id' => $product && isset($product->id) ? $product->id : 0, 'variation_id' => $product && isset($product->variation_id) ? $product->variation_id : 0, 'variation' => $values['variation'], 'subtotal' => $values['line_subtotal'], 'total' => $values['line_total'], 'subtotal_tax' => $values['line_subtotal_tax'], 'total_tax' => $values['line_tax'], 'taxes' => $values['line_tax_data'])); $item->set_backorder_meta(); // Set this to pass to legacy actions @todo remove in future release $item->legacy_values = $values; $item->legacy_cart_item_key = $cart_item_key; $order->add_item($item); } // Add fees foreach (WC()->cart->get_fees() as $fee_key => $fee) { $item = new WC_Order_Item_Fee(array('name' => $fee->name, 'tax_class' => $fee->taxable ? $fee->tax_class : 0, 'total' => $fee->amount, 'total_tax' => $fee->tax, 'taxes' => array('total' => $fee->tax_data))); // Set this to pass to legacy actions @todo remove in future release $item->legacy_fee = $fee; $item->legacy_fee_key = $fee_key; $order->add_item($item); } // Store shipping for all packages foreach (WC()->shipping->get_packages() as $package_key => $package) { if (isset($package['rates'][$this->shipping_methods[$package_key]])) { $shipping_rate = $package['rates'][$this->shipping_methods[$package_key]]; $item = new WC_Order_Item_Shipping(array('method_title' => $shipping_rate->label, 'method_id' => $shipping_rate->id, 'total' => wc_format_decimal($shipping_rate->cost), 'taxes' => $shipping_rate->taxes, 'meta_data' => $shipping_rate->get_meta_data())); // Set this to pass to legacy actions @todo remove in future release $item->legacy_package_key = $package_key; $order->add_item($item); } } // Store tax rows foreach (array_keys(WC()->cart->taxes + WC()->cart->shipping_taxes) as $tax_rate_id) { if ($tax_rate_id && apply_filters('woocommerce_cart_remove_taxes_zero_rate_id', 'zero-rated') !== $tax_rate_id) { $order->add_item(new WC_Order_Item_Tax(array('rate_id' => $tax_rate_id, 'tax_total' => WC()->cart->get_tax_amount($tax_rate_id), 'shipping_tax_total' => WC()->cart->get_shipping_tax_amount($tax_rate_id), 'rate_code' => WC_Tax::get_rate_code($tax_rate_id), 'label' => WC_Tax::get_rate_label($tax_rate_id), 'compound' => WC_Tax::is_compound($tax_rate_id)))); } } // Store coupons foreach (WC()->cart->get_coupons() as $code => $coupon) { $item = new WC_Order_Item_Coupon(array('code' => $code, 'discount' => WC()->cart->get_coupon_discount_amount($code), 'discount_tax' => WC()->cart->get_coupon_discount_tax_amount($code))); $order->add_item($item); } // Save the order $order_id = $order->save(); // Update user meta $this->update_customer_data(); // Let plugins add their own meta data do_action('woocommerce_checkout_update_order_meta', $order_id, $this->posted); // If we got here, the order was created without problems! wc_transaction_query('commit'); } catch (Exception $e) { // There was an error adding order data! wc_transaction_query('rollback'); return new WP_Error('checkout-error', $e->getMessage()); } return $order_id; }
/** * Calculate recurring line taxes when a store manager clicks the "Calc Line Tax" button on the "Edit Order" page. * * Based on the @see woocommerce_calc_line_taxes() function. * @since 1.2.4 * @return void */ public static function calculate_recurring_line_taxes() { global $woocommerce, $wpdb; check_ajax_referer('woocommerce-subscriptions', 'security'); $tax = new WC_Tax(); $taxes = $tax_rows = $item_taxes = $shipping_taxes = $return = array(); $item_tax = 0; $order_id = absint($_POST['order_id']); $country = strtoupper(esc_attr($_POST['country'])); $state = strtoupper(esc_attr($_POST['state'])); $postcode = strtoupper(esc_attr($_POST['postcode'])); $tax_class = esc_attr($_POST['tax_class']); if (isset($_POST['city'])) { $city = sanitize_title(esc_attr($_POST['city'])); } $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; $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); $item_tax_status = $product->get_tax_status(); if ($item_tax_status == 'taxable') { $tax_rates = $tax->find_rates(array('country' => $country, 'state' => $state, 'postcode' => $postcode, 'city' => $city, 'tax_class' => $tax_class)); $line_subtotal_taxes = $tax->calc_tax($line_subtotal, $tax_rates, false); $line_taxes = $tax->calc_tax($line_total, $tax_rates, false); $line_subtotal_tax = $tax->round(array_sum($line_subtotal_taxes)); $line_tax = $tax->round(array_sum($line_taxes)); if ($line_subtotal_tax < 0) { $line_subtotal_tax = 0; } if ($line_tax < 0) { $line_tax = 0; } $return = array('recurring_line_subtotal_tax' => $line_subtotal_tax, 'recurring_line_tax' => $line_tax); // Sum the item taxes foreach (array_keys($taxes + $line_taxes) as $key) { $taxes[$key] = (isset($line_taxes[$key]) ? $line_taxes[$key] : 0) + (isset($taxes[$key]) ? $taxes[$key] : 0); } } // Now calculate shipping tax $matched_tax_rates = array(); $tax_rates = $tax->find_rates(array('country' => $country, 'state' => $state, 'postcode' => $postcode, 'city' => $city, 'tax_class' => '')); if ($tax_rates) { foreach ($tax_rates as $key => $rate) { if (isset($rate['shipping']) && $rate['shipping'] == 'yes') { $matched_tax_rates[$key] = $rate; } } } $shipping_taxes = $tax->calc_shipping_tax($shipping, $matched_tax_rates); $shipping_tax = $tax->round(array_sum($shipping_taxes)); $return['recurring_shipping_tax'] = $shipping_tax; // 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)); // 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))); } // 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'] = $tax->get_rate_label($key); $item['compound'] = $tax->is_compound($key) ? 1 : 0; $item['tax_amount'] = $tax->round(isset($taxes[$key]) ? $taxes[$key] : 0); $item['shipping_tax_amount'] = $tax->round(isset($shipping_taxes[$key]) ? $shipping_taxes[$key] : 0); if (!$item['label']) { $item['label'] = $woocommerce->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; }
/** * Test is compound. */ public function test_is_compound() { global $wpdb; $tax_rate = array('tax_rate_country' => 'GB', 'tax_rate_state' => '', 'tax_rate' => '20.0000', 'tax_rate_name' => 'VAT', 'tax_rate_priority' => '1', 'tax_rate_compound' => '1', 'tax_rate_shipping' => '1', 'tax_rate_order' => '1', 'tax_rate_class' => ''); $tax_rate_id = WC_Tax::_insert_tax_rate($tax_rate); $this->assertTrue(WC_Tax::is_compound($tax_rate_id)); WC_Tax::_delete_tax_rate($tax_rate_id); }
/** * 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); } } }
/** * Get tax row amounts with or without compound taxes includes * * Deprecated because the cart can now contain subscriptions on multiple billing schedules so there is no one "total" * * @return double The total recurring tax amount tax for items in the cart (maybe not including compound taxes) * @since 1.2 */ public static function get_recurring_taxes_total($compound = true) { _deprecated_function(__METHOD__, '2.0', 'values from WC()->cart->recurring_carts'); $recurring_total = 0; foreach (WC()->cart->recurring_carts as $cart) { foreach ($cart->taxes as $key => $tax) { if (!$compound && WC_Tax::is_compound($key)) { continue; } $recurring_total += $tax; } foreach ($cart->shipping_taxes as $key => $tax) { if (!$compound && WC_Tax::is_compound($key)) { continue; } $recurring_total += $tax; } } return $recurring_total; }
/** * Get tax row amounts with or without compound taxes includes * * @return double The total recurring tax amount tax for items in the cart (maybe not including compound taxes) * @since 1.2 */ public static function get_recurring_taxes_total($compound = true) { global $woocommerce; $recurring_taxes_total = 0; foreach (self::get_recurring_taxes() as $tax_id => $tax_amount) { if (!$compound && WC_Tax::is_compound($tax_id)) { continue; } $recurring_taxes_total += $tax_amount; } return $recurring_taxes_total; }
/** * 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; }
public function woocommerce_cart_totals_taxes_total_html($html_value) { $user_currency = $this->get_currency_by_country($this->storage->get_val('woocs_user_country')); $currencies = $this->get_currencies(); if ($user_currency != $this->current_currency and !empty($user_currency)) { $tmp_curr_currency = $this->current_currency; $this->current_currency = $user_currency; $this->storage->set_val('woocs_current_currency', $user_currency); $total = 0; $compound = true; foreach (WC()->cart->taxes as $key => $tax) { if (!$compound && WC_Tax::is_compound($key)) { continue; } $total += $tax; } foreach (WC()->cart->shipping_taxes as $key => $tax) { if (!$compound && WC_Tax::is_compound($key)) { continue; } $total += $tax; } if ($user_currency == $this->default_currency) { $total = $this->back_convert($total, $currencies[$tmp_curr_currency]['rate']); } $wc_price = $this->wc_price($total, true); $html_value .= $this->get_cart_item_price_html($wc_price); $this->current_currency = $tmp_curr_currency; $this->storage->set_val('woocs_current_currency', $tmp_curr_currency); } return $html_value; }