Bug 7583: Cancel a receipt
[koha.git] / acqui / parcel.pl
1 #!/usr/bin/perl
2
3 #script to recieve orders
4
5
6 # Copyright 2000-2002 Katipo Communications
7 # Copyright 2008-2009 BibLibre SARL
8 #
9 # This file is part of Koha.
10 #
11 # Koha is free software; you can redistribute it and/or modify it under the
12 # terms of the GNU General Public License as published by the Free Software
13 # Foundation; either version 2 of the License, or (at your option) any later
14 # version.
15 #
16 # Koha is distributed in the hope that it will be useful, but WITHOUT ANY
17 # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
18 # A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
19 #
20 # You should have received a copy of the GNU General Public License along
21 # with Koha; if not, write to the Free Software Foundation, Inc.,
22 # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
23
24 =head1 NAME
25
26 parcel.pl
27
28 =head1 DESCRIPTION
29
30 This script shows all orders receipt or pending for a given supplier.
31 It allows to write an order as 'received' when he arrives.
32
33 =head1 CGI PARAMETERS
34
35 =over 4
36
37 =item booksellerid
38
39 To know the supplier this script has to show orders.
40
41 =item code
42
43 is the bookseller invoice number.
44
45 =item freight
46
47
48 =item gst
49
50
51 =item datereceived
52
53 To filter the results list on this given date.
54
55 =back
56
57 =cut
58
59 use strict;
60 #use warnings; FIXME - Bug 2505
61 use C4::Auth;
62 use C4::Acquisition;
63 use C4::Budgets;
64 use C4::Bookseller qw/ GetBookSellerFromId /;
65 use C4::Biblio;
66 use C4::Items;
67 use CGI;
68 use C4::Output;
69 use C4::Dates qw/format_date format_date_in_iso/;
70 use C4::Suggestions;
71 use JSON;
72
73 my $input=new CGI;
74 my $booksellerid=$input->param('booksellerid');
75 my $bookseller=GetBookSellerFromId($booksellerid);
76
77 my $invoice=$input->param('invoice') || '';
78 my $freight=$input->param('freight');
79 my $input_gst = ($input->param('gst') eq '' ? undef : $input->param('gst'));
80 my $gst= $input_gst // $bookseller->{gstrate} // C4::Context->preference("gist") // 0;
81 my $op = $input->param('op') // '';
82 my $datereceived = ( $op eq ('new' or 'search' ) )
83     ? C4::Dates->new($input->param('datereceived'))
84     :  C4::Dates->new($input->param('datereceived'), 'iso');
85 $datereceived = C4::Dates->new() unless $datereceived;
86 my $code            = $input->param('code');
87 my @rcv_err         = $input->param('error');
88 my @rcv_err_barcode = $input->param('error_bc');
89 my $startfrom=$input->param('startfrom');
90 my $resultsperpage = $input->param('resultsperpage');
91 $resultsperpage = 20 unless ($resultsperpage);
92 $startfrom=0 unless ($startfrom);
93
94 my ($template, $loggedinuser, $cookie)
95     = get_template_and_user({template_name => "acqui/parcel.tmpl",
96                  query => $input,
97                                  type => "intranet",
98                  authnotrequired => 0,
99                  flagsrequired => {acquisition => 'order_receive'},
100                  debug => 1,
101 });
102
103 if($op eq 'cancelreceipt') {
104     my $ordernumber = $input->param('ordernumber');
105     my $parent_ordernumber = CancelReceipt($ordernumber);
106     unless($parent_ordernumber) {
107         $template->param(error_cancelling_receipt => 1);
108     }
109 }
110
111 # If receiving error, report the error (coming from finishrecieve.pl(sic)).
112 if( scalar(@rcv_err) ) {
113         my $cnt=0;
114         my $error_loop;
115         for my $err (@rcv_err) {
116                 push @$error_loop, { "error_$err" => 1 , barcode => $rcv_err_barcode[$cnt] };
117                 $cnt++;
118         }
119         $template->param( receive_error => 1 ,
120                                                 error_loop => $error_loop,
121                                         );
122 }
123
124 my $cfstr         = "%.2f";                                                           # currency format string -- could get this from currency table.
125 my @parcelitems   = GetParcel($booksellerid, $invoice, $datereceived->output('iso'));
126 my $countlines    = scalar @parcelitems;
127 my $totalprice    = 0;
128 my $totalfreight  = 0;
129 my $totalquantity = 0;
130 my $total;
131 my $tototal;
132 my @loop_received = ();
133
134 for (my $i = 0 ; $i < $countlines ; $i++) {
135
136     #$total=($parcelitems[$i]->{'unitprice'} + $parcelitems[$i]->{'freight'}) * $parcelitems[$i]->{'quantityreceived'};   #weird, are the freight fees counted by book? (pierre)
137     $total = ($parcelitems[$i]->{'unitprice'}) * $parcelitems[$i]->{'quantityreceived'};    #weird, are the freight fees counted by book? (pierre)
138     $parcelitems[$i]->{'unitprice'} += 0;
139     my %line;
140     %line          = %{ $parcelitems[$i] };
141     $line{invoice} = $invoice;
142     $line{gst}     = $gst;
143     $line{total} = sprintf($cfstr, $total);
144     $line{booksellerid} = $booksellerid;
145     push @loop_received, \%line;
146     $totalprice += $parcelitems[$i]->{'unitprice'};
147     $line{unitprice} = sprintf($cfstr, $parcelitems[$i]->{'unitprice'});
148
149     my $suggestion   = GetSuggestionInfoFromBiblionumber($line{biblionumber});
150     $line{suggestionid}         = $suggestion->{suggestionid};
151     $line{surnamesuggestedby}   = $suggestion->{surnamesuggestedby};
152     $line{firstnamesuggestedby} = $suggestion->{firstnamesuggestedby};
153
154     #double FIXME - totalfreight is redefined later.
155
156 # FIXME - each order in a  parcel holds the freight for the whole parcel. This means if you receive a parcel with items from multiple budgets, you'll see the freight charge in each budget..
157     if ($i > 0 && $totalfreight != $parcelitems[$i]->{'freight'}) {
158         warn "FREIGHT CHARGE MISMATCH!!";
159     }
160     $totalfreight = $parcelitems[$i]->{'freight'};
161     $totalquantity += $parcelitems[$i]->{'quantityreceived'};
162     $tototal       += $total;
163 }
164
165 # We get the pending orders either all or filtered
166 my $pendingorders;
167 if($input->param('op') eq "search"){
168     my $search   = $input->param('summaryfilter') || '';
169     my $ean      = $input->param('eanfilter') || '';
170     my $basketno = $input->param('basketfilter') || '';
171     my $orderno  = $input->param('orderfilter') || '';
172     my $grouped;
173     my $owner;
174     $pendingorders = GetPendingOrders($booksellerid,$grouped,$owner,$basketno,$orderno,$search,$ean);
175 }else{
176     $pendingorders = GetPendingOrders($booksellerid);
177 }
178 my $countpendings = scalar @$pendingorders;
179
180 # pending orders totals
181 my ($totalPunitprice, $totalPquantity, $totalPecost, $totalPqtyrcvd);
182 my $ordergrandtotal;
183 my @loop_orders = ();
184 for (my $i = 0 ; $i < $countpendings ; $i++) {
185     my %line;
186     %line = %{$pendingorders->[$i]};
187    
188     $line{quantity}+=0;
189     $line{quantityreceived}+=0;
190     $line{unitprice}+=0;
191     $totalPunitprice += $line{unitprice};
192     $totalPquantity +=$line{quantity};
193     $totalPqtyrcvd +=$line{quantityreceived};
194     $totalPecost += $line{ecost};
195     $line{ecost} = sprintf("%.2f",$line{ecost});
196     $line{ordertotal} = sprintf("%.2f",$line{ecost}*$line{quantity});
197     $line{unitprice} = sprintf("%.2f",$line{unitprice});
198     $line{invoice} = $invoice;
199     $line{gst} = $gst;
200     $line{total} = $total;
201     $line{booksellerid} = $booksellerid;
202     $ordergrandtotal += $line{ecost} * $line{quantity};
203     
204     my $biblionumber = $line{'biblionumber'};
205     my $countbiblio = CountBiblioInOrders($biblionumber);
206     my $ordernumber = $line{'ordernumber'};
207     my @subscriptions = GetSubscriptionsId ($biblionumber);
208     my $itemcount = GetItemsCount($biblionumber);
209     my $holds  = GetHolds ($biblionumber);
210     my @items = GetItemnumbersFromOrder( $ordernumber );
211     my $itemholds;
212     foreach my $item (@items){
213         my $nb = GetItemHolds($biblionumber, $item);
214         if ($nb){
215             $itemholds += $nb;
216         }
217     }
218
219     my $suggestion   = GetSuggestionInfoFromBiblionumber($line{biblionumber});
220     $line{suggestionid}         = $suggestion->{suggestionid};
221     $line{surnamesuggestedby}   = $suggestion->{surnamesuggestedby};
222     $line{firstnamesuggestedby} = $suggestion->{firstnamesuggestedby};
223
224     # 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
225     $line{can_del_bib}          = 1 if $countbiblio <= 1 && $itemcount == scalar @items && !(@subscriptions) && !($holds);
226     $line{items}                = ($itemcount) - (scalar @items);
227     $line{left_item}            = 1 if $line{items} >= 1;
228     $line{left_biblio}          = 1 if $countbiblio > 1;
229     $line{biblios}              = $countbiblio - 1;
230     $line{left_subscription}    = 1 if scalar @subscriptions >= 1;
231     $line{subscriptions}        = scalar @subscriptions;
232     $line{left_holds}           = 1 if $holds >= 1;
233     $line{left_holds_on_order}  = 1 if $line{left_holds} == 1 && ($line{items} == 0 || $itemholds );
234     $line{holds}                = $holds;
235     $line{holds_on_order}       = $itemholds?$itemholds:$holds if $line{left_holds_on_order};
236     
237     
238     push @loop_orders, \%line if ($i >= $startfrom and $i < $startfrom + $resultsperpage);
239 }
240 $freight = $totalfreight unless $freight;
241 my $count = $countpendings;
242
243 if ($count>$resultsperpage){
244     my $displaynext=0;
245     my $displayprev=$startfrom;
246     if(($count - ($startfrom+$resultsperpage)) > 0 ) {
247         $displaynext = 1;
248     }
249
250     my @numbers = ();
251     for (my $i=1; $i<$count/$resultsperpage+1; $i++) {
252             my $highlight=0;
253             ($startfrom/$resultsperpage==($i-1)) && ($highlight=1);
254             push @numbers, { number => $i,
255                 highlight => $highlight ,
256                 startfrom => ($i-1)*$resultsperpage};
257     }
258
259     my $from = $startfrom*$resultsperpage+1;
260     my $to;
261     if($count < (($startfrom+1)*$resultsperpage)){
262         $to = $count;
263     } else {
264         $to = (($startfrom+1)*$resultsperpage);
265     }
266     $template->param(numbers=>\@numbers,
267                      displaynext=>$displaynext,
268                      displayprev=>$displayprev,
269                      nextstartfrom=>(($startfrom+$resultsperpage<$count)?$startfrom+$resultsperpage:$count),
270                      prevstartfrom=>(($startfrom-$resultsperpage>0)?$startfrom-$resultsperpage:0)
271                     );
272 }
273
274 #$totalfreight=$freight;
275 $tototal = $tototal + $freight;
276
277 $template->param(
278     invoice               => $invoice,
279     datereceived          => $datereceived->output('iso'),
280     invoicedatereceived   => $datereceived->output('iso'),
281     formatteddatereceived => $datereceived->output(),
282     name                  => $bookseller->{'name'},
283     booksellerid            => $booksellerid,
284     gst                   => $gst,
285     freight               => $freight,
286     invoice               => $invoice,
287     countreceived         => $countlines,
288     loop_received         => \@loop_received,
289     countpending          => $countpendings,
290     loop_orders           => \@loop_orders,
291     totalprice            => sprintf($cfstr, $totalprice),
292     totalfreight          => $totalfreight,
293     totalquantity         => $totalquantity,
294     tototal               => sprintf($cfstr, $tototal),
295     ordergrandtotal       => sprintf($cfstr, $ordergrandtotal),
296     gst                   => $gst,
297     grandtot              => sprintf($cfstr, $tototal + $gst),
298     totalPunitprice       => sprintf("%.2f", $totalPunitprice),
299     totalPquantity        => $totalPquantity,
300     totalPqtyrcvd         => $totalPqtyrcvd,
301     totalPecost           => sprintf("%.2f", $totalPecost),
302     resultsperpage        => $resultsperpage,
303     (uc(C4::Context->preference("marcflavour"))) => 1
304 );
305 output_html_with_http_headers $input, $cookie, $template->output;
306