Merge branch 'bug_8758' into 3.12-master
[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 use Date::Calc qw/Add_Delta_Days/;
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 our $basketno     = $query->param('basketno');
69 my $booksellerid = $query->param('booksellerid');
70
71 my ( $template, $loggedinuser, $cookie, $userflags ) = 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         => $basket->{creationdate},
130         authorisedby         => $basket->{authorisedby},
131         authorisedbyname     => $basket->{authorisedbyname},
132         closedate            => $basket->{closedate},
133         deliveryplace        => $basket->{deliveryplace},
134         billingplace         => $basket->{billingplace},
135         active               => $bookseller->{'active'},
136         booksellerid         => $bookseller->{'id'},
137         name                 => $bookseller->{'name'},
138         address1             => $bookseller->{'address1'},
139         address2             => $bookseller->{'address2'},
140         address3             => $bookseller->{'address3'},
141         address4             => $bookseller->{'address4'},
142       );
143 } elsif ($op eq 'attachbasket' && $template->{'VARS'}->{'CAN_user_acquisition_group_manage'} == 1) {
144       print $query->redirect('/cgi-bin/koha/acqui/basketgroup.pl?basketno=' . $basket->{'basketno'} . '&op=attachbasket&booksellerid=' . $booksellerid);
145     # check if we have to "close" a basket before building page
146 } elsif ($op eq 'export') {
147     print $query->header(
148         -type       => 'text/csv',
149         -attachment => 'basket' . $basket->{'basketno'} . '.csv',
150     );
151     print GetBasketAsCSV($query->param('basketno'), $query);
152     exit;
153 } elsif ($op eq 'close') {
154     my $confirm = $query->param('confirm') || $confirm_pref eq '2';
155     if ($confirm) {
156         my $basketno = $query->param('basketno');
157         my $booksellerid = $query->param('booksellerid');
158         $basketno =~ /^\d+$/ and CloseBasket($basketno);
159         # if requested, create basket group, close it and attach the basket
160         if ($query->param('createbasketgroup')) {
161             my $branchcode;
162             if(C4::Context->userenv and C4::Context->userenv->{'branch'}
163               and C4::Context->userenv->{'branch'} ne "NO_LIBRARY_SET") {
164                 $branchcode = C4::Context->userenv->{'branch'};
165             }
166             my $basketgroupid = NewBasketgroup( { name => $basket->{basketname},
167                             booksellerid => $booksellerid,
168                             deliveryplace => $branchcode,
169                             billingplace => $branchcode,
170                             closed => 1,
171                             });
172             ModBasket( { basketno => $basketno,
173                          basketgroupid => $basketgroupid } );
174             print $query->redirect('/cgi-bin/koha/acqui/basketgroup.pl?booksellerid='.$booksellerid.'&closed=1');
175         } else {
176             print $query->redirect('/cgi-bin/koha/acqui/booksellers.pl?booksellerid=' . $booksellerid);
177         }
178         exit;
179     } else {
180     $template->param(confirm_close => "1",
181             booksellerid    => $booksellerid,
182             basketno        => $basket->{'basketno'},
183                 basketname      => $basket->{'basketname'},
184             basketgroupname => $basket->{'basketname'});
185         
186     }
187 } elsif ($op eq 'reopen') {
188     my $basket;
189     $basket->{basketno} = $query->param('basketno');
190     $basket->{closedate} = undef;
191     ModBasket($basket);
192     print $query->redirect('/cgi-bin/koha/acqui/basket.pl?basketno='.$basket->{'basketno'})
193 } else {
194     # get librarian branch...
195     if ( C4::Context->preference("IndependantBranches") ) {
196         my $userenv = C4::Context->userenv;
197         unless ( $userenv->{flags} == 1 ) {
198             my $validtest = ( $basket->{creationdate} eq '' )
199               || ( $userenv->{branch} eq $basket->{branch} )
200               || ( $userenv->{branch} eq '' )
201               || ( $basket->{branch}  eq '' );
202             unless ($validtest) {
203                 print $query->redirect("../mainpage.pl");
204                 exit 1;
205             }
206         }
207     }
208 #if the basket is closed,and the user has the permission to edit basketgroups, display a list of basketgroups
209     my $basketgroups;
210     my $member = GetMember(borrowernumber => $loggedinuser);
211     if ($basket->{closedate} && haspermission({ acquisition => 'group_manage'} )) {
212         $basketgroups = GetBasketgroups($basket->{booksellerid});
213         for my $bg ( @{$basketgroups} ) {
214             if ($basket->{basketgroupid} && $basket->{basketgroupid} == $bg->{id}){
215                 $bg->{default} = 1;
216             }
217         }
218         my %emptygroup = ( id   =>   undef,
219                            name =>   "No group");
220         if ( ! $basket->{basketgroupid} ) {
221             $emptygroup{default} = 1;
222             $emptygroup{nogroup} = 1;
223         }
224         unshift( @$basketgroups, \%emptygroup );
225     }
226
227     # if the basket is closed, calculate estimated delivery date
228     my $estimateddeliverydate;
229     if( $basket->{closedate} ) {
230         my ($year, $month, $day) = ($basket->{closedate} =~ /(\d+)-(\d+)-(\d+)/);
231         ($year, $month, $day) = Add_Delta_Days($year, $month, $day, $bookseller->{deliverytime});
232         $estimateddeliverydate = "$year-$month-$day";
233     }
234
235     # if new basket, pre-fill infos
236     $basket->{creationdate} = ""            unless ( $basket->{creationdate} );
237     $basket->{authorisedby} = $loggedinuser unless ( $basket->{authorisedby} );
238     $debug
239       and warn sprintf
240       "loggedinuser: $loggedinuser; creationdate: %s; authorisedby: %s",
241       $basket->{creationdate}, $basket->{authorisedby};
242
243     #to get active currency
244     my $cur = GetCurrency();
245
246
247     my @results = GetOrders( $basketno );
248     my @books_loop;
249
250     my @book_foot_loop;
251     my %foot;
252     my $total_quantity = 0;
253     my $total_gste = 0;
254     my $total_gsti = 0;
255     my $total_gstvalue = 0;
256     for my $order (@results) {
257         my $line = get_order_infos( $order, $bookseller);
258         if ( $line->{uncertainprice} ) {
259             $template->param( uncertainprices => 1 );
260         }
261
262         push @books_loop, $line;
263
264         $foot{$$line{gstgsti}}{gstgsti} = $$line{gstgsti};
265         $foot{$$line{gstgsti}}{gstvalue} += $$line{gstvalue};
266         $total_gstvalue += $$line{gstvalue};
267         $foot{$$line{gstgsti}}{quantity}  += $$line{quantity};
268         $total_quantity += $$line{quantity};
269         $foot{$$line{gstgsti}}{totalgste} += $$line{totalgste};
270         $total_gste += $$line{totalgste};
271         $foot{$$line{gstgsti}}{totalgsti} += $$line{totalgsti};
272         $total_gsti += $$line{totalgsti};
273     }
274
275     push @book_foot_loop, map {$_} values %foot;
276
277     # Get cancelled orders
278     @results = GetCancelledOrders($basketno);
279     my @cancelledorders_loop;
280     for my $order (@results) {
281         my $line = get_order_infos( $order, $bookseller);
282         push @cancelledorders_loop, $line;
283     }
284
285     my $contract = &GetContract($basket->{contractnumber});
286     my @orders = GetOrders($basketno);
287
288     if ($basket->{basketgroupid}){
289         my $basketgroup = GetBasketgroup($basket->{basketgroupid});
290         for my $key (keys %$basketgroup ){
291             $basketgroup->{"basketgroup$key"} = delete $basketgroup->{$key};
292         }
293         $basketgroup->{basketgroupdeliveryplace} = C4::Branch::GetBranchName( $basketgroup->{basketgroupdeliveryplace} );
294         $basketgroup->{basketgroupbillingplace} = C4::Branch::GetBranchName( $basketgroup->{basketgroupbillingplace} );
295         $template->param(%$basketgroup);
296     }
297     my $borrower= GetMember('borrowernumber' => $loggedinuser);
298     my $budgets = GetBudgetHierarchy;
299     my $has_budgets = 0;
300     foreach my $r (@{$budgets}) {
301         if (!defined $r->{budget_amount} || $r->{budget_amount} == 0) {
302             next;
303         }
304         next unless (CanUserUseBudget($loggedinuser, $r, $userflags));
305
306         $has_budgets = 1;
307         last;
308     }
309
310     my @cancelledorders = GetCancelledOrders($basketno);
311     foreach (@cancelledorders) {
312         $_->{'line_total'} = sprintf("%.2f", $_->{'ecost'} * $_->{'quantity'});
313     }
314
315     $template->param(
316         basketno             => $basketno,
317         basketname           => $basket->{'basketname'},
318         basketnote           => $basket->{note},
319         basketbooksellernote => $basket->{booksellernote},
320         basketcontractno     => $basket->{contractnumber},
321         basketcontractname   => $contract->{contractname},
322         creationdate         => $basket->{creationdate},
323         authorisedby         => $basket->{authorisedby},
324         authorisedbyname     => $basket->{authorisedbyname},
325         closedate            => $basket->{closedate},
326         estimateddeliverydate=> $estimateddeliverydate,
327         deliveryplace        => C4::Branch::GetBranchName( $basket->{deliveryplace} ),
328         billingplace         => C4::Branch::GetBranchName( $basket->{billingplace} ),
329         active               => $bookseller->{'active'},
330         booksellerid         => $bookseller->{'id'},
331         name                 => $bookseller->{'name'},
332         books_loop           => \@books_loop,
333         book_foot_loop       => \@book_foot_loop,
334         cancelledorders_loop => \@cancelledorders,
335         total_quantity       => $total_quantity,
336         total_gste           => sprintf( "%.2f", $total_gste ),
337         total_gsti           => sprintf( "%.2f", $total_gsti ),
338         total_gstvalue       => sprintf( "%.2f", $total_gstvalue ),
339         currency             => $cur->{'currency'},
340         listincgst           => $bookseller->{listincgst},
341         basketgroups         => $basketgroups,
342         grouped              => $basket->{basketgroupid},
343         unclosable           => @orders ? 0 : 1, 
344         has_budgets          => $has_budgets,
345     );
346 }
347
348 sub get_order_infos {
349     my $order = shift;
350     my $bookseller = shift;
351     my $qty = $order->{'quantity'} || 0;
352     if ( !defined $order->{quantityreceived} ) {
353         $order->{quantityreceived} = 0;
354     }
355     my $budget = GetBudget( $order->{'budget_id'} );
356
357     my %line = %{ $order };
358     $line{order_received} = ( $qty == $order->{'quantityreceived'} );
359     $line{basketno}       = $basketno;
360     $line{budget_name}    = $budget->{budget_name};
361     $line{rrp} = ConvertCurrency( $order->{'currency'}, $line{rrp} ); # FIXME from comm
362     if ( $bookseller->{'listincgst'} ) {
363         $line{rrpgsti} = sprintf( "%.2f", $line{rrp} );
364         $line{gstgsti} = sprintf( "%.2f", $line{gstrate} * 100 );
365         $line{rrpgste} = sprintf( "%.2f", $line{rrp} / ( 1 + ( $line{gstgsti} / 100 ) ) );
366         $line{gstgste} = sprintf( "%.2f", $line{gstgsti} / ( 1 + ( $line{gstgsti} / 100 ) ) );
367         $line{ecostgsti} = sprintf( "%.2f", $line{ecost} );
368         $line{ecostgste} = sprintf( "%.2f", $line{ecost} / ( 1 + ( $line{gstgsti} / 100 ) ) );
369         $line{gstvalue} = sprintf( "%.2f", ( $line{ecostgsti} - $line{ecostgste} ) * $line{quantity});
370         $line{totalgste} = sprintf( "%.2f", $order->{quantity} * $line{ecostgste} );
371         $line{totalgsti} = sprintf( "%.2f", $order->{quantity} * $line{ecostgsti} );
372     } else {
373         $line{rrpgsti} = sprintf( "%.2f", $line{rrp} * ( 1 + ( $line{gstrate} ) ) );
374         $line{rrpgste} = sprintf( "%.2f", $line{rrp} );
375         $line{gstgsti} = sprintf( "%.2f", $line{gstrate} * 100 );
376         $line{gstgste} = sprintf( "%.2f", $line{gstrate} * 100 );
377         $line{ecostgsti} = sprintf( "%.2f", $line{ecost} * ( 1 + ( $line{gstrate} ) ) );
378         $line{ecostgste} = sprintf( "%.2f", $line{ecost} );
379         $line{gstvalue} = sprintf( "%.2f", ( $line{ecostgsti} - $line{ecostgste} ) * $line{quantity});
380         $line{totalgste} = sprintf( "%.2f", $order->{quantity} * $line{ecostgste} );
381         $line{totalgsti} = sprintf( "%.2f", $order->{quantity} * $line{ecostgsti} );
382     }
383
384     if ( $line{uncertainprice} ) {
385         $line{rrpgste} .= ' (Uncertain)';
386     }
387     if ( $line{'title'} ) {
388         my $volume      = $order->{'volume'};
389         my $seriestitle = $order->{'seriestitle'};
390         $line{'title'} .= " / $seriestitle" if $seriestitle;
391         $line{'title'} .= " / $volume"      if $volume;
392     } else {
393         $line{'title'} = "Deleted bibliographic notice, can't find title.";
394     }
395
396     my $biblionumber = $order->{'biblionumber'};
397     my $countbiblio = CountBiblioInOrders($biblionumber);
398     my $ordernumber = $order->{'ordernumber'};
399     my @subscriptions = GetSubscriptionsId ($biblionumber);
400     my $itemcount = GetItemsCount($biblionumber);
401     my $holds  = GetHolds ($biblionumber);
402     my @items = GetItemnumbersFromOrder( $ordernumber );
403     my $itemholds;
404     foreach my $item (@items){
405         my $nb = GetItemHolds($biblionumber, $item);
406         if ($nb){
407             $itemholds += $nb;
408         }
409     }
410     # 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
411     $line{can_del_bib}          = 1 if $countbiblio <= 1 && $itemcount == scalar @items && !(@subscriptions) && !($holds);
412     $line{items}                = ($itemcount) - (scalar @items);
413     $line{left_item}            = 1 if $line{items} >= 1;
414     $line{left_biblio}          = 1 if $countbiblio > 1;
415     $line{biblios}              = $countbiblio - 1;
416     $line{left_subscription}    = 1 if scalar @subscriptions >= 1;
417     $line{subscriptions}        = scalar @subscriptions;
418     ($holds >= 1) ? $line{left_holds} = 1 : $line{left_holds} = 0;
419     $line{left_holds_on_order}  = 1 if $line{left_holds}==1 && ($line{items} == 0 || $itemholds );
420     $line{holds}                = $holds;
421     $line{holds_on_order}       = $itemholds?$itemholds:$holds if $line{left_holds_on_order};
422
423
424     my $suggestion   = GetSuggestionInfoFromBiblionumber($line{biblionumber});
425     $line{suggestionid}         = $$suggestion{suggestionid};
426     $line{surnamesuggestedby}   = $$suggestion{surnamesuggestedby};
427     $line{firstnamesuggestedby} = $$suggestion{firstnamesuggestedby};
428
429     return \%line;
430 }
431
432 output_html_with_http_headers $query, $cookie, $template->output;