'UPS',
'page callback' => 'drupal_get_form',
'page arguments' => array('uc_ups_admin_settings'),
'access arguments' => array('configure quotes'),
'type' => MENU_LOCAL_TASK,
'file' => 'uc_ups.admin.inc',
);
$items['admin/store/orders/%uc_order/shipments/ups'] = array(
'title' => 'UPS shipment',
'page callback' => 'drupal_get_form',
'page arguments' => array('uc_ups_confirm_shipment', 3),
'access arguments' => array('fulfill orders'),
'file' => 'uc_ups.ship.inc',
);
$items['admin/store/orders/%uc_order/shipments/labels/ups'] = array(
'page callback' => 'theme',
'page arguments' => array('uc_ups_label_image'),
'access arguments' => array('fulfill orders'),
'file' => 'uc_ups.ship.inc',
);
return $items;
}
/**
* Implements hook_cron().
*
* Deletes UPS shipping labels from the file system automatically
* on a periodic basis. Cron must be enabled for automatic deletion.
* Default is never delete the labels, keep them forever.
*/
function uc_ups_cron() {
$cutoff = REQUEST_TIME - variable_get('uc_ups_label_lifetime', 0);
if ($cutoff == REQUEST_TIME) {
// Label lifetime is set to 0, meaning never delete.
return;
}
// Loop over label files in public://ups_labels and test
// creation date against 'uc_ups_label_lifetime'.
$files = file_scan_directory('public://ups_labels', '/^label-/');
foreach ($files as $file) {
if ($cutoff > filectime($file->uri)) {
drupal_unlink($file->uri);
watchdog('uc_ups', 'Removed uc_ups label file @file.', array('@file' => $file->uri), WATCHDOG_NOTICE);
}
}
}
/**
* Implements hook_theme().
*/
function uc_ups_theme() {
return array(
'uc_ups_option_label' => array(
'variables' => array(
'service' => NULL,
'packages' => NULL,
),
'file' => 'uc_ups.theme.inc',
),
'uc_ups_confirm_shipment' => array(
'render element' => 'form',
'file' => 'uc_ups.ship.inc',
),
'uc_ups_label_image' => array(
'variables' => array(),
'file' => 'uc_ups.ship.inc',
),
);
}
/**
* Implements hook_form_alter().
*
* Adds package type to products.
*
* @see uc_product_form()
* @see uc_ups_product_alter_validate()
*/
function uc_ups_form_alter(&$form, &$form_state, $form_id) {
if (uc_product_is_product_form($form)) {
$node = $form['#node'];
$enabled = variable_get('uc_quote_enabled', array()) + array('ups' => FALSE);
$weight = variable_get('uc_quote_method_weight', array()) + array('ups' => 0);
$ups = array(
'#type' => 'fieldset',
'#title' => t('UPS product description'),
'#collapsible' => TRUE,
'#collapsed' => ($enabled['ups'] == FALSE || uc_product_get_shipping_type($node) != 'small_package'),
'#weight' => $weight['ups'],
'#tree' => TRUE,
);
$ups['pkg_type'] = array(
'#type' => 'select',
'#title' => t('Package type'),
'#options' => _uc_ups_pkg_types(),
'#default_value' => isset($node->ups['pkg_type']) ? $node->ups['pkg_type'] : variable_get('uc_ups_pkg_type', '02'),
);
$form['shipping']['ups'] = $ups;
if ($enabled['ups']) {
$form['#validate'][] = 'uc_ups_product_alter_validate';
}
}
}
/**
* Validation handler for UPS product fields.
*
* @see uc_ups_form_alter()
*/
function uc_ups_product_alter_validate($form, &$form_state) {
if (isset($form_state['values']['shippable']) && ($form_state['values']['shipping_type'] == 'small_package' || (empty($form_state['values']['shipping_type']) && variable_get('uc_store_shipping_type', 'small_package') == 'small_package'))) {
if ($form_state['values']['ups']['pkg_type'] == '02' && (empty($form_state['values']['dim_length']) || empty($form_state['values']['dim_width']) || empty($form_state['values']['dim_height']))) {
form_set_error('base][dimensions', t('Dimensions are required for custom packaging.'));
}
}
}
/**
* Implements hook_node_insert().
*/
function uc_ups_node_insert($node) {
uc_ups_node_update($node);
}
/**
* Implements hook_node_update().
*/
function uc_ups_node_update($node) {
if (uc_product_is_product($node->type)) {
if (isset($node->ups)) {
$ups_values = $node->ups;
if (empty($node->revision)) {
db_delete('uc_ups_products')
->condition('vid', $node->vid)
->execute();
}
db_insert('uc_ups_products')
->fields(array(
'vid' => $node->vid,
'nid' => $node->nid,
'pkg_type' => $ups_values['pkg_type'],
))
->execute();
}
}
}
/**
* Implements hook_node_load().
*/
function uc_ups_node_load($nodes, $types) {
$product_types = array_intersect(uc_product_types(), $types);
if (empty($product_types)) {
return;
}
$vids = array();
$shipping_type = variable_get('uc_store_shipping_type', 'small_package');
$shipping_types = db_query("SELECT id, shipping_type FROM {uc_quote_shipping_types} WHERE id_type = :type AND id IN (:ids)", array(':type' => 'product', ':ids' => array_keys($nodes)))->fetchAllKeyed();
foreach ($nodes as $nid => $node) {
if (!in_array($node->type, $product_types)) {
continue;
}
if (isset($shipping_types[$nid])) {
$node->shipping_type = $shipping_types[$nid];
}
else {
$node->shipping_type = $shipping_type;
}
if ($node->shipping_type == 'small_package') {
$vids[$nid] = $node->vid;
}
}
if ($vids) {
$result = db_query("SELECT * FROM {uc_ups_products} WHERE vid IN (:vids)", array(':vids' => $vids), array('fetch' => PDO::FETCH_ASSOC));
foreach ($result as $ups) {
$nodes[$ups['nid']]->ups = $ups;
}
}
}
/**
* Implements hook_node_delete().
*/
function uc_ups_node_delete($node) {
db_delete('uc_ups_products')
->condition('nid', $node->nid)
->execute();
}
/**
* Implements hook_node_revision_delete().
*/
function uc_ups_node_revision_delete($node) {
db_delete('uc_ups_products')
->condition('vid', $node->vid)
->execute();
}
/******************************************************************************
* Ubercart Hooks *
******************************************************************************/
/**
* Implements hook_uc_shipping_type().
*/
function uc_ups_uc_shipping_type() {
$weight = variable_get('uc_quote_type_weight', array('small_package' => 0));
$types = array();
$types['small_package'] = array(
'id' => 'small_package',
'title' => t('Small packages'),
'weight' => $weight['small_package'],
);
return $types;
}
/**
* Implements hook_uc_shipping_method().
*/
function uc_ups_uc_shipping_method() {
$methods['ups'] = array(
'id' => 'ups',
'module' => 'uc_ups',
'title' => t('UPS'),
'operations' => array(
'configure' => array(
'title' => t('configure'),
'href' => 'admin/store/settings/quotes/settings/ups',
),
),
'quote' => array(
'type' => 'small_package',
'callback' => 'uc_ups_quote',
'accessorials' => _uc_ups_service_list(),
),
'ship' => array(
'type' => 'small_package',
'callback' => 'uc_ups_fulfill_order',
'file' => 'uc_ups.ship.inc',
'pkg_types' => _uc_ups_pkg_types(),
),
'cancel' => 'uc_ups_void_shipment',
);
return $methods;
}
/**
* Implements hook_uc_store_status().
*
* Lets the administrator know that the UPS account information has not been
* filled out.
*/
function uc_ups_uc_store_status() {
$messages = array();
$access = variable_get('uc_ups_access_license', '') != '';
$account = variable_get('uc_ups_shipper_number', '') != '';
$user = variable_get('uc_ups_user_id', '') != '';
$password = variable_get('uc_ups_password', '') != '';
if ($access && $account && $user && $password) {
$messages[] = array(
'status' => 'ok',
'title' => t('UPS Online Tools'),
'desc' => t('Information needed to access UPS Online Tools has been entered.'),
);
}
else {
$messages[] = array(
'status' => 'error',
'title' => t('UPS Online Tools'),
'desc' => t('More information is needed to access UPS Online Tools. Please enter it here.', array('!url' => url('admin/store/settings/quotes/settings/ups'))),
);
}
return $messages;
}
/******************************************************************************
* Module Functions *
******************************************************************************/
/**
* Returns XML access request to be prepended to all requests to the
* UPS webservice.
*/
function uc_ups_access_request() {
$access = variable_get('uc_ups_access_license', '');
$user = variable_get('uc_ups_user_id', '');
$password = variable_get('uc_ups_password', '');
return "
$access
$user
$password
";
}
/**
* Constructs an XML quote request.
*
* @param $packages
* Array of packages received from the cart.
* @param $origin
* Delivery origin address information.
* @param $destination
* Delivery destination address information.
* @param $ups_service
* UPS service code (refers to UPS Ground, Next-Day Air, etc.).
*
* @return
* RatingServiceSelectionRequest XML document to send to UPS.
*/
function uc_ups_shipping_quote($packages, $origin, $destination, $ups_service) {
$store['name'] = uc_store_name();
$store['owner'] = variable_get('uc_store_owner', NULL);
$store['email'] = uc_store_email();
$store['email_from'] = uc_store_email();
$store['phone'] = variable_get('uc_store_phone', NULL);
$store['fax'] = variable_get('uc_store_fax', NULL);
$store['street1'] = variable_get('uc_store_street1', NULL);
$store['street2'] = variable_get('uc_store_street2', NULL);
$store['city'] = variable_get('uc_store_city', NULL);
$store['zone'] = variable_get('uc_store_zone', NULL);
$store['postal_code'] = variable_get('uc_store_postal_code', NULL);
$store['country'] = variable_get('uc_store_country', 840);
$account = variable_get('uc_ups_shipper_number', '');
$ua = explode(' ', $_SERVER['HTTP_USER_AGENT']);
$user_agent = $ua[0];
$services = _uc_ups_service_list();
$service = array('code' => $ups_service, 'description' => $services[$ups_service]);
$pkg_types = _uc_ups_pkg_types();
$shipper_zone = uc_get_zone_code($store['zone']);
$shipper_country = uc_get_country_data(array('country_id' => $store['country']));
$shipper_country = $shipper_country[0]['country_iso_code_2'];
$shipper_zip = $store['postal_code'];
$shipto_zone = uc_get_zone_code($destination->zone);
$shipto_country = uc_get_country_data(array('country_id' => $destination->country));
$shipto_country = $shipto_country[0]['country_iso_code_2'];
$shipto_zip = $destination->postal_code;
$shipfrom_zone = uc_get_zone_code($origin->zone);
$shipfrom_country = uc_get_country_data(array('country_id' => $origin->country));
$shipfrom_country = $shipfrom_country[0]['country_iso_code_2'];
$shipfrom_zip = $origin->postal_code;
$ups_units = variable_get('uc_ups_unit_system', variable_get('uc_length_unit', 'in'));
switch ($ups_units) {
case 'in':
$units = 'LBS';
$unit_name = 'Pounds';
break;
case 'cm':
$units = 'KGS';
$unit_name = 'Kilograms';
break;
}
$shipment_weight = 0;
$package_schema = '';
foreach ($packages as $package) {
// Determine length conversion factor and weight conversion factor
// for this shipment.
$length_factor = uc_length_conversion($package->length_units, variable_get('uc_ups_unit_system', variable_get('uc_length_unit', 'in')));
switch ($ups_units) {
case 'in':
$weight_factor = uc_weight_conversion($package->weight_units, 'lb');
break;
case 'cm':
$weight_factor = uc_weight_conversion($package->weight_units, 'kg');
break;
}
// Loop over quantity of packages in this shipment.
$qty = $package->qty;
for ($i = 0; $i < $qty; $i++) {
// Build XML for this package.
$package_type = array('code' => $package->pkg_type, 'description' => $pkg_types[$package->pkg_type]);
$package_schema .= "";
$package_schema .= "";
$package_schema .= "" . $package_type['code'] . "
";
$package_schema .= "";
if ($package->pkg_type == '02' && $package->length && $package->width && $package->height) {
if ($package->length < $package->width) {
list($package->length, $package->width) = array($package->width, $package->length);
}
$package_schema .= "";
$package_schema .= "";
$package_schema .= "" . strtoupper(variable_get('uc_ups_unit_system', variable_get('uc_length_unit', 'in'))) . "
";
$package_schema .= "";
$package_schema .= "" . number_format($package->length * $length_factor, 2, '.', '') . "";
$package_schema .= "" . number_format($package->width * $length_factor, 2, '.', '') . "";
$package_schema .= "" . number_format($package->height * $length_factor, 2, '.', '') . "";
$package_schema .= "";
}
$weight = max(1, $package->weight * $weight_factor);
$shipment_weight += $weight;
$package_schema .= "";
$package_schema .= "";
$package_schema .= "" . $units . "
";
$package_schema .= "" . $unit_name . "";
$package_schema .= "";
$package_schema .= "" . number_format($weight, 1, '.', '') . "";
$package_schema .= "";
$size = $package->length * $length_factor + 2 * $length_factor * ($package->width + $package->height);
if ($size > 130 && $size <= 165) {
$package_schema .= "";
}
if (variable_get('uc_ups_insurance', TRUE)) {
$package_schema .= "";
$package_schema .= "";
$package_schema .= "" . variable_get('uc_currency_code', 'USD') . "";
$package_schema .= "" . $package->price . "";
$package_schema .= "";
$package_schema .= "";
}
$package_schema .= "";
}
}
$schema = uc_ups_access_request() . "
Complex Rate Request
1.0001
Rate
rate
" . variable_get('uc_ups_pickup_type', '01') . "
" . variable_get('uc_ups_classification', '04') . "
" . variable_get('uc_ups_shipper_number', '') . "
" . $store['city'] . "
$shipper_zone
$shipper_zip
$shipper_country
$shipto_zone
$shipto_zip
$shipto_country
";
if (variable_get('uc_ups_residential_quotes', 0)) {
$schema .= "
";
}
$schema .= "
$shipfrom_zone
$shipfrom_zip
$shipfrom_country
$units
$unit_name
" . number_format($shipment_weight, 1, '.', '') . "
{$service['code']}
{$service['description']}
";
$schema .= $package_schema;
if (variable_get('uc_ups_negotiated_rates', FALSE)) {
$schema .= "
";
}
$schema .= "
";
return $schema;
}
/**
* Callback for retrieving a UPS shipping quote.
*
* Requests a quote for each enabled UPS Service. Therefore, the quote will
* take longer to display to the user for each option the customer has
* available.
*
* @param $products
* Array of cart contents.
* @param $details
* Order details other than product information.
* @param $method
* The shipping method to create the quote.
*
* @return
* JSON object containing rate, error, and debugging information.
*/
function uc_ups_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
// has all needed fields. If not, abort.
$destination = (object) $details;
if (empty($destination->zone) ||
empty($destination->postal_code) ||
empty($destination->country) ) {
// Skip this shipping method.
return array();
}
$quotes = array();
$addresses = array(variable_get('uc_quote_store_default_address', new UcAddress()));
$key = 0;
$last_key = 0;
$packages = array();
if (variable_get('uc_ups_all_in_one', TRUE) && count($products) > 1) {
foreach ($products as $product) {
if ($product->nid) {
// Packages are grouped by the address from which they will be
// shipped. We will keep track of the different addresses in an array
// and use their keys for the array of packages.
$key = NULL;
$address = uc_quote_get_default_shipping_address($product->nid);
foreach ($addresses as $index => $value) {
if ($address->isSamePhysicalLocation($value)) {
// This is an existing address.
$key = $index;
break;
}
}
if (!isset($key)) {
// This is a new address. Increment the address counter $last_key
// instead of using [] so that it can be used in $packages and
// $addresses.
$addresses[++$last_key] = $address;
$key = $last_key;
}
}
// Add this product to the last package from the found address or start
// a new package.
if (isset($packages[$key]) && count($packages[$key])) {
$package = array_pop($packages[$key]);
}
else {
$package = _uc_ups_new_package();
}
// Grab some product properties directly from the (cached) product
// data. They are not normally available here because the $product
// object is being read out of the $order object rather than from
// the database, and the $order object only carries around a limited
// number of product properties.
$temp = node_load($product->nid);
$product->length = $temp->length;
$product->width = $temp->width;
$product->height = $temp->height;
$product->length_units = $temp->length_units;
$product->ups['pkg_type'] = isset($temp->ups) ? $temp->ups['pkg_type'] : '02';
$weight = $product->weight * $product->qty * uc_weight_conversion($product->weight_units, 'lb');
$package->weight += $weight;
$package->price += $product->price * $product->qty;
$length_factor = uc_length_conversion($product->length_units, 'in');
$package->length = max($product->length * $length_factor, $package->length);
$package->width = max($product->width * $length_factor, $package->width);
$package->height = max($product->height * $length_factor, $package->height);
$packages[$key][] = $package;
}
foreach ($packages as $addr_key => $shipment) {
foreach ($shipment as $key => $package) {
if (!$package->weight) {
unset($packages[$addr_key][$key]);
continue;
}
elseif ($package->weight > 150) {
// UPS has a weight limit on packages of 150 lbs. Pretend the
// products can be divided into enough packages.
$qty = floor($package->weight / 150) + 1;
$package->qty = $qty;
$package->weight /= $qty;
$package->price /= $qty;
}
}
}
}
else {
foreach ($products as $product) {
$key = 0;
if ($product->nid) {
$address = uc_quote_get_default_shipping_address($product->nid);
if (in_array($address, $addresses)) {
// This is an existing address.
foreach ($addresses as $index => $value) {
if ($address == $value) {
$key = $index;
break;
}
}
}
else {
// This is a new address.
$addresses[++$last_key] = $address;
$key = $last_key;
}
}
if (!isset($product->pkg_qty) || !$product->pkg_qty) {
$product->pkg_qty = 1;
}
$num_of_pkgs = (int) ($product->qty / $product->pkg_qty);
// Grab some product properties directly from the (cached) product
// data. They are not normally available here because the $product
// object is being read out of the $order object rather than from
// the database, and the $order object only carries around a limited
// number of product properties.
$temp = node_load($product->nid);
$product->length = $temp->length;
$product->width = $temp->width;
$product->height = $temp->height;
$product->length_units = $temp->length_units;
$product->ups['pkg_type'] = isset($temp->ups) ? $temp->ups['pkg_type'] : '02';
if ($num_of_pkgs) {
$package = clone $product;
$package->description = $product->model;
$package->weight = $product->weight * $product->pkg_qty;
$package->price = $product->price * $product->pkg_qty;
$package->qty = $num_of_pkgs;
$package->pkg_type = $product->ups['pkg_type'];
if ($package->weight) {
$packages[$key][] = $package;
}
}
$remaining_qty = $product->qty % $product->pkg_qty;
if ($remaining_qty) {
$package = clone $product;
$package->description = $product->model;
$package->weight = $product->weight * $remaining_qty;
$package->price = $product->price * $remaining_qty;
$package->qty = 1;
$package->pkg_type = $product->ups['pkg_type'];
if ($package->weight) {
$packages[$key][] = $package;
}
}
}
}
if (!count($packages)) {
return array();
}
$dest = (object) $details;
foreach ($packages as $key => $ship_packages) {
$orig = $addresses[$key];
$orig->email = uc_store_email();
foreach (array_keys(array_filter(variable_get('uc_ups_services', array()))) as $ups_service) {
$request = uc_ups_shipping_quote($ship_packages, $orig, $dest, $ups_service);
$resp = drupal_http_request(variable_get('uc_ups_connection_address', 'https://wwwcie.ups.com/ups.app/xml/') . 'Rate', array(
'method' => 'POST',
'data' => $request,
));
if (user_access('configure quotes') && variable_get('uc_quote_display_debug', FALSE)) {
if (!isset($debug_data[$ups_service]['debug'])) {
$debug_data[$ups_service]['debug'] = '';
}
$debug_data[$ups_service]['debug'] .= htmlentities($request) . '
' . htmlentities($resp->data);
}
$response = new SimpleXMLElement($resp->data);
if (isset($response->Response->Error)) {
foreach ($response->Response->Error as $error) {
if (user_access('configure quotes') && variable_get('uc_quote_display_debug', FALSE)) {
$debug_data[$ups_service]['error'][] = (string) $error->ErrorSeverity . ' ' . (string) $error->ErrorCode . ': ' . (string) $error->ErrorDescription;
}
if (strpos((string) $error->ErrorSeverity, 'Hard') !== FALSE) {
// All or nothing quote. If some products can't be shipped by
// a certain service, no quote is given for that service. If
// that means no quotes are given at all, they'd better call in.
unset($quotes[$ups_service]['rate']);
}
}
}
// If NegotiatedRates exist, quote based on those, otherwise, use
// TotalCharges.
if (isset($response->RatedShipment)) {
$charge = $response->RatedShipment->TotalCharges;
if (isset($response->RatedShipment->NegotiatedRates)) {
$charge = $response->RatedShipment->NegotiatedRates->NetSummaryCharges->GrandTotal;
}
if (!isset($charge->CurrencyCode) || (string) $charge->CurrencyCode == variable_get('uc_currency_code', "USD")) {
// Markup rate before customer sees it.
if (!isset($quotes[$ups_service]['rate'])) {
$quotes[$ups_service]['rate'] = 0;
}
$rate = uc_ups_rate_markup((string) $charge->MonetaryValue);
$quotes[$ups_service]['rate'] += $rate;
}
}
}
}
// Sort quotes by price, lowest to highest.
uasort($quotes, 'uc_quote_price_sort');
foreach ($quotes as $key => $quote) {
if (isset($quote['rate'])) {
$quotes[$key]['rate'] = $quote['rate'];
$quotes[$key]['label'] = $method['quote']['accessorials'][$key];
$quotes[$key]['option_label'] = theme('uc_ups_option_label', array('service' => $method['quote']['accessorials'][$key], 'packages' => $packages));
}
}
// Merge debug data into $quotes. This is necessary because
// $debug_data is not sortable by a 'rate' key, so it has to be
// kept separate from the $quotes data until this point.
if (isset($debug_data)) {
foreach ($debug_data as $key => $data) {
if (isset($quotes[$key])) {
// This is debug data for successful quotes.
$quotes[$key]['debug'] = $debug_data[$key]['debug'];
if (isset($debug_data[$key]['error'])) {
$quotes[$key]['error'] = $debug_data[$key]['error'];
}
}
else {
// This is debug data for quotes that returned error responses from UPS.
$quotes[$key] = $debug_data[$key];
}
}
}
return $quotes;
}
/**
* Constructs a void shipment request.
*
* @param $shipment_number
* The UPS shipment tracking number.
* @param $tracking_numbers
* Array of tracking numbers for individual packages in the shipment.
* Optional for shipments of only one package, as they have the same tracking
* number.
*
* @return
* XML VoidShipmentRequest message.
*/
function uc_ups_void_shipment_request($shipment_number, $tracking_numbers = array()) {
$schema = uc_ups_access_request();
$schema .= '';
$schema .= '';
$schema .= '';
$schema .= 'Void';
$schema .= '';
$schema .= '';
$schema .= t('Void shipment @ship_number and tracking numbers @track_list', array('@ship_number' => $shipment_number, '@track_list' => implode(', ', $tracking_numbers)));
$schema .= '';
$schema .= '1.0';
$schema .= '';
$schema .= '';
$schema .= '';
$schema .= '' . $shipment_number . '';
foreach ($tracking_numbers as $number) {
$schema .= '' . $number . '';
}
$schema .= '';
$schema .= '';
return $schema;
}
/**
* Instructs UPS to cancel (in whole or in part) a shipment.
*
* @param $shipment_number
* The UPS shipment tracking number.
* @param $tracking_numbers
* Array of tracking numbers for individual packages in the shipment.
* Optional for shipments of only one package, as they have the same tracking
* number.
*
* @return
* TRUE if the shipment or packages were successfully voided.
*/
function uc_ups_void_shipment($shipment_number, $tracking_numbers = array()) {
$success = FALSE;
$request = uc_ups_void_shipment_request($shipment_number, $tracking_numbers);
$resp = drupal_http_request(variable_get('uc_ups_connection_address', 'https://wwwcie.ups.com/ups.app/xml/') . 'Void', array(
'method' => 'POST',
'data' => $request,
));
$response = new SimpleXMLElement($resp->data);
if (isset($response->Response)) {
if (isset($response->Response->ResponseStatusCode)) {
$success = (string) $response->Response->ResponseStatusCode;
}
if (isset($response->Response->Error)) {
foreach ($response->Response->Error as $error) {
drupal_set_message((string) $error->ErrorSeverity . ' ' . (string) $error->ErrorCode . ': ' . (string) $error->ErrorDescription, 'error');
}
}
}
if (isset($response->Status)) {
if (isset($response->Status->StatusType)) {
$success = (string) $response->Status->StatusType->Code;
}
}
return (bool) $success;
}
/**
* Modifies the rate received from UPS before displaying to the customer.
*
* @param $rate
* Shipping rate without any rate markup.
*
* @return
* Shipping rate after markup.
*/
function uc_ups_rate_markup($rate) {
$markup = trim(variable_get('uc_ups_rate_markup', '0'));
$type = variable_get('uc_ups_rate_markup_type', 'percentage');
if (is_numeric($markup)) {
switch ($type) {
case 'percentage':
return $rate + $rate * floatval($markup) / 100;
case 'multiplier':
return $rate * floatval($markup);
case 'currency':
return $rate + floatval($markup);
}
}
else {
return $rate;
}
}
/**
* Modifies the weight of shipment before sending to UPS for a quote.
*
* @param $weight
* Shipping weight without any weight markup.
*
* @return
* Shipping weight after markup.
*/
function uc_ups_weight_markup($weight) {
$markup = trim(variable_get('uc_ups_weight_markup', '0'));
$type = variable_get('uc_ups_weight_markup_type', 'percentage');
if (is_numeric($markup)) {
switch ($type) {
case 'percentage':
return $weight + $weight * floatval($markup) / 100;
case 'multiplier':
return $weight * floatval($markup);
case 'mass':
return $weight + floatval($markup);
}
}
else {
return $weight;
}
}
/**
* Convenience function to get UPS codes for their services.
*/
function _uc_ups_service_list() {
return array(
// Domestic services.
'03' => t('UPS Ground'),
'01' => t('UPS Next Day Air'),
'13' => t('UPS Next Day Air Saver'),
'14' => t('UPS Next Day Early A.M.'),
'02' => t('UPS 2nd Day Air'),
'59' => t('UPS 2nd Day Air A.M.'),
'12' => t('UPS 3 Day Select'),
// International services.
'11' => t('UPS Standard'),
'07' => t('UPS Worldwide Express'),
'08' => t('UPS Worldwide Expedited'),
'54' => t('UPS Worldwide Express Plus'),
'65' => t('UPS Worldwide Saver'),
// Poland to Poland shipments only.
//'82' => t('UPS Today Standard'),
//'83' => t('UPS Today Dedicated Courrier'),
//'84' => t('UPS Today Intercity'),
//'85' => t('UPS Today Express'),
//'86' => t('UPS Today Express Saver'),
);
}
/**
* Convenience function to get UPS codes for their package types.
*/
function _uc_ups_pkg_types() {
return array(
// Customer Supplied Page is first so it will be the default.
'02' => t('Customer Supplied Package'),
'01' => t('UPS Letter'),
'03' => t('Tube'),
'04' => t('PAK'),
'21' => t('UPS Express Box'),
'24' => t('UPS 25KG Box'),
'25' => t('UPS 10KG Box'),
'30' => t('Pallet'),
'2a' => t('Small Express Box'),
'2b' => t('Medium Express Box'),
'2c' => t('Large Express Box'),
);
}
/**
* Pseudo-constructor to set default values of a package.
*/
function _uc_ups_new_package() {
$package = new stdClass();
$package->weight = 0;
$package->price = 0;
$package->length = 0;
$package->width = 0;
$package->height = 0;
$package->length_units = 'in';
$package->weight_units = 'lb';
$package->qty = 1;
$package->pkg_type = '02';
return $package;
}