(bug #3622) rewrite a lot of basketgrouping
[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 with
20 # Koha; if not, write to the Free Software Foundation, Inc., 59 Temple Place,
21 # Suite 330, Boston, MA  02111-1307 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
57 my $input=new CGI;
58
59 my ($template, $loggedinuser, $cookie)
60     = get_template_and_user({template_name => "acqui/basketgroup.tmpl",
61                              query => $input,
62                              type => "intranet",
63                              authnotrequired => 0,
64                              flagsrequired => {acquisition => 'group_manage'},
65                              debug => 1,
66                 });
67
68 sub parseinputbaskets {
69     my $booksellerid = shift;
70     my $baskets = &GetBasketsByBookseller($booksellerid);
71     for(my $i=0; $i < scalar @$baskets; ++$i) {
72         if( @$baskets[$i] && ! @$baskets[$i]->{'closedate'} ) {
73             splice(@$baskets, $i, 1);
74             --$i;
75         }
76     }
77     foreach my $basket (@$baskets){
78 #perl DBI uses value "undef" for the mysql "NULL" value, so i need to check everywhere where $basket->{'basketgroupid'} is used for undef ☹
79         $basket->{'basketgroupid'} = $input->param($basket->{'basketno'}.'-group') || undef;
80     }
81     return $baskets;
82 }
83
84
85
86 sub parseinputbasketgroups {
87     my $booksellerid = shift;
88     my $baskets = shift;
89     my $basketgroups = &GetBasketgroups($booksellerid);
90     my $newbasketgroups;
91     foreach my $basket (@$baskets){
92         my $basketgroup;
93         my $i = 0;
94         my $exists;
95         if(! $basket->{'basketgroupid'} || $basket->{'basketgroupid'} == 0){
96             $exists = "true";
97         } else {
98             foreach my $basketgroup (@$basketgroups){
99                 if($basket->{'basketgroupid'} == $basketgroup->{'id'}){
100                     $exists = "true";
101                     push(@{$basketgroup->{'basketlist'}}, $basket->{'basketno'});
102                     last;
103                 }
104             }
105         }
106         if (! $exists){
107 #if the basketgroup doesn't exist yet
108             $basketgroup = $newbasketgroups->{$basket->{'basketgroupid'}} || undef;
109             $basketgroup->{'booksellerid'} = $booksellerid;
110         } else {
111             while($i < scalar @$basketgroups && @$basketgroups[$i]->{'id'} != $basket->{'basketgroupid'}){
112                 ++$i;
113             }
114             $basketgroup = @$basketgroups[$i];
115         }
116         $basketgroup->{'id'}=$basket->{'basketgroupid'};
117         $basketgroup->{'name'}=$input->param('basketgroup-'.$basketgroup->{'id'}.'-name') || "";
118         $basketgroup->{'closed'}= $input->param('basketgroup-'.$basketgroup->{'id'}.'-closed');
119         push(@{$basketgroup->{'basketlist'}}, $basket->{'basketno'});
120         if (! $exists){
121             $newbasketgroups->{$basket->{'basketgroupid'}} = $basketgroup;
122         } else {
123             if($basketgroup->{'id'}){
124                 @$basketgroups[$i] = $basketgroup;
125             }
126         }
127     }
128     return($basketgroups, $newbasketgroups);
129 }
130
131 sub BasketTotal {
132     my $basketno = shift;
133     my $bookseller = shift;
134     my $total = 0;
135     my @orders = GetOrders($basketno);
136     for my $order (@orders){
137         $total = $total + ( $order->{ecost} * $order->{quantity} );
138         if ($bookseller->{invoiceincgst} && ! $bookseller->{listincgst} && ( $bookseller->{gstrate} || C4::Context->preference("gist") )) {
139             my $gst = $bookseller->{gstrate} || C4::Context->preference("gist");
140             $total = $total * ( $gst / 100 +1);
141         }
142     }
143     $total .= $bookseller->{invoiceprice};
144     return $total;
145 }
146
147 #displays all basketgroups and all closed baskets (in their respective groups)
148 sub displaybasketgroups {
149     my $basketgroups = shift;
150     my $bookseller = shift;
151     my $baskets = shift;
152     if (scalar @$basketgroups != 0) {
153         foreach my $basketgroup (@$basketgroups){
154             my $i = 0;
155             while($i < scalar(@$baskets)){
156                 my $basket = @$baskets[$i];
157                 if($basket->{'basketgroupid'} && $basket->{'basketgroupid'} == $basketgroup->{'id'}){
158                     $basket->{total} = BasketTotal($basket->{basketno}, $bookseller);
159                     push(@{$basketgroup->{'baskets'}}, $basket);
160                     splice(@$baskets, $i, 1);
161                     --$i;
162                 }
163                 ++$i;
164             }
165         }
166         $template->param(basketgroups => $basketgroups);
167     }
168     for(my $i=0; $i < scalar @$baskets; ++$i) {
169         if( ! @$baskets[$i]->{'closedate'} ) {
170             splice(@$baskets, $i, 1);
171             --$i;
172         }else{
173             @$baskets[$i]->{total} = BasketTotal(@$baskets[$i]->{basketno}, $bookseller);
174         }
175     }
176     $template->param(baskets => $baskets);
177     $template->param( booksellername => $bookseller ->{'name'});
178 }
179
180 sub printbasketgrouppdf{
181     my ($basketgroupid) = @_;
182     
183     my $pdfformat = C4::Context->preference("pdfformat");
184     eval "use $pdfformat" ;
185     warn @_;
186     eval "use C4::Branch";
187     
188     my $basketgroup = GetBasketgroup($basketgroupid);
189     my $bookseller = GetBookSellerFromId($basketgroup->{'booksellerid'});
190     my $baskets = GetBasketsByBasketgroup($basketgroupid);
191     
192     my %orders;
193     for my $basket (@$baskets) {
194         my @ba_orders;
195         my @ords = &GetOrders($basket->{basketno});
196         for my $ord (@ords) {
197             # ba_order is filled with : 
198             # 0      1        2        3         4            5         6       7      8        9
199             #isbn, itemtype, author, title, publishercode, quantity, listprice ecost discount gstrate
200             my @ba_order;
201             if ( $ord->{biblionumber} && $ord->{quantity}> 0 ) {
202                 eval "use C4::Biblio";
203                 eval "use C4::Koha";
204                 my $bib = GetBiblioData($ord->{biblionumber});
205                 my $itemtypes = GetItemTypes();
206                 if($ord->{isbn}){
207                     push(@ba_order, $ord->{isbn});
208                 } else {
209                     push(@ba_order, undef);
210                 }
211                 if ($ord->{itemtype}){
212                     push(@ba_order, $itemtypes->{$bib->{itemtype}}->{description}) if $bib->{itemtype};
213                 } else {
214                     push(@ba_order, undef);
215                 }
216 #             } else {
217 #                 push(@ba_order, undef, undef);
218                 for my $key (qw/author title publishercode quantity listprice ecost/) {
219                     push(@ba_order, $ord->{$key});                                                  #Order lines
220                 }
221                 push(@ba_order, $bookseller->{discount});
222                 push(@ba_order, $bookseller->{gstrate}*100 || C4::Context->preference("gist") || 0);
223                 push(@ba_orders, \@ba_order);
224                 # Editor Number
225                 my $en;
226                 if (C4::Context->preference("marcflavour") eq 'UNIMARC') {
227                     $en = MARC::Record::new_from_xml($ord->{marcxml},'UTF-8')->subfield('345',"b");
228                 } elsif (C4::Context->preference("marcflavour") eq 'MARC21') {
229                     $en = MARC::Record::new_from_xml($ord->{marcxml},'UTF-8')->subfield('037',"a");
230                 }
231                 if($en){
232                     push(@ba_order, $en);
233                 } else {
234                     push(@ba_order, undef);
235                 }
236             }
237         }
238         %orders->{$basket->{basketno}}=\@ba_orders;
239     }
240     print $input->header( -type => 'application/pdf', -attachment => 'basketgroup.pdf' );
241     my $branch = GetBranchInfo(GetBranch($input, GetBranches()));
242     $branch = @$branch[0];
243     my $pdf = printpdf($basketgroup, $bookseller, $baskets, $branch, \%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         if($basketgroupid){
272             my $selecteds = GetBasketsByBasketgroup($basketgroupid);
273             foreach (@{$selecteds}){
274                 $_->{total} = BasketTotal($_->{basketno}, $_);
275             }
276             $template->param(basketgroupid => $basketgroupid,
277                              selectedbaskets => $selecteds);
278         }
279         $template->param( booksellerid => $booksellerid );
280     }
281     $template->param(grouping => 1);
282     my $basketgroups = &GetBasketgroups($booksellerid);
283     my $bookseller = &GetBookSellerFromId($booksellerid);
284     my $baskets = &GetBasketsByBookseller($booksellerid);
285
286     displaybasketgroups($basketgroups, $bookseller, $baskets);
287 } elsif ($op eq 'mod_basket') {
288 #we want to modify an individual basket's group
289   my $basketno=$input->param('basketno');
290   my $basketgroupid=$input->param('basketgroupid');
291   ModBasket( { basketno => $basketno,
292                          basketgroupid => $basketgroupid } );
293   print $input->redirect("basket.pl?basketno=" . $basketno);
294 } elsif ($op eq 'validate') {
295     if(! $booksellerid){
296         $template->param( booksellererror => 1);
297     } else {
298         $template->param( booksellerid => $booksellerid );
299     }
300     my $baskets = parseinputbaskets($booksellerid);
301     my ($basketgroups, $newbasketgroups) = parseinputbasketgroups($booksellerid, $baskets);
302     foreach my $nbgid (keys %$newbasketgroups){
303 #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
304         my $bgid = NewBasketgroup($newbasketgroups->{$nbgid});
305         ${$newbasketgroups->{$nbgid}}->{'id'} = $bgid;
306         ${$newbasketgroups->{$nbgid}}->{'oldid'} = $nbgid;
307     }
308     foreach my $basket (@$baskets){
309 #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.
310         if ( $basket->{'basketgroupid'} && $newbasketgroups->{$basket->{'basketgroupid'}} ){
311             $basket->{'basketgroupid'} = ${$newbasketgroups->{$basket->{'basketgroupid'}}}->{'id'};
312         }
313         ModBasket($basket);
314     }
315     foreach my $basketgroup (@$basketgroups){
316         if(! $basketgroup->{'id'}){
317             foreach my $basket (@{$basketgroup->{'baskets'}}){
318                 if($input->param('basket'.$basket->{'basketno'}.'changed')){
319                     ModBasket($basket);
320                 }
321             }
322         } elsif ($input->param('basketgroup-'.$basketgroup->{'id'}.'-changed')){
323             ModBasketgroup($basketgroup);
324         }
325     }
326     $basketgroups = &GetBasketgroups($booksellerid);
327     my $bookseller = &GetBookSellerFromId($booksellerid);
328     $baskets = &GetBasketsByBookseller($booksellerid);
329
330     displaybasketgroups($basketgroups, $bookseller, $baskets);
331 } elsif ( $op eq 'closeandprint') {
332     my $basketgroupid = $input->param('basketgroupid');
333     
334     CloseBasketgroup($basketgroupid);
335     
336     printbasketgrouppdf($basketgroupid);
337 }elsif ($op eq 'print'){
338     my $basketgroupid = $input->param('basketgroupid');
339     
340     printbasketgrouppdf($basketgroupid);
341 }elsif( $op eq "delete"){
342     my $basketgroupid = $input->param('basketgroupid');
343     warn $basketgroupid;
344     DelBasketgroup($basketgroupid);
345     warn "---------------";
346     print $input->redirect('/cgi-bin/koha/acqui/basketgroup.pl?booksellerid=' . $booksellerid);
347     
348 }elsif ( $op eq 'reopen'){
349     my $basketgroupid   = $input->param('basketgroupid');
350     my $booksellerid    = $input->param('booksellerid');
351     
352     ReOpenBasketgroup($basketgroupid);
353         
354     print $input->redirect('/cgi-bin/koha/acqui/basketgroup.pl?booksellerid=' . $booksellerid . '#closed');
355     
356 } elsif ( $op eq 'attachbasket') {
357     
358     # Getting parameters
359     my $basketgroup = {};
360     
361     my @baskets         = $input->param('basket');
362     my $basketgroupid   = $input->param('basketgroupid');
363     my $basketgroupname = $input->param('basketgroupname');
364     my $booksellerid    = $input->param('booksellerid');
365     my $close           = $input->param('close') ? 1 : 0;
366     # If we got a basketgroupname, we create a basketgroup
367     if ($basketgroupid) {
368         $basketgroup = {
369               name => $basketgroupname,
370               id => $basketgroupid,
371               basketlist => \@baskets,
372               closed      => $close,
373         };
374         ModBasketgroup($basketgroup);
375         if($close){
376             
377         }
378     }else{
379         $basketgroup = {
380             name         => $basketgroupname,
381             booksellerid => $booksellerid,
382             basketlist   => \@baskets,
383             closed        => $close,
384         };
385         $basketgroupid = NewBasketgroup($basketgroup);
386     }
387     
388     print $input->redirect('/cgi-bin/koha/acqui/basketgroup.pl?booksellerid=' . $booksellerid);
389     
390 }else{
391     my $basketgroups = &GetBasketgroups($booksellerid);
392     my $bookseller = &GetBookSellerFromId($booksellerid);
393     my $baskets = &GetBasketsByBookseller($booksellerid);
394
395     displaybasketgroups($basketgroups, $bookseller, $baskets);
396 }
397 #prolly won't use all these, maybe just use print, the rest can be done inside validate
398 output_html_with_http_headers $input, $cookie, $template->output;