Cancel requests via RequestId in NCIP::ILS::Evergreen.
authorJason Stephenson <jstephenson@mvlc.org>
Tue, 27 Oct 2015 17:13:42 +0000 (13:13 -0400)
committerJason Stephenson <jstephenson@mvlc.org>
Tue, 27 Oct 2015 18:30:56 +0000 (14:30 -0400)
Add a routine to search for holds via the RequestIdentifierValue of
the CancelRequestItem message's RequestId.  This searches action::
hold_request_note by title and body for  uncancelled, unfilled holds
where request_lib is equal to our working org. unit.  If found, the
corresponding hold is returned to be canceled.

The original logic of searching by ItemId remains as a fallback
when the above fails and for those cases where holds were placed
before this logic was added.

Signed-off-by: Jason Stephenson <jstephenson@mvlc.org>

lib/NCIP/ILS/Evergreen.pm

index 1ee1b58..db97d70 100644 (file)
@@ -1084,60 +1084,40 @@ sub cancelrequestitem {
         return $response;
     }
 
-    # Auto-Graphics has agreed to return the ItemId that we sent them
-    # in the RequestItemResponse when they attempt CancelRequestItem
-    # for that same request.  For the sake of time, we're only going
-    # to support that method of looking up the hold request in
-    # Evergreen.  We leave it as future enhancement to make this
-    # "portable" to other vendors.  (Frankly, that's a fool's errand.
-    # NCIP is one of those "standards" where you neeed a separate
-    # implementation for every vendor.)
-    my $item_id = $request->{$message}->{ItemId};
-    unless ($item_id) {
-        # We'll throw a problem that we're missing needed information.
-        my $problem = NCIP::Problem->new();
-        $problem->ProblemType('Needed Data Missing');
-        $problem->ProblemDetail('Cannot find ItemId in message.');
-        $problem->ProblemElement('ItemId');
-        $problem->ProblemValue('NULL');
-        $response->problem($problem);
-        return $response;
-    }
-    my $idvalue = $item_id->{ItemIdentifierValue};
-    my $itemagy = $item_id->{AgencyId};
-    my $selection_ou = $self->find_location_failover($itemagy, $request, $message);
-    unless ($selection_ou) {
-        my $problem = NCIP::Problem->new(
-            {
-                ProblemType => 'Unknown Agency',
-                ProblemDetail => 'Agency is not known',
-                ProblemElement => 'AgencyId',
-                ProblemValue => $item_id->{AgencyId} || $request->{$message}->{InitiationHeader}->{ToAgencyId}->{AgencyId}
+    # First, let's see if we can find the hold via the RequestId's
+    # RequestIdentifierValue.  If not, we fall back on the ItemId.
+    my $hold = $self->find_hold_via_note('NCIP Remote Request ID', $request->{$message}->{RequestId}->{RequestIdentifierValue});
+
+    unless ($hold) {
+        my $item_id = $request->{$message}->{ItemId};
+        if ($item_id) {
+            my $idvalue = $item_id->{ItemIdentifierValue};
+            my $itemagy = $item_id->{AgencyId};
+            my $selection_ou = $self->find_location_failover($itemagy, $request, $message);
+            unless ($selection_ou) {
+                my $problem = NCIP::Problem->new(
+                    {
+                        ProblemType => 'Unknown Agency',
+                        ProblemDetail => 'Agency is not known',
+                        ProblemElement => 'AgencyId',
+                        ProblemValue => $item_id->{AgencyId} || $request->{$message}->{InitiationHeader}->{ToAgencyId}->{AgencyId}
+                    }
+                );
+                $response->problem($problem);
+                return $response;
             }
-        );
-        $response->problem($problem);
-        return $response;
-    }
 
-    # We should support looking up holds by barcode, since we still
-    # support placing them by barcode, but that is not how it is going
-    # to work with Auto-Graphics, apparently.  I'll leave the
-    # reimplementation of that for a future enhancement.
+            # We should support looking up holds by barcode, since we still
+            # support placing them by barcode, but that is not how it is going
+            # to work with Auto-Graphics, apparently.  I'll leave the
+            # reimplementation of that for a future enhancement.
 
-    # See if we can find the hold:
-    my $hold = $self->_hold_search($user, $idvalue, $selection_ou);
-    if ($hold && $hold->transit()) {
-        $response->problem(
-            NCIP::Problem->new(
-                {
-                    ProblemType => 'Request Already Processed',
-                    ProblemDetail => 'Request has already been processed',
-                    ProblemElement => 'RequestIdentifierValue',
-                    ProblemValue => $request->{message}->{RequestId}->{RequestIdentifierValue}
-                }
-            )
-       );
-    } elsif ($hold) {
+            # See if we can find the hold:
+            my $hold = $self->_hold_search($user, $idvalue, $selection_ou);
+        }
+    }
+
+    if ($hold) {
         my $result = $self->cancel_hold($hold);
         if (ref($result)) {
             $response->problem(_problem_from_event("Temporary Processing Failure", $result));
@@ -2411,6 +2391,50 @@ sub create_hold_note {
     return undef;
 }
 
+=head2 find_hold_via_note
+
+    $hold = $ils->find_hold_via_note($title, $body);
+
+Searches for a hold based on a note title and note body.  Returns the
+note if found, undef otherwise.  The search is limited to unfulfilled,
+uncanceled hold where the request_lib equals the NCIPServer working
+org. unit.
+
+=cut
+
+sub find_hold_via_note {
+    my $self = shift;
+    my $title = shift;
+    my $body = shift;
+
+    # Build the search clause up here, because it is a bit complex.
+    my $search = {
+        title => $title,
+        body => $body,
+        hold => {
+            in => {
+                select => { ahr => ['id']},
+                from => 'ahr',
+                where => {cancel_time => undef, fulfillment_time => undef,
+                          request_lib => $self->{session}->{work_ou}->id()}
+            }
+        }
+    };
+
+    my $note = $U->simplereq(
+        'open-ils.pcrud',
+        'open-ils.pcrud.search.ahrn',
+        $self->{session}->{authtoken},
+        $search,
+        {flesh => 1, flesh_fields => {ahrn => ['hold']}}
+    );
+    if (ref($note) eq 'Fieldmapper::action::hold_request_note') {
+        return $note->hold();
+    }
+
+    return undef;
+}
+
 =head2 delete_copy
 
     $ils->delete_copy($copy);