06d4d1a18a48495371f9ba2dd38755b43b4ad355
[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(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("IndependentBranches") ) {
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 $staffuser = GetMember(borrowernumber => $loggedinuser);
211     if ($basket->{closedate} && haspermission($staffuser->{userid}, { 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         $basketgroup = GetBasketgroup($basket->{basketgroupid});
291         $basketgroup->{deliveryplacename} = C4::Branch::GetBranchName( $basketgroup->{deliveryplace} );
292         $basketgroup->{billingplacename} = C4::Branch::GetBranchName( $basketgroup->{billingplace} );
293     }
294     my $borrower= GetMember('borrowernumber' => $loggedinuser);
295     my $budgets = GetBudgetHierarchy;
296     my $has_budgets = 0;
297     foreach my $r (@{$budgets}) {
298         if (!defined $r->{budget_amount} || $r->{budget_amount} == 0) {
299             next;
300         }
301         next unless (CanUserUseBudget($loggedinuser, $r, $userflags));
302
303         $has_budgets = 1;
304         last;
305     }
306
307     my @cancelledorders = GetCancelledOrders($basketno);
308     foreach (@cancelledorders) {
309         $_->{'line_total'} = sprintf("%.2f", $_->{'ecost'} * $_->{'quantity'});
310     }
311
312     $template->param(
313         basketno             => $basketno,
314         basketname           => $basket->{'basketname'},
315         basketnote           => $basket->{note},
316         basketbooksellernote => $basket->{booksellernote},
317         basketcontractno     => $basket->{contractnumber},
318         basketcontractname   => $contract->{contractname},
319         creationdate         => $basket->{creationdate},
320         authorisedby         => $basket->{authorisedby},
321         authorisedbyname     => $basket->{authorisedbyname},
322         closedate            => $basket->{closedate},
323         estimateddeliverydate=> $estimateddeliverydate,
324         deliveryplace        => C4::Branch::GetBranchName( $basket->{deliveryplace} ),
325         billingplace         => C4::Branch::GetBranchName( $basket->{billingplace} ),
326         active               => $bookseller->{'active'},
327         booksellerid         => $bookseller->{'id'},
328         name                 => $bookseller->{'name'},
329         books_loop           => \@books_loop,
330         book_foot_loop       => \@book_foot_loop,
331         cancelledorders_loop => \@cancelledorders,
332         total_quantity       => $total_quantity,
333         total_gste           => sprintf( "%.2f", $total_gste ),
334         total_gsti           => sprintf( "%.2f", $total_gsti ),
335         total_gstvalue       => sprintf( "%.2f", $total_gstvalue ),
336         currency             => $cur->{'currency'},
337         listincgst           => $bookseller->{listincgst},
338         basketgroups         => $basketgroups,
339         basketgroup          => $basketgroup,
340         grouped              => $basket->{basketgroupid},
341         unclosable           => @orders ? 0 : 1, 
342         has_budgets          => $has_budgets,
343     );
344 }
345
346 sub get_order_infos {
347     my $order = shift;
348     my $bookseller = shift;
349     my $qty = $order->{'quantity'} || 0;
350     if ( !defined $order->{quantityreceived} ) {
351         $order->{quantityreceived} = 0;
352     }
353     my $budget = GetBudget( $order->{'budget_id'} );
354
355     my %line = %{ $order };
356     $line{order_received} = ( $qty == $order->{'quantityreceived'} );
357     $line{basketno}       = $basketno;
358     $line{budget_name}    = $budget->{budget_name};
359     $line{rrp} = ConvertCurrency( $order->{'currency'}, $line{rrp} ); # FIXME from comm
360     if ( $bookseller->{'listincgst'} ) {
361         $line{rrpgsti} = sprintf( "%.2f", $line{rrp} );
362         $line{gstgsti} = sprintf( "%.2f", $line{gstrate} * 100 );
363         $line{rrpgste} = sprintf( "%.2f", $line{rrp} / ( 1 + ( $line{gstgsti} / 100 ) ) );
364         $line{gstgste} = sprintf( "%.2f", $line{gstgsti} / ( 1 + ( $line{gstgsti} / 100 ) ) );
365         $line{ecostgsti} = sprintf( "%.2f", $line{ecost} );
366         $line{ecostgste} = sprintf( "%.2f", $line{ecost} / ( 1 + ( $line{gstgsti} / 100 ) ) );
367         $line{gstvalue} = sprintf( "%.2f", ( $line{ecostgsti} - $line{ecostgste} ) * $line{quantity});
368         $line{totalgste} = sprintf( "%.2f", $order->{quantity} * $line{ecostgste} );
369         $line{totalgsti} = sprintf( "%.2f", $order->{quantity} * $line{ecostgsti} );
370     } else {
371         $line{rrpgsti} = sprintf( "%.2f", $line{rrp} * ( 1 + ( $line{gstrate} ) ) );
372         $line{rrpgste} = sprintf( "%.2f", $line{rrp} );
373         $line{gstgsti} = sprintf( "%.2f", $line{gstrate} * 100 );
374         $line{gstgste} = sprintf( "%.2f", $line{gstrate} * 100 );
375         $line{ecostgsti} = sprintf( "%.2f", $line{ecost} * ( 1 + ( $line{gstrate} ) ) );
376         $line{ecostgste} = sprintf( "%.2f", $line{ecost} );
377         $line{gstvalue} = sprintf( "%.2f", ( $line{ecostgsti} - $line{ecostgste} ) * $line{quantity});
378         $line{totalgste} = sprintf( "%.2f", $order->{quantity} * $line{ecostgste} );
379         $line{totalgsti} = sprintf( "%.2f", $order->{quantity} * $line{ecostgsti} );
380     }
381
382     if ( $line{uncertainprice} ) {
383         $line{rrpgste} .= ' (Uncertain)';
384     }
385     if ( $line{'title'} ) {
386         my $volume      = $order->{'volume'};
387         my $seriestitle = $order->{'seriestitle'};
388         $line{'title'} .= " / $seriestitle" if $seriestitle;
389         $line{'title'} .= " / $volume"      if $volume;
390     } else {
391         $line{'title'} = "Deleted bibliographic notice, can't find title.";
392     }
393
394     my $biblionumber = $order->{'biblionumber'};
395     my $countbiblio = CountBiblioInOrders($biblionumber);
396     my $ordernumber = $order->{'ordernumber'};
397     my @subscriptions = GetSubscriptionsId ($biblionumber);
398     my $itemcount = GetItemsCount($biblionumber);
399     my $holds  = GetHolds ($biblionumber);
400     my @items = GetItemnumbersFromOrder( $ordernumber );
401     my $itemholds;
402     foreach my $item (@items){
403         my $nb = GetItemHolds($biblionumber, $item);
404         if ($nb){
405             $itemholds += $nb;
406         }
407     }
408     # 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
409     $line{can_del_bib}          = 1 if $countbiblio <= 1 && $itemcount == scalar @items && !(@subscriptions) && !($holds);
410     $line{items}                = ($itemcount) - (scalar @items);
411     $line{left_item}            = 1 if $line{items} >= 1;
412     $line{left_biblio}          = 1 if $countbiblio > 1;
413     $line{biblios}              = $countbiblio - 1;
414     $line{left_subscription}    = 1 if scalar @subscriptions >= 1;
415     $line{subscriptions}        = scalar @subscriptions;
416     ($holds >= 1) ? $line{left_holds} = 1 : $line{left_holds} = 0;
417     $line{left_holds_on_order}  = 1 if $line{left_holds}==1 && ($line{items} == 0 || $itemholds );
418     $line{holds}                = $holds;
419     $line{holds_on_order}       = $itemholds?$itemholds:$holds if $line{left_holds_on_order};
420
421
422     my $suggestion   = GetSuggestionInfoFromBiblionumber($line{biblionumber});
423     $line{suggestionid}         = $$suggestion{suggestionid};
424     $line{surnamesuggestedby}   = $$suggestion{surnamesuggestedby};
425     $line{firstnamesuggestedby} = $$suggestion{firstnamesuggestedby};
426
427     return \%line;
428 }
429
430 output_html_with_http_headers $query, $cookie, $template->output;