Hook woocommerce_checkout_order_processed order items issue - php

I am working on a WooCommerce project. I need to add some entry based on ordered item in my custom table. If user ordered 3 items then those 3 entry will be place along with some data in my custom table.
For that I used woocommerce_checkout_order_processed hook. But I faced some issue, that if user adds 4 items in cart and on checkout page if user removed all items except one and finally ordered just 1 item then also in this hook I am getting all 4 items. I am not getting final ordered item in this hook.
So I changed the hook to woocommerce_thankyou . But in some case due to some reason user did not come on thank you page or on some credit card payment this hook did not work.
So can anyone tell me the best hook which can run after order place no matter if payment done or not and also I should get only ordered items. My WooCommerce version is 3+
Code :
function wc_function($order_id) {
global $wpdb;
$order = new WC_Order($order_id);
$items = $order->get_items();
foreach ($items as $item_line_id => $item) {
// Insert data in my custom table
}
}
//add_action('woocommerce_checkout_order_processed','wc_function', 10, 3);
//add_action('woocommerce_thankyou', 'wc_function', 10, 1);
Thank you !

do_action on woocommerce_checkout_order_processed passes exactly three args, third of which is the $order itself. So try using that instead:
function wc_function($order_id, $posted_data, $order) {
$items = $order->get_items();
foreach ($items as $item_line_id => $item) {
// Insert data in my custom table
}
}

add_action( 'woocommerce_checkout_order_processed', 'getswift_delivery_thankyou', 10, 1 );
add_action( 'woocommerce_thankyou', 'getswift_delivery_thankyou', 10, 1 );
You may use this hook it's working on my side... if you have any problems then discuss me we will solve them

Related

Remove the add to cart button for the specific user who has already purchased that product

I want only allow one purchase for each product, so I want to disable the add to cart for the user who already purchased that product.
I've been reading and I think I should use the woocommerce_is_purchasable hook
but I have no idea how to do it, I would appreciate the help, thank you.
Assuming you're talking about simple products*, you can do this by hooking into is_purchasable.
For the logged in customer, the following code gets the product ID's of all past orders. If the current product ID is in that collection, it returns false for is_purchasable.
Add it to the functions.php file of your child theme.
add_filter('woocommerce_is_purchasable', 'preventPurchaseIfAlreadyOrdered', 10, 2);
function preventPurchaseIfAlreadyOrdered($is_purchasable, $product) {
$productId = $product->get_id();
$orderedItemIdArray = getOrdersItemIdsForCurrentUser();
$is_purchasable = !in_array($productId, $orderedItemIdArray);
return $is_purchasable;
}
function getOrdersItemIdsForCurrentUser() {
$orders = wc_get_orders(['author' => get_current_user_id()]);
if (empty($orders)) return;
$orderedItemIdArray = [];
foreach ($orders as $order) {
$items = $order->get_items();
foreach ($items as $item) {
$orderedItemIdArray[] = $item->get_product_id();
}
}
return $orderedItemIdArray;
}
The code has been tested and works.
* for variable products, the selected variation can change without reloading the page, i.e. via Ajax. That process is more involved (but also possible).

WooCommerce: hook for admin edited orders

Good morning. I have a single custom function which should be triggered when:
an order is created or modified from frontend
an order is created or modified from backend (admin mode), in any way: refunds, products added or removed, coupon applied, order notes inserted, order action changed, etc.
In the 1st case I'm using add_action('woocommerce_checkout_order_processed', 'calcolo_corrispettivi', 10, 1). Works fine.
In the 2nd case I've tried using add_action('save_post', 'calcolo_corrispettivi', 10, 1). It crashes when triggered by non "order" type posts.
Full code:
add_action('woocommerce_checkout_order_processed', 'calcolo_corrispettivi', 10, 1);
add_action('save_post', 'calcolo_corrispettivi', 10, 1);
// Not enough for all possible 'edit' actions:
// add_action('woocommerce_order_refunded', 'calcolo_corrispettivi', 10, 1);
function calcolo_corrispettivi ( $order_id ) {
$order = wc_get_order( $order_id );
$order_refunds = $order->get_refunds();
$totale_EP = 0;
$totale_altri = 0;
foreach ( $order->get_items() as $item_id => $item) {
$prodotto = $item->get_product();
$editrice = $prodotto->get_attribute('pa_casa-editrice');
if ($editrice == "EP") {
$totale_EP = $totale_EP + $item->get_subtotal() - $order->get_total_refunded_for_item( $item_id );
}
else {
$totale_altri = $totale_altri + $item->get_subtotal() - $order->get_total_refunded_for_item( $item_id );
}
}
update_post_meta($order_id, 'totale_EP', $totale_EP);
update_post_meta($order_id, 'totale_altri', $totale_altri);
}
Is there any specific woocommerce hook for admin updated orders?
Thank you.
Update. I've also tried using woocommerce_process_shop_order_meta, as suggested below, following this question. The solution works only if I press "Update" button under "Order action":
Admin order edit page - Update button
But, for instance, if I change the quantity of a product, the order gets updated without pressing the "Update" button, and so without running my custom function:
Admin order edit page - Update single product quantity
Solution. These hooks worked for me:
Order modified by admin on backend page: woocommerce_saved_order_items (as shown here)
Note added: woocommerce_order_note_added
Refund: woocommerce_order_refunded

WooCommerce Get Product Id Inside woocommerce_cart_calculate_fees Filter [duplicate]

This question already has an answer here:
Get in WooCommerce cart the product ID of a cart item
(1 answer)
Closed 2 years ago.
I am unable to get the product id inside the woocommerce_cart_calculate_fees filter I'm assuming the syntax that I'm using is wrong as I can see the product id when I var_dump() the whole cart object.
Here's my code:
add_filter( 'woocommerce_cart_calculate_fees', 'add_administration_fees', 10, 1 );
function add_administration_fees( $cart ) {
// var_dump($cart);
foreach ($cart as $item) {
echo $item['product_id'];
}
}
If I could also do it without the foreach loop that would be great as I'm going to make it so you can only have a single product in the cart at one time. This product is also a subscription type product using the WooCommerce Subscription plugin in case this is relevant.
You will have to get the cart contents (items) from the $cart object for which you can use the WooCommerce getter function get_cart_contentents(). So your code would look like this:
add_filter( 'woocommerce_cart_calculate_fees', 'add_administration_fees', 10, 1 );
function add_administration_fees( $cart ) {
foreach ( $cart->get_cart_contents() as $item ) {
echo $item['product_id'];
}
}

How to update WooCommerce order item quantity

I need to update the order item meta in a woocommerce oder on checkout page or while woocommerce creates the order.
I'm using the plugin visual product configurator and it is not passing the right quantity of some items of the order to woocommerce order meta, especially when I use multiple variations on the same product.
Is there a hook for me to use to update the item quantity for a certain order item and how can I use it?
The plugin returns me an array with all the cart information and I can only check if an item of the order appears multiple times - if yes I need to change the quantity of that item to that number in the woocommerce order/database.
I was thinking of adding the following hook to my functions.php
add_action('woocommerce_checkout_create_order', 'change_qty', 1,1);
function change_qty($item_qty){
foreach($item_qty as $qty) {
$qty['product_id'] = $id;
$qty['qty'] = $new_qty
$order->update_meta_data('quantity', $new_qty, $id)
}
}
Whereas $item_qty is be an multi-dimensional array containing the item_ids and adjusted quantities.
Another problem I'm facing is that I dont know when I need to call that function because I get the array from the plugin on the checkout page, but I think WooCommerce has not yet created an order at that moment?
The result should be an adjusted item quantity in the woocommerce order summary in the backend.
To update the order item quantity, you can use WC_Order_Item_Product set_quantity() method.
The correct hook to update order items (line items) is woocommerce_checkout_create_order_line_item action hook, that is triggered during order creation, before data is saved to databased.
add_action('woocommerce_checkout_create_order_line_item', 'change_order_line_item_quantity', 10, 4 );
function change_order_line_item_quantity( $item, $cart_item_key, $cart_item, $order ) {
// Your code goes below
// Get order item quantity
$quantity = $item->get_quantity();
$new_qty = $quantity + 2;
// Update order item quantity
$item->set_quantity( $new_qty );
}
The function arguments (variables) are defined and usable:
$item is the WC_Order_Item_Product Object (not saved yet to database)
$cart_item_key is the related cart item key
$cart_item is the related cart item data
$order is the WC_Order Object (not saved yet to database)
Related:
Get Order items and WC_Order_Item_Product in Woocommerce 3
WC_Order_Item_Product Class and methods API Documentation
WC_Checkout and woocommerce_checkout_create_order_line_item action hook located in the create_order_line_items() method
This can help you (we hook into payment completed notification from the payment provider). If you want to update the _qty just after the order was created, I can change my function. But for now I would update it only when the payment was successful.:
/**
* Update order item qty after payment successful
*/
add_filter( 'woocommerce_payment_complete_order_status', 'update_order_item_qty', 10, 2 );
function update_order_item_qty( $order_status, $order_id ) {
//Get the order and items
$order = new WC_Order( $order_id );
$items = $order->get_items();
//New qty
$new_qty = 0;
foreach ( $items as $item_id => $item_data ) {
update_meta_data( '_qty', $new_qty, $item_id );
}
}
Please try if this is what you'r looking for.

WooCommerce use custom price when placing order

I have setup a local Wordpress environment with WooCommerce. The goal is a buy-one-get-one of equal or lesser value scenario.
I have the cart displaying a single item per line. I have isolated the cart products by 'key' not 'product_id' which is necessary for the equal or lesser portion of the requirements. I have created an array of necessary 'key' and am matching that against the cart contents by 'key'. If the keys match, 'set_price('0.00');'
This works on the cart page and checkout page. It all works beautifully until I process the order (currently using COD option only). Then all of the prices reset to the regular price as it appears on the product page (the "regular price"). So the orders do not reflect the actual cost.
Below is the code I have:
function resetPrice( $cart_obj ) {
global $allFreeItems; //all items in cart (and relevant data) that need to be free
$comparison_ids = array(); //isolate keys for comparison
foreach ($allFreeItems as $key => $value) {
$comparison_ids[] = $allFreeItems[$key][1]; //get unique key for each line item
}
foreach ( $cart_obj->get_cart() as $cart_item ) {
// The corresponding product key of line item
$product_key = $cart_item['key'];
// Compare value of above to array of key's and change value
if (in_array($product_key, $comparison_ids)) {
$cart_item['data']->set_price( 0.00 );
}
// else
// {
// $cart_item['data']->get_price();
// }
}
add_action( 'woocommerce_after_checkout_form', 'resetPrice');
add_action( 'woocommerce_before_calculate_totals', 'resetPrice');
I thought perhaps I wasn't using the correct hook, but all examples point to woocommerce_before_calculate_totals. The only difference I see is the everyone keeps using ['product_id'] rather than how I am doing it by [key] Is there something that happens when I click the "place order" button that I am not seeing? Anyone know a way around this?

Categories