woocommerce add fee to cart based on quantity - wordpress

I wan to add fee based on quantity.
For eg: If quantity in cart = 5 , then the fee to be added should be 4$,
If quantity in cart = 7, then the fee to be added should be 8$
I have tried this code to get quantity.
add_action('woocommerce_before_calculate_totals', 'woocommerce_custom_surcharge');
function woocommerce_custom_surcharge() {
global $woocommerce;
$amount = $woocommerce->cart->get_cart_item_quantities();
if($amount==5)
{
$excost = 7;
}
else if($amount==7){
$excost = 8;
}
$woocommerce->cart->add_fee('Charges delivery', $excost, $taxable = false, $tax_class = '');
}
Please help with the same.

Please Try this
function woocommerce_custom_surcharge(){
global $woocommerce;
//Getting Cart Contents.
$cart = $woocommerce->cart->get_cart();
//Calculating Quantity
foreach($cart as $cart_val => $cid){
$qty += $cid['quantity'];
}
//Your Condition
if($qty==5)
{
$excost = 7;
}
else if($qty==7){
$excost = 8;
}
$woocommerce->cart->add_fee('Charges delivery', $excost, $taxable = false, $tax_class = '');
}
From Here I found that We need to get the quantity of the cart by summing up the values of the cart.Hope this will Solve your problem.

Related

Hide payment method if specific variation selected is blocking plugins [duplicate]

In Woocommerce, i want to hide the credit card payment option if a specific product variation is in the cart. Please help.
Thanks.
This is what i have working now. I assigned a separate shipping class to each variation i want to disable a specific payment method at checkout. But it would be much easier if i coud target specific attribute values, so i don't have to assign a shipping class.
<?php
add_filter('woocommerce_available_payment_gateways', 'conditional_payment_gateways', 10, 1);
function conditional_payment_gateways( $available_gateways ) {
$shipping_class_target = 106; // the shipping class ID assigned to specific variations
$in_cart = false;
foreach ( WC()->cart->get_cart_contents() as $key => $values ) {
if ( $values[ 'data' ]->get_shipping_class_id() == $shipping_class_target ) {
$in_cart = true;
break;
}
}
if ( $in_cart ) {
unset($available_gateways['cod']); // unset 'cod'
}
else {
unset($available_gateways['bacs']); // unset 'bacs'
}
return $available_gateways;
}
If you are looking to check the variations for each item in the cart, you have to lookup the attributes $product->get_attributes() and then loop through those and get the array key and value for each.
In this example, I used
Size (pa_size) and Small
add_filter('woocommerce_available_payment_gateways', 'conditional_payment_gateways', 10, 1);
function conditional_payment_gateways( $available_gateways ) {
$in_cart = false;
foreach ( WC()->cart->get_cart_contents() as $key => $values ) {
// See if there is an attribute called 'pa_size' in the cart
// Replace with whatever attribute you want
if (array_key_exists('pa_size', (array) $values['data']->get_attributes() ) ) {
foreach ($values['data']->get_attributes() as $attribute => $variation);
// Replace 'small' with your value.
if ($variation == 'small') $in_cart = true; //edited
}
}
if ( $in_cart ) {
unset($available_gateways['cod']); // unset 'cod'
}
else {
unset($available_gateways['bacs']); // unset 'bacs'
}
return $available_gateways;
}

Change the prices of two or three products if they were added to the shopping cart together. Woocommerce

Good afternoon!
Please help me implement this feature in woocommerce.
I have three specific products (with specific IDs 2, 3, 4).
I need to make sure that when adding two of them together to the cart, the prices for both of them change automatically. For example, for a product with id #2, the price was set to $ 100, and for a product with id #3, the price became$200.
Also, when they are all added together (three of them), the price changed for all three of them: product # 2 = 100; product # 3 = 200; product # 4 = 250.
I haven't found anything like this anywhere yet, so I would appreciate any hint.
I managed to solve the problem on my own.
I made sure that the products I need "watch" each other in the basket. And if one of them "notices" the other, the price is updated for both of them.
In the same way, the price is updated if the three of them simultaneously "see" each other in the basket.
It may not be the best code, but it works and it works well.
The original code was taken from this resource and modified by me for my tasks.
(https://www.webroomtech.com/change-product-price-when-other-product-is-in-cart-woocommerce/)
function simple_func_product_in_cart($product_id){
$product_cart_id = WC()->cart->generate_cart_id( $product_id );
$in_cart = WC()->cart->find_product_in_cart( $product_cart_id );
if ( $in_cart ) {
return true;
}
return false;
}
add_action( 'woocommerce_before_calculate_totals', 'simple_change_price_of_product' );
function simple_change_price_of_product( $cart_object ) {
$target_product_id = 7101; // CHANGE THIS WITH YOUR PRODUCT ID
if(simple_product_in_cart(7105)) {
// Product is already in cart
foreach ( $cart_object->get_cart() as $key => $value ) {
if ( $value['product_id'] == $target_product_id ) {
$value['data']->set_price(160); // CHANGE THIS: set the new price
$new_price = $value['data']->get_price();
}
}
}
$target_product_id = 7101; // CHANGE THIS WITH YOUR PRODUCT ID
if(simple_product_in_cart(7107)) {
// Product is already in cart
foreach ( $cart_object->get_cart() as $key => $value ) {
if ( $value['product_id'] == $target_product_id ) {
$value['data']->set_price(160); // CHANGE THIS: set the new price
$new_price = $value['data']->get_price();
}
}
}
$target_product_id = 7105; // CHANGE THIS WITH YOUR PRODUCT ID
if(simple_product_in_cart(7101)) {
// Product is already in cart
foreach ( $cart_object->get_cart() as $key => $value ) {
if ( $value['product_id'] == $target_product_id ) {
$value['data']->set_price(170); // CHANGE THIS: set the new price
$new_price = $value['data']->get_price();
}
}
}
$target_product_id = 7105; // CHANGE THIS WITH YOUR PRODUCT ID
if(simple_product_in_cart(7107)) {
// Product is already in cart
foreach ( $cart_object->get_cart() as $key => $value ) {
if ( $value['product_id'] == $target_product_id ) {
$value['data']->set_price(170); // CHANGE THIS: set the new price
$new_price = $value['data']->get_price();
}
}
}
$target_product_id = 7107; // CHANGE THIS WITH YOUR PRODUCT ID
if(simple_product_in_cart(7101)) {
// Product is already in cart
foreach ( $cart_object->get_cart() as $key => $value ) {
if ( $value['product_id'] == $target_product_id ) {
$value['data']->set_price(180); // CHANGE THIS: set the new price
$new_price = $value['data']->get_price();
}
}
}
$target_product_id = 7107; // CHANGE THIS WITH YOUR PRODUCT ID
if(simple_product_in_cart(7105)) {
// Product is already in cart
foreach ( $cart_object->get_cart() as $key => $value ) {
if ( $value['product_id'] == $target_product_id ) {
$value['data']->set_price(180); // CHANGE THIS: set the new price
$new_price = $value['data']->get_price();
}
}
}
}

Set minimum order quantity by category (Woocommerce)

I have different product categories on my store. I have a "nettoyage" category that i'd like to allow clients to order ONLY if the number of "nettoyage" items in the cart is > 3 .
Right now, i've set up the default quantity to 3 and don't allow the user to go below on product pages. But what i'd like is to allow them to add 1 of each for example and allow them to order as long as the number of "nettoyage" products in the cart is > 3. How can i refactor this code to do this ?
Right now, i have the following code in my functions.php :
add_filter('woocommerce_quantity_input_args', 'bloomer_woocommerce_quantity_changes', 10, 2);
function bloomer_woocommerce_quantity_changes($args, $product)
{
if (!is_cart()) {
if (is_singular('product') && (has_term('nettoyage', 'product_cat'))) {
$args['input_value'] = 3; // Start from this value (default = 1)
$args['max_value'] = 10; // Max quantity (default = -1)
$args['min_value'] = 3; // Min quantity (default = 0)
$args['step'] = 1; // Increment/decrement by this value (default = 1)
}
}
return $args;
}
add_filter('woocommerce_quantity_input_args', 'min_qty_filter_callback', 20, 2);
function min_qty_filter_callback($args, $product)
{
$categories = array('Noten'); // The targeted product category(ies)
$min_qty = 3; // The minimum product quantity
$product_id = $product->is_type('simple') ? $product->get_parent_id() : $product->get_id();
if (has_term($categories, 'product_cat', $product_id)) {
$args['min_value'] = $min_qty;
}
return $args;
}
// On shop and archives pages
add_filter('woocommerce_loop_add_to_cart_args', 'min_qty_loop_add_to_cart_args', 10, 2);
function min_qty_loop_add_to_cart_args($args, $product)
{
$categories = array('nettoyage'); // The targeted product category
$min_qty = 3; // The minimum product quantity
$product_id = $product->get_id();
if (has_term($categories, 'product_cat', $product_id)) {
$args['quantity'] = $min_qty;
}
return $args;
}
add_action('woocommerce_check_cart_items', 'wc_min_item_required_qty');
function wc_min_item_required_qty()
{
$categories = array('nettoyage'); // The targeted product category
$min_item_qty = 3; // Minimum Qty required (for each item)
$display_error = false; // Initializing
// Loop through cart items
foreach (WC()->cart->get_cart() as $cart_item_key) {
$item_quantity = $cart_item['quantity']; // Cart item quantity
$product_id = $cart_item['product_id']; // The product ID
// For cart items remaining to "Noten" producct category
if (has_term($categories, 'product_cat', $product_id) && $item_quantity < $min_item_qty) {
wc_clear_notices(); // Clear all other notices
// Add an error notice (and avoid checkout).
wc_add_notice(sprintf("Le service livraison nettoyage n'est valable qu'à partir de %s paires!", $min_item_qty, $item_quantity), 'error');
break; // Stop the loop
}
}
}
Finaly found the solution. For those interested, here is the custom function :
add_action('woocommerce_check_cart_items', 'custom_set_min_total');
function custom_set_min_total()
{
if (is_cart() || is_checkout()) {
global $woocommerce, $product;
$i = 0;
foreach ($woocommerce->cart->cart_contents as $product) :
$minimum_cart_product_total = 3;
if (has_term('nettoyage', 'product_cat', $product['product_id'])) :
$total_quantity += $product['quantity'];
endif;
endforeach;
foreach ($woocommerce->cart->cart_contents as $product) :
if (has_term('nettoyage', 'product_cat', $product['product_id'])) :
if ($total_quantity < $minimum_cart_product_total && $i == 0) {
wc_add_notice(
sprintf(
'<strong>A Minimum of %s products is required from the nettoyage category before checking out.</strong>'
. '<br />Current number of items in the cart: %s.',
$minimum_cart_product_total,
$total_quantity
),
'error'
);
}
$i++;
endif;
endforeach;
}
}

Display shipping notice depending on backorders

I'm trying to display a custom notice, depending on wheater the order contains products which are in back-order or are all in stock.
I have modified code from this answer.
It works, but only in the cart. I want it to show everywhere: in the cart, in checkout, admin, emails and so on.
this is what I have:
// Conditional function: Checking cart items stock
function is_mixed_stock_items(){
$enough_stock = $out_of_stock = false; // initializing
// Loop through cart items
foreach ( WC()->cart->get_cart() as $cart_item ) {
// Get an instance of the WC_Product Object
$product = $cart_item['data'];
// Get stock quantity
$stock_qty = $product->get_stock_quantity();
// get cart item quantity
$item_qty = $cart_item['quantity'];
if( ( $stock_qty - $item_qty ) >= 0 ){
$enough_stock = true; // enough stock
} else {
$out_of_stock = true; // not enough stock
}
}
// return true if stock is mixed and false if not
return $enough_stock && $out_of_stock ? true : false;
}
// Display a custom notice
add_action( 'woocommerce_before_cart_totals', 'display_delivery_notification' );
function display_delivery_notification() {
if( is_mixed_stock_items() ){
echo'<div class="cart_totals">Forventet levering: 2-10 hverdage</div>';
}
else {
echo'<div class="cart_totals">Levering: 1-2 hverdage</div>';
}
}

WooCommerce custom function for shipping

I'm trying to create a custom function for a WooCommerce shipping plugin by wooforce. There are two plugins, ups and usps.
What I'm trying to achieve is if a customer adds a product from category X or any of its sub categories, all rates except for ups ground get unset.
If those products are not present in the cart, all options remain available.
The developers pointed me to this code, but I'm still pretty new to PHP and WordPress/WooCommerce structured PHP so I'm a bit stuck as how to proceed.
Here's the code they gave me.
add_filter('woocommerce_package_rates', 'hide_shipping_method_when_shipping_class_product_is_not_in_cart', 10, 2);
function hide_shipping_method_when_shipping_class_product_is_not_in_cart($available_shipping_methods, $package)
{
// Shipping class IDs that need the method removed
$shipping_class_ids = array(
27,
);
$shipping_services_to_hide = array(
'wf_fedex_woocommerce_shipping:FEDEX_GROUND',
'wf_fedex_woocommerce_shipping:FEDEX_2_DAY_AM'
);
$shipping_class_exists = false;
foreach(WC()->cart->cart_contents as $key => $values) {
if (in_array($values['data']->get_shipping_class_id() , $shipping_class_ids)) {
$shipping_class_exists = true;
break;
}
}
if (!$shipping_class_exists) {
foreach($shipping_services_to_hide as & $value) {
unset($available_shipping_methods[$value]);
}
}
return $available_shipping_methods;
}
I was able to figure this out on my own. Here's the code for anyone who may need this function in the future.
This function works specifically with the WooForce Shipping plugins.
add_filter('woocommerce_package_rates', 'hide_shipping_method_when_shipping_class_product_is_not_in_cart', 10, 2);
function hide_shipping_method_when_shipping_class_product_is_not_in_cart($available_shipping_methods, $package){
// set our flag to be false until we find a product in that category
$cat_check = false;
// check each cart item for our category
foreach ( WC()->cart->get_cart() as $cart_item_key => $cart_item ) {
$product = $cart_item['data'];
// replace 'membership' with your category's slug
if ( has_term( 'ammo', 'product_cat', $product->id ) ) {
$cat_check = true;
// break because we only need one "true" to matter here
break;
}
}
// if a product in the cart is in our category, do something
if ( $cat_check ) {
// we have the category, do what we want
// Shipping class IDs that need the method removed
$shipping_class_ids = array(
1,
2,
3,
18,
23,
33,
47,
49
);
$shipping_services_to_hide = array(
'wf_shipping_usps:D_PRIORITY_MAIL',
'wf_shipping_usps:D_EXPRESS_MAIL'
);
$shipping_class_exists = false;
foreach(WC()->cart->cart_contents as $key => $values) {
if (in_array($values['data']->get_shipping_class_id() , $shipping_class_ids)) {
$shipping_class_exists = true;
break;
}
}
if (!$shipping_class_exists) {
foreach($shipping_services_to_hide as & $value) {
unset($available_shipping_methods[$value]);
}
}
return $available_shipping_methods;
}
else{
return $available_shipping_methods;
}
}

Resources