From: Lebbeous Fogle-Weekley Date: Fri, 2 Mar 2012 19:02:04 +0000 (-0500) Subject: much better: sorting desc except at actual holding level, other improvements X-Git-Url: https://old-git.evergreen-ils.org/?a=commitdiff_plain;h=6ed9b7471a3d87f9f1f3a30058ff8100e5834f49;p=evergreen%2Fequinox.git much better: sorting desc except at actual holding level, other improvements all that i'm sure is left to do at the middle layer level is to support translating "06" to "Jun." and the like Signed-off-by: Lebbeous Fogle-Weekley --- diff --git a/Open-ILS/src/perlmods/lib/OpenILS/Application/Serial.pm b/Open-ILS/src/perlmods/lib/OpenILS/Application/Serial.pm index ece120b151..552611aea8 100644 --- a/Open-ILS/src/perlmods/lib/OpenILS/Application/Serial.pm +++ b/Open-ILS/src/perlmods/lib/OpenILS/Application/Serial.pm @@ -837,11 +837,13 @@ __PACKAGE__->register_method( method => "scoped_holding_summary_tree_for_bib", api_name => "open-ils.serial.holding_summary_tree.by_bib", api_level => 1, - argc => 1, + argc => 6, signature => { desc => q/Return a set of holding summaries organized into a tree of nodes that look like: {org_unit:, holding_summaries:[], children:[]} + + All arguments except the first (bibid) are optional. /, params => [ { name => "bibid", @@ -859,26 +861,39 @@ __PACKAGE__->register_method( # This is a helper for grouped_holdings_for_summary() later. sub _label_holding_level { - my ($pattern_code, $subfield, $value) = @_; + my ($pattern_field, $subfield, $value) = @_; return $value; # XXX TODO } # This is a helper for grouped_holdings_for_summary() later. sub _get_deepest_holding_level { - my ($display_grouping, $pattern_code) = @_; - - my $field = new MARC::Field( - "999", @{ OpenSRF::Utils::JSON->JSON2perl($pattern_code) } - ); - - my @subfields = @{ $MFHD_SUMMARIZED_SUBFIELDS{$display_grouping} }; + my ($display_grouping, $pattern_field) = @_; - my @present = grep { $field->subfield($_) } @subfields; + my @present = grep { $pattern_field->subfield($_) } @{ + $MFHD_SUMMARIZED_SUBFIELDS{$display_grouping} + }; return pop @present; } +# This is a helper for grouped_holdings_for_summary() later. +sub _make_grouped_holding_node { + my ($row, $subfield, $deepest_level, $pattern_field) = @_; + + return { + $subfield eq $deepest_level ? ( + label => $row->{label}, + holding => $row->{id} + ) : ( + value => $row->{value}, + label => _label_holding_level( + $pattern_field, $subfield, $row->{value} + ) + ) + }; +} + sub grouped_holdings_for_summary { my ( $self, $client, $summary_type, $summary_id, @@ -896,16 +911,18 @@ sub grouped_holdings_for_summary { if (ref $_ ne 'ARRAY') { return new OpenILS::Event( "BAD_PARAMS", note => - "expand_path, limits and offsets arguments must be arrays" + "'expand_path', 'limits' and 'offsets' arguments must " . + "be arrays" ); } } - if (not (scalar(@$limits) == scalar(@$expand_path) + 1) and - (scalar(@$offsets) == scalar(@$expand_path) + 1)) { + if (scalar(@$limits) != scalar(@$expand_path) + 1 or + scalar(@$offsets) != scalar(@$expand_path) + 1) { return new OpenILS::Event( "BAD_PARAMS", note => - "limits and offsets must be one element longer than expand_path" + "'limits' and 'offsets' arrays each must be one element " . + "longer than 'expand_path'" ); } @@ -916,19 +933,74 @@ sub grouped_holdings_for_summary { my $e = new_editor; - # First, get display grouping for requested summary (either chron or enum). + # First, get display grouping for requested summary (either chron or enum) + # and the pattern code. Even though we have to JOIN through sitem to get + # pattern_code from scap, we don't actually care about specific items yet. my $row = $e->json_query({ - select => {sdist => ["display_grouping"]}, - from => {$summary_hint => {sdist => {}}}, - where => {"+$summary_hint" => {id => $summary_id}} + select => {sdist => ["display_grouping"], scap => ["pattern_code"]}, + from => { + $summary_hint => { + sdist => { + join => { + sstr => { + join => { + sitem => { + join => { + siss => { + join => {scap => {}} + } + } + } + } + } + } + } + } + }, + where => { + "+$summary_hint" => {id => $summary_id}, + "+sitem" => {date_received => {"!=" => undef}} + }, + limit => 1 }) or return $e->die_event; - return new OpenILS::Event("BAD_PARAMS", note => "summary_id not found") - unless @$row; + # Summaries without attached holdings constitute bad data, not benign + # empty result sets. + return new OpenILS::Event( + "BAD_PARAMS", + note => "Summary #$summary_id not found, or no holdings attached" + ) unless @$row; - # And now we know which subfields we care about from + # Unless data has been disarranged, all holdings grouped together under + # the same summary should have the same pattern code, so we can take any + # result from the set we just got. + my $pattern_field; + eval { + $pattern_field = new MARC::Field( + "999", # irrelevant for our purposes + @{ OpenSRF::Utils::JSON->JSON2perl($row->[0]->{pattern_code}) } + ); + }; + if ($@) { + return new OpenILS::Event("SERIAL_CORRUPT_PATTERN_CODE", note => $@); + } + + # And now we know which subfields we will care about from # serial.materialized_holding_code. my $display_grouping = $row->[0]->{display_grouping}; + + # This will tell us when to stop grouping and start showing actual + # holdings. + my $deepest_level = + _get_deepest_holding_level($display_grouping, $pattern_field); + if (not defined $deepest_level) { + # corrupt pattern code + my $msg = "couldn't determine deepest holding level for " . + "$summary_type summary #$summary_id"; + $logger->warn($msg); + return new OpenILS::Event("SERIAL_CORRUPT_PATTERN_CODE", note => $msg); + } + my @subfields = @{ $MFHD_SUMMARIZED_SUBFIELDS{$display_grouping} }; # We look for holdings grouped at the top level once no matter what, @@ -944,8 +1016,10 @@ sub grouped_holdings_for_summary { # Now get the top level of holdings. my $top = $e->json_query({ select => { - "smhc_$subfield" => ["value"], - scap => ["pattern_code"] + "smhc_$subfield" => ["value"], ( + $subfield eq $deepest_level ? + (siss => [qw/id label date_published/]) : () + ) }, from => { $summary_hint => { @@ -956,9 +1030,7 @@ sub grouped_holdings_for_summary { sitem => { join => { siss => { - join => { - scap => {}, %subfield_joins - } + join => {%subfield_joins} } } } @@ -976,50 +1048,24 @@ sub grouped_holdings_for_summary { distinct => 1, # sic, this goes here in json_query limit => int(shift(@$limits)), offset => int(shift(@$offsets)), - order_by => [ - {class => "smhc_$subfield", field => "value", - direction => "descending"} - ] + order_by => { + "smhc_$subfield" => { + "value" => { + direction => ($subfield eq $deepest_level ? "asc" : "desc") + } + } + } }) or return $e->die_event; - # Unless data has been disarranged, all holdings grouped together under - # the same summary should have the same pattern code, so we can take any - # result from the set we just got. - - my $pattern_code = $top->[0]->{pattern_code}; - # Make the tree we have so far. - my $tree = [ - map { - +{ - value => $_->{value}, - label => - _label_holding_level($pattern_code, $subfield, $_->{value}) - }; - } @$top - ]; + my $tree = [ map( + _make_grouped_holding_node($_,$subfield,$deepest_level,$pattern_field), + @$top + ) ]; # Ok, that got us the top level, with nothing expanded. Now we loop through - # the deeper levels of @$expand_path, issuing similar queries to get us - # lower groupings and even actual specific holdings. - - # This will tell us when to stop grouping and start showing actual - # holdings. - my $deepest_level = - _get_deepest_holding_level($display_grouping, $pattern_code); - if (not defined $deepest_level) { - # corrupt pattern code - my $msg = "couldn't determine deepest holding level for " . - "$summary_type summary #$summary_id"; - $logger->warn($msg); - return new OpenILS::Event("SERIAL_CORRUPT_PATTERN_CODE", note => $msg); - } - - $logger->debug( - "deepest holding level for $summary_type summary " . - "#$summary_id is $deepest_level" - ); - + # the elements of @$expand_path, issuing similar queries to get us deeper + # groupings and even actual specific holdings. my $parent = $tree; foreach my $value (@$expand_path) { @@ -1067,10 +1113,13 @@ sub grouped_holdings_for_summary { distinct => 1, # sic, this goes here in json_query limit => int(shift(@$limits)), offset => int(shift(@$offsets)), - order_by => [ - {class => "smhc_$subfield", field => "value", - direction => "descending"} - ] + order_by => { + "smhc_$subfield" => { + "value" => { + direction => ($subfield eq $deepest_level?"asc":"desc") + } + } + } }) or return $e->die_event; return $tree unless @$level; @@ -1078,17 +1127,14 @@ sub grouped_holdings_for_summary { # Find attachment point for our results. my ($point) = grep { $_->{value} eq $value } @$parent; - # Set parent for the next iteration + # Set parent for the next iteration. $parent = $point->{children} = [ - map { - +{ - # XXX if on deepest level, show actual holdings - value => $_->{value}, - label => _label_holding_level( - $pattern_code, $subfield, $_->{value} - ) - }; - } @$level + map( + _make_grouped_holding_node( + $_, $subfield, $deepest_level, $pattern_field + ), + @$level + ) ]; last if $subfield eq $deepest_level; @@ -1101,7 +1147,7 @@ __PACKAGE__->register_method( method => "grouped_holdings_for_summary", api_name => "open-ils.serial.holdings.grouped_by_summary", api_level => 1, - argc => 1, + argc => 5, signature => { desc => q/Return a tree of holdings associated with a given summary grouped by all but the last of either chron or enum units./,