Bug 11828: Add German translation of layout2pages PDF template
[koha.git] / acqui / basketgroup.pl
1 #!/usr/bin/perl
2
3 #script to group (closed) baskets into basket groups for easier order management
4 #written by john.soros@biblibre.com 01/10/2008
5
6 # Copyright 2008 - 2009 BibLibre SARL
7 # Parts Copyright Catalyst 2010
8 #
9 # This file is part of Koha.
10 #
11 # Koha is free software; you can redistribute it and/or modify it under the
12 # terms of the GNU General Public License as published by the Free Software
13 # Foundation; either version 2 of the License, or (at your option) any later
14 # version.
15 #
16 # Koha is distributed in the hope that it will be useful, but WITHOUT ANY
17 # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
18 # A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
19 #
20 # You should have received a copy of the GNU General Public License along
21 # with Koha; if not, write to the Free Software Foundation, Inc.,
22 # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
23
24
25 =head1 NAME
26
27 basketgroup.pl
28
29 =head1 DESCRIPTION
30
31  This script lets the user group (closed) baskets into basket groups for easier order management. Note that the grouped baskets have to be from the same bookseller and
32  have to be closed to be printed or exported.
33
34 =head1 CGI PARAMETERS
35
36 =over 4
37
38 =item $booksellerid
39
40 The bookseller who we want to display the baskets (and basketgroups) of.
41
42 =back
43
44 =cut
45
46 use strict;
47 use warnings;
48 use Carp;
49
50 use C4::Input;
51 use C4::Auth;
52 use C4::Output;
53 use CGI;
54
55 use C4::Bookseller qw/GetBookSellerFromId/;
56 use C4::Budgets qw/ConvertCurrency/;
57 use C4::Acquisition qw/CloseBasketgroup ReOpenBasketgroup GetOrders GetBasketsByBasketgroup GetBasketsByBookseller ModBasketgroup NewBasketgroup DelBasketgroup GetBasketgroups ModBasket GetBasketgroup GetBasket GetBasketGroupAsCSV/;
58 use C4::Bookseller qw/GetBookSellerFromId/;
59 use C4::Branch qw/GetBranches/;
60 use C4::Members qw/GetMember/;
61
62 our $input=new CGI;
63
64 our ($template, $loggedinuser, $cookie)
65     = get_template_and_user({template_name => "acqui/basketgroup.tmpl",
66                              query => $input,
67                              type => "intranet",
68                              authnotrequired => 0,
69                              flagsrequired => {acquisition => 'group_manage'},
70                              debug => 1,
71                 });
72
73 sub BasketTotal {
74     my $basketno = shift;
75     my $bookseller = shift;
76     my $total = 0;
77     my @orders = GetOrders($basketno);
78     for my $order (@orders){
79         $total = $total + ( $order->{ecost} * $order->{quantity} );
80         if ($bookseller->{invoiceincgst} && ! $bookseller->{listincgst} && ( $bookseller->{gstrate} // C4::Context->preference("gist") )) {
81             my $gst = $bookseller->{gstrate} // C4::Context->preference("gist");
82             $total = $total * ( $gst / 100 +1);
83         }
84     }
85     $total .= " " . ($bookseller->{invoiceprice} // 0);
86     return $total;
87 }
88
89 #displays all basketgroups and all closed baskets (in their respective groups)
90 sub displaybasketgroups {
91     my $basketgroups = shift;
92     my $bookseller = shift;
93     my $baskets = shift;
94     if (scalar @$basketgroups != 0) {
95         foreach my $basketgroup (@$basketgroups){
96             my $i = 0;
97             my $basketsqty = 0;
98             while($i < scalar(@$baskets)){
99                 my $basket = @$baskets[$i];
100                 if($basket->{'basketgroupid'} && $basket->{'basketgroupid'} == $basketgroup->{'id'}){
101                     $basket->{total} = BasketTotal($basket->{basketno}, $bookseller);
102                     push(@{$basketgroup->{'baskets'}}, $basket);
103                     splice(@$baskets, $i, 1);
104                     ++$basketsqty;
105                     --$i;
106                 }
107                 ++$i;
108             }
109             $basketgroup -> {'basketsqty'} = $basketsqty;
110         }
111         $template->param(basketgroups => $basketgroups);
112     }
113     for(my $i=0; $i < scalar @$baskets; ++$i) {
114         if( ! @$baskets[$i]->{'closedate'} ) {
115             splice(@$baskets, $i, 1);
116             --$i;
117         }else{
118             @$baskets[$i]->{total} = BasketTotal(@$baskets[$i]->{basketno}, $bookseller);
119         }
120     }
121     $template->param(baskets => $baskets);
122     $template->param( booksellername => $bookseller ->{'name'});
123 }
124
125 sub printbasketgrouppdf{
126     my ($basketgroupid) = @_;
127     
128     my $pdfformat = C4::Context->preference("OrderPdfFormat");
129     if ($pdfformat eq 'pdfformat::layout3pages' || $pdfformat eq 'pdfformat::layout2pages' || $pdfformat eq 'pdfformat::layout3pagesfr'
130         || $pdfformat eq 'pdfformat::layout2pagesde'){
131         eval {
132         eval "require $pdfformat";
133             import $pdfformat;
134         };
135         if ($@){
136         }
137     }
138     else {
139         print $input->header;  
140         print $input->start_html;  # FIXME Should do a nicer page
141         print "<h1>Invalid PDF Format set</h1>";
142         print "Please go to the systempreferences and set a valid pdfformat";
143         exit;
144     }
145     
146     my $basketgroup = GetBasketgroup($basketgroupid);
147     my $bookseller = GetBookSellerFromId($basketgroup->{'booksellerid'});
148     my $baskets = GetBasketsByBasketgroup($basketgroupid);
149     
150     my %orders;
151     for my $basket (@$baskets) {
152         my @ba_orders;
153         my @ords = &GetOrders($basket->{basketno});
154         for my $ord (@ords) {
155
156             next unless ( $ord->{biblionumber} or $ord->{quantity}> 0 );
157             eval {
158                 require C4::Biblio;
159                 import C4::Biblio;
160             };
161             if ($@){
162                 croak $@;
163             }
164             eval {
165                 require C4::Koha;
166                 import C4::Koha;
167             };
168             if ($@){
169                 croak $@;
170             }
171
172             $ord->{rrp} = ConvertCurrency( $ord->{'currency'}, $ord->{rrp} );
173             if ( $bookseller->{'listincgst'} ) {
174                 $ord->{rrpgsti} = sprintf( "%.2f", $ord->{rrp} );
175                 $ord->{gstgsti} = sprintf( "%.2f", $ord->{gstrate} * 100 );
176                 $ord->{rrpgste} = sprintf( "%.2f", $ord->{rrp} / ( 1 + ( $ord->{gstgsti} / 100 ) ) );
177                 $ord->{gstgste} = sprintf( "%.2f", $ord->{gstgsti} / ( 1 + ( $ord->{gstgsti} / 100 ) ) );
178                 $ord->{ecostgsti} = sprintf( "%.2f", $ord->{ecost} );
179                 $ord->{ecostgste} = sprintf( "%.2f", $ord->{ecost} / ( 1 + ( $ord->{gstgsti} / 100 ) ) );
180                 $ord->{gstvalue} = sprintf( "%.2f", ( $ord->{ecostgsti} - $ord->{ecostgste} ) * $ord->{quantity});
181                 $ord->{totalgste} = sprintf( "%.2f", $ord->{quantity} * $ord->{ecostgste} );
182                 $ord->{totalgsti} = sprintf( "%.2f", $ord->{quantity} * $ord->{ecostgsti} );
183             } else {
184                 $ord->{rrpgsti} = sprintf( "%.2f", $ord->{rrp} * ( 1 + ( $ord->{gstrate} ) ) );
185                 $ord->{rrpgste} = sprintf( "%.2f", $ord->{rrp} );
186                 $ord->{gstgsti} = sprintf( "%.2f", $ord->{gstrate} * 100 );
187                 $ord->{gstgste} = sprintf( "%.2f", $ord->{gstrate} * 100 );
188                 $ord->{ecostgsti} = sprintf( "%.2f", $ord->{ecost} * ( 1 + ( $ord->{gstrate} ) ) );
189                 $ord->{ecostgste} = sprintf( "%.2f", $ord->{ecost} );
190                 $ord->{gstvalue} = sprintf( "%.2f", ( $ord->{ecostgsti} - $ord->{ecostgste} ) * $ord->{quantity});
191                 $ord->{totalgste} = sprintf( "%.2f", $ord->{quantity} * $ord->{ecostgste} );
192                 $ord->{totalgsti} = sprintf( "%.2f", $ord->{quantity} * $ord->{ecostgsti} );
193             }
194             my $bib = GetBiblioData($ord->{biblionumber});
195             my $itemtypes = GetItemTypes();
196
197             #FIXME DELETE ME
198             # 0      1        2        3         4            5         6       7      8        9
199             #isbn, itemtype, author, title, publishercode, quantity, listprice ecost discount gstrate
200
201             # Editor Number
202             my $en;
203             my $marcrecord=eval{MARC::Record::new_from_xml( $ord->{marcxml},'UTF-8' )};
204             if ($marcrecord){
205                 if ( C4::Context->preference("marcflavour") eq 'UNIMARC' ) {
206                     $en = $marcrecord->subfield( '345', "b" );
207                 } elsif ( C4::Context->preference("marcflavour") eq 'MARC21' ) {
208                     $en = $marcrecord->subfield( '037', "a" );
209                 }
210             }
211
212             my $ba_order = {
213                 isbn => ($ord->{isbn} ? $ord->{isbn} : undef),
214                 itemtype => ( $ord->{itemtype} and $bib->{itemtype} ? $itemtypes->{$bib->{itemtype}}->{description} : undef ),
215                 en => ( $en ? $en : undef ),
216             };
217             for my $key ( qw/ gstrate author title itemtype publishercode discount quantity rrpgsti rrpgste gstgsti gstgste ecostgsti ecostgste gstvalue totalgste totalgsti / ) {
218                 $ba_order->{$key} = $ord->{$key};
219             }
220
221             push(@ba_orders, $ba_order);
222         }
223         $orders{$basket->{basketno}} = \@ba_orders;
224     }
225     print $input->header(
226         -type       => 'application/pdf',
227         -attachment => ( $basketgroup->{name} || $basketgroupid ) . '.pdf'
228     );
229     my $pdf = printpdf($basketgroup, $bookseller, $baskets, \%orders, $bookseller->{gstrate} // C4::Context->preference("gist")) || die "pdf generation failed";
230     print $pdf;
231
232 }
233
234 my $op = $input->param('op') || 'display';
235 # possible values of $op :
236 # - add : adds a new basketgroup, or edit an open basketgroup, or display a closed basketgroup
237 # - mod_basket : modify an individual basket of the basketgroup
238 # - closeandprint : close and print an closed basketgroup in pdf. called by clicking on "Close and print" button in closed basketgroups list
239 # - print : print a closed basketgroup. called by clicking on "Print" button in closed basketgroups list
240 # - export : export in CSV a closed basketgroup. called by clicking on "Export" button in closed basketgroups list
241 # - delete : delete an open basketgroup. called by clicking on "Delete" button in open basketgroups list
242 # - reopen : reopen a closed basketgroup. called by clicking on "Reopen" button in closed basketgroup list
243 # - attachbasket : save a modified basketgroup, or creates a new basketgroup when a basket is closed. called from basket page
244 # - display : display the list of all basketgroups for a vendor
245 my $booksellerid = $input->param('booksellerid');
246 $template->param(booksellerid => $booksellerid);
247
248 if ( $op eq "add" ) {
249 #
250 # if no param('basketgroupid') is not defined, adds a new basketgroup
251 # else, edit (if it is open) or display (if it is close) the basketgroup basketgroupid
252 # the template will know if basketgroup must be displayed or edited, depending on the value of closed key
253 #
254     my $bookseller = &GetBookSellerFromId($booksellerid);
255     my $basketgroupid = $input->param('basketgroupid');
256     my $billingplace;
257     my $deliveryplace;
258     my $freedeliveryplace;
259     if ( $basketgroupid ) {
260         # Get the selected baskets in the basketgroup to display them
261         my $selecteds = GetBasketsByBasketgroup($basketgroupid);
262         foreach my $basket(@{$selecteds}){
263             $basket->{total} = BasketTotal($basket->{basketno}, $bookseller);
264         }
265         $template->param(basketgroupid => $basketgroupid,
266                          selectedbaskets => $selecteds);
267
268         # Get general informations about the basket group to prefill the form
269         my $basketgroup = GetBasketgroup($basketgroupid);
270         $template->param(
271             name            => $basketgroup->{name},
272             deliverycomment => $basketgroup->{deliverycomment},
273             freedeliveryplace => $basketgroup->{freedeliveryplace},
274         );
275         $billingplace  = $basketgroup->{billingplace};
276         $deliveryplace = $basketgroup->{deliveryplace};
277         $freedeliveryplace = $basketgroup->{freedeliveryplace};
278         $template->param( closedbg => ($basketgroup ->{'closed'}) ? 1 : 0);
279     } else {
280         $template->param( closedbg => 0);
281     }
282     # determine default billing and delivery places depending on librarian homebranch and existing basketgroup data
283     my $borrower = GetMember( ( 'borrowernumber' => $loggedinuser ) );
284     $billingplace  = $billingplace  || $borrower->{'branchcode'};
285     $deliveryplace = $deliveryplace || $borrower->{'branchcode'};
286
287     my $branches = C4::Branch::GetBranchesLoop( $billingplace );
288     $template->param( billingplaceloop => $branches );
289     $branches = C4::Branch::GetBranchesLoop( $deliveryplace );
290     $template->param( deliveryplaceloop => $branches );
291     $template->param( booksellerid => $booksellerid );
292
293     # the template will display a unique basketgroup
294     $template->param(grouping => 1);
295     my $basketgroups = &GetBasketgroups($booksellerid);
296     my $baskets = &GetBasketsByBookseller($booksellerid);
297     displaybasketgroups($basketgroups, $bookseller, $baskets);
298 } elsif ($op eq 'mod_basket') {
299 #
300 # edit an individual basket contained in this basketgroup
301 #
302   my $basketno=$input->param('basketno');
303   my $basketgroupid=$input->param('basketgroupid');
304   ModBasket( { basketno => $basketno,
305                          basketgroupid => $basketgroupid } );
306   print $input->redirect("basket.pl?basketno=" . $basketno);
307 } elsif ( $op eq 'closeandprint') {
308 #
309 # close an open basketgroup and generates a pdf
310 #
311     my $basketgroupid = $input->param('basketgroupid');
312     CloseBasketgroup($basketgroupid);
313     printbasketgrouppdf($basketgroupid);
314     exit;
315 }elsif ($op eq 'print'){
316 #
317 # print a closed basketgroup
318 #
319     my $basketgroupid = $input->param('basketgroupid');
320     printbasketgrouppdf($basketgroupid);
321     exit;
322 }elsif ( $op eq "export" ) {
323 #
324 # export a closed basketgroup in csv
325 #
326     my $basketgroupid = $input->param('basketgroupid');
327     print $input->header(
328         -type       => 'text/csv',
329         -attachment => 'basketgroup' . $basketgroupid . '.csv',
330     );
331     print GetBasketGroupAsCSV( $basketgroupid, $input );
332     exit;
333 }elsif( $op eq "delete"){
334 #
335 # delete an closed basketgroup
336 #
337     my $basketgroupid = $input->param('basketgroupid');
338     DelBasketgroup($basketgroupid);
339     print $input->redirect('/cgi-bin/koha/acqui/basketgroup.pl?booksellerid=' . $booksellerid.'&amp;listclosed=1');
340 }elsif ( $op eq 'reopen'){
341 #
342 # reopen a closed basketgroup
343 #
344     my $basketgroupid   = $input->param('basketgroupid');
345     my $booksellerid    = $input->param('booksellerid');
346     ReOpenBasketgroup($basketgroupid);
347     my $redirectpath = ((defined $input->param('mode'))&& ($input->param('mode') eq 'singlebg')) ?'/cgi-bin/koha/acqui/basketgroup.pl?op=add&amp;basketgroupid='.$basketgroupid.'&amp;booksellerid='.$booksellerid : '/cgi-bin/koha/acqui/basketgroup.pl?booksellerid=' .$booksellerid.'&amp;listclosed=1';
348     print $input->redirect($redirectpath);
349 } elsif ( $op eq 'attachbasket') {
350 #
351 # save a modified basketgroup, or creates a new basketgroup when a basket is closed. called from basket page
352 #
353     # Getting parameters
354     my $basketgroup       = {};
355     my @baskets           = $input->param('basket');
356     my $basketgroupid     = $input->param('basketgroupid');
357     my $basketgroupname   = $input->param('basketgroupname');
358     my $booksellerid      = $input->param('booksellerid');
359     my $billingplace      = $input->param('billingplace');
360     my $deliveryplace     = $input->param('deliveryplace');
361     my $freedeliveryplace = $input->param('freedeliveryplace');
362     my $deliverycomment   = $input->param('deliverycomment');
363     my $closedbg          = $input->param('closedbg') ? 1 : 0;
364     if ($basketgroupid) {
365     # If we have a basketgroupid we edit the basketgroup
366         $basketgroup = {
367               name              => $basketgroupname,
368               id                => $basketgroupid,
369               basketlist        => \@baskets,
370               billingplace      => $billingplace,
371               deliveryplace     => $deliveryplace,
372               freedeliveryplace => $freedeliveryplace,
373               deliverycomment   => $deliverycomment,
374               closed            => $closedbg,
375         };
376         ModBasketgroup($basketgroup);
377         if($closedbg){
378 # FIXME
379         }
380     }else{
381     # we create a new basketgroup (whith a closed basket)
382         $basketgroup = {
383             name              => $basketgroupname,
384             booksellerid      => $booksellerid,
385             basketlist        => \@baskets,
386             billingplace      => $billingplace,
387             deliveryplace     => $deliveryplace,
388             freedeliveryplace => $freedeliveryplace,
389             deliverycomment   => $deliverycomment,
390             closed            => $closedbg,
391         };
392         $basketgroupid = NewBasketgroup($basketgroup);
393     }
394     my $redirectpath = ((defined $input->param('mode')) && ($input->param('mode') eq 'singlebg')) ?'/cgi-bin/koha/acqui/basketgroup.pl?op=add&amp;basketgroupid='.$basketgroupid.'&amp;booksellerid='.$booksellerid : '/cgi-bin/koha/acqui/basketgroup.pl?booksellerid=' . $booksellerid;
395     $redirectpath .=  "&amp;listclosed=1" if $closedbg ;
396     print $input->redirect($redirectpath );
397     
398 }else{
399 # no param : display the list of all basketgroups for a given vendor
400     my $basketgroups = &GetBasketgroups($booksellerid);
401     my $bookseller = &GetBookSellerFromId($booksellerid);
402     my $baskets = &GetBasketsByBookseller($booksellerid);
403
404     displaybasketgroups($basketgroups, $bookseller, $baskets);
405 }
406 $template->param(listclosed => ((defined $input->param('listclosed')) && ($input->param('listclosed') eq '1'))? 1:0 );
407 #prolly won't use all these, maybe just use print, the rest can be done inside validate
408 output_html_with_http_headers $input, $cookie, $template->output;