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') // 'list';
113 my $confirm_pref= C4::Context->preference("BasketConfirmations") || '1';
114 $template->param( skip_confirm_reopen => 1) if $confirm_pref eq '2';
118 if ( $op eq 'delete_confirm' ) {
119 my $basketno = $query->param('basketno');
120 my $delbiblio = $query->param('delbiblio');
121 my @orders = GetOrders($basketno);
122 #Delete all orders included in that basket, and all items received.
123 foreach my $myorder (@orders){
124 DelOrder($myorder->{biblionumber},$myorder->{ordernumber});
126 # if $delbiblio = 1, delete the records if possible
127 if ((defined $delbiblio)and ($delbiblio ==1)){
128 my @cannotdelbiblios ;
129 foreach my $myorder (@orders){
130 my $biblionumber = $myorder->{'biblionumber'};
131 my $countbiblio = CountBiblioInOrders($biblionumber);
132 my $ordernumber = $myorder->{'ordernumber'};
133 my $subscriptions = scalar GetSubscriptionsId ($biblionumber);
134 my $itemcount = GetItemsCount($biblionumber);
136 if ($countbiblio == 0 && $itemcount == 0 && $subscriptions == 0) {
137 $error = DelBiblio($myorder->{biblionumber}) }
139 push @cannotdelbiblios, {biblionumber=> ($myorder->{biblionumber}),
140 title=> $myorder->{'title'},
141 author=> $myorder->{'author'},
142 countbiblio=> $countbiblio,
143 itemcount=>$itemcount,
144 subscriptions=>$subscriptions};
147 push @cannotdelbiblios, {biblionumber=> ($myorder->{biblionumber}),
148 title=> $myorder->{'title'},
149 author=> $myorder->{'author'},
150 othererror=> $error};
153 $template->param( cannotdelbiblios => \@cannotdelbiblios );
156 DelBasket($basketno,);
157 $template->param( delete_confirmed => 1 );
158 } elsif ( !$bookseller ) {
159 $template->param( NO_BOOKSELLER => 1 );
160 } elsif ($op eq 'export') {
161 print $query->header(
163 -attachment => 'basket' . $basket->{'basketno'} . '.csv',
165 print GetBasketAsCSV($query->param('basketno'), $query);
167 } elsif ($op eq 'email') {
169 SendAlerts( 'orderacquisition', $query->param('basketno'), 'ACQORDER' );
172 push @messages, { type => 'error', code => $@ };
173 } elsif ( ref $err and exists $err->{error} ) {
174 push @messages, { type => 'error', code => $err->{error} };
176 push @messages, { type => 'message', code => 'email_sent' };
180 } elsif ($op eq 'close') {
181 my $confirm = $query->param('confirm') || $confirm_pref eq '2';
183 my $basketno = $query->param('basketno');
184 my $booksellerid = $query->param('booksellerid');
185 $basketno =~ /^\d+$/ and CloseBasket($basketno);
186 # if requested, create basket group, close it and attach the basket
187 if ($query->param('createbasketgroup')) {
189 if(C4::Context->userenv and C4::Context->userenv->{'branch'}
190 and C4::Context->userenv->{'branch'} ne "NO_LIBRARY_SET") {
191 $branchcode = C4::Context->userenv->{'branch'};
193 my $basketgroupid = NewBasketgroup( { name => $basket->{basketname},
194 booksellerid => $booksellerid,
195 deliveryplace => $branchcode,
196 billingplace => $branchcode,
199 ModBasket( { basketno => $basketno,
200 basketgroupid => $basketgroupid } );
201 print $query->redirect('/cgi-bin/koha/acqui/basketgroup.pl?booksellerid='.$booksellerid.'&closed=1');
203 print $query->redirect('/cgi-bin/koha/acqui/booksellers.pl?booksellerid=' . $booksellerid);
208 confirm_close => "1",
209 booksellerid => $booksellerid,
210 basketno => $basket->{'basketno'},
211 basketname => $basket->{'basketname'},
212 basketgroupname => $basket->{'basketname'},
215 } elsif ($op eq 'reopen') {
216 ReopenBasket($query->param('basketno'));
217 print $query->redirect('/cgi-bin/koha/acqui/basket.pl?basketno='.$basket->{'basketno'})
219 elsif ( $op eq 'ediorder' ) {
220 edi_close_and_order()
221 } elsif ( $op eq 'mod_users' ) {
222 my $basketusers_ids = $query->param('users_ids');
223 my @basketusers = split( /:/, $basketusers_ids );
224 ModBasketUsers($basketno, @basketusers);
225 print $query->redirect("/cgi-bin/koha/acqui/basket.pl?basketno=$basketno");
227 } elsif ( $op eq 'mod_branch' ) {
228 my $branch = $query->param('branch');
229 $branch = undef if(defined $branch and $branch eq '');
231 basketno => $basket->{basketno},
234 print $query->redirect("/cgi-bin/koha/acqui/basket.pl?basketno=$basketno");
238 if ( $op eq 'list' ) {
240 # get librarian branch...
241 if ( C4::Context->preference("IndependentBranches") ) {
242 my $userenv = C4::Context->userenv;
243 unless ( C4::Context->IsSuperLibrarian() ) {
244 my $validtest = ( $basket->{creationdate} eq '' )
245 || ( $userenv->{branch} eq $basket->{branch} )
246 || ( $userenv->{branch} eq '' )
247 || ( $basket->{branch} eq '' );
248 unless ($validtest) {
249 print $query->redirect("../mainpage.pl");
254 if (!defined $basket->{branch} or $basket->{branch} eq $userenv->{branch}) {
255 push @branches_loop, {
256 branchcode => $userenv->{branch},
257 branchname => $userenv->{branchname},
263 my $branches = Koha::Libraries->search( {}, { order_by => ['branchname'] } )->unblessed;
264 foreach my $branch (@$branches) {
266 if (defined $basket->{branch}) {
267 $selected = 1 if $branch->{branchcode} eq $basket->{branch};
269 $selected = 1 if $branch->{branchcode} eq C4::Context->userenv->{branch};
271 push @branches_loop, {
272 branchcode => $branch->{branchcode},
273 branchname => $branch->{branchname},
274 selected => $selected
279 #if the basket is closed,and the user has the permission to edit basketgroups, display a list of basketgroups
280 my ($basketgroup, $basketgroups);
281 my $staffuser = GetMember(borrowernumber => $loggedinuser);
282 if ($basket->{closedate} && haspermission($staffuser->{userid}, { acquisition => 'group_manage'} )) {
283 $basketgroups = GetBasketgroups($basket->{booksellerid});
284 for my $bg ( @{$basketgroups} ) {
285 if ($basket->{basketgroupid} && $basket->{basketgroupid} == $bg->{id}){
292 # if the basket is closed, calculate estimated delivery date
293 my $estimateddeliverydate;
294 if( $basket->{closedate} ) {
295 my ($year, $month, $day) = ($basket->{closedate} =~ /(\d+)-(\d+)-(\d+)/);
296 ($year, $month, $day) = Add_Delta_Days($year, $month, $day, $bookseller->{deliverytime});
297 $estimateddeliverydate = sprintf( "%04d-%02d-%02d", $year, $month, $day );
300 # if new basket, pre-fill infos
301 $basket->{creationdate} = "" unless ( $basket->{creationdate} );
302 $basket->{authorisedby} = $loggedinuser unless ( $basket->{authorisedby} );
305 "loggedinuser: $loggedinuser; creationdate: %s; authorisedby: %s",
306 $basket->{creationdate}, $basket->{authorisedby};
308 my @basketusers_ids = GetBasketUsers($basketno);
310 foreach my $basketuser_id (@basketusers_ids) {
311 my $basketuser = GetMember(borrowernumber => $basketuser_id);
312 push @basketusers, $basketuser if $basketuser;
315 my $active_currency = Koha::Acquisition::Currencies->get_active;
317 my @orders = GetOrders( $basketno );
322 my $total_quantity = 0;
325 my $total_gstvalue = 0;
326 for my $order (@orders) {
327 $order = C4::Acquisition::populate_order_with_prices({ order => $order, booksellerid => $booksellerid, ordering => 1 });
328 my $line = get_order_infos( $order, $bookseller);
329 if ( $line->{uncertainprice} ) {
330 $template->param( uncertainprices => 1 );
333 push @books_loop, $line;
335 $foot{$$line{gstrate}}{gstrate} = $$line{gstrate};
336 $foot{$$line{gstrate}}{gstvalue} += $$line{gstvalue};
337 $total_gstvalue += $$line{gstvalue};
338 $foot{$$line{gstrate}}{quantity} += $$line{quantity};
339 $total_quantity += $$line{quantity};
340 $foot{$$line{gstrate}}{totalgste} += $$line{totalgste};
341 $total_gste += $$line{totalgste};
342 $foot{$$line{gstrate}}{totalgsti} += $$line{totalgsti};
343 $total_gsti += $$line{totalgsti};
346 push @book_foot_loop, map {$_} values %foot;
348 # Get cancelled orders
349 my @cancelledorders = GetOrders($basketno, { cancelled => 1 });
350 my @cancelledorders_loop;
351 for my $order (@cancelledorders) {
352 $order = C4::Acquisition::populate_order_with_prices({ order => $order, booksellerid => $booksellerid, ordering => 1 });
353 my $line = get_order_infos( $order, $bookseller);
354 push @cancelledorders_loop, $line;
357 my $contract = GetContract({
358 contractnumber => $basket->{contractnumber}
361 if ($basket->{basketgroupid}){
362 $basketgroup = GetBasketgroup($basket->{basketgroupid});
364 my $borrower= GetMember('borrowernumber' => $loggedinuser);
365 my $budgets = GetBudgetHierarchy;
367 foreach my $r (@{$budgets}) {
368 if (!defined $r->{budget_amount} || $r->{budget_amount} == 0) {
371 next unless (CanUserUseBudget($loggedinuser, $r, $userflags));
378 basketno => $basketno,
380 basketname => $basket->{'basketname'},
381 basketbranchcode => $basket->{branch},
382 basketnote => $basket->{note},
383 basketbooksellernote => $basket->{booksellernote},
384 basketcontractno => $basket->{contractnumber},
385 basketcontractname => $contract->{contractname},
386 branches_loop => \@branches_loop,
387 creationdate => $basket->{creationdate},
388 authorisedby => $basket->{authorisedby},
389 authorisedbyname => $basket->{authorisedbyname},
390 users_ids => join(':', @basketusers_ids),
391 users => \@basketusers,
392 closedate => $basket->{closedate},
393 estimateddeliverydate=> $estimateddeliverydate,
394 is_standing => $basket->{is_standing},
395 deliveryplace => $basket->{deliveryplace},
396 billingplace => $basket->{billingplace},
397 active => $bookseller->{'active'},
398 booksellerid => $bookseller->{'id'},
399 name => $bookseller->{'name'},
400 books_loop => \@books_loop,
401 book_foot_loop => \@book_foot_loop,
402 cancelledorders_loop => \@cancelledorders_loop,
403 total_quantity => $total_quantity,
404 total_gste => sprintf( "%.2f", $total_gste ),
405 total_gsti => sprintf( "%.2f", $total_gsti ),
406 total_gstvalue => sprintf( "%.2f", $total_gstvalue ),
407 currency => $active_currency->currency,
408 listincgst => $bookseller->{listincgst},
409 basketgroups => $basketgroups,
410 basketgroup => $basketgroup,
411 grouped => $basket->{basketgroupid},
412 # The double negatives and booleans here mean:
413 # "A basket cannot be closed if there are no orders in it or it's a standing order basket."
415 # (The template has another implicit restriction that the order cannot be closed if there
416 # are any orders with uncertain prices.)
417 unclosable => @orders ? $basket->{is_standing} : 1,
418 has_budgets => $has_budgets,
419 duplinbatch => $duplinbatch,
423 $template->param( messages => \@messages );
424 output_html_with_http_headers $query, $cookie, $template->output;
426 sub get_order_infos {
428 my $bookseller = shift;
429 my $qty = $order->{'quantity'} || 0;
430 if ( !defined $order->{quantityreceived} ) {
431 $order->{quantityreceived} = 0;
433 my $budget = GetBudget($order->{budget_id});
434 my $basket = GetBasket($order->{basketno});
436 my %line = %{ $order };
437 # Don't show unreceived standing orders as received
438 $line{order_received} = ( $qty == $order->{'quantityreceived'} && ( $basket->{is_standing} ? $qty : 1 ) );
439 $line{basketno} = $basketno;
440 $line{budget_name} = $budget->{budget_name};
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;
452 my $biblionumber = $order->{'biblionumber'};
453 my $countbiblio = CountBiblioInOrders($biblionumber);
454 my $ordernumber = $order->{'ordernumber'};
455 my @subscriptions = GetSubscriptionsId ($biblionumber);
456 my $itemcount = GetItemsCount($biblionumber);
457 my $holds = GetHolds ($biblionumber);
458 my @items = GetItemnumbersFromOrder( $ordernumber );
460 foreach my $item (@items){
461 my $nb = GetItemHolds($biblionumber, $item);
466 # 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
467 $line{can_del_bib} = 1 if $countbiblio <= 1 && $itemcount == scalar @items && !(@subscriptions) && !($holds);
468 $line{items} = ($itemcount) - (scalar @items);
469 $line{left_item} = 1 if $line{items} >= 1;
470 $line{left_biblio} = 1 if $countbiblio > 1;
471 $line{biblios} = $countbiblio - 1;
472 $line{left_subscription} = 1 if scalar @subscriptions >= 1;
473 $line{subscriptions} = scalar @subscriptions;
474 ($holds >= 1) ? $line{left_holds} = 1 : $line{left_holds} = 0;
475 $line{left_holds_on_order} = 1 if $line{left_holds}==1 && ($line{items} == 0 || $itemholds );
476 $line{holds} = $holds;
477 $line{holds_on_order} = $itemholds?$itemholds:$holds if $line{left_holds_on_order};
480 my $suggestion = GetSuggestionInfoFromBiblionumber($line{biblionumber});
481 $line{suggestionid} = $$suggestion{suggestionid};
482 $line{surnamesuggestedby} = $$suggestion{surnamesuggestedby};
483 $line{firstnamesuggestedby} = $$suggestion{firstnamesuggestedby};
485 foreach my $key (qw(transferred_from transferred_to)) {
487 my $order = GetOrder($line{$key});
488 my $bookseller = Koha::Acquisition::Bookseller->fetch({ id => $basket->{booksellerid} });
492 bookseller => $bookseller,
493 timestamp => $line{$key . '_timestamp'},
501 sub edi_close_and_order {
502 my $confirm = $query->param('confirm') || $confirm_pref eq '2';
505 basketno => $basketno,
508 if ( $basket->{branch} ) {
509 $edi_params->{branchcode} = $basket->{branch};
511 if ( create_edi_order($edi_params) ) {
512 #$template->param( edifile => 1 );
514 CloseBasket($basketno);
516 # if requested, create basket group, close it and attach the basket
517 if ( $query->param('createbasketgroup') ) {
519 if ( C4::Context->userenv
520 and C4::Context->userenv->{'branch'}
521 and C4::Context->userenv->{'branch'} ne "NO_LIBRARY_SET" )
523 $branchcode = C4::Context->userenv->{'branch'};
525 my $basketgroupid = NewBasketgroup(
527 name => $basket->{basketname},
528 booksellerid => $booksellerid,
529 deliveryplace => $branchcode,
530 billingplace => $branchcode,
536 basketno => $basketno,
537 basketgroupid => $basketgroupid
540 print $query->redirect(
541 "/cgi-bin/koha/acqui/basketgroup.pl?booksellerid=$booksellerid&closed=1"
545 print $query->redirect(
546 "/cgi-bin/koha/acqui/booksellers.pl?booksellerid=$booksellerid"
554 booksellerid => $booksellerid,
555 basketno => $basket->{basketno},
556 basketname => $basket->{basketname},
557 basketgroupname => $basket->{basketname},
560 $template->param( ean => $ean );