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 Koha::Acquisition::Booksellers;
39 use C4::Letters qw/SendAlerts/;
40 use Date::Calc qw/Add_Delta_Days/;
42 use Koha::EDI qw( create_edi_order get_edifact_ean );
50 This script display all informations about basket for the supplier given
51 on input arg. Moreover, it allows us to add a new order for this supplier from
52 an existing record, a suggestion or a new record.
64 the supplier this script have to display the basket.
73 our $basketno = $query->param('basketno');
74 my $ean = $query->param('ean');
75 my $booksellerid = $query->param('booksellerid');
76 my $duplinbatch = $query->param('duplinbatch');
78 my ( $template, $loggedinuser, $cookie, $userflags ) = get_template_and_user(
80 template_name => "acqui/basket.tt",
84 flagsrequired => { acquisition => 'order_manage' },
89 my $basket = GetBasket($basketno);
90 $booksellerid = $basket->{booksellerid} unless $booksellerid;
91 my $bookseller = Koha::Acquisition::Booksellers->find( $booksellerid );
92 my $schema = Koha::Database->new()->schema();
93 my $rs = $schema->resultset('VendorEdiAccount')->search(
94 { vendor_id => $booksellerid, } );
95 $template->param( ediaccount => ($rs->count > 0));
97 unless (CanUserManageBasket($loggedinuser, $basket, $userflags)) {
99 cannot_manage_basket => 1,
100 basketno => $basketno,
101 basketname => $basket->{basketname},
102 booksellerid => $booksellerid,
103 name => $bookseller->name,
105 output_html_with_http_headers $query, $cookie, $template->output;
109 # FIXME : what about the "discount" percentage?
110 # FIXME : the query->param('booksellerid') below is probably useless. The bookseller is always known from the basket
111 # if no booksellerid in parameter, get it from basket
112 # warn "=>".$basket->{booksellerid};
113 my $op = $query->param('op') // 'list';
115 my $confirm_pref= C4::Context->preference("BasketConfirmations") || '1';
116 $template->param( skip_confirm_reopen => 1) if $confirm_pref eq '2';
120 if ( $op eq 'delete_confirm' ) {
121 my $basketno = $query->param('basketno');
122 my $delbiblio = $query->param('delbiblio');
123 my @orders = GetOrders($basketno);
124 #Delete all orders included in that basket, and all items received.
125 foreach my $myorder (@orders){
126 DelOrder($myorder->{biblionumber},$myorder->{ordernumber});
128 # if $delbiblio = 1, delete the records if possible
129 if ((defined $delbiblio)and ($delbiblio ==1)){
130 my @cannotdelbiblios ;
131 foreach my $myorder (@orders){
132 my $biblionumber = $myorder->{'biblionumber'};
133 my $countbiblio = CountBiblioInOrders($biblionumber);
134 my $ordernumber = $myorder->{'ordernumber'};
135 my $subscriptions = scalar GetSubscriptionsId ($biblionumber);
136 my $itemcount = GetItemsCount($biblionumber);
138 if ($countbiblio == 0 && $itemcount == 0 && $subscriptions == 0) {
139 $error = DelBiblio($myorder->{biblionumber}) }
141 push @cannotdelbiblios, {biblionumber=> ($myorder->{biblionumber}),
142 title=> $myorder->{'title'},
143 author=> $myorder->{'author'},
144 countbiblio=> $countbiblio,
145 itemcount=>$itemcount,
146 subscriptions=>$subscriptions};
149 push @cannotdelbiblios, {biblionumber=> ($myorder->{biblionumber}),
150 title=> $myorder->{'title'},
151 author=> $myorder->{'author'},
152 othererror=> $error};
155 $template->param( cannotdelbiblios => \@cannotdelbiblios );
158 DelBasket($basketno,);
160 delete_confirmed => 1,
161 name => $bookseller->name,
162 booksellerid => $booksellerid,
164 } elsif ( !$bookseller ) {
165 $template->param( NO_BOOKSELLER => 1 );
166 } elsif ($op eq 'export') {
167 print $query->header(
169 -attachment => 'basket' . $basket->{'basketno'} . '.csv',
171 print GetBasketAsCSV($query->param('basketno'), $query);
173 } elsif ($op eq 'email') {
175 SendAlerts( 'orderacquisition', $query->param('basketno'), 'ACQORDER' );
178 push @messages, { type => 'error', code => $@ };
179 } elsif ( ref $err and exists $err->{error} ) {
180 push @messages, { type => 'error', code => $err->{error} };
182 push @messages, { type => 'message', code => 'email_sent' };
186 } elsif ($op eq 'close') {
187 my $confirm = $query->param('confirm') || $confirm_pref eq '2';
189 my $basketno = $query->param('basketno');
190 my $booksellerid = $query->param('booksellerid');
191 $basketno =~ /^\d+$/ and CloseBasket($basketno);
192 # if requested, create basket group, close it and attach the basket
193 if ($query->param('createbasketgroup')) {
195 if(C4::Context->userenv and C4::Context->userenv->{'branch'}
196 and C4::Context->userenv->{'branch'} ne "NO_LIBRARY_SET") {
197 $branchcode = C4::Context->userenv->{'branch'};
199 my $basketgroupid = NewBasketgroup( { name => $basket->{basketname},
200 booksellerid => $booksellerid,
201 deliveryplace => $branchcode,
202 billingplace => $branchcode,
205 ModBasket( { basketno => $basketno,
206 basketgroupid => $basketgroupid } );
207 print $query->redirect('/cgi-bin/koha/acqui/basketgroup.pl?booksellerid='.$booksellerid.'&closed=1');
209 print $query->redirect('/cgi-bin/koha/acqui/booksellers.pl?booksellerid=' . $booksellerid);
214 confirm_close => "1",
215 booksellerid => $booksellerid,
216 basketno => $basket->{'basketno'},
217 basketname => $basket->{'basketname'},
218 basketgroupname => $basket->{'basketname'},
221 } elsif ($op eq 'reopen') {
222 ReopenBasket($query->param('basketno'));
223 print $query->redirect('/cgi-bin/koha/acqui/basket.pl?basketno='.$basket->{'basketno'})
225 elsif ( $op eq 'ediorder' ) {
226 edi_close_and_order()
227 } elsif ( $op eq 'mod_users' ) {
228 my $basketusers_ids = $query->param('users_ids');
229 my @basketusers = split( /:/, $basketusers_ids );
230 ModBasketUsers($basketno, @basketusers);
231 print $query->redirect("/cgi-bin/koha/acqui/basket.pl?basketno=$basketno");
233 } elsif ( $op eq 'mod_branch' ) {
234 my $branch = $query->param('branch');
235 $branch = undef if(defined $branch and $branch eq '');
237 basketno => $basket->{basketno},
240 print $query->redirect("/cgi-bin/koha/acqui/basket.pl?basketno=$basketno");
244 if ( $op eq 'list' ) {
246 # get librarian branch...
247 if ( C4::Context->preference("IndependentBranches") ) {
248 my $userenv = C4::Context->userenv;
249 unless ( C4::Context->IsSuperLibrarian() ) {
250 my $validtest = ( $basket->{creationdate} eq '' )
251 || ( $userenv->{branch} eq $basket->{branch} )
252 || ( $userenv->{branch} eq '' )
253 || ( $basket->{branch} eq '' );
254 unless ($validtest) {
255 print $query->redirect("../mainpage.pl");
260 if (!defined $basket->{branch} or $basket->{branch} eq $userenv->{branch}) {
261 push @branches_loop, {
262 branchcode => $userenv->{branch},
263 branchname => $userenv->{branchname},
269 my $branches = Koha::Libraries->search( {}, { order_by => ['branchname'] } )->unblessed;
270 foreach my $branch (@$branches) {
272 if (defined $basket->{branch}) {
273 $selected = 1 if $branch->{branchcode} eq $basket->{branch};
275 $selected = 1 if $branch->{branchcode} eq C4::Context->userenv->{branch};
277 push @branches_loop, {
278 branchcode => $branch->{branchcode},
279 branchname => $branch->{branchname},
280 selected => $selected
285 #if the basket is closed,and the user has the permission to edit basketgroups, display a list of basketgroups
286 my ($basketgroup, $basketgroups);
287 my $staffuser = GetMember(borrowernumber => $loggedinuser);
288 if ($basket->{closedate} && haspermission($staffuser->{userid}, { acquisition => 'group_manage'} )) {
289 $basketgroups = GetBasketgroups($basket->{booksellerid});
290 for my $bg ( @{$basketgroups} ) {
291 if ($basket->{basketgroupid} && $basket->{basketgroupid} == $bg->{id}){
298 # if the basket is closed, calculate estimated delivery date
299 my $estimateddeliverydate;
300 if( $basket->{closedate} ) {
301 my ($year, $month, $day) = ($basket->{closedate} =~ /(\d+)-(\d+)-(\d+)/);
302 ($year, $month, $day) = Add_Delta_Days($year, $month, $day, $bookseller->deliverytime);
303 $estimateddeliverydate = sprintf( "%04d-%02d-%02d", $year, $month, $day );
306 # if new basket, pre-fill infos
307 $basket->{creationdate} = "" unless ( $basket->{creationdate} );
308 $basket->{authorisedby} = $loggedinuser unless ( $basket->{authorisedby} );
311 "loggedinuser: $loggedinuser; creationdate: %s; authorisedby: %s",
312 $basket->{creationdate}, $basket->{authorisedby};
314 my @basketusers_ids = GetBasketUsers($basketno);
316 foreach my $basketuser_id (@basketusers_ids) {
317 my $basketuser = GetMember(borrowernumber => $basketuser_id);
318 push @basketusers, $basketuser if $basketuser;
321 my $active_currency = Koha::Acquisition::Currencies->get_active;
323 my @orders = GetOrders( $basketno );
328 my $total_quantity = 0;
329 my $total_tax_excluded = 0;
330 my $total_tax_included = 0;
331 my $total_tax_value = 0;
332 for my $order (@orders) {
333 my $line = get_order_infos( $order, $bookseller);
334 if ( $line->{uncertainprice} ) {
335 $template->param( uncertainprices => 1 );
338 $line->{tax_rate} = $line->{tax_rate_on_ordering};
339 $line->{tax_value} = $line->{tax_value_on_ordering};
341 push @books_loop, $line;
343 $foot{$$line{tax_rate}}{tax_rate} = $$line{tax_rate};
344 $foot{$$line{tax_rate}}{tax_value} += $$line{tax_value};
345 $total_tax_value += $$line{tax_value};
346 $foot{$$line{tax_rate}}{quantity} += $$line{quantity};
347 $total_quantity += $$line{quantity};
348 $foot{$$line{tax_rate}}{total_tax_excluded} += $$line{total_tax_excluded};
349 $total_tax_excluded += $$line{total_tax_excluded};
350 $foot{$$line{tax_rate}}{total_tax_included} += $$line{total_tax_included};
351 $total_tax_included += $$line{total_tax_included};
354 push @book_foot_loop, map {$_} values %foot;
356 # Get cancelled orders
357 my @cancelledorders = GetOrders($basketno, { cancelled => 1 });
358 my @cancelledorders_loop;
359 for my $order (@cancelledorders) {
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_tax_excluded => $total_tax_excluded,
412 total_tax_included => $total_tax_included,
413 total_tax_value => $total_tax_value,
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 $template->param( messages => \@messages );
431 output_html_with_http_headers $query, $cookie, $template->output;
433 sub get_order_infos {
435 my $bookseller = shift;
436 my $qty = $order->{'quantity'} || 0;
437 if ( !defined $order->{quantityreceived} ) {
438 $order->{quantityreceived} = 0;
440 my $budget = GetBudget($order->{budget_id});
441 my $basket = GetBasket($order->{basketno});
443 my %line = %{ $order };
444 # Don't show unreceived standing orders as received
445 $line{order_received} = ( $qty == $order->{'quantityreceived'} && ( $basket->{is_standing} ? $qty : 1 ) );
446 $line{basketno} = $basketno;
447 $line{budget_name} = $budget->{budget_name};
449 $line{total_tax_included} = $line{ecost_tax_included} * $line{quantity};
450 $line{total_tax_excluded} = $line{ecost_tax_excluded} * $line{quantity};
451 $line{tax_value} = $line{tax_value_on_ordering};
452 $line{tax_rate} = $line{tax_rate_on_ordering};
454 if ( $line{uncertainprice} ) {
455 $line{rrp_tax_excluded} .= ' (Uncertain)';
457 if ( $line{'title'} ) {
458 my $volume = $order->{'volume'};
459 my $seriestitle = $order->{'seriestitle'};
460 $line{'title'} .= " / $seriestitle" if $seriestitle;
461 $line{'title'} .= " / $volume" if $volume;
464 my $biblionumber = $order->{'biblionumber'};
465 my $biblio = Koha::Biblios->find( $biblionumber );
466 my $countbiblio = CountBiblioInOrders($biblionumber);
467 my $ordernumber = $order->{'ordernumber'};
468 my @subscriptions = GetSubscriptionsId ($biblionumber);
469 my $itemcount = GetItemsCount($biblionumber);
470 my $holds_count = $biblio->holds->count;
471 my @items = GetItemnumbersFromOrder( $ordernumber );
473 foreach my $item (@items){
474 my $nb = GetItemHolds($biblionumber, $item);
479 # 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
480 $line{can_del_bib} = 1 if $countbiblio <= 1 && $itemcount == scalar @items && !(@subscriptions) && !($holds_count);
481 $line{items} = ($itemcount) - (scalar @items);
482 $line{left_item} = 1 if $line{items} >= 1;
483 $line{left_biblio} = 1 if $countbiblio > 1;
484 $line{biblios} = $countbiblio - 1;
485 $line{left_subscription} = 1 if scalar @subscriptions >= 1;
486 $line{subscriptions} = scalar @subscriptions;
487 ($holds_count >= 1) ? $line{left_holds} = 1 : $line{left_holds} = 0;
488 $line{left_holds_on_order} = 1 if $line{left_holds}==1 && ($line{items} == 0 || $itemholds );
489 $line{holds} = $holds_count;
490 $line{holds_on_order} = $itemholds?$itemholds:$holds_count if $line{left_holds_on_order};
493 my $suggestion = GetSuggestionInfoFromBiblionumber($line{biblionumber});
494 $line{suggestionid} = $$suggestion{suggestionid};
495 $line{surnamesuggestedby} = $$suggestion{surnamesuggestedby};
496 $line{firstnamesuggestedby} = $$suggestion{firstnamesuggestedby};
498 foreach my $key (qw(transferred_from transferred_to)) {
500 my $order = GetOrder($line{$key});
501 my $bookseller = Koha::Acquisition::Booksellers->find( $basket->{booksellerid} );
505 bookseller => $bookseller,
506 timestamp => $line{$key . '_timestamp'},
514 sub edi_close_and_order {
515 my $confirm = $query->param('confirm') || $confirm_pref eq '2';
518 basketno => $basketno,
521 if ( $basket->{branch} ) {
522 $edi_params->{branchcode} = $basket->{branch};
524 if ( create_edi_order($edi_params) ) {
525 #$template->param( edifile => 1 );
527 CloseBasket($basketno);
529 # if requested, create basket group, close it and attach the basket
530 if ( $query->param('createbasketgroup') ) {
532 if ( C4::Context->userenv
533 and C4::Context->userenv->{'branch'}
534 and C4::Context->userenv->{'branch'} ne "NO_LIBRARY_SET" )
536 $branchcode = C4::Context->userenv->{'branch'};
538 my $basketgroupid = NewBasketgroup(
540 name => $basket->{basketname},
541 booksellerid => $booksellerid,
542 deliveryplace => $branchcode,
543 billingplace => $branchcode,
549 basketno => $basketno,
550 basketgroupid => $basketgroupid
553 print $query->redirect(
554 "/cgi-bin/koha/acqui/basketgroup.pl?booksellerid=$booksellerid&closed=1"
558 print $query->redirect(
559 "/cgi-bin/koha/acqui/booksellers.pl?booksellerid=$booksellerid"
567 booksellerid => $booksellerid,
568 basketno => $basket->{basketno},
569 basketname => $basket->{basketname},
570 basketgroupname => $basket->{basketname},
573 $template->param( ean => $ean );