Conditionally remove order details section in Woocommerce - php

I want to remove the order details table in WooCommerce in my functions.php if a if statement is true. I've searched a lot but don't know how to do this.
This is how the file is included in WooCommerce wc-template-functions.php:
if ( ! function_exists( 'woocommerce_order_details_table' ) ) {
/**
* Displays order details in a table.
*
* #param mixed $order_id Order ID.
*/
function woocommerce_order_details_table( $order_id ) {
if ( ! $order_id ) {
return;
}
wc_get_template( 'order/order-details.php', array(
'order_id' => $order_id,
) );
}
}
So I need something like this:
if ( value != true ) {
hide_order_details();
}

Updated (Optionally showing customer details)
You can simply use the following hooked function (that has the $order_id as available argument) with your condition in an if statement (where you will define $value)
The following will remove the order details table in My account > View order:
add_action( 'woocommerce_view_order', 'custom_action_view_order', 5, 1 );
function custom_action_view_order( $order_id ){
$value = false;
if( ! $value ){
remove_action( 'woocommerce_view_order', 'woocommerce_order_details_table', 10 );
## ----- Optionally show customer details (if needed) ----- ##
if ( ! $order = wc_get_order( $order_id ) ) {
return;
}
if( is_user_logged_in() ){
wc_get_template( 'order/order-details-customer.php', array( 'order' => $order ) );
}
}
}
Code goes in function.php file of your active child theme (or active theme). Tested and works.
1) With customer details:
2) Without customer details:

From what I see, there is no hook you can use in the template.
But you can easily override the order/order-details.php template in your theme to add a condition on whether to output the detail table or not.
The concerned template is in woocommerce/templates/order/order-details.php. You can copy it to your-theme/woocommerce/templates/order/order-details.php and make the required change.
This way, you don't edit original Woocommerce files and use the right way to override woocommerce outputs. Check the order-details template yourself, you'll see there is no hook here permitting to prevent outputting the table. But a simple if wrapper with your condition around the <table> code should do the trick.
Edit: it seems that the filter woocommerce_order_item_visible used in order-details-item.php template can help you to prevent displaying some lines in the order details table. But the template is called within the order detail table html, so you cannot fully remove the table using it.
Note: I'm not sure if this template part is used somewhere else. If it's the case, you should add to your display condition to check if the actual page is the one you want to apply changes on (customer dashboard order detail). If the template is used somewhere else, It'll apply your changes in every places this template is used.

Related

Prevent User Role from changing woocommerce order status

We would like to prevent shop manager from changing order status, we found a help here in the link below Restrict user role to change only some order statuses in Woocommerce
But the issue here that it limits certain role ( shop Manager ) to some order statuses, we need to deny the shop manager from changing the order status completely not limit it to some order statuses.
Also the snippet we mentioned remove the the order statuses from the bulk action drop down & the order details here: https://prnt.sc/mpfl3b, we need to remove the statuses too from the quick action column here https://snipboard.io/B6SYHb.jpg
Simply we try to have the shop manager to when he try to change order status from bulk, order details page, or actions column to find there is no order statuses to select to change it or disable it completely.
Best Regards
As you can see in the example code the conditions of the statuses are determined in the if statement, because you want to apply this without a limit, it's just a matter of removing that if statement and returning empty arrays
p.s; if you mark my answer as the solution, then also vote for #LoicTheAztec original answer if you have not already done this, since his code just about contained the solution.
// Admin orders list: bulk order status change dropdown
function filter_dropdown_bulk_actions_shop_order( $actions ) {
// Targeting shop_manager
if( current_user_can( 'shop_manager' ) ) {
$actions = (array) null;
}
return $actions;
}
add_filter( 'bulk_actions-edit-shop_order', 'filter_dropdown_bulk_actions_shop_order', 20, 1 );
// Admin orders list: quick action
function filter_order_actions( $actions, $order ) {
// Targeting shop_manager
if( current_user_can( 'shop_manager' ) ) {
$actions = (array) null;
}
return $actions;
}
add_filter( 'woocommerce_admin_order_actions', 'filter_order_actions', 10, 2 );
// Admin order pages: order status dropdown
function filter_order_statuses( $order_statuses ) {
global $post, $pagenow;
if( $pagenow === 'post.php' || $pagenow === 'post-new.php' ) {
// Get ID
$order_id = $post->ID;
// Get an instance of the WC_Order object
$order = wc_get_order( $order_id );
// TRUE
if ( $order ) {
// Get current order status
$order_status = 'wc-' . $order->get_status();
// New order status
$new_order_statuses = array();
foreach ($order_statuses as $key => $option ) {
// Targeting "shop_manager"
if( current_user_can('shop_manager') && $key == $order_status ) {
$new_order_statuses[$key] = $option;
}
}
if( sizeof($new_order_statuses) > 0 ) {
return $new_order_statuses;
}
}
}
return $order_statuses;
}
add_filter('wc_order_statuses', 'filter_order_statuses', 10, 1 );
//Since the suggested answer apparently causes some new issues and doesn't solve the original issue in a couple of other cases, there are options to hide elements according to user type, something like the below - which is a bit of kludge, but might serve:
First, to load an admin style sheet applying only to Shop Managers:
/**
* SHOP MANAGER STYLES
* Front (Optional) and Back End stylesheet
* Style interface for users logged in with'shop_manager' role
* Add to theme functions.php
*/
add_action('admin_enqueue_scripts', 'shop_manager_styles');
//if front end stylesheet needs to be added to cover admin bar:
//add_action('wp_enqueue_scripts', 'shop_manager_styles' ) ;
function shop_manager_styles() {
$user = wp_get_current_user() ;
//uncomment following and remove next if not confined to admin
//if ( $user && in_array( 'shop_manager', $user->roles ) ) {
if ( in_array( 'shop_manager', $user->roles ) ) {
//time() as stylesheeet version to help bust caching - may not be necessary but doesn't hurt:
wp_enqueue_style(
'shop_manager_styles', get_stylesheet_directory_uri()
. '/css/shop_manager_styles.css', array(), time()
);
}
}
...and the css to hide the order-status label and menu completely, as well as related columns in shop_order sub-pages:
/** HIDE ORDER STATUS LABEL, SELECTION MENU IN ORDER EDIT
* AND RELATED COLUMNS IN shop_order SUB-PAGE
*/
.wc-order-status,
.column-order_status,
.column-wc_actions {
display: none;
}
You'd save that in your theme css folder in a new shop_manager_styles.css.
Now, you may have some need to show the order status to shop managers without their being able to edit it. That would also be doable with CSS, if also (even more) a kludge. It may be that you have other peculiarities in your installation that will prevent the above code or a minimally customized variation of it from working, but, even if it is a little less clean than removing the option via function, this kind of thing usually will work in a pinch.
(Edited to provide option to add stylesheet on front end - in case relevant options appearing in admin bar, otherwise no need to enqueue extra non-admin script.)

Add extra details Woocommerce order edit pages in admin

Hi I am using Woocommerce version 3.2.6. We have some orders.
I want to add one extra details to orders when the product id is 123 in the order edit page in wordpress backend.
I wanto add this:
Click here to view this
ie: We have order[order id =3723] , and the ordered item id is 123.
Then in http://example.com/wp-admin/post.php?post=3723&action=edit, I want to add the following link below the corresponding item details:
"Click here to view this"
How we can do this ?
Which hook is suitable for this. Actually I am searching in https://docs.woocommerce.com/wc-apidocs/hook-docs.html.
And I found Class WC_Meta_Box_Order_Items. But i don't know how to use this.
The correct code for WooCommerce version 3+ to add a custom link just after line items and only on backend is:
add_action( 'woocommerce_after_order_itemmeta', 'custom_link_after_order_itemmeta', 20, 3 );
function custom_link_after_order_itemmeta( $item_id, $item, $product ) {
// Only for "line item" order items
if( ! $item->is_type('line_item') ) return;
// Only for backend and for product ID 123
if( $product->get_id() == 123 && is_admin() )
echo ''.__("Click here to view this").'';
}
Tested and works
1) Important: Limit the code to order items "line item" type only, to avoid errors on other order items like "shipping", "fee", "discount"...
2) From the WC_Product object to get the product id you will use WC_Data get_id() method.
3) To get the Order ID from WC_Order_Item_Product object you will use WC_Order_Item method get_order_id().
4) You need to add is_admin() in the if statement to restrict the display in backend.
Order Items Meta Box uses html-order-items.php to loop through Order Items which in turn uses html-order-item.php to display each item.
For your purpose you should look inside html-order-item.php for exact place where you would want to insert your code snippet.
I assume woocommerce_after_order_itemmeta action hook is ideal as it will show the link just below meta information of the item. (In case you want to display the link before item meta than use woocommerce_before_order_itemmeta.)
add_action( 'woocommerce_after_order_itemmeta', 'wp177780_order_item_view_link', 10, 3 );
function wp177780_order_item_view_link( $item_id, $item, $_product ){
if( 123 == $_product->id ) {
echo "<a href='http://example.com/new-view/?id=" . $order->id . "'>Click here to view this</a>";
}
}

Woocommerce disable automatic order status change pending->processing

I want to dissable this option:
Whenever someone makes and order on my site and the payment is successfull the order status automaticaly changes from pending to processing.
However I don`t want this feature to have enabled. Rather I want to do it manually when i proces the orders.
I found this function in the woocommerce which is making this feature possible. I don`t want to directly change it there but rather with some kind of php snippet which overrides this function.
Here is the function which i need to change : http://woocommerce.wp-a2z.org/oik_api/wc_orderpayment_complete/
PS: I just having a hard time to do it correctly.
Update
May be this payment_complete() is not involved in the process you are looking for. Alternatively, what you could try is the woocommerce_thankyou action hook instead:
add_action( 'woocommerce_thankyou', 'thankyou_order_status', 10, 1 );
function thankyou_order_status( $order_id ){
if( ! $order_id ) return;
$order = new WC_Order( $order_id ); // Get an instance of the WC_Order object
if ( $order->has_status( 'processing' ) )
$order-> update_status( 'pending' )
}
You can use the same alternative hook: woocommerce_thankyou_{$order->get_payment_method()} (replacing $order->get_payment_method() by the payment method ID slug)
Code goes in function.php file of your active child theme (or theme) or also in any plugin file.
This code is tested on Woocommerce 3+ and works.
Using a custom function hooked in woocommerce_valid_order_statuses_for_payment_complete filter hook, where you will return the desired orders statuses that can be taken by the related function payment_complete() which is responsible of auto change the order status.
By default the array of order statuses in the filter is:
array( 'on-hold', 'pending', 'failed', 'cancelled' ).
And we can remove 'on-hold' order status this way:
add_filter( 'woocommerce_payment_complete_order_status', 'disable_auto_order_status', 10, 2 );
function disable_auto_order_status( $order_statuses, $order ) {
$return array( 'pending', 'failed', 'cancelled' );
}
Code goes in function.php file of your active child theme (or theme) or also in any plugin file.
This code is tested on Woocommerce 3+ and works.
Add the following code to your functions.php file.function
ja_order_status( $order_status, $order_id ) {
$order = new WC_Order( $order_id );
if ( 'processing' == $order_status ) {
return 'pending';
}
return $order_status;
}
add_filter( 'woocommerce_payment_complete_order_status', 'ja_order_status', 10, 2 );
Tested on WooCommerce with Storefront paid via Stripe test mode.

WooCommerce Print Invoice & Packing Lists - Change Category

I've got a WooCommerce store set up with products in several categories and using the Print Invoice & Packing List plugin to generate packing lists for orders.
The plugin orders products by default based on the first category they are listed in, in alphabetical order.
I'm trying to set the plugin to ignore a preset list of categories by ID, so all products will still display, but only listed under the category I've allowed instead of the first category in alphabetical order.
I've read through the Invoice & Packing List dev reference grabbed a SkyVerge snippet and created a custom plugin which will disable categories completely, but can't for the life of me figure out how the WooCommerce hooks should work to ignore certain categories.
This is what I have in the custom plguin at the moment, which simply removes the categories from packing lists:
if ( ! defined( 'ABSPATH' ) )
add_filter( 'wc_pip_packing_list_group_items_by_category', '__return_false' );
function sv_wc_pip_packing_list_grouping( $group_items, $order_id, $document_type ) {
if ( 'pick-list' !== $document_type ) {
return $group_items;
}
$order = wc_get_order( $order_id );
if ( ! $order->is_paid() ) {
return false;
}
return $group_items;
}
add_filter( 'wc_pip_packing_list_group_items_by_category', 'sv_wc_pip_packing_list_grouping', 10, 3 );
Appreciate any help to identify how to define item categories in this function.
i think you could try this, section Document Filters from your documentation link:
wc_pip_packing_list_exclude_item
Params: $exclude, $product, $item, $item_data
Return: (bool)
Filters if an order item should be excluded from the packing list.
in your filter function, you should be able to test the category from $product, or at least get relevant info to query it. Then you just return true or false following the case

Add custom field for WooCommerce CSV Export plugin - For customer first order [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 6 years ago.
Improve this question
I'm using Woocommerce CSV Export plugin.
I will like to have a way to check if the customer is NEW and if it is, to write in order metadata for a custom meta-key a true value.
But if user is not New, nothing will happen.
I thought first to start with the creation date of the WP user (user_registered). But I think there is a better and faster way. In other words, how can I know if this is the first order of a client...
My goal: If this customer is ordering for the first time, have a TRUE value, for this order in the Export CSV.
Then I have tried to use this answer code without success.
My question:
How could I achieve this?
Thanks
Based on this answer code (I have recently made), it's possible to have a function that will add a meta key/value in the database wp_postmeta table for a New customer first order. So we will change a bit that conditional function this way:
function new_customer_has_bought() {
$count = 0;
$new_customer = false;
// Get all customer orders
$customer_orders = get_posts( array(
'numberposts' => -1,
'meta_key' => '_customer_user',
'meta_value' => get_current_user_id()
) );
// Going through each current customer orders
foreach ( $customer_orders as $customer_order ) {
$count++;
}
// return "true" when it is the first order for this customer
if ( $count > 2 ) // or ( $count == 1 )
$new_customer = true;
return $new_customer;
}
This code goes in function.php file of your active child theme or theme, or in a plugin php file.
USAGE IN THANKYOU HOOK:
add_action( 'woocommerce_thankyou', 'tracking_new_customer' );
function tracking_new_customer( $order_id ) {
// Exit if no Order ID
if ( ! $order_id ) {
return;
}
// The paid orders are changed to "completed" status
$order = wc_get_order( $order_id );
$order->update_status( 'completed' );
// For 1st 'completed' costumer paid order status
if ( new_customer_has_bought() && $order->has_status( 'completed' ) )
{
// Create 'first_order' custom field with 'true' value
update_post_meta( $order_id, 'first_order', 'true' ); needed)
}
else // For all other customer paid orders
{
// udpdate existing 'first_order' CF to '' value (empty)
update_post_meta( $order_id, 'first_order', '' );
}
}
This code goes in function.php file of your active child theme or theme, or in a plugin php file.
Now only for the FIRST new customer order you will have a custom meta data which key is '_first_customer_order' and value is true.
To get this this value for a defined order ID, you will use this (last argument means it's a string):
// Getting the value for a defined $order_id
$first_customer_order = get_post_meta( $order_id, 'first_order', false );
// to display it
echo $first_customer_order;
All the code is tested and works.
References
Template Structure + Overriding Templates via a Theme
Checking if customer has already bought something in WooCommerce
Check if a customer has purchased a specific product earlier in WooCommerce
WP Code Reference - update_post_meta() function
WP Code Reference - get_post_meta() function

Categories