LP1331174_Long_Overdue_processing_needs_org_unit_settings
authorblake <blake@mobiusconsortium.org>
Tue, 12 Feb 2019 15:34:45 +0000 (09:34 -0600)
committerblake <blake@mobiusconsortium.org>
Tue, 12 Feb 2019 15:34:45 +0000 (09:34 -0600)
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>
Open-ILS/examples/fm_IDL.xml
Open-ILS/src/perlmods/lib/OpenILS/Application/Actor.pm
Open-ILS/src/perlmods/lib/OpenILS/Application/Cat/AssetCommon.pm
Open-ILS/src/perlmods/lib/OpenILS/Application/Storage/Publisher/action.pm
Open-ILS/src/perlmods/lib/OpenILS/Const.pm
Open-ILS/src/perlmods/lib/OpenILS/WWW/EGCatLoader/Account.pm
Open-ILS/src/sql/Pg/950.data.seed-values.sql
Open-ILS/src/sql/Pg/upgrade/XXXX.data.long-overdue-asses-fines-library-setting.sql [new file with mode: 0644]
docs/RELEASE_NOTES_NEXT/Circulation/lod_new_lib_settings.txt [new file with mode: 0644]
docs/circulation/circulating_items.adoc

index b8d0eff..de89389 100644 (file)
@@ -4538,7 +4538,7 @@ SELECT  usr,
             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
@@ -4546,8 +4546,8 @@ SELECT  usr,
 
         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>
@@ -4580,7 +4580,7 @@ SELECT  usr,
             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
@@ -4588,8 +4588,8 @@ SELECT  usr,
 
         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>
index 219f611..917ac3d 100644 (file)
@@ -1876,7 +1876,7 @@ sub user_opac_vitals {
         ->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'},
index f9f60dc..0256eb3 100644 (file)
@@ -807,7 +807,7 @@ sub set_item_lost {
         $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,
@@ -826,17 +826,18 @@ sub set_item_long_overdue {
     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
     );
 }
 
@@ -869,43 +870,54 @@ sub set_item_lost_or_lod {
         $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;
 
index 872b78d..d3625f8 100644 (file)
@@ -169,8 +169,20 @@ sub overdue_circs {
 
     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
index 7c5fb7b..059b42a 100644 (file)
@@ -77,12 +77,14 @@ econst OILS_UNLIMITED_CIRC_DURATION   => 'unlimited';
 # 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';
@@ -97,6 +99,7 @@ econst OILS_SETTING_LOST_IMMEDIATELY_AVAILABLE          => 'circ.lost_immediatel
 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';
 
 
 
index 19e8fbc..2d4e603 100644 (file)
@@ -1557,7 +1557,7 @@ sub fetch_user_circs {
                     checkin_time => undef,
                     '-or' => [
                         {stop_fines => undef},
-                        {stop_fines => {'not in' => ['LOST','CLAIMSRETURNED','LONGOVERDUE']}}
+                        {stop_fines => {'not in' => ['LOST','CLAIMSRETURNED']}}
                     ],
                 }
             },
index 1fe0bb6..736dff7 100644 (file)
@@ -16174,7 +16174,42 @@ INSERT INTO config.org_unit_setting_type
             '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
diff --git a/Open-ILS/src/sql/Pg/upgrade/XXXX.data.long-overdue-asses-fines-library-setting.sql b/Open-ILS/src/sql/Pg/upgrade/XXXX.data.long-overdue-asses-fines-library-setting.sql
new file mode 100644 (file)
index 0000000..b386395
--- /dev/null
@@ -0,0 +1,49 @@
+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;
diff --git a/docs/RELEASE_NOTES_NEXT/Circulation/lod_new_lib_settings.txt b/docs/RELEASE_NOTES_NEXT/Circulation/lod_new_lib_settings.txt
new file mode 100644 (file)
index 0000000..1631283
--- /dev/null
@@ -0,0 +1,3 @@
+*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.
index 24059ea..521d489 100644 (file)
@@ -347,7 +347,7 @@ mark the item long overdue in the borrowing patron’s account. This will be don
 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
@@ -357,7 +357,7 @@ 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]
 
 
@@ -371,9 +371,9 @@ be reinstated on the patron’s account.  If the item is checked in at a library
 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
@@ -389,7 +389,7 @@ configured period of time
 ** 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:
@@ -423,6 +423,10 @@ lost copy on the patron record when it is paid
 
 * *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:
@@ -700,4 +704,3 @@ The following permissions affect access to copy alert administration and use:
 * UPDATE_COPY_ALERT_TYPE
 * UPDATE_COPY_ALERT_SUPPRESS
 * UPDATE_COPY_ALERT
-