Bug 13323: Tax rate can change on receiving
[koha.git] / acqui / parcel.pl
1 #!/usr/bin/perl
2
3 #script to receive 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
12 # under the terms of the GNU General Public License as published by
13 # the Free Software Foundation; either version 3 of the License, or
14 # (at your option) any later version.
15 #
16 # Koha is distributed in the hope that it will be useful, but
17 # WITHOUT ANY WARRANTY; without even the implied warranty of
18 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 # GNU General Public License for more details.
20 #
21 # You should have received a copy of the GNU General Public License
22 # along with Koha; if not, see <http://www.gnu.org/licenses>.
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
46 =item gst
47
48
49 =item datereceived
50
51 To filter the results list on this given date.
52
53 =back
54
55 =cut
56
57 use strict;
58 use warnings;
59
60 use C4::Auth;
61 use C4::Acquisition;
62 use C4::Budgets;
63 use C4::Biblio;
64 use C4::Items;
65 use CGI qw ( -utf8 );
66 use C4::Output;
67 use C4::Suggestions;
68 use C4::Reserves qw/GetReservesFromBiblionumber/;
69
70 use Koha::Acquisition::Bookseller;
71 use Koha::DateUtils;
72
73 use JSON;
74
75 my $input=new CGI;
76 my $sticky_filters = $input->param('sticky_filters') || 0;
77
78 my ($template, $loggedinuser, $cookie)
79     = get_template_and_user({template_name => "acqui/parcel.tt",
80                  query => $input,
81                  type => "intranet",
82                  authnotrequired => 0,
83                  flagsrequired => {acquisition => 'order_receive'},
84                  debug => 1,
85 });
86
87 my $op = $input->param('op') // '';
88
89 # process cancellation first so that list of
90 # orders to display is calculated after
91 if ($op eq 'cancelreceipt') {
92     my $ordernumber = $input->param('ordernumber');
93     my $parent_ordernumber = CancelReceipt($ordernumber);
94     unless($parent_ordernumber) {
95         $template->param(error_cancelling_receipt => 1);
96     }
97 }
98
99 my $invoiceid = $input->param('invoiceid');
100 my $invoice;
101 $invoice = GetInvoiceDetails($invoiceid) if $invoiceid;
102
103 unless( $invoiceid and $invoice->{invoiceid} ) {
104     $template->param(
105         error_invoice_not_known => 1,
106         no_orders_to_display    => 1
107     );
108     output_html_with_http_headers $input, $cookie, $template->output;
109     exit;
110 }
111
112 my $booksellerid = $invoice->{booksellerid};
113 my $bookseller = Koha::Acquisition::Bookseller->fetch({ id => $booksellerid });
114
115 my @orders        = @{ $invoice->{orders} };
116 my $countlines    = scalar @orders;
117 my @loop_received = ();
118 my @book_foot_loop;
119 my %foot;
120 my $total_tax_excluded = 0;
121 my $total_tax_included = 0;
122
123 my $subtotal_for_funds;
124 for my $order ( @orders ) {
125     $order->{'unitprice'} += 0;
126
127     if ( $bookseller->{listincgst} and not $bookseller->{invoiceincgst} ) {
128         $order->{ecost}     = $order->{ecost_tax_excluded};
129         $order->{unitprice} = $order->{unitprice_tax_excluded};
130     }
131     elsif ( not $bookseller->{listinct} and $bookseller->{invoiceincgst} ) {
132         $order->{ecost}     = $order->{ecost_tax_included};
133         $order->{unitprice} = $order->{unitprice_tax_included};
134     } else {
135         $order->{ecost} = $order->{ecost_tax_excluded};
136         $order->{unitprice} = $order->{unitprice_tax_excluded};
137     }
138     $order->{total} = $order->{unitprice} * $order->{quantity};
139
140     my %line = %{ $order };
141     $line{invoice} = $invoice->{invoicenumber};
142     $line{holds} = 0;
143     my @itemnumbers = GetItemnumbersFromOrder( $order->{ordernumber} );
144     for my $itemnumber ( @itemnumbers ) {
145         my $holds = GetReservesFromBiblionumber({ biblionumber => $line{biblionumber}, itemnumber => $itemnumber });
146         $line{holds} += scalar( @$holds );
147     }
148     $line{budget} = GetBudgetByOrderNumber( $line{ordernumber} );
149
150     $line{tax_value} = $line{tax_value_on_receiving};
151     $line{tax_rate} = $line{tax_rate_on_receiving};
152     $foot{$line{tax_rate}}{tax_rate} = $line{tax_rate};
153     $foot{$line{tax_rate}}{tax_value} += $line{tax_value};
154     $total_tax_excluded += $line{unitprice_tax_excluded} * $line{quantity};
155     $total_tax_included += $line{unitprice_tax_included} * $line{quantity};
156
157     my $suggestion   = GetSuggestionInfoFromBiblionumber($line{biblionumber});
158     $line{suggestionid}         = $suggestion->{suggestionid};
159     $line{surnamesuggestedby}   = $suggestion->{surnamesuggestedby};
160     $line{firstnamesuggestedby} = $suggestion->{firstnamesuggestedby};
161
162     if ( $line{parent_ordernumber} != $line{ordernumber} ) {
163         if ( grep { $_->{ordernumber} == $line{parent_ordernumber} }
164             @orders
165             )
166         {
167             $line{cannot_cancel} = 1;
168         }
169     }
170
171     my $budget_name = GetBudgetName( $line{budget_id} );
172     $line{budget_name} = $budget_name;
173
174     $subtotal_for_funds->{ $line{budget_name} }{ecost} += $order->{ecost} * $order->{quantity};
175     $subtotal_for_funds->{ $line{budget_name} }{unitprice} += $order->{total};
176
177     push @loop_received, \%line;
178 }
179 push @book_foot_loop, map { $_ } values %foot;
180
181 my @loop_orders = ();
182 unless( defined $invoice->{closedate} ) {
183     my $pendingorders;
184     if ( $op eq "search" or $sticky_filters ) {
185         my ( $search, $ean, $basketname, $orderno, $basketgroupname );
186         if ( $sticky_filters ) {
187             $search = $input->cookie("filter_parcel_summary");
188             $ean = $input->cookie("filter_parcel_ean");
189             $basketname = $input->cookie("filter_parcel_basketname");
190             $orderno = $input->cookie("filter_parcel_orderno");
191             $basketgroupname = $input->cookie("filter_parcel_basketgroupname");
192         } else {
193             $search   = $input->param('summaryfilter') || '';
194             $ean      = $input->param('eanfilter') || '';
195             $basketname = $input->param('basketfilter') || '';
196             $orderno  = $input->param('orderfilter') || '';
197             $basketgroupname = $input->param('basketgroupnamefilter') || '';
198         }
199         $pendingorders = SearchOrders({
200             booksellerid => $booksellerid,
201             basketname => $basketname,
202             ordernumber => $orderno,
203             search => $search,
204             ean => $ean,
205             basketgroupname => $basketgroupname,
206             pending => 1,
207             ordered => 1,
208         });
209         $template->param(
210             summaryfilter => $search,
211             eanfilter => $ean,
212             basketfilter => $basketname,
213             orderfilter => $orderno,
214             basketgroupnamefilter => $basketgroupname,
215         );
216     }else{
217         $pendingorders = SearchOrders({
218             booksellerid => $booksellerid,
219             ordered => 1
220         });
221     }
222     my $countpendings = scalar @$pendingorders;
223
224     for (my $i = 0 ; $i < $countpendings ; $i++) {
225         my $order = $pendingorders->[$i];
226
227         if ( $bookseller->{listincgst} and not $bookseller->{invoiceincgst} ) {
228             $order->{ecost} = $order->{ecost_tax_excluded};
229         } elsif ( not $bookseller->{listinct} and $bookseller->{invoiceincgst} ) {
230             $order->{ecost} = $order->{ecost_tax_included};
231         } else {
232             $order->{ecost} = $order->{ecost_tax_excluded};
233         }
234         $order->{total} = $order->{ecost} * $order->{quantity};
235
236         my %line = %$order;
237
238         $line{invoice} = $invoice;
239         $line{booksellerid} = $booksellerid;
240
241         my $biblionumber = $line{'biblionumber'};
242         my $countbiblio = CountBiblioInOrders($biblionumber);
243         my $ordernumber = $line{'ordernumber'};
244         my @subscriptions = GetSubscriptionsId ($biblionumber);
245         my $itemcount = GetItemsCount($biblionumber);
246         my $holds  = GetHolds ($biblionumber);
247         my @items = GetItemnumbersFromOrder( $ordernumber );
248         my $itemholds;
249         foreach my $item (@items){
250             my $nb = GetItemHolds($biblionumber, $item);
251             if ($nb){
252                 $itemholds += $nb;
253             }
254         }
255
256         my $suggestion   = GetSuggestionInfoFromBiblionumber($line{biblionumber});
257         $line{suggestionid}         = $suggestion->{suggestionid};
258         $line{surnamesuggestedby}   = $suggestion->{surnamesuggestedby};
259         $line{firstnamesuggestedby} = $suggestion->{firstnamesuggestedby};
260
261         # 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
262         $line{can_del_bib}          = 1 if $countbiblio <= 1 && $itemcount == scalar @items && !(@subscriptions) && !($holds);
263         $line{items}                = ($itemcount) - (scalar @items);
264         $line{left_item}            = 1 if $line{items} >= 1;
265         $line{left_biblio}          = 1 if $countbiblio > 1;
266         $line{biblios}              = $countbiblio - 1;
267         $line{left_subscription}    = 1 if scalar @subscriptions >= 1;
268         $line{subscriptions}        = scalar @subscriptions;
269         $line{left_holds}           = ($holds >= 1) ? 1 : 0;
270         $line{left_holds_on_order}  = 1 if $line{left_holds}==1 && ($line{items} == 0 || $itemholds );
271         $line{holds}                = $holds;
272         $line{holds_on_order}       = $itemholds?$itemholds:$holds if $line{left_holds_on_order};
273
274         my $budget_name = GetBudgetName( $line{budget_id} );
275         $line{budget_name} = $budget_name;
276
277         push @loop_orders, \%line;
278     }
279
280     $template->param(
281         loop_orders  => \@loop_orders,
282     );
283 }
284
285 $template->param(
286     invoiceid             => $invoice->{invoiceid},
287     invoice               => $invoice->{invoicenumber},
288     invoiceclosedate      => $invoice->{closedate},
289     datereceived          => dt_from_string,
290     name                  => $bookseller->{'name'},
291     booksellerid          => $bookseller->{id},
292     loop_received         => \@loop_received,
293     loop_orders           => \@loop_orders,
294     book_foot_loop        => \@book_foot_loop,
295     (uc(C4::Context->preference("marcflavour"))) => 1,
296     total_tax_excluded    => $total_tax_excluded,
297     total_tax_included    => $total_tax_included,
298     subtotal_for_funds    => $subtotal_for_funds,
299     sticky_filters       => $sticky_filters,
300 );
301 output_html_with_http_headers $input, $cookie, $template->output;