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