| Business-Shipping documentation | Contained in the Business-Shipping distribution. |
Business::Shipping::Shipment::UPS
$Rev: 280 $
Defaults to true.
# Uses the standard Shipment::weight().
Assign a package type (if none given) based on the service. Set weight to 0.01 minimum. Remove "+4" from ZIP+4.
from_state only required for Offline international orders.
Returns the abbreviated form of 'from_state'.
Alaska and Hawaii are treated differently by many shippers.
Stores the name as the user entered it, and updates the sibling methods.
The correct UPS code (e.g. 03).
The semi-official UPS nickname (e.g. 'GNDRES').
The official UPS name (e.g. 'Ground Residential').
The other nickname for that service (e.g. 'Ground'), used in offline UPS data files.
Provides implementation details for service() and friends.
Daniel Browning, db@kavod.com, http://www.kavod.com/
Copyright 2003-2011 Daniel Browning <db@kavod.com>. All rights reserved. This program is free software; you may redistribute it and/or modify it under the same terms as Perl itself. See LICENSE for more info.
| Business-Shipping documentation | Contained in the Business-Shipping distribution. |
package Business::Shipping::Shipment::UPS;
use Any::Moose; use Business::Shipping::Logging; use Business::Shipping::Config; use version; our $VERSION = qv('400');
extends 'Business::Shipping::Shipment'; has 'to_residential' => (is => 'rw', default => 1); has '_service' => (is => 'rw'); has 'service_code' => (is => 'rw'); has 'service_nick' => (is => 'rw'); has 'service_name' => (is => 'rw'); has 'service_nick2' => (is => 'rw'); # We need this offline boolean to know if from_state is required. has 'offline' => (is => 'rw'); #type => 'Business::Shipping::Package #has 'packages' => (is => 'rw', isa => 'ArrayRef'); __PACKAGE__->meta()->make_immutable();
sub packaging { shift->package0->packaging(@_) } sub signature_type { shift->package0->signature_type(@_) } sub insured_currency_type { shift->package0->insured_currency_type(@_) } sub insured_value { shift->package0->insured_value(@_) }
sub massage_values { my ($self) = @_; # Check each package for a package type and assign one if none given. my %services_default_packaging_codes = ( qw/ 1DM 02 1DML 01 1DA 02 1DAL 01 1DP 02 2DM 02 2DA 02 2DML 01 2DAL 01 3DS 02 GNDCOM 02 GNDRES 02 XPR 02 UPSSTD 02 XDM 02 XPRL 01 XDML 01 XPD 02 / ); #use Data::Dumper; die "packages = " . Dumper($self->packages()); # Set default packaging code based on the service. foreach my $package ($self->packages()) { next if $package->packaging(); my $dflt_pkg_code_for_svc; if (my $service_nick = $self->service_nick()) { $dflt_pkg_code_for_svc = $services_default_packaging_codes{$service_nick}; } if ($dflt_pkg_code_for_svc) { $package->packaging($dflt_pkg_code_for_svc); } else { $package->packaging('02'); } } # UPS requires weight is at least 0.1 pounds. foreach my $package ($self->packages) { $package->weight(0.1) if (not $package->weight() or $package->weight() < 0.1); } # In the U.S., UPS only wants the 5-digit base ZIP code, not ZIP+4 $self->to_country('US') if not $self->to_country(); if ($self->to_zip()) { $self->to_zip() =~ /^(\d{5})/ and $self->to_zip($1); } #info('to_country currently = ' . $self->to_country()); # UPS prefers 'GB' instead of 'UK' $self->to_country('GB') if $self->to_country() eq 'UK'; }
sub Required { return 'service, from_state' if $_[0]->to_canada and $_[0]->offline; return 'service, from_zip, from_state' if $_[0]->intl and $_[0]->offline; return 'service, from_zip'; }
sub from_state_abbrev { my ($self) = @_; my $state_abbrevs = config_to_hash(cfg()->{ups_information}->{state_to_abbrev}); return $state_abbrevs->{ $self->from_state } || $self->from_state; }
sub from_ak_or_hi { my ($self) = @_; return unless $self->from_state(); return 1 if $self->from_state() =~ /^(AK|HI)$/i; return 0; }
sub service { my ($self, $service) = @_; if (defined $service) { $self->_service($service); my $service_map = $self->service_info($service, 'get_map'); if ($service_map) { # Record whatever the user passed in. If we need a certain format, # we can always use the sibling methods. $self->_service($service); # Setup the sibling method data $self->service_code($service_map->{code}); $self->service_nick($service_map->{nick}); $self->service_name($service_map->{name}); $self->service_nick2($service_map->{nick2}); } else { $self->user_error( "The service '$service' is not a valid service type"); } # Default values for residential addresses. if (not $self->to_residential) { if ($self->service_name eq 'Ground Residential') { $self->to_residential(1); } elsif ($self->service_name eq 'Ground Commercial') { $self->to_residential(0); } } } return $self->_service(); }
sub service_code_to_nick { return $_[0]->service_info($_[1], 'nick'); } sub service_code_to_name { return $_[0]->service_info($_[1], 'name'); }
sub service_info { my ($self, $service, $type) = @_; return unless $service and $type; return { name => 'Shop', code => 999, nick => 'SHOP', nick2 => 'Shop' } if $service eq 'shop' and $type eq 'get_map'; my $service_info_cfg = cfg()->{ups_service_info}; my $service_info; # Reset counter for 'each' keys %$service_info_cfg; while (my ($name, $other_values) = each %$service_info_cfg) { my ($nick, $code, $nick2) = split("\t", $other_values); my $service_info_hash = { name => $name, nick => $nick, code => $code, nick2 => $nick2, }; push @$service_info, $service_info_hash; } my $matching_map; my $match; foreach my $service_map (@$service_info) { if ($type eq 'get_map') { if ($service eq $service_map->{code}) { $match = 1; } elsif (lc $service eq lc $service_map->{nick}) { $match = 1; } elsif (lc $service eq lc $service_map->{name}) { $match = 1; } if ($match) { return $service_map; } } else { # Individual type if ($service_map->{code} eq $service) { return $service_map->{$type}; # TODO: check to see if none matched, then throw user_error } } } return; } 1; __END__