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
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.
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
40 The bookseller who we want to display the baskets (and basketgroups) of.
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/;
64 our ($template, $loggedinuser, $cookie)
65 = get_template_and_user
({template_name
=> "acqui/basketgroup.tmpl",
69 flagsrequired
=> {acquisition
=> 'group_manage'},
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);
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;
91 sub parseinputbasketgroups
{
92 my $booksellerid = shift;
94 my $basketgroups = &GetBasketgroups
($booksellerid);
96 foreach my $basket (@
$baskets){
100 if(! $basket->{'basketgroupid'} || $basket->{'basketgroupid'} == 0){
103 foreach my $basketgroup (@
$basketgroups){
104 if($basket->{'basketgroupid'} == $basketgroup->{'id'}){
106 push(@
{$basketgroup->{'basketlist'}}, $basket->{'basketno'});
112 #if the basketgroup doesn't exist yet
113 $basketgroup = $newbasketgroups->{$basket->{'basketgroupid'}} || undef;
114 $basketgroup->{'booksellerid'} = $booksellerid;
116 while($i < scalar @
$basketgroups && @
$basketgroups[$i]->{'id'} != $basket->{'basketgroupid'}){
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'});
126 $newbasketgroups->{$basket->{'basketgroupid'}} = $basketgroup;
128 if($basketgroup->{'id'}){
129 @
$basketgroups[$i] = $basketgroup;
133 return($basketgroups, $newbasketgroups);
137 my $basketno = shift;
138 my $bookseller = shift;
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
};
152 #displays all basketgroups and all closed baskets (in their respective groups)
153 sub displaybasketgroups
{
154 my $basketgroups = shift;
155 my $bookseller = shift;
157 if (scalar @
$basketgroups != 0) {
158 foreach my $basketgroup (@
$basketgroups){
161 while($i < scalar(@
$baskets)){
162 my $basket = @
$baskets[$i];
163 if($basket->{'basketgroupid'} && $basket->{'basketgroupid'} == $basketgroup->{'id'}){
164 $basket->{total
} = BasketTotal
($basket->{basketno
}, $bookseller);
165 push(@
{$basketgroup->{'baskets'}}, $basket);
166 splice(@
$baskets, $i, 1);
172 $basketgroup -> {'basketsqty'} = $basketsqty;
174 $template->param(basketgroups
=> $basketgroups);
176 for(my $i=0; $i < scalar @
$baskets; ++$i) {
177 if( ! @
$baskets[$i]->{'closedate'} ) {
178 splice(@
$baskets, $i, 1);
181 @
$baskets[$i]->{total
} = BasketTotal
(@
$baskets[$i]->{basketno
}, $bookseller);
184 $template->param(baskets
=> $baskets);
185 $template->param( booksellername
=> $bookseller ->{'name'});
188 sub printbasketgrouppdf
{
189 my ($basketgroupid) = @_;
191 my $pdfformat = C4
::Context
->preference("OrderPdfFormat");
192 if ($pdfformat eq 'pdfformat::layout3pages' || $pdfformat eq 'pdfformat::layout2pages' || $pdfformat eq 'pdfformat::layout3pagesfr'){
194 eval "require $pdfformat";
201 print $input->header;
202 print $input->start_html; # FIXME Should do a nicer page
203 print "<h1>Invalid PDF Format set</h1>";
204 print "Please go to the systempreferences and set a valid pdfformat";
208 my $basketgroup = GetBasketgroup
($basketgroupid);
209 my $bookseller = GetBookSellerFromId
($basketgroup->{'booksellerid'});
210 my $baskets = GetBasketsByBasketgroup
($basketgroupid);
213 for my $basket (@
$baskets) {
215 my @ords = &GetOrders
($basket->{basketno
});
216 for my $ord (@ords) {
218 next unless ( $ord->{biblionumber
} or $ord->{quantity
}> 0 );
234 $ord->{rrp
} = ConvertCurrency
( $ord->{'currency'}, $ord->{rrp
} );
235 if ( $bookseller->{'listincgst'} ) {
236 $ord->{rrpgsti
} = sprintf( "%.2f", $ord->{rrp
} );
237 $ord->{gstgsti
} = sprintf( "%.2f", $ord->{gstrate
} * 100 );
238 $ord->{rrpgste
} = sprintf( "%.2f", $ord->{rrp
} / ( 1 + ( $ord->{gstgsti} / 100 ) ) );
239 $ord->{gstgste
} = sprintf( "%.2f", $ord->{gstgsti
} / ( 1 + ( $ord->{gstgsti} / 100 ) ) );
240 $ord->{ecostgsti
} = sprintf( "%.2f", $ord->{ecost
} );
241 $ord->{ecostgste
} = sprintf( "%.2f", $ord->{ecost
} / ( 1 + ( $ord->{gstgsti} / 100 ) ) );
242 $ord->{gstvalue
} = sprintf( "%.2f", ( $ord->{ecostgsti
} - $ord->{ecostgste
} ) * $ord->{quantity
});
243 $ord->{totalgste
} = sprintf( "%.2f", $ord->{quantity
} * $ord->{ecostgste
} );
244 $ord->{totalgsti
} = sprintf( "%.2f", $ord->{quantity
} * $ord->{ecostgsti
} );
246 $ord->{rrpgsti
} = sprintf( "%.2f", $ord->{rrp
} * ( 1 + ( $ord->{gstrate
} ) ) );
247 $ord->{rrpgste
} = sprintf( "%.2f", $ord->{rrp
} );
248 $ord->{gstgsti
} = sprintf( "%.2f", $ord->{gstrate
} * 100 );
249 $ord->{gstgste
} = sprintf( "%.2f", $ord->{gstrate
} * 100 );
250 $ord->{ecostgsti
} = sprintf( "%.2f", $ord->{ecost
} * ( 1 + ( $ord->{gstrate
} ) ) );
251 $ord->{ecostgste
} = sprintf( "%.2f", $ord->{ecost
} );
252 $ord->{gstvalue
} = sprintf( "%.2f", ( $ord->{ecostgsti
} - $ord->{ecostgste
} ) * $ord->{quantity
});
253 $ord->{totalgste
} = sprintf( "%.2f", $ord->{quantity
} * $ord->{ecostgste
} );
254 $ord->{totalgsti
} = sprintf( "%.2f", $ord->{quantity
} * $ord->{ecostgsti
} );
256 my $bib = GetBiblioData
($ord->{biblionumber
});
257 my $itemtypes = GetItemTypes
();
260 # 0 1 2 3 4 5 6 7 8 9
261 #isbn, itemtype, author, title, publishercode, quantity, listprice ecost discount gstrate
265 my $marcrecord=eval{MARC
::Record
::new_from_xml
( $ord->{marcxml
},'UTF-8' )};
267 if ( C4
::Context
->preference("marcflavour") eq 'UNIMARC' ) {
268 $en = $marcrecord->subfield( '345', "b" );
269 } elsif ( C4
::Context
->preference("marcflavour") eq 'MARC21' ) {
270 $en = $marcrecord->subfield( '037', "a" );
275 isbn
=> ($ord->{isbn
} ?
$ord->{isbn
} : undef),
276 itemtype
=> ( $ord->{itemtype
} and $bib->{itemtype
} ?
$itemtypes->{$bib->{itemtype
}}->{description
} : undef ),
277 en
=> ( $en ?
$en : undef ),
279 for my $key ( qw
/ gstrate author title itemtype publishercode discount quantity rrpgsti rrpgste gstgsti gstgste ecostgsti ecostgste gstvalue totalgste totalgsti / ) {
280 $ba_order->{$key} = $ord->{$key};
283 push(@ba_orders, $ba_order);
285 $orders{$basket->{basketno
}} = \
@ba_orders;
287 print $input->header(
288 -type
=> 'application/pdf',
289 -attachment
=> ( $basketgroup->{name
} || $basketgroupid ) . '.pdf'
291 my $pdf = printpdf
($basketgroup, $bookseller, $baskets, \
%orders, $bookseller->{gstrate
} // C4
::Context
->preference("gist")) || die "pdf generation failed";
296 my $op = $input->param('op') || 'display';
297 my $booksellerid = $input->param('booksellerid');
298 $template->param(booksellerid
=> $booksellerid);
300 if ( $op eq "add" ) {
302 $template->param( ungroupedlist
=> 1);
303 my @booksellers = GetBookSeller
('');
304 for (my $i=0; $i < scalar @booksellers; $i++) {
305 my $baskets = &GetBasketsByBookseller
($booksellers[$i]->{id
});
306 for (my $j=0; $j < scalar @
$baskets; $j++) {
307 if(! @
$baskets[$i]->{closedate
} || @
$baskets[$i]->{basketgroupid
}) {
308 splice(@
$baskets, $j, 1);
312 if (scalar @
$baskets == 0){
313 splice(@booksellers, $i, 1);
318 my $basketgroupid = $input->param('basketgroupid');
321 my $freedeliveryplace;
322 if ( $basketgroupid ) {
323 # Get the selected baskets in the basketgroup to display them
324 my $selecteds = GetBasketsByBasketgroup
($basketgroupid);
325 foreach (@
{$selecteds}){
326 $_->{total
} = BasketTotal
($_->{basketno
}, $_);
328 $template->param(basketgroupid
=> $basketgroupid,
329 selectedbaskets
=> $selecteds);
331 # Get general informations about the basket group to prefill the form
332 my $basketgroup = GetBasketgroup
($basketgroupid);
334 name
=> $basketgroup->{name
},
335 deliverycomment
=> $basketgroup->{deliverycomment
},
336 freedeliveryplace
=> $basketgroup->{freedeliveryplace
},
338 $billingplace = $basketgroup->{billingplace
};
339 $deliveryplace = $basketgroup->{deliveryplace
};
340 $freedeliveryplace = $basketgroup->{freedeliveryplace
};
343 # determine default billing and delivery places depending on librarian homebranch and existing basketgroup data
344 my $borrower = GetMember
( ( 'borrowernumber' => $loggedinuser ) );
345 $billingplace = $billingplace || $borrower->{'branchcode'};
346 $deliveryplace = $deliveryplace || $borrower->{'branchcode'};
348 my $branches = C4
::Branch
::GetBranchesLoop
( $billingplace );
349 $template->param( billingplaceloop
=> $branches );
350 $branches = C4
::Branch
::GetBranchesLoop
( $deliveryplace );
351 $template->param( deliveryplaceloop
=> $branches );
353 $template->param( booksellerid
=> $booksellerid );
355 $template->param(grouping
=> 1);
356 my $basketgroups = &GetBasketgroups
($booksellerid);
357 my $bookseller = &GetBookSellerFromId
($booksellerid);
358 my $baskets = &GetBasketsByBookseller
($booksellerid);
360 displaybasketgroups
($basketgroups, $bookseller, $baskets);
361 } elsif ($op eq 'mod_basket') {
362 #we want to modify an individual basket's group
363 my $basketno=$input->param('basketno');
364 my $basketgroupid=$input->param('basketgroupid');
365 ModBasket
( { basketno
=> $basketno,
366 basketgroupid
=> $basketgroupid } );
367 print $input->redirect("basket.pl?basketno=" . $basketno);
368 } elsif ($op eq 'validate') {
370 $template->param( booksellererror
=> 1);
372 $template->param( booksellerid
=> $booksellerid );
374 my $baskets = parseinputbaskets
($booksellerid);
375 my ($basketgroups, $newbasketgroups) = parseinputbasketgroups
($booksellerid, $baskets);
376 foreach my $nbgid (keys %$newbasketgroups){
377 #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
378 my $bgid = NewBasketgroup
($newbasketgroups->{$nbgid});
379 ${$newbasketgroups->{$nbgid}}->{'id'} = $bgid;
380 ${$newbasketgroups->{$nbgid}}->{'oldid'} = $nbgid;
382 foreach my $basket (@
$baskets){
383 #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.
384 if ( $basket->{'basketgroupid'} && $newbasketgroups->{$basket->{'basketgroupid'}} ){
385 $basket->{'basketgroupid'} = ${$newbasketgroups->{$basket->{'basketgroupid'}}}->{'id'};
389 foreach my $basketgroup (@
$basketgroups){
390 if(! $basketgroup->{'id'}){
391 foreach my $basket (@
{$basketgroup->{'baskets'}}){
392 if($input->param('basket'.$basket->{'basketno'}.'changed')){
396 } elsif ($input->param('basketgroup-'.$basketgroup->{'id'}.'-changed')){
397 ModBasketgroup
($basketgroup);
400 $basketgroups = &GetBasketgroups
($booksellerid);
401 my $bookseller = &GetBookSellerFromId
($booksellerid);
402 $baskets = &GetBasketsByBookseller
($booksellerid);
404 displaybasketgroups
($basketgroups, $bookseller, $baskets);
405 } elsif ( $op eq 'closeandprint') {
406 my $basketgroupid = $input->param('basketgroupid');
408 CloseBasketgroup
($basketgroupid);
410 printbasketgrouppdf
($basketgroupid);
412 }elsif ($op eq 'print'){
413 my $basketgroupid = $input->param('basketgroupid');
415 printbasketgrouppdf
($basketgroupid);
417 }elsif ( $op eq "export" ) {
418 my $basketgroupid = $input->param('basketgroupid');
419 print $input->header(
421 -attachment
=> 'basketgroup' . $basketgroupid . '.csv',
423 print GetBasketGroupAsCSV
( $basketgroupid, $input );
425 }elsif( $op eq "delete"){
426 my $basketgroupid = $input->param('basketgroupid');
427 DelBasketgroup
($basketgroupid);
428 print $input->redirect('/cgi-bin/koha/acqui/basketgroup.pl?booksellerid=' . $booksellerid);
430 }elsif ( $op eq 'reopen'){
431 my $basketgroupid = $input->param('basketgroupid');
432 my $booksellerid = $input->param('booksellerid');
434 ReOpenBasketgroup
($basketgroupid);
436 print $input->redirect('/cgi-bin/koha/acqui/basketgroup.pl?booksellerid=' . $booksellerid . '#closed');
438 } elsif ( $op eq 'attachbasket') {
441 my $basketgroup = {};
442 my @baskets = $input->param('basket');
443 my $basketgroupid = $input->param('basketgroupid');
444 my $basketgroupname = $input->param('basketgroupname');
445 my $booksellerid = $input->param('booksellerid');
446 my $billingplace = $input->param('billingplace');
447 my $deliveryplace = $input->param('deliveryplace');
448 my $freedeliveryplace = $input->param('freedeliveryplace');
449 my $deliverycomment = $input->param('deliverycomment');
450 my $close = $input->param('close') ?
1 : 0;
451 # If we got a basketgroupname, we create a basketgroup
452 if ($basketgroupid) {
454 name
=> $basketgroupname,
455 id
=> $basketgroupid,
456 basketlist
=> \
@baskets,
457 billingplace
=> $billingplace,
458 deliveryplace
=> $deliveryplace,
459 freedeliveryplace
=> $freedeliveryplace,
460 deliverycomment
=> $deliverycomment,
463 ModBasketgroup
($basketgroup);
469 name
=> $basketgroupname,
470 booksellerid
=> $booksellerid,
471 basketlist
=> \
@baskets,
472 billingplace
=> $billingplace,
473 deliveryplace
=> $deliveryplace,
474 freedeliveryplace
=> $freedeliveryplace,
475 deliverycomment
=> $deliverycomment,
478 $basketgroupid = NewBasketgroup
($basketgroup);
481 my $url = '/cgi-bin/koha/acqui/basketgroup.pl?booksellerid=' . $booksellerid;
482 $url .= "&closed=1" if ($input->param("closed"));
483 print $input->redirect($url);
486 my $basketgroups = &GetBasketgroups
($booksellerid);
487 my $bookseller = &GetBookSellerFromId
($booksellerid);
488 my $baskets = &GetBasketsByBookseller
($booksellerid);
490 displaybasketgroups
($basketgroups, $bookseller, $baskets);
492 $template->param(closed
=> $input->param("closed"));
493 #prolly won't use all these, maybe just use print, the rest can be done inside validate
494 output_html_with_http_headers
$input, $cookie, $template->output;