ffzg/recall_notices.pl: added --interval and --dedup
[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 it 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 Modern::Perl;
58
59 use C4::Auth;
60 use C4::Acquisition;
61 use C4::Budgets;
62 use C4::Biblio;
63 use C4::Items;
64 use CGI qw ( -utf8 );
65 use C4::Output;
66 use C4::Suggestions;
67
68 use Koha::Acquisition::Baskets;
69 use Koha::Acquisition::Bookseller;
70 use Koha::Acquisition::Orders;
71 use Koha::Biblios;
72 use Koha::DateUtils;
73 use Koha::Biblios;
74
75 use JSON;
76
77 my $input=new CGI;
78 my $sticky_filters = $input->param('sticky_filters') || 0;
79
80 my ($template, $loggedinuser, $cookie)
81     = get_template_and_user({template_name => "acqui/parcel.tt",
82                  query => $input,
83                  type => "intranet",
84                  authnotrequired => 0,
85                  flagsrequired => {acquisition => 'order_receive'},
86                  debug => 1,
87 });
88
89 my $op = $input->param('op') // '';
90
91 # process cancellation first so that list of
92 # orders to display is calculated after
93 if ($op eq 'cancelreceipt') {
94     my $ordernumber = $input->param('ordernumber');
95     my $parent_ordernumber = CancelReceipt($ordernumber);
96     unless($parent_ordernumber) {
97         $template->param(error_cancelling_receipt => 1);
98     }
99 }
100
101 my $invoiceid = $input->param('invoiceid');
102 my $invoice;
103 $invoice = GetInvoiceDetails($invoiceid) if $invoiceid;
104
105 unless( $invoiceid and $invoice->{invoiceid} ) {
106     $template->param(
107         error_invoice_not_known => 1,
108         no_orders_to_display    => 1
109     );
110     output_html_with_http_headers $input, $cookie, $template->output;
111     exit;
112 }
113
114 my $booksellerid = $invoice->{booksellerid};
115 my $bookseller = Koha::Acquisition::Booksellers->find( $booksellerid );
116
117 my @orders        = @{ $invoice->{orders} };
118 my $countlines    = scalar @orders;
119 my @loop_received = ();
120 my @book_foot_loop;
121 my %foot;
122 my $total_tax_excluded = 0;
123 my $total_tax_included = 0;
124
125 my $subtotal_for_funds;
126 for my $order ( @orders ) {
127     $order->{'unitprice'} += 0;
128     $order->{'booksellerid'} = $booksellerid; # required for basket group links
129
130     my $order_object = Koha::Acquisition::Orders->find($order->{ordernumber});
131     if ( $bookseller->invoiceincgst ) {
132         $order->{ecost}     = $order->{ecost_tax_included};
133         $order->{unitprice} = $order->{unitprice_tax_included};
134     }
135     else {
136         $order->{ecost}     = $order->{ecost_tax_excluded};
137         $order->{unitprice} = $order->{unitprice_tax_excluded};
138     }
139
140     $order->{total} = get_rounded_price($order->{unitprice}) * $order->{quantity};
141
142     my %line = %{ $order };
143     $line{invoice} = $invoice->{invoicenumber};
144     my @itemnumbers = $order_object->items->get_column('itemnumber');
145     my $biblio = Koha::Biblios->find( $line{biblionumber} );
146     $line{total_holds} = $biblio ? $biblio->holds->count : 0;
147     $line{item_holds} = $biblio ? $biblio->current_holds->search(
148         {
149             itemnumber => { -in => \@itemnumbers },
150         }
151     )->count : 0;
152     $line{budget} = GetBudgetByOrderNumber( $line{ordernumber} );
153
154     $line{tax_value} = $line{tax_value_on_receiving};
155     $line{tax_rate} = $line{tax_rate_on_receiving};
156     $foot{$line{tax_rate}}{tax_rate} = $line{tax_rate};
157     $foot{$line{tax_rate}}{tax_value} += $line{tax_value};
158     $total_tax_excluded += get_rounded_price($line{unitprice_tax_excluded}) * $line{quantity};
159     $total_tax_included += get_rounded_price($line{unitprice_tax_included}) * $line{quantity};
160
161     my $suggestion   = GetSuggestionInfoFromBiblionumber($line{biblionumber});
162     $line{suggestionid}         = $suggestion->{suggestionid};
163     $line{surnamesuggestedby}   = $suggestion->{surnamesuggestedby};
164     $line{firstnamesuggestedby} = $suggestion->{firstnamesuggestedby};
165
166     if ( $line{parent_ordernumber} != $line{ordernumber} ) {
167         if ( grep { $_->{ordernumber} == $line{parent_ordernumber} }
168             @orders
169             )
170         {
171             $line{cannot_cancel} = 1;
172         }
173     }
174
175     my $budget_name = GetBudgetName( $line{budget_id} );
176     $line{budget_name} = $budget_name;
177
178     $subtotal_for_funds->{ $line{budget_name} }{ecost} += get_rounded_price($order->{ecost}) * $order->{quantity};
179     $subtotal_for_funds->{ $line{budget_name} }{unitprice} += $order->{total};
180
181     push @loop_received, \%line;
182 }
183 push @book_foot_loop, map { $_ } values %foot;
184
185 my @loop_orders = ();
186 unless( defined $invoice->{closedate} ) {
187     my $pendingorders;
188     if ( $op eq "search" or $sticky_filters ) {
189         my ( $search, $ean, $basketname, $orderno, $basketgroupname );
190         if ( $sticky_filters ) {
191             $search = $input->cookie("filter_parcel_summary");
192             $ean = $input->cookie("filter_parcel_ean");
193             $basketname = $input->cookie("filter_parcel_basketname");
194             $orderno = $input->cookie("filter_parcel_orderno");
195             $basketgroupname = $input->cookie("filter_parcel_basketgroupname");
196         } else {
197             $search   = $input->param('summaryfilter') || '';
198             $ean      = $input->param('eanfilter') || '';
199             $basketname = $input->param('basketfilter') || '';
200             $orderno  = $input->param('orderfilter') || '';
201             $basketgroupname = $input->param('basketgroupnamefilter') || '';
202         }
203         $pendingorders = SearchOrders({
204             booksellerid => $booksellerid,
205             basketname => $basketname,
206             ordernumber => $orderno,
207             search => $search,
208             ean => $ean,
209             basketgroupname => $basketgroupname,
210             pending => 1,
211             ordered => 1,
212         });
213         $template->param(
214             summaryfilter => $search,
215             eanfilter => $ean,
216             basketfilter => $basketname,
217             orderfilter => $orderno,
218             basketgroupnamefilter => $basketgroupname,
219         );
220     }else{
221         $pendingorders = SearchOrders({
222             booksellerid => $booksellerid,
223             ordered => 1
224         });
225     }
226     my $countpendings = scalar @$pendingorders;
227
228     for (my $i = 0 ; $i < $countpendings ; $i++) {
229         my $order = $pendingorders->[$i];
230
231         if ( $bookseller->invoiceincgst ) {
232             $order->{ecost} = $order->{ecost_tax_included};
233         } else {
234             $order->{ecost} = $order->{ecost_tax_excluded};
235         }
236         $order->{total} = get_rounded_price($order->{ecost}) * $order->{quantity};
237
238         my %line = %$order;
239
240         $line{invoice} = $invoice;
241         $line{booksellerid} = $booksellerid;
242
243         my $biblionumber = $line{'biblionumber'};
244         my $biblio = Koha::Biblios->find( $biblionumber );
245                 if ( ! $biblio ) {
246                         use Data::Dump qw(dump);
247                         warn "FATAL ERROR: biblionumber $biblionumber not found in line: ",dump( \%line );
248                 }
249         my $countbiblio = CountBiblioInOrders($biblionumber);
250         my $ordernumber = $line{'ordernumber'};
251         my $order_object = Koha::Acquisition::Orders->find($ordernumber);
252         my $cnt_subscriptions = $biblio ? $biblio->subscriptions->count: 0;
253         my $itemcount   = $biblio ? $biblio->items->count : 0;
254         my $holds_count = $biblio ? $biblio->holds->count : 0;
255         my @itemnumbers = $order_object->items->get_column('itemnumber');
256         my $itemholds = $biblio ? $biblio->holds->search({ itemnumber => { -in => \@itemnumbers } })->count : 0;
257
258         my $suggestion   = GetSuggestionInfoFromBiblionumber($line{biblionumber});
259         $line{suggestionid}         = $suggestion->{suggestionid};
260         $line{surnamesuggestedby}   = $suggestion->{surnamesuggestedby};
261         $line{firstnamesuggestedby} = $suggestion->{firstnamesuggestedby};
262
263         # 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
264         $line{can_del_bib}          = 1 if $countbiblio <= 1 && $itemcount == scalar @itemnumbers && !($cnt_subscriptions) && !($holds_count);
265         $line{items}                = ($itemcount) - (scalar @itemnumbers);
266         $line{left_item}            = 1 if $line{items} >= 1;
267         $line{left_biblio}          = 1 if $countbiblio > 1;
268         $line{biblios}              = $countbiblio - 1;
269         $line{left_subscription}    = 1 if $cnt_subscriptions;
270         $line{subscriptions}        = $cnt_subscriptions;
271         $line{left_holds}           = ($holds_count >= 1) ? 1 : 0;
272         $line{left_holds_on_order}  = 1 if $line{left_holds}==1 && ($line{items} == 0 || $itemholds );
273         $line{holds}                = $holds_count;
274         $line{holds_on_order}       = $itemholds?$itemholds:$holds_count if $line{left_holds_on_order};
275         $line{basket}               = Koha::Acquisition::Baskets->find( $line{basketno} );
276
277         my $budget_name = GetBudgetName( $line{budget_id} );
278         $line{budget_name} = $budget_name;
279
280         push @loop_orders, \%line;
281     }
282
283     $template->param(
284         loop_orders  => \@loop_orders,
285     );
286 }
287
288 $template->param(
289     invoiceid             => $invoice->{invoiceid},
290     invoice               => $invoice->{invoicenumber},
291     invoiceclosedate      => $invoice->{closedate},
292     datereceived          => dt_from_string,
293     name                  => $bookseller->name,
294     booksellerid          => $bookseller->id,
295     loop_received         => \@loop_received,
296     loop_orders           => \@loop_orders,
297     book_foot_loop        => \@book_foot_loop,
298     (uc(C4::Context->preference("marcflavour"))) => 1,
299     total_tax_excluded    => $total_tax_excluded,
300     total_tax_included    => $total_tax_included,
301     subtotal_for_funds    => $subtotal_for_funds,
302     sticky_filters       => $sticky_filters,
303 );
304 output_html_with_http_headers $input, $cookie, $template->output;