Woocommerce - Change tax class programmatically on Order and recalcluate - wordpress

I´m working on a solution to change the tax class based on the country of the customer AND if he can provide a VAT-ID or not.
The store is EU based and providing services to B2B and B2C.
So for all EU based companies that can provide a VAT-ID, no taxes will be charged unless the origin country is the same.
For all customers who cannot provide a VAT-ID, our local taxes will be added.
And so on...
All solutions I have found are only interacting with the cart, but as I´m creating the order programmatically I need another solution.
Is there a way (a hook maybe) to change the tax_class while creating the order?
For testing I tried to add this method but that did not work. It fires the filter but does not change the tax class in the order.
function wc_change_tax_class( $tax_class, $product ) {
$tax_class = 'Zero rate';
return $tax_class;
}
add_filter( 'woocommerce_product_get_tax_class', 'wc_change_tax_class', 1, 2 );
add_filter( 'woocommerce_product_variation_get_tax_class', 'wc_change_tax_class', 1, 2 );
Also I tried this method in the function that creates the order but with the same result. Nothing happend.
$woocommerce->customer->set_is_vat_exempt( true );
Thanks for any help!

After hours of trying to find the reason, the solution was quite easy:
All solutions I found suggested to write 'Zero rate' or 'Zero Rate'. Depending on what the Name was given in the Woocommerce settings. But for me, it does only work if you write it this way 'zero-rate'. So change the table class name and remove any spaces in the woocommerce settings and of course in the variable.
$tax_class = 'zero-rate';
Hope that saves someone's time!

Related

Woocommerce Manually Increase $post_id to skip a series of order numbers

I am having an issue since reverting my site to a history state in which the $order_id was also reverted; however my 3rd party stock management has used a bunch of order Id's, about 100 out that will create a problem when I get to them and orders are re-made using old ID's that are already in the system.
I need to increase the count of the $order_id as to avoid this; seems easy enough but I have found NO support relating to this aside from digging around in the database and that seems unessisairy for something this simple.
I can manipulate the order number using the commonly found "add prefix or suffix to order number" but that affects all orders, past and future. So if I add a 0 to the end; all the old orders in the system suddenly also have a 0 added and it breaks the links to the external api managing the orders.
I need a way to just increase the $order_id by 100 ONLY on newly generated orders. I guess I could go post 100 articles or something tedious like that but I feel there should be a rather simple way to just increase the count on the site. Skip a few numbers then good to go y'know?
here is the code I used that changes all the orders; it is not helpful really but I mentioned it so here it is:
add_filter( 'woocommerce_order_number', 'test_woocommerce_order_number', 1, 2 );
function test_woocommerce_order_number( $oldnumber, $order ) {
$prefix = "AU-";
$suffix = 0;
return $prefix . $order->id . $suffix;
}
This will change my order number from 10338 to: AU-103380 BUT it changes all orders in the system. I simply want to increase the counter so that new orders begin at 10438.
In the end I simply made a hidden post and saved it 100 times. If you run into this issue and you need to skip 1,000 or 10,000+ values of the $order->id then my solution will not work for you. This worked for me; however "workaround-y" it may be.

WooCommerce - Change customer order after it has been placed and paid

Using three plugins:
WooCommerce
Subscriptio
WooEvents
I have created a product which allows for a customer to pay for an event over five instalments.
A customer has placed an order and made their first of the five payments via PayPal and has then contacted me to advise they have booked the wrong event.
The correct event is exactly the same except the dates are a month sooner.
I have added the following snippet to be able to edit 'processing' orders:
add_filter( 'wc_order_is_editable', 'wc_make_processing_orders_editable', 10, 2 );
function wc_make_processing_orders_editable( $is_editable, $order ) {
if ( $order->get_status() == 'processing' ) {
$is_editable = true;
}
return $is_editable;
}
From the order screen within the back-end of WordPress I can see that the the order can be edit by way of removing the product from the order or editing the meta data and cost.
The correct product that should have been ordered has a different product/variation ID.
My question is simply:
Should I remove the incorrectly ordered product from the order and add the correct product (both have the same properties with the exception of the courses dates); or
Should I just change the meta data and increase the stock levels for the incorrectly product back to X and reduce the stock level for the correct product?
Your second option is much better. Change the meta from database if its accessible and then manage the stock accordingly.
I have not yet done this, but according to this exchange ...
How can I add a product to an existing and paid Woocommerce order?
... you can set the order status to "On Hold" and make changes to the order itself. I presume you would then return the status to "Processing".
I would expect that if the application permits those changes, then it would be doing the background meta changes to inventory levels, etc., and spare you the problem of doing so (and the potential errors that may occur when messing with the data tables outside of the application).
Like I said, I haven't done this. But it might be worthwhile doing a little test to make sure it works as it seems to be described in the answer to the other question.
J

WooCommerce checkout minimum order based on city

I am new to woocommerce so I need you help to findout the issue i am trying to solve from last 3 days. In short, I have a pizza store at 5 locations. There is a minimum order per location. In checkout I made a custom city select option field based on it total bill will be accepted or rejected. I am using checkout manager. Its really confusing.
So my question is how can I do this and achieve this result. I don't want to hard code everything because In future locations might change.
Any solution for this problem. Thanks In advance.
function check_min_order($order_id) {
global $woocommerce;
$order = new WC_Order($order_id);
$total = $order->calculate_totals();
if (!$total > 'YOUR MINIMUM AMOUNT HERE') {
wc_add_notice( 'You did not meet the minimum order total.', 'error' );
exit;
}
}
add_action( 'woocommerce_checkout_order_processed', 'check_min_order', 1, 1 );
Add this to your functions.php
I might have the $total variable being set using the wrong command. But this should give you a general idea of how to acheive this. It interupts the order process and checks the total to see if it meets your minimum amount. You can create a series of if statements or a switch statement for each case in your form fields. Whatever the name of the request object for the city is you can use $_REQUEST['your_city_field_name'] to get the value.
If the condition is met then it will return a woocommerce formatted error and stop the processing of the transaction. If not it will continue as normal.

Hide variations that don't match

So I'm currently working on a Woocommerce store that has lots of variations.
What I'm basically looking for is for the next variation to refresh based on what was chosen on the variation chosen before that.
For example, if you go on http://freelance.tstwebdesign.co.uk/platino/product/plain-platinum-court/,
I want to choose a selection from "Width" which should then refresh "Depth" showing only the depths available that match with that width.
How can this be done?
It's default function for not many variations. For many variations you can do it with function
// Woo Commerce – Make Variations only appear when available
function custom_wc_ajax_variation_threshold( $qty, $product ) {
return 500;
}
add_filter( ‘woocommerce_ajax_variation_threshold’, ‘custom_wc_ajax_variation_threshold’, 10, 2 );

Woocommerce: how do I add metadata to a cart item?

I have a digital product which is described by a quantity and a price, but which also needs 3 more numbers to completely specify it (Unix dates, etc). Problem: how do I get these numbers into the cart?
As far as I can see, there are 2 possible ways to handle this:
A product variation
A product custom field
It looks like variations can only handle discrete values with a limited range (ie. red/yellow/green, S/M/L, etc), and can't handle general integers, like dates. That leaves custom fields. I think I'm right in saying that custom fields are ordinary meta data on the product post page, so I can handle them with get_post_meta and update_post_meta.
So, if I go for custom fields, then I would update the product page field during ordering, and then I would read back the field during checkout, when the WC_Order is created, and add the field to the new order. However, this won't work. I can't change metadata on the product page, because the product is global to all customers, and this operation would interfere with other customers. In other words, you can't store order-specific information in a product, so neither of these options would work.
So, how do I store temporary product metadata and pass it between the ordering and checkout phases (ie. between WC_Cart and WC_Order)?
One option would be to store it as user metadata (or as session data?), but there's got to be a better way - any ideas?
It turns out to be easy to do this with session data. When you're adding an item to the cart (see the source for add_to_cart_action) you create a session variable, containing all your additional meta data:
WC()->session->set(
'my_session_var_name',
array(
'members' => $members,
'start' => $start,
'expiry' => $expiry,
'etc' => $etc));
When the user checks out, the cart data disappears, and a new order is created. You can hook into woocommerce_add_order_item_meta to add the session meta data to the order meta data:
add_action(
'woocommerce_add_order_item_meta', 'hook_new_order_item_meta', 10, 3);
function hook_new_order_item_meta($item_id, $values, $cart_item_key) {
$session_var = 'my_session_var_name';
$session_data = WC()->session->get($session_var);
if(!empty($session_data))
wc_add_order_item_meta($item_id, $session_var, $session_data);
else
error_log("no session data", 0);
}
That's it. You do have to figure out how to get the order metadata out and do something useful with it, though. You may also want to clear the session data, from hooks into woocommerce_before_cart_item_quantity_zero, and woocommerce_cart_emptied. There's gist here which has some example code for this.

Resources