Looking to create a custom order process that looks like this:
Customer adds item to cart
During Checkout Process customer uploads design to order
On Checkout payment is verified, but not captured
After design is finalized by the company, they upload the proof for customer review
the customer reviews proof on their dashboard, and clicks a button that processes the order and captures payment
I have figured out everything i need to make this happen except for how to allow the customer to change the status of their order in the dashboard. I do not need them to edit the order, just approve it for payment capture.
I think there should be an easy way to do this with custom PHP code in conjunction with a plugin like Woocommerce Status Control, but I can't seem to find a solution anywhere.
New improved answer: Allow customer to change order status in WooCommerce
You can use the following code that will:
Replace the button text "view" by "approve" on My account > Orders
Display a custom button to approve the order on My account > Order view (single order)
Display a custom success message once customer has approved an order
This will only happen on customer orders with a specific status. So you will have to define:
The order status that require an approval from customer.
The order status that reflect an approved order by the customer (on the 3 functions)
The button text for order approval
The text that will be displayed once customer has approved the order
The code:
// My account > Orders (list): Rename "view" action button text when order needs to be approved
add_filter( 'woocommerce_my_account_my_orders_actions', 'change_my_account_my_orders_view_text_button', 10, 2 );
function change_my_account_my_orders_view_text_button( $actions, $order ) {
$required_order_status = 'processing'; // Order status that requires to be approved
if( $order->has_status($required_order_status) ) {
$actions['view']['name'] = __("Approve", "woocommerce"); // Change button text
}
return $actions;
}
// My account > View Order: Add an approval button on the order
add_action( 'woocommerce_order_details_after_order_table', 'approve_order_button_process' );
function approve_order_button_process( $order ){
// Avoiding displaying buttons on email notification
if( ! ( is_wc_endpoint_url( 'view-order' ) || is_wc_endpoint_url( 'order-received' ) ) ) return;
$approved_button_text = __("Approve this order", "woocommerce");
$required_order_status = 'processing'; // Order status that requires to be approved
$approved_order_status = 'completed'; // Approved order status
// On submit change order status
if( isset($_POST["approve_order"]) && $_POST["approve_order"] == $approved_button_text
&& $order->has_status( $required_order_status ) ) {
$order->update_status( $approved_order_status ); // Change order status
}
// Display a form with a button for order approval
if( $order->has_status($required_order_status) ) {
echo '<form class="cart" method="post" enctype="multipart/form-data" style="margin-top:12px;">
<input type="submit" class="button" name="approve_order" value="Approve this order" />
</form>';
}
}
// My account > View Order: Add a custom notice when order is approved
add_action( 'woocommerce_order_details_before_order_table', 'approved_order_message' );
function approved_order_message( $order ){
// Avoiding displaying buttons on email notification
if( ! ( is_wc_endpoint_url( 'view-order' ) || is_wc_endpoint_url( 'order-received' ) ) ) return;
$approved_order_status = 'completed'; // Approved order status
if( $order->has_status( $approved_order_status ) ) {
wc_print_notice( __("This order is approved", "woocommerce"), 'success' ); // Message
}
}
Code goes in functions.php file of your active child theme (or active theme). Tested and works.
On My account > Orders (list):
On My account > Order view (when an order required to be approved):
On My account > Order view (when customer has approved the order):
For order statuses, you can create custom order statuses with code or with plugins.
I know I might be a bit late. But here I am answering this question in case anyone still needs it.
The below code will add a Mark As Completed button in the My Account Order page action list. Please be informed that it checks if the order status is set to Delivered by the admin and then it shows the button to the customers.
I have developed a plugin for this as well and it's available on WordPress repository. You may check it out in case you need it. Order Approval by Customer for WooCommerce.
/*================================
Add Delivered Order Status
==================================*/
add_action( 'init', 'msoa_register_delivered_order_status' );
function msoa_register_delivered_order_status() {
register_post_status( 'wc-delivered', array(
'label' => 'Session Completed',
'public' => true,
'show_in_admin_status_list' => true,
'show_in_admin_all_list' => true,
'exclude_from_search' => false,
'label_count' => _n_noop( 'Delivered <span class="count">(%s)</span>', 'Delivered <span class="count">(%s)</span>' )
) );
}
add_filter( 'wc_order_statuses', 'msoa_add_delivered_status_to_order_statuses' );
function msoa_add_delivered_status_to_order_statuses( $order_statuses ) {
$new_order_statuses = array();
foreach ( $order_statuses as $key => $status ) {
$new_order_statuses[ $key ] = $status;
if ( 'wc-processing' === $key ) {
$new_order_statuses['wc-delivered'] = __( 'Delivered', 'order-approval' );
}
}
return $new_order_statuses;
}
add_filter( 'woocommerce_my_account_my_orders_actions', 'msoa_mark_as_received', 10, 2 );
function msoa_mark_as_received( $actions, $order ) {
$order_id = $order->id;
if ( ! is_object( $order ) ) {
$order_id = absint( $order );
$order = wc_get_order( $order_id );
}
// check if order status delivered and form not submitted
if ( ( $order->has_status( 'delivered' ) ) && ( !isset( $_POST['mark_as_received'] ) ) ) {
$check_received = ( $order->has_status( 'delivered' ) ) ? "true" : "false";
?>
<div class="ms-mark-as-received">
<form method="post">
<input type="hidden" name="mark_as_received" value="<?php echo esc_attr( $check_received ); ?>">
<input type="hidden" name="order_id" value="<?php echo esc_attr($order_id);?>">
<?php wp_nonce_field( 'so_38792085_nonce_action', '_so_38792085_nonce_field' ); ?>
<input class="int-button-small" type="submit" value="<?php echo esc_attr_e( 'Mark as Received', 'order-approval' ); ?>" data-toggle="tooltip" title="<?php echo esc_attr_e( 'Click to mark the order as complete if you have received the product', 'order-approval' ); ?>">
</form>
</div>
<?php
}
/*
//refresh page if form submitted
* fix status not updating
*/
if( isset( $_POST['mark_as_received'] ) ) {
echo "<meta http-equiv='refresh' content='0'>";
}
// not a "mark as received" form submission
if ( ! isset( $_POST['mark_as_received'] ) ){
return $actions;
}
// basic security check
if ( ! isset( $_POST['_so_38792085_nonce_field'] ) || ! wp_verify_nonce( $_POST['_so_38792085_nonce_field'], 'so_38792085_nonce_action' ) ) {
return $actions;
}
// make sure order id is submitted
if ( ! isset( $_POST['order_id'] ) ){
$order_id = intval( $_POST['order_id'] );
$order = wc_get_order( $order_id );
$order->update_status( "completed" );
return $actions;
}
if ( isset( $_POST['mark_as_received'] ) == true ) {
$order_id = intval( $_POST['order_id'] );
$order = wc_get_order( $order_id );
$order->update_status( "completed" );
}
$actions = array(
'pay' => array(
'url' => $order->get_checkout_payment_url(),
'name' => __( 'Pay', 'woocommerce' ),
),
'view' => array(
'url' => $order->get_view_order_url(),
'name' => __( 'View', 'woocommerce' ),
),
'cancel' => array(
'url' => $order->get_cancel_order_url( wc_get_page_permalink( 'myaccount' ) ),
'name' => __( 'Cancel', 'woocommerce' ),
),
);
if ( ! $order->needs_payment() ) {
unset( $actions['pay'] );
}
if ( ! in_array( $order->get_status(), apply_filters( 'woocommerce_valid_order_statuses_for_cancel', array( 'pending', 'failed' ), $order ), true ) ) {
unset( $actions['cancel'] );
}
return $actions;
}
Related
I'm trying to make a button that changes my order status, but it can only appear on the view-quote page when the order status is at: ywraq-pending
I'm trying this code, but it shows up in all statuses:
function customer_order_confirm_args( $order_id ) {
return array(
'url' => wp_nonce_url( add_query_arg( 'complete_order', $order_id ) , 'wc_complete_order' ),
'name' => __( 'Aprovar Orçamento', 'woocommerce' )
);
}
// Add a custom action button to processing orders (My account > Orders)
add_filter( 'woocommerce_my_account_my_orders_actions', 'complete_action_button_my_accout_orders', 50, 2 );
function complete_action_button_my_accout_orders( $actions, $order ) {
if ( $order->has_status( 'ywraq-pending' ) ) {
$actions['order_confirmed'] = customer_order_confirm_args( $order->get_id() );
}
return $actions;
}
// Add a custom button to processing orders (My account > View order)
add_action( 'woocommerce_order_details_after_order_table', 'complete_action_button_my_accout_order_view' );
function complete_action_button_my_accout_order_view( $order ){
// Avoiding displaying buttons on email notification
if( is_wc_endpoint_url( 'view-quote' ) ) {
$data = customer_order_confirm_args( $order->get_id() );
echo '<div style="margin:16px 0 24px;">
<a class="button" href="'.$data['url'].'">'.$data['name'].'</a>
</div>';
}
}
// Change order status and display a message
add_action( 'template_redirect', 'action_complete_order_status' );
function action_complete_order_status( $query ) {
if ( ( is_wc_endpoint_url( 'orders' )
|| is_wc_endpoint_url( 'view-quote' ) )
&& isset( $_GET['complete_order'] )
&& $_GET['complete_order'] > 1
&& isset($_GET['_wpnonce'])
&& wp_verify_nonce($_GET['_wpnonce'], 'wc_complete_order') )
{
$order = wc_get_order( absint($_GET['complete_order']) );
if ( is_a($order, 'WC_Order') ) {
// Change order status to "ywraq-accepted"
$order->update_status( 'ywraq-accepted', __('Approvado pelo cliente', 'woocommerce') ) ;
// Add a notice (optional)
wc_add_notice( sprintf( __( 'Pedido #%s foi aprovado', 'woocommerce' ), $order->get_id() ) );
// Remove query args
wp_redirect( esc_url( remove_query_arg( array( 'complete_order', '_wpnonce' ) ) ) );
exit();
}
}
}
Can anybody help me?
If I understood your question clearly, you missed checking order status in the complete_action_button_my_accout_order_view function, so, you can achieve that with this code:
function customer_order_confirm_args( $order_id ) {
return array(
'url' => wp_nonce_url( add_query_arg( 'complete_order', $order_id ) , 'wc_complete_order' ),
'name' => __( 'Aprovar Orçamento', 'woocommerce' )
);
}
// Add a custom action button to processing orders (My account > Orders)
add_filter( 'woocommerce_my_account_my_orders_actions', 'complete_action_button_my_accout_orders', 50, 2 );
function complete_action_button_my_accout_orders( $actions, $order ) {
if ( $order->has_status( 'ywraq-pending' ) ) {
$actions['order_confirmed'] = customer_order_confirm_args( $order->get_id() );
}
return $actions;
}
// Add a custom button to processing orders (My account > View order)
add_action( 'woocommerce_order_details_after_order_table', 'complete_action_button_my_accout_order_view' );
function complete_action_button_my_accout_order_view( $order ){
// Avoiding displaying buttons on email notification && only for orders with ywraq-pending status
if( is_wc_endpoint_url( 'view-quote' )
&& $order->has_status( 'ywraq-pending' ) ) {
$data = customer_order_confirm_args( $order->get_id() );
echo '<div style="margin:16px 0 24px;"><a class="button" href="'.$data['url'].'">'.$data['name'].'</a></div>';
}
}
// Change order status and display a message
add_action( 'template_redirect', 'action_complete_order_status' );
function action_complete_order_status( $query ) {
if ( ( is_wc_endpoint_url( 'orders' )
|| is_wc_endpoint_url( 'view-quote' ) )
&& isset( $_GET['complete_order'] )
&& $_GET['complete_order'] > 1
&& isset($_GET['_wpnonce'])
&& wp_verify_nonce($_GET['_wpnonce'], 'wc_complete_order') )
{
$order = wc_get_order( absint($_GET['complete_order']) );
if ( is_a($order, 'WC_Order') ) {
// Change order status to "ywraq-accepted"
$order->update_status( 'ywraq-accepted', __('Approvado pelo cliente', 'woocommerce') ) ;
// Add a notice (optional)
wc_add_notice( sprintf( __( 'Pedido #%s foi aprovado', 'woocommerce' ), $order->get_id() ) );
// Remove query args
wp_redirect( esc_url( remove_query_arg( array( 'complete_order', '_wpnonce' ) ) ) );
exit();
}
}
}
I have created custom order status "Ready to dispatch" and custom action button as well.
The problem and question is: when I have clicked on the custom action button, order status has changed, but default action button "Complete" disappeared.
How can I make that after click of custom action button, "Complete" action button retain?
Any advice would be appreciated
My current code:
// Register new status
function register_awaiting_shipment_order_status() {
register_post_status( 'wc-ready-to-dispatch', array(
'label' => 'Ready to dispatch',
'public' => true,
'exclude_from_search' => false,
'show_in_admin_all_list' => true,
'show_in_admin_status_list' => true,
'label_count' => _n_noop( 'Ready to dispatch (%s)', 'Ready to dispatch (%s)' )
) );
}
add_action( 'init', 'register_awaiting_shipment_order_status' );
// Add your custom order status action button (for orders with "processing" status)
add_filter( 'woocommerce_admin_order_actions', 'add_custom_order_status_actions_button', 100, 2 );
function add_custom_order_status_actions_button( $actions, $order ) {
// Display the button for all orders that have a 'processing' status
if ( $order->has_status( array( 'processing' ) ) ) {
$action_slug = 'ready-to-dispatch';
// Get Order ID (compatibility all WC versions)
$order_id = method_exists( $order, 'get_id' ) ? $order->get_id() : $order->id;
// Set the action button
$actions['ready-to-dispatch'] = array(
'url' => wp_nonce_url( admin_url( 'admin-ajax.php?action=woocommerce_mark_order_status&status=ready-to-dispatch&order_id=' . $order_id ), 'woocommerce-mark-order-status' ),
'name' => __( 'Ready to dispatch', 'woocommerce' ),
'action' => 'ready-to-dispatch', // keep "view" class for a clean button CSS
);
}
return $actions;
}
// Set Here the WooCommerce icon for your action button
add_action( 'admin_head', 'add_custom_order_status_actions_button_css' );
function add_custom_order_status_actions_button_css() {
$action_slug = 'ready-to-dispatch';
echo '<style>.wc-action-button-'.$action_slug.'::after { font-family: woocommerce !important; content: "\f344" !important; }</style>';
}
// Adding custom status 'awaiting-delivery' to order edit pages dropdown
add_filter( 'wc_order_statuses', 'custom_wc_order_statuses' );
function custom_wc_order_statuses( $order_statuses ) {
$new_order_statuses = array();
// add new order status after processing
foreach ( $order_statuses as $key => $status ) {
$new_order_statuses[ $key ] = $status;
if ( 'wc-processing' === $key ) {
$new_order_statuses['wc-ready-to-dispatch'] = 'Ready to dispatch';
}
}
return $new_order_statuses;
}
// Adding custom status 'awaiting-delivery' to admin order list bulk dropdown
add_filter( 'bulk_actions-edit-shop_order', 'custom_dropdown_bulk_actions_shop_order', 1, 1 );
function custom_dropdown_bulk_actions_shop_order( $actions ) {
$actions['mark_ready-to-dispatch'] = __( 'Ready to dispatch', 'woocommerce' );
return $actions;
}
That's because in the woocommerce_admin_order_actions hook an if condition is missing, to display the button if the order contains the status ready-to-dispatch.
I have rewritten your code with this updated code. For example, the init hook has been replaced with woocommerce_register_shop_order_post_statuses to register custom order statuses.
So you get:
/**
* Register order status
*/
function filter_woocommerce_register_shop_order_post_statuses( $order_statuses ) {
// Status must start with "wc-"
$order_statuses['wc-ready-to-dispatch'] = array(
'label' => _x( 'Ready to dispatch', 'Order status', 'woocommerce' ),
'public' => false,
'exclude_from_search' => false,
'show_in_admin_all_list' => true,
'show_in_admin_status_list' => true,
/* translators: %s: number of orders */
'label_count' => _n_noop( 'Ready to dispatch <span class="count">(%s)</span>', 'Abonnement <span class="count">(%s)</span>', 'woocommerce' ),
);
return $order_statuses;
}
add_filter( 'woocommerce_register_shop_order_post_statuses', 'filter_woocommerce_register_shop_order_post_statuses', 10, 1 );
/**
* Show order status in the dropdown # single order
*/
function filter_wc_order_statuses( $order_statuses ) {
$new_order_statuses = array();
// add new order status after processing
foreach ( $order_statuses as $key => $status ) {
$new_order_statuses[ $key ] = $status;
if ( 'wc-processing' === $key ) {
// Status must start with "wc-"
$new_order_statuses['wc-ready-to-dispatch'] = _x( 'Ready to dispatch', 'Order status', 'woocommerce' );
}
}
return $new_order_statuses;
}
add_filter( 'wc_order_statuses', 'filter_wc_order_statuses', 10, 1 );
/**
* Show order status in the dropdown # bulk actions
*/
function filter_bulk_actions_edit_shop_order( $bulk_actions ) {
// Note: "mark_" must be there instead of "wc"
$bulk_actions['mark_ready-to-dispatch'] = __( 'Ready to dispatch', 'woocommerce' );
return $bulk_actions;
}
add_filter( 'bulk_actions-edit-shop_order', 'filter_bulk_actions_edit_shop_order', 10, 1 );
/**
* Add quick action button # admin orders list
*/
function filter_order_actions( $actions, $order ) {
// Get Order ID (compatibility all WC versions)
$order_id = method_exists( $order, 'get_id' ) ? $order->get_id() : $order->id;
// Display the button for all orders that have a 'processing' status
if ( $order->has_status( array( 'processing' ) ) ) {
$action_slug = 'ready-to-dispatch';
// Set the action button
$actions['ready-to-dispatch'] = array(
'url' => wp_nonce_url( admin_url( 'admin-ajax.php?action=woocommerce_mark_order_status&status=ready-to-dispatch&order_id=' . $order_id ), 'woocommerce-mark-order-status' ),
'name' => __( 'Ready to dispatch', 'woocommerce' ),
'action' => $action_slug, // keep "view" class for a clean button CSS
);
}
// Display the button for all orders that have a 'ready-to-dispatch' status
if ( $order->has_status( array( 'ready-to-dispatch' ) ) ) {
$action_slug = 'complete';
// Set the action button
$actions['complete'] = array(
'url' => wp_nonce_url( admin_url( 'admin-ajax.php?action=woocommerce_mark_order_status&status=completed&order_id=' . $order_id ), 'woocommerce-mark-order-status' ),
'name' => __( 'Complete', 'woocommerce' ),
'action' => $action_slug,
);
}
return $actions;
}
add_filter( 'woocommerce_admin_order_actions', 'filter_order_actions', 10, 2 );
/**
* Add WooCommerce icon for your action button # admin orders list
*/
function action_admin_head() {
$action_slug = 'ready-to-dispatch';
echo '<style>.wc-action-button-' . $action_slug . '::after { content: "\f344" !important; }</style>';
}
add_action( 'admin_head', 'action_admin_head' );
How do I change the order status from on hold to my own custom status for a specific shipping method if the selected payment gateway is BACS?
This is how I added my own custom status:
// Register New Order Status
add_filter( 'woocommerce_register_shop_order_post_statuses', 'register_custom_order_status' );
function register_custom_order_status( $order_statuses ){
// Status must start with "wc-"
$order_statuses['wc-custom-status'] = array(
'label' => _x( 'Calculating Shipping', 'Order status', 'woocommerce' ),
'public' => false,
'exclude_from_search' => false,
'show_in_admin_all_list' => true,
'show_in_admin_status_list' => true,
'label_count' => _n_noop( 'Calculating Shipping <span class="count">(%s)</span>', 'Calculating Shipping <span class="count">(%s)</span>', 'woocommerce' ),
);
return $order_statuses;
}
// Show Order Status in the Dropdown # Single Order and "Bulk Actions" # Orders
add_filter( 'wc_order_statuses', 'show_custom_order_status' );
function show_custom_order_status( $order_statuses ) {
$order_statuses['wc-custom-status'] = _x( 'Calculating Shipping', 'Order status', 'woocommerce' );
return $order_statuses;
}
add_filter( 'bulk_actions-edit-shop_order', 'get_custom_order_status_bulk' );
function get_custom_order_status_bulk( $bulk_actions ) {
// Note: "mark_" must be there instead of "wc"
$bulk_actions['mark_custom-status'] = 'Change status to calculating shipping';
return $bulk_actions;
}
This solution was inspired by WooCommerce change BACS order status based on user roles seems to work but it changes the order status for shipping methods not specified here:
function bacs_order_payment_pending_order_status_shipping_method( $order_id ) {
// Get $order object
$order = wc_get_order( $order_id );
// Is a WC_Order
if ( is_a( $order, 'WC_Order' ) ) {
// Get shipping method
$shipping_method = $order->get_shipping_methods();
// Shipping Methods
$methods = (array) $shipping_method;
// Shipping Methods to check
$shipping_methods_to_check = array( 'flat_rate', 'request_shipping_quote' );
// Compare
$compare = array_diff( $methods, $shipping_methods_to_check );
// Result is empty
if ( empty ( $compare ) ) {
if ( $order->get_payment_method() == 'bacs' && $order->has_status( 'on-hold' ) ) {
$order->update_status( 'custom-status' );
}
}
}
}
add_action( 'woocommerce_thankyou', 'bacs_order_payment_pending_order_status_shipping_method', 10, 1 );
The answer code from Change Woocommerce Order Status based on Shipping Method also works but I would like to specify several shipping methods.
UPDATE: In case you want to include logic to set another order status if the shipping methods are not found:
add_action( 'woocommerce_thankyou', 'bacs_order_payment_pending_order_status_shipping_method', 10, 1 );
function bacs_order_payment_pending_order_status_shipping_method( $order_id ) {
// Get WC_Order object from the order Id
$order = wc_get_order( $order_id );
// Check that we get a WC_Order
if ( is_a( $order, 'WC_Order' ) ) {
// Shipping Methods to check
$shipping_methods_to_check = array( 'flat_rate', 'request_shipping_quote' );
$condition = $order->get_payment_method() == 'bacs' && $order->has_status( 'on-hold' );
// Loop through shipping items (objects)
foreach($order->get_shipping_methods() as $shipping_item ){
// Check for matched defined shipping methods
if( in_array( $shipping_item->get_method_id(), $shipping_methods_to_check ) && $condition ){
$order->update_status( 'custom-status' ); // Change Order Status Custom
}
else {$order->update_status( 'pending' ); // Change Order Status Pending
}
}
}
}
Try the following instead (code is commented):
add_action( 'woocommerce_thankyou', 'bacs_order_payment_pending_order_status_shipping_method', 10, 1 );
function bacs_order_payment_pending_order_status_shipping_method( $order_id ) {
// Get WC_Order object from the order Id
$order = wc_get_order( $order_id );
// Check that we get a WC_Order
if ( is_a( $order, 'WC_Order' ) ) {
// Shipping Methods to check
$shipping_methods_to_check = array( 'flat_rate', 'request_shipping_quote' );
$condition = $order->get_payment_method() == 'bacs' && $order->has_status( 'on-hold' );
// Loop through shipping items (objects)
foreach($order->get_shipping_methods() as $shipping_item ){
// Check for matched defined shipping methods
if( in_array( $shipping_item->get_method_id(), $shipping_methods_to_check ) && $condition ){
$order->update_status( 'custom-status' ); // Change order status
return; // Exit
}
}
}
}
Code goes in functions.php file of the active child theme (or active theme). Tested and works.
related: Change Woocommerce Order Status based on Shipping Method
I've used the below php to add an 'imported' custom order status in woocommerce and it works fine
> **/ function register_imported_order_status() {
> register_post_status( 'wc-imported', array(
> 'label' => 'Imported',
> 'public' => true,
> 'exclude_from_search' => false,
> 'show_in_admin_all_list' => true,
> 'show_in_admin_status_list' => true,
> 'label_count' => _n_noop( 'Imported <span class="count">(%s)</span>', 'Imported <span class="count">(%s)</span>'
> )
> ) ); } add_action( 'init', 'register_imported_order_status' );
>
> // Add to list of WC Order statuses function
> add_imported_to_order_statuses( $order_statuses ) {
>
> $new_order_statuses = array();
>
> // add new order status after processing
> foreach ( $order_statuses as $key => $status ) {
>
> $new_order_statuses[ $key ] = $status;
>
> if ( 'wc-processing' === $key ) {
> $new_order_statuses['wc-imported'] = 'Imported';
> }
> }
>
> return $new_order_statuses; } add_filter( 'wc_order_statuses', 'add_imported_to_order_statuses' );
-
However when I try to bulk update the order status - the custom order status does not appear, how can I add the custom status to the bulk actions in Woocommerce Orders.
Furthermore, i want the imported status to be considered as having payment captured. Right now the system does not report sales $$$s until we change the status to completed - but we want the sales $$ to be available as soon as they checkout. How can I make this status include captured payment?
warm regards
Jacob
I built the solution via this guide
The code I use to bulk-edit the 'imported' status in WooCommerce's Orders page is below
<?php
/*
* Add your custom bulk action in dropdown
* #since 3.5.0
*/
add_filter( 'bulk_actions-edit-shop_order', 'misha_register_bulk_action' ); // edit-shop_order is the screen ID of the orders page
function misha_register_bulk_action( $bulk_actions ) {
$bulk_actions['mark_imported'] = 'Mark Imported'; // <option value="mark_imported">Mark Imported</option>
return $bulk_actions;
}
/*
* Bulk action handler
* Make sure that "action name" in the hook is the same like the option value from the above function
*/
add_action( 'admin_action_mark_imported', 'misha_bulk_process_custom_status' ); // admin_action_{action name}
function misha_bulk_process_custom_status() {
// if an array with order IDs is not presented, exit the function
if( !isset( $_REQUEST['post'] ) && !is_array( $_REQUEST['post'] ) )
return;
foreach( $_REQUEST['post'] as $order_id ) {
$order = new WC_Order( $order_id );
$order_note = 'That\'s what happened by bulk edit:';
$order->update_status( 'imported', $order_note, true ); //
}
//using add_query_arg() is not required, you can build your URL inline
$location = add_query_arg( array(
'post_type' => 'shop_order',
'marked_imported' => 1, // markED_imported=1 is the $_GET variable for notices
'changed' => count( $_REQUEST['post'] ), // number of changed orders
'ids' => join( $_REQUEST['post'], ',' ),
'post_status' => 'all'
), 'edit.php' );
wp_redirect( admin_url( $location ) );
exit;
}
/*
* Notices
*/
add_action('admin_notices', 'misha_custom_order_status_notices');
function misha_custom_order_status_notices() {
global $pagenow, $typenow;
if( $typenow == 'shop_order'
&& $pagenow == 'edit.php'
&& isset( $_REQUEST['marked_imported'] )
&& $_REQUEST['marked_imported'] == 1
&& isset( $_REQUEST['changed'] ) ) {
$message = sprintf( _n( 'Order status changed.', '%s order statuses changed.', $_REQUEST['changed'] ), number_format_i18n( $_REQUEST['changed'] ) );
echo "<div class=\"updated\"><p>{$message}</p></div>";
}
}
Dealing with digital products, I've added a GIFT function which works fine, but it does not work if the custom GIFT field is not filled in. If the GIFT field is filled in and when the order is set to Complete, the order complete email is sent to the email put in the GIFT field instead of the one entered as the billing email.
Any idea for where I'm going wrong here? I need it to send to the billing email if the GIFT field is not filled in and if the GIFT field is filled in, send only to the email entered in the GIFT field.
Here is the code:
// add gift message on checkout
add_action( 'woocommerce_after_order_notes', 'custom_checkout_field_before_billing' );
function custom_checkout_field_before_billing() {
$domain = 'woocommerce';
?>
<style>p#gift_field{display:none;}</style>
<div id="message">
<h3><i class="fa fa-gift"></i><?php _e( ' Is this a gift?', 'woocommerce' ); ?></h3>
<?php
woocommerce_form_field( 'gift_msg', array(
'type' => 'checkbox',
'class' => array( 'gift-checkbox' ),
'label' => __( 'To whom is this a gift?', 'woocommerce' ),
), WC()->checkout->get_value( 'cb_msg' ));
woocommerce_form_field( 'gift', array(
'type' => 'text',
'class' => array('msg t_msg'),
'label' => __('Enter the recipient\'s e-mail address, e.g: john.smith#email.com '),
'placeholder' => __(''),
), WC()->checkout->get_value( 'gift' ));
echo '</div>';
?><script>
jQuery(document).ready(function($) {
var a = '#gift_field';
$('input#gift_msg').change( function(){
if( $(this).is(':checked') )
$(a).show();
else
$(a).hide();
});
});
</script><?php
}
// add validation if box is checked but field is not filled in
add_action('woocommerce_after_checkout_validation', 'is_this_a_gift_validation', 20, 2 );
function is_this_a_gift_validation( $data, $errors ) {
if( isset($_POST['gift_msg']) && empty($_POST['gift']) )
$errors->add( 'gift', __( "You've chosen to send this as a gift, but did not submit a recipient email address.", "woocommerce" ) );
}
// update the gift field meta
add_action( 'woocommerce_checkout_update_order_meta', 'is_this_a_gift_save_meta');
function is_this_a_gift_save_meta( $order_id ) {
$gift_recipient_address = $_POST['gift'];
if ( ! empty( $gift_recipient_address ) )
update_post_meta( $order_id, 'gift', sanitize_text_field( $gift_recipient_address ) );
}
// add gift message to order page
function is_this_a_gift_order_display( $order ) { ?>
<div class="order_data_column">
<h3><?php _e( '<br>Gift For:', 'woocommerce' ); ?></h3>
<?php
echo get_post_meta( $order->id, 'gift', true ); ?>
</div>
<?php }
add_action( 'woocommerce_admin_order_data_after_order_details', 'is_this_a_gift_order_display' );
Here is the code that does not work as I need it to:
add_filter( 'woocommerce_email_recipient_customer_completed_order', 'is_this_a_gift_replace_email_recipient', 10, 2 );
function is_this_a_gift_replace_email_recipient( $recipient, $order ) {
if ( ! is_a( $order, 'WC_Order' ) && ( ! empty( $gift_recipient_address ))) return $recipient;
$recipient = get_post_meta( $order->id, 'gift', true );
return $recipient;
}
I would appreciate some help with this. Thanks in advance!
There are some mistakes in your two last functions… try the following (that will replace your two last functions):
// add gift message to order page
add_action( 'woocommerce_admin_order_data_after_order_details', 'is_this_a_gift_order_display' );
function is_this_a_gift_order_display( $order ) {
if( $value = $order->get_meta('gift') ) :
echo '<div class="order_data_column">
<h3>' . __( '<br>Gift For:', 'woocommerce' ) . '</h3>
<p>' . $value . '</p>
</div>';
endif;
}
add_filter( 'woocommerce_email_recipient_customer_completed_order', 'is_this_a_gift_replace_email_recipient', 10, 2 );
function is_this_a_gift_replace_email_recipient( $recipient, $order ) {
$gift_recipient = $order->get_meta('gift');
if ( is_a( $order, 'WC_Order' ) && $order->get_meta('gift') )
$recipient = $order->get_meta('gift');
return $recipient;
}
Code goes in function.php file of your active child theme (active theme). It should work.