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} and $err->{error} eq "no_email" ) {
182 $redirect_url .= '&email_error=no_email';
183 } elsif ( ref $err and exists $err->{error} and $err->{error} eq "no_basketno" ) {
184 $redirect_url .= '&email_error=no_basketno';
186 $redirect_url .= '&email_ok=1';
189 print $query->redirect($redirect_url)
191 } elsif ($op eq 'close') {
192 my $confirm = $query->param('confirm') || $confirm_pref eq '2';
194 my $basketno = $query->param('basketno');
195 my $booksellerid = $query->param('booksellerid');
196 $basketno =~ /^\d+$/ and CloseBasket($basketno);
197 # if requested, create basket group, close it and attach the basket
198 if ($query->param('createbasketgroup')) {
200 if(C4::Context->userenv and C4::Context->userenv->{'branch'}
201 and C4::Context->userenv->{'branch'} ne "NO_LIBRARY_SET") {
202 $branchcode = C4::Context->userenv->{'branch'};
204 my $basketgroupid = NewBasketgroup( { name => $basket->{basketname},
205 booksellerid => $booksellerid,
206 deliveryplace => $branchcode,
207 billingplace => $branchcode,
210 ModBasket( { basketno => $basketno,
211 basketgroupid => $basketgroupid } );
212 print $query->redirect('/cgi-bin/koha/acqui/basketgroup.pl?booksellerid='.$booksellerid.'&closed=1');
214 print $query->redirect('/cgi-bin/koha/acqui/booksellers.pl?booksellerid=' . $booksellerid);
219 confirm_close => "1",
220 booksellerid => $booksellerid,
221 basketno => $basket->{'basketno'},
222 basketname => $basket->{'basketname'},
223 basketgroupname => $basket->{'basketname'},
226 } elsif ($op eq 'reopen') {
227 ReopenBasket($query->param('basketno'));
228 print $query->redirect('/cgi-bin/koha/acqui/basket.pl?basketno='.$basket->{'basketno'})
230 elsif ( $op eq 'ediorder' ) {
231 edi_close_and_order()
232 } elsif ( $op eq 'mod_users' ) {
233 my $basketusers_ids = $query->param('users_ids');
234 my @basketusers = split( /:/, $basketusers_ids );
235 ModBasketUsers($basketno, @basketusers);
236 print $query->redirect("/cgi-bin/koha/acqui/basket.pl?basketno=$basketno");
238 } elsif ( $op eq 'mod_branch' ) {
239 my $branch = $query->param('branch');
240 $branch = undef if(defined $branch and $branch eq '');
242 basketno => $basket->{basketno},
245 print $query->redirect("/cgi-bin/koha/acqui/basket.pl?basketno=$basketno");
249 # get librarian branch...
250 if ( C4::Context->preference("IndependentBranches") ) {
251 my $userenv = C4::Context->userenv;
252 unless ( C4::Context->IsSuperLibrarian() ) {
253 my $validtest = ( $basket->{creationdate} eq '' )
254 || ( $userenv->{branch} eq $basket->{branch} )
255 || ( $userenv->{branch} eq '' )
256 || ( $basket->{branch} eq '' );
257 unless ($validtest) {
258 print $query->redirect("../mainpage.pl");
263 if (!defined $basket->{branch} or $basket->{branch} eq $userenv->{branch}) {
264 push @branches_loop, {
265 branchcode => $userenv->{branch},
266 branchname => $userenv->{branchname},
272 my $branches = Koha::Libraries->search( {}, { order_by => ['branchname'] } )->unblessed;
273 foreach my $branch (@$branches) {
275 if (defined $basket->{branch}) {
276 $selected = 1 if $branch->{branchcode} eq $basket->{branch};
278 $selected = 1 if $branch->{branchcode} eq C4::Context->userenv->{branch};
280 push @branches_loop, {
281 branchcode => $branch->{branchcode},
282 branchname => $branch->{branchname},
283 selected => $selected
288 #if the basket is closed,and the user has the permission to edit basketgroups, display a list of basketgroups
289 my ($basketgroup, $basketgroups);
290 my $staffuser = GetMember(borrowernumber => $loggedinuser);
291 if ($basket->{closedate} && haspermission($staffuser->{userid}, { acquisition => 'group_manage'} )) {
292 $basketgroups = GetBasketgroups($basket->{booksellerid});
293 for my $bg ( @{$basketgroups} ) {
294 if ($basket->{basketgroupid} && $basket->{basketgroupid} == $bg->{id}){
301 # if the basket is closed, calculate estimated delivery date
302 my $estimateddeliverydate;
303 if( $basket->{closedate} ) {
304 my ($year, $month, $day) = ($basket->{closedate} =~ /(\d+)-(\d+)-(\d+)/);
305 ($year, $month, $day) = Add_Delta_Days($year, $month, $day, $bookseller->{deliverytime});
306 $estimateddeliverydate = sprintf( "%04d-%02d-%02d", $year, $month, $day );
309 # if new basket, pre-fill infos
310 $basket->{creationdate} = "" unless ( $basket->{creationdate} );
311 $basket->{authorisedby} = $loggedinuser unless ( $basket->{authorisedby} );
314 "loggedinuser: $loggedinuser; creationdate: %s; authorisedby: %s",
315 $basket->{creationdate}, $basket->{authorisedby};
317 my @basketusers_ids = GetBasketUsers($basketno);
319 foreach my $basketuser_id (@basketusers_ids) {
320 my $basketuser = GetMember(borrowernumber => $basketuser_id);
321 push @basketusers, $basketuser if $basketuser;
324 my $active_currency = Koha::Acquisition::Currencies->get_active;
326 my @orders = GetOrders( $basketno );
331 my $total_quantity = 0;
334 my $total_gstvalue = 0;
335 for my $order (@orders) {
336 $order = C4::Acquisition::populate_order_with_prices({ order => $order, booksellerid => $booksellerid, ordering => 1 });
337 my $line = get_order_infos( $order, $bookseller);
338 if ( $line->{uncertainprice} ) {
339 $template->param( uncertainprices => 1 );
342 push @books_loop, $line;
344 $foot{$$line{gstrate}}{gstrate} = $$line{gstrate};
345 $foot{$$line{gstrate}}{gstvalue} += $$line{gstvalue};
346 $total_gstvalue += $$line{gstvalue};
347 $foot{$$line{gstrate}}{quantity} += $$line{quantity};
348 $total_quantity += $$line{quantity};
349 $foot{$$line{gstrate}}{totalgste} += $$line{totalgste};
350 $total_gste += $$line{totalgste};
351 $foot{$$line{gstrate}}{totalgsti} += $$line{totalgsti};
352 $total_gsti += $$line{totalgsti};
355 push @book_foot_loop, map {$_} values %foot;
357 # Get cancelled orders
358 my @cancelledorders = GetOrders($basketno, { cancelled => 1 });
359 my @cancelledorders_loop;
360 for my $order (@cancelledorders) {
361 $order = C4::Acquisition::populate_order_with_prices({ order => $order, booksellerid => $booksellerid, ordering => 1 });
362 my $line = get_order_infos( $order, $bookseller);
363 push @cancelledorders_loop, $line;
366 my $contract = GetContract({
367 contractnumber => $basket->{contractnumber}
370 if ($basket->{basketgroupid}){
371 $basketgroup = GetBasketgroup($basket->{basketgroupid});
373 my $borrower= GetMember('borrowernumber' => $loggedinuser);
374 my $budgets = GetBudgetHierarchy;
376 foreach my $r (@{$budgets}) {
377 if (!defined $r->{budget_amount} || $r->{budget_amount} == 0) {
380 next unless (CanUserUseBudget($loggedinuser, $r, $userflags));
387 basketno => $basketno,
389 basketname => $basket->{'basketname'},
390 basketbranchcode => $basket->{branch},
391 basketnote => $basket->{note},
392 basketbooksellernote => $basket->{booksellernote},
393 basketcontractno => $basket->{contractnumber},
394 basketcontractname => $contract->{contractname},
395 branches_loop => \@branches_loop,
396 creationdate => $basket->{creationdate},
397 authorisedby => $basket->{authorisedby},
398 authorisedbyname => $basket->{authorisedbyname},
399 users_ids => join(':', @basketusers_ids),
400 users => \@basketusers,
401 closedate => $basket->{closedate},
402 estimateddeliverydate=> $estimateddeliverydate,
403 is_standing => $basket->{is_standing},
404 deliveryplace => $basket->{deliveryplace},
405 billingplace => $basket->{billingplace},
406 active => $bookseller->{'active'},
407 booksellerid => $bookseller->{'id'},
408 name => $bookseller->{'name'},
409 books_loop => \@books_loop,
410 book_foot_loop => \@book_foot_loop,
411 cancelledorders_loop => \@cancelledorders_loop,
412 total_quantity => $total_quantity,
413 total_gste => sprintf( "%.2f", $total_gste ),
414 total_gsti => sprintf( "%.2f", $total_gsti ),
415 total_gstvalue => sprintf( "%.2f", $total_gstvalue ),
416 currency => $active_currency->currency,
417 listincgst => $bookseller->{listincgst},
418 basketgroups => $basketgroups,
419 basketgroup => $basketgroup,
420 grouped => $basket->{basketgroupid},
421 # The double negatives and booleans here mean:
422 # "A basket cannot be closed if there are no orders in it or it's a standing order basket."
424 # (The template has another implicit restriction that the order cannot be closed if there
425 # are any orders with uncertain prices.)
426 unclosable => @orders ? $basket->{is_standing} : 1,
427 has_budgets => $has_budgets,
428 duplinbatch => $duplinbatch,
432 sub get_order_infos {
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});
440 my $basket = GetBasket($order->{basketno});
442 my %line = %{ $order };
443 # Don't show unreceived standing orders as received
444 $line{order_received} = ( $qty == $order->{'quantityreceived'} && ( $basket->{is_standing} ? $qty : 1 ) );
445 $line{basketno} = $basketno;
446 $line{budget_name} = $budget->{budget_name};
448 if ( $line{uncertainprice} ) {
449 $line{rrpgste} .= ' (Uncertain)';
451 if ( $line{'title'} ) {
452 my $volume = $order->{'volume'};
453 my $seriestitle = $order->{'seriestitle'};
454 $line{'title'} .= " / $seriestitle" if $seriestitle;
455 $line{'title'} .= " / $volume" if $volume;
458 my $biblionumber = $order->{'biblionumber'};
459 my $countbiblio = CountBiblioInOrders($biblionumber);
460 my $ordernumber = $order->{'ordernumber'};
461 my @subscriptions = GetSubscriptionsId ($biblionumber);
462 my $itemcount = GetItemsCount($biblionumber);
463 my $holds = GetHolds ($biblionumber);
464 my @items = GetItemnumbersFromOrder( $ordernumber );
466 foreach my $item (@items){
467 my $nb = GetItemHolds($biblionumber, $item);
472 # 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
473 $line{can_del_bib} = 1 if $countbiblio <= 1 && $itemcount == scalar @items && !(@subscriptions) && !($holds);
474 $line{items} = ($itemcount) - (scalar @items);
475 $line{left_item} = 1 if $line{items} >= 1;
476 $line{left_biblio} = 1 if $countbiblio > 1;
477 $line{biblios} = $countbiblio - 1;
478 $line{left_subscription} = 1 if scalar @subscriptions >= 1;
479 $line{subscriptions} = scalar @subscriptions;
480 ($holds >= 1) ? $line{left_holds} = 1 : $line{left_holds} = 0;
481 $line{left_holds_on_order} = 1 if $line{left_holds}==1 && ($line{items} == 0 || $itemholds );
482 $line{holds} = $holds;
483 $line{holds_on_order} = $itemholds?$itemholds:$holds if $line{left_holds_on_order};
486 my $suggestion = GetSuggestionInfoFromBiblionumber($line{biblionumber});
487 $line{suggestionid} = $$suggestion{suggestionid};
488 $line{surnamesuggestedby} = $$suggestion{surnamesuggestedby};
489 $line{firstnamesuggestedby} = $$suggestion{firstnamesuggestedby};
491 foreach my $key (qw(transferred_from transferred_to)) {
493 my $order = GetOrder($line{$key});
494 my $bookseller = Koha::Acquisition::Bookseller->fetch({ id => $basket->{booksellerid} });
498 bookseller => $bookseller,
499 timestamp => $line{$key . '_timestamp'},
507 output_html_with_http_headers $query, $cookie, $template->output;
510 sub edi_close_and_order {
511 my $confirm = $query->param('confirm') || $confirm_pref eq '2';
514 basketno => $basketno,
517 if ( $basket->{branch} ) {
518 $edi_params->{branchcode} = $basket->{branch};
520 if ( create_edi_order($edi_params) ) {
521 #$template->param( edifile => 1 );
523 CloseBasket($basketno);
525 # if requested, create basket group, close it and attach the basket
526 if ( $query->param('createbasketgroup') ) {
528 if ( C4::Context->userenv
529 and C4::Context->userenv->{'branch'}
530 and C4::Context->userenv->{'branch'} ne "NO_LIBRARY_SET" )
532 $branchcode = C4::Context->userenv->{'branch'};
534 my $basketgroupid = NewBasketgroup(
536 name => $basket->{basketname},
537 booksellerid => $booksellerid,
538 deliveryplace => $branchcode,
539 billingplace => $branchcode,
545 basketno => $basketno,
546 basketgroupid => $basketgroupid
549 print $query->redirect(
550 "/cgi-bin/koha/acqui/basketgroup.pl?booksellerid=$booksellerid&closed=1"
554 print $query->redirect(
555 "/cgi-bin/koha/acqui/booksellers.pl?booksellerid=$booksellerid"
563 booksellerid => $booksellerid,
564 basketno => $basket->{basketno},
565 basketname => $basket->{basketname},
566 basketgroupname => $basket->{basketname},
569 $template->param( ean => $ean );