1307 lines
49 KiB
Perl
1307 lines
49 KiB
Perl
package Koha::MarcOrder;
|
|
|
|
# Copyright 2023, PTFS-Europe Ltd
|
|
#
|
|
# This file is part of Koha.
|
|
#
|
|
# Koha is free software; you can redistribute it and/or modify it
|
|
# under the terms of the GNU General Public License as published by
|
|
# the Free Software Foundation; either version 3 of the License, or
|
|
# (at your option) any later version.
|
|
#
|
|
# Koha is distributed in the hope that it will be useful, but
|
|
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
# GNU General Public License for more details.
|
|
#
|
|
# You should have received a copy of the GNU General Public License
|
|
# along with Koha; if not, see <https://www.gnu.org/licenses>.
|
|
|
|
use Modern::Perl;
|
|
use Try::Tiny qw( catch try );
|
|
use Net::FTP;
|
|
|
|
use base qw(Koha::Object);
|
|
|
|
use C4::Matcher;
|
|
use C4::ImportBatch qw(
|
|
RecordsFromMARCXMLFile
|
|
RecordsFromISO2709File
|
|
RecordsFromMarcPlugin
|
|
BatchStageMarcRecords
|
|
BatchFindDuplicates
|
|
SetImportBatchMatcher
|
|
SetImportBatchOverlayAction
|
|
SetImportBatchNoMatchAction
|
|
SetImportBatchItemAction
|
|
SetImportBatchStatus
|
|
GetImportBatchOverlayAction
|
|
GetImportBatchNoMatchAction
|
|
GetImportBatchItemAction
|
|
GetImportBatch
|
|
GetImportBatchRangeDesc
|
|
GetNumberOfNonZ3950ImportBatches
|
|
);
|
|
use C4::Search qw( FindDuplicate );
|
|
use C4::Acquisition qw( NewBasket );
|
|
use C4::Biblio qw(
|
|
AddBiblio
|
|
GetMarcFromKohaField
|
|
TransformHtmlToXml
|
|
GetMarcQuantity
|
|
GetMarcPrice
|
|
);
|
|
use C4::Items qw( AddItemFromMarc );
|
|
use C4::Budgets qw( GetBudgetByCode );
|
|
|
|
use Koha::Database;
|
|
use Koha::ImportBatchProfiles;
|
|
use Koha::ImportBatches;
|
|
use Koha::Import::Records;
|
|
use Koha::Acquisition::Currencies;
|
|
use Koha::Acquisition::Booksellers;
|
|
use Koha::Acquisition::Baskets;
|
|
use Koha::Plugins;
|
|
|
|
=head1 NAME
|
|
|
|
Koha::MarcOrder - Koha Marc Order Object class
|
|
|
|
=head1 API
|
|
|
|
=head2 Class methods
|
|
|
|
=cut
|
|
|
|
=head3 create_order_lines_from_file
|
|
|
|
my $result = Koha::MarcOrder->create_order_lines_from_file($args);
|
|
|
|
Controller for file staging, basket creation and order line creation when using the cronjob in marc_ordering_process.pl
|
|
|
|
=cut
|
|
|
|
sub create_order_lines_from_file {
|
|
my ( $self, $args ) = @_;
|
|
|
|
my $filename = $args->{filename};
|
|
my $filepath = $args->{filepath};
|
|
my $profile = $args->{profile};
|
|
my $agent = $args->{agent};
|
|
|
|
my $success;
|
|
my $error;
|
|
|
|
my $vendor_id = $profile->vendor_id;
|
|
my $budget_id = $profile->budget_id;
|
|
|
|
my $vendor_record = Koha::Acquisition::Booksellers->find( { id => $vendor_id } );
|
|
|
|
my $basket_id = _create_basket_for_file(
|
|
{
|
|
filename => $filename,
|
|
filepath => $filepath,
|
|
vendor_id => $vendor_id,
|
|
profile => $profile
|
|
}
|
|
);
|
|
|
|
my $format = index( $filename, '.mrc' ) != -1 ? 'ISO2709' : 'MARCXML';
|
|
my $params = {
|
|
record_type => $profile->record_type,
|
|
encoding => $profile->encoding,
|
|
format => $format,
|
|
filepath => $filepath,
|
|
filename => $filename,
|
|
comments => undef,
|
|
parse_items => $profile->parse_items,
|
|
matcher_id => $profile->matcher_id,
|
|
overlay_action => $profile->overlay_action,
|
|
nomatch_action => $profile->nomatch_action,
|
|
item_action => $profile->item_action,
|
|
};
|
|
|
|
try {
|
|
my $import_batch_id = _stage_file($params);
|
|
|
|
my $import_records = Koha::Import::Records->search(
|
|
{
|
|
import_batch_id => $import_batch_id,
|
|
}
|
|
);
|
|
|
|
while ( my $import_record = $import_records->next ) {
|
|
my $result = add_biblio_from_import_record(
|
|
{
|
|
import_batch_id => $import_batch_id,
|
|
import_record => $import_record,
|
|
matcher_id => $params->{matcher_id},
|
|
overlay_action => $params->{overlay_action},
|
|
agent => $agent,
|
|
}
|
|
);
|
|
warn "Duplicates found in $result->{duplicates_in_batch}, record was skipped."
|
|
if $result->{duplicates_in_batch};
|
|
next if $result->{skip};
|
|
|
|
my $order_line_details = add_items_from_import_record(
|
|
{
|
|
record_result => $result->{record_result},
|
|
basket_id => $basket_id,
|
|
vendor => $vendor_record,
|
|
budget_id => $budget_id,
|
|
agent => $agent,
|
|
}
|
|
);
|
|
}
|
|
SetImportBatchStatus( $import_batch_id, 'imported' )
|
|
if Koha::Import::Records->search( { import_batch_id => $import_batch_id, status => 'imported' } )->count ==
|
|
Koha::Import::Records->search( { import_batch_id => $import_batch_id } )->count;
|
|
|
|
$success = 1;
|
|
} catch {
|
|
$success = 0;
|
|
$error = $_;
|
|
};
|
|
|
|
return $success ? { success => 1, error => '' } : { success => 0, error => $error };
|
|
}
|
|
|
|
=head3 import_record_and_create_order_lines
|
|
|
|
my $result = Koha::MarcOrder->import_record_and_create_order_lines($args);
|
|
|
|
Controller for record import and order line creation when using the interface in addorderiso2709.pl
|
|
|
|
=cut
|
|
|
|
sub import_record_and_create_order_lines {
|
|
my ( $self, $args ) = @_;
|
|
|
|
my $import_batch_id = $args->{import_batch_id};
|
|
my $import_record_id_selected = $args->{import_record_id_selected} || ();
|
|
my $matcher_id = $args->{matcher_id};
|
|
my $overlay_action = $args->{overlay_action};
|
|
my $import_record = $args->{import_record};
|
|
my $client_item_fields = $args->{client_item_fields};
|
|
my $agent = $args->{agent};
|
|
my $basket_id = $args->{basket_id};
|
|
my $budget_id = $args->{budget_id};
|
|
my $vendor = $args->{vendor};
|
|
|
|
my $result = add_biblio_from_import_record(
|
|
{
|
|
import_batch_id => $import_batch_id,
|
|
import_record => $import_record,
|
|
matcher_id => $matcher_id,
|
|
overlay_action => $overlay_action,
|
|
agent => $agent,
|
|
import_record_id_selected => $import_record_id_selected,
|
|
}
|
|
);
|
|
|
|
return {
|
|
duplicates_in_batch => $result->{duplicates_in_batch},
|
|
skip => $result->{skip}
|
|
} if $result->{skip};
|
|
|
|
my $itemnumbers = add_items_from_import_record(
|
|
{
|
|
record_result => $result->{record_result},
|
|
basket_id => $basket_id,
|
|
vendor => $vendor,
|
|
budget_id => $budget_id,
|
|
agent => $agent,
|
|
client_item_fields => $client_item_fields
|
|
}
|
|
);
|
|
|
|
return {
|
|
duplicates_in_batch => 0,
|
|
skip => 0
|
|
};
|
|
}
|
|
|
|
=head3 _create_basket_for_file
|
|
|
|
my $basket_id = _create_basket_for_file({
|
|
filename => $filename,
|
|
vendor_id => $vendor_id,
|
|
profile => $profile
|
|
});
|
|
|
|
Creates a basket ready to receive order lines based on the imported file
|
|
|
|
=cut
|
|
|
|
sub _create_basket_for_file {
|
|
my ($args) = @_;
|
|
|
|
my $filename = $args->{filename};
|
|
my $vendor_id = $args->{vendor_id};
|
|
|
|
my $basket_name = _check_file_for_basket_name($args);
|
|
|
|
# aqbasketname.basketname has a max length of 50 characters so long file names will need to be truncated
|
|
my $basketname = length($basket_name) > 50 ? substr( $basket_name, 0, 50 ) : $basket_name;
|
|
|
|
my $basketno = NewBasket(
|
|
$vendor_id, 0, $basketname, q{},
|
|
q{}, q{}, q{}, q{}, 0, undef
|
|
);
|
|
|
|
return $basketno;
|
|
}
|
|
|
|
=head3 _stage_file
|
|
|
|
$file->_stage_file($params)
|
|
|
|
Stages a file directly using parameters from a MARC ordering account
|
|
|
|
=cut
|
|
|
|
sub _stage_file {
|
|
my ($args) = @_;
|
|
|
|
my $result = Koha::ImportBatch->new_from_file($args);
|
|
|
|
return $result->{report}->{import_batch_id};
|
|
}
|
|
|
|
=head3 _get_syspref_mappings
|
|
|
|
my $syspref_info = _get_syspref_mappings( $marcrecord, $syspref_name );
|
|
|
|
Fetches data from a MARC record based on the mappings in the syspref MarcFieldsToOrder or MarcItemFieldsToOrder using the fields selected in $fields (array).
|
|
|
|
=cut
|
|
|
|
sub _get_syspref_mappings {
|
|
my ( $record, $syspref_to_read ) = @_;
|
|
my $syspref = C4::Context->yaml_preference($syspref_to_read);
|
|
my @result;
|
|
my @tags_list;
|
|
|
|
# Check tags in syspref definition
|
|
for my $field_name ( keys %$syspref ) {
|
|
my @fields = split /\|/, $syspref->{$field_name};
|
|
for my $field (@fields) {
|
|
my ( $f, $sf ) = split /\$/, $field;
|
|
next unless $f and $sf;
|
|
push @tags_list, $f;
|
|
}
|
|
}
|
|
@tags_list = List::MoreUtils::uniq(@tags_list);
|
|
|
|
my $tags_count = _verify_number_of_fields( \@tags_list, $record );
|
|
|
|
# Return if the number of these fields in the record is not the same.
|
|
die "Invalid number of fields detected on field $tags_count->{key}, please check this file" if $tags_count->{error};
|
|
|
|
# Gather the fields
|
|
my $fields_hash;
|
|
foreach my $tag (@tags_list) {
|
|
my @tmp_fields;
|
|
foreach my $field ( $record->field($tag) ) {
|
|
push @tmp_fields, $field;
|
|
}
|
|
$fields_hash->{$tag} = \@tmp_fields;
|
|
}
|
|
|
|
if ( $tags_count->{count} ) {
|
|
for ( my $i = 0 ; $i < $tags_count->{count} ; $i++ ) {
|
|
my $r;
|
|
for my $field_name ( keys %$syspref ) {
|
|
my @fields = split /\|/, $syspref->{$field_name};
|
|
for my $field (@fields) {
|
|
my ( $f, $sf ) = split /\$/, $field;
|
|
next unless $f and $sf;
|
|
my $v = $fields_hash->{$f}[$i] ? $fields_hash->{$f}[$i]->subfield($sf) : undef;
|
|
$r->{$field_name} = $v if ( defined $v );
|
|
last if $syspref->{$field};
|
|
}
|
|
}
|
|
push @result, $r;
|
|
}
|
|
}
|
|
return \@result if $syspref_to_read eq 'MarcItemFieldsToOrder';
|
|
return $result[0] if $syspref_to_read eq 'MarcFieldsToOrder';
|
|
}
|
|
|
|
=head3 _verify_number_of_fields
|
|
|
|
my $tags_count = _verify_number_of_fields(\@tags_list, $record);
|
|
|
|
Verifies that the number of fields in the record is consistent for each field
|
|
|
|
=cut
|
|
|
|
sub _verify_number_of_fields {
|
|
my ( $tags_list, $record ) = @_;
|
|
my $tag_fields_count;
|
|
for my $tag (@$tags_list) {
|
|
my @fields = $record->field($tag);
|
|
$tag_fields_count->{$tag} = scalar @fields;
|
|
}
|
|
|
|
my $tags_count;
|
|
foreach my $key ( keys %$tag_fields_count ) {
|
|
if ( $tag_fields_count->{$key} > 0 ) { # Having 0 of a field is ok
|
|
$tags_count //= $tag_fields_count->{$key}; # Start with the count from the first occurrence
|
|
return { error => 1, key => $key }
|
|
if $tag_fields_count->{$key} !=
|
|
$tags_count; # All counts of various fields should be equal if they exist
|
|
}
|
|
}
|
|
return { error => 0, count => $tags_count };
|
|
}
|
|
|
|
=head3 add_biblio_from_import_record
|
|
|
|
my ($record_results, $duplicates_in_batch) = add_biblio_from_import_record({
|
|
import_record => $import_record,
|
|
matcher_id => $matcher_id,
|
|
overlay_action => $overlay_action,
|
|
import_record_id_selected => $import_record_id_selected,
|
|
agent => $agent,
|
|
import_batch_id => $import_batch_id
|
|
});
|
|
|
|
Takes a set of import records and adds biblio records based on the file content.
|
|
Params matcher_id and overlay_action are taken from the MARC ordering account.
|
|
Returns the new or matched biblionumber and the MARC record for each import record.
|
|
|
|
=cut
|
|
|
|
sub add_biblio_from_import_record {
|
|
my ($args) = @_;
|
|
|
|
my $import_batch_id = $args->{import_batch_id};
|
|
my $import_record_id_selected = $args->{import_record_id_selected} || ();
|
|
my $matcher_id = $args->{matcher_id};
|
|
my $overlay_action = $args->{overlay_action};
|
|
my $import_record = $args->{import_record};
|
|
my $agent = $args->{agent} || "";
|
|
my $duplicates_in_batch;
|
|
|
|
my $duplicates_found = 0;
|
|
if ( $agent eq 'client' ) {
|
|
return {
|
|
record_result => 0,
|
|
duplicates_in_batch => 0,
|
|
skip => 1
|
|
} if not grep { $_ eq $import_record->import_record_id } @{$import_record_id_selected};
|
|
}
|
|
|
|
my $marcrecord = $import_record->get_marc_record || die "Couldn't translate MARC information";
|
|
my $matches = $import_record->get_import_record_matches( { chosen => 1 } );
|
|
my $match = $matches->count ? $matches->next : undef;
|
|
my $biblionumber = $match ? $match->candidate_match_id : 0;
|
|
my $biblio = $biblionumber ? Koha::Biblios->find($biblionumber) : undef;
|
|
|
|
if ($biblio) {
|
|
$import_record->status('imported')->store;
|
|
if ( $overlay_action eq 'replace' ) {
|
|
$import_record->replace( { biblio => $biblio } );
|
|
}
|
|
} else {
|
|
if ($matcher_id) {
|
|
if ( $matcher_id eq '_TITLE_AUTHOR_' ) {
|
|
my @matches = FindDuplicate($marcrecord);
|
|
$duplicates_found = 1 if @matches;
|
|
} else {
|
|
my $matcher = C4::Matcher->fetch($matcher_id);
|
|
my @matches = $matcher->get_matches( $marcrecord, my $max_matches = 1 );
|
|
$duplicates_found = 1 if @matches;
|
|
}
|
|
return {
|
|
record_result => 0,
|
|
duplicates_in_batch => $import_batch_id,
|
|
skip => 1
|
|
} if $duplicates_found;
|
|
}
|
|
|
|
# add the biblio if no matches were found
|
|
if ( !$duplicates_found ) {
|
|
( $biblionumber, undef ) = AddBiblio( $marcrecord, '' );
|
|
$import_record->status('imported')->store;
|
|
}
|
|
}
|
|
$import_record->import_biblio->matched_biblionumber($biblionumber)->store;
|
|
|
|
my $record_result = {
|
|
biblionumber => $biblionumber,
|
|
marcrecord => $marcrecord,
|
|
import_record_id => $import_record->import_record_id,
|
|
};
|
|
|
|
return {
|
|
record_result => $record_result,
|
|
duplicates_in_batch => $duplicates_in_batch,
|
|
skip => 0
|
|
};
|
|
}
|
|
|
|
=head3 add_items_from_import_record
|
|
|
|
my $order_line_details = add_items_from_import_record({
|
|
record_result => $record_result,
|
|
basket_id => $basket_id,
|
|
vendor => $vendor,
|
|
budget_id => $budget_id,
|
|
agent => $agent,
|
|
client_item_fields => $client_item_fields
|
|
});
|
|
|
|
Adds items to biblio records based on mappings in MarcItemFieldsToOrder.
|
|
Returns an array of order line details based on newly added items.
|
|
If being called from addorderiso2709.pl then client_item_fields is a hash of all the UI form inputs needed by the script.
|
|
|
|
=cut
|
|
|
|
sub add_items_from_import_record {
|
|
my ($args) = @_;
|
|
|
|
my $record_result = $args->{record_result};
|
|
my $basket_id = $args->{basket_id};
|
|
my $budget_id = $args->{budget_id};
|
|
my $vendor = $args->{vendor};
|
|
my $agent = $args->{agent};
|
|
my $client_item_fields = $args->{client_item_fields} || undef;
|
|
my $active_currency = Koha::Acquisition::Currencies->get_active;
|
|
my $biblionumber = $record_result->{biblionumber};
|
|
my $marcrecord = $record_result->{marcrecord};
|
|
|
|
if ( $agent eq 'cron' ) {
|
|
my $marc_fields_to_order = _get_syspref_mappings( $marcrecord, 'MarcFieldsToOrder' );
|
|
my $marc_item_fields_to_order = _get_syspref_mappings( $marcrecord, 'MarcItemFieldsToOrder' );
|
|
|
|
my $item_fields = _create_item_fields_from_syspref(
|
|
{
|
|
marc_fields_to_order => $marc_fields_to_order,
|
|
marc_item_fields_to_order => $marc_item_fields_to_order,
|
|
budget_id => $budget_id
|
|
}
|
|
);
|
|
|
|
my $order_line_fields = parse_input_into_order_line_fields(
|
|
{
|
|
agent => $agent,
|
|
biblionumber => $biblionumber,
|
|
budget_id => $budget_id,
|
|
basket_id => $basket_id,
|
|
fields => $item_fields,
|
|
marcrecord => $marcrecord,
|
|
}
|
|
);
|
|
|
|
my $itemnumbers = create_items_and_generate_order_hash(
|
|
{
|
|
fields => $order_line_fields,
|
|
vendor => $vendor,
|
|
agent => $agent,
|
|
active_currency => $active_currency,
|
|
}
|
|
);
|
|
|
|
return $itemnumbers;
|
|
}
|
|
|
|
if ( $agent eq 'client' ) {
|
|
my $order_line_fields = parse_input_into_order_line_fields(
|
|
{
|
|
agent => $agent,
|
|
biblionumber => $biblionumber,
|
|
budget_id => $budget_id,
|
|
basket_id => $basket_id,
|
|
fields => $client_item_fields,
|
|
marcrecord => $marcrecord,
|
|
}
|
|
);
|
|
|
|
my $order_line_details = create_items_and_generate_order_hash(
|
|
{
|
|
fields => $order_line_fields,
|
|
vendor => $vendor,
|
|
agent => $agent,
|
|
active_currency => $active_currency,
|
|
}
|
|
);
|
|
|
|
return $order_line_details;
|
|
}
|
|
}
|
|
|
|
=head3 match_file_to_account
|
|
|
|
my $file_match = Koha::MarcOrder->match_file_to_account({
|
|
filename => $filename,
|
|
filepath => $filepath,
|
|
profile => $profile
|
|
});
|
|
|
|
Used by the cronjob to detect whether a file matches the account and should be processed
|
|
This method only checks the first record in the file.
|
|
|
|
=cut
|
|
|
|
sub match_file_to_account {
|
|
my ( $self, $args ) = @_;
|
|
|
|
my $profile = $args->{profile};
|
|
|
|
my $match = 0;
|
|
my $match_record = _retrieve_first_record_from_batch($args);
|
|
|
|
my ( $field, $subfield ) = split /\$/, $profile->match_field;
|
|
|
|
my $field_value = $match_record->subfield( $field, $subfield ) || '';
|
|
my $match_value = $profile->match_value || '';
|
|
|
|
if ( $field_value eq $match_value ) {
|
|
$match = 1;
|
|
}
|
|
|
|
return $match;
|
|
}
|
|
|
|
=head3 _check_file_for_basket_name
|
|
|
|
my $basket_name = _check_file_for_basket_name({
|
|
filename => $filename,
|
|
filepath => $filepath,
|
|
profile => $profile
|
|
});
|
|
|
|
Checks to see if the account has a basket name field assigned.
|
|
If yes, it retrieves this value to use as the name.
|
|
If not, to uses the filename.
|
|
|
|
=cut
|
|
|
|
sub _check_file_for_basket_name {
|
|
my ($args) = @_;
|
|
|
|
my $profile = $args->{profile};
|
|
|
|
my $filename = $args->{filename};
|
|
return $filename if !$profile->basket_name_field;
|
|
|
|
my $first_record = _retrieve_first_record_from_batch($args);
|
|
|
|
my ( $field, $subfield ) = split /\$/, $profile->basket_name_field;
|
|
|
|
my $field_value = $first_record->subfield( $field, $subfield ) || '';
|
|
|
|
return $field_value ? $field_value : $filename;
|
|
}
|
|
|
|
=head3 import_batches_list
|
|
|
|
Fetches import batches matching the batch to be added to the basket and returns these to the template
|
|
|
|
Koha::MarcOrder->import_batches_list();
|
|
|
|
=cut
|
|
|
|
sub import_batches_list {
|
|
my ($self) = @_;
|
|
my $batches = GetImportBatchRangeDesc();
|
|
|
|
my @list = ();
|
|
foreach my $batch (@$batches) {
|
|
if ( $batch->{'import_status'} =~ /^staged$|^reverted$/ && $batch->{'record_type'} eq 'biblio' ) {
|
|
|
|
# check if there is at least 1 line still staged
|
|
my $import_records_count = Koha::Import::Records->search(
|
|
{
|
|
import_batch_id => $batch->{'import_batch_id'},
|
|
status => $batch->{import_status}
|
|
}
|
|
)->count;
|
|
if ($import_records_count) {
|
|
push @list, {
|
|
import_batch_id => $batch->{'import_batch_id'},
|
|
num_records => $batch->{'num_records'},
|
|
num_items => $batch->{'num_items'},
|
|
staged_date => $batch->{'upload_timestamp'},
|
|
import_status => $batch->{'import_status'},
|
|
file_name => $batch->{'file_name'},
|
|
comments => $batch->{'comments'},
|
|
};
|
|
} else {
|
|
|
|
# if there are no more line to includes, set the status to imported
|
|
# FIXME This should be removed in the future.
|
|
SetImportBatchStatus( $batch->{'import_batch_id'}, 'imported' );
|
|
}
|
|
}
|
|
}
|
|
my $num_batches = GetNumberOfNonZ3950ImportBatches();
|
|
|
|
return {
|
|
list => \@list,
|
|
num_results => $num_batches
|
|
};
|
|
}
|
|
|
|
=head3 import_biblios_list
|
|
|
|
For an import batch, this function reads the files and creates all the relevant data pertaining to that file
|
|
It then returns this to the template to be shown in the UI
|
|
|
|
Koha::MarcOrder->import_biblios_list( $cgiparams->{'import_batch_id'} );
|
|
|
|
=cut
|
|
|
|
sub import_biblios_list {
|
|
my ( $self, $import_batch_id ) = @_;
|
|
my $batch = GetImportBatch( $import_batch_id, 'staged' );
|
|
return () unless $batch and $batch->{import_status} =~ /^staged$|^reverted$/;
|
|
my $import_records = Koha::Import::Records->search(
|
|
{
|
|
import_batch_id => $import_batch_id,
|
|
status => $batch->{import_status}
|
|
}
|
|
);
|
|
my @list = ();
|
|
my $item_error = 0;
|
|
|
|
my $ccodes = {
|
|
map { $_->{authorised_value} => $_->{opac_description} }
|
|
Koha::AuthorisedValues->get_descriptions_by_koha_field(
|
|
{ frameworkcode => '', kohafield => 'items.ccode' }
|
|
)
|
|
};
|
|
my $locations = {
|
|
map { $_->{authorised_value} => $_->{opac_description} }
|
|
Koha::AuthorisedValues->get_descriptions_by_koha_field(
|
|
{ frameworkcode => '', kohafield => 'items.location' }
|
|
)
|
|
};
|
|
my $notforloans = {
|
|
map { $_->{authorised_value} => $_->{lib} } Koha::AuthorisedValues->get_descriptions_by_koha_field(
|
|
{ frameworkcode => '', kohafield => 'items.notforloan' }
|
|
)
|
|
};
|
|
|
|
# location list
|
|
my @locations;
|
|
foreach ( sort keys %$locations ) {
|
|
push @locations, { code => $_, description => "$_ - " . $locations->{$_} };
|
|
}
|
|
my @ccodes;
|
|
foreach ( sort { $ccodes->{$a} cmp $ccodes->{$b} } keys %$ccodes ) {
|
|
push @ccodes, { code => $_, description => $ccodes->{$_} };
|
|
}
|
|
my @notforloans;
|
|
foreach ( sort { $notforloans->{$a} cmp $notforloans->{$b} } keys %$notforloans ) {
|
|
push @notforloans, { code => $_, description => $notforloans->{$_} };
|
|
}
|
|
|
|
my $biblio_count = 0;
|
|
while ( my $import_record = $import_records->next ) {
|
|
my $item_id = 1;
|
|
$biblio_count++;
|
|
my $matches = $import_record->get_import_record_matches( { chosen => 1 } );
|
|
my $match = $matches->count ? $matches->next : undef;
|
|
my $match_biblio = $match ? Koha::Biblios->find( { biblionumber => $match->candidate_match_id } ) : undef;
|
|
my %cellrecord = (
|
|
import_record_id => $import_record->import_record_id,
|
|
import_biblio => $import_record->import_biblio,
|
|
import => 1,
|
|
status => $import_record->status,
|
|
record_sequence => $import_record->record_sequence,
|
|
overlay_status => $import_record->overlay_status,
|
|
match_biblionumber => $match ? $match->candidate_match_id : 0,
|
|
match_citation => $match_biblio
|
|
? ( $match_biblio->title || '' ) . ' ' . ( $match_biblio->author || '' )
|
|
: '',
|
|
match_score => $match ? $match->score : 0,
|
|
);
|
|
my $marcrecord = $import_record->get_marc_record || die "couldn't translate MARC information";
|
|
|
|
my $infos = _get_syspref_mappings( $marcrecord, 'MarcFieldsToOrder' );
|
|
my $price =
|
|
$infos->{price} ? $infos->{price} : GetMarcPrice( $marcrecord, C4::Context->preference('marcflavour') );
|
|
my $replacementprice = $infos->{replacementprice} || undef;
|
|
my $quantity = $infos->{quantity} || undef;
|
|
my $budget_code = $infos->{budget_code} || undef;
|
|
my $discount = $infos->{discount} || undef;
|
|
my $sort1 = $infos->{sort1} || undef;
|
|
my $sort2 = $infos->{sort2} || undef;
|
|
my $budget_id;
|
|
|
|
if ($budget_code) {
|
|
my $biblio_budget = GetBudgetByCode($budget_code);
|
|
if ($biblio_budget) {
|
|
$budget_id = $biblio_budget->{budget_id};
|
|
}
|
|
}
|
|
|
|
# Items
|
|
my @itemlist = ();
|
|
my $all_items_quantity = 0;
|
|
my $alliteminfos = _get_syspref_mappings( $marcrecord, 'MarcItemFieldsToOrder' );
|
|
|
|
if ( $alliteminfos != -1 ) {
|
|
foreach my $iteminfos (@$alliteminfos) {
|
|
|
|
# Quantity is required, default to one if not supplied
|
|
my $quantity = delete $iteminfos->{quantity} || 1;
|
|
|
|
# Handle incorrectly named original parameters for MarcItemFieldsToOrder
|
|
$iteminfos->{location} = delete $iteminfos->{loc} if $iteminfos->{loc};
|
|
|
|
# Convert budget code to a budget id
|
|
my $item_budget_code = delete $iteminfos->{budget_code};
|
|
if ($item_budget_code) {
|
|
my $item_budget = GetBudgetByCode($item_budget_code);
|
|
$iteminfos->{budget_id} = $item_budget->{budget_id} || $budget_id;
|
|
}
|
|
|
|
# Clone the item data for the needed quantity
|
|
# Add the incremented item id for each item in that quantity
|
|
for ( my $i = 0 ; $i < $quantity ; $i++ ) {
|
|
my $itemrecord = {%$iteminfos};
|
|
$itemrecord->{item_id} = $item_id++;
|
|
|
|
$all_items_quantity++;
|
|
push @itemlist, $itemrecord;
|
|
}
|
|
}
|
|
|
|
$cellrecord{'iteminfos'} = \@itemlist;
|
|
} else {
|
|
$cellrecord{'item_error'} = 1;
|
|
}
|
|
push @list, \%cellrecord;
|
|
|
|
# If MarcItemFieldsToOrder is not set, we use MarcFieldsToOrder to populate the order form.
|
|
if ( $alliteminfos || %$alliteminfos == -1 ) {
|
|
$cellrecord{price} = $price || '';
|
|
$cellrecord{replacementprice} = $replacementprice || '';
|
|
$cellrecord{quantity} = $quantity || '';
|
|
$cellrecord{budget_id} = $budget_id || '';
|
|
} else {
|
|
|
|
# When using MarcItemFields to order we want the order to have the same quantity as total items
|
|
$cellrecord{quantity} = $all_items_quantity;
|
|
}
|
|
|
|
# The fields discount, sort1, and sort2 only exist at the order level, so always use MarcItemFieldsToOrder
|
|
$cellrecord{discount} = $discount || '';
|
|
$cellrecord{sort1} = $sort1 || '';
|
|
$cellrecord{sort2} = $sort2 || '';
|
|
|
|
}
|
|
my $num_records = $batch->{'num_records'};
|
|
my $overlay_action = GetImportBatchOverlayAction($import_batch_id);
|
|
my $nomatch_action = GetImportBatchNoMatchAction($import_batch_id);
|
|
my $item_action = GetImportBatchItemAction($import_batch_id);
|
|
my $result = {
|
|
import_biblio_list => \@list,
|
|
num_results => $num_records,
|
|
import_batch_id => $import_batch_id,
|
|
overlay_action => $overlay_action,
|
|
nomatch_action => $nomatch_action,
|
|
item_action => $item_action,
|
|
item_error => $item_error,
|
|
locationloop => \@locations,
|
|
ccodeloop => \@ccodes,
|
|
notforloanloop => \@notforloans,
|
|
batch => $batch,
|
|
};
|
|
|
|
if ( $batch->{'num_records'} > 0 ) {
|
|
if ( $batch->{'import_status'} eq 'staged' or $batch->{'import_status'} eq 'reverted' ) {
|
|
$result->{can_commit} = 1;
|
|
}
|
|
if ( $batch->{'import_status'} eq 'imported' ) {
|
|
$result->{can_revert} = 1;
|
|
}
|
|
}
|
|
if ( defined $batch->{'matcher_id'} ) {
|
|
my $matcher = C4::Matcher->fetch( $batch->{'matcher_id'} );
|
|
if ( defined $matcher ) {
|
|
$result->{'current_matcher_id'} = $batch->{'matcher_id'};
|
|
$result->{'current_matcher_code'} = $matcher->code();
|
|
$result->{'current_matcher_description'} = $matcher->description();
|
|
}
|
|
}
|
|
|
|
my @matchers = C4::Matcher::GetMatcherList();
|
|
if ( defined $batch->{'matcher_id'} ) {
|
|
for ( my $i = 0 ; $i <= $#matchers ; $i++ ) {
|
|
if ( $matchers[$i]->{'matcher_id'} == $batch->{'matcher_id'} ) {
|
|
$matchers[$i]->{'selected'} = 1;
|
|
}
|
|
}
|
|
}
|
|
$result->{available_matchers} = \@matchers;
|
|
|
|
return $result;
|
|
}
|
|
|
|
=head3 parse_input_into_order_line_fields
|
|
|
|
This function takes inputs from either the cronjob or UI and then parses that into a single set of order line fields that can be used to create items and order lines
|
|
|
|
my $order_line_fields = parse_input_into_order_line_fields(
|
|
{
|
|
agent => $agent,
|
|
biblionumber => $biblionumber,
|
|
budget_id => $budget_id,
|
|
basket_id => $basket_id,
|
|
fields => $item_fields,
|
|
marcrecord => $marcrecord,
|
|
}
|
|
);
|
|
|
|
=cut
|
|
|
|
sub parse_input_into_order_line_fields {
|
|
my ($args) = @_;
|
|
|
|
my $agent = $args->{agent};
|
|
my $client = $agent eq 'client' ? 1 : 0;
|
|
my $biblionumber = $args->{biblionumber};
|
|
my $budget_id = $args->{budget_id};
|
|
my $basket_id = $args->{basket_id};
|
|
my $fields = $args->{fields};
|
|
my $marcrecord = $args->{marcrecord};
|
|
|
|
my $quantity = $fields->{quantity} || $fields->{c_quantity} || 1;
|
|
my @homebranches = $fields->{homebranches} ? @{ $fields->{homebranches} } : ();
|
|
my @holdingbranches = $fields->{holdingbranches} ? @{ $fields->{holdingbranches} } : ();
|
|
my @itypes = $fields->{itypes} ? @{ $fields->{itypes} } : ();
|
|
my @nonpublic_notes = $fields->{nonpublic_notes} ? @{ $fields->{nonpublic_notes} } : ();
|
|
my @public_notes = $fields->{public_notes} ? @{ $fields->{public_notes} } : ();
|
|
my @locs = $fields->{locs} ? @{ $fields->{locs} } : ();
|
|
my @ccodes = $fields->{ccodes} ? @{ $fields->{ccodes} } : ();
|
|
my @notforloans = $fields->{notforloans} ? @{ $fields->{notforloans} } : ();
|
|
my @uris = $fields->{uris} ? @{ $fields->{uris} } : ();
|
|
my @copynos = $fields->{copynos} ? @{ $fields->{copynos} } : ();
|
|
my @itemprices = $fields->{itemprices} ? @{ $fields->{itemprices} } : ();
|
|
my @replacementprices = $fields->{replacementprices} ? @{ $fields->{replacementprices} } : ();
|
|
my @itemcallnumbers = $fields->{itemcallnumbers} ? @{ $fields->{itemcallnumbers} } : ();
|
|
my @coded_location_qualifiers =
|
|
$fields->{coded_location_qualifiers} ? @{ $fields->{coded_location_qualifiers} } : ();
|
|
my @barcodes = $fields->{barcodes} ? @{ $fields->{barcodes} } : ();
|
|
my @enumchrons = $fields->{enumchrons} ? @{ $fields->{enumchrons} } : ();
|
|
my @budget_codes = $fields->{budget_codes} ? @{ $fields->{budget_codes} } : ();
|
|
my $c_quantity = $fields->{c_quantity};
|
|
my $c_budget = GetBudgetByCode( $fields->{c_budget_code} );
|
|
my $c_budget_id = $c_budget->{budget_id} || $fields->{c_budget_id};
|
|
my $c_discount = $fields->{c_discount};
|
|
my $c_sort1 = $fields->{c_sort1};
|
|
my $c_sort2 = $fields->{c_sort2};
|
|
my $c_replacement_price = $fields->{c_replacement_price};
|
|
my $c_price = $fields->{c_price};
|
|
|
|
# If using the cronjob, we want to default to the account budget if not mapped on the record
|
|
if ( !$client && ( !@budget_codes || scalar(@budget_codes) == 0 ) ) {
|
|
for ( 1 .. $quantity ) {
|
|
if ($c_budget_id) {
|
|
push( @budget_codes, $c_budget_id );
|
|
} else {
|
|
push( @budget_codes, $budget_id );
|
|
}
|
|
}
|
|
}
|
|
my $loop_limit = $quantity;
|
|
|
|
my $order_line_fields = {
|
|
biblionumber => $biblionumber,
|
|
homebranch => \@homebranches,
|
|
holdingbranch => \@holdingbranches,
|
|
itemnotes_nonpublic => \@nonpublic_notes,
|
|
itemnotes => \@public_notes,
|
|
location => \@locs,
|
|
ccode => \@ccodes,
|
|
itype => \@itypes,
|
|
notforloan => \@notforloans,
|
|
uri => \@uris,
|
|
copynumber => \@copynos,
|
|
price => \@itemprices,
|
|
replacementprice => \@replacementprices,
|
|
itemcallnumber => \@itemcallnumbers,
|
|
coded_location_qualifier => \@coded_location_qualifiers,
|
|
barcode => \@barcodes,
|
|
enumchron => \@enumchrons,
|
|
budget_code => \@budget_codes,
|
|
loop_limit => $loop_limit,
|
|
basket_id => $basket_id,
|
|
budget_id => $budget_id,
|
|
c_quantity => $c_quantity,
|
|
c_budget_id => $c_budget_id,
|
|
c_discount => $c_discount,
|
|
c_sort1 => $c_sort1,
|
|
c_sort2 => $c_sort2,
|
|
c_replacement_price => $c_replacement_price,
|
|
c_price => $c_price,
|
|
marcrecord => $marcrecord,
|
|
tags => $fields->{tags},
|
|
subfields => $fields->{subfields},
|
|
field_values => $fields->{field_values},
|
|
serials => $fields->{serials},
|
|
order_vendornote => $fields->{order_vendornote},
|
|
order_internalnote => $fields->{order_internalnote},
|
|
all_currency => $fields->{all_currency},
|
|
};
|
|
|
|
return $order_line_fields;
|
|
}
|
|
|
|
=head3 create_items_and_generate_order_hash
|
|
|
|
This method is used from both the cronjob and the UI to create items and generate order line details for those new items
|
|
|
|
my $order_line_details = create_items_and_generate_order_hash(
|
|
{
|
|
fields => $order_line_fields,
|
|
vendor => $vendor,
|
|
agent => $agent,
|
|
active_currency => $active_currency,
|
|
}
|
|
);
|
|
|
|
=cut
|
|
|
|
sub create_items_and_generate_order_hash {
|
|
my ($args) = @_;
|
|
|
|
my $agent = $args->{agent};
|
|
my $fields = $args->{fields};
|
|
my $loop_limit = $fields->{loop_limit};
|
|
my $basket_id = $fields->{basket_id};
|
|
my $budget_id = $fields->{budget_id};
|
|
my $vendor = $args->{vendor};
|
|
my $active_currency = $args->{active_currency};
|
|
my $itemcreation = 0;
|
|
my @itemnumbers;
|
|
|
|
# We directly create the items if MarcItemFieldsToOrder is populated (item fields have values)
|
|
if ( C4::Context->preference('AcqCreateItem') ne 'cataloguing' && @{ $fields->{homebranch} } ) {
|
|
for ( my $i = 0 ; $i < $loop_limit ; $i++ ) {
|
|
$itemcreation = 1;
|
|
my $item = Koha::Item->new(
|
|
{
|
|
biblionumber => $fields->{biblionumber},
|
|
homebranch => @{ $fields->{homebranch} }[$i],
|
|
holdingbranch => @{ $fields->{holdingbranch} }[$i],
|
|
itemnotes_nonpublic => @{ $fields->{itemnotes_nonpublic} }[$i],
|
|
itemnotes => @{ $fields->{itemnotes} }[$i],
|
|
location => @{ $fields->{location} }[$i],
|
|
ccode => @{ $fields->{ccode} }[$i],
|
|
itype => @{ $fields->{itype} }[$i],
|
|
notforloan => @{ $fields->{notforloan} }[$i],
|
|
uri => @{ $fields->{uri} }[$i],
|
|
copynumber => @{ $fields->{copynumber} }[$i],
|
|
price => @{ $fields->{price} }[$i],
|
|
replacementprice => @{ $fields->{replacementprice} }[$i],
|
|
itemcallnumber => @{ $fields->{itemcallnumber} }[$i],
|
|
coded_location_qualifier => @{ $fields->{coded_location_qualifier} }[$i],
|
|
barcode => @{ $fields->{barcode} }[$i],
|
|
enumchron => @{ $fields->{enumchron} }[$i],
|
|
}
|
|
)->store;
|
|
push( @itemnumbers, $item->itemnumber );
|
|
}
|
|
}
|
|
|
|
if ( $itemcreation == 1 ) {
|
|
|
|
# Group orderlines from MarcItemFieldsToOrder
|
|
my $budget_hash;
|
|
my @budget_ids = @{ $fields->{budget_code} };
|
|
for ( my $i = 0 ; $i < $loop_limit ; $i++ ) {
|
|
$budget_ids[$i] = $budget_id if !$budget_ids[$i]; # Use default budget if no budget provided
|
|
$budget_hash->{ $budget_ids[$i] }->{quantity} += 1;
|
|
$budget_hash->{ $budget_ids[$i] }->{price} = @{ $fields->{price} }[$i] || $fields->{c_price};
|
|
$budget_hash->{ $budget_ids[$i] }->{replacementprice} =
|
|
@{ $fields->{replacementprice} }[$i] || $fields->{c_replacement_price};
|
|
$budget_hash->{ $budget_ids[$i] }->{itemnumbers} //= [];
|
|
push @{ $budget_hash->{ $budget_ids[$i] }->{itemnumbers} },
|
|
$itemnumbers[$i];
|
|
}
|
|
|
|
# Create orderlines from MarcItemFieldsToOrder
|
|
while ( my ( $budget_id, $infos ) = each %$budget_hash ) {
|
|
if ($budget_id) {
|
|
my %orderinfo = (
|
|
biblionumber => $fields->{biblionumber},
|
|
basketno => $basket_id,
|
|
quantity => $infos->{quantity},
|
|
budget_id => $budget_id,
|
|
currency => $active_currency->currency,
|
|
);
|
|
|
|
my $price = $infos->{price};
|
|
if ($price) {
|
|
$price = _format_price_to_CurrencyFormat_syspref($price);
|
|
$price = Koha::Number::Price->new($price)->unformat;
|
|
$orderinfo{tax_rate_on_ordering} = $vendor->tax_rate;
|
|
$orderinfo{tax_rate_on_receiving} = $vendor->tax_rate;
|
|
my $order_discount = $fields->{c_discount} ? $fields->{c_discount} : $vendor->discount;
|
|
$orderinfo{discount} = $order_discount;
|
|
$orderinfo{rrp} = $price;
|
|
$orderinfo{ecost} = $order_discount ? $price * ( 1 - $order_discount / 100 ) : $price;
|
|
$orderinfo{listprice} = $orderinfo{rrp} / $active_currency->rate;
|
|
$orderinfo{unitprice} = $orderinfo{ecost};
|
|
$orderinfo{sort1} = $fields->{c_sort1};
|
|
$orderinfo{sort2} = $fields->{c_sort2};
|
|
} else {
|
|
$orderinfo{listprice} = 0;
|
|
}
|
|
$orderinfo{replacementprice} = $infos->{replacementprice} || 0;
|
|
|
|
# Remove uncertainprice flag if we have found a price in the MARC record
|
|
$orderinfo{uncertainprice} = 0 if $orderinfo{listprice};
|
|
Koha::Plugins->call(
|
|
'before_orderline_create',
|
|
{
|
|
marcrecord => $fields->{marcrecord},
|
|
orderline => \%orderinfo,
|
|
marcfields => $fields
|
|
}
|
|
);
|
|
|
|
my $order = Koha::Acquisition::Order->new( \%orderinfo );
|
|
$order->populate_with_prices_for_ordering();
|
|
$order->populate_with_prices_for_receiving();
|
|
$order->store;
|
|
$order->add_item($_) for @{ $budget_hash->{$budget_id}->{itemnumbers} };
|
|
}
|
|
}
|
|
} else {
|
|
|
|
# Here we are using the 'MARC' for items from the 'Item information' tab for creating the items
|
|
# Add an orderline for each MARC record
|
|
# Get quantity in the MARC record (1 if none)
|
|
my $quantity = GetMarcQuantity( $fields->{marcrecord}, C4::Context->preference('marcflavour') ) || 1;
|
|
my %orderinfo = (
|
|
biblionumber => $fields->{biblionumber},
|
|
basketno => $basket_id,
|
|
quantity => $fields->{c_quantity},
|
|
branchcode => C4::Context->userenv()->{'branch'},
|
|
budget_id => $fields->{c_budget_id},
|
|
uncertainprice => 1,
|
|
sort1 => $fields->{c_sort1},
|
|
sort2 => $fields->{c_sort2},
|
|
order_internalnote => $fields->{order_internalnote},
|
|
order_vendornote => $fields->{order_vendornote},
|
|
currency => $fields->{all_currency},
|
|
replacementprice => $fields->{c_replacement_price},
|
|
);
|
|
|
|
# Get the price if there is one.
|
|
if ( $fields->{c_price} ) {
|
|
$fields->{c_price} = _format_price_to_CurrencyFormat_syspref( $fields->{c_price} );
|
|
$fields->{c_price} = Koha::Number::Price->new( $fields->{c_price} )->unformat;
|
|
$orderinfo{tax_rate_on_ordering} = $vendor->tax_rate;
|
|
$orderinfo{tax_rate_on_receiving} = $vendor->tax_rate;
|
|
my $order_discount = $fields->{c_discount} ? $fields->{c_discount} : $vendor->discount;
|
|
$orderinfo{discount} = $order_discount;
|
|
$orderinfo{rrp} = $fields->{c_price};
|
|
$orderinfo{ecost} =
|
|
$order_discount ? $fields->{c_price} * ( 1 - $order_discount / 100 ) : $fields->{c_price};
|
|
$orderinfo{listprice} = $orderinfo{rrp} / $active_currency->rate;
|
|
$orderinfo{unitprice} = $orderinfo{ecost};
|
|
} else {
|
|
$orderinfo{listprice} = 0;
|
|
}
|
|
|
|
# Remove uncertainprice flag if we have found a price in the MARC record
|
|
$orderinfo{uncertainprice} = 0 if $orderinfo{listprice};
|
|
Koha::Plugins->call(
|
|
'before_orderline_create',
|
|
{
|
|
marcrecord => $fields->{marcrecord},
|
|
orderline => \%orderinfo,
|
|
marcfields => $fields
|
|
}
|
|
);
|
|
|
|
my $order = Koha::Acquisition::Order->new( \%orderinfo );
|
|
$order->populate_with_prices_for_ordering();
|
|
$order->populate_with_prices_for_receiving();
|
|
$order->store;
|
|
|
|
my $basket = Koha::Acquisition::Baskets->find($basket_id);
|
|
if ( C4::Context->preference('AcqCreateItem') ne 'cataloguing'
|
|
&& $basket->effective_create_items eq 'ordering'
|
|
&& !$basket->is_standing )
|
|
{
|
|
my $tags = $fields->{tags} || [];
|
|
my $subfields = $fields->{subfields} || [];
|
|
my $field_values = $fields->{field_values} || [];
|
|
my $serials = $fields->{serials} || [];
|
|
my $xml = TransformHtmlToXml( $tags, $subfields, $field_values );
|
|
my $record = MARC::Record::new_from_xml( $xml, 'UTF-8' );
|
|
for ( my $qtyloop = 1 ; $qtyloop <= $fields->{c_quantity} ; $qtyloop++ ) {
|
|
my ( $biblionumber, undef, $itemnumber ) =
|
|
AddItemFromMarc( $record, $fields->{biblionumber} );
|
|
$order->add_item($itemnumber);
|
|
push @itemnumbers, $itemnumber;
|
|
}
|
|
}
|
|
}
|
|
|
|
return \@itemnumbers;
|
|
}
|
|
|
|
=head3 _format_price_to_CurrencyFormat_syspref
|
|
|
|
In France, the cents separator is the ',' but sometimes a '.' is used
|
|
In this case, the price will be x100 when unformatted
|
|
The '.' needs replacing by a ',' to get a proper price calculation
|
|
|
|
=cut
|
|
|
|
sub _format_price_to_CurrencyFormat_syspref {
|
|
my ($price) = @_;
|
|
|
|
$price =~ s/\./,/ if C4::Context->preference("CurrencyFormat") eq "FR";
|
|
return $price;
|
|
}
|
|
|
|
=head3 _create_item_fields_from_syspref
|
|
|
|
Takes the two sysprefs and returns the item fields required to process and create orderlines
|
|
|
|
my $item_fields = _create_item_fields_from_syspref(
|
|
{
|
|
marc_fields_to_order => $marc_fields_to_order,
|
|
marc_item_fields_to_order => $marc_item_fields_to_order
|
|
}
|
|
);
|
|
|
|
=cut
|
|
|
|
sub _create_item_fields_from_syspref {
|
|
my ($args) = @_;
|
|
|
|
my $marc_item_fields_to_order = $args->{marc_item_fields_to_order};
|
|
my $marc_fields_to_order = $args->{marc_fields_to_order};
|
|
my $budget_id = $args->{budget_id};
|
|
|
|
my @homebranches = ();
|
|
my @holdingbranches = ();
|
|
my @itypes = ();
|
|
my @nonpublic_notes = ();
|
|
my @public_notes = ();
|
|
my @locs = ();
|
|
my @ccodes = ();
|
|
my @notforloans = ();
|
|
my @uris = ();
|
|
my @copynos = ();
|
|
my @budget_codes = ();
|
|
my @itemprices = ();
|
|
my @replacementprices = ();
|
|
my @itemcallnumbers = ();
|
|
my @coded_location_qualifiers = ();
|
|
my @barcodes = ();
|
|
my @enumchrons = ();
|
|
|
|
foreach my $infoset (@$marc_item_fields_to_order) {
|
|
my $quantity = $infoset->{quantity} || 1;
|
|
for ( my $i = 0 ; $i < $quantity ; $i++ ) {
|
|
my $budget_code;
|
|
if ( !$infoset->{budget_code} ) {
|
|
if ( $marc_fields_to_order->{budget_code} ) {
|
|
$budget_code = $marc_fields_to_order->{budget_code};
|
|
}
|
|
} else {
|
|
$budget_code = $infoset->{budget_code};
|
|
}
|
|
|
|
my $item_budget_id;
|
|
my $item_budget = GetBudgetByCode($budget_code);
|
|
if ($item_budget) {
|
|
$item_budget_id = $item_budget->{budget_id};
|
|
} else {
|
|
$item_budget_id = $budget_id;
|
|
}
|
|
|
|
push @homebranches, $infoset->{homebranch};
|
|
push @holdingbranches, $infoset->{holdingbranch};
|
|
push @itypes, $infoset->{itype};
|
|
push @nonpublic_notes, $infoset->{nonpublic_note};
|
|
push @public_notes, $infoset->{public_note};
|
|
push @locs, $infoset->{loc};
|
|
push @ccodes, $infoset->{ccode};
|
|
push @notforloans, $infoset->{notforloan};
|
|
push @uris, $infoset->{uri};
|
|
push @copynos, $infoset->{copyno};
|
|
push @budget_codes, $item_budget_id;
|
|
push @itemprices, $infoset->{price};
|
|
push @replacementprices, $infoset->{replacementprice};
|
|
push @itemcallnumbers, $infoset->{itemcallnumber};
|
|
push @coded_location_qualifiers, $infoset->{coded_location_qualifier};
|
|
push @barcodes, $infoset->{barcode};
|
|
push @enumchrons, $infoset->{enumchron};
|
|
}
|
|
}
|
|
|
|
my $item_fields = {
|
|
quantity => scalar(@homebranches),
|
|
homebranches => \@homebranches,
|
|
holdingbranches => \@holdingbranches,
|
|
itypes => \@itypes,
|
|
nonpublic_notes => \@nonpublic_notes,
|
|
public_notes => \@public_notes,
|
|
locs => \@locs,
|
|
ccodes => \@ccodes,
|
|
notforloans => \@notforloans,
|
|
uris => \@uris,
|
|
copynos => \@copynos,
|
|
budget_codes => \@budget_codes,
|
|
itemprices => \@itemprices,
|
|
replacementprices => \@replacementprices,
|
|
itemcallnumbers => \@itemcallnumbers,
|
|
coded_location_qualifiers => \@coded_location_qualifiers,
|
|
barcodes => \@barcodes,
|
|
enumchrons => \@enumchrons,
|
|
c_quantity => $marc_fields_to_order->{quantity},
|
|
c_budget_code => $marc_fields_to_order->{budget_code},
|
|
c_price => $marc_fields_to_order->{price},
|
|
c_discount => $marc_fields_to_order->{discount},
|
|
c_sort1 => $marc_fields_to_order->{sort1},
|
|
c_sort2 => $marc_fields_to_order->{sort2},
|
|
c_replacement_price => $marc_fields_to_order->{replacementprice},
|
|
};
|
|
|
|
return $item_fields;
|
|
}
|
|
|
|
=head3 _retrieve_first_record_from_batch
|
|
|
|
=cut
|
|
|
|
sub _retrieve_first_record_from_batch {
|
|
my ($args) = @_;
|
|
|
|
my $filename = $args->{filename};
|
|
my $filepath = $args->{filepath};
|
|
my $profile = $args->{profile};
|
|
my $format = index( $filename, '.mrc' ) != -1 ? 'ISO2709' : 'MARCXML';
|
|
|
|
my ( $errors, $marcrecords );
|
|
if ( $format eq 'MARCXML' ) {
|
|
( $errors, $marcrecords ) = C4::ImportBatch::RecordsFromMARCXMLFile( $filepath, $profile->encoding );
|
|
} elsif ( $format eq 'ISO2709' ) {
|
|
( $errors, $marcrecords ) = C4::ImportBatch::RecordsFromISO2709File(
|
|
$filepath, $profile->record_type,
|
|
$profile->encoding
|
|
);
|
|
}
|
|
|
|
my $first_record = @{$marcrecords}[0];
|
|
return $first_record;
|
|
|
|
}
|
|
|
|
1;
|