Searches for all matching country/state/postcode tax rates.
public static find_shipping_rates ( array $args = [] ) : array | ||
$args | array | |
Résultat | array |
/** * Find tax rates. */ public function test_find_shipping_rates() { 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_shipping_rates(array('country' => 'GB', 'state' => 'Cambs', 'postcode' => 'PE14 1XX', 'city' => 'Somewhere', 'tax_class' => '')); $this->assertEquals($tax_rates, array($tax_rate_id => array('rate' => '20.0000', 'label' => 'VAT', 'shipping' => 'yes', 'compound' => 'no'))); 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. * @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(); }
/** * 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; }
/** * 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; }
protected function _calculate_shipping_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; } // Calc taxes for shipping foreach ($order->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(); $found_tax_classes = $order->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' => $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); } wc_update_order_item_meta($item_id, 'taxes', $shipping_taxes); } // Save tax totals $order->set_total($shipping_tax_total, 'shipping_tax'); // $order->set_total( $tax_total, 'tax' ); }