diff --git a/eod1.pl b/eod1.pl index 179c23445304d03ed570be4b68e6a89532d382b2..afc8d52c86eb03e3b86c061a85fefc096b93c74b 100755 --- a/eod1.pl +++ b/eod1.pl @@ -29,16 +29,29 @@ use Util::MongoDB; use lib 'lib'; use Alma::MARC_Extractor; -use IRMA::NA; +# use IRMA::NA; +use Univie::EoD::CrossReference; my $agent_config_file= '/etc/irma/eodagent.json'; +my $op_mode= 'complete'; -my @PARS; +my @tsv_columns= +qw( pid verdict ownerId state model + ac_number alma_notes ac_number_note aleph_url + marc_record ts_fetched fetched ts_marc mms_id lib_code + ticket ticket_status vt + df_doi val_doi doi update_doi + df_urn val_urn urn update_urn + df_hdl val_hdl hdl update_hdl + df_phaidra val_phaidra phaidra_url update_phaidra_url + ); + +my (@pars, @ac_numbers, @pids); my $arg; while (defined ($arg= shift (@ARGV))) { - if ($arg eq '-') { push (@PARS, '-'); } - elsif ($arg eq '--') { push (@PARS, @ARGV); @ARGV= (); } + if ($arg eq '-') { push (@pars, '-'); } + elsif ($arg eq '--') { push (@pars, @ARGV); @ARGV= (); } elsif ($arg =~ /^--(.+)/) { my ($opt, $val)= split ('=', $1, 2); @@ -56,7 +69,9 @@ while (defined ($arg= shift (@ARGV))) } else { - push (@PARS, $arg); + if ($arg =~ m#^[\w\d\-]+:\d+$#) { push (@pids, $arg) } + elsif ($arg =~ m#^AC\d{8}$#) { push (@ac_numbers, $arg) } + else { push (@pars, $arg); } } } @@ -65,236 +80,87 @@ print join (' ', __FILE__, __LINE__, 'caller=['. caller() . ']'), "\n"; my $agent_cnf= Util::JSON::read_json_file ($agent_config_file); # print __LINE__, " agent_cnf: ", main::Dumper ($agent_cnf); exit(0); -# Step 1: get list of books from inventory -# get handles for various databases -my $inv_db= IRMA::db::get_any_db($agent_cnf, 'inventory_database'); -my $foxml_col= $inv_db->get_collection('foxml.data'); -# print __LINE__, " foxml_col: ", Dumper($foxml_col); -print __LINE__, " foxml_col=[$foxml_col]\n"; +my %counters; +my @books_duplicate_ac_number; +my @books_problems; +my @books_ok; -my @foxml_columns= qw(ownerId state model ac_number aleph_url pid); -# my %foxml_columns= map { $_ => 1 } @foxml_columns; -my $search= { ownerId => 'ondemae7', state => 'Active', model => 'Book' }; +my $crf= Univie::EoD::CrossReference->new( agent_cnf => $agent_cnf, counters => \%counters ); -my %counters; -my $cur= $foxml_col->find( $search ); -# print __LINE__, ' cur: ', Dumper($cur); -my %ac_numbers= (); -my %pids= (); -my @books= (); -while (my $rec= $cur->next()) +my $count_objects= 0; +if (@ac_numbers) { - # print __LINE__, " rec: ", Dumper($rec); - my %book= map { $_ => $rec->{$_} } @foxml_columns; - # print __LINE__, " book: ", Dumper(\%book); - - $book{phaidra_url}= 'https://phaidra.univie.ac.at/'. $book{pid}; - push (@{$ac_numbers{$book{ac_number}}} => \%book); - $pids{$book{pid}}= \%book; + $crf->get_book_by_ac_number(\@ac_numbers); + $count_objects += @ac_numbers; +} - push (@books, \%book); +if (@pids) +{ + $crf->get_book_by_pid(\@pids); + $count_objects += @pids; } -print __LINE__, " checking for duplicate ac_numbers\n"; -foreach my $ac_number (keys %ac_numbers) +if (@pars) { - my $x= $ac_numbers{$ac_number}; - # print __LINE__, " ac_number=[$ac_number] pids=[", join(', ', map { $_->{pid} } @$x), "]\n"; - if (@$x != 1) - { # either this is a duplicate or a member of a collection (ZS) where the Alma record should point to the collection instead - print __LINE__, " duplicate_ac_number=[$ac_number] pids=[", join(', ', map { $_->{pid} } @$x), "]\n"; - $counters{duplicate_ac_number}++; - - # TODO: find out, why this is a duplicate, possibly do not mark the "canonical" version which should be identified in a ticket or so - # for now, just leave them out of further processing. - foreach my $book (@$x) - { - $book->{ac_number_note}= 'dup'; - } + while (my $par= shift (@pars)) + { + # TODO: ??? } } -my $book_count= @books; -print __LINE__, " found $book_count books\n"; +if ($count_objects == 0) +{ + $crf->get_book_inventory(); +} -# BEGIN step 2: check IRMA records -my $irma_db= IRMA::db::get_any_db($agent_cnf, 'irma_database'); -my $irma_col= $irma_db->get_collection('irma.map'); +$crf->flag_duplicate_ac_numbers(); +process_book_list($crf->get_book_list()); -# BEGIN step 3: check Alma records -my $marc_db= IRMA::db::get_any_db($agent_cnf, 'marc_database'); -my $marc_col= $marc_db->get_collection('alma.marc'); -my $req_col= $marc_db->get_collection('requests'); +print __LINE__, " counters: ", Dumper(\%counters); - my @marc_mex_fields= qw(df_doi val_doi df_phaidra val_phaidra df_urn val_urn ts_marc); - my @marc_fields= qw(ac_number mms_id fetched lib_code); - my @marc_extra_fields= qw(marc_record ts_fetched); - my $mex= Alma::MARC_Extractor->new(\@marc_fields); - $mex->{mex_ot2ut}= 0; $mex->{mex_phaidra}= 1; +Util::JSON::write_json_file('eod_problems.json', \@books_problems); -my @books_duplicate_ac_number; -my @books_problems; -my @books_ok; -BOOK3: foreach my $book (@books) +write_tsv_file('eod_data.tsv', \@books_ok); +write_tsv_file('duplicate_eod_data.tsv', \@books_duplicate_ac_number); +write_tsv_file('problems_eod_data.tsv', \@books_problems); + +exit(0); + +sub process_book_list { - my @irma_notes= (); - my ($ac_number, $pid)= map { $book->{$_} } qw(ac_number pid); + my $book_list= shift; - unless (defined ($ac_number) && $ac_number =~ m#^AC\d{8}$#) - { - $book->{problem}= "invalid ac_number=[$ac_number]"; - push (@books_problems, $book); - $book->{problem}= 'invalid_ac_number'; - $counters{invalid_ac_number}++; - next BOOK3; - } +my $book_count= @$book_list; +print __LINE__, " found $book_count books\n"; - my @irma_records= $irma_col->find({ ac_number => $ac_number })->all(); - print __LINE__, " ac_number=[$ac_number] irma_records: ", scalar @irma_records, ' ', Dumper(\@irma_records); +# BEGIN step 2: check IRMA records - my $marc= $marc_col->find_one({ ac_number => $ac_number }); - # print __LINE__, " marc: ", Dumper($marc); - unless (defined ($marc)) - { - $counters{missing_marc_record}++; - $book->{problem}= 'missing_marc_record'; - push (@books_problems, $book); - next BOOK3; - } +# BEGIN step 3: check Alma records +# my $req_col= $marc_db->get_collection('requests'); - if ($book->{ac_number_note}) - { - $counters{has_ac_number_note}++; - push (@books_duplicate_ac_number, $book); # save for later, see above near the duplicate check - next BOOK3; - } + # my @marc_mex_fields= qw(df_doi val_doi df_phaidra val_phaidra df_urn val_urn ts_marc); + # my @marc_extra_fields= qw(marc_record ts_fetched); - my @alma_notes= (); - $book->{ts_fetched}= Util::ts::ts_ISO_gmt($marc->{fetched}); - $mex->extract_identifiers2($marc, $book); - if (exists($book->{mex})) + BOOK3: foreach my $book (@$book_list) { - my $mex= $book->{mex}; - print __LINE__, " ac_number=[$ac_number] mex: ", Dumper($mex); - foreach my $mf (keys %$mex) + my ($verdict)= $crf->check_book($book); + $book->{verdict}= $verdict; + $counters{$verdict}++; + + if ($verdict eq 'ok') { - my $mfa= $mex->{$mf}; - - if (@$mfa != 1) - { # this should be inspected - print __LINE__, " ac_number=[$ac_number] multiple entries for $mf mex: ", Dumper($mex); - $counters{multiple_mex_entries}++; - $book->{problems}= 'multiple_mex_entries'; - push (@books_problems, $book); - next BOOK3; - } - - foreach my $mfe (@$mfa) - { - my ($df, $val)= @$mfe; - my $copy= 0; - if ($mf eq 'phaidra') - { - if ($val =~ m#^https?://phaidra.univie.ac.at/(.*)(o:\d+)$#) - { - $copy= 1; # only transcribe those URLs that really look like some - my ($extra, $found_pid)= ($1, $2); - my $correct_url= 'https://phaidra.univie.ac.at/'. $found_pid; - if ($correct_url ne $book->{phaidra_url} || $extra ne '') - { - $book->{update_phaidra_url}= $book->{phaidra_url}; - $counters{update_phaidra_url}++; - push(@alma_notes, 'update_phaidra_url'); - } - } - } - elsif ($mf eq 'hdl') - { - if ($val =~ m#^11353/10\.(\d+)$#) - { - $copy= 1; # only transcribe those URLs that really look like some - my $found_pid= 'o:'.$1; - if ($found_pid ne $pid) - { # TODO: - $book->{update_hdl}= $book->{hdl}; - $counters{update_hdl}++; - push(@alma_notes, 'update_hdl'); - } - } - } - elsif ($mf eq 'doi') - { - if ($val =~ m#^10.25365/digital-copy\.(\d+)$#) - { - $copy= 1; # only transcribe those URLs that really look like some -# TODO: DOI checken -# if ($found_pid ne $pid) -# { # TODO: -# $book->{update_hdl}= $book->{hdl}; -# $counters{update_hdl}++; -# push(@alma_notes, 'update_hdl'); -# } - } - } - elsif ($mf eq 'urn') - { - if ($val =~ m#^urn:nbn:at:at-ubw-\d{5}\.\d{5}\.\d{6}-\d$#) - { - $copy= 1; # only transcribe those URLs that really look like some - # TODO: check if this is the known nbn! - } - } - - - if ($copy) - { - $book->{'df_'.$mf}= $df; - $book->{'val_'.$mf}= $val; - } - else - { - push(@alma_notes, "junk_${mf}_in_marc"); - print __LINE__, " ATTN: ac_number=[$ac_number] pid=[$pid] junk data mf=[$mf] in marc record: df=[$df] val=[$val]\n"; - } - } + push (@books_ok, $book); + } + elsif ($verdict eq 'has_ac_number_note') + { + push (@books_duplicate_ac_number, $book); + } + else + { + push (@books_problems, $book); } } - else - { - # this is ok, not a bug, Alma simply does not know anything about this phaidra object - print __LINE__, " ac_number=[$ac_number] mex missing\n"; - } - - unless (exists($book->{df_phaidra})) - { # TODO: if there is no phaidra_url at all, set it... - $counters{set_phaidra_url}++; - $book->{update_phaidra_url}= $book->{phaidra_url}; - push(@alma_notes, 'set_phaidra_url'); - } - - push (@alma_notes, 'ok') unless (@alma_notes); - $book->{alma_notes}= join(',', @alma_notes); - push (@books_ok, $book); - # print __LINE__, " book: ", Dumper($book); - $counters{ok}++; } -# END check Alma records - -print __LINE__, " counters: ", Dumper(\%counters); - -Util::JSON::write_json_file('eod_problems.json', \@books_problems); - -my @tsv_columns= -qw( pid alma_notes ownerId state model ac_number ac_number_note aleph_url - marc_record ts_fetched fetched ts_marc mms_id lib_code - df_doi val_doi - df_urn val_urn - df_hdl val_hdl update_hdl - df_phaidra val_phaidra phaidra_url update_phaidra_url - ); - -write_tsv_file('eod_data.tsv', \@books_ok); -write_tsv_file('duplicate_eod_data.tsv', \@books_duplicate_ac_number); sub write_tsv_file { @@ -314,7 +180,32 @@ sub write_tsv_file __END__ -=head1 EXAMPLES +=head1 PROBLEMS + +=head2 AC06947549 + +-[ RECORD 1 ]---------------------- +pid | o:1024961 +verdict | ok +ownerId | ondemae7 +state | Active +model | Book +ac_number | AC06947549 +alma_notes | update_hdl +aleph_url | https://ubdata.univie.ac.at/AC06947549 +marc_record | marc_data_found +ts_fetched | 2023-03-18T172423 +fetched | 1679160263 +ts_marc | 20230210194745.0 +mms_id | 990074078270203332 +lib_code | 43ACC_UBW +df_hdl | 776:0:8:o +val_hdl | 11353/10.1027250 +df_phaidra | 856:4:1:u +val_phaidra | https://phaidra.univie.ac.at/o:1024961 +phaidra_url | https://phaidra.univie.ac.at/o:1024961 + +the handle value in 776:0:8:o is 11353/10.1027250 but it should be 11353/10.1024961 =head2 AC02901724 @@ -338,6 +229,7 @@ phaidra_url | https://phaidra.univie.ac.at/o:90496 update_phaidra_url | https://phaidra.univie.ac.at/o:90496 o:90495 is a collection, o:90496 is the only member; this is a ZS record, -so this is ok and the suggested change is not correct. +so this is ok and the suggested change is not correct. Filtered for now + diff --git a/lib/Univie/EoD/CrossReference.pm b/lib/Univie/EoD/CrossReference.pm new file mode 100644 index 0000000000000000000000000000000000000000..4f2c11db9afe4fc5acd2c86b37f6eec33bd6e0d3 --- /dev/null +++ b/lib/Univie/EoD/CrossReference.pm @@ -0,0 +1,358 @@ +package Univie::EoD::CrossReference; + +use strict; + +use Data::Dumper; + +use IRMA::db; +use Util::ts; + +my @foxml_columns= qw(ownerId state model ac_number aleph_url pid); +my @marc_fields= qw(ac_number mms_id fetched lib_code); + +sub new +{ + my $class= shift; + + my $self= + { + ac_numbers => {}, + pids => {}, + books => [], + }; + + bless ($self, $class); + $self->set(@_); + + $self; +} + +sub set +{ + my $self= shift; + my %par= @_; + foreach my $par (keys %par) + { + $self->{$par}= $par{$par}; + } + $self; +} + +sub get_book_list +{ + my $self= shift; + $self->{books}; +} + +sub get_db_col +{ + my $self= shift; + my $db= shift; + my $col_name= shift; + + return $self->{_db}->{$db}->{$col_name} if (defined ($self->{_db}->{$db}->{$col_name})); + + my $inv_db= IRMA::db::get_any_db($self->{agent_cnf}, $db); + $self->{_db}->{$db}->{$col_name}= my $col= $inv_db->get_collection($col_name); + print __LINE__, " db=[$db] col_name=[$col_name] col=[$col]\n"; + # print __LINE__, " col: ", Dumper($col); + $col; +} + +sub get_book_inventory +{ + my $self= shift; + my $search= { ownerId => $self->{agent_cnf}->{ownerId}, state => 'Active', model => 'Book' }; + $self->find_books($search); +} + +sub get_book_by_ac_number +{ + my $self= shift; + my $ac_numbers= shift; + + my $search= { ownerId => $self->{agent_cnf}->{ownerId}, state => 'Active', model => 'Book' }; + _modify_search ($search, 'ac_number', $ac_numbers); + $self->find_books($search); +} + +sub get_book_by_pid +{ + my $self= shift; + my $pids= shift; + + my $search= { ownerId => $self->{agent_cnf}->{ownerId}, state => 'Active', model => 'Book' }; + _modify_search ($search, 'pid', $pids); + $self->find_books($search); +} + +sub _modify_search +{ + my $s= shift; + my $what= shift; + my $val= shift; + + if (ref($val) eq 'ARRAY') { $s->{$what} = { '$in' => $val } } + else { $s->{$what}= $val; } +} + +sub find_books +{ + my $self= shift; + my $search= shift; + print __LINE__, " search: ", join(', ', %$search), "\n"; + + my $foxml_col= $self->get_db_col('inventory_database', 'foxml.data'); + my $cur= $foxml_col->find( $search ); + # print __LINE__, ' cur: ', Dumper($cur); + + while (my $foxml_rec= $cur->next()) + { + # print __LINE__, " foxml_rec=[$foxml_rec]\n"; + $self->add_book($foxml_rec); + } +} + +sub add_book +{ + my $self= shift; + my $foxml_rec= shift; + + # print __LINE__, " foxml_rec: ", Dumper($foxml_rec); + my %book= map { $_ => $foxml_rec->{$_} } @foxml_columns; + # print __LINE__, " book: ", Dumper(\%book); + + $book{phaidra_url}= 'https://phaidra.univie.ac.at/'. $book{pid}; + push (@{$self->{ac_numbers}->{$book{ac_number}}} => \%book); + $self->{pids}->{$book{pid}}= \%book; + + push (@{$self->{books}}, \%book); + + \%book; +} + +sub flag_duplicate_ac_numbers +{ + my $self= shift; + + my $ac_numbers= $self->{ac_numbers}; + print __LINE__, " checking for duplicate ac_numbers\n"; + foreach my $ac_number (keys %$ac_numbers) + { + my $x= $ac_numbers->{$ac_number}; + # print __LINE__, " ac_number=[$ac_number] pids=[", join(', ', map { $_->{pid} } @$x), "]\n"; + + if (@$x != 1) + { # either this is a duplicate or a member of a collection (ZS) where the Alma record should point to the collection instead + print __LINE__, " duplicate_ac_number=[$ac_number] pids=[", join(', ', map { $_->{pid} } @$x), "]\n"; + + # TODO: find out, why this is a duplicate, possibly do not mark the "canonical" version which should be identified in a ticket or so + # for now, just leave them out of further processing. + foreach my $book (@$x) + { + $book->{ac_number_note}= 'dup'; + } + } + } +} + +sub check_book +{ + my $self= shift; + my $book= shift; + + my @irma_notes= (); + my ($ac_number, $pid, $ac_number_note)= map { $book->{$_} } qw(ac_number pid ac_number_note); + + unless (defined ($ac_number) && $ac_number =~ m#^AC\d{8}$#) + { + $book->{problem}= "invalid ac_number=[$ac_number]"; + $book->{problem}= + return ('invalid_ac_number'); + } + + return 'ac_number_note' if ($ac_number_note ne ''); + return 'filtered_ac_numbers' if (exists ($self->{agent_cnf}->{filtered_ac_numbers}->{$ac_number})); + return 'filtered_pids' if (exists ($self->{agent_cnf}->{filtered_pids}->{$pid})); + + # check tickets + my $ticket_col= $self->get_db_col('irma_database', 'eod.tickets'); + my @tickets= $ticket_col->find({ ac_number => $ac_number })->all(); + print __LINE__, " ac_number=[$ac_number] tickets: ", scalar @tickets, "\n"; + # print __LINE__, Dumper(\@tickets); + if (@tickets > 1) + { + $book->{ticket}= join(',', map { $_->{ticket} } @tickets); + return 'multiple_tickets'; + } + elsif (@tickets == 1) + { + my $t0= @tickets[0]; + $book->{ticket}= $t0->{ticket}; + $book->{ticket_status}= $t0->{status}; + $book->{vt}= $t0->{custom_fields}->{vt}->[1]; + } + + # check IRMA for registered identifiers + my $irma_col= $self->get_db_col('irma_database', 'irma.map'); + my @irma_records= $irma_col->find({ ac_number => $ac_number })->all(); + # my @irma_records= $irma_col->find({ pid => $pid })->all(); # NOTE: there is no field named "pid" in the irma record! + print __LINE__, " ac_number=[$ac_number] irma_records: ", scalar @irma_records, "\n"; + # print __LINE__, Dumper(\@irma_records); + if (@irma_records > 1) { return 'multiple_irma_records' } + elsif (@irma_records == 1) + { + my $ir0= $irma_records[0]; + foreach my $field (qw(hdl urn doi)) + { + $book->{$field}= $ir0->{$field} if (exists ($ir0->{$field})); + } + } + elsif (@irma_records == 0) + { + print __LINE__, " ATTN: ac_number=[$ac_number] no irma_record!\n"; + $self->{counters}->{missing_irma_record}++; + } + + my $marc_col= $self->get_db_col('marc_database', 'alma.marc'); + my $marc= $marc_col->find_one({ ac_number => $ac_number }); + # print __LINE__, " marc: ", Dumper($marc); + return 'missing_marc_record' unless (defined ($marc)); + + my @alma_notes= (); + $book->{ts_fetched}= Util::ts::ts_ISO_gmt($marc->{fetched}); + + my $mex= Alma::MARC_Extractor->new(\@marc_fields); + $mex->{mex_ot2ut}= 0; $mex->{mex_phaidra}= 1; + $mex->extract_identifiers2($marc, $book); + + if (exists($book->{mex})) + { + my $mex= $book->{mex}; + print __LINE__, " ac_number=[$ac_number] mex: ", Dumper($mex); + foreach my $mf (keys %$mex) + { + my $mfa= $mex->{$mf}; + + if (@$mfa != 1) + { # this should be inspected + print __LINE__, " ATTN: ac_number=[$ac_number] multiple mex entries for $mf; mex: ", Dumper($mex); + return 'multiple_mex_entries'; + } + + foreach my $mfe (@$mfa) + { + my ($df, $val)= @$mfe; + my $copy= 0; + if ($mf eq 'phaidra') + { + if ($val =~ m#^https?://phaidra.univie.ac.at/(.*)(o:\d+)$#) + { + $copy= 1; # only transcribe those URLs that really look like some + my ($extra, $found_pid)= ($1, $2); + my $correct_url= 'https://phaidra.univie.ac.at/'. $found_pid; + if ($correct_url ne $book->{phaidra_url} || $extra ne '') + { + $book->{update_phaidra_url}= $book->{phaidra_url}; + $self->{counters}->{update_phaidra_url}++; + push(@alma_notes, 'update_phaidra_url'); + } + } + } + elsif ($mf eq 'hdl') + { + if ($val =~ m#^11353/10\.(\d+)$#) + { + $copy= 1; # only transcribe those URLs that really look like some + if ($val ne $book->{hdl}) + { # TODO: + $book->{update_hdl}= $book->{hdl}; + $self->{counters}->{update_hdl}++; + push(@alma_notes, 'update_hdl'); + } + } + } + elsif ($mf eq 'doi') + { + if ($val =~ m#^10.25365/digital-copy\.(\d+)$#) + { + $copy= 1; # only transcribe those URLs that really look like some + # TODO: DOI checken + if ($val ne $book->{doi}) + { # TODO: + $book->{update_doi}= $book->{doi}; + $self->{counters}->{update_doi}++; + push(@alma_notes, 'update_doi'); + } + } + else + { + print __LINE__, " ATTN: unknown DOI format in marc record: df=[$df] val=[$val]\n"; + $self->{counters}->{bad_doi}++; + } + } + elsif ($mf eq 'urn') + { + if ($val =~ m#^urn:nbn:at:at-ubw-\d{5}\.\d{5}\.\d{6}-\d$#) + { + $copy= 1; # only transcribe those URLs that really look like some + # TODO: check if this is the known nbn! + if ($val ne $book->{urn}) + { # TODO: + $book->{update_urn}= $book->{urn}; + $self->{counters}->{update_urn}++; + push(@alma_notes, 'update_urn'); + } + } + else + { + print __LINE__, " ATTN: unknown NBN (urn) format in marc record: df=[$df] val=[$val]\n"; + $self->{counters}->{bad_urn}++; + } + } + + if ($copy) + { + $book->{'df_'.$mf}= $df; + $book->{'val_'.$mf}= $val; + } + else + { + push(@alma_notes, "junk_${mf}_in_marc"); + print __LINE__, " ATTN: ac_number=[$ac_number] pid=[$pid] junk data mf=[$mf] in marc record: df=[$df] val=[$val]\n"; + } + } + } + } + else + { + # this is ok, not a bug, Alma simply does not know anything about this phaidra object + print __LINE__, " ac_number=[$ac_number] mex missing\n"; + } + + if (!exists($book->{val_urn}) && exists ($book->{urn})) + { + $book->{update_urn}= $book->{urn}; + $self->{counters}->{set_urn}++; + push(@alma_notes, 'set_urn'); + } + + unless (exists($book->{df_phaidra})) + { # TODO: if there is no phaidra_url at all, set it... + $self->{counters}->{set_phaidra_url}++; + $book->{update_phaidra_url}= $book->{phaidra_url}; + push(@alma_notes, 'set_phaidra_url'); + } + + push (@alma_notes, 'ok') unless (@alma_notes); + $book->{alma_notes}= join(',', @alma_notes); + + return 'ok'; +} + +=head1 INTERNAL? METHODS + +=cut + +1; +