You are here

function uc_fedex_quote in FedEx Shipping 7.2

Same name and namespace in other branches
  1. 5 uc_fedex.module \uc_fedex_quote()
  2. 6.2 uc_fedex.module \uc_fedex_quote()
  3. 6 uc_fedex.module \uc_fedex_quote()
  4. 7 uc_fedex.module \uc_fedex_quote()

Callback for retrieving a FedEx shipping quote.

Requests a quote of all available FedEx services. Quote returned from the FedEx server is parsed and only the selected services are presented to the user.

Parameters

$products: Array of cart contents.

$details: Order details other than product information.

Return value

JSON object containing rate, error, and debugging information.

1 string reference to 'uc_fedex_quote'
uc_fedex_uc_shipping_method in ./uc_fedex.module
Implements Ubercart's hook_uc_shipping_method().

File

./uc_fedex.module, line 258
FedEx Web Services Rate / Available Services Quote.

Code

function uc_fedex_quote($products, $details, $method) {

  // The uc_quote AJAX query can fire before the customer has completely
  // filled out the destination address, so check to see whether the address
  // is complete. If not, abort.
  $destination = (object) $details;
  if (empty($destination->zone) || empty($destination->postal_code) || empty($destination->country)) {

    // Skip this shipping method.
    return array();
  }

  // Assign products to one or more packages for quoting.
  $packages = _uc_fedex_package_products($products);
  if (!count($packages)) {

    // If _uc_fedex_package_products() returned no packages,
    // then at least one item must be too heavy to ship via FedEx.
    // Skip this shipping method.
    return array();
  }

  // Create and fill object with info needed about origin.
  $origin = variable_get('uc_quote_store_default_address', new UcAddress());
  $country = db_query("SELECT * FROM {uc_countries} WHERE country_id = :id", array(
    ':id' => $origin->country,
  ));
  $country_data = $country
    ->fetchObject();
  $origin->country_iso_code_2 = $country_data->country_iso_code_2;

  // Fill $destination object with extra needed info.
  if ($origin->country == $destination->country) {

    // Try to save a DB query
    $destination->country_iso_code_2 = $origin->country_iso_code_2;
  }
  else {
    $country = db_query("SELECT * FROM {uc_countries} WHERE country_id = :id", array(
      ':id' => $destination->country,
    ));
    $country_data = $country
      ->fetchObject();
    $destination->country_iso_code_2 = $country_data->country_iso_code_2;
  }
  $debug = user_access('configure quotes') && variable_get('uc_quote_display_debug', FALSE);

  // Determine if address is Residential or Commercial.
  // If Address Validation API is not used or fails, default to store default.
  $destination->residential = uc_fedex_address_is_residential($destination, variable_get('uc_fedex_residential_quotes', 1), $debug);

  // Call the method that does the actual SOAP request to the FedEx Server.
  // Response contains all available services and rates.
  $response = uc_fedex_rate_request($packages, $origin, $destination);

  // Construct an array containing only those services that the store admin
  // has allowed in admin/store/settings/quotes/edit.
  $fedex_services = array();
  switch ($method['id']) {
    case 'fedex_ground':
      $fedex_services = array_filter(variable_get('uc_fedex_ground_services', _uc_fedex_ground_services()));
      break;
    case 'fedex':
      $fedex_services = array_filter(variable_get('uc_fedex_express_services', _uc_fedex_express_services()));
      break;
    case 'fedex_freight':
      $fedex_services = array_filter(variable_get('uc_fedex_freight_services', _uc_fedex_freight_services()));
      break;
  }

  // Initialize return array.
  $quotes = array();
  if (!isset($response->RateReplyDetails)) {

    // Memphis, we have a problem ...
    // Error returned from FedEx server - will print in $message box.
    // Don't even try to extract a quote from the response, just return
    // empty quote array.
    return $quotes;
  }

  // Test responses to see if we are interested in that service.
  foreach ($response->RateReplyDetails as $options) {
    $service = $options->ServiceType;
    if (in_array($service, $fedex_services)) {

      // Check to see if we're quoting ACCOUNT or LIST rates.
      if (variable_get('uc_fedex_quote_type', 'list') == 'list') {

        // LIST rate
        // LIST quotes return both ACCOUNT rates and LIST rates:
        // Order not guaranteed.
        //   RatedShipmentDetails[0] = PAYOR_ACCOUNT
        //   RatedShipmentDetails[1] = RATED_ACCOUNT
        //   RatedShipmentDetails[2] = PAYOR_LIST
        //   RatedShipmentDetails[3] = RATED_LIST
        foreach ($options->RatedShipmentDetails as $ratedetail) {
          if ($ratedetail->ShipmentRateDetail->RateType == 'PAYOR_LIST') {
            break;
          }
        }
      }
      else {

        // ACCOUNT rate
        // ACCOUNT quotes may return either ACCOUNT rates only OR
        // ACCOUNT rates and LIST rates. Check.
        if (is_array($options->RatedShipmentDetails)) {
          foreach ($options->RatedShipmentDetails as $ratedetail) {
            if ($ratedetail->ShipmentRateDetail->RateType == 'PAYOR_ACCOUNT') {
              break;
            }
          }
        }
        else {
          $ratedetail = $options->RatedShipmentDetails;
        }
      }

      // @todo: need to handle dimensional rates, other modifiers.
      // Markup rate before customer sees it.
      $rate = uc_fedex_rate_markup($ratedetail->ShipmentRateDetail->TotalNetCharge->Amount);
      $quotes[$service] = array(
        'rate' => $rate,
        'format' => uc_currency_format($rate),
        'option_label' => theme('uc_fedex_option_label', array(
          'service' => $method['quote']['accessorials'][$service],
          'packages' => $packages,
        )),
      );
    }
  }
  if ($debug) {

    //  $quotes['data']['debug'] = htmlentities($response).'<br />';
  }

  // Sort rate quotes in order of increasing price.
  uasort($quotes, 'uc_quote_price_sort');
  return $quotes;
}