Merge remote branch 'kc/new/for-3.4/spelling' into kcmaster
[wip/koha-chris_n.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 #
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
24 =head1 NAME
25
26 basketgroup.pl
27
28 =head1 DESCRIPTION
29
30  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
31  have to be closed.
32
33 =head1 CGI PARAMETERS
34
35 =over 4
36
37 =item $booksellerid
38
39 The bookseller who we want to display the baskets (and basketgroups) of.
40
41 =back
42
43 =cut
44
45 use strict;
46 use warnings;
47
48 use C4::Input;
49 use C4::Auth;
50 use C4::Output;
51 use CGI;
52
53 use C4::Bookseller qw/GetBookSellerFromId/;
54 use C4::Acquisition qw/CloseBasketgroup ReOpenBasketgroup GetOrders GetBasketsByBasketgroup GetBasketsByBookseller ModBasketgroup NewBasketgroup DelBasketgroup GetBasketgroups ModBasket GetBasketgroup GetBasket/;
55 use C4::Bookseller qw/GetBookSellerFromId/;
56 use C4::Branch qw/GetBranches/;
57 use C4::Members qw/GetMember/;
58
59 my $input=new CGI;
60
61 my ($template, $loggedinuser, $cookie)
62     = get_template_and_user({template_name => "acqui/basketgroup.tmpl",
63                              query => $input,
64                              type => "intranet",
65                              authnotrequired => 0,
66                              flagsrequired => {acquisition => 'group_manage'},
67                              debug => 1,
68                 });
69
70 sub parseinputbaskets {
71     my $booksellerid = shift;
72     my $baskets = &GetBasketsByBookseller($booksellerid);
73     for(my $i=0; $i < scalar @$baskets; ++$i) {
74         if( @$baskets[$i] && ! @$baskets[$i]->{'closedate'} ) {
75             splice(@$baskets, $i, 1);
76             --$i;
77         }
78     }
79     foreach my $basket (@$baskets){
80 #perl DBI uses value "undef" for the mysql "NULL" value, so i need to check everywhere where $basket->{'basketgroupid'} is used for undef ☹
81         $basket->{'basketgroupid'} = $input->param($basket->{'basketno'}.'-group') || undef;
82     }
83     return $baskets;
84 }
85
86
87
88 sub parseinputbasketgroups {
89     my $booksellerid = shift;
90     my $baskets = shift;
91     my $basketgroups = &GetBasketgroups($booksellerid);
92     my $newbasketgroups;
93     foreach my $basket (@$baskets){
94         my $basketgroup;
95         my $i = 0;
96         my $exists;
97         if(! $basket->{'basketgroupid'} || $basket->{'basketgroupid'} == 0){
98             $exists = "true";
99         } else {
100             foreach my $basketgroup (@$basketgroups){
101                 if($basket->{'basketgroupid'} == $basketgroup->{'id'}){
102                     $exists = "true";
103                     push(@{$basketgroup->{'basketlist'}}, $basket->{'basketno'});
104                     last;
105                 }
106             }
107         }
108         if (! $exists){
109 #if the basketgroup doesn't exist yet
110             $basketgroup = $newbasketgroups->{$basket->{'basketgroupid'}} || undef;
111             $basketgroup->{'booksellerid'} = $booksellerid;
112         } else {
113             while($i < scalar @$basketgroups && @$basketgroups[$i]->{'id'} != $basket->{'basketgroupid'}){
114                 ++$i;
115             }
116             $basketgroup = @$basketgroups[$i];
117         }
118         $basketgroup->{'id'}=$basket->{'basketgroupid'};
119         $basketgroup->{'name'}=$input->param('basketgroup-'.$basketgroup->{'id'}.'-name') || "";
120         $basketgroup->{'closed'}= $input->param('basketgroup-'.$basketgroup->{'id'}.'-closed');
121         push(@{$basketgroup->{'basketlist'}}, $basket->{'basketno'});
122         if (! $exists){
123             $newbasketgroups->{$basket->{'basketgroupid'}} = $basketgroup;
124         } else {
125             if($basketgroup->{'id'}){
126                 @$basketgroups[$i] = $basketgroup;
127             }
128         }
129     }
130     return($basketgroups, $newbasketgroups);
131 }
132
133 sub BasketTotal {
134     my $basketno = shift;
135     my $bookseller = shift;
136     my $total = 0;
137     my @orders = GetOrders($basketno);
138     for my $order (@orders){
139         $total = $total + ( $order->{ecost} * $order->{quantity} );
140         if ($bookseller->{invoiceincgst} && ! $bookseller->{listincgst} && ( $bookseller->{gstrate} || C4::Context->preference("gist") )) {
141             my $gst = $bookseller->{gstrate} || C4::Context->preference("gist");
142             $total = $total * ( $gst / 100 +1);
143         }
144     }
145     $total .= $bookseller->{invoiceprice};
146     return $total;
147 }
148
149 #displays all basketgroups and all closed baskets (in their respective groups)
150 sub displaybasketgroups {
151     my $basketgroups = shift;
152     my $bookseller = shift;
153     my $baskets = shift;
154     if (scalar @$basketgroups != 0) {
155         foreach my $basketgroup (@$basketgroups){
156             my $i = 0;
157             while($i < scalar(@$baskets)){
158                 my $basket = @$baskets[$i];
159                 if($basket->{'basketgroupid'} && $basket->{'basketgroupid'} == $basketgroup->{'id'}){
160                     $basket->{total} = BasketTotal($basket->{basketno}, $bookseller);
161                     push(@{$basketgroup->{'baskets'}}, $basket);
162                     splice(@$baskets, $i, 1);
163                     --$i;
164                 }
165                 ++$i;
166             }
167         }
168         $template->param(basketgroups => $basketgroups);
169     }
170     for(my $i=0; $i < scalar @$baskets; ++$i) {
171         if( ! @$baskets[$i]->{'closedate'} ) {
172             splice(@$baskets, $i, 1);
173             --$i;
174         }else{
175             @$baskets[$i]->{total} = BasketTotal(@$baskets[$i]->{basketno}, $bookseller);
176         }
177     }
178     $template->param(baskets => $baskets);
179     $template->param( booksellername => $bookseller ->{'name'});
180 }
181
182 sub printbasketgrouppdf{
183     my ($basketgroupid) = @_;
184     
185     my $pdfformat = C4::Context->preference("OrderPdfFormat");
186     eval "use $pdfformat" ;
187     eval "use C4::Branch";
188     
189     my $basketgroup = GetBasketgroup($basketgroupid);
190     my $bookseller = GetBookSellerFromId($basketgroup->{'booksellerid'});
191     my $baskets = GetBasketsByBasketgroup($basketgroupid);
192     
193     my %orders;
194     for my $basket (@$baskets) {
195         my @ba_orders;
196         my @ords = &GetOrders($basket->{basketno});
197         for my $ord (@ords) {
198             # ba_order is filled with : 
199             # 0      1        2        3         4            5         6       7      8        9
200             #isbn, itemtype, author, title, publishercode, quantity, listprice ecost discount gstrate
201             my @ba_order;
202             if ( $ord->{biblionumber} && $ord->{quantity}> 0 ) {
203                 eval "use C4::Biblio";
204                 eval "use C4::Koha";
205                 my $bib = GetBiblioData($ord->{biblionumber});
206                 my $itemtypes = GetItemTypes();
207                 if($ord->{isbn}){
208                     push(@ba_order, $ord->{isbn});
209                 } else {
210                     push(@ba_order, undef);
211                 }
212                 if ($ord->{itemtype}){
213                     push(@ba_order, $itemtypes->{$bib->{itemtype}}->{description}) if $bib->{itemtype};
214                 } else {
215                     push(@ba_order, undef);
216                 }
217 #             } else {
218 #                 push(@ba_order, undef, undef);
219                 for my $key (qw/author title publishercode quantity listprice ecost/) {
220                     push(@ba_order, $ord->{$key});                                                  #Order lines
221                 }
222                 push(@ba_order, $bookseller->{discount});
223                 push(@ba_order, $bookseller->{gstrate}*100 || C4::Context->preference("gist") || 0);
224                 push(@ba_orders, \@ba_order);
225                 # Editor Number
226                 my $en;
227                 if (C4::Context->preference("marcflavour") eq 'UNIMARC') {
228                     $en = MARC::Record::new_from_xml($ord->{marcxml},'UTF-8')->subfield('345',"b");
229                 } elsif (C4::Context->preference("marcflavour") eq 'MARC21') {
230                     $en = MARC::Record::new_from_xml($ord->{marcxml},'UTF-8')->subfield('037',"a");
231                 }
232                 if($en){
233                     push(@ba_order, $en);
234                 } else {
235                     push(@ba_order, undef);
236                 }
237             }
238         }
239         $orders{$basket->{basketno}}=\@ba_orders;
240     }
241     print $input->header(
242         -type       => 'application/pdf',
243         -attachment => ( $basketgroup->{name} || $basketgroupid ) . '.pdf'
244     );
245     my $pdf = printpdf($basketgroup, $bookseller, $baskets, \%orders, $bookseller->{gstrate} || C4::Context->preference("gist")) || die "pdf generation failed";
246     print $pdf;
247     exit;
248 }
249
250 my $op = $input->param('op');
251 my $booksellerid = $input->param('booksellerid');
252 $template->param(booksellerid => $booksellerid);
253
254 if ( $op eq "add" ) {
255     if(! $booksellerid){
256         $template->param( ungroupedlist => 1);
257         my @booksellers = GetBookSeller('');
258        for (my $i=0; $i < scalar @booksellers; $i++) {
259             my $baskets = &GetBasketsByBookseller($booksellers[$i]->{id});
260             for (my $j=0; $j < scalar @$baskets; $j++) {
261                 if(! @$baskets[$i]->{closedate} || @$baskets[$i]->{basketgroupid}) {
262                     splice(@$baskets, $j, 1);
263                     $j--;
264                 }
265             }
266             if (scalar @$baskets == 0){
267                 splice(@booksellers, $i, 1);
268                 $i--;
269             }
270         }
271     } else {
272         my $basketgroupid = $input->param('basketgroupid');
273         my $billingplace;
274         my $deliveryplace;
275         if ( $basketgroupid ) {
276             # Get the selected baskets in the basketgroup to display them
277             my $selecteds = GetBasketsByBasketgroup($basketgroupid);
278             foreach (@{$selecteds}){
279                 $_->{total} = BasketTotal($_->{basketno}, $_);
280             }
281             $template->param(basketgroupid => $basketgroupid,
282                              selectedbaskets => $selecteds);
283
284             # Get general informations about the basket group to prefill the form
285             my $basketgroup = GetBasketgroup($basketgroupid);
286             $template->param(
287                 name            => $basketgroup->{name},
288                 deliverycomment => $basketgroup->{deliverycomment},
289             );
290             $billingplace  = $basketgroup->{billingplace};
291             $deliveryplace = $basketgroup->{deliveryplace};
292         }
293
294         # determine default billing and delivery places depending on librarian homebranch and existing basketgroup data
295         my $borrower = GetMember( ( 'borrowernumber' => $loggedinuser ) );
296         $billingplace  = $billingplace  || $borrower->{'branchcode'};
297         $deliveryplace = $deliveryplace || $borrower->{'branchcode'};
298         
299         my $branches = GetBranches;
300         
301         # Build the combobox to select the billing place
302         my @billingplaceloop;
303         for (sort keys %$branches) {
304             my $selected = 1 if $_ eq $billingplace;
305             my %row = (
306                 value      => $_,
307                 selected   => $selected,
308                 branchname => $branches->{$_}->{branchname},
309             );
310             push @billingplaceloop, \%row;
311         }
312         $template->param( billingplaceloop => \@billingplaceloop );
313         
314         # Build the combobox to select the delivery place
315         my @deliveryplaceloop;
316         for (sort keys %$branches) {
317             my $selected = 1 if $_ eq $deliveryplace;
318             my %row = (
319                 value      => $_,
320                 selected   => $selected,
321                 branchname => $branches->{$_}->{branchname},
322             );
323             push @deliveryplaceloop, \%row;
324         }
325         $template->param( deliveryplaceloop => \@deliveryplaceloop );
326
327         $template->param( booksellerid => $booksellerid );
328     }
329     $template->param(grouping => 1);
330     my $basketgroups = &GetBasketgroups($booksellerid);
331     my $bookseller = &GetBookSellerFromId($booksellerid);
332     my $baskets = &GetBasketsByBookseller($booksellerid);
333
334     displaybasketgroups($basketgroups, $bookseller, $baskets);
335 } elsif ($op eq 'mod_basket') {
336 #we want to modify an individual basket's group
337   my $basketno=$input->param('basketno');
338   my $basketgroupid=$input->param('basketgroupid');
339   ModBasket( { basketno => $basketno,
340                          basketgroupid => $basketgroupid } );
341   print $input->redirect("basket.pl?basketno=" . $basketno);
342 } elsif ($op eq 'validate') {
343     if(! $booksellerid){
344         $template->param( booksellererror => 1);
345     } else {
346         $template->param( booksellerid => $booksellerid );
347     }
348     my $baskets = parseinputbaskets($booksellerid);
349     my ($basketgroups, $newbasketgroups) = parseinputbasketgroups($booksellerid, $baskets);
350     foreach my $nbgid (keys %$newbasketgroups){
351 #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
352         my $bgid = NewBasketgroup($newbasketgroups->{$nbgid});
353         ${$newbasketgroups->{$nbgid}}->{'id'} = $bgid;
354         ${$newbasketgroups->{$nbgid}}->{'oldid'} = $nbgid;
355     }
356     foreach my $basket (@$baskets){
357 #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.
358         if ( $basket->{'basketgroupid'} && $newbasketgroups->{$basket->{'basketgroupid'}} ){
359             $basket->{'basketgroupid'} = ${$newbasketgroups->{$basket->{'basketgroupid'}}}->{'id'};
360         }
361         ModBasket($basket);
362     }
363     foreach my $basketgroup (@$basketgroups){
364         if(! $basketgroup->{'id'}){
365             foreach my $basket (@{$basketgroup->{'baskets'}}){
366                 if($input->param('basket'.$basket->{'basketno'}.'changed')){
367                     ModBasket($basket);
368                 }
369             }
370         } elsif ($input->param('basketgroup-'.$basketgroup->{'id'}.'-changed')){
371             ModBasketgroup($basketgroup);
372         }
373     }
374     $basketgroups = &GetBasketgroups($booksellerid);
375     my $bookseller = &GetBookSellerFromId($booksellerid);
376     $baskets = &GetBasketsByBookseller($booksellerid);
377
378     displaybasketgroups($basketgroups, $bookseller, $baskets);
379 } elsif ( $op eq 'closeandprint') {
380     my $basketgroupid = $input->param('basketgroupid');
381     
382     CloseBasketgroup($basketgroupid);
383     
384     printbasketgrouppdf($basketgroupid);
385 }elsif ($op eq 'print'){
386     my $basketgroupid = $input->param('basketgroupid');
387     
388     printbasketgrouppdf($basketgroupid);
389 }elsif( $op eq "delete"){
390     my $basketgroupid = $input->param('basketgroupid');
391     DelBasketgroup($basketgroupid);
392     print $input->redirect('/cgi-bin/koha/acqui/basketgroup.pl?booksellerid=' . $booksellerid);
393     
394 }elsif ( $op eq 'reopen'){
395     my $basketgroupid   = $input->param('basketgroupid');
396     my $booksellerid    = $input->param('booksellerid');
397     
398     ReOpenBasketgroup($basketgroupid);
399         
400     print $input->redirect('/cgi-bin/koha/acqui/basketgroup.pl?booksellerid=' . $booksellerid . '#closed');
401     
402 } elsif ( $op eq 'attachbasket') {
403     
404     # Getting parameters
405     my $basketgroup = {};
406     my @baskets         = $input->param('basket');
407     my $basketgroupid   = $input->param('basketgroupid');
408     my $basketgroupname = $input->param('basketgroupname');
409     my $booksellerid    = $input->param('booksellerid');
410     my $billingplace    = $input->param('billingplace');
411     my $deliveryplace   = $input->param('deliveryplace');
412     my $deliverycomment = $input->param('deliverycomment');
413     my $close           = $input->param('close') ? 1 : 0;
414     # If we got a basketgroupname, we create a basketgroup
415     if ($basketgroupid) {
416         $basketgroup = {
417               name            => $basketgroupname,
418               id              => $basketgroupid,
419               basketlist      => \@baskets,
420               billingplace    => $billingplace,
421               deliveryplace   => $deliveryplace,
422               deliverycomment => $deliverycomment,
423               closed          => $close,
424         };
425         ModBasketgroup($basketgroup);
426         if($close){
427             
428         }
429     }else{
430         $basketgroup = {
431             name            => $basketgroupname,
432             booksellerid    => $booksellerid,
433             basketlist      => \@baskets,
434             deliveryplace   => $deliveryplace,
435             deliverycomment => $deliverycomment,
436             closed          => $close,
437         };
438         $basketgroupid = NewBasketgroup($basketgroup);
439     }
440    
441     my $url = '/cgi-bin/koha/acqui/basketgroup.pl?booksellerid=' . $booksellerid;
442     $url .= "&closed=1" if ($input->param("closed")); 
443     print $input->redirect($url);
444     
445 }else{
446     my $basketgroups = &GetBasketgroups($booksellerid);
447     my $bookseller = &GetBookSellerFromId($booksellerid);
448     my $baskets = &GetBasketsByBookseller($booksellerid);
449
450     displaybasketgroups($basketgroups, $bookseller, $baskets);
451 }
452 $template->param(closed => $input->param("closed"));
453 #prolly won't use all these, maybe just use print, the rest can be done inside validate
454 output_html_with_http_headers $input, $cookie, $template->output;