From 8fc88553c1ce08fe208926bdc77af2d0b57e93ed Mon Sep 17 00:00:00 2001 From: miker Date: Wed, 5 Dec 2007 17:01:38 +0000 Subject: [PATCH] speedy json_query version of metarecord hold permit git-svn-id: svn://svn.open-ils.org/ILS/trunk@8139 dcc99617-32d9-48b4-a31d-7c20da2025e4 --- .../src/perlmods/OpenILS/Application/Circ/Holds.pm | 113 +++++++++++++++++++++ 1 file changed, 113 insertions(+) diff --git a/Open-ILS/src/perlmods/OpenILS/Application/Circ/Holds.pm b/Open-ILS/src/perlmods/OpenILS/Application/Circ/Holds.pm index 2801f35013..9691f2b1f5 100644 --- a/Open-ILS/src/perlmods/OpenILS/Application/Circ/Holds.pm +++ b/Open-ILS/src/perlmods/OpenILS/Application/Circ/Holds.pm @@ -1092,6 +1092,119 @@ sub ___check_title_hold_is_possible { my %prox_cache; +sub _check_metarecord_hold_is_possible { + my( $mrid, $rangelib, $depth, $request_lib, $patron, $requestor, $pickup_lib ) = @_; + + my $e = new_editor(); + + # this monster will grab the id and circ_lib of all of the "holdable" copies for the given metarecord + my $copies = $e->json_query( + { + select => { acp => ['id', 'circ_lib'] }, + from => { + acp => { + acn => { + field => 'id', + fkey => 'call_number', + 'join' => { + bre => { + field => 'id', + fkey => 'record', + 'join' => { + mmrsm => { + filter => { metarecord => $mrid }, + field => 'source', + fkey => 'id' + } + } + } + } + }, + acpl => { field => 'id', filter => { holdable => 't'}, fkey => 'location' }, + ccs => { field => 'id', filter => { holdable => 't'}, fkey => 'status' } + } + }, + where => { + '+acp' => { circulate => 't', deleted => 'f', holdable => 't' } + } + } + ); + + return $e->event unless defined $copies; + $logger->info("metarecord possible found ".scalar(@$copies)." potential copies"); + return 0 unless @$copies; + + # ----------------------------------------------------------------------- + # sort the copies into buckets based on their circ_lib proximity to + # the patron's home_ou. + # ----------------------------------------------------------------------- + + my $home_org = $patron->home_ou; + my $req_org = $request_lib->id; + + my $home_prox = + ($prox_cache{$home_org}) ? + $prox_cache{$home_org} : + $prox_cache{$home_org} = $e->search_actor_org_unit_proximity({from_org => $home_org}); + + my %buckets; + my %hash = map { ($_->to_org => $_->prox) } @$home_prox; + push( @{$buckets{ $hash{$_->{circ_lib}} } }, $_->{id} ) for @$copies; + + my @keys = sort { $a <=> $b } keys %buckets; + + + if( $home_org ne $req_org ) { + # ----------------------------------------------------------------------- + # shove the copies close to the request_lib into the primary buckets + # directly before the farthest away copies. That way, they are not + # given priority, but they are checked before the farthest copies. + # ----------------------------------------------------------------------- + my $req_prox = + ($prox_cache{$req_org}) ? + $prox_cache{$req_org} : + $prox_cache{$req_org} = $e->search_actor_org_unit_proximity({from_org => $req_org}); + + my %buckets2; + my %hash2 = map { ($_->to_org => $_->prox) } @$req_prox; + push( @{$buckets2{ $hash2{$_->{circ_lib}} } }, $_->{id} ) for @$copies; + + my $highest_key = $keys[@keys - 1]; # the farthest prox in the exising buckets + my $new_key = $highest_key - 0.5; # right before the farthest prox + my @keys2 = sort { $a <=> $b } keys %buckets2; + for my $key (@keys2) { + last if $key >= $highest_key; + push( @{$buckets{$new_key}}, $_ ) for @{$buckets2{$key}}; + } + } + + @keys = sort { $a <=> $b } keys %buckets; + + my %seen; + for my $key (@keys) { + my @cps = @{$buckets{$key}}; + + $logger->info("looking at " . scalar(@{$buckets{$key}}). " copies in proximity bucket $key"); + + for my $copyid (@cps) { + + next if $seen{$copyid}; + $seen{$copyid} = 1; # there could be dupes given the merged buckets + my $copy = $e->retrieve_asset_copy($copyid) or return $e->event; + $logger->debug("looking at bucket_key=$key, copy $copyid : circ_lib = " . $copy->circ_lib); + + my $vol = $e->retrieve_asset_call_number( + [ $copy->call_number, { flesh => 1, flesh_fields => { acn => ['record'] } } ] ); + + return 1 if verify_copy_for_hold( + $patron, $requestor, $vol->record, $copy, $pickup_lib, $request_lib ); + + } + } + + return 0; +} + sub _check_title_hold_is_possible { my( $titleid, $rangelib, $depth, $request_lib, $patron, $requestor, $pickup_lib ) = @_; -- 2.11.0