2015-12-16 2 views
4

Так, например, у меня есть продукт, который стоит £ 2/item, если вы покупаете синглы или £ 1/item, если вы покупаете его в пакетах 6.Woocommerce - Могу ли я перехватить расчет стоимости линии (Корзина)?

Клиенты вводят требуемое количество, скажем, 7, а затем добавьте его в корзину.

Общая стоимость должна составлять £ 8. £ 6 (1 пакет) + £ 2 (1 сингл). Но если я добавлю его в корзину в настоящее время, цена выйдет как 7 фунтов стерлингов, как и следовало ожидать (это всего лишь 7 х цена, которая составляет 1 фунт стерлингов).

Мне нужно перехватить/отфильтровать стоимость линии, чтобы она подсчитывала количество пакетов и количество синглов, а затем возвращает нужную сумму. Я могу спроектировать функцию и математику, мне просто нужно знать, куда ее зацепить.

У меня есть фильтр типа woocommerce_get_cart или что-то подобное? И если да, как мне изменить цену линии?

(p.s. Я знаю, что я мог бы достичь с переменными продуктами, например, но это не вариант для контроля запасов).

ответ

4
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(); 

     /** 
     * Calculate subtotals for items. This is done first so that discount logic can use the values. 
     */ 
     foreach ($this->get_cart() as $cart_item_key => $values) { 

      $_product = $values['data']; 

      // Count items + weight 
      $this->cart_contents_weight += $_product->get_weight() * $values['quantity']; 
      $this->cart_contents_count += $values['quantity']; 

      // Prices 
      $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 
       */ 
       if ($item_tax_rates !== $base_tax_rates) { 

        // 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; 
     } 

     /** 
     * Calculate totals for items 
     */ 
     foreach ($this->get_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   = WC_Tax::round($discounted_price * $values['quantity']); 

      /** 
      * 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 
       */ 
       if ($item_tax_rates !== $base_tax_rates) { 

        // 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_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 
        $discounted_price = $this->get_discounted_price($values, $adjusted_price, true); 
        $discounted_taxes = WC_Tax::calc_tax($discounted_price * $values['quantity'], $item_tax_rates, true); 
        $line_tax   = array_sum($discounted_taxes); 
        $line_total  = ($discounted_price * $values['quantity']) - $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); 
        $discounted_taxes = WC_Tax::calc_tax($discounted_price * $values['quantity'], $item_tax_rates, true); 
        $line_tax   = array_sum($discounted_taxes); 
        $line_total  = ($discounted_price * $values['quantity']) - $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 
      $this->cart_contents[ $cart_item_key ]['line_total']  = $line_total; 
      $this->cart_contents[ $cart_item_key ]['line_tax']   = $line_tax; 
      $this->cart_contents[ $cart_item_key ]['line_subtotal']  = $line_subtotal; 
      $this->cart_contents[ $cart_item_key ]['line_subtotal_tax'] = $line_subtotal_tax; 

      // Store rates ID and costs - Since 2.2 
      $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->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->is_vat_exempt()) { 
       $this->remove_taxes(); 
      } 
     } 

     do_action('woocommerce_after_calculate_totals', $this); 

     $this->set_session(); 
    } 

Это исходные итоговые расчеты по WooCommerce.

вблизи дна у вас есть:

// Allow plugins to hook and alter totals before final total is calculated 
    do_action('woocommerce_calculate_totals', $this); 

которого я верю, что вы можете использовать, чтобы сделать что-то вроде этого:

add_action('woocommerce_calculate_totals','my_woocommerce_calculate_totals'); 
    function my_woocommerce_calculate_totals($cart) { 
     // get some hints from the code above and do something like foreach ($cart->get_cart() as $cart_item_key => $values) { } 
     // do your math, then set $cart->cart_contents_total 
    } 
+0

выглядит отлично - спасибо – mevukpaul

+0

Не могли бы вы мне помочь понять, как выполнить функция my_woocommerce_calculate_totals? Для целей тестирования просто скажем, что я хотел добавить 170 к строке_цены каждого элемента. Код (не работает), который у меня есть в функциях моей функции. Php: add_action ('woocommerce_calculate_totals', 'my_woocommerce_calculate_totals'); function my_woocommerce_calculate_totals ($ cart) { foreach ($ cart-> get_cart() as $ cart_item_key => $ values) {$ line_price = $ line_price + 170; } \t \t возвращение $ cart-> cart_contents_total; } – mevukpaul