Bug 11081: (followup) Add license information
[koha.git] / acqui / basket.pl
blob5fa94f86ef8a4cb9f5caffbf24967d6371af51db
1 #!/usr/bin/perl
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>.
23 use strict;
24 use warnings;
25 use C4::Auth;
26 use C4::Koha;
27 use C4::Output;
28 use CGI qw ( -utf8 );
29 use C4::Acquisition;
30 use C4::Budgets;
31 use C4::Branch;
32 use C4::Contract;
33 use C4::Debug;
34 use C4::Biblio;
35 use C4::Members qw/GetMember/; #needed for permissions checking for changing basketgroup of a basket
36 use C4::Items;
37 use C4::Suggestions;
38 use Date::Calc qw/Add_Delta_Days/;
40 =head1 NAME
42 basket.pl
44 =head1 DESCRIPTION
46 This script display all informations about basket for the supplier given
47 on input arg. Moreover, it allows us to add a new order for this supplier from
48 an existing record, a suggestion or a new record.
50 =head1 CGI PARAMETERS
52 =over 4
54 =item $basketno
56 The basket number.
58 =item booksellerid
60 the supplier this script have to display the basket.
62 =item order
64 =back
66 =cut
68 my $query = new CGI;
69 our $basketno = $query->param('basketno');
70 my $booksellerid = $query->param('booksellerid');
71 my $duplinbatch = $query->param('duplinbatch');
73 my ( $template, $loggedinuser, $cookie, $userflags ) = get_template_and_user(
75 template_name => "acqui/basket.tt",
76 query => $query,
77 type => "intranet",
78 authnotrequired => 0,
79 flagsrequired => { acquisition => 'order_manage' },
80 debug => 1,
84 my $basket = GetBasket($basketno);
85 $booksellerid = $basket->{booksellerid} unless $booksellerid;
86 my $bookseller = Koha::Acquisition::Bookseller->fetch({ id => $booksellerid });
88 unless (CanUserManageBasket($loggedinuser, $basket, $userflags)) {
89 $template->param(
90 cannot_manage_basket => 1,
91 basketno => $basketno,
92 basketname => $basket->{basketname},
93 booksellerid => $booksellerid,
94 name => $bookseller->{name}
96 output_html_with_http_headers $query, $cookie, $template->output;
97 exit;
100 # FIXME : what about the "discount" percentage?
101 # FIXME : the query->param('booksellerid') below is probably useless. The bookseller is always known from the basket
102 # if no booksellerid in parameter, get it from basket
103 # warn "=>".$basket->{booksellerid};
104 my $op = $query->param('op');
105 if (!defined $op) {
106 $op = q{};
109 my $confirm_pref= C4::Context->preference("BasketConfirmations") || '1';
110 $template->param( skip_confirm_reopen => 1) if $confirm_pref eq '2';
112 if ( $op eq 'delete_confirm' ) {
113 my $basketno = $query->param('basketno');
114 my $delbiblio = $query->param('delbiblio');
115 my @orders = GetOrders($basketno);
116 #Delete all orders included in that basket, and all items received.
117 foreach my $myorder (@orders){
118 DelOrder($myorder->{biblionumber},$myorder->{ordernumber});
120 # if $delbiblio = 1, delete the records if possible
121 if ((defined $delbiblio)and ($delbiblio ==1)){
122 my @cannotdelbiblios ;
123 foreach my $myorder (@orders){
124 my $biblionumber = $myorder->{'biblionumber'};
125 my $countbiblio = CountBiblioInOrders($biblionumber);
126 my $ordernumber = $myorder->{'ordernumber'};
127 my $subscriptions = scalar GetSubscriptionsId ($biblionumber);
128 my $itemcount = GetItemsCount($biblionumber);
129 my $error;
130 if ($countbiblio == 0 && $itemcount == 0 && $subscriptions == 0) {
131 $error = DelBiblio($myorder->{biblionumber}) }
132 else {
133 push @cannotdelbiblios, {biblionumber=> ($myorder->{biblionumber}),
134 title=> $myorder->{'title'},
135 author=> $myorder->{'author'},
136 countbiblio=> $countbiblio,
137 itemcount=>$itemcount,
138 subscriptions=>$subscriptions};
140 if ($error) {
141 push @cannotdelbiblios, {biblionumber=> ($myorder->{biblionumber}),
142 title=> $myorder->{'title'},
143 author=> $myorder->{'author'},
144 othererror=> $error};
147 $template->param( cannotdelbiblios => \@cannotdelbiblios );
149 # delete the basket
150 DelBasket($basketno,);
151 $template->param( delete_confirmed => 1 );
152 } elsif ( !$bookseller ) {
153 $template->param( NO_BOOKSELLER => 1 );
154 } elsif ($op eq 'export') {
155 print $query->header(
156 -type => 'text/csv',
157 -attachment => 'basket' . $basket->{'basketno'} . '.csv',
159 print GetBasketAsCSV($query->param('basketno'), $query);
160 exit;
161 } elsif ($op eq 'close') {
162 my $confirm = $query->param('confirm') || $confirm_pref eq '2';
163 if ($confirm) {
164 my $basketno = $query->param('basketno');
165 my $booksellerid = $query->param('booksellerid');
166 $basketno =~ /^\d+$/ and CloseBasket($basketno);
167 # if requested, create basket group, close it and attach the basket
168 if ($query->param('createbasketgroup')) {
169 my $branchcode;
170 if(C4::Context->userenv and C4::Context->userenv->{'branch'}
171 and C4::Context->userenv->{'branch'} ne "NO_LIBRARY_SET") {
172 $branchcode = C4::Context->userenv->{'branch'};
174 my $basketgroupid = NewBasketgroup( { name => $basket->{basketname},
175 booksellerid => $booksellerid,
176 deliveryplace => $branchcode,
177 billingplace => $branchcode,
178 closed => 1,
180 ModBasket( { basketno => $basketno,
181 basketgroupid => $basketgroupid } );
182 print $query->redirect('/cgi-bin/koha/acqui/basketgroup.pl?booksellerid='.$booksellerid.'&closed=1');
183 } else {
184 print $query->redirect('/cgi-bin/koha/acqui/booksellers.pl?booksellerid=' . $booksellerid);
186 exit;
187 } else {
188 $template->param(
189 confirm_close => "1",
190 booksellerid => $booksellerid,
191 basketno => $basket->{'basketno'},
192 basketname => $basket->{'basketname'},
193 basketgroupname => $basket->{'basketname'},
196 } elsif ($op eq 'reopen') {
197 ReopenBasket($query->param('basketno'));
198 print $query->redirect('/cgi-bin/koha/acqui/basket.pl?basketno='.$basket->{'basketno'})
199 } elsif ( $op eq 'mod_users' ) {
200 my $basketusers_ids = $query->param('users_ids');
201 my @basketusers = split( /:/, $basketusers_ids );
202 ModBasketUsers($basketno, @basketusers);
203 print $query->redirect("/cgi-bin/koha/acqui/basket.pl?basketno=$basketno");
204 exit;
205 } elsif ( $op eq 'mod_branch' ) {
206 my $branch = $query->param('branch');
207 $branch = undef if(defined $branch and $branch eq '');
208 ModBasket({
209 basketno => $basket->{basketno},
210 branch => $branch
212 print $query->redirect("/cgi-bin/koha/acqui/basket.pl?basketno=$basketno");
213 exit;
214 } else {
215 my @branches_loop;
216 # get librarian branch...
217 if ( C4::Context->preference("IndependentBranches") ) {
218 my $userenv = C4::Context->userenv;
219 unless ( C4::Context->IsSuperLibrarian() ) {
220 my $validtest = ( $basket->{creationdate} eq '' )
221 || ( $userenv->{branch} eq $basket->{branch} )
222 || ( $userenv->{branch} eq '' )
223 || ( $basket->{branch} eq '' );
224 unless ($validtest) {
225 print $query->redirect("../mainpage.pl");
226 exit 1;
229 if (!defined $basket->{branch} or $basket->{branch} eq $userenv->{branch}) {
230 push @branches_loop, {
231 branchcode => $userenv->{branch},
232 branchname => $userenv->{branchname},
233 selected => 1,
236 } else {
237 # get branches
238 my $branches = C4::Branch::GetBranches;
239 my @branchcodes = sort {
240 $branches->{$a}->{branchname} cmp $branches->{$b}->{branchname}
241 } keys %$branches;
242 foreach my $branch (@branchcodes) {
243 my $selected = 0;
244 if (defined $basket->{branch}) {
245 $selected = 1 if $branch eq $basket->{branch};
246 } else {
247 $selected = 1 if $branch eq C4::Context->userenv->{branch};
249 push @branches_loop, {
250 branchcode => $branch,
251 branchname => $branches->{$branch}->{branchname},
252 selected => $selected
257 #if the basket is closed,and the user has the permission to edit basketgroups, display a list of basketgroups
258 my ($basketgroup, $basketgroups);
259 my $staffuser = GetMember(borrowernumber => $loggedinuser);
260 if ($basket->{closedate} && haspermission($staffuser->{userid}, { acquisition => 'group_manage'} )) {
261 $basketgroups = GetBasketgroups($basket->{booksellerid});
262 for my $bg ( @{$basketgroups} ) {
263 if ($basket->{basketgroupid} && $basket->{basketgroupid} == $bg->{id}){
264 $bg->{default} = 1;
265 $basketgroup = $bg;
270 # if the basket is closed, calculate estimated delivery date
271 my $estimateddeliverydate;
272 if( $basket->{closedate} ) {
273 my ($year, $month, $day) = ($basket->{closedate} =~ /(\d+)-(\d+)-(\d+)/);
274 ($year, $month, $day) = Add_Delta_Days($year, $month, $day, $bookseller->{deliverytime});
275 $estimateddeliverydate = sprintf( "%04d-%02d-%02d", $year, $month, $day );
278 # if new basket, pre-fill infos
279 $basket->{creationdate} = "" unless ( $basket->{creationdate} );
280 $basket->{authorisedby} = $loggedinuser unless ( $basket->{authorisedby} );
281 $debug
282 and warn sprintf
283 "loggedinuser: $loggedinuser; creationdate: %s; authorisedby: %s",
284 $basket->{creationdate}, $basket->{authorisedby};
286 my @basketusers_ids = GetBasketUsers($basketno);
287 my @basketusers;
288 foreach my $basketuser_id (@basketusers_ids) {
289 my $basketuser = GetMember(borrowernumber => $basketuser_id);
290 push @basketusers, $basketuser if $basketuser;
293 #to get active currency
294 my $cur = GetCurrency();
297 my @orders = GetOrders( $basketno );
298 my @books_loop;
300 my @book_foot_loop;
301 my %foot;
302 my $total_quantity = 0;
303 my $total_gste = 0;
304 my $total_gsti = 0;
305 my $total_gstvalue = 0;
306 for my $order (@orders) {
307 $order = C4::Acquisition::populate_order_with_prices({ order => $order, booksellerid => $booksellerid, ordering => 1 });
308 my $line = get_order_infos( $order, $bookseller);
309 if ( $line->{uncertainprice} ) {
310 $template->param( uncertainprices => 1 );
313 push @books_loop, $line;
315 $foot{$$line{gstrate}}{gstrate} = $$line{gstrate};
316 $foot{$$line{gstrate}}{gstvalue} += $$line{gstvalue};
317 $total_gstvalue += $$line{gstvalue};
318 $foot{$$line{gstrate}}{quantity} += $$line{quantity};
319 $total_quantity += $$line{quantity};
320 $foot{$$line{gstrate}}{totalgste} += $$line{totalgste};
321 $total_gste += $$line{totalgste};
322 $foot{$$line{gstrate}}{totalgsti} += $$line{totalgsti};
323 $total_gsti += $$line{totalgsti};
326 push @book_foot_loop, map {$_} values %foot;
328 # Get cancelled orders
329 my @cancelledorders = GetOrders($basketno, { cancelled => 1 });
330 my @cancelledorders_loop;
331 for my $order (@cancelledorders) {
332 $order = C4::Acquisition::populate_order_with_prices({ order => $order, booksellerid => $booksellerid, ordering => 1 });
333 my $line = get_order_infos( $order, $bookseller);
334 push @cancelledorders_loop, $line;
337 my $contract = GetContract({
338 contractnumber => $basket->{contractnumber}
341 if ($basket->{basketgroupid}){
342 $basketgroup = GetBasketgroup($basket->{basketgroupid});
343 $basketgroup->{deliveryplacename} = C4::Branch::GetBranchName( $basketgroup->{deliveryplace} );
344 $basketgroup->{billingplacename} = C4::Branch::GetBranchName( $basketgroup->{billingplace} );
346 my $borrower= GetMember('borrowernumber' => $loggedinuser);
347 my $budgets = GetBudgetHierarchy;
348 my $has_budgets = 0;
349 foreach my $r (@{$budgets}) {
350 if (!defined $r->{budget_amount} || $r->{budget_amount} == 0) {
351 next;
353 next unless (CanUserUseBudget($loggedinuser, $r, $userflags));
355 $has_budgets = 1;
356 last;
359 $template->param(
360 basketno => $basketno,
361 basketname => $basket->{'basketname'},
362 basketbranchname => C4::Branch::GetBranchName($basket->{branch}),
363 basketnote => $basket->{note},
364 basketbooksellernote => $basket->{booksellernote},
365 basketcontractno => $basket->{contractnumber},
366 basketcontractname => $contract->{contractname},
367 branches_loop => \@branches_loop,
368 creationdate => $basket->{creationdate},
369 authorisedby => $basket->{authorisedby},
370 authorisedbyname => $basket->{authorisedbyname},
371 users_ids => join(':', @basketusers_ids),
372 users => \@basketusers,
373 closedate => $basket->{closedate},
374 estimateddeliverydate=> $estimateddeliverydate,
375 deliveryplace => C4::Branch::GetBranchName( $basket->{deliveryplace} ),
376 billingplace => C4::Branch::GetBranchName( $basket->{billingplace} ),
377 active => $bookseller->{'active'},
378 booksellerid => $bookseller->{'id'},
379 name => $bookseller->{'name'},
380 books_loop => \@books_loop,
381 book_foot_loop => \@book_foot_loop,
382 cancelledorders_loop => \@cancelledorders_loop,
383 total_quantity => $total_quantity,
384 total_gste => sprintf( "%.2f", $total_gste ),
385 total_gsti => sprintf( "%.2f", $total_gsti ),
386 total_gstvalue => sprintf( "%.2f", $total_gstvalue ),
387 currency => $cur->{'currency'},
388 listincgst => $bookseller->{listincgst},
389 basketgroups => $basketgroups,
390 basketgroup => $basketgroup,
391 grouped => $basket->{basketgroupid},
392 unclosable => @orders ? 0 : 1,
393 has_budgets => $has_budgets,
394 duplinbatch => $duplinbatch,
398 sub get_order_infos {
399 my $order = shift;
400 my $bookseller = shift;
401 my $qty = $order->{'quantity'} || 0;
402 if ( !defined $order->{quantityreceived} ) {
403 $order->{quantityreceived} = 0;
405 my $budget = GetBudget( $order->{'budget_id'} );
407 my %line = %{ $order };
408 $line{order_received} = ( $qty == $order->{'quantityreceived'} );
409 $line{basketno} = $basketno;
410 $line{budget_name} = $budget->{budget_name};
412 if ( $line{uncertainprice} ) {
413 $line{rrpgste} .= ' (Uncertain)';
415 if ( $line{'title'} ) {
416 my $volume = $order->{'volume'};
417 my $seriestitle = $order->{'seriestitle'};
418 $line{'title'} .= " / $seriestitle" if $seriestitle;
419 $line{'title'} .= " / $volume" if $volume;
422 my $biblionumber = $order->{'biblionumber'};
423 my $countbiblio = CountBiblioInOrders($biblionumber);
424 my $ordernumber = $order->{'ordernumber'};
425 my @subscriptions = GetSubscriptionsId ($biblionumber);
426 my $itemcount = GetItemsCount($biblionumber);
427 my $holds = GetHolds ($biblionumber);
428 my @items = GetItemnumbersFromOrder( $ordernumber );
429 my $itemholds;
430 foreach my $item (@items){
431 my $nb = GetItemHolds($biblionumber, $item);
432 if ($nb){
433 $itemholds += $nb;
436 # 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
437 $line{can_del_bib} = 1 if $countbiblio <= 1 && $itemcount == scalar @items && !(@subscriptions) && !($holds);
438 $line{items} = ($itemcount) - (scalar @items);
439 $line{left_item} = 1 if $line{items} >= 1;
440 $line{left_biblio} = 1 if $countbiblio > 1;
441 $line{biblios} = $countbiblio - 1;
442 $line{left_subscription} = 1 if scalar @subscriptions >= 1;
443 $line{subscriptions} = scalar @subscriptions;
444 ($holds >= 1) ? $line{left_holds} = 1 : $line{left_holds} = 0;
445 $line{left_holds_on_order} = 1 if $line{left_holds}==1 && ($line{items} == 0 || $itemholds );
446 $line{holds} = $holds;
447 $line{holds_on_order} = $itemholds?$itemholds:$holds if $line{left_holds_on_order};
450 my $suggestion = GetSuggestionInfoFromBiblionumber($line{biblionumber});
451 $line{suggestionid} = $$suggestion{suggestionid};
452 $line{surnamesuggestedby} = $$suggestion{surnamesuggestedby};
453 $line{firstnamesuggestedby} = $$suggestion{firstnamesuggestedby};
455 foreach my $key (qw(transferred_from transferred_to)) {
456 if ($line{$key}) {
457 my $order = GetOrder($line{$key});
458 my $basket = GetBasket($order->{basketno});
459 my $bookseller = Koha::Acquisition::Bookseller->fetch({ id => $basket->{booksellerid} });
460 $line{$key} = {
461 order => $order,
462 basket => $basket,
463 bookseller => $bookseller,
464 timestamp => $line{$key . '_timestamp'},
469 return \%line;
472 output_html_with_http_headers $query, $cookie, $template->output;