Woocommerce - The first coupon has the number 0 - for-loop

Added the ability to count codes. The problem arises when the first discount gets the number 0. How to start from number 1? Thank you for your help
First Coupon - The coupon code "obo" has been applied by a customer and x '0'
Second Coupon - Coupon code 'obo' was applied by the customer and x '1'
// For all Woocommerce versions (since 3.0)
add_action( 'woocommerce_checkout_update_order_meta', 'custom_email_for_orders_with_applied_coupon' );
function custom_email_for_orders_with_applied_coupon( $order_id ){
$order = wc_get_order( $order_id );
$used_coupons = $order->get_used_coupons();
if( ! empty($used_coupons) ){
foreach ( $used_coupons as $coupon_code ) {
$coupon = new WC_Coupon( $coupon_code ); // WC_Coupon Object
$recipient = $coupon->get_meta('email_recipient'); // get recipient
$count = $coupon->get_usage_count();
if( ! empty($recipient) ) {
$subject = sprintf( __('Coupon "%s" has been applied'), $coupon_code, $count );
$content = sprintf( __(' The coupon code "%s" has been applied by a customer and "%s" '), $coupon_code, $count );
wp_mail( $recipient, $subject, $content, $count ); // Send email
}
}
}
}
Thank you for your help...
No change has any effect, always the first used coupon is named "0" and should be named "1"

Related

Woocommerce: How to fire script after product added to cart via Ajax event

I am trying to integrate webengage to the website and trying to trigger "Added to cart" event along with the product data like(name, variation, price, quantity etc..)
Without ajax, when page refreshes after adding to cart, i am able to trigger the script as below
`
<?php
add_action('wp_footer', 'single_added_to_cart_event');
function single_added_to_cart_event()
{
if( isset($_POST['add-to-cart']) && isset($_POST['quantity']) ) :
// Get added to cart product ID (or variation ID) and quantity (if needed)
$id_to_check = isset($_POST['variation_id']) ? esc_attr($_POST['variation_id']) : esc_attr($_POST['add-to-cart']);
$product_id = isset($_POST['variation_id']) ? esc_attr($_POST['variation_id']) : esc_attr($_POST['add-to-cart']);
$variation_id = isset($_POST['variation_id']) ? esc_attr($_POST['variation_id']) : 0;
$quantity = esc_attr($_POST['quantity']);
$found_in_cart = false; // Initializing
global $woocommerce;
global $post;
$term_names_array = wp_get_post_terms($product_id, 'product_cat', array('fields' => 'names'));
$term_names_string = count($term_names_array) > 0 ? implode(', ', $term_names_array) : '';
// Check cart items to be sure that the product has been added to cart (and get product data)
foreach( WC()->cart->get_cart() as $item ) {
$product = $item['data']; // The WC_Product Object
if( $product->get_id() == $id_to_check ) {
$product_name = $product->get_name(); // Product name
$sku = $product->get_sku(); // Product sku
$type = $product->get_type(); // Product sku
$price = wc_get_price_to_display($product); // Product price for display
$stock_qty = $product->get_stock_quantity(); // Product sku
$stock_status = $product->get_stock_status(); // Product sku
$attributes = $variation_id > 0 ? json_encode($product->get_attributes()) : "''";
$found_in_cart = true;
break; // Stop the loop
}
}
if( $found_in_cart ) :
// The displayed message (example)
if ( $variation_id > 0 ) {
$message = sprintf( __('Product "%s" has been added to cart. \r\nProduct type: %s \r\nProduct price: %s \r\nProduct_id: %s \r\nVariation_id: %s \r\nQuantity: %s'),
$product_name, $type, $price, $product_id, $variation_id, $quantity );
} else {
$message = sprintf( __('Product "%s" has been added to cart. \r\nProduct type: %s \r\nProduct price: %s \r\nProduct_id: %s \r\nQuantity: %s'),
$product_name, $type, $price, $product_id, $quantity );
}
// JS code goes here below
?>
<script>
webengage.track("Added To Cart", {
"Product ID" : <?php echo $product_id; ?>,
"Price" : <?php echo $price; ?>,
"Quantity" : <?php echo $quantity; ?>,
"SKU Code": "<?php echo $sku; ?>",
"Product Name" : "<?php echo $product_name; ?>",
"Currency" : "INR",
});
</script>
<?php
endif; endif;
}
So, the site is using Ajax add to cart now. I need to fire a script whenever the product is added to cart without the page reloading. And if user navigates to another product and adds to cart, only that product needs to be added to the script event dynamically and an event should be triggered to webenage along with the product details added to cart.
Note: I have mostly variation products, so the title we push to webengaeg needs to come along with the variation name choosen.
Any help is much appreciated. Thanks!
I tried without ajax and with ajax, i am not able to trigger product data added to cart.

WooCommerce shortcode to ajaxify message that display: "You need to spend to get free shipping"

I modified this script to make a shortcode that shows how much the customer need to spend to get free shipping.
/**
* #author Rodolfo Melogli
* #compatible WooCommerce 3.9
* #donate $9 https://businessbloomer.com/bloomer-armada/
*/
add_shortcode ('woo_freeshipping_target', 'woo_freeship_target' );
function woo_freeship_target() {
ob_start();
$min_amount = 279; //change this to your free shipping threshold
$current = WC()->cart->subtotal;
if ( $current < $min_amount ) {
$added_text = wc_price( $min_amount - $current );
$notice = sprintf( $added_text );
echo '<span> You need to add '.$notice.'</span>';
}
else if ( $current >= $min_amount ) {
echo '<span>Free Shipping!</span>';
}
return ob_get_clean();
}
But I cannot figure out how can I make it to auto update when the items quantity is modified. Any idea?
To ajaxify your message so it updates when the subtotal change (via ajax) use the woocommerce_add_to_cart_fragments filter hook
So you get:
function custom_message() {
// Initialize
$message = __( 'Default message', 'woocommerce' );
// True
if ( WC()->cart ) {
// Change this to your free shipping threshold
$min_amount = 279;
// Get cart subtotal
$subtotal = WC()->cart->get_subtotal();
if ( $subtotal < $min_amount ) {
$message = sprintf( __( 'You need to add %s to get free shipping', 'woocommerce' ), wc_price( $min_amount - $subtotal ) );
} else {
$message = __( 'Free shipping', 'woocommerce' );
}
}
return $message;
}
// Refreshing on cart ajax events
function filter_woocommerce_add_to_cart_fragments( $fragments ) {
$fragments['div.display-message'] = '<div class="display-message">' . custom_message() . '</div>';
return $fragments;
}
add_filter( 'woocommerce_add_to_cart_fragments', 'filter_woocommerce_add_to_cart_fragments', 10, 1 );
// Shortcode
function display_my_message() {
return '<div class="display-message">' . custom_message() . '</div>';
}
// Register shortcode
add_shortcode( 'display_message', 'display_my_message' );
SHORTCODE USAGE
In an existing page:
[display_message]
Or in PHP:
echo do_shortcode("[display_message]");
Related: WooCommerce shortcode to ajaxify message that display: "Buy X more products to get a discount"

Magento - Mage_Core_Exception: Please select a valid payment method

I create order promatically with below code
function createSaleOrderForMagento()
{
$customer_id = $this->sale_lib->get_customer();
$items = $this->sale_lib->get_cart();
if($customer_id==-1)
{
return;
}
$cust_info = $this->Customer->get_info($customer_id);
$primaryAddress = $cust_info->getPrimaryShippingAddress();
require_once '../app/Mage.php';
Mage::init();
$websiteId = Mage::app()->getWebsite()->getId();
$store = Mage::app()->getStore();
// Start New Sales Order Quote
$storeId=$store->getId();
$quote = Mage::getModel('sales/quote')->setStoreId($storeId);
// Set Sales Order Quote Currency
$baseCurrencyCode = Mage::app()->getStore($storeId)->getBaseCurrencyCode();
$currentCurrencyCode = Mage::app()->getStore($storeId)->getCurrentCurrencyCode();
$quote->setCurrency('VND');
$customer = Mage::getModel('customer/customer')->load($customer_id);
// Assign Customer To Sales Order Quote
$quote->assignCustomer($customer);
// Configure Notification
$quote->setSendCconfirmation(0);
foreach($items as $line=>$item)
{
$product=Mage::getModel('catalog/product')->load($item['item_id']);
$quote->addProduct($product,new Varien_Object(array('qty' => 1)));
}
// Set Sales Order Billing Address
// set Billing Address
$billing = $customer->getDefaultBillingAddress();
$billingAddress = Mage::getModel('sales/order_address')
->setStoreId($storeId)
->setAddressType(Mage_Sales_Model_Quote_Address::TYPE_BILLING)
->setCustomerId($customer->getId())
->setCustomerAddressId($customer->getDefaultBilling())
->setCustomer_address_id($billing->getEntityId())
->setPrefix($billing->getPrefix())
->setFirstname($billing->getFirstname())
->setMiddlename($billing->getMiddlename())
->setLastname($billing->getLastname())
->setSuffix($billing->getSuffix())
->setCompany($billing->getCompany())
->setStreet($billing->getStreet())
->setCity($billing->getCity())
->setCountry_id($billing->getCountryId())
->setRegion($billing->getRegion())
->setRegion_id($billing->getRegionId())
->setPostcode($billing->getPostcode())
->setTelephone($billing->getTelephone())
->setFax($billing->getFax());
$quote->setBillingAddress($billingAddress);
// Set Sales Order Shipping Address
$shipping = $customer->getDefaultShippingAddress();
$shippingAddress = Mage::getModel('sales/order_address')
->setStoreId($storeId)
->setAddressType(Mage_Sales_Model_Quote_Address::TYPE_SHIPPING)
->setCustomerId($customer->getId())
->setCustomerAddressId($customer->getDefaultShipping())
->setCustomer_address_id($shipping->getEntityId())
->setPrefix($shipping->getPrefix())
->setFirstname($shipping->getFirstname())
->setMiddlename($shipping->getMiddlename())
->setLastname($shipping->getLastname())
->setSuffix($shipping->getSuffix())
->setCompany($shipping->getCompany())
->setStreet($shipping->getStreet())
->setCity($shipping->getCity())
->setCountry_id($shipping->getCountryId())
->setRegion($shipping->getRegion())
->setRegion_id($shipping->getRegionId())
->setPostcode($shipping->getPostcode())
->setTelephone($shipping->getTelephone())
->setFax($shipping->getFax())->setShippingMethod('freeshipping_freeshipping');
$quote->setShippingAddress($shippingAddress)
->setShipping_method('freeshipping_freeshipping')
->setPaymentMethod('checkmo');
$quote->save();
$quote->getShippingAddress()
->setShippingMethod('freeshipping_freeshipping')
->setCollectShippingRates(true)
->setPaymentMethod('checkmo')
->collectTotals();
$quote->save();
// Create Order From Quote
$service = Mage::getModel('sales/service_quote', $quote);
//var_dump($service);
$service->submitAll();
$increment_id = $service->getOrder()->getRealOrderId();
// Resource Clean-Up
$quote = $customer = $service = null;
// Finished
return $increment_id;
}
But I got an error :
( ! ) Fatal error: Uncaught exception 'Mage_Core_Exception' with
message 'Please select a valid payment method.' in
C:\wamp\www\pmc\app\Mage.php on line 595
( ! ) Mage_Core_Exception: Please select a valid payment method. in C:\wamp\www\pmc\app\Mage.php on line 595
Please help me to solve this problem
If you check the condition of this error outputting, you will see next:
if (!($this->getQuote()->getPayment()->getMethod())) {
Mage::throwException(Mage::helper('sales')->__('Please select a valid payment method.'));
}
Which means that you need to initialize you Mage_Sales_Model_Quote_Payment model and set there your payment method:
$quote->getPayment()->setMethod('checkmo');

Woocommerce - Cannot delete a product variation

Using WooCommerce 2.6.1
I cannot delete a product variation for a variable product: the record is still in the database after the ajax call.
It seems the ajax call doesn't go through: putting error_log(print_r('remove_variation', true)); doesn't output anything (line 387 in class-wc-ajax.php).
The action is added in the constructor of the class. The function public function remove_variation() is just not called.
Has anyone had the same issue, and found a way to make it work?
/**
* Trash a variation, don't delete it permanently.
*
* This is hooked to
* Hijack WooCommerce's WC_AJAX::remove_variation() "Delete Variation" Trash a variation if it is a subscription variation via ajax function
*/
public static function remove_variations() {
if ( isset( $_POST['variation_id'] ) ) { // removing single variation
error_log("here3");
check_ajax_referer( 'delete-variation', 'security' );
$variation_ids = array( $_POST['variation_id'] );
error_log($_POST['variation_id']);
} else { // removing multiple variations
error_log("here4");
check_ajax_referer( 'delete-variations', 'security' );
$variation_ids = (array) $_POST['variation_ids'];
}
foreach ( $variation_ids as $variation_id ) {
$variation_post = get_post( $variation_id );
error_log(print_r($variation_post, ));
if ( $variation_post && $variation_post->post_type == 'product_variation' ) {
$variation_product = get_product( $variation_id );
if ( $variation_product && $variation_product->is_type( 'subscription_variation' ) ) {
wp_trash_post( $variation_id );
}
}
}
die();
}
remove && $variation_product->is_type( 'subscription_variation' ) to solve the problem of un-deletable variations. http://support.woothemes.com/requests/162693 should provide a patch, issue has been reported.
Deleting the variation completely
This is for WooCommerece version 3+
(this code to be put in functions or a custom plugin: not Rest api)
Trashing the variation does not remove the swatch,
it just makes the swatch disabled.(which may be a litle bit embarasing)
If you don't want the variation in your product portfolio anymore, you should delete it.
If you have created your variation using recognizable string in the slug (SKU), you can use below code.
function delete_variation($product_cat="all",$Sku__search_string="",$force_delete=false,$document_it=false){
// 'posts_per_page' => -1: goes through all posts
if($product_cat=="all") {
$args = array(
'post_type' => 'product',
'posts_per_page' => -1,
);
} else {
$args = array(
'post_type' => 'product',
'posts_per_page' => -1,
'product_cat' => $product_cat
);
}
$query = new WP_Query($args);
while ( $query->have_posts() ) {
$query->the_post();
$post_id = get_the_ID();
$product = wc_get_product($post_id);
$product_id = $product->get_id(); //same as post_id
//if you want to see what you are doing put $document_it to true;
if($document_it) echo "<br>*********** $product_id ****************<br>";
if($Sku__search_string!="") {
$variations = $product->get_available_variations();
foreach($variations as $variation){
//get the SKU slug of the variation
$sku=$variation["sku"];
//get the variation id
$variation_id=$variation['variation_id'];
if($document_it) echo "varid $variation_id <br>";
//and then get the actual variation product
$var_product=wc_get_product($variation_id);
//Check if the search_string is in the slug
//You can modify this, or modify the $args above,
//if you have other criteria
if(stripos($sku,$Sku__search_string)>0){
$is_deleted=false;
//here the variation is deleted
$is_deleted=$var_product->delete($force_delete);
if($is_deleted){
if($document_it) echo "<br>Deleted: $sku";
} else {
if($document_it) echo "<br>Not deleted: $sku";
}
}
}
}
}
}
If you want to delete all variations you may use this

how to import discount coupon csv file in magento admin

I have a csv of coupon codes, i want to import it in magento.
please help me to how import it.
i have a script but its not working:-
<?php
$mageFilename = '/opt/bitnami/apps/magento/htdocs/app/Mage.php';
require_once $mageFilename;
Varien_Profiler::enable();
Mage::setIsDeveloperMode(true);
ini_set('display_errors', 1);
umask(0);
Mage::app('default');
Mage::register('isSecureArea', 1);
function getAllWbsites(){
//get all wabsites
$websites = Mage::getModel('core/website')->getCollection();
$websiteIds = array();
foreach ($websites as $website){
$websiteIds[] = $website->getId();
}
return $websiteIds;
}
//read comments for each line
function generateRule($rulename, $desc, $status, $customerGroups, $couponCode, $fromDate, $toDate, $discountType, $discountAmount){
$couponCheck = Mage::getModel('salesrule/rule')->getCollection()
->addFieldToFilter('code',$couponCode)
->load();
$couponCheckArr = $couponCheck->getData();
if(count($couponCheckArr)>0) {
return false;
}
$rule = Mage::getModel('salesrule/rule');
$rule->setName($rulename);
$rule->setDescription($desc);
$rule->setFromDate($fromDate);//starting today
if($toDate!="") {
$rule->setToDate($toDate);//if you need an expiration date
}
$rule->setCouponCode($couponCode);
$rule->setUsesPerCoupon(1);//number of allowed uses for this coupon
$rule->setUsesPerCustomer(1);//number of allowed uses for this coupon for each customer
$customerGroups = explode(',',$customerGroups);
$rule->setCustomerGroupIds($customerGroups);//if you want only certain groups replace getAllCustomerGroups() with an array of desired ids
$rule->setIsActive($status);
$rule->setStopRulesProcessing(0);//set to 1 if you want all other rules after this to not be processed
$rule->setIsRss(0);//set to 1 if you want this rule to be public in rss
$rule->setIsAdvanced(1);//have no idea what it means :)
$rule->setProductIds('');
$rule->setSortOrder(0);// order in which the rules will be applied
$rule->setSimpleAction($discountType);
//all available discount types
//by_percent - Percent of product price discount
//by_fixed - Fixed amount discount
//cart_fixed - Fixed amount discount for whole cart
//buy_x_get_y - Buy X get Y free (discount amount is Y)
$rule->setDiscountAmount($discountAmount);//the discount amount/percent. if SimpleAction is by_percent this value must be <= 100
$rule->setDiscountQty(0);//Maximum Qty Discount is Applied to
$rule->setDiscountStep(0);//used for buy_x_get_y; This is X
$rule->setSimpleFreeShipping(0);//set to 1 for Free shipping
$rule->setApplyToShipping(0);//set to 0 if you don't want the rule to be applied to shipping
$rule->setWebsiteIds(getAllWbsites());//if you want only certain websites replace getAllWbsites() with an array of desired ids
$conditions = array();
$conditions[1] = array(
'type' => 'salesrule/rule_condition_combine',
'aggregator' => 'all',
'value' => 1,
'new_child' => ''
);
$rule->setData('conditions',$conditions);
$rule->loadPost($rule->getData());
$rule->setCouponType(2);
if($rule->save()) {
return true;
}
else {
return false;
}
}
$fp = fopen('coupons-feed.csv','r') or die("can't open file");
$count = 0;
$countNotImpt = 0;
$i = 0;
while($csv_line = fgetcsv($fp,1024,"\t")) {
if($i>0) {
$OneTime = $csv_line[0];
$Name = $csv_line[1];
$AlternateCode = $csv_line[2];
$DiscountType = $csv_line[3];
$MinCartValue = $csv_line[4];
$ProductsAssigned = $csv_line[5];
$Limitedtoone = $csv_line[6];
$ExcludeProducts = $csv_line[7];
$ExpirationDate = $csv_line[8];
$DateCreated = $csv_line[9];
if(generateRule($OneTime,$Name,$AlternateCode,$DiscountType,$MinCartValue,$ProductsAssigned,$Limitedtoone,$ExcludeProducts $ExpirationDate,$DateCreated )) {
$count++;
}
else{
$countNotImpt++;
}
}
$i++;
}
fclose($fp) or die("can't close file");
echo $count.' coupon successfully added.<br>';
echo $countNotImpt.' coupon already exits.<br>';
?>
i upload this script and csv on root . but its not working. please tell me about this beacause i am new in magento.
#Brar Kirmal, you can try the below script, I created this script for one of my project you can try in your project.
$mageFilename = 'Mage.php'; // it may different as per the location of this file
require_once $mageFilename;
Varien_Profiler::enable();
Mage::setIsDeveloperMode(true);
ini_set('display_errors', 1);
umask(0);
Mage::app('default');
Mage::register('isSecureArea', 1);
function getAllWbsites(){
//get all wabsites
$websites = Mage::getModel('core/website')->getCollection();
$websiteIds = array();
foreach ($websites as $website){
$websiteIds[] = $website->getId();
}
return $websiteIds;
}
//read comments for each line
function generateRule($rulename, $desc, $status, $customerGroups, $couponCode, $fromDate, $toDate, $discountType, $discountAmount){
$couponCheck = Mage::getModel('salesrule/rule')->getCollection()
->addFieldToFilter('code',$couponCode)
->load();
$couponCheckArr = $couponCheck->getData();
if(count($couponCheckArr)>0) {
return false;
}
$rule = Mage::getModel('salesrule/rule');
$rule->setName($rulename);
$rule->setDescription($desc);
$rule->setFromDate($fromDate);//starting today
if($toDate!="") {
$rule->setToDate($toDate);//if you need an expiration date
}
$rule->setCouponCode($couponCode);
$rule->setUsesPerCoupon(1);//number of allowed uses for this coupon
$rule->setUsesPerCustomer(1);//number of allowed uses for this coupon for each customer
$customerGroups = explode(',',$customerGroups);
$rule->setCustomerGroupIds($customerGroups);//if you want only certain groups replace getAllCustomerGroups() with an array of desired ids
$rule->setIsActive($status);
$rule->setStopRulesProcessing(0);//set to 1 if you want all other rules after this to not be processed
$rule->setIsRss(0);//set to 1 if you want this rule to be public in rss
$rule->setIsAdvanced(1);//have no idea what it means :)
$rule->setProductIds('');
$rule->setSortOrder(0);// order in which the rules will be applied
$rule->setSimpleAction($discountType);
//all available discount types
//by_percent - Percent of product price discount
//by_fixed - Fixed amount discount
//cart_fixed - Fixed amount discount for whole cart
//buy_x_get_y - Buy X get Y free (discount amount is Y)
$rule->setDiscountAmount($discountAmount);//the discount amount/percent. if SimpleAction is by_percent this value must be <= 100
$rule->setDiscountQty(0);//Maximum Qty Discount is Applied to
$rule->setDiscountStep(0);//used for buy_x_get_y; This is X
$rule->setSimpleFreeShipping(0);//set to 1 for Free shipping
$rule->setApplyToShipping(0);//set to 0 if you don't want the rule to be applied to shipping
$rule->setWebsiteIds(getAllWbsites());//if you want only certain websites replace getAllWbsites() with an array of desired ids
$conditions = array();
$conditions[1] = array(
'type' => 'salesrule/rule_condition_combine',
'aggregator' => 'all',
'value' => 1,
'new_child' => ''
);
$rule->setData('conditions',$conditions);
$rule->loadPost($rule->getData());
$rule->setCouponType(2);
if($rule->save()) {
return true;
}
else {
return false;
}
}
$fp = fopen('coupon.csv','r') or die("can't open file");// replace it with your file name and location
$count = 0;
$countNotImpt = 0;
$i = 0;
while($csv_line = fgetcsv($fp,1024,"\t")) {
if($i>0) {
$rulename = $csv_line[0];
$desc = $csv_line[1];
$status = $csv_line[2];
$customerGroups = $csv_line[3];
$couponCode = $csv_line[4];
$fromDate = $csv_line[5];
$toDate = $csv_line[6];
$discountType = $csv_line[7];
$discountAmount = $csv_line[8];
if(generateRule($rulename, $desc, $status, $customerGroups, $couponCode, $fromDate, $toDate, $discountType, $discountAmount)) {
$count++;
}
else{
$countNotImpt++;
}
}
$i++;
}
fclose($fp) or die("can't close file");
echo $count.' coupon successfully added.<br>';
echo $countNotImpt.' coupon already exits.<br>';

Resources