New constituent record filtering method for hold targeting, also exposed to the world...
authorMike Rylander <mrylander@gmail.com>
Fri, 31 Jan 2014 17:33:33 +0000 (12:33 -0500)
committerBill Erickson <berick@esilibrary.com>
Mon, 10 Feb 2014 16:02:14 +0000 (11:02 -0500)
Signed-off-by: Mike Rylander <mrylander@gmail.com>
Signed-off-by: Bill Erickson <berick@esilibrary.com>
Open-ILS/src/perlmods/lib/OpenILS/Application/Circ/Holds.pm
Open-ILS/src/perlmods/lib/OpenILS/Application/Storage/Publisher/action.pm

index 22979ba..ca0859d 100644 (file)
@@ -2477,10 +2477,9 @@ sub do_possibility_checks {
 
     } elsif( $hold_type eq OILS_HOLD_TYPE_METARECORD ) {
 
-        my $maps = $e->search_metabib_metarecord_source_map({metarecord=>$mrid});
-        my @recs = map { $_->source } @$maps;
+        my $recs = __PACKAGE__->method_lookup('open-ils.circ.holds.metarecord.filterd_records')->run($mrid, $holdable_formats);
         my @status = ();
-        for my $rec (@recs) {
+        for my $rec (@$recs) {
             @status = _check_title_hold_is_possible(
                 $rec, $depth, $request_lib, $patron, $e->requestor, $pickup_lib, $selection_ou, $holdable_formats, $oargs
             );
@@ -2491,6 +2490,15 @@ sub do_possibility_checks {
 #   else { Unrecognized hold_type ! }   # FIXME: return error? or 0?
 }
 
+sub MR_filter_records {
+    return $U->storagereq('open-ils.storage.metarecord.filtered_records.atomic', $_[2], $_[3]);
+}
+__PACKAGE__->register_method(
+    method   => 'MR_filter_records',
+    api_name => 'open-ils.circ.holds.metarecord.filterd_records',
+);
+
+
 my %prox_cache;
 sub create_ranged_org_filter {
     my($e, $selection_ou, $depth) = @_;
@@ -2518,11 +2526,7 @@ sub create_ranged_org_filter {
 
 sub _check_title_hold_is_possible {
     my( $titleid, $depth, $request_lib, $patron, $requestor, $pickup_lib, $selection_ou, $holdable_formats, $oargs ) = @_;
-
-    my ($types, $formats, $lang);
-    if (defined($holdable_formats)) {
-        ($types, $formats, $lang) = split '-', $holdable_formats;
-    }
+    # $holdable_formats is now unused. We pre-filter the MR's records.
 
     my $e = new_editor();
     my %org_filter = create_ranged_org_filter($e, $selection_ou, $depth);
@@ -2536,23 +2540,7 @@ sub _check_title_hold_is_possible {
                     acn => {
                         field  => 'id',
                         fkey   => 'call_number',
-                        'join' => {
-                            bre => {
-                                field  => 'id',
-                                filter => { id => $titleid },
-                                fkey   => 'record'
-                            },
-                            mrd => {
-                                field  => 'record',
-                                fkey   => 'record',
-                                filter => {
-                                    record => $titleid,
-                                    ( $types   ? (item_type => [split '', $types])   : () ),
-                                    ( $formats ? (item_form => [split '', $formats]) : () ),
-                                    ( $lang    ? (item_lang => $lang)                : () )
-                                }
-                            }
-                        }
+                        filter => { record => $titleid }
                     },
                     acpl => { field => 'id', filter => { holdable => 't'}, fkey => 'location' },
                     ccs  => { field => 'id', filter => { holdable => 't'}, fkey => 'status'   },
index 9692f27..a897126 100644 (file)
@@ -1266,6 +1266,47 @@ __PACKAGE__->register_method(
 );
 
 
+sub MR_records_matching_format {
+    my $self = shift;
+    my $client = shift;
+    my $MR = shift;
+    my $filter = shift;
+
+    # find filters for MR holds
+    my $mr_filter;
+    if (defined($filter)) {
+        ($mr_filter) = @{action::hold_request->db_Main->selectcol_arrayref(
+            'SELECT metabib.compile_composite_attr(?)',
+            {},
+            $filter
+        )};
+    }
+
+    my $records = [metabib::metarecord->retrieve($MR)->source_records];
+
+    if (!$mr_filter) {
+        $client->respond( $_->id ) for @$records;
+    } else {
+        for my $r ( map { isTrue($_->deleted) ?  () : ($_->id) } @$records ) {
+            $client->respond($r) if
+                @{action::hold_request->db_Main->selectcol_arrayref(
+                    'SELECT source FROM metabib.record_attr_vector_list WHERE source = ? AND vlist @@ ?',
+                    {},
+                    $r,
+                    $mr_filter
+                )};
+        }
+    }
+    return; # discard final l-val
+}
+__PACKAGE__->register_method(
+    api_name        => 'open-ils.storage.metarecord.filtered_records',
+    api_level       => 1,
+    stream          => 1,
+    argc            => 2,
+    method          => 'MR_records_matching_format',
+);
+
 
 sub new_hold_copy_targeter {
     my $self = shift;
@@ -1415,41 +1456,23 @@ sub new_hold_copy_targeter {
 
             my $all_copies = [];
 
-            # find filters for MR holds
-            my ($types, $formats, $lang);
-            if (defined($hold->holdable_formats)) {
-                ($types, $formats, $lang) = split '-', $hold->holdable_formats;
-            }
-
             # find all the potential copies
             if ($hold->hold_type eq 'M') {
-                my $records = [
-                    map {
-                        isTrue($_->deleted) ?  () : ($_->id)
-                    } metabib::metarecord->retrieve($hold->target)->source_records
-                ];
-                if(@$records > 0) {
-                    for my $r ( map
-                            {$_->record}
-                            metabib::record_descriptor
-                                ->search(
-                                    record => $records,
-                                    ( $types   ? (item_type => [split '', $types])   : () ),
-                                    ( $formats ? (item_form => [split '', $formats]) : () ),
-                                    ( $lang    ? (item_lang => $lang)                : () ),
-                                )
-                    ) {
-                        my ($rtree) = $self
-                            ->method_lookup( 'open-ils.storage.biblio.record_entry.ranged_tree')
-                            ->run( $r->id, $hold->selection_ou, $hold->selection_depth );
-
-                        for my $cn ( @{ $rtree->call_numbers } ) {
-                            push @$all_copies,
-                                asset::copy->search_where(
-                                    { id => [map {$_->id} @{ $cn->copies }],
-                                      deleted => 'f' }
-                                ) if ($cn && @{ $cn->copies });
-                        }
+                for my $r_id (
+                    $self->method_lookup(
+                        'open-ils.storage.metarecord.filtered_records'
+                    )->run( $hold->target, $hold->holdable_formats )
+                ) {
+                    my ($rtree) = $self
+                        ->method_lookup( 'open-ils.storage.biblio.record_entry.ranged_tree')
+                        ->run( $r_id, $hold->selection_ou, $hold->selection_depth );
+
+                    for my $cn ( @{ $rtree->call_numbers } ) {
+                        push @$all_copies,
+                            asset::copy->search_where(
+                                { id => [map {$_->id} @{ $cn->copies }],
+                                  deleted => 'f' }
+                            ) if ($cn && @{ $cn->copies });
                     }
                 }
             } elsif ($hold->hold_type eq 'T') {
@@ -2306,32 +2329,5 @@ sub title_hold_capture {
     $self->volume_hold_capture($hold,$cn_list) if (ref $cn_list and @$cn_list);
 }
 
-sub metarecord_hold_capture {
-    my $self = shift;
-    my $hold = shift;
-
-    my $titles;
-    try {
-        $titles = [ metabib::metarecord_source_map->search( metarecord => $hold->target) ];
-    
-    } catch Error with {
-        my $e = shift;
-        die "Could not retrieve initial title list:\n\n$e\n";
-    };
-
-    try {
-        my @recs = map {$_->record} metabib::record_descriptor->search( record => $titles, item_type => [split '', $hold->holdable_formats] ); 
-
-        $titles = [ biblio::record_entry->search( id => \@recs ) ];
-    
-    } catch Error with {
-        my $e = shift;
-        die "Could not retrieve format-pruned title list:\n\n$e\n";
-    };
-
-
-    $cache{titles}{$_->id} = $_ for (@$titles);
-    $self->title_hold_capture($hold,$titles) if (ref $titles and @$titles);
-}
 
 1;