From c2b0a00e09c91f03f9eb4d314550ddb72ad6beab Mon Sep 17 00:00:00 2001 From: erickson Date: Mon, 5 Feb 2007 19:14:23 +0000 Subject: [PATCH] for title hold possibility check, we now sort copies into buckets based on the copy circ lib. then we check "closest" copies first since they are the more likely to be allowed, and therefore allow the possibility check to succeed. git-svn-id: svn://svn.open-ils.org/ILS/branches/rel_1_0@6879 dcc99617-32d9-48b4-a31d-7c20da2025e4 --- .../src/perlmods/OpenILS/Application/Circ/Holds.pm | 116 ++++++++++++++++++++- 1 file changed, 115 insertions(+), 1 deletion(-) diff --git a/Open-ILS/src/perlmods/OpenILS/Application/Circ/Holds.pm b/Open-ILS/src/perlmods/OpenILS/Application/Circ/Holds.pm index ef708c0b24..9d37096ec7 100644 --- a/Open-ILS/src/perlmods/OpenILS/Application/Circ/Holds.pm +++ b/Open-ILS/src/perlmods/OpenILS/Application/Circ/Holds.pm @@ -1046,7 +1046,7 @@ sub check_title_hold { -sub _check_title_hold_is_possible { +sub ___check_title_hold_is_possible { my( $titleid, $rangelib, $depth, $request_lib, $patron, $requestor, $pickup_lib ) = @_; my $limit = 10; @@ -1081,6 +1081,120 @@ sub _check_title_hold_is_possible { return 0; } +my %prox_cache; + +sub _check_title_hold_is_possible { + my( $titleid, $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 record + my $copies = $e->json_query( + { + select => { acp => ['id', 'circ_lib'] }, + from => { + acp => { + acn => { + field => 'id', + fkey => 'call_number', + 'join' => { + bre => { + field => 'id', + filter => { id => $titleid }, + fkey => 'record' + } + } + }, + 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("title 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 $title; + 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); + + unless($title) { # grab the title if we don't already have it + my $vol = $e->retrieve_asset_call_number( + [ $copy->call_number, { flesh => 1, flesh_fields => { acn => ['record'] } } ] ); + $title = $vol->record; + } + + return 1 if verify_copy_for_hold( + $patron, $requestor, $title, $copy, $pickup_lib, $request_lib ); + + } + } + + return 0; +} + + sub _check_volume_hold_is_possible { my( $vol, $title, $rangelib, $depth, $request_lib, $patron, $requestor, $pickup_lib ) = @_; my $copies = new_editor->search_asset_copy({call_number => $vol->id}); -- 2.11.0