I believe that if it is implemented correctly, then it's not such a horrible way of treating customers. One must make sure that when using a discount coupon, the final price is at least less than the final price of the free shipping order. Lets face it, offering free shipping etc. is just another form of discount. The wish to offer a coupon code is a form of marketing, but if you are offering free shipping, you might find that offering a meaningful discount value might be just to much discount to handle. This is definitely the case with my store. I believe that I have found a solution but this does require code changes.
First the theory behind the change. I use the zone table to calculate shipping and if a coupon is entered, I wanted to override this table with some other value. (I use all three zone definitions) so the first thing that I did was to add an extra values in the 'Zone 1, 2 and 3 Shipping Table' under the admin console ie.
*Zone 1 Shipping Table
100.00:6.50:6.75,200.00:0.00:6.75,300.00:0.00:9.75,400.00:0.00:11.00,10000.00:0.00:12.75
Zone 2 Shipping Table
100.00:15.00:18.50,200.00:13.00:18.50,300.00:11.00:22.50,400.00:9.00:23.50,500.00:0.00:18.50,10000.00:0.00:22.50
Zone 3 Shipping Table
100.00:25.00:26.50,200.00:17.50:20.00,300.00:10.00:17.50,400.00:5.00:15.00,10000.00:0.00:00.00
*
The price less than or equal to 100 would cost 6.50 without a coupon and 6.75 with a coupon for Zone 1 destinations. Thus instead of 2 values per record, there are 3.
Now edit includes/modules/shipping/zones.php at the following 5 places;
Near line 144
$zones_table = split("[:,]" , $zones_cost);
to
$zones_table = split("[::,]" , $zones_cost);
Near line 147
for ($i=0; $i<$size; $i+=2) {
to
for ($i=0; $i<$size; $i+=3) {
Near line 151
$shipping = $zones_table[$i+1];
to
$shipping = ($order->info['coupon_code'] != '')? $zones_table[$i+2] : $zones_table[$i+1];
Near line 177
$shipping = $zones_table[$i+1];
to
$shipping = ($order->info['coupon_code'] != '')? $zones_table[$i+2] : $zones_table[$i+1];
Near line 186
$shipping = $zones_table[$i+1];
to
$shipping = ($order->info['coupon_code'] != '')? $zones_table[$i+2] : $zones_table[$i+1];
This means that whenever a coupon code is entered, the shipping will be adjusted to the second value, but here is the first problem that I had, the coupon code is entered on the page after selecting shipping. Ok, so wherever a coupon code is entered or removed, the user needs to be taken back to the 'shipping method' page and told to note the new shipping cost. This actually makes sense because some users might not notice the shipping cost changes if you took them directly to the third step and might later state that your site made an error in calculating the shipping costs.
You now need to change includes/modules/order_total/ot_coupon.php at 2 places. (This code takes the user back to the first step)
Near line 102
unset($_SESSION['cc_id']);
$messageStack->add_session('checkout_payment', TEXT_REMOVE_REDEEM_COUPON, 'caution');
to
unset($_SESSION['cc_id']);
zen_redirect(zen_href_link(FILENAME_CHECKOUT_SHIPPING, 'credit_class_error_code=123&credit_class_error='.TEXT_REMOVE_REDEEM_COUPON, 'SSL',true, false));
Near line 220
$messageStack->add_session('checkout', TEXT_VALID_COUPON,'success');
to
zen_redirect(zen_href_link(FILENAME_CHECKOUT_SHIPPING, 'credit_class_error_code=124&credit_class_error='.TEXT_VALID_COUPON, 'SSL',true, false));
Insert the following code near the top of includes/templates/{YOUR TEMPLATE NAME}/templates/tpl_checkout_shipping_default.php (For example, the line after '<div class="centerColumn" id="checkoutShipping">')
<?php if ($_GET['credit_class_error_code'] == 123 || $_GET['credit_class_error_code'] == 124) {?>
<div class="messageStackSuccess">
<?php echo zen_image($template->get_template_dir(ICON_IMAGE_SUCCESS, DIR_WS_TEMPLATE, $current_page_base,'images/icons'). '/' . ICON_IMAGE_SUCCESS, ICON_SUCCESS_ALT); echo zen_output_string_protected($_GET['credit_class_error']); ?></div><br />
<div class="messageStackError">
<?php echo TEXT_RECHECK_SHIPPING; ?></div>
<?php } ?>
Now for the final change, add the following line in includes/languages/english.php (and any other language files in the same folder)
define('TEXT_RECHECK_SHIPPING', 'Please recheck shipping as rates may have changed');