In Woocommerce, I've set the number of decimal to 7 on in Woocommerce general settings, so I can display the product price like this $0.0453321.
I'm wondering if I can set/round the cart total to only 2 decimals (something like this $2.34)?
The correct way is to change just the number of allowed decimals for cart and checkout pages only:
add_filter( 'wc_get_price_decimals', 'change_prices_decimals', 20, 1 );
function change_prices_decimals( $decimals ){
if( is_cart() || is_checkout() )
$decimals = 2;
return $decimals;
}
Code goes in function.php file of your active child theme (or active theme). Tested and works.
To set the dispayed cart gran total with 2 decimals use this instead (for Woocommerce 3.3+ only):
add_filter( 'woocommerce_cart_tax_totals', 'change_decimals_cart_tax_totals', 20, 2 );
function change_decimals_cart_tax_totals( $tax_totals, $cart ){
$decimals = array('decimals' => 2);
$taxes = $cart->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 ), $decimals );
}
}
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 $tax_totals;
}
add_filter( 'woocommerce_cart_totals_order_total_html', 'change_decimals_cart_totals_order_total_html', 20, 1 );
function change_decimals_cart_totals_order_total_html( $formatted_price ){
$decimals = array('decimals' => 2);
$value = '<strong>' . wc_price( WC()->cart->get_total('edit'), $decimals ) . '</strong> ';
// If prices are tax inclusive, show taxes here.
if ( wc_tax_enabled() && WC()->cart->display_prices_including_tax() ) {
$tax_string_array = array();
$cart_tax_totals = WC()->cart->get_tax_totals();
if ( get_option( 'woocommerce_tax_total_display' ) == 'itemized' ) {
foreach ( $cart_tax_totals as $code => $tax ) {
$tax_string_array[] = sprintf( '%s %s', $tax->formatted_amount, $tax->label );
}
} elseif ( ! empty( $cart_tax_totals ) ) {
$tax_string_array[] = sprintf( '%s %s', wc_price( WC()->cart->get_taxes_total( true, true ), $decimals ), WC()->countries->tax_or_vat() );
}
if ( ! empty( $tax_string_array ) ) {
$taxable_address = WC()->customer->get_taxable_address();
$estimated_text = WC()->customer->is_customer_outside_base() && ! WC()->customer->has_calculated_shipping()
? sprintf( ' ' . __( 'estimated for %s', 'woocommerce' ), WC()->countries->estimated_for_prefix( $taxable_address[0] ) . WC()->countries->countries[ $taxable_address[0] ] )
: '';
$value .= '<small class="includes_tax">' . sprintf( __( '(includes %s)', 'woocommerce' ), implode( ', ', $tax_string_array ) . $estimated_text ) . '</small>';
}
}
return $value;
}
Code goes in function.php file of your active child theme (or active theme). Tested and works.
You can't really round the prices in cart totals appart. If you do it with different hooks, you will get calculation errors. My code is just changing the number of decimals on displayed formatted prices and will not alter the calculations on real prices…
Related: Change number of decimals on Woocommerce displayed cart subtotal
If you want to change cart total only at cart and checkout page then you need to copy template in your theme
First copy 2 files from woocommerce plugin template to your theme .
1) Copy plugins\woocommerce\templates\cart\cart-totals.php to your-theme-folder\woocommerce\cart\cart-totals.php
2) Copy plugins\woocommerce\templates\checkout\review-order.php to your-theme-folder\woocommerce\checkout\review-order.php
And in both files find the wc_cart_totals_order_total_html() comment this code and put below code instead.
$args=array('decimals'=> 2);
echo wc_price(WC()->cart->total,$args);
This code is tested and its working fine.Hope it will help you as well.
In my case I needed to keep 3 decimal places "visible" throughout the site but approximate only the grand total to 2 decimal places (with a zero for the third decimal place) because my payment gateway accepted only 2 significant digits after the decimal.
Prices displayed as: 0.336
Taxes: 0.017
But grand total needed to be: 0.350 (instead of 0.353)
I ended up not using the code because it was so horrific but you can say it was a mental excercise:
add_filter( 'wc_get_price_decimals', 'change_prices_decimals', 20, 1 );
function change_prices_decimals( $decimals ){
if( is_cart() || is_checkout() )
{
$trace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS,0);
$length = count($trace);
for ($i = 0; $i < $length; $i++)
{
if($trace[$i]["function"] == "set_total"){
$decimals = 2;
return $decimals;
}
}
}
return $decimals;
}
Related
I want to add weight metadata to an order in the Frontend: My Account - Orders. I tried some things but it is not working.
I want to add is $order->get_weight(); as meta data to the order but I am getting an error.
I am already half way using this code to add a new column and show product description and quantity:
add_filter( 'woocommerce_my_account_my_orders_columns', 'additional_my_account_orders_column', 10, 1 );
function additional_my_account_orders_column( $columns ) {
$new_columns = [];
foreach ( $columns as $key => $name ) {
$new_columns[ $key ] = $name;
if ( 'order-status' === $key ) {
$new_columns['order-items'] = __( 'Descripción', 'woocommerce' );
}
}
return $new_columns;
}
add_action( 'woocommerce_my_account_my_orders_column_order-items', 'additional_my_account_orders_column_content', 10, 1 );
function additional_my_account_orders_column_content( $order ) {
$details = array();
foreach( $order->get_items() as $item )
$details[] = $item->get_name() . ' × ' . $item->get_quantity();
echo count( $details ) > 0 ? implode( '<br>', $details ) : '–';
}
Hope someone can help me get in the right direction.
This snippet inserts a new, custom column in the table of orders shown in My Account > Orders populated with the total weight of the order so the customer is aware how heavy their order was.
Specifically, this snippet has two blocks of code. The first block inserts the column. In this example, we have inserted this column between the Order Total and Order Actions column. This can be changed by changing the column key in the code. Your custom will appear after the column key you define.
The second block of code is where the magic happens. It first loops through each item in the order and gets it weight and times this by the quantity of this product. It then adds this weight of each product to a variable we have called $total_weight. The total weight is then output to the new column followed by the weight unit you have defined in your store settings under WordPress Dashboard > WooCommerce > Settings > Products > General > Measurements > Weight Unit.
/**
* Snippet Name: WooCommerce Show Order Weight Column In My Account Order View Table
* Snippet Author: ecommercehints.com
*/
// First, create the new table column between Total and Actions columns
add_filter( 'woocommerce_my_account_my_orders_columns', 'ecommercehints_weight_column_my_account_orders_table', 10, 1 );
function ecommercehints_weight_column_my_account_orders_table( $columns ) {
$weight_column = [];
foreach ( $columns as $key => $name ) {
$weight_column[ $key ] = $name;
if ( 'order-total' === $key ) { // Insert new column after Total column
$weight_column['order-items'] = __( 'Order Weight', 'woocommerce' );
}
}
return $weight_column;
}
// Second, insert the data from the order into the new column
add_action( 'woocommerce_my_account_my_orders_column_order-items', 'ecommercehints_get_order_weight', 10, 1 );
function ecommercehints_get_order_weight( $order ) {
$weight_unit = get_option('woocommerce_weight_unit');
$total_weight = 0;
foreach( $order->get_items() as $item_id => $item ){
$quantity = $item->get_quantity();
$product = $item->get_product();
$product_weight = $product->get_weight();
$total_weight += floatval( $product_weight * $quantity );
}
echo $total_weight . $weight_unit;
}
Just came across this, have you tried it? https://gist.github.com/kloon/5299119?permalink_comment_id=1415838
Here is a copy of the code in case the link eventually dies:
<?php
add_filter( 'manage_edit-shop_order_columns', 'woo_order_weight_column' );
function woo_order_weight_column( $columns ) {
$columns['total_weight'] = __( 'Weight', 'woocommerce' );
return $columns;
}
add_action( 'manage_shop_order_posts_custom_column', 'woo_custom_order_weight_column', 2 );
function woo_custom_order_weight_column( $column ) {
global $post, $woocommerce, $the_order;
if ( empty( $the_order ) || $the_order->get_id() !== $post->ID )
$the_order = new WC_Order( $post->ID );
if ( $column == 'total_weight' ) {
$weight = 0;
if ( sizeof( $the_order->get_items() ) > 0 ) {
foreach( $the_order->get_items() as $item ) {
if ( $item['product_id'] > 0 ) {
$_product = $item->get_product();
if ( ! $_product->is_virtual() ) {
$weight += $_product->get_weight() * $item['qty'];
}
}
}
}
if ( $weight > 0 ) {
print $weight . ' ' . esc_attr( get_option('woocommerce_weight_unit' ) );
} else {
print 'N/A';
}
}
}
?>
I have variable products with many variations where only a few items are actually In Stock while the majority of other variations are ''available on backorder''
I would like to be able to display a quick list of ONLY the items that are IN STOCK in the short product description of each product page so the customer doesn't have to try all variations one-by-one to finally find out which ones are in stock.
I've searched for plugins or code that can do this but did not find anything.
The closest code I found is:
add_action( 'woocommerce_after_shop_loop_item', 'bb_echo_stock_variations_loop' );
function bb_echo_stock_variations_loop(){
global $product;
if ( $product->get_type() == 'variable' ) {
foreach ( $product->get_available_variations() as $key ) {
$attr_string = array();
foreach ( $key['attributes'] as $attr_name => $attr_value ) {
$attr_string[] = $attr_value;
}
if ( $key['max_qty'] > 0 ) {
echo '<br/>' . implode( ', ', $attr_string ) . ': ' . $key['max_qty'] . ' in stock';
} else {
echo '<br/>' . implode(', ', $attr_string ) . ': out of stock';
}
}
}
}
But it displays "In stock" available variations on the SHOP page and I want it to be displayed on the single product short description.
How can I display "In stock" available variations in single product short description?
To display in stock variations list in product single pages on short description, use the following:
add_filter( 'woocommerce_short_description', 'display_in_stock_variations_to_short_description' );
function display_in_stock_variations_to_short_description( $excerpt ){
global $product;
if ( ! is_product() || empty($product) || ! is_a( $product, 'WC_Product' ) )
return $excerpt;
if( $product->is_type('variable') ) {
// Loop through visible children
foreach( $product->get_children() as $variation_id ) {
$variation = wc_get_product( $variation_id );
// Hide out of stock variations if 'Hide out of stock items from the catalog' is checked.
if ( ! $variation || ! $variation->exists() || ( 'yes' === get_option( 'woocommerce_hide_out_of_stock_items' ) && ! $variation->is_in_stock() ) ) {
continue;
}
// Filter 'woocommerce_hide_invisible_variations' to optionally hide invisible variations (disabled variations and variations with empty price).
if ( apply_filters( 'woocommerce_hide_invisible_variations', true, $product->get_id(), $variation ) && ! $variation->variation_is_visible() ) {
continue;
}
$max_qty = 0 < $variation->get_max_purchase_quantity() ? $variation->get_max_purchase_quantity() : $variation->get_stock_quantity();
$term_names = []; // Initializing
// Loop through variation attributes for current varation
foreach ( $variation->get_variation_attributes() as $attribute => $term_slug ) {
// Set the term name in an array
$term_names[] = ucfirst( str_replace( ['-', '_'],[' ', ' '], $term_slug ) );
}
if ( $max_qty > 0 ) {
$excerpt .= sprintf( '<br/>%s: %s %s',
implode(', ', $term_names),
$max_qty,
__('in stock', 'woocommerce')
);
}
}
}
return $excerpt;
}
// Avoid additional content from product short description to be displayed in variation description
add_filter( 'woocommerce_available_variation', 'filter_wc_available_variation_desscription', 10, 3);
function filter_wc_available_variation_desscription( $data, $product, $variation ) {
$max_qty = 0 < $variation->get_max_purchase_quantity() ? $variation->get_max_purchase_quantity() : $variation->get_stock_quantity();
if( $max_qty > 0 )
$data['variation_description'] = get_post_meta( $variation->get_id(), '_variation_description', true );
return $data;
}
Code goes in functions.php file of your active child theme (or active theme). Tested and works.
I'm trying to change the price for a specific product so that it shows the price with VAT (as opposed to other products where the price is shown without VAT)
I have managed to get this to work with the variable products themselves, by using the following code from https://tomjesch.com/display-woocommerce-products-with-and-without-tax/
function edit_selected_variation_price( $data, $product, $variation ) {
if(is_singular('product') && $product->get_id() == 68719 ) {
$price = $variation->price;
$price_incl_tax = $price + round($price * ( 20 / 100 ), 2);
$price_incl_tax = number_format($price_incl_tax, 2, ",", ".");
$price = number_format($price, 2, ",", ".");
$display_price = '<span class="price">';
$display_price .= '<span class="amount">£ ' . $price_incl_tax .'<small class="woocommerce-price-suffix"> incl VAT</small></span>';
$display_price .= '</span>';
$data['price_html'] = $display_price;
}
return $data;
}
add_filter( 'woocommerce_available_variation', 'edit_selected_variation_price', 10, 3);
This works when an option is chosen. However, before an option is chosen, there is a price that says FROM: £xxx which I now also want to change to say "FROM: £xxx inc VAT"
However, I can't seem to do anything to change it. So I have added the following to setup the html for the price:
function cw_change_product_html( $price_html, $product ) {
if ( $product->get_id() == 68719 ) {
$price_incl_tax = $product->price + round($price * ( 20 / 100 ), 2);
$price_incl_tax = number_format($price_incl_tax, 2, ",", ".");
$price_html = '<span class="amount">From ' . $price_incl_tax . 'incl VAT</span>';
}
echo $price_html;
}
And then I tried using these three different hooks.
add_filter( 'woocommerce_get_price_html_from_to', 'cw_change_product_html', 10, 2 );
add_filter( 'woocommerce_get_price_html', 'cw_change_product_html', 10, 2 );
add_filter('woocommerce_variable_price_html', 'cw_change_product_html', 10, 2);
Only the second one seems to trigger the code but then it outputs all of the prices for all the different variants.
Do I need to use a different hook or is there a way I can run the above code once?
There are some mistakes in your code. woocommerce_variable_price_html is best hook to be used. Also instead of using custom tax calculations, you can use WC_Tax methods to get dynamically the tax amount. Finally wc_price() is the formatted price function to be used in WooCommerce.
The code:
add_filter( 'woocommerce_variable_price_html', 'filter_wc_variable_price_html', 10, 2 );
function filter_wc_variable_price_html( $price_html, $product ) {
// only for variable product 68719
if( $product->get_id() != 68719 )
return $price_html;
$min_price = $product->get_variation_price( 'min' );
$tax_rates = WC_Tax::get_rates( $product->get_tax_class() );
$taxes = WC_Tax::calc_tax( $min_price, $tax_rates, false );
return sprintf(
__( 'From %s %s', 'woocommerce' ),
wc_price( $min_price + array_sum( $taxes ) ),
'<small class="woocommerce-price-suffix">' . __( 'incl VAT', 'woocommerce' ) . '</small>'
);
}
As your other code is a bit outdated and complicated, you can try the following instead:
add_filter( 'woocommerce_available_variation', 'filter_wc_available_variation_price_html', 10, 3);
function filter_wc_available_variation_price_html( $data, $product, $variation ) {
// only for variable product 68719
if( $product->get_id() != 68719 )
return $data;
$price = $data['display_price'];
$tax_rates = WC_Tax::get_rates( $variation->get_tax_class() );
$taxes = WC_Tax::calc_tax( $price, $tax_rates, false );
$data['price_html'] = sprintf( '%s %s',
wc_price( $price + array_sum( $taxes ) ),
'<small class="woocommerce-price-suffix">' . __( 'incl VAT', 'woocommerce' ) . '</small>'
);
return $data;
}
Code goes in function.php file of your active child theme (or active theme). Tested and works.
You are calling the right hook (woocommerce_get_price_html) but there are several flaws in your code.
Lets address your problem of running the code only for the price display at the top. Make sure the id you are checking for is the parent id.
Don't access values of the product object directly. WooCommerce provides getter functions for a lot of data. So instead use $product->get_price().
You have an undefined variable $price which will crash your code.
You can retrieve the tax percentage of the parent product, instead of hard coding it into the calculation in your function.
You can use the wc_price() function to output a formatted price.
The final code should look something like this:
add_filter( 'woocommerce_get_price_html', 'cw_change_product_html', 10, 2 );
function cw_change_product_html( $price_html, $product ) {
if ( $product->get_id() == 68719 ) {
$tax_rates = WC_Tax::get_rates( $product->get_tax_class() );
//Check the product tax rate of parent
if ( !empty( $tax_rates ) ) {
$tax_rate = reset($tax_rates);
$price_incl_tax = $product->get_price() + ( $product->get_price() * $tax_rate['rate'] / 100 );
$price_html = sprintf( 'From %s incl VAT', wc_price( $price_incl_tax, array( 'currency' => get_woocommerce_currency() ) ) );
}
}
return $price_html;
}
I'm using Woocommerce and Woocommerce Bookings for a villa booking website and I have a small issue I can't fix.
I'd like to add a field "Details" into my cart (Cart Details). This field will display the duration of the booking and also the price / night of each villa.
My villas have some resources with a specific block cost.
Regarding the duration value, I can display it by using this code bellow :
<?php
/*display_card_data();*/
$items = WC()->cart->get_cart();
foreach($items as $item) {
$duration = $item['booking']['duration'];
}
// displaying values for test
echo $duration. ' x Night Price' .$price ;
?>
I'm wondering how I can display the block cost in this field.
Please any help will be useful.
This can be done with the following code (but they can be many unit prices in WC Bookings):
add_filter( 'woocommerce_cart_item_name', 'booking_details_after_name', 30, 3 );
function booking_details_after_name( $product_name, $cart_item, $cart_item_key ) {
if ( isset( $cart_item['booking']['duration'] ) ){
// Duration
$duration = $cart_item['booking']['duration'];
// Price cost ( they can be many different )
$base_cost = get_post_meta( $cart_item['product_id'], '_wc_booking_cost', true );
$block_cost = get_post_meta( $cart_item['product_id'], '_wc_booking_block_cost', true );
// Output
$product_name .= '<br><span class="booking-details">';
$product_name .= $duration . __(" x Night Price ", "woocommerce") . wc_price($base_cost);
$product_name .= '</span>';
}
return $product_name;
}
Code goes in function.php file of your active child theme (or active theme). Tested and work.
Specific Update:
add_filter( 'woocommerce_cart_item_name', 'booking_details_after_name', 30, 3 );
function booking_details_after_name( $product_name, $cart_item, $cart_item_key ) {
if ( isset( $cart_item['booking']['duration'] ) ){
// Duration
$duration = (int) $cart_item['booking']['_duration'];
$resource_id = $cart_item['booking']['_resource_id'];
$start_time = $cart_item['booking']['_start_date'];
$end_time = $cart_item['booking']['_end_date'];
$loop_time = (int) $start_time;
$day = 86400; // In seconds
// Price cost ( they can be many different )
$res_block_cost = get_post_meta( $cart_item['product_id'], '_resource_block_costs', true );
$booking_pricing = get_post_meta( $cart_item['product_id'], '_wc_booking_pricing', true );
foreach ( $res_block_cost as $key => $value ){
if( $key == $resource_id ){
$bloc_cost = $value;
break;
}
}
$cost = array();
foreach ( $booking_pricing as $key => $value ){
$from = strtotime($value['from']);
$to = strtotime($value['to']) + 86399;
for( $i = 0; $i < $duration; $i++ ){
if( $loop_time >= $from && $loop_time <= $to ){
$cost[] = $value['cost'];
$loop_time += $day;
}
}
}
$cost = array_sum( $cost ) / $duration;
// Output
$product_name .= '<br><span class="booking-details">';
$product_name .= $duration . __(" x Night Price ", "woocommerce") . wc_price($bloc_cost + $cost);
$product_name .= '</span>';
}
return $product_name;
}
Code goes in function.php file of your active child theme (or active theme). Tested and work.
I've used this code to add additional fees to the woocommerce product https://sarkware.com/woocommerce-change-product-price-dynamically-while-adding-to-cart-without-using-plugins/
my function
function calculate_aditional_fees( $cart_object ) {
if( !WC()->session->__isset( "reload_checkout" ) ) {
$additional_price = get_option( 'additional_person_price' );
$additional_driver_price = get_option( 'additional_driver_price' );
foreach ( $cart_object->cart_contents as $key => $value ) {
if ( $additional_driver_price > 0 || $additional_price > 0 ) {
$additional_price *= $value['additional-persons'];
$additional_driver_price *= $value['additional-drivers'];
$cart_object->cart_contents[$key]['data']->price = floatval( $value['data']->price ) + $additional_driver_price + $additional_price;
}
}
}
}
The first problem was that all the extra fees ware added twice (when using the add to cart button). I've just hacked this by dividing additional charges by two.
The problem after that is that after clicking the make payment in the order form, the final price is changed - the're is one fourth of the additional charges added again.
Example. Original price 500, additional person costs 40 the user chooses to add 1 additional person.
The calculation when adding to cart is 40*1/2 (this is done twice for some reason)
after adding to cart is 540 which is ok.
But after making payment (payment method is bank/wire transfer) the confirmation shows 560 as the order price which is big problem obviously.
I would appreciate any help on this.
The fields for additional persons are added via a hook (basically as in the tutorial).
add_action( 'woocommerce_before_add_to_cart_button', 'add_form_before_booking_product' );
function add_form_before_booking_product() {
global $post;
if( function_exists('get_product') ){
$product = get_product( $post->ID );
if( $product->is_type( 'booking' ) ){
echo '<table class="variations booking__variations"><tbody>
<tr>
<td class="label"><label for="additional-persons">'. __( 'Additional persons' ) .'</label></td>
<td class="value">
<input type="number" name="additional-persons" value="0" min="0" max=10 required />
</td>
</tr>
</tbody>
</table>';
}
}
}
After Loads of searching I changed the hook to woocommerce_cart_calculate_fees
Removed the division. The problem here is that the calculation is ok, after payment also but in the cart table subtotal and total are wrong (the values aren't added).
I've tried to calculate this manually so the function looks
function calculate_aditional_fees( $cart_object ) {
if( !WC()->session->__isset( "reload_checkout" )) {
$additional_price = get_option( 'additional_person_price' );
$additional_driver_price = get_option( 'additional_driver_price' );
foreach ( $cart_object->cart_contents as $key => $value ) {
if ( $additional_driver_price > 0 || $additional_price > 0 ) {
$additional_price = get_option( 'additional_person_price' );
$additional_driver_price = get_option( 'additional_driver_price' );
$additional_price = floatval( $additional_price ) * intval( $value['additional-persons'] );
$additional_driver_price = floatval( $additional_driver_price ) * intval( $value['additional-drivers'] );
$sum =( $additional_driver_price + $additional_price ) * WC()->cart->cart_contents[$key]['quantity'];
$sum2 =( $additional_driver_price + $additional_price );
WC()->cart->cart_contents[$key]['data']->price = floatval( $value['data']->price ) + $sum2;
// $additional_sum = $sum / 1.23;
// $additional_tax = $sum-$additional_sum;
// if (!is_checkout()) {
// WC()->cart->cart_contents[$key]['line_total'] += $additional_sum;
// WC()->cart->cart_contents_total += $additional_sum;
// WC()->cart->subtotal += $sum;
// WC()->cart->subtotal_ex_tax += $additional_sum;
// WC()->cart->taxes[1] += $additional_tax;
// }
// WC()->cart->add_fee('Dodtkowe opcje',($additional_driver_price + $additional_price)*WC()->cart->cart_contents[$key]['quantity']);
}
}
}
}
add_action( 'woocommerce_cart_calculate_fees', 'calculate_aditional_fees');
When removing the comments the sum and subtotal are ok, but then after making payment the additional cost are added once again so Im back to the same problem.
This works but...
It add another line under the subtotal in cart page, the calculation are ok, not yet the solution I'm looking for (the customers don't see per product fees but as one total)
function calculate_aditional_fees( ) {
if( !WC()->session->__isset( "reload_checkout" )) {
$additional_price = get_option( 'additional_person_price' );
$additional_driver_price = get_option( 'additional_driver_price' );
$sum =0;
foreach ( WC()->cart->cart_contents as $key => $value ) {
if ( $additional_driver_price > 0 || $additional_price > 0 ) {
$additional_price = get_option( 'additional_person_price' );
$additional_driver_price = get_option( 'additional_driver_price' );
$additional_price = floatval( $additional_price ) * intval( $value['additional-persons'] );
$additional_driver_price = floatval( $additional_driver_price ) * intval( $value['additional-drivers'] );
$sum += ( $additional_driver_price + $additional_price ) * WC()->cart->cart_contents[$key]['quantity'];
}
}
WC()->cart->add_fee(__('Fee','woocommerce'),$sum);
}
}
add_action( 'woocommerce_cart_calculate_fees', 'calculate_aditional_fees');