progress
authorLebbeous Fogle-Weekley <lebbeous@esilibrary.com>
Thu, 1 Mar 2012 23:06:15 +0000 (18:06 -0500)
committerLebbeous Fogle-Weekley <lebbeous@esilibrary.com>
Wed, 7 Mar 2012 21:57:10 +0000 (16:57 -0500)
Signed-off-by: Lebbeous Fogle-Weekley <lebbeous@esilibrary.com>
Open-ILS/src/extras/ils_events.xml
Open-ILS/src/perlmods/lib/OpenILS/Application/Serial.pm

index 59ff421..a1c9ac3 100644 (file)
         <desc xml:lang="en-US">Checkin attempted on item during minimum transit checkin interval.</desc>
     </event>
 
+    <event code='11104' textcode='SERIAL_CORRUPT_PATTERN_CODE'>
+        <desc xml:lang="en-US">A serial pattern code has been configured
+        that fails to conform to MFHD standards for fields 853-855.</desc>
+    </event>
+
        <!-- ================================================================ -->
 
 </ils_events>
index 0eefc07..ece120b 100644 (file)
@@ -857,6 +857,28 @@ __PACKAGE__->register_method(
     }
 );
 
+# This is a helper for grouped_holdings_for_summary() later.
+sub _label_holding_level {
+    my ($pattern_code, $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 @present = grep { $field->subfield($_) } @subfields;
+
+    return pop @present;
+}
+
 sub grouped_holdings_for_summary {
     my (
         $self, $client, $summary_type, $summary_id,
@@ -906,9 +928,8 @@ sub grouped_holdings_for_summary {
 
     # And now we know which subfields we care about from
     # serial.materialized_holding_code.
-    my @subfields = @{
-        $MFHD_SUMMARIZED_SUBFIELDS{$row->[0]->{display_grouping}}
-    };
+    my $display_grouping = $row->[0]->{display_grouping};
+    my @subfields = @{ $MFHD_SUMMARIZED_SUBFIELDS{$display_grouping} };
 
     # We look for holdings grouped at the top level once no matter what,
     # then we'll look deeper with additional queries for every element of
@@ -917,14 +938,11 @@ sub grouped_holdings_for_summary {
     # potentially reuse if $expand_path has elements.
 
     my $subfield = shift @subfields;
-#    my %holding_leaf_select = (
-#        siss => [qw/id label date_published/],
-
-    my %deep_joins = (
-    );
+    my %subfield_joins = ("smhc_$subfield" => {class => "smhc"});
+    my %subfield_where_clauses = ("+smhc_$subfield" => {subfield => $subfield});
 
     # Now get the top level of holdings.
-    my $holdings = $e->json_query({
+    my $top = $e->json_query({
         select => {
             "smhc_$subfield" => ["value"],
             scap => ["pattern_code"]
@@ -939,10 +957,7 @@ sub grouped_holdings_for_summary {
                                     join => {
                                         siss => {
                                             join => {
-                                                scap => {},
-                                                "smhc_$subfield" => {
-                                                    class => "smhc"
-                                                }
+                                                scap => {}, %subfield_joins
                                             }
                                         }
                                     }
@@ -956,7 +971,7 @@ sub grouped_holdings_for_summary {
         where => {
             "+$summary_hint" => {id => $summary_id},
             "+sitem" => {date_received => {"!=" => undef}},
-            "+smhc_$subfield" => {subfield => $subfield}
+            %subfield_where_clauses
         },
         distinct => 1,  # sic, this goes here in json_query
         limit => int(shift(@$limits)),
@@ -967,10 +982,119 @@ sub grouped_holdings_for_summary {
         ]
     }) 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
+    ];
+
     # 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.
-    return $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"
+    );
+
+    my $parent = $tree;
+
+    foreach my $value (@$expand_path) {
+        my $prev_subfield = $subfield;
+        $subfield = shift @subfields;
+
+        # This wad of JOINs is additive over each iteration.
+        $subfield_joins{"smhc_$subfield"} = {class => "smhc"};
+
+        # The WHERE clauses also change and grow each time.
+        $subfield_where_clauses{"+smhc_$prev_subfield"}->{value} = $value;
+        $subfield_where_clauses{"+smhc_$subfield"}->{subfield} = $subfield;
+
+        my $level = $e->json_query({
+            select => {
+                "smhc_$subfield" => ["value"], (
+                    $subfield eq $deepest_level ?
+                        (siss => [qw/id label date_published/]) : ()
+                )
+            },
+            from => {
+                $summary_hint => {
+                    sdist => {
+                        join => {
+                            sstr => {
+                                join => {
+                                    sitem => {
+                                        join => {
+                                            siss => {
+                                                join => {%subfield_joins}
+                                            }
+                                        }
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+            },
+            where => {
+                "+$summary_hint" => {id => $summary_id},
+                "+sitem" => {date_received => {"!=" => undef}},
+                %subfield_where_clauses
+            },
+            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"}
+            ]
+        }) or return $e->die_event;
+
+        return $tree unless @$level;
+
+        # Find attachment point for our results.
+        my ($point) = grep { $_->{value} eq $value } @$parent;
+
+        # 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
+        ];
+
+        last if $subfield eq $deepest_level;
+    }
+
+    return $tree;
 }
 
 __PACKAGE__->register_method(