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
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.