calc_shipping_tax() public static method

Calculate the shipping tax using a passed array of rates.
public static calc_shipping_tax ( $price, $rates ) : array
return array
 /**
  * Create a order.
  *
  * @since 2.4
  *
  * @return WC_Order Order object.
  */
 public static function create_order()
 {
     // Create product
     $product = WC_Helper_Product::create_simple_product();
     WC_Helper_Shipping::create_simple_flat_rate();
     $order_data = array('status' => 'pending', 'customer_id' => 1, 'customer_note' => '', 'total' => '');
     $_SERVER['REMOTE_ADDR'] = '127.0.0.1';
     // Required, else wc_create_order throws an exception
     $order = wc_create_order($order_data);
     // Add order products
     $item_id = $order->add_product($product, 4);
     // Set billing address
     $billing_address = array('country' => 'US', 'first_name' => 'Jeroen', 'last_name' => 'Sormani', 'company' => 'WooCompany', 'address_1' => 'WooAddress', 'address_2' => '', 'postcode' => '123456', 'city' => 'WooCity', 'state' => 'NY', 'email' => '*****@*****.**', 'phone' => '555-32123');
     $order->set_address($billing_address, 'billing');
     // Add shipping costs
     $shipping_taxes = WC_Tax::calc_shipping_tax('10', WC_Tax::get_shipping_tax_rates());
     $order->add_shipping(new WC_Shipping_Rate('flat_rate_shipping', 'Flat rate shipping', '10', $shipping_taxes, 'flat_rate'));
     // Set payment gateway
     $payment_gateways = WC()->payment_gateways->payment_gateways();
     $order->set_payment_method($payment_gateways['bacs']);
     // Set totals
     $order->set_total(10, 'shipping');
     $order->set_total(0, 'cart_discount');
     $order->set_total(0, 'cart_discount_tax');
     $order->set_total(0, 'tax');
     $order->set_total(0, 'shipping_tax');
     $order->set_total(40, 'total');
     // 4 x $10 simple helper product
     return wc_get_order($order->id);
 }
 /**
  * Create a order.
  *
  * @since 2.4
  *
  * @return WC_Order Order object.
  */
 public static function create_order($customer_id = 1)
 {
     // Create product
     $product = WC_Helper_Product::create_simple_product();
     WC_Helper_Shipping::create_simple_flat_rate();
     $order_data = array('status' => 'pending', 'customer_id' => $customer_id, 'customer_note' => '', 'total' => '');
     $_SERVER['REMOTE_ADDR'] = '127.0.0.1';
     // Required, else wc_create_order throws an exception
     $order = wc_create_order($order_data);
     // Add order products
     $order->add_product($product, 4);
     // Set billing address
     $order->set_billing_first_name('Jeroen');
     $order->set_billing_last_name('Sormani');
     $order->set_billing_company('WooCompany');
     $order->set_billing_address_1('WooAddress');
     $order->set_billing_address_2('');
     $order->set_billing_city('WooCity');
     $order->set_billing_state('NY');
     $order->set_billing_postcode('123456');
     $order->set_billing_country('US');
     $order->set_billing_email('*****@*****.**');
     $order->set_billing_phone('555-32123');
     // Add shipping costs
     $shipping_taxes = WC_Tax::calc_shipping_tax('10', WC_Tax::get_shipping_tax_rates());
     $rate = new WC_Shipping_Rate('flat_rate_shipping', 'Flat rate shipping', '10', $shipping_taxes, 'flat_rate');
     $item = new WC_Order_Item_Shipping();
     $item->set_props(array('method_title' => $rate->label, 'method_id' => $rate->id, 'total' => wc_format_decimal($rate->cost), 'taxes' => $rate->taxes, 'meta_data' => $rate->get_meta_data()));
     $order->add_item($item);
     // Set payment gateway
     $payment_gateways = WC()->payment_gateways->payment_gateways();
     $order->set_payment_method($payment_gateways['bacs']);
     // Set totals
     $order->set_shipping_total(10);
     $order->set_discount_total(0);
     $order->set_discount_tax(0);
     $order->set_cart_tax(0);
     $order->set_shipping_tax(0);
     $order->set_total(40);
     // 4 x $10 simple helper product
     $order->save();
     return $order;
 }
 /**
  * Add a rate
  *
  * A a shipping rate. If taxes are not set they will be calculated based on cost.
  */
 function add_rate($args = array())
 {
     global $woocommerce;
     $defaults = array('id' => '', 'label' => '', 'cost' => '0', 'taxes' => '', 'calc_tax' => 'per_order');
     $args = wp_parse_args($args, $defaults);
     extract($args);
     // Id and label are required
     if (!$id || !$label) {
         return;
     }
     // Handle cost
     $total_cost = is_array($cost) ? array_sum($cost) : $cost;
     // Taxes - if not an array and not set to false, calc tax based on cost and passed calc_tax variable
     // This saves shipping methods having to do compelex tax calculations
     if (!is_array($taxes) && $taxes !== false && $total_cost > 0 && get_option('woocommerce_calc_taxes') == 'yes' && $this->tax_status == 'taxable') {
         $_tax = new WC_Tax();
         $taxes = array();
         switch ($calc_tax) {
             case "per_item":
                 // If we have an array of costs we can look up each items tax class and add tax accordingly
                 if (is_array($cost)) {
                     $cart = $woocommerce->cart->get_cart();
                     foreach ($cost as $cost_key => $amount) {
                         if (!isset($cart[$cost_key])) {
                             continue;
                         }
                         $_product = $cart[$cost_key]['data'];
                         $rates = $_tax->get_shipping_tax_rates($_product->get_tax_class());
                         $item_taxes = $_tax->calc_shipping_tax($amount, $rates);
                         // Sum the item taxes
                         foreach (array_keys($taxes + $item_taxes) as $key) {
                             $taxes[$key] = (isset($item_taxes[$key]) ? $item_taxes[$key] : 0) + (isset($taxes[$key]) ? $taxes[$key] : 0);
                         }
                     }
                     // Add any cost for the order - order costs are in the key 'order'
                     if (isset($cost['order'])) {
                         $rates = $_tax->get_shipping_tax_rates();
                         $item_taxes = $_tax->calc_shipping_tax($cost['order'], $rates);
                         // Sum the item taxes
                         foreach (array_keys($taxes + $item_taxes) as $key) {
                             $taxes[$key] = (isset($item_taxes[$key]) ? $item_taxes[$key] : 0) + (isset($taxes[$key]) ? $taxes[$key] : 0);
                         }
                     }
                 }
                 break;
             default:
                 $rates = $_tax->get_shipping_tax_rates();
                 $taxes = $_tax->calc_shipping_tax($total_cost, $rates);
                 break;
         }
     }
     $this->rates[] = new WC_Shipping_Rate($id, $label, $total_cost, $taxes);
 }
 /**
  * Calculate shipping when this method is used standalone.
  */
 public function calculate_shipping($package)
 {
     $_tax = new WC_Tax();
     $taxes = array();
     $shipping_cost = 0;
     // This shipping method loops through products, adding up the cost
     if (sizeof($package['contents']) > 0) {
         foreach ($package['contents'] as $item_id => $values) {
             if ($values['quantity'] > 0) {
                 if ($values['data']->needs_shipping()) {
                     $rule = false;
                     $item_shipping_cost = 0;
                     if ($values['variation_id']) {
                         $rule = woocommerce_per_product_shipping_get_matching_rule($values['variation_id'], $package);
                     }
                     if ($rule === false) {
                         $rule = woocommerce_per_product_shipping_get_matching_rule($values['product_id'], $package);
                     }
                     if ($rule) {
                         $item_shipping_cost += $rule->rule_item_cost * $values['quantity'];
                         $item_shipping_cost += $rule->rule_cost;
                     } elseif ($this->cost === '0' || $this->cost > 0) {
                         // Use default
                         $item_shipping_cost += $this->cost * $values['quantity'];
                     } else {
                         // NO default and nothing found - abort
                         return;
                     }
                     // Fee
                     $item_shipping_cost += $this->get_fee($this->fee, $item_shipping_cost) * $values['quantity'];
                     $shipping_cost += $item_shipping_cost;
                     if (get_option('woocommerce_calc_taxes') == 'yes' && $this->tax_status == 'taxable') {
                         $rates = $_tax->get_shipping_tax_rates($values['data']->get_tax_class());
                         $item_taxes = $_tax->calc_shipping_tax($item_shipping_cost, $rates);
                         // Sum the item taxes
                         foreach (array_keys($taxes + $item_taxes) as $key) {
                             $taxes[$key] = (isset($item_taxes[$key]) ? $item_taxes[$key] : 0) + (isset($taxes[$key]) ? $taxes[$key] : 0);
                         }
                     }
                 }
             }
         }
     }
     // Add order shipping cost + tax
     if ($this->order_fee) {
         $order_fee = $this->get_fee($this->order_fee, $shipping_cost);
         $shipping_cost += $order_fee;
         if (get_option('woocommerce_calc_taxes') == 'yes' && $this->tax_status == 'taxable') {
             $rates = $_tax->get_shipping_tax_rates();
             $item_taxes = $_tax->calc_shipping_tax($order_fee, $rates);
             // Sum the item taxes
             foreach (array_keys($taxes + $item_taxes) as $key) {
                 $taxes[$key] = (isset($item_taxes[$key]) ? $item_taxes[$key] : 0) + (isset($taxes[$key]) ? $taxes[$key] : 0);
             }
         }
     }
     // Add rate
     $this->add_rate(array('id' => $this->id, 'label' => $this->title, 'cost' => $shipping_cost, 'taxes' => $taxes));
 }
 /**
  * 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;
 }
Exemplo n.º 6
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;
     $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;
 }
 /**
  * Calc taxes per item being shipping in costs array.
  * @since 2.6.0
  * @access protected
  * @param  array $costs
  * @return array of taxes
  */
 protected function get_taxes_per_item($costs)
 {
     $taxes = array();
     // If we have an array of costs we can look up each items tax class and add tax accordingly
     if (is_array($costs)) {
         $cart = WC()->cart->get_cart();
         foreach ($costs as $cost_key => $amount) {
             if (!isset($cart[$cost_key])) {
                 continue;
             }
             $item_taxes = WC_Tax::calc_shipping_tax($amount, WC_Tax::get_shipping_tax_rates($cart[$cost_key]['data']->get_tax_class()));
             // Sum the item taxes
             foreach (array_keys($taxes + $item_taxes) as $key) {
                 $taxes[$key] = (isset($item_taxes[$key]) ? $item_taxes[$key] : 0) + (isset($taxes[$key]) ? $taxes[$key] : 0);
             }
         }
         // Add any cost for the order - order costs are in the key 'order'
         if (isset($costs['order'])) {
             $item_taxes = WC_Tax::calc_shipping_tax($costs['order'], WC_Tax::get_shipping_tax_rates());
             // Sum the item taxes
             foreach (array_keys($taxes + $item_taxes) as $key) {
                 $taxes[$key] = (isset($item_taxes[$key]) ? $item_taxes[$key] : 0) + (isset($taxes[$key]) ? $taxes[$key] : 0);
             }
         }
     }
     return $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;
 }
 /**
  * woocommerce_per_product_shipping_addition function.
  *
  * @access public
  * @return void
  */
 function woocommerce_per_product_shipping_addition($rates, $package)
 {
     global $woocommerce;
     $_tax = new WC_Tax();
     if ($rates) {
         foreach ($rates as $rate_id => $rate) {
             // Skip free shipping
             if ($rate->cost == 0 && apply_filters('woocommerce_per_product_shipping_skip_free_method_' . $rate->method_id, true)) {
                 continue;
             }
             // Skip self
             if ($rate->method_id == 'per_product') {
                 continue;
             }
             if (sizeof($package['contents']) > 0) {
                 foreach ($package['contents'] as $item_id => $values) {
                     if ($values['quantity'] > 0) {
                         if ($values['data']->needs_shipping()) {
                             $item_shipping_cost = 0;
                             $rule = false;
                             if ($values['variation_id']) {
                                 $rule = woocommerce_per_product_shipping_get_matching_rule($values['variation_id'], $package, false);
                             }
                             if ($rule === false) {
                                 $rule = woocommerce_per_product_shipping_get_matching_rule($values['product_id'], $package, false);
                             }
                             if (empty($rule)) {
                                 continue;
                             }
                             $item_shipping_cost += $rule->rule_item_cost * $values['quantity'];
                             $item_shipping_cost += $rule->rule_cost;
                             $rate->cost += $item_shipping_cost;
                             if ($woocommerce->shipping->shipping_methods[$rate->method_id]->tax_status == 'taxable') {
                                 $tax_rates = $_tax->get_shipping_tax_rates($values['data']->get_tax_class());
                                 $item_taxes = $_tax->calc_shipping_tax($item_shipping_cost, $tax_rates);
                                 // Sum the item taxes
                                 foreach (array_keys($rate->taxes + $item_taxes) as $key) {
                                     $rate->taxes[$key] = (isset($item_taxes[$key]) ? $item_taxes[$key] : 0) + (isset($rate->taxes[$key]) ? $rate->taxes[$key] : 0);
                                 }
                             }
                         }
                     }
                 }
             }
         }
     }
     return $rates;
 }
Exemplo n.º 11
0
 /**
  * Add a rate
  *
  * Add a shipping rate. If taxes are not set they will be calculated based on cost.
  *
  * @param array $args (default: array())
  */
 public function add_rate($args = array())
 {
     $args = wp_parse_args($args, array('id' => '', 'label' => '', 'cost' => '0', 'taxes' => '', 'calc_tax' => 'per_order'));
     // Id and label are required
     if (!$args['id'] || !$args['label']) {
         return;
     }
     // Handle cost
     $total_cost = is_array($args['cost']) ? array_sum($args['cost']) : $args['cost'];
     $taxes = $args['taxes'];
     // Taxes - if not an array and not set to false, calc tax based on cost and passed calc_tax variable
     // This saves shipping methods having to do complex tax calculations
     if (!is_array($taxes) && $taxes !== false && $total_cost > 0 && $this->is_taxable()) {
         $taxes = array();
         switch ($args['calc_tax']) {
             case "per_item":
                 // If we have an array of costs we can look up each items tax class and add tax accordingly
                 if (is_array($args['cost'])) {
                     $cart = WC()->cart->get_cart();
                     foreach ($args['cost'] as $cost_key => $amount) {
                         if (!isset($cart[$cost_key])) {
                             continue;
                         }
                         $item_taxes = WC_Tax::calc_shipping_tax($amount, WC_Tax::get_shipping_tax_rates($cart[$cost_key]['data']->get_tax_class()));
                         // Sum the item taxes
                         foreach (array_keys($taxes + $item_taxes) as $key) {
                             $taxes[$key] = (isset($item_taxes[$key]) ? $item_taxes[$key] : 0) + (isset($taxes[$key]) ? $taxes[$key] : 0);
                         }
                     }
                     // Add any cost for the order - order costs are in the key 'order'
                     if (isset($args['cost']['order'])) {
                         $item_taxes = WC_Tax::calc_shipping_tax($args['cost']['order'], WC_Tax::get_shipping_tax_rates());
                         // Sum the item taxes
                         foreach (array_keys($taxes + $item_taxes) as $key) {
                             $taxes[$key] = (isset($item_taxes[$key]) ? $item_taxes[$key] : 0) + (isset($taxes[$key]) ? $taxes[$key] : 0);
                         }
                     }
                 }
                 break;
             default:
                 $taxes = WC_Tax::calc_shipping_tax($total_cost, WC_Tax::get_shipping_tax_rates());
                 break;
         }
     }
     $this->rates[] = new WC_Shipping_Rate($args['id'], $args['label'], $total_cost, $taxes, $this->id);
 }
Exemplo n.º 12
0
 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;
 }
Exemplo n.º 13
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;
}
Exemplo n.º 14
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;
 }
Exemplo n.º 15
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);
     }
 }
Exemplo n.º 16
0
 function calculate_shipping($paquete = array())
 {
     //Peso total del pedido
     $peso_total = WC()->cart->cart_contents_weight;
     //Variables
     $volumen = $largo = $ancho = $alto = 0;
     $clases = $medidas = array();
     //Toma distintos datos de los productos
     foreach (WC()->cart->get_cart() as $identificador => $valores) {
         $producto = $valores['data'];
         $peso = $producto->get_weight() * $valores['quantity'];
         //Arregla un problema con los pesos en variaciones virtuales
         if ($producto->is_virtual()) {
             $peso_total -= $peso;
         }
         //Medidas y volúmenes
         if ($producto->length && $producto->width && $producto->height) {
             $volumen += $producto->length * $producto->width * $producto->height * $valores['quantity'];
         }
         $medidas[] = array('largo' => $producto->length, 'ancho' => $producto->width, 'alto' => $producto->height, 'cantidad' => $valores['quantity']);
         if ($producto->length > $largo) {
             $largo = $producto->length;
         }
         if ($producto->width > $ancho) {
             $ancho = $producto->width;
         }
         if ($producto->height > $alto) {
             $alto = $producto->height;
         }
         //Clase de producto
         if ($producto->needs_shipping()) {
             $clase = $producto->get_shipping_class() ? $producto->get_shipping_class() : 'todas';
             if (!isset($clases['todas'])) {
                 $clases['todas'] = 0;
             }
             $clases['todas'] += $peso;
             if (!isset($clases[$clase])) {
                 $clases[$clase] = $peso;
             } else {
                 if ($clase != 'todas') {
                     $clases[$clase] += $peso;
                 }
             }
         }
     }
     if ($this->clases_excluidas) {
         //Toma distintos datos de los productos
         foreach (WC()->cart->get_cart() as $identificador => $valores) {
             $producto = $valores['data'];
             //Clase de producto
             if (in_array($producto->get_shipping_class(), $this->clases_excluidas)) {
                 return false;
                 //No atiende a las clases de envío excluidas
             }
         }
     }
     $grupos = $this->dame_grupos($paquete, $clases);
     if (empty($grupos)) {
         return false;
         //No hay resultados
     }
     $grupos_excluidos = explode(',', preg_replace('/\\s+/', '', $this->grupos_excluidos));
     foreach ($grupos_excluidos as $grupo_excluido) {
         if (in_array($grupo_excluido, $grupos)) {
             return false;
             //No atiende a los grupos excluidos
         }
     }
     if ($this->apg_free_shipping && $this->muestra == 'yes') {
         return false;
         //Sólo muestra el envío gratuito
     }
     $tarifas = $this->dame_tarifas($grupos);
     //Recoge las tarifas programadas
     $precios = $this->dame_tarifa_mas_barata($tarifas, $peso_total, $volumen, $largo, $ancho, $alto, $grupos, $medidas, $clases);
     //Filtra las tarifas
     if (empty($precios)) {
         return false;
         //No hay tarifa
     }
     //Calculamos el precio
     $precio_total = $suma_impuestos = $suma_cargos = 0;
     $impuestos_parciales = $impuestos_totales = array();
     if ($this->tax_status != 'none') {
         $impuestos = new WC_Tax();
     }
     //Cargos adicionales
     if ($this->fee > 0) {
         $suma_cargos += $this->fee;
     }
     if ($this->cargo > 0 && !strpos($this->cargo, '%')) {
         $suma_cargos += $this->cargo;
     }
     foreach ($precios as $grupo => $precio) {
         if ($this->cargo > 0 && strpos($this->cargo, '%')) {
             $suma_cargos += $precio * (str_replace('%', '', $this->cargo) / 100);
             //Cargos adicionales
         }
         $precio += $suma_cargos;
         $precio_total += $precio;
         if ($this->tax_status != 'none') {
             $impuestos_parciales[$grupo] = $impuestos->calc_shipping_tax($precio, $impuestos->get_shipping_tax_rates($this->settings['Tax_' . $grupo]));
         }
     }
     if ($this->tax_status != 'none') {
         foreach ($impuestos_parciales as $impuesto_parcial) {
             foreach ($impuesto_parcial as $clave => $impuesto) {
                 $suma_impuestos += $impuesto;
                 $impuestos_totales[$clave] = $suma_impuestos;
             }
         }
     }
     $tarifa = array('id' => $this->id, 'label' => $this->title, 'cost' => $precio_total, 'taxes' => $impuestos_totales, 'calc_tax' => 'per_order');
     $this->add_rate($tarifa);
 }
Exemplo n.º 17
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;
 }
 public static function createSimpleOrder($total = 40)
 {
     $product = self::createSimpleProduct();
     self::createSimpleShippingFlatRate();
     $order_data = array('status' => 'pending', 'customer_id' => 1, 'customer_note' => '', 'total' => '');
     // Required, else wc_create_order throws an exception
     $_SERVER['REMOTE_ADDR'] = '127.0.0.1';
     $order = wc_create_order($order_data);
     // Add order products
     $order->add_product($product, 4);
     // Set billing address
     $shipping_address = array('country' => 'US', 'first_name' => 'Jeroen', 'last_name' => 'Sormani', 'company' => 'WooCompany', 'address_1' => 'WooAddress', 'address_2' => '', 'postcode' => '123456', 'city' => 'WooCity', 'state' => 'NY', 'email' => '*****@*****.**', 'phone' => '555-32123');
     $order->set_address($shipping_address, 'shipping');
     // Add shipping costs
     $shipping_taxes = \WC_Tax::calc_shipping_tax('10', \WC_Tax::get_shipping_tax_rates());
     $order->add_shipping(new \WC_Shipping_Rate('flagship_shipping_method|Purolator|PurolatorExpress|Purolator Express|1473811200', 'Purolator - Purolator Express', '10', $shipping_taxes, 'flagship_shipping_method'));
     // Set totals
     $order->set_total(10, 'shipping');
     $order->set_total(0, 'cart_discount');
     $order->set_total(0, 'cart_discount_tax');
     $order->set_total(0, 'tax');
     $order->set_total(0, 'shipping_tax');
     $order->set_total($total, 'total');
     // 4 x $10 simple helper product
     return wc_get_order($order->id);
 }