Modify NCIP::ILS::Evergreen based on communication and testing.
authorJason Stephenson <jason@sigio.com>
Sat, 6 Dec 2014 18:14:07 +0000 (13:14 -0500)
committerJason Stephenson <jason@sigio.com>
Sat, 6 Dec 2014 18:14:07 +0000 (13:14 -0500)
Auto-Graphics is sending our target branch code in the ToAgencyId
field of the InitiationHeader.  They are not sending some of the
optional fields that we are looking for.  Most of the changes in
this commit revolve around using the ToAgencyId as a fallback
when the other fields are not available.  The focus of these
changes are the AcceptItem and RequestItem messages since the
local location is most important there.

Signed-off-by: Jason Stephenson <jason@sigio.com>
lib/NCIP/ILS/Evergreen.pm

index d150303..8f3be5b 100644 (file)
@@ -303,10 +303,7 @@ sub acceptitem {
         # We try to find the pickup location in our database. It's OK
         # if it does not exist, the user's home library will be used
         # instead.
-        my $location = $request->{$message}->{PickupLocation};
-        if ($location) {
-            $location = $self->retrieve_org_unit_by_shortname($location);
-        }
+        my $location = $self->find_location_failover($request->{$message}->{PickupLocation}, $request, $message);
 
         # Now, we place the hold on the newly created copy on behalf
         # of the patron retrieved above.
@@ -985,6 +982,16 @@ sub requestitem {
         return $response;
     }
 
+    # We have an item.  If we have a biblio.record_entry object,
+    # Auto-Graphics expects us to place the hold such that it is
+    # limited to the branch or system whose id they have given us.
+    # We, therefore, look for an org_unit based on the ToAgencyId from
+    # the InitiationHeader.
+    my $ou;
+    if (ref($item) eq 'Fieldmapper::biblio::record_entry') {
+        $ou = $self->find_location_failover(undef, $request, $message);
+    }
+
     # See if we were given a PickupLocation.
     my $location;
     if ($request->{$message}->{PickupLocation}) {
@@ -998,7 +1005,7 @@ sub requestitem {
     my $hold_expiration = $request->{$message}->{NeedBeforeDate};
 
     # Place the hold.
-    my $hold = $self->place_hold($item, $user, $location, $hold_expiration);
+    my $hold = $self->place_hold($item, $user, $location, $hold_expiration, $ou);
     if (ref($hold) eq 'NCIP::Problem') {
         $response->problem($hold);
     } else {
@@ -1978,8 +1985,9 @@ sub retrieve_copy_status {
 
     $org_unit = $ils->retrieve_org_unit_by_shortname($shortname);
 
-Retrieves an org. unit from the database by shortname. Returns the
-org. unit as a Fieldmapper object or undefined.
+Retrieves an org. unit from the database by shortname, and fleshes the
+ou_type field. Returns the org. unit as a Fieldmapper object or
+undefined.
 
 =cut
 
@@ -1993,6 +2001,17 @@ sub retrieve_org_unit_by_shortname {
         $shortname
     );
 
+    # We want to retrieve the type and manually "flesh" the object.
+    if ($aou) {
+        my $type = $U->simplereq(
+            'open-ils.pcrud',
+            'open-ils.pcrud.retrieve.aou',
+            $self->{session}->{authtoken},
+            $aou->ou_type()
+        );
+        $aou->ou_type($type) if ($type);
+    }
+
     return $aou;
 }
 
@@ -2318,7 +2337,7 @@ sub create_fuller_copy {
 
 =head2 place_hold
 
-    $hold = $ils->place_hold($item, $user, $location, $expiration);
+    $hold = $ils->place_hold($item, $user, $location, $expiration, $org_unit);
 
 This function places a hold on $item for $user for pickup at
 $location. If location is not provided or undefined, the user's home
@@ -2328,6 +2347,14 @@ The $expiration argument is optional and must be a properly formatted
 ISO date time. It will be used as the hold expire time, if
 provided. Otherwise the system default time will be used.
 
+The $org_unit parameter is only consulted in the event of $item being
+a biblio::record_entry object.  In which case, it is expected to be
+undefined or an actor::org_unit object.  If it is present, then its id
+and ou_type depth (if the ou_type field is fleshed) will be used to
+control the selection ou and selection depth for the hold.  This
+essentially limits the hold to being filled by copies belonging to the
+specified org_unit or its children.
+
 $item can be a copy (asset::copy), volume (asset::call_number), or bib
 (biblio::record_entry). The appropriate hold type will be placed
 depending on the object.
@@ -2343,6 +2370,7 @@ sub place_hold {
     my $user = shift;
     my $location = shift;
     my $expiration = shift;
+    my $org_unit = shift;
 
     # If $location is undefined, use the user's home_ou, which should
     # have been fleshed when the user was retrieved.
@@ -2382,6 +2410,10 @@ sub place_hold {
         $hold->hold_type('T');
         $params->{hold_type} = 'T';
         $params->{titleid} = $item->id();
+        if ($org_unit && ref($org_unit) eq 'Fieldmapper::actor::org_unit') {
+            $hold->selection_ou($org_unit->id());
+            $hold->selection_depth($org_unit->ou_type->depth()) if (ref($org_unit->ou_type()));
+        }
     }
 
     # Check for a duplicate hold:
@@ -2668,7 +2700,7 @@ sub find_target_via_bibliographic_id {
             $bibid = $idobj->{BibliographicRecordIdentifier};
             my $locname = $idobj->{AgencyId};
             if ($locname) {
-                $locname =~ s/.*://;
+                $locname =~ s/^.*://;
                 $loc = $self->retrieve_org_unit_by_shortname($locname);
             }
         } elsif ($idobj->{BibliographicRecordIdentifierCode}) {
@@ -2728,6 +2760,41 @@ sub find_target_via_bibliographic_id {
     return $item;
 }
 
+=head2 find_location_failover
+
+    $location = $ils->find_location_failover($location, $request, $message);
+
+Attempts to retrieve an org_unit by shortname from the passed in
+$location.  If that fails, $request and $message are used to lookup
+the ToAgencyId/AgencyId field and that is used.  Returns an org_unit
+as retrieved by retrieve_org_unit_by_shortname if successful and undef
+on failure.
+
+=cut
+
+sub find_location_failover {
+    my ($self, $location, $request, $message) = @_;
+    if ($request && !$message) {
+        $message = $self->parse_request_type($request);
+    }
+    my $org_unit;
+    if ($location) {
+        # Because Auto-Graphics. (This should be configured somehow.)
+        $location =~ s/^[^-]+-//;
+        $org_unit = $self->retrieve_org_unit_by_shortname($location);
+    }
+    if ($request && $message && !$org_unit) {
+        $location = $request->{$message}->{InitiationHeader}->{ToAgencyId}->{AgencyId};
+        if ($location) {
+            # Because Auto-Graphics. (This should be configured somehow.)
+            $location = ~ s/^[^-]+-//;
+            $org_unit = $self->retrieve_org_unit_by_shortname($location);
+        }
+    }
+
+    return $org_unit;
+}
+
 # private subroutines not meant to be used directly by subclasses.
 # Most have to do with setup and/or state checking of implementation
 # components.