Bug 15758: Koha::Libraries - Remove GetBranches
[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::Contract;
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 Koha::Libraries;
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
240         if (!defined $basket->{branch} or $basket->{branch} eq $userenv->{branch}) {
241             push @branches_loop, {
242                 branchcode => $userenv->{branch},
243                 branchname => $userenv->{branchname},
244                 selected => 1,
245             };
246         }
247     } else {
248         # get branches
249         my $branches = Koha::Libraries->search( {}, { order_by => ['branchname'] } )->unblessed;
250         foreach my $branch (@$branches) {
251             my $selected = 0;
252             if (defined $basket->{branch}) {
253                 $selected = 1 if $branch->{branchcode} eq $basket->{branch};
254             } else {
255                 $selected = 1 if $branch->{branchcode} eq C4::Context->userenv->{branch};
256             }
257             push @branches_loop, {
258                 branchcode => $branch->{branchcode},
259                 branchname => $branch->{branchname},
260                 selected => $selected
261             };
262         }
263     }
264
265 #if the basket is closed,and the user has the permission to edit basketgroups, display a list of basketgroups
266     my ($basketgroup, $basketgroups);
267     my $staffuser = GetMember(borrowernumber => $loggedinuser);
268     if ($basket->{closedate} && haspermission($staffuser->{userid}, { acquisition => 'group_manage'} )) {
269         $basketgroups = GetBasketgroups($basket->{booksellerid});
270         for my $bg ( @{$basketgroups} ) {
271             if ($basket->{basketgroupid} && $basket->{basketgroupid} == $bg->{id}){
272                 $bg->{default} = 1;
273                 $basketgroup = $bg;
274             }
275         }
276     }
277
278     # if the basket is closed, calculate estimated delivery date
279     my $estimateddeliverydate;
280     if( $basket->{closedate} ) {
281         my ($year, $month, $day) = ($basket->{closedate} =~ /(\d+)-(\d+)-(\d+)/);
282         ($year, $month, $day) = Add_Delta_Days($year, $month, $day, $bookseller->{deliverytime});
283         $estimateddeliverydate = sprintf( "%04d-%02d-%02d", $year, $month, $day );
284     }
285
286     # if new basket, pre-fill infos
287     $basket->{creationdate} = ""            unless ( $basket->{creationdate} );
288     $basket->{authorisedby} = $loggedinuser unless ( $basket->{authorisedby} );
289     $debug
290       and warn sprintf
291       "loggedinuser: $loggedinuser; creationdate: %s; authorisedby: %s",
292       $basket->{creationdate}, $basket->{authorisedby};
293
294     my @basketusers_ids = GetBasketUsers($basketno);
295     my @basketusers;
296     foreach my $basketuser_id (@basketusers_ids) {
297         my $basketuser = GetMember(borrowernumber => $basketuser_id);
298         push @basketusers, $basketuser if $basketuser;
299     }
300
301     my $active_currency = Koha::Acquisition::Currencies->get_active;
302
303     my @orders = GetOrders( $basketno );
304     my @books_loop;
305
306     my @book_foot_loop;
307     my %foot;
308     my $total_quantity = 0;
309     my $total_gste = 0;
310     my $total_gsti = 0;
311     my $total_gstvalue = 0;
312     for my $order (@orders) {
313         $order = C4::Acquisition::populate_order_with_prices({ order => $order, booksellerid => $booksellerid, ordering => 1 });
314         my $line = get_order_infos( $order, $bookseller);
315         if ( $line->{uncertainprice} ) {
316             $template->param( uncertainprices => 1 );
317         }
318
319         push @books_loop, $line;
320
321         $foot{$$line{gstrate}}{gstrate} = $$line{gstrate};
322         $foot{$$line{gstrate}}{gstvalue} += $$line{gstvalue};
323         $total_gstvalue += $$line{gstvalue};
324         $foot{$$line{gstrate}}{quantity}  += $$line{quantity};
325         $total_quantity += $$line{quantity};
326         $foot{$$line{gstrate}}{totalgste} += $$line{totalgste};
327         $total_gste += $$line{totalgste};
328         $foot{$$line{gstrate}}{totalgsti} += $$line{totalgsti};
329         $total_gsti += $$line{totalgsti};
330     }
331
332     push @book_foot_loop, map {$_} values %foot;
333
334     # Get cancelled orders
335     my @cancelledorders = GetOrders($basketno, { cancelled => 1 });
336     my @cancelledorders_loop;
337     for my $order (@cancelledorders) {
338         $order = C4::Acquisition::populate_order_with_prices({ order => $order, booksellerid => $booksellerid, ordering => 1 });
339         my $line = get_order_infos( $order, $bookseller);
340         push @cancelledorders_loop, $line;
341     }
342
343     my $contract = GetContract({
344         contractnumber => $basket->{contractnumber}
345     });
346
347     if ($basket->{basketgroupid}){
348         $basketgroup = GetBasketgroup($basket->{basketgroupid});
349     }
350     my $borrower= GetMember('borrowernumber' => $loggedinuser);
351     my $budgets = GetBudgetHierarchy;
352     my $has_budgets = 0;
353     foreach my $r (@{$budgets}) {
354         if (!defined $r->{budget_amount} || $r->{budget_amount} == 0) {
355             next;
356         }
357         next unless (CanUserUseBudget($loggedinuser, $r, $userflags));
358
359         $has_budgets = 1;
360         last;
361     }
362
363     $template->param(
364         basketno             => $basketno,
365         basket               => $basket,
366         basketname           => $basket->{'basketname'},
367         basketbranchcode     => $basket->{branch},
368         basketnote           => $basket->{note},
369         basketbooksellernote => $basket->{booksellernote},
370         basketcontractno     => $basket->{contractnumber},
371         basketcontractname   => $contract->{contractname},
372         branches_loop        => \@branches_loop,
373         creationdate         => $basket->{creationdate},
374         authorisedby         => $basket->{authorisedby},
375         authorisedbyname     => $basket->{authorisedbyname},
376         users_ids            => join(':', @basketusers_ids),
377         users                => \@basketusers,
378         closedate            => $basket->{closedate},
379         estimateddeliverydate=> $estimateddeliverydate,
380         is_standing          => $basket->{is_standing},
381         deliveryplace        => $basket->{deliveryplace},
382         billingplace         => $basket->{billingplace},
383         active               => $bookseller->{'active'},
384         booksellerid         => $bookseller->{'id'},
385         name                 => $bookseller->{'name'},
386         books_loop           => \@books_loop,
387         book_foot_loop       => \@book_foot_loop,
388         cancelledorders_loop => \@cancelledorders_loop,
389         total_quantity       => $total_quantity,
390         total_gste           => sprintf( "%.2f", $total_gste ),
391         total_gsti           => sprintf( "%.2f", $total_gsti ),
392         total_gstvalue       => sprintf( "%.2f", $total_gstvalue ),
393         currency             => $active_currency->currency,
394         listincgst           => $bookseller->{listincgst},
395         basketgroups         => $basketgroups,
396         basketgroup          => $basketgroup,
397         grouped              => $basket->{basketgroupid},
398         # The double negatives and booleans here mean:
399         # "A basket cannot be closed if there are no orders in it or it's a standing order basket."
400         #
401         # (The template has another implicit restriction that the order cannot be closed if there
402         # are any orders with uncertain prices.)
403         unclosable           => @orders ? $basket->{is_standing} : 1,
404         has_budgets          => $has_budgets,
405         duplinbatch          => $duplinbatch,
406     );
407 }
408
409 sub get_order_infos {
410     my $order = shift;
411     my $bookseller = shift;
412     my $qty = $order->{'quantity'} || 0;
413     if ( !defined $order->{quantityreceived} ) {
414         $order->{quantityreceived} = 0;
415     }
416     my $budget = GetBudget($order->{budget_id});
417     my $basket = GetBasket($order->{basketno});
418
419     my %line = %{ $order };
420     # Don't show unreceived standing orders as received
421     $line{order_received} = ( $qty == $order->{'quantityreceived'} && ( $basket->{is_standing} ? $qty : 1 ) );
422     $line{basketno}       = $basketno;
423     $line{budget_name}    = $budget->{budget_name};
424
425     if ( $line{uncertainprice} ) {
426         $line{rrpgste} .= ' (Uncertain)';
427     }
428     if ( $line{'title'} ) {
429         my $volume      = $order->{'volume'};
430         my $seriestitle = $order->{'seriestitle'};
431         $line{'title'} .= " / $seriestitle" if $seriestitle;
432         $line{'title'} .= " / $volume"      if $volume;
433     }
434
435     my $biblionumber = $order->{'biblionumber'};
436     my $countbiblio = CountBiblioInOrders($biblionumber);
437     my $ordernumber = $order->{'ordernumber'};
438     my @subscriptions = GetSubscriptionsId ($biblionumber);
439     my $itemcount = GetItemsCount($biblionumber);
440     my $holds  = GetHolds ($biblionumber);
441     my @items = GetItemnumbersFromOrder( $ordernumber );
442     my $itemholds;
443     foreach my $item (@items){
444         my $nb = GetItemHolds($biblionumber, $item);
445         if ($nb){
446             $itemholds += $nb;
447         }
448     }
449     # 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
450     $line{can_del_bib}          = 1 if $countbiblio <= 1 && $itemcount == scalar @items && !(@subscriptions) && !($holds);
451     $line{items}                = ($itemcount) - (scalar @items);
452     $line{left_item}            = 1 if $line{items} >= 1;
453     $line{left_biblio}          = 1 if $countbiblio > 1;
454     $line{biblios}              = $countbiblio - 1;
455     $line{left_subscription}    = 1 if scalar @subscriptions >= 1;
456     $line{subscriptions}        = scalar @subscriptions;
457     ($holds >= 1) ? $line{left_holds} = 1 : $line{left_holds} = 0;
458     $line{left_holds_on_order}  = 1 if $line{left_holds}==1 && ($line{items} == 0 || $itemholds );
459     $line{holds}                = $holds;
460     $line{holds_on_order}       = $itemholds?$itemholds:$holds if $line{left_holds_on_order};
461
462
463     my $suggestion   = GetSuggestionInfoFromBiblionumber($line{biblionumber});
464     $line{suggestionid}         = $$suggestion{suggestionid};
465     $line{surnamesuggestedby}   = $$suggestion{surnamesuggestedby};
466     $line{firstnamesuggestedby} = $$suggestion{firstnamesuggestedby};
467
468     foreach my $key (qw(transferred_from transferred_to)) {
469         if ($line{$key}) {
470             my $order = GetOrder($line{$key});
471             my $bookseller = Koha::Acquisition::Bookseller->fetch({ id => $basket->{booksellerid} });
472             $line{$key} = {
473                 order => $order,
474                 basket => $basket,
475                 bookseller => $bookseller,
476                 timestamp => $line{$key . '_timestamp'},
477             };
478         }
479     }
480
481     return \%line;
482 }
483
484 output_html_with_http_headers $query, $cookie, $template->output;
485
486
487 sub edi_close_and_order {
488     my $confirm = $query->param('confirm') || $confirm_pref eq '2';
489     if ($confirm) {
490             my $edi_params = {
491                 basketno => $basketno,
492                 ean    => $ean,
493             };
494             if ( $basket->{branch} ) {
495                 $edi_params->{branchcode} = $basket->{branch};
496             }
497             if ( create_edi_order($edi_params) ) {
498                 #$template->param( edifile => 1 );
499             }
500         CloseBasket($basketno);
501
502         # if requested, create basket group, close it and attach the basket
503         if ( $query->param('createbasketgroup') ) {
504             my $branchcode;
505             if (    C4::Context->userenv
506                 and C4::Context->userenv->{'branch'}
507                 and C4::Context->userenv->{'branch'} ne "NO_LIBRARY_SET" )
508             {
509                 $branchcode = C4::Context->userenv->{'branch'};
510             }
511             my $basketgroupid = NewBasketgroup(
512                 {
513                     name          => $basket->{basketname},
514                     booksellerid  => $booksellerid,
515                     deliveryplace => $branchcode,
516                     billingplace  => $branchcode,
517                     closed        => 1,
518                 }
519             );
520             ModBasket(
521                 {
522                     basketno      => $basketno,
523                     basketgroupid => $basketgroupid
524                 }
525             );
526             print $query->redirect(
527 "/cgi-bin/koha/acqui/basketgroup.pl?booksellerid=$booksellerid&closed=1"
528             );
529         }
530         else {
531             print $query->redirect(
532                 "/cgi-bin/koha/acqui/booksellers.pl?booksellerid=$booksellerid"
533             );
534         }
535         exit;
536     }
537     else {
538         $template->param(
539             edi_confirm     => 1,
540             booksellerid    => $booksellerid,
541             basketno        => $basket->{basketno},
542             basketname      => $basket->{basketname},
543             basketgroupname => $basket->{basketname},
544         );
545         if ($ean) {
546             $template->param( ean => $ean );
547         }
548
549     }
550     return;
551 }