Bug 9261: (follow-up) make title required when adding a new suggestion
[koha.git] / acqui / basket.pl
blobe8b4199d5902dc6c974d972d7629021e186b9344
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.tmpl",
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 DelBasket($basketno);
114 $template->param( delete_confirmed => 1 );
115 } elsif ( !$bookseller ) {
116 $template->param( NO_BOOKSELLER => 1 );
117 } elsif ( $op eq 'del_basket') {
118 $template->param( delete_confirm => 1 );
119 if ( C4::Context->preference("IndependentBranches") ) {
120 my $userenv = C4::Context->userenv;
121 unless ( $userenv->{flags} == 1 ) {
122 my $validtest = ( $basket->{creationdate} eq '' )
123 || ( $userenv->{branch} eq $basket->{branch} )
124 || ( $userenv->{branch} eq '' )
125 || ( $basket->{branch} eq '' );
126 unless ($validtest) {
127 print $query->redirect("../mainpage.pl");
128 exit 1;
132 $basket->{creationdate} = "" unless ( $basket->{creationdate} );
133 $basket->{authorisedby} = $loggedinuser unless ( $basket->{authorisedby} );
134 my $contract = &GetContract($basket->{contractnumber});
135 $template->param(
136 basketno => $basketno,
137 basketname => $basket->{'basketname'},
138 basketnote => $basket->{note},
139 basketbooksellernote => $basket->{booksellernote},
140 basketcontractno => $basket->{contractnumber},
141 basketcontractname => $contract->{contractname},
142 creationdate => $basket->{creationdate},
143 authorisedby => $basket->{authorisedby},
144 authorisedbyname => $basket->{authorisedbyname},
145 closedate => $basket->{closedate},
146 deliveryplace => $basket->{deliveryplace},
147 billingplace => $basket->{billingplace},
148 active => $bookseller->{'active'},
149 booksellerid => $bookseller->{'id'},
150 name => $bookseller->{'name'},
151 address1 => $bookseller->{'address1'},
152 address2 => $bookseller->{'address2'},
153 address3 => $bookseller->{'address3'},
154 address4 => $bookseller->{'address4'},
156 } elsif ($op eq 'attachbasket' && $template->{'VARS'}->{'CAN_user_acquisition_group_manage'} == 1) {
157 print $query->redirect('/cgi-bin/koha/acqui/basketgroup.pl?basketno=' . $basket->{'basketno'} . '&op=attachbasket&booksellerid=' . $booksellerid);
158 # check if we have to "close" a basket before building page
159 } elsif ($op eq 'export') {
160 print $query->header(
161 -type => 'text/csv',
162 -attachment => 'basket' . $basket->{'basketno'} . '.csv',
164 print GetBasketAsCSV($query->param('basketno'), $query);
165 exit;
166 } elsif ($op eq 'close') {
167 my $confirm = $query->param('confirm') || $confirm_pref eq '2';
168 if ($confirm) {
169 my $basketno = $query->param('basketno');
170 my $booksellerid = $query->param('booksellerid');
171 $basketno =~ /^\d+$/ and CloseBasket($basketno);
172 # if requested, create basket group, close it and attach the basket
173 if ($query->param('createbasketgroup')) {
174 my $branchcode;
175 if(C4::Context->userenv and C4::Context->userenv->{'branch'}
176 and C4::Context->userenv->{'branch'} ne "NO_LIBRARY_SET") {
177 $branchcode = C4::Context->userenv->{'branch'};
179 my $basketgroupid = NewBasketgroup( { name => $basket->{basketname},
180 booksellerid => $booksellerid,
181 deliveryplace => $branchcode,
182 billingplace => $branchcode,
183 closed => 1,
185 ModBasket( { basketno => $basketno,
186 basketgroupid => $basketgroupid } );
187 print $query->redirect('/cgi-bin/koha/acqui/basketgroup.pl?booksellerid='.$booksellerid.'&closed=1');
188 } else {
189 print $query->redirect('/cgi-bin/koha/acqui/booksellers.pl?booksellerid=' . $booksellerid);
191 exit;
192 } else {
193 $template->param(
194 confirm_close => "1",
195 booksellerid => $booksellerid,
196 basketno => $basket->{'basketno'},
197 basketname => $basket->{'basketname'},
198 basketgroupname => $basket->{'basketname'},
201 } elsif ($op eq 'reopen') {
202 ReopenBasket($query->param('basketno'));
203 print $query->redirect('/cgi-bin/koha/acqui/basket.pl?basketno='.$basket->{'basketno'})
204 } elsif ( $op eq 'mod_users' ) {
205 my $basketusers_ids = $query->param('basketusers_ids');
206 my @basketusers = split( /:/, $basketusers_ids );
207 ModBasketUsers($basketno, @basketusers);
208 print $query->redirect("/cgi-bin/koha/acqui/basket.pl?basketno=$basketno");
209 exit;
210 } elsif ( $op eq 'mod_branch' ) {
211 my $branch = $query->param('branch');
212 $branch = undef if(defined $branch and $branch eq '');
213 ModBasket({
214 basketno => $basket->{basketno},
215 branch => $branch
217 print $query->redirect("/cgi-bin/koha/acqui/basket.pl?basketno=$basketno");
218 exit;
219 } else {
220 my @branches_loop;
221 # get librarian branch...
222 if ( C4::Context->preference("IndependentBranches") ) {
223 my $userenv = C4::Context->userenv;
224 unless ( $userenv->{flags} == 1 ) {
225 my $validtest = ( $basket->{creationdate} eq '' )
226 || ( $userenv->{branch} eq $basket->{branch} )
227 || ( $userenv->{branch} eq '' )
228 || ( $basket->{branch} eq '' );
229 unless ($validtest) {
230 print $query->redirect("../mainpage.pl");
231 exit 1;
234 if (!defined $basket->{branch} or $basket->{branch} eq $userenv->{branch}) {
235 push @branches_loop, {
236 branchcode => $userenv->{branch},
237 branchname => $userenv->{branchname},
238 selected => 1,
241 } else {
242 # get branches
243 my $branches = C4::Branch::GetBranches;
244 my @branchcodes = sort {
245 $branches->{$a}->{branchname} cmp $branches->{$b}->{branchname}
246 } keys %$branches;
247 foreach my $branch (@branchcodes) {
248 my $selected = 0;
249 if (defined $basket->{branch}) {
250 $selected = 1 if $branch eq $basket->{branch};
251 } else {
252 $selected = 1 if $branch eq C4::Context->userenv->{branch};
254 push @branches_loop, {
255 branchcode => $branch,
256 branchname => $branches->{$branch}->{branchname},
257 selected => $selected
262 #if the basket is closed,and the user has the permission to edit basketgroups, display a list of basketgroups
263 my ($basketgroup, $basketgroups);
264 my $staffuser = GetMember(borrowernumber => $loggedinuser);
265 if ($basket->{closedate} && haspermission($staffuser->{userid}, { acquisition => 'group_manage'} )) {
266 $basketgroups = GetBasketgroups($basket->{booksellerid});
267 for my $bg ( @{$basketgroups} ) {
268 if ($basket->{basketgroupid} && $basket->{basketgroupid} == $bg->{id}){
269 $bg->{default} = 1;
270 $basketgroup = $bg;
273 my %emptygroup = ( id => undef,
274 name => "No group");
275 if ( ! $basket->{basketgroupid} ) {
276 $emptygroup{default} = 1;
277 $emptygroup{nogroup} = 1;
279 unshift( @$basketgroups, \%emptygroup );
282 # if the basket is closed, calculate estimated delivery date
283 my $estimateddeliverydate;
284 if( $basket->{closedate} ) {
285 my ($year, $month, $day) = ($basket->{closedate} =~ /(\d+)-(\d+)-(\d+)/);
286 ($year, $month, $day) = Add_Delta_Days($year, $month, $day, $bookseller->{deliverytime});
287 $estimateddeliverydate = "$year-$month-$day";
290 # if new basket, pre-fill infos
291 $basket->{creationdate} = "" unless ( $basket->{creationdate} );
292 $basket->{authorisedby} = $loggedinuser unless ( $basket->{authorisedby} );
293 $debug
294 and warn sprintf
295 "loggedinuser: $loggedinuser; creationdate: %s; authorisedby: %s",
296 $basket->{creationdate}, $basket->{authorisedby};
298 my @basketusers_ids = GetBasketUsers($basketno);
299 my @basketusers;
300 foreach my $basketuser_id (@basketusers_ids) {
301 my $basketuser = GetMember(borrowernumber => $basketuser_id);
302 push @basketusers, $basketuser if $basketuser;
305 #to get active currency
306 my $cur = GetCurrency();
309 my @results = GetOrders( $basketno );
310 my @books_loop;
312 my @book_foot_loop;
313 my %foot;
314 my $total_quantity = 0;
315 my $total_gste = 0;
316 my $total_gsti = 0;
317 my $total_gstvalue = 0;
318 for my $order (@results) {
319 my $line = get_order_infos( $order, $bookseller);
320 if ( $line->{uncertainprice} ) {
321 $template->param( uncertainprices => 1 );
324 push @books_loop, $line;
326 $foot{$$line{gstgsti}}{gstgsti} = $$line{gstgsti};
327 $foot{$$line{gstgsti}}{gstvalue} += $$line{gstvalue};
328 $total_gstvalue += $$line{gstvalue};
329 $foot{$$line{gstgsti}}{quantity} += $$line{quantity};
330 $total_quantity += $$line{quantity};
331 $foot{$$line{gstgsti}}{totalgste} += $$line{totalgste};
332 $total_gste += $$line{totalgste};
333 $foot{$$line{gstgsti}}{totalgsti} += $$line{totalgsti};
334 $total_gsti += $$line{totalgsti};
337 push @book_foot_loop, map {$_} values %foot;
339 # Get cancelled orders
340 @results = GetCancelledOrders($basketno);
341 my @cancelledorders_loop;
342 for my $order (@results) {
343 my $line = get_order_infos( $order, $bookseller);
344 push @cancelledorders_loop, $line;
347 my $contract = &GetContract($basket->{contractnumber});
348 my @orders = GetOrders($basketno);
350 if ($basket->{basketgroupid}){
351 $basketgroup = GetBasketgroup($basket->{basketgroupid});
352 $basketgroup->{deliveryplacename} = C4::Branch::GetBranchName( $basketgroup->{deliveryplace} );
353 $basketgroup->{billingplacename} = C4::Branch::GetBranchName( $basketgroup->{billingplace} );
355 my $borrower= GetMember('borrowernumber' => $loggedinuser);
356 my $budgets = GetBudgetHierarchy;
357 my $has_budgets = 0;
358 foreach my $r (@{$budgets}) {
359 if (!defined $r->{budget_amount} || $r->{budget_amount} == 0) {
360 next;
362 next unless (CanUserUseBudget($loggedinuser, $r, $userflags));
364 $has_budgets = 1;
365 last;
368 $template->param(
369 basketno => $basketno,
370 basketname => $basket->{'basketname'},
371 basketbranchname => C4::Branch::GetBranchName($basket->{branch}),
372 basketnote => $basket->{note},
373 basketbooksellernote => $basket->{booksellernote},
374 basketcontractno => $basket->{contractnumber},
375 basketcontractname => $contract->{contractname},
376 branches_loop => \@branches_loop,
377 creationdate => $basket->{creationdate},
378 authorisedby => $basket->{authorisedby},
379 authorisedbyname => $basket->{authorisedbyname},
380 basketusers_ids => join(':', @basketusers_ids),
381 basketusers => \@basketusers,
382 closedate => $basket->{closedate},
383 estimateddeliverydate=> $estimateddeliverydate,
384 deliveryplace => C4::Branch::GetBranchName( $basket->{deliveryplace} ),
385 billingplace => C4::Branch::GetBranchName( $basket->{billingplace} ),
386 active => $bookseller->{'active'},
387 booksellerid => $bookseller->{'id'},
388 name => $bookseller->{'name'},
389 books_loop => \@books_loop,
390 book_foot_loop => \@book_foot_loop,
391 cancelledorders_loop => \@cancelledorders_loop,
392 total_quantity => $total_quantity,
393 total_gste => sprintf( "%.2f", $total_gste ),
394 total_gsti => sprintf( "%.2f", $total_gsti ),
395 total_gstvalue => sprintf( "%.2f", $total_gstvalue ),
396 currency => $cur->{'currency'},
397 listincgst => $bookseller->{listincgst},
398 basketgroups => $basketgroups,
399 basketgroup => $basketgroup,
400 grouped => $basket->{basketgroupid},
401 unclosable => @orders ? 0 : 1,
402 has_budgets => $has_budgets,
406 sub get_order_infos {
407 my $order = shift;
408 my $bookseller = shift;
409 my $qty = $order->{'quantity'} || 0;
410 if ( !defined $order->{quantityreceived} ) {
411 $order->{quantityreceived} = 0;
413 my $budget = GetBudget( $order->{'budget_id'} );
415 my %line = %{ $order };
416 $line{order_received} = ( $qty == $order->{'quantityreceived'} );
417 $line{basketno} = $basketno;
418 $line{budget_name} = $budget->{budget_name};
419 $line{rrp} = ConvertCurrency( $order->{'currency'}, $line{rrp} ); # FIXME from comm
420 if ( $bookseller->{'listincgst'} ) {
421 $line{rrpgsti} = sprintf( "%.2f", $line{rrp} );
422 $line{gstgsti} = sprintf( "%.2f", $line{gstrate} * 100 );
423 $line{rrpgste} = sprintf( "%.2f", $line{rrp} / ( 1 + ( $line{gstgsti} / 100 ) ) );
424 $line{gstgste} = sprintf( "%.2f", $line{gstgsti} / ( 1 + ( $line{gstgsti} / 100 ) ) );
425 $line{ecostgsti} = sprintf( "%.2f", $line{ecost} );
426 $line{ecostgste} = sprintf( "%.2f", $line{ecost} / ( 1 + ( $line{gstgsti} / 100 ) ) );
427 $line{gstvalue} = sprintf( "%.2f", ( $line{ecostgsti} - $line{ecostgste} ) * $line{quantity});
428 $line{totalgste} = sprintf( "%.2f", $order->{quantity} * $line{ecostgste} );
429 $line{totalgsti} = sprintf( "%.2f", $order->{quantity} * $line{ecostgsti} );
430 } else {
431 $line{rrpgsti} = sprintf( "%.2f", $line{rrp} * ( 1 + ( $line{gstrate} ) ) );
432 $line{rrpgste} = sprintf( "%.2f", $line{rrp} );
433 $line{gstgsti} = sprintf( "%.2f", $line{gstrate} * 100 );
434 $line{gstgste} = sprintf( "%.2f", $line{gstrate} * 100 );
435 $line{ecostgsti} = sprintf( "%.2f", $line{ecost} * ( 1 + ( $line{gstrate} ) ) );
436 $line{ecostgste} = sprintf( "%.2f", $line{ecost} );
437 $line{gstvalue} = sprintf( "%.2f", ( $line{ecostgsti} - $line{ecostgste} ) * $line{quantity});
438 $line{totalgste} = sprintf( "%.2f", $order->{quantity} * $line{ecostgste} );
439 $line{totalgsti} = sprintf( "%.2f", $order->{quantity} * $line{ecostgsti} );
442 if ( $line{uncertainprice} ) {
443 $line{rrpgste} .= ' (Uncertain)';
445 if ( $line{'title'} ) {
446 my $volume = $order->{'volume'};
447 my $seriestitle = $order->{'seriestitle'};
448 $line{'title'} .= " / $seriestitle" if $seriestitle;
449 $line{'title'} .= " / $volume" if $volume;
450 } else {
451 $line{'title'} = "Deleted bibliographic notice, can't find title.";
454 my $biblionumber = $order->{'biblionumber'};
455 my $countbiblio = CountBiblioInOrders($biblionumber);
456 my $ordernumber = $order->{'ordernumber'};
457 my @subscriptions = GetSubscriptionsId ($biblionumber);
458 my $itemcount = GetItemsCount($biblionumber);
459 my $holds = GetHolds ($biblionumber);
460 my @items = GetItemnumbersFromOrder( $ordernumber );
461 my $itemholds;
462 foreach my $item (@items){
463 my $nb = GetItemHolds($biblionumber, $item);
464 if ($nb){
465 $itemholds += $nb;
468 # 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
469 $line{can_del_bib} = 1 if $countbiblio <= 1 && $itemcount == scalar @items && !(@subscriptions) && !($holds);
470 $line{items} = ($itemcount) - (scalar @items);
471 $line{left_item} = 1 if $line{items} >= 1;
472 $line{left_biblio} = 1 if $countbiblio > 1;
473 $line{biblios} = $countbiblio - 1;
474 $line{left_subscription} = 1 if scalar @subscriptions >= 1;
475 $line{subscriptions} = scalar @subscriptions;
476 ($holds >= 1) ? $line{left_holds} = 1 : $line{left_holds} = 0;
477 $line{left_holds_on_order} = 1 if $line{left_holds}==1 && ($line{items} == 0 || $itemholds );
478 $line{holds} = $holds;
479 $line{holds_on_order} = $itemholds?$itemholds:$holds if $line{left_holds_on_order};
482 my $suggestion = GetSuggestionInfoFromBiblionumber($line{biblionumber});
483 $line{suggestionid} = $$suggestion{suggestionid};
484 $line{surnamesuggestedby} = $$suggestion{surnamesuggestedby};
485 $line{firstnamesuggestedby} = $$suggestion{firstnamesuggestedby};
487 foreach my $key (qw(transferred_from transferred_to)) {
488 if ($line{$key}) {
489 my $order = GetOrder($line{$key});
490 my $basket = GetBasket($order->{basketno});
491 my $bookseller = GetBookSellerFromId($basket->{booksellerid});
492 $line{$key} = {
493 order => $order,
494 basket => $basket,
495 bookseller => $bookseller,
496 timestamp => $line{$key . '_timestamp'},
501 return \%line;
504 output_html_with_http_headers $query, $cookie, $template->output;