First, I will explain as well as I can, but time does NOT allow me to support an on going thread. I do not intend to make this a full contribution with coding in the Admin area, etc. and I leave it to other members of the community to answer your questions.
Numerous times I’ve seen requests for
"Buy 4, get one free" coupon, etc. ~or~ "Free gift, with $30 purchase", etc.
The answer has always been ‘on the list for a future release’.
I wanted to do the same thing, so I tweaked the code a little to do it.
The changes consist of
1. Add one field to the coupons table.
2. Add one line within the core code of the ot_coupon file.
3. Add three functions to the ot_coupon file to use in above line.
4. Optional, tweak the popup_coupon_help main page file and the associated language file.
If at anytime, you don’t understand what I am saying or illustrating; STOP, you probably should not be making the changes.
Adding one field to the coupons table
Using phpMyAdmin, go to the coupons table. On the structure page, after the field listings, there is a section “Add new field”.
I added one new field after the coupon_type field. I put it there so I could see it when doing a browse of the table. Field order in a relational table does not matter.
The field was defined as coupon_for_free_gift / tinyint / default = 0
Coupons are created in Admin in the normal way and this field will get a ‘0’. No events will be triggered until you update this field (using phpMyAdmin) to a number larger than 0. The field is a dual purpose boolean (Y/N) field and a quantity field for the number of items that must be in the cart.
A few words on the coupon_type field
‘G’ = Gift Certificate, don’t mess with those records
‘S’ = Free Shipping coupon, don’t mess with those records
‘P’ = Percentage Off coupon, recommend you don’t mess with them, either
‘F’ = Fixed Amount coupon, best suited for this
Add one line within the core code of the ot_coupon file
Open \includes\modules\order_total\ ot_coupon.php
Insert at line 286,
just before “return $order_total;”
Code:
if ($this->is_coupon_for_free_gift() >= 1 && $this->is_free_gift_in_cart() >= $this->is_coupon_for_free_gift()) $order_total = $this->get_ot_if_free_gift();
This is the only change to the core code.
Insert at the new line 290, just after the closing brace
Code:
function is_coupon_for_free_gift() {
global $db;
if ($_SESSION['cc_id']) {
$coupon = $db->Execute("select * from " . TABLE_COUPONS . " where coupon_id = '" . $_SESSION['cc_id'] . "'");
$coupon_for_free_gift = $coupon->fields['coupon_for_free_gift'];
}
return $coupon_for_free_gift;
}
function is_free_gift_in_cart() {
global $order;
$products = $_SESSION['cart']->get_products();
$free_gift_in_cart = 0;
for ($i=0; $i<sizeof($products); $i++) {
if (is_product_valid($products[$i]['id'], $_SESSION['cc_id'])) {
$free_gift_in_cart += $products[$i]['quantity'];
}
}
return $free_gift_in_cart;
}
function get_ot_if_free_gift() {
global $order;
$products = $_SESSION['cart']->get_products();
$ot_if_free_gift = 0;
for ($i=0; $i<sizeof($products); $i++) {
$ot_if_free_gift += $products[$i]['final_price'] * $products[$i]['quantity'];
}
return $ot_if_free_gift;
}
The functions do the following,
is_coupon_for_free_gift()
Returns the contents of the new field that was added to the coupons table.
is_free_gift_in_cart()
Adds up the quantities of the allowed products in the cart.
get_ot_if_free_gift()
Adds up the order amount of all the products in the cart.
Putting it all together,
The core function get_order_total() adds up the value of the allowed items in the cart and the other ZenCart functions then use that information as part of the verification / calculation process.
We jump in at the last moment and ask on line 286,
do we intend that this coupon be for a free gift (qty is 1, or more)
and
have they put in the cart at least as many as we said they had to
if so,
use the total amount of the order, instead of just the value of the allowed items
Examples:
You want a coupon for a free $5 catalog, with $50 purchase.
The catalog would have to have a product code.
The coupon would be set up in normal way, single use, unlimited use, $50 minimum, etc., etc., with the catalog as the allowed product.
Using phpMyAdmin, put a 1 in the “coupon_for_free_gift” field for that coupon.
During processing, ZenCart will check if the coupon is for a free gift. If not, it finishes the original script. If it is for a free gift, it checks if the gift is in the cart and if the total of the invoice meets the minimum and, if so, gives the credit you offered. In this case, a $50 order, with a catalog in the cart, will get a $5 credit.
You want to give a “Buy 4, get one FREE” coupon.
Set everything up in Admin the way you normally would.
Using phpMyAdmin, put a 4 in the “coupon_for_free_gift” field for that coupon.
ZenCart will check if the 4 allowed items are in the cart and issue the credit you set up, if the order meets the minimum total, if any.
You could allow a mix of different items, but the current code does not check if they bought one of each or all of one item. You naturally must be sure that the offer makes sense to you.
You could apply a value to a ‘P’ type, but the % discount would be applied to the entire order and NOT just the allowed items. This could have DRAMATIC unintended results. Suggest you stick with the Fixed amount Gift Coupons.
That’s it. I wouldn’t bother doing a full contribution for a little snippet of code like this. The developers have promised to add this feature and I sure will have all the bells and whistles.
This is just to hold you over, till then.
Enjoy,
Juxi
Beautifying the results:
First, I’m lazy and don’t like to make up new CSS tags for every situation. So, I have some generic ones that I use and don’t want to be bothered with seeing which tag should be used.
Examples are
Code:
.red { color: red; }
.underline { text-decoration: underline; }
.italic { font-style: italic; }
.bold { font-weight: bold; }
This way I can just <span class=”red bold”> and not bother with finding the correct or best tag. I know I am hard coding the look of the text, but in some cases it is the best or only way to get the job done. Like in a DEFINE, where you don’t always know the final tag that will be applied. I will use one of these tags to help spruce things up.
1. Add a little color to the check-out page, to highlight the coupon code.
\includes\modules\order_total\ ot_coupon.php (the file we have been working with)
Code:
line 60, change to
$this->output[] = array('title' => $this->title . ': <span class="red">' . $this->coupon_code . '</span> :',
2. Change the “Coupon: more info” popup help to take advantage of the new available information.
\includes\languages\english\your_template_name \ popup_coupon_help.php
Code:
change
define('TEXT_COUPON_HELP_MINORDER', '<br /><br />To use this coupon, your order must be %s or more ');
add
define('TEXT_COUPON_HELP_MINQTY', 'and include at least %s of the items listed below.');
define('TEXT_COUPON_HELP_CODE', '<br /><br />Coupon Code : <span class="red">%s</span>');
\includes\templates\ your_template_name\popup_coupon_help\ tpl_main_page.php
Code:
line 32, after
$text_coupon_help = TEXT_COUPON_HELP_HEADER;
add
$text_coupon_help .= sprintf(TEXT_COUPON_HELP_CODE, $coupon->fields['coupon_code']);
new line 49, after
if ($coupon->fields['coupon_minimum_order'] > 0 ) ...
add
if ($coupon->fields['coupon_for_free_gift'] > 0 ) $text_coupon_help .= sprintf(TEXT_COUPON_HELP_MINQTY, ($coupon->fields['coupon_for_free_gift']));