Bug 5549 : Add Extra Perl Dependencies
[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::Dates qw/format_date/;
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
39 =head1 NAME
40
41 basket.pl
42
43 =head1 DESCRIPTION
44
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.
48
49 =head1 CGI PARAMETERS
50
51 =over 4
52
53 =item $basketno
54
55 The basket number.
56
57 =item booksellerid
58
59 the supplier this script have to display the basket.
60
61 =item order
62
63 =back
64
65 =cut
66
67 my $query        = new CGI;
68 my $basketno     = $query->param('basketno');
69 my $booksellerid = $query->param('booksellerid');
70
71 my ( $template, $loggedinuser, $cookie ) = get_template_and_user(
72     {
73         template_name   => "acqui/basket.tmpl",
74         query           => $query,
75         type            => "intranet",
76         authnotrequired => 0,
77         flagsrequired   => { acquisition => 'order_manage' },
78         debug           => 1,
79     }
80 );
81
82 my $basket = GetBasket($basketno);
83
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{};
93 }
94
95 my $confirm_pref= C4::Context->preference("BasketConfirmations") || '1';
96 $template->param( skip_confirm_reopen => 1) if $confirm_pref eq '2';
97
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;
116             }
117         }
118     }
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         => format_date( $basket->{creationdate} ),
130         authorisedby         => $basket->{authorisedby},
131         authorisedbyname     => $basket->{authorisedbyname},
132         closedate            => format_date( $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'},
140       );
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',
148     );
149     print GetBasketAsCSV($query->param('basketno'));
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 $basketgroupid = NewBasketgroup( { name => $basket->{basketname},
160                             booksellerid => $booksellerid,
161                             closed => 1,
162                             });
163             ModBasket( { basketno => $basketno,
164                          basketgroupid => $basketgroupid } );
165             print $query->redirect('/cgi-bin/koha/acqui/basketgroup.pl?booksellerid='.$booksellerid.'&closed=1');
166         } else {
167             print $query->redirect('/cgi-bin/koha/acqui/booksellers.pl?booksellerid=' . $booksellerid);
168         }
169         exit;
170     } else {
171     $template->param(confirm_close => "1",
172             booksellerid    => $booksellerid,
173             basketno        => $basket->{'basketno'},
174                 basketname      => $basket->{'basketname'},
175             basketgroupname => $basket->{'basketname'});
176         
177     }
178 } elsif ($op eq 'reopen') {
179     my $basket;
180     $basket->{basketno} = $query->param('basketno');
181     $basket->{closedate} = undef;
182     ModBasket($basket);
183     print $query->redirect('/cgi-bin/koha/acqui/basket.pl?basketno='.$basket->{'basketno'})
184 } else {
185     # get librarian branch...
186     if ( C4::Context->preference("IndependantBranches") ) {
187         my $userenv = C4::Context->userenv;
188         unless ( $userenv->{flags} == 1 ) {
189             my $validtest = ( $basket->{creationdate} eq '' )
190               || ( $userenv->{branch} eq $basket->{branch} )
191               || ( $userenv->{branch} eq '' )
192               || ( $basket->{branch}  eq '' );
193             unless ($validtest) {
194                 print $query->redirect("../mainpage.pl");
195                 exit 1;
196             }
197         }
198     }
199 #if the basket is closed,and the user has the permission to edit basketgroups, display a list of basketgroups
200     my $basketgroups;
201     my $member = GetMember(borrowernumber => $loggedinuser);
202     if ($basket->{closedate} && haspermission({ acquisition => 'group_manage'} )) {
203         $basketgroups = GetBasketgroups($basket->{booksellerid});
204         for my $bg ( @{$basketgroups} ) {
205             if ($basket->{basketgroupid} && $basket->{basketgroupid} == $bg->{id}){
206                 $bg->{default} = 1;
207             }
208         }
209         my %emptygroup = ( id   =>   undef,
210                            name =>   "No group");
211         if ( ! $basket->{basketgroupid} ) {
212             $emptygroup{default} = 1;
213             $emptygroup{nogroup} = 1;
214         }
215         unshift( @$basketgroups, \%emptygroup );
216     }
217     # if new basket, pre-fill infos
218     $basket->{creationdate} = ""            unless ( $basket->{creationdate} );
219     $basket->{authorisedby} = $loggedinuser unless ( $basket->{authorisedby} );
220     $debug
221       and warn sprintf
222       "loggedinuser: $loggedinuser; creationdate: %s; authorisedby: %s",
223       $basket->{creationdate}, $basket->{authorisedby};
224
225         #to get active currency
226         my $cur = GetCurrency();
227
228
229     my @results = GetOrders( $basketno );
230     
231         my $gist = $bookseller->{gstrate} // C4::Context->preference("gist") // 0;
232         $gist = 0 if $gist == 0.0000;
233         my $discount = $bookseller->{'discount'} / 100;
234     my $total_rrp = 0;      # RRP Total, its value will be assigned to $total_rrp_gsti or $total_rrp_gste depending of $bookseller->{'listincgst'}
235     my $total_rrp_gsti = 0; # RRP Total, GST included
236     my $total_rrp_gste = 0; # RRP Total, GST excluded
237     my $gist_rrp = 0;
238     my $total_rrp_est = 0;
239
240     my $qty_total;
241     my @books_loop;
242     my $suggestion;
243
244     for my $order ( @results ) {
245         my $rrp = $order->{'listprice'} || 0;
246                 my $qty = $order->{'quantity'} || 0;
247         if (!defined $order->{quantityreceived}) {
248             $order->{quantityreceived} = 0;
249         }
250         for ( qw(rrp ecost quantityreceived)) {
251             if (!defined $order->{$_}) {
252                 $order->{$_} = 0;
253             }
254         }
255
256         my $budget = GetBudget(  $order->{'budget_id'} );
257         $rrp = ConvertCurrency( $order->{'currency'}, $rrp );
258
259         $total_rrp += $qty * $order->{'rrp'};
260         my $line_total = $qty * $order->{'ecost'};
261         $total_rrp_est += $qty * $order->{'ecost'};
262                 # FIXME: what about the "actual cost" field?
263         $qty_total += $qty;
264         my %line = %{ $order };
265         my $biblionumber = $order->{'biblionumber'};
266         my $countbiblio = CountBiblioInOrders($biblionumber);
267         my $ordernumber = $order->{'ordernumber'};
268         my @subscriptions = GetSubscriptionsId ($biblionumber);
269         my $itemcount = GetItemsCount($biblionumber);
270         my $holds  = GetHolds ($biblionumber);
271         my @items = GetItemnumbersFromOrder( $ordernumber );
272         my $itemholds;
273         foreach my $item (@items){
274             my $nb = GetItemHolds($biblionumber, $item);
275             if ($nb){
276                 $itemholds += $nb;
277             }
278         }
279         # 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
280         $line{can_del_bib}          = 1 if $countbiblio <= 1 && $itemcount == scalar @items && !(@subscriptions) && !($holds);
281         $line{items}                = ($itemcount) - (scalar @items);
282         $line{left_item}            = 1 if $line{items} >= 1;
283         $line{left_biblio}          = 1 if $countbiblio > 1;
284         $line{biblios}              = $countbiblio - 1;
285         $line{left_subscription}    = 1 if scalar @subscriptions >= 1;
286         $line{subscriptions}        = scalar @subscriptions;
287         ($holds >= 1) ? $line{left_holds} = 1 : $line{left_holds} = 0;
288         $line{left_holds_on_order}  = 1 if $line{left_holds}==1 && ($line{items} == 0 || $itemholds );
289         $line{holds}                = $holds;
290         $line{holds_on_order}       = $itemholds?$itemholds:$holds if $line{left_holds_on_order};
291         $line{order_received}       = ( $qty == $order->{'quantityreceived'} );
292         $line{basketno}             = $basketno;
293         $line{budget_name}          = $budget->{budget_name};
294         $line{rrp}                  = sprintf( "%.2f", $line{'rrp'} );
295         $line{ecost}                = sprintf( "%.2f", $line{'ecost'} );
296         $line{line_total}           = sprintf( "%.2f", $line_total );
297         if ($line{uncertainprice}) {
298             $template->param( uncertainprices => 1 );
299             $line{rrp} .= ' (Uncertain)';
300         }
301         if ($line{'title'}){
302             my $volume = $order->{'volume'};
303             my $seriestitle = $order->{'seriestitle'};
304             $line{'title'} .= " / $seriestitle" if $seriestitle;
305             $line{'title'} .= " / $volume" if $volume;
306         } else {
307             $line{'title'} = "Deleted bibliographic notice, can't find title.";
308         }
309
310         $suggestion = GetSuggestionInfoFromBiblionumber($line{biblionumber});
311         $line{suggestionid}         = $suggestion->{suggestionid};
312         $line{surnamesuggestedby}   = $suggestion->{surnamesuggestedby};
313         $line{firstnamesuggestedby} = $suggestion->{firstnamesuggestedby};
314
315         push @books_loop, \%line;
316     }
317
318 my $total_est_gste;
319     my $total_est_gsti;
320     my $gist_est;
321     if ($gist){                                                    # if we have GST
322        if ( $bookseller->{'listincgst'} ) {                        # if prices already includes GST
323            $total_rrp_gsti = $total_rrp;                           # we know $total_rrp_gsti
324            $total_rrp_gste = $total_rrp_gsti / ( $gist + 1 );      # and can reverse compute other values
325            $gist_rrp       = $total_rrp_gsti - $total_rrp_gste;    #
326            $total_est_gste = $total_rrp_gste - ( $total_rrp_gste * $discount );
327            $total_est_gsti = $total_rrp_est;
328         } else {                                                    # if prices does not include GST
329            $total_rrp_gste = $total_rrp;                           # then we use the common way to compute other values
330            $gist_rrp       = $total_rrp_gste * $gist;              #
331            $total_rrp_gsti = $total_rrp_gste + $gist_rrp;          #
332            $total_est_gste = $total_rrp_est;
333            $total_est_gsti = $total_rrp_gsti - ( $total_rrp_gsti * $discount );
334        }
335        $gist_est = $gist_rrp - ( $gist_rrp * $discount );
336     } else {
337     $total_rrp_gsti = $total_rrp;
338     $total_est_gsti = $total_rrp_est;
339 }
340
341     my $contract = &GetContract($basket->{contractnumber});
342     my @orders = GetOrders($basketno);
343
344     my $borrower= GetMember('borrowernumber' => $loggedinuser);
345     my $budgets = GetBudgetHierarchy(q{},$borrower->{branchcode},$borrower->{borrowernumber});
346     my $has_budgets = 0;
347     foreach my $r (@{$budgets}) {
348         if (!defined $r->{budget_amount} || $r->{budget_amount} == 0) {
349             next;
350         }
351         $has_budgets = 1;
352         last;
353     }
354
355     my @cancelledorders = GetCancelledOrders($basketno);
356     foreach (@cancelledorders) {
357         $_->{'line_total'} = sprintf("%.2f", $_->{'ecost'} * $_->{'quantity'});
358     }
359
360     $template->param(
361         basketno             => $basketno,
362         basketname           => $basket->{'basketname'},
363         basketnote           => $basket->{note},
364         basketbooksellernote => $basket->{booksellernote},
365         basketcontractno     => $basket->{contractnumber},
366         basketcontractname   => $contract->{contractname},
367         creationdate         => C4::Dates->new($basket->{creationdate},'iso')->output,
368         authorisedby         => $basket->{authorisedby},
369         authorisedbyname     => $basket->{authorisedbyname},
370         closedate            => C4::Dates->new($basket->{closedate},'iso')->output,
371         active               => $bookseller->{'active'},
372         booksellerid         => $bookseller->{'id'},
373         name                 => $bookseller->{'name'},
374         entrydate            => C4::Dates->new($results[0]->{'entrydate'},'iso')->output,
375         books_loop           => \@books_loop,
376         cancelledorders_loop => \@cancelledorders,
377         gist_rate            => sprintf( "%.2f", $gist * 100 ) . '%',
378         total_rrp_gste       => sprintf( "%.2f", $total_rrp_gste ),
379         total_est_gste       => sprintf( "%.2f", $total_est_gste ),
380         gist_est             => sprintf( "%.2f", $gist_est ),
381         gist_rrp             => sprintf( "%.2f", $gist_rrp ),        
382         total_rrp_gsti       => sprintf( "%.2f", $total_rrp_gsti ),
383         total_est_gsti       => sprintf( "%.2f", $total_est_gsti ),
384 #        currency             => $bookseller->{'listprice'},
385         currency                => $cur->{'currency'},
386         qty_total            => $qty_total,
387         GST                  => $gist,
388         basketgroups         => $basketgroups,
389         grouped              => $basket->{basketgroupid},
390         unclosable           => @orders ? 0 : 1, 
391         has_budgets          => $has_budgets,
392     );
393 }
394
395 output_html_with_http_headers $query, $cookie, $template->output;