towards the right way of gettin tree of grouped holdings
authorLebbeous Fogle-Weekley <lebbeous@esilibrary.com>
Thu, 1 Mar 2012 19:27:55 +0000 (14:27 -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/examples/fm_IDL.xml
Open-ILS/src/perlmods/lib/OpenILS/Application/Serial.pm
Open-ILS/src/sql/Pg/upgrade/XXXX.schema.serial-holding-groups.sql

index 4071e9f..63b6efc 100644 (file)
@@ -4059,7 +4059,7 @@ SELECT  usr,
                        <field reporter:label="Bind Call Number" name="bind_call_number" reporter:datatype="link"/>
                        <field reporter:label="Bind Unit Template" name="bind_unit_template" reporter:datatype="link"/>
                        <field reporter:label="Unit Label Prefix" name="unit_label_prefix" reporter:datatype="text"/>
-                       <field reporter:label="Unit Label Suffix" name="unit_label_suffix" reporter:datatype="text"/>
+                       <field reporter:label="Display Grouping" name="display_grouping" reporter:datatype="text"/>
                        <field reporter:label="Streams" name="streams" oils_persist:virtual="true" reporter:datatype="link"/>
                        <field reporter:label="Notes" name="notes" oils_persist:virtual="true" reporter:datatype="link"/>
                        <field reporter:label="Basic Issue Summary" name="basic_summary" oils_persist:virtual="true" reporter:datatype="link"/>
@@ -4364,6 +4364,20 @@ SELECT  usr,
                        <link field="distribution" reltype="has_a" key="id" map="" class="sdist"/>
                </links>
        </class>
+       <class id="smhc" controller="open-ils.cstore" oils_obj:fieldmapper="serial::materialized_holding_code" oils_persist:tablename="serial.materialized_holding_code" reporter:label="Materialized Holding Code" oils_persist:readonly="true">
+               <fields oils_persist:primary="id" oils_persist:sequence="serial.materialized_holding_code_id_seq">
+                       <field name="id" reporter:label="ID" reporter:datatype="id" />
+                       <field name="issuance" reporter:label="Issuance" reporter:datatype="link" />
+                       <field name="holding_type" reporter:label="Holding Type" reporter:datatype="text" />
+                       <field name="ind1" reporter:label="First Indicator" reporter:datatype="text" />
+                       <field name="ind2" reporter:label="Second Indicator" reporter:datatype="text" />
+                       <field name="subfield" reporter:label="Subfield" reporter:datatype="text" />
+                       <field name="value" reporter:label="Value" reporter:datatype="text" oils_obj:validate="^\w$" />
+               </fields>
+               <links>
+                       <link field="issuance" reltype="has_a" key="id" map="" class="siss"/>
+               </links>
+       </class>
        <class id="sbsum" controller="open-ils.cstore open-ils.pcrud" oils_obj:fieldmapper="serial::basic_summary" oils_persist:tablename="serial.basic_summary" reporter:label="Basic Issue Summary">
                <fields oils_persist:primary="id" oils_persist:sequence="serial.basic_summary_id_seq">
                        <field reporter:label="ID" name="id" reporter:datatype="id" />
index 95536db..0eefc07 100644 (file)
@@ -61,8 +61,10 @@ my %MFHD_NAMES_BY_TAG = (  '853' => $MFHD_NAMES[0],
 my %MFHD_TAGS_BY_NAME = (  $MFHD_NAMES[0] => '853',
                         $MFHD_NAMES[1] => '854',
                         $MFHD_NAMES[2] => '855');
-my @MFHD_ENUM_SUBFIELDS = qw/abcdef/;   # $g and $h intentionally omitted
-my @MFHD_CHRON_SUBFIELDS = qw/ijklm/;
+my %MFHD_SUMMARIZED_SUBFIELDS = (
+   enum => [ split //, "abcdef" ],   # $g and $h intentionally omitted for now
+   chron => [ split //, "ijklm" ]
+);
 
 my $_strp_date = new DateTime::Format::Strptime(pattern => '%F');
 
@@ -857,19 +859,118 @@ __PACKAGE__->register_method(
 
 sub grouped_holdings_for_summary {
     my (
-        $self, $client,
-        $summary_type, $summary_id, $expand_path, $limits, $offsets
+        $self, $client, $summary_type, $summary_id,
+        $expand_path, $limits, $offsets
     ) = @_;
 
-    # fetch summary and flesh sdist. From that, get display_grouping (chron or enum)
+    # Validate input or set defaults.
+    ($summary_type .= "") =~ s/[^\w]//g;
+    $summary_id = int($summary_id);
+    $expand_path ||= [];
+    $limits ||= [10];
+    $offsets ||= [0];
+
+    foreach ($expand_path, $limits, $offsets) {
+        if (ref $_ ne 'ARRAY') {
+            return new OpenILS::Event(
+                "BAD_PARAMS", note =>
+                    "expand_path, limits and offsets arguments must be arrays"
+            );
+        }
+    }
+
+    if (not (scalar(@$limits) == scalar(@$expand_path) + 1) and
+        (scalar(@$offsets) == scalar(@$expand_path) + 1)) {
+        return new OpenILS::Event(
+            "BAD_PARAMS", note =>
+                "limits and offsets must be one element longer than expand_path"
+        );
+    }
+
+    # Get the class hint for whichever type of summary we're expanding.
+    my $fmclass = "Fieldmapper::serial::${summary_type}_summary";
+    my $summary_hint = $Fieldmapper::fieldmap->{$fmclass}{hint} or
+        return new OpenILS::Event("BAD_PARAMS", note => "summary_type");
 
-    # get scap (lots of joins to get there)
+    my $e = new_editor;
+
+    # First, get display grouping for requested summary (either chron or enum).
+    my $row = $e->json_query({
+        select => {sdist => ["display_grouping"]},
+        from => {$summary_hint => {sdist => {}}},
+        where => {"+$summary_hint" => {id => $summary_id}}
+    }) or return $e->die_event;
+
+    return new OpenILS::Event("BAD_PARAMS", note => "summary_id not found")
+        unless @$row;
+
+    # And now we know which subfields we care about from
+    # serial.materialized_holding_code.
+    my @subfields = @{
+        $MFHD_SUMMARIZED_SUBFIELDS{$row->[0]->{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
+    # $expand_path later.
+    # Below we define parts of the SELECT and JOIN clauses that we'll
+    # potentially reuse if $expand_path has elements.
+
+    my $subfield = shift @subfields;
+#    my %holding_leaf_select = (
+#        siss => [qw/id label date_published/],
+
+    my %deep_joins = (
+    );
 
-    # get unique values from each field of received items' issuances' holding
-    # codes and build a tree to group them
+    # Now get the top level of holdings.
+    my $holdings = $e->json_query({
+        select => {
+            "smhc_$subfield" => ["value"],
+            scap => ["pattern_code"]
+        },
+        from => {
+            $summary_hint => {
+                sdist => {
+                    join => {
+                        sstr => {
+                            join => {
+                                sitem => {
+                                    join => {
+                                        siss => {
+                                            join => {
+                                                scap => {},
+                                                "smhc_$subfield" => {
+                                                    class => "smhc"
+                                                }
+                                            }
+                                        }
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        },
+        where => {
+            "+$summary_hint" => {id => $summary_id},
+            "+sitem" => {date_received => {"!=" => undef}},
+            "+smhc_$subfield" => {subfield => $subfield}
+        },
+        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;
 
-    # only go as far as expand_path dictates in grouping issuances.
-    # scalar(@$expand_path) + 1, up to (num_grouping_fields - 1)
+    # 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;
 }
 
 __PACKAGE__->register_method(
@@ -885,9 +986,9 @@ __PACKAGE__->register_method(
             { name => "summary_id", type => "number" },
             { name => "expand_path", type => "array" },
             { name => "limits", type => "array", desc =>
-                "This should be one element longer than expand_path" },
+                "This must be exactly one element longer than expand_path" },
             { name => "offsets", type => "array", desc =>
-                "This should be one element longer than expand_path" }
+                "This must be exactly one element longer than expand_path" }
         ]
     }
 );
index b1eccd7..76d6ea6 100644 (file)
@@ -110,6 +110,11 @@ return;
 
 $func$ LANGUAGE 'plperlu';
 
+CREATE INDEX assist_holdings_display
+    ON serial.materialized_holding_code (issuance, subfield);
+
+-- XXX add more indices to assist with other joins new to Serial.pm
+
 CREATE TRIGGER materialize_holding_code
     AFTER INSERT OR UPDATE ON serial.issuance
     FOR EACH ROW EXECUTE PROCEDURE serial.materialize_holding_code() ;
@@ -117,4 +122,4 @@ CREATE TRIGGER materialize_holding_code
 -- XXX need to materialize_holding_code() for all existing rows in serial.issuance
 -- at time of upgrde script execution as well.
 
-COMMIT';
+COMMIT;