Check for eligible copies in NCIP::ILS::Evergreen->requestitem.
authorJason Stephenson <jstephenson@mvlc.org>
Tue, 24 Nov 2015 16:54:48 +0000 (11:54 -0500)
committerJason Stephenson <jstephenson@mvlc.org>
Fri, 4 Dec 2015 14:49:05 +0000 (09:49 -0500)
Add a method to count the number of copies available at the selection
ou to fill the hold.  Call this method from requestitem, and if it
returns 0, send a problem response that the requested item will not
be available by need by date.

Signed-off-by: Jason Stephenson <jstephenson@mvlc.org>
lib/NCIP/ILS/Evergreen.pm

index cd28ead..f8bba19 100644 (file)
@@ -1009,6 +1009,21 @@ sub requestitem {
     # Look for a NeedBeforeDate to set the expiration.
     my $expiration = $request->{$message}->{NeedBeforeDate};
 
+    # Check for eligible copies:
+    if ($self->count_eligible_copies($bre, $user, $pickup_ou, $selection_ou) == 0) {
+        $response->problem(
+            NCIP::Problem->new(
+                {
+                    ProblemType => 'Item Not Available By Need Before Date',
+                    ProblemDetail => 'Item requested will not be available by the date/time the User needs the Item',
+                    ProblemElement => 'BibliographicRecordIdentifier',
+                    ProblemValue => $bre->id()
+                }
+            )
+        );
+        return $response;
+    }
+
     # Place the hold:
     my $hold = $self->place_hold($bre, $user, $pickup_ou, $expiration, $selection_ou);
     if (ref($hold) eq 'NCIP::Problem') {
@@ -2374,6 +2389,114 @@ sub place_hold {
     return $hold;
 }
 
+=head2 count_eligible_copies
+
+    $result = $ils->count_eligible_copies($target, $patron, $pickup_lib, $selection_lib);
+
+This method counts the copies eligible to fill the remote hold on the
+target bre for the patron at pickup lib where the copies are owned at
+or below the selection lib.  It returns the count of copies eligible
+to fill the hold at the time of the call, so zero if none are
+available or a positive integer otherwise.
+
+=cut
+
+sub count_eligible_copies {
+    my $self = shift;
+    my $target = shift;
+    my $user = shift;
+    my $pickup_lib = shift;
+    my $selection_lib = shift;
+
+    $pickup_lib = $user->home_ou() unless ($pickup_lib);
+
+    # To be used in the pcrud query:
+    my $selection_ou = (ref($selection_lib)) ? $selection_lib->id() : 1;
+
+    # Base params for hold is possible check:
+    my $params = {
+        hold_type => 'C',
+        patronid => $user->id(),
+        pickup_lib => $pickup_lib->id()
+    };
+
+    # return value: count of eligible copies found.
+    my $eligible_copies = 0;
+
+    # pcrud query to find eligible copies:
+    my $query = {deleted => 'f', circulate => 't', holdable => 't', status => [0,7]};
+    # Limit copies by call numbers for the target bre:
+    $query->{call_number} = {
+        'in' => {
+            select => {acn => ['id']},
+            from => 'acn',
+            where => {
+                record => $target->id(),
+                deleted => 'f',
+                owning_lib => {
+                    'in' => {
+                        select => {
+                            aou => [{
+                                transform => 'actor.org_unit_descendants',
+                                column => 'id',
+                                result_field => 'id'
+                            }]
+                        },
+                        from => 'aou',
+                        where => {id => $selection_ou}
+                    }
+                }
+            }
+        }
+    };
+    # Limit copies by circ_lib:
+    $query->{circ_lib} = {
+        'in' => {
+            select => {
+                aou => [{
+                    column => 'id',
+                    transform => 'actor.org_unit_descendants',
+                    result_field => 'id'
+                }]
+            },
+            from => 'aou',
+            where => {id => $selection_ou}
+        }
+    };
+    # Limit copies by copy locations that allow circ and holds:
+    $query->{location} = {
+        'in' => {
+            select => { acpl => ['id'] },
+            from => 'acpl',
+            where => {holdable => 't', circulate => 't'}
+        }
+    };
+    # Search for the copies and check each one to see if it could fill the hold.
+    my $search = OpenSRF::AppSession->create('open-ils.pcrud')->request(
+        'open-ils.pcrud.search.acp',
+        $self->{session}->{authtoken},
+        $query
+    );
+    while (my $response = $search->recv()) {
+        if ($response->status() eq 'OK') {
+            my $copy = $response->content();
+            $params->{copy_id} = $copy->id();
+            my $result = $U->simplereq(
+                'open-ils.circ',
+                'open-ils.circ.title_hold.is_possible',
+                $self->{session}->{authtoken},
+                $params
+            );
+            if ($result->{success}) {
+                $eligible_copies++;
+            }
+        }
+    }
+    $search->finish();
+
+    return $eligible_copies;
+}
+
 =head2 cancel_hold
 
     $result = $ils->cancel_hold($hold);