File Coverage

blib/lib/Geo/Address/Mail/Standardizer/USPS/AMS/Results.pm
Criterion Covered Total %
statement 1 3 33.3
branch n/a
condition n/a
subroutine 1 1 100.0
pod n/a
total 2 4 50.0


line stmt bran cond sub pod time code
1             package Geo::Address::Mail::Standardizer::USPS::AMS::Results;
2              
3 1     1   64450 use Moose;
  0            
  0            
4             use Message::Stack;
5             use Message::Stack::Message;
6             use MooseX::Storage;
7             with qw(MooseX::Storage::Deferred);
8              
9             =head1 NAME
10              
11             Geo::Address::Mail::Standardizer::USPS::AMS::Results - results object from the USPS Address Matching System
12              
13             =head1 SYNOPSIS
14              
15             my $address = new Geo::Address::Mail::US;
16             my $ms = new Geo::Address::Mail::Standardizer::USPS::AMS;
17             my $result = $ms->standardize($addr);
18              
19             $result->address; # new standardized Geo::Address::Mail::US object
20             $result->multiple; # boolean indicating whether multiple addresses are returned.
21             $result->single; # boolean indicating whether a single address was returned.
22             $result->found; # integer indicating the number of candidates
23             $result->error; # string with an error message
24             $result->default; # boolean indicating a Z4_DEFAULT return code, which means:
25             # "An address was found, but a more specific address could be
26             # found with more information"
27             $result->candidates; # reference to an array of Geo::Address::Mail::US objects, all
28             # of which are possible matches
29             $result->changed; # A hashref whose values are key => 1 pairs indicating which
30             # fields were changed during standardization
31              
32             $result->standardized_address; # The standardized address, in the case of a single
33             # matching address
34              
35             =head1 DESCRIPTION
36              
37             The results of a call to Geo::Address::Mail::Standardizer::USPS::AMS's standardize method.
38              
39             =cut
40              
41             extends 'Geo::Address::Mail::Standardizer::Results';
42              
43             use Geo::Address::Mail::US;
44             use Moose::Util::TypeConstraints;
45              
46             our $VERSION = '0.05';
47              
48             subtype 'Address' => as 'Geo::Address::Mail::US';
49             subtype 'AddressList' => as 'ArrayRef[Address]';
50              
51             coerce 'Address'
52             => from 'HashRef'
53             => via { new Geo::Address::Mail::US $_ };
54              
55             coerce 'AddressList'
56             => from 'ArrayRef[HashRef]'
57             => via { [ map { new Geo::Address::Mail::US $_ } @$_ ] };
58              
59             has error => (is => 'ro', isa => 'Str|Undef', predicate => 'has_error');
60             has found => (is => 'ro', isa => 'Int', predicate => 'has_found');
61             has default => (is => 'ro', isa => 'Bool', predicate => 'has_default');
62             has single => (is => 'ro', isa => 'Bool', predicate => 'has_single');
63             has multiple => (is => 'ro', isa => 'Bool', predicate => 'has_multiple');
64             has changed => (is => 'ro', isa => 'HashRef', predicate => 'has_changed');
65             has footnotes => (is => 'ro', isa => 'HashRef', predicate => 'has_footnotes');
66             has messages => ( is => 'ro', isa => 'Message::Stack', lazy_build => 1);
67              
68             has candidates =>
69             is => 'ro',
70             isa => 'AddressList',
71             coerce => 1,
72             traits => [ 'Array' ],
73             handles =>
74             {
75             has_candidates => 'count',
76             num_candidates => 'count',
77             get_candidate => 'get',
78             };
79              
80             has '+standardized_address' =>
81             isa => 'Address',
82             coerce => 1;
83              
84              
85             sub _build_messages {
86             my $self = shift;
87              
88             # These are the footnotes direct from the USPS AMS API docs
89             my $codes = {
90              
91             # The address was found to have a different 5-digit ZIP Code than given in the
92             # submitted list. The correct ZIP Code is shown in the output address.
93             'A' => Message::Stack::Message->new(
94             id => 'zip_code_corrected',
95             level => 'info',
96             scope => 'standardization',
97             subject => 'zip',
98             text => 'ZIP Code Corrected',
99             ),
100              
101             # The spelling of the city name and/or state abbreviation in the submitted address
102             # was found to be different than the standard spelling. The standard spelling of the
103             # city name and state abbreviation are shown in the output address.
104             'B' => Message::Stack::Message->new(
105             id => 'city_state_corrected',
106             level => 'info',
107             scope => 'standardization',
108             subject => 'address',
109             text => 'City/State Corrected',
110             ),
111              
112             # The ZIP Code in the submitted address could not be found because neither a
113             # valid city, state, nor valid 5-digit ZIP Code was present. It is also recommended
114             # that the requestor check the submitted address for accuracy.
115             'C' => Message::Stack::Message->new(
116             id => 'invalid_city_state_zip',
117             level => 'error',
118             scope => 'standardization',
119             subject => 'zip',
120             text => 'Invalid City/State/ZIP',
121             ),
122              
123             # This is a record listed by the United States Postal Service on the national
124             # ZIP+4 file as a non-deliverable location. It is recommended that the requestor
125             # verify the accuracy of the submitted address.
126             'D' => Message::Stack::Message->new(
127             id => 'no_zip_code_assigned',
128             level => 'error',
129             scope => 'standardization',
130             subject => 'zip',
131             text => 'No ZIP+4 Code Assigned',
132             ),
133              
134             # Multiple records were returned, but each shares the same 5-digit ZIP Code.
135             'E' => Message::Stack::Message->new(
136             id => 'multiple_within_zip',
137             level => 'notice',
138             scope => 'standardization',
139             subject => 'zip',
140             text => 'ZIP Code Assigned with a Multiple Response',
141             ),
142              
143             # The address, exactly as submitted, could not be found in the city, state, or
144             # ZIP Code provided. It is also recommended that the requestor check the submitted
145             # address for accuracy. For example, the street address line may be abbreviated
146             # excessively and may not be fully recognizable.
147             'F' => Message::Stack::Message->new(
148             id => 'address_not_found',
149             level => 'error',
150             scope => 'standardization',
151             subject => 'address',
152             text => 'Address Not Found',
153             ),
154              
155             # Information in the firm line was determined to be a part of the address. It
156             # was moved out of the firm line and incorporated into the address line.
157             'G' => Message::Stack::Message->new(
158             id => 'firm_line_incorporated',
159             level => 'notice',
160             scope => 'standardization',
161             subject => 'address',
162             text => 'All or Part of the Firm Line User For Address Line',
163             ),
164              
165             # ZIP+4 information indicates this address is a building. The address as
166             # submitted does not contain an apartment/suite number. It is recommended
167             # that the requestor check the submitted address and add the missing apartment
168             # or suite number to ensure the correct Delivery Point Barcode (DPBC).
169             'H' => Message::Stack::Message->new(
170             id => 'missing_secondary_number',
171             level => 'warning',
172             scope => 'standardization',
173             subject => 'address',
174             text => 'Missing Secondary Number',
175             ),
176              
177             # More than one ZIP+4 Code was found to satisfy the address as submitted.
178             # The submitted address did not contain sufficiently complete or correct
179             # data to determine a single ZIP+4 Code. It is recommended that the requestor
180             # check the address for accuracy and completeness. For example, firm name,
181             # or institution name, doctor’s name, suite number, apartment number, box
182             # number, floor number, etc. may be missing or incorrect. Also pre-directional
183             # or post-directional indicators (North = N, South = S, East = E, West = W,
184             # etc.) and/or street suffixes (Street = ST, Avenue = AVE, Road = RD,
185             # Circle = CIR, etc.) may be missing or incorrect.
186             'I' => Message::Stack::Message->new(
187             id => 'insufficient_data',
188             level => 'error',
189             scope => 'standardization',
190             subject => 'address',
191             text => 'Insufficient/Incorrect Data',
192             ),
193              
194             # The input contained two addresses. For example: 123 MAIN ST PO BOX 99.
195             'J' => Message::Stack::Message->new(
196             id => 'dual_address',
197             level => 'error',
198             scope => 'standardization',
199             subject => 'address',
200             text => 'PO Box Dual Address',
201             ),
202              
203             # CASS rule does not allow a match when the cardinal point of a directional
204             # changes more than 90%.
205             'K' => Message::Stack::Message->new(
206             id => 'cardinal_rule_violation',
207             level => 'error',
208             scope => 'standardization',
209             subject => 'address',
210             text => 'Multiple Response Due To Cardinal Rule',
211             ),
212              
213             # An address component (i.e., directional or suffix only) was added, changed,
214             # or deleted in order to achieve a match.
215             'L' => Message::Stack::Message->new(
216             id => 'address_component_changed',
217             level => 'info',
218             scope => 'standardization',
219             subject => 'address',
220             text => 'Address Component Changed',
221             ),
222              
223             # The spelling of the street name was changed in order to achieve a match.
224             'M' => Message::Stack::Message->new(
225             id => 'street_name_changed',
226             level => 'info',
227             scope => 'standardization',
228             subject => 'address',
229             text => 'Street Name Changed',
230             ),
231              
232             # The delivery address was standardized. For example, if STREET was in the
233             # delivery address, the system will return ST as its standard spelling.
234             'N' => Message::Stack::Message->new(
235             id => 'address_standardized',
236             level => 'info',
237             scope => 'standardization',
238             subject => 'address',
239             text => 'Address Standardized',
240             ),
241              
242             # More than one ZIP+4 Code was found to satisfy the address as submitted. The
243             # lowest ZIP +4 addon may be used to break the tie between the records.
244             'O' => Message::Stack::Message->new(
245             id => 'lowest_four_tiebreaker',
246             level => 'notice',
247             scope => 'standardization',
248             subject => 'zip',
249             text => 'Multiple response can be broken by using the lowest +4',
250             ),
251              
252             # The delivery address is matchable, but is known by another (preferred) name.
253             # For example, in New York, NY, AVENUE OF THE AMERICAS is also known as 6TH AVE.
254             # An inquiry using a delivery address of 55 AVE OF THE AMERICAS would be flagged
255             # with a Footnote Flag P.
256             'P' => Message::Stack::Message->new(
257             id => 'better_address_exists',
258             level => 'notice',
259             scope => 'standardization',
260             subject => 'address',
261             text => 'Better Address Exists',
262             ),
263              
264             # Match to an address with a unique ZIP Code.
265             'Q' => Message::Stack::Message->new(
266             id => 'unique_zip_code',
267             level => 'info',
268             scope => 'standardization',
269             subject => 'zip',
270             text => 'Unique ZIP Code Match',
271             ),
272              
273             # The delivery address is matchable, but the EWS file indicates that an exact
274             # match will be available soon.
275             'R' => Message::Stack::Message->new(
276             id => 'ews_no_match',
277             level => 'error',
278             scope => 'standardization',
279             subject => 'ews',
280             text => 'No Match due to EWS',
281             ),
282              
283             # The secondary information (i.e., floor, suite, apartment, or box number) does
284             # not match that on the national ZIP+4 file. This secondary information, although
285             # present on the input address, was not valid in the range found on the national
286             # ZIP+4 file.
287             'S' => Message::Stack::Message->new(
288             id => 'incorrect_secondary_number',
289             level => 'error',
290             scope => 'standardization',
291             subject => 'secondary_number',
292             text => 'Incorrect Secondary Number',
293             ),
294              
295             # The search resulted in a single response; however, the record matched was
296             # flagged as having magnet street syndrome. “Whenever an input address has a
297             # single suffix word or a single directional word as the street name, or whenever
298             # the ZIP+4 File records being matched to have a single suffix word or a single
299             # directional word as the street name field, then an exact match between the
300             # street, suffix and/or post- directional and the same components on the ZIP+4
301             # File must occur before a match can be made. Adding, changing or deleting a
302             # component from the input address to obtain a match to a ZIP+4 record will be
303             # considered incorrect.” Instead of returning a “no match” in this situation a
304             # multiple response is returned to allow access the candidate record.
305             'T' => Message::Stack::Message->new(
306             id => 'magnet_street_syndrome',
307             level => 'warning',
308             scope => 'standardization',
309             subject => 'address',
310             text => 'Multiple response due to Magnet Street Syndrome',
311             ),
312              
313             # The city or post office name in the submitted address is not recognized
314             # by the United States Postal Service as an official last line name (preferred
315             # city name), and is not acceptable as an alternate name. This does denote an
316             # error and the preferred city name will be provided as output.
317             'U' => Message::Stack::Message->new(
318             id => 'unofficial_post_office_name',
319             level => 'warning',
320             scope => 'standardization',
321             subject => 'post_office',
322             text => 'Unofficial Post Office Name',
323             ),
324              
325             # The city and state in the submitted address could not be verified as
326             # corresponding to the given 5-digit ZIP Code. This comment does not
327             # necessarily denote an error; however, it is recommended that the requestor
328             # check the city and state in the submitted address for accuracy.
329             'V' => Message::Stack::Message->new(
330             id => 'unverifiable_city_state',
331             level => 'warning',
332             scope => 'standardization',
333             subject => 'city_state',
334             text => 'Unverifiable City/State',
335             ),
336              
337             # The input address record contains a delivery address other than a PO BOX,
338             # General Delivery, or Postmaster with a 5-digit ZIP Code that is identified
339             # as a “small town default.” The United States Postal Service does not provide
340             # street delivery for this ZIP Code. The United States Postal Service requires
341             # use of a PO BOX, General Delivery, or Postmaster for delivery within this ZIP
342             # Code.
343             'W' => Message::Stack::Message->new(
344             id => 'invalid_delivery_address',
345             level => 'error',
346             scope => 'standardization',
347             subject => 'address',
348             text => 'Invalid Delivery Address',
349             ),
350              
351             # Default match inside a unique ZIP Code.
352             'X' => Message::Stack::Message->new(
353             id => 'unique_zip_code_default',
354             level => 'info',
355             scope => 'standardization',
356             subject => 'default',
357             text => 'Unique Zip Code Default',
358             ),
359              
360             # Match made to a record with a military ZIP Code.
361             'Y' => Message::Stack::Message->new(
362             id => 'military_match',
363             level => 'info',
364             scope => 'standardization',
365             subject => 'match',
366             text => 'Military Match',
367             ),
368              
369             # The ZIPMOVE product shows which ZIP + 4 records have moved from one ZIP Code to
370             # another. If an input address matches to a ZIP + 4 record which the ZIPMOVE product
371             # indicates as having moved, the search is performed again in the new ZIP Code.
372             'Z' => Message::Stack::Message->new(
373             id => 'zip_move_match',
374             level => 'info',
375             scope => 'standardization',
376             subject => 'match',
377             text => 'ZIP Move Match',
378             )
379             };
380              
381             # All of that, for this.
382             my $stack = Message::Stack->new;
383             my $footnotes = $self->footnotes;
384             foreach my $fn (keys(%{$footnotes})) {
385             $stack->add($codes->{uc($fn)});
386             }
387              
388             return $stack;
389             }
390              
391             __PACKAGE__->meta->make_immutable;
392              
393              
394             =head1 AUTHOR
395              
396             Mike Eldridge <diz@cpan.org>
397              
398             =head1 COPYRIGHT
399              
400             Copyright (c) 2010 Mike Eldridge
401              
402             =head1 LICENSE
403              
404             This program is free software; you can redistribute it and/or modify it
405             under the terms of either: the GNU General Public License as published
406             by the Free Software Foundation; or the Artistic License.
407              
408             See http://dev.perl.org/licenses/ for more information.
409              
410             =cut
411              
412              
413             1;