Bug 10913: The delete basket confirmation page is never displayed
[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
11 # under the terms of the GNU General Public License as published by
12 # the Free Software Foundation; either version 3 of the License, or
13 # (at your option) any later version.
14 #
15 # Koha is distributed in the hope that it will be useful, but
16 # WITHOUT ANY WARRANTY; without even the implied warranty of
17 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 # GNU General Public License for more details.
19 #
20 # You should have received a copy of the GNU General Public License
21 # along with Koha; if not, see <http://www.gnu.org/licenses>.
22
23 use strict;
24 use warnings;
25 use C4::Auth;
26 use C4::Koha;
27 use C4::Output;
28 use CGI qw ( -utf8 );
29 use C4::Acquisition;
30 use C4::Budgets;
31 use C4::Branch;
32 use C4::Contract;
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.tt",
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 = Koha::Acquisition::Bookseller->fetch({ id => $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 'export') {
154     print $query->header(
155         -type       => 'text/csv',
156         -attachment => 'basket' . $basket->{'basketno'} . '.csv',
157     );
158     print GetBasketAsCSV($query->param('basketno'), $query);
159     exit;
160 } elsif ($op eq 'close') {
161     my $confirm = $query->param('confirm') || $confirm_pref eq '2';
162     if ($confirm) {
163         my $basketno = $query->param('basketno');
164         my $booksellerid = $query->param('booksellerid');
165         $basketno =~ /^\d+$/ and CloseBasket($basketno);
166         # if requested, create basket group, close it and attach the basket
167         if ($query->param('createbasketgroup')) {
168             my $branchcode;
169             if(C4::Context->userenv and C4::Context->userenv->{'branch'}
170               and C4::Context->userenv->{'branch'} ne "NO_LIBRARY_SET") {
171                 $branchcode = C4::Context->userenv->{'branch'};
172             }
173             my $basketgroupid = NewBasketgroup( { name => $basket->{basketname},
174                             booksellerid => $booksellerid,
175                             deliveryplace => $branchcode,
176                             billingplace => $branchcode,
177                             closed => 1,
178                             });
179             ModBasket( { basketno => $basketno,
180                          basketgroupid => $basketgroupid } );
181             print $query->redirect('/cgi-bin/koha/acqui/basketgroup.pl?booksellerid='.$booksellerid.'&closed=1');
182         } else {
183             print $query->redirect('/cgi-bin/koha/acqui/booksellers.pl?booksellerid=' . $booksellerid);
184         }
185         exit;
186     } else {
187     $template->param(
188         confirm_close   => "1",
189         booksellerid    => $booksellerid,
190         basketno        => $basket->{'basketno'},
191         basketname      => $basket->{'basketname'},
192         basketgroupname => $basket->{'basketname'},
193     );
194     }
195 } elsif ($op eq 'reopen') {
196     ReopenBasket($query->param('basketno'));
197     print $query->redirect('/cgi-bin/koha/acqui/basket.pl?basketno='.$basket->{'basketno'})
198 } elsif ( $op eq 'mod_users' ) {
199     my $basketusers_ids = $query->param('users_ids');
200     my @basketusers = split( /:/, $basketusers_ids );
201     ModBasketUsers($basketno, @basketusers);
202     print $query->redirect("/cgi-bin/koha/acqui/basket.pl?basketno=$basketno");
203     exit;
204 } elsif ( $op eq 'mod_branch' ) {
205     my $branch = $query->param('branch');
206     $branch = undef if(defined $branch and $branch eq '');
207     ModBasket({
208         basketno => $basket->{basketno},
209         branch   => $branch
210     });
211     print $query->redirect("/cgi-bin/koha/acqui/basket.pl?basketno=$basketno");
212     exit;
213 } else {
214     my @branches_loop;
215     # get librarian branch...
216     if ( C4::Context->preference("IndependentBranches") ) {
217         my $userenv = C4::Context->userenv;
218         unless ( C4::Context->IsSuperLibrarian() ) {
219             my $validtest = ( $basket->{creationdate} eq '' )
220               || ( $userenv->{branch} eq $basket->{branch} )
221               || ( $userenv->{branch} eq '' )
222               || ( $basket->{branch}  eq '' );
223             unless ($validtest) {
224                 print $query->redirect("../mainpage.pl");
225                 exit 1;
226             }
227         }
228         if (!defined $basket->{branch} or $basket->{branch} eq $userenv->{branch}) {
229             push @branches_loop, {
230                 branchcode => $userenv->{branch},
231                 branchname => $userenv->{branchname},
232                 selected => 1,
233             };
234         }
235     } else {
236         # get branches
237         my $branches = C4::Branch::GetBranches;
238         my @branchcodes = sort {
239             $branches->{$a}->{branchname} cmp $branches->{$b}->{branchname}
240         } keys %$branches;
241         foreach my $branch (@branchcodes) {
242             my $selected = 0;
243             if (defined $basket->{branch}) {
244                 $selected = 1 if $branch eq $basket->{branch};
245             } else {
246                 $selected = 1 if $branch eq C4::Context->userenv->{branch};
247             }
248             push @branches_loop, {
249                 branchcode => $branch,
250                 branchname => $branches->{$branch}->{branchname},
251                 selected => $selected
252             };
253         }
254     }
255
256 #if the basket is closed,and the user has the permission to edit basketgroups, display a list of basketgroups
257     my ($basketgroup, $basketgroups);
258     my $staffuser = GetMember(borrowernumber => $loggedinuser);
259     if ($basket->{closedate} && haspermission($staffuser->{userid}, { acquisition => 'group_manage'} )) {
260         $basketgroups = GetBasketgroups($basket->{booksellerid});
261         for my $bg ( @{$basketgroups} ) {
262             if ($basket->{basketgroupid} && $basket->{basketgroupid} == $bg->{id}){
263                 $bg->{default} = 1;
264                 $basketgroup = $bg;
265             }
266         }
267     }
268
269     # if the basket is closed, calculate estimated delivery date
270     my $estimateddeliverydate;
271     if( $basket->{closedate} ) {
272         my ($year, $month, $day) = ($basket->{closedate} =~ /(\d+)-(\d+)-(\d+)/);
273         ($year, $month, $day) = Add_Delta_Days($year, $month, $day, $bookseller->{deliverytime});
274         $estimateddeliverydate = sprintf( "%04d-%02d-%02d", $year, $month, $day );
275     }
276
277     # if new basket, pre-fill infos
278     $basket->{creationdate} = ""            unless ( $basket->{creationdate} );
279     $basket->{authorisedby} = $loggedinuser unless ( $basket->{authorisedby} );
280     $debug
281       and warn sprintf
282       "loggedinuser: $loggedinuser; creationdate: %s; authorisedby: %s",
283       $basket->{creationdate}, $basket->{authorisedby};
284
285     my @basketusers_ids = GetBasketUsers($basketno);
286     my @basketusers;
287     foreach my $basketuser_id (@basketusers_ids) {
288         my $basketuser = GetMember(borrowernumber => $basketuser_id);
289         push @basketusers, $basketuser if $basketuser;
290     }
291
292     #to get active currency
293     my $cur = GetCurrency();
294
295
296     my @orders = GetOrders( $basketno );
297     my @books_loop;
298
299     my @book_foot_loop;
300     my %foot;
301     my $total_quantity = 0;
302     my $total_gste = 0;
303     my $total_gsti = 0;
304     my $total_gstvalue = 0;
305     for my $order (@orders) {
306         $order = C4::Acquisition::populate_order_with_prices({ order => $order, booksellerid => $booksellerid, ordering => 1 });
307         my $line = get_order_infos( $order, $bookseller);
308         if ( $line->{uncertainprice} ) {
309             $template->param( uncertainprices => 1 );
310         }
311
312         push @books_loop, $line;
313
314         $foot{$$line{gstrate}}{gstrate} = $$line{gstrate};
315         $foot{$$line{gstrate}}{gstvalue} += $$line{gstvalue};
316         $total_gstvalue += $$line{gstvalue};
317         $foot{$$line{gstrate}}{quantity}  += $$line{quantity};
318         $total_quantity += $$line{quantity};
319         $foot{$$line{gstrate}}{totalgste} += $$line{totalgste};
320         $total_gste += $$line{totalgste};
321         $foot{$$line{gstrate}}{totalgsti} += $$line{totalgsti};
322         $total_gsti += $$line{totalgsti};
323     }
324
325     push @book_foot_loop, map {$_} values %foot;
326
327     # Get cancelled orders
328     my @cancelledorders = GetOrders($basketno, { cancelled => 1 });
329     my @cancelledorders_loop;
330     for my $order (@cancelledorders) {
331         $order = C4::Acquisition::populate_order_with_prices({ order => $order, booksellerid => $booksellerid, ordering => 1 });
332         my $line = get_order_infos( $order, $bookseller);
333         push @cancelledorders_loop, $line;
334     }
335
336     my $contract = GetContract({
337         contractnumber => $basket->{contractnumber}
338     });
339
340     if ($basket->{basketgroupid}){
341         $basketgroup = GetBasketgroup($basket->{basketgroupid});
342         $basketgroup->{deliveryplacename} = C4::Branch::GetBranchName( $basketgroup->{deliveryplace} );
343         $basketgroup->{billingplacename} = C4::Branch::GetBranchName( $basketgroup->{billingplace} );
344     }
345     my $borrower= GetMember('borrowernumber' => $loggedinuser);
346     my $budgets = GetBudgetHierarchy;
347     my $has_budgets = 0;
348     foreach my $r (@{$budgets}) {
349         if (!defined $r->{budget_amount} || $r->{budget_amount} == 0) {
350             next;
351         }
352         next unless (CanUserUseBudget($loggedinuser, $r, $userflags));
353
354         $has_budgets = 1;
355         last;
356     }
357
358     $template->param(
359         basketno             => $basketno,
360         basketname           => $basket->{'basketname'},
361         basketbranchname     => C4::Branch::GetBranchName($basket->{branch}),
362         basketnote           => $basket->{note},
363         basketbooksellernote => $basket->{booksellernote},
364         basketcontractno     => $basket->{contractnumber},
365         basketcontractname   => $contract->{contractname},
366         branches_loop        => \@branches_loop,
367         creationdate         => $basket->{creationdate},
368         authorisedby         => $basket->{authorisedby},
369         authorisedbyname     => $basket->{authorisedbyname},
370         users_ids            => join(':', @basketusers_ids),
371         users                => \@basketusers,
372         closedate            => $basket->{closedate},
373         estimateddeliverydate=> $estimateddeliverydate,
374         deliveryplace        => C4::Branch::GetBranchName( $basket->{deliveryplace} ),
375         billingplace         => C4::Branch::GetBranchName( $basket->{billingplace} ),
376         active               => $bookseller->{'active'},
377         booksellerid         => $bookseller->{'id'},
378         name                 => $bookseller->{'name'},
379         books_loop           => \@books_loop,
380         book_foot_loop       => \@book_foot_loop,
381         cancelledorders_loop => \@cancelledorders_loop,
382         total_quantity       => $total_quantity,
383         total_gste           => sprintf( "%.2f", $total_gste ),
384         total_gsti           => sprintf( "%.2f", $total_gsti ),
385         total_gstvalue       => sprintf( "%.2f", $total_gstvalue ),
386         currency             => $cur->{'currency'},
387         listincgst           => $bookseller->{listincgst},
388         basketgroups         => $basketgroups,
389         basketgroup          => $basketgroup,
390         grouped              => $basket->{basketgroupid},
391         unclosable           => @orders ? 0 : 1, 
392         has_budgets          => $has_budgets,
393     );
394 }
395
396 sub get_order_infos {
397     my $order = shift;
398     my $bookseller = shift;
399     my $qty = $order->{'quantity'} || 0;
400     if ( !defined $order->{quantityreceived} ) {
401         $order->{quantityreceived} = 0;
402     }
403     my $budget = GetBudget( $order->{'budget_id'} );
404
405     my %line = %{ $order };
406     $line{order_received} = ( $qty == $order->{'quantityreceived'} );
407     $line{basketno}       = $basketno;
408     $line{budget_name}    = $budget->{budget_name};
409
410     if ( $line{uncertainprice} ) {
411         $line{rrpgste} .= ' (Uncertain)';
412     }
413     if ( $line{'title'} ) {
414         my $volume      = $order->{'volume'};
415         my $seriestitle = $order->{'seriestitle'};
416         $line{'title'} .= " / $seriestitle" if $seriestitle;
417         $line{'title'} .= " / $volume"      if $volume;
418     } else {
419         $line{'title'} = "Deleted bibliographic notice, can't find title.";
420     }
421
422     my $biblionumber = $order->{'biblionumber'};
423     my $countbiblio = CountBiblioInOrders($biblionumber);
424     my $ordernumber = $order->{'ordernumber'};
425     my @subscriptions = GetSubscriptionsId ($biblionumber);
426     my $itemcount = GetItemsCount($biblionumber);
427     my $holds  = GetHolds ($biblionumber);
428     my @items = GetItemnumbersFromOrder( $ordernumber );
429     my $itemholds;
430     foreach my $item (@items){
431         my $nb = GetItemHolds($biblionumber, $item);
432         if ($nb){
433             $itemholds += $nb;
434         }
435     }
436     # 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
437     $line{can_del_bib}          = 1 if $countbiblio <= 1 && $itemcount == scalar @items && !(@subscriptions) && !($holds);
438     $line{items}                = ($itemcount) - (scalar @items);
439     $line{left_item}            = 1 if $line{items} >= 1;
440     $line{left_biblio}          = 1 if $countbiblio > 1;
441     $line{biblios}              = $countbiblio - 1;
442     $line{left_subscription}    = 1 if scalar @subscriptions >= 1;
443     $line{subscriptions}        = scalar @subscriptions;
444     ($holds >= 1) ? $line{left_holds} = 1 : $line{left_holds} = 0;
445     $line{left_holds_on_order}  = 1 if $line{left_holds}==1 && ($line{items} == 0 || $itemholds );
446     $line{holds}                = $holds;
447     $line{holds_on_order}       = $itemholds?$itemholds:$holds if $line{left_holds_on_order};
448
449
450     my $suggestion   = GetSuggestionInfoFromBiblionumber($line{biblionumber});
451     $line{suggestionid}         = $$suggestion{suggestionid};
452     $line{surnamesuggestedby}   = $$suggestion{surnamesuggestedby};
453     $line{firstnamesuggestedby} = $$suggestion{firstnamesuggestedby};
454
455     foreach my $key (qw(transferred_from transferred_to)) {
456         if ($line{$key}) {
457             my $order = GetOrder($line{$key});
458             my $basket = GetBasket($order->{basketno});
459             my $bookseller = Koha::Acquisition::Bookseller->fetch({ id => $basket->{booksellerid} });
460             $line{$key} = {
461                 order => $order,
462                 basket => $basket,
463                 bookseller => $bookseller,
464                 timestamp => $line{$key . '_timestamp'},
465             };
466         }
467     }
468
469     return \%line;
470 }
471
472 output_html_with_http_headers $query, $cookie, $template->output;