Bug 15632: Koha::Patron::Messages - Remove GetMessagesCount
[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 my $duplinbatch =  $query->param('duplinbatch');
72
73 my ( $template, $loggedinuser, $cookie, $userflags ) = get_template_and_user(
74     {
75         template_name   => "acqui/basket.tt",
76         query           => $query,
77         type            => "intranet",
78         authnotrequired => 0,
79         flagsrequired   => { acquisition => 'order_manage' },
80         debug           => 1,
81     }
82 );
83
84 my $basket = GetBasket($basketno);
85 $booksellerid = $basket->{booksellerid} unless $booksellerid;
86 my $bookseller = Koha::Acquisition::Bookseller->fetch({ id => $booksellerid });
87
88 unless (CanUserManageBasket($loggedinuser, $basket, $userflags)) {
89     $template->param(
90         cannot_manage_basket => 1,
91         basketno => $basketno,
92         basketname => $basket->{basketname},
93         booksellerid => $booksellerid,
94         name => $bookseller->{name}
95     );
96     output_html_with_http_headers $query, $cookie, $template->output;
97     exit;
98 }
99
100 # FIXME : what about the "discount" percentage?
101 # FIXME : the query->param('booksellerid') below is probably useless. The bookseller is always known from the basket
102 # if no booksellerid in parameter, get it from basket
103 # warn "=>".$basket->{booksellerid};
104 my $op = $query->param('op');
105 if (!defined $op) {
106     $op = q{};
107 }
108
109 my $confirm_pref= C4::Context->preference("BasketConfirmations") || '1';
110 $template->param( skip_confirm_reopen => 1) if $confirm_pref eq '2';
111
112 if ( $op eq 'delete_confirm' ) {
113     my $basketno = $query->param('basketno');
114     my $delbiblio = $query->param('delbiblio');
115     my @orders = GetOrders($basketno);
116 #Delete all orders included in that basket, and all items received.
117     foreach my $myorder (@orders){
118         DelOrder($myorder->{biblionumber},$myorder->{ordernumber});
119     }
120 # if $delbiblio = 1, delete the records if possible
121     if ((defined $delbiblio)and ($delbiblio ==1)){
122         my @cannotdelbiblios ;
123         foreach my $myorder (@orders){
124             my $biblionumber = $myorder->{'biblionumber'};
125             my $countbiblio = CountBiblioInOrders($biblionumber);
126             my $ordernumber = $myorder->{'ordernumber'};
127             my $subscriptions = scalar GetSubscriptionsId ($biblionumber);
128             my $itemcount = GetItemsCount($biblionumber);
129             my $error;
130             if ($countbiblio == 0 && $itemcount == 0 && $subscriptions == 0) {
131                 $error = DelBiblio($myorder->{biblionumber}) }
132             else {
133                 push @cannotdelbiblios, {biblionumber=> ($myorder->{biblionumber}),
134                                          title=> $myorder->{'title'},
135                                          author=> $myorder->{'author'},
136                                          countbiblio=> $countbiblio,
137                                          itemcount=>$itemcount,
138                                          subscriptions=>$subscriptions};
139             }
140             if ($error) {
141                 push @cannotdelbiblios, {biblionumber=> ($myorder->{biblionumber}),
142                                          title=> $myorder->{'title'},
143                                          author=> $myorder->{'author'},
144                                          othererror=> $error};
145             }
146         }
147         $template->param( cannotdelbiblios => \@cannotdelbiblios );
148     }
149  # delete the basket
150     DelBasket($basketno,);
151     $template->param( delete_confirmed => 1 );
152 } elsif ( !$bookseller ) {
153     $template->param( NO_BOOKSELLER => 1 );
154 } elsif ($op eq 'export') {
155     print $query->header(
156         -type       => 'text/csv',
157         -attachment => 'basket' . $basket->{'basketno'} . '.csv',
158     );
159     print GetBasketAsCSV($query->param('basketno'), $query);
160     exit;
161 } elsif ($op eq 'close') {
162     my $confirm = $query->param('confirm') || $confirm_pref eq '2';
163     if ($confirm) {
164         my $basketno = $query->param('basketno');
165         my $booksellerid = $query->param('booksellerid');
166         $basketno =~ /^\d+$/ and CloseBasket($basketno);
167         # if requested, create basket group, close it and attach the basket
168         if ($query->param('createbasketgroup')) {
169             my $branchcode;
170             if(C4::Context->userenv and C4::Context->userenv->{'branch'}
171               and C4::Context->userenv->{'branch'} ne "NO_LIBRARY_SET") {
172                 $branchcode = C4::Context->userenv->{'branch'};
173             }
174             my $basketgroupid = NewBasketgroup( { name => $basket->{basketname},
175                             booksellerid => $booksellerid,
176                             deliveryplace => $branchcode,
177                             billingplace => $branchcode,
178                             closed => 1,
179                             });
180             ModBasket( { basketno => $basketno,
181                          basketgroupid => $basketgroupid } );
182             print $query->redirect('/cgi-bin/koha/acqui/basketgroup.pl?booksellerid='.$booksellerid.'&closed=1');
183         } else {
184             print $query->redirect('/cgi-bin/koha/acqui/booksellers.pl?booksellerid=' . $booksellerid);
185         }
186         exit;
187     } else {
188     $template->param(
189         confirm_close   => "1",
190         booksellerid    => $booksellerid,
191         basketno        => $basket->{'basketno'},
192         basketname      => $basket->{'basketname'},
193         basketgroupname => $basket->{'basketname'},
194     );
195     }
196 } elsif ($op eq 'reopen') {
197     ReopenBasket($query->param('basketno'));
198     print $query->redirect('/cgi-bin/koha/acqui/basket.pl?basketno='.$basket->{'basketno'})
199 } elsif ( $op eq 'mod_users' ) {
200     my $basketusers_ids = $query->param('users_ids');
201     my @basketusers = split( /:/, $basketusers_ids );
202     ModBasketUsers($basketno, @basketusers);
203     print $query->redirect("/cgi-bin/koha/acqui/basket.pl?basketno=$basketno");
204     exit;
205 } elsif ( $op eq 'mod_branch' ) {
206     my $branch = $query->param('branch');
207     $branch = undef if(defined $branch and $branch eq '');
208     ModBasket({
209         basketno => $basket->{basketno},
210         branch   => $branch
211     });
212     print $query->redirect("/cgi-bin/koha/acqui/basket.pl?basketno=$basketno");
213     exit;
214 } else {
215     my @branches_loop;
216     # get librarian branch...
217     if ( C4::Context->preference("IndependentBranches") ) {
218         my $userenv = C4::Context->userenv;
219         unless ( C4::Context->IsSuperLibrarian() ) {
220             my $validtest = ( $basket->{creationdate} eq '' )
221               || ( $userenv->{branch} eq $basket->{branch} )
222               || ( $userenv->{branch} eq '' )
223               || ( $basket->{branch}  eq '' );
224             unless ($validtest) {
225                 print $query->redirect("../mainpage.pl");
226                 exit 1;
227             }
228         }
229         if (!defined $basket->{branch} or $basket->{branch} eq $userenv->{branch}) {
230             push @branches_loop, {
231                 branchcode => $userenv->{branch},
232                 branchname => $userenv->{branchname},
233                 selected => 1,
234             };
235         }
236     } else {
237         # get branches
238         my $branches = C4::Branch::GetBranches;
239         my @branchcodes = sort {
240             $branches->{$a}->{branchname} cmp $branches->{$b}->{branchname}
241         } keys %$branches;
242         foreach my $branch (@branchcodes) {
243             my $selected = 0;
244             if (defined $basket->{branch}) {
245                 $selected = 1 if $branch eq $basket->{branch};
246             } else {
247                 $selected = 1 if $branch eq C4::Context->userenv->{branch};
248             }
249             push @branches_loop, {
250                 branchcode => $branch,
251                 branchname => $branches->{$branch}->{branchname},
252                 selected => $selected
253             };
254         }
255     }
256
257 #if the basket is closed,and the user has the permission to edit basketgroups, display a list of basketgroups
258     my ($basketgroup, $basketgroups);
259     my $staffuser = GetMember(borrowernumber => $loggedinuser);
260     if ($basket->{closedate} && haspermission($staffuser->{userid}, { acquisition => 'group_manage'} )) {
261         $basketgroups = GetBasketgroups($basket->{booksellerid});
262         for my $bg ( @{$basketgroups} ) {
263             if ($basket->{basketgroupid} && $basket->{basketgroupid} == $bg->{id}){
264                 $bg->{default} = 1;
265                 $basketgroup = $bg;
266             }
267         }
268     }
269
270     # if the basket is closed, calculate estimated delivery date
271     my $estimateddeliverydate;
272     if( $basket->{closedate} ) {
273         my ($year, $month, $day) = ($basket->{closedate} =~ /(\d+)-(\d+)-(\d+)/);
274         ($year, $month, $day) = Add_Delta_Days($year, $month, $day, $bookseller->{deliverytime});
275         $estimateddeliverydate = sprintf( "%04d-%02d-%02d", $year, $month, $day );
276     }
277
278     # if new basket, pre-fill infos
279     $basket->{creationdate} = ""            unless ( $basket->{creationdate} );
280     $basket->{authorisedby} = $loggedinuser unless ( $basket->{authorisedby} );
281     $debug
282       and warn sprintf
283       "loggedinuser: $loggedinuser; creationdate: %s; authorisedby: %s",
284       $basket->{creationdate}, $basket->{authorisedby};
285
286     my @basketusers_ids = GetBasketUsers($basketno);
287     my @basketusers;
288     foreach my $basketuser_id (@basketusers_ids) {
289         my $basketuser = GetMember(borrowernumber => $basketuser_id);
290         push @basketusers, $basketuser if $basketuser;
291     }
292
293     my $active_currency = Koha::Acquisition::Currencies->get_active;
294
295     my @orders = GetOrders( $basketno );
296     my @books_loop;
297
298     my @book_foot_loop;
299     my %foot;
300     my $total_quantity = 0;
301     my $total_gste = 0;
302     my $total_gsti = 0;
303     my $total_gstvalue = 0;
304     for my $order (@orders) {
305         $order = C4::Acquisition::populate_order_with_prices({ order => $order, booksellerid => $booksellerid, ordering => 1 });
306         my $line = get_order_infos( $order, $bookseller);
307         if ( $line->{uncertainprice} ) {
308             $template->param( uncertainprices => 1 );
309         }
310
311         push @books_loop, $line;
312
313         $foot{$$line{gstrate}}{gstrate} = $$line{gstrate};
314         $foot{$$line{gstrate}}{gstvalue} += $$line{gstvalue};
315         $total_gstvalue += $$line{gstvalue};
316         $foot{$$line{gstrate}}{quantity}  += $$line{quantity};
317         $total_quantity += $$line{quantity};
318         $foot{$$line{gstrate}}{totalgste} += $$line{totalgste};
319         $total_gste += $$line{totalgste};
320         $foot{$$line{gstrate}}{totalgsti} += $$line{totalgsti};
321         $total_gsti += $$line{totalgsti};
322     }
323
324     push @book_foot_loop, map {$_} values %foot;
325
326     # Get cancelled orders
327     my @cancelledorders = GetOrders($basketno, { cancelled => 1 });
328     my @cancelledorders_loop;
329     for my $order (@cancelledorders) {
330         $order = C4::Acquisition::populate_order_with_prices({ order => $order, booksellerid => $booksellerid, ordering => 1 });
331         my $line = get_order_infos( $order, $bookseller);
332         push @cancelledorders_loop, $line;
333     }
334
335     my $contract = GetContract({
336         contractnumber => $basket->{contractnumber}
337     });
338
339     if ($basket->{basketgroupid}){
340         $basketgroup = GetBasketgroup($basket->{basketgroupid});
341         $basketgroup->{deliveryplacename} = C4::Branch::GetBranchName( $basketgroup->{deliveryplace} );
342         $basketgroup->{billingplacename} = C4::Branch::GetBranchName( $basketgroup->{billingplace} );
343     }
344     my $borrower= GetMember('borrowernumber' => $loggedinuser);
345     my $budgets = GetBudgetHierarchy;
346     my $has_budgets = 0;
347     foreach my $r (@{$budgets}) {
348         if (!defined $r->{budget_amount} || $r->{budget_amount} == 0) {
349             next;
350         }
351         next unless (CanUserUseBudget($loggedinuser, $r, $userflags));
352
353         $has_budgets = 1;
354         last;
355     }
356
357     $template->param(
358         basketno             => $basketno,
359         basketname           => $basket->{'basketname'},
360         basketbranchname     => C4::Branch::GetBranchName($basket->{branch}),
361         basketnote           => $basket->{note},
362         basketbooksellernote => $basket->{booksellernote},
363         basketcontractno     => $basket->{contractnumber},
364         basketcontractname   => $contract->{contractname},
365         branches_loop        => \@branches_loop,
366         creationdate         => $basket->{creationdate},
367         authorisedby         => $basket->{authorisedby},
368         authorisedbyname     => $basket->{authorisedbyname},
369         users_ids            => join(':', @basketusers_ids),
370         users                => \@basketusers,
371         closedate            => $basket->{closedate},
372         estimateddeliverydate=> $estimateddeliverydate,
373         deliveryplace        => C4::Branch::GetBranchName( $basket->{deliveryplace} ),
374         billingplace         => C4::Branch::GetBranchName( $basket->{billingplace} ),
375         active               => $bookseller->{'active'},
376         booksellerid         => $bookseller->{'id'},
377         name                 => $bookseller->{'name'},
378         books_loop           => \@books_loop,
379         book_foot_loop       => \@book_foot_loop,
380         cancelledorders_loop => \@cancelledorders_loop,
381         total_quantity       => $total_quantity,
382         total_gste           => sprintf( "%.2f", $total_gste ),
383         total_gsti           => sprintf( "%.2f", $total_gsti ),
384         total_gstvalue       => sprintf( "%.2f", $total_gstvalue ),
385         currency             => $active_currency->currency,
386         listincgst           => $bookseller->{listincgst},
387         basketgroups         => $basketgroups,
388         basketgroup          => $basketgroup,
389         grouped              => $basket->{basketgroupid},
390         unclosable           => @orders ? 0 : 1, 
391         has_budgets          => $has_budgets,
392         duplinbatch          => $duplinbatch,
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     }
419
420     my $biblionumber = $order->{'biblionumber'};
421     my $countbiblio = CountBiblioInOrders($biblionumber);
422     my $ordernumber = $order->{'ordernumber'};
423     my @subscriptions = GetSubscriptionsId ($biblionumber);
424     my $itemcount = GetItemsCount($biblionumber);
425     my $holds  = GetHolds ($biblionumber);
426     my @items = GetItemnumbersFromOrder( $ordernumber );
427     my $itemholds;
428     foreach my $item (@items){
429         my $nb = GetItemHolds($biblionumber, $item);
430         if ($nb){
431             $itemholds += $nb;
432         }
433     }
434     # 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
435     $line{can_del_bib}          = 1 if $countbiblio <= 1 && $itemcount == scalar @items && !(@subscriptions) && !($holds);
436     $line{items}                = ($itemcount) - (scalar @items);
437     $line{left_item}            = 1 if $line{items} >= 1;
438     $line{left_biblio}          = 1 if $countbiblio > 1;
439     $line{biblios}              = $countbiblio - 1;
440     $line{left_subscription}    = 1 if scalar @subscriptions >= 1;
441     $line{subscriptions}        = scalar @subscriptions;
442     ($holds >= 1) ? $line{left_holds} = 1 : $line{left_holds} = 0;
443     $line{left_holds_on_order}  = 1 if $line{left_holds}==1 && ($line{items} == 0 || $itemholds );
444     $line{holds}                = $holds;
445     $line{holds_on_order}       = $itemholds?$itemholds:$holds if $line{left_holds_on_order};
446
447
448     my $suggestion   = GetSuggestionInfoFromBiblionumber($line{biblionumber});
449     $line{suggestionid}         = $$suggestion{suggestionid};
450     $line{surnamesuggestedby}   = $$suggestion{surnamesuggestedby};
451     $line{firstnamesuggestedby} = $$suggestion{firstnamesuggestedby};
452
453     foreach my $key (qw(transferred_from transferred_to)) {
454         if ($line{$key}) {
455             my $order = GetOrder($line{$key});
456             my $basket = GetBasket($order->{basketno});
457             my $bookseller = Koha::Acquisition::Bookseller->fetch({ id => $basket->{booksellerid} });
458             $line{$key} = {
459                 order => $order,
460                 basket => $basket,
461                 bookseller => $bookseller,
462                 timestamp => $line{$key . '_timestamp'},
463             };
464         }
465     }
466
467     return \%line;
468 }
469
470 output_html_with_http_headers $query, $cookie, $template->output;