Adding link to moremember to directly email members.
[koha.git] / tools / 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
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 sub getCallnum {
137 #grabs a callnumber for the specified barcode
138 my ($barcode) = @_;
139 my $query = "select dewey from items,biblioitems where items.biblionumber=biblioitems.biblionumber and items.barcode=?";
140 my $dbh = C4::Context->dbh;
141 my $sth = $dbh->prepare($query);
142 $sth->execute($barcode);
143 my ($callnum) = $sth->fetchrow_array();
144 warn "Call number is:".$barcode;
145 return $callnum;
146 }
147 # Takes inventary codes from database and if they are between
148 # the interval specify by parameters, it generates the correspond barcodes
149 sub barcodesGenerator {
150         my ($from, $to, $rangeType, $individualCodes,$text_under_label) = @_;
151         # Returns a database handler
152         my $dbh = C4::Context->dbh;
153         # Create the query to database
154         # Assigns a temporary filename for the pdf file
155         my $tmpFileName = &assingFilename($from, $to);
156         # warn "range type: ".$rangeType;
157         if ($rangeType eq 'continuous') {
158                 # Set the temp directory for pdf´s files
159                 if (!defined($ENV{'TEMP'})) {
160                         $ENV{'TEMP'} = '/tmp/';
161                 }       
162                 $tmpFileName = $ENV{'TEMP'}.$tmpFileName;
163                 # Creates a PDF object
164                 my $pdf = PDF::API2->new(-file => $tmpFileName);
165                 # Set the positions where barcodes are going to be placed
166                 C4::Barcodes::PrinterConfig::setPositionsForX($labelConfig{'marginLeft'}, $labelConfig{'labelWidth'}, $labelConfig{'columns'}, $labelConfig{'pageType'});
167                 C4::Barcodes::PrinterConfig::setPositionsForY($labelConfig{'marginBottom'}, $labelConfig{'labelHeigth'}, $labelConfig{'rows'}, $labelConfig{'pageType'});
168                 # Creates a font object
169                 my $tr = $pdf->corefont('Helvetica-Bold');
170                 # Barcode position
171                 my ($page, $gfx, $text);
172                 for (my $code=$from; $code<=$to; $code++) {
173                         # Generetase checksum
174                         my $codeC = &checksum($code);
175                         # Generate the corresponde barcode to $code
176                         # warn "Code is :-->".$codeC."<--";
177                         my $barcode = $pdf->barcode(-font => $tr,       # The font object to use
178                                                                                 -type => 'ean128',      # Standard of codification
179                                                                                 -code => $codeC, # Text to codify
180                                                                                 -extn   => '012345',    # Barcode extension (if it is aplicable)
181                                                                                 -umzn => 10,            # Top limit of the finished bar
182                                                                                 -lmzn => 10,            # Bottom limit of the finished bar
183                                                                                 -zone => 15,            # Bars size
184                                                                                 -quzn => 0,             # Space destinated for legend
185                                                                                 -ofwt => 0.01,  # Bars width
186                                                                                 -fnsz => 8,             # Font size
187                                                                                 -text => ''
188                                                                                 );
189                         
190                         (my $x, my $y, $pdf, $page, $gfx, $text, $tr, $label) = C4::Barcodes::PrinterConfig::getLabelPosition(
191                                                                                                                                                                                 $label, 
192                                                                                                                                                                                 $pdf, 
193                                                                                                                                                                                 $page,
194                                                                                                                                                                                 $gfx,
195                                                                                                                                                                                 $text,
196                                                                                                                                                                                 $tr,
197                                                                                                                                                                                 $pageType);     
198                         # Assigns a barcodes to $gfx
199                         $gfx->barcode($barcode, $x, $y , (72/$labelConfig{'systemDpi'}));
200                         # Assigns the additional information to the barcode (Legend)
201                         $text->translate($x - 48, $y - 22);
202                         warn "code is ".$codeC;
203                         if ($text_under_label) {
204                                 $text->text($text_under_label);
205                         } else {
206                         $text->text(getCallnum($code));
207                         }
208                 }
209                 # Writes the objects added in $gfx to $page
210                 $pdf->finishobjects($page,$gfx, $text);
211                 # Save changes to the PDF
212                 $pdf->saveas;
213                 # Close the conection with the PDF file
214                 $pdf->end;
215                 # Show the PDF file
216                 print $cgi->redirect("/cgi-bin/koha/barcodes/pdfViewer.pl?tmpFileName=$tmpFileName");
217         } else {
218                 my $rangeCondition;
219                 if ($individualCodes ne "") {
220                         $rangeCondition = "AND (I.barcode IN " . $individualCodes . ")";
221                 } else {
222                         $rangeCondition =  "AND (I.barcode >= " . $from . " AND I.barcode <="  . $to . " )";
223                 }
224                 warn "above the query"; 
225                 my $query = "SELECT CONCAT('$numbersystem',REPEAT('0',((12 - LENGTH('$numbersystem')) - LENGTH(I.barcode))), I.barcode) AS Codigo, I.dewey as dewey B.title, B.author FROM biblio B, items I WHERE (I.biblionumber = B.biblioNumber ) " .$rangeCondition. " AND (I.barcode <> 'FALTA') ORDER BY Codigo";
226                 
227                 # Prepare the query
228                 my $sth = $dbh->prepare($query);
229                 # Executes the query
230                 $sth->execute;
231                 if ($sth->rows) { # There are inventary codes
232                         # Set the temp directory for pdf´s files
233                         if (!defined($ENV{'TEMP'})) {
234                                 $ENV{'TEMP'} = '/tmp/';
235                         }       
236                         # Assigns a temporary filename for the pdf file
237                         my $tmpFileName = &assingFilename($from, $to);
238                         $tmpFileName = $ENV{'TEMP'}.$tmpFileName;
239                         # Creates a PDF object
240                         my $pdf = PDF::API2->new(-file => $tmpFileName);
241                         # Set the positions where barcodes are going to be placed
242                         C4::Barcodes::PrinterConfig::setPositionsForX($labelConfig{'marginLeft'}, $labelConfig{'labelWidth'}, $labelConfig{'columns'}, $labelConfig{'pageType'});
243                         C4::Barcodes::PrinterConfig::setPositionsForY($labelConfig{'marginBottom'}, $labelConfig{'labelHeigth'}, $labelConfig{'rows'}, $labelConfig{'pageType'});
244                         # Creates a font object
245                         my $tr = $pdf->corefont('Helvetica-Bold');
246                         # Barcode position
247                         my ($page, $gfx, $text);
248                         while (my ($code,$dewey,$title,$author) = $sth->fetchrow_array) {
249                                 # Generetase checksum
250                                 $code = &checksum($code);
251                                 # Generate the corresponde barcode to $code
252                                 my $barcode = $pdf->barcode(-font => $tr,       # The font object to use
253                                                                                         -type => 'ean13',       # Standard of codification
254                                                                                         -code => $code, # Text to codify
255                                                                                         -extn   => '012345',    # Barcode extension (if it is aplicable)
256                                                                                         -umzn => 10,            # Top limit of the finished bar
257                                                                                         -lmzn => 10,            # Bottom limit of the finished bar
258                                                                                         -zone => 15,            # Bars size
259                                                                                         -quzn => 0,             # Space destinated for legend
260                                                                                         -ofwt => 0.01,  # Bars width
261                                                                                         -fnsz => 8,             # Font size
262                                                                                         -text => ''
263                                                                                         );
264                                 
265                                 (my $x, my $y, $pdf, $page, $gfx, $text, $tr, $label) = C4::Barcodes::PrinterConfig::getLabelPosition(
266                                                                                                                                                                                         $label, 
267                                                                                                                                                                                         $pdf, 
268                                                                                                                                                                                         $page,
269                                                                                                                                                                                         $gfx,
270                                                                                                                                                                                         $text,
271                                                                                                                                                                                         $tr,
272                                                                                                                                                                                         $pageType);     
273                                 # Assigns a barcodes to $gfx
274                                 $gfx->barcode($barcode, $x, $y , (72/$labelConfig{'systemDpi'}));
275                                 # Assigns the additional information to the barcode (Legend)
276                                 $text->translate($x - 48, $y - 22);
277                                 if ($text_under_label) {
278                                         $text->text($text_under_label);
279                                 } else {
280                                         warn "here a dewey:".$dewey;
281                                         $text->text(substr $dewey, 0, 30);
282                                         $text->translate($x - 48, $y - 29);
283                                         #$text->text(substr $author, 0, 30);
284                                 }
285                         }
286                         # Writes the objects added in $gfx to $page
287                         $pdf->finishobjects($page,$gfx, $text);
288                         # Save changes to the PDF
289                         $pdf->saveas;
290                         # Close the conection with the PDF file
291                         $pdf->end;
292                         # Show the PDF file
293                         print $cgi->redirect("/cgi-bin/koha/tools/pdfViewer.pl?tmpFileName=$tmpFileName");
294                 } else {
295                         # Rollback and shows the error legend
296                         print $cgi->redirect("/cgi-bin/koha/tools/barcodes.pl?error=1");
297                 }
298         $sth->finish;
299         }
300 }
301
302 barcodesGenerator($from, $to, $rangeType, $individualCodes,$text_under_label);