3 #script to show display basket of orders
4 #written by chris@katipo.co.nz 24/2/2000
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>.
30 this script allows to create a new record to order it. This record shouldn't exist
38 the bookseller the librarian has to buy a new book.
41 the title of this new record.
44 the author of this new record.
46 =item publication year
47 the publication year of this new record.
50 the number of this order.
55 the basket number for this new order.
58 if this order comes from a suggestion.
61 the item's id in the breeding reservoir
78 use C4::Suggestions; # GetSuggestion
79 use C4::Biblio; # GetBiblioData GetMarcPrice
80 use C4::Items; #PrepareItemRecord
84 use C4::Search qw/FindDuplicate/;
86 #needed for z3950 import:
87 use C4::ImportBatch qw/GetImportRecordMarc SetImportRecordStatus/;
89 use Koha::Acquisition::Booksellers;
90 use Koha::Acquisition::Currencies;
91 use Koha::BiblioFrameworks;
92 use Koha::DateUtils qw( dt_from_string );
93 use Koha::MarcSubfieldStructures;
96 use Koha::RecordProcessor;
99 my $booksellerid = $input->param('booksellerid'); # FIXME: else ERROR!
100 my $budget_id = $input->param('budget_id') || 0;
101 my $title = $input->param('title');
102 my $author = $input->param('author');
103 my $publicationyear = $input->param('publicationyear');
104 my $ordernumber = $input->param('ordernumber') || '';
105 our $biblionumber = $input->param('biblionumber');
106 our $basketno = $input->param('basketno');
107 my $suggestionid = $input->param('suggestionid');
108 my $close = $input->param('close');
109 my $uncertainprice = $input->param('uncertainprice');
110 my $import_batch_id = $input->param('import_batch_id'); # if this is filled, we come from a staged file, and we will return here after saving the order !
111 my $from_subscriptionid = $input->param('from_subscriptionid');
117 our ( $template, $loggedinuser, $cookie, $userflags ) = get_template_and_user(
119 template_name => "acqui/neworderempty.tt",
122 authnotrequired => 0,
123 flagsrequired => { acquisition => 'order_manage' },
128 our $marcflavour = C4::Context->preference('marcflavour');
131 my $order = GetOrder($ordernumber);
132 $basketno = $order->{'basketno'};
135 our $basket = GetBasket($basketno);
136 my $basketobj = Koha::Acquisition::Baskets->find( $basketno );
137 $booksellerid = $basket->{booksellerid} unless $booksellerid;
138 my $bookseller = Koha::Acquisition::Booksellers->find( $booksellerid );
140 my $contract = GetContract({
141 contractnumber => $basket->{contractnumber}
144 #simple parameters reading (all in one :-)
145 our $params = $input->Vars;
146 my $listprice=0; # the price, that can be in MARC record if we have one
147 if ( $ordernumber eq '' and defined $params->{'breedingid'}){
148 #we want to import from the breeding reservoir (from a z3950 search)
149 my ($marcrecord, $encoding) = MARCfindbreeding($params->{'breedingid'});
150 die("Could not find the selected record in the reservoir, bailing") unless $marcrecord;
152 # Remove all the items (952) from the imported record
153 foreach my $item ($marcrecord->field('952')) {
154 $marcrecord->delete_field($item);
159 ($biblionumber,$duplicatetitle) = FindDuplicate($marcrecord);
160 if($biblionumber && !$input->param('use_external_source')) {
161 #if duplicate record found and user did not decide yet, first warn user
162 #and let them choose between using a new record or an existing record
163 Load_Duplicate($duplicatetitle);
166 #from this point: add a new record
168 $params->{'frameworkcode'} or $params->{'frameworkcode'} = "";
169 ( $biblionumber, $bibitemnum ) = AddBiblio( $marcrecord, $params->{'frameworkcode'} );
170 # get the price if there is one.
171 $listprice = GetMarcPrice($marcrecord, $marcflavour);
172 SetImportRecordStatus($params->{'breedingid'}, 'imported');
177 my ( @order_user_ids, @order_users, @catalog_details );
178 our $tagslib = GetMarcStructure(1, 'ACQ', { unsafe => 1 } );
179 my ( $itemnumber_tag, $itemnumber_subtag ) = GetMarcFromKohaField( 'items.itemnumber', 'ACQ' );
180 if ( not $ordernumber ) { # create order
183 if ( $biblionumber ) {
184 $data = GetBiblioData($biblionumber);
186 # get suggestion fields if applicable. If it's a subscription renewal, then the biblio already exists
187 # otherwise, retrieve suggestion information.
188 elsif ($suggestionid) {
189 $data = GetSuggestion($suggestionid);
190 $budget_id ||= $data->{'budgetid'} // 0;
193 if ( not $biblionumber and Koha::BiblioFrameworks->find('ACQ') ) {
194 #my $acq_mss = Koha::MarcSubfieldStructures->search({ frameworkcode => 'ACQ', tagfield => { '!=' => $itemnumber_tag } });
195 foreach my $tag ( sort keys %{$tagslib} ) {
197 next if $tag eq $itemnumber_tag; # skip items fields
198 foreach my $subfield ( sort keys %{ $tagslib->{$tag} } ) {
199 my $mss = $tagslib->{$tag}{$subfield};
200 next if IsMarcStructureInternal($mss);
201 next if $mss->{tab} == -1;
202 my $value = $mss->{defaultvalue};
204 if ($suggestionid and $mss->{kohafield}) {
205 # Reading suggestion info if ordering from a suggestion
206 if ( $mss->{kohafield} eq 'biblio.title' ) {
207 $value = $data->{title};
209 elsif ( $mss->{kohafield} eq 'biblio.author' ) {
210 $value = $data->{author};
212 elsif ( $mss->{kohafield} eq 'biblioitems.publishercode' ) {
213 $value = $data->{publishercode};
215 elsif ( $mss->{kohafield} eq 'biblioitems.editionstatement' ) {
216 $value = $data->{editionstatement};
218 elsif ( $mss->{kohafield} eq 'biblioitems.publicationyear' ) {
219 $value = $data->{publicationyear};
221 elsif ( $mss->{kohafield} eq 'biblioitems.isbn' ) {
222 $value = $data->{isbn};
224 elsif ( $mss->{kohafield} eq 'biblio.seriestitle' ) {
225 $value = $data->{seriestitle};
229 if ( $value eq '' ) {
231 # get today date & replace <<YYYY>>, <<MM>>, <<DD>> if provided in the default value
232 my $today_dt = dt_from_string;
233 my $year = $today_dt->strftime('%Y');
234 my $month = $today_dt->strftime('%m');
235 my $day = $today_dt->strftime('%d');
236 $value =~ s/<<YYYY>>/$year/g;
237 $value =~ s/<<MM>>/$month/g;
238 $value =~ s/<<DD>>/$day/g;
240 # And <<USER>> with surname (?)
242 ( C4::Context->userenv
243 ? C4::Context->userenv->{'surname'}
244 : "superlibrarian" );
245 $value =~ s/<<USER>>/$username/g;
247 push @catalog_details, {
249 subfield => $subfield,
250 %$mss, # Do we need plugins support (?)
258 $data = GetOrder($ordernumber);
259 $biblionumber = $data->{'biblionumber'};
260 $budget_id = $data->{'budget_id'};
263 subscriptionid => $data->{subscriptionid},
266 $basket = GetBasket( $data->{'basketno'} );
267 $basketno = $basket->{'basketno'};
269 @order_user_ids = GetOrderUsers($ordernumber);
270 foreach my $order_user_id (@order_user_ids) {
271 # FIXME Could be improved with search -in
272 my $order_patron = Koha::Patrons->find( $order_user_id );
273 push @order_users, $order_patron if $order_patron;
278 # - no ordernumber but a biblionumber: from a subscription, from an existing record
279 # - no ordernumber, no biblionumber: from a suggestion, from a new order
280 if ( not $ordernumber or $biblionumber ) {
281 if ( C4::Context->preference('UseACQFrameworkForBiblioRecords') ) {
282 my $record = $biblionumber ? GetMarcBiblio({ biblionumber => $biblionumber }) : undef;
283 foreach my $tag ( sort keys %{$tagslib} ) {
285 next if $tag eq $itemnumber_tag; # skip items fields
286 my @fields = $biblionumber ? $record->field($tag) : ();
287 foreach my $subfield ( sort keys %{ $tagslib->{$tag} } ) {
288 my $mss = $tagslib->{$tag}{$subfield};
289 next if IsMarcStructureInternal($mss);
290 next if $mss->{tab} == -1;
291 # We only need to display the values
292 my $value = join '; ', map { $_->subfield( $subfield ) } @fields;
294 push @catalog_details, {
296 subfield => $subfield,
306 $template->param( catalog_details => \@catalog_details, );
309 $suggestion = GetSuggestionInfo($suggestionid) if $suggestionid;
311 my @currencies = Koha::Acquisition::Currencies->search;
312 my $active_currency = Koha::Acquisition::Currencies->get_active;
314 # build bookfund list
315 my $patron = Koha::Patrons->find( $loggedinuser )->unblessed;
317 my $budget = GetBudget($budget_id);
319 my $budget_loop = [];
320 my $budgets = GetBudgetHierarchy;
321 foreach my $r (@{$budgets}) {
322 next unless (CanUserUseBudget($patron, $r, $userflags));
323 if (!defined $r->{budget_amount} || $r->{budget_amount} <0) {
326 push @{$budget_loop}, {
327 b_id => $r->{budget_id},
328 b_txt => $r->{budget_name},
329 b_sort1_authcat => $r->{'sort1_authcat'},
330 b_sort2_authcat => $r->{'sort2_authcat'},
331 b_active => $r->{budget_period_active},
332 b_sel => ( $r->{budget_id} == $budget_id ) ? 1 : 0,
333 b_level => $r->{budget_level},
338 $budget_id = $data->{'budget_id'};
339 $budget_name = $budget->{'budget_name'};
343 $template->param( sort1 => $data->{'sort1'} );
344 $template->param( sort2 => $data->{'sort2'} );
346 if ($basketobj->effective_create_items eq 'ordering' && !$ordernumber) {
347 # Check if ACQ framework exists
348 my $marc = GetMarcStructure(1, 'ACQ', { unsafe => 1 } );
350 $template->param('NoACQframework' => 1);
353 AcqCreateItemOrdering => 1,
354 UniqueItemFields => C4::Context->preference('UniqueItemFields'),
358 # Get the item types list, but only if item_level_itype is YES. Otherwise, it will be in the item, no need to display it in the biblio
360 @itemtypes = Koha::ItemTypes->search unless C4::Context->preference('item-level_itypes');
362 if ( defined $from_subscriptionid ) {
363 my $lastOrderReceived = GetLastOrderReceivedFromSubscriptionid $from_subscriptionid;
364 if ( defined $lastOrderReceived ) {
365 $budget_id = $lastOrderReceived->{budgetid};
366 $data->{listprice} = $lastOrderReceived->{listprice};
367 $data->{uncertainprice} = $lastOrderReceived->{uncertainprice};
368 $data->{tax_rate} = $lastOrderReceived->{tax_rate_on_ordering};
369 $data->{discount} = $lastOrderReceived->{discount};
370 $data->{rrp} = $lastOrderReceived->{rrp};
371 $data->{ecost} = $lastOrderReceived->{ecost};
372 $data->{quantity} = $lastOrderReceived->{quantity};
373 $data->{unitprice} = $lastOrderReceived->{unitprice};
374 $data->{order_internalnote} = $lastOrderReceived->{order_internalnote};
375 $data->{order_vendornote} = $lastOrderReceived->{order_vendornote};
376 $data->{sort1} = $lastOrderReceived->{sort1};
377 $data->{sort2} = $lastOrderReceived->{sort2};
379 $basket = GetBasket( $input->param('basketno') );
382 $template->param( subscriptionid => $from_subscriptionid );
385 # Find the items.barcode subfield for barcode validations
386 my (undef, $barcode_subfield) = GetMarcFromKohaField('items.barcode', '');
391 budget_id => $budget_id,
392 budget_name => $budget_name
395 # get option values for gist syspref
396 my @gst_values = map {
398 }, split( '\|', C4::Context->preference("gist") );
400 my $quantity = $input->param('rr_quantity_to_order') ?
401 $input->param('rr_quantity_to_order') :
406 existing => $biblionumber,
407 ordernumber => $ordernumber,
408 # basket informations
409 basketno => $basketno,
411 basketname => $basket->{'basketname'},
412 basketnote => $basket->{'note'},
413 booksellerid => $basket->{'booksellerid'},
414 basketbooksellernote => $basket->{booksellernote},
415 basketcontractno => $basket->{contractnumber},
416 basketcontractname => $contract->{contractname},
417 creationdate => $basket->{creationdate},
418 authorisedby => $basket->{'authorisedby'},
419 authorisedbyname => $basket->{'authorisedbyname'},
420 closedate => $basket->{'closedate'},
422 suggestionid => $suggestion->{suggestionid},
423 surnamesuggestedby => $suggestion->{surnamesuggestedby},
424 firstnamesuggestedby => $suggestion->{firstnamesuggestedby},
425 biblionumber => $biblionumber,
426 uncertainprice => $data->{'uncertainprice'},
427 discount_2dp => sprintf( "%.2f", $bookseller->discount ) , # for display
428 discount => $bookseller->discount,
429 orderdiscount_2dp => sprintf( "%.2f", $data->{'discount'} || 0 ),
430 orderdiscount => $data->{'discount'},
431 order_internalnote => $data->{'order_internalnote'},
432 order_vendornote => $data->{'order_vendornote'},
433 listincgst => $bookseller->listincgst,
434 invoiceincgst => $bookseller->invoiceincgst,
435 name => $bookseller->name,
436 cur_active_sym => $active_currency->symbol,
437 cur_active => $active_currency->currency,
438 currencies => \@currencies,
439 currency => $data->{currency},
440 vendor_currency => $bookseller->listprice,
441 orderexists => ( $new eq 'yes' ) ? 0 : 1,
442 title => $data->{'title'},
443 author => $data->{'author'},
444 publicationyear => $data->{'publicationyear'} ? $data->{'publicationyear'} : $data->{'copyrightdate'},
445 editionstatement => $data->{'editionstatement'},
446 budget_loop => $budget_loop,
447 isbn => $data->{'isbn'},
448 ean => $data->{'ean'},
449 seriestitle => $data->{'seriestitle'},
450 itemtypeloop => \@itemtypes,
451 quantity => $quantity,
452 quantityrec => $quantity,
453 rrp => $data->{'rrp'},
454 gst_values => \@gst_values,
455 tax_rate => $data->{tax_rate_on_ordering} ? $data->{tax_rate_on_ordering}+0.0 : $bookseller->tax_rate ? $bookseller->tax_rate+0.0 : 0,
456 listprice => sprintf( "%.2f", $data->{listprice} || $data->{price} || $listprice),
457 total => sprintf( "%.2f", ($data->{ecost} || 0) * ($data->{'quantity'} || 0) ),
458 ecost => sprintf( "%.2f", $data->{ecost} || 0),
459 unitprice => sprintf( "%.2f", $data->{unitprice} || 0),
460 publishercode => $data->{'publishercode'},
461 barcode_subfield => $barcode_subfield,
462 import_batch_id => $import_batch_id,
463 acqcreate => $basketobj->effective_create_items eq "ordering" ? 1 : "",
464 users_ids => join(':', @order_user_ids),
465 users => \@order_users,
466 (uc(C4::Context->preference("marcflavour"))) => 1
469 output_html_with_http_headers $input, $cookie, $template->output;
472 =head2 MARCfindbreeding
474 $record = MARCfindbreeding($breedingid);
476 Look up the import record repository for the record with
477 record with id $breedingid. If found, returns the decoded
478 MARC::Record; otherwise, -1 is returned (FIXME).
479 Returns as second parameter the character encoding.
483 sub MARCfindbreeding {
485 my ($marc, $encoding) = GetImportRecordMarc($id);
486 # remove the - in isbn, koha store isbn without any -
488 my $record = MARC::Record->new_from_usmarc($marc);
489 my ($isbnfield,$isbnsubfield) = GetMarcFromKohaField('biblioitems.isbn','');
490 if ( $record->field($isbnfield) ) {
491 foreach my $field ( $record->field($isbnfield) ) {
492 foreach my $subfield ( $field->subfield($isbnsubfield) ) {
493 my $newisbn = $field->subfield($isbnsubfield);
495 $field->update( $isbnsubfield => $newisbn );
499 # fix the unimarc 100 coded field (with unicode information)
500 if ($marcflavour eq 'UNIMARC' && $record->subfield(100,'a')) {
501 my $f100a=$record->subfield(100,'a');
502 my $f100 = $record->field(100);
503 my $f100temp = $f100->as_string;
504 $record->delete_field($f100);
505 if ( length($f100temp) > 28 ) {
506 substr( $f100temp, 26, 2, "50" );
507 $f100->update( 'a' => $f100temp );
508 my $f100 = MARC::Field->new( '100', '', '', 'a' => $f100temp );
509 $record->insert_fields_ordered($f100);
513 if ( !defined(ref($record)) ) {
517 # normalize author : probably UNIMARC specific...
518 if ( C4::Context->preference("z3950NormalizeAuthor")
519 and C4::Context->preference("z3950AuthorAuthFields") )
521 my ( $tag, $subfield ) = GetMarcFromKohaField("biblio.author", '');
524 C4::Context->preference("z3950AuthorAuthFields");
525 my @auth_fields = split /,/, $auth_fields;
528 if ( $record->field($tag) ) {
529 foreach my $tmpfield ( $record->field($tag)->subfields ) {
531 my $subfieldcode = shift @$tmpfield;
532 my $subfieldvalue = shift @$tmpfield;
534 $field->add_subfields(
535 "$subfieldcode" => $subfieldvalue )
536 if ( $subfieldcode ne $subfield );
540 MARC::Field->new( $tag, "", "",
541 $subfieldcode => $subfieldvalue )
542 if ( $subfieldcode ne $subfield );
546 $record->delete_field( $record->field($tag) );
547 foreach my $fieldtag (@auth_fields) {
548 next unless ( $record->field($fieldtag) );
549 my $lastname = $record->field($fieldtag)->subfield('a');
550 my $firstname = $record->field($fieldtag)->subfield('b');
551 my $title = $record->field($fieldtag)->subfield('c');
552 my $number = $record->field($fieldtag)->subfield('d');
554 $field->add_subfields(
555 "$subfield" => ucfirst($title) . " "
556 . ucfirst($firstname) . " "
560 $field->add_subfields(
561 "$subfield" => ucfirst($firstname) . ", "
562 . ucfirst($lastname) );
565 $record->insert_fields_ordered($field);
567 return $record, $encoding;
574 my ($duplicatetitle)= @_;
575 ($template, $loggedinuser, $cookie) = get_template_and_user(
577 template_name => "acqui/neworderempty_duplicate.tt",
580 authnotrequired => 0,
581 flagsrequired => { acquisition => 'order_manage' },
587 biblionumber => $biblionumber,
588 basketno => $basketno,
589 booksellerid => $basket->{'booksellerid'},
590 breedingid => $params->{'breedingid'},
591 duplicatetitle => $duplicatetitle,
592 (uc(C4::Context->preference("marcflavour"))) => 1
595 output_html_with_http_headers $input, $cookie, $template->output;