Exemplo n.º 1
0
 /**
  * Get discount amount for a cart item.
  *
  * @param  float $discounting_amount Amount the coupon is being applied to
  * @param  array|null $cart_item Cart item being discounted if applicable
  * @param  boolean $single True if discounting a single qty item, false if its the line
  * @return float Amount this coupon has discounted
  */
 public function get_discount_amount($discounting_amount, $cart_item = null, $single = false)
 {
     $discount = 0;
     $cart_item_qty = is_null($cart_item) ? 1 : $cart_item['quantity'];
     if ($this->is_type(array('percent_product', 'percent'))) {
         $discount = $this->get_amount() * ($discounting_amount / 100);
     } elseif ($this->is_type('fixed_cart') && !is_null($cart_item) && WC()->cart->subtotal_ex_tax) {
         /**
          * This is the most complex discount - we need to divide the discount between rows based on their price in.
          * proportion to the subtotal. This is so rows with different tax rates get a fair discount, and so rows.
          * with no price (free) don't get discounted.
          *
          * Get item discount by dividing item cost by subtotal to get a %.
          *
          * Uses price inc tax if prices include tax to work around https://github.com/woothemes/woocommerce/issues/7669 and https://github.com/woothemes/woocommerce/issues/8074.
          */
         if (wc_prices_include_tax()) {
             $discount_percent = $cart_item['data']->get_price_including_tax() * $cart_item_qty / WC()->cart->subtotal;
         } else {
             $discount_percent = $cart_item['data']->get_price_excluding_tax() * $cart_item_qty / WC()->cart->subtotal_ex_tax;
         }
         $discount = $this->get_amount() * $discount_percent / $cart_item_qty;
     } elseif ($this->is_type('fixed_product')) {
         $discount = min($this->get_amount(), $discounting_amount);
         $discount = $single ? $discount : $discount * $cart_item_qty;
     }
     $discount = min($discount, $discounting_amount);
     // Handle the limit_usage_to_x_items option
     if ($this->is_type(array('percent_product', 'fixed_product'))) {
         if ($discounting_amount) {
             if ('' === $this->get_limit_usage_to_x_items()) {
                 $limit_usage_qty = $cart_item_qty;
             } else {
                 $limit_usage_qty = min($this->get_limit_usage_to_x_items(), $cart_item_qty);
                 $this->set_limit_usage_to_x_items(max(0, $this->get_limit_usage_to_x_items() - $limit_usage_qty));
             }
             if ($single) {
                 $discount = $discount * $limit_usage_qty / $cart_item_qty;
             } else {
                 $discount = $discount / $cart_item_qty * $limit_usage_qty;
             }
         }
     }
     $discount = round($discount, wc_get_rounding_precision());
     return apply_filters('woocommerce_coupon_get_discount_amount', $discount, $discounting_amount, $cart_item, $single, $this);
 }
Exemplo n.º 2
0
 /**
  * Calculate totals for the items in the cart.
  */
 public function calculate_totals()
 {
     $this->reset();
     $this->coupons = $this->get_coupons();
     do_action('woocommerce_before_calculate_totals', $this);
     if ($this->is_empty()) {
         $this->set_session();
         return;
     }
     $tax_rates = array();
     $shop_tax_rates = array();
     $cart = $this->get_cart();
     /**
      * Calculate subtotals for items. This is done first so that discount logic can use the values.
      */
     foreach ($cart as $cart_item_key => $values) {
         $_product = $values['data'];
         $line_price = $_product->get_price() * $values['quantity'];
         $line_subtotal = 0;
         $line_subtotal_tax = 0;
         /**
          * No tax to calculate.
          */
         if (!$_product->is_taxable()) {
             // Subtotal is the undiscounted price
             $this->subtotal += $line_price;
             $this->subtotal_ex_tax += $line_price;
             /**
              * Prices include tax.
              *
              * To prevent rounding issues we need to work with the inclusive price where possible.
              * otherwise we'll see errors such as when working with a 9.99 inc price, 20% VAT which would.
              * be 8.325 leading to totals being 1p off.
              *
              * Pre tax coupons come off the price the customer thinks they are paying - tax is calculated.
              * afterwards.
              *
              * e.g. $100 bike with $10 coupon = customer pays $90 and tax worked backwards from that.
              */
         } elseif ($this->prices_include_tax) {
             // Get base tax rates
             if (empty($shop_tax_rates[$_product->tax_class])) {
                 $shop_tax_rates[$_product->tax_class] = WC_Tax::get_base_tax_rates($_product->tax_class);
             }
             // Get item tax rates
             if (empty($tax_rates[$_product->get_tax_class()])) {
                 $tax_rates[$_product->get_tax_class()] = WC_Tax::get_rates($_product->get_tax_class());
             }
             $base_tax_rates = $shop_tax_rates[$_product->tax_class];
             $item_tax_rates = $tax_rates[$_product->get_tax_class()];
             /**
              * ADJUST TAX - Calculations when base tax is not equal to the item tax.
              *
              * The woocommerce_adjust_non_base_location_prices filter can stop base taxes being taken off when dealing with out of base locations.
              * e.g. If a product costs 10 including tax, all users will pay 10 regardless of location and taxes.
              * This feature is experimental @since 2.4.7 and may change in the future. Use at your risk.
              */
             if ($item_tax_rates !== $base_tax_rates && apply_filters('woocommerce_adjust_non_base_location_prices', true)) {
                 // Work out a new base price without the shop's base tax
                 $taxes = WC_Tax::calc_tax($line_price, $base_tax_rates, true, true);
                 // Now we have a new item price (excluding TAX)
                 $line_subtotal = $line_price - array_sum($taxes);
                 // Now add modified taxes
                 $tax_result = WC_Tax::calc_tax($line_subtotal, $item_tax_rates);
                 $line_subtotal_tax = array_sum($tax_result);
                 /**
                  * Regular tax calculation (customer inside base and the tax class is unmodified.
                  */
             } else {
                 // Calc tax normally
                 $taxes = WC_Tax::calc_tax($line_price, $item_tax_rates, true);
                 $line_subtotal_tax = array_sum($taxes);
                 $line_subtotal = $line_price - array_sum($taxes);
             }
             /**
              * Prices exclude tax.
              *
              * This calculation is simpler - work with the base, untaxed price.
              */
         } else {
             // Get item tax rates
             if (empty($tax_rates[$_product->get_tax_class()])) {
                 $tax_rates[$_product->get_tax_class()] = WC_Tax::get_rates($_product->get_tax_class());
             }
             $item_tax_rates = $tax_rates[$_product->get_tax_class()];
             // Base tax for line before discount - we will store this in the order data
             $taxes = WC_Tax::calc_tax($line_price, $item_tax_rates);
             $line_subtotal_tax = array_sum($taxes);
             $line_subtotal = $line_price;
         }
         // Add to main subtotal
         $this->subtotal += $line_subtotal + $line_subtotal_tax;
         $this->subtotal_ex_tax += $line_subtotal;
     }
     // Order cart items by price so coupon logic is 'fair' for customers and not based on order added to cart.
     uasort($cart, array($this, 'sort_by_subtotal'));
     /**
      * Calculate totals for items.
      */
     foreach ($cart as $cart_item_key => $values) {
         $_product = $values['data'];
         // Prices
         $base_price = $_product->get_price();
         $line_price = $_product->get_price() * $values['quantity'];
         // Tax data
         $taxes = array();
         $discounted_taxes = array();
         /**
          * No tax to calculate.
          */
         if (!$_product->is_taxable()) {
             // Discounted Price (price with any pre-tax discounts applied)
             $discounted_price = $this->get_discounted_price($values, $base_price, true);
             $line_subtotal_tax = 0;
             $line_subtotal = $line_price;
             $line_tax = 0;
             $line_total = round($discounted_price * $values['quantity'], wc_get_rounding_precision());
             /**
              * Prices include tax.
              */
         } elseif ($this->prices_include_tax) {
             $base_tax_rates = $shop_tax_rates[$_product->tax_class];
             $item_tax_rates = $tax_rates[$_product->get_tax_class()];
             /**
              * ADJUST TAX - Calculations when base tax is not equal to the item tax.
              *
              * The woocommerce_adjust_non_base_location_prices filter can stop base taxes being taken off when dealing with out of base locations.
              * e.g. If a product costs 10 including tax, all users will pay 10 regardless of location and taxes.
              * This feature is experimental @since 2.4.7 and may change in the future. Use at your risk.
              */
             if ($item_tax_rates !== $base_tax_rates && apply_filters('woocommerce_adjust_non_base_location_prices', true)) {
                 // Work out a new base price without the shop's base tax
                 $taxes = WC_Tax::calc_tax($line_price, $base_tax_rates, true, true);
                 // Now we have a new item price (excluding TAX)
                 $line_subtotal = round($line_price - array_sum($taxes), wc_get_rounding_precision());
                 $taxes = WC_Tax::calc_tax($line_subtotal, $item_tax_rates);
                 $line_subtotal_tax = array_sum($taxes);
                 // Adjusted price (this is the price including the new tax rate)
                 $adjusted_price = ($line_subtotal + $line_subtotal_tax) / $values['quantity'];
                 // Apply discounts and get the discounted price FOR A SINGLE ITEM
                 $discounted_price = $this->get_discounted_price($values, $adjusted_price, true);
                 // Convert back to line price
                 $discounted_line_price = $discounted_price * $values['quantity'];
                 // Now use rounded line price to get taxes.
                 $discounted_taxes = WC_Tax::calc_tax($discounted_line_price, $item_tax_rates, true);
                 $line_tax = array_sum($discounted_taxes);
                 $line_total = $discounted_line_price - $line_tax;
                 /**
                  * Regular tax calculation (customer inside base and the tax class is unmodified.
                  */
             } else {
                 // Work out a new base price without the item tax
                 $taxes = WC_Tax::calc_tax($line_price, $item_tax_rates, true);
                 // Now we have a new item price (excluding TAX)
                 $line_subtotal = $line_price - array_sum($taxes);
                 $line_subtotal_tax = array_sum($taxes);
                 // Calc prices and tax (discounted)
                 $discounted_price = $this->get_discounted_price($values, $base_price, true);
                 // Convert back to line price
                 $discounted_line_price = $discounted_price * $values['quantity'];
                 // Now use rounded line price to get taxes.
                 $discounted_taxes = WC_Tax::calc_tax($discounted_line_price, $item_tax_rates, true);
                 $line_tax = array_sum($discounted_taxes);
                 $line_total = $discounted_line_price - $line_tax;
             }
             // Tax rows - merge the totals we just got
             foreach (array_keys($this->taxes + $discounted_taxes) as $key) {
                 $this->taxes[$key] = (isset($discounted_taxes[$key]) ? $discounted_taxes[$key] : 0) + (isset($this->taxes[$key]) ? $this->taxes[$key] : 0);
             }
             /**
              * Prices exclude tax.
              */
         } else {
             $item_tax_rates = $tax_rates[$_product->get_tax_class()];
             // Work out a new base price without the shop's base tax
             $taxes = WC_Tax::calc_tax($line_price, $item_tax_rates);
             // Now we have the item price (excluding TAX)
             $line_subtotal = $line_price;
             $line_subtotal_tax = array_sum($taxes);
             // Now calc product rates
             $discounted_price = $this->get_discounted_price($values, $base_price, true);
             $discounted_taxes = WC_Tax::calc_tax($discounted_price * $values['quantity'], $item_tax_rates);
             $discounted_tax_amount = array_sum($discounted_taxes);
             $line_tax = $discounted_tax_amount;
             $line_total = $discounted_price * $values['quantity'];
             // Tax rows - merge the totals we just got
             foreach (array_keys($this->taxes + $discounted_taxes) as $key) {
                 $this->taxes[$key] = (isset($discounted_taxes[$key]) ? $discounted_taxes[$key] : 0) + (isset($this->taxes[$key]) ? $this->taxes[$key] : 0);
             }
         }
         // Cart contents total is based on discounted prices and is used for the final total calculation
         $this->cart_contents_total += $line_total;
         /**
          * Store costs + taxes for lines. For tax inclusive prices, we do some extra rounding logic so the stored
          * values "add up" when viewing the order in admin. This does have the disadvatage of not being able to
          * recalculate the tax total/subtotal accurately in the future, but it does ensure the data looks correct.
          *
          * Tax exclusive prices are not affected.
          */
         if (!$_product->is_taxable() || $this->prices_include_tax) {
             $this->cart_contents[$cart_item_key]['line_total'] = round($line_total + $line_tax - wc_round_tax_total($line_tax), $this->dp);
             $this->cart_contents[$cart_item_key]['line_subtotal'] = round($line_subtotal + $line_subtotal_tax - wc_round_tax_total($line_subtotal_tax), $this->dp);
             $this->cart_contents[$cart_item_key]['line_tax'] = wc_round_tax_total($line_tax);
             $this->cart_contents[$cart_item_key]['line_subtotal_tax'] = wc_round_tax_total($line_subtotal_tax);
             $this->cart_contents[$cart_item_key]['line_tax_data'] = array('total' => array_map('wc_round_tax_total', $discounted_taxes), 'subtotal' => array_map('wc_round_tax_total', $taxes));
         } else {
             $this->cart_contents[$cart_item_key]['line_total'] = $line_total;
             $this->cart_contents[$cart_item_key]['line_subtotal'] = $line_subtotal;
             $this->cart_contents[$cart_item_key]['line_tax'] = $line_tax;
             $this->cart_contents[$cart_item_key]['line_subtotal_tax'] = $line_subtotal_tax;
             $this->cart_contents[$cart_item_key]['line_tax_data'] = array('total' => $discounted_taxes, 'subtotal' => $taxes);
         }
     }
     // Only calculate the grand total + shipping if on the cart/checkout
     if (is_checkout() || is_cart() || defined('WOOCOMMERCE_CHECKOUT') || defined('WOOCOMMERCE_CART')) {
         // Calculate the Shipping
         $this->calculate_shipping();
         // Trigger the fees API where developers can add fees to the cart
         $this->calculate_fees();
         // Total up/round taxes and shipping taxes
         if ($this->round_at_subtotal) {
             $this->tax_total = WC_Tax::get_tax_total($this->taxes);
             $this->shipping_tax_total = WC_Tax::get_tax_total($this->shipping_taxes);
             $this->taxes = array_map(array('WC_Tax', 'round'), $this->taxes);
             $this->shipping_taxes = array_map(array('WC_Tax', 'round'), $this->shipping_taxes);
         } else {
             $this->tax_total = array_sum($this->taxes);
             $this->shipping_tax_total = array_sum($this->shipping_taxes);
         }
         // VAT exemption done at this point - so all totals are correct before exemption
         if (WC()->customer->get_is_vat_exempt()) {
             $this->remove_taxes();
         }
         // Allow plugins to hook and alter totals before final total is calculated
         do_action('woocommerce_calculate_totals', $this);
         // Grand Total - Discounted product prices, discounted tax, shipping cost + tax
         $this->total = max(0, apply_filters('woocommerce_calculated_total', round($this->cart_contents_total + $this->tax_total + $this->shipping_tax_total + $this->shipping_total + $this->fee_total, $this->dp), $this));
     } else {
         // Set tax total to sum of all tax rows
         $this->tax_total = WC_Tax::get_tax_total($this->taxes);
         // VAT exemption done at this point - so all totals are correct before exemption
         if (WC()->customer->get_is_vat_exempt()) {
             $this->remove_taxes();
         }
     }
     do_action('woocommerce_after_calculate_totals', $this);
     $this->set_session();
 }
Exemplo n.º 3
0
 /**
  * Load options.
  *
  * @access public
  */
 public static function init()
 {
     self::$precision = wc_get_rounding_precision();
     self::$round_at_subtotal = 'yes' === get_option('woocommerce_tax_round_at_subtotal');
     add_action('update_option_woocommerce_tax_classes', array(__CLASS__, 'maybe_remove_tax_class_rates'), 10, 2);
 }
Exemplo n.º 4
0
 /**
  * Enqueue scripts.
  */
 public function admin_scripts()
 {
     global $wp_query, $post;
     $screen = get_current_screen();
     $screen_id = $screen ? $screen->id : '';
     $wc_screen_id = sanitize_title(__('WooCommerce', 'woocommerce'));
     $suffix = defined('SCRIPT_DEBUG') && SCRIPT_DEBUG ? '' : '.min';
     // Register scripts
     wp_register_script('woocommerce_admin', WC()->plugin_url() . '/assets/js/admin/woocommerce_admin' . $suffix . '.js', array('jquery', 'jquery-blockui', 'jquery-ui-sortable', 'jquery-ui-widget', 'jquery-ui-core', 'jquery-tiptip'), WC_VERSION);
     wp_register_script('jquery-blockui', WC()->plugin_url() . '/assets/js/jquery-blockui/jquery.blockUI' . $suffix . '.js', array('jquery'), '2.70', true);
     wp_register_script('jquery-tiptip', WC()->plugin_url() . '/assets/js/jquery-tiptip/jquery.tipTip' . $suffix . '.js', array('jquery'), WC_VERSION, true);
     wp_register_script('accounting', WC()->plugin_url() . '/assets/js/accounting/accounting' . $suffix . '.js', array('jquery'), '0.4.2');
     wp_register_script('round', WC()->plugin_url() . '/assets/js/round/round' . $suffix . '.js', array('jquery'), WC_VERSION);
     wp_register_script('wc-admin-meta-boxes', WC()->plugin_url() . '/assets/js/admin/meta-boxes' . $suffix . '.js', array('jquery', 'jquery-ui-datepicker', 'jquery-ui-sortable', 'accounting', 'round', 'wc-enhanced-select', 'plupload-all', 'stupidtable', 'jquery-tiptip'), WC_VERSION);
     wp_register_script('zeroclipboard', WC()->plugin_url() . '/assets/js/zeroclipboard/jquery.zeroclipboard' . $suffix . '.js', array('jquery'), WC_VERSION);
     wp_register_script('qrcode', WC()->plugin_url() . '/assets/js/jquery-qrcode/jquery.qrcode' . $suffix . '.js', array('jquery'), WC_VERSION);
     wp_register_script('stupidtable', WC()->plugin_url() . '/assets/js/stupidtable/stupidtable' . $suffix . '.js', array('jquery'), WC_VERSION);
     wp_register_script('serializejson', WC()->plugin_url() . '/assets/js/jquery-serializejson/jquery.serializejson' . $suffix . '.js', array('jquery'), '2.6.1');
     wp_register_script('flot', WC()->plugin_url() . '/assets/js/jquery-flot/jquery.flot' . $suffix . '.js', array('jquery'), WC_VERSION);
     wp_register_script('flot-resize', WC()->plugin_url() . '/assets/js/jquery-flot/jquery.flot.resize' . $suffix . '.js', array('jquery', 'flot'), WC_VERSION);
     wp_register_script('flot-time', WC()->plugin_url() . '/assets/js/jquery-flot/jquery.flot.time' . $suffix . '.js', array('jquery', 'flot'), WC_VERSION);
     wp_register_script('flot-pie', WC()->plugin_url() . '/assets/js/jquery-flot/jquery.flot.pie' . $suffix . '.js', array('jquery', 'flot'), WC_VERSION);
     wp_register_script('flot-stack', WC()->plugin_url() . '/assets/js/jquery-flot/jquery.flot.stack' . $suffix . '.js', array('jquery', 'flot'), WC_VERSION);
     wp_register_script('wc-settings-tax', WC()->plugin_url() . '/assets/js/admin/settings-views-html-settings-tax' . $suffix . '.js', array('jquery', 'wp-util', 'underscore', 'backbone', 'jquery-blockui'), WC_VERSION);
     wp_register_script('wc-backbone-modal', WC()->plugin_url() . '/assets/js/admin/backbone-modal' . $suffix . '.js', array('underscore', 'backbone', 'wp-util'), WC_VERSION);
     wp_register_script('wc-shipping-zones', WC()->plugin_url() . '/assets/js/admin/wc-shipping-zones' . $suffix . '.js', array('jquery', 'wp-util', 'underscore', 'backbone', 'jquery-ui-sortable', 'wc-enhanced-select', 'wc-backbone-modal'), WC_VERSION);
     wp_register_script('wc-shipping-zone-methods', WC()->plugin_url() . '/assets/js/admin/wc-shipping-zone-methods' . $suffix . '.js', array('jquery', 'wp-util', 'underscore', 'backbone', 'jquery-ui-sortable', 'wc-backbone-modal'), WC_VERSION);
     wp_register_script('wc-shipping-classes', WC()->plugin_url() . '/assets/js/admin/wc-shipping-classes' . $suffix . '.js', array('jquery', 'wp-util', 'underscore', 'backbone'), WC_VERSION);
     wp_register_script('select2', WC()->plugin_url() . '/assets/js/select2/select2' . $suffix . '.js', array('jquery'), '3.5.4');
     wp_register_script('wc-enhanced-select', WC()->plugin_url() . '/assets/js/admin/wc-enhanced-select' . $suffix . '.js', array('jquery', 'select2'), WC_VERSION);
     wp_localize_script('wc-enhanced-select', 'wc_enhanced_select_params', array('i18n_matches_1' => _x('One result is available, press enter to select it.', 'enhanced select', 'woocommerce'), 'i18n_matches_n' => _x('%qty% results are available, use up and down arrow keys to navigate.', 'enhanced select', 'woocommerce'), 'i18n_no_matches' => _x('No matches found', 'enhanced select', 'woocommerce'), 'i18n_ajax_error' => _x('Loading failed', 'enhanced select', 'woocommerce'), 'i18n_input_too_short_1' => _x('Please enter 1 or more characters', 'enhanced select', 'woocommerce'), 'i18n_input_too_short_n' => _x('Please enter %qty% or more characters', 'enhanced select', 'woocommerce'), 'i18n_input_too_long_1' => _x('Please delete 1 character', 'enhanced select', 'woocommerce'), 'i18n_input_too_long_n' => _x('Please delete %qty% characters', 'enhanced select', 'woocommerce'), 'i18n_selection_too_long_1' => _x('You can only select 1 item', 'enhanced select', 'woocommerce'), 'i18n_selection_too_long_n' => _x('You can only select %qty% items', 'enhanced select', 'woocommerce'), 'i18n_load_more' => _x('Loading more results…', 'enhanced select', 'woocommerce'), 'i18n_searching' => _x('Searching…', 'enhanced select', 'woocommerce'), 'ajax_url' => admin_url('admin-ajax.php'), 'search_products_nonce' => wp_create_nonce('search-products'), 'search_customers_nonce' => wp_create_nonce('search-customers')));
     // Accounting
     wp_localize_script('accounting', 'accounting_params', array('mon_decimal_point' => wc_get_price_decimal_separator()));
     // WooCommerce admin pages
     if (in_array($screen_id, wc_get_screen_ids())) {
         wp_enqueue_script('iris');
         wp_enqueue_script('woocommerce_admin');
         wp_enqueue_script('wc-enhanced-select');
         wp_enqueue_script('jquery-ui-sortable');
         wp_enqueue_script('jquery-ui-autocomplete');
         $locale = localeconv();
         $decimal = isset($locale['decimal_point']) ? $locale['decimal_point'] : '.';
         $params = array('i18n_decimal_error' => sprintf(__('Please enter in decimal (%s) format without thousand separators.', 'woocommerce'), $decimal), 'i18n_mon_decimal_error' => sprintf(__('Please enter in monetary decimal (%s) format without thousand separators and currency symbols.', 'woocommerce'), wc_get_price_decimal_separator()), 'i18n_country_iso_error' => __('Please enter in country code with two capital letters.', 'woocommerce'), 'i18_sale_less_than_regular_error' => __('Please enter in a value less than the regular price.', 'woocommerce'), 'decimal_point' => $decimal, 'mon_decimal_point' => wc_get_price_decimal_separator());
         wp_localize_script('woocommerce_admin', 'woocommerce_admin', $params);
     }
     // Edit product category pages
     if (in_array($screen_id, array('edit-product_cat'))) {
         wp_enqueue_media();
     }
     // Products
     if (in_array($screen_id, array('edit-product'))) {
         wp_register_script('woocommerce_quick-edit', WC()->plugin_url() . '/assets/js/admin/quick-edit' . $suffix . '.js', array('jquery', 'woocommerce_admin'), WC_VERSION);
         wp_enqueue_script('woocommerce_quick-edit');
     }
     // Meta boxes
     if (in_array($screen_id, array('product', 'edit-product'))) {
         wp_enqueue_media();
         wp_register_script('wc-admin-product-meta-boxes', WC()->plugin_url() . '/assets/js/admin/meta-boxes-product' . $suffix . '.js', array('wc-admin-meta-boxes', 'media-models'), WC_VERSION);
         wp_register_script('wc-admin-variation-meta-boxes', WC()->plugin_url() . '/assets/js/admin/meta-boxes-product-variation' . $suffix . '.js', array('wc-admin-meta-boxes', 'serializejson', 'media-models'), WC_VERSION);
         wp_enqueue_script('wc-admin-product-meta-boxes');
         wp_enqueue_script('wc-admin-variation-meta-boxes');
         $params = array('post_id' => isset($post->ID) ? $post->ID : '', 'plugin_url' => WC()->plugin_url(), 'ajax_url' => admin_url('admin-ajax.php'), 'woocommerce_placeholder_img_src' => wc_placeholder_img_src(), 'add_variation_nonce' => wp_create_nonce('add-variation'), 'link_variation_nonce' => wp_create_nonce('link-variations'), 'delete_variations_nonce' => wp_create_nonce('delete-variations'), 'load_variations_nonce' => wp_create_nonce('load-variations'), 'save_variations_nonce' => wp_create_nonce('save-variations'), 'bulk_edit_variations_nonce' => wp_create_nonce('bulk-edit-variations'), 'i18n_link_all_variations' => esc_js(sprintf(__('Are you sure you want to link all variations? This will create a new variation for each and every possible combination of variation attributes (max %d per run).', 'woocommerce'), defined('WC_MAX_LINKED_VARIATIONS') ? WC_MAX_LINKED_VARIATIONS : 50)), 'i18n_enter_a_value' => esc_js(__('Enter a value', 'woocommerce')), 'i18n_enter_menu_order' => esc_js(__('Variation menu order (determines position in the list of variations)', 'woocommerce')), 'i18n_enter_a_value_fixed_or_percent' => esc_js(__('Enter a value (fixed or %)', 'woocommerce')), 'i18n_delete_all_variations' => esc_js(__('Are you sure you want to delete all variations? This cannot be undone.', 'woocommerce')), 'i18n_last_warning' => esc_js(__('Last warning, are you sure?', 'woocommerce')), 'i18n_choose_image' => esc_js(__('Choose an image', 'woocommerce')), 'i18n_set_image' => esc_js(__('Set variation image', 'woocommerce')), 'i18n_variation_added' => esc_js(__("variation added", 'woocommerce')), 'i18n_variations_added' => esc_js(__("variations added", 'woocommerce')), 'i18n_no_variations_added' => esc_js(__("No variations added", 'woocommerce')), 'i18n_remove_variation' => esc_js(__('Are you sure you want to remove this variation?', 'woocommerce')), 'i18n_scheduled_sale_start' => esc_js(__('Sale start date (YYYY-MM-DD format or leave blank)', 'woocommerce')), 'i18n_scheduled_sale_end' => esc_js(__('Sale end date (YYYY-MM-DD format or leave blank)', 'woocommerce')), 'i18n_edited_variations' => esc_js(__('Save changes before changing page?', 'woocommerce')), 'i18n_variation_count_single' => esc_js(__('%qty% variation', 'woocommerce')), 'i18n_variation_count_plural' => esc_js(__('%qty% variations', 'woocommerce')), 'variations_per_page' => absint(apply_filters('woocommerce_admin_meta_boxes_variations_per_page', 15)));
         wp_localize_script('wc-admin-variation-meta-boxes', 'woocommerce_admin_meta_boxes_variations', $params);
     }
     if (in_array(str_replace('edit-', '', $screen_id), wc_get_order_types('order-meta-boxes'))) {
         wp_register_script('wc-admin-order-meta-boxes', WC()->plugin_url() . '/assets/js/admin/meta-boxes-order' . $suffix . '.js', array('wc-admin-meta-boxes', 'wc-backbone-modal'), WC_VERSION);
         wp_enqueue_script('wc-admin-order-meta-boxes');
         $params = array('countries' => json_encode(array_merge(WC()->countries->get_allowed_country_states(), WC()->countries->get_shipping_country_states())), 'i18n_select_state_text' => esc_attr__('Select an option…', 'woocommerce'));
         wp_localize_script('wc-admin-order-meta-boxes', 'woocommerce_admin_meta_boxes_order', $params);
     }
     if (in_array($screen_id, array('shop_coupon', 'edit-shop_coupon'))) {
         wp_register_script('wc-admin-coupon-meta-boxes', WC()->plugin_url() . '/assets/js/admin/meta-boxes-coupon' . $suffix . '.js', array('wc-admin-meta-boxes'), WC_VERSION);
         wp_enqueue_script('wc-admin-coupon-meta-boxes');
     }
     if (in_array(str_replace('edit-', '', $screen_id), array_merge(array('shop_coupon', 'product'), wc_get_order_types('order-meta-boxes')))) {
         $post_id = isset($post->ID) ? $post->ID : '';
         $currency = '';
         if ($post_id && in_array(get_post_type($post_id), wc_get_order_types('order-meta-boxes'))) {
             $order = wc_get_order($post_id);
             $currency = $order->get_order_currency();
         }
         $params = array('remove_item_notice' => __('Are you sure you want to remove the selected items? If you have previously reduced this item\'s stock, or this order was submitted by a customer, you will need to manually restore the item\'s stock.', 'woocommerce'), 'i18n_select_items' => __('Please select some items.', 'woocommerce'), 'i18n_do_refund' => __('Are you sure you wish to process this refund? This action cannot be undone.', 'woocommerce'), 'i18n_delete_refund' => __('Are you sure you wish to delete this refund? This action cannot be undone.', 'woocommerce'), 'i18n_delete_tax' => __('Are you sure you wish to delete this tax column? This action cannot be undone.', 'woocommerce'), 'remove_item_meta' => __('Remove this item meta?', 'woocommerce'), 'remove_attribute' => __('Remove this attribute?', 'woocommerce'), 'name_label' => __('Name', 'woocommerce'), 'remove_label' => __('Remove', 'woocommerce'), 'click_to_toggle' => __('Click to toggle', 'woocommerce'), 'values_label' => __('Value(s)', 'woocommerce'), 'text_attribute_tip' => __('Enter some text, or some attributes by pipe (|) separating values.', 'woocommerce'), 'visible_label' => __('Visible on the product page', 'woocommerce'), 'used_for_variations_label' => __('Used for variations', 'woocommerce'), 'new_attribute_prompt' => __('Enter a name for the new attribute term:', 'woocommerce'), 'calc_totals' => __('Calculate totals based on order items, discounts, and shipping?', 'woocommerce'), 'calc_line_taxes' => __('Calculate line taxes? This will calculate taxes based on the customers country. If no billing/shipping is set it will use the store base country.', 'woocommerce'), 'copy_billing' => __('Copy billing information to shipping information? This will remove any currently entered shipping information.', 'woocommerce'), 'load_billing' => __('Load the customer\'s billing information? This will remove any currently entered billing information.', 'woocommerce'), 'load_shipping' => __('Load the customer\'s shipping information? This will remove any currently entered shipping information.', 'woocommerce'), 'featured_label' => __('Featured', 'woocommerce'), 'prices_include_tax' => esc_attr(get_option('woocommerce_prices_include_tax')), 'tax_based_on' => esc_attr(get_option('woocommerce_tax_based_on')), 'round_at_subtotal' => esc_attr(get_option('woocommerce_tax_round_at_subtotal')), 'no_customer_selected' => __('No customer selected', 'woocommerce'), 'plugin_url' => WC()->plugin_url(), 'ajax_url' => admin_url('admin-ajax.php'), 'order_item_nonce' => wp_create_nonce('order-item'), 'add_attribute_nonce' => wp_create_nonce('add-attribute'), 'save_attributes_nonce' => wp_create_nonce('save-attributes'), 'calc_totals_nonce' => wp_create_nonce('calc-totals'), 'get_customer_details_nonce' => wp_create_nonce('get-customer-details'), 'search_products_nonce' => wp_create_nonce('search-products'), 'grant_access_nonce' => wp_create_nonce('grant-access'), 'revoke_access_nonce' => wp_create_nonce('revoke-access'), 'add_order_note_nonce' => wp_create_nonce('add-order-note'), 'delete_order_note_nonce' => wp_create_nonce('delete-order-note'), 'calendar_image' => WC()->plugin_url() . '/assets/images/calendar.png', 'post_id' => isset($post->ID) ? $post->ID : '', 'base_country' => WC()->countries->get_base_country(), 'currency_format_num_decimals' => wc_get_price_decimals(), 'currency_format_symbol' => get_woocommerce_currency_symbol($currency), 'currency_format_decimal_sep' => esc_attr(wc_get_price_decimal_separator()), 'currency_format_thousand_sep' => esc_attr(wc_get_price_thousand_separator()), 'currency_format' => esc_attr(str_replace(array('%1$s', '%2$s'), array('%s', '%v'), get_woocommerce_price_format())), 'rounding_precision' => wc_get_rounding_precision(), 'tax_rounding_mode' => WC_TAX_ROUNDING_MODE, 'product_types' => array_unique(array_merge(array('simple', 'grouped', 'variable', 'external'), array_keys(wc_get_product_types()))), 'i18n_download_permission_fail' => __('Could not grant access - the user may already have permission for this file or billing email is not set. Ensure the billing email is set, and the order has been saved.', 'woocommerce'), 'i18n_permission_revoke' => __('Are you sure you want to revoke access to this download?', 'woocommerce'), 'i18n_tax_rate_already_exists' => __('You cannot add the same tax rate twice!', 'woocommerce'), 'i18n_product_type_alert' => __('Your product has variations! Before changing the product type, it is a good idea to delete the variations to avoid errors in the stock reports.', 'woocommerce'), 'i18n_delete_note' => __('Are you sure you wish to delete this note? This action cannot be undone.', 'woocommerce'));
         wp_localize_script('wc-admin-meta-boxes', 'woocommerce_admin_meta_boxes', $params);
     }
     // Term ordering - only when sorting by term_order
     if ((strstr($screen_id, 'edit-pa_') || !empty($_GET['taxonomy']) && in_array($_GET['taxonomy'], apply_filters('woocommerce_sortable_taxonomies', array('product_cat')))) && !isset($_GET['orderby'])) {
         wp_register_script('woocommerce_term_ordering', WC()->plugin_url() . '/assets/js/admin/term-ordering' . $suffix . '.js', array('jquery-ui-sortable'), WC_VERSION);
         wp_enqueue_script('woocommerce_term_ordering');
         $taxonomy = isset($_GET['taxonomy']) ? wc_clean($_GET['taxonomy']) : '';
         $woocommerce_term_order_params = array('taxonomy' => $taxonomy);
         wp_localize_script('woocommerce_term_ordering', 'woocommerce_term_ordering_params', $woocommerce_term_order_params);
     }
     // Product sorting - only when sorting by menu order on the products page
     if (current_user_can('edit_others_pages') && $screen_id == 'edit-product' && isset($wp_query->query['orderby']) && $wp_query->query['orderby'] == 'menu_order title') {
         wp_register_script('woocommerce_product_ordering', WC()->plugin_url() . '/assets/js/admin/product-ordering' . $suffix . '.js', array('jquery-ui-sortable'), WC_VERSION, true);
         wp_enqueue_script('woocommerce_product_ordering');
     }
     // Reports Pages
     if (in_array($screen_id, apply_filters('woocommerce_reports_screen_ids', array($wc_screen_id . '_page_wc-reports', 'toplevel_page_wc-reports', 'dashboard')))) {
         wp_register_script('wc-reports', WC()->plugin_url() . '/assets/js/admin/reports' . $suffix . '.js', array('jquery', 'jquery-ui-datepicker'), WC_VERSION);
         wp_enqueue_script('wc-reports');
         wp_enqueue_script('flot');
         wp_enqueue_script('flot-resize');
         wp_enqueue_script('flot-time');
         wp_enqueue_script('flot-pie');
         wp_enqueue_script('flot-stack');
     }
     // API settings
     if ($wc_screen_id . '_page_wc-settings' === $screen_id && isset($_GET['section']) && 'keys' == $_GET['section']) {
         wp_register_script('wc-api-keys', WC()->plugin_url() . '/assets/js/admin/api-keys' . $suffix . '.js', array('jquery', 'woocommerce_admin', 'underscore', 'backbone', 'wp-util', 'qrcode', 'zeroclipboard'), WC_VERSION, true);
         wp_enqueue_script('wc-api-keys');
         wp_localize_script('wc-api-keys', 'woocommerce_admin_api_keys', array('ajax_url' => admin_url('admin-ajax.php'), 'update_api_nonce' => wp_create_nonce('update-api-key'), 'clipboard_failed' => esc_html__('Copying to clipboard failed. Please press Ctrl/Cmd+C to copy.', 'woocommerce')));
     }
     // System status
     if ($wc_screen_id . '_page_wc-status' === $screen_id) {
         wp_enqueue_script('zeroclipboard');
     }
     if (in_array($screen_id, array('user-edit', 'profile'))) {
         wp_register_script('wc-users', WC()->plugin_url() . '/assets/js/admin/users' . $suffix . '.js', array('jquery', 'wc-enhanced-select'), WC_VERSION, true);
         wp_enqueue_script('wc-users');
         wp_localize_script('wc-users', 'wc_users_params', array('countries' => json_encode(array_merge(WC()->countries->get_allowed_country_states(), WC()->countries->get_shipping_country_states())), 'i18n_select_state_text' => esc_attr__('Select an option…', 'woocommerce')));
     }
 }
Exemplo n.º 5
0
 /**
  * Load options.
  *
  * @access public
  */
 public static function init()
 {
     self::$precision = wc_get_rounding_precision();
     self::$round_at_subtotal = 'yes' === get_option('woocommerce_tax_round_at_subtotal');
 }
Exemplo n.º 6
0
 /**
  * Gets the total discount amount.
  * @param  bool $ex_tax Show discount excl any tax.
  * @return float
  */
 public function get_total_discount($ex_tax = true)
 {
     if (!$this->order_version || version_compare($this->order_version, '2.3.7', '<')) {
         // Backwards compatible total calculation - totals were not stored consistently in old versions.
         if ($ex_tax) {
             if ($this->prices_include_tax) {
                 $total_discount = (double) $this->cart_discount - (double) $this->cart_discount_tax;
             } else {
                 $total_discount = (double) $this->cart_discount;
             }
         } else {
             if ($this->prices_include_tax) {
                 $total_discount = (double) $this->cart_discount;
             } else {
                 $total_discount = (double) $this->cart_discount + (double) $this->cart_discount_tax;
             }
         }
         // New logic - totals are always stored exclusive of tax, tax total is stored in cart_discount_tax
     } else {
         if ($ex_tax) {
             $total_discount = (double) $this->cart_discount;
         } else {
             $total_discount = (double) $this->cart_discount + (double) $this->cart_discount_tax;
         }
     }
     return apply_filters('woocommerce_order_amount_total_discount', round($total_discount, wc_get_rounding_precision()), $this);
 }
/**
 * Helper function to get around WooCommerce version 2.6.3 which removed the constant WC_ROUNDING_PRECISION and
 * introduced the function wc_get_rounding_precision. Every version 2.6.2 and earlier has the constant. Every version
 * 2.6.4 and later (hopefully) will also have the constant AND the wc_get_rounding_precision function. 2.6.3 only has
 * the function however.
 *
 * @see https://github.com/Prospress/woocommerce-subscriptions/issues/1545
 *
 * @return int rounding precision
 */
function wcs_get_rounding_precision()
{
    if (function_exists('wc_get_rounding_precision')) {
        $precision = wc_get_rounding_precision();
    } elseif (defined('WC_ROUNDING_PRECISION')) {
        $precision = WC_ROUNDING_PRECISION;
    } else {
        $precision = wc_get_price_decimals() + 2;
    }
    return $precision;
}