File Coverage

blib/lib/Business/Shipping/Shipment.pm
Criterion Covered Total %
statement 21 113 18.5
branch 0 50 0.0
condition 0 18 0.0
subroutine 7 22 31.8
pod 15 15 100.0
total 43 218 19.7


line stmt bran cond sub pod time code
1             package Business::Shipping::Shipment;
2              
3             =head1 NAME
4              
5             Business::Shipping::Shipment - Abstract class
6              
7             =head1 DESCRIPTION
8              
9             Abstract Class: real implementations are done in subclasses.
10              
11             Shipments have a source, a destination, packages, and other attributes.
12              
13             =head1 METHODS
14              
15             =cut
16              
17 2     2   7563 use Any::Moose;
  2         7  
  2         16  
18             extends 'Business::Shipping';
19 2     2   1250 use Business::Shipping::Logging;
  2         5  
  2         235  
20 2     2   11 use Business::Shipping::Config;
  2         4  
  2         138  
21 2     2   12 use Business::Shipping::Util;
  2         3  
  2         71  
22 2     2   8 use version; our $VERSION = qv('400');
  2         4  
  2         14  
23              
24             =head2 service
25              
26             =head2 from_country
27              
28             =head2 from_zip
29              
30             =head2 from_city
31              
32             =head2 to_country
33              
34             =head2 to_zip
35              
36             =head2 to_city
37              
38             =head2 packages
39              
40             =cut
41              
42             # of Business::Shipping::Package objects.
43             has 'packages' => (is => 'rw', isa => 'ArrayRef');
44             has 'current_package_index' => (is => 'rw');
45             has 'from_zip' => (is => 'rw');
46             has 'from_city' => (is => 'rw');
47             has 'to_city' => (is => 'rw');
48             has 'shipment_num' => (is => 'rw');
49              
50             __PACKAGE__->meta()->make_immutable();
51              
52             =head2 weight
53              
54             Forward the weight to the current package.
55              
56             =cut
57              
58             =head2 default_package()
59              
60             Only used for forwarding methods in simple uses of the class. For example:
61              
62             $rate_request->init(
63             service => '',
64             weight => '',
65             packaging => '',
66             );
67              
68             Which is simpler than:
69              
70             $rate_request->shipment->service( '' );
71             $rate_request->shipment->packages_index( 0 )->weight( '' );
72             $rate_request->shipment->packages_index( 0 )->packaging( '' );
73            
74             Note that it only works when there is one package only (no multiple packages).
75              
76             =head2 package0
77              
78             Alias for default_package.
79              
80             =head2 dflt_pkg
81              
82             Alias for default_package.
83              
84             =cut
85              
86 0     0 1   sub package0 { $_[0]->packages->[0] }
87             *default_package = *package0;
88             *dflt_pkg = *package0;
89              
90             sub weight {
91 0     0 1   my ($self, $in_weight) = @_;
92              
93 0 0         if ($in_weight) {
94 0           return $self->package0->weight($in_weight);
95             }
96             else {
97 0           my $sum_weight;
98 0           foreach my $package ($self->packages) {
99 0 0         next unless defined $package->weight();
100 0           $sum_weight += $package->weight();
101             }
102 0           return $sum_weight;
103             }
104             }
105              
106             =head2 total_weight
107              
108             Returns the weight of all packages within the shipment.
109              
110             =cut
111              
112             sub total_weight {
113 0     0 1   my $self = shift;
114              
115 0           my $total_weight;
116 0           foreach my $package (@{ $self->packages() }) {
  0            
117 0           $total_weight += $package->weight();
118             }
119 0           return $total_weight;
120             }
121              
122             =head2 to_zip( $to_zip )
123              
124             Throw away the "four" from zip+four.
125              
126             Redefines the MethodMaker implementation of this attribute.
127              
128             =cut
129              
130 2     2   777 no warnings 'redefine';
  2         2  
  2         275  
131              
132             sub to_zip {
133 0     0 1   my $self = shift;
134              
135 0 0         if ($_[0]) {
136 0           my $to_zip = shift;
137              
138             #
139             # U.S. only: need to throw away the "plus four" of zip+four.
140             #
141 0 0 0       if ($self->domestic and $to_zip and length($to_zip) > 5) {
      0        
142 0           $to_zip = substr($to_zip, 0, 5);
143             }
144              
145 0           $self->{'to_zip'} = $to_zip;
146             }
147              
148 0           return $self->{'to_zip'};
149             }
150 2     2   11 use warnings; # end 'redefine'
  2         4  
  2         2643  
151              
152             =head2 to_country()
153              
154             to_country must be overridden to transform from various forms (alternate
155             spellings of the full name, abbreviatations, alternate abbreviations) into
156             the full name that we use internally.
157              
158             May be overridden by subclasses to provide their own spelling ("United Kingdom"
159             vs "Great Britain", etc.).
160              
161             Redefines the MethodMaker implementation of this attribute.
162              
163             =cut
164              
165             sub to_country {
166 0     0 1   my ($self, $to_country) = @_;
167              
168 0 0         if (defined $to_country) {
169 0           my $abbrevs
170             = config_to_hash(cfg()->{ups_information}->{abbrev_to_country});
171 0           my $abbrev_to_country = $abbrevs->{$to_country};
172              
173             #use Data::Dumper; print STDERR "cfg() -> { ups_information } -> { abbrev_to_country } = " . Dumper( cfg()->{ ups_information }->{ abbrev_to_country } ) . "\nhash = " . Dumper( $abbrevs ) . "\n\n to_country = $to_country, abbrev_to_country = $abbrev_to_country\n";
174 0   0       $to_country = $abbrev_to_country || $to_country;
175             }
176 0 0         $self->{to_country} = $to_country if defined $to_country;
177              
178 0           return $self->{to_country};
179             }
180              
181             =head2 to_country_abbrev()
182              
183             Returns the abbreviated form of 'to_country'.
184              
185             Redefines the MethodMaker implementation of this attribute.
186              
187             =cut
188              
189             sub to_country_abbrev {
190 0     0 1   my ($self) = @_;
191              
192 0           my $country_abbrevs
193             = config_to_hash(cfg()->{ups_information}->{country_to_abbrev});
194              
195 0 0         return $country_abbrevs->{ $self->to_country } or $self->to_country;
196             }
197              
198             =head2 from_country()
199              
200              
201             =cut
202              
203             sub from_country {
204 0     0 1   my ($self, $from_country) = @_;
205              
206 0 0         if (defined $from_country) {
207 0           my $abbrevs
208             = config_to_hash(cfg()->{ups_information}->{abbrev_to_country});
209 0   0       $from_country = $abbrevs->{$from_country} || $from_country;
210             }
211 0 0         $self->{from_country} = $from_country if defined $from_country;
212              
213 0           return $self->{from_country};
214             }
215              
216             =head2 from_country_abbrev()
217              
218             =cut
219              
220             sub from_country_abbrev {
221 0     0 1   my ($self) = @_;
222 0 0         return unless $self->from_country;
223              
224 0           my $countries
225             = config_to_hash(cfg()->{ups_information}->{country_to_abbrev});
226 0           my $from_country_abbrev = $countries->{ $self->from_country };
227              
228 0   0       return $from_country_abbrev || $self->from_country;
229             }
230              
231             =head2 domestic_or_ca()
232              
233             Returns 1 (true) if the to_country value for this shipment is domestic (United
234             States) or Canada.
235              
236             Returns 1 if to_country is not set.
237              
238             =cut
239              
240             sub domestic_or_ca {
241 0     0 1   my ($self) = @_;
242              
243 0 0         return 1 if not $self->to_country;
244 0 0 0       return 1 if $self->to_canada or $self->domestic;
245 0           return 0;
246             }
247              
248             =head2 intl()
249              
250             Uses to_country() value to determine if the order is International (non-US).
251              
252             Returns 1 or 0 (true or false).
253              
254             =cut
255              
256             sub intl {
257 0     0 1   my ($self) = @_;
258              
259 0 0         if ($self->to_country) {
260 0 0         if ($self->to_country !~ /(US)|(United States)/) {
261 0           return 1;
262             }
263             }
264              
265 0           return 0;
266             }
267              
268             =head2 domestic()
269              
270             Returns the opposite of $self->intl
271            
272             =cut
273              
274             sub domestic {
275 0     0 1   my ($self) = @_;
276              
277 0 0         if ($self->intl) {
278 0           return 0;
279             }
280              
281 0           return 1;
282             }
283              
284             =head2 from_canada()
285              
286             UPS treats Canada differently.
287              
288             =cut
289              
290             sub from_canada {
291 0     0 1   my ($self) = @_;
292              
293 0 0         if ($self->from_country) {
294 0 0         if ($self->from_country =~ /^((CA)|(Canada))$/i) {
295 0           return 1;
296             }
297             }
298              
299 0           return 0;
300             }
301              
302             =head2 to_canada()
303              
304             UPS treats Canada differently.
305              
306             =cut
307              
308             sub to_canada {
309 0     0 1   my ($self) = @_;
310              
311 0 0         if ($self->to_country) {
312 0 0         if ($self->to_country =~ /^((CA)|(Canada))$/i) {
313 0           return 1;
314             }
315             }
316              
317 0           return 0;
318             }
319              
320             =head2 to_ak_or_hi()
321              
322             Alaska and Hawaii are treated differently by many shippers.
323              
324             =cut
325              
326             sub to_ak_or_hi {
327 0     0 1   my ($self) = @_;
328              
329 0 0         return unless $self->to_zip;
330              
331 0           my @ak_hi_zip_config_params = (
332             qw/
333             hi_special_zipcodes_124_224
334             hi_special_zipcodes_126_226
335             ak_special_zipcodes_124_224
336             ak_special_zipcodes_126_226
337             /
338             );
339              
340 0           for (@ak_hi_zip_config_params) {
341 0           my $zips = cfg()->{ups_information}->{$_};
342 0           my $to_zip = $self->to_zip;
343 0 0         if ($zips =~ /$to_zip/) {
344 0           return 1;
345             }
346             }
347              
348 0           return 0;
349             }
350              
351             =head2 add_package( %args )
352              
353             Adds a new package to the shipment.
354              
355             =cut
356              
357             # This is from 0.04.
358             # Needs to be made compatible with the new version.
359              
360             sub add_package {
361 0     0 1   my ($self, %options) = @_;
362              
363             #trace( 'called with ' . uneval( @_ ) );
364              
365 0 0         if (not $self->shipper) {
366 0           error "Need shipper to get the package subclass.";
367 0           return;
368             }
369              
370 0           debug "add_package shipper = " . $self->shipper;
371              
372 0           my $package;
373 0           eval {
374 0           $package
375             = Business::Shipping->_new_subclass($self->shipper . '::Package');
376             };
377 0 0         logdie "Error when creating Package subclass: $@" if $@;
378 0 0         logdie "package was undefined." if not defined $package;
379              
380 0           $package->init(%options);
381              
382             # If the passed package has an ID. Do not evaluate for perl trueness,
383             # because 0 is a valid true value in this case.
384 0 0         if (defined $package->id()) {
385 0           info 'Using id in passed package';
386 0           $self->packages_set($package->id => $package);
387 0           return 1;
388             }
389              
390 0           $self->packages_push($package);
391              
392 0           return 1;
393             }
394              
395             1;
396              
397             __END__