Tried the above solutions, but they didn't quite do it. We needed to use the Special Offers module to allow free ground shipping in a particular zone on purchases above a certain amount.
We added a function to /shipping/shipping.php
PHP Code:
//rtraction njs - calculate free shipping
function func_free_shipping()
{
global $userinfo, $cart, $customer_available_offers, $sql_tbl; //rtraction njs - added for checking cart
//check offers
func_check_new_offers();
$free_shipping = false;
$min_purch = 0;
$zonenum = 0;
$zonefield = "";
$now = time();
$zonematch = false;
$ship_bonus = false;
$cart_subtotal = $cart["subtotal"];
$zonestate = $userinfo["s_country"] . "_" . $userinfo["s_state"];
foreach ($customer_available_offers as $offer_num)
{
$this_offer = func_get_offer($offer_num);
$offer_cond = func_offer_get_conditions($offer_num, "");
$offer_bonus = func_offer_get_bonuses($offer_num, "");
//check to make sure offer is active
if ($now > $this_offer["offer_start"] && $now < $this_offer["offer_end"] && $this_offer["offer_avail"] == "Y")
{
foreach ($offer_cond as $offer_item)
{
if ($offer_item["condition_type"] == "T" && $offer_item["avail"] == "Y")
{
//free shipping discount
$min_purch = $offer_item["amount_min"];
}
elseif ($offer_item["condition_type"] == "Z")
{
//rtraction njs - zone is assigned to special
if ($offer_item["params"][0]["param_id"] != "")
{
$zonenum = $offer_item["params"][0]["param_id"];
$zonefield = func_query_first_cell("SELECT field FROM $sql_tbl[zone_element] WHERE zoneid=$zonenum AND field='$zonestate'");
if ($zonefield != "")
{
$zonematch = true;
}
}
}
}
foreach ($offer_bonus as $offer_item)
{
if ($offer_item["bonus_type"] == "S" && $offer_item["avail"] == "Y")
{
//free shipping discount
$ship_bonus = true;
}
}
}
}
if ($customer_available_offers != null && $ship_bonus == true && $cart_subtotal > $min_purch && ($zonematch == true || $zonenum == 0))
{
$free_shipping = true;
}
return $free_shipping;
}
Then in our shipping module, we need to call the function and evaluate it. This project is using FedEx, but the same logic would work for others.
/shipping/mod_FEDEX_direct.php:
After:
PHP Code:
if (!empty($carrier_codes) && is_array($carrier_codes)) {
Add:
PHP Code:
$free_shipping = func_free_shipping();
After:
PHP Code:
$estimated_rate = func_array_path($parsed, $type."/ENTRY/$k/ESTIMATEDCHARGES/DISCOUNTEDCHARGES/NETCHARGE/0/#");
Add:
PHP Code:
//rtraction njs - store handling in separate variable
$handling_rate = func_array_path($parsed, $type."/ENTRY/$k/ESTIMATEDCHARGES/VARIABLEHANDLING/VARIABLEHANDLINGCHARGE/0/#");
if ($handling_rate > 0)
{
$estimated_rate = func_array_path($parsed, $type."/ENTRY/$k/ESTIMATEDCHARGES/VARIABLEHANDLING/TOTALCUSTOMERCHARGE/0/#");
}
//rtraction njs - free ground shipping on valid orders
$current_service = func_array_path($parsed, $type."/ENTRY/$k/SERVICE/0/#");
if ($current_service == "FEDEXGROUND" && $free_shipping == true)
{
if ($handling_rate > 0)
{
$estimated_rate = $handling_rate;
} else {
$estimated_rate = 0;
}
}
We found that X-Cart wasn't using the handling charge that FedEx was returning. This was added to the total shipping charge.