#}
__PACKAGE__->register_method(
+ method => 'fetch_web_action_print_template',
+ api_name => 'open-ils.actor.web_action_print_template.fetch',
+ signature => q/
+ Given a blob of ILL action status information, generate some useful HTML for printing, based on the acting org unit and action.
+ @param authtoken Login session key
+ @pararm blob Action status blob
+ /
+);
+sub fetch_web_action_print_template {
+ my( $self, $client, $owner, $focus, $action, $direction ) = @_;
+ my $e = new_editor();
+ my $orgs = $U->get_org_ancestors($owner);
+
+ return $e->search_actor_web_action_print_template([
+ { owner => $orgs,
+ focus => $focus,
+ -or => [{action => $action},{action => undef}],
+ -or => [{direction => $direction},{direction => undef}]
+ },
+ { order_by => [
+ { class => 'awapt',
+ field => 'action',
+ compare => { '=' => undef }
+ },
+ { class => 'awapt',
+ field => 'direction',
+ compare => { '=' => undef }
+ }
+ ]}
+ ])->[0];
+}
+
+sub find_user_lib {
+ my $lib = shift;
+ my $e = new_editor();
+
+ $lib = $e->retrieve_actor_org_unit($lib) if (!ref($lib));
+
+ while ($lib) {
+ my $type = $e->retrieve_actor_org_unit_type($lib->ou_type);
+ return $lib if ($U->is_true($type->can_have_users));
+ return undef unless ($lib->parent_ou);
+ $lib = $e->retrieve_actor_org_unit($lib->parent_ou);
+ }
+
+ return undef;
+}
+
+__PACKAGE__->register_method(
+ method => "remote_auth_init",
+ api_name => "open-ils.actor.remote.authenticate.init",
+);
+sub remote_auth_init {
+ my($self, $client, $uname, $uhome) = @_;
+
+ $uhome = find_user_lib($uhome);
+ return 0 if (!$uhome);
+
+ $uhome = $uhome->id;
+
+ my $e = new_editor();
+ my $user = $e->search_actor_user({
+ usrname => "$uname:$uhome",
+ home_ou => $uhome,
+ # deleted accounts must be re-fetched, updated, and
+ # un-deleted in open-ils.actor.remote.authenticate.complete
+ deleted => 'f'
+ });
+
+ return -1 unless @$user; # No local user matching the requested criteria, yet
+ return $U->simplereq( "open-ils.auth", "open-ils.auth.authenticate.init", "$uname:$uhome" );
+}
+
+__PACKAGE__->register_method(
+ method => "remote_auth_complete",
+ api_name => "open-ils.actor.remote.authenticate.complete",
+);
+sub remote_auth_complete {
+ my($self, $client, $args) = @_;
+
+ my $uhome = find_user_lib($$args{home});
+ return $U->DB_UPDATE_FAILED() if (!$uhome);
+
+ $$args{home} = $uhome->id;
+
+ my $actor = OpenSRF::AppSession->create("open-ils.actor");
+ my $ugroup = $actor->request(
+ "open-ils.actor.ou_setting.ancestor_default",
+ $$args{home},"ff.remote.user_cache.default_group"
+ )->gather(1);
+
+ if ($ugroup && ref($ugroup)) {
+ $ugroup = $ugroup->{'value'};
+ } else {
+ $ugroup = 1;
+ }
+
+ my $e = new_editor();
+ my $user = $e->search_actor_user({
+ usrname => "$$args{username}:$$args{home}",
+ home_ou => $$args{home}
+ })->[0];
+
+ my $remote_user;
+ if (!$user or $U->is_true($user->deleted)) {
+
+ $remote_user = $U->simplereq(
+ "fulfillment.laicore",
+ "fulfillment.laicore.lookup_user",
+ $$args{home}, $$args{username}, $$args{password}
+ );
+
+ $remote_user = OpenSRF::Utils::JSON->JSON2perl($remote_user)
+ if (!ref($remote_user)); # XXX arg.... (what's this now?)
+ }
+
+
+ my $seed_needed = 0;
+ if ($user) {
+ if ($U->is_true($user->deleted)) {
+ my $evt = resurrect_user($user, $remote_user, $ugroup, $args);
+ return $evt if $evt;
+ $seed_needed = 1;
+ }
+ } else {
+
+ my $u = $remote_user;
+
+ if ($u && !$$u{error}) { # create user ...
+ $seed_needed = 1;
+
+ $logger->info("FF creating new user for $$args{username}");
+
+ for my $k (keys %$u) {
+ delete $$u{$k} if ref($$u{$k});
+ }
+
+ my $evt;
+ my $patron = Fieldmapper::actor::user->new();
+ my $card = Fieldmapper::actor::card->new();
+
+ # how we find them locally
+ $patron->usrname( "$$args{username}:$$args{home}" );
+ $patron->passwd( $$args{password} );
+ $patron->profile( $ugroup );
+ $patron->home_ou( $$args{home} );
+ $patron->ident_type(3);
+
+ # what we can glean from the remote system
+ $patron->first_given_name( $$u{given_name} || '...' );
+ $patron->family_name( $$u{surname} || '...' );
+ $patron->suffix( $$u{suffix} );
+ $patron->prefix( $$u{prefix} );
+ $patron->alias( $$u{initials} );
+
+ # Set up all of the virtual IDs, isnew, etc.
+ $patron->isnew(1);
+ $patron->id(-1);
+ $patron->card(-1);
+
+ $card->isnew(1);
+ $card->id(-1);
+ $card->usr(-1);
+ $card->org($$args{home});
+ $card->barcode($$u{user_barcode} || $$u{user_id} || $$args{username});
+
+ $patron->cards([$card]);
+
+ my $session = $apputils->start_db_session();
+ $logger->info("Creating new remote-proxy patron...");
+
+ # $new_patron is the patron in progress. $patron is the original patron
+ # passed in with the method. new_patron will change as the components
+ # of patron are added/updated.
+
+ my $new_patron;
+
+ # unflesh the real items on the patron
+ $patron->card( $patron->card->id ) if(ref($patron->card));
+
+ # create the patron first so we can use his id
+ my $id = $session->request( "open-ils.storage.direct.actor.user.create", $patron)->gather(1);
+ return $U->DB_UPDATE_FAILED($patron) unless $id;
+
+ $logger->info("Successfully created new user [$id] in DB");
+
+ $new_patron = $session->request( "open-ils.storage.direct.actor.user.retrieve", $id)->gather(1);
+
+ ( $new_patron, $evt ) = _add_update_cards($session, $patron, $new_patron);
+ return $evt if $evt;
+
+ # re-update the patron
+ ( $new_patron, $evt ) = _update_patron($session, $new_patron, undef, 1);
+ return $evt if $evt;
+
+ $apputils->commit_db_session($session);
+ }
+ }
+
+ $$args{username} = "$$args{username}:$$args{home}";
+
+ if ($seed_needed) {
+ # initial call to .init exited early w/ no seed,
+ # so we need to create one now that we have a user
+ my $seed = $U->simplereq(
+ "open-ils.auth",
+ "open-ils.auth.authenticate.init",
+ $$args{username}
+ );
+
+ $$args{password} = md5_hex($seed . md5_hex($$args{password}));
+ }
+
+ return $U->simplereq( "open-ils.auth", "open-ils.auth.authenticate.complete", $args );
+}
+
+# the steps involved in user resurrection are just different
+# enough from user creation that blending them into one chain
+# of code gets messy. There may some room for combining
+# and refactoring here, since there is some duplication.
+sub resurrect_user {
+ my $user = shift;
+ my $remote_user = shift;
+ my $ugroup = shift;
+ my $args = shift;
+
+ $logger->info("Resurrecting deleted user ".$user->id);
+
+ my $e = new_editor(xact => 1);
+
+ my $card = $e->search_actor_card({usr => $user->id})->[0];
+
+ if (!$card) {
+ $card = Fieldmapper::actor::card->new();
+ $card->usr($user->id);
+ $card->isnew(1); # for our own tracking
+ $user->clear_card;
+ }
+
+ $user->deleted('f');
+ $user->usrname("$$args{username}:$$args{home}");
+ $user->passwd($$args{password});
+ $user->profile($ugroup);
+ $user->home_ou($$args{home});
+ $user->ident_type(3);
+
+ # what we can glean from the remote system
+ my $u = $remote_user;
+ $user->first_given_name($$u{given_name} || '...');
+ $user->family_name($$u{surname} || '...');
+ $user->suffix($$u{suffix});
+ $user->prefix($$u{prefix});
+ $user->alias($$u{initials});
+ $card->org($$args{home});
+ $card->barcode($$u{user_barcode} || $$u{user_id} || $$args{username});
+
+ $e->update_actor_user($user) or return $e->die_event;
+
+ if ($card->isnew) {
+ # create the new card and update the user
+ # object to refer to the card
+
+ $e->create_actor_card($card) or return $e->die_event;
+
+ # created a new card, tell the user object about it.
+ $user->card($card->id);
+ $e->update_actor_user($user) or return $e->die_event;
+
+ } else {
+ $e->update_actor_card($card) or return $e->die_event;
+ }
+
+ $e->commit;
+ return;
+}
+
+
+
+
+__PACKAGE__->register_method(
method => "update_user_setting",
api_name => "open-ils.actor.patron.settings.update",
);
return $s;
}
+__PACKAGE__->register_method(
+ method => "purge_bibs_by_owner",
+ api_name => "open-ils.cat.biblio.record.purge_by_owner",
+ signature => q/ Inserts a new biblio with the given XML /
+);
+
+sub purge_bibs_by_owner {
+ my( $self, $client, $auth, $owner ) = @_;
+
+ my $e = new_editor(authtoken => $auth);
+ return $e->die_event unless $e->checkauth;
+ return $e->die_event unless $e->allowed('UPDATE_MARC', $owner);
+
+ return OpenSRF::AppSession
+ ->create("open-ils.storage")
+ ->request("open-ils.storage.biblio.record_entry.purge_by_owner", $owner )
+ ->gather(1);
+}
__PACKAGE__->register_method(
# {"select":{"acp":["id"],"circ":[{"aggregate":true,"transform":"count","alias":"count","column":"id"}]},"from":{"acp":{"circ":{"field":"target_copy","fkey":"id","type":"left"},"acn"{"field":"id","fkey":"call_number"}}},"where":{"+acn":{"record":200057}}
+__PACKAGE__->register_method(
+ method => "item_transaction_disposition",
+ api_name => "open-ils.circ.item.transaction.disposition",
+ signature => {
+ desc => q/Given an item barcode, determines the disposition of the
+ copy with regard to open transactions. The goal is to report
+ on where the copy is going (if en route to or from a hold or
+ transit) or whether the copy is circulating. Since it's
+ possible for more than one copy with the provided barcode may
+ have some relationship to the context org unit, some data is
+ returned as arrays, while other data is returned as a single
+ object.
+
+ Lender transactions each are limited to one occurrence in total,
+ because they refer to a specific copy, which lives within ctx_ou.
+ All other actions may refer to multiple copies and thus have
+ multiple transactions.
+
+ Lender transit is the transit back home of the loaned copy
+ Borrower transits are all transits to elsewhere by copies
+ owned elsewhere.
+ /,
+ params => [
+ {desc => 'Authentication token', type => 'string'},
+ {desc => 'Context Org Unit ID', type => 'number'},
+ {desc => 'Copy Barcodde', type => 'string'},
+ ],
+ return => {desc => q/
+ Array of copies, sorted by locally owned copy first, followed
+ by copies owned by others. Each field in the response, minus
+ the 'copy' field, is optionally.
+ { copy : <copy>
+ circ : <circ>
+ hold : <hold>
+ transit : <transit>
+ }
+ /}
+ }
+);
+
+sub item_transaction_disposition {
+ my ($self, $client, $auth, $ctx_ou, $barcode) = @_;
+
+ my $e = new_editor(authtoken => $auth);
+ return $e->event unless $e->checkauth;
+ return $e->event unless $e->allowed('VIEW_CIRCULATIONS'); # catchall
+
+ # context ou may be a parent or a child of the various transaction
+ # and item owning lib org units.
+ my $org_list = $U->get_org_full_path($ctx_ou);
+
+ my $local_copy = $e->search_asset_copy({
+ deleted => 'f',
+ barcode => $barcode,
+ circ_lib => $org_list
+ })->[0];
+
+ my $remote_copies = $e->search_asset_copy({
+ deleted => 'f',
+ barcode => $barcode,
+ circ_lib => {'not in' => $org_list}
+ });
+
+ my @resp;
+
+ push(@resp,
+ collect_copy_transactions(
+ $e, $local_copy->id, $ctx_ou, $org_list, 1)
+ ) if $local_copy;
+
+ push(@resp,
+ collect_copy_transactions(
+ $e, $_->id, $ctx_ou, $org_list)
+ ) for @$remote_copies;
+
+ return \@resp;
+}
+
+sub collect_copy_transactions {
+ my ($e, $copy_id, $ctx_ou, $org_list, $local) = @_;
+ my $next_action = '';
+
+ my $transit_flesh = {
+ flesh => 4,
+ flesh_fields => {
+ atc => ['source', 'dest', 'hold_transit_copy'],
+ ahtc => ['hold'],
+ ahr => ['usr'],
+ au => ['card'],
+ aou => ['ill_address']
+ }
+ };
+
+ my $circ_flesh = {
+ flesh => 2,
+ flesh_fields => {
+ circ => ['usr'],
+ au => ['card']
+ }
+ };
+
+ my $hold_flesh = {
+ flesh => 3,
+ flesh_fields => {
+ ahr => ['transit', 'usr', 'cancel_cause'],
+ au => ['card'],
+ ahtc => ['source', 'dest']
+ }
+ };
+
+ my %resp = (
+ copy => $e->retrieve_asset_copy([
+ $copy_id, {
+ flesh => 3,
+ flesh_fields => {
+ acp => ['call_number', 'status'],
+ acn => ['record'],
+ # flesh simple_record for now as a hack to display title/author
+ bre => ['simple_record']
+ }
+ }
+ ])
+ );
+
+ $resp{copy}->call_number->record->clear_marc;
+
+ my $hold = $e->search_action_hold_request([
+ { fulfillment_time => undef,
+ cancel_time => undef,
+ frozen => 'f',
+ current_copy => $copy_id
+ }, $hold_flesh
+ ])->[0];
+
+ if ($hold) {
+ if ($local) {
+ $next_action = 'ill-home-capture' unless $hold->capture_time;
+ $resp{can_retarget_hold} = 1;
+
+ } else {
+ # for non-local copies, only the borrower can cancel
+ # or retarget the hold
+ if (grep {$hold->request_lib == $_} @$org_list) {
+ $resp{can_cancel_hold} = 1;
+ $resp{can_retarget_hold} = 1;
+ }
+
+ if ($hold->pickup_lib == $ctx_ou) {
+
+ # hold is en route to here, maybe there is work for us to do
+
+ if ($hold->shelf_time) {
+ $next_action = 'ill-foreign-checkout';
+ } elsif ($hold->capture_time) {
+ $next_action = 'ill-foreign-receive';
+ }
+ }
+ }
+
+ $resp{hold} = $hold;
+ }
+
+ # non-local copies must be circulting "here" to be relevant
+ my %circ_filter = (circ_lib => $org_list) unless $local;
+
+ my $circ = $e->search_action_circulation([{
+ checkin_time => undef,
+ target_copy => $copy_id,
+ %circ_filter
+ }, $circ_flesh])->[0];
+
+ if ($circ) {
+ $next_action = 'ill-foreign-checkin' unless $local;
+ $resp{circ} = $circ;
+ }
+
+ my %transit_filter;
+
+ # non-local copies must be coming to / going from "here" to be relevant
+ $transit_filter{'-or'} =
+ [{dest => $org_list}, {source => $org_list}]
+ unless $local;
+
+ # no need to re-fetch transits linked to holds
+ $transit_filter{id} = {'<>' => $hold->transit->id}
+ if $hold and $hold->transit;
+
+ my $transit = $e->search_action_transit_copy([{
+ target_copy => $copy_id,
+ dest_recv_time => undef,
+ %transit_filter
+ }, $transit_flesh])->[0];
+
+ if ($transit) {
+ if ($transit->dest->id == $ctx_ou) {
+ if ($local) {
+ $next_action = 'transit-home-receive'
+ } else {
+ $next_action = 'transit-foreign-return';
+ }
+ }
+ $resp{transit} = $transit;
+ }
+
+ $resp{next_action} = $next_action;
+ return \%resp;
+}
+
+
+
1;
$circulator->do_renew();
}
+ my $remote = 0;
if( $circulator->bail_out ) {
my @ee;
} else {
$circulator->editor->commit;
+ $remote = 1;
if ($circulator->generate_lost_overdue) {
# Generating additional overdue billings has to happen after the
$circulator->script_runner->cleanup if $circulator->script_runner;
+ if ($remote) {
+ my $ff_action = $circulator->ff_action || '';
+ my $cl = $circulator->circ_lib;
+ $cl = $cl->id if (ref $cl);
+
+ # user_barcode is not fleshed (or needed) in all contexts
+ my $user_barcode = $circulator->patron->card->barcode
+ if $circulator->patron and $circulator->patron->card;
+
+ $logger->info("circulator: performing FF action '$ff_action'");
+
+ my $FF = OpenSRF::AppSession->create('fulfillment.laicore');
+
+ if ($ff_action eq 'ill-home-capture') {
+ $FF->request( 'fulfillment.laicore.circ.lender.checkout',
+ $cl, $circulator->copy->barcode )->gather(1);
+
+ } elsif ($ff_action eq 'ill-foreign-receive') {
+
+ # create the temporary copy for the borrower
+ my $tmp_copy = $FF->request(
+ 'fulfillment.laicore.item.create_for_borrower',
+ $cl, $circulator->copy->id)->gather(1);
+
+ if ($tmp_copy) {
+ my $bc = $tmp_copy->{barcode};
+
+ $logger->info("circulator: created tmp copy for ".
+ "borrower, attempting hold placement for $bc at $cl");
+
+ # place a hold on the temp copy for the borrower
+ # at the borrowing library
+
+ # ensure the borrower hold is placed against the same
+ # patron for which the FF hold was captured and transited.
+ $user_barcode = $circulator->editor->retrieve_actor_user([
+ $circulator->hold->usr,
+ {flesh => 1, flesh_fields => {au => ['card']}}
+ ])->card->barcode;
+
+ $FF->request(
+ 'fulfillment.laicore.hold.borrower.place',
+ $cl, $bc, $user_barcode)->gather(1);
+
+ # check the temp copy in at the borrowing library
+ # to capture the hold for the patron.
+
+ $FF->request(
+ 'fulfillment.laicore.circ.borrower.checkin',
+ $cl, $bc, $user_barcode)->gather(1);
+
+ } else {
+
+ # some connectors may not allow us to create borrower copies.
+ $logger->info("FF no borrower copy created for copy ".
+ $circulator->copy->barcode.", skipping borrower library hold");
+ }
+
+ } elsif ($ff_action eq 'ill-foreign-checkout') {
+ $FF->request( 'fulfillment.laicore.circ.borrower.checkout',
+ $cl, $circulator->copy->barcode, $user_barcode)->gather(1);
+
+ } elsif ($ff_action eq 'ill-foreign-checkin') {
+ $FF->request( 'fulfillment.laicore.circ.borrower.checkin',
+ $cl, $circulator->copy->barcode )->gather(1);
+
+ } elsif ($ff_action eq 'transit-home-receive') {
+ $FF->request( 'fulfillment.laicore.circ.lender.checkin',
+ $cl, $circulator->copy->barcode )->gather(1);
+ }
+ }
+
return undef if $circulator->bail_out;
$circulator->do_hold_notify($circulator->notify_hold)
skip_permit_key
skip_deposit_fee
skip_rental_fee
+ ff_action
use_booking
generate_lost_overdue
clear_expired
return 1;
}
+ my $copy = $e->retrieve_asset_copy($hold->current_copy) if $hold->current_copy;
+
# If the hold is captured, reset the copy status
- if( $hold->capture_time and $hold->current_copy ) {
+ if( $hold->capture_time and $copy ) {
my $copy = $e->retrieve_asset_copy($hold->current_copy)
or return $e->die_event;
$U->create_events_for_hook('hold_request.cancel.staff', $hold, $hold->pickup_lib);
}
+ # perform FF tasks after the hold is successfully canceled -------
+ # do not block on FF calls. Fire and forget.
+
+ # the hold within the lender ILS is fulfilled the moment the FF hold is
+ # captured. It makes no sense to cancel the lender-ILS hold after that.
+ if ($copy and !$hold->capture_time) {
+ my $ses = OpenSRF::AppSession->create('fulfillment.laicore');
+ $ses->request(
+ 'fulfillment.laicore.hold.lender.delete_earliest',
+ $copy->source_lib,
+ $copy->barcode
+ );
+ }
+
+ if ($hold->shelf_time) {
+ # The requested copy has made it to the borrower and a tmp copy
+ # has been created w/ a hold.
+ # TODO: cancel the hold within the borrower ILS on the tmp copy
+ }
+
return 1;
}
my $hid = $hold->id;
- if( $hold->capture_time and $hold->current_copy ) {
+ my $copy = $e->retrieve_asset_copy($hold->current_copy) if $hold->current_copy;
+
+ if( $hold->capture_time and $copy ) {
my $copy = $e->retrieve_asset_copy($hold->current_copy)
or return $e->die_event;
$e->update_action_hold_request($hold) or return $e->die_event;
$e->commit;
+ # TODO: we should only cancel the lender hold
+ # if the FF hold has not yet been captured ?
+ if ($copy) {
+ $U->simplereq(
+ "fulfillment.laicore",
+ "fulfillment.laicore.hold.lender.delete_earliest",
+ $copy->source_lib, $copy->barcode
+ );
+ }
+
$U->storagereq(
'open-ils.storage.action.hold_request.copy_targeter', undef, $hold->id );
return () if $depth == $top_org->ou_type->depth;
my $org_list = $U->storagereq('open-ils.storage.actor.org_unit.descendants.atomic', $selection_ou, $depth);
- %org_filter = (circ_lib => []);
- push(@{$org_filter{circ_lib}}, $_->id) for @$org_list;
+ %org_filter = (circ_lib => {'not in' => []});
+ push(@{$org_filter{circ_lib}{'not in'}}, $_->id) for @$org_list;
$logger->info("hold org filter at depth $depth and selection_ou ".
- "$selection_ou created list of @{$org_filter{circ_lib}}");
+ "$selection_ou created list of @{$org_filter{circ_lib}{'not in'}}");
return %org_filter;
}
__PACKAGE__->table( 'actor_card' );
__PACKAGE__->columns( Primary => qw/id/ );
-__PACKAGE__->columns( Essential => qw/usr barcode active/ );
+__PACKAGE__->columns( Essential => qw/usr barcode active org/ );
#-------------------------------------------------------------------------------
package actor::user_access_entry;
fine_level circulate deposit price ref opac_visible
circ_as_type circ_modifier deposit_amount location mint_condition
holdable dummy_title dummy_author deleted alert_message
- age_protect floating cost status_changed_time active_date/ );
+ age_protect floating cost status_changed_time active_date source_lib/ );
#-------------------------------------------------------------------------------
package asset::copy_part_map;
biblio::record_entry->table( 'biblio_record_entry' );
biblio::record_entry->columns( Essential => qw/id tcn_source tcn_value creator editor
create_date edit_date source active quality owner share_depth
- deleted marc last_xact_id fingerprint/ );
+ deleted marc last_xact_id fingerprint remote_id/ );
#-------------------------------------------------------------------------------
package biblio::record_note;
use POSIX qw(ceil);
use OpenILS::Application::Circ::CircCommon;
use OpenILS::Application::AppUtils;
+use FulfILLment::AT::Reactor::ItemLoad;
+use FulfILLment::AT::Reactor::ItemRefresh;
my $U = "OpenILS::Application::AppUtils";
# Used in build_hold_sort_clause(). See the hash %order_by_sprintf_args in
frozen => 'f',
prev_check_time => { '<=' => $expire_threshold },
},
- { order_by => 'selection_depth DESC, request_time,prev_check_time' } ) ];
+ { order_by => 'selection_depth, request_time,prev_check_time' } ) ];
# find all the holds holds needing first time targeting
push @$holds, action::hold_request->search(
prev_check_time => undef,
frozen => 'f',
cancel_time => undef,
- { order_by => 'selection_depth DESC, request_time' } );
+ { order_by => 'selection_depth, request_time' } );
} else {
# find all the holds holds needing first time targeting ONLY
prev_check_time => undef,
cancel_time => undef,
frozen => 'f',
- { order_by => 'selection_depth DESC, request_time' } ) ];
+ { order_by => 'selection_depth, request_time' } ) ];
}
} catch Error with {
my $e = shift;
for my $hold (@$holds) {
try {
+ my $old_current_copy = $hold->current_copy;
+
#start a transaction if needed
if ($self->method_lookup('open-ils.storage.transaction.current')->run) {
$log->debug("Cleaning up after previous transaction\n");
$self->method_lookup('open-ils.storage.transaction.begin')->run( $client );
$log->info("Processing hold ".$hold->id."...\n");
+
#first, re-fetch the hold, to make sure it's not captured already
$hold->remove_from_object_index();
$hold = action::hold_request->retrieve( $hold->id );
( $lang ? (item_lang => $lang) : () ),
)
) {
+
+ FulfILLment::AT::Reactor::ItemLoad->ByBib( { target => $_->to_fieldmapper } )
+ for ( metabib::metarecord->retrieve($hold->target)->source_records );
+
my ($rtree) = $self
->method_lookup( 'open-ils.storage.biblio.record_entry.ranged_tree')
->run( $r->id, $hold->selection_ou, $hold->selection_depth );
}
}
} elsif ($hold->hold_type eq 'T') {
+
+ FulfILLment::AT::Reactor::ItemLoad->ByBib(
+ { target => biblio::record_entry->retrieve($hold->target)->to_fieldmapper }
+ );
+
my ($rtree) = $self
->method_lookup( 'open-ils.storage.biblio.record_entry.ranged_tree')
->run( $hold->target, $hold->selection_ou, $hold->selection_depth );
) if ($cn && @{ $cn->copies });
}
} elsif ($hold->hold_type eq 'V') {
+
+ FulfILLment::AT::Reactor::ItemLoad->ByBib(
+ { target => asset::call_number->retrieve($hold->target)->record->to_fieldmapper }
+ );
+
my ($vtree) = $self
->method_lookup( 'open-ils.storage.asset.call_number.ranged_tree')
->run( $hold->target, $hold->selection_ou, $hold->selection_depth );
) if ($itree && @{ $itree->items });
} elsif ($hold->hold_type eq 'C' || $hold->hold_type eq 'R' || $hold->hold_type eq 'F') {
+
+ FulfILLment::AT::Reactor::ItemRefresh->ByItem(
+ { target => asset::copy->retrieve($hold->target)->to_fieldmapper }
+ );
+
my $_cp = asset::copy->retrieve($hold->target);
push @$all_copies, $_cp if $_cp;
}
$hold
);
- $all_copies = [ grep { ''.$_->circ_lib ne $pu_lib && ( $_->status == 0 || $_->status == 7 ) } @good_copies ];
+ #$all_copies = [ grep { ''.$_->circ_lib ne $pu_lib && ( $_->status == 0 || $_->status == 7 ) } @good_copies ];
+ $all_copies = [];
+ for my $prox (keys %$prox_list) {
+ push @$all_copies, @{$$prox_list{$prox}};
+ }
my $min_prox = [ sort keys %$prox_list ]->[0];
my $best;
}
$self->method_lookup('open-ils.storage.transaction.commit')->run;
+
+ # FF-----------------
+ my $skip_target = 0;
+ if ($old_current_copy && $best && ($best->id == $old_current_copy->id)) { # old copy and new copy are the same, leave it alone
+ $skip_target = 1;
+ } elsif ($old_current_copy) { # old copy to remotely untarget, since we have a new one
+ $U->simplereq(
+ "fulfillment.laicore",
+ "fulfillment.laicore.hold.lender.delete_earliest",
+ '' . $old_current_copy->source_lib,
+ $old_current_copy->barcode
+ );
+ }
+
+ if ($best && !$skip_target) { # new copy to target
+ $U->simplereq(
+ "fulfillment.laicore",
+ "fulfillment.laicore.hold.lender.place",
+ ''. $best->source_lib,
+ $best->barcode
+ );
+ }
+ # FF-----------------
+
+
$log->info("\tProcessing of hold ".$hold->id." complete.");
push @successes,
actor::org_unit
->db_Main
->selectcol_arrayref(
- 'SELECT id FROM actor.org_unit_descendants(?,?)',
+ 'SELECT id FROM actor.org_unit WHERE id NOT IN (SELECT id FROM actor.org_unit_descendants(?,?))',
{},
$ou,
$depth
actor::org_unit
->db_Main
->selectcol_arrayref(
- 'SELECT id FROM actor.org_unit_descendants(?,?)',
+ 'SELECT id FROM actor.org_unit WHERE id NOT IN (SELECT id FROM actor.org_unit_descendants(?,?))',
{},
$ou,
$depth
my $offset = shift || 0;
my $ou_sql = defined($depth) ?
- "SELECT id FROM actor.org_unit_descendants(?,?)":
- "SELECT id FROM actor.org_unit_descendants(?)";
+ "SELECT id FROM actor.org_unit WHERE id NOT IN (SELECT id FROM actor.org_unit_descendants(?,?))":
+ "SELECT id FROM actor.org_unit WHERE id NOT IN (SELECT id FROM actor.org_unit_descendants(?))";
my $ou_list =
actor::org_unit
cachable => 1,
);
+sub purge_bibs_by_owner {
+ my $self = shift;
+ my $client = shift;
+ my $owner = ''.shift;
+
+ return biblio::record_entry->db_Main->do( 'DELETE FROM biblio.record_entry WHERE owner = ?', {}, $owner );
+}
+__PACKAGE__->register_method(
+ api_name => 'open-ils.storage.biblio.record_entry.purge_by_owner',
+ method => 'purge_bibs_by_owner',
+ api_level => 1,
+ argc => 1,
+ cachable => 1,
+);
+
sub record_by_copy {
my $self = shift;
my $client = shift;