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;
97 our $input = CGI->new;
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
175 C4::Acquisition::FillWithDefaultValues($marcrecord, {only_mandatory => 1});
177 $params->{'frameworkcode'} or $params->{'frameworkcode'} = "";
178 ( $biblionumber, $bibitemnum ) = AddBiblio( $marcrecord, $params->{'frameworkcode'} );
179 # get the price if there is one.
180 $listprice = GetMarcPrice($marcrecord, $marcflavour);
181 SetImportRecordStatus($params->{'breedingid'}, 'imported');
183 my $dbh = C4::Context->dbh;
185 q|UPDATE import_biblios SET matched_biblionumber = ? WHERE import_record_id = ?|,
186 undef, $biblionumber, $params->{breedingid}
192 my ( @order_user_ids, @order_users, @catalog_details );
193 our $tagslib = GetMarcStructure(1, 'ACQ', { unsafe => 1 } );
194 my ( $itemnumber_tag, $itemnumber_subtag ) = GetMarcFromKohaField( 'items.itemnumber' );
195 if ( not $ordernumber ) { # create order
198 if ( $biblionumber ) {
199 $data = GetBiblioData($biblionumber);
201 # get suggestion fields if applicable. If it's a subscription renewal, then the biblio already exists
202 # otherwise, retrieve suggestion information.
203 elsif ($suggestionid) {
204 $data = GetSuggestion($suggestionid);
205 $budget_id ||= $data->{'budgetid'} // 0;
208 if ( not $biblionumber and Koha::BiblioFrameworks->find('ACQ') ) {
209 #my $acq_mss = Koha::MarcSubfieldStructures->search({ frameworkcode => 'ACQ', tagfield => { '!=' => $itemnumber_tag } });
210 foreach my $tag ( sort keys %{$tagslib} ) {
212 next if $tag eq $itemnumber_tag; # skip items fields
213 foreach my $subfield ( sort keys %{ $tagslib->{$tag} } ) {
214 my $mss = $tagslib->{$tag}{$subfield};
215 next if IsMarcStructureInternal($mss);
216 next if $mss->{tab} == -1;
217 my $value = $mss->{defaultvalue};
219 if ($suggestionid and $mss->{kohafield}) {
220 # Reading suggestion info if ordering from a suggestion
221 if ( $mss->{kohafield} eq 'biblio.title' ) {
222 $value = $data->{title};
224 elsif ( $mss->{kohafield} eq 'biblio.author' ) {
225 $value = $data->{author};
227 elsif ( $mss->{kohafield} eq 'biblioitems.publishercode' ) {
228 $value = $data->{publishercode};
230 elsif ( $mss->{kohafield} eq 'biblioitems.editionstatement' ) {
231 $value = $data->{editionstatement};
233 elsif ( $mss->{kohafield} eq 'biblioitems.publicationyear' ) {
234 $value = $data->{publicationyear};
236 elsif ( $mss->{kohafield} eq 'biblioitems.isbn' ) {
237 $value = $data->{isbn};
239 elsif ( $mss->{kohafield} eq 'biblio.seriestitle' ) {
240 $value = $data->{seriestitle};
246 # get today date & replace <<YYYY>>, <<YY>>, <<MM>>, <<DD>> if provided in the default value
247 my $today_dt = dt_from_string;
248 my $year = $today_dt->strftime('%Y');
249 my $shortyear = $today_dt->strftime('%y');
250 my $month = $today_dt->strftime('%m');
251 my $day = $today_dt->strftime('%d');
252 $value =~ s/<<YYYY>>/$year/g;
253 $value =~ s/<<YY>>/$shortyear/g;
254 $value =~ s/<<MM>>/$month/g;
255 $value =~ s/<<DD>>/$day/g;
257 # And <<USER>> with surname (?)
259 ( C4::Context->userenv
260 ? C4::Context->userenv->{'surname'}
261 : "superlibrarian" );
262 $value =~ s/<<USER>>/$username/g;
264 push @catalog_details, {
266 subfield => $subfield,
267 %$mss, # Do we need plugins support (?)
275 $data = GetOrder($ordernumber);
276 $budget_id = $data->{'budget_id'};
279 subscriptionid => $data->{subscriptionid},
282 $basket = GetBasket( $data->{'basketno'} );
283 $basketno = $basket->{'basketno'};
285 @order_user_ids = GetOrderUsers($ordernumber);
286 foreach my $order_user_id (@order_user_ids) {
287 # FIXME Could be improved with search -in
288 my $order_patron = Koha::Patrons->find( $order_user_id );
289 push @order_users, $order_patron if $order_patron;
292 $biblionumber = $data->{biblionumber};
295 # - no ordernumber but a biblionumber: from a subscription, from an existing record
296 # - no ordernumber, no biblionumber: from a suggestion, from a new order
297 if ( not $ordernumber or $biblionumber ) {
298 if ( C4::Context->preference('UseACQFrameworkForBiblioRecords') ) {
299 my $record = $biblionumber ? GetMarcBiblio({ biblionumber => $biblionumber }) : undef;
300 foreach my $tag ( sort keys %{$tagslib} ) {
302 next if $tag eq $itemnumber_tag; # skip items fields
303 my @fields = $biblionumber ? $record->field($tag) : ();
304 foreach my $subfield ( sort keys %{ $tagslib->{$tag} } ) {
305 my $mss = $tagslib->{$tag}{$subfield};
306 next if IsMarcStructureInternal($mss);
307 next if $mss->{tab} == -1;
308 # We only need to display the values
309 my $value = join '; ', map { $tag < 10 ? $_->data : $_->subfield( $subfield ) } @fields;
311 push @catalog_details, {
313 subfield => $subfield,
323 $template->param( catalog_details => \@catalog_details, );
326 $suggestion = GetSuggestionInfo($suggestionid) if $suggestionid;
328 my @currencies = Koha::Acquisition::Currencies->search;
329 my $active_currency = Koha::Acquisition::Currencies->get_active;
331 # build bookfund list
332 my $patron = Koha::Patrons->find( $loggedinuser )->unblessed;
334 my $budget = GetBudget($budget_id);
336 my $budget_loop = [];
337 my $budgets = GetBudgetHierarchy;
338 foreach my $r (@{$budgets}) {
339 next unless (CanUserUseBudget($patron, $r, $userflags));
340 push @{$budget_loop}, {
341 b_id => $r->{budget_id},
342 b_txt => $r->{budget_name},
343 b_sort1_authcat => $r->{'sort1_authcat'},
344 b_sort2_authcat => $r->{'sort2_authcat'},
345 b_active => $r->{budget_period_active},
346 b_sel => ( $r->{budget_id} == $budget_id ) ? 1 : 0,
347 b_level => $r->{budget_level},
352 $template->param( sort1 => $data->{'sort1'} );
353 $template->param( sort2 => $data->{'sort2'} );
355 if ($basketobj->effective_create_items eq 'ordering' && !$ordernumber) {
356 # Check if ACQ framework exists
357 my $marc = GetMarcStructure(1, 'ACQ', { unsafe => 1 } );
359 $template->param('NoACQframework' => 1);
362 AcqCreateItemOrdering => 1,
363 UniqueItemFields => C4::Context->preference('UniqueItemFields'),
367 # 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
369 @itemtypes = Koha::ItemTypes->search unless C4::Context->preference('item-level_itypes');
371 if ( defined $from_subscriptionid ) {
372 # Get the last received order for this subscription
373 my $lastOrderReceived = Koha::Acquisition::Orders->search(
375 subscriptionid => $from_subscriptionid,
376 datereceived => { '!=' => undef }
380 [ { -desc => 'datereceived' }, { -desc => 'ordernumber' } ]
383 if ( $lastOrderReceived->count ) {
384 $lastOrderReceived = $lastOrderReceived->next->unblessed; # FIXME We should send the object to the template
385 $budget_id = $lastOrderReceived->{budgetid};
386 $data->{listprice} = $lastOrderReceived->{listprice};
387 $data->{uncertainprice} = $lastOrderReceived->{uncertainprice};
388 $data->{tax_rate} = $lastOrderReceived->{tax_rate_on_ordering};
389 $data->{discount} = $lastOrderReceived->{discount};
390 $data->{rrp} = $lastOrderReceived->{rrp};
391 $data->{replacementprice} = $lastOrderReceived->{replacementprice};
392 $data->{ecost} = $lastOrderReceived->{ecost};
393 $data->{quantity} = $lastOrderReceived->{quantity};
394 $data->{unitprice} = $lastOrderReceived->{unitprice};
395 $data->{order_internalnote} = $lastOrderReceived->{order_internalnote};
396 $data->{order_vendornote} = $lastOrderReceived->{order_vendornote};
397 $data->{sort1} = $lastOrderReceived->{sort1};
398 $data->{sort2} = $lastOrderReceived->{sort2};
400 $basket = GetBasket( $input->param('basketno') );
403 my $subscription = Koha::Subscriptions->find($from_subscriptionid);
405 subscriptionid => $from_subscriptionid,
406 subscription => $subscription,
410 # Find the items.barcode subfield for barcode validations
411 my (undef, $barcode_subfield) = GetMarcFromKohaField( 'items.barcode' );
414 # get option values for TaxRates syspref
415 my @gst_values = map {
417 }, split( '\|', C4::Context->preference("TaxRates") );
419 my $quantity = $input->param('rr_quantity_to_order') ?
420 $input->param('rr_quantity_to_order') :
426 existing => $biblionumber,
427 # basket informations
428 basketname => $basket->{'basketname'},
429 basketnote => $basket->{'note'},
430 booksellerid => $basket->{'booksellerid'},
431 basketbooksellernote => $basket->{booksellernote},
432 basketcontractno => $basket->{contractnumber},
433 basketcontractname => $contract->{contractname},
434 creationdate => $basket->{creationdate},
435 authorisedby => $basket->{'authorisedby'},
436 authorisedbyname => $basket->{'authorisedbyname'},
437 closedate => $basket->{'closedate'},
439 suggestionid => $suggestion->{suggestionid},
440 surnamesuggestedby => $suggestion->{surnamesuggestedby},
441 firstnamesuggestedby => $suggestion->{firstnamesuggestedby},
442 biblionumber => $biblionumber,
443 uncertainprice => $data->{'uncertainprice'},
444 discount_2dp => sprintf( "%.2f", $bookseller->discount ) , # for display
445 discount => $bookseller->discount,
446 orderdiscount_2dp => sprintf( "%.2f", $data->{'discount'} || 0 ),
447 orderdiscount => $data->{'discount'},
448 order_internalnote => $data->{'order_internalnote'},
449 order_vendornote => $data->{'order_vendornote'},
450 listincgst => $bookseller->listincgst,
451 invoiceincgst => $bookseller->invoiceincgst,
452 cur_active_sym => $active_currency->symbol,
453 cur_active => $active_currency->currency,
454 currencies => \@currencies,
455 currency => $data->{currency},
456 vendor_currency => $bookseller->listprice,
457 orderexists => ( $new eq 'yes' ) ? 0 : 1,
458 title => $data->{'title'},
459 author => $data->{'author'},
460 publicationyear => $data->{'publicationyear'} ? $data->{'publicationyear'} : $data->{'copyrightdate'},
461 editionstatement => $data->{'editionstatement'},
462 budget_loop => $budget_loop,
463 isbn => $data->{'isbn'},
464 ean => $data->{'ean'},
465 seriestitle => $data->{'seriestitle'},
466 itemtypeloop => \@itemtypes,
467 quantity => $quantity,
468 quantityrec => $quantity,
469 rrp => $data->{'rrp'},
470 replacementprice => $data->{'replacementprice'},
471 gst_values => \@gst_values,
472 tax_rate => $data->{tax_rate_on_ordering} ? $data->{tax_rate_on_ordering}+0.0 : $bookseller->tax_rate ? $bookseller->tax_rate+0.0 : 0,
473 listprice => sprintf( "%.2f", $data->{listprice} || $data->{price} || $listprice),
474 total => sprintf( "%.2f", ($data->{ecost} || 0) * ($data->{'quantity'} || 0) ),
475 ecost => sprintf( "%.2f", $data->{ecost} || 0),
476 unitprice => sprintf( "%.2f", $data->{unitprice} || 0),
477 publishercode => $data->{'publishercode'},
478 barcode_subfield => $barcode_subfield,
479 import_batch_id => $import_batch_id,
480 acqcreate => $basketobj->effective_create_items eq "ordering" ? 1 : "",
481 users_ids => join(':', @order_user_ids),
482 users => \@order_users,
483 (uc(C4::Context->preference("marcflavour"))) => 1
486 output_html_with_http_headers $input, $cookie, $template->output;
489 =head2 MARCfindbreeding
491 $record = MARCfindbreeding($breedingid);
493 Look up the import record repository for the record with
494 record with id $breedingid. If found, returns the decoded
495 MARC::Record; otherwise, -1 is returned (FIXME).
496 Returns as second parameter the character encoding.
500 sub MARCfindbreeding {
502 my ($marc, $encoding) = GetImportRecordMarc($id);
503 # remove the - in isbn, koha store isbn without any -
505 my $record = MARC::Record->new_from_usmarc($marc);
506 my ($isbnfield,$isbnsubfield) = GetMarcFromKohaField( 'biblioitems.isbn' );
507 if ( $record->field($isbnfield) ) {
508 foreach my $field ( $record->field($isbnfield) ) {
509 foreach my $subfield ( $field->subfield($isbnsubfield) ) {
510 my $newisbn = $field->subfield($isbnsubfield);
512 $field->update( $isbnsubfield => $newisbn );
516 # fix the unimarc 100 coded field (with unicode information)
517 if ($marcflavour eq 'UNIMARC' && $record->subfield(100,'a')) {
518 my $f100a=$record->subfield(100,'a');
519 my $f100 = $record->field(100);
520 my $f100temp = $f100->as_string;
521 $record->delete_field($f100);
522 if ( length($f100temp) > 28 ) {
523 substr( $f100temp, 26, 2, "50" );
524 $f100->update( 'a' => $f100temp );
525 my $f100 = MARC::Field->new( '100', '', '', 'a' => $f100temp );
526 $record->insert_fields_ordered($f100);
530 if ( !defined(ref($record)) ) {
534 # normalize author : probably UNIMARC specific...
535 if ( C4::Context->preference("z3950NormalizeAuthor")
536 and C4::Context->preference("z3950AuthorAuthFields") )
538 my ( $tag, $subfield ) = GetMarcFromKohaField( "biblio.author" );
541 C4::Context->preference("z3950AuthorAuthFields");
542 my @auth_fields = split /,/, $auth_fields;
545 if ( $record->field($tag) ) {
546 foreach my $tmpfield ( $record->field($tag)->subfields ) {
548 my $subfieldcode = shift @$tmpfield;
549 my $subfieldvalue = shift @$tmpfield;
551 $field->add_subfields(
552 "$subfieldcode" => $subfieldvalue )
553 if ( $subfieldcode ne $subfield );
557 MARC::Field->new( $tag, "", "",
558 $subfieldcode => $subfieldvalue )
559 if ( $subfieldcode ne $subfield );
563 $record->delete_field( $record->field($tag) );
564 foreach my $fieldtag (@auth_fields) {
565 next unless ( $record->field($fieldtag) );
566 my $lastname = $record->field($fieldtag)->subfield('a');
567 my $firstname = $record->field($fieldtag)->subfield('b');
568 my $title = $record->field($fieldtag)->subfield('c');
569 my $number = $record->field($fieldtag)->subfield('d');
571 $field->add_subfields(
572 "$subfield" => ucfirst($title) . " "
573 . ucfirst($firstname) . " "
577 $field->add_subfields(
578 "$subfield" => ucfirst($firstname) . ", "
579 . ucfirst($lastname) );
582 $record->insert_fields_ordered($field);
584 return $record, $encoding;
591 my ($duplicatetitle)= @_;
592 ($template, $loggedinuser, $cookie) = get_template_and_user(
594 template_name => "acqui/neworderempty_duplicate.tt",
597 flagsrequired => { acquisition => 'order_manage' },
603 biblionumber => $biblionumber,
604 basketno => $basketno,
605 booksellerid => $basket->{'booksellerid'},
606 breedingid => $params->{'breedingid'},
607 duplicatetitle => $duplicatetitle,
608 (uc(C4::Context->preference("marcflavour"))) => 1
611 output_html_with_http_headers $input, $cookie, $template->output;