Bug 7751: Decrease Loans for Items in Demand for Holds
[koha.git] / acqui / basket.pl
blob9b36c14846c5ddced2f97e4b8d54f7539567e8b5
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 under the
11 # terms of the GNU General Public License as published by the Free Software
12 # Foundation; either version 2 of the License, or (at your option) any later
13 # version.
15 # Koha is distributed in the hope that it will be useful, but WITHOUT ANY
16 # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
17 # A PARTICULAR PURPOSE. See the GNU General Public License for more details.
19 # You should have received a copy of the GNU General Public License along
20 # with Koha; if not, write to the Free Software Foundation, Inc.,
21 # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
23 use strict;
24 use warnings;
25 use C4::Auth;
26 use C4::Koha;
27 use C4::Output;
28 use CGI;
29 use C4::Acquisition;
30 use C4::Budgets;
31 use C4::Bookseller qw( GetBookSellerFromId);
32 use C4::Debug;
33 use C4::Biblio;
34 use C4::Members qw/GetMember/; #needed for permissions checking for changing basketgroup of a basket
35 use C4::Items;
36 use C4::Suggestions;
37 use Date::Calc qw/Add_Delta_Days/;
39 =head1 NAME
41 basket.pl
43 =head1 DESCRIPTION
45 This script display all informations about basket for the supplier given
46 on input arg. Moreover, it allows us to add a new order for this supplier from
47 an existing record, a suggestion or a new record.
49 =head1 CGI PARAMETERS
51 =over 4
53 =item $basketno
55 The basket number.
57 =item booksellerid
59 the supplier this script have to display the basket.
61 =item order
63 =back
65 =cut
67 my $query = new CGI;
68 my $basketno = $query->param('basketno');
69 my $booksellerid = $query->param('booksellerid');
71 my ( $template, $loggedinuser, $cookie, $userflags ) = get_template_and_user(
73 template_name => "acqui/basket.tmpl",
74 query => $query,
75 type => "intranet",
76 authnotrequired => 0,
77 flagsrequired => { acquisition => 'order_manage' },
78 debug => 1,
82 my $basket = GetBasket($basketno);
84 # FIXME : what about the "discount" percentage?
85 # FIXME : the query->param('booksellerid') below is probably useless. The bookseller is always known from the basket
86 # if no booksellerid in parameter, get it from basket
87 # warn "=>".$basket->{booksellerid};
88 $booksellerid = $basket->{booksellerid} unless $booksellerid;
89 my ($bookseller) = GetBookSellerFromId($booksellerid);
90 my $op = $query->param('op');
91 if (!defined $op) {
92 $op = q{};
95 my $confirm_pref= C4::Context->preference("BasketConfirmations") || '1';
96 $template->param( skip_confirm_reopen => 1) if $confirm_pref eq '2';
98 if ( $op eq 'delete_confirm' ) {
99 my $basketno = $query->param('basketno');
100 DelBasket($basketno);
101 $template->param( delete_confirmed => 1 );
102 } elsif ( !$bookseller ) {
103 $template->param( NO_BOOKSELLER => 1 );
104 } elsif ( $op eq 'del_basket') {
105 $template->param( delete_confirm => 1 );
106 if ( C4::Context->preference("IndependantBranches") ) {
107 my $userenv = C4::Context->userenv;
108 unless ( $userenv->{flags} == 1 ) {
109 my $validtest = ( $basket->{creationdate} eq '' )
110 || ( $userenv->{branch} eq $basket->{branch} )
111 || ( $userenv->{branch} eq '' )
112 || ( $basket->{branch} eq '' );
113 unless ($validtest) {
114 print $query->redirect("../mainpage.pl");
115 exit 1;
119 $basket->{creationdate} = "" unless ( $basket->{creationdate} );
120 $basket->{authorisedby} = $loggedinuser unless ( $basket->{authorisedby} );
121 my $contract = &GetContract($basket->{contractnumber});
122 $template->param(
123 basketno => $basketno,
124 basketname => $basket->{'basketname'},
125 basketnote => $basket->{note},
126 basketbooksellernote => $basket->{booksellernote},
127 basketcontractno => $basket->{contractnumber},
128 basketcontractname => $contract->{contractname},
129 creationdate => $basket->{creationdate},
130 authorisedby => $basket->{authorisedby},
131 authorisedbyname => $basket->{authorisedbyname},
132 closedate => $basket->{closedate},
133 active => $bookseller->{'active'},
134 booksellerid => $bookseller->{'id'},
135 name => $bookseller->{'name'},
136 address1 => $bookseller->{'address1'},
137 address2 => $bookseller->{'address2'},
138 address3 => $bookseller->{'address3'},
139 address4 => $bookseller->{'address4'},
141 } elsif ($op eq 'attachbasket' && $template->{'VARS'}->{'CAN_user_acquisition_group_manage'} == 1) {
142 print $query->redirect('/cgi-bin/koha/acqui/basketgroup.pl?basketno=' . $basket->{'basketno'} . '&op=attachbasket&booksellerid=' . $booksellerid);
143 # check if we have to "close" a basket before building page
144 } elsif ($op eq 'export') {
145 print $query->header(
146 -type => 'text/csv',
147 -attachment => 'basket' . $basket->{'basketno'} . '.csv',
149 print GetBasketAsCSV($query->param('basketno'), $query);
150 exit;
151 } elsif ($op eq 'close') {
152 my $confirm = $query->param('confirm') || $confirm_pref eq '2';
153 if ($confirm) {
154 my $basketno = $query->param('basketno');
155 my $booksellerid = $query->param('booksellerid');
156 $basketno =~ /^\d+$/ and CloseBasket($basketno);
157 # if requested, create basket group, close it and attach the basket
158 if ($query->param('createbasketgroup')) {
159 my $branchcode;
160 if(C4::Context->userenv and C4::Context->userenv->{'branch'}
161 and C4::Context->userenv->{'branch'} ne "NO_LIBRARY_SET") {
162 $branchcode = C4::Context->userenv->{'branch'};
164 my $basketgroupid = NewBasketgroup( { name => $basket->{basketname},
165 booksellerid => $booksellerid,
166 deliveryplace => $branchcode,
167 billingplace => $branchcode,
168 closed => 1,
170 ModBasket( { basketno => $basketno,
171 basketgroupid => $basketgroupid } );
172 print $query->redirect('/cgi-bin/koha/acqui/basketgroup.pl?booksellerid='.$booksellerid.'&closed=1');
173 } else {
174 print $query->redirect('/cgi-bin/koha/acqui/booksellers.pl?booksellerid=' . $booksellerid);
176 exit;
177 } else {
178 $template->param(confirm_close => "1",
179 booksellerid => $booksellerid,
180 basketno => $basket->{'basketno'},
181 basketname => $basket->{'basketname'},
182 basketgroupname => $basket->{'basketname'});
185 } elsif ($op eq 'reopen') {
186 my $basket;
187 $basket->{basketno} = $query->param('basketno');
188 $basket->{closedate} = undef;
189 ModBasket($basket);
190 print $query->redirect('/cgi-bin/koha/acqui/basket.pl?basketno='.$basket->{'basketno'})
191 } else {
192 # get librarian branch...
193 if ( C4::Context->preference("IndependantBranches") ) {
194 my $userenv = C4::Context->userenv;
195 unless ( $userenv->{flags} == 1 ) {
196 my $validtest = ( $basket->{creationdate} eq '' )
197 || ( $userenv->{branch} eq $basket->{branch} )
198 || ( $userenv->{branch} eq '' )
199 || ( $basket->{branch} eq '' );
200 unless ($validtest) {
201 print $query->redirect("../mainpage.pl");
202 exit 1;
206 #if the basket is closed,and the user has the permission to edit basketgroups, display a list of basketgroups
207 my $basketgroups;
208 my $member = GetMember(borrowernumber => $loggedinuser);
209 if ($basket->{closedate} && haspermission({ acquisition => 'group_manage'} )) {
210 $basketgroups = GetBasketgroups($basket->{booksellerid});
211 for my $bg ( @{$basketgroups} ) {
212 if ($basket->{basketgroupid} && $basket->{basketgroupid} == $bg->{id}){
213 $bg->{default} = 1;
216 my %emptygroup = ( id => undef,
217 name => "No group");
218 if ( ! $basket->{basketgroupid} ) {
219 $emptygroup{default} = 1;
220 $emptygroup{nogroup} = 1;
222 unshift( @$basketgroups, \%emptygroup );
225 # if the basket is closed, calculate estimated delivery date
226 my $estimateddeliverydate;
227 if( $basket->{closedate} ) {
228 my ($year, $month, $day) = ($basket->{closedate} =~ /(\d+)-(\d+)-(\d+)/);
229 ($year, $month, $day) = Add_Delta_Days($year, $month, $day, $bookseller->{deliverytime});
230 $estimateddeliverydate = "$year-$month-$day";
233 # if new basket, pre-fill infos
234 $basket->{creationdate} = "" unless ( $basket->{creationdate} );
235 $basket->{authorisedby} = $loggedinuser unless ( $basket->{authorisedby} );
236 $debug
237 and warn sprintf
238 "loggedinuser: $loggedinuser; creationdate: %s; authorisedby: %s",
239 $basket->{creationdate}, $basket->{authorisedby};
241 #to get active currency
242 my $cur = GetCurrency();
245 my @results = GetOrders( $basketno );
247 my $gist = $bookseller->{gstrate} // C4::Context->preference("gist") // 0;
248 $gist = 0 if $gist == 0.0000;
249 my $discount = $bookseller->{'discount'} / 100;
250 my $total_rrp = 0; # RRP Total, its value will be assigned to $total_rrp_gsti or $total_rrp_gste depending of $bookseller->{'listincgst'}
251 my $total_rrp_gsti = 0; # RRP Total, GST included
252 my $total_rrp_gste = 0; # RRP Total, GST excluded
253 my $gist_rrp = 0;
254 my $total_rrp_est = 0;
256 my $qty_total;
257 my @books_loop;
258 my $suggestion;
260 for my $order ( @results ) {
261 my $rrp = $order->{'listprice'} || 0;
262 my $qty = $order->{'quantity'} || 0;
263 if (!defined $order->{quantityreceived}) {
264 $order->{quantityreceived} = 0;
266 for ( qw(rrp ecost quantityreceived)) {
267 if (!defined $order->{$_}) {
268 $order->{$_} = 0;
272 my $budget = GetBudget( $order->{'budget_id'} );
273 $rrp = ConvertCurrency( $order->{'currency'}, $rrp );
275 $total_rrp += $qty * $order->{'rrp'};
276 my $line_total = $qty * $order->{'ecost'};
277 $total_rrp_est += $qty * $order->{'ecost'};
278 # FIXME: what about the "actual cost" field?
279 $qty_total += $qty;
280 my %line = %{ $order };
281 my $biblionumber = $order->{'biblionumber'};
282 my $countbiblio = CountBiblioInOrders($biblionumber);
283 my $ordernumber = $order->{'ordernumber'};
284 my @subscriptions = GetSubscriptionsId ($biblionumber);
285 my $itemcount = GetItemsCount($biblionumber);
286 my $holds = GetHolds ($biblionumber);
287 my @items = GetItemnumbersFromOrder( $ordernumber );
288 my $itemholds;
289 foreach my $item (@items){
290 my $nb = GetItemHolds($biblionumber, $item);
291 if ($nb){
292 $itemholds += $nb;
295 # 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
296 $line{can_del_bib} = 1 if $countbiblio <= 1 && $itemcount == scalar @items && !(@subscriptions) && !($holds);
297 $line{items} = ($itemcount) - (scalar @items);
298 $line{left_item} = 1 if $line{items} >= 1;
299 $line{left_biblio} = 1 if $countbiblio > 1;
300 $line{biblios} = $countbiblio - 1;
301 $line{left_subscription} = 1 if scalar @subscriptions >= 1;
302 $line{subscriptions} = scalar @subscriptions;
303 ($holds >= 1) ? $line{left_holds} = 1 : $line{left_holds} = 0;
304 $line{left_holds_on_order} = 1 if $line{left_holds}==1 && ($line{items} == 0 || $itemholds );
305 $line{holds} = $holds;
306 $line{holds_on_order} = $itemholds?$itemholds:$holds if $line{left_holds_on_order};
307 $line{order_received} = ( $qty == $order->{'quantityreceived'} );
308 $line{basketno} = $basketno;
309 $line{budget_name} = $budget->{budget_name};
310 $line{rrp} = sprintf( "%.2f", $line{'rrp'} );
311 $line{ecost} = sprintf( "%.2f", $line{'ecost'} );
312 $line{line_total} = sprintf( "%.2f", $line_total );
313 if ($line{uncertainprice}) {
314 $template->param( uncertainprices => 1 );
315 $line{rrp} .= ' (Uncertain)';
317 if ($line{'title'}){
318 my $volume = $order->{'volume'};
319 my $seriestitle = $order->{'seriestitle'};
320 $line{'title'} .= " / $seriestitle" if $seriestitle;
321 $line{'title'} .= " / $volume" if $volume;
322 } else {
323 $line{'title'} = "Deleted bibliographic notice, can't find title.";
326 $suggestion = GetSuggestionInfoFromBiblionumber($line{biblionumber});
327 $line{suggestionid} = $suggestion->{suggestionid};
328 $line{surnamesuggestedby} = $suggestion->{surnamesuggestedby};
329 $line{firstnamesuggestedby} = $suggestion->{firstnamesuggestedby};
331 push @books_loop, \%line;
334 my $total_est_gste;
335 my $total_est_gsti;
336 my $gist_est;
337 if ($gist){ # if we have GST
338 if ( $bookseller->{'listincgst'} ) { # if prices already includes GST
339 $total_rrp_gsti = $total_rrp; # we know $total_rrp_gsti
340 $total_rrp_gste = $total_rrp_gsti / ( $gist + 1 ); # and can reverse compute other values
341 $gist_rrp = $total_rrp_gsti - $total_rrp_gste; #
342 $total_est_gste = $total_rrp_gste - ( $total_rrp_gste * $discount );
343 $total_est_gsti = $total_rrp_est;
344 } else { # if prices does not include GST
345 $total_rrp_gste = $total_rrp; # then we use the common way to compute other values
346 $gist_rrp = $total_rrp_gste * $gist; #
347 $total_rrp_gsti = $total_rrp_gste + $gist_rrp; #
348 $total_est_gste = $total_rrp_est;
349 $total_est_gsti = $total_rrp_gsti - ( $total_rrp_gsti * $discount );
351 $gist_est = $gist_rrp - ( $gist_rrp * $discount );
352 } else {
353 $total_rrp_gsti = $total_rrp;
354 $total_est_gsti = $total_rrp_est;
357 my $contract = &GetContract($basket->{contractnumber});
358 my @orders = GetOrders($basketno);
360 my $borrower= GetMember('borrowernumber' => $loggedinuser);
361 my $budgets = GetBudgetHierarchy;
362 my $has_budgets = 0;
363 foreach my $r (@{$budgets}) {
364 if (!defined $r->{budget_amount} || $r->{budget_amount} == 0) {
365 next;
367 next unless (CanUserUseBudget($loggedinuser, $r, $userflags));
369 $has_budgets = 1;
370 last;
373 my @cancelledorders = GetCancelledOrders($basketno);
374 foreach (@cancelledorders) {
375 $_->{'line_total'} = sprintf("%.2f", $_->{'ecost'} * $_->{'quantity'});
378 $template->param(
379 basketno => $basketno,
380 basketname => $basket->{'basketname'},
381 basketnote => $basket->{note},
382 basketbooksellernote => $basket->{booksellernote},
383 basketcontractno => $basket->{contractnumber},
384 basketcontractname => $contract->{contractname},
385 creationdate => $basket->{creationdate},
386 authorisedby => $basket->{authorisedby},
387 authorisedbyname => $basket->{authorisedbyname},
388 closedate => $basket->{closedate},
389 estimateddeliverydate=> $estimateddeliverydate,
390 active => $bookseller->{'active'},
391 booksellerid => $bookseller->{'id'},
392 name => $bookseller->{'name'},
393 books_loop => \@books_loop,
394 cancelledorders_loop => \@cancelledorders,
395 gist_rate => sprintf( "%.2f", $gist * 100 ) . '%',
396 total_rrp_gste => sprintf( "%.2f", $total_rrp_gste ),
397 total_est_gste => sprintf( "%.2f", $total_est_gste ),
398 gist_est => sprintf( "%.2f", $gist_est ),
399 gist_rrp => sprintf( "%.2f", $gist_rrp ),
400 total_rrp_gsti => sprintf( "%.2f", $total_rrp_gsti ),
401 total_est_gsti => sprintf( "%.2f", $total_est_gsti ),
402 # currency => $bookseller->{'listprice'},
403 currency => $cur->{'currency'},
404 qty_total => $qty_total,
405 GST => $gist,
406 basketgroups => $basketgroups,
407 grouped => $basket->{basketgroupid},
408 unclosable => @orders ? 0 : 1,
409 has_budgets => $has_budgets,
413 output_html_with_http_headers $query, $cookie, $template->output;