I've got a customized WooCommerce shop where I want to be able to grey out certain product variations based on conditions, but I'm not sure where in the code to do it.
I have two prices for each item, one is a member price and one is a retail price.
I want everyone to see each variation but not be able to select the one that isn't available to them, so that non-members can see the retail price but can't select it, and vice versa.
The other customization I want is the following: I want to be able to only allow members to buy 5 products at member price per month, and then it will switch them over to retail price, so I need to be able to grey out the member price for members based on certain conditions as well.
Can anyone point me to the files/hooks/actions where I can inject some custom code into the variation output so I can make this happen?
Thanks.
For your two questions you can use in a different way woocommerce_add_to_cart_validation filter hook. With some conditions based on your users roles and on existing function arguments, customer will be able to select a variation of your product, but will not be able to added it to cart, if he is not allowed. You can even display a notice when customer try to add something when is not allowed…
add_filter( 'woocommerce_add_to_cart_validation', 'custom_add_to_cart_validation', 10, 5 );
function custom_add_to_cart_validation( $passed, $product_id, $quantity, $variation_id, $variations ) {
// Your code goes here
// If $passed is set to "false", the product is not added
// $passed = false;
return $passed;
}
For your last question, you will need to set/update some custom user meta data regarding the 5 products by month for the members, each time they place an order. You can use for this the woocommerce_thankyou or woocommerce_order_status_completed action hooks to set that custom data in the user meta data. Then you will be able to check this data enabling or disabling the right product variation in the woocommerce_add_to_cart_validation filter hook.
To finish, if you really want to grey out some variations, you will have to use Javascript/jQuery, but is going to be quite difficult as there is already a lot of javascript/Ajax WooCommerce events on product variations, that will conflict yours. But in WooCommerce everything is possible depending on time and skills…
Related
I am creating an eCommerce store for a relative's business. He has products that the user must personalize on the website. I am coding a separate page that will allow the user to do this, that will link back to the store and add the item to the cart when they are done.
I found a solution to add each product to the cart separately, instead of adding to the quantity (since each product added has been personalized), and a solution to change the price of items in the cart.
WooCommerce: Add product to cart with price override?
https://businessbloomer.com/woocommerce-display-separate-cart-items-product-quantity-1/
The problem is that all the items are changed, not just the last one added.
For example: User designs a ballpoint pen with her name on it. The price is $4. The user then designs a gel pen with her name. The cart will show two separate pens with an increased calculated price, but the price will increase for all pens, not just the last one added. I need to find a way to set the price for the last item added, based on the price sent from the product building page. So far, nothing I've tried has worked.
Variable products won't work for this site.
//To display a product separately every time it is added
function bbloomer_split_product_individual_cart_items( $cart_item_data, $product_id ){
$unique_cart_item_key = uniqid();
$cart_item_data['unique_key'] = $unique_cart_item_key;
return $cart_item_data;
}
add_filter( 'woocommerce_add_cart_item_data','bbloomer_split_product_individual_cart_items', 10, 2 );
add_filter( 'woocommerce_is_sold_individually', '__return_true' );
//To change the item price programmatically. Changes all items with the same ID
//I need it to change only the last one added.
//Set to retrieve new price from the customizing page
add_action( 'woocommerce_before_calculate_totals', 'add_custom_price', 10, 1);
/**
* #param $cart_obj
*/
function add_custom_price($cart_obj ) {
ob_start();
include 'createbb.php';
global $custom_price;
$target_product_id = 17;
// This is necessary for WC 3.0+
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
foreach ( $cart_obj->get_cart() as $key => $value ) {
if ($value['product_id'] == $target_product_id) {
$value['data']->set_price($custom_price);
}
}
ob_end_clean();
}
The type of functionality you are looking for is actually so common that it has a name "Product Options" (this is different to variations). This feature allows you to add configurable add-on's to the price of a product through a design on the edit product page. In a lot of eCommerce platforms like OpenCart you have this sort of functionality built in for free, however Automattic opted to keep it as a separate bolt on which they charge for:
https://woocommerce.com/products/product-add-ons/
Before you say it yes it is annoying that they charge for it, really this is such a common thing for people to request you can tell that it was a calculated decision to monetise it. And yes it is still very possible to program everything bespoke, but you are inevitably re-inventing the wheel for no reason other than to avoid paying for the feature (there are free versions of the plugin above that others have made, google is your friend).
Consider something, what if Automattic change their hooks in the future? you'll have to modify your code, assuming you find out before it borks the site. What if you wish to change options, or you need someone else to change them and you are not around?
If you weigh things up, you'll find the best option in the end is either to grab the official plug-in, or use one of the free alternatives. Trust me I am doing you a favour.
Koda
I am using woocommerce subscription with the gifting extension. With this it is possible to gift a subscription to a recipient. I am trying to make it possible to gift a subscription to multiple people in one order.
The tricky thing is that each product by default can only be gifted to 1 person. So in order to gift to multiple people, the same product has to be added to the cart multiple times.
With the use of this thread: WooCommerce - Treat cart items separate if quantity is more than 1
I have managed to add the same product to the cart and show in on multiple lines. So if I enter quantity 5 of my subscription product and add it to the cart I get five entries in my cart. Which is great, as now I can gift every line to another person.
However, when I proceed to checkout it gets messed up again. Instead of showing the product on separate lines, everything get jammed together. Thus on checkout I get to see 1 line with quantity 5, instead of 5 lines with quantity 1.
This is where the question comes in:
How can I make sure that the order review table on the checkout page shows separate lines for a product with quantity x>1 instead of 1 line with quantity x?
Remark:
I figured out that it only does not work when the woocommerce subscription gifting add-on is active. It overrides seem to override the wc_cart_item_data
you can use this code
function separate_individual_cart_items( $cart_item_data, $product_id ) {
$unique_cart_item_key = md5( microtime() . rand() );
$cart_item_data['unique_key'] = $unique_cart_item_key;
return $cart_item_data;
}
add_filter( 'woocommerce_add_cart_item_data', 'separate_individual_cart_items', 10, 2 );
you can put this code into functions.php or into yout own plugin ( a best solution).
And a observation because this question is similar like this question
WooCommerce - Treat cart items separate if quantity is more than 1
but I can't close the question, sorry... my reputation is low)
I have a function which updates the price of a variation depending on a few conditions. Our shop sells courses and based on date (custom field), variations past todays date are removed from the dropdown selection.
Everything works as it should. However, the problem is, the product page is very slow and the filter adds 5-8 seconds to the load time.
When I put an echo in the function outputting the variation ID it outputs 12 times per the amount of variations. We have around 20 Variations so this functions runs 240+times.
Here is the filter and function:
add_filter('woocommerce_product_variation_get_price', 'repeat_price_filter', 10, 2);
function repeat_price_filter($price, $product_this){
if( isset($product_this->variation_id) ):
$wc_pf = new WC_Product_Factory();
$var_product = $wc_pf->get_product( $product_this->variation_id );
//if condtions, modify price here.
endif;
return $price;
}
How can I find out what's calling this filter repeatedly? I tried putting an IF in the to check for only instock variations which helped marginally.
I have another function which updates the price for the product page, is there any way to ONLY use this filter for the cart/checkout etc?
Thanks!
I need the following and i´m turning around the thing but can´t get a clean way on doing it:
Some products needs to belong to x category, if a customer buy one of those products, all the rest of the products behind that category should get outofstock or unpublished.
So i need a way to create a function that could run once a product is sold and then find all those products with same category and change their metadata, in this case i will solve the rest of the thing just changing the outofstock meta, but knowing that i guess i will also be able to edit any other post meta value.
I know how to update a meta value, i can´t imagine how to hook/filter the rest. Any ideas? Thanks
Have you taken a look at the WooCommerce hooks?
I would check out the woocommerce_order_status_.$new_status->slug hook for the status completed. So something like:
function the_function($order_id) {
// get the order object
$order = new WC_Order( $order_id );
}
add_action( 'woocommerce_order_status_completed', 'the_function' );
hey i'm implementing a custom discount system since magento discount system does not feet my requirements so i'm trying to apply a discount on an Mage_Sales_Model_Quote_Item I've read some and I've found the following function setOriginalCustomPrice the thing is that it applies on the item, and if the user changes the quantity he will get the discount on the item with the new quantity, so i'm trying to use a different method addOption on the item and only on the cart page show the calculations based on the quantity in the option value
$item->addOption(array('code'=>'promo','value' => serialize(['amount'=>10,'qty'=>1])));
and in the cart page
$promo = $item->getOptionByCode('promo');
echo '<div class="orig-price">'.$item->getOriginalPrice().'</div>';
echo '<div class="new-price">'.$item->getOriginalPrice() - ($promo['amount'] * $promo['qty']).'</div>';
the problem is that it does'nt actually apply the new price on the product,
so i want to customize Mage_Sales_Model_Quote->collectTotals() to show my discounts
and send it to the admin back-end when order is completed
how can i achieve that?
thanks in advance
I think there is a fundamental flaw in your approach. I'm not sure what you don't like in standard discounts, and what you can't achieve with catalog or shopping cart rules, but what you're trying to do definitely breaks these features (along with my heart).
However, if you're sure about what you're trying to do, then don't customize Mage_Sales_Model_Quote->collectTotals().
This function just... well, it collects all totals: subtotal, shipping, discount, etc. And it looks like you're changing only price output, but Magento itself doesn't know anything about it.
So if you want to let Magento know that you're changing the item price, you have to either add your own total, or change one of the existing totals. After that Magento will do everything else. Since after your changes Magento outputs already calculated price instead of original one, it may be strange for customer to see the original price in the cart and the additional discount total. So it looks like you will have to change subtotal total.
To do that you have to rewrite Mage_Sales_Model_Quote_Address_Total_Subtotal class in your extension and insert your calculation in _initItem() method. Around line 111 in the original file you will see the code:
$item->setPrice($finalPrice)
->setBaseOriginalPrice($finalPrice);
And this is where Magento sets price for the item, so you can insert your calculations and change $finalPrice before that. If you have virtual products, you will have to change collect() method too.