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 our $ean = $query->param('ean');
75 our $booksellerid = $query->param('booksellerid');
76 my $duplinbatch = $query->param('duplinbatch');
78 our ( $template, $loggedinuser, $cookie, $userflags ) = get_template_and_user
(
80 template_name
=> "acqui/basket.tt",
84 flagsrequired
=> { acquisition
=> 'order_manage' },
89 our $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 our $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 $biblio = Koha
::Biblios
->find( $biblionumber );
134 my $countbiblio = CountBiblioInOrders
($biblionumber);
135 my $ordernumber = $myorder->{'ordernumber'};
136 my $subscriptions = scalar GetSubscriptionsId
($biblionumber);
137 my $itemcount = $biblio->items->count;
139 if ($countbiblio == 0 && $itemcount == 0 && $subscriptions == 0) {
140 $error = DelBiblio
($myorder->{biblionumber
}) }
142 push @cannotdelbiblios, {biblionumber
=> ($myorder->{biblionumber
}),
143 title
=> $myorder->{'title'},
144 author
=> $myorder->{'author'},
145 countbiblio
=> $countbiblio,
146 itemcount
=>$itemcount,
147 subscriptions
=>$subscriptions};
150 push @cannotdelbiblios, {biblionumber
=> ($myorder->{biblionumber
}),
151 title
=> $myorder->{'title'},
152 author
=> $myorder->{'author'},
153 othererror
=> $error};
156 $template->param( cannotdelbiblios
=> \
@cannotdelbiblios );
159 DelBasket
($basketno,);
161 delete_confirmed
=> 1,
162 name
=> $bookseller->name,
163 booksellerid
=> $booksellerid,
165 } elsif ( !$bookseller ) {
166 $template->param( NO_BOOKSELLER
=> 1 );
167 } elsif ($op eq 'export') {
168 print $query->header(
170 -attachment
=> 'basket' . $basket->{'basketno'} . '.csv',
172 print GetBasketAsCSV
($query->param('basketno'), $query);
174 } elsif ($op eq 'email') {
176 SendAlerts
( 'orderacquisition', $query->param('basketno'), 'ACQORDER' );
179 push @messages, { type
=> 'error', code
=> $@
};
180 } elsif ( ref $err and exists $err->{error
} ) {
181 push @messages, { type
=> 'error', code
=> $err->{error
} };
183 push @messages, { type
=> 'message', code
=> 'email_sent' };
187 } elsif ($op eq 'close') {
188 my $confirm = $query->param('confirm') || $confirm_pref eq '2';
190 my $basketno = $query->param('basketno');
191 my $booksellerid = $query->param('booksellerid');
192 $basketno =~ /^\d+$/ and CloseBasket
($basketno);
193 # if requested, create basket group, close it and attach the basket
194 if ($query->param('createbasketgroup')) {
196 if(C4
::Context
->userenv and C4
::Context
->userenv->{'branch'}
197 and C4
::Context
->userenv->{'branch'} ne "NO_LIBRARY_SET") {
198 $branchcode = C4
::Context
->userenv->{'branch'};
200 my $basketgroupid = NewBasketgroup
( { name
=> $basket->{basketname
},
201 booksellerid
=> $booksellerid,
202 deliveryplace
=> $branchcode,
203 billingplace
=> $branchcode,
206 ModBasket
( { basketno
=> $basketno,
207 basketgroupid
=> $basketgroupid } );
208 print $query->redirect('/cgi-bin/koha/acqui/basketgroup.pl?booksellerid='.$booksellerid.'&closed=1');
210 print $query->redirect('/cgi-bin/koha/acqui/booksellers.pl?booksellerid=' . $booksellerid);
215 confirm_close
=> "1",
216 booksellerid
=> $booksellerid,
217 basketno
=> $basket->{'basketno'},
218 basketname
=> $basket->{'basketname'},
219 basketgroupname
=> $basket->{'basketname'},
222 } elsif ($op eq 'reopen') {
223 ReopenBasket
(scalar $query->param('basketno'));
224 print $query->redirect('/cgi-bin/koha/acqui/basket.pl?basketno='.$basket->{'basketno'})
226 elsif ( $op eq 'ediorder' ) {
227 edi_close_and_order
()
228 } elsif ( $op eq 'mod_users' ) {
229 my $basketusers_ids = $query->param('users_ids');
230 my @basketusers = split( /:/, $basketusers_ids );
231 ModBasketUsers
($basketno, @basketusers);
232 print $query->redirect("/cgi-bin/koha/acqui/basket.pl?basketno=$basketno");
234 } elsif ( $op eq 'mod_branch' ) {
235 my $branch = $query->param('branch');
236 $branch = undef if(defined $branch and $branch eq '');
238 basketno
=> $basket->{basketno
},
241 print $query->redirect("/cgi-bin/koha/acqui/basket.pl?basketno=$basketno");
245 if ( $op eq 'list' ) {
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;
330 my $total_tax_excluded = 0;
331 my $total_tax_included = 0;
332 my $total_tax_value = 0;
333 for my $order (@orders) {
334 my $line = get_order_infos
( $order, $bookseller);
335 if ( $line->{uncertainprice
} ) {
336 $template->param( uncertainprices
=> 1 );
339 $line->{tax_rate
} = $line->{tax_rate_on_ordering
};
340 $line->{tax_value
} = $line->{tax_value_on_ordering
};
342 push @books_loop, $line;
344 $foot{$$line{tax_rate
}}{tax_rate
} = $$line{tax_rate
};
345 $foot{$$line{tax_rate
}}{tax_value
} += $$line{tax_value
};
346 $total_tax_value += $$line{tax_value
};
347 $foot{$$line{tax_rate
}}{quantity
} += $$line{quantity
};
348 $total_quantity += $$line{quantity
};
349 $foot{$$line{tax_rate
}}{total_tax_excluded
} += $$line{total_tax_excluded
};
350 $total_tax_excluded += $$line{total_tax_excluded
};
351 $foot{$$line{tax_rate
}}{total_tax_included
} += $$line{total_tax_included
};
352 $total_tax_included += $$line{total_tax_included
};
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 my $line = get_order_infos
( $order, $bookseller);
362 push @cancelledorders_loop, $line;
365 my $contract = GetContract
({
366 contractnumber
=> $basket->{contractnumber
}
369 if ($basket->{basketgroupid
}){
370 $basketgroup = GetBasketgroup
($basket->{basketgroupid
});
372 my $borrower= GetMember
('borrowernumber' => $loggedinuser);
373 my $budgets = GetBudgetHierarchy
;
375 foreach my $r (@
{$budgets}) {
376 if (!defined $r->{budget_amount
} || $r->{budget_amount
} == 0) {
379 next unless (CanUserUseBudget
($loggedinuser, $r, $userflags));
386 basketno
=> $basketno,
388 basketname
=> $basket->{'basketname'},
389 basketbranchcode
=> $basket->{branch
},
390 basketnote
=> $basket->{note
},
391 basketbooksellernote
=> $basket->{booksellernote
},
392 basketcontractno
=> $basket->{contractnumber
},
393 basketcontractname
=> $contract->{contractname
},
394 branches_loop
=> \
@branches_loop,
395 creationdate
=> $basket->{creationdate
},
396 authorisedby
=> $basket->{authorisedby
},
397 authorisedbyname
=> $basket->{authorisedbyname
},
398 users_ids
=> join(':', @basketusers_ids),
399 users
=> \
@basketusers,
400 closedate
=> $basket->{closedate
},
401 estimateddeliverydate
=> $estimateddeliverydate,
402 is_standing
=> $basket->{is_standing
},
403 deliveryplace
=> $basket->{deliveryplace
},
404 billingplace
=> $basket->{billingplace
},
405 active
=> $bookseller->active,
406 booksellerid
=> $bookseller->id,
407 name
=> $bookseller->name,
408 books_loop
=> \
@books_loop,
409 book_foot_loop
=> \
@book_foot_loop,
410 cancelledorders_loop
=> \
@cancelledorders_loop,
411 total_quantity
=> $total_quantity,
412 total_tax_excluded
=> $total_tax_excluded,
413 total_tax_included
=> $total_tax_included,
414 total_tax_value
=> $total_tax_value,
415 currency
=> $active_currency->currency,
416 listincgst
=> $bookseller->listincgst,
417 basketgroups
=> $basketgroups,
418 basketgroup
=> $basketgroup,
419 grouped
=> $basket->{basketgroupid
},
420 # The double negatives and booleans here mean:
421 # "A basket cannot be closed if there are no orders in it or it's a standing order basket."
423 # (The template has another implicit restriction that the order cannot be closed if there
424 # are any orders with uncertain prices.)
425 unclosable
=> @orders ?
$basket->{is_standing
} : 1,
426 has_budgets
=> $has_budgets,
427 duplinbatch
=> $duplinbatch,
431 $template->param( messages
=> \
@messages );
432 output_html_with_http_headers
$query, $cookie, $template->output;
434 sub get_order_infos
{
436 my $bookseller = shift;
437 my $qty = $order->{'quantity'} || 0;
438 if ( !defined $order->{quantityreceived
} ) {
439 $order->{quantityreceived
} = 0;
441 my $budget = GetBudget
($order->{budget_id
});
442 my $basket = GetBasket
($order->{basketno
});
444 my %line = %{ $order };
445 # Don't show unreceived standing orders as received
446 $line{order_received
} = ( $qty == $order->{'quantityreceived'} && ( $basket->{is_standing
} ?
$qty : 1 ) );
447 $line{basketno
} = $basketno;
448 $line{budget_name
} = $budget->{budget_name
};
450 $line{total_tax_included
} = $line{ecost_tax_included
} * $line{quantity
};
451 $line{total_tax_excluded
} = $line{ecost_tax_excluded
} * $line{quantity
};
452 $line{tax_value
} = $line{tax_value_on_ordering
};
453 $line{tax_rate
} = $line{tax_rate_on_ordering
};
455 if ( $line{uncertainprice
} ) {
456 $line{rrp_tax_excluded
} .= ' (Uncertain)';
458 if ( $line{'title'} ) {
459 my $volume = $order->{'volume'};
460 my $seriestitle = $order->{'seriestitle'};
461 $line{'title'} .= " / $seriestitle" if $seriestitle;
462 $line{'title'} .= " / $volume" if $volume;
465 my $biblionumber = $order->{'biblionumber'};
466 if ( $biblionumber ) { # The biblio still exists
467 my $biblio = Koha
::Biblios
->find( $biblionumber );
468 my $countbiblio = CountBiblioInOrders
($biblionumber);
469 my $ordernumber = $order->{'ordernumber'};
470 my @subscriptions = GetSubscriptionsId
($biblionumber);
471 my $itemcount = $biblio->items->count;
472 my $holds_count = $biblio->holds->count;
473 my @items = GetItemnumbersFromOrder
( $ordernumber );
474 my $itemholds = $biblio->holds->search({ itemnumber
=> { -in => \
@items } })->count;
476 # 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
477 $line{can_del_bib
} = 1 if $countbiblio <= 1 && $itemcount == scalar @items && !(@subscriptions) && !($holds_count);
478 $line{items
} = ($itemcount) - (scalar @items);
479 $line{left_item
} = 1 if $line{items
} >= 1;
480 $line{left_biblio
} = 1 if $countbiblio > 1;
481 $line{biblios
} = $countbiblio - 1;
482 $line{left_subscription
} = 1 if scalar @subscriptions >= 1;
483 $line{subscriptions
} = scalar @subscriptions;
484 ($holds_count >= 1) ?
$line{left_holds
} = 1 : $line{left_holds
} = 0;
485 $line{left_holds_on_order
} = 1 if $line{left_holds
}==1 && ($line{items
} == 0 || $itemholds );
486 $line{holds
} = $holds_count;
487 $line{holds_on_order
} = $itemholds?
$itemholds:$holds_count if $line{left_holds_on_order
};
491 my $suggestion = GetSuggestionInfoFromBiblionumber
($line{biblionumber
});
492 $line{suggestionid
} = $$suggestion{suggestionid
};
493 $line{surnamesuggestedby
} = $$suggestion{surnamesuggestedby
};
494 $line{firstnamesuggestedby
} = $$suggestion{firstnamesuggestedby
};
496 foreach my $key (qw(transferred_from transferred_to)) {
498 my $order = GetOrder
($line{$key});
499 my $bookseller = Koha
::Acquisition
::Booksellers
->find( $basket->{booksellerid
} );
503 bookseller
=> $bookseller,
504 timestamp
=> $line{$key . '_timestamp'},
512 sub edi_close_and_order
{
513 my $confirm = $query->param('confirm') || $confirm_pref eq '2';
516 basketno
=> $basketno,
519 if ( $basket->{branch
} ) {
520 $edi_params->{branchcode
} = $basket->{branch
};
522 if ( create_edi_order
($edi_params) ) {
523 #$template->param( edifile => 1 );
525 CloseBasket
($basketno);
527 # if requested, create basket group, close it and attach the basket
528 if ( $query->param('createbasketgroup') ) {
530 if ( C4
::Context
->userenv
531 and C4
::Context
->userenv->{'branch'}
532 and C4
::Context
->userenv->{'branch'} ne "NO_LIBRARY_SET" )
534 $branchcode = C4
::Context
->userenv->{'branch'};
536 my $basketgroupid = NewBasketgroup
(
538 name
=> $basket->{basketname
},
539 booksellerid
=> $booksellerid,
540 deliveryplace
=> $branchcode,
541 billingplace
=> $branchcode,
547 basketno
=> $basketno,
548 basketgroupid
=> $basketgroupid
551 print $query->redirect(
552 "/cgi-bin/koha/acqui/basketgroup.pl?booksellerid=$booksellerid&closed=1"
556 print $query->redirect(
557 "/cgi-bin/koha/acqui/booksellers.pl?booksellerid=$booksellerid"
565 booksellerid
=> $booksellerid,
566 basketno
=> $basket->{basketno
},
567 basketname
=> $basket->{basketname
},
568 basketgroupname
=> $basket->{basketname
},
571 $template->param( ean
=> $ean );