Backport of 850052e7e6b4cb0c64 from master user/senator/850052e-for-rel_1_6_1
authorLebbeous Fogle-Weekley <lebbeous@esilibrary.com>
Tue, 29 Nov 2011 19:26:00 +0000 (14:26 -0500)
committerLebbeous Fogle-Weekley <lebbeous@esilibrary.com>
Tue, 29 Nov 2011 21:54:51 +0000 (16:54 -0500)
This *may* fix a problem in 1.6.1.x where calling
open-ils.storage.actor.org_unit.closed_date.overlap with an OU argument
that has no hours of operation defined sends the storage service into an
infinite loop.  Not wholly tested.

Signed-off-by: Lebbeous Fogle-Weekley <lebbeous@esilibrary.com>
Open-ILS/src/perlmods/OpenILS/Application/Storage/Publisher/actor.pm

index 343eae6..6a2eea3 100644 (file)
@@ -208,7 +208,7 @@ __PACKAGE__->register_method(
 );
 
 
-sub org_closed_overlap {
+sub new_org_closed_overlap {
        my $self = shift;
        my $client = shift;
        my $ou = shift;
@@ -241,7 +241,7 @@ sub org_closed_overlap {
                        $before = $_dt_parser->parse_datetime( $begin );
                        $before->subtract( minutes => 1 );
 
-                       while ( my $_b = org_closed_overlap($self, $client, $ou, $before->iso8601, -1, 1 ) ) {
+                       while ( my $_b = new_org_closed_overlap($self, $client, $ou, $before->iso8601, -1, 1 ) ) {
                                $before = $_dt_parser->parse_datetime( clense_ISO8601($_b->{start}) );
                        }
                        $begin = clense_ISO8601($before->iso8601);
@@ -251,7 +251,7 @@ sub org_closed_overlap {
                        $after = $_dt_parser->parse_datetime( $end );
                        $after->add( minutes => 1 );
 
-                       while ( my $_a = org_closed_overlap($self, $client, $ou, $after->iso8601, 1, 1 ) ) {
+                       while ( my $_a = new_org_closed_overlap($self, $client, $ou, $after->iso8601, 1, 1 ) ) {
                                $after = $_dt_parser->parse_datetime( clense_ISO8601($_a->{end}) );
                        }
                        $end = clense_ISO8601($after->iso8601);
@@ -280,7 +280,7 @@ sub org_closed_overlap {
                                if (my $closure = actor::org_unit::closed_date->db_Main->selectrow_hashref( $sql, {}, $begin, $ou )) {
                                        $before = $_dt_parser->parse_datetime( $begin );
                                        $before->subtract( minutes => 1 );
-                                       while ( my $_b = org_closed_overlap($self, $client, $ou, $before->iso8601, -1 ) ) {
+                                       while ( my $_b = new_org_closed_overlap($self, $client, $ou, $before->iso8601, -1 ) ) {
                                                $before = $_dt_parser->parse_datetime( clense_ISO8601($_b->{start}) );
                                        }
                                }
@@ -306,7 +306,7 @@ sub org_closed_overlap {
                                        $after = $_dt_parser->parse_datetime( $end );
                                        $after->add( minutes => 1 );
 
-                                       while ( my $_a = org_closed_overlap($self, $client, $ou, $after->iso8601, 1 ) ) {
+                                       while ( my $_a = new_org_closed_overlap($self, $client, $ou, $after->iso8601, 1 ) ) {
                                                $after = $_dt_parser->parse_datetime( clense_ISO8601($_a->{end}) );
                                        }
                                        $end = clense_ISO8601($after->iso8601);
@@ -324,6 +324,126 @@ sub org_closed_overlap {
 }
 __PACKAGE__->register_method(
        api_name        => 'open-ils.storage.actor.org_unit.closed_date.overlap',
+       api_level       => 0,
+       method          => 'new_org_closed_overlap',
+);
+
+sub org_closed_overlap {
+    my $self = shift;
+    my $client = shift;
+    my $ou = shift;
+    my $date = shift;
+    my $direction = shift || 0;
+    my $no_hoo = shift || 0;
+
+    return undef unless ($date && $ou);
+
+    my $t = actor::org_unit::closed_date->table;
+    my $sql = <<"    SQL";
+        SELECT  *
+          FROM  $t
+          WHERE ? between close_start and close_end
+            AND org_unit = ?
+          ORDER BY close_start ASC, close_end DESC
+          LIMIT 1
+    SQL
+
+    $date = clense_ISO8601($date);
+    my ($begin, $end) = ($date,$date);
+
+    my $hoo = actor::org_unit::hours_of_operation->retrieve($ou);
+
+    if (my $closure = actor::org_unit::closed_date->db_Main->selectrow_hashref( $sql, {}, $date, $ou )) {
+        $begin = clense_ISO8601($closure->{close_start});
+        $end = clense_ISO8601($closure->{close_end});
+
+        if ( $direction <= 0 ) {
+            $before = $_dt_parser->parse_datetime( $begin );
+            $before->subtract( minutes => 1 );
+
+            while ( my $_b = org_closed_overlap($self, $client, $ou, $before->strftime('%FT%T%z'), -1, 1 ) ) {
+                $before = $_dt_parser->parse_datetime( clense_ISO8601($_b->{start}) );
+            }
+            $begin = clense_ISO8601($before->strftime('%FT%T%z'));
+        }
+
+        if ( $direction >= 0 ) {
+            $after = $_dt_parser->parse_datetime( $end );
+            $after->add( minutes => 1 );
+
+            while ( my $_a = org_closed_overlap($self, $client, $ou, $after->strftime('%FT%T%z'), 1, 1 ) ) {
+                $after = $_dt_parser->parse_datetime( clense_ISO8601($_a->{end}) );
+            }
+            $end = clense_ISO8601($after->strftime('%FT%T%z'));
+        }
+    }
+
+    if ( !$no_hoo ) {
+        if ( $hoo ) {
+
+            if ( $direction <= 0 ) {
+                my $begin_dow = $_dt_parser->parse_datetime( $begin )->day_of_week_0;
+                my $begin_open_meth = "dow_".$begin_dow."_open";
+                my $begin_close_meth = "dow_".$begin_dow."_close";
+
+                my $count = 1;
+                while ($hoo->$begin_open_meth eq '00:00:00' and $hoo->$begin_close_meth eq '00:00:00') {
+                    $begin = clense_ISO8601($_dt_parser->parse_datetime( $begin )->subtract( days => 1)->strftime('%FT%T%z'));
+                    $begin_dow++;
+                    $begin_dow %= 7;
+                    $count++;
+                    last if ($count > 6);
+                    $begin_open_meth = "dow_".$begin_dow."_open";
+                    $begin_close_meth = "dow_".$begin_dow."_close";
+                }
+
+                if (my $closure = actor::org_unit::closed_date->db_Main->selectrow_hashref( $sql, {}, $begin, $ou )) {
+                    $before = $_dt_parser->parse_datetime( $begin );
+                    $before->subtract( minutes => 1 );
+                    while ( my $_b = org_closed_overlap($self, $client, $ou, $before->strftime('%FT%T%z'), -1 ) ) {
+                        $before = $_dt_parser->parse_datetime( clense_ISO8601($_b->{start}) );
+                    }
+                }
+            }
+    
+            if ( $direction >= 0 ) {
+                my $end_dow = $_dt_parser->parse_datetime( $end )->day_of_week_0;
+                my $end_open_meth = "dow_".$end_dow."_open";
+                my $end_close_meth = "dow_".$end_dow."_close";
+    
+                $count = 1;
+                while ($hoo->$end_open_meth eq '00:00:00' and $hoo->$end_close_meth eq '00:00:00') {
+                    $end = clense_ISO8601($_dt_parser->parse_datetime( $end )->add( days => 1)->strftime('%FT%T%z'));
+                    $end_dow++;
+                    $end_dow %= 7;
+                    $count++;
+                    last if ($count > 6);
+                    $end_open_meth = "dow_".$end_dow."_open";
+                    $end_close_meth = "dow_".$end_dow."_close";
+                }
+
+                if (my $closure = actor::org_unit::closed_date->db_Main->selectrow_hashref( $sql, {}, $end, $ou )) {
+                    $after = $_dt_parser->parse_datetime( $end );
+                    $after->add( minutes => 1 );
+
+                    while ( my $_a = org_closed_overlap($self, $client, $ou, $after->strftime('%FT%T%z'), 1 ) ) {
+                        $after = $_dt_parser->parse_datetime( clense_ISO8601($_a->{end}) );
+                    }
+                    $end = clense_ISO8601($after->strftime('%FT%T%z'));
+                }
+            }
+
+        }
+    }
+
+    if ($begin eq $date && $end eq $date) {
+        return undef;
+    }
+
+    return { start => $begin, end => $end };
+}
+__PACKAGE__->register_method(
+       api_name        => 'open-ils.storage.actor.org_unit.closed_date.overlap',
        api_level       => 1,
        method          => 'org_closed_overlap',
 );