Bug 8508 - Holds to Pull : Library dropdown options are erroneously concatenated...
[koha.git] / acqui / basketgroup.pl
blob8782a45938d61dfc1486ea3837f79ad65076dfa9
1 #!/usr/bin/perl
3 #script to group (closed) baskets into basket groups for easier order management
4 #written by john.soros@biblibre.com 01/10/2008
6 # Copyright 2008 - 2009 BibLibre SARL
7 # Parts Copyright Catalyst 2010
9 # This file is part of Koha.
11 # Koha is free software; you can redistribute it and/or modify it under the
12 # terms of the GNU General Public License as published by the Free Software
13 # Foundation; either version 2 of the License, or (at your option) any later
14 # version.
16 # Koha is distributed in the hope that it will be useful, but WITHOUT ANY
17 # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
18 # A PARTICULAR PURPOSE. See the GNU General Public License for more details.
20 # You should have received a copy of the GNU General Public License along
21 # with Koha; if not, write to the Free Software Foundation, Inc.,
22 # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
25 =head1 NAME
27 basketgroup.pl
29 =head1 DESCRIPTION
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.
34 =head1 CGI PARAMETERS
36 =over 4
38 =item $booksellerid
40 The bookseller who we want to display the baskets (and basketgroups) of.
42 =back
44 =cut
46 use strict;
47 use warnings;
48 use Carp;
50 use C4::Input;
51 use C4::Auth;
52 use C4::Output;
53 use CGI;
55 use C4::Bookseller qw/GetBookSellerFromId/;
56 use C4::Budgets qw/ConvertCurrency/;
57 use C4::Acquisition qw/CloseBasketgroup ReOpenBasketgroup GetOrders GetBasketsByBasketgroup GetBasketsByBookseller ModBasketgroup NewBasketgroup DelBasketgroup GetBasketgroups ModBasket GetBasketgroup GetBasket GetBasketGroupAsCSV/;
58 use C4::Bookseller qw/GetBookSellerFromId/;
59 use C4::Branch qw/GetBranches/;
60 use C4::Members qw/GetMember/;
62 our $input=new CGI;
64 our ($template, $loggedinuser, $cookie)
65 = get_template_and_user({template_name => "acqui/basketgroup.tmpl",
66 query => $input,
67 type => "intranet",
68 authnotrequired => 0,
69 flagsrequired => {acquisition => 'group_manage'},
70 debug => 1,
71 });
73 sub parseinputbaskets {
74 my $booksellerid = shift;
75 my $baskets = &GetBasketsByBookseller($booksellerid);
76 for(my $i=0; $i < scalar @$baskets; ++$i) {
77 if( @$baskets[$i] && ! @$baskets[$i]->{'closedate'} ) {
78 splice(@$baskets, $i, 1);
79 --$i;
82 foreach my $basket (@$baskets){
83 #perl DBI uses value "undef" for the mysql "NULL" value, so i need to check everywhere where $basket->{'basketgroupid'} is used for undef ☹
84 $basket->{'basketgroupid'} = $input->param($basket->{'basketno'}.'-group') || undef;
86 return $baskets;
91 sub parseinputbasketgroups {
92 my $booksellerid = shift;
93 my $baskets = shift;
94 my $basketgroups = &GetBasketgroups($booksellerid);
95 my $newbasketgroups;
96 foreach my $basket (@$baskets){
97 my $basketgroup;
98 my $i = 0;
99 my $exists;
100 if(! $basket->{'basketgroupid'} || $basket->{'basketgroupid'} == 0){
101 $exists = "true";
102 } else {
103 foreach my $basketgroup (@$basketgroups){
104 if($basket->{'basketgroupid'} == $basketgroup->{'id'}){
105 $exists = "true";
106 push(@{$basketgroup->{'basketlist'}}, $basket->{'basketno'});
107 last;
111 if (! $exists){
112 #if the basketgroup doesn't exist yet
113 $basketgroup = $newbasketgroups->{$basket->{'basketgroupid'}} || undef;
114 $basketgroup->{'booksellerid'} = $booksellerid;
115 } else {
116 while($i < scalar @$basketgroups && @$basketgroups[$i]->{'id'} != $basket->{'basketgroupid'}){
117 ++$i;
119 $basketgroup = @$basketgroups[$i];
121 $basketgroup->{'id'}=$basket->{'basketgroupid'};
122 $basketgroup->{'name'}=$input->param('basketgroup-'.$basketgroup->{'id'}.'-name') || "";
123 $basketgroup->{'closed'}= $input->param('basketgroup-'.$basketgroup->{'id'}.'-closed');
124 push(@{$basketgroup->{'basketlist'}}, $basket->{'basketno'});
125 if (! $exists){
126 $newbasketgroups->{$basket->{'basketgroupid'}} = $basketgroup;
127 } else {
128 if($basketgroup->{'id'}){
129 @$basketgroups[$i] = $basketgroup;
133 return($basketgroups, $newbasketgroups);
136 sub BasketTotal {
137 my $basketno = shift;
138 my $bookseller = shift;
139 my $total = 0;
140 my @orders = GetOrders($basketno);
141 for my $order (@orders){
142 $total = $total + ( $order->{ecost} * $order->{quantity} );
143 if ($bookseller->{invoiceincgst} && ! $bookseller->{listincgst} && ( $bookseller->{gstrate} // C4::Context->preference("gist") )) {
144 my $gst = $bookseller->{gstrate} // C4::Context->preference("gist");
145 $total = $total * ( $gst / 100 +1);
148 $total .= $bookseller->{invoiceprice};
149 return $total;
152 #displays all basketgroups and all closed baskets (in their respective groups)
153 sub displaybasketgroups {
154 my $basketgroups = shift;
155 my $bookseller = shift;
156 my $baskets = shift;
157 if (scalar @$basketgroups != 0) {
158 foreach my $basketgroup (@$basketgroups){
159 my $i = 0;
160 while($i < scalar(@$baskets)){
161 my $basket = @$baskets[$i];
162 if($basket->{'basketgroupid'} && $basket->{'basketgroupid'} == $basketgroup->{'id'}){
163 $basket->{total} = BasketTotal($basket->{basketno}, $bookseller);
164 push(@{$basketgroup->{'baskets'}}, $basket);
165 splice(@$baskets, $i, 1);
166 --$i;
168 ++$i;
171 $template->param(basketgroups => $basketgroups);
173 for(my $i=0; $i < scalar @$baskets; ++$i) {
174 if( ! @$baskets[$i]->{'closedate'} ) {
175 splice(@$baskets, $i, 1);
176 --$i;
177 }else{
178 @$baskets[$i]->{total} = BasketTotal(@$baskets[$i]->{basketno}, $bookseller);
181 $template->param(baskets => $baskets);
182 $template->param( booksellername => $bookseller ->{'name'});
185 sub printbasketgrouppdf{
186 my ($basketgroupid) = @_;
188 my $pdfformat = C4::Context->preference("OrderPdfFormat");
189 if ($pdfformat eq 'pdfformat::layout3pages' || $pdfformat eq 'pdfformat::layout2pages'){
190 eval {
191 eval "require $pdfformat";
192 import $pdfformat;
194 if ($@){
197 else {
198 print $input->header;
199 print $input->start_html; # FIXME Should do a nicer page
200 print "<h1>Invalid PDF Format set</h1>";
201 print "Please go to the systempreferences and set a valid pdfformat";
202 exit;
205 my $basketgroup = GetBasketgroup($basketgroupid);
206 my $bookseller = GetBookSellerFromId($basketgroup->{'booksellerid'});
207 my $baskets = GetBasketsByBasketgroup($basketgroupid);
209 my %orders;
210 for my $basket (@$baskets) {
211 my @ba_orders;
212 my @ords = &GetOrders($basket->{basketno});
213 for my $ord (@ords) {
215 next unless ( $ord->{biblionumber} or $ord->{quantity}> 0 );
216 eval {
217 require C4::Biblio;
218 import C4::Biblio;
220 if ($@){
221 croak $@;
223 eval {
224 require C4::Koha;
225 import C4::Koha;
227 if ($@){
228 croak $@;
231 $ord->{rrp} = ConvertCurrency( $ord->{'currency'}, $ord->{rrp} );
232 if ( $bookseller->{'listincgst'} ) {
233 $ord->{rrpgsti} = sprintf( "%.2f", $ord->{rrp} );
234 $ord->{gstgsti} = sprintf( "%.2f", $ord->{gstrate} * 100 );
235 $ord->{rrpgste} = sprintf( "%.2f", $ord->{rrp} / ( 1 + ( $ord->{gstgsti} / 100 ) ) );
236 $ord->{gstgste} = sprintf( "%.2f", $ord->{gstgsti} / ( 1 + ( $ord->{gstgsti} / 100 ) ) );
237 $ord->{ecostgsti} = sprintf( "%.2f", $ord->{ecost} );
238 $ord->{ecostgste} = sprintf( "%.2f", $ord->{ecost} / ( 1 + ( $ord->{gstgsti} / 100 ) ) );
239 $ord->{gstvalue} = sprintf( "%.2f", ( $ord->{ecostgsti} - $ord->{ecostgste} ) * $ord->{quantity});
240 $ord->{totalgste} = sprintf( "%.2f", $ord->{quantity} * $ord->{ecostgste} );
241 $ord->{totalgsti} = sprintf( "%.2f", $ord->{quantity} * $ord->{ecostgsti} );
242 } else {
243 $ord->{rrpgsti} = sprintf( "%.2f", $ord->{rrp} * ( 1 + ( $ord->{gstrate} ) ) );
244 $ord->{rrpgste} = sprintf( "%.2f", $ord->{rrp} );
245 $ord->{gstgsti} = sprintf( "%.2f", $ord->{gstrate} * 100 );
246 $ord->{gstgste} = sprintf( "%.2f", $ord->{gstrate} * 100 );
247 $ord->{ecostgsti} = sprintf( "%.2f", $ord->{ecost} * ( 1 + ( $ord->{gstrate} ) ) );
248 $ord->{ecostgste} = sprintf( "%.2f", $ord->{ecost} );
249 $ord->{gstvalue} = sprintf( "%.2f", ( $ord->{ecostgsti} - $ord->{ecostgste} ) * $ord->{quantity});
250 $ord->{totalgste} = sprintf( "%.2f", $ord->{quantity} * $ord->{ecostgste} );
251 $ord->{totalgsti} = sprintf( "%.2f", $ord->{quantity} * $ord->{ecostgsti} );
253 my $bib = GetBiblioData($ord->{biblionumber});
254 my $itemtypes = GetItemTypes();
256 #FIXME DELETE ME
257 # 0 1 2 3 4 5 6 7 8 9
258 #isbn, itemtype, author, title, publishercode, quantity, listprice ecost discount gstrate
260 # Editor Number
261 my $en;
262 my $marcrecord=eval{MARC::Record::new_from_xml( $ord->{marcxml},'UTF-8' )};
263 if ($marcrecord){
264 if ( C4::Context->preference("marcflavour") eq 'UNIMARC' ) {
265 $en = $marcrecord->subfield( '345', "b" );
266 } elsif ( C4::Context->preference("marcflavour") eq 'MARC21' ) {
267 $en = $marcrecord->subfield( '037', "a" );
271 my $ba_order = {
272 isbn => ($ord->{isbn} ? $ord->{isbn} : undef),
273 itemtype => ( $ord->{itemtype} and $bib->{itemtype} ? $itemtypes->{$bib->{itemtype}}->{description} : undef ),
274 en => ( $en ? $en : undef ),
276 for my $key ( qw/ gstrate author title itemtype publishercode discount quantity rrpgsti rrpgste gstgsti gstgste ecostgsti ecostgste gstvalue totalgste totalgsti / ) {
277 $ba_order->{$key} = $ord->{$key};
280 push(@ba_orders, $ba_order);
282 $orders{$basket->{basketno}} = \@ba_orders;
284 print $input->header(
285 -type => 'application/pdf',
286 -attachment => ( $basketgroup->{name} || $basketgroupid ) . '.pdf'
288 my $pdf = printpdf($basketgroup, $bookseller, $baskets, \%orders, $bookseller->{gstrate} // C4::Context->preference("gist")) || die "pdf generation failed";
289 print $pdf;
293 my $op = $input->param('op') || 'display';
294 my $booksellerid = $input->param('booksellerid');
295 $template->param(booksellerid => $booksellerid);
297 if ( $op eq "add" ) {
298 if(! $booksellerid){
299 $template->param( ungroupedlist => 1);
300 my @booksellers = GetBookSeller('');
301 for (my $i=0; $i < scalar @booksellers; $i++) {
302 my $baskets = &GetBasketsByBookseller($booksellers[$i]->{id});
303 for (my $j=0; $j < scalar @$baskets; $j++) {
304 if(! @$baskets[$i]->{closedate} || @$baskets[$i]->{basketgroupid}) {
305 splice(@$baskets, $j, 1);
306 $j--;
309 if (scalar @$baskets == 0){
310 splice(@booksellers, $i, 1);
311 $i--;
314 } else {
315 my $basketgroupid = $input->param('basketgroupid');
316 my $billingplace;
317 my $deliveryplace;
318 my $freedeliveryplace;
319 if ( $basketgroupid ) {
320 # Get the selected baskets in the basketgroup to display them
321 my $selecteds = GetBasketsByBasketgroup($basketgroupid);
322 foreach (@{$selecteds}){
323 $_->{total} = BasketTotal($_->{basketno}, $_);
325 $template->param(basketgroupid => $basketgroupid,
326 selectedbaskets => $selecteds);
328 # Get general informations about the basket group to prefill the form
329 my $basketgroup = GetBasketgroup($basketgroupid);
330 $template->param(
331 name => $basketgroup->{name},
332 deliverycomment => $basketgroup->{deliverycomment},
333 freedeliveryplace => $basketgroup->{freedeliveryplace},
335 $billingplace = $basketgroup->{billingplace};
336 $deliveryplace = $basketgroup->{deliveryplace};
337 $freedeliveryplace = $basketgroup->{freedeliveryplace};
340 # determine default billing and delivery places depending on librarian homebranch and existing basketgroup data
341 my $borrower = GetMember( ( 'borrowernumber' => $loggedinuser ) );
342 $billingplace = $billingplace || $borrower->{'branchcode'};
343 $deliveryplace = $deliveryplace || $borrower->{'branchcode'};
345 my $branches = C4::Branch::GetBranchesLoop( $billingplace );
346 $template->param( billingplaceloop => $branches );
347 $branches = C4::Branch::GetBranchesLoop( $deliveryplace );
348 $template->param( deliveryplaceloop => $branches );
350 $template->param( booksellerid => $booksellerid );
352 $template->param(grouping => 1);
353 my $basketgroups = &GetBasketgroups($booksellerid);
354 my $bookseller = &GetBookSellerFromId($booksellerid);
355 my $baskets = &GetBasketsByBookseller($booksellerid);
357 displaybasketgroups($basketgroups, $bookseller, $baskets);
358 } elsif ($op eq 'mod_basket') {
359 #we want to modify an individual basket's group
360 my $basketno=$input->param('basketno');
361 my $basketgroupid=$input->param('basketgroupid');
362 ModBasket( { basketno => $basketno,
363 basketgroupid => $basketgroupid } );
364 print $input->redirect("basket.pl?basketno=" . $basketno);
365 } elsif ($op eq 'validate') {
366 if(! $booksellerid){
367 $template->param( booksellererror => 1);
368 } else {
369 $template->param( booksellerid => $booksellerid );
371 my $baskets = parseinputbaskets($booksellerid);
372 my ($basketgroups, $newbasketgroups) = parseinputbasketgroups($booksellerid, $baskets);
373 foreach my $nbgid (keys %$newbasketgroups){
374 #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
375 my $bgid = NewBasketgroup($newbasketgroups->{$nbgid});
376 ${$newbasketgroups->{$nbgid}}->{'id'} = $bgid;
377 ${$newbasketgroups->{$nbgid}}->{'oldid'} = $nbgid;
379 foreach my $basket (@$baskets){
380 #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.
381 if ( $basket->{'basketgroupid'} && $newbasketgroups->{$basket->{'basketgroupid'}} ){
382 $basket->{'basketgroupid'} = ${$newbasketgroups->{$basket->{'basketgroupid'}}}->{'id'};
384 ModBasket($basket);
386 foreach my $basketgroup (@$basketgroups){
387 if(! $basketgroup->{'id'}){
388 foreach my $basket (@{$basketgroup->{'baskets'}}){
389 if($input->param('basket'.$basket->{'basketno'}.'changed')){
390 ModBasket($basket);
393 } elsif ($input->param('basketgroup-'.$basketgroup->{'id'}.'-changed')){
394 ModBasketgroup($basketgroup);
397 $basketgroups = &GetBasketgroups($booksellerid);
398 my $bookseller = &GetBookSellerFromId($booksellerid);
399 $baskets = &GetBasketsByBookseller($booksellerid);
401 displaybasketgroups($basketgroups, $bookseller, $baskets);
402 } elsif ( $op eq 'closeandprint') {
403 my $basketgroupid = $input->param('basketgroupid');
405 CloseBasketgroup($basketgroupid);
407 printbasketgrouppdf($basketgroupid);
408 exit;
409 }elsif ($op eq 'print'){
410 my $basketgroupid = $input->param('basketgroupid');
412 printbasketgrouppdf($basketgroupid);
413 exit;
414 }elsif ( $op eq "export" ) {
415 my $basketgroupid = $input->param('basketgroupid');
416 print $input->header(
417 -type => 'text/csv',
418 -attachment => 'basketgroup' . $basketgroupid . '.csv',
420 print GetBasketGroupAsCSV( $basketgroupid, $input );
421 exit;
422 }elsif( $op eq "delete"){
423 my $basketgroupid = $input->param('basketgroupid');
424 DelBasketgroup($basketgroupid);
425 print $input->redirect('/cgi-bin/koha/acqui/basketgroup.pl?booksellerid=' . $booksellerid);
427 }elsif ( $op eq 'reopen'){
428 my $basketgroupid = $input->param('basketgroupid');
429 my $booksellerid = $input->param('booksellerid');
431 ReOpenBasketgroup($basketgroupid);
433 print $input->redirect('/cgi-bin/koha/acqui/basketgroup.pl?booksellerid=' . $booksellerid . '#closed');
435 } elsif ( $op eq 'attachbasket') {
437 # Getting parameters
438 my $basketgroup = {};
439 my @baskets = $input->param('basket');
440 my $basketgroupid = $input->param('basketgroupid');
441 my $basketgroupname = $input->param('basketgroupname');
442 my $booksellerid = $input->param('booksellerid');
443 my $billingplace = $input->param('billingplace');
444 my $deliveryplace = $input->param('deliveryplace');
445 my $freedeliveryplace = $input->param('freedeliveryplace');
446 my $deliverycomment = $input->param('deliverycomment');
447 my $close = $input->param('close') ? 1 : 0;
448 # If we got a basketgroupname, we create a basketgroup
449 if ($basketgroupid) {
450 $basketgroup = {
451 name => $basketgroupname,
452 id => $basketgroupid,
453 basketlist => \@baskets,
454 billingplace => $billingplace,
455 deliveryplace => $deliveryplace,
456 freedeliveryplace => $freedeliveryplace,
457 deliverycomment => $deliverycomment,
458 closed => $close,
460 ModBasketgroup($basketgroup);
461 if($close){
464 }else{
465 $basketgroup = {
466 name => $basketgroupname,
467 booksellerid => $booksellerid,
468 basketlist => \@baskets,
469 deliveryplace => $deliveryplace,
470 freedeliveryplace => $freedeliveryplace,
471 deliverycomment => $deliverycomment,
472 closed => $close,
474 $basketgroupid = NewBasketgroup($basketgroup);
477 my $url = '/cgi-bin/koha/acqui/basketgroup.pl?booksellerid=' . $booksellerid;
478 $url .= "&closed=1" if ($input->param("closed"));
479 print $input->redirect($url);
481 }else{
482 my $basketgroups = &GetBasketgroups($booksellerid);
483 my $bookseller = &GetBookSellerFromId($booksellerid);
484 my $baskets = &GetBasketsByBookseller($booksellerid);
486 displaybasketgroups($basketgroups, $bookseller, $baskets);
488 $template->param(closed => $input->param("closed"));
489 #prolly won't use all these, maybe just use print, the rest can be done inside validate
490 output_html_with_http_headers $input, $cookie, $template->output;