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