wiring up booking pickup and return with new methods in the open-ils.circ service
authormiker <miker@dcc99617-32d9-48b4-a31d-7c20da2025e4>
Mon, 14 Dec 2009 21:24:25 +0000 (21:24 +0000)
committermiker <miker@dcc99617-32d9-48b4-a31d-7c20da2025e4>
Mon, 14 Dec 2009 21:24:25 +0000 (21:24 +0000)
git-svn-id: svn://svn.open-ils.org/ILS/trunk@15161 dcc99617-32d9-48b4-a31d-7c20da2025e4

Open-ILS/examples/fm_IDL.xml
Open-ILS/src/extras/ils_events.xml
Open-ILS/src/perlmods/OpenILS/Application/AppUtils.pm
Open-ILS/src/perlmods/OpenILS/Application/Circ/Circulate.pm

index 40bbdd8..520ea51 100644 (file)
@@ -2396,6 +2396,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
                        <field reporter:label="Resource Attribute Maps" name="attr_maps" oils_persist:virtual="true" reporter:datatype="link"/>
                        <field reporter:label="Reservation Target Resources" name="tgt_rsrcs" oils_persist:virtual="true" reporter:datatype="link"/>
                        <field reporter:label="Reservation Current Resources" name="curr_rsrcs" oils_persist:virtual="true" reporter:datatype="link"/>
+                       <field reporter:label="Catalog Item" name="catalog_item" oils_persist:virtual="true" reporter:datatype="link"/>
                </fields>
                <links>
                        <link field="owner" reltype="has_a" key="id" map="" class="aou"/>
index 898afcb..8b14d15 100644 (file)
        <event code='7019' textcode='HOLD_CAPTURE_DELAYED'>
                <desc xml:lang="en-US">Hold capture was delayed for this item</desc>
        </event>
+       <event code='7020' textcode='COPY_RESERVED'>
+               <desc xml:lang="en-US">Item reserved for booking request</desc>
+       </event>
+       <event code='7021' textcode='RESERVATION_NOT_FOUND'>
+               <desc xml:lang="en-US">Booking reservation not found</desc>
+       </event>
 
 
 
index f78d102..55546dc 100644 (file)
@@ -796,6 +796,64 @@ sub DB_UPDATE_FAILED {
                payload => ($payload) ? $payload : undef ); 
 }
 
+sub fetch_booking_reservation {
+       my( $self, $id ) = @_;
+       my( $res, $evt );
+
+       $res = $self->simplereq(
+               'open-ils.cstore', 
+               'open-ils.cstore.direct.booking.reservation.retrieve', $id
+       );
+
+       # simplereq doesn't know how to flesh so ...
+       if ($res) {
+               $res->usr(
+                       $self->simplereq(
+                               'open-ils.cstore', 
+                               'open-ils.cstore.direct.actor.user.retrieve', $res->usr
+                       )
+               );
+
+               $res->target_resource_type(
+                       $self->simplereq(
+                               'open-ils.cstore', 
+                               'open-ils.cstore.direct.booking.resource_type.retrieve', $res->target_resource_type
+                       )
+               );
+
+               if ($res->current_resource) {
+                       $res->current_resource(
+                               $self->simplereq(
+                                       'open-ils.cstore', 
+                                       'open-ils.cstore.direct.booking.resource.retrieve', $res->current_resource
+                               )
+                       );
+
+                       if ($self->is_true( $res->target_resource_type->catalog_item )) {
+                               $res->current_resource->catalog_item( $self->fetch_copy_by_barcode( $res->current_resource->barcode ) );
+                       }
+               }
+
+               if ($res->target_resource) {
+                       $res->target_resource(
+                               $self->simplereq(
+                                       'open-ils.cstore', 
+                                       'open-ils.cstore.direct.booking.resource.retrieve', $res->target_resource
+                               )
+                       );
+
+                       if ($self->is_true( $res->target_resource_type->catalog_item )) {
+                               $res->target_resource->catalog_item( $self->fetch_copy_by_barcode( $res->target_resource->barcode ) );
+                       }
+               }
+
+       } else {
+               $evt = OpenILS::Event->new('RESERVATION_NOT_FOUND');
+       }
+
+       return ($res, $evt);
+}
+
 sub fetch_circ_duration_by_name {
        my( $self, $name ) = @_;
        my( $dur, $evt );
@@ -936,6 +994,16 @@ sub unflesh_copy {
        return $copy;
 }
 
+sub unflesh_reservation {
+       my( $self, $reservation ) = @_;
+       return undef unless $reservation;
+       $reservation->usr( $reservation->usr->id ) if ref($reservation->usr);
+       $reservation->target_resource_type( $reservation->target_resource_type->id ) if ref($reservation->target_resource_type);
+       $reservation->target_resource( $reservation->target_resource->id ) if ref($reservation->target_resource);
+       $reservation->current_resource( $reservation->current_resource->id ) if ref($reservation->current_resource);
+       return $reservation;
+}
+
 # un-fleshes a copy and updates it in the DB
 # returns a DB_UPDATE_FAILED event on error
 # returns undef on success
@@ -964,6 +1032,29 @@ sub update_copy {
        return undef;
 }
 
+sub update_reservation {
+       my( $self, %params ) = @_;
+
+       my $reservation = $params{reservation}  || die "update_reservation(): reservation required";
+       my $editor              = $params{editor} || die "update_reservation(): copy editor required";
+       my $session             = $params{session};
+
+       $logger->debug("Updating copy in the database: " . $reservation->id);
+
+       $self->unflesh_reservation($reservation);
+
+       my $s;
+       my $meth = 'open-ils.cstore.direct.booking.reservation.update';
+
+       $s = $session->request( $meth, $reservation )->gather(1) if $session;
+       $s = $self->cstorereq( $meth, $reservation ) unless $session;
+
+       $logger->debug("Update of copy ".$reservation->id." returned: $s");
+
+       return $self->DB_UPDATE_FAILED($reservation) unless $s;
+       return undef;
+}
+
 sub fetch_billable_xact {
        my( $self, $id ) = @_;
        my($xact, $evt);
index fa84d32..aabce13 100644 (file)
@@ -150,6 +150,13 @@ __PACKAGE__->register_method(
 
 __PACKAGE__->register_method(
     method  => "run_method",
+    api_name    => "open-ils.circ.reservation.pickup");
+__PACKAGE__->register_method(
+    method  => "run_method",
+    api_name    => "open-ils.circ.reservation.return");
+
+__PACKAGE__->register_method(
+    method  => "run_method",
     api_name    => "open-ils.circ.checkout.inspect",
     desc => q/
         Returns the circ matrix test result and, on success, the rule set and matrix test object
@@ -172,6 +179,9 @@ sub run_method {
     # Go ahead and load the script runner to make sure we have all 
     # of the objects we need
     # --------------------------------------------------------------------------
+    $circulator->is_res_checkin($circulator->is_checkin(1)) if $api =~ /reservation.return/;
+    $circulator->is_res_checkout(1) if $api =~ /reservation.pickup/;
+
     $circulator->is_renewal(1) if $api =~ /renew/;
     $circulator->is_checkin(1) if $api =~ /checkin/;
     $circulator->noop if $circulator->claims_never_checked_out;
@@ -206,15 +216,22 @@ sub run_method {
             $circulator->do_checkout();
         }
 
+    } elsif( $circulator->is_res_checkout ) {
+        $circulator->do_reservation_pickup();
+
     } elsif( $api =~ /inspect/ ) {
         my $data = $circulator->do_inspect();
         $circulator->editor->rollback;
         return $data;
 
-    } elsif( $api =~ /checkout/ ) {
+    } elsif( $api =~ // ) {
         $circulator->is_checkout(1);
         $circulator->do_checkout();
 
+    } elsif( $circulator->is_res_checkin ) {
+        $circulator->do_reservation_return();
+        $circulator->do_checkin();
+
     } elsif( $api =~ /checkin/ ) {
         $circulator->do_checkin();
 
@@ -338,6 +355,7 @@ my @AUTOLOAD_FIELDS = qw/
     notify_hold
     remote_hold
     backdate
+    reservation
     copy
     copy_id
     copy_barcode
@@ -349,10 +367,12 @@ my @AUTOLOAD_FIELDS = qw/
     title
     is_renewal
     is_checkout
+    is_res_checkout
     is_noncat
     is_precat
     request_precat
     is_checkin
+    is_res_checkin
     noncat_type
     editor
     events
@@ -1324,6 +1344,28 @@ sub update_copy {
     $copy->circ_lib($circ_lib) if $circ_lib;
 }
 
+sub update_reservation {
+    my $self = shift;
+    my $reservation = $self->reservation;
+
+    my $usr = $reservation->usr;
+    my $target_rt = $reservation->target_resource_type;
+    my $target_r = $reservation->target_resource;
+    my $current_r = $reservation->current_resource;
+
+    $reservation->usr($usr->id) if $usr;
+    $reservation->target_resource_type($target_rt->id) if $target_rt;
+    $reservation->target_resource($target_r->id) if $target_r;
+    $reservation->current_resource($current_r->id) if $current_r;
+
+    return $self->bail_on_events($self->editor->event)
+        unless $self->editor->update_booking_reservation($self->reservation);
+
+    my $evt;
+    ($reservation, $evt) = $U->fetch_booking_reservation($reservation->id);
+    $self->reservation($reservation);
+}
+
 
 sub bail_on_events {
     my( $self, @evts ) = @_;
@@ -1464,6 +1506,7 @@ sub find_related_user_hold {
 
 sub run_checkout_scripts {
     my $self = shift;
+    my $nobail = shift;
 
     my $evt;
     my $runner = $self->script_runner;
@@ -1498,13 +1541,13 @@ sub run_checkout_scripts {
 
         unless($duration) {
             ($duration, $evt) = $U->fetch_circ_duration_by_name($duration_name);
-            return $self->bail_on_events($evt) if $evt;
+            return $self->bail_on_events($evt) if ($evt && !$nobail);
         
             ($recurring, $evt) = $U->fetch_recurring_fine_by_name($recurring_name);
-            return $self->bail_on_events($evt) if $evt;
+            return $self->bail_on_events($evt) if ($evt && !$nobail);
         
             ($max_fine, $evt) = $U->fetch_max_fine_by_name($max_fine_name);
-            return $self->bail_on_events($evt) if $evt;
+            return $self->bail_on_events($evt) if ($evt && !$nobail);
         }
 
     } else {
@@ -1591,6 +1634,73 @@ sub build_checkout_circ_object {
     $self->circ($circ);
 }
 
+sub do_reservation_pickup {
+    my $self = shift;
+
+    $self->log_me("do_reservation_pickup()");
+
+    my ($reservation, $evt) = $U->fetch_booking_reservation($self->reservation);
+    return $self->bail_on_events($evt) if $evt;
+
+    $self->reservation( $reservation );
+    $self->reservation->pickup_time('now');
+
+    if (
+        $self->reservation->current_resource &&
+        $self->reservation->current_resource->catalog_item
+    ) {
+        $self->copy( $self->reservation->current_resource->catalog_item );
+        $self->patron( $self->reservation->usr );
+        $self->run_checkout_scripts(1);
+
+        my $duration   = $self->duration_rule;
+        my $max        = $self->max_fine_rule;
+        my $recurring  = $self->recurring_fines_rule;
+
+        if ($duration && $max && $recurring) {
+            my $policy = $self->get_circ_policy($duration, $recurring, $max);
+
+            my $dname = $duration->name;
+            my $mname = $max->name;
+            my $rname = $recurring->name;
+
+            $logger->debug("circulator: building reservation ".
+                "with duration=$dname, maxfine=$mname, recurring=$rname");
+
+            $self->reservation->fine_amount($policy->{recurring_fine});
+            $self->reservation->max_fine($policy->{max_fine});
+            $self->reservation->fine_interval($recurring->recurrence_interval);
+        }
+
+        $self->copy->status(OILS_COPY_STATUS_CHECKED_OUT);
+        $self->update_copy();
+
+    } else {
+        $self->reservation->fine_amount($self->reservation->fine_amount);
+        $self->reservation->max_fine($self->reservation->max_fine);
+        $self->reservation->fine_interval($self->reservation->fine_interval);
+    }
+
+    $self->update_reservation();
+}
+
+sub do_reservation_return {
+    my $self = shift;
+    my $request = shift;
+
+    $self->log_me("do_reservation_return()");
+
+    my ($reservation, $evt) = $U->fetch_booking_reservation($self->reservation);
+    return $self->bail_on_events($evt) if $evt;
+
+    $self->reservation( $reservation );
+    $self->reservation->return_time('now');
+    $self->update_reservation();
+
+    if ( $self->reservation->current_resource && $self->reservation->current_resource->catalog_item ) {
+        $self->copy( $self->reservation->current_resource->catalog_item );
+    }
+}
 
 sub booking_adjusted_due_date {
     my $self = shift;