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