Bug 10541: enable cross-browser AJAX in additem.js
[koha.git] / acqui / basketgroup.pl
blob398980c53b24d7ffa98baeb8e15762f87ba90c5a
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 my $basketsqty = 0;
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);
167 ++$basketsqty;
168 --$i;
170 ++$i;
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);
179 --$i;
180 }else{
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'){
193 eval {
194 eval "require $pdfformat";
195 import $pdfformat;
197 if ($@){
200 else {
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";
205 exit;
208 my $basketgroup = GetBasketgroup($basketgroupid);
209 my $bookseller = GetBookSellerFromId($basketgroup->{'booksellerid'});
210 my $baskets = GetBasketsByBasketgroup($basketgroupid);
212 my %orders;
213 for my $basket (@$baskets) {
214 my @ba_orders;
215 my @ords = &GetOrders($basket->{basketno});
216 for my $ord (@ords) {
218 next unless ( $ord->{biblionumber} or $ord->{quantity}> 0 );
219 eval {
220 require C4::Biblio;
221 import C4::Biblio;
223 if ($@){
224 croak $@;
226 eval {
227 require C4::Koha;
228 import C4::Koha;
230 if ($@){
231 croak $@;
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} );
245 } else {
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();
259 #FIXME DELETE ME
260 # 0 1 2 3 4 5 6 7 8 9
261 #isbn, itemtype, author, title, publishercode, quantity, listprice ecost discount gstrate
263 # Editor Number
264 my $en;
265 my $marcrecord=eval{MARC::Record::new_from_xml( $ord->{marcxml},'UTF-8' )};
266 if ($marcrecord){
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" );
274 my $ba_order = {
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";
292 print $pdf;
296 my $op = $input->param('op') || 'display';
297 my $booksellerid = $input->param('booksellerid');
298 $template->param(booksellerid => $booksellerid);
300 if ( $op eq "add" ) {
301 if(! $booksellerid){
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);
309 $j--;
312 if (scalar @$baskets == 0){
313 splice(@booksellers, $i, 1);
314 $i--;
317 } else {
318 my $basketgroupid = $input->param('basketgroupid');
319 my $billingplace;
320 my $deliveryplace;
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);
333 $template->param(
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') {
369 if(! $booksellerid){
370 $template->param( booksellererror => 1);
371 } else {
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'};
387 ModBasket($basket);
389 foreach my $basketgroup (@$basketgroups){
390 if(! $basketgroup->{'id'}){
391 foreach my $basket (@{$basketgroup->{'baskets'}}){
392 if($input->param('basket'.$basket->{'basketno'}.'changed')){
393 ModBasket($basket);
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);
411 exit;
412 }elsif ($op eq 'print'){
413 my $basketgroupid = $input->param('basketgroupid');
415 printbasketgrouppdf($basketgroupid);
416 exit;
417 }elsif ( $op eq "export" ) {
418 my $basketgroupid = $input->param('basketgroupid');
419 print $input->header(
420 -type => 'text/csv',
421 -attachment => 'basketgroup' . $basketgroupid . '.csv',
423 print GetBasketGroupAsCSV( $basketgroupid, $input );
424 exit;
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') {
440 # Getting parameters
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) {
453 $basketgroup = {
454 name => $basketgroupname,
455 id => $basketgroupid,
456 basketlist => \@baskets,
457 billingplace => $billingplace,
458 deliveryplace => $deliveryplace,
459 freedeliveryplace => $freedeliveryplace,
460 deliverycomment => $deliverycomment,
461 closed => $close,
463 ModBasketgroup($basketgroup);
464 if($close){
467 }else{
468 $basketgroup = {
469 name => $basketgroupname,
470 booksellerid => $booksellerid,
471 basketlist => \@baskets,
472 billingplace => $billingplace,
473 deliveryplace => $deliveryplace,
474 freedeliveryplace => $freedeliveryplace,
475 deliverycomment => $deliverycomment,
476 closed => $close,
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);
485 }else{
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;