From 3c2e4791a12e285df79d9583299d93edade6a36f Mon Sep 17 00:00:00 2001 From: erickson Date: Wed, 15 Feb 2006 06:22:48 +0000 Subject: [PATCH] first round of new circ checkin logic. more testing, etc. to come. git-svn-id: svn://svn.open-ils.org/ILS/trunk@3074 dcc99617-32d9-48b4-a31d-7c20da2025e4 --- Open-ILS/src/extras/ils_events.xml | 15 + .../perlmods/OpenILS/Application/AppUtils.pm | 1 + .../OpenILS/Application/Circ/Circulate.pm | 273 +++++++++++++++++- .../OpenILS/Application/Circ/Transit.pm | 4 +- 4 files changed, 283 insertions(+), 10 deletions(-) diff --git a/Open-ILS/src/extras/ils_events.xml b/Open-ILS/src/extras/ils_events.xml index 7a6cdefdfc..c4f98c7cc5 100644 --- a/Open-ILS/src/extras/ils_events.xml +++ b/Open-ILS/src/extras/ils_events.xml @@ -56,6 +56,21 @@ + + + The given copy is not in a standard circulation status + + + + + + The given circulation is not in a standard status or + the circulation was never fully closed properly + + + + + diff --git a/Open-ILS/src/perlmods/OpenILS/Application/AppUtils.pm b/Open-ILS/src/perlmods/OpenILS/Application/AppUtils.pm index e61a132608..c0f0246890 100644 --- a/Open-ILS/src/perlmods/OpenILS/Application/AppUtils.pm +++ b/Open-ILS/src/perlmods/OpenILS/Application/AppUtils.pm @@ -827,6 +827,7 @@ sub fetch_open_transit_by_copy { sub unflesh_copy { my( $self, $copy ) = @_; + return undef unless $copy; $copy->status( $copy->status->id ) if ref($copy->status); $copy->location( $copy->location->id ) if ref($copy->location); $copy->circ_lib( $copy->circ_lib->id ) if ref($copy->circ_lib); diff --git a/Open-ILS/src/perlmods/OpenILS/Application/Circ/Circulate.pm b/Open-ILS/src/perlmods/OpenILS/Application/Circ/Circulate.pm index c2a5aa0e1d..711c5e7ffb 100644 --- a/Open-ILS/src/perlmods/OpenILS/Application/Circ/Circulate.pm +++ b/Open-ILS/src/perlmods/OpenILS/Application/Circ/Circulate.pm @@ -881,6 +881,252 @@ sub _checkout_noncat { } +__PACKAGE__->register_method( + method => "generic_receive", + api_name => "open-ils.circ.checkin__", +); + +sub generic_receive { + my( $self, $connection, $authtoken, $params ) = @_; + my( $ctx, $requestor, $evt ); + + ( $requestor, $evt ) = $U->checkses($authtoken) if $__isrenewal; + ( $requestor, $evt ) = $U->checksesperm( + $authtoken, 'COPY_CHECKIN' ) unless $__isrenewal; + return $evt if $evt; + + # ------------------------------------------------------------------------------ + # load up the circ objects + if( !( $ctx = $params->{_ctx}) ) { + ( $ctx, $evt ) = create_circ_ctx( %$params, + requestor => $requestor, + session => $U->start_db_session(), + type => 'circ', + fetch_copy_statuses => 1, + fetch_copy_locations => 1, + no_runner => 1, + ); + return $evt if $evt; + } + $ctx->{session} = $U->start_db_session() unless $ctx->{session}; + $ctx->{authtoken} = $authtoken; + my $session = $ctx->{session}; + + my $copy = $ctx->{copy}; + $U->unflesh_copy($copy); + $logger->debug("Checkin copy called by user ".$requestor->id." for copy ".$copy->id); + return OpenILS::Event->new('COPY_NOT_FOUND') unless $copy; + # ------------------------------------------------------------------------------ + + if(!$ctx->{force}) { + return $evt if ($evt = _checkin_check_copy_status($copy)); + } + + my ($circ) = $U->fetch_open_circulation($copy->id); + my ($transit) = $U->fetch_open_transit_by_copy($copy->id); + + if( $circ ) { + + # There is an open circ on this item so close out the circ + $ctx->{circ} = $circ; + $evt = _checkin_handle_circ($ctx); + return $evt if $evt; + + } elsif( $transit ) { + + # is this item currently in transit? + $ctx->{transit} = $transit; + $evt = $transcode->transit_receive( $copy, $requestor, $session ); + + if( !$U->event_equals($evt, 'SUCCESS') ) { + + # either an error occurred or a ROUTE_ITEM was generated and the + # item must be forwarded on to its destination. + $evt->{payload}->{copy} = $U->unflesh_copy($copy); + return $evt; + + } else { + + if($evt->{ishold}) { + + # copy was received as a hold transit. Copy is at target lib + # and hold transit is complete. We're done here... + $U->commit_db_session($session); + return _checkin_flesh_event($ctx, $evt); + } + $evt = undef; + } + } + + # If it's a renewal, we're not concerned with holds and transits. + # We just want the item to be checked in. + if($__isrenewal) { + $U->commit_db_session($session); + return OpenILS::Event->new('SUCCESS'); + } + + # Now, let's see if this copy is needed for a hold + my ($hold) = $holdcode->find_local_hold( $session, $copy, $requestor ); + + if($hold) { + + $ctx->{hold} = $hold; + + # Capture the hold with this copy + return $evt if ($evt = _checkin_capture_hold($ctx)); + + if( $hold->pickup_lib == $requestor->home_ou ) { + + # This hold was captured in the correct location + $evt = OpenILS::Event->new('SUCCESS'); + + } else { + + # Hold needs to be picked up elsewhere. Build a hold + # transit and route the item. + return $evt if ($evt =_checkin_build_hold_transit($ctx)); + $evt = OpenILS::Event->new('ROUTE_ITEM', org => $hold->pickup_lib); + } + + } else { # not needed for a hold + + if( $copy->circ_lib == $requestor->home_ou ) { + + # Copy is in the right place. Re-shelve the thing. + $copy->status($U->copy_status_from_name('reshelving')->id ); + return $evt if ( $evt = $U->update_copy( + copy => $copy, editor => $requestor->id, session => $session )); + $evt = OpenILS::Event->new('SUCCESS'); + $evt = OpenILS::Event->new('ITEM_NOT_CATALOGED') if $ctx->{precat}; + + } else { + + # Copy wants to go home. Transit it there. + return $evt if ( $evt = _checkin_build_generic_copy_transit($ctx) ); + $evt = OpenILS::Event->new('ROUTE_ITEM', org => $copy->circ_lib); + } + } + + $logger->info("Copy checkin finished with event: ".$evt->{textcode}); + + $U->commit_db_session($session); + return _checkin_flesh_event($ctx, $evt); +} + + +sub _checkin_check_copy_status { + my $copy = shift; + my $stat = (ref($copy->status)) ? $copy->status->id : $copy->status; + my $evt = OpenILS::Event->new('COPY_BAD_STATUS', payload => $copy ); + return $evt if ($stat == $U->copy_status_from_name('lost')->id); + return $evt if ($stat == $U->copy_status_from_name('missing')->id); + + # XXX Really do this? + my ($circ) = $U->fetch_open_circulation($copy->id); + if($circ) { + $evt = OpenILS::Event->new('CIRC_BAD_STATUS', payload => $copy ); + return $evt if ($circ->stop_fines =~ /longoverdue/); + return $evt if ($circ->stop_fines =~ /claimsreturned/); + } + + return undef; +} + +# Just gets the copy back home. Returns undef on success, event on error +sub _checkin_build_generic_copy_transit { + + my $ctx = shift; + my $requestor = $ctx->{requestor}; + my $copy = $ctx->{copy}; + my $transit = Fieldmapper::action::transit_copy->new; + my $session = $ctx->{session}; + + $logger->activity("User ". $requestor->id ." creating a ". + " new copy transit for copy ".$copy->id." to org ".$copy->circ_lib); + + $transit->source($requestor->home_ou); + $transit->dest($copy->circ_lib); + $transit->target_copy($copy->id); + $transit->source_send_time('now'); + $transit->copy_status($copy->status); + + $logger->debug("Creating new copy_transit in DB"); + + my $s = $session->request( + "open-ils.storage.direct.action.transit_copy.create", $transit )->gather(1); + return $U->DB_UPDATE_FAILED($transit) unless $s; + + $logger->info("Checkin copy successfully created new transit: $s"); + + $copy->status($U->copy_status_from_name('in transit')->id ); + + return $U->update_copy( copy => $copy, + editor => $requestor->id, session => $session ); + +} + + +sub _checkin_build_hold_transit { + my $ctx = shift; + + my $copy = $ctx->{copy}; + my $hold = $ctx->{hold}; + my $trans = Fieldmapper::action::hold_transit_copy->new; + + $trans->hold($hold->id); + $trans->source($ctx->{requestor}->home_ou); + $trans->dest($hold->pickup_lib); + $trans->source_send_time("now"); + $trans->target_copy($copy->id); + $trans->copy_status($copy->status); + + my $id = $ctx->{session}->request( + "open-ils.storage.direct.action.hold_transit_copy.create", $trans )->gather(1); + return $U->DB_UPDATE_FAILED($trans) unless $id; + + $logger->info("Checkin copy successfully created hold transit: $id"); + + $copy->status($U->copy_status_from_name('in transit')->id ); + return $U->update_copy( copy => $copy, + editor => $ctx->{requestor}->id, session => $ctx->{session} ); +} + +# Returns event on error, undef on success +sub _checkin_capture_hold { + my $ctx = shift; + my $copy = $ctx->{copy}; + my $hold = $ctx->{hold}; + + $logger->debug("Checkin copy capturing hold ".$hold->id); + + $hold->current_copy($copy->id); + $hold->capture_time('now'); + + my $stat = $ctx->{session}->request( + "open-ils.storage.direct.action.hold_request.update", $hold)->gather(1); + return $U->DB_UPDATE_FAILED($hold) unless $stat; + + $copy->status( $U->copy_status_from_name('on holds shelf')->id ); + + return $U->update_copy( copy => $copy, + editor => $ctx->{requestor}->id, session => $ctx->{session} ); +} + +sub _checkin_flesh_event { + my $ctx = shift; + my $evt = shift; + + my $payload = {}; + $payload->{copy} = $U->unflesh_copy($ctx->{copy}); + $payload->{record} = $U->record_to_mvr($ctx->{title}) if($ctx->{title} and !$ctx->{precat}); + $payload->{circ} = $ctx->{circ} if $ctx->{circ}; + $payload->{transit} = $ctx->{transit} if $ctx->{transit}; + + $evt->{payload} = $payload; + return $evt; +} + + # ------------------------------------------------------------------------------ __PACKAGE__->register_method( @@ -1038,10 +1284,14 @@ sub _check_checkin_holds { } +sub _checkin_handle_circ { return _update_checkin_circ_and_copy(@_); } + sub _update_checkin_circ_and_copy { my $ctx = shift; $U->logmark; + $logger->info("Handling circulation found in checkin..."); + my $circ = $ctx->{circ}; my $copy = $ctx->{copy}; my $requestor = $ctx->{requestor}; @@ -1067,9 +1317,9 @@ sub _update_checkin_circ_and_copy { $circ->xact_finish($backdate); - my $bills = $session->request( # XXX what other search criteria?? + my $bills = $session->request( # XXX Verify this call is correct "open-ils.storage.direct.money.billing.search_where.atomic", - billing_ts => { ">=" => $backdate })->gather(1); + billing_ts => { ">=" => $backdate }, "xact" => $circ->id )->gather(1); if($bills) { for my $bill (@$bills) { @@ -1118,7 +1368,7 @@ sub renew { # renew privelages ( $requestor, $patron, $evt ) = $U->checkses_requestor( $authtoken, $params->{patron}, 'RENEW_CIRC' ); - return $evt if $evt; + if($evt) { $__isrenewal = 0; return $evt; } # fetch and build the circulation environment @@ -1131,24 +1381,27 @@ sub renew { fetch_copy_statuses => 1, fetch_copy_locations => 1, ); - return $evt if $evt; + if($evt) { $__isrenewal = 0; return $evt; } $params->{_ctx} = $ctx; # make sure they have some renewals left and make sure the circulation exists ($circ, $evt) = _check_renewal_remaining($ctx); - return $evt if $evt; + if($evt) { $__isrenewal = 0; return $evt; } $ctx->{old_circ} = $circ; my $renewals = $circ->renewal_remaining - 1; # run the renew permit script - return $evt if( ($evt = _run_renew_scripts($ctx)) ); + $evt = _run_renew_scripts($ctx); + if($evt) { $__isrenewal = 0; return $evt; } # checkin the cop #$ctx->{patron} = $ctx->{patron}->id; $evt = $self->checkin($client, $authtoken, $ctx ); #{ barcode => $params->{barcode}, patron => $params->{patron}} ); - return $evt unless $U->event_equals($evt, 'SUCCESS'); + if( !$U->event_equals($evt, 'SUCCESS') ) { + $__isrenewal = 0; return $evt; + } # re-fetch the context since objects have changed in the checkin ( $ctx, $evt ) = create_circ_ctx( %$params, @@ -1160,7 +1413,7 @@ sub renew { fetch_copy_statuses => 1, fetch_copy_locations => 1, ); - return $evt if $evt; + if($evt) { $__isrenewal = 0; return $evt; } $params->{_ctx} = $ctx; $ctx->{renewal_remaining} = $renewals; @@ -1169,7 +1422,9 @@ sub renew { if( $U->event_equals($evt, 'ITEM_NOT_CATALOGED')) { $ctx->{precat} = 1; } else { - return $evt unless $U->event_equals($evt, 'SUCCESS'); + if(!$U->event_equals($evt, 'SUCCESS')) { + if($evt) { $__isrenewal = 0; return $evt; } + } } $params->{permit_key} = $evt->{payload}; diff --git a/Open-ILS/src/perlmods/OpenILS/Application/Circ/Transit.pm b/Open-ILS/src/perlmods/OpenILS/Application/Circ/Transit.pm index fd5c18071f..3c7a9445d1 100644 --- a/Open-ILS/src/perlmods/OpenILS/Application/Circ/Transit.pm +++ b/Open-ILS/src/perlmods/OpenILS/Application/Circ/Transit.pm @@ -81,8 +81,10 @@ sub transit_receive { return $U->DB_UPDATE_FAILED($transit) unless $r; # if this is a hold transit, finalize the hold transit + my $ishold = 0; if( ($evt = _finish_hold_transit( $session, $requestor, $copy, $transit->id )) ) { + $ishold = 1; return $evt unless $U->event_equals($evt, 'SUCCESS'); $evt = undef; } @@ -91,7 +93,7 @@ sub transit_receive { #recover this copy's status from the transit $copy->status( $transit->copy_status ); - return OpenILS::Event->new('SUCCESS', payload => $copy); + return OpenILS::Event->new('SUCCESS', ishold => $ishold, payload => $copy); } -- 2.43.2