LP1913807 Staff catalog shows preferred lib holdings counts
[evergreen-equinox.git] / Open-ILS / src / perlmods / lib / OpenILS / Application / Search / Biblio.pm
index 06d695a..9fe2500 100644 (file)
@@ -2887,8 +2887,9 @@ sub mk_copy_query {
     my $copy_offset = shift;
     my $pref_ou = shift;
     my $is_staff = shift;
+    my $base_query = shift;
 
-    my $query = $U->basic_opac_copy_query(
+    my $query = $base_query || $U->basic_opac_copy_query(
         $rec_id, undef, undef, $copy_limit, $copy_offset, $is_staff
     );
 
@@ -2912,6 +2913,16 @@ sub mk_copy_query {
                 }
             }
         }};
+
+        if ($pref_ou) {
+            # Make sure the pref OU is included in the results
+            my $in = $query->{from}->{acp}->[1]->{aou}->{filter}->{id}->{in};
+            delete $query->{from}->{acp}->[1]->{aou}->{filter}->{id};
+            $query->{from}->{acp}->[1]->{aou}->{filter}->{'-or'} = [
+                {id => {in => $in}},
+                {id => $pref_ou}
+            ];
+        }
     };
 
     # Unsure if we want these in the shared function, leaving here for now
@@ -2937,6 +2948,7 @@ __PACKAGE__->register_method(
     signature => {
         desc   => q/Returns bib record 856 URL content./,
         params => [
+            {desc => 'Context org unit ID', type => 'number'},
             {desc => 'Record ID or Array of Record IDs', type => 'number or array'}
         ],
         return => {
@@ -2947,23 +2959,35 @@ __PACKAGE__->register_method(
 );
 
 sub record_urls {
-    my ($self, $client, $record_ids) = @_;
+    my ($self, $client, $org_id, $record_ids) = @_;
 
     $record_ids = [$record_ids] unless ref $record_ids eq 'ARRAY';
 
     my $e = new_editor();
 
     for my $record_id (@$record_ids) {
+
+        my @urls;
+
+        # Start with scoped located URIs
+        my $uris = $e->json_query({
+            from => ['evergreen.located_uris_as_uris', $record_id, $org_id]});
+
+        for my $uri (@$uris) {
+            push(@urls, {
+                href => $uri->{href},
+                label => $uri->{label},
+                note => $uri->{use_restriction}
+            });
+        }
+
+        # Logic copied from TPAC misc_utils.tts
         my $bib = $e->retrieve_biblio_record_entry($record_id)
             or return $e->event;
 
         my $marc_doc = $U->marc_xml_to_doc($bib->marc);
 
-        # Logic copied from TPAC misc_utils.tts
-        my @urls;
-
-        for my $node ($marc_doc->findnodes(
-            '//*[@tag="856" and @ind1="4" and (@ind2="0" or @ind2="1")]')) {
+        for my $node ($marc_doc->findnodes('//*[@tag="856" and @ind1="4"]')) {
 
             # asset.uri's
             next if $node->findnodes('./*[@code="9" or @code="w" or @code="n"]');
@@ -2985,7 +3009,8 @@ sub record_urls {
                 push(@urls, {
                     href => $href,
                     label => ($first && $label) ?  $label->textContent : $href,
-                    note => ($first && $notes) ? $notes->textContent : ''
+                    note => ($first && $notes) ? $notes->textContent : '',
+                    ind2 => $node->getAttribute('ind2')
                 });
                 $first = 0;
             }
@@ -3043,8 +3068,10 @@ __PACKAGE__->register_method(
 
 
 sub catalog_record_summary {
-    my ($self, $client, $org_id, $record_ids) = @_;
+    my ($self, $client, $org_id, $record_ids, $options) = @_;
     my $e = new_editor();
+    $options ||= {};
+    my $pref_ou = $options->{pref_ou};
 
     my $is_meta = ($self->api_name =~ /metabib/);
     my $is_staff = ($self->api_name =~ /staff/);
@@ -3064,26 +3091,128 @@ sub catalog_record_summary {
     for my $rec_id (@$record_ids) {
 
         my $response = $is_meta ? 
-            get_one_metarecord_summary($self, $e, $rec_id) :
-            get_one_record_summary($self, $e, $rec_id);
+            get_one_metarecord_summary($self, $e, $org_id, $rec_id) :
+            get_one_record_summary($self, $e, $org_id, $rec_id);
 
         ($response->{copy_counts}) = $copy_method->run($org_id, $rec_id);
 
+        $response->{first_call_number} = get_first_call_number(
+            $e, $rec_id, $org_id, $is_staff, $is_meta, $options);
+
+        if ($pref_ou) {
+
+            # If we already have the pref ou copy counts, avoid the extra fetch.
+            my ($match) = 
+                grep {$_->{org_unit} eq $pref_ou} @{$response->{copy_counts}};
+
+            if (!$match) {
+                my ($counts) = $copy_method->run($pref_ou, $rec_id);
+                ($match) = grep {$_->{org_unit} eq $pref_ou} @$counts;
+            }
+
+            $response->{pref_ou_copy_counts} = $match;
+        }
+
         $response->{hold_count} = 
             $U->simplereq('open-ils.circ', $holds_method, $rec_id);
 
+        if ($options->{flesh_copies}) {
+            $response->{copies} = get_representative_copies(
+                $e, $rec_id, $org_id, $is_staff, $is_meta, $options);
+        }
+
         $client->respond($response);
     }
 
     return undef;
 }
 
+# Returns a snapshot of copy information for a given record or metarecord,
+# sorted by pref org and search org.
+sub get_representative_copies {
+    my ($e, $rec_id, $org_id, $is_staff, $is_meta, $options) = @_;
+
+    my @rec_ids;
+    my $limit = $options->{copy_limit};
+    my $copy_depth = $options->{copy_depth};
+    my $copy_offset = $options->{copy_offset};
+    my $pref_ou = $options->{pref_ou};
+
+    my $org_tree = $U->get_org_tree;
+    if (!$org_id) { $org_id = $org_tree->id; }
+    my $org = $U->find_org($org_tree, $org_id);
+
+    return [] unless $org;
+
+    my $func = 'unapi.biblio_record_entry_feed';
+    my $includes = '{holdings_xml,acp,acnp,acns}';
+    my $limits = "acn=>$limit,acp=>$limit";
+
+    if ($is_meta) {
+        $func = 'unapi.metabib_virtual_record_feed';
+        $includes = '{holdings_xml,acp,acnp,acns,mmr.unapi}';
+        $limits .= ",bre=>$limit";
+    }
+
+    my $xml_query = $e->json_query({from => [
+        $func, '{'.$rec_id.'}', 'marcxml', 
+        $includes, $org->shortname, $copy_depth, $limits,
+        undef, undef,undef, undef, undef, 
+        undef, undef, undef, $pref_ou
+    ]})->[0];
+
+    my $xml = $xml_query->{$func};
+
+    my $doc = XML::LibXML->new->parse_string($xml);
+
+    my $copies = [];
+    for my $volume ($doc->documentElement->findnodes('//*[local-name()="volume"]')) {
+        my $label = $volume->getAttribute('label');
+        my $prefix = $volume->getElementsByTagName('call_number_prefix')->[0]->getAttribute('label');
+        my $suffix = $volume->getElementsByTagName('call_number_suffix')->[0]->getAttribute('label');
+
+        my $copies_node = $volume->findnodes('./*[local-name()="copies"]')->[0];
+
+        for my $copy ($copies_node->findnodes('./*[local-name()="copy"]')) {
+
+            my $status = $copy->getElementsByTagName('status')->[0]->textContent;
+            my $location = $copy->getElementsByTagName('location')->[0]->textContent;
+            my $circ_lib_sn = $copy->getElementsByTagName('circ_lib')->[0]->getAttribute('shortname');
+
+            push(@$copies, {
+                call_number_label => $label,
+                call_number_prefix_label => $prefix,
+                call_number_suffix_label => $suffix,
+                circ_lib_sn => $circ_lib_sn,
+                copy_status => $status,
+                copy_location => $location
+            });
+        }
+    }
+
+    return $copies;
+}
+
+sub get_first_call_number {
+    my ($e, $rec_id, $org_id, $is_staff, $is_meta, $options) = @_;
+
+    my $limit = $options->{copy_limit};
+    $options->{copy_limit} = 1;
+
+    my $copies = get_representative_copies(
+        $e, $rec_id, $org_id, $is_staff, $is_meta, $options);
+
+    $options->{copy_limit} = $limit;
+
+    return $copies->[0];
+}
+
 sub get_one_rec_urls {
-    my ($self, $e, $bib_id) = @_;
+    my ($self, $e, $org_id, $bib_id) = @_;
 
     my ($resp) = $self->method_lookup(
         'open-ils.search.biblio.record.resource_urls.retrieve')
-        ->run($bib_id);
+        ->run($org_id, $bib_id);
 
     return $resp->{urls};
 }
@@ -3091,15 +3220,15 @@ sub get_one_rec_urls {
 # Start with a bib summary and augment the data with additional
 # metarecord content.
 sub get_one_metarecord_summary {
-    my ($self, $e, $rec_id) = @_;
+    my ($self, $e, $org_id, $rec_id) = @_;
 
     my $meta = $e->retrieve_metabib_metarecord($rec_id) or return {};
     my $maps = $e->search_metabib_metarecord_source_map({metarecord => $rec_id});
 
     my $bre_id = $meta->master_record; 
 
-    my $response = get_one_record_summary($e, $bre_id);
-    $response->{urls} = get_one_rec_urls($self, $e, $bre_id);
+    my $response = get_one_record_summary($self, $e, $org_id, $bre_id);
+    $response->{urls} = get_one_rec_urls($self, $e, $org_id, $bre_id);
 
     $response->{metabib_id} = $rec_id;
     $response->{metabib_records} = [map {$_->source} @$maps];
@@ -3124,7 +3253,7 @@ sub get_one_metarecord_summary {
 }
 
 sub get_one_record_summary {
-    my ($self, $e, $rec_id) = @_;
+    my ($self, $e, $org_id, $rec_id) = @_;
 
     my $bre = $e->retrieve_biblio_record_entry([$rec_id, {
         flesh => 1,
@@ -3157,7 +3286,7 @@ sub get_one_record_summary {
         record => $bre,
         display => $display,
         attributes => $attributes,
-        urls => get_one_rec_urls($self, $e, $rec_id)
+        urls => get_one_rec_urls($self, $e, $org_id, $rec_id)
     };
 }