Vendor Per Product Tax

Setting up taxes and tax rates is one of the first tasks you want to perform when setting up a store. However, the tax calculation gets carried out by WooCommerc. This document might help you further in how WooCommerce handles the tax :
Therefore, the tax will be either calculated as per admin’s location or customer’s location.

However, for a multivendor site, sometimes a vendor needs to earn tax as per the law in their own state.

As a workaround, this following code will let the vendor add tax per product.

add_action( 'mvx_frontend_dashboard_product_options_stock_status', 'mvx_extra_fields_in_products_grouped',10,3 );
function mvx_extra_fields_in_products_grouped($post__ID, $product_object, $post){
    $get_tax_rate = get_post_meta($post__ID,'_extra_tax_per_product_key',true);
    ?>
    <div class="form-group">
        <label class="control-label col-sm-3 col-md-3" for="_extra_tax_per_product"><?php echo __( 'Per product tax', 'woocommerce' ); ?></label>
            <div class="col-md-6 col-sm-9">
                <input type="text" id="_extra_tax_per_product" name="_extra_tax_per_product" value="<?php print_r($get_tax_rate); ?>" class="form-control">
            </div>
    </div>
    <?php
}

add_action( 'mvx_frontend_dashboard_after_general_product', 'mvx_extra_fields_in_products',10,3);
function mvx_extra_fields_in_products($post__ID, $product_object, $post){
    $get_tax_rate = get_post_meta($post__ID,'_extra_tax_per_product_key',true);
    ?>
    <div class="form-group">
        <label class="control-label col-sm-3 col-md-3" for="_extra_tax_per_product"><?php echo __( 'Per product tax', 'woocommerce' ); ?></label>
            <div class="col-md-6 col-sm-9">
                <input type="text" id="_extra_tax_per_product" name="_extra_tax_per_product" value="<?php print_r($get_tax_rate); ?>" class="form-control">
            </div>
    </div>
    <?php
}

This code will add a section like this screenshot:

Now, we also add a checking, if a vendor hasn’t added per product tax, then WooCommerce’s tax rule will be applied. For this use this code :

/**
** Per product on tax setting woocommerce
**/
add_filter( 'woocommerce_tax_settings', 'vendor_based_tax' );
function vendor_based_tax( $settings ){
  $settings[2]['options']['per_product'] = __('Per product tax','dc-woocommerce-multi-vendor');
  return $settings;
}

/**
** Extra fields save in cluding product tax rate
**/

add_action('mvx_process_product_object','save_tax_rate', 10, 2);
function save_tax_rate($product, $post){ 
    $per_tax_price = $post['_extra_tax_per_product'];
    update_post_meta($product->get_id(),'_extra_tax_per_product_key',$per_tax_price);

    $tax_rate_id = get_post_meta( $product->get_id() , 'product_tax_rate_id' ,true );
    if ( metadata_exists( 'post', $product->get_id(), 'product_tax_rate_id' ) && $tax_rate_id ) {

    	$tax_rate = array(
    		'tax_rate_country'  => '',
    		'tax_rate_state'    => '',
    		'tax_rate'          => $per_tax_price,
    		'tax_rate_name'     => __( 'Per Product Tax('.$product->get_name().')', 'dc-woocommerce-multi-vendor'),
    		'tax_rate_priority' => 1,
    		'tax_rate_compound' => 0,
    		'tax_rate_shipping' => 1,
    		'tax_rate_order'    => 3,
    		);

    	WC_Tax::_update_tax_rate( $tax_rate_id, $tax_rate );
    } else {
    	$tax_rate = array(
    		'tax_rate_country'  => '',
    		'tax_rate_state'    => '',
    		'tax_rate'          => $per_tax_price,
    		'tax_rate_name'     => __( 'Per Product Tax('.$product->get_name().')', 'dc-woocommerce-multi-vendor'),
    		'tax_rate_priority' => 1,
    		'tax_rate_compound' => 0,
    		'tax_rate_shipping' => 1,
    		'tax_rate_order'    => 3,
    		);
    	$tax_rate_id = WC_Tax::_insert_tax_rate( $tax_rate );
    	update_post_meta($product->get_id(),'product_tax_rate_id',$tax_rate_id);
    }
}

/**
**  Add tax on parent order
**/

add_filter( 'woocommerce_cart_totals_get_item_tax_rates', 'woocommerce_cart_totals_get_item_tax_rates_per_product' , 10 , 3 );
function woocommerce_cart_totals_get_item_tax_rates_per_product( $item_tax_rates, $items, $cart ){
	
	// check per product tax is enable or not
	$tax_based_on = get_option( 'woocommerce_tax_based_on' );
	if( 'per_product' !== $tax_based_on ) return $item_tax_rates;

	$find_rate = array();
	$product_tax_rate = get_post_meta( $items->object['product_id'] , 'product_tax_rate_id' ,true );
	
	if( !$product_tax_rate ) return $item_tax_rates;

	$get_tax_rate = WC_Tax::_get_tax_rate( $product_tax_rate );
	$find_rate[$get_tax_rate['tax_rate_id']] = array(  
		'rate' => $get_tax_rate['tax_rate'],
		'label' => $get_tax_rate['tax_rate_name'],
		'shipping' => 'yes',
		'compound' => 'no'  
		);
	return $find_rate;
}


/**
***  Add shipping on parent order
**/

add_filter( 'woocommerce_shipping_method_add_rate', 'vendor_based_shipping_rate_per_product', 10 , 3 );
function vendor_based_shipping_rate_per_product( $rate, $args, $package ){
	// check per product tax is enable or not
	$tax_based_on = get_option( 'woocommerce_tax_based_on' );
	if( 'per_product' !== $tax_based_on ) return $rate;

  	$taxes      = $args['taxes'];
	$total_cost = is_array( $args['cost'] ) ? array_sum( $args['cost'] ) : $args['cost'];
	if ( $args['package'] ) {
 	   foreach ( $args['package']['contents'] as $item ) {
 	   		$product = $item['data'];
 	   		$product_tax_rate = get_post_meta( $product->get_id() , 'product_tax_rate_id' ,true );

 	   		if( $product_tax_rate ){
	 	   		$get_tax_rate = WC_Tax::_get_tax_rate( $product_tax_rate );
	 	   		$find_rate[$get_tax_rate['tax_rate_id']] = array(  
	 	   			'rate' => $get_tax_rate['tax_rate'],
	 	   			'label' => $get_tax_rate['tax_rate_name'],
	 	   			'shipping' => 'yes',
	 	   			'compound' => 'no'  
	 	   			);

	 	   		if ( ! is_array( $taxes ) && false !== $taxes && $total_cost > 0 && $package->is_taxable() ) {

	 	   			$taxes = 'per_item' === $args['calc_tax'] ? $package->get_taxes_per_item( $args['cost'] ) : WC_Tax::calc_shipping_tax( $total_cost, $find_rate );
	 	   		}
	 	   		$total_cost = wc_format_decimal( $total_cost, $args['price_decimals'] );
	 	   		$rate->set_taxes( $taxes );
	 	   	}
    	}
	}
	return $rate;
}


/**
***  Add tax on sub order
**/
add_action( 'woocommerce_order_item_after_calculate_taxes', 'calculate_tax_for_per_product', 10 , 2 );
function calculate_tax_for_per_product( $item, $calculate_tax_for ){

  	// check per product tax is enable or not
	$tax_based_on = get_option( 'woocommerce_tax_based_on' );
	if( 'per_product' !== $tax_based_on ) return $item;

  	$product_tax_rate = get_post_meta( $item->get_product_id() , 'product_tax_rate_id' ,true );
  	if( !$product_tax_rate ) return $item;

  	$get_tax_rate = WC_Tax::_get_tax_rate( $product_tax_rate );
  	$find_rate[$get_tax_rate['tax_rate_id']] = array(  
  		'rate' => $get_tax_rate['tax_rate'],
  		'label' => $get_tax_rate['tax_rate_name'],
  		'shipping' => 'yes',
  		'compound' => 'no'  
  		);

  	$tax_rates                      = $find_rate;
  	$taxes                          = WC_Tax::calc_tax( $item->get_total(), $tax_rates, false );

  	if ( method_exists( $item, 'get_subtotal' ) ) {
  		$subtotal_taxes = WC_Tax::calc_tax( $item->get_subtotal(), $tax_rates, false );
  		$item->set_taxes(
  			array(
  				'total'    => $taxes,
  				'subtotal' => $subtotal_taxes,
  				)
  			);
  	} else {
  		$item->set_taxes( array( 'total' => $taxes ) );
  	}
	return $item;
}

/**
** Add shipping on sub order  
**/
add_action( 'woocommerce_order_item_shipping_after_calculate_taxes', 'add_shipping_on_sub', 99 , 2 );
function add_shipping_on_sub( $item, $calculate_tax_for ){
	// check per product tax is enable or not
	$tax_based_on = get_option( 'woocommerce_tax_based_on' );
	if( 'per_product' !== $tax_based_on ) return $item;

	$order = wc_get_order( $item->get_order_id() );
	$items = $order->get_items();
	$find_rate = array();
	foreach ( $items as $itemt ) {
		$product_tax_rate = get_post_meta( $itemt['product_id'] , 'product_tax_rate_id' ,true );

		if( $product_tax_rate ){
			$get_tax_rate = WC_Tax::_get_tax_rate( $product_tax_rate );
			$find_rate[$get_tax_rate['tax_rate_id']] = array(  
				'rate' => $get_tax_rate['tax_rate'],
				'label' => $get_tax_rate['tax_rate_name'],
				'shipping' => 'yes',
				'compound' => 'no'  
				);
		}
	}

	if ( wc_tax_enabled() && $find_rate ) {
		$taxes     = WC_Tax::calc_tax( $item->get_total(), $find_rate, false );
		$item->set_taxes( array( 'total' => $taxes ) );
	} else {
		$item->set_taxes( false );
	}
	return $item;
}

Leave a Reply