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