This wires up most of the new billing interface, which has aesthetic and internal...
authorphasefx <phasefx@dcc99617-32d9-48b4-a31d-7c20da2025e4>
Tue, 8 Dec 2009 14:23:29 +0000 (14:23 +0000)
committerphasefx <phasefx@dcc99617-32d9-48b4-a31d-7c20da2025e4>
Tue, 8 Dec 2009 14:23:29 +0000 (14:23 +0000)
know if we lost anything.

Also some drive-by edits to other files:
  lighter-weight refresh callback for billing interface in display.js
  tweaks to logging levels in error.js
  default non-maximized window size for the main menu in menu_frame.xul
  some utility functions (addProperty, removeProperty) in widgets.js
  an attempt to workaround the "parent window loses focus or gets lowered behind another application after a child modal window closes" issue in window.js
  made the patron.util.retrieve_au_via_id utility method .authoritative
  tweaked the CSS for currently selected rows in lists/trees
  whitespace/indentation in bill_history.js

TODO:
  Wire up Refund and Show in Catalog menu options (though refunds should be working via the checkbox column).
  Provide an alternate bill history view which centers around payments received, rather than the billable transactions

WISHLIST:
  Library filtering for transactions.  The interface is currently using open-ils.actor.user.transaction.fleshed.retrieve for fleshing rows; if we
could get it to return a generalized location field regardless of the transaction type (circ, grocery, booking, etc.), then this'll be much easier to
do in the client.

git-svn-id: svn://svn.open-ils.org/ILS/trunk@15097 dcc99617-32d9-48b4-a31d-7c20da2025e4

14 files changed:
Open-ILS/web/opac/locale/en-US/lang.dtd
Open-ILS/xul/staff_client/chrome/content/main/constants.js
Open-ILS/xul/staff_client/chrome/content/main/menu_frame.xul
Open-ILS/xul/staff_client/chrome/content/util/error.js
Open-ILS/xul/staff_client/chrome/content/util/widgets.js
Open-ILS/xul/staff_client/chrome/content/util/window.js
Open-ILS/xul/staff_client/server/locale/en-US/patron.properties
Open-ILS/xul/staff_client/server/patron/bill2.js
Open-ILS/xul/staff_client/server/patron/bill2.xul
Open-ILS/xul/staff_client/server/patron/bill_history.js
Open-ILS/xul/staff_client/server/patron/display.js
Open-ILS/xul/staff_client/server/patron/util.js
Open-ILS/xul/staff_client/server/skin/circ.css
Open-ILS/xul/staff_client/server/skin/global.css

index 6108fba..7c8bf63 100644 (file)
 <!ENTITY staff.patron.bill_interface.selected_billed.label "Checked Billed:">
 <!ENTITY staff.patron.bill_interface.selected_paid.label "Checked Paid:">
 <!ENTITY staff.patron.bill_interface.voided_this_session.label "Voided this session:">
+<!ENTITY staff.patron.bill_interface.change_due_upon_payment.label "Change Due Upon Payment:">
+<!ENTITY staff.patron.bill_interface.pending.label "Pending:">
+<!ENTITY staff.patron.bill_interface.total.label "Total:">
+<!ENTITY staff.patron.bill_interface.checked.label "Checked:">
+<!ENTITY staff.patron.bill_interface.payment.label "Payment">
+<!ENTITY staff.patron.bill_interface.change.label "Change">
+<!ENTITY staff.patron.bill_interface.owed.label "Owed">
+<!ENTITY staff.patron.bill_interface.billed.label "Billed">
+<!ENTITY staff.patron.bill_interface.paid.label "Paid">
 
 <!ENTITY staff.patron.bills_overlay.still_checked_out.label "Red Items are still Checked Out">
 <!ENTITY staff.patron.bills_overlay.uncheck_all.label "Uncheck All">
+<!ENTITY staff.patron.bills_overlay.uncheck_all.accesskey "U">
 <!ENTITY staff.patron.bills_overlay.check_all.label "Check All">
+<!ENTITY staff.patron.bills_overlay.check_all.accesskey "k">
+<!ENTITY staff.patron.bills_overlay.check_all_refunds.label "Check All Refunds">
+<!ENTITY staff.patron.bills_overlay.check_all_refunds.accesskey "f">
 <!ENTITY staff.patron.bills_overlay.print_bills.label "Print Bills" >
+<!ENTITY staff.patron.bills_overlay.print_bills.accesskey "" >
 <!ENTITY staff.patron.bills_overlay.alternate_view.label "Alternate View">
 <!ENTITY staff.patron.bills_overlay.alternate_view.accesskey "V">
+<!ENTITY staff.patron.bills_overlay.receipt_options.label "Receipt Options">
+<!ENTITY staff.patron.bills_overlay.receipt_options.accesskey "O">
+<!ENTITY staff.patron.bills_overlay.receipt_upon_payment.label "Receipt Upon Payment">
+<!ENTITY staff.patron.bills_overlay.receipt_upon_payment.accesskey "U">
+<!ENTITY staff.patron.bills_overlay.printer_prompt.label "Printer Prompt">
+<!ENTITY staff.patron.bills_overlay.printer_prompt.accesskey "P">
+<!ENTITY staff.patron.bills_overlay.number_of_copies.label "Number of Copies:">
+<!ENTITY staff.patron.bills_overlay.number_of_copies.accesskey "N">
 <!ENTITY staff.patron.bills_overlay.summary.label "Summary">
 <!ENTITY staff.patron.bills_overlay.net_balance.value "Net Balance">
 <!ENTITY staff.patron.bills_overlay.new_balance.value "= New Balance">
index 5687bfa..1d22a87 100644 (file)
@@ -337,7 +337,7 @@ const urls = {
     'XUL_REMOTE_OPAC_WRAPPER' : '/xul/server/cat/opac.xul',
     'XUL_OPAC_WRAPPER' : 'chrome://open_ils_staff_client/content/cat/opac.xul',
     'XUL_PATRON_BARCODE_ENTRY' : '/xul/server/patron/barcode_entry.xul',
-    'XUL_PATRON_BILLS' : '/xul/server/patron/bills.xul',
+    'XUL_PATRON_BILLS' : '/xul/server/patron/bill2.xul',
     'XUL_PATRON_BILL_CC_INFO' : '/xul/server/patron/bill_cc_info.xul',
     'XUL_PATRON_BILL_CHECK_INFO' : '/xul/server/patron/bill_check_info.xul',
     'XUL_PATRON_BILL_DETAILS' : '/xul/server/patron/bill_details.xul',
index cb04409..9b87990 100644 (file)
@@ -29,7 +29,7 @@
 
 <window id="menu_frame_win"
     onload="try { my_init(); font_helper(); persist_helper(); } catch(E) { alert(E); }"
-    orient="vertical" width="800" height="500"
+    orient="vertical" width="1024" height="740"
     sizemode="maximized" oils_persist="width height" title="&staff.main.menu.title;"
     xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
 
index 70f0829..9ab2510 100644 (file)
@@ -57,7 +57,7 @@ util.error.prototype = {
         'D_DEBUG' : { 'debug' : true, 'console' : true }, 
         'D_TRACE' :  { 'debug' : false }, 
         'D_ALERT' : { 'alert' : true, 'debug' : true },
-        'D_WARN' : { 'debug' : false }, 
+        'D_WARN' : { 'debug' : true }, 
         'D_COLUMN_RENDER_ERROR' : { 'debug' : false }, 
         'D_XULRUNNER' : { 'debug' : false }, 
         'D_DECK' : { 'debug' : false },
@@ -116,7 +116,7 @@ util.error.prototype = {
         'D_CACHE' : { 'debug' : false, 'console' : false, 'alert' : false },
         'D_SES' : { 'debug' : true, 'console' : true },
         'D_SES_FUNC' : { 'debug' : false }, 
-        'D_SES_RESULT' : { 'debug' : false }, 
+        'D_SES_RESULT' : { 'debug' : true }, 
         'D_SES_ERROR' : { 'debug' : true, 'console' : true }, 
         'D_SPAWN' : { 'debug' : false }, 
         'D_STRING' : { 'debug' : false },
index 683c6ac..0ef5dd9 100644 (file)
@@ -405,4 +405,47 @@ util.widgets.load_attributes = function (file) {
     }
 }
 
+util.widgets.addProperty = function(e,c) {
+       if(!e || !c) return;
+
+       var prop_class_string = e.getAttribute('properties');
+       var prop_class_array;
+
+       if(prop_class_string)
+               prop_class_array = prop_class_string.split(/\s+/);
+
+       var string_ip = ""; /*strip out nulls*/
+       for (var prop_class in prop_class_array) {
+               if (prop_class_array[prop_class] == c) { return; }
+               if(prop_class_array[prop_class] !=null)
+                       string_ip += prop_class_array[prop_class] + " ";
+       }
+       string_ip += c;
+       e.setAttribute('properties',string_ip);
+}
+
+util.widgets.removeProperty = function(e, c) {
+       if(!e || !c) return;
+
+       var prop_class_string = '';
+
+       var prop_class_array = e.getAttribute('properties');
+       if( prop_class_array )
+               prop_class_array = prop_class_array.split(/\s+/);
+
+       var first = 1;
+       for (var prop_class in prop_class_array) {
+               if (prop_class_array[prop_class] != c) {
+                       if (first == 1) {
+                               prop_class_string = prop_class_array[prop_class];
+                               first = 0;
+                       } else {
+                               prop_class_string = prop_class_string + ' ' +
+                                       prop_class_array[prop_class];
+                       }
+               }
+       }
+       e.setAttribute('properties', prop_class_string);
+}
+
 dump('exiting util/widgets.js\n');
index bce5632..9d80367 100644 (file)
@@ -100,6 +100,7 @@ util.window.prototype = {
             data.init({'via':'stash'});
             var x = data.modal_xulG_stack[key].pop();
             data.stash('modal_xulG_stack');
+            w.focus();
             return x;
         } else {
             if (my_xulG) {
index 99e3957..0286f9d 100644 (file)
@@ -10,6 +10,7 @@ staff.patron.barcode_entry.patron_consent_deny=Deny
 staff.patron.barcode_entry.patron_consent_confirm=Check here to confirm this message
 staff.patron.barcode_entry.patron_display_error=spawning patron display
 staff.patron.barcode_entry.user_perm_display_error=spawning user perm editor
+staff.patron.bill_interface.payment_pending.column_header=Payment Pending
 staff.patron.bill_cc_info.need_cc_number=You must provide a credit card number
 staff.patron.bill_cc_info.need_approval_code=You must provide an approval code or an imprint slip number
 staff.patron.bill_details.my_init.error=bill_details.xul, my_init:
@@ -26,7 +27,6 @@ staff.patron.bill_details.handle_void.confirm_void_billing_yes=Yes
 staff.patron.bill_details.handle_void.confirm_void_billing_no=No
 staff.patron.bill_details.handle_void.confirm_void_billing_confirm_message=Check here to confirm this message
 staff.patron.bill_details.handle_void.voiding_error=Error voiding bills.
-staff.patron.bill_details.handle_void.billings_voided=Billings voided.
 staff.patron.bill_history.retrieve_mbts_for_list.close_win_try_again=Please close this window and try again.
 staff.patron.bill_history.my_init.current_bills=Current Bills
 staff.patron.bill_history.my_init.bill_history=Bill History
@@ -36,6 +36,12 @@ staff.patron.bill_history.handle_add.title=Bill Patron
 staff.patron.bill_history.handle_add.btn_yes=Yes
 staff.patron.bill_history.handle_add.btn_no=No
 staff.patron.bill_history.handle_add.confirm_message=Check here to confirm this message
+staff.patron.bill_history.handle_void.message_plural=Are you sure you would like to void all billings on bills %1$s?
+staff.patron.bill_history.handle_void.message_singular=Are you sure you would like to void all billings on bill %1$s?
+staff.patron.bill_history.handle_void.title=Void All Billings
+staff.patron.bill_history.handle_void.btn_yes=Yes
+staff.patron.bill_history.handle_void.btn_no=No
+staff.patron.bill_history.handle_void.confirm_message=Check here to confirm this message
 staff.patron.bill_history.print_bills.print_error=printing bills
 staff.patron.bills.init_controller.money_summary_label=Money Summary
 staff.patron.bills.bill_payment_amount.credit_amount=Patron only has %1$s in credit.
index 6a7bdfd..9d6e0a7 100644 (file)
@@ -9,9 +9,10 @@ function my_init() {
         JSAN.use('util.network'); g.network = new util.network();
         JSAN.use('util.date');
         JSAN.use('util.money');
+        JSAN.use('util.widgets');
         JSAN.use('patron.util');
         JSAN.use('OpenILS.data'); g.data = new OpenILS.data(); g.data.init({'via':'stash'});
-        //g.data.temp = ''; g.data.stash('temp');
+        g.data.voided_billings = []; g.data.stash('voided_billings');
 
         g.error.sdump('D_TRACE','my_init() for bill2.xul');
 
@@ -27,6 +28,8 @@ function my_init() {
 
         g.patron_id = xul_param('patron_id');
 
+        $('circulating_hint').hidden = true;
+
         init_lists();
 
         retrieve_mbts_for_list();
@@ -46,14 +49,14 @@ function my_init() {
                     try {
                         g.patron = req.getResultObject();
                         if (typeof g.patron.ilsevent != 'undefined') throw(g.patron);
-                        $('credit_forward').setAttribute('value','$' + util.money.sanitize( g.patron.credit_forward_balance() ));
+                        $('credit_forward').setAttribute('value',util.money.sanitize( g.patron.credit_forward_balance() ));
                     } catch(E) {
                         alert('Error in bill2.js, retrieve patron callback: ' + E);
                     }
                 }
             );
         } else {
-            $('credit_forward').setAttribute('value','$' + util.money.sanitize( g.patron.credit_forward_balance() ));
+            $('credit_forward').setAttribute('value',util.money.sanitize( g.patron.credit_forward_balance() ));
         }
 
         default_focus();
@@ -79,9 +82,34 @@ function event_listeners() {
             false
         );
 
+        $('voidall').addEventListener(
+            'command',
+            handle_void_all,
+            false
+        );
+
         $('payment').addEventListener(
             'change',
-            function(ev) { distribute_payment(); },
+            function(ev) {
+                if ($('payment_type').value == 'credit_payment') {
+                    JSAN.use('util.money');
+                    JSAN.use('patron.util'); g.patron = patron.util.retrieve_au_via_id(ses(),g.patron_id);
+                    var proposed = util.money.dollars_float_to_cents_integer(ev.target.value);
+                    var available = util.money.dollars_float_to_cents_integer(g.patron.credit_forward_balance());
+                    if (proposed > available) {
+                        alert($("patronStrings").getFormattedString('staff.patron.bills.bill_payment_amount.credit_amount', [g.patron.credit_forward_balance()]));
+                        ev.target.value = util.money.cents_as_dollars( available );
+                        ev.target.setAttribute('value',ev.target.value);
+                    }
+                }
+                distribute_payment(); 
+            },
+            false
+        );
+
+        $('payment').addEventListener(
+            'focus',
+            function(ev) { ev.target.select(); },
             false
         );
 
@@ -110,6 +138,21 @@ function event_listeners() {
             false
         );
 
+        $('bill_history_btn').addEventListener(
+            'command',
+            function() {
+                xulG.display_window.g.patron.right_deck.reset_iframe( 
+                    urls.XUL_PATRON_BILL_HISTORY,
+                    {},
+                    {
+                        'patron_id' : g.patron_id,
+                        'refresh' : function() { refresh(); }
+                    }
+                );
+            },
+            false
+        );
+
         $('convert_change_to_credit').addEventListener(
             'command',
             function(ev) {
@@ -122,6 +165,18 @@ function event_listeners() {
             false
         );
 
+        $('apply_payment_btn').addEventListener(
+            'command',
+            function(ev) {
+                try {
+                    apply_payment();
+                } catch(E) {
+                    alert('Error in bill2.js, apply_payment_btn: ' + E);
+                }
+            },
+            false
+        );
+
     } catch(E) {
         alert('Error in bill2.js, event_listeners(): ' + E);
     }
@@ -146,14 +201,14 @@ function tally_pending() {
             if (g.check_map[retrieve_ids[i]]) { 
                 var value = util.money.dollars_float_to_cents_integer( row_params.row.my.payment_pending );
                 payment_pending += value;
-                if (value != '0.00') { payments.push( [ retrieve_ids[i], value ] ); }
+                if (value != '0.00') { payments.push( [ retrieve_ids[i], util.money.cents_as_dollars(value) ] ); }
             }
         }
         var change_pending = payment_tendered - payment_pending;
         $('pending_payment').value = util.money.cents_as_dollars( payment_pending );
         $('pending_change').value = util.money.cents_as_dollars( change_pending );
         $('change_due').value = util.money.cents_as_dollars( change_pending );
-        return { 'payments' : payments, 'change' : change_pending };
+        return { 'payments' : payments, 'change' : util.money.cents_as_dollars( change_pending ) };
     } catch(E) {
         alert('Error in bill2.js, tally_pending(): ' + E);
     }
@@ -181,14 +236,32 @@ function tally_selected() {
             selected_paid += tp;
             selected_balance += bo;
         }
-        //$('checked_billed').setAttribute('value', '$' + util.money.cents_as_dollars( selected_billed ) );
-        //$('checked_paid').setAttribute('value', '$' + util.money.cents_as_dollars( selected_paid ) );
-        //$('checked_owed').setAttribute('value', '$' + util.money.cents_as_dollars( selected_balance ) );
+        //$('checked_billed').setAttribute('value', util.money.cents_as_dollars( selected_billed ) );
+        //$('checked_paid').setAttribute('value', util.money.cents_as_dollars( selected_paid ) );
+        //$('checked_owed').setAttribute('value', util.money.cents_as_dollars( selected_balance ) );
     } catch(E) {
         alert('Error in bill2.js, tally_selected(): ' + E);
     }
 }
 
+function tally_voided() {
+    try {
+        JSAN.use('util.money');
+        var voided_total = 0;
+
+        g.data.stash_retrieve();
+
+        for (var i = 0; i < g.data.voided_billings.length; i++) {
+            var billing = g.data.voided_billings[i];
+            var bv = util.money.dollars_float_to_cents_integer( billing.amount() );
+            voided_total += bv;
+        }
+        $('currently_voided').setAttribute('value', util.money.cents_as_dollars( voided_total ) );
+    } catch(E) {
+        alert('Error in bill2.js, tally_voided(): ' + E);
+    }
+}
+
 function tally_all() {
     try {
         JSAN.use('util.money');
@@ -228,15 +301,15 @@ function tally_all() {
                 checked_balance += bo;
             }
         }
-        $('checked_billed').setAttribute('value', '$' + util.money.cents_as_dollars( checked_billed ) );
-        $('checked_paid').setAttribute('value', '$' + util.money.cents_as_dollars( checked_paid ) );
-        $('checked_owed').setAttribute('value', '$' + util.money.cents_as_dollars( checked_balance ) );
-        $('checked_owed2').setAttribute('value', '$' + util.money.cents_as_dollars( checked_balance ) );
-        $('total_billed').setAttribute('value', '$' + util.money.cents_as_dollars( total_billed ) );
-        $('total_paid').setAttribute('value', '$' + util.money.cents_as_dollars( total_paid ) );
-        $('total_owed').setAttribute('value', '$' + util.money.cents_as_dollars( total_balance ) );
-        $('total_owed2').setAttribute('value', '$' + util.money.cents_as_dollars( total_balance ) );
-        $('refunds_owed').setAttribute('value', '$' + util.money.cents_as_dollars( Math.abs( refunds_owed ) ) );
+        $('checked_billed').setAttribute('value', util.money.cents_as_dollars( checked_billed ) );
+        $('checked_paid').setAttribute('value', util.money.cents_as_dollars( checked_paid ) );
+        $('checked_owed').setAttribute('value', util.money.cents_as_dollars( checked_balance ) );
+        $('checked_owed2').setAttribute('value', util.money.cents_as_dollars( checked_balance ) );
+        $('total_billed').setAttribute('value', util.money.cents_as_dollars( total_billed ) );
+        $('total_paid').setAttribute('value', util.money.cents_as_dollars( total_paid ) );
+        $('total_owed').setAttribute('value', util.money.cents_as_dollars( total_balance ) );
+        $('total_owed2').setAttribute('value', util.money.cents_as_dollars( total_balance ) );
+        $('refunds_owed').setAttribute('value', util.money.cents_as_dollars( Math.abs( refunds_owed ) ) );
         // tally_selected();
     } catch(E) {
         alert('Error in bill2.js, tally_all(): ' + E);
@@ -251,6 +324,7 @@ function check_all() {
             row_params.row.my.checked = true;
             g.bill_list.refresh_row(row_params);
         }
+        tally_all();
         distribute_payment();
     } catch(E) {
         alert('Error in bill2.js, check_all(): ' + E);
@@ -266,6 +340,7 @@ function uncheck_all() {
             row_params.row.my.checked = false;
             g.bill_list.refresh_row(row_params);
         }
+        tally_all();
         distribute_payment();
     } catch(E) {
         alert('Error in bill2.js, check_all(): ' + E);
@@ -276,13 +351,14 @@ function uncheck_all() {
 function check_all_refunds() {
     try {
         for (var i in g.bill_map) {
-            g.check_map[i] = true;
             if ( Number( g.bill_map[i].transaction.balance_owed() ) < 0 ) {
+                g.check_map[i] = true;
                 var row_params = g.row_map[i];
                 row_params.row.my.checked = true;
                 g.bill_list.refresh_row(row_params);
             }
         }
+        tally_all();
         distribute_payment();
     } catch(E) {
         alert('Error in bill2.js, check_all_refunds(): ' + E);
@@ -328,7 +404,8 @@ function init_lists() {
         'columns' : 
             [
                 {
-                    'id' : 'select', 'type' : 'checkbox', 'editable' : true, 'label' : '', 'render' : function(my) { return String( my.checked ) == 'true'; }, 
+                    'id' : 'select', 'primary' : true, 'type' : 'checkbox', 'editable' : true, 'label' : '', 'style' : 'min-width: 3em;',
+                    'render' : function(my) { return String( my.checked ) == 'true'; }, 
                 }
             ].concat(
                 patron.util.mbts_columns({
@@ -341,7 +418,9 @@ function init_lists() {
             ).concat( 
                 [
                     {
-                        'id' : 'payment_pending', 'editable' : false, 'label' : 'Payment Pending', 'sort_type' : 'money', 'render' : function(my) { return my.payment_pending || '0.00'; }, 
+                        'id' : 'payment_pending', 'editable' : false, 'sort_type' : 'money', 
+                        'label' : $('patronStrings').getString('staff.patron.bill_interface.payment_pending.column_header'),
+                        'render' : function(my) { return my.payment_pending || '0.00'; }, 
                     }
                 ]
             ))),
@@ -392,6 +471,22 @@ function init_lists() {
             try {
                 var id = params.retrieve_id;
                 var row = params.row;
+
+                function handle_props(row) {
+                    try {
+                        if ( row && row.my && row.my.mbts && Number( row.my.mbts.balance_owed() ) < 0 ) {
+                            util.widgets.addProperty(params.row_node.firstChild,'refundable');
+                        }
+                        if ( row && row.my && row.my.circ && ! row.my.circ.checkin_time() ) {
+                            $('circulating_hint').hidden = false;
+                            util.widgets.addProperty(params.row_node.firstChild,'circulating');
+                        }
+                    } catch(E) {
+                        g.error.sdump('D_WARN','Error setting list properties in bill2.js: ' + E);
+                        alert('Error setting list properties in bill2.js: ' + E);
+                    }
+                }
+
                 if (id) {
                     if (typeof row.my == 'undefined') row.my = {};
                     if (typeof row.my.mbts == 'undefined' ) {
@@ -402,10 +497,10 @@ function init_lists() {
                             row.my.acp = blob.copy;
                             row.my.mvr = blob.record;
                             if (typeof params.on_retrieve == 'function') {
-                                if ( Number( row.my.mbts.balance_owed() ) < 0 ) {
-                                    params.row_node.firstChild.setAttribute('properties','refundable');
+                                if ( row.my.mbts && Number( row.my.mbts.balance_owed() ) < 0 ) {
                                     row.my.checked = false;
                                 }
+                                handle_props(row);
                                 params.on_retrieve(row);
                             };
                             g.bill_map[ id ] = blob;
@@ -413,11 +508,17 @@ function init_lists() {
                             tally_all();
                         } );
                     } else {
-                        if (typeof params.on_retrieve == 'function') { params.on_retrieve(row); }
+                        if (typeof params.on_retrieve == 'function') { 
+                            handle_props(row);
+                            params.on_retrieve(row); 
+                        }
                     }
                 } else {
-                    if (typeof params.on_retrieve == 'function') { params.on_retrieve(row); }
+                    if (typeof params.on_retrieve == 'function') { 
+                        params.on_retrieve(row); 
+                    }
                 }
+
                 return row;
             } catch(E) {
                 alert('Error in bill2.js, retrieve_row(): ' + E);
@@ -430,10 +531,11 @@ function init_lists() {
 }
 
 function handle_add() {
-    if(g.bill_list_selection.length > 1)
+    if(g.bill_list_selection.length > 1) {
         var msg = $("patronStrings").getFormattedString('staff.patron.bill_history.handle_add.message_plural', [g.bill_list_selection]);
-    else
+    } else {
         var msg = $("patronStrings").getFormattedString('staff.patron.bill_history.handle_add.message_singular', [g.bill_list_selection]);
+    }
         
     var r = g.error.yns_alert(msg,
         $("patronStrings").getString('staff.patron.bill_history.handle_add.title'),
@@ -451,13 +553,34 @@ function handle_add() {
                 { 'patron_id' : g.patron_id, 'xact_id' : g.bill_list_selection[i] }
             );
         }
-        g.bill_list.clear();
-        retrieve_mbts_for_list();
-        if (typeof window.refresh == 'function') window.refresh();
+        refresh();
+        if (typeof window.xulG == 'object' && typeof window.xulG.refresh == 'function') window.xulG.refresh();
+    }
+}
+
+function handle_void_all() {
+    if(g.bill_list_selection.length > 1) {
+        var msg = $("patronStrings").getFormattedString('staff.patron.bill_history.handle_void.message_plural', [g.bill_list_selection]);
+    } else {
+        var msg = $("patronStrings").getFormattedString('staff.patron.bill_history.handle_void.message_singular', [g.bill_list_selection]);
+    }
+        
+    var r = g.error.yns_alert(msg,
+        $("patronStrings").getString('staff.patron.bill_history.handle_void.title'),
+        $("patronStrings").getString('staff.patron.bill_history.handle_void.btn_yes'),
+        $("patronStrings").getString('staff.patron.bill_history.handle_void.btn_no'),null,
+        $("patronStrings").getString('staff.patron.bill_history.handle_void.confirm_message'));
+    if (r == 0) {
+        for (var i = 0; i < g.bill_list_selection.length; i++) {
+            void_all_billings( g.bill_list_selection[i] );
+        }
+        refresh();
         if (typeof window.xulG == 'object' && typeof window.xulG.refresh == 'function') window.xulG.refresh();
+        if (typeof window.xulG == 'object' && typeof window.xulG.on_money_change == 'function') window.xulG.on_money_change();
     }
 }
 
+
 function handle_details() {
     JSAN.use('util.window'); var win = new util.window();
     for (var i = 0; i < g.bill_list_selection.length; i++) {
@@ -468,8 +591,8 @@ function handle_details() {
             {
                 'patron_id' : g.patron_id,
                 'mbts_id' : g.bill_list_selection[i],
-                'refresh' : function() { 
-                    if (typeof window.refresh == 'function') window.refresh();
+                'refresh' : function() {
+                    refresh(); 
                     if (typeof window.xulG == 'object' && typeof window.xulG.refresh == 'function') window.xulG.refresh();
                 }, 
             }
@@ -574,15 +697,25 @@ function apply_payment() {
         }
         if ( pay( payment_blob ) ) {
 
-            g.data.voided_billings = []; g.data.stash('voided_billings');
-            g.bill_list.clear();
-            retrieve_mbts_for_list();
-            if (typeof window.refresh == 'function') window.refresh();
+            $('payment').value = ''; $('payment').select(); $('payment').focus();
+            refresh({'clear_voided_summary':true});
             if (typeof window.xulG == 'object' && typeof window.xulG.refresh == 'function') window.xulG.refresh();
+            if (typeof window.xulG == 'object' && typeof window.xulG.on_money_change == 'function') window.xulG.on_money_change();
+            if ( $('payment_type').value == 'credit_payment' || $('convert_change_to_credit').checked ) {
+                JSAN.use('patron.util'); 
+                patron.util.retrieve_au_via_id(ses(),g.patron_id, function(req) {
+                    var au_obj = req.getResultObject();
+                    if (typeof au_obj.ils_event == 'undefined') {
+                        g.patron = au_obj;
+                        $('credit_forward').setAttribute('value',util.money.sanitize( g.patron.credit_forward_balance() ));
+                    }
+                });
+            }
             try {
+                if ( ! $('receipt_upon_payment').hasAttribute('checked') ) { return; } // Skip print attempt
                 var no_print_prompting = g.data.hash.aous['circ.staff_client.do_not_auto_attempt_print'];
                 if (no_print_prompting) {
-                    if (no_print_prompting.indexOf( "Bill Pay" ) > -1) return; // Skip print attempt
+                    if (no_print_prompting.indexOf( "Bill Pay" ) > -1) { return; } // Skip print attempt
                 }
                 netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
                 g.data.stash_retrieve();
@@ -590,12 +723,12 @@ function apply_payment() {
                 JSAN.use('patron.util'); JSAN.use('util.functional');
                 var params = { 
                     'patron' : g.patron,
-                    'lib' : data.hash.aou[ ses('ws_ou') ],
+                    'lib' : g.data.hash.aou[ ses('ws_ou') ],
                     'staff' : ses('staff'),
-                    'header' : data.print_list_templates[template].header,
-                    'line_item' : data.print_list_templates[template].line_item,
-                    'footer' : data.print_list_templates[template].footer,
-                    'type' : data.print_list_templates[template].type,
+                    'header' : g.data.print_list_templates[template].header,
+                    'line_item' : g.data.print_list_templates[template].line_item,
+                    'footer' : g.data.print_list_templates[template].footer,
+                    'type' : g.data.print_list_templates[template].type,
                     'list' : util.functional.map_list(
                         payment_blob.payments,
                         function(o) {
@@ -612,11 +745,11 @@ function apply_payment() {
                     'data' : g.previous_summary
                 };
                 g.error.sdump('D_DEBUG',js2JSON(params));
-                if ($('auto_print').checked) params.no_prompt = true;
+                if (! $('printer_prompt').hasAttribute('checked')) params.no_prompt = true;
                 JSAN.use('util.print'); var print = new util.print();
-                print.tree_list( params );
+                print.tree_list( params ); 
             } catch(E) {
-                g.standard_unexpected_error_alert('bill receipt', E);
+                g.error.standard_unexpected_error_alert('bill receipt', E);
             }
         }
     } catch(E) {
@@ -634,22 +767,21 @@ function pay(payment_blob) {
                 $("patronStrings").getString('staff.patron.bills.pay.annotate_payment.title')
             );
         }
-        previous_summary = {
-            original_balance : obj.controller.view.bill_total_owed.value,
-            voided_balance : obj.controller.view.voided_balance.value,
-            payment_received : obj.controller.view.bill_payment_amount.value,
-            payment_applied : obj.controller.view.bill_payment_applied.value,
-            change_given : obj.controller.view.bill_change_amount.value,
-            credit_given : obj.controller.view.bill_credit_amount.value,
-            new_balance : obj.controller.view.bill_new_balance.value,
-            payment_type : obj.controller.view.payment_type.getAttribute('label'),
+        g.previous_summary = {
+            original_balance : $('total_owed').value,
+            voided_balance : $('currently_voided').value,
+            payment_received : $('payment').value,
+            payment_applied : $('pending_payment').value,
+            change_given : $('convert_change_to_credit').checked ? 0 : $('pending_change').value,
+            credit_given : $('convert_change_to_credit').checked ? $('pending_change').value : 0,
+            new_balance : util.money.cents_as_dollars( 
+                util.money.dollars_float_to_cents_integer( $('total_owed').value ) - 
+                util.money.dollars_float_to_cents_integer( $('pending_payment').value )
+            ),
+            payment_type : $('payment_type').getAttribute('label'),
             note : payment_blob.note
         }
-        var robj = g.network.request(
-            api.BILL_PAY.app,    
-            api.BILL_PAY.method,
-            [ ses(), payment_blob ]
-        );
+        var robj = g.network.simple_request( 'BILL_PAY', [ ses(), payment_blob ]);
         if (robj == 1) { return true; } 
         if (typeof robj.ilsevent != 'undefined') {
             switch(Number(robj.ilsevent)) {
@@ -659,9 +791,65 @@ function pay(payment_blob) {
             }
         }
     } catch(E) {
-        obj.error.standard_unexpected_error_alert($("patronStrings").getString('staff.patron.bills.pay.payment_failed'),E);
+        g.error.standard_unexpected_error_alert($("patronStrings").getString('staff.patron.bills.pay.payment_failed'),E);
         return false;
     }
 }
 
+function refresh(params) {
+    try {
+        if (params && params.clear_voided_summary) {
+            g.data.voided_billings = []; g.data.stash('voided_billings');
+        }
+        g.bill_list.clear();
+        retrieve_mbts_for_list();
+        tally_voided();
+        distribute_payment(); 
+    } catch(E) {
+        alert('Error in bill2.js, refresh(): ' + E);
+    }
+}
+
+function void_all_billings(mobts_id) {
+    try {
+        JSAN.use('util.functional');
+        
+        var mb_list = g.network.simple_request( 'FM_MB_RETRIEVE_VIA_MBTS_ID.authoritative', [ ses(), mobts_id ] );
+        if (typeof mb_list.ilsevent != 'undefined') throw(mb_list);
+
+        mb_list = util.functional.filter_list( mb_list, function(o) { return ! get_bool( o.voided() ) });
+
+        if (mb_list.length == 0) { alert($("patronStrings").getString('staff.patron.bills.void_all_billings.all_voided')); return; }
+
+        var sum = 0;
+        for (var i = 0; i < mb_list.length; i++) sum += util.money.dollars_float_to_cents_integer( mb_list[i].amount() );
+        sum = util.money.cents_as_dollars( sum );
+
+        var msg = $("patronStrings").getFormattedString('staff.patron.bills.void_all_billings.void.message', [sum]);
+        var r = g.error.yns_alert(msg,
+            $("patronStrings").getString('staff.patron.bills.void_all_billings.void.title'),
+            $("patronStrings").getString('staff.patron.bills.void_all_billings.void.yes'),
+            $("patronStrings").getString('staff.patron.bills.void_all_billings.void.no'), null,
+            $("patronStrings").getString('staff.patron.bills.void_all_billings.void.confirm_message'));
+        if (r == 0) {
+            var robj = g.network.simple_request('FM_MB_VOID',[ses()].concat(util.functional.map_list(mb_list,function(o){return o.id();})));
+            if (robj.ilsevent) {
+                switch(Number(robj.ilsevent)) {
+                    default: 
+                        g.error.standard_unexpected_error_alert($("patronStrings").getString('staff.patron.bills.void_all_billings.error_voiding_bills'),robj); 
+                        refresh(); return; 
+                    break;
+                }
+            }
+
+            g.data.stash_retrieve(); if (! g.data.voided_billings ) g.data.voided_billings = []; 
+            for (var i = 0; i < mb_list.length; i++) {
+                    g.data.voided_billings.push( mb_list[i] );
+            }
+            g.data.stash('voided_billings');
+        }
+    } catch(E) {
+        try { g.error.standard_unexpected_error_alert('bill2.js, void_all_billings():',E); } catch(F) { alert(E); }
+    }
+}
 
index b7c3961..61d5260 100644 (file)
@@ -21,7 +21,7 @@
 <!--<?xul-overlay href="/xul/server/patron/bill_summary_overlay.xul"?>-->
 
 <window id="bill_interface_win" width="700" height="550" oils_persist="sizemode width height"
-    onload="try{ my_init(); font_helper(); persist_helper(); } catch(E) { alert(E); }"
+    onload="try{ font_helper(); persist_helper(); my_init(); } catch(E) { alert(E); }"
     xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
 
     <!-- ///////////////////////////////////////////////////////////////////////////////////////////////////////////// -->
                 <button id="bill_patron_btn" label="&staff.patron.bills_overlay.bill_patron.label;" accesskey="&staff.patron.bills_overlay.bill_patron.accesskey;" />
                 <button id="bill_history_btn" label="&staff.patron.bills_overlay.history.label;" accesskey="&staff.patron.bills_overlay.history.accesskey;" />
                 <spacer flex="1"/>
+                <vbox pack="center">
+                    <label id="circulating_hint" hidden="true" style="background: red; color: white" value="&staff.patron.bills_overlay.still_checked_out.label;"/>
+                </vbox>
                 <menubar>
                     <menu label="&staff.patron.bill_interface.actions.label;" accesskey="&staff.patron.bill_interface.actions.accesskey;">
                         <menupopup>
             <tree id="bill_tree" flex="1" enableColumnDrag="true" seltype="multiple" editable="true" context="actions_popup"/>
             <hbox>
                 <hbox id="bill_list_actions" />
-                <button label="Check All" oncommand="check_all();"/>
-                <button label="Uncheck All" oncommand="uncheck_all();"/>
-                <button label="Check All Refunds" oncommand="check_all_refunds();"/>
-                <button id="print" label="Print Bills" oncommand="print_bills();"/>
+                <button label="&staff.patron.bills_overlay.check_all.label;" accesskey="&staff.patron.bills_overlay.check_all.accesskey;" oncommand="check_all();"/>
+                <button label="&staff.patron.bills_overlay.uncheck_all.label;" accesskey="&staff.patron.bills_overlay.uncheck_all.accesskey;" oncommand="uncheck_all();"/>
+                <button label="&staff.patron.bills_overlay.check_all_refunds.label;" accesskey="&staff.patron.bills_overlay.check_all_refunds.accesskey;" oncommand="check_all_refunds();"/>
+                <button id="print" label="&staff.patron.bills_overlay.print_bills.label;" accesskey="&staff.patron.bills_overlay.print_bills.accesskey;" oncommand="print_bills();"/>
                 <spacer flex="1"/>
-                <button label="Receipt Options" type="menu">
+                <button label="&staff.patron.bills_overlay.receipt_options.label;" accesskey="&staff.patron.bills_overlay.receipt_options.accesskey;" type="menu">
                     <menupopup>
-                        <menuitem type="checkbox" label="Receipt Upon Payment" checked="true"/>
-                        <menuitem type="checkbox" label="Printer Prompt" />
+                        <menuitem id="receipt_upon_payment" type="checkbox" label="&staff.patron.bills_overlay.receipt_upon_payment.label;" accesskey="&staff.patron.bills_overlay.receipt_upon_payment.accesskey;" checked="true"/>
+                        <menuitem id="printer_prompt" type="checkbox" label="&staff.patron.bills_overlay.printer_prompt.label;" accesskey="&staff.patron.bills_overlay.printer_prompt.accesskey;" />
                         <hbox style="border: solid thin black">
                             <vbox pack="center">
-                                <label value="Number of Copies:" />
+                                <label value="&staff.patron.bills_overlay.number_of_copies.label;" accesskey="&staff.patron.bills_overlay.number_of_copies.accesskey;" control="num_of_receipts" />
                             </vbox>
                             <vbox pack="center">
                                 <textbox id="num_of_receipts" value="1" type="number" min="0" size="2"/>
             <hbox>
                 <vbox>
                     <hbox>
-                        <label value='&staff.patron.bill_interface.voided_this_session.label;' class="emphasis1"/><label id="currently_voided" value="$0.00"/>
+                        <label value='&staff.patron.bill_interface.voided_this_session.label;' class="emphasis1"/><label id="currently_voided" value="0.00"/>
                     </hbox>
-                    <hbox><label value='Change Due Upon Payment:' class="big_emphasis1"/><label id="change_due" value="$0.00" class="big_emphasis1"/></hbox>
-                    <checkbox id="convert_change_to_credit" label="Convert to Patron Credit" />
+                    <hbox><label value='&staff.patron.bill_interface.change_due_upon_payment.label;' class="big_emphasis1"/><label id="change_due" value="0.00" class="big_emphasis1"/></hbox>
+                    <checkbox id="convert_change_to_credit" label="&staff.patron.bills_overlay.convert_change_to_credit.label;" accesskey="&staff.patron.bills_overlay.convert_change_to_credit.accesskey;"/>
                 </vbox>
                 <spacer flex="1"/>
                 <grid>
                     <rows>
                         <row>
                             <spacer />
-                            <label id="pending_payment_label" value="Payment" class="emphasis1" />
-                            <label id="pending_change_label" value="Change" class="emphasis1" />
+                            <label id="pending_payment_label" value="&staff.patron.bill_interface.payment.label;" class="emphasis1" />
+                            <label id="pending_change_label" value="&staff.patron.bill_interface.change.label;" class="emphasis1" />
                         </row>
                         <row>
-                            <label id="pending_label" value="Pending" class="emphasis1" />
-                            <hbox><textbox id="pending_payment" readonly="true" context="clipboard" size="6" value='$0.00'/></hbox>
-                            <hbox><textbox id="pending_change" readonly="true" context="clipboard" size="6" value='$0.00'/></hbox>
+                            <label id="pending_label" value="&staff.patron.bill_interface.pending.label;" class="emphasis1" />
+                            <hbox><textbox id="pending_payment" readonly="true" context="clipboard" size="6" value='0.00'/></hbox>
+                            <hbox><textbox id="pending_change" readonly="true" context="clipboard" size="6" value='0.00'/></hbox>
                         </row>
                     </rows>
                 </grid>
                     <rows>
                         <row>
                             <spacer />
-                            <label id="owed_label" value="Owed" control="total_owed" class="emphasis1"/>
-                            <label id="billed_label" value="Billed" control="total_billed" class="emphasis2"/>
-                            <label id="paid_label" value="Paid" control="total_paid" class="emphasis2"/>
+                            <label id="owed_label" value="&staff.patron.bill_interface.owed.label;" control="total_owed" class="emphasis1"/>
+                            <label id="billed_label" value="&staff.patron.bill_interface.billed.label;" control="total_billed" class="emphasis2"/>
+                            <label id="paid_label" value="&staff.patron.bill_interface.paid.label;" control="total_paid" class="emphasis2"/>
                         </row>
                         <row>
-                            <label id="total_label" value="Total:" control="total_owed" class="emphasis1"/>
+                            <label id="total_label" value="&staff.patron.bill_interface.total.label;" control="total_owed" class="emphasis1"/>
                             <hbox><textbox id="total_owed" readonly="true" context="clipboard" size="6"/></hbox>
                             <hbox><textbox id="total_billed" readonly="true" context="clipboard" size="6"/></hbox>
                             <hbox><textbox id="total_paid" readonly="true" context="clipboard" size="6"/></hbox>
                         </row>
                         <row>
-                            <label id="checked_label" value="Checked:" control="checked_owed" class="emphasis2"/>
+                            <label id="checked_label" value="&staff.patron.bill_interface.checked.label;" control="checked_owed" class="emphasis2"/>
                             <hbox><textbox id="checked_owed" readonly="true" context="clipboard" size="6"/></hbox>
                             <hbox><textbox id="checked_billed" readonly="true" context="clipboard" size="6"/></hbox>
                             <hbox><textbox id="checked_paid" readonly="true" context="clipboard" size="6"/></hbox>
index da3a199..f7648f0 100644 (file)
@@ -40,32 +40,32 @@ function retrieve_mbts_for_list() {
     } else {
         //g.mbts_ids.reverse();
     
-                function gen_func(r) {
-                    return function() {
-                        if (typeof r == 'object') {
-                            g.bill_list.append( 
-                                { 
-                                    'retrieve_id' : r.id(), 
-                                    'row' : { 
-                                        'my' : { 
-                                            'mbts' : r 
-                                        } 
-                                    } 
+        function gen_func(r) {
+            return function() {
+                if (typeof r == 'object') {
+                    g.bill_list.append( 
+                        { 
+                            'retrieve_id' : r.id(), 
+                            'row' : { 
+                                'my' : { 
+                                    'mbts' : r 
                                 } 
-                            );
-                        } else {
-                            g.bill_list.append( 
-                                { 
-                                    'retrieve_id' : r, 
-                                    'row' : 
-                                        'my' : {} 
-                                    } 
-                                } 
-                            );
-                        }
-                    }
+                            } 
+                        } 
+                    );
+                } else {
+                    g.bill_list.append( 
+                        { 
+                            'retrieve_id' : r, 
+                            'row' : { 
+                                'my' : {
+                            } 
+                        } 
+                    );
                 }
-    
+            }
+        }
+
         for (var i = 0; i < g.mbts_ids.length; i++) {
             dump('i = ' + i + ' g.mbts_ids[i] = ' + g.mbts_ids[i] + '\n');
             g.funcs.push( gen_func(g.mbts_ids[i]) );
index 9c4db7d..f7c889b 100644 (file)
@@ -428,7 +428,7 @@ patron.display.prototype = {
                                     'url_prefix' : xulG.url_prefix,
                                     'on_money_change' : function(b) {
                                         netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
-                                        obj.refresh_all();
+                                        obj.summary_window.refresh();
                                     }
                                 }
                             );
index 078f354..533ab81 100644 (file)
@@ -562,7 +562,7 @@ patron.util.retrieve_au_via_id = function(session, id, f) {
     JSAN.use('util.network');
     var network = new util.network();
     var patron_obj = network.simple_request(
-        'FM_AU_RETRIEVE_VIA_ID',
+        'FM_AU_RETRIEVE_VIA_ID.authoritative',
         [ session, id ],
         f
     );
index 133848a..3b26874 100644 (file)
@@ -7,6 +7,10 @@ treechildren::-moz-tree-row(refundable) {
     background-color: pink;
 }
 
+treechildren::-moz-tree-row(circulating) {
+    background-color: red; color: white;
+}
+
 treechildren::-moz-tree-row(backdate_failed) {
     background-color: pink ! important;
 }
index 823605b..cdc252d 100644 (file)
@@ -12,12 +12,14 @@ treechildren::-moz-tree-checkbox(checked) {
 }
 
 treechildren::-moz-tree-row(selected) {
-    background-color: lightblue ! important;
+    border: thin dashed lightblue ! important;
 }
 
+/*
 treechildren::-moz-tree-cell-text(selected,focus) {
     color: black;
 }
+*/
 
 /*
 * { font-size-adjust: .5; }