Merge remote-tracking branch 'origin/new/bug_8233'
[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 GetBranchName);
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         $text->translate(20/mm,  ($height-20)/mm);
96         $text->text( ( $basket->{billingplace} ? "Billing at " . C4::Branch::GetBranchName( $basket->{billingplace} ) : "" )
97             . ( $basket->{billingplace} and $basket->{deliveryplace} ? " and " : "" )
98             . ( $basket->{deliveryplace} ? "delivery at " . C4::Branch::GetBranchName( $basket->{deliveryplace}) : "" )
99         );
100
101         my $pdftable = new PDF::Table();
102         my $abaskets;
103         my $arrbasket;
104         my @keys = ('Document','Qty','RRT GST Inc.','Discount','Discount price GST Exc.','GST', 'Total GST Inc.'); 
105         for my $bkey (@keys) {
106             push(@$arrbasket, $bkey);
107         }
108         push(@$abaskets, $arrbasket);
109 #         @{$orders->{$basket->{basketno}}});
110         foreach my $line (@{$orders->{$basket->{basketno}}}) {
111             $arrbasket = undef;
112             push(@$arrbasket, @$line[3]." / ".@$line[2].(@$line[0]?" ISBN : ".@$line[0]:'').(@$line[10]?" EN : ".@$line[10]:'').", ".@$line[1].(@$line[4]?' published by '.@$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]));
113             push(@$abaskets, $arrbasket);
114         }
115         
116         $pdftable->table($pdf, $page, $abaskets,
117                                         x => 10/mm,
118                                         w => ($width - 20)/mm,
119                                         start_y => 270/mm,
120                                         next_y  => 285/mm,
121                                         start_h => 250/mm,
122                                         next_h  => 250/mm,
123                                         padding => 5,
124                                         padding_right => 5,
125                                         background_color_odd  => "lightgray",
126                                         font       => $pdf->corefont("Times", -encoding => "utf8"),
127                                         font_size => 3/mm,
128                                         header_props   =>    {
129                                             font       => $pdf->corefont("Times", -encoding => "utf8"),
130                                             font_size  => 10,
131                                             bg_color   => 'gray',
132                                             repeat     => 1,
133                                         },
134                                         column_props => [
135                                             {
136                                                 min_w => 100/mm,       # Minimum column width.
137                                             },
138                                             {
139                                                 justify => 'right', # One of left|right ,
140                                             },
141                                             {
142                                                 justify => 'right', # One of left|right ,
143                                             },
144                                             {
145                                                 justify => 'right', # One of left|right ,
146                                             },
147                                             {
148                                                 justify => 'right', # One of left|right ,
149                                             },
150                                             {
151                                                 justify => 'right', # One of left|right ,
152                                             },
153                                             {
154                                                 justify => 'right', # One of left|right ,
155                                             },
156                                         ],
157              );
158     }
159     $pdf->mediabox($width/mm, $height/mm);
160 }
161
162 sub printbaskets {
163     my ($pdf, $basketgroup, $hbaskets, $bookseller, $GSTrate, $orders) = @_;
164     
165     # get library name
166     my $libraryname = C4::Context->preference("LibraryName");
167     
168     my $cur_format = C4::Context->preference("CurrencyFormat");
169     my $num;
170     
171     if ( $cur_format eq 'FR' ) {
172         $num = new Number::Format(
173             'decimal_fill'      => '2',
174             'decimal_point'     => ',',
175             'int_curr_symbol'   => '',
176             'mon_thousands_sep' => ' ',
177             'thousands_sep'     => ' ',
178             'mon_decimal_point' => ','
179         );
180     } else {  # US by default..
181         $num = new Number::Format(
182             'int_curr_symbol'   => '',
183             'mon_thousands_sep' => ',',
184             'mon_decimal_point' => '.'
185         );
186     }
187     
188     $pdf->mediabox($width/mm, $height/mm);
189     my $page = $pdf->openpage(2);
190     # create a text
191     my $text = $page->text;
192     
193     # add basketgroup number
194     $text->font( $pdf->corefont("Times", -encoding => "utf8"), 6/mm );
195     $text->translate(($width-40)/mm,  ($height-53)/mm);
196     $text->text("".$basketgroup->{'id'});
197     # print the libraryname in the header
198     $text->font( $pdf->corefont("Times", -encoding => "utf8"), 6/mm );
199     $text->translate(30/mm,  ($height-28.5)/mm);
200     $text->text($libraryname);
201     my $pdftable = new PDF::Table();
202     my $abaskets;
203     my $arrbasket;
204     # header of the table
205     my @keys = ('Lot',  'Basket (N°)', 'RRT GST Inc.', 'Discount', 'Discount price','GST rate', 'Total GST exc.','GST', 'Total GST Inc.');
206     for my $bkey (@keys) {
207         push(@$arrbasket, $bkey);
208     }
209     my $grandtotal=0;
210     my $grandgst=0;
211     # calculate each basket total
212     push(@$abaskets, $arrbasket);
213     for my $basket (@$hbaskets) {
214         $arrbasket = undef;
215         my ($total, $gst, $totallist) = (0, 0, 0);
216         my $ords = $orders->{$basket->{basketno}};
217         my $ordlength = @$ords;
218         foreach my $ord (@$ords) {
219             $total += @$ord[5] * @$ord[7];
220             $gst   += (@$ord[5] * @$ord[7]) * $GSTrate/(1+$GSTrate);
221             $totallist += @$ord[5]*@$ord[6];
222         }
223         $total=$num->round($total);
224         $gst=$num->round($gst);
225         $grandtotal +=$total;
226         $grandgst +=$gst;
227         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));
228         push(@$abaskets, $arrbasket);
229     }
230     # now, push total
231     undef $arrbasket;
232     push @$arrbasket,'','','','Total',$num->format_price($grandtotal),'',$num->format_price($grandtotal-$grandgst), $num->format_price($grandgst),$num->format_price($grandtotal);
233     push @$abaskets,$arrbasket;
234     # height is width and width is height in this function, as the pdf is in landscape mode for the Tables.
235
236     $pdftable->table($pdf, $page, $abaskets,
237                                     x => 5/mm,
238                                     w => ($width - 10)/mm,
239                                     start_y =>  230/mm,
240                                     next_y  => 230/mm,
241                                     start_h => 230/mm,
242                                     next_h  => 230/mm,
243                                     font       => $pdf->corefont("Times", -encoding => "utf8"),
244                                     font_size => 3/mm,
245                                     padding => 5,
246                                     padding_right => 10,
247                                     background_color_odd  => "lightgray",
248                                     header_props   =>    {
249                                         bg_color   => 'gray',
250                                         repeat     => 1,
251                                     },
252                                     column_props => [
253                                         {
254                                         },
255                                         {
256                                         },
257                                         {
258                                             justify => 'right',
259                                         },
260                                         {
261                                             justify => 'right',
262                                         },
263                                         {
264                                             justify => 'right',
265                                         },
266                                         {
267                                             justify => 'right',
268                                         },
269                                         {
270                                             justify => 'right',
271                                         },
272                                         {
273                                             justify => 'right',
274                                         },
275                                         {
276                                             justify => 'right',
277                                         },
278                                     ],
279     );
280     $pdf->mediabox($height/mm, $width/mm);
281 }
282
283 sub printhead {
284     my ($pdf, $basketgroup, $bookseller) = @_;
285
286     # get library name
287     my $libraryname = C4::Context->preference("LibraryName");
288     # get branch details
289     my $billingdetails  = GetBranchDetail( $basketgroup->{billingplace} );
290     my $deliverydetails = GetBranchDetail( $basketgroup->{deliveryplace} );
291     my $freedeliveryplace = $basketgroup->{freedeliveryplace};
292     # get the subject
293     my $subject;
294
295     # open 1st page (with the header)
296     my $page = $pdf->openpage(1);
297     
298     # create a text
299     my $text = $page->text;
300     
301     # print the libraryname in the header
302     $text->font( $pdf->corefont("Times", -encoding => "utf8"), 6/mm );
303     $text->translate(30/mm,  ($height-28.5)/mm);
304     $text->text($libraryname);
305
306     # print order info, on the default PDF
307     $text->font( $pdf->corefont("Times", -encoding => "utf8"), 8/mm );
308     $text->translate(100/mm,  ($height-5-48)/mm);
309     $text->text($basketgroup->{'id'});
310     
311     # print the date
312     my $today = C4::Dates->today();
313     $text->translate(130/mm,  ($height-5-48)/mm);
314     $text->text($today);
315     
316     $text->font( $pdf->corefont("Times", -encoding => "utf8"), 4/mm );
317     
318     # print billing infos
319     $text->translate(100/mm,  ($height-86)/mm);
320     $text->text($libraryname);
321     $text->translate(100/mm,  ($height-97)/mm);
322     $text->text($billingdetails->{branchname});
323     $text->translate(100/mm,  ($height-108.5)/mm);
324     $text->text($billingdetails->{branchphone});
325     $text->translate(100/mm,  ($height-115.5)/mm);
326     $text->text($billingdetails->{branchfax});
327     $text->translate(100/mm,  ($height-122.5)/mm);
328     $text->text($billingdetails->{branchaddress1});
329     $text->translate(100/mm,  ($height-127.5)/mm);
330     $text->text($billingdetails->{branchaddress2});
331     $text->translate(100/mm,  ($height-132.5)/mm);
332     $text->text($billingdetails->{branchaddress3});
333     $text->translate(100/mm,  ($height-137.5)/mm);
334     $text->text(join(' ', $billingdetails->{branchzip}, $billingdetails->{branchcity}, $billingdetails->{branchcountry}));
335     $text->translate(100/mm,  ($height-147.5)/mm);
336     $text->text($billingdetails->{branchemail});
337     
338     # print subject
339     $text->translate(100/mm,  ($height-145.5)/mm);
340     $text->text($subject);
341     
342     # print bookseller infos
343     $text->translate(100/mm,  ($height-180)/mm);
344     $text->text($bookseller->{name});
345     $text->translate(100/mm,  ($height-185)/mm);
346     $text->text($bookseller->{postal});
347     $text->translate(100/mm,  ($height-190)/mm);
348     $text->text($bookseller->{address1});
349     $text->translate(100/mm,  ($height-195)/mm);
350     $text->text($bookseller->{address2});
351     $text->translate(100/mm,  ($height-200)/mm);
352     $text->text($bookseller->{address3});
353     
354     # print delivery infos
355     $text->font( $pdf->corefont("Times-Bold", -encoding => "utf8"), 4/mm );
356     $text->translate(50/mm,  ($height-237)/mm);
357     if ($freedeliveryplace) {
358         my $start = 242;
359         my @fdp = split('\n', $freedeliveryplace);
360         foreach (@fdp) {
361             $text->text($_);
362             $text->translate( 50 / mm, ( $height - $start ) / mm );
363             $start += 5;
364         }
365     } else {
366         $text->text($deliverydetails->{branchaddress1});
367         $text->translate(50/mm,  ($height-242)/mm);
368         $text->text($deliverydetails->{branchaddress2});
369         $text->translate(50/mm,  ($height-247)/mm);
370         $text->text($deliverydetails->{branchaddress3});
371         $text->translate(50/mm,  ($height-252)/mm);
372         $text->text(join(' ', $deliverydetails->{branchzip}, $deliverydetails->{branchcity}, $deliverydetails->{branchcountry}));
373     }
374     $text->translate(50/mm,  ($height-262)/mm);
375     $text->text($basketgroup->{deliverycomment});
376 }
377
378 sub printfooters {
379         my ($pdf) = @_;
380         for (my $i=1;$i <= $pdf->pages;$i++) {
381         my $page = $pdf->openpage($i);
382         my $text = $page->text;
383         $text->font( $pdf->corefont("Times", -encoding => "utf8"), 3/mm );
384         $text->translate(10/mm,  10/mm);
385         $text->text("Page $i / ".$pdf->pages);
386         }
387 }
388
389 sub printpdf {
390     my ($basketgroup, $bookseller, $baskets, $orders, $GST) = @_;
391     # open the default PDF that will be used for base (1st page already filled)
392     my $pdf_template = C4::Context->config('intrahtdocs') . '/' . C4::Context->preference('template') . '/pdf/layout3pages.pdf';
393     my $pdf = PDF::API2->open($pdf_template);
394     $pdf->pageLabel( 0, {
395         -style => 'roman',
396     } ); # start with roman numbering
397     # fill the 1st page (basketgroup information)
398     printhead($pdf, $basketgroup, $bookseller);
399     # fill the 2nd page (orders summary)
400     printbaskets($pdf, $basketgroup, $baskets, $bookseller, $GST, $orders);
401     # fill other pages (orders)
402     printorders($pdf, $basketgroup, $baskets, $orders);
403     # print something on each page (usually the footer, but you could also put a header
404     printfooters($pdf);
405     return $pdf->stringify;
406 }
407
408 1;