Merge remote-tracking branch 'kc/new/bug_5616' into kcmaster
[koha.git] / acqui / pdfformat / layout3pages.pm
1 #!/usr/bin/perl
2
3 #example script to print a basketgroup
4 #written 07/11/08 by john.soros@biblibre.com and paul.poulain@biblibre.com
5
6 # Copyright 2008-2009 BibLibre SARL
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
20 # with Koha; if not, write to the Free Software Foundation, Inc.,
21 # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22
23 #you can use any PDF::API2 module, all you need to do is return the stringifyed pdf object from the printpdf sub.
24 package pdfformat::layout3pages;
25 use vars qw($VERSION @ISA @EXPORT);
26 use Number::Format qw(format_price);
27 use MIME::Base64;
28 use strict;
29 use warnings;
30 use utf8;
31
32 use C4::Branch qw(GetBranchDetail);
33
34 BEGIN {
35          use Exporter   ();
36          our ($VERSION, @ISA, @EXPORT, @EXPORT_OK, %EXPORT_TAGS);
37         # set the version for version checking
38          $VERSION     = 1.00;
39         @ISA    = qw(Exporter);
40         @EXPORT = qw(printpdf);
41 }
42
43
44 #be careful, all the sizes (height, width, etc...) are in mm, not PostScript points (the default measurment of PDF::API2).
45 #The constants exported tranform that into PostScript points (/mm for milimeter, /in for inch, pt is postscript point, and as so is there only to show what is happening.
46 use constant mm => 25.4 / 72;
47 use constant in => 1 / 72;
48 use constant pt => 1;
49
50 use PDF::API2;
51 #A4 paper specs
52 my ($height, $width) = (297, 210);
53 use PDF::Table;
54
55 sub printorders {
56     my ($pdf, $basketgroup, $baskets, $orders) = @_;
57     
58     my $cur_format = C4::Context->preference("CurrencyFormat");
59     my $num;
60     
61     if ( $cur_format eq 'FR' ) {
62         $num = new Number::Format(
63             'decimal_fill'      => '2',
64             'decimal_point'     => ',',
65             'int_curr_symbol'   => '',
66             'mon_thousands_sep' => ' ',
67             'thousands_sep'     => ' ',
68             'mon_decimal_point' => ','
69         );
70     } else {  # US by default..
71         $num = new Number::Format(
72             'int_curr_symbol'   => '',
73             'mon_thousands_sep' => ',',
74             'mon_decimal_point' => '.'
75         );
76     }
77
78     $pdf->mediabox($height/mm, $width/mm);
79     my $number = 3;
80     for my $basket (@$baskets){
81         my $page = $pdf->page();
82         
83         # print basket header (box)
84         my $box = $page->gfx;
85         $box->rectxy(($width - 10)/mm, ($height - 5)/mm, 10/mm, ($height - 25)/mm);
86         $box->stroke;
87 #         $box->restore();
88         
89         # create a text
90         my $text = $page->text;
91         # add basketgroup number
92         $text->font( $pdf->corefont("Times", -encoding => "utf8"), 6/mm );
93         $text->translate(20/mm,  ($height-15)/mm);
94         $text->text("Order N°".$basketgroup->{'id'}.". Basket N° ".$basket->{basketno}.". ".$basket->{booksellernote});
95         
96         my $pdftable = new PDF::Table();
97         my $abaskets;
98         my $arrbasket;
99         my @keys = ('Document','Qty','RRT GST Inc.','Discount','Discount price GST Exc.','GST', 'Total GST Inc.'); 
100         for my $bkey (@keys) {
101             push(@$arrbasket, $bkey);
102         }
103         push(@$abaskets, $arrbasket);
104 #         @{$orders->{$basket->{basketno}}});
105         foreach my $line (@{$orders->{$basket->{basketno}}}) {
106             $arrbasket = undef;
107             push(@$arrbasket, @$line[3]." / ".@$line[2].(@$line[0]?" ISBN : ".@$line[0]:'').(@$line[10]?" EN : ".@$line[10]:'').", ".@$line[1].(@$line[4]?' publié par '.@$line[4]:''), @$line[5],$num->format_price(@$line[6]),$num->format_price(@$line[8]).'%',$num->format_price(@$line[7]/(1+@$line[9]/100)),$num->format_price(@$line[9]).'%',$num->format_price($num->round(@$line[7])*@$line[5]));
108             push(@$abaskets, $arrbasket);
109         }
110         
111         $pdftable->table($pdf, $page, $abaskets,
112                                         x => 10/mm,
113                                         w => ($width - 20)/mm,
114                                         start_y => 270/mm,
115                                         next_y  => 285/mm,
116                                         start_h => 250/mm,
117                                         next_h  => 250/mm,
118                                         padding => 5,
119                                         padding_right => 5,
120                                         background_color_odd  => "lightgray",
121                                         font       => $pdf->corefont("Times", -encoding => "utf8"),
122                                         font_size => 3/mm,
123                                         header_props   =>    {
124                                             font       => $pdf->corefont("Times", -encoding => "utf8"),
125                                             font_size  => 10,
126                                             bg_color   => 'gray',
127                                             repeat     => 1,
128                                         },
129                                         column_props => [
130                                             {
131                                                 min_w => 100/mm,       # Minimum column width.
132                                             },
133                                             {
134                                                 justify => 'right', # One of left|right ,
135                                             },
136                                             {
137                                                 justify => 'right', # One of left|right ,
138                                             },
139                                             {
140                                                 justify => 'right', # One of left|right ,
141                                             },
142                                             {
143                                                 justify => 'right', # One of left|right ,
144                                             },
145                                             {
146                                                 justify => 'right', # One of left|right ,
147                                             },
148                                             {
149                                                 justify => 'right', # One of left|right ,
150                                             },
151                                         ],
152              );
153     }
154     $pdf->mediabox($width/mm, $height/mm);
155 }
156
157 sub printbaskets {
158     my ($pdf, $basketgroup, $hbaskets, $bookseller, $GSTrate, $orders) = @_;
159     
160     # get library name
161     my $libraryname = C4::Context->preference("LibraryName");
162     
163     my $cur_format = C4::Context->preference("CurrencyFormat");
164     my $num;
165     
166     if ( $cur_format eq 'FR' ) {
167         $num = new Number::Format(
168             'decimal_fill'      => '2',
169             'decimal_point'     => ',',
170             'int_curr_symbol'   => '',
171             'mon_thousands_sep' => ' ',
172             'thousands_sep'     => ' ',
173             'mon_decimal_point' => ','
174         );
175     } else {  # US by default..
176         $num = new Number::Format(
177             'int_curr_symbol'   => '',
178             'mon_thousands_sep' => ',',
179             'mon_decimal_point' => '.'
180         );
181     }
182     
183     $pdf->mediabox($width/mm, $height/mm);
184     my $page = $pdf->openpage(2);
185     # create a text
186     my $text = $page->text;
187     
188     # add basketgroup number
189     $text->font( $pdf->corefont("Times", -encoding => "utf8"), 6/mm );
190     $text->translate(($width-40)/mm,  ($height-53)/mm);
191     $text->text("".$basketgroup->{'id'});
192     # print the libraryname in the header
193     $text->font( $pdf->corefont("Times", -encoding => "utf8"), 6/mm );
194     $text->translate(30/mm,  ($height-28.5)/mm);
195     $text->text($libraryname);
196     my $pdftable = new PDF::Table();
197     my $abaskets;
198     my $arrbasket;
199     # header of the table
200     my @keys = ('Lot',  'Basket (N°)', 'RRT GST Inc.', 'Discount', 'Discount price','GST rate', 'Total GST exc.','GST', 'Total GST Inc.');
201     for my $bkey (@keys) {
202         push(@$arrbasket, $bkey);
203     }
204     my $grandtotal=0;
205     my $grandgst=0;
206     # calculate each basket total
207     push(@$abaskets, $arrbasket);
208     for my $basket (@$hbaskets) {
209         $arrbasket = undef;
210         my ($total, $gst, $totallist) = (0, 0, 0);
211         my $ords = $orders->{$basket->{basketno}};
212         my $ordlength = @$ords;
213         foreach my $ord (@$ords) {
214             $total += @$ord[5] * @$ord[7];
215             $gst   += (@$ord[5] * @$ord[7]) * $GSTrate/(1+$GSTrate);
216             $totallist += @$ord[5]*@$ord[6];
217         }
218         $total=$num->round($total);
219         $gst=$num->round($gst);
220         $grandtotal +=$total;
221         $grandgst +=$gst;
222         push(@$arrbasket, $basket->{contractname}, $basket->{basketname}.'(N°'.$basket->{basketno}.')',$num->format_price($totallist), $num->format_price($bookseller->{discount}).'%', $num->format_price($total), $num->format_price($GSTrate*100).'%', $num->format_price($total-$gst), $num->format_price($gst), $num->format_price($total));
223         push(@$abaskets, $arrbasket);
224     }
225     # now, push total
226     undef $arrbasket;
227     push @$arrbasket,'','','','Total',$num->format_price($grandtotal),'',$num->format_price($grandtotal-$grandgst), $num->format_price($grandgst),$num->format_price($grandtotal);
228     push @$abaskets,$arrbasket;
229     # height is width and width is height in this function, as the pdf is in landscape mode for the Tables.
230
231     $pdftable->table($pdf, $page, $abaskets,
232                                     x => 5/mm,
233                                     w => ($width - 10)/mm,
234                                     start_y =>  230/mm,
235                                     next_y  => 230/mm,
236                                     start_h => 230/mm,
237                                     next_h  => 230/mm,
238                                     font       => $pdf->corefont("Times", -encoding => "utf8"),
239                                     font_size => 3/mm,
240                                     padding => 5,
241                                     padding_right => 10,
242                                     background_color_odd  => "lightgray",
243                                     header_props   =>    {
244                                         bg_color   => 'gray',
245                                         repeat     => 1,
246                                     },
247                                     column_props => [
248                                         {
249                                         },
250                                         {
251                                         },
252                                         {
253                                             justify => 'right',
254                                         },
255                                         {
256                                             justify => 'right',
257                                         },
258                                         {
259                                             justify => 'right',
260                                         },
261                                         {
262                                             justify => 'right',
263                                         },
264                                         {
265                                             justify => 'right',
266                                         },
267                                         {
268                                             justify => 'right',
269                                         },
270                                         {
271                                             justify => 'right',
272                                         },
273                                     ],
274     );
275     $pdf->mediabox($height/mm, $width/mm);
276 }
277
278 sub printhead {
279     my ($pdf, $basketgroup, $bookseller) = @_;
280
281     # get library name
282     my $libraryname = C4::Context->preference("LibraryName");
283     # get branch details
284     my $billingdetails  = GetBranchDetail( $basketgroup->{billingplace} );
285     my $deliverydetails = GetBranchDetail( $basketgroup->{deliveryplace} );
286     my $freedeliveryplace = $basketgroup->{freedeliveryplace};
287     # get the subject
288     my $subject;
289
290     # open 1st page (with the header)
291     my $page = $pdf->openpage(1);
292     
293     # create a text
294     my $text = $page->text;
295     
296     # print the libraryname in the header
297     $text->font( $pdf->corefont("Times", -encoding => "utf8"), 6/mm );
298     $text->translate(30/mm,  ($height-28.5)/mm);
299     $text->text($libraryname);
300
301     # print order info, on the default PDF
302     $text->font( $pdf->corefont("Times", -encoding => "utf8"), 8/mm );
303     $text->translate(100/mm,  ($height-5-48)/mm);
304     $text->text($basketgroup->{'id'});
305     
306     # print the date
307     my $today = C4::Dates->today();
308     $text->translate(130/mm,  ($height-5-48)/mm);
309     $text->text($today);
310     
311     $text->font( $pdf->corefont("Times", -encoding => "utf8"), 4/mm );
312     
313     # print billing infos
314     $text->translate(100/mm,  ($height-86)/mm);
315     $text->text($libraryname);
316     $text->translate(100/mm,  ($height-97)/mm);
317     $text->text($billingdetails->{branchname});
318     $text->translate(100/mm,  ($height-108.5)/mm);
319     $text->text($billingdetails->{branchphone});
320     $text->translate(100/mm,  ($height-115.5)/mm);
321     $text->text($billingdetails->{branchfax});
322     $text->translate(100/mm,  ($height-122.5)/mm);
323     $text->text($billingdetails->{branchaddress1});
324     $text->translate(100/mm,  ($height-127.5)/mm);
325     $text->text($billingdetails->{branchaddress2});
326     $text->translate(100/mm,  ($height-132.5)/mm);
327     $text->text($billingdetails->{branchaddress3});
328     $text->translate(100/mm,  ($height-137.5)/mm);
329     $text->text(join(' ', $billingdetails->{branchzip}, $billingdetails->{branchcity}, $billingdetails->{branchcountry}));
330     $text->translate(100/mm,  ($height-147.5)/mm);
331     $text->text($billingdetails->{branchemail});
332     
333     # print subject
334     $text->translate(100/mm,  ($height-145.5)/mm);
335     $text->text($subject);
336     
337     # print bookseller infos
338     $text->translate(100/mm,  ($height-180)/mm);
339     $text->text($bookseller->{name});
340     $text->translate(100/mm,  ($height-185)/mm);
341     $text->text($bookseller->{postal});
342     $text->translate(100/mm,  ($height-190)/mm);
343     $text->text($bookseller->{address1});
344     $text->translate(100/mm,  ($height-195)/mm);
345     $text->text($bookseller->{address2});
346     $text->translate(100/mm,  ($height-200)/mm);
347     $text->text($bookseller->{address3});
348     
349     # print delivery infos
350     $text->font( $pdf->corefont("Times-Bold", -encoding => "utf8"), 4/mm );
351     $text->translate(50/mm,  ($height-237)/mm);
352     if ($freedeliveryplace) {
353         my $start = 242;
354         my @fdp = split('\n', $freedeliveryplace);
355         foreach (@fdp) {
356             $text->text($_);
357             $text->translate( 50 / mm, ( $height - $start ) / mm );
358             $start += 5;
359         }
360     } else {
361         $text->text($deliverydetails->{branchaddress1});
362         $text->translate(50/mm,  ($height-242)/mm);
363         $text->text($deliverydetails->{branchaddress2});
364         $text->translate(50/mm,  ($height-247)/mm);
365         $text->text($deliverydetails->{branchaddress3});
366         $text->translate(50/mm,  ($height-252)/mm);
367         $text->text(join(' ', $deliverydetails->{branchzip}, $deliverydetails->{branchcity}, $deliverydetails->{branchcountry}));
368     }
369     $text->translate(50/mm,  ($height-262)/mm);
370     $text->text($basketgroup->{deliverycomment});
371 }
372
373 sub printfooters {
374         my ($pdf) = @_;
375         for (my $i=1;$i <= $pdf->pages;$i++) {
376         my $page = $pdf->openpage($i);
377         my $text = $page->text;
378         $text->font( $pdf->corefont("Times", -encoding => "utf8"), 3/mm );
379         $text->translate(10/mm,  10/mm);
380         $text->text("Page $i / ".$pdf->pages);
381         }
382 }
383
384 sub printpdf {
385     my ($basketgroup, $bookseller, $baskets, $orders, $GST) = @_;
386     # open the default PDF that will be used for base (1st page already filled)
387     my $pdf_template = C4::Context->config('intrahtdocs') . '/' . C4::Context->preference('template') . '/pdf/layout3pages.pdf';
388     my $pdf = PDF::API2->open($pdf_template);
389     $pdf->pageLabel( 0, {
390         -style => 'roman',
391     } ); # start with roman numbering
392     # fill the 1st page (basketgroup information)
393     printhead($pdf, $basketgroup, $bookseller);
394     # fill the 2nd page (orders summary)
395     printbaskets($pdf, $basketgroup, $baskets, $bookseller, $GST, $orders);
396     # fill other pages (orders)
397     printorders($pdf, $basketgroup, $baskets, $orders);
398     # print something on each page (usually the footer, but you could also put a header
399     printfooters($pdf);
400     return $pdf->stringify;
401 }
402
403 1;