LP1183964: Payment Limit Options
authorJason Boyer <jboyer@library.in.gov>
Fri, 13 May 2016 16:51:07 +0000 (12:51 -0400)
committerMike Rylander <mrylander@gmail.com>
Tue, 9 Aug 2016 16:33:34 +0000 (12:33 -0400)
Add support for 2 new OU settings, a payment warning
amount (try to pay more than this and you're required
to confirm it) and a hard limit where no payment larger
will be accepted. Support is also added to both the XUL
client and webstaff client.

Signed-off-by: Jason Boyer <jboyer@library.in.gov>
Signed-off-by: Jeanette Lundgren <jlundgren@cwmars.org>
Signed-off-by: Mike Rylander <mrylander@gmail.com>

Open-ILS/src/sql/Pg/950.data.seed-values.sql
Open-ILS/src/sql/Pg/upgrade/XXXX_lp1183964_payment_limit.sql [new file with mode: 0644]
Open-ILS/src/templates/staff/circ/patron/index.tt2
Open-ILS/web/js/ui/default/staff/circ/patron/bills.js
Open-ILS/xul/staff_client/server/locale/en-US/patron.properties
Open-ILS/xul/staff_client/server/patron/bill2.js
docs/RELEASE_NOTES_NEXT/Circulation/limit_payment_amounts_accepted.txt [new file with mode: 0644]

index 7cda842..46825ea 100644 (file)
@@ -5078,6 +5078,26 @@ INSERT into config.org_unit_setting_type
         'Amount of time after which no negative balances (refunds) are allowed on bills for lost/long overdue materials. The "Prohibit negative balance on bills for lost materials" setting must also be set to "true".',
         'coust', 'description'),
     'interval', null)
+,(  'ui.circ.billing.amount_limit', 'gui',
+    oils_i18n_gettext(
+      'ui.circ.billing.amount_limit',
+      'Maximum payment amount allowed.',
+      'coust', 'label'),
+    oils_i18n_gettext(
+      'ui.circ.billing.amount_limit',
+      'The payment amount in the Patron Bills interface may not exceed the value of this setting.',
+      'coust', 'description'),
+    'currency',null)
+,(  'ui.circ.billing.amount_warn', 'gui',
+    oils_i18n_gettext(
+      'ui.circ.billing.amount_warn',
+      'Payment amount threshold for Are You Sure? dialog.',
+      'coust', 'label'),
+    oils_i18n_gettext(
+      'ui.circ.billing.amount_warn',
+      'In the Patron Bills interface, a payment attempt will warn if the amount exceeds the value of this setting.',
+      'coust', 'description'),
+    'currency', null)
 ;
 
 UPDATE config.org_unit_setting_type
diff --git a/Open-ILS/src/sql/Pg/upgrade/XXXX_lp1183964_payment_limit.sql b/Open-ILS/src/sql/Pg/upgrade/XXXX_lp1183964_payment_limit.sql
new file mode 100644 (file)
index 0000000..d48593e
--- /dev/null
@@ -0,0 +1,33 @@
+BEGIN;
+
+SELECT evergreen.upgrade_deps_block_check('XXXX', :eg_version);
+
+INSERT INTO config.org_unit_setting_type ( name, grp, label, description, datatype )
+    VALUES (
+        'ui.circ.billing.amount_limit', 'gui',
+        oils_i18n_gettext(
+            'ui.circ.billing.amount_limit',
+            'Maximum payment amount allowed.',
+            'coust', 'label'),
+        oils_i18n_gettext(
+            'ui.circ.billing.amount_limit',
+            'The payment amount in the Patron Bills interface may not exceed the value of this setting.',
+            'coust', 'description'),
+        'currency'
+    );
+
+INSERT INTO config.org_unit_setting_type ( name, grp, label, description, datatype )
+    VALUES (
+        'ui.circ.billing.amount_warn', 'gui',
+        oils_i18n_gettext(
+            'ui.circ.billing.amount_warn',
+            'Payment amount threshold for Are You Sure? dialog.',
+            'coust', 'label'),
+        oils_i18n_gettext(
+            'ui.circ.billing.amount_warn',
+            'In the Patron Bills interface, a payment attempt will warn if the amount exceeds the value of this setting.',
+            'coust', 'description'),
+        'currency'
+    );
+
+COMMIT;
index 07c967e..cc3ee09 100644 (file)
@@ -46,6 +46,9 @@ angular.module('egCoreMod').run(['egStrings', function(s) {
   s.CHECK_IN_CONFIRM = "[% l('Check In Items?') %]";
   s.REG_INVALID_FIELDS = 
     "[% l('Please enter valid values for all required fields.') %]"
+  s.PAYMENT_WARN_AMOUNT = "[% l('Are you sure you want to apply a payment of $[_1]?', '{{payment_amount}}') %]";
+  s.PAYMENT_WARN_AMOUNT_TITLE = "[% l('Verify Payment Amount') %]";
+  s.PAYMENT_OVER_MAX = "[% l('Payments over $[_1] are denied by policy.', '{{max_amount}}') %]";
 }]);
 </script>
 
index 0c366d8..c9b6c44 100644 (file)
@@ -13,7 +13,7 @@ function($q , egCore , patronSvc) {
     service.fetchBillSettings = function() {
         if (service.settings) return $q.when(service.settings);
         return egCore.org.settings(
-            ['ui.circ.billing.uncheck_bills_and_unfocus_payment_box']
+            ['ui.circ.billing.uncheck_bills_and_unfocus_payment_box','ui.circ.billing.amount_warn','ui.circ.billing.amount_limit']
         ).then(function(s) {return service.settings = s});
     }
 
@@ -112,9 +112,11 @@ function($q , egCore , patronSvc) {
  */
 .controller('PatronBillsCtrl',
        ['$scope','$q','$routeParams','egCore','egConfirmDialog','$location',
-        'egGridDataProvider','billSvc','patronSvc','egPromptDialog', 'egBilling',
+        'egGridDataProvider','billSvc','patronSvc','egPromptDialog', 'egAlertDialog',
+        'egBilling',
 function($scope , $q , $routeParams , egCore , egConfirmDialog , $location,
-         egGridDataProvider , billSvc , patronSvc , egPromptDialog, egBilling) {
+         egGridDataProvider , billSvc , patronSvc , egPromptDialog, egAlertDialog,
+         egBilling) {
 
     $scope.initTab('bills', $routeParams.id);
     billSvc.userId = $routeParams.id;
@@ -128,6 +130,9 @@ function($scope , $q , $routeParams , egCore , egConfirmDialog , $location,
     $scope.annotate_payment = false;
     $scope.receipt_count = 1;
     $scope.receipt_on_pay = false;
+    $scope.warn_amount = 1000;
+    $scope.max_amount = 100000;
+    $scope.amount_verified = false;
 
     // pre-define list-returning funcs in case we access them
     // before the grid instantiates
@@ -376,6 +381,12 @@ function($scope , $q , $routeParams , egCore , egConfirmDialog , $location,
             // arrive, manually de-select everything.
             $scope.gridControls.selectItems([]);
         }
+        if (s['ui.circ.billing.amount_warn']) {
+            $scope.warn_amount = Number(s['ui.circ.billing.amount_warn']);
+        }
+        if (s['ui.circ.billing.amount_limit']) {
+            $scope.max_amount = Number(s['ui.circ.billing.amount_limit']);
+        }
     });
 
     $scope.gridControls.allItemsRetrieved = function() {
@@ -424,6 +435,37 @@ function($scope , $q , $routeParams , egCore , egConfirmDialog , $location,
     }
 
     $scope.applyPayment = function() {
+
+        if ($scope.payment_amount > $scope.max_amount ) {
+            egAlertDialog.open(
+                egCore.strings.PAYMENT_OVER_MAX,
+                {   max_amount : ''+$scope.max_amount,
+                    ok : function() {
+                        $scope.payment_amount = 0;
+                    }
+                }
+            );
+            return;
+        }
+
+        if (($scope.payment_amount > $scope.warn_amount) && ($scope.amount_verified == false)) {
+            egConfirmDialog.open(
+                egCore.strings.PAYMENT_WARN_AMOUNT_TITLE, egCore.strings.PAYMENT_WARN_AMOUNT,
+                {   payment_amount : ''+$scope.payment_amount,
+                    ok : function() {
+                        $scope.amount_verfied = true;
+                        $scope.applyPayment();
+                    },
+                    cancel : function() {
+                        $scope.payment_amount = 0;
+                    }
+                }
+            );
+            return;
+        }
+
+        $scope.amount_verfied = false;
+
         if ($scope.annotate_payment) {
             egPromptDialog.open(
                 egCore.strings.ANNOTATE_PAYMENT_MSG, '',
index 29f8c38..99c92b8 100644 (file)
@@ -70,6 +70,9 @@ staff.patron.bills.pay.annotate_payment.title=Annotate Payment
 staff.patron.bills.pay.refund_exceeds_desk_payment=%1$s\n\nAnother way to "zero" this transaction is to use Add Billing and add a miscellaneous bill to counter the negative balance.
 staff.patron.bills.pay.invalid_user_xact_id=%1$s\n\nThis patron data is stale.  Refreshing patron data.  You should re-attempt the payment.
 staff.patron.bills.pay.payment_failed=Bill payment likely failed
+staff.patron.bills.pay.over_warn_limit.title=Verify Payment Amount
+staff.patron.bills.pay.over_warn_limit=Are you sure you want to apply a payment of $%1$s?
+staff.patron.bills.pay.over_limit=Payments over $%1$s are denied by policy.
 staff.patron.bills.info_box.label_value.reservation=Reservation
 # 1 - Resource Barcode  2 - Resource Type Name
 staff.patron.bills.info_box.value_format.reservation=%1$s : %2$s
index 8f0c19b..8e7764b 100644 (file)
@@ -155,6 +155,7 @@ function event_listeners() {
             'keypress',
             function(ev) {
                 if (! (ev.keyCode == 13 /* enter */ || ev.keyCode == 77 /* mac enter */) ) { return; }
+                if (!verify_amount()) { return; }
                 distribute_payment();
                 $('apply_payment_btn').focus();
             },
@@ -213,8 +214,10 @@ function event_listeners() {
             function(ev) {
                 try {
                     $('apply_payment_btn').disabled = true;
-                    apply_payment();
-                    tally_all();
+                    if (verify_amount()) {
+                        apply_payment();
+                        tally_all();
+                    }
                     $('apply_payment_btn').disabled = false;
                 } catch(E) {
                     alert('Error in bill2.js, apply_payment_btn: ' + E);
@@ -858,6 +861,40 @@ function distribute_payment() {
     }
 }
 
+function verify_amount() {
+
+    try {
+        var amt_warn = Number(g.data.hash.aous['ui.circ.billing.amount_warn']) || 1000;
+        var amt_limit = Number(g.data.hash.aous['ui.circ.billing.amount_limit']) || 100000;
+        var box = $('payment');
+        var amt = Number(box.value);
+
+        if (amt <= amt_warn) { return true;}
+
+        if (amt > amt_limit) {
+            alert($("patronStrings").getFormattedString('staff.patron.bills.pay.over_limit', [amt_limit]));
+        } else {
+            var r = g.error.yns_alert(
+                    $('patronStrings').getFormattedString('staff.patron.bills.pay.over_warn_limit', [amt]),
+                    $('patronStrings').getString('staff.patron.bills.pay.over_warn_limit.title'),
+                    $('commonStrings').getString('common.yes'),
+                    $('commonStrings').getString('common.no'),
+                    null
+                );
+            if (r == 0) { return true; }
+        }
+
+        box.value = ''; box.select(); box.focus();
+        distribute_payment();
+        return false;
+
+    } catch (e) {
+      return false;
+    }
+
+}
+
+
 function apply_payment() {
     try {
         var payment_blob = {};
diff --git a/docs/RELEASE_NOTES_NEXT/Circulation/limit_payment_amounts_accepted.txt b/docs/RELEASE_NOTES_NEXT/Circulation/limit_payment_amounts_accepted.txt
new file mode 100644 (file)
index 0000000..4b8328f
--- /dev/null
@@ -0,0 +1,16 @@
+Set Per-OU Limits on Allowed Payment Amounts
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+Two new OU Settings have been added to prevent clerks
+from accidentally clearing all patron bills by scanning
+a barcode into the Payment Amount field, or accidentally
+entering the amount without a decimal point (such as you
+would when using a cash register).
+
+The first setting is the amount above which staff will
+be asked if they're sure they want to apply the payment,
+the second is the maximum amount of money that can be
+accepted through the staff client.
+
+These settings only effect the staff client, not credit
+cards accepted through the OPAC, or direct API calls
+from third party tools.