File Coverage

blib/lib/Business/ES/CodigoPostal.pm
Criterion Covered Total %
statement 100 101 99.0
branch 69 72 95.8
condition 17 19 89.4
subroutine 15 15 100.0
pod 4 4 100.0
total 205 211 97.1


line stmt bran cond sub pod time code
1             package Business::ES::CodigoPostal;
2              
3             # ABSTRACT: Validación de códigos postales españoles y obtención de provincia
4              
5 4     4   976256 use strict;
  4         9  
  4         161  
6 4     4   19 use warnings;
  4         11  
  4         294  
7              
8 4     4   22 use Exporter 'import';
  4         7  
  4         301  
9             our @EXPORT_OK = qw(validate_cp);
10              
11             use Class::XSAccessor {
12 4         43 accessors => [qw(codigo ca error iso_3166_2 strict provincia prov_code region valid)]
13 4     4   4545 };
  4         12073  
14              
15             our $VERSION = '0.02';
16              
17              
18 4         1183 use constant PROVINCIAS => {
19             '01' => 'Álava',
20             '02' => 'Albacete',
21             '03' => 'Alicante',
22             '04' => 'Almería',
23             '05' => 'Ávila',
24             '06' => 'Badajoz',
25             '07' => 'Islas Baleares',
26             '08' => 'Barcelona',
27             '09' => 'Burgos',
28             '10' => 'Cáceres',
29             '11' => 'Cádiz',
30             '12' => 'Castellón',
31             '13' => 'Ciudad Real',
32             '14' => 'Córdoba',
33             '15' => 'La Coruña',
34             '16' => 'Cuenca',
35             '17' => 'Gerona',
36             '18' => 'Granada',
37             '19' => 'Guadalajara',
38             '20' => 'Guipúzcoa',
39             '21' => 'Huelva',
40             '22' => 'Huesca',
41             '23' => 'Jaén',
42             '24' => 'León',
43             '25' => 'Lérida',
44             '26' => 'La Rioja',
45             '27' => 'Lugo',
46             '28' => 'Madrid',
47             '29' => 'Málaga',
48             '30' => 'Murcia',
49             '31' => 'Navarra',
50             '32' => 'Orense',
51             '33' => 'Asturias',
52             '34' => 'Palencia',
53             '35' => 'Las Palmas',
54             '36' => 'Pontevedra',
55             '37' => 'Salamanca',
56             '38' => 'Santa Cruz de Tenerife',
57             '39' => 'Cantabria',
58             '40' => 'Segovia',
59             '41' => 'Sevilla',
60             '42' => 'Soria',
61             '43' => 'Tarragona',
62             '44' => 'Teruel',
63             '45' => 'Toledo',
64             '46' => 'Valencia',
65             '47' => 'Valladolid',
66             '48' => 'Vizcaya',
67             '49' => 'Zamora',
68             '50' => 'Zaragoza',
69             '51' => 'Ceuta',
70             '52' => 'Melilla',
71 4     4   3012 };
  4         9  
72              
73 4         407 use constant ISO_3166_2 => {
74             '01' => 'ES-VI',
75             '02' => 'ES-AB',
76             '03' => 'ES-A',
77             '04' => 'ES-AL',
78             '05' => 'ES-AV',
79             '06' => 'ES-BA',
80             '07' => 'ES-PM',
81             '08' => 'ES-B',
82             '09' => 'ES-BU',
83             '10' => 'ES-CC',
84             '11' => 'ES-CA',
85             '12' => 'ES-CS',
86             '13' => 'ES-CR',
87             '14' => 'ES-CO',
88             '15' => 'ES-C',
89             '16' => 'ES-CU',
90             '17' => 'ES-GI',
91             '18' => 'ES-GR',
92             '19' => 'ES-GU',
93             '20' => 'ES-SS',
94             '21' => 'ES-H',
95             '22' => 'ES-HU',
96             '23' => 'ES-J',
97             '24' => 'ES-LE',
98             '25' => 'ES-L',
99             '26' => 'ES-LO',
100             '27' => 'ES-LU',
101             '28' => 'ES-M',
102             '29' => 'ES-MA',
103             '30' => 'ES-MU',
104             '31' => 'ES-NA',
105             '32' => 'ES-OR',
106             '33' => 'ES-O',
107             '34' => 'ES-P',
108             '35' => 'ES-GC',
109             '36' => 'ES-PO',
110             '37' => 'ES-SA',
111             '38' => 'ES-TF',
112             '39' => 'ES-S',
113             '40' => 'ES-SG',
114             '41' => 'ES-SE',
115             '42' => 'ES-SO',
116             '43' => 'ES-T',
117             '44' => 'ES-TE',
118             '45' => 'ES-TO',
119             '46' => 'ES-V',
120             '47' => 'ES-VA',
121             '48' => 'ES-BI',
122             '49' => 'ES-ZA',
123             '50' => 'ES-Z',
124             '51' => 'ES-CE',
125             '52' => 'ES-ML',
126 4     4   27 };
  4         7  
127              
128             use constant {
129 4         6018 'ERROR_DIGITS5' => "Código postal no son 5 dígitos",
130             'ERROR_DEFINED' => "Código postal no definido",
131             'ERROR_ASSIGN' => "Código postal no asignado",
132 4     4   24 };
  4         7  
133              
134              
135             sub insular {
136 3     3 1 15 my $self = shift;
137              
138 3 50       12 return unless $self->valid;
139            
140 3         10 my $prov = $self->prov_code;
141              
142             # Baleares, Las Palmas, Santa Cruz de Tenerife
143 3 100 100     28 return 1 if $prov eq '07' || $prov eq '35' || $prov eq '38';
      66        
144              
145 1         5 return 0;
146             }
147              
148              
149             sub _comunidad_autonoma {
150 84     84   177 my $prov_code = shift;
151              
152 84 100       186 return 'Illes Balears' if $prov_code eq '07';
153 82 100       148 return 'La Rioja' if $prov_code eq '26';
154 81 100       171 return 'Comunidad de Madrid' if $prov_code eq '28';
155 72 100       163 return 'Región de Murcia' if $prov_code eq '30';
156 71 100       139 return 'Comunidad Foral de Navarra' if $prov_code eq '31';
157 70 100       150 return 'Principado de Asturias' if $prov_code eq '33';
158 69 100       171 return 'Cantabria' if $prov_code eq '39';
159 68 100       147 return 'Ceuta' if $prov_code eq '51';
160 65 100       130 return 'Melilla' if $prov_code eq '52';
161            
162 59 100       212 return 'Castilla-La Mancha' if $prov_code =~ /^(02|13|16|19|45)$/;
163 54 100       222 return 'Castilla y León' if $prov_code =~ /^(05|09|24|34|37|40|42|47|49)$/;
164 45 100       118 return 'Comunitat Valenciana' if $prov_code =~ /^(03|12|46)$/;
165              
166 42 100       132 return 'País Vasco' if $prov_code =~ /^(01|20|48)$/;
167 36 100       146 return 'Andalucía' if $prov_code =~ /^(04|11|14|18|21|23|29|41)$/;
168 23 100       90 return 'Extremadura' if $prov_code =~ /^(06|10)$/;
169 21 100       87 return 'Cataluña' if $prov_code =~ /^(08|17|25|43)$/;
170 13 100       58 return 'Galicia' if $prov_code =~ /^(15|27|32|36)$/;
171 9 100       48 return 'Aragón' if $prov_code =~ /^(22|44|50)$/;
172 4 50       32 return 'Canarias' if $prov_code =~ /^(35|38)$/;
173            
174 0         0 return;
175             }
176              
177             # Devuelve : Peninsula Baleares Canarias Ceuta Melilla
178             sub _region {
179 84     84   133 my $pv = shift;
180            
181 84 100       188 return 'Baleares' if $pv eq '07';
182 82 100 100     322 return 'Canarias' if $pv eq '35' || $pv eq '38';
183 78 100       159 return 'Ceuta' if $pv eq '51';
184 75 100       187 return 'Melilla' if $pv eq '52';
185            
186 69         594 return 'Peninsula';
187             }
188              
189              
190             sub _normalize {
191 8     8   20 my $cp = shift;
192              
193 8 50       24 return undef unless defined $cp;
194              
195 8         40 $cp =~ s/\s+//g;
196 8         40 $cp =~ s/\D//g;
197              
198 8 100       25 return undef unless length($cp);
199            
200 7         55 return sprintf('%05d', $cp);
201             }
202              
203              
204             sub validate_cp {
205 104     104 1 191011 my ($cp, $opts) = @_;
206 104   100     518 $opts ||= {};
207              
208 104 100 100     503 $cp = _normalize($cp) unless $opts->{strict} // 1;
209              
210 104 100       243 return { valid => 0, error => ERROR_DEFINED } unless $cp;
211            
212 100 100       608 return { valid => 0, error => ERROR_DIGITS5, codigo => $cp } unless $cp =~ /\A[0-9]{5}\z/;
213 92 100 100     443 return { valid => 0, error => ERROR_ASSIGN , codigo => $cp } unless $cp >= 1000 && $cp <= 52999;
214              
215 84         190 my $prov_code = substr($cp, 0, 2);
216              
217             # Valid
218             return {
219             valid => 1,
220             codigo => $cp,
221             ca => _comunidad_autonoma($prov_code),
222             prov_code => $prov_code,
223             region => _region($prov_code),
224             provincia => PROVINCIAS->{ $prov_code },
225 84         211 iso_3166_2 => ISO_3166_2->{ $prov_code }
226             };
227             }
228              
229              
230             sub new {
231 76     76 1 134244 my $class = shift;
232 76 100 66     409 my %args = @_ == 1 && ref($_[0]) eq 'HASH' ? %{$_[0]} : @_;
  1         5  
233 76         210 my $self = bless {}, $class;
234              
235 76 100       341 $self->strict(defined $args{strict} ? $args{strict} : 1);
236            
237 76 100       319 $self->set($args{codigo}) if defined $args{codigo};
238              
239 76         233 return $self;
240             }
241              
242              
243             sub _set_error {
244 9     9   51 my $self = shift;
245 9         34 $self->error(shift);
246              
247 9         31 $self->codigo(undef);
248 9         24 $self->ca(undef);
249 9         21 $self->provincia(undef);
250 9         40 $self->prov_code(undef);
251 9         27 $self->region(undef);
252 9         31 $self->iso_3166_2(undef);
253            
254 9         23 $self->valid(0);
255             }
256              
257              
258             sub set {
259 78     78 1 5665 my ($self,$cp) = @_;
260 78         109 my $res;
261            
262             # Normalize
263 78 100       199 unless ( $self->strict ) {
264 2         8 $cp = _normalize($cp);
265 2         11 $res = validate_cp($cp, { strict => 0 });
266             } else {
267 76         167 $res = validate_cp($cp);
268             }
269              
270             ## OK
271 78 100       248 if ( $res->{valid} ) {
272 69         206 $self->codigo($res->{codigo});
273 69         152 $self->ca($res->{ca});
274 69         150 $self->provincia($res->{provincia});
275 69         148 $self->prov_code($res->{prov_code});
276 69         155 $self->region($res->{region});
277 69         165 $self->iso_3166_2($res->{iso_3166_2});
278 69         130 $self->valid(1);
279 69         204 $self->error(undef);
280            
281 69         217 return 1;
282             }
283              
284             ## KO
285 9         37 $self->_set_error($res->{error});
286              
287 9         31 return 0;
288             }
289              
290             1;
291              
292             __END__