[ic] ups_cache expires

Steve Graham icdev at mrlock.com
Mon Feb 6 16:22:20 EST 2006


At 10:06 AM 2/3/2006, you wrote:


>>Patches are always welcome! 8-)
>>
>> >
>> > I know this is not really an issue on 1 day cache expire, but with
>> > expire set to 30+ days - it will add up.
>>
>>It also cuts down unnecessary traffic. +1.
>>
>>--
>>Mike Heins

Hello List,

Here is the QueryUPS.pm complete file with suggested modifications:

Changes I suggest:
1 - make sure the weight is rounded up to next whole value - UPS & 
our cache table need whole numbers.
2 - Only store & search the cache table for the 1st three digits of 
the zip code. (Saves alot of data entry)
3 - If the cache result is old, and for some reason www UPS fails to 
return data - then use the old value.
4 - If the zip code is not in the cache, and UPS returns data, but 
the shipping amount < 0.00 then don't store it in the table.
      I do have a record of this happening.

Comments???
Steve Graham


Code Starts after this line >>>>>

package Vend::Ship::QueryUPS;

use Vend::Util;
use Vend::Interpolate;
use Vend::Data;
use Vend::Ship;
use Business::UPS;

sub calculate {
         my ($mode, $weight, $row, $opt, $tagopt, $extra) = @_;

my $tmp_weight;
my $zip5;

# force weight up to next pound.
# At present UPS only uses weights rounded to next pound.
$tmp_weight = int($weight);
if ($tmp_weight < $weight) {
   $weight = $tmp_weight + 1;
}

         $opt->{service}         ||= $opt->{table};
         if(! $opt->{service} and $extra =~ /^\w+$/)  {
                 $opt->{service} = $extra;
         }
         $opt->{service} ||= $opt->{table} || $mode;

         $opt->{origin}                  ||= $::Variable->{UPS_ORIGIN};
         $opt->{country_field}   ||= $::Variable->{UPS_COUNTRY_FIELD} 
|| 'country';
         $opt->{geo}                             ||= 
$::Variable->{UPS_POSTCODE_FIELD} || 'zip';

         my $origin  = $opt->{origin};
         my $country = $opt->{country} || $::Values->{$opt->{country_field}};

         $country ||= $opt->{default_country} || 'US';

         my $zip     = $opt->{zip}         || $::Values->{$opt->{geo}};
         $zip ||= $opt->{default_geo};

         my $modulo = $opt->{aggregate};

         if($modulo and $modulo <= 1) {
                 $modulo = $::Variable->{UPS_QUERY_MODULO} || 150;
         }
         elsif(! $modulo) {
                 $modulo = 9999999;
         }

         $country = uc $country;

     my %exception = ( UK => 'GB');

         if(! $::Variable->{UPS_COUNTRY_REMAP} ) {
                 # do nothing
         }
         elsif ($::Variable->{UPS_COUNTRY_REMAP} =~ /=/) {
                 my $new = 
Vend::Util::get_option_hash($::Variable->{UPS_COUNTRY_REMAP});
                 Vend::Util::get_option_hash(\%exception, $new);
         }
         else {
                 Vend::Util::hash_string($::Variable->{UPS_COUNTRY_REMAP}, 
\%exception);
         }

         $country = $exception{$country} if $exception{$country};

         # In the U.S., UPS only wants the 5-digit base ZIP code, not ZIP+4
         $country eq 'US' and $zip =~ /^(\d{5})/ and $zip = $1;
         $zip5 = $zip;
         $country eq 'US' and $zip =~ /^(\d{3})/ and $zip = $1;

#::logDebug("calling QueryUPS with: " . join("|", $opt->{service}, 
$origin, $zip, $weight, $country,$modulo));

         my $cache;
         my $cache_code;
         my $db;
         my $now;
         my $updated;
         my %cline;
         my $shipping;
         my $tmp_shipping;
         my $zone;
         my $error;

         my $ctable = $opt->{cache_table} || 'ups_cache';


         if($Vend::Database{$ctable}) {
                 $Vend::WriteDatabase{$ctable} = 1;
                 CACHE: {
                         $db = dbref($ctable)
                                 or last CACHE;
                         my $tname = $db->name();
                         $cache = 1;
                         %cline = (
                                 weight => $weight,
                                 origin => $origin,
                                 country => $country,
                                 zip     => $zip,
                                 shipmode => $opt->{service},
                         );

                         my @items;
                         # reverse sort makes zip first
                         for(reverse sort keys %cline) {
                                 push @items, "$_ = " . 
$db->quote($cline{$_}, $_);
                         }

                         my $string = join " AND ", @items;
                         my $q = qq{SELECT code,cost,updated from 
$tname WHERE $string};
                         my $ary = $db->query($q);
#::logDebug("query cache: " . ::uneval($ary));
                         if($ary and $ary->[0] and $cache_code = 
$ary->[0][0]) {
                                 $shipping = $ary->[0][1];
                                 $updated = $ary->[0][2];
                                 $now = time();
                                 if($now - $updated > 1204000) {
                                         $tmp_shipping = $shipping;
                                         undef $shipping;
                                         $updated = $now;
                                 }
                                 elsif($shipping <= 0) {
                                         $error = $shipping;
                                         $updated = $now;
                                         $shipping = 0;
                                 }
                         }
#::logDebug("shipping is: " . (defined $shipping ? $shipping : 'undef'));
                 }
         }

         my $w = $weight;
         my $maxcost;
         my $tmpcost;

         unless(defined $shipping) {
                 $shipping = 0;
                 while($w > $modulo) {
                         $w -= $modulo;
                         if($maxcost) {
                                 $shipping += $maxcost;
                                 next;
                         }

                         ($maxcost, $zone, $error)
                                 = getUPS( $opt->{service}, $origin, 
$zip5, $modulo, $country);
                         if($error) {
                                 do_error(       "Ship mode %s: Error 
calling UPS service %s",
                                                         $mode,
                                                         $opt->{service}, );
                                 return 0;
                         }
                         $shipping += $maxcost;
                 }

                 undef $error;
#::logDebug("calling getUPS( $opt->{service}, $origin, $zip5, $w, $country)");
                 ($tmpcost, $zone, $error)
                         = getUPS( $opt->{service}, $origin, $zip5, 
$w, $country);

                 $shipping += $tmpcost;
         # Only store it if shipping >0
         # I have found a few entries with the shipping amount 
missing for some reason.
         # with no error returned from UPS.  Only store if shipping>0
            if ($shipping > 0){
                 if($cache) {
                         $cline{updated} = $now || time();
                         $cline{cost} = $shipping || $error;
                         $db->set_slice($cache_code, \%cline);
                 }
            }

         }

         if($error) {
                 do_error(       "Ship mode %s: Error calling UPS service %s",
                                         $mode,
                                         $opt->{service}, );
                 $shipping = 0;
         }
         if ($shipping <=0) {
          # if for some reason ups www fails, as it does occasionally
          # and we have an old cache_value - Use it!!
          if ($tmp_shipping>0) {
            $shipping = $tmp_shipping; }
         }
         return $shipping;
}



More information about the interchange-users mailing list