Jump to content
torinwalker

New UPS XML Shipping Module available

Recommended Posts

I was thinking of using it further down, around line 900.
OK, I didn't understand you well. That is even simpler:

	function _upsGetTimeServices() {

   if ( date("m") == "02" || ((date("m") == "03") && (date("j") < 5)) ) {
	 $shipdate = '20060306';				
	   } elseif (defined('SHIPPING_DAYS_DELAY')) {
		 $shipdate = date("Ymd", time()+(86400*SHIPPING_DAYS_DELAY));
   } else {
		 $shipdate = $this->today;
   }

Share this post


Link to post
Share on other sites
OK, I didn't understand you well. That is even simpler:

	function _upsGetTimeServices() {

   if ( date("m") == "02" || ((date("m") == "03") && (date("j") < 5)) ) {
	 $shipdate = '20060306';				
	   } elseif (defined('SHIPPING_DAYS_DELAY')) {
		 $shipdate = date("Ymd", time()+(86400*SHIPPING_DAYS_DELAY));
   } else {
		 $shipdate = $this->today;
   }

 

That did it! Thanks!


Do, or do not. There is no try.

 

Order Editor 5.0.6 "Ultra Violet" is now available!

For support or to post comments, suggestions, etc, please visit the Order Editor support thread.

Share this post


Link to post
Share on other sites

Jan! My parade of bizarre questions continues!

 

In a different module, a modified 1.2.2, I have this, along with a bunch of other stuff, in my SHIPPING_DAYS_DELAY code:

 

 elseif ($day_of_the_week == "4") { // order supposed to leave on Thursday => Monday
			$shipdate = date("Ymd", time()+(86400*constant('MODULE_SHIPPING_UPSXML_DAYS_DELAY_' . $vendors_id)) + 345600);

		 }

 

But I want to modify this so that it won't apply if the service being quoted is Next Day Air (ie Next Day Air can ship on Thursday but other methods can not).

 

Something along the lines of

elseif (($day_of_the_week == "4") && ($this->servicesType != ['Next Day Air'])){

 

would work, theoretically, but I just made up the "($this->servicesType != ['Next Day Air'])" part, almost totally at random.

 

What do you think?


Do, or do not. There is no try.

 

Order Editor 5.0.6 "Ultra Violet" is now available!

For support or to post comments, suggestions, etc, please visit the Order Editor support thread.

Share this post


Link to post
Share on other sites
I want to modify this so that it won't apply if the service being quoted is Next Day Air (ie Next Day Air can ship on Thursday but other methods can not).
That won't fly I'm afraid. When shipdate is being set, the first UPS query (to the gettimes thing) still needs to be done. So the whole service thing is not set yet.

 

With what you want to do is to look at the day of the week, if today is a Thursday do the time query, set apart the Next Day Air and do another query of the UPS server with the shipdate later. The first time you don't need the "shop" mode for the query, but only the one for a specific rate, the Next Day Air one. Doesn't make much sense for you I guess, but I have the developer info here.

Share this post


Link to post
Share on other sites
That won't fly I'm afraid. When shipdate is being set, the first UPS query (to the gettimes thing) still needs to be done. So the whole service thing is not set yet.

 

With what you want to do is to look at the day of the week, if today is a Thursday do the time query, set apart the Next Day Air and do another query of the UPS server with the shipdate later. The first time you don't need the "shop" mode for the query, but only the one for a specific rate, the Next Day Air one. Doesn't make much sense for you I guess, but I have the developer info here.

 

Interesting. I'm not sure I "get" how to accomplish this, but it sounds fun.

 

It would need to be set up to do two separate queries for shipdate, first just for Next Day Air and then later for the other methods?


Do, or do not. There is no try.

 

Order Editor 5.0.6 "Ultra Violet" is now available!

For support or to post comments, suggestions, etc, please visit the Order Editor support thread.

Share this post


Link to post
Share on other sites
Interesting. I'm not sure I "get" how to accomplish this, but it sounds fun.

 

It would need to be set up to do two separate queries for shipdate, first just for Next Day Air and then later for the other methods?

Yes, but only if it is a Thursday. This will take quite a bit of time I'm afraid. In 1.2 at around line 300 you will find:

$this->servicesTimeintransit = $this->_upsGetTimeServices();

My approach would be to add the logic for a Thursday around there (because you then need two queries) and change it to have a variable for the Next Day Air query:

$this->servicesTimeintransit = $this->_upsGetTimeServices(date("Ymd"));

Then change the function _upsGetTimeServices(); to

function _upsGetTimeServices($shipdate = '') {
if (empty($shipdate)) {
existing code
}

Then the tough part comes: getting the Next Day Air quote out from the "Thursday query", do the second one and insert the Next Day Air one from the first query into the results of the second...

Share this post


Link to post
Share on other sites
Yes, but only if it is a Thursday. This will take quite a bit of time I'm afraid. In 1.2 at around line 300 you will find:

$this->servicesTimeintransit = $this->_upsGetTimeServices();

My approach would be to add the logic for a Thursday around there (because you then need two queries) and change it to have a variable for the Next Day Air query:

$this->servicesTimeintransit = $this->_upsGetTimeServices(date("Ymd"));

Then change the function _upsGetTimeServices(); to

function _upsGetTimeServices($shipdate = '') {
if (empty($shipdate)) {
existing code
}

Then the tough part comes: getting the Next Day Air quote out from the "Thursday query", do the second one and insert the Next Day Air one from the first query into the results of the second...

 

Hmmmm.... I might laze out on this one and just put a little note about Next Day Air on the shipping page. This is a lot of modification for a service type hardly anyone ever uses.

 

Cheers

Stew


Do, or do not. There is no try.

 

Order Editor 5.0.6 "Ultra Violet" is now available!

For support or to post comments, suggestions, etc, please visit the Order Editor support thread.

Share this post


Link to post
Share on other sites

I just wanted to drop in and say that I really like the UPSXML module. There are so many crazy things that you can do with it.

 

Many thanks to all who have contributed to this module, both standard and MVS versions.


Do, or do not. There is no try.

 

Order Editor 5.0.6 "Ultra Violet" is now available!

For support or to post comments, suggestions, etc, please visit the Order Editor support thread.

Share this post


Link to post
Share on other sites
That won't fly I'm afraid. When shipdate is being set, the first UPS query (to the gettimes thing) still needs to be done. So the whole service thing is not set yet.

 

With what you want to do is to look at the day of the week, if today is a Thursday do the time query, set apart the Next Day Air and do another query of the UPS server with the shipdate later. The first time you don't need the "shop" mode for the query, but only the one for a specific rate, the Next Day Air one. Doesn't make much sense for you I guess, but I have the developer info here.

 

I've thought of a different way of accomplishing this- by having a second UPSXML module that only quotes for Next Day Air and doesn't have the restriction on shipping on Thursday (I'm really nuking this out :)).

 

Question: how can I modify the module so that it doesn't display the line that the module title and icon usually appear on? I've gotten to the point where the line is blank, but I'd like it to not have that line at all, for cosmetic reasons.

 

Also, semi-related: can this module quote for Saturday delivery?


Do, or do not. There is no try.

 

Order Editor 5.0.6 "Ultra Violet" is now available!

For support or to post comments, suggestions, etc, please visit the Order Editor support thread.

Share this post


Link to post
Share on other sites

Jan

Thank you for a great contribution. I am trying to get the latest version adapted for MVS. I have most of the code worked out and even added in the Days delay code that Stew has been posting about. However, I haven't worked out the length,width,height calculator (it is reporting different dimensions than the product description, i.e. product list with12x12x12 and when I look at the UPSXML.log I see 10x6x6) and it is calculating for all products no matter what vendor they are being shipped with which returns an inaccuarate rate from UPS. I don't know if the Insrance add-in is functioning correctly yet or not.

 

This is what I have so far and any help on getting this to work with MVS would appreciated.

<?php

 

require ('includes/classes/xmldocument.php');

// if using the optional dimensional support, set to 1, otherwise leave as 0

// define('DIMENSIONS_SUPPORTED', 1);

// obsolete: is set in admin now

 

class upsxml {

var $code, $title, $description, $icon, $enabled, $types, $boxcount;

 

//***************

function upsxml() {

global $_POST, $shipping_weight, $order, $cart, $shipping_num_boxes;

$this->delivery_country_id = $order->delivery['country']['id'];

$this->delivery_zone_id = $order->delivery['zone_id'];

$this->code = 'upsxml';

$this->title = MODULE_SHIPPING_UPSXML_RATES_TEXT_TITLE;

$this->description = MODULE_SHIPPING_UPSXML_RATES_TEXT_DESCRIPTION;

$this->icon = DIR_WS_ICONS . 'shipping_ups.gif';

$this->protocol = 'https';

$this->port = '443';

$this->path = '/ups.app/xml/Rate';

$this->transitpath = '/ups.app/xml/TimeInTransit';

$this->version = 'UPSXML Rate 1.0001';

$this->transitversion = 'UPSXML Time In Transit 1.0001';

$this->timeout = '60';

$this->xpci_version = '1.0001';

$this->transitxpci_version = '1.0002';

$this->items_qty = 0;

$this->timeintransit = '0';

$this->timeInTransitView = MODULE_SHIPPING_UPSXML_RATES_TIME_IN_TRANSIT_VIEW;

$this->weight_for_timeintransit = '0';

$now_unix_time = mktime(date("H"), date("i"), date("s"), date("m"), date("d"), date("Y"));

$this->today_unix_time = $now_unix_time;

$this->today = date("Ymd");

 

// to enable logging, create an empty "upsxml.log" file at the location you set below, give it write permissions (777) and uncomment the next line

 

// when cURL is not compiled into PHP (Windows users, some Linux users)

// you can set the next variable to "1" and then exec(curl -d $xmlRequest, $xmlResponse)

// will be used

$this->use_exec = '0';

 

// Available pickup types - set in admin

$this->pickup_methods = array(

'Daily Pickup' => '01',

'Customer Counter' => '03',

'One Time Pickup' => '06',

'On Call Air Pickup' => '07',

'Suggested Retail Rates (UPS Store)' => '11',

'Letter Center' => '19',

'Air Service Center' => '20'

);

 

// Available package types

$this->package_types = array(

'UPS Letter' => '01',

'Package' => '02',

'UPS Tube' => '03',

'UPS Pak' => '04',

'UPS Express Box' => '21',

'UPS 25kg Box' => '24',

'UPS 10kg Box' => '25'

);

 

// Human-readable Service Code lookup table. The values returned by the Rates and Service "shop" method are numeric.

// Using these codes, and the admininstratively defined Origin, the proper human-readable service name is returned.

// Note: The origin specified in the admin configuration affects only the product name as displayed to the user.

$this->service_codes = array(

// US Origin

'US Origin' => array(

'01' => MODULE_SHIPPING_UPSXML_SERVICE_CODE_US_ORIGIN_01,

'02' => MODULE_SHIPPING_UPSXML_SERVICE_CODE_US_ORIGIN_02,

'03' => MODULE_SHIPPING_UPSXML_SERVICE_CODE_US_ORIGIN_03,

'07' => MODULE_SHIPPING_UPSXML_SERVICE_CODE_US_ORIGIN_07,

'08' => MODULE_SHIPPING_UPSXML_SERVICE_CODE_US_ORIGIN_08,

'11' => MODULE_SHIPPING_UPSXML_SERVICE_CODE_US_ORIGIN_11,

'12' => MODULE_SHIPPING_UPSXML_SERVICE_CODE_US_ORIGIN_12,

'13' => MODULE_SHIPPING_UPSXML_SERVICE_CODE_US_ORIGIN_13,

'14' => MODULE_SHIPPING_UPSXML_SERVICE_CODE_US_ORIGIN_14,

'54' => MODULE_SHIPPING_UPSXML_SERVICE_CODE_US_ORIGIN_54,

'59' => MODULE_SHIPPING_UPSXML_SERVICE_CODE_US_ORIGIN_59,

),

// Canada Origin

'Canada Origin' => array(

'01' => MODULE_SHIPPING_UPSXML_SERVICE_CODE_CANADA_ORIGIN_01,

'07' => MODULE_SHIPPING_UPSXML_SERVICE_CODE_CANADA_ORIGIN_07,

'08' => MODULE_SHIPPING_UPSXML_SERVICE_CODE_CANADA_ORIGIN_08,

'11' => MODULE_SHIPPING_UPSXML_SERVICE_CODE_CANADA_ORIGIN_11,

'12' => MODULE_SHIPPING_UPSXML_SERVICE_CODE_CANADA_ORIGIN_12,

'13' => MODULE_SHIPPING_UPSXML_SERVICE_CODE_CANADA_ORIGIN_13,

'14' => MODULE_SHIPPING_UPSXML_SERVICE_CODE_CANADA_ORIGIN_14,

'54' => MODULE_SHIPPING_UPSXML_SERVICE_CODE_CANADA_ORIGIN_54,

'65' => MODULE_SHIPPING_UPSXML_SERVICE_CODE_CANADA_ORIGIN_65

),

// European Union Origin

'European Union Origin' => array(

'07' => MODULE_SHIPPING_UPSXML_SERVICE_CODE_EU_ORIGIN_07,

'11' => MODULE_SHIPPING_UPSXML_SERVICE_CODE_EU_ORIGIN_11,

'54' => MODULE_SHIPPING_UPSXML_SERVICE_CODE_EU_ORIGIN_54,

'65' => MODULE_SHIPPING_UPSXML_SERVICE_CODE_EU_ORIGIN_65

),

// Puerto Rico Origin

'Puerto Rico Origin' => array(

'01' => MODULE_SHIPPING_UPSXML_SERVICE_CODE_PR_ORIGIN_01,

'02' => MODULE_SHIPPING_UPSXML_SERVICE_CODE_PR_ORIGIN_02,

'03' => MODULE_SHIPPING_UPSXML_SERVICE_CODE_PR_ORIGIN_03,

'07' => MODULE_SHIPPING_UPSXML_SERVICE_CODE_PR_ORIGIN_07,

'08' => MODULE_SHIPPING_UPSXML_SERVICE_CODE_PR_ORIGIN_08,

'14' => MODULE_SHIPPING_UPSXML_SERVICE_CODE_PR_ORIGIN_14,

'54' => MODULE_SHIPPING_UPSXML_SERVICE_CODE_PR_ORIGIN_54

),

// Mexico Origin

'Mexico Origin' => array(

'07' => MODULE_SHIPPING_UPSXML_SERVICE_CODE_MEXICO_ORIGIN_07,

'08' => MODULE_SHIPPING_UPSXML_SERVICE_CODE_MEXICO_ORIGIN_08,

'54' => MODULE_SHIPPING_UPSXML_SERVICE_CODE_MEXICO_ORIGIN_54

),

// All other origins

'All other origins' => array(

'07' => MODULE_SHIPPING_UPSXML_SERVICE_CODE_OTHER_ORIGIN_07,

'08' => MODULE_SHIPPING_UPSXML_SERVICE_CODE_OTHER_ORIGIN_08,

'54' => MODULE_SHIPPING_UPSXML_SERVICE_CODE_OTHER_ORIGIN_54

)

);

}

 

function access_key($vendors_id='1') {

$this->access_key = constant('MODULE_SHIPPING_UPSXML_RATES_ACCESS_KEY_' . $vendors_id);

return $this->access_key;

}

 

function access_username($vendors_id='1') {

$this->access_username = constant('MODULE_SHIPPING_UPSXML_RATES_USERNAME_' . $vendors_id);

return $this->access_username;

}

 

function access_password($vendors_id='1') {

$this->access_password = constant('MODULE_SHIPPING_UPSXML_RATES_PASSWORD_' . $vendors_id);

return $this->access_password;

}

 

function origin($vendors_id='1') {

$this->origin = constant('MODULE_SHIPPING_UPSXML_RATES_ORIGIN_' . $vendors_id);

return $this->origin;

}

 

function origin_city($vendors_id='1') {

$this->origin_city = constant('MODULE_SHIPPING_UPSXML_RATES_CITY_' . $vendors_id);

return $this->origin_city;

}

 

function origin_stateprov($vendors_id='1') {

$this->origin_stateprov = constant('MODULE_SHIPPING_UPSXML_RATES_STATEPROV_' . $vendors_id);

return $this->origin_stateprov;

}

 

function origin_country($vendors_id='1') {

$this->origin_country = constant('MODULE_SHIPPING_UPSXML_RATES_COUNTRY_' . $vendors_id);

return $this->origin_country;

}

 

function origin_postalcode($vendors_id='1') {

$this->origin_postalcode = constant('MODULE_SHIPPING_UPSXML_RATES_POSTALCODE_' . $vendors_id);

return $this->origin_postalcode;

}

 

function pickup_method($vendors_id='1') {

$this->pickup_method = constant('MODULE_SHIPPING_UPSXML_RATES_PICKUP_METHOD_' . $vendors_id);

return $this->pickup_method;

}

 

function package_type($vendors_id='1') {

$this->package_type = constant('MODULE_SHIPPING_UPSXML_RATES_PACKAGE_TYPE_' . $vendors_id);

return $this->package_type;

}

 

function unit_weight($vendors_id='1') {

$this->unit_weight = constant('MODULE_SHIPPING_UPSXML_RATES_UNIT_WEIGHT_' . $vendors_id);

return $this->unit_weight;

}

 

function unit_length($vendors_id='1') {

$this->unit_length = constant('MODULE_SHIPPING_UPSXML_RATES_UNIT_LENGTH_' . $vendors_id);

return $this->unit_length;

}

 

function handling_type($vendors_id='1') {

$this->handling_type = constant('MODULE_SHIPPING_UPSXML_HANDLING_TYPE_' . $vendors_id);

return $this->handling_type;

}

 

function handling_fee($vendors_id='1') {

$this->handling_fee = constant('MODULE_SHIPPING_UPSXML_RATES_HANDLING_' . $vendors_id);

return $this->handling_fee;

}

 

function quote_type($vendors_id='1') {

$this->quote_type = constant('MODULE_SHIPPING_UPSXML_RATES_QUOTE_TYPE_' . $vendors_id);

return $this->quote_type;

}

 

function customer_classification($vendors_id='1') {

$this->customer_classification = constant('MODULE_SHIPPING_UPSXML_RATES_CUSTOMER_CLASSIFICATION_CODE_' . $vendors_id);

return $this->customer_classification;

}

 

function host($vendors_id) {

$this->host = constant('MODULE_SHIPPING_UPSXML_RATES_MODE_' . $vendors_id) == 'Test' ? 'wwwcie.ups.com' : 'wwwcie.ups.com';

return $this->host;

}

function email_errors($vendors_id) {

$this->email_errors = ((constant('MODULE_SHIPPING_UPSXML_EMAIL_ERRORS_' . $vendors_id) == 'Yes') ? true : false);

return $this->email_errors;

}

 

function dimensions_support($vendors_id) {

 

if (constant('MODULE_SHIPPING_UPSXML_DIMENSIONS_SUPPORT_' . $vendors_id) == "Ready-to-ship only") {

$this->dimensions_support = 1;

} elseif (constant('MODULE_SHIPPING_UPSXML_DIMENSIONS_SUPPORT_' . $vendors_id) == "With product dimensions") {

$this->dimensions_support = 2;

} else {

$this->dimensions_support = 0;

}

return $this->dimensions_support;

}

// insurance addition

function pkgvalue($vendors_id) {

if (constant('MODULE_SHIPPING_UPSXML_INSURE_' . $vendors_id) == 'False')

{ $this->pkgvalue = 100; }

if (constant('MODULE_SHIPPING_UPSXML_INSURE_' . $vendors_id) == 'True')

{ $this->pkgvalue = ceil($order->info['subtotal']); }

// end insurance addition

return $this->pkgvalue;

}

 

function sort_order($vendors_id='1')

{ $sort_order = 'MODULE_SHIPPING_UPSXML_RATES_SORT_ORDER_' . $vendors_id;

if (defined($sort_order))

{ $this->sort_order = constant($sort_order);

}

else

{ $this->sort_order = '-';

}

return $this->sort_order;

}

 

function tax_class($vendors_id='1') {

$this->tax_class = constant('MODULE_SHIPPING_UPSXML_RATES_TAX_CLASS_' . $vendors_id);

return $this->tax_class;

}

 

function enabled($vendors_id='1') {

$this->enabled = false;

$status = @constant('MODULE_SHIPPING_UPSXML_RATES_STATUS_' . $vendors_id);

if (isset ($status) && $status != '') {

$this->enabled = (($status == 'True') ? true : false);

}

if ( ($this->enabled == true) && ((int)constant('MODULE_SHIPPING_UPSXML_RATES_ZONE_' . $vendors_id) > 0) ) {

$check_flag = false;

$check_query = tep_db_query("select zone_id from " . TABLE_ZONES_TO_GEO_ZONES . " where geo_zone_id = '" . (int)constant('MODULE_SHIPPING_UPSXML_RATES_ZONE_' . $vendors_id) . "' and zone_country_id = '" . $this->delivery_country_id . "' order by zone_id");

while ($check = tep_db_fetch_array($check_query)) {

if ($check['zone_id'] < 1) {

$check_flag = true;

break;

}

elseif ($check['zone_id'] == $this->delivery_zone_id) {

$check_flag = true;

break;

}

}

 

if ($check_flag == false) {

$this->enabled = false;

}//if

}//if

return $this->enabled;

}

 

function zones($vendors_id='1') {

if ( ($this->enabled == true) && ((int)constant('MODULE_SHIPPING_UPSXML_RATES_ZONE_' . $vendors_id) > 0) ) {

$check_flag = false;

$check_query = tep_db_query("select zone_id from " . TABLE_ZONES_TO_GEO_ZONES . " where geo_zone_id = '" . (int)constant('MODULE_SHIPPING_UPSXML_RATES_ZONE_' . $vendors_id) . "' and zone_country_id = '" . $this->delivery_zone_id . "' order by zone_id");

while ($check = tep_db_fetch_array($check_query)) {

if ($check['zone_id'] < 1) {

$check_flag = true;

break;

} elseif ($check['zone_id'] == $this->delivery_zone_id) {

$check_flag = true;

break;

} //if

}//while

 

if ($check_flag == false) {

$this->enabled = false;

}//if

}//if

return $this->enabled;

}//function

 

// class methods

function quote($method = '', $module = '', $vendors_id = '1') {

global $_POST, $order, $shipping_weight, $shipping_num_boxes, $total_weight, $boxcount, $cart;

// UPS purports that if the origin is left out, it defaults to the account's location. Yeah, right.

$state = $order->delivery['state'];

$zone_query = tep_db_query("select zone_code from " . TABLE_ZONES . " where zone_name = '" . $order->delivery['state'] . "'");

if (tep_db_num_rows($zone_query)) {

$zone = tep_db_fetch_array($zone_query);

$state = $zone['zone_code'];

}

$this->_upsOrigin(constant('MODULE_SHIPPING_UPSXML_RATES_CITY_' . $vendors_id), constant('MODULE_SHIPPING_UPSXML_RATES_STATEPROV_' . $vendors_id), constant('MODULE_SHIPPING_UPSXML_RATES_COUNTRY_' . $vendors_id), constant('MODULE_SHIPPING_UPSXML_RATES_POSTALCODE_' . $vendors_id));

$this->_upsDest($order->delivery['city'], $state, $order->delivery['country']['iso_code_2'], $order->delivery['postcode']);

// MVS - Remove products from other vendors from the productsArray

$products_array = $cart->get_products();

$productsArray = array();

if (is_array ($products_array)) {

foreach ($products_array as $product_data) {

if ($product_data['vendors_id'] = $vendors_id) {

$productsArray[] = $product_data;

}

}

}

// End MVS

 

if ($this->dimensions_support($vendors_id) == '2') {

// sort $productsArray according to ready-to-ship (first) and not-ready-to-ship (last)

usort($productsArray, ready_to_shipCmp);

// Use packing algoritm to return the number of boxes we'll ship

$boxesToShip = $this->packProducts($productsArray);

// Quote for the number of boxes

for ($i = 0; $i < count($boxesToShip); $i++) {

$this->_addItem($boxesToShip[$i]['length'], $boxesToShip[$i]['width'], $boxesToShip[$i]['height'], $boxesToShip[$i]['current_weight']);

$totalWeight += $boxesToShip[$i]['current_weight'];

}

} elseif ($this->dimensions_support($vendors_id) == '1') {

$totalWeight = 0;

$total_non_ready_to_ship_weight = 0;

// sort $productsArray according to ready-to-ship (first) and not-ready-to-ship (last)

usort($productsArray, ready_to_shipCmp);

$non_ready_to_shipArray = array();

// walk through the productsArray, separate the items ready-to-ship and add them to

// the items (boxes) list, add the weight to the totalWeight

// and add the other items to a separate array

for ($i = 0; $i < count($productsArray); $i++) {

if ($productsArray[$i]['ready_to_ship'] == '1') {

for ($z = 0; $z < $productsArray[$i]['quantity']; $z++) {

$this->_addItem($productsArray[$i]['length'], $productsArray[$i]['width'], $productsArray[$i]['height'], $productsArray[$i]['weight']);

$totalWeight += $productsArray[$i]['weight'];

} // end for ($z = 0; $z < $productsArray[$i]['quantity']; $z++)

} // end if($productsArray['ready_to_ship'] == '1')

else {

$non_ready_to_shipArray[] = $productsArray[$i];

}

} // end for ($i = 0; $i < count($productsArray); $i++)

// Ready_to_ship items out of the way, now assess remaining weight of products

 

for ($x = 0; $x < count($non_ready_to_shipArray); $x++) {

$total_non_ready_to_ship_weight += ($non_ready_to_shipArray[$x]['weight'] * $non_ready_to_shipArray[$x]['quantity']);

} // end for ($x = 0; count($non_ready_to_shipArray); $x++)

 

if (tep_not_null($non_ready_to_shipArray)) {

// adapted code from includes/classes/shipping.php

$shipping_non_ready_to_ship_boxes = 1;

$shipping_non_ready_to_ship_weight = $total_non_ready_to_ship_weight;

if (SHIPPING_BOX_WEIGHT >= $total_non_ready_to_ship_weight*SHIPPING_BOX_PADDING/100) {

$total_non_ready_to_ship_weight = $total_non_ready_to_ship_weight+SHIPPING_BOX_WEIGHT;

} else {

$total_non_ready_to_ship_weight += $total_non_ready_to_ship_weight*SHIPPING_BOX_PADDING/100;

}

if ($total_non_ready_to_ship_weight > SHIPPING_MAX_WEIGHT) { // Split into many boxes

$shipping_non_ready_to_ship_boxes = ceil($total_non_ready_to_ship_weight/SHIPPING_MAX_WEIGHT);

$shipping_non_ready_to_ship_weight = round($total_non_ready_to_ship_weight/$shipping_non_ready_to_ship_boxes,1);

}

// end adapted code from includes/classes/shipping.php

// weight and number of boxes of non-read-to-ship is determined, now add them to the items list

for ($y = 0; $y < $shipping_non_ready_to_ship_boxes; $y++) {

$this->_addItem(0, 0, 0, $shipping_non_ready_to_ship_weight );

$totalWeight += $shipping_non_ready_to_ship_weight;

} // end for ($y = 0; $y < $shipping_non_ready_to_ship_boxes; $y++)

} // end if (tep_not_null($non_ready_to_shipArray))

} else {

// The old method. Let osCommerce tell us how many boxes, plus the weight of each (or total? - might be sw/num boxes)

$this->items_qty = 0; //reset quantities

for ($i = 0; $i < $shipping_num_boxes; $i++) {

$this->_addItem (0, 0, 0, $shipping_weight);

}

}

 

// BOF Time In Transit: comment out this section if you don't want/need to have

// expected delivery dates

if ($this->dimensions_support($vendors_id) > 0) {

$this->weight_for_timeintransit = round($totalWeight,1);

} else {

$this->weight_for_timeintransit = round($shipping_num_boxes * $shipping_weight,1);

}

// Added to workaround time in transit error 270033 if total weight of packages is over 150lbs or 70kgs

if (($this->weight_for_timeintransit > 150) && ($this->unit_weight == "LBS")) {

$this->weight_for_timeintransit = 150;

} else if (($this->weight_for_timeintransit > 70) && ($this->unit_weight == "KGS")) {

$this->weight_for_timeintransit = 70;

}

// debug only:

echo '<pre>Packages and variables:<br>';

print_r($this);

echo '<br>';

exit;

 

$this->servicesTimeintransit = $this->_upsGetTimeServices($vendors_id);

if ($this->logfile) {

error_log("------------------------------------------\n", 3, $this->logfile);

error_log("Time in Transit: " . $this->timeintransit . "\n", 3, $this->logfile);

}

 

// EOF Time In Transit

 

$upsQuote = $this->_upsGetQuote($vendors_id);

if ((is_array($upsQuote)) && (sizeof($upsQuote) > 0)) {

if ($this->dimensions_support($vendors_id) > 0) {

$this->quotes = array('id' => $this->code,

'module' => $this->title . ' (' . $this->boxCount . ($this->boxCount > 1 ? ' pkg(s), ' : ' pkg, ') . $totalWeight . ' ' . strtolower($this->unit_weight) . ' total)'

);

} else {

$this->quotes = array('id' => $this->code,

'module' => $this->title . ' (' . $shipping_num_boxes . ($this->boxCount > 1 ? ' pkg(s) x ' : ' pkg x ') . $shipping_weight . ' ' . strtolower($this->unit_weight) . ' total)'

);

}

 

$methods = array();

for ($i=0; $i < sizeof($upsQuote); $i++) {

list($type, $cost) = each($upsQuote[$i]);

// BOF limit choices, behaviour changed from versions < 1.2

if (exclude_choices($type, $vendors_id)) continue;

// EOF limit choices

if ( $method == '' || $method == $type ) {

$_type = $type;

if ($this->timeInTransitView == "Raw") {

if (isset($this->servicesTimeintransit[$type])) {

$_type = $_type . ", ".$this->servicesTimeintransit[$type]["date"];

}

} else {

if (isset($this->servicesTimeintransit[$type])) {

$eta_array = explode("-", $this->servicesTimeintransit[$type]["date"]);

$months = array (" ", "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December");

$eta_arrival_date = $months[(int)$eta_array[1]]." ".$eta_array[2].", ".$eta_array[0];

$_type .= ", <acronym title='Estimated Delivery Date'>EDD</acronym>: ".$eta_arrival_date;

}

}

 

 

//MVS Start

$vendors_data_query = tep_db_query("select handling_charge, handling_per_box, vendor_country, vendors_zipcode from " . TABLE_VENDORS . " where vendors_id = '" . (int)$vendors_id . "'" );

$vendors_data = tep_db_fetch_array($vendors_data_query);

$country_name = tep_get_countries($vendors_data['vendor_country'], true);

//MVS Start

$handling_charge = $vendors_data['handling_charge'];

$handling_per_box = $vendors_data['handling_per_box'];

if ($handling_charge > $handling_per_box*$shipping_num_boxes) {

$handling = $handling_charge;

} else {

$handling = $handling_per_box*$shipping_num_boxes;

}

//MVS End

$handling_fee = constant('MODULE_SHIPPING_UPSXML_RATES_HANDLING_' . $vendors_id);

// changed to make handling percentage based

if ($this->handling_type == "Percentage") {

$methods[] = array('id' => $type, 'title' => $_type, 'cost' => ((($this->handling_fee * $cost)/100) + $cost));

} else {

$methods[] = array('id' => $type, 'title' => $_type, 'cost' => ($this->handling_fee + $cost));

}

//$methods[] = array('id' => $type, 'title' => $_type, 'cost' => ($handling_fee + $cost + $handling));

}

}

if ($this->tax_class($vendors_id) > 0) {

$this->quotes['tax'] = tep_get_tax_rate($this->tax_class($vendors_id), $order->delivery['country']['id'], $order->delivery['zone_id']);

}

$this->quotes['methods'] = $methods;

} else {

if ( $upsQuote != false ) {

$errmsg = $upsQuote;

} else {

$errmsg = MODULE_SHIPPING_UPSXML_RATES_TEXT_UNKNOWN_ERROR;

}

$errmsg .= '<br>' . MODULE_SHIPPING_UPSXML_RATES_TEXT_IF_YOU_PREFER . ' ' . STORE_NAME.' via <a href="mailto:'.STORE_OWNER_EMAIL_ADDRESS.'"><u>Email</U></a>.';

$this->quotes = array('module' => $this->title, 'error' => $errmsg);

}

if (tep_not_null($this->icon)) {

$this->quotes['icon'] = tep_image($this->icon, $this->title);

}

// echo '<br> the handling fee from UPS module: ' . $handling_fee;

return $this->quotes;

}

 

//**************

function check($vendors_id='1') {

if (!isset($this->_check)) {

$check_query = tep_db_query("select configuration_value from " . TABLE_VENDOR_CONFIGURATION . " where vendors_id = '". $vendors_id ."' and configuration_key = 'MODULE_SHIPPING_UPSXML_RATES_STATUS_" . $vendors_id . "'");

$this->_check = tep_db_num_rows($check_query);

}

return $this->_check;

}

 

//**************

function install($vendors_id='1') {

tep_db_query("insert into " . TABLE_VENDOR_CONFIGURATION . " (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, set_function, date_added, vendors_id) values ('Enable UPS Shipping', 'MODULE_SHIPPING_UPSXML_RATES_STATUS_" . $vendors_id . "', 'True', 'Do you want to offer UPS shipping?', '6', '0', 'tep_cfg_select_option(array(\'True\', \'False\'), ', now(), '" . $vendors_id . "')");

tep_db_query("insert into " . TABLE_VENDOR_CONFIGURATION . " (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, date_added, vendors_id) values ('UPS Rates Access Key', 'MODULE_SHIPPING_UPSXML_RATES_ACCESS_KEY_" . $vendors_id . "', '', 'Enter the XML rates access key assigned to you by UPS.', '6', '1', now(), '" . $vendors_id . "')");

tep_db_query("insert into " . TABLE_VENDOR_CONFIGURATION . " (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, date_added, vendors_id) values ('UPS Rates Username', 'MODULE_SHIPPING_UPSXML_RATES_USERNAME_" . $vendors_id . "', '', 'Enter your UPS Services account username.', '6', '2', now(), '" . $vendors_id . "')");

tep_db_query("insert into " . TABLE_VENDOR_CONFIGURATION . " (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, date_added, vendors_id) values ('UPS Rates Password', 'MODULE_SHIPPING_UPSXML_RATES_PASSWORD_" . $vendors_id . "', '', 'Enter your UPS Services account password.', '6', '3', now(), '" . $vendors_id . "')");

tep_db_query("insert into " . TABLE_VENDOR_CONFIGURATION . " (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, set_function, date_added, vendors_id) values ('Pickup Method', 'MODULE_SHIPPING_UPSXML_RATES_PICKUP_METHOD_" . $vendors_id . "', 'Daily Pickup', 'How do you give packages to UPS (only used when origin is US)?', '6', '4', 'tep_cfg_select_option(array(\'Daily Pickup\', \'Customer Counter\', \'One Time Pickup\', \'On Call Air Pickup\', \'Letter Center\', \'Air Service Center\', \'Suggested Retail Rates (UPS Store)\'), ', now(), '" . $vendors_id . "')");

tep_db_query("insert into " . TABLE_VENDOR_CONFIGURATION . " (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, set_function, date_added, vendors_id) values ('Packaging Type', 'MODULE_SHIPPING_UPSXML_RATES_PACKAGE_TYPE_" . $vendors_id . "', 'Package', 'What kind of packaging do you use?', '6', '5', 'tep_cfg_select_option(array(\'Package\', \'UPS Letter\', \'UPS Tube\', \'UPS Pak\', \'UPS Express Box\', \'UPS 25kg Box\', \'UPS 10kg box\'), ', now(), '" . $vendors_id . "')");

tep_db_query("insert into " . TABLE_VENDOR_CONFIGURATION . " (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, set_function, date_added, vendors_id) values ('Customer Classification Code', 'MODULE_SHIPPING_UPSXML_RATES_CUSTOMER_CLASSIFICATION_CODE_" . $vendors_id . "', '01', '01 - If you are billing to a UPS account and have a daily UPS pickup, 03 - If you do not have a UPS account or you are billing to a UPS account but do not have a daily pickup, 04 - If you are shipping from a retail outlet (only used when origin is US)', '6', '6', 'tep_cfg_select_option(array(\'01\', \'03\', \'04\'), ', now(), '" . $vendors_id . "')");

tep_db_query("insert into " . TABLE_VENDOR_CONFIGURATION . " (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, set_function, date_added, vendors_id) values ('Shipping Origin', 'MODULE_SHIPPING_UPSXML_RATES_ORIGIN_" . $vendors_id . "', 'US Origin', 'What origin point should be used (this setting affects only what UPS product names are shown to the user)', '6', '7', 'tep_cfg_select_option(array(\'US Origin\', \'Canada Origin\', \'European Union Origin\', \'Puerto Rico Origin\', \'Mexico Origin\', \'All other origins\'), ', now(), '" . $vendors_id . "')");

tep_db_query("insert into " . TABLE_VENDOR_CONFIGURATION . " (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, date_added, vendors_id) values ('Origin City', 'MODULE_SHIPPING_UPSXML_RATES_CITY_" . $vendors_id . "', '', 'Enter the name of the origin city.', '6', '8', now(), '" . $vendors_id . "')");

tep_db_query("insert into " . TABLE_VENDOR_CONFIGURATION . " (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, date_added, vendors_id) values ('Origin State/Province', 'MODULE_SHIPPING_UPSXML_RATES_STATEPROV_" . $vendors_id . "', '', 'Enter the two-letter code for your origin state/province.', '6', '9', now(), '" . $vendors_id . "')");

tep_db_query("insert into " . TABLE_VENDOR_CONFIGURATION . " (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, date_added, vendors_id) values ('Origin Country', 'MODULE_SHIPPING_UPSXML_RATES_COUNTRY_" . $vendors_id . "', '', 'Enter the two-letter code for your origin country.', '6', '10', now(), '" . $vendors_id . "')");

tep_db_query("insert into " . TABLE_VENDOR_CONFIGURATION . " (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, date_added, vendors_id) values ('Origin Zip Code', 'MODULE_SHIPPING_UPSXML_RATES_POSTALCODE_" . $vendors_id . "', '', 'Enter your origin zip/postcode.', '6', '11', now(), '" . $vendors_id . "')");

tep_db_query("insert into " . TABLE_VENDOR_CONFIGURATION . " (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, set_function, date_added, vendors_id) values ('Test or Production Mode', 'MODULE_SHIPPING_UPSXML_RATES_MODE_" . $vendors_id . "', 'Test', 'Use this module in Test or Production mode?', '6', '12', 'tep_cfg_select_option(array(\'Test\', \'Production\'), ', now(), '" . $vendors_id . "')");

tep_db_query("insert into " . TABLE_VENDOR_CONFIGURATION . " (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, set_function, date_added, vendors_id) values ('Unit Weight', 'MODULE_SHIPPING_UPSXML_RATES_UNIT_WEIGHT_" . $vendors_id . "', 'LBS', 'By what unit are your packages weighed?', '6', '13', 'tep_cfg_select_option(array(\'LBS\', \'KGS\'), ', now(), '" . $vendors_id . "')");

tep_db_query("insert into " . TABLE_VENDOR_CONFIGURATION . " (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, set_function, date_added, vendors_id) values ('Unit Length', 'MODULE_SHIPPING_UPSXML_RATES_UNIT_LENGTH_" . $vendors_id . "', 'IN', 'By what unit are your packages sized?', '6', '14', 'tep_cfg_select_option(array(\'IN\', \'CM\'), ', now(), '" . $vendors_id . "')");

tep_db_query("insert into " . TABLE_VENDOR_CONFIGURATION . " (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, set_function, date_added, vendors_id) values ('Dimensions Support', 'MODULE_SHIPPING_UPSXML_DIMENSIONS_SUPPORT_" . $vendors_id . "', 'No', 'Do you use the additional dimensions support (read dimensions.txt in the package)?', '6', '23', 'tep_cfg_select_option(array(\'No\', \'Ready-to-ship only\', \'With product dimensions\'), ', now(), '" . $vendors_id . "')");

tep_db_query("insert into " . TABLE_VENDOR_CONFIGURATION . " (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, set_function, date_added, vendors_id) values ('Quote Type', 'MODULE_SHIPPING_UPSXML_RATES_QUOTE_TYPE_" . $vendors_id . "', 'Commercial', 'Quote for Residential or Commercial Delivery', '6', '15', 'tep_cfg_select_option(array(\'Commercial\', \'Residential\'), ', now(), '" . $vendors_id . "')");

// added for handling type selection

tep_db_query("insert into " . TABLE_VENDOR_CONFIGURATION . " (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, set_function, date_added, vendors_id) values ('Handling Type', 'MODULE_SHIPPING_UPSXML_HANDLING_TYPE_" . $vendors_id . "', 'Flat Fee', 'Handling type for this shipping method.', '6', '16', 'tep_cfg_select_option(array(\'Flat Fee\', \'Percentage\'), ', now(), '" . $vendors_id . "')");

tep_db_query("insert into " . TABLE_VENDOR_CONFIGURATION . " (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, date_added, vendors_id) values ('Handling Fee', 'MODULE_SHIPPING_UPSXML_RATES_HANDLING_" . $vendors_id . "', '0', 'Handling fee for this shipping method.', '6', '16', now(), '" . $vendors_id . "')");

tep_db_query("insert into " . TABLE_VENDOR_CONFIGURATION . " (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, use_function, set_function, date_added, vendors_id) values ('Tax Class', 'MODULE_SHIPPING_UPSXML_RATES_TAX_CLASS_" . $vendors_id . "', '0', 'Use the following tax class on the shipping fee.', '6', '17', 'tep_get_tax_class_title', 'tep_cfg_pull_down_tax_classes(', now(), '" . $vendors_id . "')");

tep_db_query("insert into " . TABLE_VENDOR_CONFIGURATION . " (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, use_function, set_function, date_added, vendors_id) values ('Shipping Zone', 'MODULE_SHIPPING_UPSXML_RATES_ZONE_" . $vendors_id . "', '0', 'If a zone is selected, only enable this shipping method for that zone.', '6', '18', 'tep_get_zone_class_title', 'tep_cfg_pull_down_zone_classes(', now(), '" . $vendors_id . "')");

tep_db_query("insert into " . TABLE_VENDOR_CONFIGURATION . " (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, date_added, vendors_id) values ('Sort order of display.', 'MODULE_SHIPPING_UPSXML_RATES_SORT_ORDER_" . $vendors_id . "', '0', 'Sort order of display. Lowest is displayed first.', '6', '19', now(), '" . $vendors_id . "')");

// add key for disallowed shipping methods

tep_db_query("insert into " . TABLE_VENDOR_CONFIGURATION . " ( configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, set_function, date_added, vendors_id) values ('Disallowed Shipping Methods', 'MODULE_SHIPPING_UPSXML_TYPES_" . $vendors_id . "', '', 'Select the UPS services <span style=\'color: red; font-weight: bold\'>not</span> to be offered.', '6', '20', 'tep_cfg_select_multioption(array(\'Next Day Air\', \'2nd Day Air\', \'Ground\', \'Worldwide Express\', \'Worldwide Express Plus\', \'Worldwide Expedited\', \'Express\', \'Standard\', \'3 Day Select\', \'Next Day Air Saver\', \'Next Day Air Early A.M.\', \'Expedited\', \'2nd Day Air A.M.\', \'Express Saver\', \'Express Early A.M.\', \'Express Plus\'), ', now(), '" . $vendors_id . "')");

tep_db_query("insert into " . TABLE_VENDOR_CONFIGURATION . " (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, set_function, date_added, vendors_id) values ('Enable Insurance', 'MODULE_SHIPPING_UPSXML_INSURE_" . $vendors_id . "', 'True', 'Do you want to insure packages shipped by UPS?', '6', '22', 'tep_cfg_select_option(array(\'True\', \'False\'), ', now(), '" . $vendors_id . "')");

tep_db_query("insert into " . TABLE_VENDOR_CONFIGURATION . " (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, last_modified, date_added, use_function, set_function, vendors_id) values ('Shipping Delay', 'MODULE_SHIPPING_UPSXML_DAYS_DELAY_" . $vendors_id . "', '1', 'How many days from when an order is placed to when you ship it (Decimals are allowed). Arrival date estimations are based on this value.', '6', '21', NULL, now(), NULL, NULL, '" . $vendors_id . "')");

// add key for enabling email error messages

tep_db_query("insert into " . TABLE_VENDOR_CONFIGURATION . " (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, set_function, date_added, vendors_id) values ('Email UPS errors', 'MODULE_SHIPPING_UPSXML_EMAIL_ERRORS_" . $vendors_id . "', 'Yes', 'Do you want to receive UPS errors by email?', '6', '24', 'tep_cfg_select_option(array(\'Yes\', \'No\'), ', now(), '" . $vendors_id . "')");

tep_db_query("insert into " . TABLE_VENDOR_CONFIGURATION . " (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, date_added, vendors_id) values ('UPS currency code', 'MODULE_SHIPPING_UPSXML_CURRENCY_CODE_" . $vendors_id . "', 'USD', 'Set the currency that UPS is to deliver pricing in (Default USD)', '6', '25', now(), '" . $vendors_id . "')");

// add key for time in transit view type

tep_db_query("insert into " . TABLE_VENDOR_CONFIGURATION . " (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, set_function, date_added, vendors_id) values ('Time in Transit View Type', 'MODULE_SHIPPING_UPSXML_RATES_TIME_IN_TRANSIT_VIEW_" . $vendors_id . "', 'Raw', 'How the module should display the time in transit to the customer.', '6', '16', 'tep_cfg_select_option(array(\'Raw\', \'Detailed\'), ', now(), '" . $vendors_id . "')");

}

 

//****************

function remove($vendors_id) {

tep_db_query("delete from " . TABLE_VENDOR_CONFIGURATION . " where vendors_id = '". $vendors_id ."' and configuration_key in ('" . implode("', '", $this->keys($vendors_id)) . "')");

}

 

//*************

function keys($vendors_id) {

return array('MODULE_SHIPPING_UPSXML_RATES_STATUS_' . $vendors_id,

'MODULE_SHIPPING_UPSXML_RATES_ACCESS_KEY_' . $vendors_id,

'MODULE_SHIPPING_UPSXML_RATES_USERNAME_' . $vendors_id,

'MODULE_SHIPPING_UPSXML_RATES_PASSWORD_' . $vendors_id,

'MODULE_SHIPPING_UPSXML_RATES_PICKUP_METHOD_' . $vendors_id,

'MODULE_SHIPPING_UPSXML_RATES_PACKAGE_TYPE_' . $vendors_id,

'MODULE_SHIPPING_UPSXML_RATES_CUSTOMER_CLASSIFICATION_CODE_' . $vendors_id,

'MODULE_SHIPPING_UPSXML_RATES_ORIGIN_' . $vendors_id,

'MODULE_SHIPPING_UPSXML_RATES_CITY_' . $vendors_id,

'MODULE_SHIPPING_UPSXML_RATES_STATEPROV_' . $vendors_id,

'MODULE_SHIPPING_UPSXML_RATES_COUNTRY_' . $vendors_id,

'MODULE_SHIPPING_UPSXML_RATES_POSTALCODE_' . $vendors_id,

'MODULE_SHIPPING_UPSXML_RATES_MODE_' . $vendors_id,

'MODULE_SHIPPING_UPSXML_RATES_UNIT_WEIGHT_' . $vendors_id,

'MODULE_SHIPPING_UPSXML_RATES_UNIT_LENGTH_' . $vendors_id,

'MODULE_SHIPPING_UPSXML_DIMENSIONS_SUPPORT_' . $vendors_id,

'MODULE_SHIPPING_UPSXML_RATES_QUOTE_TYPE_' . $vendors_id,

'MODULE_SHIPPING_UPSXML_HANDLING_TYPE_' . $vendors_id,

'MODULE_SHIPPING_UPSXML_RATES_HANDLING_' . $vendors_id,

'MODULE_SHIPPING_UPSXML_RATES_TAX_CLASS_' . $vendors_id,

'MODULE_SHIPPING_UPSXML_RATES_ZONE_' . $vendors_id,

'MODULE_SHIPPING_UPSXML_RATES_SORT_ORDER_' . $vendors_id,

'MODULE_SHIPPING_UPSXML_TYPES_' . $vendors_id,

'MODULE_SHIPPING_UPSXML_INSURE_' . $vendors_id,

'MODULE_SHIPPING_UPSXML_DAYS_DELAY_' . $vendors_id,

'MODULE_SHIPPING_UPSXML_EMAIL_ERRORS_' . $vendors_id,

'MODULE_SHIPPING_UPSXML_CURRENCY_CODE_' . $vendors_id,

'MODULE_SHIPPING_UPSXML_RATES_TIME_IN_TRANSIT_VIEW_' . $vendors_id

);

}

 

//***********************

function _upsProduct($prod, $vendors_id){

$this->_upsProductCode = $prod;

}

 

//**********************************************

function _upsOrigin($city, $stateprov, $country, $postal){

$this->_upsOriginCity = $city;

$this->_upsOriginStateProv = $stateprov;

$this->_upsOriginCountryCode = $country;

$postal = str_replace(' ', '', $postal);

if ($country == 'US') {

$this->_upsOriginPostalCode = substr($postal, 0, 5);

} else {

$this->_upsOriginPostalCode = $postal;

}

}

 

//**********************************************

function _upsDest($city, $stateprov, $country, $postal) {

$this->_upsDestCity = $city;

$this->_upsDestStateProv = $stateprov;

$this->_upsDestCountryCode = $country;

$postal = str_replace(' ', '', $postal);

if ($country == 'US') {

$this->_upsDestPostalCode = substr($postal, 0, 5);

} else {

$this->_upsDestPostalCode = $postal;

}

}

 

//************************

function _upsAction($action, $vendors_id) {

// rate - Single Quote; shop - All Available Quotes

$this->_upsActionCode = $action;

}

 

//********************************************

function _addItem($length, $width, $height, $weight) {

// Add box or item to shipment list. Round weights to 1 decimal places.

if ((float)$weight < 1.0) {

$weight = 1;

} else {

$weight = round($weight, 1);

}

$index = $this->items_qty;

$this->item_length[$index] = ($length ? (string)$length : '0' );

$this->item_width[$index] = ($width ? (string)$width : '0' );

$this->item_height[$index] = ($height ? (string)$height : '0' );

$this->item_weight[$index] = ($weight ? (string)$weight : '0' );

$this->items_qty++;

}

 

//********************

function getPackagesByVol() {

$packages = array();

$packages_query = tep_db_query("select * from " . TABLE_PACKAGING . " order by package_cost;");

while ($package = tep_db_fetch_array($packages_query)) {

$packages[] = array(

'id' => $package['package_id'],

'name' => $package['package_name'],

'description' => $package['package_description'],

'length' => $package['package_length'],

'width' => $package['package_width'],

'height' => $package['package_height'],

'empty_weight' => $package['package_empty_weight'],

'max_weight' => $package['package_max_weight'],

'cost' => $package['package_cost']);

}

return $packages;

}

 

//********************************

 

/*

function getPackagesByVol() {

$packages = array();

$packages_query = tep_db_query("select *, (package_length * package_width * package_height) as volume from " . TABLE_PACKAGING . " order by volume;");

while ($package = tep_db_fetch_array($packages_query)) {

$packages[] = array(

'id' => $package['package_id'],

'name' => $package['package_name'],

'description' => $package['package_description'],

'length' => $package['package_length'],

'width' => $package['package_width'],

'height' => $package['package_height'],

'empty_weight' => $package['package_empty_weight'],

'max_weight' => $package['package_max_weight'],

'volume' => $package['volume'] );

}

return $packages;

}

*/

 

//********************************

function packProducts($productsArray) {

// A very simple box packing algorithm. Given a list of packages, returns an array of boxes.

// This algorithm is trivial. It works on the premise that you have selected boxes that fit your products, and that their volumes are resonable multiples

// of the products they store. For example, if you sell CDs and these CDs are 5x5x0.5", your boxes should be 5x5x0.5 (1 CD mailer), 5x5x2.5 (5 CD mailer)

// and 5x5x5 (10 CD mailer). No matter how many CDs a customer buys, this routine will always find the optimal packing.

// Your milage may differ, depending on what variety of products you sell, and how they're boxed. I just made up this algorithm in a hurry to fill a small

// niche. You are encouraged to find better algorithms. Better algorithms mean better packaging, resulting in higher quoting accuracy and less loss due to

// inaccurate quoting.

Share this post


Link to post
Share on other sites

here is the rest of the code.

 

NOTE

the function _getpackagesByVol part is where i started putting the old packing algorithm by Torin Walker back in.

 

	//********************************
function packProducts($productsArray) {
	// A very simple box packing algorithm. Given a list of packages, returns an array of boxes.
	// This algorithm is trivial. It works on the premise that you have selected boxes that fit your products, and that their volumes are resonable multiples
	// of the products they store. For example, if you sell CDs and these CDs are 5x5x0.5", your boxes should be 5x5x0.5 (1 CD mailer), 5x5x2.5 (5 CD mailer)
	// and 5x5x5 (10 CD mailer). No matter how many CDs a customer buys, this routine will always find the optimal packing.
	// Your milage may differ, depending on what variety of products you sell, and how they're boxed. I just made up this algorithm in a hurry to fill a small
	// niche. You are encouraged to find better algorithms. Better algorithms mean better packaging, resulting in higher quoting accuracy and less loss due to
	// inaccurate quoting. The algorithm proceeds as follows:
	// Get the first, smallest box, and try to put everything into it. If not all of it fits, try fitting it all into the next largest box. Keep increasing
	// the size of the box until no larger box can be obtained, then spill over into a second, smallest box. Once again, increase the box size until
	// everything fits, or spill over again. Repeat until everything is boxed. The cost of a box determines the order in which it is tried. There will definitely
	// be cases where it is cheaper to send two small packages rather than one larger one. In that case, you'll need a better algorithm.
	// Get the available packages and "prepare" empty boxes with weight and remaining volume counters. (Take existing box and add 'remaining_volume' and 'current_weight';
	$definedPackages = $this->getPackagesByVol();
	$emptyBoxesArray = array();
	for ($i = 0; $i < count($definedPackages); $i++) {
		$definedBox = $definedPackages[$i];
		$definedBox['remaining_volume'] = $definedBox['volume'];
		$definedBox['current_weight'] = $definedBox['empty_weight'];
		$emptyBoxesArray[] = $definedBox;
	}
	$packedBoxesArray = array();
	$currentBox = NULL;
	$index_of_largest_box = count($emptyBoxesArray)-1;
	// Get the product array and expand multiple qty items.
	$productsRemaining = array();
	for ($i = 0; $i < count($productsArray); $i++) {
		$product = $productsArray[$i];
	// sanity checks on the product
	if (!$this->fitsInBox($product, $emptyBoxesArray[$index_of_largest_box])) {
		$product['ready_to_ship'] = '1';
	}
		if (($product['length'] == 0 || $product['width'] == 0 || $product['height'] == 0) && $product['weight'] > 0) {
	  $density = 0.7;
	  if ($this->unit_length == 'CM') {
	  $product['length']=$product['width']=$product['height']= round(10*(pow($product['weight']/$density, 1/3)),1);
	  } else {
// non-metric: inches and pounds
		  $product['length']=$product['width']=$product['height']= round(pow($product['weight']*27.67/$density, 1/3),1);
	  }
	} // end sanity check
		for ($j = 0; $j < $productsArray[$i]['quantity']; $j++) {
			$productsRemaining[] = $product;
		}
	}
// make sure the products that did not fit the largest box and are now set as ready-to-ship
// are out of the way as soon as possible
usort($productsRemaining, ready_to_shipCmp);
	// Worst case, you'll need as many boxes as products ordered.
	while (count($productsRemaining)) {
		// Immediately set aside products that are already packed and ready.
		if ($productsRemaining[0]['ready_to_ship'] == '1') {
			$packedBoxesArray[] = array (
			'length' => $productsRemaining[0]['length'],
			'width' => $productsRemaining[0]['width'],
			'height' => $productsRemaining[0]['height'],
			'current_weight' => $productsRemaining[0]['weight']);
			$productsRemaining = array_slice($productsRemaining, 1);
			continue;
		}
		//Cylcle through boxes, increasing box size if all doesn't fit.
		if (count($emptyBoxesArray) == 0) {
			print_r("ERROR: No boxes to ship unpackaged product<br>");
			break;
		}
		for ($b = 0; $b < count($emptyBoxesArray) && tep_not_null($productsRemaining); $b++) {
		$result = $this->fitProductsInBox($productsRemaining, $emptyBoxesArray[$b], $packedBoxesArray, $b, count($emptyBoxesArray) -1 );
		$packedBoxesArray = $result['packed_boxes'];
		$productsRemaining = $result['remaining'];
		}
	} // end while

	return $packedBoxesArray;
}

//*****************************
function fitsInBox($product, $box) {
	// in case by accident or by choice length, width or height is not set
	// we will estimate it by using a set density and the product['weight'] variable
	// will only be used in the check for whether it fits the largest box
	// after that it will already be set, if product['weight'] is set at least
	if ($product['length'] == 0 || $product['width'] == 0 || $product['height'] == 0) {
	  $density = 1;
	  if ($this->unit_length == 'CM') {
	  $product['length']=$product['width']=$product['height']= round(10*(pow($product['weight']/$density, 1/3)),1);
	  } else {
// non-metric: inches and pounds
		  $product['length']=$product['width']=$product['height']= round(pow($product['weight']*27.67/$density, 1/3),1);
	  }
	} 
	$productVolume = $product['length'] * $product['width'] * $product['height'];
// check if the diagonal of the product is not bigger than the diagonal of the box
if ( ( pow($product['length'],2) + pow($product['width'],2) + pow($product['height'],2) ) > ( pow($box['length'],2) + pow($box['width'],2) + pow($box['height'],2)) ) {
	return false;
} 

	if ($productVolume <= $box['remaining_volume']) {
		if ($box['max_weight'] == 0 || ($box['current_weight'] + $product['weight'] <= $box['max_weight'])) {
			return true;
		}
	}
	return false;
}

//***********************************
function putProductInBox($product, $box) {
	$productVolume = $product['length'] * $product['width'] * $product['height'];
	$box['remaining_volume'] -= $productVolume;
	$box['products'][] = $product;
	$box['current_weight'] += $product['weight'];
	return $box;
}
//*********************	
 function fitProductsInBox($productsRemaining, $emptyBox, $packedBoxesArray, $box_no, $index_of_largest_box) { 
			$currentBox = $emptyBox;
			//Try to fit each product in box
			for ($p = 0; $p < count($productsRemaining); $p++) {
				if ($this->fitsInBox($productsRemaining[$p], $currentBox)) {
					//It fits. Put it in the box.
					$currentBox = $this->putProductInBox($productsRemaining[$p], $currentBox);
					if ($p == count($productsRemaining) - 1) {
						$packedBoxesArray[] = $currentBox;
						$productsRemaining = array_slice($productsRemaining, $p + 1);
						$result_array = array('remaining' => $productsRemaining, 'box_no' => $box_no, 'packed_boxes' => $packedBoxesArray);
						return ($result_array);
					}
				} else {
					if ($box_no == $index_of_largest_box) {
						//We're at the largest box already, and it's full. Keep what we've packed so far and get another box.
						$packedBoxesArray[] = $currentBox;
						$productsRemaining = array_slice($productsRemaining, $p);
						$result_array = array('remaining' => $productsRemaining, 'box_no' => $box_no, 'packed_boxes' => $packedBoxesArray);
						return ($result_array);
					}
					// Not all of them fit. Stop packing remaining products and try next box.
					$result_array = array('remaining' => $productsRemaining, 'box_no' => $box_no, 'packed_boxes' => $packedBoxesArray);
						return ($result_array);
				} // end else
		} // end for
	 } // end function

//*********************
function _upsGetQuote($vendors_id='1') {

	// Create the access request
	$accessRequestHeader =
	"<?xml version=\"1.0\"?>\n".
	"<AccessRequest xml:lang=\"en-US\">\n".
	"   <AccessLicenseNumber>". $this->access_key($vendors_id) ."</AccessLicenseNumber>\n".
	"   <UserId>". $this->access_username($vendors_id) ."</UserId>\n".
	"   <Password>". $this->access_password($vendors_id) ."</Password>\n".
	"</AccessRequest>\n";

	$ratingServiceSelectionRequestHeader =
	"<?xml version=\"1.0\"?>\n".
	"<RatingServiceSelectionRequest xml:lang=\"en-US\">\n".
	"   <Request>\n".
	"	   <TransactionReference>\n".
	"		   <CustomerContext>Rating and Service</CustomerContext>\n".
	"		   <XpciVersion>". $this->xpci_version ."</XpciVersion>\n".
	"	   </TransactionReference>\n".
	"	   <RequestAction>Rate</RequestAction>\n".
	"	   <RequestOption>shop</RequestOption>\n".
	"   </Request>\n";
// according to UPS the CustomerClassification and PickupType containers should
// not be present when the origin country is non-US see:
// [url=http://forums.oscommerce.com/index.php?s=&showtopic=49382&view=findpost&p=730947]http://forums.oscommerce.com/index.php?s=&...ndpost&p=730947[/url]
if ($this->origin_country($vendors_id) == 'US') {
$ratingServiceSelectionRequestHeader .=
	"   <PickupType>\n".
	"	   <Code>". $this->pickup_methods[$this->pickup_method($vendors_id)] ."</Code>\n".
	"   </PickupType>\n";
}
$ratingServiceSelectionRequestHeader .=
	"   <Shipment>\n".
	"	   <Shipper>\n".
	"		   <Address>\n".
	"			   <City>". $this->_upsOriginCity ."</City>\n".
	"			   <StateProvinceCode>". $this->_upsOriginStateProv ."</StateProvinceCode>\n".
	"			   <CountryCode>". $this->_upsOriginCountryCode ."</CountryCode>\n".
	"			   <PostalCode>". $this->_upsOriginPostalCode ."</PostalCode>\n".
	"		   </Address>\n".
	"	   </Shipper>\n".
	"	   <ShipTo>\n".
	"		   <Address>\n".
	"			   <City>". $this->_upsDestCity ."</City>\n".
	"			   <StateProvinceCode>". $this->_upsDestStateProv ."</StateProvinceCode>\n".
	"			   <CountryCode>". $this->_upsDestCountryCode ."</CountryCode>\n".
	"			   <PostalCode>". $this->_upsDestPostalCode ."</PostalCode>\n".
	($this->quote_type($vendors_id) == "Residential" ? "<ResidentialAddressIndicator/>\n" : "") .
	"		   </Address>\n".
	"	   </ShipTo>\n";
	for ($i = 0; $i < $this->items_qty; $i++) {

		$ratingServiceSelectionRequestPackageContent .=
		"	   <Package>\n".
		"		   <PackagingType>\n".
		"			   <Code>". $this->package_types[$this->package_type($vendors_id)] ."</Code>\n".
		"		   </PackagingType>\n";
		if ($this->dimensions_support($vendors_id) == '1' || '2') {

			$ratingServiceSelectionRequestPackageContent .=
			"		   <Dimensions>\n".
			"			   <UnitOfMeasurement>\n".
			"				   <Code>". $this->unit_length($vendors_id) ."</Code>\n".
			"			   </UnitOfMeasurement>\n".
			"			   <Length>". $this->item_length[$i] ."</Length>\n".
			"			   <Width>". $this->item_width[$i] ."</Width>\n".
			"			   <Height>". $this->item_height[$i] ."</Height>\n".
			"		   </Dimensions>\n";
		}

		$ratingServiceSelectionRequestPackageContent .=
		"		   <PackageWeight>\n".
		"			   <UnitOfMeasurement>\n".
		"				   <Code>". $this->unit_weight($vendors_id) ."</Code>\n".
		"			   </UnitOfMeasurement>\n".
		"			   <Weight>". $this->item_weight[$i] ."</Weight>\n".
		"		   </PackageWeight>\n".
		"	   </Package>\n";
	}

	$ratingServiceSelectionRequestFooter =
	"   </Shipment>\n";
// according to UPS the CustomerClassification and PickupType containers should
// not be present when the origin country is non-US see:
// [url=http://forums.oscommerce.com/index.php?s=&showtopic=49382&view=findpost&p=730947]http://forums.oscommerce.com/index.php?s=&...ndpost&p=730947[/url]
if ($this->origin_country($vendors_id) == 'US') {
$ratingServiceSelectionRequestFooter .=
	"   <CustomerClassification>\n".
	"	   <Code>". $this->customer_classification($vendors_id) ."</Code>\n".
" </CustomerClassification>\n";
}
$ratingServiceSelectionRequestFooter .=
"</RatingServiceSelectionRequest>\n";

	$xmlRequest = $accessRequestHeader .
	$ratingServiceSelectionRequestHeader .
	$ratingServiceSelectionRequestPackageContent .
	$ratingServiceSelectionRequestFooter;

							$host = $this->host($vendors_id);

	//post request $strXML;
	$xmlResult = $this->_post($this->protocol, $host, $this->port, $this->path, $this->version, $this->timeout, $xmlRequest);

	return $this->_parseResult($xmlResult, $vendors_id);
}

//******************************************************************
function _post($protocol, $host, $port, $path, $version, $timeout, $xmlRequest) {
	$url = $protocol."://".$host.":".$port.$path;
	if ($this->logfile) {
		error_log("------------------------------------------\n", 3, $this->logfile);
		error_log("DATE AND TIME: ".date('Y-m-d H:i:s')."\n", 3, $this->logfile);
		error_log("UPS URL: " . $url . "\n", 3, $this->logfile);
	}
	if (function_exists('exec') && $this->use_exec == '1' ) {
	exec('which curl', $curl_output);
	if ($curl_output) {
	$curl_path = $curl_output[0];
	}
	else {
	$curl_path = 'curl'; // change this if necessary
	}
	if ($this->logfile) {
		error_log("UPS REQUEST using exec(): " . $xmlRequest . "\n", 3, $this->logfile);
	}
// add option -k to the statement: $command = "".$curl_path." -k -d \"". etcetera if you get
// curl error 60: error setting certificate verify locations
// using addslashes was the only way to avoid UPS returning the 1001 error: The XML document is not well formed
	$command = "".$curl_path." -d \"".addslashes($xmlRequest)."\" ".$url."";
	exec($command, $xmlResponse);
	if ( empty($xmlResponse) && $this->logfile) { // using exec no curl errors can be retrieved
		error_log("Error from cURL using exec() since there is no \$xmlResponse\n", 3, $this->logfile);
	}
	if ($this->logfile) {
		error_log("UPS RESPONSE using exec(): " . $xmlResponse[0] . "\n", 3, $this->logfile);
	}
	} elseif ($this->use_exec == '1') { // if NOT (function_exists('exec') && $this->use_exec == '1'
	if ($this->logfile) {
		error_log("Sorry, exec() cannot be called\n", 3, $this->logfile);
	}
	} else { // default behavior: cURL is assumed to be compiled in PHP
	$ch = curl_init();
	curl_setopt($ch, CURLOPT_URL, $url);
	// uncomment the next line if you get curl error 60: error setting certificate verify locations
	// curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
	// uncommenting the next line is most likely not necessary in case of error 60
	// curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
	curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
	curl_setopt($ch, CURLOPT_HEADER, 0);
	curl_setopt($ch, CURLOPT_POST, 1);
	curl_setopt($ch, CURLOPT_POSTFIELDS, $xmlRequest);
	curl_setopt($ch, CURLOPT_TIMEOUT, (int)$timeout);

	if ($this->logfile) {
		error_log("UPS REQUEST: " . $xmlRequest . "\n", 3, $this->logfile);
	}
	$xmlResponse = curl_exec ($ch);
	if (curl_errno($ch) && $this->logfile) {
	$error_from_curl = sprintf('Error [%d]: %s', curl_errno($ch), curl_error($ch));
		error_log("Error from cURL: " . $error_from_curl . "\n", 3, $this->logfile);
	}
// send email if enabled in the admin section
	if (curl_errno($ch) && $this->email_errors) {
	$error_from_curl = sprintf('Error [%d]: %s', curl_errno($ch), curl_error($ch));
	error_log("Error from cURL: " . $error_from_curl . " experienced by customer with id " . $_SESSION['customer_id'] . " on " . date('Y-m-d H:i:s'), 1, STORE_OWNER_EMAIL_ADDRESS);
	}
 // log errors to file ups_error.log when set
	if (curl_errno($ch) && $this->ups_error_file) {
	$error_from_curl = sprintf('Error [%d]: %s', curl_errno($ch), curl_error($ch));
	error_log(date('Y-m-d H:i:s')."\tcURL\t" . $error_from_curl . "\t" . $_SESSION['customer_id']."\n", 3, $this->ups_error_file);	
	}
	if ($this->logfile) {
		error_log("UPS RESPONSE: " . $xmlResponse . "\n", 3, $this->logfile);
	}
	curl_close ($ch);
	}

	if(!$xmlResponse || strstr(strtolower(substr($xmlResponse, 0, 120)), "bad request"))  {
/* Sometimes the UPS server responds with an HTML message (differing depending on whether the test server
  or the production server is used) but both have in the title tag "Bad request".
  Parsing this response will result in a fatal error:
  Call to a member function on a non-object in /blabla/includes/classes/xmldocument.php on line 57
  It only results in not showing Estimated Delivery Dates to the customer so avoiding the fatal error should do.
*/
		$xmlResponse = "<?xml version=\"1.0\"?>\n".
		"<RatingServiceSelectionResponse>\n".
		"   <Response>\n".
		"	   <TransactionReference>\n".
		"		   <CustomerContext>Rating and Service</CustomerContext>\n".
		"		   <XpciVersion>1.0001</XpciVersion>\n".
		"	   </TransactionReference>\n".
		"	   <ResponseStatusCode>0</ResponseStatusCode>\n".
		"	   <ResponseStatusDescription>". MODULE_SHIPPING_UPSXML_RATES_TEXT_COMM_UNKNOWN_ERROR ."</ResponseStatusDescription>\n".
		"   </Response>\n".
		"</RatingServiceSelectionResponse>\n";
	return $xmlResponse;
	}
	if ($this->use_exec == '1') {
	return $xmlResponse[0]; // $xmlResponse is an array in this case
	} else {
	return $xmlResponse;
	}
}

//*****************************
function _parseResult($xmlResult, $vendors_id) {
	// Parse XML message returned by the UPS post server.
	$doc = new XMLDocument();
	$xp = new XMLParser();
	$xp->setDocument($doc);
	$xp->parse($xmlResult);
	$doc = $xp->getDocument();
	// Get version. Must be xpci version 1.0001 or this might not work.
	$responseVersion = $doc->getValueByPath('RatingServiceSelectionResponse/Response/TransactionReference/XpciVersion');
	if ($this->xpci_version != $responseVersion) {
		$message = MODULE_SHIPPING_UPSXML_RATES_TEXT_COMM_VERSION_ERROR;
		return $message;
	}
	// Get response code. 1 = SUCCESS, 0 = FAIL
	$responseStatusCode = $doc->getValueByPath('RatingServiceSelectionResponse/Response/ResponseStatusCode');
	if ($responseStatusCode != '1') {
		$errorMsg = $doc->getValueByPath('RatingServiceSelectionResponse/Response/Error/ErrorCode');
		$errorMsg .= ": ";
		$errorMsg .= $doc->getValueByPath('RatingServiceSelectionResponse/Response/Error/ErrorDescription');
	// send email if enabled in the admin section
	if ($this->email_errors) {
	error_log("UPSXML Rates Error: " . $errorMsg . " experienced by customer with id " . $_SESSION['customer_id'] . " on " . date('Y-m-d H:i:s'), 1, STORE_OWNER_EMAIL_ADDRESS);
	}
	// log errors to file ups_error.log when set
	if ($this->ups_error_file) {
	error_log(date('Y-m-d H:i:s')."\tRates\t" . $errorMsg . "\t" . $_SESSION['customer_id']."\n", 3, $this->ups_error_file);	
	}
		return $errorMsg;
	}
	$root = $doc->getRoot();
	$ratedShipments = $root->getElementsByName("RatedShipment");
	$aryProducts = false;
	for ($i = 0; $i < count($ratedShipments); $i++) {
		$serviceCode = $ratedShipments[$i]->getValueByPath("/Service/Code");
		$totalCharge = $ratedShipments[$i]->getValueByPath("/TotalCharges/MonetaryValue");
		if (!($serviceCode && $totalCharge)) {
			continue;
		}
		$ratedPackages = $ratedShipments[$i]->getElementsByName("RatedPackage");
		$this->boxCount = count($ratedPackages);
		$gdaysToDelivery = $ratedShipments[$i]->getValueByPath("/GuaranteedDaysToDelivery");
		$scheduledTime = $ratedShipments[$i]->getValueByPath("/ScheduledDeliveryTime");
		$title = '';
		$title = $this->service_codes[$this->origin($vendors_id)][$serviceCode];

		$aryProducts[$i] = array($title => $totalCharge);
	}
	return $aryProducts;
}

// BOF Time In Transit

// GM 11-15-2004: renamed from _upsGetTime()
function _upsGetTimeServices($vendors_id) {

/*	  if (constant('MODULE_SHIPPING_UPSXML_DAYS_DELAY_' . $vendors_id) > 0) {
	$shipdate = date("Ymd", time()+(86400*constant('MODULE_SHIPPING_UPSXML_DAYS_DELAY_' . $vendors_id)));
  } else {
	$shipdate = $this->today;
  } */
if (constant('MODULE_SHIPPING_UPSXML_DAYS_DELAY_' . $vendors_id) > 0) {
$shipdate = date("Ymd", time()+(86400*constant('MODULE_SHIPPING_UPSXML_DAYS_DELAY_' . $vendors_id)));
$day_of_the_week = date ("w", time()+(86400*constant('MODULE_SHIPPING_UPSXML_DAYS_DELAY_' . $vendors_id)));
if ($day_of_the_week == "0" || $day_of_the_week == "7") { // order supposed to leave on Sunday => Monday
$shipdate = date("Ymd", time()+(86400*constant('MODULE_SHIPPING_UPSXML_DAYS_DELAY_' . $vendors_id)) + 86400);
} 
elseif ($day_of_the_week == "4") { // order supposed to leave on Thursday => Monday
$shipdate = date("Ymd", time()+(86400*constant('MODULE_SHIPPING_UPSXML_DAYS_DELAY_' . $vendors_id)) + 345600);

} 
elseif ($day_of_the_week == "5") { // order supposed to leave on Friday => Monday
$shipdate = date("Ymd", time()+(86400*constant('MODULE_SHIPPING_UPSXML_DAYS_DELAY_' . $vendors_id)) + 259200);

}
elseif ($day_of_the_week == "6") { // order supposed to leave on Saturday => Monday
$shipdate = date("Ymd", $this->today_unix_time + (86400*constant('MODULE_SHIPPING_UPSXML_DAYS_DELAY_' . $vendors_id)) + 172800);

}
} else {
$shipdate = $this->today;
}
	// Create the access request
  $accessRequestHeader =
	"<?xml version=\"1.0\"?>\n".
	"<AccessRequest xml:lang=\"en-US\">\n".
	"   <AccessLicenseNumber>". $this->access_key($vendors_id) ."</AccessLicenseNumber>\n".
	"   <UserId>". $this->access_username($vendors_id) ."</UserId>\n".
	"   <Password>". $this->access_password($vendors_id) ."</Password>\n".
	"</AccessRequest>\n";

	$timeintransitSelectionRequestHeader =
	"<?xml version=\"1.0\"?>\n".
	"<TimeInTransitRequest xml:lang=\"en-US\">\n".
	"   <Request>\n".
	"	   <TransactionReference>\n".
	"		   <CustomerContext>Time in Transit</CustomerContext>\n".
	"		   <XpciVersion>". $this->transitxpci_version ."</XpciVersion>\n".
	"	   </TransactionReference>\n".
	"	   <RequestAction>TimeInTransit</RequestAction>\n".
	"   </Request>\n".
	"   <TransitFrom>\n".
	"	   <AddressArtifactFormat>\n".
	"		   <PoliticalDivision2>". $this->origin_city($vendors_id) ."</PoliticalDivision2>\n".
	"		   <PoliticalDivision1>". $this->origin_stateprov($vendors_id) ."</PoliticalDivision1>\n".
	"		   <CountryCode>". $this->_upsOriginCountryCode ."</CountryCode>\n".
	"		   <PostcodePrimaryLow>". $this->origin_postalcode($vendors_id) ."</PostcodePrimaryLow>\n".
	"	   </AddressArtifactFormat>\n".
	"   </TransitFrom>\n".
	"   <TransitTo>\n".
	"	   <AddressArtifactFormat>\n".
	"		   <PoliticalDivision2>". $this->_upsDestCity ."</PoliticalDivision2>\n".
	"		   <PoliticalDivision1>". $this->_upsDestStateProv ."</PoliticalDivision1>\n".
	"		   <CountryCode>". $this->_upsDestCountryCode ."</CountryCode>\n".
	"		   <PostcodePrimaryLow>". $this->_upsDestPostalCode ."</PostcodePrimaryLow>\n".
	"		   <PostcodePrimaryHigh>". $this->_upsDestPostalCode ."</PostcodePrimaryHigh>\n".
	"	   </AddressArtifactFormat>\n".
	"   </TransitTo>\n".
	"   <PickupDate>" . $shipdate . "</PickupDate>\n".
	"   <ShipmentWeight>\n".
	"	   <UnitOfMeasurement>\n".
	"		   <Code>" . $this->unit_weight($vendors_id) . "</Code>\n".
	"	   </UnitOfMeasurement>\n".
	"	   <Weight>" . $this->weight_for_timeintransit . "</Weight>\n".
	"   </ShipmentWeight>\n".
	"   <InvoiceLineTotal>\n". 
	 " <CurrencyCode>" . constant('MODULE_SHIPPING_UPSXML_CURRENCY_CODE_' . $vendors_id) . "</CurrencyCode>\n".
//		"	   <CurrencyCode>" . MODULE_SHIPPING_UPSXML_CURRENCY_CODE_ . $vendors_id . "</CurrencyCode>\n".
//		"	   <MonetaryValue>100</MonetaryValue>\n".
	"	   <MonetaryValue>" . $this->pkgvalue($vendors_id) . "</MonetaryValue>\n".
	"   </InvoiceLineTotal>\n".
	"</TimeInTransitRequest>\n";

	$xmlTransitRequest = $accessRequestHeader .
	$timeintransitSelectionRequestHeader;

	//post request $strXML;
	$xmlTransitResult = $this->_post($this->protocol, $this->host($vendors_id), $this->port, $this->transitpath, $this->transitversion, $this->timeout, $xmlTransitRequest);
	return $this->_transitparseResult($xmlTransitResult);
}

//***************************************

// GM 11-15-2004: modified to return array with time for each service, as
//				opposed to single transit time for hardcoded "GND" code

function _transitparseResult($xmlTransitResult) {
		   $transitTime = array();

	// Parse XML message returned by the UPS post server.
	$doc = new XMLDocument();
	$xp = new XMLParser();
	$xp->setDocument($doc);
	$xp->parse($xmlTransitResult);
	$doc = $xp->getDocument();
	// Get version. Must be xpci version 1.0001 or this might not work.
// 1.0001 and 1.0002 seem to be very similar, forget about this for the moment
/*		$responseVersion = $doc->getValueByPath('TimeInTransitResponse/Response/TransactionReference/XpciVersion');
	if ($this->transitxpci_version != $responseVersion) {
		$message = MODULE_SHIPPING_UPSXML_RATES_TEXT_COMM_VERSION_ERROR;
		return $message;
	} */
	$responseVersion = $doc->getValueByPath('TimeInTransitResponse/Response/TransactionReference/XpciVersion');
	if ($this->transitxpci_version != $responseVersion) {
		$message = MODULE_SHIPPING_UPSXML_RATES_TEXT_COMM_VERSION_ERROR;
		return $message;
	}
	// Get response code. 1 = SUCCESS, 0 = FAIL
	$responseStatusCode = $doc->getValueByPath('TimeInTransitResponse/Response/ResponseStatusCode');
	if ($responseStatusCode != '1') {
		$errorMsg = $doc->getValueByPath('TimeInTransitResponse/Response/Error/ErrorCode');
		$errorMsg .= ": ";
		$errorMsg .= $doc->getValueByPath('TimeInTransitResponse/Response/Error/ErrorDescription');
	// send email if enabled in the admin section
	if ($this->email_errors) {
	error_log("UPSXML TimeInTransit Error: " . $errorMsg . " experienced by customer with id " . $_SESSION['customer_id'] . " on " . date('Y-m-d H:i:s'), 1, STORE_OWNER_EMAIL_ADDRESS);
	}
	// log errors to file ups_error.log when set
	if ($this->ups_error_file) {
	error_log(date('Y-m-d H:i:s')."\tTimeInTransit\t" . $errorMsg . "\t" . $_SESSION['customer_id'] ."\n", 3, $this->ups_error_file);	
	}
	return $errorMsg;
		return $errorMsg;
	}
	$root = $doc->getRoot();
	$rootChildren = $root->getChildren();
	for ($r = 0; $r < count($rootChildren); $r++) {
		$elementName = $rootChildren[$r]->getName();
		if ($elementName == "TransitResponse") {
			$transitResponse = $root->getElementsByName("TransitResponse");
			$serviceSummary = $transitResponse['0']->getElementsByName("ServiceSummary");
			$this->numberServices = count($serviceSummary);
			for ($s = 0; $s < $this->numberServices; $s++) {
							 // index by Desc because that's all we can relate back to the service with
							// (though it can probably return the code as well..)
				$serviceDesc = $serviceSummary[$s]->getValueByPath("Service/Description");

							$transitTime[$serviceDesc]["days"] = $serviceSummary[$s]->getValueByPath("EstimatedArrival/BusinessTransitDays");
							$transitTime[$serviceDesc]["date"] = $serviceSummary[$s]->getValueByPath("EstimatedArrival/Date");
							$transitTime[$serviceDesc]["guaranteed"] = $serviceSummary[$s]->getValueByPath("Guaranteed/Code");
			}
		}
	}
	if ($this->logfile) {
		error_log("------------------------------------------\n", 3, $this->logfile);
			  foreach($transitTime as $desc => $time) {
				 error_log("Business Transit: " . $desc ." = ". $time["date"] . "\n", 3, $this->logfile);
			  }
	}
	return $transitTime;
}

//EOF Time In Transit

}

//***************************
 function exclude_choices($type, $vendors_id) {
// used for exclusion of UPS shipping options, read from db
$disallowed_types = explode(",", @constant('MODULE_SHIPPING_UPSXML_TYPES_' . $vendors_id));
if (strstr($type, "UPS")) {
	// this will chop off "UPS" from the beginning of the line - typically something like UPS Next Day Air (1 Business Days)
  $type_minus_ups = explode("UPS", $type );
	$type_root = trim($type_minus_ups[1]);
} elseif (strstr($type, "(")) {
  $type_root = trim($type);
}
for ($za = 0; $za < count ($disallowed_types); $za++ ) {
  if ($type_root == trim($disallowed_types[$za])) {
	return true;
	exit;
  } // end if ($type_root == $disallowed_types[$za] ...
}
// if the type is not disallowed:
return false;
}

//******************************
function ready_to_shipCmp( $a, $b) {
if ( $a['ready_to_ship'] == $b['ready_to_ship'] )
return 0;
if ( $a['ready_to_ship'] > $b['ready_to_ship'] )
return -1;
return 1;
}

?>

Edited by HallMarc

Share this post


Link to post
Share on other sites
Thank you for a great contribution.
Thanks, but it's not mine really. I just did some bug fixes and added some nice things to have.
I am trying to get the latest version adapted for MVS.
That is quite a job, chapeau!

However, I haven't worked out the length,width,height calculator (it is reporting different dimensions than the product description, i.e. product list with12x12x12 and when I look at the UPSXML.log I see 10x6x6) and it is calculating for all products no matter what vendor they are being shipped with which returns an inaccuarate rate from UPS. I don't know if the Insrance add-in is functioning correctly yet or not.

IMO the insurance stuff was left out of the XML request code as far as I can see.

 

A few things I saw: Line 208 and further, the bug fix for the test server always being used was not added:

function host($vendors_id) {
// next line with bug (ancient one)
// $this->host = constant('MODULE_SHIPPING_UPSXML_RATES_MODE_' . $vendors_id) == 'Test' ? 'wwwcie.ups.com' : 'wwwcie.ups.com';
$this->host = constant('MODULE_SHIPPING_UPSXML_RATES_MODE_' . $vendors_id) == 'Test' ? 'wwwcie.ups.com' : 'www.ups.com';
return $this->host;
}

Line 319 is what got you in trouble I think (all packages quoted for):

if ($product_data['vendors_id'] = $vendors_id)

Should be:

if ($product_data['vendors_id'] == $vendors_id)

Line 404-407: debug code uncommented (but you know that I guess, I think I saw it one more time later on).

 

At the bottom: function exclude_choices (was trimmed down from earlier versions due to the fixes that were made to _upsGetTimeServices)

} elseif (strstr($type, "(")) {
$type_root = trim($type);
}

Should be:

} else {
$type_root = trim($type);
}

You absolutely need the new function getPackagesByVol() because in the "old" code the volume of the box was calculated later and added to the array, but now it is calculated by MySQL (resulting in the need for several bug fixes later >_< ). That is not set in your code now. Also the code needs the boxes to be in volume order, not package cost order.

 

Hope this fixes your problems.

Share this post


Link to post
Share on other sites
I've thought of a different way of accomplishing this- by having a second UPSXML module that only quotes for Next Day Air and doesn't have the restriction on shipping on Thursday (I'm really nuking this out :) ).

 

Question: how can I modify the module so that it doesn't display the line that the module title and icon usually appear on? I've gotten to the point where the line is blank, but I'd like it to not have that line at all, for cosmetic reasons.

 

Also, semi-related: can this module quote for Saturday delivery?

 

Hey Jan-

 

Sorry to double-post, but I figured you missed this one with all the discussion of the MVS module (thanks for the help with that!).

 

Also, about my workaround for my Next Day Air $shipdate issue, I believe this will make checkout_shipping.php take a lot longer to load, no? Because I'm adding in more modules for the script to deal with?

 

Cheers

Stew


Do, or do not. There is no try.

 

Order Editor 5.0.6 "Ultra Violet" is now available!

For support or to post comments, suggestions, etc, please visit the Order Editor support thread.

Share this post


Link to post
Share on other sites

Jan,

I did the few things you posted and I am still seeing this in the request

			 <PackagingType>
		   <Code>02</Code>
	   </PackagingType>
	   <Dimensions>
		   <UnitOfMeasurement>
			   <Code>IN</Code>
		   </UnitOfMeasurement>
		   <Length>10.00</Length>
		   <Width>6.00</Width>
		   <Height>6.00</Height>
	   </Dimensions>
	   <PackageWeight>
		   <UnitOfMeasurement>
			   <Code>LBS</Code>
		   </UnitOfMeasurement>
		   <Weight>7.5</Weight>
	   </PackageWeight>
   </Package>
   <Package>
	   <PackagingType>
		   <Code>02</Code>
	   </PackagingType>
	   <Dimensions>
		   <UnitOfMeasurement>
			   <Code>IN</Code>
		   </UnitOfMeasurement>
		   <Length>10.00</Length>
		   <Width>6.00</Width>
		   <Height>6.00</Height>
	   </Dimensions>
	   <PackageWeight>
		   <UnitOfMeasurement>
			   <Code>LBS</Code>
		   </UnitOfMeasurement>
		   <Weight>7.5</Weight>
	   </PackageWeight>
   </Package>
  </Shipment>
  <CustomerClassification>
   <Code>01</Code>
</CustomerClassification>
</RatingServiceSelectionRequest>

 

The weight is correct but the lwh should be reading 12x12x12. I know you have put in code that converts to volume so why is it reporting this? It's only one item and it is reporting two!! Wasn't doing that before.

Edited by HallMarc

Share this post


Link to post
Share on other sites

I just ran it again and what is actually happening is it is send the XML requests twice and in the second rate request is when it doubles the cart contents. Something isn't being unset.

Edited by HallMarc

Share this post


Link to post
Share on other sites

Here is the log minus UPS response

 

------------------------------------------
DATE AND TIME: 2006-02-22 10:27:08
UPS URL: https://wwwcie.ups.com:443/ups.app/xml/TimeInTransit
UPS REQUEST: <?xml version="1.0"?>
<AccessRequest xml:lang="en-US">
  <AccessLicenseNumber>**********</AccessLicenseNumber>
  <UserId>**********</UserId>
  <Password>**********</Password>
</AccessRequest>
<?xml version="1.0"?>
<TimeInTransitRequest xml:lang="en-US">
  <Request>
   <TransactionReference>
	   <CustomerContext>Time in Transit</CustomerContext>
	   <XpciVersion>1.0002</XpciVersion>
   </TransactionReference>
   <RequestAction>TimeInTransit</RequestAction>
  </Request>
  <TransitFrom>
   <AddressArtifactFormat>
	   <PoliticalDivision2>Van Nuys</PoliticalDivision2>
	   <PoliticalDivision1>CA</PoliticalDivision1>
	   <CountryCode>US</CountryCode>
	   <PostcodePrimaryLow>94106</PostcodePrimaryLow>
   </AddressArtifactFormat>
  </TransitFrom>
  <TransitTo>
   <AddressArtifactFormat>
	   <PoliticalDivision2>Havertown</PoliticalDivision2>
	   <PoliticalDivision1>PA</PoliticalDivision1>
	   <CountryCode>US</CountryCode>
	   <PostcodePrimaryLow>19083</PostcodePrimaryLow>
	   <PostcodePrimaryHigh>19083</PostcodePrimaryHigh>
   </AddressArtifactFormat>
  </TransitTo>
  <PickupDate>20060227</PickupDate>
  <ShipmentWeight>
   <UnitOfMeasurement>
	   <Code>LBS</Code>
   </UnitOfMeasurement>
   <Weight>7.5</Weight>
  </ShipmentWeight>
  <InvoiceLineTotal>
<CurrencyCode>USD</CurrencyCode>
   <MonetaryValue>0</MonetaryValue>
  </InvoiceLineTotal>
</TimeInTransitRequest>


------------------------------------------
------------------------------------------
Time in Transit: 0
------------------------------------------
DATE AND TIME: 2006-02-22 10:27:09
UPS URL: https://wwwcie.ups.com:443/ups.app/xml/Rate
UPS REQUEST: <?xml version="1.0"?>
<AccessRequest xml:lang="en-US">
  <AccessLicenseNumber>**********</AccessLicenseNumber>
  <UserId>**********</UserId>
  <Password>**********</Password>
</AccessRequest>
<?xml version="1.0"?>
<RatingServiceSelectionRequest xml:lang="en-US">
  <Request>
   <TransactionReference>
	   <CustomerContext>Rating and Service</CustomerContext>
	   <XpciVersion>1.0001</XpciVersion>
   </TransactionReference>
   <RequestAction>Rate</RequestAction>
   <RequestOption>shop</RequestOption>
  </Request>
  <PickupType>
   <Code>01</Code>
  </PickupType>
  <Shipment>
   <Shipper>
	   <Address>
		   <City>Van Nuys</City>
		   <StateProvinceCode>CA</StateProvinceCode>
		   <CountryCode>US</CountryCode>
		   <PostalCode>94106</PostalCode>
	   </Address>
   </Shipper>
   <ShipTo>
	   <Address>
		   <City>Havertown</City>
		   <StateProvinceCode>PA</StateProvinceCode>
		   <CountryCode>US</CountryCode>
		   <PostalCode>19083</PostalCode>
	   </Address>
   </ShipTo>
   <Package>
	   <PackagingType>
		   <Code>02</Code>
	   </PackagingType>
	   <Dimensions>
		   <UnitOfMeasurement>
			   <Code>IN</Code>
		   </UnitOfMeasurement>
		   <Length>10.00</Length>
		   <Width>6.00</Width>
		   <Height>6.00</Height>
	   </Dimensions>
	   <PackageWeight>
		   <UnitOfMeasurement>
			   <Code>LBS</Code>
		   </UnitOfMeasurement>
		   <Weight>7.5</Weight>
	   </PackageWeight>
   </Package>
  </Shipment>
  <CustomerClassification>
   <Code>01</Code>
</CustomerClassification>
</RatingServiceSelectionRequest>


------------------------------------------
DATE AND TIME: 2006-02-22 10:27:10
UPS URL: https://wwwcie.ups.com:443/ups.app/xml/TimeInTransit
UPS REQUEST: <?xml version="1.0"?>
<AccessRequest xml:lang="en-US">
  <AccessLicenseNumber>**********</AccessLicenseNumber>
  <UserId>**********</UserId>
  <Password>**********</Password>
</AccessRequest>
<?xml version="1.0"?>
<TimeInTransitRequest xml:lang="en-US">
  <Request>
   <TransactionReference>
	   <CustomerContext>Time in Transit</CustomerContext>
	   <XpciVersion>1.0002</XpciVersion>
   </TransactionReference>
   <RequestAction>TimeInTransit</RequestAction>
  </Request>
  <TransitFrom>
   <AddressArtifactFormat>
	   <PoliticalDivision2>Van Nuys</PoliticalDivision2>
	   <PoliticalDivision1>CA</PoliticalDivision1>
	   <CountryCode>US</CountryCode>
	   <PostcodePrimaryLow>94106</PostcodePrimaryLow>
   </AddressArtifactFormat>
  </TransitFrom>
  <TransitTo>
   <AddressArtifactFormat>
	   <PoliticalDivision2>Havertown</PoliticalDivision2>
	   <PoliticalDivision1>PA</PoliticalDivision1>
	   <CountryCode>US</CountryCode>
	   <PostcodePrimaryLow>19083</PostcodePrimaryLow>
	   <PostcodePrimaryHigh>19083</PostcodePrimaryHigh>
   </AddressArtifactFormat>
  </TransitTo>
  <PickupDate>20060227</PickupDate>
  <ShipmentWeight>
   <UnitOfMeasurement>
	   <Code>LBS</Code>
   </UnitOfMeasurement>
   <Weight>7.5</Weight>
  </ShipmentWeight>
  <InvoiceLineTotal>
<CurrencyCode>USD</CurrencyCode>
   <MonetaryValue>0</MonetaryValue>
  </InvoiceLineTotal>
</TimeInTransitRequest>

------------------------------------------
------------------------------------------
Time in Transit: 0
------------------------------------------
DATE AND TIME: 2006-02-22 10:27:14
UPS URL: https://wwwcie.ups.com:443/ups.app/xml/Rate
UPS REQUEST: <?xml version="1.0"?>
<AccessRequest xml:lang="en-US">
  <AccessLicenseNumber>**********</AccessLicenseNumber>
  <UserId>**********</UserId>
  <Password>**********</Password>
</AccessRequest>
<?xml version="1.0"?>
<RatingServiceSelectionRequest xml:lang="en-US">
  <Request>
   <TransactionReference>
	   <CustomerContext>Rating and Service</CustomerContext>
	   <XpciVersion>1.0001</XpciVersion>
   </TransactionReference>
   <RequestAction>Rate</RequestAction>
   <RequestOption>shop</RequestOption>
  </Request>
  <PickupType>
   <Code>01</Code>
  </PickupType>
  <Shipment>
   <Shipper>
	   <Address>
		   <City>Van Nuys</City>
		   <StateProvinceCode>CA</StateProvinceCode>
		   <CountryCode>US</CountryCode>
		   <PostalCode>94106</PostalCode>
	   </Address>
   </Shipper>
   <ShipTo>
	   <Address>
		   <City>Havertown</City>
		   <StateProvinceCode>PA</StateProvinceCode>
		   <CountryCode>US</CountryCode>
		   <PostalCode>19083</PostalCode>
	   </Address>
   </ShipTo>
   <Package>
	   <PackagingType>
		   <Code>02</Code>
	   </PackagingType>
	   <Dimensions>
		   <UnitOfMeasurement>
			   <Code>IN</Code>
		   </UnitOfMeasurement>
		   <Length>10.00</Length>
		   <Width>6.00</Width>
		   <Height>6.00</Height>
	   </Dimensions>
	   <PackageWeight>
		   <UnitOfMeasurement>
			   <Code>LBS</Code>
		   </UnitOfMeasurement>
		   <Weight>7.5</Weight>
	   </PackageWeight>
   </Package>
   <Package>
	   <PackagingType>
		   <Code>02</Code>
	   </PackagingType>
	   <Dimensions>
		   <UnitOfMeasurement>
			   <Code>IN</Code>
		   </UnitOfMeasurement>
		   <Length>10.00</Length>
		   <Width>6.00</Width>
		   <Height>6.00</Height>
	   </Dimensions>
	   <PackageWeight>
		   <UnitOfMeasurement>
			   <Code>LBS</Code>
		   </UnitOfMeasurement>
		   <Weight>7.5</Weight>
	   </PackageWeight>
   </Package>
  </Shipment>
  <CustomerClassification>
   <Code>01</Code>
</CustomerClassification>
</RatingServiceSelectionRequest>

Share this post


Link to post
Share on other sites

I need a bit of help please with this module. I've got it working, had to take out the "EED" because that part wouldn't work right but now the only problem I seem to be experiencing is a lack of detail in one of the shipping options.

 

What I mean is this. I've left only 4 shipping options active. Ground, Standard, Express and Express saver. The Standard, Express and Express Saver all show up properly, but Ground does not shop up at all and there is instead a shipping price without a name. If I click to disable every shipping option, this one without a name still shows up.

 

Any guidance would be appreciated.

 

Thanks

Share this post


Link to post
Share on other sites
Here is the log minus UPS response

 

			   <Length>10.00</Length>
		   <Width>6.00</Width>
		   <Height>6.00</Height>

I have been through your code a couple of times and I don't see anything strange (apart from the things I posted about earlier). Were do these numbers for length, width, and height come from? Are those dimensions for a box? They don't seem to come from your product because you said you entered that in the admin as 12x12x12 didn't you?

 

Also I'm not 100% sure that the $vendors_id that you bring in to the class through the function quote is available as a (class) variable for all the other things were it is needed. I might be wrong.

 

If you change (your) line 746-249:

for ($b = 0; $b < count($emptyBoxesArray) && tep_not_null($productsRemaining); $b++) {
$result = $this->fitProductsInBox($productsRemaining, $emptyBoxesArray[$b], $packedBoxesArray, $b, count($emptyBoxesArray) -1 );
$packedBoxesArray = $result['packed_boxes'];
$productsRemaining = $result['remaining'];

To:

			for ($b = 0; $b < count($emptyBoxesArray) && tep_not_null($productsRemaining); $b++) {
			$result = $this->fitProductsInBox($productsRemaining, $emptyBoxesArray[$b], $packedBoxesArray, $b, count($emptyBoxesArray) -1 );
	echo '<pre>Results: ';
	print_r($result);
	echo '<br>';

			$packedBoxesArray = $result['packed_boxes'];
			$productsRemaining = $result['remaining'];

You can follow the emptying of the productRemaining array and filling up of the $packedBoxes with all the product details. Perhaps you get a clue there about what goes wrong.

Share this post


Link to post
Share on other sites
What I mean is this. I've left only 4 shipping options active. Ground, Standard, Express and Express saver. The Standard, Express and Express Saver all show up properly, but Ground does not shop up at all and there is instead a shipping price without a name. If I click to disable every shipping option, this one without a name still shows up.
Weird. It could mean UPS has a new shipping option that hasn't been defined in the language file (but that seems unlikely). Better enable full logging, to see what that Shipping option is.

 

Also, I don't quite follow you. Express and Express saver are not shipping methods in the US. And then only shipments from the US can have Ground as a shipping method.

 

No other shipments than from US and Puerto Rico origin have a shipping option called "UPS Ground" (according to the developer docs for the Rates and Service Selection of January 1, 2006).

Share this post


Link to post
Share on other sites
I have been through your code a couple of times and I don't see anything strange (apart from the things I posted about earlier). Were do these numbers for length, width, and height come from? Are those dimensions for a box? They don't seem to come from your product because you said you entered that in the admin as 12x12x12 didn't you?

 

Also I'm not 100% sure that the $vendors_id that you bring in to the class through the function quote is available as a (class) variable for all the other things were it is needed. I might be wrong.

 

If you change (your) line 746-249:

for ($b = 0; $b < count($emptyBoxesArray) && tep_not_null($productsRemaining); $b++) {
$result = $this->fitProductsInBox($productsRemaining, $emptyBoxesArray[$b], $packedBoxesArray, $b, count($emptyBoxesArray) -1 );
$packedBoxesArray = $result['packed_boxes'];
$productsRemaining = $result['remaining'];

To:

			for ($b = 0; $b < count($emptyBoxesArray) && tep_not_null($productsRemaining); $b++) {
			$result = $this->fitProductsInBox($productsRemaining, $emptyBoxesArray[$b], $packedBoxesArray, $b, count($emptyBoxesArray) -1 );
	echo '<pre>Results: ';
	print_r($result);
	echo '<br>';

			$packedBoxesArray = $result['packed_boxes'];
			$productsRemaining = $result['remaining'];

You can follow the emptying of the productRemaining array and filling up of the $packedBoxes with all the product details. Perhaps you get a clue there about what goes wrong.

Results: Array
(
[remaining] => Array
	(
		[0] => Array
			(
				[id] => 11
				[name] => Fire Down Below
				[model] => DVD-FDBL
				[image] => dvd/fire_down_below.gif
				[price] => 47.3000
				[quantity] => 1
				[weight] => 7.000
				[final_price] => 47.3
				[tax_class_id] => 1
				[attributes] => 
				[attributes_values] => 
				[vendors_id] => 1
				[vendors_name] => My Store
				[height] => 6.5
				[width] => 6.5
				[length] => 6.5
			)

	)

[box_no] => 0
[packed_boxes] => Array
	(
	)

)
Results: Array
(
[remaining] => Array
	(
		[0] => Array
			(
				[id] => 11
				[name] => Fire Down Below
				[model] => DVD-FDBL
				[image] => dvd/fire_down_below.gif
				[price] => 47.3000
				[quantity] => 1
				[weight] => 7.000
				[final_price] => 47.3
				[tax_class_id] => 1
				[attributes] => 
				[attributes_values] => 
				[vendors_id] => 1
				[vendors_name] => My Store
				[height] => 6.5
				[width] => 6.5
				[length] => 6.5
			)

	)

[box_no] => 1
[packed_boxes] => Array
	(
	)

)
Results: Array
(
[remaining] => Array
	(
		[0] => Array
			(
				[id] => 11
				[name] => Fire Down Below
				[model] => DVD-FDBL
				[image] => dvd/fire_down_below.gif
				[price] => 47.3000
				[quantity] => 1
				[weight] => 7.000
				[final_price] => 47.3
				[tax_class_id] => 1
				[attributes] => 
				[attributes_values] => 
				[vendors_id] => 1
				[vendors_name] => My Store
				[height] => 6.5
				[width] => 6.5
				[length] => 6.5
			)

	)

[box_no] => 2
[packed_boxes] => Array
	(
	)

)
Results: Array
(
[remaining] => Array
	(
		[0] => Array
			(
				[id] => 11
				[name] => Fire Down Below
				[model] => DVD-FDBL
				[image] => dvd/fire_down_below.gif
				[price] => 47.3000
				[quantity] => 1
				[weight] => 7.000
				[final_price] => 47.3
				[tax_class_id] => 1
				[attributes] => 
				[attributes_values] => 
				[vendors_id] => 1
				[vendors_name] => My Store
				[height] => 6.5
				[width] => 6.5
				[length] => 6.5
			)

	)

[box_no] => 3
[packed_boxes] => Array
	(
	)

)
Results: Array
(
[remaining] => Array
	(
	)

[box_no] => 4
[packed_boxes] => Array
	(
		[0] => Array
			(
				[id] => 1
				[name] => 6x3x3
				[description] => Box
				[length] => 10.00
				[width] => 6.00
				[height] => 6.00
				[empty_weight] => 0.50
				[max_weight] => 40.00
				[volume] => 360.00
				[remaining_volume] => 85.375
				[current_weight] => 7.5
				[products] => Array
					(
						[0] => Array
							(
								[id] => 11
								[name] => Fire Down Below
								[model] => DVD-FDBL
								[image] => dvd/fire_down_below.gif
								[price] => 47.3000
								[quantity] => 1
								[weight] => 7.000
								[final_price] => 47.3
								[tax_class_id] => 1
								[attributes] => 
								[attributes_values] => 
								[vendors_id] => 1
								[vendors_name] => My Store
								[height] => 6.5
								[width] => 6.5
								[length] => 6.5
							)

					)

			)

	)

)
Results: Array
(
[remaining] => Array
	(
		[0] => Array
			(
				[id] => 11
				[name] => Fire Down Below
				[model] => DVD-FDBL
				[image] => dvd/fire_down_below.gif
				[price] => 47.3000
				[quantity] => 1
				[weight] => 7.000
				[final_price] => 47.3
				[tax_class_id] => 1
				[attributes] => 
				[attributes_values] => 
				[vendors_id] => 1
				[vendors_name] => My Store
				[height] => 6.5
				[width] => 6.5
				[length] => 6.5
			)

	)

[box_no] => 0
[packed_boxes] => Array
	(
	)

)
Results: Array
(
[remaining] => Array
	(
		[0] => Array
			(
				[id] => 11
				[name] => Fire Down Below
				[model] => DVD-FDBL
				[image] => dvd/fire_down_below.gif
				[price] => 47.3000
				[quantity] => 1
				[weight] => 7.000
				[final_price] => 47.3
				[tax_class_id] => 1
				[attributes] => 
				[attributes_values] => 
				[vendors_id] => 1
				[vendors_name] => My Store
				[height] => 6.5
				[width] => 6.5
				[length] => 6.5
			)

	)

[box_no] => 1
[packed_boxes] => Array
	(
	)

)
Results: Array
(
[remaining] => Array
	(
		[0] => Array
			(
				[id] => 11
				[name] => Fire Down Below
				[model] => DVD-FDBL
				[image] => dvd/fire_down_below.gif
				[price] => 47.3000
				[quantity] => 1
				[weight] => 7.000
				[final_price] => 47.3
				[tax_class_id] => 1
				[attributes] => 
				[attributes_values] => 
				[vendors_id] => 1
				[vendors_name] => My Store
				[height] => 6.5
				[width] => 6.5
				[length] => 6.5
			)

	)

[box_no] => 2
[packed_boxes] => Array
	(
	)

)
Results: Array
(
[remaining] => Array
	(
		[0] => Array
			(
				[id] => 11
				[name] => Fire Down Below
				[model] => DVD-FDBL
				[image] => dvd/fire_down_below.gif
				[price] => 47.3000
				[quantity] => 1
				[weight] => 7.000
				[final_price] => 47.3
				[tax_class_id] => 1
				[attributes] => 
				[attributes_values] => 
				[vendors_id] => 1
				[vendors_name] => My Store
				[height] => 6.5
				[width] => 6.5
				[length] => 6.5
			)

	)

[box_no] => 3
[packed_boxes] => Array
	(
	)

)
Results: Array
(
[remaining] => Array
	(
	)

[box_no] => 4
[packed_boxes] => Array
	(
		[0] => Array
			(
				[id] => 1
				[name] => 6x3x3
				[description] => Box
				[length] => 10.00
				[width] => 6.00
				[height] => 6.00
				[empty_weight] => 0.50
				[max_weight] => 40.00
				[volume] => 360.00
				[remaining_volume] => 85.375
				[current_weight] => 7.5
				[products] => Array
					(
						[0] => Array
							(
								[id] => 11
								[name] => Fire Down Below
								[model] => DVD-FDBL
								[image] => dvd/fire_down_below.gif
								[price] => 47.3000
								[quantity] => 1
								[weight] => 7.000
								[final_price] => 47.3
								[tax_class_id] => 1
								[attributes] => 
								[attributes_values] => 
								[vendors_id] => 1
								[vendors_name] => My Store
								[height] => 6.5
								[width] => 6.5
								[length] => 6.5
							)

					)

			)

	)

)

 

 

Um yikes. I don't know where it is getting 6.5x6.5x6.5. The packing box dimensions it is getting from my UPS packaging table

Edited by HallMarc

Share this post


Link to post
Share on other sites
Um yikes. I don't know where it is getting 6.5x6.5x6.5. The packing box dimensions it is getting from my UPS packaging table
It is calculating that from the weight of the product, assuming a density of 0.7:

// sanity checks on the product
if (!$this->fitsInBox($product, $emptyBoxesArray[$index_of_largest_box])) {
$product['ready_to_ship'] = '1';
}
if (($product['length'] == 0 || $product['width'] == 0 || $product['height'] == 0) && $product['weight'] > 0) {
$density = 0.7;
if ($this->unit_length == 'CM') {
$product['length']=$product['width']=$product['height']= round(10*(pow($product['weight']/$density, 1/3)),1);
} else {
// non-metric: inches and pounds
$product['length']=$product['width']=$product['height']= round(pow($product['weight']*27.67/$density, 1/3),1);
}
} // end sanity check

6.5 inch * 2.54 = 16.5 cm (1.65 dm). 1.65 x 1.65 x 1.65 = 4.5 liter. 4.5 liter * .7 = 3.15 kg. 3.15 kg/0.453 (1 lbs = 0.453 kg) = 6.95 lbs. Taking into consideration rounding errors, this must be the reason. Apparently, one of the dimensions of the product is zero.

Share this post


Link to post
Share on other sites
6.5 inch * 2.54 = 16.5 cm (1.65 dm). 1.65 x 1.65 x 1.65 = 4.5 liter. 4.5 liter * .7 = 3.15 kg. 3.15 kg/0.453 (1 lbs = 0.453 kg) = 6.95 lbs. Taking into consideration rounding errors, this must be the reason. Apparently, one of the dimensions of the product is zero.

None of the dimensions are zero. And how is it getting 6.5inches from 12inches?

Share this post


Link to post
Share on other sites
Also, I don't quite follow you. Express and Express saver are not shipping methods in the US. And then only shipments from the US can have Ground as a shipping method.

 

No other shipments than from US and Puerto Rico origin have a shipping option called "UPS Ground" (according to the developer docs for the Rates and Service Selection of January 1, 2006).

 

You're entirely right about that, Express and Express Saver are both options in Canada and it turns out that Ground is not an option for Canada which is why it's not showing up, so it boils down to finding out why I am getting one option with no name. The other odd thing is that if you chose the "no name" shipping option, then click continue in the checkout process, shipping switches to standard and the standard price instead of the price that was associated with the "no name" shipping.

 

So, how do I turn on full logging? and what exactly am I looking for? I'm very new to php.

 

Robin

Share this post


Link to post
Share on other sites
You're entirely right about that, Express and Express Saver are both options in Canada and it turns out that Ground is not an option for Canada which is why it's not showing up, so it boils down to finding out why I am getting one option with no name. The other odd thing is that if you chose the "no name" shipping option, then click continue in the checkout process, shipping switches to standard and the standard price instead of the price that was associated with the "no name" shipping.

 

So, how do I turn on full logging? and what exactly am I looking for? I'm very new to php.

 

Robin

 

Did you change the names of the service type options in the language definition file or otherwise modify the module?


Do, or do not. There is no try.

 

Order Editor 5.0.6 "Ultra Violet" is now available!

For support or to post comments, suggestions, etc, please visit the Order Editor support thread.

Share this post


Link to post
Share on other sites
Did you change the names of the service type options in the language definition file or otherwise modify the module?

 

No, I didn't. I looked at it, as instructed in the "read me" file that came with the contribution, to see what shipping options applied to Canada. That's when I realized why "Ground" was not showing up. But other than reading it, I didn't touch it.

 

Robin

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×