More back end work for marking items.
authorJason Stephenson <jason@sigio.com>
Sun, 15 Jul 2018 21:11:46 +0000 (17:11 -0400)
committerJason Stephenson <jason@sigio.com>
Fri, 26 Oct 2018 23:04:55 +0000 (19:04 -0400)
This work unifies the back end behavior more for the different
statuses.

The tests will have to be reworked.

Open-ILS/src/extras/ils_events.xml
Open-ILS/src/perlmods/lib/OpenILS/Application/Circ.pm

index 9f92944..362fff5 100644 (file)
     <event code='11010' textcode='SERIAL_CAPTION_AND_PATTERN_NOT_EMPTY'>
         <desc xml:lang="en-US">The prediction pattern still has dependent objects</desc>
     </event>
+
+       <!-- ================================================================ -->
+
+    <event code='12000' textcode='ITEM_TO_MARK_CHECKED_OUT'>
+      <desc xml:lang="en-US">The item to be marked is checked out to a patron.</desc>
+    </event>
+    <event code='12001' textcode='ITEM_TO_MARK_IN_TRANSIT'>
+      <desc xml:lang="en-US">The item to be marked is in transit.</desc>
+    </event>
+    <event code='12002' textcode='ITEM_TO_MARK_LAST_HOLD_COPY'>
+      <desc xml:lang="en-US">The item to be marked is the last possible target for a hold.</desc>
+    </event>
 </ils_events>
 
 
index c4be222..bbeeae5 100644 (file)
@@ -1307,31 +1307,24 @@ sub mark_item {
     my( $self, $conn, $auth, $copy_id, $args ) = @_;
     $args ||= {};
 
-    # Items must be checked in before any attempt is made to mark damaged or discard
-    my $evt = try_checkin($auth, $copy_id) if
-        ($self->api_name=~ /(?:damaged|discard)/ && $args->{handle_checkin});
-    return $evt if $evt;
-
     my $e = new_editor(authtoken=>$auth, xact =>1);
     return $e->die_event unless $e->checkauth;
     my $copy = $e->retrieve_asset_copy([
         $copy_id,
-        {flesh => 1, flesh_fields => {'acp' => ['call_number']}}])
+        {flesh => 1, flesh_fields => {'acp' => ['call_number','status']}}])
             or return $e->die_event;
 
-    my $owning_lib = 
+    my $owning_lib =
         ($copy->call_number->id == OILS_PRECAT_CALL_NUMBER) ? 
             $copy->circ_lib : $copy->call_number->owning_lib;
 
+    my $evt; # For later.
     my $perm = 'MARK_ITEM_MISSING';
     my $stat = OILS_COPY_STATUS_MISSING;
 
     if( $self->api_name =~ /damaged/ ) {
         $perm = 'MARK_ITEM_DAMAGED';
         $stat = OILS_COPY_STATUS_DAMAGED;
-        my $evt = handle_mark_damaged($e, $copy, $owning_lib, $args);
-        return $evt if $evt;
-
     } elsif ( $self->api_name =~ /bindery/ ) {
         $perm = 'MARK_ITEM_BINDERY';
         $stat = OILS_COPY_STATUS_BINDERY;
@@ -1355,20 +1348,85 @@ sub mark_item {
     # caller may proceed if either perm is allowed
     return $e->die_event unless $e->allowed([$perm, 'UPDATE_COPY'], $owning_lib);
 
-    $copy->status($stat);
-    $copy->edit_date('now');
-    $copy->editor($e->requestor->id);
-
-    $e->update_asset_copy($copy) or return $e->die_event;
+    # Copy status checks.
+    if ($copy->status->id() == OILS_COPY_STATUS_CHECKED_OUT) {
+        # Items must be checked in before any attempt is made to change its status.
+        if ($args->{handle_checkin}) {
+            $evt = try_checkin($auth, $copy_id);
+        } else {
+            $evt = OpenILS::Event->new('ITEM_TO_MARK_CHECKED_OUT');
+        }
+    } elsif ($copy->status->id() == OILS_COPY_STATUS_IN_TRANSIT) {
+        # Items in transit need to have the transit aborted before being marked.
+        if ($args->{handle_transit}) {
+            if ($e->allowed('ABORT_TRANSIT')) {
+                my $transit = $e->search_action_transit_copy(
+                    {
+                        target_copy => $copy->id,
+                        dest_recv_time => undef,
+                        cancel_time => undef
+                    }
+                );
+                if ($transit && @{$transit}) {
+                    # Abort the transit and do not retarget holds nor commit the transaction.
+                    # NOTE: __abort_transit should probably be moved/renamed since we're reaching in to use it.
+                    my $r = OpenILS::Application::Circ::Transit::__abort_transit($e, $transit->[0], $copy, 1, 1);
+                    $evt = $r if (ref $r); #__abort_transit returns 1 or an event.
+                }
+            } else {
+                $evt = $e->event;
+            }
+        } else {
+            $evt = OpenILS::Event->new('ITEM_TO_MARK_IN_TRANSIT');
+        }
+    } elsif ($copy->status->restrict_copy_delete() && $self->api_name =~ /discard/) {
+        # Items with restrict_copy_delete status require the
+        # COPY_DELETE_WARNING.override permission to be marked for
+        # discard.
+        if ($args->{handle_copy_delete_warning}) {
+            $evt = $e->event unless $e->allowed(['COPY_DELETE_WARNING.override'], $owning_lib);
+        } else {
+            $evt = OpenILS::Event->new('COPY_DELETE_WARNING');
+        }
+    }
+    return $evt if $evt;
 
+    # Retrieving holds for later use.
     my $holds = $e->search_action_hold_request(
-        { 
+        {
             current_copy => $copy->id,
             fulfillment_time => undef,
             cancel_time => undef,
-        }
+        },
+        {flesh=>1, flesh_fields=>{ahr=>['eligible_copies']}}
     );
 
+    # Handle extra mark damaged charges, etc.
+    if ($self->api_name =~ /damaged/) {
+        $evt = handle_mark_damaged($e, $copy, $owning_lib, $args);
+        return $evt if $evt;
+    }
+
+    # Throw event if attempting to  mark discard the only copy to fill a hold.
+    if ($self->api_name =~ /discard/) {
+        if (!$args->{handle_last_hold_copy}) {
+            for my $hold (@$holds) {
+                my $eligible = $hold->eligible_copies();
+                if (scalar(@{$eligible}) < 2) {
+                    $evt = OpenILS::Event->new('ITEM_TO_MARK_LAST_HOLD_COPY');
+                    last;
+                }
+            }
+        }
+        return $evt if $evt;
+    }
+
+    $copy->status($stat);
+    $copy->edit_date('now');
+    $copy->editor($e->requestor->id);
+
+    $e->update_asset_copy($copy) or return $e->die_event;
+
     $e->commit;
 
     if( $self->api_name =~ /damaged/ ) {