File Coverage

blib/lib/Net/Easypost/Shipment.pm
Criterion Covered Total %
statement 32 45 71.1
branch 5 8 62.5
condition 2 3 66.6
subroutine 9 10 90.0
pod 3 3 100.0
total 51 69 73.9


line stmt bran cond sub pod time code
1             package Net::Easypost::Shipment;
2             $Net::Easypost::Shipment::VERSION = '0.23';
3 6     6   33 use Carp qw/croak/;
  6         9  
  6         268  
4 6     6   29 use Types::Standard qw/ArrayRef HashRef InstanceOf Str/;
  6         12  
  6         53  
5              
6 6     6   4769 use Moo;
  6         12  
  6         25  
7             with qw/Net::Easypost::PostOnBuild/;
8             with qw/Net::Easypost::Resource/;
9 6     6   1791 use namespace::autoclean;
  6         12  
  6         54  
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   21764 return [qw/to_address from_address parcel customs_info scan_form rates options/];
45             }
46              
47 6     6   858 sub _build_role { 'shipment' }
48 6     6   326 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 44 my ($self) = @_;
75              
76             # want a hashref of e.g., shipment[to_address][id] => foo from all defined attributes
77             return {
78             (defined $self->options
79 0         0 ? map { $self->role . "[options][$_]" => $self->options->{$_} } %{$self->options}
  0         0  
80             : ()),
81 38         505 map { $self->role . "[$_][id]" => $self->$_->id }
82 12 50       223 grep { defined $self->$_ }
  48         710  
83             qw(to_address from_address parcel customs_info)
84             };
85             }
86              
87             sub clone {
88 0     0 1 0 my ($self) = @_;
89              
90             return Net::Easypost::Shipment->new(
91 0         0 map { $_ => $self->$_ }
92 0         0 grep { defined $self->$_ }
93 0         0 'id', @{ $self->fieldnames }
  0         0  
94             );
95             }
96              
97             sub buy {
98 2     2 1 11 my ($self, %options) = @_;
99              
100 2         7 my $rate;
101 2 100 66     21 if (exists $options{rate} && $options{rate} eq 'lowest') {
    50          
102             ($rate) =
103 1         2 sort { $a->{rate} <=> $b->{rate} } @{ $self->rates };
  5         14  
  1         7  
104             }
105             elsif (exists $options{service_type}) {
106             ($rate) =
107 1         4 grep { $options{service_type} eq $_->service } @{ $self->rates };
  4         22  
  1         8  
108             }
109             else {
110 0         0 croak "Missing 'service' or 'rate' from options hash";
111             }
112              
113 2 50       9 unless ($rate) {
114 0         0 my $msg = "Allowed services and rates for this shipment are:\n";
115 0         0 foreach my $rate (@{ $self->rates }) {
  0         0  
116 0         0 $msg .= sprintf("\t%-15s: %4.2f\n", $rate->service, $rate->rate);
117             }
118              
119 0         0 croak "Invalid service '$options{service_type}' selected for shipment " . $self->id . "\n$msg";
120             }
121              
122 2         27 my $response = $self->requester->post(
123             $self->operation . '/' . $self->id . '/buy',
124             $rate->serialize
125             );
126              
127 2         9 my $label = $response->{postage_label};
128             return Net::Easypost::Label->new(
129             id => $label->{id},
130             tracking_code => $response->{tracking_code},
131             url => $label->{label_url},
132             filetype => $label->{label_file_type},
133             rate => Net::Easypost::Rate->new($response->{selected_rate}),
134             filename => 'EASYPOST_LABEL_'
135             . $label->{id}
136             . '.'
137 2         87 . substr($label->{label_file_type}, index($label->{label_file_type}, '/') + 1),
138             );
139             }
140              
141             1;
142              
143             __END__