3 #script to add an order into the system
4 #written 29/2/00 by chris@katipo.co.nz
6 # Copyright 2000-2002 Katipo Communications
8 # This file is part of Koha.
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.
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.
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>.
29 this script allows to add an order.
34 =item neworderempty.pl to add an order from an existing record or from nothing.
36 =item newordersuggestion.pl to add an order from an existing suggestion.
42 All of the cgi parameters below are related to the new order.
47 the number of this new order.
50 the number of this new basket
53 the bookseller the librarian has to pay.
58 the title of the record ordered.
61 the author of the record ordered.
63 =item C<copyrightdate>
64 the copyrightdate of the record ordered.
67 the ISBN of the record ordered.
72 the quantity to order.
75 the price of this order.
77 =item C<uncertainprice>
78 uncertain price, can't close basket until prices of all orders are known.
81 the branch where this order will be received.
89 budget_id used to pay this order.
91 =item C<sort1> & C<sort2>
106 the number of the invoice for this order.
108 =item C<publishercode>
110 =item C<suggestionid>
111 if it is an order from an existing suggestion : the id of this suggestion.
120 use CGI qw ( -utf8 );
121 use JSON qw ( to_json encode_json );
123 use C4::Acquisition qw( FillWithDefaultValues ModOrderUsers );
124 use C4::Auth qw( get_template_and_user );
126 use C4::Biblio qw( AddBiblio GetMarcFromKohaField TransformHtmlToXml TransformKohaToMarc );
127 use C4::Budgets qw( GetBudget GetBudgetSpent GetBudgetOrdered FieldsForCalculatingFundValues );
128 use C4::Items qw( AddItemFromMarc );
129 use C4::Log qw( logaction );
130 use C4::Output qw( output_html_with_http_headers );
131 use C4::Suggestions qw( ModSuggestion );
132 use Koha::Acquisition::Baskets;
133 use Koha::Acquisition::Currencies qw( get_active );
134 use Koha::Acquisition::Orders;
135 use Koha::AdditionalFields;
136 use Koha::DateUtils qw( dt_from_string );
138 ### "-------------------- addorder.pl ----------"
140 # FIXME: This needs to do actual error checking and possibly return user to the same form,
141 # not just blindly call C4 functions and print a redirect.
143 my $input = CGI->new;
145 my $op = $input->param('op') // q{};
147 if ( $op eq 'cud-order' ) {
148 my $use_ACQ_framework = $input->param('use_ACQ_framework');
150 # Check if order total amount exceed allowed budget
151 my $confirm_budget_exceeding = $input->param('confirm_budget_exceeding');
152 unless ($confirm_budget_exceeding) {
153 my $budget_id = $input->param('budget_id');
154 my $total = $input->param('total');
155 my $budget = GetBudget($budget_id);
156 my $budget_spent = GetBudgetSpent($budget_id);
157 my $budget_ordered = GetBudgetOrdered($budget_id);
159 my $ordernumber = $input->param('ordernumber');
162 # modifying an existing order so remove order price from $budget_ordered
163 my $order = Koha::Acquisition::Orders->find($ordernumber);
165 # get correct unitprice and ecost fields
166 my ( $unitprice_field, $ecost_field ) = FieldsForCalculatingFundValues();
167 $budget_ordered = $budget_ordered - ( $order->$ecost_field * $order->quantity );
170 my $budget_used = $budget_spent + $budget_ordered;
171 my $budget_remaining = $budget->{budget_amount} - $budget_used;
172 my $budget_encumbrance = $budget->{budget_amount} * $budget->{budget_encumb} / 100;
173 my $budget_expenditure = $budget->{budget_expend};
175 if ( $total > $budget_remaining
176 || ( ( $budget_encumbrance + 0 ) && ( $budget_used + $total ) > $budget_encumbrance )
177 || ( ( $budget_expenditure + 0 ) && ( $budget_used + $total ) > $budget_expenditure ) )
179 my ( $template, $loggedinuser, $cookie ) = get_template_and_user(
181 template_name => "acqui/addorder.tt",
184 flagsrequired => { acquisition => 'order_manage' },
188 my $url = $input->referer();
189 unless ( defined $url ) {
190 my $basketno = $input->param('basketno');
191 $url = "/cgi-bin/koha/acqui/basket.pl?basketno=$basketno";
194 my $vars = $input->Vars;
196 foreach ( keys %$vars ) {
199 values => [ $input->multi_param($_) ],
203 if ( ( $budget_encumbrance + 0 )
204 && ( $budget_used + $total ) > $budget_encumbrance
205 && $total <= $budget_remaining )
208 encumbrance_exceeded => 1,
209 encumbrance => sprintf( "%.2f", $budget->{'budget_encumb'} ),
212 if ( ( $budget_expenditure + 0 )
213 && ( $budget_used + $total ) > $budget_expenditure
214 && $total <= $budget_remaining )
216 my $currency = Koha::Acquisition::Currencies->get_active;
218 expenditure_exceeded => 1,
219 expenditure => sprintf( "%.2f", $budget_expenditure ),
220 currency => ($currency) ? $currency->symbol : '',
223 if ( $total > $budget_remaining ) {
224 $template->param( budget_exceeded => 1 );
228 not_enough_budget => 1,
230 vars_loop => \@vars_loop,
232 output_html_with_http_headers $input, $cookie, $template->output;
237 # get_template_and_user used only to check auth & get user id
238 my ( $template, $loggedinuser, $cookie ) = get_template_and_user(
240 template_name => "acqui/booksellers.tt",
243 flagsrequired => { acquisition => 'order_manage' },
249 ordernumber => scalar $input->param('ordernumber'),
250 basketno => scalar $input->param('basketno'),
251 biblionumber => scalar $input->param('biblionumber'),
252 invoiceid => scalar $input->param('invoiceid'),
253 quantity => scalar $input->param('quantity'),
254 budget_id => scalar $input->param('budget_id'),
255 currency => scalar $input->param('currency'),
256 listprice => scalar $input->param('listprice'),
257 uncertainprice => scalar $input->param('uncertainprice'),
258 tax_rate_on_ordering => scalar $input->param('tax_rate'),
259 discount => scalar $input->param('discount'),
260 rrp => scalar $input->param('rrp'),
261 replacementprice => scalar $input->param('replacementprice'),
262 ecost => scalar $input->param('ecost'),
263 unitprice => scalar $input->param('unitprice'),
264 order_internalnote => scalar $input->param('order_internalnote'),
265 order_vendornote => scalar $input->param('order_vendornote'),
266 sort1 => scalar $input->param('sort1'),
267 sort2 => scalar $input->param('sort2'),
268 subscriptionid => scalar $input->param('subscriptionid'),
269 estimated_delivery_date => scalar $input->param('estimated_delivery_date'),
272 $orderinfo->{uncertainprice} ||= 0;
273 $orderinfo->{subscriptionid} ||= undef;
275 my $user = $input->remote_user;
276 my $basketno = $$orderinfo{basketno};
277 my $basket = Koha::Acquisition::Baskets->find($basketno);
279 # Order related fields we're going to log
280 my @log_order_fields = (
284 'unitprice_tax_excluded',
285 'unitprice_tax_included',
291 'ecost_tax_excluded',
292 'ecost_tax_included',
293 'tax_rate_on_ordering'
296 # create, modify or delete biblio
297 # create if $quantity>0 and $existing='no'
298 # modify if $quantity>0 and $existing='yes'
299 if ( $basket->{is_standing} || $orderinfo->{quantity} ne '0' ) {
301 #TODO:check to see if biblio exists
302 unless ( $$orderinfo{biblionumber} ) {
305 if ($use_ACQ_framework) {
306 my @tags = $input->multi_param('bib_tag');
307 my @subfields = $input->multi_param('bib_subfield');
308 my @field_values = $input->multi_param('bib_field_value');
309 my $xml = TransformHtmlToXml( \@tags, \@subfields, \@field_values );
310 $record = MARC::Record::new_from_xml( $xml, 'UTF-8' );
313 #if it doesn't create it
314 $record = TransformKohaToMarc(
316 "biblio.title" => $input->param('title') || '',
317 "biblio.author" => $input->param('author') || '',
318 "biblio.seriestitle" => $input->param('series') || '',
319 "biblioitems.isbn" => $input->param('isbn') || '',
320 "biblioitems.ean" => $input->param('ean') || '',
321 "biblioitems.publishercode" => $input->param('publishercode') || '',
322 "biblioitems.publicationyear" => $input->param('publicationyear') || '',
323 "biblio.copyrightdate" => $input->param('publicationyear') || '',
324 "biblioitems.itemtype" => $input->param('itemtype') || '',
325 "biblioitems.editionstatement" => $input->param('editionstatement') || '',
329 C4::Acquisition::FillWithDefaultValues($record);
331 # create the record in catalogue, with framework ''
332 my ( $biblionumber, $bibitemnum ) = AddBiblio( $record, '' );
334 $orderinfo->{biblionumber} = $biblionumber;
337 # change suggestion status if applicable
338 if ( my $suggestionid = $input->param('suggestionid') ) {
341 suggestionid => $suggestionid,
342 biblionumber => $orderinfo->{biblionumber},
346 if ( C4::Context->preference('PlaceHoldsOnOrdersFromSuggestions') ) {
347 my $suggestion = Koha::Suggestions->find($suggestionid);
349 $suggestion->place_hold();
354 $orderinfo->{unitprice} = $orderinfo->{ecost}
355 if not defined $orderinfo->{unitprice}
356 or $orderinfo->{unitprice} eq '';
361 if ( $orderinfo->{ordernumber} ) {
362 $order = Koha::Acquisition::Orders->find( $orderinfo->{ordernumber} );
363 $order->set($orderinfo);
364 $log_action_name = 'MODIFY_ORDER';
366 $order = Koha::Acquisition::Order->new($orderinfo);
367 $log_action_name = 'CREATE_ORDER';
369 $order->populate_with_prices_for_ordering();
372 # Log the order creation
373 if ( C4::Context->preference("AcquisitionLog") ) {
375 foreach my $field (@log_order_fields) {
376 $infos->{$field} = $order->$field;
385 my $order_users_ids = $input->param('users_ids');
386 my @order_users = split( /:/, $order_users_ids );
387 ModOrderUsers( $order->ordernumber, @order_users );
389 # Retrieve and save additional fields values
390 my @additional_fields = Koha::AdditionalFields->search( { tablename => 'aqorders' } )->as_list;
391 my @additional_field_values;
392 foreach my $af (@additional_fields) {
394 my $value = $input->param("additional_field_$id");
395 push @additional_field_values, {
400 $order->set_additional_fields( \@additional_field_values );
402 # now, add items if applicable
403 if ( $basket->effective_create_items eq 'ordering' ) {
405 my @tags = $input->multi_param('tag');
406 my @subfields = $input->multi_param('subfield');
407 my @field_values = $input->multi_param('field_value');
408 my @serials = $input->multi_param('serial');
409 my @itemid = $input->multi_param('itemid');
411 #Rebuilding ALL the data for items into a hash
412 # parting them on $itemid.
416 my $range = scalar(@itemid);
417 for ( my $i = 0 ; $i < $range ; $i++ ) {
418 unless ( $itemhash{ $itemid[$i] } ) {
421 push @{ $itemhash{ $itemid[$i] }->{'tags'} }, $tags[$i];
422 push @{ $itemhash{ $itemid[$i] }->{'subfields'} }, $subfields[$i];
423 push @{ $itemhash{ $itemid[$i] }->{'field_values'} }, $field_values[$i];
425 foreach my $item ( keys %itemhash ) {
426 my $xml = TransformHtmlToXml(
427 $itemhash{$item}->{'tags'},
428 $itemhash{$item}->{'subfields'},
429 $itemhash{$item}->{'field_values'},
434 my $record = MARC::Record::new_from_xml( $xml, 'UTF-8' );
435 my ( $barcodefield, $barcodesubfield ) = GetMarcFromKohaField('items.barcode');
436 next unless ( defined $barcodefield && defined $barcodesubfield );
437 my $barcode = $record->subfield( $barcodefield, $barcodesubfield ) || '';
438 my $aBpref = C4::Context->preference('autoBarcode');
439 if ( $barcode eq '' && $aBpref ne 'OFF' ) {
441 if ( $aBpref eq 'hbyymmincr' ) {
442 my ( $homebranchfield, $homebranchsubfield ) = GetMarcFromKohaField('items.homebranch');
443 my $homebranch = $record->subfield( $homebranchfield, $homebranchsubfield );
444 $barcodeobj = C4::Barcodes->new( $aBpref, $homebranch );
446 $barcodeobj = C4::Barcodes->new($aBpref);
448 $barcode = $barcodeobj->value();
449 $record->field($barcodefield)->delete_subfield( code => $barcodesubfield );
450 $record->field($barcodefield)->add_subfields( $barcodesubfield => $barcode );
452 my ( $biblionumber, $bibitemnum, $itemnumber ) = AddItemFromMarc( $record, $$orderinfo{biblionumber} );
453 $order->add_item($itemnumber);
459 if ( C4::Context->preference("AcquisitionLog") && $basketno ) {
460 my $modified = Koha::Acquisition::Baskets->find($basketno);
465 to_json( $modified->unblessed )
469 my $booksellerid = $$orderinfo{booksellerid};
470 if ( my $import_batch_id = $input->param('import_batch_id') ) {
471 print $input->redirect(
472 "/cgi-bin/koha/acqui/addorderiso2709.pl?import_batch_id=$import_batch_id&basketno=$basketno&booksellerid=$booksellerid"
474 } elsif ( defined $orderinfo->{invoiceid} ) {
475 print $input->redirect( "/cgi-bin/koha/acqui/parcel.pl?invoiceid=" . $orderinfo->{invoiceid} );
477 print $input->redirect("/cgi-bin/koha/acqui/basket.pl?basketno=$basketno");
481 my $basketno = $input->param('basketno');
482 print $input->redirect("/cgi-bin/koha/acqui/basket.pl?basketno=$basketno");