File Coverage

blib/lib/Net/Easypost/Shipment.pm
Criterion Covered Total %
statement 32 43 74.4
branch 4 6 66.6
condition 2 3 66.6
subroutine 9 10 90.0
pod 3 3 100.0
total 50 65 76.9


line stmt bran cond sub pod time code
1             package Net::Easypost::Shipment;
2             $Net::Easypost::Shipment::VERSION = '0.20';
3 6     6   41 use Carp qw/croak/;
  6         13  
  6         421  
4 6     6   38 use Types::Standard qw/ArrayRef HashRef InstanceOf Str/;
  6         14  
  6         81  
5              
6 6     6   6575 use Moo;
  6         16  
  6         40  
7             with qw/Net::Easypost::PostOnBuild/;
8             with qw/Net::Easypost::Resource/;
9 6     6   2140 use namespace::autoclean;
  6         14  
  6         60  
10              
11             has [qw/from_address to_address/] => (
12             is => 'ro',
13             isa => InstanceOf['Net::Easypost::Address'],
14             required => 1,
15             );
16              
17             has 'parcel' => (
18             is => 'rw',
19             isa => InstanceOf['Net::Easypost::Parcel'],
20             required => 1,
21             );
22              
23             has 'customs_info' => (
24             is => 'rw',
25             isa => InstanceOf['Net::Easypost::CustomsInfo'],
26             );
27              
28             has 'scan_form' => (
29             is => 'rw',
30             isa => InstanceOf['Net::Easypost::ScanForm'],
31             );
32              
33             has 'rates' => (
34             is => 'rwp',
35             isa => ArrayRef[InstanceOf['Net::Easypost::Rate']],
36             );
37              
38             has 'options' => (
39             is => 'rw',
40             isa => HashRef[Str],
41             );
42              
43             sub _build_fieldnames {
44 6     6   20287 return [qw/to_address from_address parcel customs_info scan_form rates options/];
45             }
46              
47 6     6   1013 sub _build_role { 'shipment' }
48 6     6   316 sub _build_operation { '/shipments' }
49              
50             sub BUILD {}
51             after BUILD => sub {
52             my ($self) = @_;
53              
54             my $resp = $self->requester->post(
55             $self->operation,
56             $self->serialize,
57             );
58             $self->_set_id( $resp->{id} );
59             $self->_set_rates(
60             [ map {
61             Net::Easypost::Rate->new(
62             id => $_->{id},
63             carrier => $_->{carrier},
64             service => $_->{service},
65             rate => $_->{rate},
66             shipment_id => $self->id,
67             )
68             } @{ $resp->{rates} }
69             ]
70             );
71             };
72              
73             sub serialize {
74 12     12 1 42 my ($self) = @_;
75              
76             # want a hashref of e.g., shipment[to_address][id] => foo from all defined attributes
77             return {
78 38         580 map { $self->role . "[$_][id]" => $self->$_->id }
79 12         43 grep { defined $self->$_ }
  48         711  
80             qw(to_address from_address parcel customs_info)
81             };
82             }
83              
84             sub clone {
85 0     0 1 0 my ($self) = @_;
86              
87             return Net::Easypost::Shipment->new(
88 0         0 map { $_ => $self->$_ }
89 0         0 grep { defined $self->$_ }
90 0         0 'id', @{ $self->fieldnames }
  0         0  
91             );
92             }
93              
94             sub buy {
95 2     2 1 11 my ($self, %options) = @_;
96              
97 2         6 my $rate;
98 2 100 66     21 if (exists $options{rate} && $options{rate} eq 'lowest') {
    50          
99             ($rate) =
100 1         3 sort { $a->{rate} <=> $b->{rate} } @{ $self->rates };
  5         20  
  1         10  
101             }
102             elsif (exists $options{service_type}) {
103             ($rate) =
104 1         3 grep { $options{service_type} eq $_->service } @{ $self->rates };
  4         12  
  1         4  
105             }
106             else {
107 0         0 croak "Missing 'service' or 'rate' from options hash";
108             }
109              
110 2 50       12 unless ($rate) {
111 0         0 my $msg = "Allowed services and rates for this shipment are:\n";
112 0         0 foreach my $rate (@{ $self->rates }) {
  0         0  
113 0         0 $msg .= sprintf("\t%-15s: %4.2f\n", $rate->service, $rate->rate);
114             }
115              
116 0         0 croak "Invalid service '$options{service_type}' selected for shipment " . $self->id . "\n$msg";
117             }
118              
119 2         27 my $response = $self->requester->post(
120             $self->operation . '/' . $self->id . '/buy',
121             $rate->serialize
122             );
123              
124 2         13 my $label = $response->{postage_label};
125             return Net::Easypost::Label->new(
126             id => $label->{id},
127             tracking_code => $response->{tracking_code},
128             url => $label->{label_url},
129             filetype => $label->{label_file_type},
130             rate => Net::Easypost::Rate->new($response->{selected_rate}),
131             filename => 'EASYPOST_LABEL_'
132             . $label->{id}
133             . '.'
134 2         84 . substr($label->{label_file_type}, index($label->{label_file_type}, '/') + 1),
135             );
136             }
137              
138             1;
139              
140             __END__