Bug 7169: Change booksellers search results display
[koha.git] / acqui / basket.pl
1 #!/usr/bin/perl
2
3 #script to show display basket of orders
4
5 # Copyright 2000 - 2004 Katipo
6 # Copyright 2008 - 2009 BibLibre SARL
7 #
8 # This file is part of Koha.
9 #
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.
14 #
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.
18 #
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.
22
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
38 =head1 NAME
39
40 basket.pl
41
42 =head1 DESCRIPTION
43
44  This script display all informations about basket for the supplier given
45  on input arg.  Moreover, it allows us to add a new order for this supplier from
46  an existing record, a suggestion or a new record.
47
48 =head1 CGI PARAMETERS
49
50 =over 4
51
52 =item $basketno
53
54 The basket number.
55
56 =item booksellerid
57
58 the supplier this script have to display the basket.
59
60 =item order
61
62 =back
63
64 =cut
65
66 my $query        = new CGI;
67 my $basketno     = $query->param('basketno');
68 my $booksellerid = $query->param('booksellerid');
69
70 my ( $template, $loggedinuser, $cookie ) = get_template_and_user(
71     {
72         template_name   => "acqui/basket.tmpl",
73         query           => $query,
74         type            => "intranet",
75         authnotrequired => 0,
76         flagsrequired   => { acquisition => 'order_manage' },
77         debug           => 1,
78     }
79 );
80
81 my $basket = GetBasket($basketno);
82
83 # FIXME : what about the "discount" percentage?
84 # FIXME : the query->param('booksellerid') below is probably useless. The bookseller is always known from the basket
85 # if no booksellerid in parameter, get it from basket
86 # warn "=>".$basket->{booksellerid};
87 $booksellerid = $basket->{booksellerid} unless $booksellerid;
88 my ($bookseller) = GetBookSellerFromId($booksellerid);
89 my $op = $query->param('op');
90 if (!defined $op) {
91     $op = q{};
92 }
93
94 my $confirm_pref= C4::Context->preference("BasketConfirmations") || '1';
95 $template->param( skip_confirm_reopen => 1) if $confirm_pref eq '2';
96
97 if ( $op eq 'delete_confirm' ) {
98     my $basketno = $query->param('basketno');
99     DelBasket($basketno);
100     $template->param( delete_confirmed => 1 );
101 } elsif ( !$bookseller ) {
102     $template->param( NO_BOOKSELLER => 1 );
103 } elsif ( $op eq 'del_basket') {
104     $template->param( delete_confirm => 1 );
105     if ( C4::Context->preference("IndependantBranches") ) {
106         my $userenv = C4::Context->userenv;
107         unless ( $userenv->{flags} == 1 ) {
108             my $validtest = ( $basket->{creationdate} eq '' )
109               || ( $userenv->{branch} eq $basket->{branch} )
110               || ( $userenv->{branch} eq '' )
111               || ( $basket->{branch}  eq '' );
112             unless ($validtest) {
113                 print $query->redirect("../mainpage.pl");
114                 exit 1;
115             }
116         }
117     }
118     $basket->{creationdate} = ""            unless ( $basket->{creationdate} );
119     $basket->{authorisedby} = $loggedinuser unless ( $basket->{authorisedby} );
120     my $contract = &GetContract($basket->{contractnumber});
121     $template->param(
122         basketno             => $basketno,
123         basketname           => $basket->{'basketname'},
124         basketnote           => $basket->{note},
125         basketbooksellernote => $basket->{booksellernote},
126         basketcontractno     => $basket->{contractnumber},
127         basketcontractname   => $contract->{contractname},
128         creationdate         => $basket->{creationdate},
129         authorisedby         => $basket->{authorisedby},
130         authorisedbyname     => $basket->{authorisedbyname},
131         closedate            => $basket->{closedate},
132         active               => $bookseller->{'active'},
133         booksellerid         => $bookseller->{'id'},
134         name                 => $bookseller->{'name'},
135         address1             => $bookseller->{'address1'},
136         address2             => $bookseller->{'address2'},
137         address3             => $bookseller->{'address3'},
138         address4             => $bookseller->{'address4'},
139       );
140 } elsif ($op eq 'attachbasket' && $template->{'VARS'}->{'CAN_user_acquisition_group_manage'} == 1) {
141       print $query->redirect('/cgi-bin/koha/acqui/basketgroup.pl?basketno=' . $basket->{'basketno'} . '&op=attachbasket&booksellerid=' . $booksellerid);
142     # check if we have to "close" a basket before building page
143 } elsif ($op eq 'export') {
144     print $query->header(
145         -type       => 'text/csv',
146         -attachment => 'basket' . $basket->{'basketno'} . '.csv',
147     );
148     print GetBasketAsCSV($query->param('basketno'));
149     exit;
150 } elsif ($op eq 'close') {
151     my $confirm = $query->param('confirm') || $confirm_pref eq '2';
152     if ($confirm) {
153         my $basketno = $query->param('basketno');
154         my $booksellerid = $query->param('booksellerid');
155         $basketno =~ /^\d+$/ and CloseBasket($basketno);
156         # if requested, create basket group, close it and attach the basket
157         if ($query->param('createbasketgroup')) {
158             my $basketgroupid = NewBasketgroup( { name => $basket->{basketname},
159                             booksellerid => $booksellerid,
160                             closed => 1,
161                             });
162             ModBasket( { basketno => $basketno,
163                          basketgroupid => $basketgroupid } );
164             print $query->redirect('/cgi-bin/koha/acqui/basketgroup.pl?booksellerid='.$booksellerid.'&closed=1');
165         } else {
166             print $query->redirect('/cgi-bin/koha/acqui/booksellers.pl?booksellerid=' . $booksellerid);
167         }
168         exit;
169     } else {
170     $template->param(confirm_close => "1",
171             booksellerid    => $booksellerid,
172             basketno        => $basket->{'basketno'},
173                 basketname      => $basket->{'basketname'},
174             basketgroupname => $basket->{'basketname'});
175         
176     }
177 } elsif ($op eq 'reopen') {
178     my $basket;
179     $basket->{basketno} = $query->param('basketno');
180     $basket->{closedate} = undef;
181     ModBasket($basket);
182     print $query->redirect('/cgi-bin/koha/acqui/basket.pl?basketno='.$basket->{'basketno'})
183 } else {
184     # get librarian branch...
185     if ( C4::Context->preference("IndependantBranches") ) {
186         my $userenv = C4::Context->userenv;
187         unless ( $userenv->{flags} == 1 ) {
188             my $validtest = ( $basket->{creationdate} eq '' )
189               || ( $userenv->{branch} eq $basket->{branch} )
190               || ( $userenv->{branch} eq '' )
191               || ( $basket->{branch}  eq '' );
192             unless ($validtest) {
193                 print $query->redirect("../mainpage.pl");
194                 exit 1;
195             }
196         }
197     }
198 #if the basket is closed,and the user has the permission to edit basketgroups, display a list of basketgroups
199     my $basketgroups;
200     my $member = GetMember(borrowernumber => $loggedinuser);
201     if ($basket->{closedate} && haspermission({ acquisition => 'group_manage'} )) {
202         $basketgroups = GetBasketgroups($basket->{booksellerid});
203         for my $bg ( @{$basketgroups} ) {
204             if ($basket->{basketgroupid} && $basket->{basketgroupid} == $bg->{id}){
205                 $bg->{default} = 1;
206             }
207         }
208         my %emptygroup = ( id   =>   undef,
209                            name =>   "No group");
210         if ( ! $basket->{basketgroupid} ) {
211             $emptygroup{default} = 1;
212             $emptygroup{nogroup} = 1;
213         }
214         unshift( @$basketgroups, \%emptygroup );
215     }
216     # if new basket, pre-fill infos
217     $basket->{creationdate} = ""            unless ( $basket->{creationdate} );
218     $basket->{authorisedby} = $loggedinuser unless ( $basket->{authorisedby} );
219     $debug
220       and warn sprintf
221       "loggedinuser: $loggedinuser; creationdate: %s; authorisedby: %s",
222       $basket->{creationdate}, $basket->{authorisedby};
223
224         #to get active currency
225         my $cur = GetCurrency();
226
227
228     my @results = GetOrders( $basketno );
229     
230         my $gist = $bookseller->{gstrate} // C4::Context->preference("gist") // 0;
231         $gist = 0 if $gist == 0.0000;
232         my $discount = $bookseller->{'discount'} / 100;
233     my $total_rrp = 0;      # RRP Total, its value will be assigned to $total_rrp_gsti or $total_rrp_gste depending of $bookseller->{'listincgst'}
234     my $total_rrp_gsti = 0; # RRP Total, GST included
235     my $total_rrp_gste = 0; # RRP Total, GST excluded
236     my $gist_rrp = 0;
237     my $total_rrp_est = 0;
238
239     my $qty_total;
240     my @books_loop;
241     my $suggestion;
242
243     for my $order ( @results ) {
244         my $rrp = $order->{'listprice'} || 0;
245                 my $qty = $order->{'quantity'} || 0;
246         if (!defined $order->{quantityreceived}) {
247             $order->{quantityreceived} = 0;
248         }
249         for ( qw(rrp ecost quantityreceived)) {
250             if (!defined $order->{$_}) {
251                 $order->{$_} = 0;
252             }
253         }
254
255         my $budget = GetBudget(  $order->{'budget_id'} );
256         $rrp = ConvertCurrency( $order->{'currency'}, $rrp );
257
258         $total_rrp += $qty * $order->{'rrp'};
259         my $line_total = $qty * $order->{'ecost'};
260         $total_rrp_est += $qty * $order->{'ecost'};
261                 # FIXME: what about the "actual cost" field?
262         $qty_total += $qty;
263         my %line = %{ $order };
264         my $biblionumber = $order->{'biblionumber'};
265         my $countbiblio = CountBiblioInOrders($biblionumber);
266         my $ordernumber = $order->{'ordernumber'};
267         my @subscriptions = GetSubscriptionsId ($biblionumber);
268         my $itemcount = GetItemsCount($biblionumber);
269         my $holds  = GetHolds ($biblionumber);
270         my @items = GetItemnumbersFromOrder( $ordernumber );
271         my $itemholds;
272         foreach my $item (@items){
273             my $nb = GetItemHolds($biblionumber, $item);
274             if ($nb){
275                 $itemholds += $nb;
276             }
277         }
278         # 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
279         $line{can_del_bib}          = 1 if $countbiblio <= 1 && $itemcount == scalar @items && !(@subscriptions) && !($holds);
280         $line{items}                = ($itemcount) - (scalar @items);
281         $line{left_item}            = 1 if $line{items} >= 1;
282         $line{left_biblio}          = 1 if $countbiblio > 1;
283         $line{biblios}              = $countbiblio - 1;
284         $line{left_subscription}    = 1 if scalar @subscriptions >= 1;
285         $line{subscriptions}        = scalar @subscriptions;
286         ($holds >= 1) ? $line{left_holds} = 1 : $line{left_holds} = 0;
287         $line{left_holds_on_order}  = 1 if $line{left_holds}==1 && ($line{items} == 0 || $itemholds );
288         $line{holds}                = $holds;
289         $line{holds_on_order}       = $itemholds?$itemholds:$holds if $line{left_holds_on_order};
290         $line{order_received}       = ( $qty == $order->{'quantityreceived'} );
291         $line{basketno}             = $basketno;
292         $line{budget_name}          = $budget->{budget_name};
293         $line{rrp}                  = sprintf( "%.2f", $line{'rrp'} );
294         $line{ecost}                = sprintf( "%.2f", $line{'ecost'} );
295         $line{line_total}           = sprintf( "%.2f", $line_total );
296         if ($line{uncertainprice}) {
297             $template->param( uncertainprices => 1 );
298             $line{rrp} .= ' (Uncertain)';
299         }
300         if ($line{'title'}){
301             my $volume = $order->{'volume'};
302             my $seriestitle = $order->{'seriestitle'};
303             $line{'title'} .= " / $seriestitle" if $seriestitle;
304             $line{'title'} .= " / $volume" if $volume;
305         } else {
306             $line{'title'} = "Deleted bibliographic notice, can't find title.";
307         }
308
309         $suggestion = GetSuggestionInfoFromBiblionumber($line{biblionumber});
310         $line{suggestionid}         = $suggestion->{suggestionid};
311         $line{surnamesuggestedby}   = $suggestion->{surnamesuggestedby};
312         $line{firstnamesuggestedby} = $suggestion->{firstnamesuggestedby};
313
314         push @books_loop, \%line;
315     }
316
317 my $total_est_gste;
318     my $total_est_gsti;
319     my $gist_est;
320     if ($gist){                                                    # if we have GST
321        if ( $bookseller->{'listincgst'} ) {                        # if prices already includes GST
322            $total_rrp_gsti = $total_rrp;                           # we know $total_rrp_gsti
323            $total_rrp_gste = $total_rrp_gsti / ( $gist + 1 );      # and can reverse compute other values
324            $gist_rrp       = $total_rrp_gsti - $total_rrp_gste;    #
325            $total_est_gste = $total_rrp_gste - ( $total_rrp_gste * $discount );
326            $total_est_gsti = $total_rrp_est;
327         } else {                                                    # if prices does not include GST
328            $total_rrp_gste = $total_rrp;                           # then we use the common way to compute other values
329            $gist_rrp       = $total_rrp_gste * $gist;              #
330            $total_rrp_gsti = $total_rrp_gste + $gist_rrp;          #
331            $total_est_gste = $total_rrp_est;
332            $total_est_gsti = $total_rrp_gsti - ( $total_rrp_gsti * $discount );
333        }
334        $gist_est = $gist_rrp - ( $gist_rrp * $discount );
335     } else {
336     $total_rrp_gsti = $total_rrp;
337     $total_est_gsti = $total_rrp_est;
338 }
339
340     my $contract = &GetContract($basket->{contractnumber});
341     my @orders = GetOrders($basketno);
342
343     my $borrower= GetMember('borrowernumber' => $loggedinuser);
344     my $budgets = GetBudgetHierarchy(q{},$borrower->{branchcode},$borrower->{borrowernumber});
345     my $has_budgets = 0;
346     foreach my $r (@{$budgets}) {
347         if (!defined $r->{budget_amount} || $r->{budget_amount} == 0) {
348             next;
349         }
350         $has_budgets = 1;
351         last;
352     }
353
354     my @cancelledorders = GetCancelledOrders($basketno);
355     foreach (@cancelledorders) {
356         $_->{'line_total'} = sprintf("%.2f", $_->{'ecost'} * $_->{'quantity'});
357     }
358
359     $template->param(
360         basketno             => $basketno,
361         basketname           => $basket->{'basketname'},
362         basketnote           => $basket->{note},
363         basketbooksellernote => $basket->{booksellernote},
364         basketcontractno     => $basket->{contractnumber},
365         basketcontractname   => $contract->{contractname},
366         creationdate         => $basket->{creationdate},
367         authorisedby         => $basket->{authorisedby},
368         authorisedbyname     => $basket->{authorisedbyname},
369         closedate            => $basket->{closedate},
370         active               => $bookseller->{'active'},
371         booksellerid         => $bookseller->{'id'},
372         name                 => $bookseller->{'name'},
373         books_loop           => \@books_loop,
374         cancelledorders_loop => \@cancelledorders,
375         gist_rate            => sprintf( "%.2f", $gist * 100 ) . '%',
376         total_rrp_gste       => sprintf( "%.2f", $total_rrp_gste ),
377         total_est_gste       => sprintf( "%.2f", $total_est_gste ),
378         gist_est             => sprintf( "%.2f", $gist_est ),
379         gist_rrp             => sprintf( "%.2f", $gist_rrp ),        
380         total_rrp_gsti       => sprintf( "%.2f", $total_rrp_gsti ),
381         total_est_gsti       => sprintf( "%.2f", $total_est_gsti ),
382 #        currency             => $bookseller->{'listprice'},
383         currency                => $cur->{'currency'},
384         qty_total            => $qty_total,
385         GST                  => $gist,
386         basketgroups         => $basketgroups,
387         grouped              => $basket->{basketgroupid},
388         unclosable           => @orders ? 0 : 1, 
389         has_budgets          => $has_budgets,
390     );
391 }
392
393 output_html_with_http_headers $query, $cookie, $template->output;