File Coverage

blib/lib/Business/DK/FI.pm
Criterion Covered Total %
statement 71 71 100.0
branch 4 4 100.0
condition n/a
subroutine 20 20 100.0
pod 3 3 100.0
total 98 98 100.0


line stmt bran cond sub pod time code
1             package Business::DK::FI;
2              
3 7     7   18970 use strict;
  7         14  
  7         253  
4 7     7   39 use warnings;
  7         12  
  7         272  
5 7     7   31 use vars qw($VERSION @EXPORT_OK);
  7         11  
  7         538  
6 7     7   4663 use Params::Validate qw(validate_pos SCALAR ARRAYREF);
  7         60288  
  7         672  
7 7     7   4736 use Readonly;
  7         29528  
  7         505  
8 7     7   53 use base qw(Exporter);
  7         13  
  7         766  
9 7     7   2126 use English qw( -no_match_vars );
  7         8487  
  7         49  
10 7     7   3344 use 5.006;
  7         25  
11              
12             $VERSION = '0.09';
13             @EXPORT_OK = qw(validate validateFI generate);
14              
15 7     7   40 use constant MODULUS_OPERAND => 10;
  7         10  
  7         608  
16 7     7   39 use constant THRESHOLD => 10;
  7         11  
  7         464  
17 7     7   33 use constant DEDUCTION => 9;
  7         11  
  7         412  
18 7     7   50 use constant INVALID => 0;
  7         8  
  7         318  
19 7     7   44 use constant VALID => 1;
  7         20  
  7         5146  
20              
21             Readonly::Array my @CONTROLCIFERS => qw(1 2 1 2 1 2 1 2 1 2 1 2 1 2);
22             Readonly::Scalar my $CONTROL_LENGTH => scalar @CONTROLCIFERS;
23              
24             ## no critic (NamingConventions::Capitalization)
25              
26             sub validateFI {
27 8     8 1 45 return validate(shift);
28             }
29              
30             sub validate {
31 18     18 1 1590 my ($fi_number) = @ARG;
32              
33 18         638 validate_pos( @ARG, { type => SCALAR, regex => qr/^\d{15}$/xsm } );
34              
35 11         200 my ($last_digit);
36 11         331 ( $fi_number, $last_digit )
37             = $fi_number =~ m/^(\d{$CONTROL_LENGTH})(\d{1})$/xsm;
38              
39 11         51 my $sum = _calculate_sum( $fi_number, \@CONTROLCIFERS );
40 11         33 my $checksum = _calculate_checksum($sum);
41              
42 11 100       46 if ( $checksum == $last_digit ) {
43 10         58 return VALID;
44             }
45             else {
46 1         5 return INVALID;
47             }
48             }
49              
50             sub _calculate_checksum {
51 14     14   48 my ($sum) = @ARG;
52              
53 14         267 validate_pos( @ARG, { type => SCALAR, regex => qr/^\d+$/xsm }, );
54              
55 14         213 return ( THRESHOLD - ( $sum % MODULUS_OPERAND ) );
56             }
57              
58             sub _calculate_sum {
59 14     14   37 my ( $number, $CONTROLCIFERS ) = @ARG;
60              
61 14         239 validate_pos(
62             @ARG,
63             { type => SCALAR, regex => qr/^\d+$/xsm },
64             { type => ARRAYREF },
65             );
66              
67 14         188 my $sum = 0;
68 14         112 my @numbers = split //smx, $number;
69              
70             ## no critic (ControlStructures::ProhibitCStyleForLoops)
71 14         61 for ( my $i = 0; $i < scalar @numbers; $i++ ) {
72 196         586 my $tmp_sum = $numbers[$i] * $CONTROLCIFERS->[$i];
73              
74 196 100       1226 if ( $tmp_sum >= THRESHOLD ) {
75 41         116 $sum += ( $tmp_sum - DEDUCTION );
76             }
77             else {
78 155         475 $sum += $tmp_sum;
79             }
80             }
81 14         107 return $sum;
82             }
83              
84             sub generate {
85 7     7 1 907 my ($number) = @ARG;
86              
87             #number has to be a positive number between 1 and 99999999999999
88             validate_pos(
89             @ARG,
90             { type => SCALAR,
91             regex => qr/^\d+$/,
92             callbacks => {
93 6     6   61 'higher than 0' => sub { shift() >= 1 },
94             'lower than 99999999999999' =>
95 6     6   35 sub { shift() <= 99999999999999 },
96             },
97             },
98 7         150 );
99              
100             #padding with zeroes up to our maximum length
101 3         43 my $pattern = '%0' . $CONTROL_LENGTH . 's';
102 3         9 my $reformatted_number = sprintf $pattern, $number;
103              
104             #this call takes care of the check of the product of the above statement
105 3         6 my $sum = _calculate_sum( $reformatted_number, \@CONTROLCIFERS );
106 3         4 my $checksum = _calculate_checksum($sum);
107              
108 3         5 my $finalized_number = $reformatted_number . $checksum;
109              
110 3         11 return $finalized_number;
111             }
112              
113             1;
114              
115             __END__