Bug 11433: (code cleanup) remove unused 'attachbasket' op value in basket.pl
[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::Branch;
32 use C4::Bookseller qw( GetBookSellerFromId);
33 use C4::Debug;
34 use C4::Biblio;
35 use C4::Members qw/GetMember/;  #needed for permissions checking for changing basketgroup of a basket
36 use C4::Items;
37 use C4::Suggestions;
38 use Date::Calc qw/Add_Delta_Days/;
39
40 =head1 NAME
41
42 basket.pl
43
44 =head1 DESCRIPTION
45
46  This script display all informations about basket for the supplier given
47  on input arg.  Moreover, it allows us to add a new order for this supplier from
48  an existing record, a suggestion or a new record.
49
50 =head1 CGI PARAMETERS
51
52 =over 4
53
54 =item $basketno
55
56 The basket number.
57
58 =item booksellerid
59
60 the supplier this script have to display the basket.
61
62 =item order
63
64 =back
65
66 =cut
67
68 my $query        = new CGI;
69 our $basketno     = $query->param('basketno');
70 my $booksellerid = $query->param('booksellerid');
71
72 my ( $template, $loggedinuser, $cookie, $userflags ) = get_template_and_user(
73     {
74         template_name   => "acqui/basket.tmpl",
75         query           => $query,
76         type            => "intranet",
77         authnotrequired => 0,
78         flagsrequired   => { acquisition => 'order_manage' },
79         debug           => 1,
80     }
81 );
82
83 my $basket = GetBasket($basketno);
84 $booksellerid = $basket->{booksellerid} unless $booksellerid;
85 my ($bookseller) = GetBookSellerFromId($booksellerid);
86
87 unless (CanUserManageBasket($loggedinuser, $basket, $userflags)) {
88     $template->param(
89         cannot_manage_basket => 1,
90         basketno => $basketno,
91         basketname => $basket->{basketname},
92         booksellerid => $booksellerid,
93         name => $bookseller->{name}
94     );
95     output_html_with_http_headers $query, $cookie, $template->output;
96     exit;
97 }
98
99 # FIXME : what about the "discount" percentage?
100 # FIXME : the query->param('booksellerid') below is probably useless. The bookseller is always known from the basket
101 # if no booksellerid in parameter, get it from basket
102 # warn "=>".$basket->{booksellerid};
103 my $op = $query->param('op');
104 if (!defined $op) {
105     $op = q{};
106 }
107
108 my $confirm_pref= C4::Context->preference("BasketConfirmations") || '1';
109 $template->param( skip_confirm_reopen => 1) if $confirm_pref eq '2';
110
111 if ( $op eq 'delete_confirm' ) {
112     my $basketno = $query->param('basketno');
113     my $delbiblio = $query->param('delbiblio');
114     my @orders = GetOrders($basketno);
115 #Delete all orders included in that basket, and all items received.
116     foreach my $myorder (@orders){
117         DelOrder($myorder->{biblionumber},$myorder->{ordernumber});
118     }
119 # if $delbiblio = 1, delete the records if possible
120     if ((defined $delbiblio)and ($delbiblio ==1)){
121         my @cannotdelbiblios ;
122         foreach my $myorder (@orders){
123             my $biblionumber = $myorder->{'biblionumber'};
124             my $countbiblio = CountBiblioInOrders($biblionumber);
125             my $ordernumber = $myorder->{'ordernumber'};
126             my $subscriptions = scalar GetSubscriptionsId ($biblionumber);
127             my $itemcount = GetItemsCount($biblionumber);
128             my $error;
129             if ($countbiblio == 0 && $itemcount == 0 && $subscriptions == 0) {
130                 $error = DelBiblio($myorder->{biblionumber}) }
131             else {
132                 push @cannotdelbiblios, {biblionumber=> ($myorder->{biblionumber}),
133                                          title=> $myorder->{'title'},
134                                          author=> $myorder->{'author'},
135                                          countbiblio=> $countbiblio,
136                                          itemcount=>$itemcount,
137                                          subscriptions=>$subscriptions};
138             }
139             if ($error) {
140                 push @cannotdelbiblios, {biblionumber=> ($myorder->{biblionumber}),
141                                          title=> $myorder->{'title'},
142                                          author=> $myorder->{'author'},
143                                          othererror=> $error};
144             }
145         }
146         $template->param( cannotdelbiblios => \@cannotdelbiblios );
147     }
148  # delete the basket
149     DelBasket($basketno,);
150     $template->param( delete_confirmed => 1 );
151 } elsif ( !$bookseller ) {
152     $template->param( NO_BOOKSELLER => 1 );
153 } elsif ( $op eq 'del_basket') {
154     $template->param( delete_confirm => 1 );
155     if ( C4::Context->preference("IndependentBranches") ) {
156         my $userenv = C4::Context->userenv;
157         unless ( C4::Context->IsSuperLibrarian() ) {
158             my $validtest = ( $basket->{creationdate} eq '' )
159               || ( $userenv->{branch} eq $basket->{branch} )
160               || ( $userenv->{branch} eq '' )
161               || ( $basket->{branch}  eq '' );
162             unless ($validtest) {
163                 print $query->redirect("../mainpage.pl");
164                 exit 1;
165             }
166         }
167     }
168     $basket->{creationdate} = ""            unless ( $basket->{creationdate} );
169     $basket->{authorisedby} = $loggedinuser unless ( $basket->{authorisedby} );
170     my $contract = &GetContract($basket->{contractnumber});
171     $template->param(
172         basketno             => $basketno,
173         basketname           => $basket->{'basketname'},
174         basketnote           => $basket->{note},
175         basketbooksellernote => $basket->{booksellernote},
176         basketcontractno     => $basket->{contractnumber},
177         basketcontractname   => $contract->{contractname},
178         creationdate         => $basket->{creationdate},
179         authorisedby         => $basket->{authorisedby},
180         authorisedbyname     => $basket->{authorisedbyname},
181         closedate            => $basket->{closedate},
182         deliveryplace        => $basket->{deliveryplace},
183         billingplace         => $basket->{billingplace},
184         active               => $bookseller->{'active'},
185         booksellerid         => $bookseller->{'id'},
186         name                 => $bookseller->{'name'},
187         address1             => $bookseller->{'address1'},
188         address2             => $bookseller->{'address2'},
189         address3             => $bookseller->{'address3'},
190         address4             => $bookseller->{'address4'},
191       );
192 } elsif ($op eq 'export') {
193     print $query->header(
194         -type       => 'text/csv',
195         -attachment => 'basket' . $basket->{'basketno'} . '.csv',
196     );
197     print GetBasketAsCSV($query->param('basketno'), $query);
198     exit;
199 } elsif ($op eq 'close') {
200     my $confirm = $query->param('confirm') || $confirm_pref eq '2';
201     if ($confirm) {
202         my $basketno = $query->param('basketno');
203         my $booksellerid = $query->param('booksellerid');
204         $basketno =~ /^\d+$/ and CloseBasket($basketno);
205         # if requested, create basket group, close it and attach the basket
206         if ($query->param('createbasketgroup')) {
207             my $branchcode;
208             if(C4::Context->userenv and C4::Context->userenv->{'branch'}
209               and C4::Context->userenv->{'branch'} ne "NO_LIBRARY_SET") {
210                 $branchcode = C4::Context->userenv->{'branch'};
211             }
212             my $basketgroupid = NewBasketgroup( { name => $basket->{basketname},
213                             booksellerid => $booksellerid,
214                             deliveryplace => $branchcode,
215                             billingplace => $branchcode,
216                             closed => 1,
217                             });
218             ModBasket( { basketno => $basketno,
219                          basketgroupid => $basketgroupid } );
220             print $query->redirect('/cgi-bin/koha/acqui/basketgroup.pl?booksellerid='.$booksellerid.'&closed=1');
221         } else {
222             print $query->redirect('/cgi-bin/koha/acqui/booksellers.pl?booksellerid=' . $booksellerid);
223         }
224         exit;
225     } else {
226     $template->param(
227         confirm_close   => "1",
228         booksellerid    => $booksellerid,
229         basketno        => $basket->{'basketno'},
230         basketname      => $basket->{'basketname'},
231         basketgroupname => $basket->{'basketname'},
232     );
233     }
234 } elsif ($op eq 'reopen') {
235     ReopenBasket($query->param('basketno'));
236     print $query->redirect('/cgi-bin/koha/acqui/basket.pl?basketno='.$basket->{'basketno'})
237 } elsif ( $op eq 'mod_users' ) {
238     my $basketusers_ids = $query->param('basketusers_ids');
239     my @basketusers = split( /:/, $basketusers_ids );
240     ModBasketUsers($basketno, @basketusers);
241     print $query->redirect("/cgi-bin/koha/acqui/basket.pl?basketno=$basketno");
242     exit;
243 } elsif ( $op eq 'mod_branch' ) {
244     my $branch = $query->param('branch');
245     $branch = undef if(defined $branch and $branch eq '');
246     ModBasket({
247         basketno => $basket->{basketno},
248         branch   => $branch
249     });
250     print $query->redirect("/cgi-bin/koha/acqui/basket.pl?basketno=$basketno");
251     exit;
252 } else {
253     my @branches_loop;
254     # get librarian branch...
255     if ( C4::Context->preference("IndependentBranches") ) {
256         my $userenv = C4::Context->userenv;
257         unless ( C4::Context->IsSuperLibrarian() ) {
258             my $validtest = ( $basket->{creationdate} eq '' )
259               || ( $userenv->{branch} eq $basket->{branch} )
260               || ( $userenv->{branch} eq '' )
261               || ( $basket->{branch}  eq '' );
262             unless ($validtest) {
263                 print $query->redirect("../mainpage.pl");
264                 exit 1;
265             }
266         }
267         if (!defined $basket->{branch} or $basket->{branch} eq $userenv->{branch}) {
268             push @branches_loop, {
269                 branchcode => $userenv->{branch},
270                 branchname => $userenv->{branchname},
271                 selected => 1,
272             };
273         }
274     } else {
275         # get branches
276         my $branches = C4::Branch::GetBranches;
277         my @branchcodes = sort {
278             $branches->{$a}->{branchname} cmp $branches->{$b}->{branchname}
279         } keys %$branches;
280         foreach my $branch (@branchcodes) {
281             my $selected = 0;
282             if (defined $basket->{branch}) {
283                 $selected = 1 if $branch eq $basket->{branch};
284             } else {
285                 $selected = 1 if $branch eq C4::Context->userenv->{branch};
286             }
287             push @branches_loop, {
288                 branchcode => $branch,
289                 branchname => $branches->{$branch}->{branchname},
290                 selected => $selected
291             };
292         }
293     }
294
295 #if the basket is closed,and the user has the permission to edit basketgroups, display a list of basketgroups
296     my ($basketgroup, $basketgroups);
297     my $staffuser = GetMember(borrowernumber => $loggedinuser);
298     if ($basket->{closedate} && haspermission($staffuser->{userid}, { acquisition => 'group_manage'} )) {
299         $basketgroups = GetBasketgroups($basket->{booksellerid});
300         for my $bg ( @{$basketgroups} ) {
301             if ($basket->{basketgroupid} && $basket->{basketgroupid} == $bg->{id}){
302                 $bg->{default} = 1;
303                 $basketgroup = $bg;
304             }
305         }
306     }
307
308     # if the basket is closed, calculate estimated delivery date
309     my $estimateddeliverydate;
310     if( $basket->{closedate} ) {
311         my ($year, $month, $day) = ($basket->{closedate} =~ /(\d+)-(\d+)-(\d+)/);
312         ($year, $month, $day) = Add_Delta_Days($year, $month, $day, $bookseller->{deliverytime});
313         $estimateddeliverydate = "$year-$month-$day";
314     }
315
316     # if new basket, pre-fill infos
317     $basket->{creationdate} = ""            unless ( $basket->{creationdate} );
318     $basket->{authorisedby} = $loggedinuser unless ( $basket->{authorisedby} );
319     $debug
320       and warn sprintf
321       "loggedinuser: $loggedinuser; creationdate: %s; authorisedby: %s",
322       $basket->{creationdate}, $basket->{authorisedby};
323
324     my @basketusers_ids = GetBasketUsers($basketno);
325     my @basketusers;
326     foreach my $basketuser_id (@basketusers_ids) {
327         my $basketuser = GetMember(borrowernumber => $basketuser_id);
328         push @basketusers, $basketuser if $basketuser;
329     }
330
331     #to get active currency
332     my $cur = GetCurrency();
333
334
335     my @results = GetOrders( $basketno );
336     my @books_loop;
337
338     my @book_foot_loop;
339     my %foot;
340     my $total_quantity = 0;
341     my $total_gste = 0;
342     my $total_gsti = 0;
343     my $total_gstvalue = 0;
344     for my $order (@results) {
345         my $line = get_order_infos( $order, $bookseller);
346         if ( $line->{uncertainprice} ) {
347             $template->param( uncertainprices => 1 );
348         }
349
350         push @books_loop, $line;
351
352         $foot{$$line{gstgsti}}{gstgsti} = $$line{gstgsti};
353         $foot{$$line{gstgsti}}{gstvalue} += $$line{gstvalue};
354         $total_gstvalue += $$line{gstvalue};
355         $foot{$$line{gstgsti}}{quantity}  += $$line{quantity};
356         $total_quantity += $$line{quantity};
357         $foot{$$line{gstgsti}}{totalgste} += $$line{totalgste};
358         $total_gste += $$line{totalgste};
359         $foot{$$line{gstgsti}}{totalgsti} += $$line{totalgsti};
360         $total_gsti += $$line{totalgsti};
361     }
362
363     push @book_foot_loop, map {$_} values %foot;
364
365     # Get cancelled orders
366     @results = GetCancelledOrders($basketno);
367     my @cancelledorders_loop;
368     for my $order (@results) {
369         my $line = get_order_infos( $order, $bookseller);
370         push @cancelledorders_loop, $line;
371     }
372
373     my $contract = &GetContract($basket->{contractnumber});
374     my @orders = GetOrders($basketno);
375
376     if ($basket->{basketgroupid}){
377         $basketgroup = GetBasketgroup($basket->{basketgroupid});
378         $basketgroup->{deliveryplacename} = C4::Branch::GetBranchName( $basketgroup->{deliveryplace} );
379         $basketgroup->{billingplacename} = C4::Branch::GetBranchName( $basketgroup->{billingplace} );
380     }
381     my $borrower= GetMember('borrowernumber' => $loggedinuser);
382     my $budgets = GetBudgetHierarchy;
383     my $has_budgets = 0;
384     foreach my $r (@{$budgets}) {
385         if (!defined $r->{budget_amount} || $r->{budget_amount} == 0) {
386             next;
387         }
388         next unless (CanUserUseBudget($loggedinuser, $r, $userflags));
389
390         $has_budgets = 1;
391         last;
392     }
393
394     $template->param(
395         basketno             => $basketno,
396         basketname           => $basket->{'basketname'},
397         basketbranchname     => C4::Branch::GetBranchName($basket->{branch}),
398         basketnote           => $basket->{note},
399         basketbooksellernote => $basket->{booksellernote},
400         basketcontractno     => $basket->{contractnumber},
401         basketcontractname   => $contract->{contractname},
402         branches_loop        => \@branches_loop,
403         creationdate         => $basket->{creationdate},
404         authorisedby         => $basket->{authorisedby},
405         authorisedbyname     => $basket->{authorisedbyname},
406         basketusers_ids      => join(':', @basketusers_ids),
407         basketusers          => \@basketusers,
408         closedate            => $basket->{closedate},
409         estimateddeliverydate=> $estimateddeliverydate,
410         deliveryplace        => C4::Branch::GetBranchName( $basket->{deliveryplace} ),
411         billingplace         => C4::Branch::GetBranchName( $basket->{billingplace} ),
412         active               => $bookseller->{'active'},
413         booksellerid         => $bookseller->{'id'},
414         name                 => $bookseller->{'name'},
415         books_loop           => \@books_loop,
416         book_foot_loop       => \@book_foot_loop,
417         cancelledorders_loop => \@cancelledorders_loop,
418         total_quantity       => $total_quantity,
419         total_gste           => sprintf( "%.2f", $total_gste ),
420         total_gsti           => sprintf( "%.2f", $total_gsti ),
421         total_gstvalue       => sprintf( "%.2f", $total_gstvalue ),
422         currency             => $cur->{'currency'},
423         listincgst           => $bookseller->{listincgst},
424         basketgroups         => $basketgroups,
425         basketgroup          => $basketgroup,
426         grouped              => $basket->{basketgroupid},
427         unclosable           => @orders ? 0 : 1, 
428         has_budgets          => $has_budgets,
429     );
430 }
431
432 sub get_order_infos {
433     my $order = shift;
434     my $bookseller = shift;
435     my $qty = $order->{'quantity'} || 0;
436     if ( !defined $order->{quantityreceived} ) {
437         $order->{quantityreceived} = 0;
438     }
439     my $budget = GetBudget( $order->{'budget_id'} );
440
441     my %line = %{ $order };
442     $line{order_received} = ( $qty == $order->{'quantityreceived'} );
443     $line{basketno}       = $basketno;
444     $line{budget_name}    = $budget->{budget_name};
445     $line{rrp} = ConvertCurrency( $order->{'currency'}, $line{rrp} ); # FIXME from comm
446     if ( $bookseller->{'listincgst'} ) {
447         $line{rrpgsti} = sprintf( "%.2f", $line{rrp} );
448         $line{gstgsti} = sprintf( "%.2f", $line{gstrate} * 100 );
449         $line{rrpgste} = sprintf( "%.2f", $line{rrp} / ( 1 + ( $line{gstgsti} / 100 ) ) );
450         $line{gstgste} = sprintf( "%.2f", $line{gstgsti} / ( 1 + ( $line{gstgsti} / 100 ) ) );
451         $line{ecostgsti} = sprintf( "%.2f", $line{ecost} );
452         $line{ecostgste} = sprintf( "%.2f", $line{ecost} / ( 1 + ( $line{gstgsti} / 100 ) ) );
453         $line{gstvalue} = sprintf( "%.2f", ( $line{ecostgsti} - $line{ecostgste} ) * $line{quantity});
454         $line{totalgste} = sprintf( "%.2f", $order->{quantity} * $line{ecostgste} );
455         $line{totalgsti} = sprintf( "%.2f", $order->{quantity} * $line{ecostgsti} );
456     } else {
457         $line{rrpgsti} = sprintf( "%.2f", $line{rrp} * ( 1 + ( $line{gstrate} ) ) );
458         $line{rrpgste} = sprintf( "%.2f", $line{rrp} );
459         $line{gstgsti} = sprintf( "%.2f", $line{gstrate} * 100 );
460         $line{gstgste} = sprintf( "%.2f", $line{gstrate} * 100 );
461         $line{ecostgsti} = sprintf( "%.2f", $line{ecost} * ( 1 + ( $line{gstrate} ) ) );
462         $line{ecostgste} = sprintf( "%.2f", $line{ecost} );
463         $line{gstvalue} = sprintf( "%.2f", ( $line{ecostgsti} - $line{ecostgste} ) * $line{quantity});
464         $line{totalgste} = sprintf( "%.2f", $order->{quantity} * $line{ecostgste} );
465         $line{totalgsti} = sprintf( "%.2f", $order->{quantity} * $line{ecostgsti} );
466     }
467
468     if ( $line{uncertainprice} ) {
469         $line{rrpgste} .= ' (Uncertain)';
470     }
471     if ( $line{'title'} ) {
472         my $volume      = $order->{'volume'};
473         my $seriestitle = $order->{'seriestitle'};
474         $line{'title'} .= " / $seriestitle" if $seriestitle;
475         $line{'title'} .= " / $volume"      if $volume;
476     } else {
477         $line{'title'} = "Deleted bibliographic notice, can't find title.";
478     }
479
480     my $biblionumber = $order->{'biblionumber'};
481     my $countbiblio = CountBiblioInOrders($biblionumber);
482     my $ordernumber = $order->{'ordernumber'};
483     my @subscriptions = GetSubscriptionsId ($biblionumber);
484     my $itemcount = GetItemsCount($biblionumber);
485     my $holds  = GetHolds ($biblionumber);
486     my @items = GetItemnumbersFromOrder( $ordernumber );
487     my $itemholds;
488     foreach my $item (@items){
489         my $nb = GetItemHolds($biblionumber, $item);
490         if ($nb){
491             $itemholds += $nb;
492         }
493     }
494     # 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
495     $line{can_del_bib}          = 1 if $countbiblio <= 1 && $itemcount == scalar @items && !(@subscriptions) && !($holds);
496     $line{items}                = ($itemcount) - (scalar @items);
497     $line{left_item}            = 1 if $line{items} >= 1;
498     $line{left_biblio}          = 1 if $countbiblio > 1;
499     $line{biblios}              = $countbiblio - 1;
500     $line{left_subscription}    = 1 if scalar @subscriptions >= 1;
501     $line{subscriptions}        = scalar @subscriptions;
502     ($holds >= 1) ? $line{left_holds} = 1 : $line{left_holds} = 0;
503     $line{left_holds_on_order}  = 1 if $line{left_holds}==1 && ($line{items} == 0 || $itemholds );
504     $line{holds}                = $holds;
505     $line{holds_on_order}       = $itemholds?$itemholds:$holds if $line{left_holds_on_order};
506
507
508     my $suggestion   = GetSuggestionInfoFromBiblionumber($line{biblionumber});
509     $line{suggestionid}         = $$suggestion{suggestionid};
510     $line{surnamesuggestedby}   = $$suggestion{surnamesuggestedby};
511     $line{firstnamesuggestedby} = $$suggestion{firstnamesuggestedby};
512
513     foreach my $key (qw(transferred_from transferred_to)) {
514         if ($line{$key}) {
515             my $order = GetOrder($line{$key});
516             my $basket = GetBasket($order->{basketno});
517             my $bookseller = GetBookSellerFromId($basket->{booksellerid});
518             $line{$key} = {
519                 order => $order,
520                 basket => $basket,
521                 bookseller => $bookseller,
522                 timestamp => $line{$key . '_timestamp'},
523             };
524         }
525     }
526
527     return \%line;
528 }
529
530 output_html_with_http_headers $query, $cookie, $template->output;