find_rates() public static method

Searches for all matching country/state/postcode tax rates.
public static find_rates ( array $args = [] ) : array
$args array
return array
 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;
 }
示例#2
0
/**
 * 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;
 }
示例#4
0
 /**
  * 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;
}
示例#6
0
 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);
     }
 }
示例#7
0
 /**
  * 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;
 }
示例#11
0
 /**
  * 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));
     }
 }
示例#14
0
 /**
  * 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);
             }
         }
     }
 }