Add custom field as an order note in Woocommerce - php

I'm trying to add a custom field jckwds_date as an order note. I can't for the life of me figure out why this code isn't working in functions.php?
The code also only allows the note to be added in the are a certain role type.
function wdm_my_custom_notes_on_single_order_page($order){
$user = wp_get_current_user();
$allowed_roles = array('eu_no_vat', 'super_wholesale_customer', 'wholesale_customer');
if( array_intersect($allowed_roles, $user->roles ) ) {
$value = get_post_meta( $product->get_id(), 'jckwds_date', true );
echo $value;
$order->add_order_note( $value, $is_customer_note = 1 );
}
}
Basically I need THIS:
To be added HERE:

Update:
The following code will add from the order custom field 'jckwds_date' (or checkout posted field value 'jckwds_date') an order note that will appear in backend for defined user roles:
add_action( 'woocommerce_checkout_update_order_meta', 'product_custom_field_to_custom_order_notes', 100, 2 );
function product_custom_field_to_custom_order_notes( $order_id, $data ){
// HERE define allowed user roles
$allowed_roles = array('administrator', 'super_wholesale_customer', 'wholesale_customer');
$user_id = get_post_meta( '_customer_user', 'jckwds_date', true );
$user = new WP_User( $user_id );
// Exit if no matched user roles
if( ! array_intersect( $allowed_roles, $user->roles ) ) return;
// Get the date custom field (or checkout field)
if( get_post_meta( $order_id, 'jckwds_date', true ) ){
$note = get_post_meta( $order_id, 'jckwds_date', true );
} elseif( isset( $_POST['jckwds_date'] ) ){
$note = sanitize_text_field( $_POST['jckwds_date'] );
}
// The order note
if( isset($note) && ! empty($note) ){
$order = wc_get_order( $order_id ); // The WC_Order Object
$order->add_order_note( $note ); // Add the note
$order->save(); // Save the order
}
}
Code goes in function.php file of the active child theme (or active theme). It should work.

add_filter( 'woocommerce_checkout_fields' , 'custom_add_checkout_fields' );
// Our hooked in function - $fields is passed via the filter!
function custom_add_checkout_fields( $fields ) {
unset($fields['order']['order_comments']);
$fields['order']['order_note']['priority'] = 5;
$fields['order']['order_note'] = array(
'label' => __('Order Notes', 'woocommerce'),
'placeholder' => _x('Order Notes', 'placeholder', 'woocommerce'),
'required' => true,
'class' => array('form-row-wide'),
'clear' => true
);
return $fields;
}

Try this
$order = wc_get_order( $order_id );
$note = __("This my custom note...");
$order->add_order_note( $note );
$order->save();

Try this
add_action('woocommerce_checkout_update_order_meta', 'checkout_field_update_order_meta');
function checkout_field_update_order_meta($order_id)
{
if (!empty($_POST['field_name'])) {
update_post_meta($order_id, 'MY Custom Field', sanitize_text_field($_POST['field_name']));
}
}

Try this code.
add_action( 'woocommerce_thankyou', 'my_note_custom' );
function my_note_custom( $order_id ) {
$order = new WC_Order( $order_id );
$note = __("This my custom note...");
$order->add_order_note( $note );
$order->save();
}

Found out it was a simple as changing the $product to $order as it is the order custom field value I'm trying to retrieve.
Full code below:
function wdm_my_custom_notes_on_single_order_page($order){
$user = wp_get_current_user();
$allowed_roles = array('eu_no_vat', 'super_wholesale_customer', 'wholesale_customer');
if( array_intersect($allowed_roles, $user->roles ) ) {
$value = get_post_meta( $order->get_id(), 'jckwds_date', true );
$note = '<b>Wholesale</b>';
echo $value;
$order->add_order_note( $value, $is_customer_note = 1 );
}
}

Related

WOOCOMMERCE call function from URL

I have a php function that creates a new session (WC()->session->set).
I want to make a link on site's header that calls a function to remove that session ( WC()->session->set( 'the_session', null );
how it should be done? couldn't find a way :(
tried to use $_get on functions, which didn't work
EDIT:
here is the code Im using, it add's the option to edit orders that have been made already:
/**
* #snippet Edit Order Functionality # WooCommerce My Account Page
* #how-to Get CustomizeWoo.com FREE
* #sourcecode https://businessbloomer.com/?p=91893
* #author Rodolfo Melogli
* #compatible WooCommerce 4.1
* #donate $9 https://businessbloomer.com/bloomer-armada/
*/
// ----------------
// 1. Allow Order Again for Processing Status
add_filter( 'woocommerce_valid_order_statuses_for_order_again', 'bbloomer_order_again_statuses' );
function bbloomer_order_again_statuses( $statuses ) {
$statuses[] = 'processing';
return $statuses;
}
// ----------------
// 2. Add Order Actions # My Account
add_filter( 'woocommerce_my_account_my_orders_actions', 'bbloomer_add_edit_order_my_account_orders_actions', 50, 2 );
function bbloomer_add_edit_order_my_account_orders_actions( $actions, $order ) {
if ( $order->has_status( 'processing' ) ) {
$actions['edit-order'] = array(
'url' => wp_nonce_url( add_query_arg( array( 'order_again' => $order->get_id(), 'edit_order' => $order->get_id() ) ), 'woocommerce-order_again' ),
'name' => __( 'שנה בחירה', 'woocommerce' )
);
}
return $actions;
}
// ----------------
// 3. Detect Edit Order Action and Store in Session
add_action( 'woocommerce_cart_loaded_from_session', 'bbloomer_detect_edit_order' );
function bbloomer_detect_edit_order( $cart ) {
if ( isset( $_GET['edit_order'], $_GET['_wpnonce'] ) && is_user_logged_in() && wp_verify_nonce( wp_unslash( $_GET['_wpnonce'] ), 'woocommerce-order_again' ) ) WC()->session->set( 'edit_order', absint( $_GET['edit_order'] ) );
}
// ----------------
// 4. Display Cart Notice re: Edited Order
add_action( 'woocommerce_before_cart', 'bbloomer_show_me_session' );
function bbloomer_show_me_session() {
if ( ! is_cart() ) return;
$edited = WC()->session->get('edit_order');
if ( ! empty( $edited ) ) {
$order = new WC_Order( $edited );
$credit = $order->get_total();
wc_print_notice( 'A credit of ' . wc_price($credit) . ' has been applied to this new order. Feel free to add products to it or change other details such as delivery date.', 'notice' );
}
}
// ----------------
// 5. Calculate New Total if Edited Order
add_action( 'woocommerce_cart_calculate_fees', 'bbloomer_use_edit_order_total', 20, 1 );
function bbloomer_use_edit_order_total( $cart ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) ) return;
$edited = WC()->session->get('edit_order');
if ( ! empty( $edited ) ) {
$order = new WC_Order( $edited );
$credit = -1 * $order->get_total();
$cart->add_fee( 'Credit', $credit );
}
}
// ----------------
// 6. Save Order Action if New Order is Placed
add_action( 'woocommerce_checkout_update_order_meta', 'bbloomer_save_edit_order' );
function bbloomer_save_edit_order( $order_id ) {
$edited = WC()->session->get( 'edit_order' );
if ( ! empty( $edited ) ) {
// update this new order
update_post_meta( $order_id, '_edit_order', $edited );
$neworder = new WC_Order( $order_id );
$oldorder_edit = get_edit_post_link( $edited );
$neworder->add_order_note( 'Order placed after editing. Old order number: ' . $edited . '' );
// cancel previous order
$oldorder = new WC_Order( $edited );
$neworder_edit = get_edit_post_link( $order_id );
$oldorder->update_status( 'cancelled', 'Order cancelled after editing. New order number: ' . $order_id . ' -' );
WC()->session->set( 'edit_order', null );
}
}
I want to make a button on my website header, that removes the session after the user clicked "edit order", if he decided to cancel the editing and stay with his original order, the line that does that is
WC()->session->set( 'edit_order', null );
and I want it to be a link
Found the right way:
add_action('afterheader','leave_edit_order');
function after_header_block_yhm()
{
do_action( 'afterheader');
}
add_shortcode('under_header_location','after_header_block_yhm');
function leave_edit_order(){
$edited = WC()->session->get('edit_order');
if(!empty($edited) && isset($_GET['cancel_edit_order'])){
WC()->session->set( 'edit_order', null );
wc_print_notice( 'You left "edit order" session, enjoy your stay.' );
}
add_action('afterheader','leave_edit_order');
Made a new action called 'afterheader" and a new shortcode called 'under_header_location',
then used elementor to put the shortcode in the place I wanted, and then called the function in that new action I made
on the function Im checking that the user has ?cancel_edit_order on his url and then calling the function

Save meta value when WooCommerce order status is completed

I made a code to save a value based on a meta key when a certain product is purchased (order status = completed).
I have written the code below to complete this task. However, the meta data does not appear to be saved? Any advice?
add_action( 'woocommerce_order_status_completed', 'wpglorify_change_role_on_purchase2' );
function wpglorify_change_role_on_purchase2( $order_id ) {
// get order object and items
$order = new WC_Order( $order_id );
$items = $order->get_items();
$user_is= $user->ID;
$meta_key = get_field("field");
$field = get_user_meta($user_is, $meta_key);
$meta_value = 5;
$product_id = 1289;
foreach ( $items as $item ) {
if( $product_id == $item['product_id'] && $order->user_id ) {
$user = new WP_User( $order->user_id );
update_user_meta($user_is, $field, $meta_value, '');
}
}
}
Your code contains some mistakes:
get_field() is a ACF function, and doesn't seem to apply here
You're using $user->ID; but $user is undefined
Furthermore, it is important to determine whether you want to update user meta or post meta data
1) To update user meta you can use:
// Update user meta
function action_woocommerce_order_status_completed( $order_id, $order ) {
// Product IDs
$product_id = 1289;
// Meta data
$meta_value = 5;
$meta_key = 'my_meta_key';
// Is a order
if ( is_a( $order, 'WC_Order' ) ) {
// Getting the user ID
$user_id = $order->get_user_id();
// User ID exists
if ( $user_id >= 1 ) {
// Loop through order items
foreach ( $order->get_items() as $key => $item ) {
// Compare
if ( $item->get_product_id() == $product_id ) {
// Update user meta
update_user_meta( $user_id, $meta_key, $meta_value );
// Break loop
break;
}
}
}
}
}
add_action( 'woocommerce_order_status_completed', 'action_woocommerce_order_status_completed', 10, 2 );
2) To update post meta you can use:
// Update post meta
function action_woocommerce_order_status_completed( $order_id, $order ) {
// Product IDs
$product_id = 1289;
// Meta data
$meta_value = 5;
$meta_key = 'my_meta_key';
// Is a order
if ( is_a( $order, 'WC_Order' ) ) {
// Loop through order items
foreach ( $order->get_items() as $key => $item ) {
// Compare
if ( $item->get_product_id() == $product_id ) {
// Add the meta data
$order->update_meta_data( $meta_key, $meta_value );
// Save
$order->save();
/** OR the older way **/
// update_post_meta( $order_id, $meta_key, $meta_value );
// Break loop
break;
}
}
}
}
add_action( 'woocommerce_order_status_completed', 'action_woocommerce_order_status_completed', 10, 2 );

Change order status for backordered items in Woocommerce

I am configuring a webshop using WordPress and WooCommerce. I have a plugin installed called Woo Multi Order Creator. What is does is that whenever an order of more than 1 item is made, it divides the main order into multiple orders, one order per purchased item.
Now, what I want to do is to make it change the order status of each order, if the item in each order is containing meta key with the value "Backordered".
For example if product A and product B are purchased. Product A is in backorder, and therefore has
{$wpdb->prefix}woocommerce_order_itemmeta.meta_key = 'Backordered'
and product B would be in stock, and it would not have the metakey for backorder.
Now, the thing is that the plugin divides this order into two orders, one per purchased item. What I want it to do further, is to see if the items containted in each new order has the metakey for backorder, and if it has then change the order status to 'waiting', for every order.
Plugin code:
<?php /*
Plugin Name: Woo Product Wise Multi Order Creator
Description: Create multiple orders in woocommerce product wise.
Plugin URI: http://www.thewpexperts.co.uk
Version: 2.0.0
Author: TheWPexperts
Author URI: http://www.thewpexperts.com/
*/
/*
Copyright 2017 The WP Experts
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License, version 2, as
published by the Free Software Foundation.
Permission is hereby granted, free of charge, to any person obtaining a copy of this
software and associated documentation files (the "Software"), to deal in the Software
without restriction, including without limitation the rights to use, copy, modify, merge,
publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or
substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
define( 'WOO_MULTI_ORDER_URL', plugins_url('/', __FILE__) );
define( 'WOO_MULTI_ORDER_DIR', dirname(__FILE__) );
if ( ! class_exists( 'WC_CPInstallCheck' ) ) {
class WC_CPInstallCheck {
static function install() {
if ( !is_plugin_active('woocommerce/woocommerce.php')){
deactivate_plugins(__FILE__);
$error_message = __('This plugin requires WooCommerce plugins to be active!', 'woocommerce');
die($error_message);
}
}
}
}
register_activation_hook( __FILE__, array('WC_CPInstallCheck', 'install') );
add_action('init','woo_multi_order_load_function');
function woo_multi_order_load_function() {
$enableMultiOrder = get_option('enableMultiOrder');
$customOrderPermit = get_option('customOrderPermit');
add_action('admin_menu', 'register_multi_order_setting_submenu',99);
if($enableMultiOrder == 1){
add_action('woocommerce_multiorder_checkout_before_order_info', 'destinationStep');
add_action( 'woocommerce_thankyou', 'multi_order_generator', 10, 1 );
if($customOrderPermit ==1){
add_action( 'woocommerce_after_order_notes', 'woo_order_dates_checkout_field' );
add_action( 'wp_head', 'date_picker_scripts' );
add_action( 'woocommerce_checkout_update_order_meta', 'checkout_update_delivery_meta' );
add_filter("manage_edit-shop_order_columns", "woo_order_extra_columns");
add_action("manage_posts_custom_column", "woo_order_extra_columns_content");
add_filter( 'manage_edit-shop_order_sortable_columns', 'my_sortable_cake_column' );
}
}
}
function your_plugin_settings_link($links) {
$settings_link = 'Settings';
array_unshift($links, $settings_link);
return $links;
}
$plugin = plugin_basename(__FILE__);
add_filter("plugin_action_links_$plugin", 'your_plugin_settings_link' );
function register_multi_order_setting_submenu() {
add_submenu_page( 'woocommerce', 'Multi-order Setting', 'Multi-order Setting', 'manage_options', 'multi-order-setting', 'multi_order_setting' );
}
function multi_order_setting(){
include(WOO_MULTI_ORDER_DIR.'/admin/settings.php');
}
function date_picker_scripts() {
$customOrderPermit = get_option('customOrderPermit');
if(is_page('checkout')){
wp_enqueue_script( 'jquery' );
wp_enqueue_script( 'jquery-ui-datepicker', array( 'jquery' ) );
wp_register_style('jquery-ui', 'http://ajax.googleapis.com/ajax/libs/jqueryui/1.8/themes/base/jquery-ui.css');
wp_enqueue_style( 'jquery-ui' );
}
}
function checkout_update_delivery_meta( $order_id ) {
$dateArray = array();
$customOrderPermit = get_option('customOrderPermit');
$dayDifference = get_option('dayDifference');
$dt = date('d/m/y', strtotime("+".$dayDifference." days"));
if ( count($_POST['customDatePicker'])>0) {
foreach($_POST['customDatePicker'] as $customDatePicker){
if(!empty($customDatePicker)){
$dateArray[] = $customDatePicker;
}else{
$dateArray[] = $dt;
}
}
}
$dateValue = join( ', ', $dateArray );
update_post_meta( $order_id, 'Delivery_Dates', $dateValue);
}
function woo_order_dates_checkout_field( $checkout ) {
global $woocommerce,$orderRate;
$customOrderPermit = get_option('customOrderPermit');
$dayDifference = get_option('dayDifference');
$dt = date('Y-m-d', strtotime("+".$dayDifference." days"));
$items = $woocommerce->cart->get_cart();
foreach($items as $item => $values) {
$_product = $values['data']->post;
$price = get_post_meta($values['product_id'] , '_price', true);
echo "<b>".$_product->post_title."</b> ";
echo '<input type="text" class="deliveryDate" id="datepicker'.$_product->ID.'" name="customDatePicker[]" placeholder="Choose dates">'; ?>
<script type="text/javascript">
jQuery(document).ready(function() {
jQuery("#datepicker<?php echo $_product->ID;?>").datepicker({
dateFormat: 'dd/mm/yy',
minDate: new Date('<?php echo $dt; ?>'),
});
});
</script>
<?php
}
}
function multi_order_generator($order_id) {
$customOrderPermit = get_option('customOrderPermit');
$order = new WC_Order( $order_id );
$items = $order->get_items();
$count =0;
$productID = array();
$productQty = array();
$deliveryDate = get_post_meta( $order_id, 'Delivery_Dates',true);
$dateArray = explode(',',$deliveryDate);
foreach($items as $order_item_id => $item){
if($count >0){
$productName = get_the_title($item['product_id']);
$orderValueID = createNewOrderAndRecordPayment($order_id);
addProductWithOrder($orderValueID,$item['product_id'],$item['qty']);
if($customOrderPermit == 1){
update_post_meta($orderValueID,'_Delivery_Date',$dateArray[$count]);
}
wc_delete_order_item($order_item_id);
}else{
if($customOrderPermit == 1){
update_post_meta($order_id,'_Delivery_Date',$dateArray[0]);
}
}
$count++;
}
}
function addProductWithOrder($orderID,$productID,$productQty){
$ProOrderItem = new WC_Order($orderID);
$ProOrderItem->add_product(get_product($productID),$productQty);
}
function createNewOrderAndRecordPayment($orderID) {
global $wpdb;
global $woocommerce;
$original_order = new WC_Order($orderID);
$currentUser = wp_get_current_user();
//1 Create Order
$order_data = array(
'post_type' => 'shop_order',
'post_status' => 'publish',
'ping_status' => 'closed',
'post_author' => $currentUser->ID,
'post_excerpt' => $original_order->customer_message,
'post_password' => uniqid( 'order_' ) // Protects the post just in case
);
$order_id = wp_insert_post( $order_data, true );
if ( is_wp_error( $order_id ) ){
$msg = "Unable to create order:" . $order_id->get_error_message();;
throw new Exception( $msg );
} else {
$order = new WC_Order($order_id);
//2 Update Order Header
update_post_meta( $order_id, '_order_shipping', get_post_meta($orderID, '_order_shipping', true) );
update_post_meta( $order_id, '_order_discount', get_post_meta($orderID, '_order_discount', true) );
update_post_meta( $order_id, '_cart_discount', get_post_meta($orderID, '_cart_discount', true) );
update_post_meta( $order_id, '_order_tax', get_post_meta($orderID, '_order_tax', true) );
update_post_meta( $order_id, '_order_shipping_tax', get_post_meta($orderID, '_order_shipping_tax', true) );
update_post_meta( $order_id, '_order_total', get_post_meta($orderID, '_order_total', true) );
update_post_meta( $order_id, '_order_key', 'wc_' . apply_filters('woocommerce_generate_order_key', uniqid('order_') ) );
update_post_meta( $order_id, '_customer_user', get_post_meta($orderID, '_customer_user', true) );
update_post_meta( $order_id, '_order_currency', get_post_meta($orderID, '_order_currency', true) );
update_post_meta( $order_id, '_prices_include_tax', get_post_meta($orderID, '_prices_include_tax', true) );
update_post_meta( $order_id, '_customer_ip_address', get_post_meta($orderID, '_customer_ip_address', true) );
update_post_meta( $order_id, '_customer_user_agent', get_post_meta($orderID, '_customer_user_agent', true) );
//3 Add Billing Fields
update_post_meta( $order_id, '_billing_city', get_post_meta($orderID, '_billing_city', true));
update_post_meta( $order_id, '_billing_state', get_post_meta($orderID, '_billing_state', true));
update_post_meta( $order_id, '_billing_postcode', get_post_meta($orderID, '_billing_postcode', true));
update_post_meta( $order_id, '_billing_email', get_post_meta($orderID, '_billing_email', true));
update_post_meta( $order_id, '_billing_phone', get_post_meta($orderID, '_billing_phone', true));
update_post_meta( $order_id, '_billing_address_1', get_post_meta($orderID, '_billing_address_1', true));
update_post_meta( $order_id, '_billing_address_2', get_post_meta($orderID, '_billing_address_2', true));
update_post_meta( $order_id, '_billing_country', get_post_meta($orderID, '_billing_country', true));
update_post_meta( $order_id, '_billing_first_name', get_post_meta($orderID, '_billing_first_name', true));
update_post_meta( $order_id, '_billing_last_name', get_post_meta($orderID, '_billing_last_name', true));
update_post_meta( $order_id, '_billing_company', get_post_meta($orderID, '_billing_company', true));
//4 Add Shipping Fields
update_post_meta( $order_id, '_shipping_country', get_post_meta($orderID, '_shipping_country', true));
update_post_meta( $order_id, '_shipping_first_name', get_post_meta($orderID, '_shipping_first_name', true));
update_post_meta( $order_id, '_shipping_last_name', get_post_meta($orderID, '_shipping_last_name', true));
update_post_meta( $order_id, '_shipping_company', get_post_meta($orderID, '_shipping_company', true));
update_post_meta( $order_id, '_shipping_address_1', get_post_meta($orderID, '_shipping_address_1', true));
update_post_meta( $order_id, '_shipping_address_2', get_post_meta($orderID, '_shipping_address_2', true));
update_post_meta( $order_id, '_shipping_city', get_post_meta($orderID, '_shipping_city', true));
update_post_meta( $order_id, '_shipping_state', get_post_meta($orderID, '_shipping_state', true));
update_post_meta( $order_id, '_shipping_postcode', get_post_meta($orderID, '_shipping_postcode', true));
//6 Copy shipping items and shipping item meta from original order
$original_order_shipping_items = $original_order->get_items('shipping');
foreach ( $original_order_shipping_items as $original_order_shipping_item ) {
$item_id = wc_add_order_item( $order_id, array(
'order_item_name' => $original_order_shipping_item['name'],
'order_item_type' => 'shipping'
) );
if ( $item_id ) {
wc_add_order_item_meta( $item_id, 'method_id', $original_order_shipping_item['method_id'] );
wc_add_order_item_meta( $item_id, 'cost', wc_format_decimal( $original_order_shipping_item['cost'] ) );
}
}
// Store coupons
$original_order_coupons = $original_order->get_items('coupon');
foreach ( $original_order_coupons as $original_order_coupon ) {
$item_id = wc_add_order_item( $order_id, array(
'order_item_name' => $original_order_coupon['name'],
'order_item_type' => 'coupon'
) );
// Add line item meta
if ( $item_id ) {
wc_add_order_item_meta( $item_id, 'discount_amount', $original_order_coupon['discount_amount'] );
}
}
//Payment Info
update_post_meta( $order_id, '_payment_method', get_post_meta($orderID, '_payment_method', true) );
update_post_meta( $order_id, '_payment_method_title', get_post_meta($orderID, '_payment_method_title', true) );
update_post_meta( $order->id, 'Transaction ID', get_post_meta($orderID, 'Transaction ID', true) );
$order->payment_complete();
//6 Set Order Status to processing to trigger initial emails to end user and vendor
$order->update_status('processing');
}
return $order_id;
}
function woo_order_extra_columns($columns)
{
$newcolumns = array(
"cb" => "<input type = \"checkbox\" />",
"delivery" => esc_html__('Delivery', 'woocommerce'),
);
$columns = array_merge($newcolumns, $columns);
return $columns;
}
function woo_order_extra_columns_content($column)
{
global $post;
$order_id = $post->ID;
switch ($column)
{
case "delivery":
$daliveryDate = get_post_meta($order_id,'_Delivery_Date',true);
if ( empty( $daliveryDate ) )
echo __( '-' );
else
printf( __( '%s' ), $daliveryDate );
break;
}
}
function my_sortable_cake_column( $columns ) {
$columns['delivery'] = 'delivery';
return $columns;
}
It changes the order status to processing at line 253.
I'm guessing that it is around here that a bit of code should be added to make it change order status to waiting instead, if the item in the order has the metakey for backorder.
I hope that someone with more expertise than my very limited knowlegde can come to my assistance.
Here is a hooked function that is triggered when orders get a "processing" status.
Inside the function we look for order items that are "Backordered" with a simple and light SQL query from the order ID.
If a "Backordered" item is found, we change the order status to "on-hold" (the correct order status for your case).
The code:
add_action('woocommerce_order_status_processing', 'pending_back_orders_to_on_hold', 60, 2 );
function pending_back_orders_to_on_hold( $order_id, $order ) {
global $wpdb;
// The SQL query for Order items in backorder
$results = $wpdb->get_col( "
SELECT woim.meta_value FROM {$wpdb->prefix}woocommerce_order_itemmeta as woim
INNER JOIN {$wpdb->prefix}woocommerce_order_items as woi ON woim.order_item_id = woi.order_item_id
WHERE woi.order_id = '$order_id' AND woim.meta_key = 'Backordered'
" );
// If an item is 'Backordered' we change the order status to "on-hold"
if(reset($results) > 0)
$order->update_status('on-hold');
}
Code goes in function.php file of your active child theme (or active theme).
Tested and works.
Update (related to your comment)
If you want to change the code inside the plugin for that purpose, you will replace line 253:
$order->update_status('processing');
By the following code:
$line_item_ids = array_keys( $order->get_items() );
$backordered = wc_get_order_item_meta( reset($line_item_ids), 'Backordered', true );
$changed_status = $backorders > 0 ? 'on-hold' : 'processing';
$order->update_status( $changed_status );
It should work, but this is not a good practice.

Save and display a custom field as order item meta data in WooCommerce

In woocommerce, I have maisd wome customizations and I can add a custom text field in my products, Display the values in cart and checkout (see the screenshots below).
Text field in product page:
Value in the cart:
Value in the checkout:
But I can not get it to appear in the purchase details or in the administration section (see the screenshots below).
Checkout details without the value:
Administration orders without the value:
In my code below, could someone tell what I am doing wrong?
The code that I use in my functions.php file:
// Add the field to the product
add_action('woocommerce_before_add_to_cart_button', 'my_custom_checkout_field');
function my_custom_checkout_field() {
global $product;
$id = $product->get_id();
// Get the field name of InputText1
$InputText1Name = get_post_meta($id, 'InputText1', true);
if ((!empty(get_post_meta($id, $InputText1, true)))){
echo '<div id="InputText1">';
echo '<label>'.__($InputText1Name).'</label> <input type="text" name="$InputText1V">';
echo '</div>';
}
}
// Store custom field
function save_my_custom_checkout_field( $cart_item_data, $product_id ) {
if( isset( $_REQUEST['$InputText1V'] ) ) {
$cart_item_data[ '$InputText1V' ] = $_REQUEST['$InputText1V'];
/* below statement make sure every add to cart action as unique line item */
$cart_item_data['unique_key'] = md5( microtime().rand() );
}
return $cart_item_data;
}
add_action( 'woocommerce_add_cart_item_data', 'save_my_custom_checkout_field', 10, 2 );
// Render meta on cart and checkout
function render_meta_on_cart_and_checkout( $cart_data, $cart_item = null ){
// Get the product id inside the cart
foreach( WC()->cart->get_cart() as $cart_item ){
$product_id = $cart_item['product_id'];
}
// Get the field name of InputText1
$InputText1Name = get_post_meta($product_id, 'InputText1', true);
$custom_items = array();
/* Woo 2.4.2 updates */
if( !empty( $cart_data ) ) {
$custom_items = $cart_data;
}
if( isset( $cart_item['$InputText1V'] ) ) {
$custom_items[] = array( "name" => $InputText1Name, "value" => $cart_item['$InputText1V'] );
}
return $custom_items;
}
add_filter( 'woocommerce_get_item_data', 'render_meta_on_cart_and_checkout', 10, 2 );
// Display as order meta
function my_field_order_meta_handler( $item_id, $values, $cart_item_key ) {
if( isset( $values['$InputText1V'] ) ) {
wc_add_order_item_meta( $product_id, "$InputText1V", $values['$InputText1V'] );
}
}
// Update the order meta with field value
add_action('woocommerce_checkout_update_order_meta', 'my_custom_checkout_field_update_order_meta');
function my_custom_checkout_field_update_order_meta( $order_id ) {
if ($_POST['$InputText1V']) update_post_meta( $order_id, '$InputText1Name', esc_attr($_POST['$InputText1V']));
}
// Update the user meta with field value
add_action('woocommerce_checkout_update_user_meta', 'my_custom_checkout_field_update_user_meta');
function my_custom_checkout_field_update_user_meta( $user_id ) {
if ($user_id && $_POST['$InputText1V']) update_user_meta( $user_id, '$InputText1V', esc_attr($_POST['$InputText1V']) );
}
add_filter( 'woocommerce_hidden_order_itemmeta', 'hide_order_item_meta_fields' );
// Display field value on the order edit page
add_action( 'woocommerce_admin_order_data_after_billing_address', 'my_custom_checkout_field_display_admin_order_meta', 10, 1 );
function my_custom_checkout_field_display_admin_order_meta( $order ){
$order_id = method_exists( $order, 'get_id' ) ? $order->get_id() : $order->id;
echo '<p><strong>'.__($InputText1V).':</strong> ' . get_post_meta( $order_id, $InputText1V, true ) . '</p>';
}
function hide_order_item_meta_fields( $fields ) {
$fields[] = 'current_view';
$fields[] = 'custom_image';//Add all meta keys to this array,so that it will not be displayed in order meta box
return $fields;
}
add_action( 'woocommerce_after_order_itemmeta', 'order_meta_customized_display',10, 3 );
function order_meta_customized_display( $item_id, $item, $product ){
$order_product_id = $item['product_id'];
$field1name = get_post_meta($order_product_id, 'InputText1', true);
echo'<br>';
print_r($InputText1V);
echo'<br>';
echo $field1name;
echo ': ';
}
There are errors and missing things in your code. You don't need all that functions too and you should really avoid to use $ (and if you can capitals) in your custom field slugs (or in key slugs and even in function names) in your code.
I have tested and revisited your code. Here is what you need and can remove everything else:
// Add the field to the product
add_action('woocommerce_before_add_to_cart_button', 'my_custom_checkout_field');
function my_custom_checkout_field() {
global $product;
$product_id = $product->get_id();
// Get the field name of InputText1
$label = get_post_meta($product_id, 'InputText1', true);
if( ! empty( $label ) ){
echo '<div id="InputText1">
<label>'.$label.':</label> <input type="text" name="custom_slug" value="">
</div>';
}
}
// Store custom field label and value in cart item data
add_filter( 'woocommerce_add_cart_item_data', 'save_my_custom_checkout_field', 10, 2 );
function save_my_custom_checkout_field( $cart_item_data, $product_id ) {
if( isset( $_REQUEST['custom_slug'] ) ) {
$cart_item_data['custom_data']['label'] = get_post_meta($product_id, 'InputText1', true);
$cart_item_data['custom_data']['value'] = sanitize_text_field( $_REQUEST['custom_slug'] );
$cart_item_data['custom_data']['ukey'] = md5( microtime().rand() );
}
return $cart_item_data;
}
// Display items custom fields label and value in cart and checkout pages
add_filter( 'woocommerce_get_item_data', 'render_meta_on_cart_and_checkout', 10, 2 );
function render_meta_on_cart_and_checkout( $cart_data, $cart_item ){
$custom_items = array();
/* Woo 2.4.2 updates */
if( !empty( $cart_data ) ) {
$custom_items = $cart_data;
}
if( isset( $cart_item['custom_data'] ) ) {
$custom_items[] = array(
'name' => $cart_item['custom_data']['label'],
'value' => $cart_item['custom_data']['value'],
);
}
return $custom_items;
}
// Save item custom fields label and value as order item meta data
add_action('woocommerce_add_order_item_meta','save_in_order_item_meta', 10, 3 );
function save_in_order_item_meta( $item_id, $values, $cart_item_key ) {
if( isset( $values['custom_data'] ) ) {
wc_add_order_item_meta( $item_id, $values['custom_data']['label'], $values['custom_data']['value'] );
}
}
Code goes in function.php file of your active child theme (or active theme).
Tested and works.
This way you will get the display in Order received, Order view, Edit order (admin) and email notifications…

Resend programmatically a WooCommerce customer_on_hold_order email notification

I noticed that the customer on hold order email is not available so i tried to replace the actions with a single action that would send the appropriate email.
This seems to work except for the on-hold status. I dont see what the difference is between the on-hold and processing case other than its not in the $available_emails in class-wc-meta-box-order-actions.php and I have removed all the others and they still work.
What I am doing wrong? Is it a way to make this possible?
My code is:
function ulmh_resend1( $actions ) {
$actions['ulmh_resend'] = __( 'Resend Email', 'text_domain' );
return $actions;
}
function ulmh_resend2( $order ) {
$mailer = WC()->mailer();
$mails = $mailer->get_emails();
if ($order->has_status( 'on-hold' )) {
$eml = 'customer_on_hold_order';
}elseif ($order->has_status( 'processing' )) {
$eml = 'customer_processing_order';
}elseif ($order->has_status( 'completed' )) {
$eml = 'customer_completed_order';
} else {
$eml = "nothing";
}
if ( ! empty( $mails ) ) {
foreach ( $mails as $mail ) {
if ( $mail->id == eml ) {
$mail->trigger( $order->id );
}
}
}
}
function ulmh_resend3( $order_emails ) {
$remove = array( 'new_order', 'cancelled_order', 'customer_processing_order', 'customer_completed_order', 'customer_invoice' );
$order_emails = array_diff( $order_emails, $remove );
return $order_emails;
}
add_action( 'woocommerce_order_actions', 'ulmh_resend1' );
add_action( 'woocommerce_order_action_ulmh_resend', 'ulmh_resend2' );
add_filter( 'woocommerce_resend_order_emails_available', 'ulmh_resend3' );
I have revisited and compacted your code because there where some errors like a typo error in if ( $mail->id == eml ){ for eml as a variable name… Also to get the Order ID from the WC_Order object you should use $order->get_id() method instead of $order->id.
Here is this new functional code:
add_action( 'woocommerce_order_actions', 'ulmh_resend1' );
function ulmh_resend1( $actions ) {
$actions['ulmh_resend'] = __( 'Resend Email', 'text_domain' );
return $actions;
}
add_action( 'woocommerce_order_action_ulmh_resend', 'ulmh_resend2' );
function ulmh_resend2( $order ) {
$wc_emails = WC()->mailer()->get_emails();
if( empty( $wc_emails ) ) return;
if ($order->has_status( 'on-hold' ))
$email_id = 'customer_on_hold_order';
elseif ($order->has_status( 'processing' ))
$email_id = 'customer_processing_order';
elseif ($order->has_status( 'completed' ))
$email_id = 'customer_completed_order';
else
$email_id = "nothing";
foreach ( $wc_emails as $wc_mail )
if ( $wc_mail->id == $email_id )
$wc_mail->trigger( $order->get_id() );
}
add_filter( 'woocommerce_resend_order_emails_available', 'ulmh_resend3' );
function ulmh_resend3( $order_emails ) {
$remove = array( 'new_order', 'cancelled_order', 'customer_processing_order', 'customer_completed_order', 'customer_invoice' );
$order_emails = array_diff( $order_emails, $remove );
return $order_emails;
}
Code goes in function.php file of your active child theme (or theme) or also in any plugin file.
This code is tested in WooCommerce 3+ and works fine now for on-hold order status email notifications, when resending

Categories