adding minor features to barcode generator :
[koha.git] / barcodes / barcodesGenerator.pl
1 #!/usr/bin/perl
2
3 # script to generate items barcodes
4 # written 07/04
5 # by Veleda Matias - matias_veleda@hotmail.com - Physics Library UNLP Argentina and
6 #    Castañeda Sebastian - seba3c@yahoo.com.ar - Physics Library UNLP Argentina and
7
8 # This file is part of Koha.
9 #
10 # Koha is free software; you can redistribute it and/or modify it under the
11 # terms of the GNU General Public License as published by the Free Software
12 # Foundation; either version 2 of the License, or (at your option) any later
13 # version.
14 #
15 # Koha is distributed in the hope that it will be useful, but WITHOUT ANY
16 # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
17 # A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
18 #
19 # You should have received a copy of the GNU General Public License along with
20 # Koha; if not, write to the Free Software Foundation, Inc., 59 Temple Place,
21 # Suite 330, Boston, MA  02111-1307 USA
22
23 require Exporter;
24
25 use strict;
26
27 use CGI;
28 use C4::Context;
29 use C4::Output;
30 use HTML::Template;
31 use PDF::API2;
32 use PDF::API2::Page;
33 use PDF::API2::PDF::Utils;
34 use C4::Barcodes::PrinterConfig;
35 use Time::localtime; 
36
37
38 # This function returns the path to deal with the correct files, considering
39 # templates set and language.
40 sub getPath {
41         my $type = shift @_;
42         my $templatesSet = C4::Context->preference('template');
43         my $lang = C4::Context->preference('opaclanguages');
44         if ($type eq "intranet") {
45                 return "$ENV{'DOCUMENT_ROOT'}/intranet-tmpl/$templatesSet/$lang";
46         } else {
47                 return "$ENV{'DOCUMENT_ROOT'}/opac-tmpl/$templatesSet/$lang";
48         }
49 }
50
51 # Load a configuration file. Before use this function, check if that file exists.
52 sub loadConfFromFile {
53   my $fileName = shift @_;
54         my %keyValues;
55         open FILE, "<$fileName";
56         while (<FILE>) {
57                 chomp;
58                 if (/\s*([\w_]*)\s*=\s*([\[\]\<\>\w_\s:@,\.-]*)\s*/) {
59                         $keyValues{$1} = $2;
60                 }
61         }
62         close FILE;
63         return %keyValues;
64 }
65
66 # Save settings to a configuration file. It delete previous configuration settings.
67 sub saveConfToFile {
68         my $fileName = shift @_;
69         my %keyValues = %{shift @_};
70         my $i;
71         open FILE, ">$fileName";                        
72         my $i;
73         foreach $i (keys(%keyValues)) {
74     print FILE $i." = ".$keyValues{$i}."\n";
75         }
76         close FILE;
77 }
78
79 # Load the config file.
80 my $filenameConf = &getPath("intranet")."/includes/labelConfig/itemsLabelConfig.conf";
81 my %labelConfig = &loadConfFromFile($filenameConf);
82
83 # Creates a CGI object and take its parameters
84 my $cgi = new CGI;
85 my $from = $cgi->param('from');
86 my $to = $cgi->param('to');
87 my $individualCodes = $cgi->param('individualCodes');
88 my $rangeType = $cgi->param('rangeType');
89 my $pageType = $cgi->param('pages');
90 my $label = $cgi->param('label');
91 my $numbersystem = $cgi->param('numbersystem');
92 my $text_under_label = $cgi->param('text_under_label');
93
94 # Generate the checksum from an inventary code
95 sub checksum {
96
97   sub calculateDigit {
98     my $code = shift @_;
99     my $sum = 0;
100           my $odd_parity = 1;
101     my $i;
102     for ($i = length($code) - 1; $i >= 0; $i--){
103            if ( $odd_parity ) {
104                   $sum = $sum + ( 3 * substr($code, $i, 1) );
105      } else {
106                         $sum = $sum + substr($code, $i, 1); }
107                   $odd_parity = !$odd_parity;
108            }
109     my $check_digit = 10 - ($sum%10);
110         if ($check_digit==10) {
111                 $check_digit=0;
112         }
113           return $code.$check_digit;
114   }
115
116   my $currentCode = shift @_;
117   $currentCode = &calculateDigit($currentCode);
118   return $currentCode;
119 }
120
121 # Assigns a temporary name to the PDF file
122 sub assingFilename {
123         my ($from, $to) = @_;
124         my $ip = $cgi->remote_addr();
125         my $random = int(rand(1000000));
126     my $timeObj = localtime();
127         my ($day, $month, $year, $hour, $min, $sec) = ($timeObj->mday,
128                                                                                                    $timeObj->mon + 1,
129                                                                                                    $timeObj->year + 1900,
130                                                                                                    $timeObj->hour,
131                                                                                                    $timeObj->min,
132                                                                                                    $timeObj->sec);
133         my $tmpFileName = $random.'-'.$ip.'-(From '.$from.' to '.$to.')-['.$day.'.'.$month.'.'.$year.']-['.$hour.':'.$min.':'.$sec.'].pdf';
134         return $tmpFileName;
135 }
136
137 # Takes inventary codes from database and if they are between
138 # the interval specify by parameters, it generates the correspond barcodes
139 sub barcodesGenerator {
140         my ($from, $to, $rangeType, $individualCodes,$text_under_label) = @_;
141         # Returns a database handler
142         my $dbh = C4::Context->dbh;
143         # Create the query to database
144         # Assigns a temporary filename for the pdf file
145         my $tmpFileName = &assingFilename($from, $to);
146         if ($rangeType eq 'continuous2') {
147                 # Set the temp directory for pdf´s files
148                 if (!defined($ENV{'TEMP'})) {
149                         $ENV{'TEMP'} = '/tmp/';
150                 }       
151                 $tmpFileName = $ENV{'TEMP'}.$tmpFileName;
152                 # Creates a PDF object
153                 my $pdf = PDF::API2->new(-file => $tmpFileName);
154                 # Set the positions where barcodes are going to be placed
155                 C4::Barcodes::PrinterConfig::setPositionsForX($labelConfig{'marginLeft'}, $labelConfig{'labelWidth'}, $labelConfig{'columns'}, $labelConfig{'pageType'});
156                 C4::Barcodes::PrinterConfig::setPositionsForY($labelConfig{'marginBottom'}, $labelConfig{'labelHeigth'}, $labelConfig{'rows'}, $labelConfig{'pageType'});
157                 # Creates a font object
158                 my $tr = $pdf->corefont('Helvetica-Bold');
159                 # Barcode position
160                 my ($page, $gfx, $text);
161                 for (my $code=$from; $code<=$to; $code++) {
162                         # Generetase checksum
163                         my $codeC = &checksum($code);
164                         # Generate the corresponde barcode to $code
165                         my $barcode = $pdf->barcode(-font => $tr,       # The font object to use
166                                                                                 -type => 'ean13',       # Standard of codification
167                                                                                 -code => $codeC, # Text to codify
168                                                                                 -extn   => '012345',    # Barcode extension (if it is aplicable)
169                                                                                 -umzn => 10,            # Top limit of the finished bar
170                                                                                 -lmzn => 10,            # Bottom limit of the finished bar
171                                                                                 -zone => 15,            # Bars size
172                                                                                 -quzn => 0,             # Space destinated for legend
173                                                                                 -ofwt => 0.01,  # Bars width
174                                                                                 -fnsz => 8,             # Font size
175                                                                                 -text => ''
176                                                                                 );
177                         
178                         (my $x, my $y, $pdf, $page, $gfx, $text, $tr, $label) = C4::Barcodes::PrinterConfig::getLabelPosition(
179                                                                                                                                                                                 $label, 
180                                                                                                                                                                                 $pdf, 
181                                                                                                                                                                                 $page,
182                                                                                                                                                                                 $gfx,
183                                                                                                                                                                                 $text,
184                                                                                                                                                                                 $tr,
185                                                                                                                                                                                 $pageType);     
186                         # Assigns a barcodes to $gfx
187                         $gfx->barcode($barcode, $x, $y , (72/$labelConfig{'systemDpi'}));
188                         # Assigns the additional information to the barcode (Legend)
189                         $text->translate($x - 48, $y - 22);
190                         if ($text_under_label) {
191                                 $text->text($text_under_label);
192                         }
193                 }
194                 # Writes the objects added in $gfx to $page
195                 $pdf->finishobjects($page,$gfx, $text);
196                 # Save changes to the PDF
197                 $pdf->saveas;
198                 # Close the conection with the PDF file
199                 $pdf->end;
200                 # Show the PDF file
201                 print $cgi->redirect("/cgi-bin/koha/barcodes/pdfViewer.pl?tmpFileName=$tmpFileName");
202         } else {
203                 my $rangeCondition;
204                 if ($individualCodes ne "") {
205                         $rangeCondition = "AND (I.barcode IN " . $individualCodes . ")";
206                 } else {
207                         $rangeCondition =  "AND (I.barcode >= " . $from . " AND I.barcode <="  . $to . " )";
208                 }
209                         
210                 my $query = "SELECT CONCAT('$numbersystem',REPEAT('0',((12 - LENGTH('$numbersystem')) - LENGTH(I.barcode))), I.barcode) AS Codigo, B.title, B.author FROM biblio B, items I WHERE (I.biblionumber = B.biblioNumber ) " .$rangeCondition. " AND (I.barcode <> 'FALTA') ORDER BY Codigo";
211                 
212                 # Prepare the query
213                 my $sth = $dbh->prepare($query);
214                 # Executes the query
215                 $sth->execute;
216                 if ($sth->rows) { # There are inventary codes
217                         # Set the temp directory for pdf´s files
218                         if (!defined($ENV{'TEMP'})) {
219                                 $ENV{'TEMP'} = '/tmp/';
220                         }       
221                         # Assigns a temporary filename for the pdf file
222                         my $tmpFileName = &assingFilename($from, $to);
223                         $tmpFileName = $ENV{'TEMP'}.$tmpFileName;
224                         # Creates a PDF object
225                         my $pdf = PDF::API2->new(-file => $tmpFileName);
226                         # Set the positions where barcodes are going to be placed
227                         C4::Barcodes::PrinterConfig::setPositionsForX($labelConfig{'marginLeft'}, $labelConfig{'labelWidth'}, $labelConfig{'columns'}, $labelConfig{'pageType'});
228                         C4::Barcodes::PrinterConfig::setPositionsForY($labelConfig{'marginBottom'}, $labelConfig{'labelHeigth'}, $labelConfig{'rows'}, $labelConfig{'pageType'});
229                         # Creates a font object
230                         my $tr = $pdf->corefont('Helvetica-Bold');
231                         # Barcode position
232                         my ($page, $gfx, $text);
233                         while (my ($code,$title,$author) = $sth->fetchrow_array) {
234                                 # Generetase checksum
235                                 $code = &checksum($code);
236                                 # Generate the corresponde barcode to $code
237                                 my $barcode = $pdf->barcode(-font => $tr,       # The font object to use
238                                                                                         -type => 'ean13',       # Standard of codification
239                                                                                         -code => $code, # Text to codify
240                                                                                         -extn   => '012345',    # Barcode extension (if it is aplicable)
241                                                                                         -umzn => 10,            # Top limit of the finished bar
242                                                                                         -lmzn => 10,            # Bottom limit of the finished bar
243                                                                                         -zone => 15,            # Bars size
244                                                                                         -quzn => 0,             # Space destinated for legend
245                                                                                         -ofwt => 0.01,  # Bars width
246                                                                                         -fnsz => 8,             # Font size
247                                                                                         -text => ''
248                                                                                         );
249                                 
250                                 (my $x, my $y, $pdf, $page, $gfx, $text, $tr, $label) = C4::Barcodes::PrinterConfig::getLabelPosition(
251                                                                                                                                                                                         $label, 
252                                                                                                                                                                                         $pdf, 
253                                                                                                                                                                                         $page,
254                                                                                                                                                                                         $gfx,
255                                                                                                                                                                                         $text,
256                                                                                                                                                                                         $tr,
257                                                                                                                                                                                         $pageType);     
258                                 # Assigns a barcodes to $gfx
259                                 $gfx->barcode($barcode, $x, $y , (72/$labelConfig{'systemDpi'}));
260                                 # Assigns the additional information to the barcode (Legend)
261                                 $text->translate($x - 48, $y - 22);
262                                 if ($text_under_label) {
263                                         $text->text($text_under_label);
264                                 } else {
265                                         $text->text(substr $title, 0, 30);
266                                         $text->translate($x - 48, $y - 29);
267                                         $text->text(substr $author, 0, 30);
268                                 }
269                         }
270                         # Writes the objects added in $gfx to $page
271                         $pdf->finishobjects($page,$gfx, $text);
272                         # Save changes to the PDF
273                         $pdf->saveas;
274                         # Close the conection with the PDF file
275                         $pdf->end;
276                         # Show the PDF file
277                         print $cgi->redirect("/cgi-bin/koha/barcodes/pdfViewer.pl?tmpFileName=$tmpFileName");
278                 } else {
279                         # Rollback and shows the error legend
280                         print $cgi->redirect("/cgi-bin/koha/barcodes/barcodes.pl?error=1");
281                 }
282         $sth->finish;
283         }
284 }
285
286 barcodesGenerator($from, $to, $rangeType, $individualCodes,$text_under_label);