Bug 10573: French translation for printing a basketgroup
[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.
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 parseinputbaskets {
74     my $booksellerid = shift;
75     my $baskets = &GetBasketsByBookseller($booksellerid);
76     for(my $i=0; $i < scalar @$baskets; ++$i) {
77         if( @$baskets[$i] && ! @$baskets[$i]->{'closedate'} ) {
78             splice(@$baskets, $i, 1);
79             --$i;
80         }
81     }
82     foreach my $basket (@$baskets){
83 #perl DBI uses value "undef" for the mysql "NULL" value, so i need to check everywhere where $basket->{'basketgroupid'} is used for undef ☹
84         $basket->{'basketgroupid'} = $input->param($basket->{'basketno'}.'-group') || undef;
85     }
86     return $baskets;
87 }
88
89
90
91 sub parseinputbasketgroups {
92     my $booksellerid = shift;
93     my $baskets = shift;
94     my $basketgroups = &GetBasketgroups($booksellerid);
95     my $newbasketgroups;
96     foreach my $basket (@$baskets){
97         my $basketgroup;
98         my $i = 0;
99         my $exists;
100         if(! $basket->{'basketgroupid'} || $basket->{'basketgroupid'} == 0){
101             $exists = "true";
102         } else {
103             foreach my $basketgroup (@$basketgroups){
104                 if($basket->{'basketgroupid'} == $basketgroup->{'id'}){
105                     $exists = "true";
106                     push(@{$basketgroup->{'basketlist'}}, $basket->{'basketno'});
107                     last;
108                 }
109             }
110         }
111         if (! $exists){
112 #if the basketgroup doesn't exist yet
113             $basketgroup = $newbasketgroups->{$basket->{'basketgroupid'}} || undef;
114             $basketgroup->{'booksellerid'} = $booksellerid;
115         } else {
116             while($i < scalar @$basketgroups && @$basketgroups[$i]->{'id'} != $basket->{'basketgroupid'}){
117                 ++$i;
118             }
119             $basketgroup = @$basketgroups[$i];
120         }
121         $basketgroup->{'id'}=$basket->{'basketgroupid'};
122         $basketgroup->{'name'}=$input->param('basketgroup-'.$basketgroup->{'id'}.'-name') || "";
123         $basketgroup->{'closed'}= $input->param('basketgroup-'.$basketgroup->{'id'}.'-closed');
124         push(@{$basketgroup->{'basketlist'}}, $basket->{'basketno'});
125         if (! $exists){
126             $newbasketgroups->{$basket->{'basketgroupid'}} = $basketgroup;
127         } else {
128             if($basketgroup->{'id'}){
129                 @$basketgroups[$i] = $basketgroup;
130             }
131         }
132     }
133     return($basketgroups, $newbasketgroups);
134 }
135
136 sub BasketTotal {
137     my $basketno = shift;
138     my $bookseller = shift;
139     my $total = 0;
140     my @orders = GetOrders($basketno);
141     for my $order (@orders){
142         $total = $total + ( $order->{ecost} * $order->{quantity} );
143         if ($bookseller->{invoiceincgst} && ! $bookseller->{listincgst} && ( $bookseller->{gstrate} // C4::Context->preference("gist") )) {
144             my $gst = $bookseller->{gstrate} // C4::Context->preference("gist");
145             $total = $total * ( $gst / 100 +1);
146         }
147     }
148     $total .= $bookseller->{invoiceprice};
149     return $total;
150 }
151
152 #displays all basketgroups and all closed baskets (in their respective groups)
153 sub displaybasketgroups {
154     my $basketgroups = shift;
155     my $bookseller = shift;
156     my $baskets = shift;
157     if (scalar @$basketgroups != 0) {
158         foreach my $basketgroup (@$basketgroups){
159             my $i = 0;
160             my $basketsqty = 0;
161             while($i < scalar(@$baskets)){
162                 my $basket = @$baskets[$i];
163                 if($basket->{'basketgroupid'} && $basket->{'basketgroupid'} == $basketgroup->{'id'}){
164                     $basket->{total} = BasketTotal($basket->{basketno}, $bookseller);
165                     push(@{$basketgroup->{'baskets'}}, $basket);
166                     splice(@$baskets, $i, 1);
167                     ++$basketsqty;
168                     --$i;
169                 }
170                 ++$i;
171             }
172             $basketgroup -> {'basketsqty'} = $basketsqty;
173         }
174         $template->param(basketgroups => $basketgroups);
175     }
176     for(my $i=0; $i < scalar @$baskets; ++$i) {
177         if( ! @$baskets[$i]->{'closedate'} ) {
178             splice(@$baskets, $i, 1);
179             --$i;
180         }else{
181             @$baskets[$i]->{total} = BasketTotal(@$baskets[$i]->{basketno}, $bookseller);
182         }
183     }
184     $template->param(baskets => $baskets);
185     $template->param( booksellername => $bookseller ->{'name'});
186 }
187
188 sub printbasketgrouppdf{
189     my ($basketgroupid) = @_;
190     
191     my $pdfformat = C4::Context->preference("OrderPdfFormat");
192     if ($pdfformat eq 'pdfformat::layout3pages' || $pdfformat eq 'pdfformat::layout2pages' || $pdfformat eq 'pdfformat::layout3pagesfr'){
193         eval {
194         eval "require $pdfformat";
195             import $pdfformat;
196         };
197         if ($@){
198         }
199     }
200     else {
201         print $input->header;  
202         print $input->start_html;  # FIXME Should do a nicer page
203         print "<h1>Invalid PDF Format set</h1>";
204         print "Please go to the systempreferences and set a valid pdfformat";
205         exit;
206     }
207     
208     my $basketgroup = GetBasketgroup($basketgroupid);
209     my $bookseller = GetBookSellerFromId($basketgroup->{'booksellerid'});
210     my $baskets = GetBasketsByBasketgroup($basketgroupid);
211     
212     my %orders;
213     for my $basket (@$baskets) {
214         my @ba_orders;
215         my @ords = &GetOrders($basket->{basketno});
216         for my $ord (@ords) {
217
218             next unless ( $ord->{biblionumber} or $ord->{quantity}> 0 );
219             eval {
220                 require C4::Biblio;
221                 import C4::Biblio;
222             };
223             if ($@){
224                 croak $@;
225             }
226             eval {
227                 require C4::Koha;
228                 import C4::Koha;
229             };
230             if ($@){
231                 croak $@;
232             }
233
234             $ord->{rrp} = ConvertCurrency( $ord->{'currency'}, $ord->{rrp} );
235             if ( $bookseller->{'listincgst'} ) {
236                 $ord->{rrpgsti} = sprintf( "%.2f", $ord->{rrp} );
237                 $ord->{gstgsti} = sprintf( "%.2f", $ord->{gstrate} * 100 );
238                 $ord->{rrpgste} = sprintf( "%.2f", $ord->{rrp} / ( 1 + ( $ord->{gstgsti} / 100 ) ) );
239                 $ord->{gstgste} = sprintf( "%.2f", $ord->{gstgsti} / ( 1 + ( $ord->{gstgsti} / 100 ) ) );
240                 $ord->{ecostgsti} = sprintf( "%.2f", $ord->{ecost} );
241                 $ord->{ecostgste} = sprintf( "%.2f", $ord->{ecost} / ( 1 + ( $ord->{gstgsti} / 100 ) ) );
242                 $ord->{gstvalue} = sprintf( "%.2f", ( $ord->{ecostgsti} - $ord->{ecostgste} ) * $ord->{quantity});
243                 $ord->{totalgste} = sprintf( "%.2f", $ord->{quantity} * $ord->{ecostgste} );
244                 $ord->{totalgsti} = sprintf( "%.2f", $ord->{quantity} * $ord->{ecostgsti} );
245             } else {
246                 $ord->{rrpgsti} = sprintf( "%.2f", $ord->{rrp} * ( 1 + ( $ord->{gstrate} ) ) );
247                 $ord->{rrpgste} = sprintf( "%.2f", $ord->{rrp} );
248                 $ord->{gstgsti} = sprintf( "%.2f", $ord->{gstrate} * 100 );
249                 $ord->{gstgste} = sprintf( "%.2f", $ord->{gstrate} * 100 );
250                 $ord->{ecostgsti} = sprintf( "%.2f", $ord->{ecost} * ( 1 + ( $ord->{gstrate} ) ) );
251                 $ord->{ecostgste} = sprintf( "%.2f", $ord->{ecost} );
252                 $ord->{gstvalue} = sprintf( "%.2f", ( $ord->{ecostgsti} - $ord->{ecostgste} ) * $ord->{quantity});
253                 $ord->{totalgste} = sprintf( "%.2f", $ord->{quantity} * $ord->{ecostgste} );
254                 $ord->{totalgsti} = sprintf( "%.2f", $ord->{quantity} * $ord->{ecostgsti} );
255             }
256             my $bib = GetBiblioData($ord->{biblionumber});
257             my $itemtypes = GetItemTypes();
258
259             #FIXME DELETE ME
260             # 0      1        2        3         4            5         6       7      8        9
261             #isbn, itemtype, author, title, publishercode, quantity, listprice ecost discount gstrate
262
263             # Editor Number
264             my $en;
265             my $marcrecord=eval{MARC::Record::new_from_xml( $ord->{marcxml},'UTF-8' )};
266             if ($marcrecord){
267                 if ( C4::Context->preference("marcflavour") eq 'UNIMARC' ) {
268                     $en = $marcrecord->subfield( '345', "b" );
269                 } elsif ( C4::Context->preference("marcflavour") eq 'MARC21' ) {
270                     $en = $marcrecord->subfield( '037', "a" );
271                 }
272             }
273
274             my $ba_order = {
275                 isbn => ($ord->{isbn} ? $ord->{isbn} : undef),
276                 itemtype => ( $ord->{itemtype} and $bib->{itemtype} ? $itemtypes->{$bib->{itemtype}}->{description} : undef ),
277                 en => ( $en ? $en : undef ),
278             };
279             for my $key ( qw/ gstrate author title itemtype publishercode discount quantity rrpgsti rrpgste gstgsti gstgste ecostgsti ecostgste gstvalue totalgste totalgsti / ) {
280                 $ba_order->{$key} = $ord->{$key};
281             }
282
283             push(@ba_orders, $ba_order);
284         }
285         $orders{$basket->{basketno}} = \@ba_orders;
286     }
287     print $input->header(
288         -type       => 'application/pdf',
289         -attachment => ( $basketgroup->{name} || $basketgroupid ) . '.pdf'
290     );
291     my $pdf = printpdf($basketgroup, $bookseller, $baskets, \%orders, $bookseller->{gstrate} // C4::Context->preference("gist")) || die "pdf generation failed";
292     print $pdf;
293
294 }
295
296 my $op = $input->param('op') || 'display';
297 my $booksellerid = $input->param('booksellerid');
298 $template->param(booksellerid => $booksellerid);
299
300 if ( $op eq "add" ) {
301     if(! $booksellerid){
302         $template->param( ungroupedlist => 1);
303         my @booksellers = GetBookSeller('');
304        for (my $i=0; $i < scalar @booksellers; $i++) {
305             my $baskets = &GetBasketsByBookseller($booksellers[$i]->{id});
306             for (my $j=0; $j < scalar @$baskets; $j++) {
307                 if(! @$baskets[$i]->{closedate} || @$baskets[$i]->{basketgroupid}) {
308                     splice(@$baskets, $j, 1);
309                     $j--;
310                 }
311             }
312             if (scalar @$baskets == 0){
313                 splice(@booksellers, $i, 1);
314                 $i--;
315             }
316         }
317     } else {
318         my $basketgroupid = $input->param('basketgroupid');
319         my $billingplace;
320         my $deliveryplace;
321         my $freedeliveryplace;
322         if ( $basketgroupid ) {
323             # Get the selected baskets in the basketgroup to display them
324             my $selecteds = GetBasketsByBasketgroup($basketgroupid);
325             foreach (@{$selecteds}){
326                 $_->{total} = BasketTotal($_->{basketno}, $_);
327             }
328             $template->param(basketgroupid => $basketgroupid,
329                              selectedbaskets => $selecteds);
330
331             # Get general informations about the basket group to prefill the form
332             my $basketgroup = GetBasketgroup($basketgroupid);
333             $template->param(
334                 name            => $basketgroup->{name},
335                 deliverycomment => $basketgroup->{deliverycomment},
336                 freedeliveryplace => $basketgroup->{freedeliveryplace},
337             );
338             $billingplace  = $basketgroup->{billingplace};
339             $deliveryplace = $basketgroup->{deliveryplace};
340             $freedeliveryplace = $basketgroup->{freedeliveryplace};
341         }
342
343         # determine default billing and delivery places depending on librarian homebranch and existing basketgroup data
344         my $borrower = GetMember( ( 'borrowernumber' => $loggedinuser ) );
345         $billingplace  = $billingplace  || $borrower->{'branchcode'};
346         $deliveryplace = $deliveryplace || $borrower->{'branchcode'};
347
348         my $branches = C4::Branch::GetBranchesLoop( $billingplace );
349         $template->param( billingplaceloop => $branches );
350         $branches = C4::Branch::GetBranchesLoop( $deliveryplace );
351         $template->param( deliveryplaceloop => $branches );
352
353         $template->param( booksellerid => $booksellerid );
354     }
355     $template->param(grouping => 1);
356     my $basketgroups = &GetBasketgroups($booksellerid);
357     my $bookseller = &GetBookSellerFromId($booksellerid);
358     my $baskets = &GetBasketsByBookseller($booksellerid);
359
360     displaybasketgroups($basketgroups, $bookseller, $baskets);
361 } elsif ($op eq 'mod_basket') {
362 #we want to modify an individual basket's group
363   my $basketno=$input->param('basketno');
364   my $basketgroupid=$input->param('basketgroupid');
365   ModBasket( { basketno => $basketno,
366                          basketgroupid => $basketgroupid } );
367   print $input->redirect("basket.pl?basketno=" . $basketno);
368 } elsif ($op eq 'validate') {
369     if(! $booksellerid){
370         $template->param( booksellererror => 1);
371     } else {
372         $template->param( booksellerid => $booksellerid );
373     }
374     my $baskets = parseinputbaskets($booksellerid);
375     my ($basketgroups, $newbasketgroups) = parseinputbasketgroups($booksellerid, $baskets);
376     foreach my $nbgid (keys %$newbasketgroups){
377 #javascript just picks an ID that's higher than anything else, the ID might not be correct..chenge it and change all the basket's basketgroupid as well
378         my $bgid = NewBasketgroup($newbasketgroups->{$nbgid});
379         ${$newbasketgroups->{$nbgid}}->{'id'} = $bgid;
380         ${$newbasketgroups->{$nbgid}}->{'oldid'} = $nbgid;
381     }
382     foreach my $basket (@$baskets){
383 #if the basket was added to a new basketgroup, first change the groupid to the groupid of the basket in mysql, because it contains the id from javascript otherwise.
384         if ( $basket->{'basketgroupid'} && $newbasketgroups->{$basket->{'basketgroupid'}} ){
385             $basket->{'basketgroupid'} = ${$newbasketgroups->{$basket->{'basketgroupid'}}}->{'id'};
386         }
387         ModBasket($basket);
388     }
389     foreach my $basketgroup (@$basketgroups){
390         if(! $basketgroup->{'id'}){
391             foreach my $basket (@{$basketgroup->{'baskets'}}){
392                 if($input->param('basket'.$basket->{'basketno'}.'changed')){
393                     ModBasket($basket);
394                 }
395             }
396         } elsif ($input->param('basketgroup-'.$basketgroup->{'id'}.'-changed')){
397             ModBasketgroup($basketgroup);
398         }
399     }
400     $basketgroups = &GetBasketgroups($booksellerid);
401     my $bookseller = &GetBookSellerFromId($booksellerid);
402     $baskets = &GetBasketsByBookseller($booksellerid);
403
404     displaybasketgroups($basketgroups, $bookseller, $baskets);
405 } elsif ( $op eq 'closeandprint') {
406     my $basketgroupid = $input->param('basketgroupid');
407     
408     CloseBasketgroup($basketgroupid);
409     
410     printbasketgrouppdf($basketgroupid);
411     exit;
412 }elsif ($op eq 'print'){
413     my $basketgroupid = $input->param('basketgroupid');
414     
415     printbasketgrouppdf($basketgroupid);
416     exit;
417 }elsif ( $op eq "export" ) {
418     my $basketgroupid = $input->param('basketgroupid');
419     print $input->header(
420         -type       => 'text/csv',
421         -attachment => 'basketgroup' . $basketgroupid . '.csv',
422     );
423     print GetBasketGroupAsCSV( $basketgroupid, $input );
424     exit;
425 }elsif( $op eq "delete"){
426     my $basketgroupid = $input->param('basketgroupid');
427     DelBasketgroup($basketgroupid);
428     print $input->redirect('/cgi-bin/koha/acqui/basketgroup.pl?booksellerid=' . $booksellerid);
429     
430 }elsif ( $op eq 'reopen'){
431     my $basketgroupid   = $input->param('basketgroupid');
432     my $booksellerid    = $input->param('booksellerid');
433     
434     ReOpenBasketgroup($basketgroupid);
435         
436     print $input->redirect('/cgi-bin/koha/acqui/basketgroup.pl?booksellerid=' . $booksellerid . '#closed');
437     
438 } elsif ( $op eq 'attachbasket') {
439     
440     # Getting parameters
441     my $basketgroup       = {};
442     my @baskets           = $input->param('basket');
443     my $basketgroupid     = $input->param('basketgroupid');
444     my $basketgroupname   = $input->param('basketgroupname');
445     my $booksellerid      = $input->param('booksellerid');
446     my $billingplace      = $input->param('billingplace');
447     my $deliveryplace     = $input->param('deliveryplace');
448     my $freedeliveryplace = $input->param('freedeliveryplace');
449     my $deliverycomment   = $input->param('deliverycomment');
450     my $close             = $input->param('close') ? 1 : 0;
451     # If we got a basketgroupname, we create a basketgroup
452     if ($basketgroupid) {
453         $basketgroup = {
454               name              => $basketgroupname,
455               id                => $basketgroupid,
456               basketlist        => \@baskets,
457               billingplace      => $billingplace,
458               deliveryplace     => $deliveryplace,
459               freedeliveryplace => $freedeliveryplace,
460               deliverycomment   => $deliverycomment,
461               closed            => $close,
462         };
463         ModBasketgroup($basketgroup);
464         if($close){
465             
466         }
467     }else{
468         $basketgroup = {
469             name              => $basketgroupname,
470             booksellerid      => $booksellerid,
471             basketlist        => \@baskets,
472             billingplace      => $billingplace,
473             deliveryplace     => $deliveryplace,
474             freedeliveryplace => $freedeliveryplace,
475             deliverycomment   => $deliverycomment,
476             closed            => $close,
477         };
478         $basketgroupid = NewBasketgroup($basketgroup);
479     }
480    
481     my $url = '/cgi-bin/koha/acqui/basketgroup.pl?booksellerid=' . $booksellerid;
482     $url .= "&closed=1" if ($input->param("closed")); 
483     print $input->redirect($url);
484     
485 }else{
486     my $basketgroups = &GetBasketgroups($booksellerid);
487     my $bookseller = &GetBookSellerFromId($booksellerid);
488     my $baskets = &GetBasketsByBookseller($booksellerid);
489
490     displaybasketgroups($basketgroups, $bookseller, $baskets);
491 }
492 $template->param(closed => $input->param("closed"));
493 #prolly won't use all these, maybe just use print, the rest can be done inside validate
494 output_html_with_http_headers $input, $cookie, $template->output;