Get a rates code. Code is made up of COUNTRY-STATE-NAME-Priority. E.g GB-VAT-1, US-AL-TAX-1.
public static get_rate_code ( mixed $key_or_rate ) : string | ||
$key_or_rate | mixed | Tax rate ID, or the db row itself in object format |
return | string |
/** * Get taxes, merged by code, formatted ready for output. * * @access public * @return void */ public function get_tax_totals() { $taxes = $this->get_taxes(); $tax_totals = array(); foreach ($taxes as $key => $tax) { $code = $this->tax->get_rate_code($key); if (!isset($tax_totals[$code])) { $tax_totals[$code] = new stdClass(); $tax_totals[$code]->amount = 0; } $tax_totals[$code]->is_compound = $this->tax->is_compound($key); $tax_totals[$code]->label = $this->tax->get_rate_label($key); $tax_totals[$code]->amount += $tax; $tax_totals[$code]->formatted_amount = woocommerce_price($tax_totals[$code]->amount); } return apply_filters('woocommerce_cart_tax_totals', $tax_totals, $this); }
/** * Add a tax row to the order * * @since 2.2 * @param int tax_rate_id * @return int|bool Item ID or false */ public function add_tax($tax_rate_id, $tax_amount = 0, $shipping_tax_amount = 0) { $code = WC_Tax::get_rate_code($tax_rate_id); if (!$code) { return false; } $item_id = wc_add_order_item($this->id, array('order_item_name' => $code, 'order_item_type' => 'tax')); if (!$item_id) { return false; } wc_add_order_item_meta($item_id, 'rate_id', $tax_rate_id); wc_add_order_item_meta($item_id, 'label', WC_Tax::get_rate_label($tax_rate_id)); wc_add_order_item_meta($item_id, 'compound', WC_Tax::is_compound($tax_rate_id) ? 1 : 0); wc_add_order_item_meta($item_id, 'tax_amount', wc_format_decimal($tax_amount)); wc_add_order_item_meta($item_id, 'shipping_tax_amount', wc_format_decimal($shipping_tax_amount)); do_action('woocommerce_order_add_tax', $this->id, $item_id, $tax_rate_id, $tax_amount, $shipping_tax_amount); return $item_id; }
/** * Get taxes, merged by code, formatted ready for output. * * @return array */ public function get_tax_totals() { $taxes = $this->get_taxes(); $tax_totals = array(); foreach ($taxes as $key => $tax) { $code = WC_Tax::get_rate_code($key); if ($code || $key === apply_filters('woocommerce_cart_remove_taxes_zero_rate_id', 'zero-rated')) { if (!isset($tax_totals[$code])) { $tax_totals[$code] = new stdClass(); $tax_totals[$code]->amount = 0; } $tax_totals[$code]->tax_rate_id = $key; $tax_totals[$code]->is_compound = WC_Tax::is_compound($key); $tax_totals[$code]->label = WC_Tax::get_rate_label($key); $tax_totals[$code]->amount += wc_round_tax_total($tax); $tax_totals[$code]->formatted_amount = wc_price(wc_round_tax_total($tax_totals[$code]->amount)); } } if (apply_filters('woocommerce_cart_hide_zero_taxes', true)) { $amounts = array_filter(wp_list_pluck($tax_totals, 'amount')); $tax_totals = array_intersect_key($tax_totals, $amounts); } return apply_filters('woocommerce_cart_tax_totals', $tax_totals, $this); }
</th> <th><?php _e('Rate %', 'woocommerce'); ?> </th> </tr> </thead> <?php $rates = $wpdb->get_results("SELECT * FROM {$wpdb->prefix}woocommerce_tax_rates ORDER BY tax_rate_name LIMIT 100"); foreach ($rates as $rate) { echo ' <tr> <td><input type="radio" id="add_order_tax_' . absint($rate->tax_rate_id) . '" name="add_order_tax" value="' . absint($rate->tax_rate_id) . '" /></td> <td><label for="add_order_tax_' . absint($rate->tax_rate_id) . '">' . WC_Tax::get_rate_label($rate) . '</label></td> <td>' . (isset($classes_options[$rate->tax_rate_class]) ? $classes_options[$rate->tax_rate_class] : '-') . '</td> <td>' . WC_Tax::get_rate_code($rate) . '</td> <td>' . WC_Tax::get_rate_percent($rate) . '</td> </tr> '; } ?> </table> <?php if (absint($wpdb->get_var("SELECT COUNT(tax_rate_id) FROM {$wpdb->prefix}woocommerce_tax_rates;")) > 100) { ?> <p> <label for="manual_tax_rate_id"><?php _e('Or, enter tax rate ID:', 'woocommerce'); ?> </label><br/> <input type="number" name="manual_tax_rate_id" id="manual_tax_rate_id" step="1" placeholder="<?php
/** * Add tax lines to the order. * * @param WC_Order $order */ protected function create_order_tax_lines(&$order) { foreach (array_keys(WC()->cart->taxes + WC()->cart->shipping_taxes) as $tax_rate_id) { if ($tax_rate_id && apply_filters('woocommerce_cart_remove_taxes_zero_rate_id', 'zero-rated') !== $tax_rate_id) { $item = new WC_Order_Item_Tax(); $item->set_props(array('rate_id' => $tax_rate_id, 'tax_total' => WC()->cart->get_tax_amount($tax_rate_id), 'shipping_tax_total' => WC()->cart->get_shipping_tax_amount($tax_rate_id), 'rate_code' => WC_Tax::get_rate_code($tax_rate_id), 'label' => WC_Tax::get_rate_label($tax_rate_id), 'compound' => WC_Tax::is_compound($tax_rate_id))); $order->add_item($item); } } }
/** * Create an order. Error codes: * 520 - Cannot insert order into the database. * 521 - Cannot get order after creation. * 522 - Cannot update order. * 525 - Cannot create line item. * 526 - Cannot create fee item. * 527 - Cannot create shipping item. * 528 - Cannot create tax item. * 529 - Cannot create coupon item. * @throws Exception * @return int|WP_ERROR */ public function create_order() { global $wpdb; // Give plugins the opportunity to create an order themselves if ($order_id = apply_filters('woocommerce_create_order', null, $this)) { return $order_id; } try { // Start transaction if available wc_transaction_query('start'); // Insert or update the post data $order_id = absint(WC()->session->order_awaiting_payment); $cart_hash = md5(json_encode(wc_clean(WC()->cart->get_cart_for_session())) . WC()->cart->total); /** * If there is an order pending payment, we can resume it here so * long as it has not changed. If the order has changed, i.e. * different items or cost, create a new order. We use a hash to * detect changes which is based on cart items + order total. */ if ($order_id && ($order = wc_get_order($order_id)) && $order->has_cart_hash($cart_hash) && $order->has_status(array('pending', 'failed'))) { // Action for 3rd parties. do_action('woocommerce_resume_order', $order_id); // Remove all items - we will re-add them later. $order->remove_order_items(); /** * Not resuming - lets create a new order object. */ } else { $order = new WC_Order(); } $order->set_created_via('checkout'); $order->set_cart_hash($cart_hash); $order->set_customer_id($this->customer_id); $order->set_currency(get_woocommerce_currency()); $order->set_prices_include_tax('yes' === get_option('woocommerce_prices_include_tax')); $order->set_customer_ip_address(WC_Geolocation::get_ip_address()); $order->set_customer_user_agent(wc_get_user_agent()); $order->set_customer_note(isset($this->posted['order_comments']) ? $this->posted['order_comments'] : ''); $order->set_payment_method($this->payment_method); $order->set_shipping_total(WC()->cart->shipping_total); $order->set_discount_total(WC()->cart->get_cart_discount_total()); $order->set_discount_tax(WC()->cart->get_cart_discount_tax_total()); $order->set_cart_tax(WC()->cart->tax_total); $order->set_shipping_tax(WC()->cart->shipping_tax_total); $order->set_total(WC()->cart->total); // Billing and shipping addresses if ($address_keys = array_merge(array_keys($this->checkout_fields['billing']), array_keys($this->checkout_fields['shipping']))) { foreach ($address_keys as $key) { if (is_callable(array($order, "set_{$key}"))) { $order->{"set_{$key}"}($this->get_posted_address_data(str_replace(array('billing_', 'shipping_'), '', $key), strstr($key, 'billing_') ? 'billing' : 'shipping')); } } } // Add line items. foreach (WC()->cart->get_cart() as $cart_item_key => $values) { $product = $values['data']; $item = new WC_Order_Item_Product(array('quantity' => $values['quantity'], 'name' => $product ? $product->get_title() : '', 'tax_class' => $product ? $product->get_tax_class() : '', 'product_id' => $product && isset($product->id) ? $product->id : 0, 'variation_id' => $product && isset($product->variation_id) ? $product->variation_id : 0, 'variation' => $values['variation'], 'subtotal' => $values['line_subtotal'], 'total' => $values['line_total'], 'subtotal_tax' => $values['line_subtotal_tax'], 'total_tax' => $values['line_tax'], 'taxes' => $values['line_tax_data'])); $item->set_backorder_meta(); // Set this to pass to legacy actions @todo remove in future release $item->legacy_values = $values; $item->legacy_cart_item_key = $cart_item_key; $order->add_item($item); } // Add fees foreach (WC()->cart->get_fees() as $fee_key => $fee) { $item = new WC_Order_Item_Fee(array('name' => $fee->name, 'tax_class' => $fee->taxable ? $fee->tax_class : 0, 'total' => $fee->amount, 'total_tax' => $fee->tax, 'taxes' => array('total' => $fee->tax_data))); // Set this to pass to legacy actions @todo remove in future release $item->legacy_fee = $fee; $item->legacy_fee_key = $fee_key; $order->add_item($item); } // Store shipping for all packages foreach (WC()->shipping->get_packages() as $package_key => $package) { if (isset($package['rates'][$this->shipping_methods[$package_key]])) { $shipping_rate = $package['rates'][$this->shipping_methods[$package_key]]; $item = new WC_Order_Item_Shipping(array('method_title' => $shipping_rate->label, 'method_id' => $shipping_rate->id, 'total' => wc_format_decimal($shipping_rate->cost), 'taxes' => $shipping_rate->taxes, 'meta_data' => $shipping_rate->get_meta_data())); // Set this to pass to legacy actions @todo remove in future release $item->legacy_package_key = $package_key; $order->add_item($item); } } // Store tax rows foreach (array_keys(WC()->cart->taxes + WC()->cart->shipping_taxes) as $tax_rate_id) { if ($tax_rate_id && apply_filters('woocommerce_cart_remove_taxes_zero_rate_id', 'zero-rated') !== $tax_rate_id) { $order->add_item(new WC_Order_Item_Tax(array('rate_id' => $tax_rate_id, 'tax_total' => WC()->cart->get_tax_amount($tax_rate_id), 'shipping_tax_total' => WC()->cart->get_shipping_tax_amount($tax_rate_id), 'rate_code' => WC_Tax::get_rate_code($tax_rate_id), 'label' => WC_Tax::get_rate_label($tax_rate_id), 'compound' => WC_Tax::is_compound($tax_rate_id)))); } } // Store coupons foreach (WC()->cart->get_coupons() as $code => $coupon) { $item = new WC_Order_Item_Coupon(array('code' => $code, 'discount' => WC()->cart->get_coupon_discount_amount($code), 'discount_tax' => WC()->cart->get_coupon_discount_tax_amount($code))); $order->add_item($item); } // Save the order $order_id = $order->save(); // Update user meta $this->update_customer_data(); // Let plugins add their own meta data do_action('woocommerce_checkout_update_order_meta', $order_id, $this->posted); // If we got here, the order was created without problems! wc_transaction_query('commit'); } catch (Exception $e) { // There was an error adding order data! wc_transaction_query('rollback'); return new WP_Error('checkout-error', $e->getMessage()); } return $order_id; }
/** * Test rate code. */ public function test_get_rate_code() { global $wpdb; $tax_rate = array('tax_rate_country' => 'GB', 'tax_rate_state' => '', 'tax_rate' => '20.0000', 'tax_rate_name' => 'VAT', 'tax_rate_priority' => '1', 'tax_rate_compound' => '1', 'tax_rate_shipping' => '1', 'tax_rate_order' => '1', 'tax_rate_class' => ''); $tax_rate_id = WC_Tax::_insert_tax_rate($tax_rate); $this->assertEquals(WC_Tax::get_rate_code($tax_rate_id), 'GB-VAT-1'); WC_Tax::_delete_tax_rate($tax_rate_id); }
/** * When a new order is inserted, add subscriptions related order meta. * * @since 1.0 */ public static function add_order_meta($order_id, $posted) { global $woocommerce; if (!WC_Subscriptions_Cart::cart_contains_subscription_renewal('child') && WC_Subscriptions_Order::order_contains_subscription($order_id)) { // This works because the 'woocommerce_add_order_item_meta' runs before the 'woocommerce_checkout_update_order_meta' hook // Set the recurring totals so totals display correctly on order page update_post_meta($order_id, '_order_recurring_discount_cart', WC_Subscriptions_Cart::get_recurring_discount_cart()); update_post_meta($order_id, '_order_recurring_discount_cart_tax', WC_Subscriptions_Cart::get_recurring_discount_cart_tax()); update_post_meta($order_id, '_order_recurring_discount_total', WC_Subscriptions_Cart::get_recurring_discount_total()); update_post_meta($order_id, '_order_recurring_shipping_tax_total', WC_Subscriptions_Cart::get_recurring_shipping_tax_total()); update_post_meta($order_id, '_order_recurring_shipping_total', WC_Subscriptions_Cart::get_recurring_shipping_total()); update_post_meta($order_id, '_order_recurring_tax_total', WC_Subscriptions_Cart::get_recurring_total_tax()); update_post_meta($order_id, '_order_recurring_total', WC_Subscriptions_Cart::get_recurring_total()); // Set the recurring payment method - it starts out the same as the original by may change later update_post_meta($order_id, '_recurring_payment_method', get_post_meta($order_id, '_payment_method', true)); update_post_meta($order_id, '_recurring_payment_method_title', get_post_meta($order_id, '_payment_method_title', true)); $order = new WC_Order($order_id); $order_fees = $order->get_fees(); // the fee order items have already been set, we just need to to add the recurring total meta $cart_fees = $woocommerce->cart->get_fees(); foreach ($order->get_fees() as $item_id => $order_fee) { // Find the matching fee in the cart foreach ($cart_fees as $fee_index => $cart_fee) { if (sanitize_title($order_fee['name']) == $cart_fee->id) { woocommerce_add_order_item_meta($item_id, '_recurring_line_total', wc_format_decimal($cart_fee->recurring_amount)); woocommerce_add_order_item_meta($item_id, '_recurring_line_tax', wc_format_decimal($cart_fee->recurring_tax)); unset($cart_fees[$fee_index]); break; } } } // Get recurring taxes into same format as _order_taxes $order_recurring_taxes = array(); foreach (WC_Subscriptions_Cart::get_recurring_taxes() as $tax_key => $tax_amount) { $item_id = woocommerce_add_order_item($order_id, array('order_item_name' => WC_Tax::get_rate_code($tax_key), 'order_item_type' => 'recurring_tax')); if ($item_id) { wc_add_order_item_meta($item_id, 'rate_id', $tax_key); wc_add_order_item_meta($item_id, 'label', WC_Tax::get_rate_label($tax_key)); wc_add_order_item_meta($item_id, 'compound', absint(WC_Tax::is_compound($tax_key) ? 1 : 0)); wc_add_order_item_meta($item_id, 'tax_amount', wc_format_decimal(isset(WC()->cart->recurring_taxes[$tax_key]) ? WC()->cart->recurring_taxes[$tax_key] : 0)); wc_add_order_item_meta($item_id, 'shipping_tax_amount', wc_format_decimal(isset(WC()->cart->recurring_shipping_taxes[$tax_key]) ? WC()->cart->recurring_shipping_taxes[$tax_key] : 0)); } } $payment_gateways = $woocommerce->payment_gateways->payment_gateways(); if ('yes' == get_option(WC_Subscriptions_Admin::$option_prefix . '_turn_off_automatic_payments', 'no')) { update_post_meta($order_id, '_wcs_requires_manual_renewal', 'true'); } elseif (isset($payment_gateways[$posted['payment_method']]) && !$payment_gateways[$posted['payment_method']]->supports('subscriptions')) { update_post_meta($order_id, '_wcs_requires_manual_renewal', 'true'); } $cart_item = WC_Subscriptions_Cart::cart_contains_subscription_renewal(); if (isset($cart_item['subscription_renewal']) && 'parent' == $cart_item['subscription_renewal']['role']) { update_post_meta($order_id, '_original_order', $cart_item['subscription_renewal']['original_order']); } // WC 2.1+ if (!WC_Subscriptions::is_woocommerce_pre('2.1')) { // Recurring coupons if ($applied_coupons = $woocommerce->cart->get_coupons()) { foreach ($applied_coupons as $code => $coupon) { if (!isset($woocommerce->cart->recurring_coupon_discount_amounts[$code])) { continue; } $item_id = woocommerce_add_order_item($order_id, array('order_item_name' => $code, 'order_item_type' => 'recurring_coupon')); // Add line item meta if ($item_id) { woocommerce_add_order_item_meta($item_id, 'discount_amount', isset($woocommerce->cart->recurring_coupon_discount_amounts[$code]) ? $woocommerce->cart->recurring_coupon_discount_amounts[$code] : 0); } } } // Add recurring shipping order items if (WC_Subscriptions_Cart::cart_contains_subscriptions_needing_shipping()) { $packages = $woocommerce->shipping->get_packages(); $checkout = $woocommerce->checkout(); foreach ($packages as $i => $package) { if (isset($package['rates'][$checkout->shipping_methods[$i]])) { $method = $package['rates'][$checkout->shipping_methods[$i]]; $item_id = woocommerce_add_order_item($order_id, array('order_item_name' => $method->label, 'order_item_type' => 'recurring_shipping')); if ($item_id) { woocommerce_add_order_item_meta($item_id, 'method_id', $method->id); woocommerce_add_order_item_meta($item_id, 'cost', WC_Subscriptions::format_total($method->cost)); woocommerce_add_order_item_meta($item_id, 'taxes', array_map('wc_format_decimal', $method->taxes)); do_action('woocommerce_subscriptions_add_recurring_shipping_order_item', $order_id, $item_id, $i); } } } } // Remove shipping on original order if it was added but is not required if (!WC_Subscriptions_Cart::charge_shipping_up_front()) { foreach ($order->get_shipping_methods() as $order_item_id => $shipping_method) { woocommerce_update_order_item_meta($order_item_id, 'cost', WC_Subscriptions::format_total(0)); } } } else { update_post_meta($order_id, '_recurring_shipping_method', get_post_meta($order_id, '_shipping_method', true), true); update_post_meta($order_id, '_recurring_shipping_method_title', get_post_meta($order_id, '_shipping_method_title', true), true); } } }
/** * Set properties based on passed in tax rate by ID. * @param int $tax_rate_id * @throws WC_Data_Exception */ public function set_rate($tax_rate_id) { $this->set_rate_id($tax_rate_id); $this->set_rate_code(WC_Tax::get_rate_code($tax_rate_id)); $this->set_label(WC_Tax::get_rate_code($tax_rate_id)); $this->set_compound(WC_Tax::get_rate_code($tax_rate_id)); }
/** * Returns an array of taxes merged by code, formatted with recurring amount ready for output. * * @return array Array of tax_id => tax_amounts for items in the cart * @since 1.3.5 */ public static function get_recurring_tax_totals($tax_totals, $cart) { if (self::cart_contains_subscription()) { $recurring_taxes = self::get_recurring_taxes(); // Add any recurring tax not already handled - when a subscription has a free trial and a sign-up fee, we get a recurring shipping tax with no initial shipping tax foreach ($recurring_taxes as $key => $tax) { $code = WC_Tax::get_rate_code($key); if (!isset($tax_totals[$code])) { $tax_totals[$code] = new stdClass(); $tax_totals[$code]->is_compound = WC_Tax::is_compound($key); $tax_totals[$code]->label = WC_Tax::get_rate_label($key); $tax_totals[$code]->amount = 0; } if (!isset($tax_totals[$code]->recurring_amount)) { $tax_totals[$code]->recurring_amount = 0; } $tax_totals[$code]->recurring_amount += $tax; } // Now create the correctly formed subscription price string for each total foreach ($tax_totals as $code => $tax) { $include_trial = 0 == $tax_totals[$code]->amount ? true : false; $tax_totals[$code]->formatted_amount = self::get_cart_subscription_string($tax_totals[$code]->amount, $tax_totals[$code]->recurring_amount, array('include_trial' => $include_trial)); } } return apply_filters('woocommerce_cart_recurring_tax_totals', $tax_totals, $cart); }
/** * Parse a single tax item * * @since 3.0.0 * @param array $tax_item_data Raw tax item data * @return array|null Parsed tax item data or null */ private function parse_tax_item($tax_item_data) { $tax_rates = $this->get_tax_rates(); // normalize tax fields foreach ($this->tax_item_mapping as $from => $to) { if (isset($tax_item_data[$from])) { $tax_item_data[$to] = $tax_item_data[$from]; unset($tax_item_data[$from]); } } // if neither tax or shipping amount provided, bail out // TODO: should we throw here instead? {IT 2016-05-30} if (!isset($tax_item_data['tax_amount']) && !isset($tax_item_data['shipping_tax_amount'])) { return; } // default rate id to 0 if not set if (!isset($tax_item_data['rate_id'])) { $tax_item_data['rate_id'] = 0; } // keep a reference to the rate_id provided in the CSV file $original_rate_id = $tax_item_data['rate_id']; // try and look up rate id by code // Code is made up of COUNTRY-STATE-NAME-Priority. E.g GB-VAT-1, US-AL-TAX-1. // We do this instead of relying blindly on rate_id because tax code is more // portable than rate_id across stores if (isset($tax_item_data['code'])) { foreach ($tax_rates as $tax_rate) { if (WC_Tax::get_rate_code($tax_rate->tax_rate_id) == $tax_item_data['code']) { // found the tax by code $tax_item_data['rate_id'] = $tax_rate->tax_rate_id; $tax_item_data['label'] = $tax_rate->tax_rate_name; break; } } } // try and look up rate id by label if needed if (!$tax_item_data['rate_id'] && isset($tax_item_data['label']) && $tax_item_data['label']) { foreach ($tax_rates as $tax_rate) { if (0 === strcasecmp($tax_rate->tax_rate_name, $tax_item_data['label'])) { // found the tax by label $tax_item_data['rate_id'] = $tax_rate->tax_rate_id; break; } } } // check for a rate being specified which does not exist, and clear it out (technically an error?) if ($tax_item_data['rate_id'] && !isset($tax_rates[$tax_item_data['rate_id']])) { $tax_item_data['rate_id'] = 0; } // fetch tax rate code if ($tax_item_data['rate_id'] && (!isset($tax_item_data['code']) || $tax_item_data['code'])) { $tax_item_data['code'] = WC_Tax::get_rate_code($tax_item_data['rate_id']); } else { $tax_item_data['code'] = ''; } // default label of 'Tax' if not provided if (!isset($tax_item_data['label']) || !$tax_item_data['label']) { $tax_item_data['label'] = esc_html__('Tax', 'woocommerce-csv-import-suite'); } // default tax amounts to 0 if not set if (!isset($tax_item_data['tax_amount'])) { $tax_item_data['tax_amount'] = 0; } if (!isset($tax_item_data['shipping_tax_amount'])) { $tax_item_data['shipping_tax_amount'] = 0; } // handle compound flag by using the defined tax rate value (if any) if (!isset($tax_item_data['compound'])) { $tax_item_data['compound'] = ''; if ($tax_item_data['rate_id']) { $tax_item_data['compound'] = $tax_rates[$tax_item_data['rate_id']]->tax_rate_compound; } } // store a reference of the original rate_id, so that we can match refund // taxes to the correct tax rate if ($tax_item_data['rate_id'] && $tax_item_data['rate_id'] != $original_rate_id) { $tax_item_data['_original_rate_id'] = $original_rate_id; } return $tax_item_data; }