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>.
33 use C4::Members qw/GetMember/; #needed for permissions checking for changing basketgroup of a basket
37 use C4::Letters qw/SendAlerts/;
38 use Date::Calc qw/Add_Delta_Days/;
40 use Koha::EDI qw( create_edi_order get_edifact_ean );
48 This script display all informations about basket for the supplier given
49 on input arg. Moreover, it allows us to add a new order for this supplier from
50 an existing record, a suggestion or a new record.
62 the supplier this script have to display the basket.
71 our $basketno = $query->param('basketno');
72 my $ean = $query->param('ean');
73 my $booksellerid = $query->param('booksellerid');
74 my $duplinbatch = $query->param('duplinbatch');
76 my ( $template, $loggedinuser, $cookie, $userflags ) = get_template_and_user(
78 template_name => "acqui/basket.tt",
82 flagsrequired => { acquisition => 'order_manage' },
87 my $basket = GetBasket($basketno);
88 $booksellerid = $basket->{booksellerid} unless $booksellerid;
89 my $bookseller = Koha::Acquisition::Bookseller->fetch({ id => $booksellerid });
90 my $schema = Koha::Database->new()->schema();
91 my $rs = $schema->resultset('VendorEdiAccount')->search(
92 { vendor_id => $booksellerid, } );
93 $template->param( ediaccount => ($rs->count > 0));
95 unless (CanUserManageBasket($loggedinuser, $basket, $userflags)) {
97 cannot_manage_basket => 1,
98 basketno => $basketno,
99 basketname => $basket->{basketname},
100 booksellerid => $booksellerid,
101 name => $bookseller->{name}
103 output_html_with_http_headers $query, $cookie, $template->output;
107 # FIXME : what about the "discount" percentage?
108 # FIXME : the query->param('booksellerid') below is probably useless. The bookseller is always known from the basket
109 # if no booksellerid in parameter, get it from basket
110 # warn "=>".$basket->{booksellerid};
111 my $op = $query->param('op');
116 my $confirm_pref= C4::Context->preference("BasketConfirmations") || '1';
117 $template->param( skip_confirm_reopen => 1) if $confirm_pref eq '2';
119 $template->param( email_ok => 1 ) if defined $query->param('email_ok');
120 $template->param( email_error => $query->param('email_error') ) if defined $query->param('email_error');
123 if ( $op eq 'delete_confirm' ) {
124 my $basketno = $query->param('basketno');
125 my $delbiblio = $query->param('delbiblio');
126 my @orders = GetOrders($basketno);
127 #Delete all orders included in that basket, and all items received.
128 foreach my $myorder (@orders){
129 DelOrder($myorder->{biblionumber},$myorder->{ordernumber});
131 # if $delbiblio = 1, delete the records if possible
132 if ((defined $delbiblio)and ($delbiblio ==1)){
133 my @cannotdelbiblios ;
134 foreach my $myorder (@orders){
135 my $biblionumber = $myorder->{'biblionumber'};
136 my $countbiblio = CountBiblioInOrders($biblionumber);
137 my $ordernumber = $myorder->{'ordernumber'};
138 my $subscriptions = scalar GetSubscriptionsId ($biblionumber);
139 my $itemcount = GetItemsCount($biblionumber);
141 if ($countbiblio == 0 && $itemcount == 0 && $subscriptions == 0) {
142 $error = DelBiblio($myorder->{biblionumber}) }
144 push @cannotdelbiblios, {biblionumber=> ($myorder->{biblionumber}),
145 title=> $myorder->{'title'},
146 author=> $myorder->{'author'},
147 countbiblio=> $countbiblio,
148 itemcount=>$itemcount,
149 subscriptions=>$subscriptions};
152 push @cannotdelbiblios, {biblionumber=> ($myorder->{biblionumber}),
153 title=> $myorder->{'title'},
154 author=> $myorder->{'author'},
155 othererror=> $error};
158 $template->param( cannotdelbiblios => \@cannotdelbiblios );
161 DelBasket($basketno,);
162 $template->param( delete_confirmed => 1 );
163 } elsif ( !$bookseller ) {
164 $template->param( NO_BOOKSELLER => 1 );
165 } elsif ($op eq 'export') {
166 print $query->header(
168 -attachment => 'basket' . $basket->{'basketno'} . '.csv',
170 print GetBasketAsCSV($query->param('basketno'), $query);
172 } elsif ($op eq 'email') {
173 my $redirect_url = '/cgi-bin/koha/acqui/basket.pl?basketno='.$basket->{'basketno'};
177 $err = SendAlerts( 'orderacquisition', $query->param('basketno'), 'ACQORDER' );
180 $redirect_url .= '&email_error='.$@;
181 } elsif ( ref $err and exists $err->{error} ) {
182 $redirect_url .= '&email_error=' . $err->{error};
184 $redirect_url .= '&email_ok=1';
187 print $query->redirect($redirect_url)
189 } elsif ($op eq 'close') {
190 my $confirm = $query->param('confirm') || $confirm_pref eq '2';
192 my $basketno = $query->param('basketno');
193 my $booksellerid = $query->param('booksellerid');
194 $basketno =~ /^\d+$/ and CloseBasket($basketno);
195 # if requested, create basket group, close it and attach the basket
196 if ($query->param('createbasketgroup')) {
198 if(C4::Context->userenv and C4::Context->userenv->{'branch'}
199 and C4::Context->userenv->{'branch'} ne "NO_LIBRARY_SET") {
200 $branchcode = C4::Context->userenv->{'branch'};
202 my $basketgroupid = NewBasketgroup( { name => $basket->{basketname},
203 booksellerid => $booksellerid,
204 deliveryplace => $branchcode,
205 billingplace => $branchcode,
208 ModBasket( { basketno => $basketno,
209 basketgroupid => $basketgroupid } );
210 print $query->redirect('/cgi-bin/koha/acqui/basketgroup.pl?booksellerid='.$booksellerid.'&closed=1');
212 print $query->redirect('/cgi-bin/koha/acqui/booksellers.pl?booksellerid=' . $booksellerid);
217 confirm_close => "1",
218 booksellerid => $booksellerid,
219 basketno => $basket->{'basketno'},
220 basketname => $basket->{'basketname'},
221 basketgroupname => $basket->{'basketname'},
224 } elsif ($op eq 'reopen') {
225 ReopenBasket($query->param('basketno'));
226 print $query->redirect('/cgi-bin/koha/acqui/basket.pl?basketno='.$basket->{'basketno'})
228 elsif ( $op eq 'ediorder' ) {
229 edi_close_and_order()
230 } elsif ( $op eq 'mod_users' ) {
231 my $basketusers_ids = $query->param('users_ids');
232 my @basketusers = split( /:/, $basketusers_ids );
233 ModBasketUsers($basketno, @basketusers);
234 print $query->redirect("/cgi-bin/koha/acqui/basket.pl?basketno=$basketno");
236 } elsif ( $op eq 'mod_branch' ) {
237 my $branch = $query->param('branch');
238 $branch = undef if(defined $branch and $branch eq '');
240 basketno => $basket->{basketno},
243 print $query->redirect("/cgi-bin/koha/acqui/basket.pl?basketno=$basketno");
247 # get librarian branch...
248 if ( C4::Context->preference("IndependentBranches") ) {
249 my $userenv = C4::Context->userenv;
250 unless ( C4::Context->IsSuperLibrarian() ) {
251 my $validtest = ( $basket->{creationdate} eq '' )
252 || ( $userenv->{branch} eq $basket->{branch} )
253 || ( $userenv->{branch} eq '' )
254 || ( $basket->{branch} eq '' );
255 unless ($validtest) {
256 print $query->redirect("../mainpage.pl");
261 if (!defined $basket->{branch} or $basket->{branch} eq $userenv->{branch}) {
262 push @branches_loop, {
263 branchcode => $userenv->{branch},
264 branchname => $userenv->{branchname},
270 my $branches = Koha::Libraries->search( {}, { order_by => ['branchname'] } )->unblessed;
271 foreach my $branch (@$branches) {
273 if (defined $basket->{branch}) {
274 $selected = 1 if $branch->{branchcode} eq $basket->{branch};
276 $selected = 1 if $branch->{branchcode} eq C4::Context->userenv->{branch};
278 push @branches_loop, {
279 branchcode => $branch->{branchcode},
280 branchname => $branch->{branchname},
281 selected => $selected
286 #if the basket is closed,and the user has the permission to edit basketgroups, display a list of basketgroups
287 my ($basketgroup, $basketgroups);
288 my $staffuser = GetMember(borrowernumber => $loggedinuser);
289 if ($basket->{closedate} && haspermission($staffuser->{userid}, { acquisition => 'group_manage'} )) {
290 $basketgroups = GetBasketgroups($basket->{booksellerid});
291 for my $bg ( @{$basketgroups} ) {
292 if ($basket->{basketgroupid} && $basket->{basketgroupid} == $bg->{id}){
299 # if the basket is closed, calculate estimated delivery date
300 my $estimateddeliverydate;
301 if( $basket->{closedate} ) {
302 my ($year, $month, $day) = ($basket->{closedate} =~ /(\d+)-(\d+)-(\d+)/);
303 ($year, $month, $day) = Add_Delta_Days($year, $month, $day, $bookseller->{deliverytime});
304 $estimateddeliverydate = sprintf( "%04d-%02d-%02d", $year, $month, $day );
307 # if new basket, pre-fill infos
308 $basket->{creationdate} = "" unless ( $basket->{creationdate} );
309 $basket->{authorisedby} = $loggedinuser unless ( $basket->{authorisedby} );
312 "loggedinuser: $loggedinuser; creationdate: %s; authorisedby: %s",
313 $basket->{creationdate}, $basket->{authorisedby};
315 my @basketusers_ids = GetBasketUsers($basketno);
317 foreach my $basketuser_id (@basketusers_ids) {
318 my $basketuser = GetMember(borrowernumber => $basketuser_id);
319 push @basketusers, $basketuser if $basketuser;
322 my $active_currency = Koha::Acquisition::Currencies->get_active;
324 my @orders = GetOrders( $basketno );
329 my $total_quantity = 0;
332 my $total_gstvalue = 0;
333 for my $order (@orders) {
334 $order = C4::Acquisition::populate_order_with_prices({ order => $order, booksellerid => $booksellerid, ordering => 1 });
335 my $line = get_order_infos( $order, $bookseller);
336 if ( $line->{uncertainprice} ) {
337 $template->param( uncertainprices => 1 );
340 push @books_loop, $line;
342 $foot{$$line{gstrate}}{gstrate} = $$line{gstrate};
343 $foot{$$line{gstrate}}{gstvalue} += $$line{gstvalue};
344 $total_gstvalue += $$line{gstvalue};
345 $foot{$$line{gstrate}}{quantity} += $$line{quantity};
346 $total_quantity += $$line{quantity};
347 $foot{$$line{gstrate}}{totalgste} += $$line{totalgste};
348 $total_gste += $$line{totalgste};
349 $foot{$$line{gstrate}}{totalgsti} += $$line{totalgsti};
350 $total_gsti += $$line{totalgsti};
353 push @book_foot_loop, map {$_} values %foot;
355 # Get cancelled orders
356 my @cancelledorders = GetOrders($basketno, { cancelled => 1 });
357 my @cancelledorders_loop;
358 for my $order (@cancelledorders) {
359 $order = C4::Acquisition::populate_order_with_prices({ order => $order, booksellerid => $booksellerid, ordering => 1 });
360 my $line = get_order_infos( $order, $bookseller);
361 push @cancelledorders_loop, $line;
364 my $contract = GetContract({
365 contractnumber => $basket->{contractnumber}
368 if ($basket->{basketgroupid}){
369 $basketgroup = GetBasketgroup($basket->{basketgroupid});
371 my $borrower= GetMember('borrowernumber' => $loggedinuser);
372 my $budgets = GetBudgetHierarchy;
374 foreach my $r (@{$budgets}) {
375 if (!defined $r->{budget_amount} || $r->{budget_amount} == 0) {
378 next unless (CanUserUseBudget($loggedinuser, $r, $userflags));
385 basketno => $basketno,
387 basketname => $basket->{'basketname'},
388 basketbranchcode => $basket->{branch},
389 basketnote => $basket->{note},
390 basketbooksellernote => $basket->{booksellernote},
391 basketcontractno => $basket->{contractnumber},
392 basketcontractname => $contract->{contractname},
393 branches_loop => \@branches_loop,
394 creationdate => $basket->{creationdate},
395 authorisedby => $basket->{authorisedby},
396 authorisedbyname => $basket->{authorisedbyname},
397 users_ids => join(':', @basketusers_ids),
398 users => \@basketusers,
399 closedate => $basket->{closedate},
400 estimateddeliverydate=> $estimateddeliverydate,
401 is_standing => $basket->{is_standing},
402 deliveryplace => $basket->{deliveryplace},
403 billingplace => $basket->{billingplace},
404 active => $bookseller->{'active'},
405 booksellerid => $bookseller->{'id'},
406 name => $bookseller->{'name'},
407 books_loop => \@books_loop,
408 book_foot_loop => \@book_foot_loop,
409 cancelledorders_loop => \@cancelledorders_loop,
410 total_quantity => $total_quantity,
411 total_gste => sprintf( "%.2f", $total_gste ),
412 total_gsti => sprintf( "%.2f", $total_gsti ),
413 total_gstvalue => sprintf( "%.2f", $total_gstvalue ),
414 currency => $active_currency->currency,
415 listincgst => $bookseller->{listincgst},
416 basketgroups => $basketgroups,
417 basketgroup => $basketgroup,
418 grouped => $basket->{basketgroupid},
419 # The double negatives and booleans here mean:
420 # "A basket cannot be closed if there are no orders in it or it's a standing order basket."
422 # (The template has another implicit restriction that the order cannot be closed if there
423 # are any orders with uncertain prices.)
424 unclosable => @orders ? $basket->{is_standing} : 1,
425 has_budgets => $has_budgets,
426 duplinbatch => $duplinbatch,
430 sub get_order_infos {
432 my $bookseller = shift;
433 my $qty = $order->{'quantity'} || 0;
434 if ( !defined $order->{quantityreceived} ) {
435 $order->{quantityreceived} = 0;
437 my $budget = GetBudget($order->{budget_id});
438 my $basket = GetBasket($order->{basketno});
440 my %line = %{ $order };
441 # Don't show unreceived standing orders as received
442 $line{order_received} = ( $qty == $order->{'quantityreceived'} && ( $basket->{is_standing} ? $qty : 1 ) );
443 $line{basketno} = $basketno;
444 $line{budget_name} = $budget->{budget_name};
446 if ( $line{uncertainprice} ) {
447 $line{rrpgste} .= ' (Uncertain)';
449 if ( $line{'title'} ) {
450 my $volume = $order->{'volume'};
451 my $seriestitle = $order->{'seriestitle'};
452 $line{'title'} .= " / $seriestitle" if $seriestitle;
453 $line{'title'} .= " / $volume" if $volume;
456 my $biblionumber = $order->{'biblionumber'};
457 my $countbiblio = CountBiblioInOrders($biblionumber);
458 my $ordernumber = $order->{'ordernumber'};
459 my @subscriptions = GetSubscriptionsId ($biblionumber);
460 my $itemcount = GetItemsCount($biblionumber);
461 my $holds = GetHolds ($biblionumber);
462 my @items = GetItemnumbersFromOrder( $ordernumber );
464 foreach my $item (@items){
465 my $nb = GetItemHolds($biblionumber, $item);
470 # 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
471 $line{can_del_bib} = 1 if $countbiblio <= 1 && $itemcount == scalar @items && !(@subscriptions) && !($holds);
472 $line{items} = ($itemcount) - (scalar @items);
473 $line{left_item} = 1 if $line{items} >= 1;
474 $line{left_biblio} = 1 if $countbiblio > 1;
475 $line{biblios} = $countbiblio - 1;
476 $line{left_subscription} = 1 if scalar @subscriptions >= 1;
477 $line{subscriptions} = scalar @subscriptions;
478 ($holds >= 1) ? $line{left_holds} = 1 : $line{left_holds} = 0;
479 $line{left_holds_on_order} = 1 if $line{left_holds}==1 && ($line{items} == 0 || $itemholds );
480 $line{holds} = $holds;
481 $line{holds_on_order} = $itemholds?$itemholds:$holds if $line{left_holds_on_order};
484 my $suggestion = GetSuggestionInfoFromBiblionumber($line{biblionumber});
485 $line{suggestionid} = $$suggestion{suggestionid};
486 $line{surnamesuggestedby} = $$suggestion{surnamesuggestedby};
487 $line{firstnamesuggestedby} = $$suggestion{firstnamesuggestedby};
489 foreach my $key (qw(transferred_from transferred_to)) {
491 my $order = GetOrder($line{$key});
492 my $bookseller = Koha::Acquisition::Bookseller->fetch({ id => $basket->{booksellerid} });
496 bookseller => $bookseller,
497 timestamp => $line{$key . '_timestamp'},
505 output_html_with_http_headers $query, $cookie, $template->output;
508 sub edi_close_and_order {
509 my $confirm = $query->param('confirm') || $confirm_pref eq '2';
512 basketno => $basketno,
515 if ( $basket->{branch} ) {
516 $edi_params->{branchcode} = $basket->{branch};
518 if ( create_edi_order($edi_params) ) {
519 #$template->param( edifile => 1 );
521 CloseBasket($basketno);
523 # if requested, create basket group, close it and attach the basket
524 if ( $query->param('createbasketgroup') ) {
526 if ( C4::Context->userenv
527 and C4::Context->userenv->{'branch'}
528 and C4::Context->userenv->{'branch'} ne "NO_LIBRARY_SET" )
530 $branchcode = C4::Context->userenv->{'branch'};
532 my $basketgroupid = NewBasketgroup(
534 name => $basket->{basketname},
535 booksellerid => $booksellerid,
536 deliveryplace => $branchcode,
537 billingplace => $branchcode,
543 basketno => $basketno,
544 basketgroupid => $basketgroupid
547 print $query->redirect(
548 "/cgi-bin/koha/acqui/basketgroup.pl?booksellerid=$booksellerid&closed=1"
552 print $query->redirect(
553 "/cgi-bin/koha/acqui/booksellers.pl?booksellerid=$booksellerid"
561 booksellerid => $booksellerid,
562 basketno => $basket->{basketno},
563 basketname => $basket->{basketname},
564 basketgroupname => $basket->{basketname},
567 $template->param( ean => $ean );