Woocommerce coupon code for personalized customer - php

I have generated coupon code dynamically for each customer when they purchasing a product from the website and i have set certain conditions.
When I have dynamically created a coupon code, it stored in woocommerce > coupons section.
function couponCodeGeneration($order_id, $i){
// Get the order ID
$coupon_code = $order_id."".$i; // Coupon Code
$amount = '100%'; // Amount
$discount_type = 'percent'; // Type: fixed_cart, percent, fixed_product, percent_product
wp_coupon_exist( $coupon_code );
if( wp_coupon_exist( $coupon_code ) ) {
//coupon code exists.
} else {
//coupon code not exists, so inserting coupon code
$coupon = array(
'post_title' => $coupon_code,
'post_content' => '',
'post_status' => 'publish',
'post_author' => 1,
'post_type' => 'shop_coupon'
//'post_category' => array(1)
);
$new_coupon_id = wp_insert_post( $coupon );
//SET THE PRODUCT CATEGORIES
wp_set_object_terms($post_id, 'Holiday Season offers', 'product_cat');
// Add meta
update_post_meta( $new_coupon_id, 'discount_type', $discount_type );
update_post_meta( $new_coupon_id, 'coupon_amount', $amount );
update_post_meta( $new_coupon_id, 'individual_use', 'yes' );
update_post_meta( $new_coupon_id, 'product_ids', '' );
update_post_meta( $new_coupon_id, 'exclude_product_ids', '' );
update_post_meta( $new_coupon_id, 'usage_limit', '1' );
update_post_meta( $new_coupon_id, 'expiry_date', '2019-07-31' );
update_post_meta( $new_coupon_id, 'apply_before_tax', 'yes' );
update_post_meta( $new_coupon_id, 'free_shipping', 'no' );
update_post_meta( $new_coupon_id, 'limit_usage_to_x_items', '1' );
update_post_meta( $new_coupon_id, 'usage_limit_per_user', '1' );
update_post_meta( $post_id, 'times', '1' );
echo '<div class="couponCode"><strong>Your Coupon Code for your next purchase - '.$coupon_code.'</strong><hr></div>';
}
}
I need help in the following situation.
The generated coupon code should not be used by another customer. The coupon only personal to that customer. Coupon code cannot be transferred.
When customer placing an order, the generated coupon code not stored in admin orders page. How do I know which coupon code is generated by which customer.
Can someone give me a suggestions.

Since Woocommerce 3 your code is really outdated, with a lot of mistakes. wp_coupon_exist() function doesn't exist.
To restrict the coupon to a specific customer, you can use Email restrictions WC_Coupon method that will also allow you to know which customer has generated the coupon code.
You could also set a some custom meta data if needed saving the user ID or the user complete name.
So there is two functions in my code:
The first one that checks if the coupon code doesn't exist
The second one that generate the coupon code as you planned.
The code:
// Utility function that check if coupon exist
function does_coupon_exist( $coupon_code ) {
global $wpdb;
$value = $wpdb->get_var( "
SELECT ID
FROM {$wpdb->prefix}posts
WHERE post_type = 'shop_coupon'
AND post_name = '".strtolower($coupon_code)."'
AND post_status = 'publish';
");
return $value > 0 ? true : false;
}
function coupon_code_generation( $order_id, $i ){
$coupon_code = $order_id."".$i; // Coupon Code
// Check that coupon code not exists
if( ! does_coupon_exist( $coupon_code ) ) {
// Get a new instance of the WC_Coupon object
$coupon = new WC_Coupon();
// Get the instance of the WC_Order object
$order = wc_get_order( $order_id );
## --- Coupon settings --- ##
$discount_type = 'percent'; // Type
$coupon_amount = '100'; // Amount
$customer_email = array( $order->get_billing_email() ); // Customer billing email
$product_categories_names = array('Holiday Season offers');
$date_expires = '2019-07-31';
// Convert to term IDs
$term_ids = array();
foreach( $product_categories_names as $term_name ) {
if ( term_exists( $term_name, 'product_cat' ) )
$term_ids[] = get_term_by( 'name', $term_name, 'product_cat' )->term_id;
}
## --- Coupon settings --- ##
// Set the necessary coupon data
$coupon->set_code( $coupon_code );
$coupon->set_discount_type( 'percent' );
$coupon->set_amount( 100 );
if( is_array($term_ids) && sizeof($term_ids) > 0 )
$coupon->set_product_categories( $term_ids );
$coupon->set_email_restrictions( $customer_email );
$coupon->set_individual_use( true );
$coupon->set_usage_limit( 1 );
$coupon->set_usage_limit_per_user( 1 );
$coupon->set_limit_usage_to_x_items( 1 );
$coupon->set_date_expires( date( "Y-m-d H:i:s", strtotime($date_expires) ) );
// Save the data
$post_id = $coupon->save();
}
echo isset($post_id) && $post_id > 0 ? sprintf(
'<div class="couponCode"><strong>%s <code>%s</code></strong>.<hr></div>',
__("Your Coupon Code for your next purchase is", "woocommerce"), $coupon_code
) : __("Sorry, a coupon code already exist.", "woocommerce");
}
Code goes in function.php file of your active child theme (or active theme). tested and works.
You will get an output something like (when the coupon is generated):
Your Coupon Code for your next purchase is 1198A
Or if coupon exist:
Sorry, a coupon code already exist.

I have fixed my issue.
Add the following code in functions.php
add_filter( 'woocommerce_coupon_is_valid', 'wc_riotxoa_coupon_is_valid', 20, 2 );
if ( ! function_exists( 'wc_riotxoa_coupon_is_valid' ) ) {
function wc_riotxoa_coupon_is_valid( $result, $coupon ) {
$user = wp_get_current_user();
$restricted_emails = $coupon->get_email_restrictions();
return ( in_array( $user->user_email, $restricted_emails ) ? $result : false );
}
}
Ref: https://gist.github.com/riotxoa/f4f1a895052c195394ba4841085a0e83

Related

Process custom bulk action on admin Orders list in Woocommerce

I have added a custom action in my woocommerce orders page like shown below, and I also have a custom order field "number of meals". Now what I want is when I select the orders in bulk and use that custom action then count of number of meals should get decreased by 1.
For example if order id 1 & 2 had 15 & 12 number of meals respectively then after using the action it should become 14 & 11…
The screenshot of my orders page, the custom hook and the custom order field I created:
My code:
add_filter( 'bulk_actions-edit-shop_order', 'decrease_number_of_meals_by_1' );
function decrease_number_of_meals_by_1( $bulk_actions ) {
$bulk_actions['decrease_number_of_meals'] = 'Decrease Number of Meals by 1';
return $bulk_actions;
}
add_action( 'admin_action_decrease_number_of_meals', 'fire_my_hook' );
function fire_my_hook() {
if( !isset( $_REQUEST['post'] ) && !is_array( $_REQUEST['post'] ) )
return;
foreach( $_REQUEST['post'] as $order_id ) {
$order = new WC_Order( $order_id );
$no_of_meals = $order->get_post_meta( $order_id, '_wc_acof_{3}', true );
}
}
I am stuck here and have no idea on how to do it further.
Please guide me on how can I achieve this.
You are not using the right way and hooks. Also the right custom field meta key should be _wc_acof_3 when using WooCommerce Admin Custom Order Fields plugin.
So try the following instead:
// Add a bulk action to Orders bulk actions dropdown
add_filter( 'bulk_actions-edit-shop_order', 'decrease_meals_orders_bulk_actions' );
function decrease_meals_orders_bulk_actions( $bulk_actions ) {
$bulk_actions['decrease_meals'] = 'Decrease Number of Meals by 1';
return $bulk_actions;
}
// Process the bulk action from selected orders
add_filter( 'handle_bulk_actions-edit-shop_order', 'decrease_meals_bulk_action_edit_shop_order', 10, 3 );
function decrease_meals_bulk_action_edit_shop_order( $redirect_to, $action, $post_ids ) {
if ( $action === 'decrease_meals' ){
$processed_ids = array(); // Initializing
foreach ( $post_ids as $post_id ) {
// Get number of meals
$nb_meal = (int) get_post_meta( $post_id, '_wc_acof_3', true );
// Save the decreased number of meals ($meals - 1)
update_post_meta( $post_id, '_wc_acof_3', $nb_meal - 1 );
$processed_ids[] = $post_id; // Adding processed order IDs to an array
}
// Adding the right query vars to the returned URL
$redirect_to = add_query_arg( array(
'decrease_meals' => '1',
'processed_count' => count( $processed_ids ),
'processed_ids' => implode( ',', $processed_ids ),
), $redirect_to );
}
return $redirect_to;
}
// Display the results notice from bulk action on orders
add_action( 'admin_notices', 'decrease_meals_bulk_action_admin_notice' );
function decrease_meals_bulk_action_admin_notice() {
global $pagenow;
if ( 'edit.php' === $pagenow && isset($_GET['post_type'])
&& 'shop_order' === $_GET['post_type'] && isset($_GET['decrease_meals']) {
$count = intval( $_REQUEST['processed_count'] );
printf( '<div class="notice notice-success fade is-dismissible"><p>' .
_n( 'Decreased meals for %s Order.',
'Decreased meals for %s Orders.',
$count,
'woocommerce'
) . '</p></div>', $count );
}
Code goes in function.php file of your active child theme (or active theme). Tested and works.

Add custom field as an order note in Woocommerce

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 );
}
}

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.

Exclude product from all coupons in WooCommerce

I have searched all over the internet, but it doesn't seem to be any answer anywhere in spite of countless people asking the question.
Is there any way to exclude a specific product from ALL coupons?
I understand that you can do it on coupon level, but this is rather messy especially as a lot of people have automatic coupons, several people creating coupons etc…
TLDR: Any way to make a product excluded from all coupons at Product level.
Here is a nice way to automate this process.
1) We add a custom checkbox in product general settings metabox to disable the coupon functionality for the current product. So you will get this in Backend Edit Product pages:
All selected products will be saved in an array and will be used in the following…
2) This selected products will be excluded from coupon discount at product level and the product discount amount will be set to zero.
The code:
// Create and display the custom field in product general setting tab
add_action( 'woocommerce_product_options_general_product_data', 'add_custom_field_general_product_fields' );
function add_custom_field_general_product_fields(){
global $post;
echo '<div class="product_custom_field">';
// Custom Product Checkbox Field
woocommerce_wp_checkbox( array(
'id' => '_disabled_for_coupons',
'label' => __('Disabled for coupons', 'woocommerce'),
'description' => __('Disable this products from coupon discounts', 'woocommerce'),
'desc_tip' => 'true',
) );
echo '</div>';;
}
// Save the custom field and update all excluded product Ids in option WP settings
add_action( 'woocommerce_process_product_meta', 'save_custom_field_general_product_fields', 10, 1 );
function save_custom_field_general_product_fields( $post_id ){
$current_disabled = isset( $_POST['_disabled_for_coupons'] ) ? 'yes' : 'no';
$disabled_products = get_option( '_products_disabled_for_coupons' );
if( empty($disabled_products) ) {
if( $current_disabled == 'yes' )
$disabled_products = array( $post_id );
} else {
if( $current_disabled == 'yes' ) {
$disabled_products[] = $post_id;
$disabled_products = array_unique( $disabled_products );
} else {
if ( ( $key = array_search( $post_id, $disabled_products ) ) !== false )
unset( $disabled_products[$key] );
}
}
update_post_meta( $post_id, '_disabled_for_coupons', $current_disabled );
update_option( '_products_disabled_for_coupons', $disabled_products );
}
// Make coupons invalid at product level
add_filter('woocommerce_coupon_is_valid_for_product', 'set_coupon_validity_for_excluded_products', 12, 4);
function set_coupon_validity_for_excluded_products($valid, $product, $coupon, $values ){
if( ! count(get_option( '_products_disabled_for_coupons' )) > 0 ) return $valid;
$disabled_products = get_option( '_products_disabled_for_coupons' );
if( in_array( $product->get_id(), $disabled_products ) )
$valid = false;
return $valid;
}
// Set the product discount amount to zero
add_filter( 'woocommerce_coupon_get_discount_amount', 'zero_discount_for_excluded_products', 12, 5 );
function zero_discount_for_excluded_products($discount, $discounting_amount, $cart_item, $single, $coupon ){
if( ! count(get_option( '_products_disabled_for_coupons' )) > 0 ) return $discount;
$disabled_products = get_option( '_products_disabled_for_coupons' );
if( in_array( $cart_item['product_id'], $disabled_products ) )
$discount = 0;
return $discount;
}
Code goes in function.php file of your active child theme (or active theme) or in any plugin file.
Tested and perfectly works

Update all variations prices of a variable product in Woocommerce

I need to get all variation id and update price in loop.
Simple query and loop looks like:
$params = array(
‘posts_per_page’ => -1,
‘post_type’ => ‘product_variation’,
‘post_parent’ => $product->get_id() // tried $post-ID
);
$variations = get_posts( $params );
foreach ( $variations as $variation ) {
$variation_ID = $variation->ID; // tried $post-ID, $product->get_id()
$regular_price=34;
update_post_meta( $variation_ID, ‘_regular_price’, (float)$regular_price );
update_post_meta( $variation_ID, ‘_price’, (float)$regular_price );
}
This doesn't seem to work:
(‘post_parent’ => $product->get_id())
Neither does this:
($variation_ID = $variation->ID;).
First in your code ‘ or ’ should be replaced by '.
Also if used $post-ID should be replaced by $post->ID
Depending on where and how you are using this code, you should try to include global $post; first to be able to use the WP_Post object $post.
Then you could try to use this customized version of your code instead:
global $post;
$regular_price = 13;
// Only for product post type
if( $post->post_type == 'product' )
$product = wc_get_product( $post->ID ); // An instance of the WC_Product object
// Only for variable products
if( $product->is_type('variable') ){
foreach( $product->get_available_variations() as $variation_values ){
$variation_id = $variation_values['variation_id']; // variation id
// Updating active price and regular price
update_post_meta( $variation_id, '_regular_price', $regular_price );
update_post_meta( $variation_id, '_price', $regular_price );
wc_delete_product_transients( $variation_id ); // Clear/refresh the variation cache
}
// Clear/refresh the variable product cache
wc_delete_product_transients( $post->ID );
}
This code is tested on WooCommerce version 3+ and works

Categories