Bug 11347: DBRev 3.17.00.010
[koha.git] / acqui / basket.pl
blob5366bf89d77fd6084e5dd1728e5d5d6139f3c620
1 #!/usr/bin/perl
3 #script to show display basket of orders
5 # Copyright 2000 - 2004 Katipo
6 # Copyright 2008 - 2009 BibLibre SARL
8 # This file is part of Koha.
10 # Koha is free software; you can redistribute it and/or modify it under the
11 # terms of the GNU General Public License as published by the Free Software
12 # Foundation; either version 2 of the License, or (at your option) any later
13 # version.
15 # Koha is distributed in the hope that it will be useful, but WITHOUT ANY
16 # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
17 # A PARTICULAR PURPOSE. See the GNU General Public License for more details.
19 # You should have received a copy of the GNU General Public License along
20 # with Koha; if not, write to the Free Software Foundation, Inc.,
21 # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
23 use strict;
24 use warnings;
25 use C4::Auth;
26 use C4::Koha;
27 use C4::Output;
28 use CGI;
29 use C4::Acquisition;
30 use C4::Budgets;
31 use C4::Branch;
32 use C4::Bookseller qw( GetBookSellerFromId);
33 use C4::Debug;
34 use C4::Biblio;
35 use C4::Members qw/GetMember/; #needed for permissions checking for changing basketgroup of a basket
36 use C4::Items;
37 use C4::Suggestions;
38 use Date::Calc qw/Add_Delta_Days/;
40 =head1 NAME
42 basket.pl
44 =head1 DESCRIPTION
46 This script display all informations about basket for the supplier given
47 on input arg. Moreover, it allows us to add a new order for this supplier from
48 an existing record, a suggestion or a new record.
50 =head1 CGI PARAMETERS
52 =over 4
54 =item $basketno
56 The basket number.
58 =item booksellerid
60 the supplier this script have to display the basket.
62 =item order
64 =back
66 =cut
68 my $query = new CGI;
69 our $basketno = $query->param('basketno');
70 my $booksellerid = $query->param('booksellerid');
72 my ( $template, $loggedinuser, $cookie, $userflags ) = get_template_and_user(
74 template_name => "acqui/basket.tt",
75 query => $query,
76 type => "intranet",
77 authnotrequired => 0,
78 flagsrequired => { acquisition => 'order_manage' },
79 debug => 1,
83 my $basket = GetBasket($basketno);
84 $booksellerid = $basket->{booksellerid} unless $booksellerid;
85 my ($bookseller) = GetBookSellerFromId($booksellerid);
87 unless (CanUserManageBasket($loggedinuser, $basket, $userflags)) {
88 $template->param(
89 cannot_manage_basket => 1,
90 basketno => $basketno,
91 basketname => $basket->{basketname},
92 booksellerid => $booksellerid,
93 name => $bookseller->{name}
95 output_html_with_http_headers $query, $cookie, $template->output;
96 exit;
99 # FIXME : what about the "discount" percentage?
100 # FIXME : the query->param('booksellerid') below is probably useless. The bookseller is always known from the basket
101 # if no booksellerid in parameter, get it from basket
102 # warn "=>".$basket->{booksellerid};
103 my $op = $query->param('op');
104 if (!defined $op) {
105 $op = q{};
108 my $confirm_pref= C4::Context->preference("BasketConfirmations") || '1';
109 $template->param( skip_confirm_reopen => 1) if $confirm_pref eq '2';
111 if ( $op eq 'delete_confirm' ) {
112 my $basketno = $query->param('basketno');
113 my $delbiblio = $query->param('delbiblio');
114 my @orders = GetOrders($basketno);
115 #Delete all orders included in that basket, and all items received.
116 foreach my $myorder (@orders){
117 DelOrder($myorder->{biblionumber},$myorder->{ordernumber});
119 # if $delbiblio = 1, delete the records if possible
120 if ((defined $delbiblio)and ($delbiblio ==1)){
121 my @cannotdelbiblios ;
122 foreach my $myorder (@orders){
123 my $biblionumber = $myorder->{'biblionumber'};
124 my $countbiblio = CountBiblioInOrders($biblionumber);
125 my $ordernumber = $myorder->{'ordernumber'};
126 my $subscriptions = scalar GetSubscriptionsId ($biblionumber);
127 my $itemcount = GetItemsCount($biblionumber);
128 my $error;
129 if ($countbiblio == 0 && $itemcount == 0 && $subscriptions == 0) {
130 $error = DelBiblio($myorder->{biblionumber}) }
131 else {
132 push @cannotdelbiblios, {biblionumber=> ($myorder->{biblionumber}),
133 title=> $myorder->{'title'},
134 author=> $myorder->{'author'},
135 countbiblio=> $countbiblio,
136 itemcount=>$itemcount,
137 subscriptions=>$subscriptions};
139 if ($error) {
140 push @cannotdelbiblios, {biblionumber=> ($myorder->{biblionumber}),
141 title=> $myorder->{'title'},
142 author=> $myorder->{'author'},
143 othererror=> $error};
146 $template->param( cannotdelbiblios => \@cannotdelbiblios );
148 # delete the basket
149 DelBasket($basketno,);
150 $template->param( delete_confirmed => 1 );
151 } elsif ( !$bookseller ) {
152 $template->param( NO_BOOKSELLER => 1 );
153 } elsif ( $op eq 'del_basket') {
154 $template->param( delete_confirm => 1 );
155 if ( C4::Context->preference("IndependentBranches") ) {
156 my $userenv = C4::Context->userenv;
157 unless ( C4::Context->IsSuperLibrarian() ) {
158 my $validtest = ( $basket->{creationdate} eq '' )
159 || ( $userenv->{branch} eq $basket->{branch} )
160 || ( $userenv->{branch} eq '' )
161 || ( $basket->{branch} eq '' );
162 unless ($validtest) {
163 print $query->redirect("../mainpage.pl");
164 exit 1;
168 $basket->{creationdate} = "" unless ( $basket->{creationdate} );
169 $basket->{authorisedby} = $loggedinuser unless ( $basket->{authorisedby} );
170 my $contract = &GetContract($basket->{contractnumber});
171 $template->param(
172 basketno => $basketno,
173 basketname => $basket->{'basketname'},
174 basketnote => $basket->{note},
175 basketbooksellernote => $basket->{booksellernote},
176 basketcontractno => $basket->{contractnumber},
177 basketcontractname => $contract->{contractname},
178 creationdate => $basket->{creationdate},
179 authorisedby => $basket->{authorisedby},
180 authorisedbyname => $basket->{authorisedbyname},
181 closedate => $basket->{closedate},
182 deliveryplace => $basket->{deliveryplace},
183 billingplace => $basket->{billingplace},
184 active => $bookseller->{'active'},
185 booksellerid => $bookseller->{'id'},
186 name => $bookseller->{'name'},
187 address1 => $bookseller->{'address1'},
188 address2 => $bookseller->{'address2'},
189 address3 => $bookseller->{'address3'},
190 address4 => $bookseller->{'address4'},
192 } elsif ($op eq 'export') {
193 print $query->header(
194 -type => 'text/csv',
195 -attachment => 'basket' . $basket->{'basketno'} . '.csv',
197 print GetBasketAsCSV($query->param('basketno'), $query);
198 exit;
199 } elsif ($op eq 'close') {
200 my $confirm = $query->param('confirm') || $confirm_pref eq '2';
201 if ($confirm) {
202 my $basketno = $query->param('basketno');
203 my $booksellerid = $query->param('booksellerid');
204 $basketno =~ /^\d+$/ and CloseBasket($basketno);
205 # if requested, create basket group, close it and attach the basket
206 if ($query->param('createbasketgroup')) {
207 my $branchcode;
208 if(C4::Context->userenv and C4::Context->userenv->{'branch'}
209 and C4::Context->userenv->{'branch'} ne "NO_LIBRARY_SET") {
210 $branchcode = C4::Context->userenv->{'branch'};
212 my $basketgroupid = NewBasketgroup( { name => $basket->{basketname},
213 booksellerid => $booksellerid,
214 deliveryplace => $branchcode,
215 billingplace => $branchcode,
216 closed => 1,
218 ModBasket( { basketno => $basketno,
219 basketgroupid => $basketgroupid } );
220 print $query->redirect('/cgi-bin/koha/acqui/basketgroup.pl?booksellerid='.$booksellerid.'&closed=1');
221 } else {
222 print $query->redirect('/cgi-bin/koha/acqui/booksellers.pl?booksellerid=' . $booksellerid);
224 exit;
225 } else {
226 $template->param(
227 confirm_close => "1",
228 booksellerid => $booksellerid,
229 basketno => $basket->{'basketno'},
230 basketname => $basket->{'basketname'},
231 basketgroupname => $basket->{'basketname'},
234 } elsif ($op eq 'reopen') {
235 ReopenBasket($query->param('basketno'));
236 print $query->redirect('/cgi-bin/koha/acqui/basket.pl?basketno='.$basket->{'basketno'})
237 } elsif ( $op eq 'mod_users' ) {
238 my $basketusers_ids = $query->param('basketusers_ids');
239 my @basketusers = split( /:/, $basketusers_ids );
240 ModBasketUsers($basketno, @basketusers);
241 print $query->redirect("/cgi-bin/koha/acqui/basket.pl?basketno=$basketno");
242 exit;
243 } elsif ( $op eq 'mod_branch' ) {
244 my $branch = $query->param('branch');
245 $branch = undef if(defined $branch and $branch eq '');
246 ModBasket({
247 basketno => $basket->{basketno},
248 branch => $branch
250 print $query->redirect("/cgi-bin/koha/acqui/basket.pl?basketno=$basketno");
251 exit;
252 } else {
253 my @branches_loop;
254 # get librarian branch...
255 if ( C4::Context->preference("IndependentBranches") ) {
256 my $userenv = C4::Context->userenv;
257 unless ( C4::Context->IsSuperLibrarian() ) {
258 my $validtest = ( $basket->{creationdate} eq '' )
259 || ( $userenv->{branch} eq $basket->{branch} )
260 || ( $userenv->{branch} eq '' )
261 || ( $basket->{branch} eq '' );
262 unless ($validtest) {
263 print $query->redirect("../mainpage.pl");
264 exit 1;
267 if (!defined $basket->{branch} or $basket->{branch} eq $userenv->{branch}) {
268 push @branches_loop, {
269 branchcode => $userenv->{branch},
270 branchname => $userenv->{branchname},
271 selected => 1,
274 } else {
275 # get branches
276 my $branches = C4::Branch::GetBranches;
277 my @branchcodes = sort {
278 $branches->{$a}->{branchname} cmp $branches->{$b}->{branchname}
279 } keys %$branches;
280 foreach my $branch (@branchcodes) {
281 my $selected = 0;
282 if (defined $basket->{branch}) {
283 $selected = 1 if $branch eq $basket->{branch};
284 } else {
285 $selected = 1 if $branch eq C4::Context->userenv->{branch};
287 push @branches_loop, {
288 branchcode => $branch,
289 branchname => $branches->{$branch}->{branchname},
290 selected => $selected
295 #if the basket is closed,and the user has the permission to edit basketgroups, display a list of basketgroups
296 my ($basketgroup, $basketgroups);
297 my $staffuser = GetMember(borrowernumber => $loggedinuser);
298 if ($basket->{closedate} && haspermission($staffuser->{userid}, { acquisition => 'group_manage'} )) {
299 $basketgroups = GetBasketgroups($basket->{booksellerid});
300 for my $bg ( @{$basketgroups} ) {
301 if ($basket->{basketgroupid} && $basket->{basketgroupid} == $bg->{id}){
302 $bg->{default} = 1;
303 $basketgroup = $bg;
308 # if the basket is closed, calculate estimated delivery date
309 my $estimateddeliverydate;
310 if( $basket->{closedate} ) {
311 my ($year, $month, $day) = ($basket->{closedate} =~ /(\d+)-(\d+)-(\d+)/);
312 ($year, $month, $day) = Add_Delta_Days($year, $month, $day, $bookseller->{deliverytime});
313 $estimateddeliverydate = "$year-$month-$day";
316 # if new basket, pre-fill infos
317 $basket->{creationdate} = "" unless ( $basket->{creationdate} );
318 $basket->{authorisedby} = $loggedinuser unless ( $basket->{authorisedby} );
319 $debug
320 and warn sprintf
321 "loggedinuser: $loggedinuser; creationdate: %s; authorisedby: %s",
322 $basket->{creationdate}, $basket->{authorisedby};
324 my @basketusers_ids = GetBasketUsers($basketno);
325 my @basketusers;
326 foreach my $basketuser_id (@basketusers_ids) {
327 my $basketuser = GetMember(borrowernumber => $basketuser_id);
328 push @basketusers, $basketuser if $basketuser;
331 #to get active currency
332 my $cur = GetCurrency();
335 my @results = GetOrders( $basketno );
336 my @books_loop;
338 my @book_foot_loop;
339 my %foot;
340 my $total_quantity = 0;
341 my $total_gste = 0;
342 my $total_gsti = 0;
343 my $total_gstvalue = 0;
344 for my $order (@results) {
345 my $line = get_order_infos( $order, $bookseller);
346 if ( $line->{uncertainprice} ) {
347 $template->param( uncertainprices => 1 );
350 push @books_loop, $line;
352 $foot{$$line{gstgsti}}{gstgsti} = $$line{gstgsti};
353 $foot{$$line{gstgsti}}{gstvalue} += $$line{gstvalue};
354 $total_gstvalue += $$line{gstvalue};
355 $foot{$$line{gstgsti}}{quantity} += $$line{quantity};
356 $total_quantity += $$line{quantity};
357 $foot{$$line{gstgsti}}{totalgste} += $$line{totalgste};
358 $total_gste += $$line{totalgste};
359 $foot{$$line{gstgsti}}{totalgsti} += $$line{totalgsti};
360 $total_gsti += $$line{totalgsti};
363 push @book_foot_loop, map {$_} values %foot;
365 # Get cancelled orders
366 @results = GetCancelledOrders($basketno);
367 my @cancelledorders_loop;
368 for my $order (@results) {
369 my $line = get_order_infos( $order, $bookseller);
370 push @cancelledorders_loop, $line;
373 my $contract = &GetContract($basket->{contractnumber});
374 my @orders = GetOrders($basketno);
376 if ($basket->{basketgroupid}){
377 $basketgroup = GetBasketgroup($basket->{basketgroupid});
378 $basketgroup->{deliveryplacename} = C4::Branch::GetBranchName( $basketgroup->{deliveryplace} );
379 $basketgroup->{billingplacename} = C4::Branch::GetBranchName( $basketgroup->{billingplace} );
381 my $borrower= GetMember('borrowernumber' => $loggedinuser);
382 my $budgets = GetBudgetHierarchy;
383 my $has_budgets = 0;
384 foreach my $r (@{$budgets}) {
385 if (!defined $r->{budget_amount} || $r->{budget_amount} == 0) {
386 next;
388 next unless (CanUserUseBudget($loggedinuser, $r, $userflags));
390 $has_budgets = 1;
391 last;
394 $template->param(
395 basketno => $basketno,
396 basketname => $basket->{'basketname'},
397 basketbranchname => C4::Branch::GetBranchName($basket->{branch}),
398 basketnote => $basket->{note},
399 basketbooksellernote => $basket->{booksellernote},
400 basketcontractno => $basket->{contractnumber},
401 basketcontractname => $contract->{contractname},
402 branches_loop => \@branches_loop,
403 creationdate => $basket->{creationdate},
404 authorisedby => $basket->{authorisedby},
405 authorisedbyname => $basket->{authorisedbyname},
406 basketusers_ids => join(':', @basketusers_ids),
407 basketusers => \@basketusers,
408 closedate => $basket->{closedate},
409 estimateddeliverydate=> $estimateddeliverydate,
410 deliveryplace => C4::Branch::GetBranchName( $basket->{deliveryplace} ),
411 billingplace => C4::Branch::GetBranchName( $basket->{billingplace} ),
412 active => $bookseller->{'active'},
413 booksellerid => $bookseller->{'id'},
414 name => $bookseller->{'name'},
415 books_loop => \@books_loop,
416 book_foot_loop => \@book_foot_loop,
417 cancelledorders_loop => \@cancelledorders_loop,
418 total_quantity => $total_quantity,
419 total_gste => sprintf( "%.2f", $total_gste ),
420 total_gsti => sprintf( "%.2f", $total_gsti ),
421 total_gstvalue => sprintf( "%.2f", $total_gstvalue ),
422 currency => $cur->{'currency'},
423 listincgst => $bookseller->{listincgst},
424 basketgroups => $basketgroups,
425 basketgroup => $basketgroup,
426 grouped => $basket->{basketgroupid},
427 unclosable => @orders ? 0 : 1,
428 has_budgets => $has_budgets,
432 sub get_order_infos {
433 my $order = shift;
434 my $bookseller = shift;
435 my $qty = $order->{'quantity'} || 0;
436 if ( !defined $order->{quantityreceived} ) {
437 $order->{quantityreceived} = 0;
439 my $budget = GetBudget( $order->{'budget_id'} );
441 my %line = %{ $order };
442 $line{order_received} = ( $qty == $order->{'quantityreceived'} );
443 $line{basketno} = $basketno;
444 $line{budget_name} = $budget->{budget_name};
445 $line{rrp} = ConvertCurrency( $order->{'currency'}, $line{rrp} ); # FIXME from comm
446 if ( $bookseller->{'listincgst'} ) {
447 $line{rrpgsti} = sprintf( "%.2f", $line{rrp} );
448 $line{gstgsti} = sprintf( "%.2f", $line{gstrate} * 100 );
449 $line{rrpgste} = sprintf( "%.2f", $line{rrp} / ( 1 + ( $line{gstgsti} / 100 ) ) );
450 $line{gstgste} = sprintf( "%.2f", $line{gstgsti} / ( 1 + ( $line{gstgsti} / 100 ) ) );
451 $line{ecostgsti} = sprintf( "%.2f", $line{ecost} );
452 $line{ecostgste} = sprintf( "%.2f", $line{ecost} / ( 1 + ( $line{gstgsti} / 100 ) ) );
453 $line{gstvalue} = sprintf( "%.2f", ( $line{ecostgsti} - $line{ecostgste} ) * $line{quantity});
454 $line{totalgste} = sprintf( "%.2f", $order->{quantity} * $line{ecostgste} );
455 $line{totalgsti} = sprintf( "%.2f", $order->{quantity} * $line{ecostgsti} );
456 } else {
457 $line{rrpgsti} = sprintf( "%.2f", $line{rrp} * ( 1 + ( $line{gstrate} ) ) );
458 $line{rrpgste} = sprintf( "%.2f", $line{rrp} );
459 $line{gstgsti} = sprintf( "%.2f", $line{gstrate} * 100 );
460 $line{gstgste} = sprintf( "%.2f", $line{gstrate} * 100 );
461 $line{ecostgsti} = sprintf( "%.2f", $line{ecost} * ( 1 + ( $line{gstrate} ) ) );
462 $line{ecostgste} = sprintf( "%.2f", $line{ecost} );
463 $line{gstvalue} = sprintf( "%.2f", ( $line{ecostgsti} - $line{ecostgste} ) * $line{quantity});
464 $line{totalgste} = sprintf( "%.2f", $order->{quantity} * $line{ecostgste} );
465 $line{totalgsti} = sprintf( "%.2f", $order->{quantity} * $line{ecostgsti} );
468 if ( $line{uncertainprice} ) {
469 $line{rrpgste} .= ' (Uncertain)';
471 if ( $line{'title'} ) {
472 my $volume = $order->{'volume'};
473 my $seriestitle = $order->{'seriestitle'};
474 $line{'title'} .= " / $seriestitle" if $seriestitle;
475 $line{'title'} .= " / $volume" if $volume;
476 } else {
477 $line{'title'} = "Deleted bibliographic notice, can't find title.";
480 my $biblionumber = $order->{'biblionumber'};
481 my $countbiblio = CountBiblioInOrders($biblionumber);
482 my $ordernumber = $order->{'ordernumber'};
483 my @subscriptions = GetSubscriptionsId ($biblionumber);
484 my $itemcount = GetItemsCount($biblionumber);
485 my $holds = GetHolds ($biblionumber);
486 my @items = GetItemnumbersFromOrder( $ordernumber );
487 my $itemholds;
488 foreach my $item (@items){
489 my $nb = GetItemHolds($biblionumber, $item);
490 if ($nb){
491 $itemholds += $nb;
494 # if the biblio is not in other orders and if there is no items elsewhere and no subscriptions and no holds we can then show the link "Delete order and Biblio" see bug 5680
495 $line{can_del_bib} = 1 if $countbiblio <= 1 && $itemcount == scalar @items && !(@subscriptions) && !($holds);
496 $line{items} = ($itemcount) - (scalar @items);
497 $line{left_item} = 1 if $line{items} >= 1;
498 $line{left_biblio} = 1 if $countbiblio > 1;
499 $line{biblios} = $countbiblio - 1;
500 $line{left_subscription} = 1 if scalar @subscriptions >= 1;
501 $line{subscriptions} = scalar @subscriptions;
502 ($holds >= 1) ? $line{left_holds} = 1 : $line{left_holds} = 0;
503 $line{left_holds_on_order} = 1 if $line{left_holds}==1 && ($line{items} == 0 || $itemholds );
504 $line{holds} = $holds;
505 $line{holds_on_order} = $itemholds?$itemholds:$holds if $line{left_holds_on_order};
508 my $suggestion = GetSuggestionInfoFromBiblionumber($line{biblionumber});
509 $line{suggestionid} = $$suggestion{suggestionid};
510 $line{surnamesuggestedby} = $$suggestion{surnamesuggestedby};
511 $line{firstnamesuggestedby} = $$suggestion{firstnamesuggestedby};
513 foreach my $key (qw(transferred_from transferred_to)) {
514 if ($line{$key}) {
515 my $order = GetOrder($line{$key});
516 my $basket = GetBasket($order->{basketno});
517 my $bookseller = GetBookSellerFromId($basket->{booksellerid});
518 $line{$key} = {
519 order => $order,
520 basket => $basket,
521 bookseller => $bookseller,
522 timestamp => $line{$key . '_timestamp'},
527 return \%line;
530 output_html_with_http_headers $query, $cookie, $template->output;