File Coverage

blib/lib/Amazon/MWS/XML/Response/FeedSubmissionResult.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             package Amazon::MWS::XML::Response::FeedSubmissionResult;
2              
3 7     7   656 use strict;
  7         24  
  7         241  
4 7     7   46 use warnings;
  7         18  
  7         241  
5 7     7   2720 use XML::Compile::Schema;
  0            
  0            
6             use Data::Dumper;
7              
8             use Moo;
9             use MooX::Types::MooseLike::Base qw(:all);
10              
11             use namespace::clean;
12              
13             =head1 NAME
14              
15             Amazon::MWS::XML::Response::FeedSubmissionResult -- response parser
16              
17             =head1 SYNOPSIS
18              
19             my $res = Amazon::MWS::XML::Response::FeedSubmissionResult->new(xml => $xml);
20             if ($res->is_success) { ... };
21              
22             =head1 ACCESSOR
23              
24             =head2 xml
25              
26             The xml string
27              
28             =head2 xml_reader
29              
30             A sub reference with the AmazonEnvelope reader.
31              
32             =head2 structure
33              
34             Lazy attribute built via parsing the xml string passed at the constructor.
35              
36             =head1 METHODS
37              
38             =head2 is_success
39              
40             =head2 errors
41              
42             =head2 report_errors
43              
44             A list of error messages, where each element is an hashref with this keys:
45              
46             =over 4
47              
48             =item code (numeric)
49              
50             =item type (warning or error)
51              
52             =item message (human-readable)
53              
54             =back
55              
56             =cut
57              
58             has xml => (is => 'ro', required => '1');
59             has xml_reader => (is => 'ro',
60             required => 1);
61             has structure => (is => 'lazy');
62              
63             sub _build_structure {
64             my $self = shift;
65             my $struct = $self->xml_reader->($self->xml);
66             die "not a processing report xml" unless $struct->{MessageType} eq 'ProcessingReport';
67             if (@{$struct->{Message}} > 1) {
68             die $self->xml . " returned more than 1 message!";
69             }
70             return $struct->{Message}->[0]->{ProcessingReport};
71             }
72              
73             has skus_errors => (is => 'lazy');
74             has skus_warnings => (is => 'lazy');
75             has orders_errors => (is => 'lazy');
76             has orders_warnings => (is => 'lazy');
77              
78             sub _build_skus_errors {
79             my $self = shift;
80             return $self->_parse_results(sku => 'Error');
81             }
82              
83             sub _build_skus_warnings {
84             my $self = shift;
85             return $self->_parse_results(sku => 'Warning');
86             }
87              
88             sub _build_orders_errors {
89             my $self = shift;
90             return $self->_parse_results(order_id => 'Error');
91             }
92              
93             sub _build_orders_warnings {
94             my $self = shift;
95             return $self->_parse_results(order_id => 'Warning');
96             }
97              
98             sub report_errors {
99             my ($self) = @_;
100             my $struct = $self->structure;
101             my @output;
102             if ($struct->{Result}) {
103             foreach my $res (@{ $struct->{Result} }) {
104             if (my $type = $res->{ResultCode}) {
105             if ($type eq 'Error' or $type eq 'Warning') {
106             my @error_chunks;
107             my $error_code = 0;
108             if (my $details = $res->{AdditionalInfo}) {
109             foreach my $key (keys %$details) {
110             push @error_chunks, "$key: $details->{$key}";
111             }
112             }
113             push @error_chunks, $type;
114             if ($res->{ResultMessageCode}) {
115             $error_code = $res->{ResultMessageCode};
116             }
117             if ($res->{ResultDescription}) {
118             push @error_chunks, $res->{ResultDescription};
119             }
120             push @output, {
121             code => $error_code,
122             type => lc($type),
123             message => join(' ', @error_chunks),
124             };
125             }
126             }
127             }
128             }
129             return @output;
130             }
131              
132             sub _parse_results {
133             my ($self, $type, $code) = @_;
134             die unless ($code eq 'Error' or $code eq 'Warning');
135             my $struct = $self->structure;
136             my @msgs;
137             my %map = (sku => 'SKU',
138             order_id => 'AmazonOrderID');
139              
140             my $key = $map{$type} or die "Bad type $type";
141             if ($struct->{Result}) {
142             foreach my $res (@{ $struct->{Result} }) {
143             if ($res->{ResultCode} and $res->{ResultCode} eq $code) {
144             if (my $value = $res->{AdditionalInfo}->{$key}) {
145             push @msgs, {
146             $type => $value,
147             # this is a bit misnamed, but not too much
148             error => $res->{ResultDescription} || '',
149             code => $res->{ResultMessageCode} || '',
150             };
151             }
152             else {
153             push @msgs, {
154             error => $res->{ResultDescription} || '',
155             code => $res->{ResultMessageCode} || '',
156             };
157             }
158             }
159             }
160             }
161             @msgs ? return \@msgs : return;
162             }
163              
164              
165              
166             sub is_success {
167             my $self = shift;
168             my $struct = $self->structure;
169             if ($struct->{StatusCode} eq 'Complete') {
170             # Compute the total - successful
171             my $success = $struct->{ProcessingSummary}->{MessagesSuccessful};
172             my $error = $struct->{ProcessingSummary}->{MessagesWithError};
173             # we ignore the warnings here.
174             # my $warning = $struct->{ProcessingSummary}->{MessagesWithWarning};
175             my $total = $struct->{ProcessingSummary}->{MessagesProcessed};
176             if (!$error and $total == $success) {
177             return 1;
178             }
179             }
180             return;
181             }
182              
183             sub warnings {
184             my $self = shift;
185             return $self->_format_msgs($self->skus_warnings);
186             }
187              
188             sub errors {
189             my $self = shift;
190             return $self->_format_msgs($self->skus_errors);
191             }
192              
193             sub _format_msgs {
194             my ($self, $list) = @_;
195             if ($list && @$list) {
196             my @errors;
197             foreach my $err (@$list) {
198             if ($err->{sku}) {
199             push @errors, "SKU $err->{sku}: $err->{error} ($err->{code})";
200             }
201             elsif ($err->{order_id}) {
202             push @errors, "Order $err->{order_id}: $err->{error} ($err->{code})";
203             }
204             else {
205             push @errors, "$err->{error} ($err->{code})";
206             }
207             }
208             return join("\n", @errors);
209             }
210             return;
211             }
212              
213             =head2 Failures and warnings
214              
215             They return a list of skus or order_id.
216              
217             =over 4
218              
219             =item failed_skus
220              
221             =item skus_with_warnings
222              
223             =item failed_orders
224              
225             =item orders_with_warnings
226              
227             =back
228              
229             =cut
230              
231             sub failed_skus {
232             my ($self) = @_;
233             return $self->_list_faulty(sku => $self->skus_errors);
234             }
235              
236             sub skus_with_warnings {
237             my ($self) = @_;
238             return $self->_list_faulty(sku => $self->skus_warnings);
239             }
240              
241             sub failed_orders {
242             my ($self) = @_;
243             return $self->_list_faulty(order_id => $self->orders_errors);
244             }
245              
246             sub orders_with_warnings {
247             my ($self) = @_;
248             return $self->_list_faulty(order_id => $self->orders_warnings);
249             }
250              
251              
252             sub _list_faulty {
253             my ($self, $what, $list) = @_;
254             die unless $what;
255             if ($list && @$list) {
256             return map { $_->{$what} } @$list;
257             }
258             else {
259             return;
260             }
261             }
262              
263              
264              
265             1;