Jump to content
  • Checkout
  • Login
  • Get in touch

osCommerce

The e-commerce.

Question about UPS


fribhey

Recommended Posts

does anyone know how i can limit the UPS options to only these four:

Ground

3 Day Select

2nd Day Air

Next Day Air Saver

 

right now these are the options available to the customer:

Next Day Air Early AM

Next Day Air

Next Day Air Saver

2nd Day Air

3 Day Select

Ground

Link to comment
Share on other sites

  • 1 month later...
  • 3 weeks later...

Hi all, yes I am a newbie to OSCommerce, but I am initmatley fimiliar with PHP and PERL. I do have a solution to your question. It may not be the cleanest solution available, but since no one has posted one, this one will get you going. It worked great for me!

 

Look this the snippit of code below in the "modules/shipping/ups.php" file:

 

for ($i; $i<$qsize; $i++) {
? ? ? ? ?list($type, $cost) = each($upsQuote[$i]);
? ? ? ? ?$methods[] = array('id' => $type,
? ? ? ? ?'title' => $this->types[$type],
? ? ? ? ?'cost' => ($cost + MODULE_SHIPPING_UPS_HANDLING) * ? ? $shipping_num_boxes);

 

Should be somewhere around line 99 or so.

 

The line

for ($i; $i<$qsize; $i++) {

is what we are going to be changing.

 

this is the line of code that loops through the enumeration of the different types of shipping UPS offers.

 

Changing the code to this:

 

for ($i=3; $i<$qsize; $i++) {

 

(notice the new "=3" right behind the first $i) will prevent the module from displaying the first three shipping options (essentially telling the php engine to skip the first three entires, typically the overnight's). The lower the number (3, in this case) the fewer methods it will truncate off the top of the "UPS Shipping" list. the higher, the more it removes.

 

to remove items off the bottom of the list (say you don't offer ground shipping)

change the line to look like this:

 

for ($i; $i<$qsize-1; $i++) {

 

notice the "-1" behind "$qsize"

 

This will remove the ground shipping. the "-1" is actually means "$qsize MINUS 1" - it's not a negative number, you're doing math here. So, the higher the number the more methods you remove from the bottom of the list. (a "2" would remove the "ground" and the "3 Day Select" options).

 

Give it a try. Hope this helps and no one gets upset because my first post here is so long. :thumbsup:

 

mpiscopo, sorry, I don't know what the "hundreweight" service is, can't help ya there.

 

Victor

Edited by vshortt
Link to comment
Share on other sites

Victor;

 

No worries about anyone getting upset about a long post - your post was very informative, with examples and an excellent explanation! Actually, there is a contribution already available which limits the methods which are made available to the customer called UPS Choice.

 

Victor, I do have another request if you might be willing to take a look at it...

 

The contribution mentioned above adds a new function (tep_cfg_select_multioption) to the general functions file for osC and then utilizes a new key in the configuration table to allow for selecting which options are to be made available from the Admin area for the shipping module. This is all very slick and works very nicely, but there are a couple of problems:

 

It is based on the original UPS module from osC, which utilizes an HTML request to the UPS API. This method is deprecated and may not be supported by UPS at some point in the future. The UPS XML Rates and Services contribution utilizes an XML request method, produces more accurate quotes and has the option to add package dimensions to the request

 

BUT... it does not allow for the selection of methods as in the UPS Choice module.

 

I have been struggling for several weeks to get the method selection capability to work in the XML version, without success.

 

It might be of some help that the format of the code which gives this selectability in the UPS Choice module (an HTML request method) is somewhat different than the format used in the similar USPS Methods module, which affords the same ability to select allowed methods, but uses an XML request method.

 

If you or anyone else could help with getting the option selection capability added into the UPSXML module, I (and probably others) would be thrilled and grateful. I am convinced that the XML method is the hands down winner for UPS rate requests, but it simply offers TOO MANY shipping options to the customer.

 

Thanks in advance to anyone who can help resolve this :thumbsup:

... if you want to REALLY see something that doesn't set up right out of the box without some tweaking,

try being a Foster Parent!

Link to comment
Share on other sites

Dear Mugitty,

 

My proposed solution for UPSXML is a bit of a hack, since you can't change it from the admin section, but if it is found useful maybe someone else can find a solution for that.

This little hack reads the strings to match with the options you don't want from a file (typically in includes/languages/modules/shipping/upsxml_exclude_choices.txt) where every exclusion is on its own line like:

Next Day Air Early A.M
2nd Day Air A.M.

Then only a few lines of code need to be inserted in /includes/modules/shipping/upsxml.php starting around line 255 in function quotes:

  if (tep_not_null($this->icon)) {
	 $this->quotes['icon'] = tep_image($this->icon, $this->title);
 }
// inserted for exclusion of UPS shipping options, read from file
// upsxml_exclude_choices.txt (every option on its own line)
$upsxml_exclude_choices = DIR_FS_CATALOG . DIR_WS_LANGUAGES . "english/modules/shipping/upsxml_exclude_choices.txt";
if (file_exists($upsxml_exclude_choices) && filesize($upsxml_exclude_choices) > 0 ) {
$exclude_choices_array = file($upsxml_exclude_choices);
$temp_upsxml_methods = $this->quotes['methods'];
unset ($this->quotes['methods']);
$counted_in_array_temp_upsxml_methods = count ($temp_upsxml_methods);
$keys_to_be_deleted_array = array();
for ($ya = 0; $ya < $counted_in_array_temp_upsxml_methods; $ya++ ) {
for ($za = 0; $za < count ($exclude_choices_array); $za++ ) {
if (strstr($temp_upsxml_methods[$ya]['id'], trim($exclude_choices_array[$za] ) )) {
$keys_to_be_deleted_array[] = $ya;
} // end if ( strstr ...
} // end for ($za = 0; ...
} // end for ($ya = 0; ...

if (!empty($keys_to_be_deleted_array)) { 
for ($ia = 0; $ia < count($keys_to_be_deleted_array); $ia++) {
 unset ($temp_upsxml_methods[$keys_to_be_deleted_array[$ia]]);
 }
$temp_upsxml_methods = array_values($temp_upsxml_methods);  
} // end if (!empty($keys_to...
$this->quotes['methods'] = $temp_upsxml_methods;
} // end if (file_exist($upsxml_exclude_choices) ...
// EOF UPSXML exclude choices
 return $this->quotes;
   }

Since you only define the options you don't want and the code is only executed when the file exists and is not empty I feel it shouldn't be able to break much if it doesn't work ;)

It works fine on my test server...

Link to comment
Share on other sites

Jan;

 

I really appreciate you posting your solution for this. I am convinced that your code can be turned around just a bit so the selected options could be determined in the Admin area for UPSXML, but I just have not been able to get my head around how to code it.

 

Here's what I have so far...

 

1) Create a new function in admin/includes/functions/general.php

Insert just before the closing ?> of the file

// Alias function for Store configuration values in the Administration Tool
 function tep_cfg_select_multioption($select_array, $key_value, $key = '') {
   for ($i=0; $i<sizeof($select_array); $i++) {
     $name = (($key) ? 'configuration[' . $key . '][]' : 'configuration_value');
     $string .= '<br><input type="checkbox" name="' . $name . '" value="' . $select_array[$i] . '"';
     $key_values = explode( ", ", $key_value);
     if ( in_array($select_array[$i], $key_values) ) $string .= ' CHECKED';
     $string .= '> ' . $select_array[$i];
   } 
   $string .= '<input type="hidden" name="' . $name . '" value="--none--">';
   return $string;
 }

This is used in both UPS Choice (HTML API) and in USPS Methods (XML API) contributions and is identical in both, except that the UPS Choice does not have the next to last line:

$string .= '<input type="hidden" name="' . $name . '" value="--none--">';

 

2) Amend catalog/admin/modules.php (around line 43) so that it reads like this

if (tep_not_null($action)) {
   switch ($action) {
     case 'save':
       while (list($key, $value) = each($HTTP_POST_VARS['configuration'])) {
         if( is_array( $value ) ){
         $value = implode( ", ", $value);
   $value = ereg_replace (", --none--", "", $value);
     }
         tep_db_query("update " . TABLE_CONFIGURATION . " set configuration_value = '" . $value . "' where configuration_key = '" . $key . "'");
       }
       tep_redirect(tep_href_link(FILENAME_MODULES, 'set=' . $set . '&module=' . $HTTP_GET_VARS['module']));
       break;
     case 'install':

 

3) Add a new configuration key (MODULE_SHIPPING_UPSXML_TYPES) to "function install" in catalog/includes/modules/shipping/upsxml.php

(I'm not sure here whether the values should be text or the numeric value for each method, so this example shows text in the configuration_value field and numeric equivalent in the set_function field)

 tep_db_query("insert into " . TABLE_CONFIGURATION . " (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, set_function, date_added) values ( 'Shipping Methods', 'MODULE_SHIPPING_UPSXML_TYPES', 'Next Day Air,2nd Day Air,Ground,Worldwide Express,Worldwide Expedited,Standard,3 Day Select,Next Day Air Saver,Next Day Air Early A.M.,Worldwide Express Plus,2nd Day Air A.M.,Express NA1,Express Saver', 'Select the USPS services to be offered.', '6', '20', 'tep_cfg_select_multioption(array(\'01\',\'02\', \'03\', \'07\', \'08\', \'11\', \'12\', \'13\', \'14\', \'54\', \'59\', \'64\',\'65\'), ', now() )");

 

4) A couple of lines below that, add the new key to "function keys"

function keys() {
 return array('MODULE_SHIPPING_UPSXML_RATES_STATUS', 'MODULE_SHIPPING_UPSXML_RATES_ACCESS_KEY', 'MODULE_SHIPPING_UPSXML_RATES_USERNAME', 'MODULE_SHIPPING_UPSXML_RATES_PASSWORD', 'MODULE_SHIPPING_UPSXML_RATES_PICKUP_METHOD', 'MODULE_SHIPPING_UPSXML_RATES_PACKAGE_TYPE', 'MODULE_SHIPPING_UPSXML_RATES_CUSTOMER_CLASSIFICATION_CODE', 'MODULE_SHIPPING_UPSXML_RATES_ORIGIN', 'MODULE_SHIPPING_UPSXML_RATES_CITY', 'MODULE_SHIPPING_UPSXML_RATES_STATEPROV', 'MODULE_SHIPPING_UPSXML_RATES_COUNTRY', 'MODULE_SHIPPING_UPSXML_RATES_POSTALCODE', 'MODULE_SHIPPING_UPSXML_RATES_MODE', 'MODULE_SHIPPING_UPSXML_RATES_UNIT_WEIGHT', 'MODULE_SHIPPING_UPSXML_RATES_UNIT_LENGTH', 'MODULE_SHIPPING_UPSXML_RATES_QUOTE_TYPE', 'MODULE_SHIPPING_UPSXML_RATES_HANDLING', 'MODULE_SHIPPING_UPSXML_RATES_TAX_CLASS', 'MODULE_SHIPPING_UPSXML_RATES_ZONE', 'MODULE_SHIPPING_UPSXML_RATES_SORT_ORDER', 'MODULE_SHIPPING_UPSXML_TYPES');
   }

 

All of this is hunky-dorey, as it gives a series of checkboxes in the Admin area for UPSXML, I am able to select the boxes I want and they appear to be saved to the configuration. The problem I am having is how to call these allowed methods in the upsxml.php file

 

In the same area that you were working in I've tried the following, which doesn't give me any errors but it also doesn't limit the methods shown to the customer.

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

//add for select options

       reset($this->quotes['methods']);
       $allowed_types = explode(", ", MODULE_SHIPPING_UPSXML_TYPES);

       while (list($key, $value) = each($this->quotes['methods'])) {

  if ( !in_array($key, $allowed_types) ) continue;
    }

//end select options
 
 return $this->quotes;

I would think that where you've used something like "if (strstr($temp_upsxml_methods[$ya]['id'], trim($exclude_choices_array[$za]" to remove the undesired methods based on your file, that we could use something similar to show the "allowed_types" as dictated in the Admin area for the module.

 

I just don't understand PHP well enough to solve this, but am convinced that what is above is only a couple of lines of code away from working.

 

Any help would be greatly appreciated so that I could repackage this whole UPSXML module with this capability and get it up for everyone to use.

... if you want to REALLY see something that doesn't set up right out of the box without some tweaking,

try being a Foster Parent!

Link to comment
Share on other sites

I would think that where you've used something like "if (strstr($temp_upsxml_methods[$ya]['id'], trim($exclude_choices_array[$za]) ))" to remove the undesired methods based on your file, that we could use something similar to show the "allowed_types" as dictated in the Admin area for the module.

Dear Muggity,

My feeling is that you are very, very close to finishing your project. I believe (haven't tried it yet) that if you change that line of code to:

if (!strstr($temp_upsxml_methods[$ya]['id'], $exclude_choices_array[$za] ))

you end up with the same thing: the keys of the methods you want to exclude. The only difference being that you start with the ones you want and I with the ones you want to exclude (in the long run more flexible, but your way of doing it is much more attractive for the average shop owner).

 

Whether you get your allowed or excluded methods from the database or a file shouldn't make much of a difference for this particular piece of code.

 

The code you use doesn't throw out the unwanted methods (unset(...) ) so that is perhaps the reason it hasn't worked yet.

 

The trim() is only needed because the file() command takes the lines from the file, but keeps the line endings. It took me quite a while to figure out why the code wasn't working without the trim ;)

 

I will take a closer look and get back to you. Keep up the good work!

Link to comment
Share on other sites

Jan;

 

Thanks for replying. I didn't mention that I applied your code to our site and it works a charm!!!

 

I'm still interested, though, in achieving it the other way for the same reason you pointed out... the average store owner (plus the fact that the deprecated HTML UPS Choice contribution and the USPS Methods both use the Admin selectable method - so for consistancy's sake)

 

Thanks again - it looks sooo much better without those multiple Next Day and Second Day options!

... if you want to REALLY see something that doesn't set up right out of the box without some tweaking,

try being a Foster Parent!

Link to comment
Share on other sites

Dear Mugitty,

 

I applied your code to our site and it works a charm!!!

That is nice to hear !

 

I reworked the piece of code to work the other way round (with allowed methods instead of excluded methods) and this works on my test server:

  if (tep_not_null($this->icon)) {
	 $this->quotes['icon'] = tep_image($this->icon, $this->title);
 }
// inserted for exclusion of UPS shipping options, read from db
// for speed of testing now read from define: 3 Day Select AND Next Day Air Early A.M. omitted
// note that if you allow methods containing the string "Next Day Air" also "Next Day Air Early A.M."
// will be included in the allowed options...therefore the "Next Day Air (" in the define...
DEFINE('MODULE_SHIPPING_UPSXML_TYPES','Next Day Air (,2nd Day Air,Ground,Worldwide Express,Worldwide Expedited,Standard,Next Day Air Saver,Worldwide Express Plus,2nd Day Air A.M.,Express NA1,Express Saver');
$allowed_types = explode(",", MODULE_SHIPPING_UPSXML_TYPES);
$temp_upsxml_methods = $this->quotes['methods'];
$wanted_upsxml_methods = array();
unset ($this->quotes['methods']);
$counted_in_array_temp_upsxml_methods = count ($temp_upsxml_methods);
for ($ya = 0; $ya < $counted_in_array_temp_upsxml_methods; $ya++ ) {
for ($za = 0; $za < count ($allowed_types); $za++ ) {
if (strstr($temp_upsxml_methods[$ya]['id'], $allowed_types[$za] )) {
$keys_to_be_kept_array[] = $ya;
     } // end if ( ! strstr ...
  } // end for ($za = 0; ...
} // end for ($ya = 0; ...
$keys_array = array_unique($keys_to_be_kept_array);
$keys_array = array_values($keys_array);

if (!empty($keys_array)) { 
for ($ia = 0; $ia < count($keys_array); $ia++) {
 $wanted_upsxml_methods[] = $temp_upsxml_methods[$keys_array[$ia]];
 }
$wanted_upsxml_methods = array_values($wanted_upsxml_methods);  
} // end if (!empty($keys_array))

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

// EOF UPSXML exclude choices
 return $this->quotes;
   }

I did run into a bit of a snag: if you allow methods containing the string "Next Day Air" also "Next Day Air Early A.M." will be included. Therefore I added a ' (' to avoid that. This will look rather strangely in the admin section, unless you add the whole thing that is returned by UPS ( I mean with the (1 Business Days) behind it. Also I used "," in the explode instead of ", " perhaps the space after the comma went lost in the posting process?

Link to comment
Share on other sites

Jan;

 

This is great! I'll look at it when I get home from work today or tomorrow and see what can be done about the string problem. Maybe there's a PHP command that tells it to only match exact strings...?

 

Thanks so much for your efforts - I've been trying to sort this out for ages.

 

Stuart

Edited by mugitty

... if you want to REALLY see something that doesn't set up right out of the box without some tweaking,

try being a Foster Parent!

Link to comment
Share on other sites

Stuart,

Maybe there's a PHP command that tells it to only match exact strings...?

Sure : == . We just need to take out the service (e.g. Next Day Air) from the strings returned by UPS (e.g. out of: "UPS Next Day Air (1 Business Days)"), but that just takes doing some "explode" 's and if else's to fix. I'll work on it tonight (my time is 2 hours after server time).

Link to comment
Share on other sites

Jan;

 

I don't want to digress from the great work you've done, but I keep coming back to the successful implementation of USPS Methods (XML API) and UPS Choice (HTML API) and am curious about a couple of things:

 

The UPS Choice module which allows selection of allowed shipping methods from within the Admin interface has this within function quote:

      $upsQuote = $this->_upsGetQuote();

 

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

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

                              'module' => $this->title . ' (' . $shipping_num_boxes . ' x ' . $shipping_weight . 'lbs)');

 

        $methods = array();

  $allowed_methods = explode(", ", MODULE_SHIPPING_UPS_TYPES);

  $std_rcd = false;

        $qsize = sizeof($upsQuote);

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

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

    if ($type=='STD') {

    if ($std_rcd) continue;

    else $std_rcd = true;

  };

    if (!in_array($type, $allowed_methods)) continue;

          $methods[] = array('id' => $type,

                            'title' => $this->types[$type],

                            'cost' => ($cost + MODULE_SHIPPING_UPS_HANDLING) * $shipping_num_boxes);

        }

 

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

  if ($this->tax_class > 0) {

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

        }

      } else {

        $this->quotes = array('module' => $this->title,

                              'error' => 'We are unable to obtain a rate quote for UPS shipping.<br>Please contact the store if no other alternative is shown.');

      }

 

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

 

      return $this->quotes;

    }

while the original UPSXML has this:
  $upsQuote = $this->_upsGetQuote();

 

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

  if (DIMENSIONS_SUPPORTED) {

    $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]);

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

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

    }

  }

 

  if ($this->tax_class > 0) {

    $this->quotes['tax'] = tep_get_tax_rate($this->tax_class, $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);

  }

 

  return $this->quotes;

    }

After adding the new configuration key why won't something like this work in UPSXML?:
  $methods = array();

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

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

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

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

//    }

//  }

 

//method used in UPS Choice

                        $allowed_methods = explode(", ", MODULE_SHIPPING_UPSXML_TYPES);

                        $qsize = sizeof($upsQuote);

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

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

                                if (!in_array($type, $allowed_methods)) continue;

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

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

          }

        }

//end UPS Choice method

 

  if ($this->tax_class > 0) {

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

  }

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

I can get the key to appear in Admin and select the options I want and they appear to be saved just as they should be. When I enter the new key as numerical values
tep_db_query("insert into " . TABLE_CONFIGURATION . " (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, set_function, date_added) values ( 'Shipping Methods', 'MODULE_SHIPPING_UPSXML_TYPES', 'UPS Next Day Air,UPS 2nd Day Air,UPS Ground,UPS Worldwide Express,UPS Worldwide Expedited,UPS Standard,UPS 3 Day Select,UPS Next Day Air Saver,UPS Next Day Air Early A.M.,UPS Worldwide Express Plus,UPS 2nd Day Air A.M.,UPS Express NA1,UPS Express Saver', 'Select the USPS services to be offered.', '6', '20', 'tep_cfg_select_multioption(array(\'01\',\'02\', \'03\', \'07\', \'08\', \'11\', \'12\', \'13\', \'14\', \'54\', \'59\', \'64\',\'65\'), ', now() )");

the UPS title shows up in the customer view, but no rates are displayed.

 

If I try to enter the new key as textual values

tep_db_query("insert into " . TABLE_CONFIGURATION . " (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, set_function, date_added) values ( 'Shipping Methods', 'MODULE_SHIPPING_UPSXML_TYPES', 'UPS Next Day Air,UPS 2nd Day Air,UPS Ground,UPS Worldwide Express,UPS Worldwide Expedited,UPS Standard,UPS 3 Day Select,UPS Next Day Air Saver,UPS Next Day Air Early A.M.,UPS Worldwide Express Plus,UPS 2nd Day Air A.M.,UPS Express NA1,UPS Express Saver', 'Select the USPS services to be offered.', '6', '20', 'tep_cfg_select_multioption(array(\'UPS Next Day Air\',\'UPS 2nd Day Air\', \'UPS Ground\', \'UPS Worldwide Express\', \'UPS Worldwide Expedited\', \'UPS Standard\', \'UPS 3 Day Select\', \'UPS Next Day Air Saver\', \'UPS Next Day Air Early A.M.\', \'UPS Worldwide Express Plus\', \'UPS 2nd Day Air A.M.\', \'UPS Express NA1\',\'UPS Express Saver\'), ', now() )");

then in the Admin area, click "INSTALL" to install the mod, everything looks fine, but when I click on "EDIT" to enter my specifics, I get

Parse error: parse error, unexpected T_STRING, expecting ')' in /home/farmex/public_html/shop_adm/modules.php(220) : eval()'d code on line 1
So I get no rates displayed to the customer in either case. I just can't figure out why the second key entry kicks out the error and why the methods array won't work :(

... if you want to REALLY see something that doesn't set up right out of the box without some tweaking,

try being a Foster Parent!

Link to comment
Share on other sites

Stuart,

 

Starting with the error in the last block of code:

Worldwide Express Plus\', \'UPS 2nd Day Air A.M.\', \'UPS Express NA1\',\'UPS Express Saver\'), ', now() )");

If I counted correctly you have 6 opening brackets "(" but only 5 closing brackets. Also there is a lone quote just before now(). I suspect it should have been:

Worldwide Express Plus\', \'UPS 2nd Day Air A.M.\', \'UPS Express NA1\',\'UPS Express Saver\'), '', now() ))");

 

I never looked at how to implement a contribution in the admin section so I know less about it than you do now.

 

The succesful methods you mention rely on the service type that is in the array to be exactly something like "UPS Next Day Air". Alas, when it is "UPS Next Day Air (1 Business Days)" the PHP function "in_array" should find a "no match". So IMHO we are stuck with string comparison methods and not the shorter in_array method... I have even seen "UPS Worldwide Express (270013: Invalid Shipment Contents Value Business Days)" when choosing a delivery address outside the US when shipping from within...

 

Because string comparisons have to take into account more possibilities the code becomes quite a bit longer than the nice short code in the examples you give. To get the exact matches with or without UPS at the beginning of the description and with or without the (x Business Days) at the end I came up with the following (working) code, in a new function that only worked when I added it after the very last curly brace in includes/modules/shipping/upsxml.php:

 

    function exclude_choices($temp_upsxml_methods) {
// used for exclusion of UPS shipping options, read from db
// for speed of testing now read from define: 3 Day Select AND Next Day Air Early A.M. AND Groudn omitted
DEFINE('MODULE_SHIPPING_UPSXML_TYPES','Next Day Air,2nd Day Air,Worldwide Express,Worldwide Expedited,Standard,Next Day Air Saver,Worldwide Express Plus,2nd Day Air A.M.,Express NA1,Express Saver');  
$allowed_types = explode(",", MODULE_SHIPPING_UPSXML_TYPES);

$wanted_upsxml_methods = array();

$counted_in_array_temp_upsxml_methods = count ($temp_upsxml_methods);
foreach ($temp_upsxml_methods as $ups_service ) {
if (strstr($ups_service['id'], "UPS")) {
// this will chop off "UPS" from the beginning of the service description (id)
$ups_service_minus_ups = explode("UPS", $ups_service['id'] );
if (strstr($ups_service['id'], "(")) {
// this will chop off (x Business Days)
$ups_service_minus_bd = explode("(", $ups_service_minus_ups[1] );
// get rid of white space with trim
$ups_service_root[] = trim($ups_service_minus_bd[0]);
} else { // end if (strstr($ups_service['id'], "("))
// if service description contains UPS but not (x Business days):
$ups_service_root[] = trim($ups_service_minus_ups[1]);
}
// end if (strstr($ups_service['id'], "UPS"):
} elseif (strstr($ups_service['id'], "(")) { 
// if service description doesn't contain UPS, but does (x Business Days):
$ups_service_minus_ups_bd = explode("(", $ups_service['id'] );
$ups_service_root[] = trim($ups_service_minus_ups_bd[0]);
} else { // service description neither contain UPS nor (x Business Days)
$ups_service_root[] = trim($ups_service['id']);
} 
} // end foreach

for ($ya = 0; $ya < $counted_in_array_temp_upsxml_methods; $ya++ ) {
for ($za = 0; $za < count ($allowed_types); $za++ ) {
if ($ups_service_root[$ya] == $allowed_types[$za]) {
$keys_to_be_kept_array[] = $ya;
     } // end if ($ups_service_root[$ya] ...
  } // end for ($za = 0; ...
} // end for ($ya = 0; ...
// array_unique shouldn't be necessary, but just in case
$keys_array = array_unique($keys_to_be_kept_array);
// put the numerical keys in consecutive order, 0,1,2,3 etc.
$keys_array = array_values($keys_array);

if (!empty($keys_array)) { 
for ($ia = 0; $ia < count($keys_array); $ia++) {
 $wanted_upsxml_methods[] = $temp_upsxml_methods[$keys_array[$ia]];
 }
$wanted_upsxml_methods = array_values($wanted_upsxml_methods);  
} else { // end if (!empty($keys_array))
// if no methods should be kept (keys_array empty)
// something must have gone really bad: last escape: keep what we started with
$wanted_upsxml_methods = $temp_upsxml_methods;
}
return $wanted_upsxml_methods;
}

 

The call to that function is (as before) just before the return quotes statement in the function quote:

 

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

// BOF UPSXML exclude choices, to be kept are read from db
  $temp_upsxml_methods = $this->quotes['methods'];
  unset($this->quotes['methods']);
  $this->quotes['methods'] = exclude_choices($temp_upsxml_methods);

// EOF UPSXML exclude choices
 return $this->quotes;
   }

Of course in your new contribution the DEFINE should be left out. I hope you get this working.

Link to comment
Share on other sites

Jan;

 

Good eyes on the code in that last block, but I took a look at the other modules that use the same function, and it appears that everywhere the functions tep_cfg_select_option or tep_cfg_select_multioption are used, that strange sequence exists. It is a strange format, but that last segment being formed the way it is probably has something to do with what I thought was an extra few characters in admin/modules.php (around line 220)

 

eval('$keys .= ' . $value['set_function'] . "'" . $value['value'] . "', '" . $key . "');");

 

That being said, this is proving such a bugger that I'm going to focus on this last code that you offered and see if I can wrap it up and get it contributed that way, rather than drive myself nuts with why it won't work in the same manner as the other two modules seem to.

 

Thanks again very much for your help- I'll post here as well as contributions when I get it done (should be this weekend) :thumbsup:

Edited by mugitty

... if you want to REALLY see something that doesn't set up right out of the box without some tweaking,

try being a Foster Parent!

Link to comment
Share on other sites

Stuart,

 

why it won't work in the same manner as the other two modules seem to.

I have been thinking about that and I believe the reason is that the other two modules deal with the allowed methods the moment the quote from UPS is received and is prepared for the building of the array that is sent to (I think) shipping.xml. See for example the code from UPS Choice:

? ? ? $methods = array();
? $allowed_methods = explode(", ", MODULE_SHIPPING_UPS_TYPES);
// part left out
? ? if (!in_array($type, $allowed_methods)) continue;
// here the array is built up, but if $type is not in the $allowed_methods, it
// never reaches the array...
? ? ? ? ? $methods[] = array('id' => $type,
? ? ? ? ? ? ? ? ? ? ? ? ? ? 'title' => $this->types[$type],
? ? ? ? ? ? ? ? ? ? ? ? ? ? 'cost' => ($cost + MODULE_SHIPPING_UPS_HANDLING) * $shipping_num_boxes);
? ? ? ? }

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

 

Both you and I have left that alone and dealt with the allowed methods after they all have been included.

Considering that you can't/shouldn't use in_array because of the different responses you might get from UPS (the same service might be returned with different values for Business Days (or in case with the error I mentioned in an earlier post) the code will never be so lovely short as with the other contributions.

 

But I'm not a professional PHP coder, so this code should be marked with "AMATEUR AT WORK". ;) There is a good chance that a pro can shorten and improve the code. For example if there are no services left, this code uses the original quotes. Perhaps it should be empty (e.g. an address abroad and the shop doesn't want to ship abroad) and then return an error message like "We can't give you any shipping quotes at the moment, contact the shop owner" ?

 

I haven't looked at intervening with the build-up of the quotes array earlier to not include the unwanted quotes. I will take a look at it later.

 

Good to hear that you tackled that error "eval()'d code on line 1".

Link to comment
Share on other sites

Stuart,

 

Indeed things could be made simpler by intervening earlier: avoiding insertion of the unwanted choices instead of taking them out later.

 

For reason of clarity I did the checking of the choices in a separate function. This also means only a single line has to commented out if things go bad ;)

 

The single line that calls the checking function is more or less as per the other contributions:

 // starts somewhere around line 232
	 $methods = array();
	 for ($i=0; $i < sizeof($upsQuote); $i++) {
   list($type, $cost) = each($upsQuote[$i]);
   // next line is the only one needed for exclusion of choices apart
   // from inserting the function exclude_choices after the last 
   // curly brace in the original file /includes/modules/shipping/upsxml.php
   // but before the closing php tag!
   if (!exclude_choices($type)) continue;	
   if ( $method == '' || $method == $type ) {
  	 $methods[] = array('id' => $type, 'title' => $type, 'cost' => ($this->handling_fee + $cost));
   } 
	 }

The "new" function exclude_choices compares the type of service (typically "UPS Next Day Air (1 Business Days)" to the list of allowed types. It can deal with or without the UPS in front of it and with or without the (x Business Days) and is not bothered by anything that comes after the opening bracket "(".

 

I hope this meets your requirements ;)

 

    function exclude_choices($type) {
// used for exclusion of UPS shipping options, read from db
// for speed of testing now read from define: 2nd Day Air A.M. omitted
DEFINE('MODULE_SHIPPING_UPSXML_TYPES','Next Day Air,2nd Day Air,3 Day Select,Next Day Air Early A.M.,Ground,Worldwide Express,Worldwide Expedited,Standard,Next Day Air Saver,Worldwide Express Plus,Express NA1,Express Saver');  
$allowed_types = explode(",", MODULE_SHIPPING_UPSXML_TYPES);
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 );
if (strstr($type, "(")) {
// this will chop off (x Business Days)
$type_minus_bd = explode("(", $type_minus_ups[1] );
// get rid of white space with trim
$type_root = trim($type_minus_bd[0]);
} else { // end if (strstr($type, "("))
// if service description contains UPS but not (x Business days):
$type_root = trim($type_minus_ups[1]);
} // end if (strstr($type, "UPS"):
} elseif (strstr($type, "(")) { 
// if service description doesn't contain UPS, but does (x Business Days):
$type_minus_ups_bd = explode("(", $type );
$type_root = trim($type_minus_ups_bd[0]);
} else { // service description neither contain UPS nor (x Business Days)
$type_root = trim($type);
} 

 for ($za = 0; $za < count ($allowed_types); $za++ ) {
if ($type_root == $allowed_types[$za]) {
 return true;
 exit;
     } // end if ($type_root == $allowed_types[$za] ...
 }  
// if the type is not allowed:
      return false;
}

Link to comment
Share on other sites

Jan;

 

I was just about to post that I had failed miserably in getting the code from your post #14 to be able to work using the new configuration value from the database. I tried about a dozen different scenarios and placements and received either differing errors messages or a result that was error-free, but didn't limit the choices shown to the customer.

 

I was going to tell you that I was ready to just package up your first modification using the text file (cause it works great!) as the optional means for a shop owner to limit options. (... and the more I work with this, the cleaner that method looks!) but, with your new input this morning, I'll take another stab at the Admin multioption method.

 

BTW, I didn't really "tackle" anything with that eval() error - that was still one of the errors I ended up with last night. I haven't changed the way the keys that use tep_cfg_select_option or tep_cfg_select_multioption are presented with one 'missing' closing bracket, because all of the others seem to work fine.

 

OK... back to it with your new code ;)

P.S. I haven't looked at it yet, but isn't the transit time that's shown after each shipping option from a separate API - (time in transit as opposed to rates and services)?

Edited by mugitty

... if you want to REALLY see something that doesn't set up right out of the box without some tweaking,

try being a Foster Parent!

Link to comment
Share on other sites

BTW, I didn't really "tackle" anything with that eval() error - that was still one of the errors I ended up with last night.

Oh shute...

 

One problem that I might have overlooked is the explode of the allowed_types. I use a comma for the explode, but if there are spaces after the comma in the database field, the code fails ("[space]Next Day Air" is not the same as "Next Day Air"). This would be easy to remedy if we also trim() the allowed_types:

if ($type_root == trim($allowed_types[$za])) {
?return true;
?exit;

Did you check the database to see what really goes into the db field as allowed types? Perhaps doing it manually first to be sure everything works as I advertise ;)

 

I have never looked into that admin code before, so I can't be much help now. I will see if I can understand it myself. Don't count on it though ;)

 

If you think of giving up, perhaps it is an idea to just use the text file for exclusions again and then were it says "return true;" make it "return false;" and vice versa in the last version of exclude_choices. I think this way the code is simpler to install and maintain and also cleaner.

 

You could even start with building an array of the known services of today, just after the start of the function and comment them all. If people don't want any particular service, uncomment the line (and change the name of allowed_type to not_allowed_type to avoid confusion). We should then do something about the case when there nothing is commented out I guess.

 

// $not_allowed_types[] = 'Next Day Air';
// $not_allowed_types[] = '2nd Day Air'; // etcetera, etcetera

 

Harder to implement for the average user of osCommerce I think, so your contribution working from the admin part would still be the best....

Link to comment
Share on other sites

:D :D :D

Jan, you are the MASTER :thumbsup:

 

It is now working from the database, selectable from the Admin section for the UPSXML module!

 

The eval() error was occurring because the field for set_function was varchar(255) and the string was longer than 255 characters (DUH!). Changed the type to text and the error went away.

 

The (270013: Invalid Shipment Contents Value Business Days) error on international shipments has nothing to do with rates and services, but is an error from within the time in transit section of the code. This feature I believe was added to this contribution after its initial release and I think I remember seeing a thread about this issue - something that's being fed to the time in transit API is not as it should be.

 

I'm off now to see if I can isolate that problem and get it fixed (with my limited sub-amateur coding abilities)

 

Stay tuned to this channel for continued progress reports ;)

... if you want to REALLY see something that doesn't set up right out of the box without some tweaking,

try being a Foster Parent!

Link to comment
Share on other sites

New version just uploaded:

 

Admin selectable shipping methods, Time In Transit International error fix, updated install instructions

 

UPSXML_1.04

 

Support thread: HERE

... if you want to REALLY see something that doesn't set up right out of the box without some tweaking,

try being a Foster Parent!

Link to comment
Share on other sites

  • 2 weeks later...

Hi there,

This is my first post, so forgive me if I make mistakes. I have searched and searched, but this was the only post I saw that related to my problem. I hope you can help.

 

I have installed the upsxml 1.04 contribution and everything seems to be working pretty well. The rates are much closer to my own.

However, I am getting the same "/admin/modules.php(220) : eval()'d code on line 1" error.

 

then in the Admin area, click "INSTALL" to install the mod, everything looks fine, but when I click on "EDIT" to enter my specifics, I get

Parse error: parse error, unexpected T_STRING, expecting ')' in /home/farmex/public_html/shop_adm/modules.php(220) : eval()'d code on line 1

 

but I do get rates for the customer. The only services that show up are next day air, 2nd day air, 3 day select, and ground. No next day air saver or 2nd day air saver.

 

Also, in the admin, it shows "Shipping Methods

Select the UPS services to be offered." with the update button below. It was my understanding that there are supposed to be radio or check boxes, so that I can select the services available? :(

or did I misunderstand?

 

I would like to get this working without the errors, of course.

 

Any ideas?

 

Thanks,

Erin :)

Link to comment
Share on other sites

Any ideas?
Oh yes, you must have forgotten STEP 5 of the instructions, because what the install function in admin does is put a very long function in the database, in the column "set_function". If the column width is not big enough (it needs more than 255 characters) than that truncated value gives that particular error message (I know because I made the same mistake).

 

Once you have done step 5, you will need to de-install UPSXML in the admin section and then re-install again with the settings you put in earlier. You should be fine after that.

 

--------

STEP 5

--------

 

The configuration key which allows for selecting the types of methods to show your customers is type

"VARCHAR(255)" in the stock osC installation, which is not long enough to hold all of the possible UPS methods.

 

You have 2 options to deal with this:

 

1) Go to the configuration table in your database and change the type for

field "set_function" from VARCHAR(255) to TEXT

 

-- OR --

 

2) In catalog/includes/modules/shipping/upsxml.php (about line 291)

Find the key MODULE_SHIPPING_UPSXML_TYPES

and remove at least 2 of the shipping methods listed there to reduce the field to

less than 255 characters

Link to comment
Share on other sites

Oh yes, you must have forgotten STEP 5 of the instructions, because what the install function in admin does is put a very long function in the database, in the column "set_function". If the column width is not big enough (it needs more than 255 characters) than that truncated value gives that particular error message (I know because I made the same mistake).

 

Thanks, Jan!

 

I did make the mistake, after all. I did set the TEXT in the database, but only after I got some other error. After rereading all your posts, I figured I should uninstall and reinstall the contribution, and it worked!!!

Thanks, for all your help. I am learning fast! :thumbsup:

 

 

Love And Peace,

Erin

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...