File Coverage

blib/lib/Business/UPS/Tracking.pm
Criterion Covered Total %
statement 7 9 77.7
branch n/a
condition n/a
subroutine 3 3 100.0
pod n/a
total 10 12 83.3


line stmt bran cond sub pod time code
1             # ============================================================================
2             package Business::UPS::Tracking;
3             # ============================================================================
4 5     5   359750 use utf8;
  5         74  
  5         34  
5 5     5   1098 use 5.0100;
  5         20  
  5         221  
6              
7 5     5   25045 use Moose;
  0            
  0            
8             with qw(Business::UPS::Tracking::Role::Base);
9              
10             no if $] >= 5.017004, warnings => qw(experimental::smartmatch);
11              
12             use Business::UPS::Tracking::Exception;
13             use LWP::UserAgent;
14             use Business::UPS::Tracking::Utils;
15             use Business::UPS::Tracking::Request;
16              
17             our $VERSION = "1.11";
18             our $AUTHORITY = 'cpan:MAROS';
19             our $CHECKSUM = $ENV{TRACKING_CHECKSUM} // 1 ;
20              
21             =encoding utf8
22              
23             =head1 NAME
24              
25             Business::UPS::Tracking - Interface to the UPS tracking webservice
26              
27             =head1 SYNOPSIS
28              
29             use Business::UPS::Tracking;
30            
31             my $tracking = Business::UPS::Tracking->new(
32             AccessLicenseNumber => '1CFFED5A5E91B17',
33             UserId => 'myupsuser',
34             Password => 'secret',
35             );
36            
37             eval {
38             my $response = $tracking->request(
39             TrackingNumber => '1Z12345E1392654435',
40             )->run();
41            
42             foreach my $shipment ($response->shipment) {
43             say 'Service code is '.$shipment->ServiceCode;
44             foreach my $package ($shipment->Package) {
45             say 'Status is '.$package->CurrentStatus;
46             }
47             }
48             };
49            
50             if (my $e = Exception::Class->caught) {
51             given ($e) {
52             when ($_->isa('Business::UPS::Tracking::X::HTTP')) {
53             say 'HTTP ERROR:'.$e->full_message;
54             }
55             when ($_->isa('Business::UPS::Tracking::X::UPS')) {
56             say 'UPS ERROR:'.$e->full_message.' ('.$e->code.')';
57             }
58             default {
59             say 'SOME ERROR:'.$e;
60             }
61             }
62             }
63              
64             =head1 DESCRIPTION
65              
66             =head2 Class structure
67              
68             .-----------------------------------.
69             | Business::UPS::Tracking |
70             '-----------------------------------'
71             ^
72             HAS ONE
73             |
74             .-----------------------------------.
75             | B::U::T::Request |
76             '-----------------------------------'
77             ^
78             HAS ONE
79             |
80             .-----------------------------------.
81             | B::U::T::Response |
82             '-----------------------------------'
83             |
84             HAS MANY
85             v
86             .-----------------------------------.
87             | B::U::T::Shipment |
88             '-----------------------------------'
89             ^ ^
90             ISA ISA
91             | |
92             .---------------------------------. .-----------------------------------.
93             | B::U::T::Shipment::Freight | | B::U::T::Shipment::Smallpackage |
94             |---------------------------------| |-----------------------------------|
95             | Freight shipment type | | Small package shipment type |
96             | Not yet implemented | '-----------------------------------'
97             '---------------------------------' |
98             HAS MANY
99             v
100             .-----------------------------------.
101             | B::U::T::Element::Package |
102             '-----------------------------------'
103             |
104             HAS MANY
105             v
106             .-----------------------------------.
107             | B::U::T::Element::Activity |
108             '-----------------------------------'
109              
110             =head2 Exception Handling
111              
112             If anythis goes wrong Business::UPS::Tracking throws an exception. Exceptions
113             are always L<Exception::Class> objects which contain structured information
114             about the error. Please refer to the synopsis or to the L<Exception::Class>
115             documentation for documentation how to catch and rethrow exeptions.
116              
117             The following exception classes are defined:
118              
119             =head3 Business::UPS::Tracking::X
120              
121             Basic exception class. All other exception classes inherit from this class.
122              
123             =head3 Business::UPS::Tracking::X::HTTP
124              
125             HTTP error. The object provides additional parameters:
126              
127             =over
128              
129             =item * http_response : L<HTTP::Response> object
130              
131             =item * request : L<Business::UPS::Tracking::Request> object
132              
133             =back
134              
135             =head3 Business::UPS::Tracking::X::UPS
136              
137             UPS error message.The object provides additional parameters:
138              
139             =over
140              
141             =item * code : UPS error code
142              
143             =item * severity : Error severity 'hard' or 'soft'
144              
145             =item * context : L<XML::LibXML::Node> object containing the whole error response.
146              
147             =item * request : L<Business::UPS::Tracking::Request> object
148              
149             =back
150              
151             =head3 Business::UPS::Tracking::X::XML
152              
153             XML parser or schema error.
154              
155             =over
156              
157             =item * method
158              
159             =item * depth
160              
161             =item * evaltext
162              
163             =item * sub_name
164              
165             =item * last_error
166              
167             =item * sub
168              
169             =item * is_require
170              
171             =item * has_args
172              
173             =back
174              
175             =head2 Accessor / method naming
176              
177             The naming of the methods and accessors tries to stick close to the names
178             used by the UPS webservice. All accessors containg uppercase letters access
179             xml data. Lowercase-only accessors and methods are used for utility
180             functions.
181              
182             =head2 UPS license
183              
184             In order to use this module you need to obtain a "Tracking WebService"
185             license key. See L<http://www.ups.com/e_comm_access/gettools_index> for more
186             information.
187              
188             =head1 METHODS
189              
190             =head2 new
191              
192             my $tracking = Business::UPS::Tracking->new(%params);
193              
194             Create a C<Business::UPS::Tracking> object. See L<ACCESSORS> for available
195             parameters.
196              
197             =head2 access_request
198              
199             UPS access request.
200              
201             =head2 request
202              
203             my $request = $tracking->request(%request_params);
204              
205             Returns a L<Business::UPS::Tracking::Request> object.
206              
207             =head2 request_run
208              
209             my $response = $tracking->request_run(%request_params);
210              
211             Generates a L<Business::UPS::Tracking::Request> object and imideately
212             executes it, returning a L<Business::UPS::Tracking::Response> object.
213              
214             =head1 ACCESSORS
215              
216             =head2 AccessLicenseNumber
217              
218             UPS tracking service access license number
219              
220             =head2 UserId
221              
222             UPS account username
223              
224             =head2 Password
225              
226             UPS account password
227              
228             =head2 config
229              
230             Optionally you can retrieve all or some UPS webservice credentials from a
231             configuration file. This accessor holds the path to this file.
232             Defaults to C<~/.ups_tracking>
233              
234             Example configuration file:
235              
236             <?xml version="1.0"?>
237             <UPS_tracking_webservice_config>
238             <AccessLicenseNumber>1CFFED5A5E91B17</AccessLicenseNumber>
239             <UserId>myupsuser</UserId>
240             <Password>secret</Password>
241             </UPS_tracking_webservice_config>
242              
243             =head2 retry_http
244              
245             Number of retries if http errors occur
246              
247             Defaults to 0
248              
249             =head2 url
250              
251             UPS Tracking webservice url.
252              
253             Defaults to https://wwwcie.ups.com/ups.app/xml/Track
254              
255             =head2 _ua
256              
257             L<LWP::UserAgent> object.
258              
259             Automatically generated
260              
261             =cut
262              
263             has 'retry_http' => (
264             is => 'rw',
265             isa => 'Int',
266             default => 0,
267             documentation => 'Number of retries if HTTP errors occur [Default 0]',
268             );
269             has 'url' => (
270             is => 'rw',
271             default => sub { 'https://wwwcie.ups.com/ups.app/xml/Track' },
272             documentation => 'UPS webservice url',
273             );
274             has '_ua' => (
275             is => 'rw',
276             lazy => 1,
277             isa => 'LWP::UserAgent',
278             builder => '_build_ua',
279             );
280              
281              
282             sub _build_ua {
283             my ($self) = @_;
284              
285             my $ua = LWP::UserAgent->new(
286             agent => __PACKAGE__ . " ". $VERSION,
287             timeout => 50,
288             env_proxy => 1,
289             );
290              
291             return $ua;
292             }
293              
294             sub access_request {
295             my ($self) = @_;
296              
297             my $license = Business::UPS::Tracking::Utils::escape_xml($self->AccessLicenseNumber);
298             my $username = Business::UPS::Tracking::Utils::escape_xml($self->UserId);
299             my $password = Business::UPS::Tracking::Utils::escape_xml($self->Password);
300            
301             return <<ACR
302             <?xml version="1.0"?>
303             <AccessRequest xml:lang='en-US'>
304             <AccessLicenseNumber>$license</AccessLicenseNumber>
305             <UserId>$username</UserId>
306             <Password>$password</Password>
307             </AccessRequest>
308             ACR
309             }
310              
311             sub request {
312             my ( $self, %params ) = @_;
313             return Business::UPS::Tracking::Request->new(
314             %params,
315             tracking => $self,
316             );
317             }
318              
319             sub request_run {
320             my ( $self, %params ) = @_;
321             return $self->request(%params)->run();
322             }
323              
324             __PACKAGE__->meta->make_immutable;
325             no Moose;
326              
327             =head1 SUPPORT
328              
329             Please report any bugs or feature requests to
330             C<bug-buisness-ups-tracking@rt.cpan.org>, or through the web interface at
331             L<http://rt.cpan.org/Public/Bug/Report.html?Queue=Business::UPS::Tracking>.
332             I will be notified, and then you'll automatically be notified of progress on
333             your report as I make changes.
334              
335             =head1 SEE ALSO
336              
337             Download the UPS "OnLine® Tools Tracking Developer Guide" and get a
338             developer key at L<http://www.ups.com/e_comm_access/gettools_index?loc=en_US>.
339             Please check the "Developer Guide" for more detailed documentation on the
340             various fields.
341              
342             The L<WebService::UPS::TrackRequest> provides an alternative simpler
343             implementation.
344              
345             =head1 AUTHOR
346              
347             MaroÅ¡ Kollár
348             CPAN ID: MAROS
349             maros [at] k-1.com
350            
351             http://www.k-1.com
352              
353             =head1 COPYRIGHT
354              
355             Business::UPS::Tracking is Copyright (c) 2012 MaroÅ¡ Kollár
356             - L<http://www.k-1.com>
357              
358             =head1 LICENCE
359              
360             This library is free software, you can redistribute it and/or modify
361             it under the same terms as Perl itself.
362              
363             =cut
364              
365             'Where is my "30 HP NorTrac Bulldozer" I ordered at Amazon recently? (http://www.amazon.com/30-HP-NorTrac-Bulldozer-Backhoe/dp/B000EIWSN0)';