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   17383 use strict;
  7         11  
  7         252  
4 7     7   33 use warnings;
  7         9  
  7         273  
5 7     7   32 use vars qw($VERSION @EXPORT_OK);
  7         10  
  7         527  
6 7     7   4128 use Params::Validate qw(validate_pos SCALAR ARRAYREF);
  7         51744  
  7         529  
7 7     7   3734 use Readonly;
  7         19454  
  7         405  
8 7     7   41 use base qw(Exporter);
  7         10  
  7         688  
9 7     7   1737 use English qw( -no_match_vars );
  7         6738  
  7         44  
10 7     7   2586 use 5.005.03;
  7         18  
11              
12             $VERSION = '0.08';
13             @EXPORT_OK = qw(validate validateFI generate);
14              
15 7     7   41 use constant MODULUS_OPERAND => 10;
  7         20  
  7         537  
16 7     7   38 use constant THRESHOLD => 10;
  7         8  
  7         300  
17 7     7   28 use constant DEDUCTION => 9;
  7         6  
  7         352  
18 7     7   33 use constant INVALID => 0;
  7         10  
  7         342  
19 7     7   28 use constant VALID => 1;
  7         9  
  7         4086  
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 22 return validate(shift);
28             }
29              
30             sub validate {
31 18     18 1 674 my ($fi_number) = @ARG;
32              
33 18         400 validate_pos( @ARG, { type => SCALAR, regex => qr/^\d{15}$/xsm } );
34              
35 11         106 my ($last_digit);
36 11         156 ( $fi_number, $last_digit )
37             = $fi_number =~ m/^(\d{$CONTROL_LENGTH})(\d{1})$/xsm;
38              
39 11         32 my $sum = _calculate_sum( $fi_number, \@CONTROLCIFERS );
40 11         24 my $checksum = _calculate_checksum($sum);
41              
42 11 100       31 if ( $checksum == $last_digit ) {
43 10         37 return VALID;
44             } else {
45 1         5 return INVALID;
46             }
47             }
48              
49             sub _calculate_checksum {
50 14     14   21 my ($sum) = @ARG;
51              
52 14         139 validate_pos( @ARG, { type => SCALAR, regex => qr/^\d+$/xsm }, );
53              
54 14         134 return ( THRESHOLD - ( $sum % MODULUS_OPERAND ) );
55             }
56              
57             sub _calculate_sum {
58 14     14   26 my ( $number, $CONTROLCIFERS ) = @ARG;
59              
60 14         141 validate_pos(
61             @ARG,
62             { type => SCALAR, regex => qr/^\d+$/xsm },
63             { type => ARRAYREF },
64             );
65              
66 14         128 my $sum = 0;
67 14         96 my @numbers = split //smx, $number;
68              
69             ## no critic (ControlStructures::ProhibitCStyleForLoops)
70 14         54 for ( my $i = 0; $i < scalar @numbers; $i++ ) {
71 196         399 my $tmp_sum = $numbers[$i] * $CONTROLCIFERS->[$i];
72              
73 196 100       796 if ( $tmp_sum >= THRESHOLD ) {
74 41         77 $sum += ( $tmp_sum - DEDUCTION );
75             } else {
76 155         288 $sum += $tmp_sum;
77             }
78             }
79 14         52 return $sum;
80             }
81              
82             sub generate {
83 7     7 1 456 my ($number) = @ARG;
84              
85             #number has to be a positive number between 1 and 99999999999999
86             validate_pos(
87             @ARG,
88             { type => SCALAR,
89             regex => qr/^\d+$/,
90             callbacks => {
91 6     6   54 'higher than 0' => sub { shift() >= 1 },
92             'lower than 99999999999999' =>
93 5     5   25 sub { shift() <= 99999999999999 },
94             },
95             },
96 7         125 );
97              
98             #padding with zeroes up to our maximum length
99 3         36 my $pattern = '%0' . $CONTROL_LENGTH . 's';
100 3         8 my $reformatted_number = sprintf $pattern, $number;
101              
102             #this call takes care of the check of the product of the above statement
103 3         7 my $sum = _calculate_sum( $reformatted_number, \@CONTROLCIFERS );
104 3         4 my $checksum = _calculate_checksum($sum);
105              
106 3         4 my $finalized_number = $reformatted_number . $checksum;
107              
108 3         10 return $finalized_number;
109             }
110              
111             1;
112              
113             __END__