Fix FSF address in directory acqui/
[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 #
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     warn @_;
188     eval "use C4::Branch";
189     
190     my $basketgroup = GetBasketgroup($basketgroupid);
191     my $bookseller = GetBookSellerFromId($basketgroup->{'booksellerid'});
192     my $baskets = GetBasketsByBasketgroup($basketgroupid);
193     
194     my %orders;
195     for my $basket (@$baskets) {
196         my @ba_orders;
197         my @ords = &GetOrders($basket->{basketno});
198         for my $ord (@ords) {
199             # ba_order is filled with : 
200             # 0      1        2        3         4            5         6       7      8        9
201             #isbn, itemtype, author, title, publishercode, quantity, listprice ecost discount gstrate
202             my @ba_order;
203             if ( $ord->{biblionumber} && $ord->{quantity}> 0 ) {
204                 eval "use C4::Biblio";
205                 eval "use C4::Koha";
206                 my $bib = GetBiblioData($ord->{biblionumber});
207                 my $itemtypes = GetItemTypes();
208                 if($ord->{isbn}){
209                     push(@ba_order, $ord->{isbn});
210                 } else {
211                     push(@ba_order, undef);
212                 }
213                 if ($ord->{itemtype}){
214                     push(@ba_order, $itemtypes->{$bib->{itemtype}}->{description}) if $bib->{itemtype};
215                 } else {
216                     push(@ba_order, undef);
217                 }
218 #             } else {
219 #                 push(@ba_order, undef, undef);
220                 for my $key (qw/author title publishercode quantity listprice ecost/) {
221                     push(@ba_order, $ord->{$key});                                                  #Order lines
222                 }
223                 push(@ba_order, $bookseller->{discount});
224                 push(@ba_order, $bookseller->{gstrate}*100 || C4::Context->preference("gist") || 0);
225                 push(@ba_orders, \@ba_order);
226                 # Editor Number
227                 my $en;
228                 if (C4::Context->preference("marcflavour") eq 'UNIMARC') {
229                     $en = MARC::Record::new_from_xml($ord->{marcxml},'UTF-8')->subfield('345',"b");
230                 } elsif (C4::Context->preference("marcflavour") eq 'MARC21') {
231                     $en = MARC::Record::new_from_xml($ord->{marcxml},'UTF-8')->subfield('037',"a");
232                 }
233                 if($en){
234                     push(@ba_order, $en);
235                 } else {
236                     push(@ba_order, undef);
237                 }
238             }
239         }
240         %orders->{$basket->{basketno}}=\@ba_orders;
241     }
242     print $input->header( -type => 'application/pdf', -attachment => $basketgroup->{name}.'.pdf' );
243     my $pdf = printpdf($basketgroup, $bookseller, $baskets, \%orders, $bookseller->{gstrate} || C4::Context->preference("gist")) || die "pdf generation failed";
244     print $pdf;
245     exit;
246 }
247
248 my $op = $input->param('op');
249 my $booksellerid = $input->param('booksellerid');
250 $template->param(booksellerid => $booksellerid);
251
252 if ( $op eq "add" ) {
253     if(! $booksellerid){
254         $template->param( ungroupedlist => 1);
255         my @booksellers = GetBookSeller('');
256        for (my $i=0; $i < scalar @booksellers; $i++) {
257             my $baskets = &GetBasketsByBookseller($booksellers[$i]->{id});
258             for (my $j=0; $j < scalar @$baskets; $j++) {
259                 if(! @$baskets[$i]->{closedate} || @$baskets[$i]->{basketgroupid}) {
260                     splice(@$baskets, $j, 1);
261                     $j--;
262                 }
263             }
264             if (scalar @$baskets == 0){
265                 splice(@booksellers, $i, 1);
266                 $i--;
267             }
268         }
269     } else {
270         my $basketgroupid = $input->param('basketgroupid');
271         my $billingplace;
272         my $deliveryplace;
273         if ( $basketgroupid ) {
274             # Get the selected baskets in the basketgroup to display them
275             my $selecteds = GetBasketsByBasketgroup($basketgroupid);
276             foreach (@{$selecteds}){
277                 $_->{total} = BasketTotal($_->{basketno}, $_);
278             }
279             $template->param(basketgroupid => $basketgroupid,
280                              selectedbaskets => $selecteds);
281
282             # Get general informations about the basket group to prefill the form
283             my $basketgroup = GetBasketgroup($basketgroupid);
284             $template->param(
285                 name            => $basketgroup->{name},
286                 deliverycomment => $basketgroup->{deliverycomment},
287             );
288             $billingplace  = $basketgroup->{billingplace};
289             $deliveryplace = $basketgroup->{deliveryplace};
290         }
291
292         # determine default billing and delivery places depending on librarian homebranch and existing basketgroup data
293         my $borrower = GetMember( ( 'borrowernumber' => $loggedinuser ) );
294         $billingplace  = $billingplace  || $borrower->{'branchcode'};
295         $deliveryplace = $deliveryplace || $borrower->{'branchcode'};
296         
297         my $branches = GetBranches;
298         
299         # Build the combobox to select the billing place
300         my @billingplaceloop;
301         for (sort keys %$branches) {
302             my $selected = 1 if $_ eq $billingplace;
303             my %row = (
304                 value      => $_,
305                 selected   => $selected,
306                 branchname => $branches->{$_}->{branchname},
307             );
308             push @billingplaceloop, \%row;
309         }
310         $template->param( billingplaceloop => \@billingplaceloop );
311         
312         # Build the combobox to select the delivery place
313         my @deliveryplaceloop;
314         for (sort keys %$branches) {
315             my $selected = 1 if $_ eq $deliveryplace;
316             my %row = (
317                 value      => $_,
318                 selected   => $selected,
319                 branchname => $branches->{$_}->{branchname},
320             );
321             push @deliveryplaceloop, \%row;
322         }
323         $template->param( deliveryplaceloop => \@deliveryplaceloop );
324
325         $template->param( booksellerid => $booksellerid );
326     }
327     $template->param(grouping => 1);
328     my $basketgroups = &GetBasketgroups($booksellerid);
329     my $bookseller = &GetBookSellerFromId($booksellerid);
330     my $baskets = &GetBasketsByBookseller($booksellerid);
331
332     displaybasketgroups($basketgroups, $bookseller, $baskets);
333 } elsif ($op eq 'mod_basket') {
334 #we want to modify an individual basket's group
335   my $basketno=$input->param('basketno');
336   my $basketgroupid=$input->param('basketgroupid');
337   ModBasket( { basketno => $basketno,
338                          basketgroupid => $basketgroupid } );
339   print $input->redirect("basket.pl?basketno=" . $basketno);
340 } elsif ($op eq 'validate') {
341     if(! $booksellerid){
342         $template->param( booksellererror => 1);
343     } else {
344         $template->param( booksellerid => $booksellerid );
345     }
346     my $baskets = parseinputbaskets($booksellerid);
347     my ($basketgroups, $newbasketgroups) = parseinputbasketgroups($booksellerid, $baskets);
348     foreach my $nbgid (keys %$newbasketgroups){
349 #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
350         my $bgid = NewBasketgroup($newbasketgroups->{$nbgid});
351         ${$newbasketgroups->{$nbgid}}->{'id'} = $bgid;
352         ${$newbasketgroups->{$nbgid}}->{'oldid'} = $nbgid;
353     }
354     foreach my $basket (@$baskets){
355 #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.
356         if ( $basket->{'basketgroupid'} && $newbasketgroups->{$basket->{'basketgroupid'}} ){
357             $basket->{'basketgroupid'} = ${$newbasketgroups->{$basket->{'basketgroupid'}}}->{'id'};
358         }
359         ModBasket($basket);
360     }
361     foreach my $basketgroup (@$basketgroups){
362         if(! $basketgroup->{'id'}){
363             foreach my $basket (@{$basketgroup->{'baskets'}}){
364                 if($input->param('basket'.$basket->{'basketno'}.'changed')){
365                     ModBasket($basket);
366                 }
367             }
368         } elsif ($input->param('basketgroup-'.$basketgroup->{'id'}.'-changed')){
369             ModBasketgroup($basketgroup);
370         }
371     }
372     $basketgroups = &GetBasketgroups($booksellerid);
373     my $bookseller = &GetBookSellerFromId($booksellerid);
374     $baskets = &GetBasketsByBookseller($booksellerid);
375
376     displaybasketgroups($basketgroups, $bookseller, $baskets);
377 } elsif ( $op eq 'closeandprint') {
378     my $basketgroupid = $input->param('basketgroupid');
379     
380     CloseBasketgroup($basketgroupid);
381     
382     printbasketgrouppdf($basketgroupid);
383 }elsif ($op eq 'print'){
384     my $basketgroupid = $input->param('basketgroupid');
385     
386     printbasketgrouppdf($basketgroupid);
387 }elsif( $op eq "delete"){
388     my $basketgroupid = $input->param('basketgroupid');
389     warn $basketgroupid;
390     DelBasketgroup($basketgroupid);
391     warn "---------------";
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;