Bug 10181: Make string translatable
[koha.git] / acqui / basket.pl
blobf6e21d72e4e49c50c1a8a8b99abb559b71e648e3
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
11 # under the terms of the GNU General Public License as published by
12 # the Free Software Foundation; either version 3 of the License, or
13 # (at your option) any later version.
15 # Koha is distributed in the hope that it will be useful, but
16 # WITHOUT ANY WARRANTY; without even the implied warranty of
17 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 # GNU General Public License for more details.
20 # You should have received a copy of the GNU General Public License
21 # along with Koha; if not, see <http://www.gnu.org/licenses>.
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::Contract;
34 use C4::Debug;
35 use C4::Biblio;
36 use C4::Members qw/GetMember/; #needed for permissions checking for changing basketgroup of a basket
37 use C4::Items;
38 use C4::Suggestions;
39 use Date::Calc qw/Add_Delta_Days/;
41 =head1 NAME
43 basket.pl
45 =head1 DESCRIPTION
47 This script display all informations about basket for the supplier given
48 on input arg. Moreover, it allows us to add a new order for this supplier from
49 an existing record, a suggestion or a new record.
51 =head1 CGI PARAMETERS
53 =over 4
55 =item $basketno
57 The basket number.
59 =item booksellerid
61 the supplier this script have to display the basket.
63 =item order
65 =back
67 =cut
69 my $query = new CGI;
70 our $basketno = $query->param('basketno');
71 my $booksellerid = $query->param('booksellerid');
73 my ( $template, $loggedinuser, $cookie, $userflags ) = get_template_and_user(
75 template_name => "acqui/basket.tt",
76 query => $query,
77 type => "intranet",
78 authnotrequired => 0,
79 flagsrequired => { acquisition => 'order_manage' },
80 debug => 1,
84 my $basket = GetBasket($basketno);
85 $booksellerid = $basket->{booksellerid} unless $booksellerid;
86 my ($bookseller) = GetBookSellerFromId($booksellerid);
88 unless (CanUserManageBasket($loggedinuser, $basket, $userflags)) {
89 $template->param(
90 cannot_manage_basket => 1,
91 basketno => $basketno,
92 basketname => $basket->{basketname},
93 booksellerid => $booksellerid,
94 name => $bookseller->{name}
96 output_html_with_http_headers $query, $cookie, $template->output;
97 exit;
100 # FIXME : what about the "discount" percentage?
101 # FIXME : the query->param('booksellerid') below is probably useless. The bookseller is always known from the basket
102 # if no booksellerid in parameter, get it from basket
103 # warn "=>".$basket->{booksellerid};
104 my $op = $query->param('op');
105 if (!defined $op) {
106 $op = q{};
109 my $confirm_pref= C4::Context->preference("BasketConfirmations") || '1';
110 $template->param( skip_confirm_reopen => 1) if $confirm_pref eq '2';
112 if ( $op eq 'delete_confirm' ) {
113 my $basketno = $query->param('basketno');
114 my $delbiblio = $query->param('delbiblio');
115 my @orders = GetOrders($basketno);
116 #Delete all orders included in that basket, and all items received.
117 foreach my $myorder (@orders){
118 DelOrder($myorder->{biblionumber},$myorder->{ordernumber});
120 # if $delbiblio = 1, delete the records if possible
121 if ((defined $delbiblio)and ($delbiblio ==1)){
122 my @cannotdelbiblios ;
123 foreach my $myorder (@orders){
124 my $biblionumber = $myorder->{'biblionumber'};
125 my $countbiblio = CountBiblioInOrders($biblionumber);
126 my $ordernumber = $myorder->{'ordernumber'};
127 my $subscriptions = scalar GetSubscriptionsId ($biblionumber);
128 my $itemcount = GetItemsCount($biblionumber);
129 my $error;
130 if ($countbiblio == 0 && $itemcount == 0 && $subscriptions == 0) {
131 $error = DelBiblio($myorder->{biblionumber}) }
132 else {
133 push @cannotdelbiblios, {biblionumber=> ($myorder->{biblionumber}),
134 title=> $myorder->{'title'},
135 author=> $myorder->{'author'},
136 countbiblio=> $countbiblio,
137 itemcount=>$itemcount,
138 subscriptions=>$subscriptions};
140 if ($error) {
141 push @cannotdelbiblios, {biblionumber=> ($myorder->{biblionumber}),
142 title=> $myorder->{'title'},
143 author=> $myorder->{'author'},
144 othererror=> $error};
147 $template->param( cannotdelbiblios => \@cannotdelbiblios );
149 # delete the basket
150 DelBasket($basketno,);
151 $template->param( delete_confirmed => 1 );
152 } elsif ( !$bookseller ) {
153 $template->param( NO_BOOKSELLER => 1 );
154 } elsif ( $op eq 'del_basket') {
155 $template->param( delete_confirm => 1 );
156 if ( C4::Context->preference("IndependentBranches") ) {
157 my $userenv = C4::Context->userenv;
158 unless ( C4::Context->IsSuperLibrarian() ) {
159 my $validtest = ( $basket->{creationdate} eq '' )
160 || ( $userenv->{branch} eq $basket->{branch} )
161 || ( $userenv->{branch} eq '' )
162 || ( $basket->{branch} eq '' );
163 unless ($validtest) {
164 print $query->redirect("../mainpage.pl");
165 exit 1;
169 $basket->{creationdate} = "" unless ( $basket->{creationdate} );
170 $basket->{authorisedby} = $loggedinuser unless ( $basket->{authorisedby} );
171 my $contract = GetContract({
172 contractnumber => $basket->{contractnumber}
174 $template->param(
175 basketno => $basketno,
176 basketname => $basket->{'basketname'},
177 basketnote => $basket->{note},
178 basketbooksellernote => $basket->{booksellernote},
179 basketcontractno => $basket->{contractnumber},
180 basketcontractname => $contract->{contractname},
181 creationdate => $basket->{creationdate},
182 authorisedby => $basket->{authorisedby},
183 authorisedbyname => $basket->{authorisedbyname},
184 closedate => $basket->{closedate},
185 deliveryplace => $basket->{deliveryplace},
186 billingplace => $basket->{billingplace},
187 active => $bookseller->{'active'},
188 booksellerid => $bookseller->{'id'},
189 name => $bookseller->{'name'},
190 address1 => $bookseller->{'address1'},
191 address2 => $bookseller->{'address2'},
192 address3 => $bookseller->{'address3'},
193 address4 => $bookseller->{'address4'},
195 } elsif ($op eq 'export') {
196 print $query->header(
197 -type => 'text/csv',
198 -attachment => 'basket' . $basket->{'basketno'} . '.csv',
200 print GetBasketAsCSV($query->param('basketno'), $query);
201 exit;
202 } elsif ($op eq 'close') {
203 my $confirm = $query->param('confirm') || $confirm_pref eq '2';
204 if ($confirm) {
205 my $basketno = $query->param('basketno');
206 my $booksellerid = $query->param('booksellerid');
207 $basketno =~ /^\d+$/ and CloseBasket($basketno);
208 # if requested, create basket group, close it and attach the basket
209 if ($query->param('createbasketgroup')) {
210 my $branchcode;
211 if(C4::Context->userenv and C4::Context->userenv->{'branch'}
212 and C4::Context->userenv->{'branch'} ne "NO_LIBRARY_SET") {
213 $branchcode = C4::Context->userenv->{'branch'};
215 my $basketgroupid = NewBasketgroup( { name => $basket->{basketname},
216 booksellerid => $booksellerid,
217 deliveryplace => $branchcode,
218 billingplace => $branchcode,
219 closed => 1,
221 ModBasket( { basketno => $basketno,
222 basketgroupid => $basketgroupid } );
223 print $query->redirect('/cgi-bin/koha/acqui/basketgroup.pl?booksellerid='.$booksellerid.'&closed=1');
224 } else {
225 print $query->redirect('/cgi-bin/koha/acqui/booksellers.pl?booksellerid=' . $booksellerid);
227 exit;
228 } else {
229 $template->param(
230 confirm_close => "1",
231 booksellerid => $booksellerid,
232 basketno => $basket->{'basketno'},
233 basketname => $basket->{'basketname'},
234 basketgroupname => $basket->{'basketname'},
237 } elsif ($op eq 'reopen') {
238 ReopenBasket($query->param('basketno'));
239 print $query->redirect('/cgi-bin/koha/acqui/basket.pl?basketno='.$basket->{'basketno'})
240 } elsif ( $op eq 'mod_users' ) {
241 my $basketusers_ids = $query->param('basketusers_ids');
242 my @basketusers = split( /:/, $basketusers_ids );
243 ModBasketUsers($basketno, @basketusers);
244 print $query->redirect("/cgi-bin/koha/acqui/basket.pl?basketno=$basketno");
245 exit;
246 } elsif ( $op eq 'mod_branch' ) {
247 my $branch = $query->param('branch');
248 $branch = undef if(defined $branch and $branch eq '');
249 ModBasket({
250 basketno => $basket->{basketno},
251 branch => $branch
253 print $query->redirect("/cgi-bin/koha/acqui/basket.pl?basketno=$basketno");
254 exit;
255 } else {
256 my @branches_loop;
257 # get librarian branch...
258 if ( C4::Context->preference("IndependentBranches") ) {
259 my $userenv = C4::Context->userenv;
260 unless ( C4::Context->IsSuperLibrarian() ) {
261 my $validtest = ( $basket->{creationdate} eq '' )
262 || ( $userenv->{branch} eq $basket->{branch} )
263 || ( $userenv->{branch} eq '' )
264 || ( $basket->{branch} eq '' );
265 unless ($validtest) {
266 print $query->redirect("../mainpage.pl");
267 exit 1;
270 if (!defined $basket->{branch} or $basket->{branch} eq $userenv->{branch}) {
271 push @branches_loop, {
272 branchcode => $userenv->{branch},
273 branchname => $userenv->{branchname},
274 selected => 1,
277 } else {
278 # get branches
279 my $branches = C4::Branch::GetBranches;
280 my @branchcodes = sort {
281 $branches->{$a}->{branchname} cmp $branches->{$b}->{branchname}
282 } keys %$branches;
283 foreach my $branch (@branchcodes) {
284 my $selected = 0;
285 if (defined $basket->{branch}) {
286 $selected = 1 if $branch eq $basket->{branch};
287 } else {
288 $selected = 1 if $branch eq C4::Context->userenv->{branch};
290 push @branches_loop, {
291 branchcode => $branch,
292 branchname => $branches->{$branch}->{branchname},
293 selected => $selected
298 #if the basket is closed,and the user has the permission to edit basketgroups, display a list of basketgroups
299 my ($basketgroup, $basketgroups);
300 my $staffuser = GetMember(borrowernumber => $loggedinuser);
301 if ($basket->{closedate} && haspermission($staffuser->{userid}, { acquisition => 'group_manage'} )) {
302 $basketgroups = GetBasketgroups($basket->{booksellerid});
303 for my $bg ( @{$basketgroups} ) {
304 if ($basket->{basketgroupid} && $basket->{basketgroupid} == $bg->{id}){
305 $bg->{default} = 1;
306 $basketgroup = $bg;
311 # if the basket is closed, calculate estimated delivery date
312 my $estimateddeliverydate;
313 if( $basket->{closedate} ) {
314 my ($year, $month, $day) = ($basket->{closedate} =~ /(\d+)-(\d+)-(\d+)/);
315 ($year, $month, $day) = Add_Delta_Days($year, $month, $day, $bookseller->{deliverytime});
316 $estimateddeliverydate = "$year-$month-$day";
319 # if new basket, pre-fill infos
320 $basket->{creationdate} = "" unless ( $basket->{creationdate} );
321 $basket->{authorisedby} = $loggedinuser unless ( $basket->{authorisedby} );
322 $debug
323 and warn sprintf
324 "loggedinuser: $loggedinuser; creationdate: %s; authorisedby: %s",
325 $basket->{creationdate}, $basket->{authorisedby};
327 my @basketusers_ids = GetBasketUsers($basketno);
328 my @basketusers;
329 foreach my $basketuser_id (@basketusers_ids) {
330 my $basketuser = GetMember(borrowernumber => $basketuser_id);
331 push @basketusers, $basketuser if $basketuser;
334 #to get active currency
335 my $cur = GetCurrency();
338 my @results = GetOrders( $basketno );
339 my @books_loop;
341 my @book_foot_loop;
342 my %foot;
343 my $total_quantity = 0;
344 my $total_gste = 0;
345 my $total_gsti = 0;
346 my $total_gstvalue = 0;
347 for my $order (@results) {
348 my $line = get_order_infos( $order, $bookseller);
349 if ( $line->{uncertainprice} ) {
350 $template->param( uncertainprices => 1 );
353 push @books_loop, $line;
355 $foot{$$line{gstgsti}}{gstgsti} = $$line{gstgsti};
356 $foot{$$line{gstgsti}}{gstvalue} += $$line{gstvalue};
357 $total_gstvalue += $$line{gstvalue};
358 $foot{$$line{gstgsti}}{quantity} += $$line{quantity};
359 $total_quantity += $$line{quantity};
360 $foot{$$line{gstgsti}}{totalgste} += $$line{totalgste};
361 $total_gste += $$line{totalgste};
362 $foot{$$line{gstgsti}}{totalgsti} += $$line{totalgsti};
363 $total_gsti += $$line{totalgsti};
366 push @book_foot_loop, map {$_} values %foot;
368 # Get cancelled orders
369 @results = GetCancelledOrders($basketno);
370 my @cancelledorders_loop;
371 for my $order (@results) {
372 my $line = get_order_infos( $order, $bookseller);
373 push @cancelledorders_loop, $line;
376 my $contract = GetContract({
377 contractnumber => $basket->{contractnumber}
379 my @orders = GetOrders($basketno);
381 if ($basket->{basketgroupid}){
382 $basketgroup = GetBasketgroup($basket->{basketgroupid});
383 $basketgroup->{deliveryplacename} = C4::Branch::GetBranchName( $basketgroup->{deliveryplace} );
384 $basketgroup->{billingplacename} = C4::Branch::GetBranchName( $basketgroup->{billingplace} );
386 my $borrower= GetMember('borrowernumber' => $loggedinuser);
387 my $budgets = GetBudgetHierarchy;
388 my $has_budgets = 0;
389 foreach my $r (@{$budgets}) {
390 if (!defined $r->{budget_amount} || $r->{budget_amount} == 0) {
391 next;
393 next unless (CanUserUseBudget($loggedinuser, $r, $userflags));
395 $has_budgets = 1;
396 last;
399 $template->param(
400 basketno => $basketno,
401 basketname => $basket->{'basketname'},
402 basketbranchname => C4::Branch::GetBranchName($basket->{branch}),
403 basketnote => $basket->{note},
404 basketbooksellernote => $basket->{booksellernote},
405 basketcontractno => $basket->{contractnumber},
406 basketcontractname => $contract->{contractname},
407 branches_loop => \@branches_loop,
408 creationdate => $basket->{creationdate},
409 authorisedby => $basket->{authorisedby},
410 authorisedbyname => $basket->{authorisedbyname},
411 basketusers_ids => join(':', @basketusers_ids),
412 basketusers => \@basketusers,
413 closedate => $basket->{closedate},
414 estimateddeliverydate=> $estimateddeliverydate,
415 deliveryplace => C4::Branch::GetBranchName( $basket->{deliveryplace} ),
416 billingplace => C4::Branch::GetBranchName( $basket->{billingplace} ),
417 active => $bookseller->{'active'},
418 booksellerid => $bookseller->{'id'},
419 name => $bookseller->{'name'},
420 books_loop => \@books_loop,
421 book_foot_loop => \@book_foot_loop,
422 cancelledorders_loop => \@cancelledorders_loop,
423 total_quantity => $total_quantity,
424 total_gste => sprintf( "%.2f", $total_gste ),
425 total_gsti => sprintf( "%.2f", $total_gsti ),
426 total_gstvalue => sprintf( "%.2f", $total_gstvalue ),
427 currency => $cur->{'currency'},
428 listincgst => $bookseller->{listincgst},
429 basketgroups => $basketgroups,
430 basketgroup => $basketgroup,
431 grouped => $basket->{basketgroupid},
432 unclosable => @orders ? 0 : 1,
433 has_budgets => $has_budgets,
437 sub get_order_infos {
438 my $order = shift;
439 my $bookseller = shift;
440 my $qty = $order->{'quantity'} || 0;
441 if ( !defined $order->{quantityreceived} ) {
442 $order->{quantityreceived} = 0;
444 my $budget = GetBudget( $order->{'budget_id'} );
446 my %line = %{ $order };
447 $line{order_received} = ( $qty == $order->{'quantityreceived'} );
448 $line{basketno} = $basketno;
449 $line{budget_name} = $budget->{budget_name};
450 $line{rrp} = ConvertCurrency( $order->{'currency'}, $line{rrp} ); # FIXME from comm
451 if ( $bookseller->{'listincgst'} ) {
452 $line{rrpgsti} = sprintf( "%.2f", $line{rrp} );
453 $line{gstgsti} = sprintf( "%.2f", $line{gstrate} * 100 );
454 $line{rrpgste} = sprintf( "%.2f", $line{rrp} / ( 1 + ( $line{gstgsti} / 100 ) ) );
455 $line{gstgste} = sprintf( "%.2f", $line{gstgsti} / ( 1 + ( $line{gstgsti} / 100 ) ) );
456 $line{ecostgsti} = sprintf( "%.2f", $line{ecost} );
457 $line{ecostgste} = sprintf( "%.2f", $line{ecost} / ( 1 + ( $line{gstgsti} / 100 ) ) );
458 $line{gstvalue} = sprintf( "%.2f", ( $line{ecostgsti} - $line{ecostgste} ) * $line{quantity});
459 $line{totalgste} = sprintf( "%.2f", $order->{quantity} * $line{ecostgste} );
460 $line{totalgsti} = sprintf( "%.2f", $order->{quantity} * $line{ecostgsti} );
461 } else {
462 $line{rrpgsti} = sprintf( "%.2f", $line{rrp} * ( 1 + ( $line{gstrate} ) ) );
463 $line{rrpgste} = sprintf( "%.2f", $line{rrp} );
464 $line{gstgsti} = sprintf( "%.2f", $line{gstrate} * 100 );
465 $line{gstgste} = sprintf( "%.2f", $line{gstrate} * 100 );
466 $line{ecostgsti} = sprintf( "%.2f", $line{ecost} * ( 1 + ( $line{gstrate} ) ) );
467 $line{ecostgste} = sprintf( "%.2f", $line{ecost} );
468 $line{gstvalue} = sprintf( "%.2f", ( $line{ecostgsti} - $line{ecostgste} ) * $line{quantity});
469 $line{totalgste} = sprintf( "%.2f", $order->{quantity} * $line{ecostgste} );
470 $line{totalgsti} = sprintf( "%.2f", $order->{quantity} * $line{ecostgsti} );
473 if ( $line{uncertainprice} ) {
474 $line{rrpgste} .= ' (Uncertain)';
476 if ( $line{'title'} ) {
477 my $volume = $order->{'volume'};
478 my $seriestitle = $order->{'seriestitle'};
479 $line{'title'} .= " / $seriestitle" if $seriestitle;
480 $line{'title'} .= " / $volume" if $volume;
483 my $biblionumber = $order->{'biblionumber'};
484 my $countbiblio = CountBiblioInOrders($biblionumber);
485 my $ordernumber = $order->{'ordernumber'};
486 my @subscriptions = GetSubscriptionsId ($biblionumber);
487 my $itemcount = GetItemsCount($biblionumber);
488 my $holds = GetHolds ($biblionumber);
489 my @items = GetItemnumbersFromOrder( $ordernumber );
490 my $itemholds;
491 foreach my $item (@items){
492 my $nb = GetItemHolds($biblionumber, $item);
493 if ($nb){
494 $itemholds += $nb;
497 # 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
498 $line{can_del_bib} = 1 if $countbiblio <= 1 && $itemcount == scalar @items && !(@subscriptions) && !($holds);
499 $line{items} = ($itemcount) - (scalar @items);
500 $line{left_item} = 1 if $line{items} >= 1;
501 $line{left_biblio} = 1 if $countbiblio > 1;
502 $line{biblios} = $countbiblio - 1;
503 $line{left_subscription} = 1 if scalar @subscriptions >= 1;
504 $line{subscriptions} = scalar @subscriptions;
505 ($holds >= 1) ? $line{left_holds} = 1 : $line{left_holds} = 0;
506 $line{left_holds_on_order} = 1 if $line{left_holds}==1 && ($line{items} == 0 || $itemholds );
507 $line{holds} = $holds;
508 $line{holds_on_order} = $itemholds?$itemholds:$holds if $line{left_holds_on_order};
511 my $suggestion = GetSuggestionInfoFromBiblionumber($line{biblionumber});
512 $line{suggestionid} = $$suggestion{suggestionid};
513 $line{surnamesuggestedby} = $$suggestion{surnamesuggestedby};
514 $line{firstnamesuggestedby} = $$suggestion{firstnamesuggestedby};
516 foreach my $key (qw(transferred_from transferred_to)) {
517 if ($line{$key}) {
518 my $order = GetOrder($line{$key});
519 my $basket = GetBasket($order->{basketno});
520 my $bookseller = GetBookSellerFromId($basket->{booksellerid});
521 $line{$key} = {
522 order => $order,
523 basket => $basket,
524 bookseller => $bookseller,
525 timestamp => $line{$key . '_timestamp'},
530 return \%line;
533 output_html_with_http_headers $query, $cookie, $template->output;