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