File Coverage

blib/lib/Validate/NPI.pm
Criterion Covered Total %
statement 27 27 100.0
branch 8 10 80.0
condition n/a
subroutine 4 4 100.0
pod 1 1 100.0
total 40 42 95.2


line stmt bran cond sub pod time code
1 1     1   552 use strict;
  1         2  
  1         32  
2 1     1   6 use warnings;
  1         1  
  1         47  
3             package Validate::NPI;
4             # ABSTRACT: Validates National Provider Identifier (NPI) numbers
5              
6 1     1   6 use vars qw{ $VERSION @ISA @EXPORT };
  1         4  
  1         347  
7             $VERSION = '0.03';
8              
9             require Exporter;
10              
11             @ISA = qw(Exporter);
12             @EXPORT = qw(validate_npi);
13              
14             sub validate_npi {
15 3     3 1 245 my ($value,$msg)=@_;
16              
17             # Assume the 9-position identifier part of the NPI is 123456789.
18             # Using the Luhn formula on the identifier portion, the check digit is calculated as follows:
19             # NPI without check digit: 1 2 3 4 5 6 7 8 9
20             # Step 1: Double the value of alternate digits, beginning with the rightmost digit.
21             # 2 6 10 14 18
22             # Step 2: Add constant 24, to account for the 80840 prefix that would be present on a card issuer
23             # identifier, plus the individual digits of products of doubling, plus unaffected digits.
24             # 24 + 2 + 2 + 6 + 4 + 1 + 0 + 6 + 1 + 4 + 8 + 1 + 8 = 67
25             # Step 3: Subtract from next higher number ending in zero.
26             # 70 - 67 = 3
27             # Check digit = 3
28             # NPI with check digit = 1234567893
29              
30 3 100       12 if ($value!~/^\d{10}$/) {
31 1 50       6 push @$msg,"NPI must be exactly 10 digits long" if ref $msg eq 'ARRAY';
32 1         3 return 0;
33             }
34 2         14 my @digits=split(//,$value);
35 2         5 map { $digits[$_]*=2 } (0,2,4,6,8);
  10         20  
36 2         3 my $sum=24;
37 2         6 for my $d (@digits[0..8]) {
38 18 100       31 if ($d>9) {
39 6         17 $sum+=int($d/10)+$d%10; # individual digits
40             } else {
41 12         20 $sum+=$d;
42             }
43             }
44 2         7 my $m=10*(int($sum/10)+1);
45 2         4 $m-=$sum;
46 2 100       8 if ($m!=$digits[9]) {
47 1 50       6 push @$msg,"NPI does not validate" if ref $msg eq 'ARRAY';
48 1         4 return 0;
49             }
50 1         10 1;
51             }
52              
53             1;
54              
55             __END__