File Coverage

blib/lib/Webservice/Shipment/Carrier/USPS.pm
Criterion Covered Total %
statement 69 70 98.5
branch 15 24 62.5
condition 1 2 50.0
subroutine 16 17 94.1
pod 6 6 100.0
total 107 119 89.9


line stmt bran cond sub pod time code
1             package Webservice::Shipment::Carrier::USPS;
2              
3 2     2   262414 use Mojo::Base 'Webservice::Shipment::Carrier';
  2         15  
  2         15  
4              
5 2     2   244 use constant DEBUG => $ENV{MOJO_SHIPMENT_DEBUG};
  2         4  
  2         102  
6              
7 2     2   527 use Mojo::Template;
  2         4019  
  2         13  
8 2     2   67 use Mojo::URL;
  2         4  
  2         11  
9 2     2   46 use Mojo::IOLoop;
  2         4  
  2         20  
10 2     2   46 use Mojo::IOLoop::Delay;
  2         5  
  2         10  
11 2     2   592 use Time::Piece;
  2         7087  
  2         10  
12              
13             has api_url => sub { Mojo::URL->new('http://production.shippingapis.com/ShippingAPI.dll?API=TrackV2') };
14              
15             has template => <<'XML';
16             % my ($self, $id) = @_;
17            
18            
19             1
20             127.0.0.1
21             Restore Health
22            
23            
24             XML
25              
26             has carrier_description => sub { 'USPS' };
27             has validation_regex => sub { qr/\b(9\d\d\d ?\d\d\d\d ?\d\d\d\d ?\d\d\d\d ?\d\d\d\d ?\d\d|91\d\d ?\d\d\d\d ?\d\d\d\d ?\d\d\d\d ?\d\d\d\d)\b/i };
28              
29             sub human_url {
30 4     4 1 9 my ($self, $id, $dom) = @_;
31 4         19 return Mojo::URL->new('https://tools.usps.com/go/TrackConfirmAction')->query(tLabels => $id);
32             }
33              
34             sub extract_destination {
35 18     18 1 41 my ($self, $id, $dom, $target) = @_;
36              
37 18         58 my %targets = (
38             postal_code => 'DestinationZip',
39             state => 'DestinationState',
40             city => 'DestinationCity',
41             country => 'DestinationCountryCode',
42             );
43              
44 18 100       66 my $t = $targets{$target} or return;
45 12 100       27 my $addr = $dom->at($t) or return;
46 9         2589 return $addr->text;
47             }
48              
49             sub extract_service {
50 3     3 1 10 my ($self, $id, $dom) = @_;
51 3         11 my $class = $dom->at('Class');
52 3         624 my $service = 'USPS';
53 3 50       10 $service .= ' ' . $class->text if $class;
54 3         106 return $service;
55             }
56              
57             sub extract_status{
58 3     3 1 8 my ($self, $id, $dom) = @_;
59 3         10 my $summary = $dom->at('TrackSummary');
60 3 50       2532 return unless $summary;
61 3         24 my $event = $summary->at('Event')->text;
62 3 50       804 my $delivered = ($event =~ /delivered/i) ? 1 : 0;
63              
64 3         11 my $desc = $dom->at('StatusSummary');
65 3 50       2323 $desc = $desc ? $desc->text : $event;
66              
67 3         104 my $date = $summary->at('EventDate');
68 3 50       648 $date = $date ? $date->text : '';
69 3         95 my $fmt = '%B %d, %Y';
70              
71 3 50       10 if ($date) {
72 3 50       9 if (my $time = $summary->at('EventTime')) {
73 3         555 $time = $time->text;
74 3         85 $date .= " T $time";
75 3         6 $fmt .= ' T %H:%M %p';
76             }
77 3   50     9 $date = eval { Time::Piece->strptime($date, $fmt) } || '';
78 3 50       393 warn $@ if $@;
79             }
80 3         17 return ($desc, $date, $delivered);
81             }
82              
83 3     3 1 8 sub extract_weight { '' }
84              
85             sub request {
86 3     3 1 17 my ($self, $id, $cb) = @_;
87              
88 3         14 my $xml = Mojo::Template->new->render($self->template, $self, $id);
89 3         5037 warn "Request:\n$xml" if DEBUG;
90 3         14 my $url = $self->api_url->clone->query({XML => $xml});
91              
92 3 100       974 unless ($cb) {
93 2         12 my $tx = $self->ua->get($url);
94 2         6890 return _handle_response($tx);
95             }
96              
97             Mojo::IOLoop::Delay->new->steps(
98 1     1   237 sub { $self->ua->get($url, shift->begin) },
99             sub {
100 1     1   3218 my ($ua, $tx) = @_;
101 1 50       4 die $tx->error->{message} if $tx->error;
102 1         20 my $dom = _handle_response($tx);
103 1         401 $self->$cb(undef, $dom);
104             },
105 1     0   5 )->catch(sub{ $self->$cb(pop, undef) })->wait;
  0         0  
106             }
107              
108             sub _handle_response {
109 3     3   6 my $tx = shift;
110 3         9 my $dom = $tx->res->dom;
111 3         35543 warn "Response:\n$dom\n" if DEBUG;
112 3         14 return $dom->at('TrackResponse TrackInfo');
113             }
114              
115             1;
116              
117             =head1 NAME
118              
119             Webservice::Shipment::Carrier::USPS - USPS handling for Webservice::Shipment
120              
121             =head1 DESCRIPTION
122              
123             Implements USPS handling for L.
124             It is a subclass of L which implements all the necessary methods.
125              
126             =head1 ATTRIBUTES
127              
128             L implements all of the attributes from L and implements the following new ones
129              
130             =head2 template
131              
132             The string template used with L to format the request.
133              
134             =head1 NOTES
135              
136             The service does not provide weight information, so C will always return an empty string.
137