.\" Automatically generated by Pod::Man 2.25 (Pod::Simple 3.16) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is turned on, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .ie \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . nr % 0 . rr F .\} .el \{\ . de IX .. .\} .\" .\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). .\" Fear. Run. Save yourself. No user-serviceable parts. . \" fudge factors for nroff and troff .if n \{\ . ds #H 0 . ds #V .8m . ds #F .3m . ds #[ \f1 . ds #] \fP .\} .if t \{\ . ds #H ((1u-(\\\\n(.fu%2u))*.13m) . ds #V .6m . ds #F 0 . ds #[ \& . ds #] \& .\} . \" simple accents for nroff and troff .if n \{\ . ds ' \& . ds ` \& . ds ^ \& . ds , \& . ds ~ ~ . ds / .\} .if t \{\ . ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" . ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' . ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' . ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' . ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' . ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' .\} . \" troff and (daisy-wheel) nroff accents .ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' .ds 8 \h'\*(#H'\(*b\h'-\*(#H' .ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] .ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' .ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' .ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] .ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] .ds ae a\h'-(\w'a'u*4/10)'e .ds Ae A\h'-(\w'A'u*4/10)'E . \" corrections for vroff .if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' .if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' . \" for low resolution devices (crt and lpr) .if \n(.H>23 .if \n(.V>19 \ \{\ . ds : e . ds 8 ss . ds o a . ds d- d\h'-1'\(ga . ds D- D\h'-1'\(hy . ds th \o'bp' . ds Th \o'LP' . ds ae ae . ds Ae AE .\} .rm #[ #] #H #V #F C .\" ======================================================================== .\" .IX Title "Business::BR::CNPJ 3pm" .TH Business::BR::CNPJ 3pm "2008-07-01" "perl v5.14.2" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" Business::BR::CNPJ \- Perl module to test for correct CNPJ numbers .SH "SYNOPSIS" .IX Header "SYNOPSIS" .Vb 1 \& use Business::BR::CNPJ; \& \& print "ok " if test_cnpj(\*(Aq90.117.749/7654\-80\*(Aq); # prints \*(Aqok \*(Aq \& print "bad " unless test_cnpj(\*(Aq88.222.111/0001\-10\*(Aq); # prints \*(Aqbad \*(Aq .Ve .SH "DESCRIPTION" .IX Header "DESCRIPTION" The \s-1CNPJ\s0 number is an identification number of Brazilian companies emitted by the Brazilian Ministry of Revenue, which is called \&\*(L"Ministe\*'rio da Fazenda\*(R". .PP \&\s-1CNPJ\s0 stands for \*(L"Cadastro Nacional de Pessoa Juri\*'dica\*(R" (literally, national juridical person registration) as opposed to the \s-1CPF\s0 number for natural persons. Sometime ago, it was called \s-1CGC\s0 (\*(L"Cadastro Geral de Contribuinte\*(R" or general taxpayer registration). .PP The \s-1CNPJ\s0 is comprised of a base of 8 digits, a 4\-digits radical and 2 check digits. It is usually written like '11.111.111/0001\-55' so as to be more human-readable. .PP This module provides \f(CW\*(C`test_cnpj\*(C'\fR for checking that a \s-1CNPJ\s0 number is \fIcorrect\fR. Here a \fIcorrect \s-1CNPJ\s0 number\fR means .IP "\(bu" 4 it is 14 digits long .IP "\(bu" 4 it satisfies the two check equations mentioned below .PP Before checking, any non-digit letter is stripped, making it easy to test formatted entries like '11.111.111/0001\-55' and entries with extra blanks like ' 43.337.004 / 0001\-72 '. .IP "\fBtest_cnpj\fR" 4 .IX Item "test_cnpj" .Vb 3 \& test_cnpj(\*(Aq48.999.764/0001\-60\*(Aq) # incorrect CPF, returns 0 \& test_cnpj(\*(Aq 43.337.004/0001\-72 \*(Aq) # is ok, returns 1 \& test_cnpj(\*(Aq888\*(Aq) # nope, returns undef .Ve .Sp Tests whether a \s-1CNPJ\s0 number is correct. Before testing, any non-digit character is stripped. Then it is expected to be 14 digits long and to satisfy two check equations which validate the last two check digits. See \*(L"\s-1THE\s0 \s-1CHECK\s0 \s-1EQUATIONS\s0\*(R". .Sp The policy to get rid of '.', '/' and '\-' is very liberal. It indeeds discards anything that is not a digit (0, 1, ..., 9) or letter. That is handy for discarding spaces as well. .Sp .Vb 1 \& test_cnpj(\*(Aq 66.818.021/0001\-27 \*(Aq) # is ok, returns 1 .Ve .Sp But extraneous inputs like 'a53##045%4\-20**0001!50' are also accepted. If you are worried about this kind of input, just check against a regex: .Sp .Vb 2 \& warn "bad CNPJ: only digits (14) expected" \& unless ($cnpj =~ /^\ed{14}$/); \& \& warn "bad CNPJ: does not match mask \*(Aq_\|_._\|_\|_._\|_\|_/_\|_\|_\|_\-_\|_\*(Aq" \& unless ($cnpj =~ /^\ed{2}\e.\ed{3}\e.\ed{3}/\ed{4}\-\ed{2}$/); .Ve .Sp \&\s-1NOTE\s0. Integer numbers like 3337004000158 (or 3_337_004_0001_58) with fewer than 14 digits will be normalized (eg. to 03_337_004_0001_58) before testing. .IP "\fBcanon_cnpj\fR" 4 .IX Item "canon_cnpj" .Vb 2 \& canon_cnpj(1); # returns \*(Aq00000000000001\*(Aq \& canon_cnpj(\*(Aq99.999.222/0001\-12\*(Aq); # returns \*(Aq99999222000112\*(Aq .Ve .Sp Canon's a candidate for a \s-1CNPJ\s0 number. In case, the argument is an integer, it is formatted to at least fourteen digits. Otherwise, it is stripped of any non-alphanumeric characters and returned as it is. .IP "\fBformat_cnpj\fR" 4 .IX Item "format_cnpj" .Vb 1 \& format_cnpj(\*(Aq00 000 000 0000 00\*(Aq); # returns \*(Aq00.000.000/0000\-00\*(Aq .Ve .Sp Formats its input into '00.000.000/0000\-00' mask. First, the argument is canon'ed and then dots, slash and hyphen are added to the first 14 digits of the result. .IP "\fBparse_cnpj\fR" 4 .IX Item "parse_cnpj" .Vb 2 \& ($base, $filial, $dv) = parse_cnpj($cpf); \& $hashref = parse_cnpj(\*(Aq11.222.333/4444\-00\*(Aq); # { base => \*(Aq11222333\*(Aq, filial => \*(Aq4444\*(Aq dv => \*(Aq00\*(Aq } .Ve .Sp Splits a candidate for \s-1CNPJ\s0 number into base, radical and check digits (dv \- di\*'gitos de verificac\*,a\*~o). It canon's the argument before splitting it into 8\-, 4\- and 2\-digits parts. In a list context, returns a three-element list with the base, the radical and the check digits. In a scalar context, returns a hash ref with keys 'base', 'filial' and 'dv' and associated values. .IP "\fBrandom_cnpj\fR" 4 .IX Item "random_cnpj" .Vb 1 \& $rand_cnpj = random_cnpj($valid); \& \& $good_cnpj = random_cnpj(); \& $cnpj = random_cnpj(1); # also a good one \& $bad_cnpj = random_cnpj(0); # bad CNPJ .Ve .Sp Generates a random \s-1CNPJ\s0. If \f(CW$valid\fR is omitted or 1, it is guaranteed to be \fIcorrect\fR. If \f(CW$valid\fR is 0, it is guaranteed to be \fIincorrect\fR. This function is intented for mass test. (Use it wisely.) .Sp The implementation is: generate a 8\-digits random number for the base, and the variation is chosen 95% of the time to be '0001' and the other 5% a skewed random distribution with the expression \&\f(CW\*(C`int(sqr rand(1E8))\*(C'\fR is used. A uniform distribution is expected from \&\f(CW\*(C`rand\*(C'\fR. With the base and variation, the check digits are computed. If \f(CW$valid\fR==0, the check digits are computed \fBnot to\fR satisfy the check equations. .SS "\s-1EXPORT\s0" .IX Subsection "EXPORT" \&\f(CW\*(C`test_cnpj\*(C'\fR is exported by default. \f(CW\*(C`canon_cnpj\*(C'\fR, \f(CW\*(C`format_cnpj\*(C'\fR, \&\f(CW\*(C`parse_cnpj\*(C'\fR and \f(CW\*(C`random_cnpj\*(C'\fR can be exported on demand. .SH "THE CHECK EQUATIONS" .IX Header "THE CHECK EQUATIONS" A correct \s-1CNPJ\s0 number has two check digits which are computed from the 12 first digits. Consider the \s-1CNPJ\s0 number written as 14 digits .PP .Vb 1 \& c[1] c[2] c[3] c[4] c[5] c[6] c[7] c[8] c[9] c[10] c[11] c[12] dv[1] dv[2] .Ve .PP To check whether a \s-1CNPJ\s0 is correct or not, it has to satisfy the check equations: .PP .Vb 4 \& 5*c[1]+4*c[2]+3*c[3]+2*c[4]+9*c[5]+ \& 8*c[6]+7*c[7]+6*c[8]+5*c[9]+4*c[10]+ \& 3*c[11]+2*c[12]+dv[1] = 0 (mod 11) or \& = 1 (mod 11) (if dv[1]=0) .Ve .PP and .PP .Vb 4 \& 6*c[1]+5*c[2]+4*c[3]+3*c[4]+2*c[5]+ \& 9*c[6]+8*c[7]+7*c[8]+6*c[9]+5*c[10]+ \& 4*c[11]+3*c[12]+2*dv[1]+dv[2] = 0 (mod 11) or \& = 1 (mod 11) (if dv[2]=0) .Ve .SH "BUGS" .IX Header "BUGS" I heard that there are exceptions of \s-1CNPJ\s0 numbers which don't obey the check equations and are still authentic. I have never found one of them. .SH "SEE ALSO" .IX Header "SEE ALSO" To make sure this module works, one can try the results obtained against those found with \*(L"Emissa\*~o de Comprovante de Inscric\*,a\*~o e de Situac\*,a\*~o Cadastral de Pessoa Juri\*'dica\*(R", a web page which the Brazilian Ministry of Revenue provides for public consultation on regularity status of the taxpayer. This page tells if the \s-1CNPJ\s0 number is a correct entry (14\-digits\-long with verified check digits), if it references a real company and if it is regular with the government body. .PP Given a bad \s-1CNPJ\s0, the after-submit page tells \*(L"O nu\*'mero do \s-1CNPJ\s0 na\*~o e\*' va\*'lido\*(R" (the \s-1CNPJ\s0 number is not valid). If the \s-1CNPJ\s0 is a good one but does not reference a real company, it says \*(L"\s-1CNPJ\s0 na\*~o existe em nossa base de dados\*(R" (\s-1CNPJ\s0 does not exist in our database). Otherwise, it shows a details form for the identified taxpayer. .PP Note that this module only tests correctness. It doesn't enter the merit whether the \s-1CNPJ\s0 number actually exists at the Brazilian government databases. .PP As you might have guessed, this is not the first Perl module to approach this kind of functionality. Take a look at .PP .Vb 1 \& http://search.cpan.org/search?module=Brasil::Checar::CGC .Ve .PP Please reports bugs via \s-1CPAN\s0 \s-1RT\s0, http://rt.cpan.org/NoAuth/Bugs.html?Dist=Business\-BR\-Ids By doing so, the author will receive your reports and patches, as well as the problem and solutions will be documented. .SH "AUTHOR" .IX Header "AUTHOR" A. R. Ferreira, .SH "COPYRIGHT AND LICENSE" .IX Header "COPYRIGHT AND LICENSE" Copyright (C) 2005 by A. R. Ferreira .PP This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself, either Perl version 5.8.6 or, at your option, any later version of Perl 5 you may have available.