woocommerce add custom price while add to cart - woocommerce

Hi I need to add an extra price to product price while add to cart.
http://url/warenkorb/?add-to-cart=1539&added_price=5.00
I have used the code following code to achive this.
add_filter( 'woocommerce_add_cart_item', 'c_other_options_add_cart_item', 20, 1 );
function c_other_options_add_cart_item( $cart_item ) {
if (isset($cart_item['_other_options'])) :
if( isset($cart_item['_other_options']['product-price']) )
$extra_cost = floatval($cart_item['_other_options']['product-price']);
$cart_item['data']->adjust_price( $extra_cost );
// here the real adjustment is going on...
endif;
return $cart_item;
}
add_filter( 'woocommerce_add_cart_item_data', c_other_options_add_cart_item_data', 10, 2 );
function c_other_options_add_cart_item_data($cart_item_meta, $product_id){
global $woocommerce;
$product = new WC_Product( $product_id);
$price = $product->price;
if(empty($cart_item_meta['_other_options']))
$cart_item_meta['_other_options'] = array();
$cart_item_meta['_other_options']['product-price'] = esc_attr($_REQUEST['price']) - $price;
return $cart_item_meta;
}
It shows the modified price on add to cart page but not in the cart/checkout page. Please Help me to achieve this. Thanks in advance.

You have to use woocommerce_before_calculate_totals hook for this purpose,
like this
function calculate_extra_fee( $cart_object ) {
/* Extra fee */
$additionalPrice = 100;
foreach ( $cart_object->cart_contents as $key => $value ) {
/* if you want to add extra fee for particular product, otherwise remove the if condition */
if( $value['product_id'] == 100) {
$quantity = intval( $value['quantity'] );
$orgPrice = intval( $value['data']->price );
$value['data']->price = ( ( $orgPrice + $additionalPrice ) * $quantity );
}
}
}
add_action( 'woocommerce_before_calculate_totals', 'calculate_extra_fee', 1, 1 );

Related

Issue with changing WooCommerce cart item prices based on product meta

When the product subtotal is more than 3000, it has to be another price.
I added it as a meta field to products. On Stack Overflow, a long time ago someone advised me the filter for a special price called woocommerce_cart_item_name
I modified it a little for my purpose:
function kia_add_subtitle_to_cart_product( $title, $cart_item ){
$threshold = 3000; // Change price if > 3000
$_product = $cart_item['data'];
$meta = $_product->get_meta( '_opt_price_var');
$price = $_product->get_regular_price();
$subtotal = $cart_item['quantity'] * $price;
if ( $subtotal > $threshold && ( $meta )) {
$_product->set_price( $meta );
}
echo $title;
}
add_filter( 'woocommerce_cart_item_name', 'kia_add_subtitle_to_cart_product', 10, 2 );
The special price is showing only in the cart form, but not in cart totals and not in the checkout, in totals and in checkout the price is still regular, the main calculator doesn't take it from this filter.
How can I fix it? How to include it in the main calculator too?
I tried different hooks that can be responsive for the calculator - both add_action and add_filter, with and without 10, 2 - it isn't it.
add_action('woocommerce_before_shipping_calculator', 'kia_add_subtitle_to_cart_product',10,2);
add_action('woocommerce_before_cart_totals', 'kia_add_subtitle_to_cart_product', 10, 2 );
The woocommerce_cart_item_name hook is being misused in your code attempt. A filter hook should always return something compared to the use of echo.
You should use the woocommerce_before_calculate_totals hook instead
So you get:
function action_woocommerce_before_calculate_totals( $cart ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) ) return;
if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 ) return;
// Change price if > 3000
$threshold = 3000;
// Loop through cart items
foreach ( $cart->get_cart() as $cart_item ) {
// Get regular price
$price = $cart_item['data']->get_regular_price();
// Subtotal = Get quantity * price
$subtotal = $cart_item['quantity'] * $price;
// Greater than
if ( $subtotal > $threshold ) {
// Get meta
$meta = $cart_item['data']->get_meta( '_opt_price_var', true );
// NOT empty
if ( ! empty ( $meta ) ) {
// Set new price
$cart_item['data']->set_price( $meta );
}
}
}
}
add_action( 'woocommerce_before_calculate_totals', 'action_woocommerce_before_calculate_totals', 10, 1 );
add_filter('woocommerce_calculated_total', 'custom_calculated_total', 10, 2);
function custom_calculated_total($total, $cart_object) {
if (is_admin() && !defined('DOING_AJAX'))
return;
if (!WC()->cart->is_empty()):
foreach ($cart_object->cart_contents as $key => $cart_item) {
$meta = $cart_item['data']->get_meta('_opt_price_var');
if ($total >= 3000 && ( $meta )) {
$total = $meta;
}
}
endif;
return $total;
}

Save value from a custom row added after the order table and display it in WooCommerce orders and emails

This code I wrote displays personalized information on the WooCommerce checkout page.
add_action( 'woocommerce_cart_totals_after_order_total', 'show_total_discount_cart_checkout', 9999 );
add_action( 'woocommerce_review_order_after_order_total', 'show_total_discount_cart_checkout', 9999 );
function show_total_discount_cart_checkout() {
$discount_total = 0;
foreach ( WC()->cart->get_cart() as $cart_item_key => $cart_item ) {
$product = $cart_item['data'];
$subtotal = WC()->cart->get_product_subtotal( $product, $cart_item['quantity'] );
$total = WC()->cart->total;
$pctm = 90.00;
$valor_descontado = $total - ($total / 100 * $pctm);
$sale_price = '10%';
$discount = ( WC()->cart->total - $valor_descontado );
$discount_total = $discount;
}
if ( $discount_total > 0 ) {
echo '<tr><th>VOCÊ RECEBERÁ DE CASHBACK:</th><td data-title="You">' . wc_price( $discount_total + WC()->cart->get_discount_total() ) .'</td></tr>';
}
}
The result:
I need this information to also be displayed in WooCommerce orders and emails. I believe I can come up with a solution myself to display this value on several other pages, but can someone first tell me how to save/store the value of this calculation?
First of all, I've rewritten your existing code for the following reasons:
Requesting subtotals and totals is best done outside the foreach loop, because otherwise these values ​​will be overwritten every time
The result of $subtotal is not used anywhere in your code
Since the result of $subtotal is not used anyway, loop through the cart seems unnecessary
$sale_price is also not used anywhere in your code
Since $discount_total = $discount it is not necessary to use a new variable
A session variable is created/added
Your existing code, but optimized:
function action_woocommerce_after_order_total() {
// WC Cart NOT null
if ( ! is_null( WC()->cart ) ) {
// Get cart
$cart = WC()->cart;
// Getters
$cart_total = $cart->total;
$cart_discount_total = $cart->get_discount_total();
// Settings
$pctm = 90;
// Calculations
$discounted_value = $cart_total - ( $cart_total / 100 * $pctm );
$discount_total = $cart_total - $discounted_value;
// Greater than
if ( $discount_total > 0 ) {
// Result
$result = $discount_total + $cart_discount_total;
// The Output
echo '<tr class="my-class">
<th>' . __( 'VOCÊ RECEBERÁ DE CASHBACK', 'woocommerce' ) . '</th>
<td data-title="You">' . wc_price( $result ) . '</td>
</tr>';
// Set session
WC()->session->set( 'session_result', $result );
}
}
}
add_action( 'woocommerce_cart_totals_after_order_total', 'action_woocommerce_after_order_total', 10 );
add_action( 'woocommerce_review_order_after_order_total', 'action_woocommerce_after_order_total', 10 );
To answer your question:
Step 1) We get the result from the session variable and add it as order data, so that we can use/obtain this information everywhere via the $order object
// Add as custom order meta data and reset WC Session variable
function action_woocommerce_checkout_create_order( $order, $data ) {
// Isset
if ( WC()->session->__isset( 'session_result' ) ) {
// Get
$result = (float) WC()->session->get( 'session_result' );
// Add as meta data
$order->update_meta_data( 'result', $result );
// Unset
WC()->session->__unset( 'session_result' );
}
}
add_action( 'woocommerce_checkout_create_order', 'action_woocommerce_checkout_create_order', 10, 2 );
Step 2) Use the woocommerce_get_order_item_totals filter hook, which will allow you to add a new row to the existing tables with the $result.
The new row will be added in:
Email notifications
Order received (thank you page)
My account -> view order
function filter_woocommerce_get_order_item_totals( $total_rows, $order, $tax_display ) {
// Get meta
$result = $order->get_meta( 'result' );
// NOT empty
if ( ! empty ( $result ) ) {
// Add new row
$total_rows['total_result']['label'] = __( 'VOCÊ RECEBERÁ DE CASHBACK', 'woocommerce' );
$total_rows['total_result']['value'] = wc_price( $result );
}
return $total_rows;
}
add_filter( 'woocommerce_get_order_item_totals', 'filter_woocommerce_get_order_item_totals', 10, 3 );

How to add ACF field to custom column on WooCommerce admin orders list

ACF is set up for post type on WooCommerce products. However, I am trying to add a custom column to WooCommerce orders list within Admin dashboard and add the products ACF field.
I have added the column to display after order_status, but I'm having problems getting the ACF field to display.
// ADD NEW COLUMN
add_filter( 'manage_edit-shop_order_columns', 'custom_shop_order_column', 20 );
function custom_shop_order_column($columns)
{
$reordered_columns = array();
foreach( $columns as $key => $column){
$reordered_columns[$key] = $column;
if( $key == 'order_status' ){
$reordered_columns['my-column'] = __( 'Location','theme_domain');
}
}
return $reordered_columns;
}
Here, adding ACF to new colum.
// ADD ACF FIELD TO COLUMN
add_action( 'manage_shop_order_posts_custom_column' , 'custom_orders_list_column_content', 20, 2 );
function custom_orders_list_column_content( $column, $post_id )
{
if ( 'Location' == $column_name ){
$product_id = method_exists( $product, 'get_id' ) ? $product->get_id() : $product->id;
echo get_field( 'location', $product_id );
}
return true;
}
Still learning and not sure how to do this, any advice?
An order generally consists of several products, therefore you cannot use $product_id directly, but you have to loop through the order items.
So you get:
/**
* Add columns
*/
function filter_manage_edit_shop_order_columns( $columns ) {
$reordered_columns = array();
foreach ( $columns as $key => $column ) {
$reordered_columns[$key] = $column;
if ( $key == 'order_status' ) {
$reordered_columns['my-column'] = __( 'Location','theme_domain' );
}
}
return $reordered_columns;
}
add_filter( 'manage_edit-shop_order_columns', 'filter_manage_edit_shop_order_columns', 10, 1 );
/**
* Populate columns
*/
function filter_manage_shop_order_posts_custom_column( $column, $post_id ) {
// Compare
if ( $column == 'my-column' ) {
// Get order
$order = wc_get_order( $post_id );
// Is a WC_Order
if ( is_a( $order, 'WC_Order' ) ) {
// Get items
$items = $order->get_items();
// Loop through
foreach ( $items as $key => $item ) {
// Product ID
$product_id = $item->get_variation_id() > 0 ? $item->get_variation_id() : $item->get_product_id();
// Get field
$address = get_field( 'location', $product_id );
// Output
echo ($address) ? '<div>Address: ' . $address . '</div>' : '<div>Address: No address found!</div>';
}
}
}
}
add_filter( 'manage_shop_order_posts_custom_column', 'filter_manage_shop_order_posts_custom_column', 10, 2 );

Woocommerce - custom functions runs only on update cart

I wrote a very small function to disable installation as a method (from table rate shipping plugin) if a product is not in the cart or if the quantity of that product in the cart is less than 6.
This works, but only when I click on "update cart" button and not, for example, when I click on cart.
here's the function, directly from my function.php file in my custom theme:
function disable_installation_for_less_than( $rates ) {
global $woocommerce;
$items = $woocommerce->cart->get_cart();
$installation = $rates['table_rate_shipping_installation'];
foreach ( $items as $item => $values ) {
$productID = $values['product_id'];
$productQuantity = $values['quantity'];
unset( $rates['table_rate_shipping_installation'] );
if ( $productID == 2412 ) {
if ( $productQuantity < 6 ) {
unset( $rates['table_rate_shipping_installation'] );
} else {
array_push($rates, $installation);
}
}
}
return $rates;
}
add_filter( 'woocommerce_package_rates', 'disable_installation_for_less_than', 10, 3 );
Any idea why? am I using the wrong hook?
Thanks for any help
Also, rather then un-setting the installation and re-set it only when needed, is there a better way to say "if this product is NOT in the cart" then remove this?
thanks
Ok, I managed to solve it this way:
function disable_installation_for_less_than( $rates ) {
global $woocommerce;
$items = $woocommerce->cart->get_cart();
$showInstallation= false;
foreach ( $items as $item => $values ) {
$productID = $values['product_id'];
$productQuantity = $values['quantity'];
if ( $productID == 2412 ) {
$showInstallation= true;
if ( $productQuantity < 6 ) {
unset( $rates['table_rate_shipping_installation'] );
}
}
}
if ($showInstallation== false){
unset( $rates['table_rate_shipping_installation'] );
}
return $rates;
}
add_filter( 'woocommerce_package_rates', 'disable_installation_for_less_than', 10, 2 );
It's working now.

How to change woocommerce price according to user input

I have used the hook woocommerce_before_calculate_totals but stuck in getting dynamic value in my function. Even i have used session but it didn't work on passing dynamic price.
The following snippet adds 100 to all the products in the cart, you can put your own conditions and pricing calculation there.
function calculate_product_price( $cart_object ) {
/* Gift wrap price */
$additionalPrice = 100;
foreach ( $cart_object->cart_contents as $key => $value ) {
//You can add your condition here
$quantity = floatval( $value['quantity'] );
$orgPrice = floatval( $value['data']->price );
$value['data']->price = ( ( $orgPrice + $additionalPrice ) * $quantity );
}
}
add_action( 'woocommerce_before_calculate_totals', 'calculate_product_price', 1, 1 );

Resources