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