From: erickson Date: Sun, 23 Nov 2008 15:32:00 +0000 (+0000) Subject: plugged in the new and improved in-db penalty calculation X-Git-Url: https://old-git.evergreen-ils.org/?a=commitdiff_plain;h=3fec6eaefb6dea89e8520c3998509066856cc9a4;p=Evergreen.git plugged in the new and improved in-db penalty calculation git-svn-id: svn://svn.open-ils.org/ILS/trunk@11307 dcc99617-32d9-48b4-a31d-7c20da2025e4 --- diff --git a/Open-ILS/src/perlmods/OpenILS/Application/Actor.pm b/Open-ILS/src/perlmods/OpenILS/Application/Actor.pm index 6b5038e343..3b3d073fb2 100644 --- a/Open-ILS/src/perlmods/OpenILS/Application/Actor.pm +++ b/Open-ILS/src/perlmods/OpenILS/Application/Actor.pm @@ -2730,39 +2730,37 @@ __PACKAGE__->register_method( api_name => "open-ils.actor.user.penalties.update"); sub update_penalties { - my( $self, $conn, $auth, $user_id ) = @_; + my($self, $conn, $auth, $user_id) = @_; my $e = new_editor(authtoken=>$auth, xact => 1); return $e->die_event unless $e->checkauth; my $user = $e->retrieve_actor_user($user_id) or return $e->die_event; return $e->die_event unless $e->allowed('UPDATE_USER', $user->home_ou); - my $evt = OpenILS::Utils::Penalty->calculate_penalties($e, $user_id); + my $evt = OpenILS::Utils::Penalty->calculate_penalties($e, $user_id, $e->requestor->ws_ou); return $evt if $evt; $e->commit; return 1; } + __PACKAGE__->register_method( method => "apply_penalty", api_name => "open-ils.actor.user.penalty.apply"); sub apply_penalty { - my($self, $conn, $auth, $user_id, $penalty_name) = @_; + my($self, $conn, $auth, $penalty) = @_; my $e = new_editor(authtoken=>$auth, xact => 1); return $e->die_event unless $e->checkauth; - my $user = $e->retrieve_actor_user($user_id) or return $e->die_event; + my $user = $e->retrieve_actor_user(penalty->usr) or return $e->die_event; return $e->die_event unless $e->allowed('UPDATE_USER', $user->home_ou); - my $penalty = $e->search_config_standing_penalty({name => $penalty_name})->[0] - or return $e->die_event; - # is it already applied? return 1 if $e->search_actor_user_standing_penalty( - {usr => $user_id, standing_penalty => $penalty->id})->[0]; + { usr => $penalty->usr, + standing_penalty => $penalty->standing_penalty, + org_unit => $penalty->org_unit + })->[0]; - my $newp = Fieldmapper::actor::user_standing_penalty->new; - $newp->standing_penalty($penalty->id); - $newp->usr($user_id); - $e->create_actor_user_standing_penalty($newp) or return $e->die_event; + $e->create_actor_user_standing_penalty($penalty) or return $e->die_event; $e->commit; return 1; } diff --git a/Open-ILS/src/perlmods/OpenILS/Application/Circ/Circulate.pm b/Open-ILS/src/perlmods/OpenILS/Application/Circ/Circulate.pm index 65d44fb8c3..d4942d5af0 100644 --- a/Open-ILS/src/perlmods/OpenILS/Application/Circ/Circulate.pm +++ b/Open-ILS/src/perlmods/OpenILS/Application/Circ/Circulate.pm @@ -835,9 +835,9 @@ sub run_patron_permit_scripts { my $patron_events = $result->{events}; - OpenILS::Utils::Penalty->calculate_penalties($self->editor, undef, $self->patron); + OpenILS::Utils::Penalty->calculate_penalties($self->editor, $self->patron->id, $self->circ_lib); my $mask = ($self->is_renewal) ? 'RENEW' : 'CIRC'; - my $penalties = OpenILS::Utils::penalty->retrieve_penalties($self->editor, $patronid, $mask); + my $penalties = OpenILS::Utils::Penalty->retrieve_penalties($self->editor, $patronid, $self->circ_lib, $mask); push( @allevents, OpenILS::Event->new($_)) for (@$penalties, @$patron_events); } @@ -1176,7 +1176,7 @@ sub do_checkout { # Update the patron penalty info in the DB. Run it for permit-overrides # since the penalties are not updated during the permit phase # ------------------------------------------------------------------------------ - $U->update_patron_penalties_nonblock(patronid => $self->patron->id) if $self->permit_override; + OpenILS::Utils::Penalty->calculate_penalties($self->editor, $self->patron->id, $self->circ_lib); my $record = $U->record_to_mvr($self->title) unless $self->is_precat; $self->push_events( @@ -1756,7 +1756,7 @@ sub do_checkin { unless @{$self->events}; } - $U->update_patron_penalties_nonblock(patronid => $self->patron->id) if $self->is_checkin; + OpenILS::Utils::Penalty->calculate_penalties($self->editor, $self->patron->id, $self->circ_lib); $self->checkin_flesh_events; return; } diff --git a/Open-ILS/src/perlmods/OpenILS/Application/Circ/Money.pm b/Open-ILS/src/perlmods/OpenILS/Application/Circ/Money.pm index 7c5aa6b981..9e5670bc86 100644 --- a/Open-ILS/src/perlmods/OpenILS/Application/Circ/Money.pm +++ b/Open-ILS/src/perlmods/OpenILS/Application/Circ/Money.pm @@ -27,6 +27,7 @@ use Data::Dumper; use OpenILS::Event; use OpenSRF::Utils::Logger qw/:logger/; use OpenILS::Utils::CStoreEditor qw/:funcs/; +use OpenILS::Utils::Penalty; __PACKAGE__->register_method( method => "make_payments", @@ -192,12 +193,11 @@ sub make_payments { $apputils->commit_db_session($session); - # ------------------------------------------------------------------------------ - # Update the patron penalty info in the DB - # ------------------------------------------------------------------------------ - $U->update_patron_penalties_nonblock(patronid => $userid); + $client->respond_complete(1); - $client->respond_complete(1); + $e = new_editor(xact => 1); + $evt = OpenILS::Utils::Penalty->calculate_penalties($e, $userid, $drawer); + $e->commit unless $evt; return undef; } @@ -379,31 +379,28 @@ sub billing_items_create { my( $self, $client, $login, $billing ) = @_; my $e = new_editor(authtoken => $login, xact => 1); - return $e->event unless $e->checkauth; - return $e->event unless $e->allowed('CREATE_BILL'); + return $e->die_event unless $e->checkauth; + return $e->die_event unless $e->allowed('CREATE_BILL'); my $xact = $e->retrieve_money_billable_transaction($billing->xact) - or return $e->event; + or return $e->die_event; # if the transaction was closed, re-open it if($xact->xact_finish) { $xact->clear_xact_finish; $e->update_money_billable_transaction($xact) - or return $e->event; + or return $e->die_event; } my $amt = $billing->amount; $amt =~ s/\$//og; $billing->amount($amt); - $e->create_money_billing($billing) or return $e->event; + $e->create_money_billing($billing) or return $e->die_event; + my $evt = OpenILS::Utils::Penalty->calculate_penalties($e, $xact->usr, $e->requestor->ws_ou); + return $evt if $evt; $e->commit; - # ------------------------------------------------------------------------------ - # Update the patron penalty info in the DB - # ------------------------------------------------------------------------------ - $U->update_patron_penalties_nonblock(patronid => $xact->usr); - return $billing->id; } @@ -449,9 +446,8 @@ sub void_bill { return $evt if $evt; } + OpenILS::Utils::Penalty->calculate_penalties($e, $_, $e->requestor->ws_ou) for keys %users; $e->commit; - # update the penalties for each affected user - $U->update_patron_penalties_nonblock(patronid => $_) for keys %users; return 1; } diff --git a/Open-ILS/src/perlmods/OpenILS/Utils/Penalty.pm b/Open-ILS/src/perlmods/OpenILS/Utils/Penalty.pm index 2a9683cf65..51288421ee 100644 --- a/Open-ILS/src/perlmods/OpenILS/Utils/Penalty.pm +++ b/Open-ILS/src/perlmods/OpenILS/Utils/Penalty.pm @@ -15,100 +15,39 @@ my $U = "OpenILS::Application::AppUtils"; # calculate and update the well-known penalties sub calculate_penalties { - my($class, $e, $user_id, $user) = @_; + my($class, $e, $user_id, $context_org) = @_; - $user = $user || $e->retrieve_actor_user($user_id); - $user_id = $user->id; - my $grp_id = (ref $user->profile) ? $user->profile->id : $user->profile; + my $penalties = $e->json_query({from => ['actor.calculate_system_penalties',$user_id, $context_org]}); - my $penalties = $e->search_actor_user_standing_penalty({usr => $user_id}); - my $stats = $class->collect_user_stats($e, $user_id); - my $overdue = $stats->{overdue}; - my $mon_owed = $stats->{money_owed}; - my $thresholds = $class->get_group_penalty_thresholds($e, $grp_id); + for my $pen_obj (@$penalties) { - $logger->info("patron $user_id in group $grp_id has $overdue overdue circulations and owes $mon_owed"); + next if grep { # leave duplicate penalties in place + $_->{org_unit} == $pen_obj->{org_unit} and + $_->{standing_penalty} == $pen_obj->{standing_penalty} and + ($_->{id} || '') ne ($pen_obj->{id} || '') } @$penalties; - for my $thresh (@$thresholds) { - my $evt; + if(defined $pen_obj->{id}) { + $e->delete_actor_user_standing_penalty($pen_obj->{id}) + or return $e->die_event; - if($thresh->penalty == OILS_PENALTY_PATRON_EXCEEDS_FINES) { - $evt = $class->check_apply_penalty( - $e, $user_id, $penalties, OILS_PENALTY_PATRON_EXCEEDS_FINES, $thresh->threshold, $mon_owed); - return $evt if $evt; + } else { + my $newp = Fieldmapper::actor::user_standing_penalty->new; + $newp->$_($pen_obj->{$_}) for keys %$pen_obj; + $e->create_actor_user_standing_penalty($newp) + or return $e->die_event; } - - if($thresh->penalty == OILS_PENALTY_PATRON_EXCEEDS_OVERDUE_COUNT) { - $evt = $class->check_apply_penalty( - $e, $user_id, $penalties, OILS_PENALTY_PATRON_EXCEEDS_OVERDUE_COUNT, $thresh->threshold, $overdue); - return $evt if $evt; - } - } -} - -# if a given penalty does not already exist in the DB, this creates it. -# If it does exist and should not, this removes it. -sub check_apply_penalty { - my($class, $e, $user_id, $all_penalties, $penalty_id, $threshold, $value) = @_; - my ($existing) = grep { $_->standing_penalty == $penalty_id } @$all_penalties; - - # penalty threshold has been exceeded and needs to be added - if($value >= $threshold and not $existing) { - my $newp = Fieldmapper::actor::user_standing_penalty->new; - $newp->standing_penalty($penalty_id); - $newp->usr($user_id); - $e->create_actor_user_standing_penalty($newp) or return $e->die_event; - - # patron is within penalty range and existing penalty must be removed - } elsif($value < $threshold and $existing) { - $e->delete_actor_user_standing_penalty($existing) - or return $e->die_event; } return undef; } - -sub collect_user_stats { - my($class, $e, $user_id) = @_; - - my $stor_ses = $U->start_db_session(); - my $money_owed = $stor_ses->request( - 'open-ils.storage.actor.user.total_owed', $user_id)->gather(1); - my $checkouts = $stor_ses->request( - 'open-ils.storage.actor.user.checked_out.count', $user_id)->gather(1); - $U->rollback_db_session($stor_ses); - - return { - overdue => $checkouts->{overdue} || 0, - money_owed => $money_owed || 0 - }; -} - -# get the ranged set of penalties for a give group -# XXX this could probably benefit from a stored proc -sub get_group_penalty_thresholds { - my($class, $e, $grp_id) = @_; - my @thresholds; - my $cur_grp = $grp_id; - do { - my $thresh = $e->search_permission_grp_penalty_threshold({grp => $cur_grp}); - for my $t (@$thresh) { - push(@thresholds, $t) unless (grep { $_->name eq $t->name } @thresholds); - } - } while(defined ($cur_grp = $e->retrieve_permission_grp_tree($cur_grp)->parent)); - - return \@thresholds; -} - - # any penalties whose block_list has an item from @fatal_mask will be sorted # into the fatal_penalties set. Others will be sorted into the info_penalties set sub retrieve_penalties { - my($class, $e, $user_id, @fatal_mask) = @_; + my($class, $e, $user_id, $context_org, @fatal_mask) = @_; my $penalties = $e->search_actor_user_standing_penalty([ - {usr => $user_id}, + {usr => $user_id, org_unit => $U->get_org_ancestors($context_org)}, {flesh => 1, flesh_fields => {ausp => ['standing_penalty']}} ]);