Lines 30-36
use Encode;
Link Here
|
30 |
use C4::Context; |
30 |
use C4::Context; |
31 |
use C4::Auth qw( get_template_and_user ); |
31 |
use C4::Auth qw( get_template_and_user ); |
32 |
use C4::Output qw( output_html_with_http_headers ); |
32 |
use C4::Output qw( output_html_with_http_headers ); |
33 |
use C4::ImportBatch qw( SetImportBatchStatus GetImportBatch GetImportBatchRangeDesc GetNumberOfNonZ3950ImportBatches GetImportBatchOverlayAction GetImportBatchNoMatchAction GetImportBatchItemAction ); |
33 |
use C4::ImportBatch qw( SetImportBatchStatus ); |
34 |
use C4::Matcher; |
34 |
use C4::Matcher; |
35 |
use C4::Search qw( FindDuplicate ); |
35 |
use C4::Search qw( FindDuplicate ); |
36 |
use C4::Biblio qw( |
36 |
use C4::Biblio qw( |
Lines 41-47
use C4::Biblio qw(
Link Here
|
41 |
TransformHtmlToXml |
41 |
TransformHtmlToXml |
42 |
); |
42 |
); |
43 |
use C4::Items qw( PrepareItemrecordDisplay AddItemFromMarc ); |
43 |
use C4::Items qw( PrepareItemrecordDisplay AddItemFromMarc ); |
44 |
use C4::Budgets qw( GetBudget GetBudgets GetBudgetHierarchy CanUserUseBudget GetBudgetByCode ); |
44 |
use C4::Budgets qw( GetBudget GetBudgets GetBudgetHierarchy CanUserUseBudget ); |
45 |
use C4::Suggestions; # GetSuggestion |
45 |
use C4::Suggestions; # GetSuggestion |
46 |
use C4::Members; |
46 |
use C4::Members; |
47 |
|
47 |
|
Lines 54-59
use Koha::Acquisition::Booksellers;
Link Here
|
54 |
use Koha::ImportBatches; |
54 |
use Koha::ImportBatches; |
55 |
use Koha::Import::Records; |
55 |
use Koha::Import::Records; |
56 |
use Koha::Patrons; |
56 |
use Koha::Patrons; |
|
|
57 |
use Koha::MarcOrder; |
57 |
|
58 |
|
58 |
my $input = CGI->new; |
59 |
my $input = CGI->new; |
59 |
my ($template, $loggedinuser, $cookie, $userflags) = get_template_and_user({ |
60 |
my ($template, $loggedinuser, $cookie, $userflags) = get_template_and_user({ |
Lines 90-96
my $basket = Koha::Acquisition::Baskets->find( $cgiparams->{basketno} );
Link Here
|
90 |
if ($op eq ""){ |
91 |
if ($op eq ""){ |
91 |
$template->param("basketno" => $cgiparams->{'basketno'}); |
92 |
$template->param("basketno" => $cgiparams->{'basketno'}); |
92 |
#display batches |
93 |
#display batches |
93 |
import_batches_list($template); |
94 |
Koha::MarcOrder->import_batches_list($template); |
94 |
# |
95 |
# |
95 |
# 2nd step = display the content of the chosen file |
96 |
# 2nd step = display the content of the chosen file |
96 |
# |
97 |
# |
Lines 104-110
if ($op eq ""){
Link Here
|
104 |
bookseller => $bookseller, |
105 |
bookseller => $bookseller, |
105 |
"allmatch" => $allmatch, |
106 |
"allmatch" => $allmatch, |
106 |
); |
107 |
); |
107 |
import_biblios_list($template, $cgiparams->{'import_batch_id'}); |
108 |
Koha::MarcOrder->import_biblios_list($template, $cgiparams->{'import_batch_id'}); |
108 |
if ( $basket->effective_create_items eq 'ordering' && !$basket->is_standing ) { |
109 |
if ( $basket->effective_create_items eq 'ordering' && !$basket->is_standing ) { |
109 |
# prepare empty item form |
110 |
# prepare empty item form |
110 |
my $cell = PrepareItemrecordDisplay( '', '', undef, 'ACQ' ); |
111 |
my $cell = PrepareItemrecordDisplay( '', '', undef, 'ACQ' ); |
Lines 153-376
if ($op eq ""){
Link Here
|
153 |
my @sort2 = $input->multi_param('sort2'); |
154 |
my @sort2 = $input->multi_param('sort2'); |
154 |
my $matcher_id = $input->param('matcher_id'); |
155 |
my $matcher_id = $input->param('matcher_id'); |
155 |
my $active_currency = Koha::Acquisition::Currencies->get_active; |
156 |
my $active_currency = Koha::Acquisition::Currencies->get_active; |
156 |
my $biblio_count = 0; |
|
|
157 |
while( my $import_record = $import_records->next ){ |
157 |
while( my $import_record = $import_records->next ){ |
158 |
$biblio_count++; |
158 |
my $marcrecord = $import_record->get_marc_record || die "couldn't translate marc information"; |
159 |
my $duplifound = 0; |
159 |
my @homebranches = $input->multi_param( 'homebranch_' . $import_record->import_record_id ); |
160 |
# Check if this import_record_id was selected |
160 |
my @holdingbranches = $input->multi_param( 'holdingbranch_' . $import_record->import_record_id ); |
161 |
next if not grep { $_ eq $import_record->import_record_id } @import_record_id_selected; |
161 |
my @itypes = $input->multi_param( 'itype_' . $import_record->import_record_id ); |
162 |
my $marcrecord = $import_record->get_marc_record || die "couldn't translate marc information"; |
162 |
my @nonpublic_notes = $input->multi_param( 'nonpublic_note_' . $import_record->import_record_id ); |
163 |
my $matches = $import_record->get_import_record_matches({ chosen => 1 }); |
163 |
my @public_notes = $input->multi_param( 'public_note_' . $import_record->import_record_id ); |
164 |
my $match = $matches->count ? $matches->next : undef; |
164 |
my @locs = $input->multi_param( 'loc_' . $import_record->import_record_id ); |
165 |
my $biblionumber = $match ? $match->candidate_match_id : 0; |
165 |
my @ccodes = $input->multi_param( 'ccode_' . $import_record->import_record_id ); |
166 |
my $c_quantity = shift( @quantities ) || GetMarcQuantity($marcrecord, C4::Context->preference('marcflavour') ) || 1; |
166 |
my @notforloans = $input->multi_param( 'notforloan_' . $import_record->import_record_id ); |
167 |
my $c_budget_id = shift( @budgets_id ) || $input->param('all_budget_id') || $budget_id; |
167 |
my @uris = $input->multi_param( 'uri_' . $import_record->import_record_id ); |
168 |
my $c_discount = shift ( @discount); |
168 |
my @copynos = $input->multi_param( 'copyno_' . $import_record->import_record_id ); |
169 |
my $c_sort1 = shift( @sort1 ) || $input->param('all_sort1') || ''; |
169 |
my @budget_codes = $input->multi_param( 'budget_code_' . $import_record->import_record_id ); |
170 |
my $c_sort2 = shift( @sort2 ) || $input->param('all_sort2') || ''; |
170 |
my @itemprices = $input->multi_param( 'itemprice_' . $import_record->import_record_id ); |
171 |
my $c_replacement_price = shift( @orderreplacementprices ); |
171 |
my @replacementprices = $input->multi_param( 'replacementprice_' . $import_record->import_record_id ); |
172 |
my $c_price = shift( @prices ) || GetMarcPrice($marcrecord, C4::Context->preference('marcflavour')); |
172 |
my @itemcallnumbers = $input->multi_param( 'itemcallnumber_' . $import_record->import_record_id ); |
|
|
173 |
|
174 |
my $client_item_fields = { |
175 |
homebranches => \@homebranches, |
176 |
holdingbranches => \@holdingbranches, |
177 |
itypes => \@itypes, |
178 |
nonpublic_notes => \@nonpublic_notes, |
179 |
public_notes => \@public_notes, |
180 |
locs => \@locs, |
181 |
ccodes => \@ccodes, |
182 |
notforloans => \@notforloans, |
183 |
uris => \@uris, |
184 |
copynos => \@copynos, |
185 |
budget_codes => \@budget_codes, |
186 |
itemprices => \@itemprices, |
187 |
replacementprices => \@replacementprices, |
188 |
itemcallnumbers => \@itemcallnumbers, |
189 |
c_quantity => shift(@quantities) |
190 |
|| GetMarcQuantity( $marcrecord, C4::Context->preference('marcflavour') ) |
191 |
|| 1, |
192 |
c_budget_id => shift(@budgets_id) || $input->param('all_budget_id') || $budget_id, |
193 |
c_discount => shift(@discount), |
194 |
c_sort1 => shift(@sort1) || $input->param('all_sort1') || '', |
195 |
c_sort2 => shift(@sort2) || $input->param('all_sort2') || '', |
196 |
c_replacement_price => shift(@orderreplacementprices), |
197 |
c_price => shift(@prices) || GetMarcPrice( $marcrecord, C4::Context->preference('marcflavour') ), |
198 |
}; |
199 |
|
200 |
my $args = { |
201 |
import_batch_id => $import_batch_id, |
202 |
import_record => $import_record, |
203 |
matcher_id => $matcher_id, |
204 |
overlay_action => $overlay_action, |
205 |
agent => 'client', |
206 |
import_record_id_selected => \@import_record_id_selected, |
207 |
client_item_fields => $client_item_fields, |
208 |
basket_id => $cgiparams->{'basketno'}, |
209 |
vendor => $bookseller, |
210 |
budget_id => $budget_id, |
211 |
}; |
212 |
my $result = Koha::MarcOrder->import_record_and_create_order_lines($args); |
213 |
|
214 |
$duplinbatch = $result->{duplicates_in_batch} if $result->{duplicates_in_batch}; |
215 |
next if $result->{skip}; # If a duplicate is found, or the import record wasn't selected it will be skipped |
173 |
|
216 |
|
174 |
# Insert the biblio, or find it through matcher |
|
|
175 |
if ( $biblionumber ) { # If matched during staging we can continue |
176 |
$import_record->status('imported')->store; |
177 |
if( $overlay_action eq 'replace' ){ |
178 |
my $biblio = Koha::Biblios->find( $biblionumber ); |
179 |
$import_record->replace({ biblio => $biblio }); |
180 |
} |
181 |
} else { # Otherwise we check for duplicates, and skip if they exist |
182 |
if ($matcher_id) { |
183 |
if ( $matcher_id eq '_TITLE_AUTHOR_' ) { |
184 |
$duplifound = 1 if FindDuplicate($marcrecord); |
185 |
} |
186 |
else { |
187 |
my $matcher = C4::Matcher->fetch($matcher_id); |
188 |
my @matches = $matcher->get_matches( $marcrecord, my $max_matches = 1 ); |
189 |
$duplifound = 1 if @matches; |
190 |
} |
191 |
|
192 |
$duplinbatch = $import_batch_id and next if $duplifound; |
193 |
} |
194 |
|
195 |
# remove hyphens (-) from ISBN |
196 |
# FIXME: This should probably be optional |
197 |
my ( $isbnfield, $isbnsubfield ) = GetMarcFromKohaField( 'biblioitems.isbn' ); |
198 |
if ( $marcrecord->field($isbnfield) ) { |
199 |
foreach my $field ( $marcrecord->field($isbnfield) ) { |
200 |
foreach my $subfield ( $field->subfield($isbnsubfield) ) { |
201 |
my $newisbn = $field->subfield($isbnsubfield); |
202 |
$newisbn =~ s/-//g; |
203 |
$field->update( $isbnsubfield => $newisbn ); |
204 |
} |
205 |
} |
206 |
} |
207 |
|
208 |
# add the biblio |
209 |
( $biblionumber, undef ) = AddBiblio( $marcrecord, $cgiparams->{'frameworkcode'} || '' ); |
210 |
$import_record->status('imported')->store; |
211 |
} |
212 |
|
213 |
$import_record->import_biblio->matched_biblionumber($biblionumber)->store; |
214 |
|
215 |
# Add items from MarcItemFieldsToOrder |
216 |
my @homebranches = $input->multi_param('homebranch_' . $import_record->import_record_id); |
217 |
my $count = scalar @homebranches; |
218 |
my @holdingbranches = $input->multi_param('holdingbranch_' . $import_record->import_record_id); |
219 |
my @itypes = $input->multi_param('itype_' . $import_record->import_record_id); |
220 |
my @nonpublic_notes = $input->multi_param('nonpublic_note_' . $import_record->import_record_id); |
221 |
my @public_notes = $input->multi_param('public_note_' . $import_record->import_record_id); |
222 |
my @locs = $input->multi_param('loc_' . $import_record->import_record_id); |
223 |
my @ccodes = $input->multi_param('ccode_' . $import_record->import_record_id); |
224 |
my @notforloans = $input->multi_param('notforloan_' . $import_record->import_record_id); |
225 |
my @uris = $input->multi_param('uri_' . $import_record->import_record_id); |
226 |
my @copynos = $input->multi_param('copyno_' . $import_record->import_record_id); |
227 |
my @budget_ids = |
228 |
$input->multi_param( 'budget_code_' . $import_record->import_record_id ); # bad field name used in template! |
229 |
my @itemprices = $input->multi_param('itemprice_' . $import_record->import_record_id); |
230 |
my @replacementprices = $input->multi_param('replacementprice_' . $import_record->import_record_id); |
231 |
my @itemcallnumbers = $input->multi_param('itemcallnumber_' . $import_record->import_record_id); |
232 |
my $itemcreation = 0; |
233 |
|
234 |
my @itemnumbers; |
235 |
for (my $i = 0; $i < $count; $i++) { |
236 |
$itemcreation = 1; |
237 |
my $item = Koha::Item->new( |
238 |
{ |
239 |
biblionumber => $biblionumber, |
240 |
homebranch => $homebranches[$i], |
241 |
holdingbranch => $holdingbranches[$i], |
242 |
itemnotes_nonpublic => $nonpublic_notes[$i], |
243 |
itemnotes => $public_notes[$i], |
244 |
location => $locs[$i], |
245 |
ccode => $ccodes[$i], |
246 |
itype => $itypes[$i], |
247 |
notforloan => $notforloans[$i], |
248 |
uri => $uris[$i], |
249 |
copynumber => $copynos[$i], |
250 |
price => $itemprices[$i], |
251 |
replacementprice => $replacementprices[$i], |
252 |
itemcallnumber => $itemcallnumbers[$i], |
253 |
} |
254 |
)->store; |
255 |
push( @itemnumbers, $item->itemnumber ); |
256 |
} |
257 |
if ($itemcreation == 1) { |
258 |
# Group orderlines from MarcItemFieldsToOrder |
259 |
my $budget_hash; |
260 |
for (my $i = 0; $i < $count; $i++) { |
261 |
$budget_ids[$i] = $budget_id if !$budget_ids[$i]; # Use default budget if no budget selected in the UI |
262 |
$budget_hash->{ $budget_ids[$i] }->{quantity} += 1; |
263 |
$budget_hash->{ $budget_ids[$i] }->{price} = $itemprices[$i]; |
264 |
$budget_hash->{ $budget_ids[$i] }->{replacementprice} = |
265 |
$replacementprices[$i]; |
266 |
$budget_hash->{ $budget_ids[$i] }->{itemnumbers} //= []; |
267 |
push @{ $budget_hash->{ $budget_ids[$i] }->{itemnumbers} }, |
268 |
$itemnumbers[$i]; |
269 |
} |
270 |
|
271 |
# Create orderlines from MarcItemFieldsToOrder |
272 |
while(my ($budget_id, $infos) = each %$budget_hash) { |
273 |
if ($budget_id) { |
274 |
my %orderinfo = ( |
275 |
biblionumber => $biblionumber, |
276 |
basketno => $cgiparams->{'basketno'}, |
277 |
quantity => $infos->{quantity}, |
278 |
budget_id => $budget_id, |
279 |
currency => $cgiparams->{'all_currency'}, |
280 |
); |
281 |
|
282 |
my $price = $infos->{price}; |
283 |
if ($price){ |
284 |
# in France, the cents separator is the , but sometimes, ppl use a . |
285 |
# in this case, the price will be x100 when unformatted ! Replace the . by a , to get a proper price calculation |
286 |
$price =~ s/\./,/ if C4::Context->preference("CurrencyFormat") eq "FR"; |
287 |
$price = Koha::Number::Price->new($price)->unformat; |
288 |
$orderinfo{tax_rate_on_ordering} = $bookseller->tax_rate; |
289 |
$orderinfo{tax_rate_on_receiving} = $bookseller->tax_rate; |
290 |
my $order_discount = $c_discount ? $c_discount : $bookseller->discount; |
291 |
$orderinfo{discount} = $order_discount; |
292 |
$orderinfo{rrp} = $price; |
293 |
$orderinfo{ecost} = $order_discount ? $price * ( 1 - $order_discount / 100 ) : $price; |
294 |
$orderinfo{listprice} = $orderinfo{rrp} / $active_currency->rate; |
295 |
$orderinfo{unitprice} = $orderinfo{ecost}; |
296 |
$orderinfo{sort1} = $c_sort1; |
297 |
$orderinfo{sort2} = $c_sort2; |
298 |
} else { |
299 |
$orderinfo{listprice} = 0; |
300 |
} |
301 |
$orderinfo{replacementprice} = $infos->{replacementprice} || 0; |
302 |
|
303 |
# remove uncertainprice flag if we have found a price in the MARC record |
304 |
$orderinfo{uncertainprice} = 0 if $orderinfo{listprice}; |
305 |
|
306 |
my $order = Koha::Acquisition::Order->new( \%orderinfo ); |
307 |
$order->populate_with_prices_for_ordering(); |
308 |
$order->populate_with_prices_for_receiving(); |
309 |
$order->store; |
310 |
$order->add_item( $_ ) for @{ $budget_hash->{$budget_id}->{itemnumbers} }; |
311 |
} |
312 |
} |
313 |
} else { |
314 |
# 3rd add order |
315 |
my $patron = Koha::Patrons->find( $loggedinuser ); |
316 |
# get quantity in the MARC record (1 if none) |
317 |
my $quantity = GetMarcQuantity($marcrecord, C4::Context->preference('marcflavour')) || 1; |
318 |
my %orderinfo = ( |
319 |
biblionumber => $biblionumber, |
320 |
basketno => $cgiparams->{'basketno'}, |
321 |
quantity => $c_quantity, |
322 |
branchcode => $patron->branchcode, |
323 |
budget_id => $c_budget_id, |
324 |
uncertainprice => 1, |
325 |
sort1 => $c_sort1, |
326 |
sort2 => $c_sort2, |
327 |
order_internalnote => $cgiparams->{'all_order_internalnote'}, |
328 |
order_vendornote => $cgiparams->{'all_order_vendornote'}, |
329 |
currency => $cgiparams->{'all_currency'}, |
330 |
replacementprice => $c_replacement_price, |
331 |
); |
332 |
# get the price if there is one. |
333 |
if ($c_price){ |
334 |
# in France, the cents separator is the , but sometimes, ppl use a . |
335 |
# in this case, the price will be x100 when unformatted ! Replace the . by a , to get a proper price calculation |
336 |
$c_price =~ s/\./,/ if C4::Context->preference("CurrencyFormat") eq "FR"; |
337 |
$c_price = Koha::Number::Price->new($c_price)->unformat; |
338 |
$orderinfo{tax_rate_on_ordering} = $bookseller->tax_rate; |
339 |
$orderinfo{tax_rate_on_receiving} = $bookseller->tax_rate; |
340 |
my $order_discount = $c_discount ? $c_discount : $bookseller->discount; |
341 |
$orderinfo{discount} = $order_discount; |
342 |
$orderinfo{rrp} = $c_price; |
343 |
$orderinfo{ecost} = $order_discount ? $c_price * ( 1 - $order_discount / 100 ) : $c_price; |
344 |
$orderinfo{listprice} = $orderinfo{rrp} / $active_currency->rate; |
345 |
$orderinfo{unitprice} = $orderinfo{ecost}; |
346 |
} else { |
347 |
$orderinfo{listprice} = 0; |
348 |
} |
349 |
|
350 |
# remove uncertainprice flag if we have found a price in the MARC record |
351 |
$orderinfo{uncertainprice} = 0 if $orderinfo{listprice}; |
352 |
|
353 |
my $order = Koha::Acquisition::Order->new( \%orderinfo ); |
354 |
$order->populate_with_prices_for_ordering(); |
355 |
$order->populate_with_prices_for_receiving(); |
356 |
$order->store; |
357 |
|
358 |
# 4th, add items if applicable |
359 |
# parse the item sent by the form, and create an item just for the import_record_id we are dealing with |
360 |
# this is not optimised, but it's working ! |
361 |
if ( $basket->effective_create_items eq 'ordering' && !$basket->is_standing ) { |
362 |
my @tags = $input->multi_param('tag'); |
363 |
my @subfields = $input->multi_param('subfield'); |
364 |
my @field_values = $input->multi_param('field_value'); |
365 |
my @serials = $input->multi_param('serial'); |
366 |
my $xml = TransformHtmlToXml( \@tags, \@subfields, \@field_values ); |
367 |
my $record = MARC::Record::new_from_xml( $xml, 'UTF-8' ); |
368 |
for (my $qtyloop=1;$qtyloop <= $c_quantity;$qtyloop++) { |
369 |
my ( $biblionumber, undef, $itemnumber ) = AddItemFromMarc( $record, $biblionumber ); |
370 |
$order->add_item( $itemnumber ); |
371 |
} |
372 |
} |
373 |
} |
374 |
$imported++; |
217 |
$imported++; |
375 |
} |
218 |
} |
376 |
|
219 |
|
Lines 416-738
foreach my $r ( @{$budgets_hierarchy} ) {
Link Here
|
416 |
$template->param( budget_loop => $budget_loop,); |
259 |
$template->param( budget_loop => $budget_loop,); |
417 |
|
260 |
|
418 |
output_html_with_http_headers $input, $cookie, $template->output; |
261 |
output_html_with_http_headers $input, $cookie, $template->output; |
419 |
|
|
|
420 |
|
421 |
sub import_batches_list { |
422 |
my ($template) = @_; |
423 |
my $batches = GetImportBatchRangeDesc(); |
424 |
|
425 |
my @list = (); |
426 |
foreach my $batch (@$batches) { |
427 |
if ( $batch->{'import_status'} =~ /^staged$|^reverted$/ && $batch->{'record_type'} eq 'biblio') { |
428 |
# check if there is at least 1 line still staged |
429 |
my $import_records_count = Koha::Import::Records->search({ |
430 |
import_batch_id => $batch->{'import_batch_id'}, |
431 |
status => $batch->{import_status} |
432 |
})->count; |
433 |
if ( $import_records_count ) { |
434 |
push @list, { |
435 |
import_batch_id => $batch->{'import_batch_id'}, |
436 |
num_records => $batch->{'num_records'}, |
437 |
num_items => $batch->{'num_items'}, |
438 |
staged_date => $batch->{'upload_timestamp'}, |
439 |
import_status => $batch->{'import_status'}, |
440 |
file_name => $batch->{'file_name'}, |
441 |
comments => $batch->{'comments'}, |
442 |
}; |
443 |
} else { |
444 |
# if there are no more line to includes, set the status to imported |
445 |
# FIXME This should be removed in the future. |
446 |
SetImportBatchStatus( $batch->{'import_batch_id'}, 'imported' ); |
447 |
} |
448 |
} |
449 |
} |
450 |
$template->param(batch_list => \@list); |
451 |
my $num_batches = GetNumberOfNonZ3950ImportBatches(); |
452 |
$template->param(num_results => $num_batches); |
453 |
} |
454 |
|
455 |
sub import_biblios_list { |
456 |
my ($template, $import_batch_id) = @_; |
457 |
my $batch = GetImportBatch($import_batch_id,'staged'); |
458 |
return () unless $batch and $batch->{import_status} =~ /^staged$|^reverted$/; |
459 |
my $import_records = Koha::Import::Records->search({ |
460 |
import_batch_id => $import_batch_id, |
461 |
status => $batch->{import_status} |
462 |
}); |
463 |
my @list = (); |
464 |
my $item_error = 0; |
465 |
|
466 |
my $ccodes = { map { $_->{authorised_value} => $_->{opac_description} } Koha::AuthorisedValues->get_descriptions_by_koha_field( { frameworkcode => '', kohafield => 'items.ccode' } ) }; |
467 |
my $locations = { map { $_->{authorised_value} => $_->{opac_description} } Koha::AuthorisedValues->get_descriptions_by_koha_field( { frameworkcode => '', kohafield => 'items.location' } ) }; |
468 |
my $notforloans = { map { $_->{authorised_value} => $_->{lib} } Koha::AuthorisedValues->get_descriptions_by_koha_field( { frameworkcode => '', kohafield => 'items.notforloan' } ) }; |
469 |
# location list |
470 |
my @locations; |
471 |
foreach (sort keys %$locations) { |
472 |
push @locations, { code => $_, description => "$_ - " . $locations->{$_} }; |
473 |
} |
474 |
my @ccodes; |
475 |
foreach (sort {$ccodes->{$a} cmp $ccodes->{$b}} keys %$ccodes) { |
476 |
push @ccodes, { code => $_, description => $ccodes->{$_} }; |
477 |
} |
478 |
my @notforloans; |
479 |
foreach (sort {$notforloans->{$a} cmp $notforloans->{$b}} keys %$notforloans) { |
480 |
push @notforloans, { code => $_, description => $notforloans->{$_} }; |
481 |
} |
482 |
|
483 |
my $biblio_count = 0; |
484 |
while ( my $import_record = $import_records->next ) { |
485 |
my $item_id = 1; |
486 |
$biblio_count++; |
487 |
my $matches = $import_record->get_import_record_matches({ chosen => 1 }); |
488 |
my $match = $matches->count ? $matches->next : undef; |
489 |
my $match_biblio = $match ? Koha::Biblios->find({ biblionumber => $match->candidate_match_id }) : undef; |
490 |
my %cellrecord = ( |
491 |
import_record_id => $import_record->import_record_id, |
492 |
import_biblio => $import_record->import_biblio, |
493 |
import => 1, |
494 |
status => $import_record->status, |
495 |
record_sequence => $import_record->record_sequence, |
496 |
overlay_status => $import_record->overlay_status, |
497 |
match_biblionumber => $match ? $match->candidate_match_id : 0, |
498 |
match_citation => $match_biblio ? ($match_biblio->title || '') . ' ' .( $match_biblio->author || ''): '', |
499 |
match_score => $match ? $match->score : 0, |
500 |
); |
501 |
my $marcrecord = $import_record->get_marc_record || die "couldn't translate marc information"; |
502 |
|
503 |
my $infos = get_infos_syspref('MarcFieldsToOrder', $marcrecord, ['price', 'quantity', 'budget_code', 'discount', 'sort1', 'sort2','replacementprice']); |
504 |
my $price = $infos->{price}; |
505 |
my $replacementprice = $infos->{replacementprice}; |
506 |
my $quantity = $infos->{quantity}; |
507 |
my $budget_code = $infos->{budget_code}; |
508 |
my $discount = $infos->{discount}; |
509 |
my $sort1 = $infos->{sort1}; |
510 |
my $sort2 = $infos->{sort2}; |
511 |
my $budget_id; |
512 |
|
513 |
if ($budget_code) { |
514 |
my $biblio_budget = GetBudgetByCode($budget_code); |
515 |
if ($biblio_budget) { |
516 |
$budget_id = $biblio_budget->{budget_id}; |
517 |
} |
518 |
} |
519 |
|
520 |
# Items |
521 |
my @itemlist = (); |
522 |
my $all_items_quantity = 0; |
523 |
my $alliteminfos = get_marc_item_fields_to_order($marcrecord); |
524 |
if ($alliteminfos != -1) { |
525 |
foreach my $iteminfos (@$alliteminfos) { |
526 |
# Quantity is required, default to one if not supplied |
527 |
my $quantity = delete $iteminfos->{quantity} || 1; |
528 |
|
529 |
# Handle incorrectly named original parameters for MarcItemFieldsToOrder |
530 |
$iteminfos->{location} = delete $iteminfos->{loc} if $iteminfos->{loc}; |
531 |
$iteminfos->{copynumber} = delete $iteminfos->{copyno} if $iteminfos->{copyno}; |
532 |
|
533 |
# Convert budge code to a budget id |
534 |
my $item_budget_code = delete $iteminfos->{budget_code}; |
535 |
if ( $item_budget_code ) { |
536 |
my $item_budget = GetBudgetByCode( $item_budget_code ); |
537 |
$iteminfos->{budget_id} = $item_budget->{budget_id} || $budget_id; |
538 |
} |
539 |
|
540 |
# Clone the item data for the needed quantity |
541 |
# Add the incremented item id for each item in that quantity |
542 |
for (my $i = 0; $i < $quantity; $i++) { |
543 |
my $itemrecord = { %$iteminfos }; |
544 |
$itemrecord->{item_id} = $item_id++; |
545 |
$all_items_quantity++; |
546 |
push @itemlist, $itemrecord; |
547 |
} |
548 |
} |
549 |
|
550 |
$cellrecord{'iteminfos'} = \@itemlist; |
551 |
} else { |
552 |
$cellrecord{'item_error'} = 1; |
553 |
} |
554 |
push @list, \%cellrecord; |
555 |
|
556 |
# If MarcItemFieldsToOrder is not set, we use MarcFieldsToOrder to populate the order form. |
557 |
if ($alliteminfos == -1 || scalar(@$alliteminfos) == 0) { |
558 |
$cellrecord{price} = $price || ''; |
559 |
$cellrecord{replacementprice} = $replacementprice || ''; |
560 |
$cellrecord{quantity} = $quantity || ''; |
561 |
$cellrecord{budget_id} = $budget_id || ''; |
562 |
} else { |
563 |
# When using MarcItemFields to order we want the order to have the same quantity as total items |
564 |
$cellrecord{quantity} = $all_items_quantity; |
565 |
} |
566 |
# The fields discount, sort1, and sort2 only exist at the order level, so always use MarcItemFieldsToOrder |
567 |
$cellrecord{discount} = $discount || ''; |
568 |
$cellrecord{sort1} = $sort1 || ''; |
569 |
$cellrecord{sort2} = $sort2 || ''; |
570 |
|
571 |
} |
572 |
my $num_records = $batch->{'num_records'}; |
573 |
my $overlay_action = GetImportBatchOverlayAction($import_batch_id); |
574 |
my $nomatch_action = GetImportBatchNoMatchAction($import_batch_id); |
575 |
my $item_action = GetImportBatchItemAction($import_batch_id); |
576 |
$template->param(import_biblio_list => \@list, |
577 |
num_results => $num_records, |
578 |
import_batch_id => $import_batch_id, |
579 |
"overlay_action_${overlay_action}" => 1, |
580 |
overlay_action => $overlay_action, |
581 |
"nomatch_action_${nomatch_action}" => 1, |
582 |
nomatch_action => $nomatch_action, |
583 |
"item_action_${item_action}" => 1, |
584 |
item_action => $item_action, |
585 |
item_error => $item_error, |
586 |
libraries => Koha::Libraries->search, |
587 |
locationloop => \@locations, |
588 |
itemtypes => Koha::ItemTypes->search, |
589 |
ccodeloop => \@ccodes, |
590 |
notforloanloop => \@notforloans, |
591 |
); |
592 |
batch_info($template, $batch); |
593 |
} |
594 |
|
595 |
sub batch_info { |
596 |
my ($template, $batch) = @_; |
597 |
$template->param(batch_info => 1, |
598 |
file_name => $batch->{'file_name'}, |
599 |
comments => $batch->{'comments'}, |
600 |
import_status => $batch->{'import_status'}, |
601 |
upload_timestamp => $batch->{'upload_timestamp'}, |
602 |
num_records => $batch->{'num_records'}, |
603 |
num_items => $batch->{'num_items'}); |
604 |
if ($batch->{'num_records'} > 0) { |
605 |
if ($batch->{'import_status'} eq 'staged' or $batch->{'import_status'} eq 'reverted') { |
606 |
$template->param(can_commit => 1); |
607 |
} |
608 |
if ($batch->{'import_status'} eq 'imported') { |
609 |
$template->param(can_revert => 1); |
610 |
} |
611 |
} |
612 |
if (defined $batch->{'matcher_id'}) { |
613 |
my $matcher = C4::Matcher->fetch($batch->{'matcher_id'}); |
614 |
if (defined $matcher) { |
615 |
$template->param('current_matcher_id' => $batch->{'matcher_id'}, |
616 |
'current_matcher_code' => $matcher->code(), |
617 |
'current_matcher_description' => $matcher->description()); |
618 |
} |
619 |
} |
620 |
add_matcher_list($batch->{'matcher_id'}, $template); |
621 |
} |
622 |
|
623 |
sub add_matcher_list { |
624 |
my ($current_matcher_id, $template) = @_; |
625 |
my @matchers = C4::Matcher::GetMatcherList(); |
626 |
if (defined $current_matcher_id) { |
627 |
for (my $i = 0; $i <= $#matchers; $i++) { |
628 |
if ($matchers[$i]->{'matcher_id'} == $current_matcher_id) { |
629 |
$matchers[$i]->{'selected'} = 1; |
630 |
} |
631 |
} |
632 |
} |
633 |
$template->param(available_matchers => \@matchers); |
634 |
} |
635 |
|
636 |
sub get_infos_syspref { |
637 |
my ($syspref_name, $record, $field_list) = @_; |
638 |
my $syspref = C4::Context->preference($syspref_name); |
639 |
$syspref = "$syspref\n\n"; # YAML is anal on ending \n. Surplus does not hurt |
640 |
my $yaml = eval { |
641 |
YAML::XS::Load(Encode::encode_utf8($syspref)); |
642 |
}; |
643 |
if ( $@ ) { |
644 |
warn "Unable to parse $syspref syspref : $@"; |
645 |
return (); |
646 |
} |
647 |
my $r; |
648 |
for my $field_name ( @$field_list ) { |
649 |
next unless exists $yaml->{$field_name}; |
650 |
my @fields = split /\|/, $yaml->{$field_name}; |
651 |
for my $field ( @fields ) { |
652 |
my ( $f, $sf ) = split /\$/, $field; |
653 |
next unless $f and $sf; |
654 |
if ( my $v = $record->subfield( $f, $sf ) ) { |
655 |
$r->{$field_name} = $v; |
656 |
} |
657 |
last if $yaml->{$field}; |
658 |
} |
659 |
} |
660 |
return $r; |
661 |
} |
662 |
|
663 |
sub equal_number_of_fields { |
664 |
my ($tags_list, $record) = @_; |
665 |
my $tag_fields_count; |
666 |
for my $tag (@$tags_list) { |
667 |
my @fields = $record->field($tag); |
668 |
$tag_fields_count->{$tag} = scalar @fields; |
669 |
} |
670 |
|
671 |
my $tags_count; |
672 |
foreach my $key ( keys %$tag_fields_count ) { |
673 |
if ( $tag_fields_count->{$key} > 0 ) { # Having 0 of a field is ok |
674 |
$tags_count //= $tag_fields_count->{$key}; # Start with the count from the first occurrence |
675 |
return -1 if $tag_fields_count->{$key} != $tags_count; # All counts of various fields should be equal if they exist |
676 |
} |
677 |
} |
678 |
|
679 |
return $tags_count; |
680 |
} |
681 |
|
682 |
sub get_marc_item_fields_to_order { |
683 |
my ($record) = @_; |
684 |
|
685 |
my $syspref = C4::Context->preference('MarcItemFieldsToOrder'); |
686 |
$syspref = "$syspref\n\n"; # YAML is anal on ending \n. Surplus does not hurt |
687 |
my $yaml = eval { |
688 |
YAML::XS::Load(Encode::encode_utf8($syspref)); |
689 |
}; |
690 |
if ( $@ ) { |
691 |
warn "Unable to parse $syspref syspref : $@"; |
692 |
return (); |
693 |
} |
694 |
|
695 |
my @result; |
696 |
my @tags_list; |
697 |
|
698 |
# Check tags in syspref definition |
699 |
for my $field_name ( keys %$yaml ) { |
700 |
my @fields = split /\|/, $yaml->{$field_name}; |
701 |
for my $field ( @fields ) { |
702 |
my ( $f, $sf ) = split /\$/, $field; |
703 |
next unless $f and $sf; |
704 |
push @tags_list, $f; |
705 |
} |
706 |
} |
707 |
@tags_list = List::MoreUtils::uniq(@tags_list); |
708 |
|
709 |
my $tags_count = equal_number_of_fields(\@tags_list, $record); |
710 |
# Return if the number of these fields in the record is not the same. |
711 |
return -1 if $tags_count == -1; |
712 |
|
713 |
# Gather the fields |
714 |
my $fields_hash; |
715 |
foreach my $tag (@tags_list) { |
716 |
my @tmp_fields; |
717 |
foreach my $field ($record->field($tag)) { |
718 |
push @tmp_fields, $field; |
719 |
} |
720 |
$fields_hash->{$tag} = \@tmp_fields; |
721 |
} |
722 |
|
723 |
for (my $i = 0; $i < $tags_count; $i++) { |
724 |
my $r; |
725 |
for my $field_name ( keys %$yaml ) { |
726 |
my @fields = split /\|/, $yaml->{$field_name}; |
727 |
for my $field ( @fields ) { |
728 |
my ( $f, $sf ) = split /\$/, $field; |
729 |
next unless $f and $sf; |
730 |
my $v = $fields_hash->{$f}[$i] ? $fields_hash->{$f}[$i]->subfield( $sf ) : undef; |
731 |
$r->{$field_name} = $v if (defined $v); |
732 |
last if $yaml->{$field}; |
733 |
} |
734 |
} |
735 |
push @result, $r; |
736 |
} |
737 |
return \@result; |
738 |
} |
739 |
- |