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__ |