Create a coupon programmatically since WooCommerce 3+ - php

I add coupons at woocommerce with this code programmatically.
if(empty($coupon_post)){
$coupon = array(
'post_title' => $coupon_code,
'post_content' => '',
'post_status' => 'publish',
'post_author' => 1,
'post_type' => 'shop_coupon'
);
$new_coupon_id = wp_insert_post( $coupon );
// 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', '' );
update_post_meta( $new_coupon_id, 'expiry_date', '' );
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, 'exclude_sale_items', 'no' );
update_post_meta( $new_coupon_id, 'free_shipping', 'no' );
update_post_meta( $new_coupon_id, 'product_categories', '' );
update_post_meta( $new_coupon_id, 'exclude_product_categories', '' );
update_post_meta( $new_coupon_id, 'minimum_amount', '' );
update_post_meta( $new_coupon_id, 'customer_email', '' );
}
But it says always the usage_limit = 1.
I add additional this code to update:
add_action( 'save_post_shop_coupon', 'my_child_after_coupon_save', 10, 3 );
function my_child_after_coupon_save( $post_id, $post, $update ) {
update_post_meta( $post_id, 'usage_limit', '');
}
But it doesn't work first.But if I open the coupon in the backend and update without any changes. The usage limit is set to unlimited.
How can trigger this, that I needn't to open all coupons.

Since WooCommerce 3, your code is a bit outdated as for example apply_before_tax is not used anymore. You should better use all available WC_Coupon setter methods, for coupon creation.
In the code below I just use the necessary setter methods (related to your code):
// Get an empty instance of the WC_Coupon Object
$coupon = new WC_Coupon();
// Set the necessary coupon data (since WC 3+)
$coupon->set_code( $coupon_code ); // (string)
// $coupon->set_description( $description ); // (string)
$coupon->set_discount_type( $discount_type ); // (string)
$coupon->set_amount( $coupon_amount ); // (float)
// $coupon->set_date_expires( $date_expires ); // (string|integer|null)
// $coupon->set_date_created( $date_created ); // (string|integer|null)
// $coupon->set_date_modified( $date_created ); // (string|integer|null)
// $coupon->set_usage_count( $usage_count ); // (integer)
$coupon->set_individual_use( true ); // (boolean)
// $coupon->set_product_ids( $product_ids ); // (array)
// $coupon->set_excluded_product_ids( $excl_product_ids ); // (array)
$coupon->set_usage_limit( 0 ); // (integer)
// $coupon->set_usage_limit_per_user( $usage_limit_per_user ); // (integer)
// $coupon->set_limit_usage_to_x_items( $limit_usage_to_x_items ); // (integer|null)
// $coupon->set_free_shipping( $free_shipping ); // (boolean) | default: false
// $coupon->set_product_categories( $product_categories ); // (array)
// $coupon->set_excluded_product_categories( $excl_product_categories ); // (array)
// $coupon->set_exclude_sale_items( $excl_sale_items ); // (boolean)
// $coupon->set_minimum_amount( $minimum_amount ); // (float)
// $coupon->set_maximum_amount( $maximum_amount ); // (float)
// $coupon->set_email_restrictions( $email_restrictions ); // (array)
// $coupon->set_used_by( $used_by ); // (array)
// $coupon->set_virtual( $is_virtual ); // (array)
// Create, publish and save coupon (data)
$coupon->save();
Now to update coupons you can use the following hooked function with any setter method like:
add_action( 'woocommerce_coupon_options_save', 'action_coupon_options_save', 10, 2 );
function action_coupon_options_save( $post_id, $coupon ) {
$coupon->set_usage_limit( 0 );
$coupon->save();
}
Code goes in functions.php file of the active child theme (or active theme).

Related

Create a WooCommerce product with the same name when a custom post type is published

I have a custom post type called Event which I want to sell through woocommerce. So what I want, when I create a Event post, it automatically creates a product under woocommerce with the same name. Is it possible?
I tried the following code found in Create a Woocommerce product when post is created
add_action( 'save_event', 'auto_create_product_from_post', 100, 2 );
function auto_create_product_from_post($id, $post){
$post_id = wp_insert_post( array(
//'post_title' => 'Adams Product',
'post_title' => $post.post_title,
'post_content' => $post.post_title,
'post_status' => 'publish',
'post_type' => "product",
) );
wp_set_object_terms( $post_id, 'simple', 'product_type' );
update_post_meta( $post_id, '_visibility', 'visible' );
update_post_meta( $post_id, '_stock_status', 'instock');
update_post_meta( $post_id, 'total_sales', '0' );
update_post_meta( $post_id, '_downloadable', 'no' );
update_post_meta( $post_id, '_virtual', 'yes' );
update_post_meta( $post_id, '_regular_price', '' );
update_post_meta( $post_id, '_sale_price', '' );
update_post_meta( $post_id, '_purchase_note', '' );
update_post_meta( $post_id, '_featured', 'no' );
update_post_meta( $post_id, '_weight', '' );
update_post_meta( $post_id, '_length', '' );
update_post_meta( $post_id, '_width', '' );
update_post_meta( $post_id, '_height', '' );
update_post_meta( $post_id, '_sku', '' );
update_post_meta( $post_id, '_product_attributes', array() );
update_post_meta( $post_id, '_sale_price_dates_from', '' );
update_post_meta( $post_id, '_sale_price_dates_to', '' );
update_post_meta( $post_id, '_price', '' );
update_post_meta( $post_id, '_sold_individually', '' );
update_post_meta( $post_id, '_manage_stock', 'no' );
update_post_meta( $post_id, '_backorders', 'no' );
update_post_meta( $post_id, '_stock', '' );
}
But the above code gives me Recoverable fatal error: Object of class WP_Post could not be converted to string error. I changed the action hook to publish_event but my website has gone in to a infinite loop and still creating a lots of products even after I removed the code.
The wrong part is $post.post_title… $post is a WP_Post object so use -> in $post->post_title, to get the post title as . is used for string concatenation in PHP.
So in your code:
$product = wp_insert_post( array(
//'post_title' => 'Adams Product',
'post_title' => $post->post_title, // <=== HERE
'post_content' => $post->post_content, // <=== Changed
'post_status' => 'publish',
'post_type' => "product",
) );
This will solve your issue.
A better way: Since WooCommerce 3, you could use CRUD Objects like:
add_action( 'save_event', 'auto_create_product_from_post', 100, 2 );
function auto_create_product_from_post($id, $post){
// Create an empty instance of the WC_Product
$product = new WC_Product_Simple(); // <=== Simple product
$product->set_name( $post->post_title );
$product->set_status( $post->post_status );
$product->set_description( $post->post_content ); // (optional)
$product->set_short_description( $post->post_excerpt ); // (optional)
// You can use any available WC_Product methods to set other properties
// see: https://docs.woocommerce.com/wc-apidocs/class-WC_Product.html
$product->save(); // Save (publish) new product
}
Code goes in functions.php file of your active child theme (or active theme). Tested and work.

Get woocommerce product ID by product name

I am working on a custom function to create a woocommerce product programmatically when user click a button on the post contact form. The below is the code i am using to create the product, but yet i am stuck to add this product to the cart via code since i can not manage to get the product id within the function code. Need your help to tell me how to get the product id to add it to the cart.
function contactform7_before_send_mail( $tour_to_product ) {
$tour_to_product = WPCF7_Submission::get_instance();
if ( $tour_to_product ) {
$formData = $tour_to_product->get_posted_data();
}
$tourprice =$formData['tour-price'];
$tourdiscountprice =$formData['tour-discount-price'];
$tourname =$formData['tour-name'];
$noadults =$formData['no-adult'];
$nochild =$formData['no-child'];
if(!empty($formData['tour-discount-price']))
{
$finalprice =$formData['tour-discount-price'];
} else {
$finalprice =$formData['tour-price'];
}
$post = array(
'post_author' => $user_id,
'post_content' => '',
'post_status' => "publish",
'post_title' => $tourname,
'post_parent' => '',
'post_type' => "product",
);
//Create post
$post_id = wp_insert_post( $post, $wp_error );
if($post_id){
global $tour_id;
$attach_id = get_post_meta($product->parent_id, "_thumbnail_id", true);
add_post_meta($post_id, '_thumbnail_id', $attach_id);
// i am trying here to get the product id
$tour_id = get_post_meta($product->id());
}
wp_set_object_terms( $post_id, 'Tours', 'product_cat' );
wp_set_object_terms( $post_id, 'simple', 'product_type');
update_post_meta( $post_id, '_visibility', 'visible' );
update_post_meta( $post_id, '_stock_status', 'instock');
update_post_meta( $post_id, 'total_sales', '0');
update_post_meta( $post_id, '_downloadable', 'no');
update_post_meta( $post_id, '_virtual', 'yes');
update_post_meta( $post_id, '_regular_price', $tourprice );
update_post_meta( $post_id, '_sale_price', $tourdiscountprice );
update_post_meta( $post_id, '_purchase_note', "" );
update_post_meta( $post_id, '_featured', "no" );
update_post_meta( $post_id, '_sku', "");
update_post_meta( $post_id, '_product_attributes', array());
update_post_meta( $post_id, '_sale_price_dates_from', "" );
update_post_meta( $post_id, '_sale_price_dates_to', "" );
update_post_meta( $post_id, '_price', $tourprice );
update_post_meta( $post_id, '_sold_individually', "" );
update_post_meta( $post_id, '_manage_stock', "no" );
update_post_meta( $post_id, '_backorders', "no" );
update_post_meta( $post_id, '_stock', "" );
// i am trying to output the product id for testing
echo "<script type='text/javascript'>alert('$tour_id')</script>";
}
remove_all_filters ('wpcf7_before_send_mail');
add_action( 'wpcf7_before_send_mail', 'contactform7_before_send_mail' );
That's right. The code line below contains the id of the last post added.
$post_id = wp_insert_post( $post, $wp_error ); //<== ID

How to use customer email address as their own coupon code in woocommerce

I am trying to use customer email address as their own coupon code with a special discount. To achieve this I tried bellow code but nothing happen shows error Call to undefined function get_currentuserinfo(). Is it possible to use coupon code virtually not saving like custom post_type?
Here is the code what I'm trying so far.
global $current_user;
get_currentuserinfo();
$user_email = $current_user->user_email ;
$coupon_code = $user_email; // Code
$amount = '10'; // Amount
$discount_type = 'fixed_cart'; // Type: fixed_cart, percent, fixed_product, percent_product
$coupon = array(
'post_title' => $coupon_code,
'post_content' => '',
'post_status' => 'publish',
'post_author' => 1,
'post_type' => 'shop_coupon'
);
$new_coupon_id = wp_insert_post( $coupon );
// 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', 'no' );
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', '' );
update_post_meta( $new_coupon_id, 'expiry_date', '' );
update_post_meta( $new_coupon_id, 'apply_before_tax', 'yes' );
update_post_meta( $new_coupon_id, 'free_shipping', 'no' );
The get_currentuserinfo() function is deprecated. Use wp_get_current_user() instead.
You should use in your code:
// (Optional) depending where you are using this code
is_user_logged_in(){
global $current_user;
// If global $current_user is not working
if(empty($current_user))
$current_user = wp_get_current_user();
// Here goes all your other code below… …
}
After that, I have never tried to set an email as coupon code slug programatically, but it should work as it's possible to set in woocommerce a coupon code with an email address (I have test it with success)…
add_action( 'user_register', 'coupon_email', 10, 1 );
function coupon_email( $user_id ) {
if ( isset( $_POST['email_address'] ) )
$coupon = array(
'post_title' => $_POST['email_address'],
'post_content' => '',
'post_status' => 'publish',
'post_author' => 1,
'post_type' => 'shop_coupon'
);
$new_coupon_id = wp_insert_post( $coupon );
}
This will add a coupon with the users email address as the title and input every time a new user registers for your website.

Check if WooCommerce Coupon already exists

I'm editing a packing slip, which is generated when the order is paid and being packed. The packing slip automatically adds a coupon which will be printed on it as well, if a product of a certain category is included.
My problem is, that every time I refresh or reopen the packing slip, a new coupon is being generated with the same coupon code. So I would like to implement a rule, that checks if the coupon_code already exists.
add_action( 'wpo_wcpdf_after_order_details', 'wpo_wcpdf_custom_text_categories', 10, 2 );
function wpo_wcpdf_custom_text_categories ($template_type, $order) {
// collect categories from order items
$order_cats = array();
$items = $order->get_items();
foreach ($items as $item_id => $item) {
$product = $order->get_product_from_item($item);
if ($product) {
$terms = get_the_terms( $product->id , 'product_cat' );
foreach ($terms as $term) {
$order_cats[$term->term_id] = $term->name;
}
}
}
$target = array('Testtragen', 'Testtragetuch');
//
// check for your category requirement
if(count(array_intersect($order_cats, $target)) > 0 && $template_type == 'packing-slip'){
$coupon_code = $order->get_order_number();
$discount_type = 'fixed_product'; // Type: fixed_cart, percent, fixed_product, percent_product
$order_date = get_post_meta( $order->id, '_wcpdf_order_date', true );
$due_date = date_i18n( get_option( 'date_format' ), strtotime( $invoice_date . ' + 60 days') );
$email = $order->billing_email;
$amount = '10'; // Amount
$discount_type = 'fixed_cart'; // Type: fixed_cart, percent, fixed_product, percent_product
$coupon = array(
'post_title' => $coupon_code,
'post_content' => '',
'post_status' => 'publish',
'post_author' => 1,
'post_type' => 'shop_coupon'
);
/*
$new_coupon_id = wp_insert_post( $coupon );
// 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', 'no' );
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', '' );
update_post_meta( $new_coupon_id, 'expiry_date', '' );
update_post_meta( $new_coupon_id, 'apply_before_tax', 'yes' );
update_post_meta( $new_coupon_id, 'free_shipping', 'no' );
*/
}
}
So I would like to add an if statement before the wp_insert_post($coupon), that all this code only gets executed if the coupon with the coupon_code doesn't already exist.
I tried : term_exists( $coupon_code, ‘coupons’)but this didn't work.
Thanks for your help!
Update (added WooCommerce 3 compatibility)
Here it is a solution creating a special meta_key for the $order->id to avoid new coupon generation with the same coupon code, when refreshing or reopening the packing slip.
Here is your changed code (with comment explanations):
add_action( 'wpo_wcpdf_after_order_details', 'wpo_wcpdf_custom_text_categories', 10, 2 );
function wpo_wcpdf_custom_text_categories ($template_type, $order) {
// collect categories from order items
$order_cats = array();
$order_id = method_exists( $order, 'get_id' ) ? $order->get_id() : $order->id;
// Loop through order items
foreach ($order->get_items() as $item_id => $item) {
$product = version_compare( WC_VERSION, '3.0', '<' ) ? $product_id = version_compare( WC_VERSION, '3.0', '<' ) ? $cart_item['data']->id : $cart_item['data']->get_id() : $item->get_product();
$product_id = method_exists( $product, 'get_id' ) ? $item->get_product_id() : $item['product_id'];
if ($product) {
$terms = get_the_terms( $product_id , 'product_cat' );
foreach ($terms as $term) {
$order_cats[$term->term_id] = $term->name;
}
}
}
$target = array('Testtragen', 'Testtragetuch');
//
// check for your category requirement
if(count(array_intersect($order_cats, $target)) > 0 && $template_type == 'packing-slip'){
$coupon_code = $order->get_order_number();
$discount_type = 'fixed_product'; // Type: fixed_cart, percent, fixed_product, percent_product
$order_date = get_post_meta( $order_id, '_wcpdf_order_date', true );
$due_date = date_i18n( get_option( 'date_format' ), strtotime( $invoice_date . ' + 60 days') );
$email = method_exists( $order, 'get_billing_email' ) ? $order->get_billing_email() : $order->billing_email;
$amount = '10'; // Amount
$discount_type = 'fixed_cart'; // Type: fixed_cart, percent, fixed_product, percent_product
$coupon = array(
'post_title' => $coupon_code,
'post_content' => '',
'post_status' => 'publish',
'post_author' => 1,
'post_type' => 'shop_coupon'
);
// ### We create a meta_key '_wcpdf_coupon' for this order with value 'no'
if( empty( get_post_meta( $order_id, '_wcpdf_coupon', true) ) ) {
add_post_meta( $order_id, '_wcpdf_coupon', 'no', true );
}
// ### if this meta_key for this order has a value = 'no' was update it to 'yes'
if( get_post_meta( $order_id, '_wcpdf_coupon', true) == 'no' ) {
// Now we update it to 'yes'. This avoid the coupon be reused for this order.
update_post_meta( $order_id, '_wcpdf_coupon', 'yes');
$new_coupon_id = wp_insert_post( $coupon );
// 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', 'no' );
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', '' );
update_post_meta( $new_coupon_id, 'expiry_date', '' );
update_post_meta( $new_coupon_id, 'apply_before_tax', 'yes' );
update_post_meta( $new_coupon_id, 'free_shipping', 'no' );
}
}
}
This should solve this issue…

Programatically create multiple coupons in WooCommerce

I've been looking for a way to add coupons in bulk to WooCommerce, it's actually a list of 800 membership numbers, that grant a discount, and coupons seem to the best way to do this.
I've found a way to add a single coupon programatically: http://docs.woothemes.com/document/create-a-coupon-programatically/ but my limited PHP knowledge doesn't seem adequate to add 800.
I'm guessing an array or somehow linking to a .csv would do it, but I'm not sure. I'd be grateful for any help.
You could create an array of 800 diferent keys and just make a foreach loop to repeat the process for each different key you have on the array like this
forehach ( $your_800_array as $coupon_code){
//the code from the page you posted
$amount = '10'; // Amount
$discount_type = 'fixed_cart'; // Type: fixed_cart, percent, fixed_product, percent_product
$coupon = array(
'post_title' => $coupon_code,
'post_content' => '',
'post_status' => 'publish',
'post_author' => 1,
'post_type' => 'shop_coupon'
);
$new_coupon_id = wp_insert_post( $coupon );
// 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', 'no' );
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', '' );
update_post_meta( $new_coupon_id, 'expiry_date', '' );
update_post_meta( $new_coupon_id, 'apply_before_tax', 'yes' );
update_post_meta( $new_coupon_id, 'free_shipping', 'no' );
}
(Used the code that OP posted inside the loop. Not actually tested)

Categories