2d4241e02532de7ec03bd5e4acba60dcc2058e77
[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 Modern::Perl;
47 use Carp qw( croak );
48
49 use C4::Auth qw( get_template_and_user );
50 use C4::Output qw( output_html_with_http_headers );
51 use CGI qw ( -utf8 );
52 use File::Spec;
53
54 use C4::Acquisition qw( GetOrders GetOrder get_rounded_price GetBasket GetBasketgroup GetBasketsByBasketgroup GetBasketgroups GetBasketsByBookseller ModBasket CloseBasketgroup GetBasketGroupAsCSV DelBasketgroup ReOpenBasketgroup ModBasketgroup NewBasket NewBasketgroup );
55 use Koha::EDI qw( get_edifact_ean create_edi_order );
56
57 use Koha::Biblioitems;
58 use Koha::Acquisition::Booksellers;
59 use Koha::ItemTypes;
60 use Koha::Patrons;
61
62 our $input=CGI->new;
63
64 our ($template, $loggedinuser, $cookie)
65     = get_template_and_user({template_name => "acqui/basketgroup.tt",
66                              query => $input,
67                              type => "intranet",
68                              flagsrequired => {acquisition => 'group_manage'},
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         # FIXME The following is wrong
78         if ( $bookseller->listincgst ) {
79             $total = $total + ( get_rounded_price($order->{ecost_tax_included}) * $order->{quantity} );
80         } else {
81             $total = $total + ( get_rounded_price($order->{ecost_tax_excluded}) * $order->{quantity} );
82         }
83     }
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     my @valid_pdfformats = qw(pdfformat::layout3pages pdfformat::layout2pages pdfformat::layout3pagesfr pdfformat::layout2pagesde);
128     if (grep {$_ eq $pdfformat} @valid_pdfformats) {
129         $pdfformat = "Koha::$pdfformat";
130         my $pdfformat_filepath = File::Spec->catfile(split /::/, $pdfformat) . '.pm';
131         require $pdfformat_filepath;
132         import $pdfformat qw(printpdf);
133     }
134     else {
135         print $input->header;
136         print $input->start_html;  # FIXME Should do a nicer page
137         print "<h1>Invalid PDF Format set</h1>";
138         print "Please go to the systempreferences and set a valid pdfformat";
139         exit;
140     }
141
142     my $basketgroup = GetBasketgroup($basketgroupid);
143     my $bookseller = Koha::Acquisition::Booksellers->find( $basketgroup->{booksellerid} );
144     my $baskets = GetBasketsByBasketgroup($basketgroupid);
145
146     my %orders;
147     for my $basket (@$baskets) {
148         my @ba_orders;
149         my @ords = &GetOrders($basket->{basketno});
150         for my $ord (@ords) {
151
152             next unless ( $ord->{biblionumber} or $ord->{quantity}> 0 );
153             eval {
154                 require C4::Biblio;
155                 import C4::Biblio;
156             };
157             if ($@){
158                 croak $@;
159             }
160             eval {
161                 require C4::Koha;
162                 import C4::Koha;
163             };
164             if ($@){
165                 croak $@;
166             }
167
168             $ord->{tax_value} = $ord->{tax_value_on_ordering};
169             $ord->{tax_rate} = $ord->{tax_rate_on_ordering};
170             $ord->{total_tax_included} = get_rounded_price($ord->{ecost_tax_included}) * $ord->{quantity};
171             $ord->{total_tax_excluded} = get_rounded_price($ord->{ecost_tax_excluded}) * $ord->{quantity};
172
173             my $biblioitem = Koha::Biblioitems->search({ biblionumber => $ord->{biblionumber} })->next;
174
175             #FIXME DELETE ME
176             # 0      1        2        3         4            5         6       7      8        9
177             #isbn, itemtype, author, title, publishercode, quantity, listprice ecost discount tax_rate
178
179             # Editor Number
180             my $en;
181             my $edition;
182             $ord->{marcxml} = C4::Biblio::GetXmlBiblio( $ord->{biblionumber} );
183             my $marcrecord=eval{MARC::Record::new_from_xml( $ord->{marcxml},'UTF-8' )};
184             if ($marcrecord){
185                 if ( C4::Context->preference("marcflavour") eq 'UNIMARC' ) {
186                     $en = $marcrecord->subfield( '345', "b" );
187                     $edition = $marcrecord->subfield( '205', 'a' );
188                 } elsif ( C4::Context->preference("marcflavour") eq 'MARC21' ) {
189                     $en = $marcrecord->subfield( '037', "a" );
190                     $edition = $marcrecord->subfield( '250', 'a' );
191                 }
192             }
193
194             my $itemtype = ( $ord->{itemtype} and $biblioitem->itemtype )
195                 ? Koha::ItemTypes->find( $biblioitem->itemtype )
196                 : undef;
197             $ord->{itemtype} = $itemtype ? $itemtype->description : undef;
198
199             $ord->{en} = $en ? $en : undef;
200             $ord->{edition} = $edition ? $edition : undef;
201
202             push(@ba_orders, $ord);
203         }
204         $orders{$basket->{basketno}} = \@ba_orders;
205     }
206     print $input->header(
207         -type       => 'application/pdf',
208         -attachment => ( $basketgroup->{name} || $basketgroupid ) . '.pdf'
209     );
210     my $pdf = printpdf($basketgroup, $bookseller, $baskets, \%orders, $bookseller->tax_rate // C4::Context->preference("TaxRates")) || die "pdf generation failed";
211     print $pdf;
212
213 }
214
215 sub generate_edifact_orders {
216     my $basketgroupid = shift;
217     my $baskets       = GetBasketsByBasketgroup($basketgroupid);
218     my $ean           = get_edifact_ean();
219
220     if($ean) {
221         for my $basket ( @{$baskets} ) {
222             create_edi_order( { ean => $ean, basketno => $basket->{basketno}, } );
223         }
224     } else {
225         my $booksellerid = $input->param('booksellerid') || 0;
226         print $input->redirect('/cgi-bin/koha/acqui/basketgroup.pl?booksellerid=' .
227                                $booksellerid .
228                                '&message=No%20EDIFACT%20Setup');
229     }
230     return;
231 }
232
233 my $op = $input->param('op') || 'display';
234 # possible values of $op :
235 # - add : adds a new basketgroup, or edit an open basketgroup, or display a closed basketgroup
236 # - mod_basket : modify an individual basket of the basketgroup
237 # - closeandprint : close and print an closed basketgroup in pdf. called by clicking on "Close and print" button in closed basketgroups list
238 # - print : print a closed basketgroup. called by clicking on "Print" button in closed basketgroups list
239 # - ediprint : generate edi order messages for the baskets in the group
240 # - export : export in CSV a closed basketgroup. called by clicking on "Export" button in closed basketgroups list
241 # - delete : delete an open basketgroup. called by clicking on "Delete" button in open basketgroups list
242 # - reopen : reopen a closed basketgroup. called by clicking on "Reopen" button in closed basketgroup list
243 # - attachbasket : save a modified basketgroup, or creates a new basketgroup when a basket is closed. called from basket page
244 # - display : display the list of all basketgroups for a vendor
245 my $booksellerid = $input->param('booksellerid');
246 $template->param(booksellerid => $booksellerid);
247 my $bookseller = Koha::Acquisition::Booksellers->find( $booksellerid );
248
249 my $schema = Koha::Database->new()->schema();
250 my $rs = $schema->resultset('VendorEdiAccount')->search(
251     { vendor_id => $booksellerid, } );
252 $template->param( ediaccount => ($rs->count > 0));
253
254 if ( $op eq "add" ) {
255 #
256 # if no param('basketgroupid') is not defined, adds a new basketgroup
257 # else, edit (if it is open) or display (if it is close) the basketgroup basketgroupid
258 # the template will know if basketgroup must be displayed or edited, depending on the value of closed key
259 #
260     my $bookseller = Koha::Acquisition::Booksellers->find( $booksellerid );
261     my $basketgroupid = $input->param('basketgroupid');
262     my $billingplace;
263     my $deliveryplace;
264     my $freedeliveryplace;
265     if ( $basketgroupid ) {
266         # Get the selected baskets in the basketgroup to display them
267         my $selecteds = GetBasketsByBasketgroup($basketgroupid);
268         foreach my $basket(@{$selecteds}){
269             $basket->{total} = BasketTotal($basket->{basketno}, $bookseller);
270         }
271         $template->param(basketgroupid => $basketgroupid,
272                          selectedbaskets => $selecteds);
273
274         # Get general informations about the basket group to prefill the form
275         my $basketgroup = GetBasketgroup($basketgroupid);
276         $template->param(
277             name            => $basketgroup->{name},
278             deliverycomment => $basketgroup->{deliverycomment},
279             freedeliveryplace => $basketgroup->{freedeliveryplace},
280         );
281         $billingplace  = $basketgroup->{billingplace};
282         $deliveryplace = $basketgroup->{deliveryplace};
283         $freedeliveryplace = $basketgroup->{freedeliveryplace};
284         $template->param( closedbg => ($basketgroup ->{'closed'}) ? 1 : 0);
285     } else {
286         # When creating a new basket group preselect billing and delivery place based on logged-in user
287         my $patron = Koha::Patrons->find( $loggedinuser );
288         $billingplace  = $patron->branchcode;
289         $deliveryplace = $patron->branchcode;
290         $template->param( closedbg => 0);
291     }
292
293     $template->param( billingplace => $billingplace );
294     $template->param( deliveryplace => $deliveryplace );
295     $template->param( booksellerid => $booksellerid );
296
297     # the template will display a unique basketgroup
298     $template->param(grouping => 1);
299     my $basketgroups = &GetBasketgroups($booksellerid);
300     my $baskets = &GetBasketsByBookseller($booksellerid);
301     displaybasketgroups($basketgroups, $bookseller, $baskets);
302 } elsif ($op eq 'mod_basket') {
303 #
304 # edit an individual basket contained in this basketgroup
305 #
306   my $basketno=$input->param('basketno');
307   my $basketgroupid=$input->param('basketgroupid');
308   ModBasket( { basketno => $basketno,
309                          basketgroupid => $basketgroupid } );
310   print $input->redirect("basket.pl?basketno=" . $basketno);
311 } elsif ( $op eq 'closeandprint') {
312 #
313 # close an open basketgroup and generates a pdf
314 #
315     my $basketgroupid = $input->param('basketgroupid');
316     CloseBasketgroup($basketgroupid);
317     printbasketgrouppdf($basketgroupid);
318     exit;
319 }elsif ($op eq 'print'){
320 #
321 # print a closed basketgroup
322 #
323     my $basketgroupid = $input->param('basketgroupid');
324     printbasketgrouppdf($basketgroupid);
325     exit;
326 }elsif ( $op eq "export" ) {
327 #
328 # export a closed basketgroup in csv
329 #
330     my $basketgroupid = $input->param('basketgroupid');
331     my $basketgroup = GetBasketgroup($basketgroupid);
332     print $input->header(
333         -type       => 'text/csv',
334         -attachment => ( $basketgroup->{name} || $basketgroupid ) . '.csv'
335     );
336     print GetBasketGroupAsCSV( $basketgroupid, $input );
337     exit;
338 }elsif( $op eq "delete"){
339 #
340 # delete an closed basketgroup
341 #
342     my $basketgroupid = $input->param('basketgroupid');
343     DelBasketgroup($basketgroupid);
344     print $input->redirect('/cgi-bin/koha/acqui/basketgroup.pl?booksellerid=' . $booksellerid.'&amp;listclosed=1');
345 }elsif ( $op eq 'reopen'){
346 #
347 # reopen a closed basketgroup
348 #
349     my $basketgroupid   = $input->param('basketgroupid');
350     my $booksellerid    = $input->param('booksellerid');
351     ReOpenBasketgroup($basketgroupid);
352     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';
353     print $input->redirect($redirectpath);
354 } elsif ( $op eq 'attachbasket') {
355 #
356 # save a modified basketgroup, or creates a new basketgroup when a basket is closed. called from basket page
357 #
358     # Getting parameters
359     my $basketgroup       = {};
360     my @baskets           = $input->multi_param('basket');
361     my $basketgroupid     = $input->param('basketgroupid');
362     my $basketgroupname   = $input->param('basketgroupname');
363     my $booksellerid      = $input->param('booksellerid');
364     my $billingplace      = $input->param('billingplace');
365     my $deliveryplace     = $input->param('deliveryplace');
366     my $freedeliveryplace = $input->param('freedeliveryplace');
367     my $deliverycomment   = $input->param('deliverycomment');
368     my $closedbg          = $input->param('closedbg') ? 1 : 0;
369     if ($basketgroupid) {
370     # If we have a basketgroupid we edit the basketgroup
371         $basketgroup = {
372               name              => $basketgroupname,
373               id                => $basketgroupid,
374               basketlist        => \@baskets,
375               billingplace      => $billingplace,
376               deliveryplace     => $deliveryplace,
377               freedeliveryplace => $freedeliveryplace,
378               deliverycomment   => $deliverycomment,
379               closed            => $closedbg,
380         };
381         ModBasketgroup($basketgroup);
382         if($closedbg){
383 # FIXME
384         }
385     }else{
386     # we create a new basketgroup (with a closed basket)
387         $basketgroup = {
388             name              => $basketgroupname,
389             booksellerid      => $booksellerid,
390             basketlist        => \@baskets,
391             billingplace      => $billingplace,
392             deliveryplace     => $deliveryplace,
393             freedeliveryplace => $freedeliveryplace,
394             deliverycomment   => $deliverycomment,
395             closed            => $closedbg,
396         };
397         $basketgroupid = NewBasketgroup($basketgroup);
398     }
399     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;
400     $redirectpath .=  "&amp;listclosed=1" if $closedbg ;
401     print $input->redirect($redirectpath );
402     
403 } elsif ( $op eq 'ediprint') {
404     my $basketgroupid = $input->param('basketgroupid');
405     if ($template->param( 'ediaccount' )) {
406         generate_edifact_orders( $basketgroupid );
407         exit;
408     } else {
409         $template->param('NoEDIMessage' => 1);
410         my $basketgroups = &GetBasketgroups($booksellerid);
411         my $bookseller = Koha::Acquisition::Booksellers->find( $booksellerid );
412         my $baskets = &GetBasketsByBookseller($booksellerid);
413
414         displaybasketgroups($basketgroups, $bookseller, $baskets);
415     }
416 }else{
417 # no param : display the list of all basketgroups for a given vendor
418     my $basketgroups = &GetBasketgroups($booksellerid);
419     my $bookseller = Koha::Acquisition::Booksellers->find( $booksellerid );
420     my $baskets = &GetBasketsByBookseller($booksellerid);
421
422     displaybasketgroups($basketgroups, $bookseller, $baskets);
423 }
424 $template->param(listclosed => ((defined $input->param('listclosed')) && ($input->param('listclosed') eq '1'))? 1:0 );
425 #prolly won't use all these, maybe just use print, the rest can be done inside validate
426 output_html_with_http_headers $input, $cookie, $template->output;