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
76 use C4::Suggestions; # GetSuggestion
77 use C4::Biblio; # GetBiblioData GetMarcPrice
78 use C4::Items; #PrepareItemRecord
82 use C4::Search qw/FindDuplicate/;
84 #needed for z3950 import:
85 use C4::ImportBatch qw/GetImportRecordMarc SetImportRecordStatus/;
87 use Koha::Acquisition::Booksellers;
88 use Koha::Acquisition::Currencies;
89 use Koha::BiblioFrameworks;
90 use Koha::DateUtils qw( dt_from_string );
91 use Koha::MarcSubfieldStructures;
94 use Koha::RecordProcessor;
95 use Koha::Subscriptions;
98 my $booksellerid = $input->param('booksellerid'); # FIXME: else ERROR!
99 my $budget_id = $input->param('budget_id') || 0;
100 my $title = $input->param('title');
101 my $author = $input->param('author');
102 my $publicationyear = $input->param('publicationyear');
103 my $ordernumber = $input->param('ordernumber') || '';
104 our $biblionumber = $input->param('biblionumber');
105 our $basketno = $input->param('basketno');
106 my $suggestionid = $input->param('suggestionid');
107 my $uncertainprice = $input->param('uncertainprice');
108 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 !
109 my $from_subscriptionid = $input->param('from_subscriptionid');
113 our ( $template, $loggedinuser, $cookie, $userflags ) = get_template_and_user(
115 template_name => "acqui/neworderempty.tt",
118 flagsrequired => { acquisition => 'order_manage' },
123 our $marcflavour = C4::Context->preference('marcflavour');
126 my $order = GetOrder($ordernumber);
127 $basketno = $order->{'basketno'};
130 our $basket = GetBasket($basketno);
131 my $basketobj = Koha::Acquisition::Baskets->find( $basketno );
132 $booksellerid = $basket->{booksellerid} unless $booksellerid;
133 my $bookseller = Koha::Acquisition::Booksellers->find( $booksellerid );
135 output_and_exit( $input, $cookie, $template, 'unknown_basket') unless $basketobj;
136 output_and_exit( $input, $cookie, $template, 'unknown_vendor') unless $bookseller;
139 ordernumber => $ordernumber,
140 basketno => $basketno,
142 booksellerid => $basket->{'booksellerid'},
143 name => $bookseller->name,
145 output_and_exit( $input, $cookie, $template, 'order_cannot_be_edited' )
146 if $ordernumber and $basketobj->closedate;
148 my $contract = GetContract({
149 contractnumber => $basket->{contractnumber}
152 #simple parameters reading (all in one :-)
153 our $params = $input->Vars;
154 my $listprice=0; # the price, that can be in MARC record if we have one
155 if ( $ordernumber eq '' and defined $params->{'breedingid'}){
156 #we want to import from the breeding reservoir (from a z3950 search)
157 my ($marcrecord, $encoding) = MARCfindbreeding($params->{'breedingid'});
158 die("Could not find the selected record in the reservoir, bailing") unless $marcrecord;
160 # Remove all the items (952) from the imported record
161 foreach my $item ($marcrecord->field('952')) {
162 $marcrecord->delete_field($item);
167 ($biblionumber,$duplicatetitle) = FindDuplicate($marcrecord);
168 if($biblionumber && !$input->param('use_external_source')) {
169 #if duplicate record found and user did not decide yet, first warn user
170 #and let them choose between using a new record or an existing record
171 Load_Duplicate($duplicatetitle);
174 #from this point: add a new record
176 $params->{'frameworkcode'} or $params->{'frameworkcode'} = "";
177 ( $biblionumber, $bibitemnum ) = AddBiblio( $marcrecord, $params->{'frameworkcode'} );
178 # get the price if there is one.
179 $listprice = GetMarcPrice($marcrecord, $marcflavour);
180 SetImportRecordStatus($params->{'breedingid'}, 'imported');
185 my ( @order_user_ids, @order_users, @catalog_details );
186 our $tagslib = GetMarcStructure(1, 'ACQ', { unsafe => 1 } );
187 my ( $itemnumber_tag, $itemnumber_subtag ) = GetMarcFromKohaField( 'items.itemnumber' );
188 if ( not $ordernumber ) { # create order
191 if ( $biblionumber ) {
192 $data = GetBiblioData($biblionumber);
194 # get suggestion fields if applicable. If it's a subscription renewal, then the biblio already exists
195 # otherwise, retrieve suggestion information.
196 elsif ($suggestionid) {
197 $data = GetSuggestion($suggestionid);
198 $budget_id ||= $data->{'budgetid'} // 0;
201 if ( not $biblionumber and Koha::BiblioFrameworks->find('ACQ') ) {
202 #my $acq_mss = Koha::MarcSubfieldStructures->search({ frameworkcode => 'ACQ', tagfield => { '!=' => $itemnumber_tag } });
203 foreach my $tag ( sort keys %{$tagslib} ) {
205 next if $tag eq $itemnumber_tag; # skip items fields
206 foreach my $subfield ( sort keys %{ $tagslib->{$tag} } ) {
207 my $mss = $tagslib->{$tag}{$subfield};
208 next if IsMarcStructureInternal($mss);
209 next if $mss->{tab} == -1;
210 my $value = $mss->{defaultvalue};
212 if ($suggestionid and $mss->{kohafield}) {
213 # Reading suggestion info if ordering from a suggestion
214 if ( $mss->{kohafield} eq 'biblio.title' ) {
215 $value = $data->{title};
217 elsif ( $mss->{kohafield} eq 'biblio.author' ) {
218 $value = $data->{author};
220 elsif ( $mss->{kohafield} eq 'biblioitems.publishercode' ) {
221 $value = $data->{publishercode};
223 elsif ( $mss->{kohafield} eq 'biblioitems.editionstatement' ) {
224 $value = $data->{editionstatement};
226 elsif ( $mss->{kohafield} eq 'biblioitems.publicationyear' ) {
227 $value = $data->{publicationyear};
229 elsif ( $mss->{kohafield} eq 'biblioitems.isbn' ) {
230 $value = $data->{isbn};
232 elsif ( $mss->{kohafield} eq 'biblio.seriestitle' ) {
233 $value = $data->{seriestitle};
239 # get today date & replace <<YYYY>>, <<MM>>, <<DD>> if provided in the default value
240 my $today_dt = dt_from_string;
241 my $year = $today_dt->strftime('%Y');
242 my $month = $today_dt->strftime('%m');
243 my $day = $today_dt->strftime('%d');
244 $value =~ s/<<YYYY>>/$year/g;
245 $value =~ s/<<MM>>/$month/g;
246 $value =~ s/<<DD>>/$day/g;
248 # And <<USER>> with surname (?)
250 ( C4::Context->userenv
251 ? C4::Context->userenv->{'surname'}
252 : "superlibrarian" );
253 $value =~ s/<<USER>>/$username/g;
255 push @catalog_details, {
257 subfield => $subfield,
258 %$mss, # Do we need plugins support (?)
266 $data = GetOrder($ordernumber);
267 $biblionumber = $data->{'biblionumber'};
268 $budget_id = $data->{'budget_id'};
271 subscriptionid => $data->{subscriptionid},
274 $basket = GetBasket( $data->{'basketno'} );
275 $basketno = $basket->{'basketno'};
277 @order_user_ids = GetOrderUsers($ordernumber);
278 foreach my $order_user_id (@order_user_ids) {
279 # FIXME Could be improved with search -in
280 my $order_patron = Koha::Patrons->find( $order_user_id );
281 push @order_users, $order_patron if $order_patron;
286 # - no ordernumber but a biblionumber: from a subscription, from an existing record
287 # - no ordernumber, no biblionumber: from a suggestion, from a new order
288 if ( not $ordernumber or $biblionumber ) {
289 if ( C4::Context->preference('UseACQFrameworkForBiblioRecords') ) {
290 my $record = $biblionumber ? GetMarcBiblio({ biblionumber => $biblionumber }) : undef;
291 foreach my $tag ( sort keys %{$tagslib} ) {
293 next if $tag eq $itemnumber_tag; # skip items fields
294 my @fields = $biblionumber ? $record->field($tag) : ();
295 foreach my $subfield ( sort keys %{ $tagslib->{$tag} } ) {
296 my $mss = $tagslib->{$tag}{$subfield};
297 next if IsMarcStructureInternal($mss);
298 next if $mss->{tab} == -1;
299 # We only need to display the values
300 my $value = join '; ', map { $tag < 10 ? $_->data : $_->subfield( $subfield ) } @fields;
302 push @catalog_details, {
304 subfield => $subfield,
314 $template->param( catalog_details => \@catalog_details, );
317 $suggestion = GetSuggestionInfo($suggestionid) if $suggestionid;
319 my @currencies = Koha::Acquisition::Currencies->search;
320 my $active_currency = Koha::Acquisition::Currencies->get_active;
322 # build bookfund list
323 my $patron = Koha::Patrons->find( $loggedinuser )->unblessed;
325 my $budget = GetBudget($budget_id);
327 my $budget_loop = [];
328 my $budgets = GetBudgetHierarchy;
329 foreach my $r (@{$budgets}) {
330 next unless (CanUserUseBudget($patron, $r, $userflags));
331 if (!defined $r->{budget_amount} || $r->{budget_amount} <0) {
334 push @{$budget_loop}, {
335 b_id => $r->{budget_id},
336 b_txt => $r->{budget_name},
337 b_sort1_authcat => $r->{'sort1_authcat'},
338 b_sort2_authcat => $r->{'sort2_authcat'},
339 b_active => $r->{budget_period_active},
340 b_sel => ( $r->{budget_id} == $budget_id ) ? 1 : 0,
341 b_level => $r->{budget_level},
346 $template->param( sort1 => $data->{'sort1'} );
347 $template->param( sort2 => $data->{'sort2'} );
349 if ($basketobj->effective_create_items eq 'ordering' && !$ordernumber) {
350 # Check if ACQ framework exists
351 my $marc = GetMarcStructure(1, 'ACQ', { unsafe => 1 } );
353 $template->param('NoACQframework' => 1);
356 AcqCreateItemOrdering => 1,
357 UniqueItemFields => C4::Context->preference('UniqueItemFields'),
361 # 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
363 @itemtypes = Koha::ItemTypes->search unless C4::Context->preference('item-level_itypes');
365 if ( defined $from_subscriptionid ) {
366 my $lastOrderReceived = GetLastOrderReceivedFromSubscriptionid $from_subscriptionid;
367 if ( defined $lastOrderReceived ) {
368 $budget_id = $lastOrderReceived->{budgetid};
369 $data->{listprice} = $lastOrderReceived->{listprice};
370 $data->{uncertainprice} = $lastOrderReceived->{uncertainprice};
371 $data->{tax_rate} = $lastOrderReceived->{tax_rate_on_ordering};
372 $data->{discount} = $lastOrderReceived->{discount};
373 $data->{rrp} = $lastOrderReceived->{rrp};
374 $data->{replacementprice} = $lastOrderReceived->{replacementprice};
375 $data->{ecost} = $lastOrderReceived->{ecost};
376 $data->{quantity} = $lastOrderReceived->{quantity};
377 $data->{unitprice} = $lastOrderReceived->{unitprice};
378 $data->{order_internalnote} = $lastOrderReceived->{order_internalnote};
379 $data->{order_vendornote} = $lastOrderReceived->{order_vendornote};
380 $data->{sort1} = $lastOrderReceived->{sort1};
381 $data->{sort2} = $lastOrderReceived->{sort2};
383 $basket = GetBasket( $input->param('basketno') );
386 my $subscription = Koha::Subscriptions->find($from_subscriptionid);
388 subscriptionid => $from_subscriptionid,
389 subscription => $subscription,
393 # Find the items.barcode subfield for barcode validations
394 my (undef, $barcode_subfield) = GetMarcFromKohaField( 'items.barcode' );
397 # get option values for gist syspref
398 my @gst_values = map {
400 }, split( '\|', C4::Context->preference("gist") );
402 my $quantity = $input->param('rr_quantity_to_order') ?
403 $input->param('rr_quantity_to_order') :
409 existing => $biblionumber,
410 # basket informations
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 cur_active_sym => $active_currency->symbol,
436 cur_active => $active_currency->currency,
437 currencies => \@currencies,
438 currency => $data->{currency},
439 vendor_currency => $bookseller->listprice,
440 orderexists => ( $new eq 'yes' ) ? 0 : 1,
441 title => $data->{'title'},
442 author => $data->{'author'},
443 publicationyear => $data->{'publicationyear'} ? $data->{'publicationyear'} : $data->{'copyrightdate'},
444 editionstatement => $data->{'editionstatement'},
445 budget_loop => $budget_loop,
446 isbn => $data->{'isbn'},
447 ean => $data->{'ean'},
448 seriestitle => $data->{'seriestitle'},
449 itemtypeloop => \@itemtypes,
450 quantity => $quantity,
451 quantityrec => $quantity,
452 rrp => $data->{'rrp'},
453 replacementprice => $data->{'replacementprice'},
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 flagsrequired => { acquisition => 'order_manage' },
586 biblionumber => $biblionumber,
587 basketno => $basketno,
588 booksellerid => $basket->{'booksellerid'},
589 breedingid => $params->{'breedingid'},
590 duplicatetitle => $duplicatetitle,
591 (uc(C4::Context->preference("marcflavour"))) => 1
594 output_html_with_http_headers $input, $cookie, $template->output;