File Coverage

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


line stmt bran cond sub pod time code
1             package Business::DK::FI;
2              
3 7     7   38042 use strict;
  7         13  
  7         283  
4 7     7   38 use warnings;
  7         16  
  7         360  
5 7     7   38 use vars qw($VERSION @EXPORT_OK);
  7         18  
  7         480  
6 7     7   8282 use Params::Validate qw(validate_pos SCALAR ARRAYREF);
  7         82717  
  7         730  
7 7     7   12763 use Readonly;
  7         35442  
  7         586  
8 7     7   63 use base qw(Exporter);
  7         13  
  7         967  
9 7     7   2860 use English qw( -no_match_vars );
  7         11329  
  7         62  
10 7     7   4322 use 5.005.03;
  7         28  
  7         468  
11              
12             $VERSION = '0.07';
13             @EXPORT_OK = qw(validate validateFI generate);
14              
15 7     7   43 use constant MODULUS_OPERAND => 10;
  7         14  
  7         525  
16 7     7   220 use constant THRESHOLD => 10;
  7         14  
  7         341  
17 7     7   35 use constant DEDUCTION => 9;
  7         13  
  7         303  
18 7     7   45 use constant INVALID => 0;
  7         27  
  7         322  
19 7     7   44 use constant VALID => 1;
  7         18  
  7         5714  
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 26 return validate(shift);
28             }
29              
30             sub validate {
31 18     18 1 950 my ($fi_number) = @ARG;
32              
33 18         522 validate_pos( @ARG, { type => SCALAR, regex => qr/^\d{15}$/xsm } );
34              
35 11         148 my ($last_digit);
36 11         204 ( $fi_number, $last_digit )
37             = $fi_number =~ m/^(\d{$CONTROL_LENGTH})(\d{1})$/xsm;
38              
39 11         45 my $sum = _calculate_sum( $fi_number, \@CONTROLCIFERS );
40 11         33 my $checksum = _calculate_checksum($sum);
41              
42 11 100       35 if ( $checksum == $last_digit ) {
43 10         53 return VALID;
44             } else {
45 1         9 return INVALID;
46             }
47             }
48              
49             sub _calculate_checksum {
50 14     14   24 my ($sum) = @ARG;
51              
52 14         191 validate_pos( @ARG, { type => SCALAR, regex => qr/^\d+$/xsm }, );
53              
54 14         152 return ( THRESHOLD - ( $sum % MODULUS_OPERAND ) );
55             }
56              
57             sub _calculate_sum {
58 14     14   31 my ( $number, $CONTROLCIFERS ) = @ARG;
59              
60 14         320 validate_pos(
61             @ARG,
62             { type => SCALAR, regex => qr/^\d+$/xsm },
63             { type => ARRAYREF },
64             );
65              
66 14         197 my $sum = 0;
67 14         90 my @numbers = split //smx, $number;
68              
69             ## no critic (ControlStructures::ProhibitCStyleForLoops)
70 14         62 for ( my $i = 0; $i < scalar @numbers; $i++ ) {
71 196         568 my $tmp_sum = $numbers[$i] * $CONTROLCIFERS->[$i];
72              
73 196 100       1030 if ( $tmp_sum >= THRESHOLD ) {
74 41         99 $sum += ( $tmp_sum - DEDUCTION );
75             } else {
76 155         366 $sum += $tmp_sum;
77             }
78             }
79 14         73 return $sum;
80             }
81              
82             sub generate {
83 7     7 1 848 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   59 'higher than 0' => sub { shift() >= 1 },
92             'lower than 99999999999999' =>
93 6     6   37 sub { shift() <= 99999999999999 },
94             },
95             },
96 7         166 );
97              
98             #padding with zeroes up to our maximum length
99 3         45 my $pattern = '%0' . $CONTROL_LENGTH . 's';
100 3         7 my $reformatted_number = sprintf $pattern, $number;
101              
102             #this call takes care of the check of the product of the above statement
103 3         8 my $sum = _calculate_sum( $reformatted_number, \@CONTROLCIFERS );
104 3         6 my $checksum = _calculate_checksum($sum);
105              
106 3         7 my $finalized_number = $reformatted_number . $checksum;
107              
108 3         13 return $finalized_number;
109             }
110              
111             1;
112              
113             __END__