Bug 16225 - Extra closing quote in circulation home page template
[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         $basketgroup->{deliveryplacename} = C4::Branch::GetBranchName( $basketgroup->{deliveryplace} );
352         $basketgroup->{billingplacename} = C4::Branch::GetBranchName( $basketgroup->{billingplace} );
353     }
354     my $borrower= GetMember('borrowernumber' => $loggedinuser);
355     my $budgets = GetBudgetHierarchy;
356     my $has_budgets = 0;
357     foreach my $r (@{$budgets}) {
358         if (!defined $r->{budget_amount} || $r->{budget_amount} == 0) {
359             next;
360         }
361         next unless (CanUserUseBudget($loggedinuser, $r, $userflags));
362
363         $has_budgets = 1;
364         last;
365     }
366
367     $template->param(
368         basketno             => $basketno,
369         basketname           => $basket->{'basketname'},
370         basketbranchname     => C4::Branch::GetBranchName($basket->{branch}),
371         basketnote           => $basket->{note},
372         basketbooksellernote => $basket->{booksellernote},
373         basketcontractno     => $basket->{contractnumber},
374         basketcontractname   => $contract->{contractname},
375         branches_loop        => \@branches_loop,
376         creationdate         => $basket->{creationdate},
377         authorisedby         => $basket->{authorisedby},
378         authorisedbyname     => $basket->{authorisedbyname},
379         users_ids            => join(':', @basketusers_ids),
380         users                => \@basketusers,
381         closedate            => $basket->{closedate},
382         estimateddeliverydate=> $estimateddeliverydate,
383         deliveryplace        => C4::Branch::GetBranchName( $basket->{deliveryplace} ),
384         billingplace         => C4::Branch::GetBranchName( $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         unclosable           => @orders ? 0 : 1, 
401         has_budgets          => $has_budgets,
402         duplinbatch          => $duplinbatch,
403     );
404 }
405
406 sub get_order_infos {
407     my $order = shift;
408     my $bookseller = shift;
409     my $qty = $order->{'quantity'} || 0;
410     if ( !defined $order->{quantityreceived} ) {
411         $order->{quantityreceived} = 0;
412     }
413     my $budget = GetBudget( $order->{'budget_id'} );
414
415     my %line = %{ $order };
416     $line{order_received} = ( $qty == $order->{'quantityreceived'} );
417     $line{basketno}       = $basketno;
418     $line{budget_name}    = $budget->{budget_name};
419
420     if ( $line{uncertainprice} ) {
421         $line{rrpgste} .= ' (Uncertain)';
422     }
423     if ( $line{'title'} ) {
424         my $volume      = $order->{'volume'};
425         my $seriestitle = $order->{'seriestitle'};
426         $line{'title'} .= " / $seriestitle" if $seriestitle;
427         $line{'title'} .= " / $volume"      if $volume;
428     }
429
430     my $biblionumber = $order->{'biblionumber'};
431     my $countbiblio = CountBiblioInOrders($biblionumber);
432     my $ordernumber = $order->{'ordernumber'};
433     my @subscriptions = GetSubscriptionsId ($biblionumber);
434     my $itemcount = GetItemsCount($biblionumber);
435     my $holds  = GetHolds ($biblionumber);
436     my @items = GetItemnumbersFromOrder( $ordernumber );
437     my $itemholds;
438     foreach my $item (@items){
439         my $nb = GetItemHolds($biblionumber, $item);
440         if ($nb){
441             $itemholds += $nb;
442         }
443     }
444     # 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
445     $line{can_del_bib}          = 1 if $countbiblio <= 1 && $itemcount == scalar @items && !(@subscriptions) && !($holds);
446     $line{items}                = ($itemcount) - (scalar @items);
447     $line{left_item}            = 1 if $line{items} >= 1;
448     $line{left_biblio}          = 1 if $countbiblio > 1;
449     $line{biblios}              = $countbiblio - 1;
450     $line{left_subscription}    = 1 if scalar @subscriptions >= 1;
451     $line{subscriptions}        = scalar @subscriptions;
452     ($holds >= 1) ? $line{left_holds} = 1 : $line{left_holds} = 0;
453     $line{left_holds_on_order}  = 1 if $line{left_holds}==1 && ($line{items} == 0 || $itemholds );
454     $line{holds}                = $holds;
455     $line{holds_on_order}       = $itemholds?$itemholds:$holds if $line{left_holds_on_order};
456
457
458     my $suggestion   = GetSuggestionInfoFromBiblionumber($line{biblionumber});
459     $line{suggestionid}         = $$suggestion{suggestionid};
460     $line{surnamesuggestedby}   = $$suggestion{surnamesuggestedby};
461     $line{firstnamesuggestedby} = $$suggestion{firstnamesuggestedby};
462
463     foreach my $key (qw(transferred_from transferred_to)) {
464         if ($line{$key}) {
465             my $order = GetOrder($line{$key});
466             my $basket = GetBasket($order->{basketno});
467             my $bookseller = Koha::Acquisition::Bookseller->fetch({ id => $basket->{booksellerid} });
468             $line{$key} = {
469                 order => $order,
470                 basket => $basket,
471                 bookseller => $bookseller,
472                 timestamp => $line{$key . '_timestamp'},
473             };
474         }
475     }
476
477     return \%line;
478 }
479
480 output_html_with_http_headers $query, $cookie, $template->output;
481
482
483 sub edi_close_and_order {
484     my $confirm = $query->param('confirm') || $confirm_pref eq '2';
485     if ($confirm) {
486             my $edi_params = {
487                 basketno => $basketno,
488                 ean    => $ean,
489             };
490             if ( $basket->{branch} ) {
491                 $edi_params->{branchcode} = $basket->{branch};
492             }
493             if ( create_edi_order($edi_params) ) {
494                 #$template->param( edifile => 1 );
495             }
496         CloseBasket($basketno);
497
498         # if requested, create basket group, close it and attach the basket
499         if ( $query->param('createbasketgroup') ) {
500             my $branchcode;
501             if (    C4::Context->userenv
502                 and C4::Context->userenv->{'branch'}
503                 and C4::Context->userenv->{'branch'} ne "NO_LIBRARY_SET" )
504             {
505                 $branchcode = C4::Context->userenv->{'branch'};
506             }
507             my $basketgroupid = NewBasketgroup(
508                 {
509                     name          => $basket->{basketname},
510                     booksellerid  => $booksellerid,
511                     deliveryplace => $branchcode,
512                     billingplace  => $branchcode,
513                     closed        => 1,
514                 }
515             );
516             ModBasket(
517                 {
518                     basketno      => $basketno,
519                     basketgroupid => $basketgroupid
520                 }
521             );
522             print $query->redirect(
523 "/cgi-bin/koha/acqui/basketgroup.pl?booksellerid=$booksellerid&closed=1"
524             );
525         }
526         else {
527             print $query->redirect(
528                 "/cgi-bin/koha/acqui/booksellers.pl?booksellerid=$booksellerid"
529             );
530         }
531         exit;
532     }
533     else {
534         $template->param(
535             edi_confirm     => 1,
536             booksellerid    => $booksellerid,
537             basketno        => $basket->{basketno},
538             basketname      => $basket->{basketname},
539             basketgroupname => $basket->{basketname},
540         );
541         if ($ean) {
542             $template->param( ean => $ean );
543         }
544
545     }
546     return;
547 }