From 18f672d40658964f85657713c743acafe22f3633 Mon Sep 17 00:00:00 2001 From: Bill Erickson Date: Wed, 17 Apr 2013 10:31:04 -0400 Subject: [PATCH] LP 1169193 long-overdue automated processing Middle layer components for marking circulations long overdue. The automation is controlled with an Action/Trigger event definition (sample included in seed data), which uses a new MarkItemLongOverdue reactor. The reactor makes use of a new util function (AssetCommon.pm) for doing the actual work and looking up the relevant org unit settings. Inluded is a new PatronNotInCollections Validator, which can be used to avoid marking circulations long overdue for patrons that are in collections processing. Signed-off-by: Bill Erickson Signed-off-by: Jason Stephenson --- .../action_trigger_filters.json.example | 2 +- .../OpenILS/Application/Cat/AssetCommon.pm | 72 +++++++++++++++---- .../Trigger/Reactor/MarkItemLongOverdue.pm | 60 ++++++++++++++++ .../OpenILS/Application/Trigger/Validator.pm | 27 +++++++ 4 files changed, 146 insertions(+), 15 deletions(-) create mode 100644 Open-ILS/src/perlmods/lib/OpenILS/Application/Trigger/Reactor/MarkItemLongOverdue.pm diff --git a/Open-ILS/examples/action_trigger_filters.json.example b/Open-ILS/examples/action_trigger_filters.json.example index d599d7bd42..31d713d79b 100644 --- a/Open-ILS/examples/action_trigger_filters.json.example +++ b/Open-ILS/examples/action_trigger_filters.json.example @@ -4,7 +4,7 @@ "filter" : { "checkin_time" : null, "-or" : - [ { "stop_fines" : ["MAXFINES", "LONGOVERDUE"] }, + [ { "stop_fines" : ["MAXFINES"] }, { "stop_fines" : null } ] } diff --git a/Open-ILS/src/perlmods/lib/OpenILS/Application/Cat/AssetCommon.pm b/Open-ILS/src/perlmods/lib/OpenILS/Application/Cat/AssetCommon.pm index 0e6797455e..1cf8cc8bed 100644 --- a/Open-ILS/src/perlmods/lib/OpenILS/Application/Cat/AssetCommon.pm +++ b/Open-ILS/src/perlmods/lib/OpenILS/Application/Cat/AssetCommon.pm @@ -642,7 +642,47 @@ sub copy_perm_org { sub set_item_lost { - my($class, $e, $copy_id) = @_; + my ($class, $e, $copy_id) = @_; + + return $class->set_item_lost_or_lod( + $e, $copy_id, + perm => 'SET_CIRC_LOST', + status => OILS_COPY_STATUS_LOST, + ous_proc_fee => OILS_SETTING_LOST_PROCESSING_FEE, + ous_void_od => OILS_SETTING_VOID_OVERDUE_ON_LOST, + bill_type => 3, + bill_fee_type => 4, + bill_note => 'Lost Materials', + bill_fee_note => 'Lost Materials Processing Fee', + event => 'COPY_MARKED_LOST', + stop_fines => OILS_STOP_FINES_LOST, + at_hook => 'lost' + ); +} + +sub set_item_long_overdue { + my ($class, $e, $copy_id) = @_; + + return $class->set_item_lost_or_lod( + $e, $copy_id, + perm => 'SET_CIRC_LONG_OVERDUE', + status => 16, # Long Overdue + ous_proc_fee => 'circ.longoverdue_materials_processing_fee', + ous_void_od => 'circ.void_overdue_on_longoverdue', + bill_type => 10, + bill_fee_type => 11, + bill_note => 'Long Overdue Materials', + bill_fee_note => 'Long Overdue Materials Processing Fee', + event => 'COPY_MARKED_LONG_OVERDUE', + stop_fines => 'LONGOVERDUE', + at_hook => 'longoverdue' + ); +} + +# LOST or LONGOVERDUE +# basic process is the same. details change. +sub set_item_lost_or_lod { + my ($class, $e, $copy_id, %args) = @_; my $copy = $e->retrieve_asset_copy([ $copy_id, @@ -657,21 +697,21 @@ sub set_item_lost { {checkin_time => undef, target_copy => $copy->id} )->[0] or return $e->die_event; - $e->allowed('SET_CIRC_LOST', $circ->circ_lib) or return $e->die_event; + $e->allowed($args{perm}, $circ->circ_lib) or return $e->die_event; - return $e->die_event(OpenILS::Event->new('COPY_MARKED_LOST')) - if $copy->status == OILS_COPY_STATUS_LOST; + return $e->die_event(OpenILS::Event->new($args{event})) + if $copy->status == $args{status}; # --------------------------------------------------------------------- # fetch the related org settings my $proc_fee = $U->ou_ancestor_setting_value( - $owning_lib, OILS_SETTING_LOST_PROCESSING_FEE, $e) || 0; + $owning_lib, $args{ous_proc_fee}, $e) || 0; my $void_overdue = $U->ou_ancestor_setting_value( - $owning_lib, OILS_SETTING_VOID_OVERDUE_ON_LOST, $e) || 0; + $owning_lib, $args{ous_void_od}, $e) || 0; # --------------------------------------------------------------------- # move the copy into LOST status - $copy->status(OILS_COPY_STATUS_LOST); + $copy->status($args{status}); $copy->editor($e->requestor->id); $copy->edit_date('now'); $e->update_asset_copy($copy) or return $e->die_event; @@ -679,22 +719,22 @@ sub set_item_lost { my $price = $U->get_copy_price($e, $copy, $copy->call_number); if( $price > 0 ) { - my $evt = OpenILS::Application::Circ::CircCommon->create_bill( - $e, $price, 3, 'Lost Materials', $circ->id); + my $evt = OpenILS::Application::Circ::CircCommon->create_bill($e, + $price, $args{bill_type}, $args{bill_note}, $circ->id); return $evt if $evt; } # --------------------------------------------------------------------- # if there is a processing fee, charge that too if( $proc_fee > 0 ) { - my $evt = OpenILS::Application::Circ::CircCommon->create_bill( - $e, $proc_fee, 4, 'Lost Materials Processing Fee', $circ->id); + my $evt = OpenILS::Application::Circ::CircCommon->create_bill($e, + $proc_fee, $args{bill_fee_type}, $args{bill_fee_note}, $circ->id); return $evt if $evt; } # --------------------------------------------------------------------- # mark the circ as lost and stop the fines - $circ->stop_fines(OILS_STOP_FINES_LOST); + $circ->stop_fines($args{stop_fines}); $circ->stop_fines_time('now') unless $circ->stop_fines_time; $e->update_action_circulation($circ) or return $e->die_event; @@ -709,9 +749,13 @@ sub set_item_lost { return $evt if $evt; my $ses = OpenSRF::AppSession->create('open-ils.trigger'); - $ses->request('open-ils.trigger.event.autocreate', 'lost', $circ, $circ->circ_lib); + $ses->request( + 'open-ils.trigger.event.autocreate', + $args{at_hook}, $circ, $circ->circ_lib + ); - my $evt2 = OpenILS::Utils::Penalty->calculate_penalties($e, $circ->usr, $U->xact_org($circ->id,$e)); + my $evt2 = OpenILS::Utils::Penalty->calculate_penalties( + $e, $circ->usr, $U->xact_org($circ->id, $e)); return $evt2 if $evt2; return undef; diff --git a/Open-ILS/src/perlmods/lib/OpenILS/Application/Trigger/Reactor/MarkItemLongOverdue.pm b/Open-ILS/src/perlmods/lib/OpenILS/Application/Trigger/Reactor/MarkItemLongOverdue.pm new file mode 100644 index 0000000000..26e6aae58b --- /dev/null +++ b/Open-ILS/src/perlmods/lib/OpenILS/Application/Trigger/Reactor/MarkItemLongOverdue.pm @@ -0,0 +1,60 @@ +package OpenILS::Application::Trigger::Reactor::MarkItemLongOverdue; +use base 'OpenILS::Application::Trigger::Reactor'; +use strict; use warnings; +use Error qw/:try/; +use Data::Dumper; +use OpenSRF::Utils::Logger qw/:logger/; +use OpenILS::Utils::CStoreEditor q/:funcs/; +use OpenILS::Application::Cat::AssetCommon; +$Data::Dumper::Indent = 0; + + +sub ABOUT { + return < 1); + + my $requestor = $e->retrieve_actor_user($$env{params}{editor}); + + if (!$requestor) { + $logger->error("trigger: MarkItemLongOverdue require 'editor' param"); + return 0; + } + + $e->requestor($requestor); + + my $circ = $$env{target}; + my $evt = OpenILS::Application::Cat::AssetCommon-> + set_item_long_overdue($e, $circ->target_copy); + + if ($evt) { + $logger->error("trigger: MarkItemLongOverdue ". + "failed with event $evt->{textcode}"); + return 0; + } + + $e->commit; + + my $ses = OpenSRF::AppSession->create('open-ils.trigger'); + $ses->request('open-ils.trigger.event.autocreate', + 'longoverdue.auto', $circ, $circ->circ_lib); + + return 1; +} + +1; diff --git a/Open-ILS/src/perlmods/lib/OpenILS/Application/Trigger/Validator.pm b/Open-ILS/src/perlmods/lib/OpenILS/Application/Trigger/Validator.pm index 6b5dc3c399..db909a51b1 100644 --- a/Open-ILS/src/perlmods/lib/OpenILS/Application/Trigger/Validator.pm +++ b/Open-ILS/src/perlmods/lib/OpenILS/Application/Trigger/Validator.pm @@ -6,6 +6,7 @@ use OpenSRF::Utils qw/:datetime/; use OpenSRF::Utils::Logger qw/:logger/; use OpenILS::Const qw/:const/; use OpenILS::Application::AppUtils; +use OpenILS::Utils::CStoreEditor qw/:funcs/; sub fourty_two { return 42 } sub NOOP_True { return 1 } sub NOOP_False { return 0 } @@ -161,4 +162,30 @@ sub PatronNotBarred { return !PatronBarred(@_); } +# core type "circ". +# Being "In Collections" means having the PATRON_IN_COLLECTIONS penalty +# applied to the user at or above the circ_lib of the target circ. +sub PatronNotInCollections { + my ($self, $env) = @_; + my $user = $env->{target}->usr; + my $org = $env->{target}->circ_lib; + + # beware environment fleshing + $user = $user->id if ref $user; + $org = $org->id if ref $org; + + my $existing = new_editor()->search_actor_user_standing_penalty({ + usr => $user, + org_unit => $U->get_org_ancestors($org, 1), + standing_penalty => 30, # PATRON_IN_COLLECTIONS + '-or' => [ + {stop_date => undef}, + {stop_date => {'>' => 'now'}} + ] + }); + + return @$existing ? 0 : 1; +} + + 1; -- 2.43.2