From ffc3ac9c6f2a1945f869e3943d56a4d3d2fa968c Mon Sep 17 00:00:00 2001 From: erickson Date: Tue, 1 Feb 2011 23:39:00 +0000 Subject: [PATCH] make sure that inline overdue fines generation completes before we attempt to void overdues fines in checkin, otherwise it's possible to create multiple services (storage and cstore) competing for the same DB row mid-transaction, resulting in cstore timeouts and rollback of checkin. This could happen with backdated or amnesty checkins git-svn-id: svn://svn.open-ils.org/ILS/trunk@19357 dcc99617-32d9-48b4-a31d-7c20da2025e4 --- .../lib/OpenILS/Application/Circ/Circulate.pm | 44 +++++++++++++--------- 1 file changed, 27 insertions(+), 17 deletions(-) diff --git a/Open-ILS/src/perlmods/lib/OpenILS/Application/Circ/Circulate.pm b/Open-ILS/src/perlmods/lib/OpenILS/Application/Circ/Circulate.pm index c000676b45..b6bbedc424 100644 --- a/Open-ILS/src/perlmods/lib/OpenILS/Application/Circ/Circulate.pm +++ b/Open-ILS/src/perlmods/lib/OpenILS/Application/Circ/Circulate.pm @@ -2220,7 +2220,6 @@ sub do_checkin { # run the fine generator against this circ, if this circ is there $self->generate_fines_start if $self->circ; - if( $self->checkin_check_holds_shelf() ) { $self->bail_on_events(OpenILS::Event->new('NO_CHANGE')); $self->hold($U->fetch_open_hold_by_copy($self->copy->id)); @@ -2316,6 +2315,8 @@ sub do_checkin { } if( $self->is_renewal ) { + $self->finish_fines_and_voiding; + return if $self->bail_out; $self->push_events(OpenILS::Event->new('SUCCESS')); return; } @@ -2425,8 +2426,7 @@ sub do_checkin { unless @{$self->events}; } - # gather any updates to the circ after fine generation, if there was a circ - $self->generate_fines_finish if ($self->circ); + $self->finish_fines_and_voiding; OpenILS::Utils::Penalty->calculate_penalties( $self->editor, $self->patron->id, $self->circ_lib) if $self->patron; @@ -2435,6 +2435,30 @@ sub do_checkin { return; } +sub finish_fines_and_voiding { + my $self = shift; + + # gather any updates to the circ after fine generation, if there was a circ + $self->generate_fines_finish if ($self->circ); + + return unless $self->backdate or $self->void_overdues; + + # void overdues after fine generation to prevent concurrent DB access to overdue billings + my $note = 'System: Amnesty Checkin' if $self->void_overdues; + + my $evt = OpenILS::Application::Circ::CircCommon->void_overdues( + $self->editor, $self->circ, $self->backdate, $note); + + return $self->bail_on_events($evt) if $evt; + + # make sure the circ isn't closed if we just voided some fines + $evt = OpenILS::Application::Circ::CircCommon->reopen_xact($self->editor, $self->circ->id); + return $self->bail_on_events($evt) if $evt; + + return undef; +} + + # if a deposit was payed for this item, push the event sub check_circ_deposit { my $self = shift; @@ -2946,12 +2970,6 @@ sub checkin_handle_circ { return $self->bail_on_events($evt) if $evt; } - if($self->void_overdues) { - my $evt = OpenILS::Application::Circ::CircCommon->void_overdues( - $self->editor, $circ, undef, 'System: Amnesty Checkin'); # TODO i18n for system-generated notes - return $self->bail_on_events($evt) if $evt; - } - if(!$circ->stop_fines) { $circ->stop_fines(OILS_STOP_FINES_CHECKIN); $circ->stop_fines(OILS_STOP_FINES_RENEW) if $self->is_renewal; @@ -3008,10 +3026,6 @@ sub checkin_handle_circ { return $self->bail_on_events($self->editor->event) unless $self->editor->update_action_circulation($circ); - # make sure the circ isn't closed if we just voided some fines - $evt = OpenILS::Application::Circ::CircCommon->reopen_xact($self->editor, $circ->id); - return $self->bail_on_events($evt) if $evt; - return undef; } @@ -3074,10 +3088,6 @@ sub checkin_handle_backdate { $bd = cleanse_ISO8601($new_date->ymd . 'T' . $original_date->strftime('%T%z')); $self->backdate($bd); - - my $evt = OpenILS::Application::Circ::CircCommon->void_overdues($self->editor, $self->circ, $bd); - return $evt if $evt; - return undef; } -- 2.11.0