public function set_base_tax_rates($rates, $tax_class) { $location = WC_Tax::get_tax_location($tax_class); if (in_array($tax_class, array('virtual-rate', 'virtual-reduced-rate')) && isset($location[0]) && sizeof($location) === 4 && $location[0] !== WC()->countries->get_base_country()) { list($country, $state, $postcode, $city) = $location; $rates = WC_Tax::find_rates(array('country' => $country, 'state' => $state, 'postcode' => $postcode, 'city' => $city, 'tax_class' => $tax_class)); } return $rates; }
/** * 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; }
public static function calculate_shipping_tax($shipping_amount, $order) { $tax_based_on = get_option('woocommerce_tax_based_on'); $wc_tax_enabled = get_option('woocommerce_calc_taxes'); // if taxes aren't enabled don't calculate them if ('no' === $wc_tax_enabled) { return 0; } if ('base' === $tax_based_on) { $default = wc_get_base_location(); $country = $default['country']; $state = $default['state']; $postcode = ''; $city = ''; } elseif ('billing' === $tax_based_on) { $country = $order->billing_country; $state = $order->billing_state; $postcode = $order->billing_postcode; $city = $order->billing_city; } else { $country = $order->shipping_country; $state = $order->shipping_state; $postcode = $order->shipping_postcode; $city = $order->shipping_city; } // Now calculate shipping tax $matched_tax_rates = array(); $tax_rates = WC_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']) && 'yes' === $rate['shipping']) { $matched_tax_rates[$key] = $rate; } } } $shipping_taxes = WC_Tax::calc_shipping_tax($shipping_amount, $matched_tax_rates); $shipping_tax_total = WC_Tax::round(array_sum($shipping_taxes)); return $shipping_tax_total; }
/** * Calc line tax */ public static function calc_line_taxes() { global $wpdb; check_ajax_referer('calc-totals', 'security'); if (!current_user_can('edit_shop_orders')) { die(-1); } $tax = new WC_Tax(); $order_id = absint($_POST['order_id']); $items = array(); $country = strtoupper(esc_attr($_POST['country'])); $state = strtoupper(esc_attr($_POST['state'])); $postcode = strtoupper(esc_attr($_POST['postcode'])); $city = wc_clean(esc_attr($_POST['city'])); $order = wc_get_order($order_id); $taxes = array(); $shipping_taxes = array(); // Parse the jQuery serialized items parse_str($_POST['items'], $items); // Prevent undefined warnings if (!isset($items['line_tax'])) { $items['line_tax'] = array(); } if (!isset($items['line_subtotal_tax'])) { $items['line_subtotal_tax'] = array(); } $items['order_taxes'] = array(); // Action $items = apply_filters('woocommerce_ajax_calc_line_taxes', $items, $order_id, $country, $_POST); // Get items and fees taxes if (isset($items['order_item_id'])) { $line_total = $line_subtotal = $order_item_tax_class = array(); foreach ($items['order_item_id'] as $item_id) { $item_id = absint($item_id); $line_total[$item_id] = isset($items['line_total'][$item_id]) ? wc_format_decimal($items['line_total'][$item_id]) : 0; $line_subtotal[$item_id] = isset($items['line_subtotal'][$item_id]) ? wc_format_decimal($items['line_subtotal'][$item_id]) : $line_total[$item_id]; $order_item_tax_class[$item_id] = isset($items['order_item_tax_class'][$item_id]) ? sanitize_text_field($items['order_item_tax_class'][$item_id]) : ''; $product_id = $order->get_item_meta($item_id, '_product_id', true); // Get product details if (get_post_type($product_id) == 'product') { $_product = wc_get_product($product_id); $item_tax_status = $_product->get_tax_status(); } else { $item_tax_status = 'taxable'; } if ('0' !== $order_item_tax_class[$item_id] && 'taxable' === $item_tax_status) { $tax_rates = WC_Tax::find_rates(array('country' => $country, 'state' => $state, 'postcode' => $postcode, 'city' => $city, 'tax_class' => $order_item_tax_class[$item_id])); $line_taxes = WC_Tax::calc_tax($line_total[$item_id], $tax_rates, false); $line_subtotal_taxes = WC_Tax::calc_tax($line_subtotal[$item_id], $tax_rates, false); // Set the new line_tax foreach ($line_taxes as $_tax_id => $_tax_value) { $items['line_tax'][$item_id][$_tax_id] = $_tax_value; } // Set the new line_subtotal_tax foreach ($line_subtotal_taxes as $_tax_id => $_tax_value) { $items['line_subtotal_tax'][$item_id][$_tax_id] = $_tax_value; } // 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); } } } } // Get shipping taxes if (isset($items['shipping_method_id'])) { $matched_tax_rates = array(); $tax_rates = WC_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']) && 'yes' == $rate['shipping']) { $matched_tax_rates[$key] = $rate; } } } $shipping_cost = $shipping_taxes = array(); foreach ($items['shipping_method_id'] as $item_id) { $item_id = absint($item_id); $shipping_cost[$item_id] = isset($items['shipping_cost'][$item_id]) ? wc_format_decimal($items['shipping_cost'][$item_id]) : 0; $_shipping_taxes = WC_Tax::calc_shipping_tax($shipping_cost[$item_id], $matched_tax_rates); // Set the new shipping_taxes foreach ($_shipping_taxes as $_tax_id => $_tax_value) { $items['shipping_taxes'][$item_id][$_tax_id] = $_tax_value; $shipping_taxes[$_tax_id] = isset($shipping_taxes[$_tax_id]) ? $shipping_taxes[$_tax_id] + $_tax_value : $_tax_value; } } } // Remove old tax rows $order->remove_order_items('tax'); // Add tax rows foreach (array_keys($taxes + $shipping_taxes) as $tax_rate_id) { $order->add_tax($tax_rate_id, isset($taxes[$tax_rate_id]) ? $taxes[$tax_rate_id] : 0, isset($shipping_taxes[$tax_rate_id]) ? $shipping_taxes[$tax_rate_id] : 0); } // Create the new order_taxes foreach ($order->get_taxes() as $tax_id => $tax_item) { $items['order_taxes'][$tax_id] = absint($tax_item['rate_id']); } // Save order items wc_save_order_items($order_id, $items); // Return HTML items $order = wc_get_order($order_id); $data = get_post_meta($order_id); include 'admin/meta-boxes/views/html-order-items.php'; die; }
function woocommerce_calc_line_taxes() { global $woocommerce; check_ajax_referer('calc-totals', 'security'); $tax = new WC_Tax(); $base_tax_amount = 0; $line_tax_amount = 0; $country = strtoupper(esc_attr($_POST['country'])); $state = strtoupper(esc_attr($_POST['state'])); $postcode = strtoupper(esc_attr($_POST['postcode'])); $line_subtotal = esc_attr($_POST['line_subtotal']); $line_total = esc_attr($_POST['line_total']); $item_id = esc_attr($_POST['item_id']); $tax_class = esc_attr($_POST['tax_class']); // Get product details $_product = new WC_Product($item_id); $item_tax_status = $_product->get_tax_status(); if ($item_tax_status == 'taxable') { $tax_rates = $tax->find_rates($country, $state, $postcode, $tax_class); $line_subtotal_tax_amount = rtrim(rtrim(number_format(array_sum($tax->calc_tax($line_subtotal, $tax_rates, false)), 4, '.', ''), '0'), '.'); $line_tax_amount = rtrim(rtrim(number_format(array_sum($tax->calc_tax($line_total, $tax_rates, false)), 4, '.', ''), '0'), '.'); } if ($line_subtotal_tax_amount < 0) { $line_subtotal_tax_amount = 0; } if ($line_tax_amount < 0) { $line_tax_amount = 0; } echo json_encode(array('line_subtotal_tax' => $line_subtotal_tax_amount, 'line_tax' => $line_tax_amount)); // Quit out die; }
public static function add_line_taxes($order_id) { global $wpdb; check_ajax_referer('calc-totals', 'security'); if (!current_user_can('edit_shop_orders')) { die(-1); } $tax = new WC_Tax(); $items = array(); $country = strtoupper(esc_attr($_POST['country'])); $state = strtoupper(esc_attr($_POST['state'])); $postcode = strtoupper(esc_attr($_POST['postcode'])); $city = wc_clean(esc_attr($_POST['city'])); $order = wc_get_order(absint($order_id)); $taxes = array(); $shipping_taxes = array(); // Parse the jQuery serialized items parse_str($_POST['items'], $items); // Prevent undefined warnings if (!isset($items['line_tax'])) { $items['line_tax'] = array(); } if (!isset($items['line_subtotal_tax'])) { $items['line_subtotal_tax'] = array(); } $items['order_taxes'] = array(); // Action $items = apply_filters('woocommerce_ajax_calc_line_taxes', $items, $order_id, $country, $_POST); // Get items and fees taxes if (isset($items['order_item_id'])) { $line_total = $line_subtotal = $order_item_tax_class = array(); foreach ($items['order_item_id'] as $parent_item_id) { $parent_item_id = absint($parent_item_id); $item_id = self::get_child_item_id($parent_item_id); if (empty($item_id)) { //no current suborder items continue; } $line_total[$item_id] = isset($items['line_total'][$parent_item_id]) ? wc_format_decimal($items['line_total'][$parent_item_id]) : 0; $line_subtotal[$item_id] = isset($items['line_subtotal'][$parent_item_id]) ? wc_format_decimal($items['line_subtotal'][$parent_item_id]) : $line_total[$parent_item_id]; $order_item_tax_class[$item_id] = isset($items['order_item_tax_class'][$parent_item_id]) ? sanitize_text_field($items['order_item_tax_class'][$parent_item_id]) : ''; $product_id = $order->get_item_meta($item_id, '_product_id', true); $vendor = yith_get_vendor($product_id, 'product'); if (!$vendor->is_valid()) { // no vnedor products continue; } $vendor_order_ids = $vendor->get_orders('suborder'); if (!in_array($order_id, $vendor_order_ids)) { // the current product isn't in the current suborder continue; } // Get product details if (get_post_type($product_id) == 'product') { $_product = wc_get_product($product_id); $item_tax_status = $_product->get_tax_status(); } else { $item_tax_status = 'taxable'; } if ('0' !== $order_item_tax_class[$item_id] && 'taxable' === $item_tax_status) { $tax_rates = WC_Tax::find_rates(array('country' => $country, 'state' => $state, 'postcode' => $postcode, 'city' => $city, 'tax_class' => $order_item_tax_class[$item_id])); $line_taxes = WC_Tax::calc_tax($line_total[$item_id], $tax_rates, false); $line_subtotal_taxes = WC_Tax::calc_tax($line_subtotal[$item_id], $tax_rates, false); // Set the new line_tax foreach ($line_taxes as $_tax_id => $_tax_value) { $items['line_tax'][$item_id][$_tax_id] = $_tax_value; } // Set the new line_subtotal_tax foreach ($line_subtotal_taxes as $_tax_id => $_tax_value) { $items['line_subtotal_tax'][$item_id][$_tax_id] = $_tax_value; } // 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); } } } } // Get shipping taxes if (isset($items['shipping_method_id'])) { $matched_tax_rates = array(); $tax_rates = WC_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']) && 'yes' == $rate['shipping']) { $matched_tax_rates[$key] = $rate; } } } $shipping_cost = $shipping_taxes = array(); foreach ($items['shipping_method_id'] as $item_id) { $item_id = absint($item_id); $shipping_cost[$item_id] = isset($items['shipping_cost'][$parent_item_id]) ? wc_format_decimal($items['shipping_cost'][$parent_item_id]) : 0; $_shipping_taxes = WC_Tax::calc_shipping_tax($shipping_cost[$item_id], $matched_tax_rates); // Set the new shipping_taxes foreach ($_shipping_taxes as $_tax_id => $_tax_value) { $items['shipping_taxes'][$item_id][$_tax_id] = $_tax_value; $shipping_taxes[$_tax_id] = isset($shipping_taxes[$_tax_id]) ? $shipping_taxes[$_tax_id] + $_tax_value : $_tax_value; } } } // Remove old tax rows $order->remove_order_items('tax'); // Add tax rows foreach (array_keys($taxes + $shipping_taxes) as $tax_rate_id) { $order->add_tax($tax_rate_id, isset($taxes[$tax_rate_id]) ? $taxes[$tax_rate_id] : 0, isset($shipping_taxes[$tax_rate_id]) ? $shipping_taxes[$tax_rate_id] : 0); } // Create the new order_taxes foreach ($order->get_taxes() as $tax_id => $tax_item) { $items['order_taxes'][$tax_id] = absint($tax_item['rate_id']); } foreach ($items as $meta_key => $meta_values) { if (is_array($meta_values)) { foreach ($meta_values as $key => $meta_value) { if ('order_taxes' == $meta_key) { continue; } else { if ('order_item_id' == $meta_key) { $child_item_id = self::get_child_item_id($meta_value); if ($child_item_id) { $items[$meta_key][$key] = $child_item_id; } else { unset($items[$meta_key][$key]); } } else { if ('meta_key' == $meta_key || 'meta_value' == $meta_key) { unset($items[$meta_key][$key]); } else { if ('line_tax' == $meta_key || 'line_subtotal_tax' == $meta_key || 'refund_line_tax' == $meta_key) { $line_tax_ids = $items[$meta_key]; $child_item_ids = array_keys($order->get_items()); foreach ($line_tax_ids as $line_tax_id => $line_tax_value) { if (!in_array($line_tax_id, $child_item_ids)) { unset($items[$meta_key][$line_tax_id]); } } } else { $child_item_id = self::get_child_item_id($meta_value); if ($child_item_id) { $items[$meta_key][$child_item_id] = $items[$meta_key][$key]; unset($items[$meta_key][$key]); } } } } } } } else { if ('_order_total' == $meta_key) { $items['_order_total'] = $order->get_total(); } } } if (!empty($items['order_item_id'])) { wc_save_order_items($order_id, $items); } }
/** * Calc line tax. */ public static function calc_line_taxes() { global $wpdb; check_ajax_referer('calc-totals', 'security'); if (!current_user_can('edit_shop_orders')) { die(-1); } $tax = new WC_Tax(); $tax_based_on = get_option('woocommerce_tax_based_on'); $order_id = absint($_POST['order_id']); $items = array(); $country = strtoupper(esc_attr($_POST['country'])); $state = strtoupper(esc_attr($_POST['state'])); $postcode = strtoupper(esc_attr($_POST['postcode'])); $city = wc_clean(esc_attr($_POST['city'])); $order = wc_get_order($order_id); $taxes = array(); $shipping_taxes = array(); $order_item_tax_classes = array(); // Default to base if ('base' === $tax_based_on || empty($country)) { $default = wc_get_base_location(); $country = $default['country']; $state = $default['state']; $postcode = ''; $city = ''; } // Parse the jQuery serialized items parse_str($_POST['items'], $items); // Prevent undefined warnings if (!isset($items['line_tax'])) { $items['line_tax'] = array(); } if (!isset($items['line_subtotal_tax'])) { $items['line_subtotal_tax'] = array(); } $items['order_taxes'] = array(); // Action $items = apply_filters('woocommerce_ajax_calc_line_taxes', $items, $order_id, $country, $_POST); $is_vat_exempt = get_post_meta($order_id, '_is_vat_exempt', true); // Tax is calculated only if tax is enabled and order is not vat exempted if (wc_tax_enabled() && $is_vat_exempt !== 'yes') { // Get items and fees taxes if (isset($items['order_item_id'])) { $line_total = $line_subtotal = array(); foreach ($items['order_item_id'] as $item_id) { $item_id = absint($item_id); $line_total[$item_id] = isset($items['line_total'][$item_id]) ? wc_format_decimal($items['line_total'][$item_id]) : 0; $line_subtotal[$item_id] = isset($items['line_subtotal'][$item_id]) ? wc_format_decimal($items['line_subtotal'][$item_id]) : $line_total[$item_id]; $order_item_tax_classes[$item_id] = isset($items['order_item_tax_class'][$item_id]) ? sanitize_text_field($items['order_item_tax_class'][$item_id]) : ''; $product_id = $order->get_item_meta($item_id, '_product_id', true); // Get product details if (get_post_type($product_id) == 'product') { $_product = wc_get_product($product_id); $item_tax_status = $_product->get_tax_status(); } else { $item_tax_status = 'taxable'; } if ('0' !== $order_item_tax_classes[$item_id] && 'taxable' === $item_tax_status) { $tax_rates = WC_Tax::find_rates(array('country' => $country, 'state' => $state, 'postcode' => $postcode, 'city' => $city, 'tax_class' => $order_item_tax_classes[$item_id])); $line_taxes = WC_Tax::calc_tax($line_total[$item_id], $tax_rates, false); $line_subtotal_taxes = WC_Tax::calc_tax($line_subtotal[$item_id], $tax_rates, false); // Set the new line_tax foreach ($line_taxes as $_tax_id => $_tax_value) { $items['line_tax'][$item_id][$_tax_id] = $_tax_value; } // Set the new line_subtotal_tax foreach ($line_subtotal_taxes as $_tax_id => $_tax_value) { $items['line_subtotal_tax'][$item_id][$_tax_id] = $_tax_value; } // 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); } } } } // Get shipping taxes if (isset($items['shipping_method_id'])) { $matched_tax_rates = array(); $order_item_tax_classes = array_unique(array_values($order_item_tax_classes)); // If multiple classes are found, use the first one. Don't bother with standard rate, we can get that later. if (sizeof($order_item_tax_classes) > 1 && !in_array('', $order_item_tax_classes)) { $tax_classes = WC_Tax::get_tax_classes(); foreach ($tax_classes as $tax_class) { $tax_class = sanitize_title($tax_class); if (in_array($tax_class, $order_item_tax_classes)) { $matched_tax_rates = WC_Tax::find_shipping_rates(array('country' => $country, 'state' => $state, 'postcode' => $postcode, 'city' => $city, 'tax_class' => $tax_class)); break; } } // If a single tax class is found, use it } elseif (sizeof($order_item_tax_classes) === 1) { $matched_tax_rates = WC_Tax::find_shipping_rates(array('country' => $country, 'state' => $state, 'postcode' => $postcode, 'city' => $city, 'tax_class' => $order_item_tax_classes[0])); } // Get standard rate if no taxes were found if (!sizeof($matched_tax_rates)) { $matched_tax_rates = WC_Tax::find_shipping_rates(array('country' => $country, 'state' => $state, 'postcode' => $postcode, 'city' => $city)); } $shipping_cost = $shipping_taxes = array(); foreach ($items['shipping_method_id'] as $item_id) { $item_id = absint($item_id); $shipping_cost[$item_id] = isset($items['shipping_cost'][$item_id]) ? wc_format_decimal($items['shipping_cost'][$item_id]) : 0; $_shipping_taxes = WC_Tax::calc_shipping_tax($shipping_cost[$item_id], $matched_tax_rates); // Set the new shipping_taxes foreach ($_shipping_taxes as $_tax_id => $_tax_value) { $items['shipping_taxes'][$item_id][$_tax_id] = $_tax_value; $shipping_taxes[$_tax_id] = isset($shipping_taxes[$_tax_id]) ? $shipping_taxes[$_tax_id] + $_tax_value : $_tax_value; } } } } // Remove old tax rows $order->remove_order_items('tax'); // Add tax rows foreach (array_keys($taxes + $shipping_taxes) as $tax_rate_id) { $order->add_tax($tax_rate_id, isset($taxes[$tax_rate_id]) ? $taxes[$tax_rate_id] : 0, isset($shipping_taxes[$tax_rate_id]) ? $shipping_taxes[$tax_rate_id] : 0); } // Create the new order_taxes foreach ($order->get_taxes() as $tax_id => $tax_item) { $items['order_taxes'][$tax_id] = absint($tax_item['rate_id']); } $items = apply_filters('woocommerce_ajax_after_calc_line_taxes', $items, $order_id, $country, $_POST); // Save order items wc_save_order_items($order_id, $items); // Return HTML items $order = wc_get_order($order_id); $data = get_post_meta($order_id); include 'admin/meta-boxes/views/html-order-items.php'; die; }
/** * TaxJar API call * * @return void */ public function taxjar_api_call($options = array()) { global $woocommerce; $this->_log(':::: TaxJar Plugin requested ::::'); // Process $options array and turn them into varibables $options = is_array($options) ? $options : array(); extract(array_replace_recursive(array('to_country' => null, 'to_state' => null, 'to_zip' => null, 'to_city' => null, 'amount' => null, 'shipping_amount' => null), $options)); // Initalize some variables & properties $store_settings = $this->get_store_settings(); $customer = $woocommerce->customer; $this->tax_rate = 0; $this->amount_to_collect = 0; $this->item_collectable = 0; $this->shipping_collectable = 0; $this->freight_taxable = 1; $this->has_nexus = 0; $this->tax_source = 'origin'; $this->rate_id = null; // Strict conditions to be met before API call can be conducted if (empty($to_state) || empty($to_country) || empty($to_zip) || $customer->is_vat_exempt()) { return false; } // Setup Vars for API call $to_zip = explode(',', $to_zip); $to_zip = array_shift($to_zip); $from_country = $store_settings['store_country_setting']; $from_state = $store_settings['store_state_setting']; $from_zip = $store_settings['taxjar_zip_code_setting']; $from_city = $store_settings['taxjar_city_setting']; $this->_log(':::: TaxJar API called ::::'); $url = $this->uri . 'taxes'; $body_string = sprintf('plugin=woo&to_state=%s&from_state=%s&amount=%s&shipping=%s&from_city=%s&from_zip=%s&to_city=%s&to_zip=%s&from_country=%s&to_country=%s&line_items[][quantity]=1&line_items[][unit_price]=%s', $to_state, $from_state, $amount, $shipping_amount, $from_city, $from_zip, $to_city, $to_zip, $from_country, $to_country, $amount); // Build the URL and Transient key $url = str_replace(' ', '%20', $url); $cache_key = hash('md5', $url . '/' . $body_string); // To check to see if we hit the API or not $taxjar_response = false; // Make sure we don't have a cached rate if (false === ($cache_value = wp_cache_get($cache_key, 'taxjar'))) { // Log this request $this->_log("Requesting: " . $url); // Make API call with API token in header $response = wp_remote_post($url, array('headers' => array('Authorization' => 'Token token="' . $this->settings['api_token'] . '"', 'Content-Type' => 'application/x-www-form-urlencoded'), 'user-agent' => $this->ua, 'body' => $body_string)); // Fail loudly if we get an error from wp_remote_post if (is_wp_error($response)) { new WP_Error('request', __("There was an error retrieving the tax rates. Please check your server configuration.")); } else { if (200 == $response['response']['code']) { // Log the response $this->_log("Received: " . $response['body']); // Decode Response $taxjar_response = json_decode($response['body']); $taxjar_response = $taxjar_response->tax; // Update Properties based on Response $this->has_nexus = (int) $taxjar_response->has_nexus; $this->tax_source = empty($taxjar_response->tax_source) ? 'origin' : $taxjar_response->tax_source; $this->amount_to_collect = $taxjar_response->amount_to_collect; if (!empty($taxjar_response->breakdown)) { if (!empty($taxjar_response->breakdown->shipping)) { $this->shipping_collectable = $taxjar_response->breakdown->shipping->tax_collectable; } $this->item_collectable = $this->amount_to_collect - $this->shipping_collectable; } $this->tax_rate = $taxjar_response->rate; $this->freight_taxable = (int) $taxjar_response->freight_taxable; // Create cache value $cache_value = $this->amount_to_collect . '::' . $this->tax_rate . '::' . $this->freight_taxable . '::' . $this->has_nexus . '::' . $this->tax_source . '::' . $this->item_collectable . '::' . $this->shipping_collectable; // Log the new cached value $this->_log("Cache Value: " . $cache_value); // Set Cache wp_cache_set($cache_key, $cache_value, 'taxjar', $this->cache_time); } else { // Log Response Error $this->_log("Received (" . $response['response']['code'] . "): " . $response['body']); } } } else { // Read the cached value based on our delimiter $cache_value = explode('::', $cache_value); // Set properties to the cached values $this->amount_to_collect = $cache_value[0]; $this->tax_rate = $cache_value[1]; $this->freight_taxable = $cache_value[2]; $this->has_nexus = $cache_value[3]; $this->tax_source = $cache_value[4]; $this->item_collectable = $cache_value[5]; $this->shipping_collectable = $cache_value[6]; // Log Cached Response $this->_log("Cached Amount: " . $this->amount_to_collect); $this->_log("Cached Nexus: " . $this->has_nexus); $this->_log("Cached Source: " . $this->tax_source); $this->_log("Cached Rate: " . $this->tax_rate); $this->_log("Shipping Taxable? " . $this->freight_taxable); $this->_log("Item Tax to Collect: " . $this->item_collectable); $this->_log("Shipping Tax to Collect: " . $this->shipping_collectable); } // Remove taxes if they are set somehow and customer is exempt if ($customer->is_vat_exempt()) { $wc_cart_object->remove_taxes(); } elseif ($this->has_nexus) { //} else { // Use Woo core to find matching rates for taxable address $source_zip = $this->tax_source == 'destination' ? $to_zip : $from_zip; $source_city = $this->tax_source == 'destination' ? $to_city : $from_city; if (strtoupper($to_city) == strtoupper($from_city)) { $source_city = $to_city; } // Setup Tax Rates $tax_rates = array("tax_rate_country" => $to_country, "tax_rate_state" => $to_state, "tax_rate_name" => sprintf("%s Tax", $to_state), "tax_rate_priority" => 1, "tax_rate_compound" => false, "tax_rate_shipping" => $this->freight_taxable, "tax_rate" => $this->tax_rate * 100, "tax_rate_class" => ''); // Clear the cached rates $this->clear_wc_tax_cache($to_country, $to_state, $source_city, $source_zip); $this->_log($source_city); $wc_rates = WC_Tax::find_rates(array('country' => $to_country, 'state' => $to_state, 'postcode' => $source_zip, 'city' => $source_city, 'tax_class' => '')); // If we have rates, use those, but if no rates returned create one to link with, or use the first rate returned. if (!empty($wc_rates)) { $this->_log('::: TAX RATES FOUND :::'); $this->_log($wc_rates); // Get the existing ID $rate_id = key($wc_rates); // Update Tax Rates with TaxJar rates ( rates might be coming from a cached taxjar rate ) $this->_log(':: UPDATING TAX RATES TO ::'); $this->_log($tax_rates); WC_TAX::_update_tax_rate($rate_id, $tax_rates); } else { // Insert a rate if we did not find one $this->_log(':: Adding New Tax Rate ::'); $rate_id = WC_Tax::_insert_tax_rate($tax_rates); WC_Tax::_update_tax_rate_postcodes($rate_id, wc_clean($source_zip)); WC_Tax::_update_tax_rate_cities($rate_id, wc_clean($source_city)); } $this->_log('Tax Rate ID Set: ' . $rate_id); $this->rate_id = $rate_id; } }
function get_package_shipping_rates($package = array()) { global $woocommerce; $_tax = new WC_Tax(); // See if we have an explicitly set shipping tax class if ($shipping_tax_class = get_option('woocommerce_shipping_tax_class')) { $tax_class = $shipping_tax_class == 'standard' ? '' : $shipping_tax_class; } if (isset($package['full_address']) && !empty($package['full_address'])) { $country = $package['full_address']['country']; $state = $package['full_address']['state']; $postcode = $package['full_address']['postcode']; $city = $package['full_address']['city']; } else { // Prices which include tax should always use the base rate if we don't know where the user is located // Prices excluding tax however should just not add any taxes, as they will be added during checkout if (get_option('woocommerce_prices_include_tax') == 'yes' || get_option('woocommerce_default_customer_address') == 'base') { $country = $woocommerce->countries->get_base_country(); $state = $woocommerce->countries->get_base_state(); $postcode = ''; $city = ''; } else { return array(); } } // If we are here then shipping is taxable - work it out // This will be per order shipping - loop through the order and find the highest tax class rate $found_tax_classes = array(); $matched_tax_rates = array(); $rates = false; // Loop cart and find the highest tax band if (sizeof($woocommerce->cart->get_cart()) > 0) { foreach ($woocommerce->cart->get_cart() as $item) { $found_tax_classes[] = $item['data']->get_tax_class(); } } $found_tax_classes = array_unique($found_tax_classes); // If multiple classes are found, use highest if (sizeof($found_tax_classes) > 1) { if (in_array('', $found_tax_classes)) { $rates = $_tax->find_rates(array('country' => $country, 'state' => $state, 'city' => $city, 'postcode' => $postcode)); } else { $tax_classes = array_filter(array_map('trim', explode("\n", get_option('woocommerce_tax_classes')))); foreach ($tax_classes as $tax_class) { if (in_array($tax_class, $found_tax_classes)) { $rates = $_tax->find_rates(array('country' => $country, 'state' => $state, 'postcode' => $postcode, 'city' => $city, 'tax_class' => $tax_class)); break; } } } // If a single tax class is found, use it } elseif (sizeof($found_tax_classes) == 1) { $rates = $_tax->find_rates(array('country' => $country, 'state' => $state, 'postcode' => $postcode, 'city' => $city, 'tax_class' => $found_tax_classes[0])); } // If no class rate are found, use standard rates if (!$rates) { $rates = $_tax->find_rates(array('country' => $country, 'state' => $state, 'postcode' => $postcode, 'city' => $city)); } if ($rates) { foreach ($rates as $key => $rate) { if (isset($rate['shipping']) && $rate['shipping'] == 'yes') { $matched_tax_rates[$key] = $rate; } } } return $matched_tax_rates; }
/** * 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; }
/** * Shipping tax amounts. */ public function test_calc_shipping_tax() { global $wpdb; $wpdb->query("DELETE FROM {$wpdb->prefix}woocommerce_tax_rates"); $wpdb->query("DELETE FROM {$wpdb->prefix}woocommerce_tax_rate_locations"); $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' => '0', 'tax_rate_shipping' => '1', 'tax_rate_order' => '1', 'tax_rate_class' => ''); $tax_rate_id = WC_Tax::_insert_tax_rate($tax_rate); $tax_rates = WC_Tax::find_rates(array('country' => 'GB', 'state' => 'Cambs', 'postcode' => 'PE14 1XX', 'city' => 'Somewhere', 'tax_class' => '')); $calced_tax = WC_Tax::calc_shipping_tax('10', $tax_rates); $this->assertEquals($calced_tax, array($tax_rate_id => '2')); WC_Tax::_delete_tax_rate($tax_rate_id); }
/** * Calculate taxes for all line items and shipping, and store the totals and tax rows. * * Will use the base country unless customer addresses are set. * * @return bool success or fail. */ public function calculate_taxes() { $tax_total = 0; $shipping_tax_total = 0; $taxes = array(); $shipping_taxes = array(); $tax_based_on = get_option('woocommerce_tax_based_on'); // If is_vat_exempt is 'yes', or wc_tax_enabled is false, return and do nothing. if ('yes' === $this->is_vat_exempt || !wc_tax_enabled()) { return false; } if ('billing' === $tax_based_on) { $country = $this->billing_country; $state = $this->billing_state; $postcode = $this->billing_postcode; $city = $this->billing_city; } elseif ('shipping' === $tax_based_on) { $country = $this->shipping_country; $state = $this->shipping_state; $postcode = $this->shipping_postcode; $city = $this->shipping_city; } // Default to base if ('base' === $tax_based_on || empty($country)) { $default = wc_get_base_location(); $country = $default['country']; $state = $default['state']; $postcode = ''; $city = ''; } // Get items foreach ($this->get_items(array('line_item', 'fee')) as $item_id => $item) { $product = $this->get_product_from_item($item); $line_total = isset($item['line_total']) ? $item['line_total'] : 0; $line_subtotal = isset($item['line_subtotal']) ? $item['line_subtotal'] : 0; $tax_class = $item['tax_class']; $item_tax_status = $product ? $product->get_tax_status() : 'taxable'; if ('0' !== $tax_class && 'taxable' === $item_tax_status) { $tax_rates = WC_Tax::find_rates(array('country' => $country, 'state' => $state, 'postcode' => $postcode, 'city' => $city, 'tax_class' => $tax_class)); $line_subtotal_taxes = WC_Tax::calc_tax($line_subtotal, $tax_rates, false); $line_taxes = WC_Tax::calc_tax($line_total, $tax_rates, false); $line_subtotal_tax = max(0, array_sum($line_subtotal_taxes)); $line_tax = max(0, array_sum($line_taxes)); $tax_total += $line_tax; wc_update_order_item_meta($item_id, '_line_subtotal_tax', wc_format_decimal($line_subtotal_tax)); wc_update_order_item_meta($item_id, '_line_tax', wc_format_decimal($line_tax)); wc_update_order_item_meta($item_id, '_line_tax_data', array('total' => $line_taxes, 'subtotal' => $line_subtotal_taxes)); // 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); } } } // Calc taxes for shipping foreach ($this->get_shipping_methods() as $item_id => $item) { $shipping_tax_class = get_option('woocommerce_shipping_tax_class'); // Inherit tax class from items if ('' === $shipping_tax_class) { $tax_classes = WC_Tax::get_tax_classes(); foreach ($tax_classes as $tax_class) { $tax_class = sanitize_title($tax_class); if (in_array($tax_class, $found_tax_classes)) { $tax_rates = WC_Tax::find_shipping_rates(array('country' => $country, 'state' => $state, 'postcode' => $postcode, 'city' => $city, 'tax_class' => $tax_class)); break; } } } else { $tax_rates = WC_Tax::find_shipping_rates(array('country' => $country, 'state' => $state, 'postcode' => $postcode, 'city' => $city, 'tax_class' => 'standard' === $shipping_tax_class ? '' : $shipping_tax_class)); } $line_taxes = WC_Tax::calc_tax($item['cost'], $tax_rates, false); $line_tax = max(0, array_sum($line_taxes)); $shipping_tax_total += $line_tax; wc_update_order_item_meta($item_id, '_line_tax', wc_format_decimal($line_tax)); wc_update_order_item_meta($item_id, '_line_tax_data', array('total' => $line_taxes)); // Sum the item taxes foreach (array_keys($shipping_taxes + $line_taxes) as $key) { $shipping_taxes[$key] = (isset($line_taxes[$key]) ? $line_taxes[$key] : 0) + (isset($shipping_taxes[$key]) ? $shipping_taxes[$key] : 0); } } // Save tax totals $this->set_total($shipping_tax_total, 'shipping_tax'); $this->set_total($tax_total, 'tax'); // Tax rows $this->remove_order_items('tax'); // Now merge to keep tax rows foreach (array_keys($taxes + $shipping_taxes) as $tax_rate_id) { $this->add_tax($tax_rate_id, isset($taxes[$tax_rate_id]) ? $taxes[$tax_rate_id] : 0, isset($shipping_taxes[$tax_rate_id]) ? $shipping_taxes[$tax_rate_id] : 0); } return true; }
/** * @used-by callback_init_combined_tax_classes */ private static function init_tax_classes() { $standard_class_pos = array_search('Standard', static::$predefined_tax_classes); if ($standard_class_pos !== FALSE) { $tax_classes = array_merge(array_slice(static::$predefined_tax_classes, 0, $standard_class_pos), array_slice(static::$predefined_tax_classes, $standard_class_pos + 1)); } else { $tax_classes =& static::$predefined_tax_classes; } $redefined = array_map('trim', array_merge($tax_classes, array_diff(WC_Tax::get_tax_classes(), $tax_classes))); update_option('woocommerce_tax_classes', implode("\n", $redefined)); /////////////////////////////////////////////// // check and add '과세 상품' class $taxed_class = sanitize_title(static::$predefined_tax_classes[0]); /** @var array $taxed following keys are present: * - rate * - label * - shipping * - compound */ $taxed = WC_Tax::find_rates(array('country' => 'KR', 'state' => '', 'city' => '', 'postcode' => '', 'tax_class' => $taxed_class)); $taxed_rate_label = static::$predefined_tax_rates[0]; //과세율 $taxed_rate_found = static::find_tax_rate_label($taxed, $taxed_rate_label); if (!$taxed_rate_found) { WC_Tax::_insert_tax_rate(array('tax_rate_country' => 'KR', 'tax_rate_state' => '', 'tax_rate' => '10.00', 'tax_rate_name' => $taxed_rate_label, 'tax_rate_priority' => 1, 'tax_rate_shipping' => 1, 'tax_rate_compound' => 0, 'tax_rate_order' => 0, 'tax_rate_class' => $taxed_class)); } /////////////////////////////////////////////// // check and add '비과세 상품' class $untaxed_class = sanitize_title(static::$predefined_tax_classes[1]); /** @var array $untaxed */ $untaxed = WC_Tax::find_rates(array('country' => 'KR', 'state' => '', 'city' => '', 'postcode' => '', 'tax_class' => $untaxed_class)); $untaxed_rate_label = static::$predefined_tax_rates[1]; // 비과세율 $untaxed_rate_found = static::find_tax_rate_label($untaxed, $untaxed_rate_label); if (!$untaxed_rate_found) { WC_Tax::_insert_tax_rate(array('tax_rate_country' => 'KR', 'tax_rate_state' => '', 'tax_rate' => '0.00', 'tax_rate_name' => $untaxed_rate_label, 'tax_rate_priority' => 1, 'tax_rate_shipping' => 0, 'tax_rate_compound' => 0, 'tax_rate_order' => 0, 'tax_rate_class' => $untaxed_class)); } }
/** * Calculate taxes for all line items and shipping, and store the totals and tax rows. * * Will use the base country unless customer addresses are set. * @param $args array Added in 2.7.0 to pass things like location. */ public function calculate_taxes($args = array()) { $tax_based_on = get_option('woocommerce_tax_based_on'); $args = wp_parse_args($args, array('country' => 'billing' === $tax_based_on ? $this->get_billing_country() : $this->get_shipping_country(), 'state' => 'billing' === $tax_based_on ? $this->get_billing_state() : $this->get_shipping_state(), 'postcode' => 'billing' === $tax_based_on ? $this->get_billing_postcode() : $this->get_shipping_postcode(), 'city' => 'billing' === $tax_based_on ? $this->get_billing_city() : $this->get_shipping_city())); // Default to base if ('base' === $tax_based_on || empty($args['country'])) { $default = wc_get_base_location(); $args['country'] = $default['country']; $args['state'] = $default['state']; $args['postcode'] = ''; $args['city'] = ''; } // Calc taxes for line items foreach ($this->get_items(array('line_item', 'fee')) as $item_id => $item) { $tax_class = $item->get_tax_class(); $tax_status = $item->get_tax_status(); if ('0' !== $tax_class && 'taxable' === $tax_status) { $tax_rates = WC_Tax::find_rates(array('country' => $args['country'], 'state' => $args['state'], 'postcode' => $args['postcode'], 'city' => $args['city'], 'tax_class' => $tax_class)); $total = $item->get_total(); $taxes = WC_Tax::calc_tax($total, $tax_rates, false); if ($item->is_type('line_item')) { $subtotal = $item->get_subtotal(); $subtotal_taxes = WC_Tax::calc_tax($subtotal, $tax_rates, false); $item->set_taxes(array('total' => $taxes, 'subtotal' => $subtotal_taxes)); } else { $item->set_taxes(array('total' => $taxes)); } $item->save(); } } // Calc taxes for shipping foreach ($this->get_shipping_methods() as $item_id => $item) { $shipping_tax_class = get_option('woocommerce_shipping_tax_class'); // Inherit tax class from items if ('' === $shipping_tax_class) { $tax_rates = array(); $tax_classes = array_merge(array(''), WC_Tax::get_tax_classes()); $found_tax_classes = $this->get_items_tax_classes(); foreach ($tax_classes as $tax_class) { $tax_class = sanitize_title($tax_class); if (in_array($tax_class, $found_tax_classes)) { $tax_rates = WC_Tax::find_shipping_rates(array('country' => $args['country'], 'state' => $args['state'], 'postcode' => $args['postcode'], 'city' => $args['city'], 'tax_class' => $tax_class)); break; } } } else { $tax_rates = WC_Tax::find_shipping_rates(array('country' => $args['country'], 'state' => $args['state'], 'postcode' => $args['postcode'], 'city' => $args['city'], 'tax_class' => 'standard' === $shipping_tax_class ? '' : $shipping_tax_class)); } $item->set_taxes(array('total' => WC_Tax::calc_tax($item->get_total(), $tax_rates, false))); $item->save(); } $this->update_taxes(); }
/** * Calculate wcmp vendor shipping tax * * @param double $shipping_amount * @param object $order */ public function calculate_shipping_tax($shipping_amount, $order) { global $WCMp, $woocommerce; $wc_tax_enabled = get_option('woocommerce_calc_taxes'); if ('no' === $wc_tax_enabled) { return 0; } $tax_based_on = get_option('woocommerce_tax_based_on'); $WC_Tax = new WC_Tax(); if ('base' === $tax_based_on) { $default = wc_get_base_location(); $country = $default['country']; $state = $default['state']; $postcode = ''; $city = ''; } elseif ('billing' === $tax_based_on) { $country = $order->billing_country; $state = $order->billing_state; $postcode = $order->billing_postcode; $city = $order->billing_city; } else { $country = $order->shipping_country; $state = $order->shipping_state; $postcode = $order->shipping_postcode; $city = $order->shipping_city; } $matched_tax_rates = array(); $tax_rates = $WC_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']) && 'yes' === $rate['shipping']) { $matched_tax_rates[$key] = $rate; } } } $vendor_shipping_taxes = $WC_Tax->calc_shipping_tax($shipping_amount, $matched_tax_rates); $vendor_shipping_tax_total = $WC_Tax->round(array_sum($vendor_shipping_taxes)); return $vendor_shipping_tax_total; }
/** * Calculate taxes for all line items and shipping, and store the totals and tax rows. * * Will use the base country unless customer addresses are set. * * @return bool success or fail */ public function calculate_taxes() { $tax_total = 0; $taxes = array(); $tax_based_on = get_option('woocommerce_tax_based_on'); if ('billing' === $tax_based_on) { $country = $this->billing_country; $state = $this->billing_state; $postcode = $this->billing_postcode; $city = $this->billing_city; } elseif ('shipping' === $tax_based_on) { $country = $this->shipping_country; $state = $this->shipping_state; $postcode = $this->shipping_postcode; $city = $this->shipping_city; } // Default to base if ('base' === $tax_based_on || empty($country)) { $default = wc_get_base_location(); $country = $default['country']; $state = $default['state']; $postcode = ''; $city = ''; } // Get items foreach ($this->get_items(array('line_item', 'fee')) as $item_id => $item) { $product = $this->get_product_from_item($item); $line_total = isset($item['line_total']) ? $item['line_total'] : 0; $line_subtotal = isset($item['line_subtotal']) ? $item['line_subtotal'] : 0; $tax_class = $item['tax_class']; $item_tax_status = $product ? $product->get_tax_status() : 'taxable'; if ('0' !== $tax_class && 'taxable' === $item_tax_status) { $tax_rates = WC_Tax::find_rates(array('country' => $country, 'state' => $state, 'postcode' => $postcode, 'city' => $city, 'tax_class' => $tax_class)); $line_subtotal_taxes = WC_Tax::calc_tax($line_subtotal, $tax_rates, false); $line_taxes = WC_Tax::calc_tax($line_total, $tax_rates, false); $line_subtotal_tax = max(0, array_sum($line_subtotal_taxes)); $line_tax = max(0, array_sum($line_taxes)); $tax_total += $line_tax; wc_update_order_item_meta($item_id, '_line_subtotal_tax', wc_format_decimal($line_subtotal_tax)); wc_update_order_item_meta($item_id, '_line_tax', wc_format_decimal($line_tax)); wc_update_order_item_meta($item_id, '_line_tax_data', array('total' => $line_taxes, 'subtotal' => $line_subtotal_taxes)); // 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 = WC_Tax::find_rates(array('country' => $country, 'state' => $state, 'postcode' => $postcode, 'city' => $city, 'tax_class' => '')); if (!empty($tax_rates)) { foreach ($tax_rates as $key => $rate) { if (isset($rate['shipping']) && 'yes' === $rate['shipping']) { $matched_tax_rates[$key] = $rate; } } } $shipping_taxes = WC_Tax::calc_shipping_tax($this->order_shipping, $matched_tax_rates); $shipping_tax_total = WC_Tax::round(array_sum($shipping_taxes)); // Save tax totals $this->set_total($shipping_tax_total, 'shipping_tax'); $this->set_total($tax_total, 'tax'); // Tax rows $this->remove_order_items('tax'); // Now merge to keep tax rows foreach (array_keys($taxes + $shipping_taxes) as $tax_rate_id) { $this->add_tax($tax_rate_id, isset($taxes[$tax_rate_id]) ? $taxes[$tax_rate_id] : 0, isset($shipping_taxes[$tax_rate_id]) ? $shipping_taxes[$tax_rate_id] : 0); } return true; }
protected function _calculate_fee_taxes(&$order) { $tax_total = 0; $shipping_tax_total = 0; $taxes = array(); $shipping_taxes = array(); $tax_based_on = get_option('woocommerce_tax_based_on'); // If is_vat_exempt is 'yes', or wc_tax_enabled is false, return and do nothing. if ('yes' === $order->is_vat_exempt || !wc_tax_enabled()) { return false; } if ('billing' === $tax_based_on) { $country = $order->billing_country; $state = $order->billing_state; $postcode = $order->billing_postcode; $city = $order->billing_city; } elseif ('shipping' === $tax_based_on) { $country = $order->shipping_country; $state = $order->shipping_state; $postcode = $order->shipping_postcode; $city = $order->shipping_city; } // Default to base if ('base' === $tax_based_on || empty($country)) { $default = wc_get_base_location(); $country = $default['country']; $state = $default['state']; $postcode = ''; $city = ''; } // Get items foreach ($order->get_items(array('fee')) as $item_id => $item) { $product = $order->get_product_from_item($item); $line_total = isset($item['line_total']) ? $item['line_total'] : 0; $line_subtotal = isset($item['line_subtotal']) ? $item['line_subtotal'] : 0; $tax_class = $item['tax_class']; $item_tax_status = $product ? $product->get_tax_status() : 'taxable'; if ('0' !== $tax_class && 'taxable' === $item_tax_status) { $tax_rates = WC_Tax::find_rates(array('country' => $country, 'state' => $state, 'postcode' => $postcode, 'city' => $city, 'tax_class' => $tax_class)); $line_subtotal_taxes = WC_Tax::calc_tax($line_subtotal, $tax_rates, false); $line_taxes = WC_Tax::calc_tax($line_total, $tax_rates, false); $line_subtotal_tax = max(0, array_sum($line_subtotal_taxes)); $line_tax = max(0, array_sum($line_taxes)); $tax_total += $line_tax; wc_update_order_item_meta($item_id, '_line_subtotal_tax', wc_format_decimal($line_subtotal_tax)); wc_update_order_item_meta($item_id, '_line_tax', wc_format_decimal($line_tax)); wc_update_order_item_meta($item_id, '_line_tax_data', array('total' => $line_taxes, 'subtotal' => $line_subtotal_taxes)); // 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); } } } }