From: Bill Erickson Date: Wed, 30 Nov 2011 20:42:30 +0000 (-0500) Subject: ACQ Vandelay : vl ML bits for updating acq records X-Git-Url: https://old-git.evergreen-ils.org/?a=commitdiff_plain;h=febd4d50b5f7b0075081857f6356e7d21a06e1bd;p=evergreen%2Fequinox.git ACQ Vandelay : vl ML bits for updating acq records Signed-off-by: Bill Erickson --- diff --git a/Open-ILS/src/perlmods/lib/OpenILS/Application/Acq/Order.pm b/Open-ILS/src/perlmods/lib/OpenILS/Application/Acq/Order.pm index 1b1aff30e9..620404803f 100644 --- a/Open-ILS/src/perlmods/lib/OpenILS/Application/Acq/Order.pm +++ b/Open-ILS/src/perlmods/lib/OpenILS/Application/Acq/Order.pm @@ -10,6 +10,7 @@ sub new { $self->{args} = { lid => 0, li => 0, + vqbr => 0, copies => 0, bibs => 0, progress => 0, @@ -18,9 +19,9 @@ sub new { picklist => undef, complete => 0, indexed => 0, + queue => undef, total => 0 }; - $self->{ingest_queue} = []; $self->{cache} = {}; $self->throttle(5) unless $self->throttle; $self->{post_proc_queue} = []; @@ -96,6 +97,12 @@ sub add_li { $self->{args}->{progress} += 1; return $self; } +sub add_vqbr { + my $self = shift; + $self->{args}->{vqbr} += 1; + $self->{args}->{progress} += 1; + return $self; +} sub add_copy { my $self = shift; $self->{args}->{copies} += 1; @@ -125,41 +132,6 @@ sub complete { return $self; } -sub ingest_ses { - my($self, $val) = @_; - $self->{ingest_ses} = $val if $val; - return $self->{ingest_ses}; -} - -sub push_ingest_queue { - my($self, $rec_id) = @_; - - $self->ingest_ses(OpenSRF::AppSession->connect('open-ils.ingest')) - unless $self->ingest_ses; - - my $req = $self->ingest_ses->request('open-ils.ingest.full.biblio.record', $rec_id); - - push(@{$self->{ingest_queue}}, $req); -} - -sub process_ingest_records { - my $self = shift; - return unless @{$self->{ingest_queue}}; - - for my $req (@{$self->{ingest_queue}}) { - - try { - $req->gather(1); - $self->{args}->{indexed} += 1; - $self->{args}->{progress} += 1; - } otherwise {}; - - $self->respond; - } - $self->ingest_ses->disconnect; -} - - sub cache { my($self, $org, $key, $val) = @_; $self->{cache}->{$org} = {} unless $self->{cache}->{org}; @@ -189,6 +161,9 @@ use OpenILS::Application::Cat::AssetCommon; use MARC::Record; use MARC::Batch; use MARC::File::XML (BinaryEncoding => 'UTF-8'); +use Digest::MD5 qw(md5_hex); +use Data::Dumper; +$Data::Dumper::Indent = 0; my $U = 'OpenILS::Application::AppUtils'; @@ -319,20 +294,135 @@ sub delete_lineitem { # begins and commit transactions as it goes sub create_lineitem_list_assets { - my($mgr, $li_ids) = @_; + my($mgr, $li_ids, $vandelay) = @_; return undef if check_import_li_marc_perms($mgr, $li_ids); - # create the bibs/volumes/copies and ingest the records - for my $li_id (@$li_ids) { + $logger->info("acq-vl: procesing recs via Vandelay with args " . Dumper($vandelay)); + + my $res = import_li_bibs_via_vandelay($mgr, $li_ids, $vandelay); + return undef unless $res; + + # create the bibs/volumes/copies for the successfully imported records + for my $li_id (@{$res->{li_ids}}) { $mgr->editor->xact_begin; my $data = create_lineitem_assets($mgr, $li_id) or return undef; $mgr->editor->xact_commit; - # XXX ingest is in-db now - #$mgr->push_ingest_queue($data->{li}->eg_bib_id) if $data->{new_bib}; $mgr->respond; } - $mgr->process_ingest_records; - return 1; + + return $res; +} + + +sub import_li_bibs_via_vandelay { + my ($mgr, $li_ids, $vandelay) = @_; + my $res = {li_ids => []}; + my $e = $mgr->editor; + $e->xact_begin; + + my $queue; + if (my $name = $vandelay->{queue_name}) { + + # first, see if a queue w/ this name already exists + # for this user. If so, use that instead. + + $queue = $e->search_vandelay_bib_queue( + {name => $name, owner => $e->requestor->id})->[0]; + + if ($queue) { + + $logger->info("acq-vl: using existing queue $name"); + + } else { + + $logger->info("acq-vl: creating new vandelay queue $name"); + + $queue = new Fieldmapper::vandelay::bib_queue; + $queue->name($name); + $queue->owner($e->requestor->id); + $queue->match_set($vandelay->{match_set} || undef); # avoid '' + $queue = $e->create_vandelay_bib_queue($queue) or return $res; + } + + } else { + $queue = $e->retrieve_vandelay_queue($vandelay->{existing_queue}) + or return undef; + } + + + return $res unless $queue; + $mgr->{args}->{queue} = $queue; + + # load the lineitems into the queue for merge processing + my @vqbr_ids; + my @lis; + for my $li_id (@$li_ids) { + + my $li = $e->retrieve_acq_lineitem($li_id) or return $res; + + my $vqbr = Fieldmapper::vandelay::queued_bib_record->new; + $vqbr->marc($li->marc); + $vqbr->queue($queue->id); + $vqbr->bib_source($vandelay->{bib_source} || undef); # avoid '' + $vqbr = $e->create_vandelay_queued_bib_record($vqbr) or return $res; + push(@vqbr_ids, $vqbr->id); + $mgr->add_vqbr; + $mgr->respond; + + # tell the acq record which vandelay record it's linked to + $li->queued_record($vqbr->id); + $e->update_acq_lineitem($li) or return $res; + push(@lis, $li); + } + + $logger->info("acq-vl: created vandelay records [@vqbr_ids]"); + + # we have to commit the transaction now since + # vandelay uses its own transactions. + $e->commit; + + # Import the bibs via vandelay. Note: Vandely will + # update acq.lineitem.eg_bib_id on successful import. + + $vandelay->{report_all} = 1; + my $ses = OpenSRF::AppSession->create('open-ils.vandelay'); + my $req = $ses->request( + 'open-ils.vandelay.bib_record.list.import', + $e->authtoken, \@vqbr_ids, $vandelay); + + # pull the responses, noting all that were successfully imported + my @success_lis; + while (my $resp = $req->recv(timeout => 600)) { + my $stat = $resp->content; + + if(!$stat or $U->event_code($stat)) { # import failure + $logger->error("acq-vl: error importing vandelay record " . Dumper($stat)); + next; + } + + # "imported" here refers to the vqbr, not the + # success/failure of the vqbr merge attempt + next unless $stat->{imported}; + + my ($imported) = grep {$_->queued_record eq $stat->{imported}} @lis; + my $vqbr_id = $imported->id; + + if ($stat->{no_import}) { + $logger->info("acq-vl: vandelay record $vqbr_id did not import"); + + } else { # successful import + + push(@success_lis, $vqbr_id); + $mgr->add_bib; + $mgr->respond; + $logger->info("acq-vl: vandelay record $vqbr_id successfully imported"); + } + } + + $ses->kill_me; + $logger->info("acq-vl: successfully imported lineitems [@success_lis]"); + + return {queue => $queue, li_ids => \@success_lis}; } # returns event on error, undef on success @@ -964,15 +1054,7 @@ sub create_lineitem_assets { } ]) or return 0; - # ----------------------------------------------------------------- - # first, create the bib record if necessary - # ----------------------------------------------------------------- - my $new_bib = 0; - unless($li->eg_bib_id) { - create_bib($mgr, $li) or return 0; - $new_bib = 1; - } - + # note: at this point, the bib record this LI links to should already be created # ----------------------------------------------------------------- # The lineitem is going live, promote user request holds to real holds @@ -1011,29 +1093,7 @@ sub create_lineitem_assets { create_copy($mgr, $volume, $lid, $li) or return 0; } - return { li => $li, new_bib => $new_bib }; -} - -sub create_bib { - my($mgr, $li) = @_; - - my $record = OpenILS::Application::Cat::BibCommon->biblio_record_xml_import( - $mgr->editor, - $li->marc, - undef, # bib source - undef, - 1, # override tcn collisions - ); - - if($U->event_code($record)) { - $mgr->editor->event($record); - $mgr->editor->rollback; - return 0; - } - - $li->eg_bib_id($record->id); - $mgr->add_bib; - return update_lineitem($mgr, $li); + return { li => $li }; } sub create_volume { @@ -1185,10 +1245,12 @@ __PACKAGE__->register_method( method => 'upload_records', api_name => 'open-ils.acq.process_upload_records', stream => 1, + max_chunk_count => 1 ); sub upload_records { - my($self, $conn, $auth, $key) = @_; + my($self, $conn, $auth, $key, $args) = @_; + $args ||= {}; my $e = new_editor(authtoken => $auth, xact => 1); return $e->die_event unless $e->checkauth; @@ -1197,14 +1259,13 @@ sub upload_records { my $cache = OpenSRF::Utils::Cache->new; my $data = $cache->get_cache("vandelay_import_spool_$key"); - my $purpose = $data->{purpose}; my $filename = $data->{path}; - my $provider = $data->{provider}; - my $picklist = $data->{picklist}; - my $create_po = $data->{create_po}; - my $activate_po = $data->{activate_po}; - my $ordering_agency = $data->{ordering_agency}; - my $create_assets = $data->{create_assets}; + my $provider = $args->{provider}; + my $picklist = $args->{picklist}; + my $create_po = $args->{create_po}; + my $activate_po = $args->{activate_po}; + my $ordering_agency = $args->{ordering_agency}; + my $vandelay = $args->{vandelay}; my $po; my $evt; @@ -1295,15 +1356,16 @@ sub upload_records { $mgr->respond; } - my $die_event = activate_purchase_order_impl($mgr, $po->id) if $po and $activate_po; - return $die_event if $die_event; - $e->commit; unlink($filename); $cache->delete_cache('vandelay_import_spool_' . $key); - if ($create_assets) { - create_lineitem_list_assets($mgr, \@li_list) or return $e->die_event; + if ($po and $activate_po) { + my $die_event = activate_purchase_order_impl($mgr, $po->id, $vandelay); + return $die_event if $die_event; + + } elsif ($vandelay) { + create_lineitem_list_assets($mgr, \@li_list, $vandelay) or return $e->die_event; } return $mgr->respond_complete; @@ -1529,6 +1591,7 @@ sub create_purchase_order_api { $pargs{provider} = $po->provider if $po->provider; $pargs{ordering_agency} = $po->ordering_agency if $po->ordering_agency; $pargs{prepayment_required} = $po->prepayment_required if $po->prepayment_required; + my $vandelay = $args->{vandelay}; $po = create_purchase_order($mgr, %pargs) or return $e->die_event; @@ -1554,7 +1617,7 @@ sub create_purchase_order_api { # commit before starting the asset creation $e->xact_commit; - if($li_ids and $$args{create_assets}) { + if($li_ids and $vandelay) { create_lineitem_list_assets($mgr, $li_ids) or return $e->die_event; } @@ -1846,7 +1909,7 @@ sub receive_lineitem_api { my $res = receive_lineitem($mgr, $li_id) or return $e->die_event; $e->commit; $conn->respond_complete($res); - $mgr->run_post_response_hooks; + $mgr->run_post_response_hooks } @@ -2178,54 +2241,57 @@ __PACKAGE__->register_method( ); sub activate_purchase_order { - my($self, $conn, $auth, $po_id) = @_; + my($self, $conn, $auth, $po_id, $vandelay) = @_; my $dry_run = ($self->api_name =~ /\.dry_run/) ? 1 : 0; - my $e = new_editor(xact=>1, authtoken=>$auth); + my $e = new_editor(authtoken=>$auth); return $e->die_event unless $e->checkauth; my $mgr = OpenILS::Application::Acq::BatchManager->new(editor => $e, conn => $conn); - my $die_event = activate_purchase_order_impl($mgr, $po_id, $dry_run); + my $die_event = activate_purchase_order_impl($mgr, $po_id, $vandelay, $dry_run); return $e->die_event if $die_event; - if ($dry_run) { - $e->rollback; - } else { - $e->commit; - } $conn->respond_complete(1); - $mgr->run_post_response_hooks; + $mgr->run_post_response_hooks unless $dry_run; return undef; } +# xacts managed within sub activate_purchase_order_impl { - my ($mgr, $po_id, $dry_run) = @_; + my ($mgr, $po_id, $vandelay, $dry_run) = @_; + + # read-only until lineitem asset creation my $e = $mgr->editor; + $e->xact_begin; my $po = $e->retrieve_acq_purchase_order($po_id) or return $e->die_event; return $e->die_event unless $e->allowed('CREATE_PURCHASE_ORDER', $po->ordering_agency); - my $provider = $e->retrieve_acq_provider($po->provider); - $po->state('on-order'); - $po->order_date('now'); - update_purchase_order($mgr, $po) or return $e->die_event; + # find lineitems and create assets for all - my $query = [ - { - purchase_order => $po_id, - state => [qw/pending-order new order-ready/] - }, - {limit => 1} - ]; + my $query = { + purchase_order => $po_id, + state => [qw/pending-order new order-ready/] + }; - while( my $li_id = $e->search_acq_lineitem($query, {idlist => 1})->[0] ) { + my $li_ids = $e->search_acq_lineitem($query, {idlist => 1}); - my $li; - if($dry_run) { - $li = $e->retrieve_acq_lineitem($li_id); - } else { - # can't activate a PO w/o assets. Create lineitem assets as necessary - my $data = create_lineitem_assets($mgr, $li_id) or return $e->die_event; - $li = $data->{li}; + my $vl_resp; # imported li's and the queue the managing queue + if (!$dry_run) { + $e->rollback; # read-only thus far + $vl_resp = create_lineitem_list_assets($mgr, $li_ids, $vandelay) or return $e->die_event; + $e->xact_begin; + } + + # create fund debits for lineitems + + for my $li_id (@$li_ids) { + my $li = $e->retrieve_acq_lineitem($li_id); + + if (!$li->eg_bib_id and !$dry_run) { + # we encountered a lineitem that was not successfully imported. + # we cannot continue. rollback and report. + $e->rollback; + return OpenILS::Event->new('ACQ_LI_IMPORT_FAILED', {queue => $vl_resp->{queue}}); } $li->state('on-order'); @@ -2237,6 +2303,8 @@ sub activate_purchase_order_impl { $mgr->respond; } + # create po-item debits + for my $po_item (@{$e->search_acq_po_item({purchase_order => $po_id})}) { my $debit = create_fund_debit( @@ -2253,6 +2321,15 @@ sub activate_purchase_order_impl { $mgr->respond; } + # mark PO as ordered + + $po->state('on-order'); + $po->order_date('now'); + update_purchase_order($mgr, $po) or return $e->die_event; + + # clean up the xact + $dry_run and $e->rollback or $e->commit; + # tell the world we activated a PO $U->create_events_for_hook('acqpo.activated', $po, $po->ordering_agency) unless $dry_run; diff --git a/Open-ILS/src/perlmods/lib/OpenILS/Application/Vandelay.pm b/Open-ILS/src/perlmods/lib/OpenILS/Application/Vandelay.pm index b30d6527c9..279b793eb8 100644 --- a/Open-ILS/src/perlmods/lib/OpenILS/Application/Vandelay.pm +++ b/Open-ILS/src/perlmods/lib/OpenILS/Application/Vandelay.pm @@ -879,6 +879,8 @@ sub import_record_list_impl { report_all => $$args{report_all} }; + $conn->max_chunk_count(1) if $$args{report_all}; + my $auto_overlay_exact = $$args{auto_overlay_exact}; my $auto_overlay_1match = $$args{auto_overlay_1match}; my $auto_overlay_best = $$args{auto_overlay_best_match}; @@ -896,6 +898,7 @@ sub import_record_list_impl { my $search_func = 'search_vandelay_queued_bib_record'; my $retrieve_queue_func = 'retrieve_vandelay_bib_queue'; my $update_queue_func = 'update_vandelay_bib_queue'; + my $delete_queue_func = 'delete_vandelay_bib_queue'; my $rec_class = 'vqbr'; my $editor = new_editor(); @@ -912,6 +915,7 @@ sub import_record_list_impl { $update_queue_func =~ s/bib/authority/o; $update_func =~ s/bib/authority/o; $search_func =~ s/bib/authority/o; + $delete_queue_func =~ s/bib/authority/o; $rec_class = 'vqar'; } @@ -927,6 +931,7 @@ sub import_record_list_impl { $$report_args{e} = $e; $$report_args{evt} = undef; $$report_args{import_error} = undef; + $$report_args{no_import} = 0; my $rec = $e->$retrieve_func([ $rec_id, @@ -1090,6 +1095,19 @@ sub import_record_list_impl { if($e->$update_func($rec)) { + if($type eq 'bib') { + + # see if this record is linked from an acq record. + my $li = $e->search_acq_lineitem( + {queued_record => $rec->id, state => {'!=' => 'canceled'}})->[0]; + + if ($li) { + # if so, update the acq lineitem to point to the imported record + $li->eg_bib_id($rec->imported_as); + $$report_args{evt} = $e->die_event unless $e->update_acq_lineitem($li); + } + } + push @success_rec_ids, $rec_id; finish_rec_import_attempt($report_args); @@ -1101,6 +1119,7 @@ sub import_record_list_impl { if(!$imported) { $logger->info("vl: record $rec_id was not imported"); $$report_args{evt} = $e->event unless $$report_args{evt}; + $$report_args{no_import} = 1; finish_rec_import_attempt($report_args); } } @@ -1114,7 +1133,6 @@ sub import_record_list_impl { unless(@$remaining) { my $queue = $e->$retrieve_queue_func($q_id); - unless($U->is_true($queue->complete)) { $queue->complete('t'); $e->$update_queue_func($queue) or return $e->die_event; @@ -1283,6 +1301,8 @@ sub finish_rec_import_attempt { total => $$args{total}, progress => $$args{progress}, imported => ($rec) ? $rec->id : undef, + import_error => $error, + no_import => $$args{no_import}, err_event => $evt }); $$args{step} *= 2 unless $$args{step} == 256; diff --git a/Open-ILS/src/perlmods/lib/OpenILS/WWW/Vandelay.pm b/Open-ILS/src/perlmods/lib/OpenILS/WWW/Vandelay.pm index f5cb956629..0cdc41d395 100644 --- a/Open-ILS/src/perlmods/lib/OpenILS/WWW/Vandelay.pm +++ b/Open-ILS/src/perlmods/lib/OpenILS/WWW/Vandelay.pm @@ -66,15 +66,8 @@ sub spool_marc { my $purpose = $cgi->param('purpose') || ''; my $infile = $cgi->param('marc_upload') || ''; my $bib_source = $cgi->param('bib_source') || ''; - my $provider = $cgi->param('provider') || ''; - my $picklist = $cgi->param('picklist') || ''; - my $create_po = $cgi->param('create_po') || ''; - my $activate_po = $cgi->param('activate_po') || ''; - my $ordering_agency = $cgi->param('ordering_agency') || ''; - my $create_assets = $cgi->param('create_assets') || ''; - $logger->debug("purpose = $purpose, infile = $infile, bib_source = $bib_source ". - "provider = $provider, picklist = $picklist, create_po = $create_po, ordering_agency = $ordering_agency"); + $logger->debug("purpose = $purpose, infile = $infile, bib_source = $bib_source"); my $conf = OpenSRF::Utils::SettingsClient->new; my $dir = $conf->config_value( @@ -113,11 +106,6 @@ sub spool_marc { { purpose => $purpose, path => $outfile, bib_source => $bib_source, - provider => $provider, - picklist => $picklist, - create_po => $create_po, - create_assets => $create_assets, - ordering_agency => $ordering_agency } ); }