File Coverage

blib/lib/No/KontoNr.pm
Criterion Covered Total %
statement 57 66 86.3
branch 19 40 47.5
condition 5 13 38.4
subroutine 8 8 100.0
pod 6 6 100.0
total 95 133 71.4


line stmt bran cond sub pod time code
1             package No::KontoNr;
2              
3             require Exporter;
4             @ISA=qw(Exporter);
5             @EXPORT_OK = qw(kontonr_ok kredittkortnr_ok
6             kontonr_f nok_f
7             mod_11 mod_10);
8              
9 1     1   2420 use strict;
  1         2  
  1         66  
10 1     1   6 use vars qw($VERSION);
  1         2  
  1         1566  
11             $VERSION = sprintf("%d.%02d", q$Revision: 1.9 $ =~ /(\d+)\.(\d+)/);
12              
13             =head1 NAME
14              
15             No::KontoNr - Check Norwegian bank account numbers
16              
17             =head1 SYNOPSIS
18              
19             use No::KontoNr qw(kontonr_ok);
20              
21             if (personnr_ok($nr)) {
22             # ...
23             }
24              
25             =head1 DESCRIPTION
26              
27             B
28              
29             Denne modulen kan brukes for å sjekke norske bankontonumre. Det siste
30             sifferet i et banknummer er kontrollsiffer og må stemme overens med
31             resten for at det skal være et gyldig nummer.
32              
33             Modulen inneholder også funksjoner for å regne ut modulus 10 og
34             modulus 11 kontrollsiffer. Disse algoritmene brukes blandt annet hvis
35             du vil generere KID når du skal fylle ut giroblanketter. De finnes
36             også en fuksjon som kan brukes for å formatere kronebeløp.
37              
38             Ingen av funksjonene eksporteres implisitt. Du må be om dem.
39             Følgende funksjoner er tilgjengelig:
40              
41             =over
42              
43             =item kontonr_ok($nr)
44              
45             Funksjonen kontonr_ok() vil returnere FALSE hvis kontonummeret gitt
46             som argument ikke er gyldig. Hvis nummeret er gyldig så vil
47             funksjonen returnere $nr på standard form (11 siffer for
48             bankkontonummer og 7 siffer for gamle postgironummer) . Nummeret som
49             gis til kontonr_ok() kan inneholde blanke eller punktumer.
50              
51             =cut
52              
53             sub kontonr_ok
54             {
55 35   100 35 1 409 my $nr = shift || return 0;
56 33         60 $nr =~ s/[ \.]//g; # det er ok med mellomrom og punktum i nummeret
57              
58 33 100       77 return "" if $nr =~ /\D/; # bare sifre skal gjenstå nå
59              
60 32         51 my $last = chop($nr);
61 32         47 $nr =~ s/^0000//; # postgiro nr skrives av og til som 0000.XX.XXXXX
62 32         40 my $check;
63 32 100       71 if (length($nr) == 6) { # postgiro nr
    100          
64 4         9 $check = mod_10($nr);
65             } elsif (length($nr) == 10) { # vanlig bankkontonr
66 26         46 $check = mod_11($nr);
67             } else {
68 2         6 return ""; # ulovlig lengde
69             }
70              
71             # Siste siffer er kontrollsiffer, plukk det av
72 30 100 66     149 return "" if !defined($check) || $check != $last;
73 21         59 return "$nr$last";
74             }
75              
76              
77             =item kontonr_f($nr)
78              
79             Funksjonen kontonr_f() vil formattere et kontonummer på standard form
80             ("####.##.#####"). Hvis kontonummeret ikke er gyldig så byttes alle
81             sifferene ut med "?".
82              
83             =cut
84              
85             sub kontonr_f
86             {
87 3     3 1 31 my $nr = kontonr_ok(shift);
88 3 100       10 return "????.??.?????" unless $nr;
89 2 100       6 $nr = "0000$nr" if length($nr) == 7;
90 2         19 $nr =~ s/^(\d{4})(\d\d)(\d{5})$/$1.$2.$3/;
91 2         7 $nr;
92             }
93              
94              
95             =item kredittkortnr_ok($nr)
96              
97             Funksjonen kredittkortnr_ok() vil returnere FALSE hvis
98             kredittkortnummeret gitt som argument ikke er gyldig. Hvis nummeret
99             er gyldig så vil funksjonen returnere kortselskapets navn. Nummeret
100             som gis til kredittkortnr_ok() kan inneholde blanke eller punktumer.
101              
102             =cut
103              
104             sub kredittkortnr_ok
105             {
106 1   50 1 1 13 my $nr = shift || return 0;
107 1         6 $nr =~ s/[ \.]//g; # det er ok med mellomrom og punktum i nummeret
108 1 50       5 return 0 if $nr =~ /\D/;
109              
110             # Basert på http://www.websitter.com/cardtype.html
111 1         2 my $type;
112 1 50 0     7 if ($nr =~ /^5[1-5]/) {
    0          
    0          
    0          
    0          
113 1         2 $type = "MasterCard";
114 1 50       4 return 0 if length($nr) != 16;
115             } elsif ($nr =~ /^4/) {
116 0         0 $type = "VISA";
117 0 0 0     0 return 0 if length($nr) != 13 and length($nr) != 16;
118             } elsif ($nr =~ /^3[47]/) {
119 0         0 $type = "American Express";
120 0 0       0 return 0 if length($nr) != 15;
121             } elsif ($nr =~ /^30[0-5]/ || $nr =~ /^3[68]/) {
122 0         0 $type = "Diners Club";
123 0 0       0 return 0 if length($nr) != 14;
124             } elsif ($nr =~ /^6011/) {
125 0         0 $type = "Discover";
126 0 0       0 return 0 if length($nr) != 16;
127             } else {
128 0         0 return 0;
129             }
130              
131             # Siste siffer er kontrollsiffer
132 1         4 my $last = chop($nr);
133 1 50       3 return 0 if $last != mod_10($nr);
134 1         3 return $type;
135             }
136              
137              
138             =item nok_f($tall)
139              
140             Denne funksjonen vil formatere tall på formen:
141              
142             300,50
143             4.300,-
144              
145             Det skulle passe bra når man skal skrive ut kronebeløp. Ørebeløpet
146             "00" byttes ut med strengen "- ", dvs. at tallene laines opp korrekt
147             hvis du høyrejusterer dem.
148              
149             =cut
150              
151             sub nok_f
152             {
153 5     5 1 63 my $kr = sprintf "%.2f", shift;
154 5         48 $kr =~ s/\.(\d\d)$/,$1/;
155 5         14 $kr =~ s/,00$/,- /;
156 5         50 1 while $kr =~ s/(\d)(\d\d\d)(?=[.,])/$1.$2/;
157 5         15 $kr;
158             }
159              
160              
161             =item mod_10($tall)
162              
163             Denne funksjonen regner ut modulus 10 kontrollsifferet til tallet gitt
164             som argument. Hvis argumentet inneholder tegn som ikke er siffer så
165             ignoreres de.
166              
167             Modulus 10 algoritmen benyttes blandt annet for å generere
168             kontrollsiffer til de fleste internasjonale kredittkortnummer.
169              
170             =cut
171              
172             sub mod_10
173             {
174 19     19 1 145 my $digits = shift;
175 19         21 my $sum = 0; # which we subtract from :-)
176 19         20 my $factor = 2;
177 19         20 my $s;
178 19         104 foreach $s (reverse ($digits =~ /(\d)/g)) {
179 103         145 my $p = $s * $factor;
180 103 100       172 if ($p >= 10) {
181 27         28 $sum--;
182 27         29 $p -= 10;
183             }
184 103         137 $sum -= $p;
185 103         145 $factor = 3 - $factor; # alternates between 2 and 1
186             }
187 19         58 $sum % 10;
188             }
189              
190              
191             =item mod_11($tall)
192              
193             Denne funksjonen regner ut modulus 11 kontrollsifferet til tallet gitt
194             som argument. Hvis argumentet inneholder tegn som ikke er siffer så
195             ignoreres de. Når denne algoritmen benyttes så kan det være tall som
196             det ikke finnes noe gyldig kontrollsiffer for, og da vil mod_11()
197             returnere verdien I.
198              
199             Modulus 11 algoritmen benyttes blandt annet for å generere
200             kontrollsiffer til norske bankkontonummer.
201              
202             =cut
203              
204             sub mod_11
205             {
206 26     26 1 231 my @digits = reverse (shift =~ /(\d)/g);
207 26         99 my @factors = (2..7) x ((@digits-1)/6+1);
208 26         34 my $sum = 0;
209 26         430 $sum -= shift(@digits) * shift(@factors) while @digits;
210 26         40 my $k = $sum % 11;
211 26 50       50 return undef if $k == 10;
212 26         52 $k;
213             }
214              
215             1;
216              
217             =back
218              
219             =head1 SEE ALSO
220              
221             L
222              
223             =head1 AUTHOR
224              
225             Gisle Aas
226              
227             =cut
228