Merge branch 'bug_8117' 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 ($basketgroup, $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                 $basketgroup = $bg;
217             }
218         }
219         my %emptygroup = ( id   =>   undef,
220                            name =>   "No group");
221         if ( ! $basket->{basketgroupid} ) {
222             $emptygroup{default} = 1;
223             $emptygroup{nogroup} = 1;
224         }
225         unshift( @$basketgroups, \%emptygroup );
226     }
227
228     # if the basket is closed, calculate estimated delivery date
229     my $estimateddeliverydate;
230     if( $basket->{closedate} ) {
231         my ($year, $month, $day) = ($basket->{closedate} =~ /(\d+)-(\d+)-(\d+)/);
232         ($year, $month, $day) = Add_Delta_Days($year, $month, $day, $bookseller->{deliverytime});
233         $estimateddeliverydate = "$year-$month-$day";
234     }
235
236     # if new basket, pre-fill infos
237     $basket->{creationdate} = ""            unless ( $basket->{creationdate} );
238     $basket->{authorisedby} = $loggedinuser unless ( $basket->{authorisedby} );
239     $debug
240       and warn sprintf
241       "loggedinuser: $loggedinuser; creationdate: %s; authorisedby: %s",
242       $basket->{creationdate}, $basket->{authorisedby};
243
244     #to get active currency
245     my $cur = GetCurrency();
246
247
248     my @results = GetOrders( $basketno );
249     my @books_loop;
250
251     my @book_foot_loop;
252     my %foot;
253     my $total_quantity = 0;
254     my $total_gste = 0;
255     my $total_gsti = 0;
256     my $total_gstvalue = 0;
257     for my $order (@results) {
258         my $line = get_order_infos( $order, $bookseller);
259         if ( $line->{uncertainprice} ) {
260             $template->param( uncertainprices => 1 );
261         }
262
263         push @books_loop, $line;
264
265         $foot{$$line{gstgsti}}{gstgsti} = $$line{gstgsti};
266         $foot{$$line{gstgsti}}{gstvalue} += $$line{gstvalue};
267         $total_gstvalue += $$line{gstvalue};
268         $foot{$$line{gstgsti}}{quantity}  += $$line{quantity};
269         $total_quantity += $$line{quantity};
270         $foot{$$line{gstgsti}}{totalgste} += $$line{totalgste};
271         $total_gste += $$line{totalgste};
272         $foot{$$line{gstgsti}}{totalgsti} += $$line{totalgsti};
273         $total_gsti += $$line{totalgsti};
274     }
275
276     push @book_foot_loop, map {$_} values %foot;
277
278     # Get cancelled orders
279     @results = GetCancelledOrders($basketno);
280     my @cancelledorders_loop;
281     for my $order (@results) {
282         my $line = get_order_infos( $order, $bookseller);
283         push @cancelledorders_loop, $line;
284     }
285
286     my $contract = &GetContract($basket->{contractnumber});
287     my @orders = GetOrders($basketno);
288
289     if ($basket->{basketgroupid}){
290         my $basketgroup = GetBasketgroup($basket->{basketgroupid});
291         for my $key (keys %$basketgroup ){
292             $basketgroup->{"basketgroup$key"} = delete $basketgroup->{$key};
293         }
294         $basketgroup->{basketgroupdeliveryplace} = C4::Branch::GetBranchName( $basketgroup->{basketgroupdeliveryplace} );
295         $basketgroup->{basketgroupbillingplace} = C4::Branch::GetBranchName( $basketgroup->{basketgroupbillingplace} );
296         $template->param(%$basketgroup);
297     }
298     my $borrower= GetMember('borrowernumber' => $loggedinuser);
299     my $budgets = GetBudgetHierarchy;
300     my $has_budgets = 0;
301     foreach my $r (@{$budgets}) {
302         if (!defined $r->{budget_amount} || $r->{budget_amount} == 0) {
303             next;
304         }
305         next unless (CanUserUseBudget($loggedinuser, $r, $userflags));
306
307         $has_budgets = 1;
308         last;
309     }
310
311     my @cancelledorders = GetCancelledOrders($basketno);
312     foreach (@cancelledorders) {
313         $_->{'line_total'} = sprintf("%.2f", $_->{'ecost'} * $_->{'quantity'});
314     }
315
316     $template->param(
317         basketno             => $basketno,
318         basketname           => $basket->{'basketname'},
319         basketnote           => $basket->{note},
320         basketbooksellernote => $basket->{booksellernote},
321         basketcontractno     => $basket->{contractnumber},
322         basketcontractname   => $contract->{contractname},
323         creationdate         => $basket->{creationdate},
324         authorisedby         => $basket->{authorisedby},
325         authorisedbyname     => $basket->{authorisedbyname},
326         closedate            => $basket->{closedate},
327         estimateddeliverydate=> $estimateddeliverydate,
328         deliveryplace        => C4::Branch::GetBranchName( $basket->{deliveryplace} ),
329         billingplace         => C4::Branch::GetBranchName( $basket->{billingplace} ),
330         active               => $bookseller->{'active'},
331         booksellerid         => $bookseller->{'id'},
332         name                 => $bookseller->{'name'},
333         books_loop           => \@books_loop,
334         book_foot_loop       => \@book_foot_loop,
335         cancelledorders_loop => \@cancelledorders,
336         total_quantity       => $total_quantity,
337         total_gste           => sprintf( "%.2f", $total_gste ),
338         total_gsti           => sprintf( "%.2f", $total_gsti ),
339         total_gstvalue       => sprintf( "%.2f", $total_gstvalue ),
340         currency             => $cur->{'currency'},
341         listincgst           => $bookseller->{listincgst},
342         basketgroups         => $basketgroups,
343         basketgroup          => $basketgroup,
344         grouped              => $basket->{basketgroupid},
345         unclosable           => @orders ? 0 : 1, 
346         has_budgets          => $has_budgets,
347     );
348 }
349
350 sub get_order_infos {
351     my $order = shift;
352     my $bookseller = shift;
353     my $qty = $order->{'quantity'} || 0;
354     if ( !defined $order->{quantityreceived} ) {
355         $order->{quantityreceived} = 0;
356     }
357     my $budget = GetBudget( $order->{'budget_id'} );
358
359     my %line = %{ $order };
360     $line{order_received} = ( $qty == $order->{'quantityreceived'} );
361     $line{basketno}       = $basketno;
362     $line{budget_name}    = $budget->{budget_name};
363     $line{rrp} = ConvertCurrency( $order->{'currency'}, $line{rrp} ); # FIXME from comm
364     if ( $bookseller->{'listincgst'} ) {
365         $line{rrpgsti} = sprintf( "%.2f", $line{rrp} );
366         $line{gstgsti} = sprintf( "%.2f", $line{gstrate} * 100 );
367         $line{rrpgste} = sprintf( "%.2f", $line{rrp} / ( 1 + ( $line{gstgsti} / 100 ) ) );
368         $line{gstgste} = sprintf( "%.2f", $line{gstgsti} / ( 1 + ( $line{gstgsti} / 100 ) ) );
369         $line{ecostgsti} = sprintf( "%.2f", $line{ecost} );
370         $line{ecostgste} = sprintf( "%.2f", $line{ecost} / ( 1 + ( $line{gstgsti} / 100 ) ) );
371         $line{gstvalue} = sprintf( "%.2f", ( $line{ecostgsti} - $line{ecostgste} ) * $line{quantity});
372         $line{totalgste} = sprintf( "%.2f", $order->{quantity} * $line{ecostgste} );
373         $line{totalgsti} = sprintf( "%.2f", $order->{quantity} * $line{ecostgsti} );
374     } else {
375         $line{rrpgsti} = sprintf( "%.2f", $line{rrp} * ( 1 + ( $line{gstrate} ) ) );
376         $line{rrpgste} = sprintf( "%.2f", $line{rrp} );
377         $line{gstgsti} = sprintf( "%.2f", $line{gstrate} * 100 );
378         $line{gstgste} = sprintf( "%.2f", $line{gstrate} * 100 );
379         $line{ecostgsti} = sprintf( "%.2f", $line{ecost} * ( 1 + ( $line{gstrate} ) ) );
380         $line{ecostgste} = sprintf( "%.2f", $line{ecost} );
381         $line{gstvalue} = sprintf( "%.2f", ( $line{ecostgsti} - $line{ecostgste} ) * $line{quantity});
382         $line{totalgste} = sprintf( "%.2f", $order->{quantity} * $line{ecostgste} );
383         $line{totalgsti} = sprintf( "%.2f", $order->{quantity} * $line{ecostgsti} );
384     }
385
386     if ( $line{uncertainprice} ) {
387         $line{rrpgste} .= ' (Uncertain)';
388     }
389     if ( $line{'title'} ) {
390         my $volume      = $order->{'volume'};
391         my $seriestitle = $order->{'seriestitle'};
392         $line{'title'} .= " / $seriestitle" if $seriestitle;
393         $line{'title'} .= " / $volume"      if $volume;
394     } else {
395         $line{'title'} = "Deleted bibliographic notice, can't find title.";
396     }
397
398     my $biblionumber = $order->{'biblionumber'};
399     my $countbiblio = CountBiblioInOrders($biblionumber);
400     my $ordernumber = $order->{'ordernumber'};
401     my @subscriptions = GetSubscriptionsId ($biblionumber);
402     my $itemcount = GetItemsCount($biblionumber);
403     my $holds  = GetHolds ($biblionumber);
404     my @items = GetItemnumbersFromOrder( $ordernumber );
405     my $itemholds;
406     foreach my $item (@items){
407         my $nb = GetItemHolds($biblionumber, $item);
408         if ($nb){
409             $itemholds += $nb;
410         }
411     }
412     # 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
413     $line{can_del_bib}          = 1 if $countbiblio <= 1 && $itemcount == scalar @items && !(@subscriptions) && !($holds);
414     $line{items}                = ($itemcount) - (scalar @items);
415     $line{left_item}            = 1 if $line{items} >= 1;
416     $line{left_biblio}          = 1 if $countbiblio > 1;
417     $line{biblios}              = $countbiblio - 1;
418     $line{left_subscription}    = 1 if scalar @subscriptions >= 1;
419     $line{subscriptions}        = scalar @subscriptions;
420     ($holds >= 1) ? $line{left_holds} = 1 : $line{left_holds} = 0;
421     $line{left_holds_on_order}  = 1 if $line{left_holds}==1 && ($line{items} == 0 || $itemholds );
422     $line{holds}                = $holds;
423     $line{holds_on_order}       = $itemholds?$itemholds:$holds if $line{left_holds_on_order};
424
425
426     my $suggestion   = GetSuggestionInfoFromBiblionumber($line{biblionumber});
427     $line{suggestionid}         = $$suggestion{suggestionid};
428     $line{surnamesuggestedby}   = $$suggestion{surnamesuggestedby};
429     $line{firstnamesuggestedby} = $$suggestion{firstnamesuggestedby};
430
431     return \%line;
432 }
433
434 output_html_with_http_headers $query, $cookie, $template->output;