Take the 2-minute tour ×
WordPress Development Stack Exchange is a question and answer site for WordPress developers and administrators. It's 100% free, no registration required.

I'm new to WooCommerce and I have the problem that grouped products always show the default VAT because I can't change the tax setting on the grouped products. The simple products combined by the grouped one have the reduced rate.

So I probably have to change the output in my (sub-)theme to the VAT of the first connected simple product, right?

How can I do that?

** Edit **

I have no problem with the shop calculating the VAT wrong. I have a problem with displaying the tax on grouped products. It shows the default rate with the grouped product even if all connected simple products have a reduced rate. And since I have to show the rate on the product page in germany I have to change that.

share|improve this question
    
Just to clarify some thoughts and a question. In my mind what you want makes no sense, because normally - at least here in germany and some other european countries, from which I know the rules - the VAT isn't something you can choose yourself, it is legally binding! This also implies for selling various types together, ergo for grouped products. What that means is, if you lower the VAT, you have to pay it, but your customer doesn't. That is bad, at the least when you are going to make tax filing. So I'm guessing what you really want is to give a discount on grouped products, right? –  ialocin Sep 13 '13 at 9:10
    
I have some products with regular 19% VAT and some food products that are 7%. If I group different 7% products (different packaging sizes) the grouped product still shows 19% (the default rate) in overviews and on the page of the grouped product. The simple products show the correct 7% on their pages. But it seems like I can't set the VAT rate on a grouped product page and it doesn't respect the setting of the products linked either. –  dantz Sep 13 '13 at 9:19
    
That's most likely a configuration problem. Or do you have some tweaks in your code which could do that? I did a quick test on my development site and there is no problem at all with the setting you describe- the different taxes are calculated as expected. –  ialocin Sep 13 '13 at 9:23
    
Last question: the code that output the wrong rate come from the plugin template files or come from your theme / child theme? If the second, you should post here the code to someone help you. –  G. M. Sep 13 '13 at 11:06
    
Please follow up on the questions you asked, it's an important part of the process on WPSE - see What should I do when someone answers my question? and Why is voting important? for a deeper insight. Thank you! –  ialocin Nov 7 '13 at 13:14
add comment

2 Answers

code update:

add_action( 'woocommerce_grouped_product_list_before_price', 
            'woocommerce_grouped_product_tax_on_single', 10, 1, $child_product, $mode );

function woocommerce_grouped_product_tax_on_single( $child_product, $mode = null ) {
//uncomment next line and choose one of the output options from »switch case "{OPTION}"«
//$mode = 'tax-name-rate-amount';
    $_taxobj = new WC_Tax();
    $obj = $_taxobj->get_shop_base_rate($child_product->get_tax_class());
    $i_or_e = get_option('woocommerce_prices_include_tax') == 'no' ? 'excl.' : 'incl.'; 
?>
    <td class="grp_tax">
    <?php
        foreach ( $obj as $sobj ) {

           $stax = woocommerce_price( $sobj['rate'] / 100 * 
                   ( get_option('woocommerce_prices_include_tax') == 'no' ? 
                   $child_product->get_price_including_tax() : 
                   $child_product->get_price_excluding_tax() ) );

            switch ($mode) {
                case null:
                    $format = " %s %s";
                    $variables = array($i_or_e, $sobj['label']);
                    break;
                case "tax-name":
                    $format = " %s %s";
                    $variables = array($i_or_e, $sobj['label']);
                    break;
                case "tax-name-rate":
                    $format = " %s %s %s%%";
                    $variables = array($i_or_e, 
                                        $sobj['label'], 
                                        number_format($sobj['rate']));
                    break;
                case "tax-name-rate-amount":
                    $format = " %s %s (%s%% - %s)";
                    $variables = array($i_or_e, 
                                        $sobj['label'], 
                                        number_format($sobj['rate']), 
                                        $stax);
                    break;
            }
            $output = vsprintf($format, $variables);
        }
        echo $output;
        ?>
    </td>
    <?php
}

The updated code is pretty much the same, but with some new features. Like @noxoc pointed out, it would be nicer to use a hook. Above code uses the woocommerce_grouped_product_list_before_price action to hook in. This one is already defined inside grouped.php. Unfortunately this - in my mind - doesn't read nice, because you get something like »tax information price«, personally I want it to read like »price tax information«. For that I added a action woocommerce_grouped_product_list_after_price inside grouped.php:

    //this is the existing action
    <?php do_action ( 'woocommerce_grouped_product_list_before_price', 
                      $child_product['product'] ); ?>
    //this is the table cell for the price
    <td class="price">
        {SOME CODE}
    </td>
    //this is the NEW action you have to add yourself
    <?php do_action ( 'woocommerce_grouped_product_list_after_price', 
                      $child_product['product'] ); ?>

As you can see the new action pretty much replicates the existing one. If you added the action, you can change the add_action() line in above code to use it:

    add_action( 'woocommerce_grouped_product_list_after_price', 
    'woocommerce_grouped_product_tax_on_single', 10, 1, $child_product, $mode );

Additionally I added some options to choose which information to show on output. You have to set the $mode variable for that. This should be pretty much self-explanatory - see the comment inside code. This could for example be used for setting the variable at a options page in the backend. Besides that it of course is possible to change the formatting of the output, just follow the use cases in the code do your own.




code:

    $_taxobj = new WC_Tax();
    $obj = $_taxobj->get_shop_base_rate($child_product['product']->get_tax_class());

    $i_or_e = get_option('woocommerce_prices_include_tax') == 'no' ? 'excl.' : 'incl.';
    foreach ( $obj as $sobj ) { printf(" %s %s%% %s", $i_or_e, number_format($sobj['rate']), $sobj['label']); }

That would be going into the grouped.php located at {THEME-FOLDER}/woocommerce/single-product/add-to-cart/ inside the <td class="price">{CONTENT INSIDE}</td> code. The code is able to distinguish between included/excluded tax and gets according the tax rate as well as the tax label for the simple products inside the group.

share|improve this answer
    
Thanks for your effort. Calculation works fine. but on the product page of the grouped product and when the grouped page is shown in category listings it still shows the default rate. –  dantz Sep 13 '13 at 10:12
    
@ialocin I've just edited your echo syntax with printf for readability, but the code how is doesn't handle any number of thax, just one, because your echo (and my printf) are ouside of the foreach loop. After that, why run 2 identical foreach loops? You can improve your code, I think ;). Maybe: $i_or_e = get_option('woocommerce_prices_include_tax') == 'no' ? 'excl.' : 'incl.'; foreach ( $obj as $sobj ) { printf(" %s %s%% %s", $i_or_e, $sobj['rate'], $sobj['label']); } –  G. M. Sep 13 '13 at 13:31
    
@G.M. I give it a try, but I'm assuming you are right :) I eliminated the second foreach anyway, but this solution would be even nicer. What I meant by any number of tax classes is just that now it takes the class from the product, before I only checked for reduced or not. (3 min later) Of course you are right with your optimization, I changed it. Thanks! –  ialocin Sep 13 '13 at 13:40
    
@ialocin. You're welcome and +1 –  G. M. Sep 13 '13 at 14:11
    
Hi Ialocin, do you create plugins, i need to hire someone who can! –  Lucky Luke Sep 23 '13 at 12:44
add comment

You could add a custom field to the product group eg. tax_class and then overwrite it with a filter in you functions.php. Example:

add_filter( 'woocommerce_de_print_including_tax', 'foo_woocommerce_de_print_including_tax', 10 , 1);
function foo_woocommerce_de_print_including_tax($value) {
    global $product;
    $product->tax_class = get_post_meta($product->id, 'tax_class', true);
    return $value;
}

However I'm not sure which filter would suit best. This seems a bit dirty, but should do the trick.

share|improve this answer
    
The filters you are looking for are woocommerce_grouped_price_html, which shows the »From: xxx €« for the group, so it's not helpful for the question asked. And woocommerce_get_price_html, this applies not only to simple products inside a grouped one, but to all of them. Those are the filter used inside class-wc-product-grouped.php. I'm 99% certain there isn't a filter which applies only to childes of a grouped product. Btw there already is a custom field for the tax class, it is: _tax_class. –  ialocin Sep 17 '13 at 11:19
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.