Added two library settings.
"Assess Billing When Marked Long-Overdue"
Making it an option to bill patrons when marking LOD.
"Continue Overdue Billing When Marked Long-Overdue"
Allowing the system to continue to generate overdue fines
after the circulation has been marked LONGOVERDUE.
Altered the select query to respect that setting.
Edited the query in fm_IDL so that Long overdues
are still listed in the OPAC for the patrons even
without billing. If there are bills, they are listed
at the bottom under the fine category.
Signed-off-by: blake <blake@mobiusconsortium.org>
CASE
WHEN (
((fine_interval >= '1 day' AND due_date < 'today') OR (fine_interval < '1 day' AND due_date < 'now'))
- AND (stop_fines IS NULL OR stop_fines NOT IN ('LOST','CLAIMSRETURNED','LONGOVERDUE'))
+ AND (stop_fines IS NULL OR stop_fines NOT IN ('LOST','CLAIMSRETURNED','LONGOVERDUE') OR (stop_fines IN ('LONGOVERDUE') AND ID NOT IN(SELECT xact FROM money.billing WHERE xact=acirc.id)))
) THEN 1
ELSE 0
END
SUM( CASE WHEN (xact_finish IS NULL AND stop_fines = 'LOST') THEN 1 ELSE 0 END) AS lost,
SUM( CASE WHEN stop_fines = 'CLAIMSRETURNED' THEN 1 ELSE 0 END) AS claims_returned,
- SUM( CASE WHEN (xact_finish IS NULL AND stop_fines = 'LONGOVERDUE') THEN 1 ELSE 0 END) AS long_overdue
- FROM action.circulation
+ SUM( CASE WHEN (xact_finish IS NULL AND stop_fines = 'LONGOVERDUE' AND ID IN(SELECT xact FROM money.billing WHERE xact=acirc.id)) THEN 1 ELSE 0 END) AS long_overdue
+ FROM action.circulation acirc
WHERE checkin_time IS NULL
GROUP BY 1
]]></oils_persist:source_definition>
CASE
WHEN (
((fine_interval >= '1 day' AND due_date < 'today') OR (fine_interval < '1 day' AND due_date < 'now'))
- AND (stop_fines IS NULL OR stop_fines NOT IN ('LOST','CLAIMSRETURNED','LONGOVERDUE'))
+ AND (stop_fines IS NULL OR stop_fines NOT IN ('LOST','CLAIMSRETURNED','LONGOVERDUE') OR (stop_fines IN ('LONGOVERDUE') AND ID NOT IN(SELECT xact FROM money.billing WHERE xact=acirc.id)))
) THEN id::TEXT
ELSE '0'
END
STRING_AGG( CASE WHEN (xact_finish IS NULL AND stop_fines = 'LOST') THEN id::TEXT ELSE '0' END,',') AS lost,
STRING_AGG( CASE WHEN stop_fines = 'CLAIMSRETURNED' THEN id::TEXT ELSE '0' END,',') AS claims_returned,
- STRING_AGG( CASE WHEN (xact_finish IS NULL AND stop_fines = 'LONGOVERDUE') THEN id::TEXT ELSE '0' END,',') AS long_overdue
- FROM action.circulation
+ STRING_AGG( CASE WHEN (xact_finish IS NULL AND stop_fines = 'LONGOVERDUE' AND ID IN(SELECT xact FROM money.billing WHERE xact=acirc.id)) THEN id::TEXT ELSE '0' END,',') AS long_overdue
+ FROM action.circulation acirc
WHERE checkin_time IS NULL
GROUP BY 1
]]></oils_persist:source_definition>
->run($auth => $user_id);
return $out if (defined($U->event_code($out)));
- $out->{"total_out"} = reduce { $a + $out->{$b} } 0, qw/out overdue/;
+ $out->{"total_out"} = reduce { $a + $out->{$b} } 0, qw/out overdue long_overdue/;
my $unread_msgs = $e->search_actor_usr_message([
{usr => $user_id, read_date => undef, deleted => 'f'},
$e, $copy_id,
perm => 'SET_CIRC_LOST',
status => OILS_COPY_STATUS_LOST,
- alt_status => 16, #Long Overdue,
+ alt_status => OILS_COPY_STATUS_LONG_OVERDUE,
ous_proc_fee => OILS_SETTING_LOST_PROCESSING_FEE,
ous_void_od => OILS_SETTING_VOID_OVERDUE_ON_LOST,
bill_type => 3,
return $class->set_item_lost_or_lod(
$e, $copy_id,
perm => 'SET_CIRC_LONG_OVERDUE',
- status => 16, # Long Overdue
+ status => OILS_COPY_STATUS_LONG_OVERDUE,
alt_status => OILS_COPY_STATUS_LOST,
- ous_proc_fee => 'circ.longoverdue_materials_processing_fee',
- ous_void_od => 'circ.void_overdue_on_longoverdue',
+ ous_proc_fee => OILS_SETTING_LONG_OVERDUE_PROCESSING_FEE,
+ ous_void_od => OILS_SETTING_VOID_OVERDUE_ON_LONG_OVERDUE,
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'
+ stop_fines => OILS_STOP_FINES_LONGOVERDUE,
+ at_hook => 'longoverdue',
+ ous_assess_billing => OILS_SETTING_LONG_OVERDUE_ASSESS_BILLING
);
}
$owning_lib, $args{ous_proc_fee}, $e) || 0;
my $void_overdue = $U->ou_ancestor_setting_value(
$owning_lib, $args{ous_void_od}, $e) || 0;
+ my $lod_assess_billing = $U->ou_ancestor_setting_value(
+ $owning_lib, $args{ous_assess_billing}, $e);
+ $lod_assess_billing = 1 unless defined $lod_assess_billing;
# ---------------------------------------------------------------------
- # move the copy into LOST status
+ # move the copy into LOST/LONGOVERDUE status
$copy->status($args{status});
$copy->editor($e->requestor->id);
$copy->edit_date('now');
$e->update_asset_copy($copy) or return $e->die_event;
- my $price = $U->get_copy_price($e, $copy, $copy->call_number);
+ # ---------------------------------------------------------------------
+ # Assess billing only when proceeding as "Lost"
+ # or if this is lod and circ.longoverdue.assess_billing is true *or null
- if( $price > 0 ) {
- my $evt = OpenILS::Application::Circ::CircCommon->create_bill($e,
- $price, $args{bill_type}, $args{bill_note}, $circ->id);
- return $evt if $evt;
- }
+ if( !( ($args{status} == OILS_COPY_STATUS_LONG_OVERDUE) && !$lod_assess_billing) ) {
- # ---------------------------------------------------------------------
- # if there is a processing fee, charge that too
- if( $proc_fee > 0 ) {
- 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;
+ my $price = $U->get_copy_price($e, $copy, $copy->call_number);
+
+ if( $price > 0 ) {
+ 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, $args{bill_fee_type}, $args{bill_fee_note}, $circ->id);
+ return $evt if $evt;
+ }
}
# ---------------------------------------------------------------------
- # mark the circ as lost and stop the fines
+ # mark the circ as lost/longoverdue and stop the fines
$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;
- # ---------------------------------------------------------------------
- # zero out overdue fines on this circ if configured
- if( $void_overdue ) {
- my $evt = OpenILS::Application::Circ::CircCommon->void_or_zero_overdues($e, $circ, {force_zero => 1, note => "System: OVERDUE REVERSED for " . $args{bill_note} . " Processing"});
- return $evt if $evt;
+ if( !( ($args{status} == OILS_COPY_STATUS_LONG_OVERDUE) && !$lod_assess_billing) ) {
+ # ---------------------------------------------------------------------
+ # zero out overdue fines on this circ if configured
+ if( $void_overdue ) {
+ my $evt = OpenILS::Application::Circ::CircCommon->void_or_zero_overdues($e, $circ, {force_zero => 1, note => "System: OVERDUE REVERSED for " . $args{bill_note} . " Processing"});
+ return $evt if $evt;
+ }
}
-
my $evt = OpenILS::Application::Circ::CircCommon->reopen_xact($e, $circ->id);
return $evt if $evt;
my $sql = <<" SQL";
SELECT $contents
- FROM $c_t
- WHERE stop_fines IS NULL
+ FROM $c_t acirc
+ WHERE
+ (
+ (stop_fines IS NULL)
+ OR
+ (stop_fines='LONGOVERDUE' AND
+ COALESCE (
+ (SELECT value::BOOLEAN FROM
+ actor.org_unit_ancestor_setting
+ ('circ.longoverdue.continue_overdue_billing',acirc.circ_lib)
+ ),FALSE
+ )
+ )
+ )
$fines_filter
AND due_date < ( CURRENT_TIMESTAMP - grace_period )
AND fine_interval < ?::INTERVAL
# Settings
# ---------------------------------------------------------------------
econst OILS_SETTING_LOST_PROCESSING_FEE => 'circ.lost_materials_processing_fee';
+econst OILS_SETTING_LONG_OVERDUE_PROCESSING_FEE => 'circ.longoverdue_materials_processing_fee';
econst OILS_SETTING_DEF_ITEM_PRICE => 'cat.default_item_price';
econst OILS_SETTING_MIN_ITEM_PRICE => 'circ.min_item_price';
econst OILS_SETTING_MAX_ITEM_PRICE => 'circ.max_item_price';
econst OILS_SETTING_ORG_BOUNCED_EMAIL => 'org.bounced_emails';
econst OILS_SETTING_CHARGE_LOST_ON_ZERO => 'circ.charge_lost_on_zero';
econst OILS_SETTING_VOID_OVERDUE_ON_LOST => 'circ.void_overdue_on_lost';
+econst OILS_SETTING_VOID_OVERDUE_ON_LONG_OVERDUE => 'circ.void_overdue_on_longoverdue';
econst OILS_SETTING_HOLD_SOFT_STALL => 'circ.hold_stalling.soft';
econst OILS_SETTING_HOLD_HARD_STALL => 'circ.hold_stalling.hard';
econst OILS_SETTING_HOLD_SOFT_BOUNDARY => 'circ.hold_boundary.soft';
econst OILS_SETTING_BLOCK_HOLD_FOR_EXPIRED_PATRON => 'circ.holds.expired_patron_block';
econst OILS_SETTING_GENERATE_OVERDUE_ON_LOST_RETURN => 'circ.lost.generate_overdue_on_checkin';
econst OILS_SETTING_MAX_DUPLICATE_HOLDS => 'circ.holds.max_duplicate_holds';
+econst OILS_SETTING_LONG_OVERDUE_ASSESS_BILLING => 'circ.longoverdue.assess_billing';
checkin_time => undef,
'-or' => [
{stop_fines => undef},
- {stop_fines => {'not in' => ['LOST','CLAIMSRETURNED','LONGOVERDUE']}}
+ {stop_fines => {'not in' => ['LOST','CLAIMSRETURNED']}}
],
}
},
'circ.max_accept_return_of_longoverdue',
'coust',
'description'
+ )
+), (
+ 'circ.longoverdue.assess_billing',
+ 'finance', 'bool',
+ oils_i18n_gettext(
+ 'circ.longoverdue.assess_billing',
+ 'Assess Billing When Marked Long-Overdue',
+ 'coust',
+ 'label'
+ ),
+ oils_i18n_gettext(
+ 'circ.longoverdue.assess_billing',
+ 'When an item is marked long overdue a bill for the item will be ' ||
+ 'assesed unless this setting is false. The default is true. If false ' ||
+ 'void overdue setting will be ignored and processing fee will be ignored',
+ 'coust',
+ 'description'
+ )
+), (
+ 'circ.longoverdue.continue_overdue_billing',
+ 'finance', 'bool',
+ oils_i18n_gettext(
+ 'circ.longoverdue.continue_overdue_billing',
+ 'Continue Overdue Billing When Marked Long-Overdue',
+ 'coust',
+ 'label'
+ ),
+ oils_i18n_gettext(
+ 'circ.longoverdue.continue_overdue_billing',
+ 'When an item is marked long overdue, overdues are halted. ' ||
+ 'A setting of true here will allow the overdues to continue ' ||
+ 'until another condition is met.',
+ 'coust',
+ 'description'
)
+
);
-- mark long-overdue reactor
--- /dev/null
+BEGIN;
+
+SELECT evergreen.upgrade_deps_block_check('XXXX', :eg_version);
+
+INSERT INTO config.org_unit_setting_type ( name, grp, label, description, datatype ) VALUES (
+ 'circ.longoverdue.assess_billing',
+ 'finance',
+ oils_i18n_gettext(
+ 'circ.longoverdue.assess_billing',
+ 'Assess Billing When Marked Long-Overdue',
+ 'coust',
+ 'label'
+ ),
+ oils_i18n_gettext(
+ 'circ.longoverdue.assess_billing',
+ 'When an item is marked long overdue, a bill for the item will be ' ||
+ 'assessed unless this setting is false. The default is true. If false, ' ||
+ '"Void Overdue Fines When Items are Marked Long-Overdue" and "Long-Overdue'||
+ ' Materials Processing Fee" settings will be ignored.',
+ 'coust',
+ 'description'
+ ), 'bool'
+)
+;
+
+INSERT INTO config.org_unit_setting_type ( name, grp, label, description, datatype ) VALUES (
+ 'circ.longoverdue.continue_overdue_billing',
+ 'finance',
+ oils_i18n_gettext(
+ 'circ.longoverdue.continue_overdue_billing',
+ 'Continue Overdue Billing When Marked Long-Overdue',
+ 'coust',
+ 'label'
+ ),
+ oils_i18n_gettext(
+ 'circ.longoverdue.continue_overdue_billing',
+ 'When an item is marked long overdue, overdues are halted. ' ||
+ 'A setting of true here will allow the overdues to continue ' ||
+ 'until another condition is met.',
+ 'coust',
+ 'description'
+ ), 'bool'
+ )
+ ;
+
+
+
+
+COMMIT;
--- /dev/null
+*New Library Setting*
+**Finances: Assess Billing When Marked Long-Overdue - When an item is marked long overdue a bill for the item will be assesed unless this setting is false. The default is true. If false, void overdue setting will be ignored and processing fee will be ignored
+**Finances: Continue Overdue Billing When Marked Long-Overdue - When an item is marked long overdue, overdues are halted. A setting of true here will allow the overdues to continue until another condition is met.
automatically through a Notification/Action Trigger. When the item is marked
long overdue, several actions will take place:
-. The item will go into the status of “Long Overdue”
+. The item will go into the status of “Long Overdue”
. The item will be moved to the “Lost, Claimed Returned, Long Overdue, Has
Unpaid Billings” section of the Items Out screen in the patron’s account
Optionally the patron can be billed for the item price, a long overdue
processing fee, and any overdue fines can be voided from the account. Patrons
can also be sent a notification that the item was marked long overdue.
-
+
image::media/long_overdue1.jpg[Patron Account-Long Overdue]
other than its home library, a library setting controls whether the item can
immediately fill a hold or circulate, or if it needs to be sent to its home
library for processing.
-
+
image::media/long_overdue2.jpg[Long Overdue Checkin]
-
+
*Notification/Action Triggers*
Evergreen has two sample Notification/Action Triggers that are related to
** 6 Month Long Overdue Notice—will send patron notification that an item has
been marked long overdue on their account
-*Library Settings*
+*Library Settings*
The following Library Settings enable you to set preferences related to long
overdue items:
* *Finances: Void Overdue Fines When Items are Marked Long-Overdue*
+* *Finances: Assess Billing When Marked Long-Overdue* -Optionally skip billing price of item
+
+* *Finances: Continue Overdue Billing When Marked Long-Overdue*
+
*Permissions to use this Feature*
The following permissions are related to this feature:
* UPDATE_COPY_ALERT_TYPE
* UPDATE_COPY_ALERT_SUPPRESS
* UPDATE_COPY_ALERT
-