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