Remove warnings and display of patron data Conifer does not care about
authordbs <dbs@6d9bc8c9-1ec2-4278-b937-99fde70a366f>
Sat, 2 May 2009 18:05:15 +0000 (18:05 +0000)
committerdbs <dbs@6d9bc8c9-1ec2-4278-b937-99fde70a366f>
Sat, 2 May 2009 18:05:15 +0000 (18:05 +0000)
git-svn-id: svn://svn.open-ils.org/ILS-Contrib/conifer/trunk@435 6d9bc8c9-1ec2-4278-b937-99fde70a366f

xul/server/patron/summary.js [new file with mode: 0644]
xul/server/patron/summary_overlay.xul [new file with mode: 0644]
xul/server/patron/util.js [new file with mode: 0644]

diff --git a/xul/server/patron/summary.js b/xul/server/patron/summary.js
new file mode 100644 (file)
index 0000000..65f26d1
--- /dev/null
@@ -0,0 +1,775 @@
+dump('entering patron.summary.js\n');
+
+function $(id) { return document.getElementById(id); }
+var patronStrings = $('patronStrings');
+
+if (typeof patron == 'undefined') patron = {};
+patron.summary = function (params) {
+
+       JSAN.use('util.error'); this.error = new util.error();
+       JSAN.use('util.window'); this.window = new util.window();
+       JSAN.use('util.network'); this.network = new util.network();
+       this.w = window;
+}
+
+patron.summary.prototype = {
+
+       'init' : function( params ) {
+
+               var obj = this;
+
+               obj.barcode = params['barcode'];
+               obj.id = params['id'];
+               if (params['show_name']) {
+                       document.getElementById('patron_name').hidden = false;
+                       document.getElementById('patron_name').setAttribute('hidden','false');
+               }
+
+               JSAN.use('OpenILS.data'); this.OpenILS = {}; 
+               obj.OpenILS.data = new OpenILS.data(); obj.OpenILS.data.init({'via':'stash'});
+
+               JSAN.use('util.controller'); obj.controller = new util.controller();
+               obj.controller.init(
+                       {
+                               control_map : {
+                                       'cmd_broken' : [
+                                               ['command'],
+                                               function() { alert($("commonStrings").getString('common.unimplemented')); }
+                                       ],
+                                       'patron_alert' : [
+                                               ['render'],
+                                               function(e) {
+                                                       return function() {
+                                                               JSAN.use('util.widgets');
+                                                               util.widgets.remove_children( e );
+                                                               if (obj.patron.alert_message()) {
+                                                                       e.appendChild(
+                                                                               document.createTextNode(
+                                                                                       obj.patron.alert_message()
+                                                                               )
+                                                                       );
+                                                                       e.parentNode.hidden = false;
+                                                               } else {
+                                                                       e.parentNode.hidden = true;
+                                                               }
+                                                       };
+                                               }
+                                       ],
+                                       'patron_usrname' : [
+                                               ['render'],
+                                               function(e) {
+                                                       return function() {
+                                                               e.setAttribute('value',obj.patron.usrname());
+                                                       };
+                                               }
+                                       ],
+                                       'patron_profile' : [
+                                               ['render'],
+                                               function(e) {
+                                                       return function() { 
+                                                               e.setAttribute('value',
+                                                                       obj.OpenILS.data.hash.pgt[
+                                                                               obj.patron.profile()
+                                                                       ].name()
+                                                               );
+                                                       };
+                                               }
+                                       ],
+                                       'patron_net_access' : [
+                                               ['render'],
+                                               function(e) {
+                                                       return function() { 
+                                                               // not applicable to Conifer
+                                                       };
+                                               }
+                                       ],
+                                       'patron_standing_penalties' : [
+                                               ['render'],
+                                               function(e) {
+                                                       return function() {
+                                                               JSAN.use('util.widgets');
+                                                               util.widgets.remove_children(e);
+                                                               var penalties = obj.patron.standing_penalties();
+                                if (penalties.length == 0) {
+                                                                       var row = document.createElement('row');
+                                                                       var label = document.createElement('label');
+                                    label.setAttribute('value',patronStrings.getString('staff.patron.summary.standing_penalty.none'));
+                                    addCSSClass(label,'NO_PENALTY');
+                                                                       row.appendChild(label);
+                                                                       e.appendChild(row);
+                                }
+                                                               for (var i = 0; i < penalties.length; i++) {
+
+                                                                       var row = document.createElement('row');
+                                                                       var label = document.createElement('label');
+
+                                                                       //x.setAttribute('value',penalties[i].penalty_type());
+                                                                       label.setAttribute('value',penalties[i].standing_penalty().label());
+                                                                       row.appendChild(label);
+
+                                                               var button = document.createElement('button');
+                                                               button.setAttribute('label', patronStrings.getString('staff.patron.summary.standing_penalty.remove'));
+                                    button.setAttribute('image','/xul/server/skin/media/images/icon_delete.gif');
+                                                               button.setAttribute('disabled','true');
+                                                               button.setAttribute('hidden','true');
+                                    button.setAttribute('retrieve_ausp_id',penalties[i].id());
+                                                               row.appendChild(button);
+
+                                    // XXX check a permission here? How to fire the remove action ??? XXX
+                                    if (penalties[i].standing_penalty().id() > 100) {
+                                                                   button.setAttribute('disabled','false');
+                                                                   button.setAttribute('hidden','false');
+                                        button.addEventListener(
+                                            'command',
+                                            function(ev) {
+                                                try {
+                                                    JSAN.use('util.functional');
+                                                    var id = ev.target.getAttribute('retrieve_ausp_id');
+                                                    var penalty = util.functional.find_list( obj.patron.standing_penalties(), function(o) { return o.id() == id; } );
+                                                    penalty.isdeleted(1);
+
+                                                    var req = obj.network.simple_request( 'FM_AUSP_REMOVE', [ ses(), penalty ] );
+                                                    if (typeof req.ilsevent != 'undefined' || String(req) != '1') {
+                                                        obj.error.standard_unexpected_error_alert(
+                                                            patronStrings.getFormattedString(
+                                                                'staff.patron.standing_penalty.remove_error',
+                                                                [obj.data.hash.csp[id].name()]
+                                                            ),
+                                                            req
+                                                        );
+                                                    }
+                                                    if (typeof xulG.refresh == 'function') { xulG.refresh(); }
+                                                } catch(F) {
+                                                    obj.error.standard_unexpected_error_alert(
+                                                        patronStrings.getFormattedString(
+                                                            'staff.patron.standing_penalty.remove_error',
+                                                            [ev.target.getAttribute('retrieve_ausp_id')]
+                                                        ),
+                                                        F
+                                                    );
+                                                }
+                                            },
+                                            false
+                                        );
+                                    }
+
+                                    if (penalties[i].standing_penalty().block_list()) {
+                                        if (penalties[i].standing_penalty().block_list().match(/RENEW/)) addCSSClass(label,'PENALTY_RENEW');
+                                        if (penalties[i].standing_penalty().block_list().match(/HOLD/)) addCSSClass(label,'PENALTY_HOLD');
+                                        if (penalties[i].standing_penalty().block_list().match(/CIRC/)) addCSSClass(label,'PENALTY_CIRC');
+                                    }
+
+                                                                       e.appendChild(row);
+                                                               }
+                                                       };
+                                               }
+                                       ],
+                                       'patron_credit' : [
+                                               ['render'],
+                                               function(e) {
+                                                       return function() { 
+                                                               JSAN.use('util.money');
+                                                               e.setAttribute('value',
+                                                                       '$' + 
+                                                                       util.money.sanitize(
+                                                                               obj.patron.credit_forward_balance()
+                                                                       )
+                                                               );
+                                                       };
+                                               }
+                                       ],
+                                       'patron_bill' : [
+                                               ['render'],
+                                               function(e) {
+                                                       return function() { 
+                                                               e.setAttribute('value','...');
+                                var under_btn; 
+                                if (xulG) {
+                                    if (xulG.display_window) {
+                                        under_btn = xulG.display_window.document.getElementById('under_bills');
+                                        if (under_btn) under_btn.setAttribute('value','...');
+                                    }
+                                }
+                                                               obj.network.simple_request(
+                                                                       'FM_MOUS_RETRIEVE.authoritative',
+                                                                       [ ses(), obj.patron.id() ],
+                                                                       function(req) {
+                                                                               JSAN.use('util.money');
+                                                                               var robj = req.getResultObject();
+                                                                               e.setAttribute('value', patronStrings.getFormattedString('staff.patron.summary.patron_bill.money', [util.money.sanitize( robj.balance_owed() )]));
+                                                                               if (under_btn) under_btn.setAttribute('value', 
+                                            patronStrings.getFormattedString('staff.patron.summary.patron_bill.money', [util.money.sanitize( robj.balance_owed() )]));
+                                                                       }
+                                                               );
+                                                               /*
+                                                               obj.network.simple_request(
+                                                                       'FM_MBTS_IDS_RETRIEVE_ALL_HAVING_BALANCE.authoritative',
+                                                                       [ ses(), obj.patron.id() ],
+                                                                       function(req) {
+                                                                               JSAN.use('util.money');
+                                                                               var list = req.getResultObject();
+                                                                               if (typeof list.ilsevent != 'undefined') {
+                                                                                       e.setAttribute('value', '??? See Bills');
+                                                                                       return;
+                                                                               }
+                                                                               var sum = 0;
+                                                                               for (var i = 0; i < list.length; i++) {
+                                                                                       var robj = typeof list[i] == 'object' ? list[i] : obj.network.simple_request('FM_MBTS_RETRIEVE.authoritative',[ses(),list[i]]);
+                                                                                       sum += util.money.dollars_float_to_cents_integer( robj.balance_owed() );
+                                                                               } 
+                                                                               if (sum > 0) addCSSClass(document.documentElement,'PATRON_HAS_BILLS');
+                                                                               JSAN.use('util.money');
+                                                                               e.setAttribute('value', '$' + util.money.sanitize( util.money.cents_as_dollars( sum ) ));
+                                                                       }
+                                                               );
+                                                               */
+                                                       };
+                                               }
+                                       ],
+                                       'patron_checkouts' : [
+                                               ['render'],
+                                               function(e) {
+                                                       return function() { 
+                                                               e.setAttribute('value','...');
+                                                               var e2 = document.getElementById( 'patron_overdue' ); if (e2) e2.setAttribute('value','...');
+                                                               var e3 = document.getElementById( 'patron_claimed_returned' ); if (e3) e3.setAttribute('value','...');
+                                                               var e4 = document.getElementById( 'patron_long_overdue' ); if (e4) e4.setAttribute('value','...');
+                                                               var e5 = document.getElementById( 'patron_lost' ); if (e5) e5.setAttribute('value','...');
+                                                               var e6 = document.getElementById( 'patron_noncat' ); if (e6) e6.setAttribute('value','...');
+                                var under_btn; 
+                                if (xulG) {
+                                    if (xulG.display_window) {
+                                        under_btn = xulG.display_window.document.getElementById('under_items');
+                                        if (under_btn) under_btn.setAttribute('value','...');
+                                    }
+                                }
+                                                               obj.network.simple_request(
+                                                                       'FM_CIRC_COUNT_RETRIEVE_VIA_USER.authoritative',
+                                                                       [ ses(), obj.patron.id() ],
+                                                                       function(req) {
+                                                                               try {
+                                                                                       var robj = req.getResultObject();
+                                                                                       e.setAttribute('value', robj.out + robj.overdue + robj.claims_returned + robj.long_overdue );
+                                                                                       if (e2) e2.setAttribute('value', robj.overdue   );
+                                                                                       if (e3) e3.setAttribute('value', robj.claims_returned   );
+                                                                                       if (e4) e4.setAttribute('value', robj.long_overdue      );
+                                                                                       if (e5) e5.setAttribute('value', robj.lost      );
+                                            if (under_btn) under_btn.setAttribute('value', 
+                                                String( robj.out + robj.overdue + robj.claims_returned + robj.long_overdue) + 
+                                                ( robj.overdue > 0 || robj.claims_returned > 0 || robj.long_overdue > 0 ? '*' : '' )
+                                            );
+                                                                               } catch(E) {
+                                                                                       alert(E);
+                                                                               }
+                                                                       }
+                                                               );
+                                                               obj.network.simple_request(
+                                                                       'FM_ANCC_RETRIEVE_VIA_USER.authoritative',
+                                                                       [ ses(), obj.patron.id() ],
+                                                                       function(req) {
+                                                                               var robj = req.getResultObject();
+                                                                               if (e6) e6.setAttribute('value',robj.length);
+                                                                       }
+                                                               );
+                                                       };
+                                               }
+                                       ],
+                                       'patron_overdue' : [
+                                               ['render'],
+                                               function(e) {
+                                                       return function() { 
+                                                               /* handled by 'patron_checkouts' */
+                                                       };
+                                               }
+                                       ],
+                                       'patron_holds' : [
+                                               ['render'],
+                                               function(e) {
+                                                       return function() { 
+                                                               e.setAttribute('value','...');
+                                                               var e2 = document.getElementById('patron_holds_available');
+                                                               if (e2) e2.setAttribute('value','...');
+                                var under_btn; 
+                                if (xulG) {
+                                    if (xulG.display_window) {
+                                        under_btn = xulG.display_window.document.getElementById('under_holds');
+                                        if (under_btn) under_btn.setAttribute('value','...');
+                                    }
+                                }
+                                                               obj.network.simple_request(
+                                                                       'FM_AHR_COUNT_RETRIEVE.authoritative',
+                                                                       [ ses(), obj.patron.id() ],
+                                                                       function(req) {
+                                                                               e.setAttribute('value',
+                                                                                       req.getResultObject().total
+                                                                               );
+                                                                               if (e2) e2.setAttribute('value',
+                                                                                       req.getResultObject().ready
+                                                                               );
+                                        if (under_btn) under_btn.setAttribute( 'value', req.getResultObject().ready + '/' + req.getResultObject().total );
+                                                                       }
+                                                               );
+                                                       };
+                                               }
+                                       ],
+                                       'patron_holds_available' : [
+                                               ['render'],
+                                               function(e) {
+                                                       return function() { 
+                                                               /* handled by 'patron_holds' */
+                                                       };
+                                               }
+                                       ],
+                                       'patron_card' : [
+                                               ['render'],
+                                               function(e) {
+                                                       return function() { 
+                                                               e.setAttribute('value',
+                                                                       obj.patron.card().barcode()
+                                                               );
+                                                       };
+                                               }
+                                       ],
+                                       'patron_ident_type_1' : [
+                                               ['render'],
+                                               function(e) {
+                                                       return function() { 
+                                                               var ident_string = '';
+                                                               var ident = obj.OpenILS.data.hash.cit[
+                                                                       obj.patron.ident_type()
+                                                               ];
+                                                               if (ident) ident_string = ident.name()
+                                                               e.setAttribute('value',
+                                                                       ident_string
+                                                               );
+                                                       };
+                                               }
+                                       ],
+                                       'patron_ident_value_1' : [
+                                               ['render'],
+                                               function(e) {
+                                                       return function() { 
+                                                               var val = obj.patron.ident_value();
+                                                               val = val.replace(/.+(\d\d\d\d)$/,'xxxx$1');
+                                                               e.setAttribute('value', val);
+                                                       };
+                                               }
+                                       ],
+                                       'patron_ident_type_2' : [
+                                               ['render'],
+                                               function(e) {
+                                                       return function() { 
+                                                               var ident_string = '';
+                                                               var ident = obj.OpenILS.data.hash.cit[
+                                                                       obj.patron.ident_type2()
+                                                               ];
+                                                               if (ident) ident_string = ident.name()
+                                                               e.setAttribute('value',
+                                                                       ident_string
+                                                               );
+                                                       };
+                                               }
+                                       ],
+                                       'patron_ident_value_2' : [
+                                               ['render'],
+                                               function(e) {
+                                                       return function() { 
+                                                               var val = obj.patron.ident_value2();
+                                                               val = val.replace(/.+(\d\d\d\d)$/,'xxxx$1');
+                                                               e.setAttribute('value', val);
+                                                       };
+                                               }
+                                       ],
+                                       'patron_date_of_exp' : [
+                                               ['render'],
+                                               function(e) {
+                                                       return function() { 
+                                                               e.setAttribute('value',
+                                                                       patronStrings.getString('staff.patron.summary.expires_on') + ' ' + (
+                                                                               obj.patron.expire_date() ?
+                                                                               obj.patron.expire_date().substr(0,10) :
+                                                                           patronStrings.getString('staff.patron.field.unset') 
+                                                                       )
+                                                               );
+                                                       };
+                                               }
+                                       ],
+                                       'patron_date_of_birth' : [
+                                               ['render'],
+                                               function(e) {
+                                                       return function() { 
+                                                               // not applicable to Conifer
+                                                       };
+                                               }
+                                       ],
+                                       'patron_day_phone' : [
+                                               ['render'],
+                                               function(e) {
+                                                       return function() { 
+                                                               e.setAttribute('value',
+                                                                       obj.patron.day_phone()
+                                                               );
+                                                       };
+                                               }
+                                       ],
+                                       'patron_evening_phone' : [
+                                               ['render'],
+                                               function(e) {
+                                                       return function() { 
+                                                               e.setAttribute('value',
+                                                                       obj.patron.evening_phone()
+                                                               );
+                                                       };
+                                               }
+                                       ],
+                                       'patron_other_phone' : [
+                                               ['render'],
+                                               function(e) {
+                                                       return function() { 
+                                                               e.setAttribute('value',
+                                                                       obj.patron.other_phone()
+                                                               );
+                                                       };
+                                               }
+                                       ],
+                                       'patron_email' : [
+                                               ['render'],
+                                               function(e) {
+                                                       return function() { 
+                                                               e.setAttribute('value',
+                                                                       obj.patron.email()
+                                                               );
+                                                       };
+                                               }
+                                       ],
+                                       'patron_alias' : [
+                                               ['render'],
+                                               function(e) {
+                                                       return function() { 
+                                                               e.setAttribute('value',
+                                                                       obj.patron.alias()
+                                                               );
+                                                       };
+                                               }
+                                       ],
+                                       'patron_photo_url' : [
+                                               ['render'],
+                                               function(e) {
+                                                       return function() { 
+                                                               e.setAttribute('src',
+                                                                       obj.patron.photo_url()
+                                                               );
+                                                       };
+                                               }
+                                       ],
+                                       'patron_library' : [
+                                               ['render'],
+                                               function(e) {
+                                                       return function() { 
+                                                               e.setAttribute('value',
+                                                                       obj.OpenILS.data.hash.aou[
+                                                                               obj.patron.home_ou()
+                                                                       ].shortname()
+                                                               );
+                                                               e.setAttribute('tooltiptext',
+                                                                       obj.OpenILS.data.hash.aou[
+                                                                               obj.patron.home_ou()
+                                                                       ].name()
+                                                               );
+                                                       };
+                                               }
+                                       ],
+                                       'patron_last_library' : [
+                                               ['render'],
+                                               function(e) {
+                                                       return function() { 
+                                                               e.setAttribute('value',
+                                                                       obj.OpenILS.data.hash.aou[
+                                                                               obj.patron.home_ou()
+                                                                       ].shortname()
+                                                               );
+                                                               e.setAttribute('tooltiptext',
+                                                                       obj.OpenILS.data.hash.aou[
+                                                                               obj.patron.home_ou()
+                                                                       ].name()
+                                                               );
+                                                       };
+                                               }
+                                       ],
+                                       'patron_mailing_address_street1' : [
+                                               ['render'],
+                                               function(e) {
+                                                       return function() { 
+                                                               e.setAttribute('value',
+                                                                       obj.patron.mailing_address().street1()
+                                                               );
+                                                               if (!get_bool(obj.patron.mailing_address().valid())){e.setAttribute('style','color: red');}
+                                                       };
+                                               }
+                                       ],
+                                       'patron_mailing_address_street2' : [
+                                               ['render'],
+                                               function(e) {
+                                                       return function() { 
+                                                               e.setAttribute('value',
+                                                                       obj.patron.mailing_address().street2()
+                                                               );
+                                                               if (!get_bool(obj.patron.mailing_address().valid())){e.setAttribute('style','color: red');}
+                                                       };
+                                               }
+                                       ],
+                                       'patron_mailing_address_city' : [
+                                               ['render'],
+                                               function(e) {
+                                                       return function() { 
+                                                               e.setAttribute('value',
+                                                                       obj.patron.mailing_address().city()
+                                                               );
+                                                               if (!get_bool(obj.patron.mailing_address().valid())){e.setAttribute('style','color: red');}
+                                                       };
+                                               }
+                                       ],
+                                       'patron_mailing_address_state' : [
+                                               ['render'],
+                                               function(e) {
+                                                       return function() { 
+                                                               e.setAttribute('value',
+                                                                       obj.patron.mailing_address().state()
+                                                               );
+                                                               if (!get_bool(obj.patron.mailing_address().valid())){e.setAttribute('style','color: red');}
+                                                       };
+                                               }
+                                       ],
+                                       'patron_mailing_address_post_code' : [
+                                               ['render'],
+                                               function(e) {
+                                                       return function() { 
+                                                               e.setAttribute('value',
+                                                                       obj.patron.mailing_address().post_code()
+                                                               );
+                                                               if (!get_bool(obj.patron.mailing_address().valid())){e.setAttribute('style','color: red');}
+                                                       };
+                                               }
+                                       ],
+                                       'patron_physical_address_street1' : [
+                                               ['render'],
+                                               function(e) {
+                                                       return function() { 
+                                                               e.setAttribute('value',
+                                                                       obj.patron.billing_address().street1()
+                                                               );
+                                                               if (!get_bool(obj.patron.billing_address().valid())){e.setAttribute('style','color: red');}
+                                                       };
+                                               }
+                                       ],
+                                       'patron_physical_address_street2' : [
+                                               ['render'],
+                                               function(e) {
+                                                       return function() { 
+                                                               e.setAttribute('value',
+                                                                       obj.patron.billing_address().street2()
+                                                               );
+                                                               if (!get_bool(obj.patron.billing_address().valid())){e.setAttribute('style','color: red');}
+                                                       };
+                                               }
+                                       ],
+                                       'patron_physical_address_city' : [
+                                               ['render'],
+                                               function(e) {
+                                                       return function() { 
+                                                               e.setAttribute('value',
+                                                                       obj.patron.billing_address().city()
+                                                               );
+                                                               if (!get_bool(obj.patron.billing_address().valid())){e.setAttribute('style','color: red');}
+                                                       };
+                                               }
+                                       ],
+                                       'patron_physical_address_state' : [
+                                               ['render'],
+                                               function(e) {
+                                                       return function() { 
+                                                               e.setAttribute('value',
+                                                                       obj.patron.billing_address().state()
+                                                               );
+                                                               if (!get_bool(obj.patron.billing_address().valid())){e.setAttribute('style','color: red');}
+                                                       };
+                                               }
+                                       ],
+                                       'patron_physical_address_post_code' : [
+                                               ['render'],
+                                               function(e) {
+                                                       return function() { 
+                                                               e.setAttribute('value',
+                                                                       obj.patron.billing_address().post_code()
+                                                               );
+                                                               if (!get_bool(obj.patron.billing_address().valid())){e.setAttribute('style','color: red');}
+                                                       };
+                                               }
+                                       ]
+                               }
+                       }
+               );
+
+               obj.retrieve();
+
+               try {
+                       var caption = document.getElementById("PatronSummaryContact_caption");
+                       var arrow = document.getAnonymousNodes(caption)[0];
+                       var gb_content = document.getAnonymousNodes(caption.parentNode)[1];
+                       arrow.addEventListener(
+                               'click',
+                               function() {
+                                       setTimeout(
+                                               function() {
+                                                       //alert('setting shrink_state to ' + gb_content.hidden);
+                                                       //caption.setAttribute('shrink_state',gb_content.hidden);
+                                                       netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
+                                                       JSAN.use('util.file'); var file = new util.file('patron_id_shrink');
+                                                       file.set_object(String(gb_content.hidden)); file.close();
+                                               }, 0
+                                       );
+                               }, false
+                       );
+                       //var shrink_state = caption.getAttribute('shrink_state');
+                       var shrink_state = false;
+                       netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
+                       JSAN.use('util.file'); var file = new util.file('patron_id_shrink');
+                       if (file._file.exists()) {
+                               shrink_state = file.get_object(); file.close();
+                       }
+                       //alert('shrink_state retrieved as ' + shrink_state);
+                       if (shrink_state != 'false' && shrink_state) {
+                               JSAN.use('util.widgets');
+                               //alert('clicking the widget');
+                               util.widgets.click( arrow );
+                       }
+               } catch(E) {
+                       obj.error.sdump('D_ERROR','with shrink_state in summary.js: ' + E);
+               }
+       },
+
+       'retrieve' : function() {
+
+               try {
+
+                       var obj = this;
+
+                       var chain = [];
+
+                       // Retrieve the patron
+                               function blah_retrieve() {
+                                       try {
+                                               var robj;
+                                               if (obj.barcode && obj.barcode != 'null') {
+                                                       robj = obj.network.simple_request(
+                                                               'FM_AU_RETRIEVE_VIA_BARCODE.authoritative',
+                                                               [ ses(), obj.barcode ]
+                                                       );
+                                               } else if (obj.id && obj.id != 'null') {
+                                                       robj = obj.network.simple_request(
+                                                               'FM_AU_FLESHED_RETRIEVE_VIA_ID',
+                                                               [ ses(), obj.id ]
+                                                       );
+                                               } else {
+                                                       throw(patronStrings.getString('staff.patron.summary.retrieve.no_barcode'));
+                                               }
+                                               if (robj) {
+
+                                                       if (instanceOf(robj,au)) {
+
+                                                               obj.patron = robj;
+                                                               JSAN.use('patron.util');
+                                                               document.getElementById('patron_name').setAttribute('value',
+                                                                       ( obj.patron.prefix() ? obj.patron.prefix() + ' ' : '') + 
+                                                                       obj.patron.family_name() + ', ' + 
+                                                                       obj.patron.first_given_name() + ' ' +
+                                                                       ( obj.patron.second_given_name() ? obj.patron.second_given_name() + ' ' : '' ) +
+                                                                       ( obj.patron.suffix() ? obj.patron.suffix() : '')
+                                                               );
+                                                               patron.util.set_penalty_css(obj.patron);
+                                                               JSAN.use('OpenILS.data'); var data = new OpenILS.data(); data.init({'via':'stash'});
+                                                               data.last_patron = obj.patron.id(); data.stash('last_patron');
+
+                                                       } else {
+
+                                                               throw(robj);
+
+                                                       }
+                                               } else {
+
+                                                       throw(robj);
+
+                                               }
+
+                                       } catch(E) {
+                                               throw(E);
+                                       }
+                               };
+                               blah_retrieve();
+
+                       /*
+                       // Retrieve the survey responses for required surveys
+                       chain.push(
+                               function() {
+                                       try {
+                                               var surveys = obj.OpenILS.data.list.my_asv;
+                                               var survey_responses = {};
+                                               for (var i = 0; i < surveys.length; i++) {
+                                                       var s = obj.network.request(
+                                                               api.FM_ASVR_RETRIEVE.app,
+                                                               api.FM_ASVR_RETRIEVE.method,
+                                                               [ ses(), surveys[i].id(), obj.patron.id() ]
+                                                       );
+                                                       survey_responses[ surveys[i].id() ] = s;
+                                               }
+                                               obj.patron.survey_responses( survey_responses );
+                                       } catch(E) {
+                                               var error = ('patron.summary.retrieve : ' + js2JSON(E));
+                                               obj.error.sdump('D_ERROR',error);
+                                               throw(error);
+                                       }
+                               }
+                       );
+                       */
+
+                       // Update the screen
+                       chain.push( function() { obj.controller.render(); } );
+
+                       // On Complete
+
+                       chain.push( function() {
+
+                               if (typeof window.xulG == 'object' && typeof window.xulG.on_finished == 'function') {
+                                       obj.error.sdump('D_PATRON_SUMMARY',
+                                               'patron.summary: Calling external .on_finished()\n');
+                                       window.xulG.on_finished(obj.patron);
+                               } else {
+                                       obj.error.sdump('D_PATRON_SUMMARY','patron.summary: No external .on_finished()\n');
+                               }
+
+                       } );
+
+                       // Do it
+                       JSAN.use('util.exec'); obj.exec = new util.exec();
+                       obj.exec.on_error = function(E) {
+
+                               if (typeof window.xulG == 'object' && typeof window.xulG.on_error == 'function') {
+                                       window.xulG.on_error(E);
+                               } else {
+                                       alert(js2JSON(E));
+                               }
+
+                       }
+                       this.exec.chain( chain );
+
+               } catch(E) {
+                       if (typeof window.xulG == 'object' && typeof window.xulG.on_error == 'function') {
+                               window.xulG.on_error(E);
+                       } else {
+                               alert(js2JSON(E));
+                       }
+               }
+       }
+}
+
+dump('exiting patron.summary.js\n');
diff --git a/xul/server/patron/summary_overlay.xul b/xul/server/patron/summary_overlay.xul
new file mode 100644 (file)
index 0000000..0d77dff
--- /dev/null
@@ -0,0 +1,221 @@
+<?xml version="1.0"?>
+<!DOCTYPE overlay PUBLIC "" ""[
+       <!--#include virtual="/opac/locale/${locale}/lang.dtd"-->
+]>
+<overlay id="patron_summary_overlay" 
+       xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+
+<script>dump('loading patron/summary_overlay.xul\n');</script>
+
+<commandset id="patron_summary_cmds" />
+
+<box id="patron_summary_main" flex="1" orient="vertical" class="my_overflow">
+       <vbox id="patron_info_sidebar" />
+</box>
+
+<vbox id="patron_info_sidebar" flex="1">
+       <label id="patron_name" hidden="true" class="patronNameLarge"/>
+       <groupbox id="PatronSummaryAlert_groupbox" flex="0" hidden="true" class="alert">
+               <caption id="psagbc" label="&staff.patron.summary_overlay.psagbc.alert.label;" class="shrinkable_groupbox"/>
+               <description id="patron_alert"/>
+       </groupbox>
+       <groupbox id="PatronSummaryStanding_groupbox" flex="0" class="standing">
+               <caption id="pssgbc" label="&staff.patron.summary_overlay.pssgbc.standing.label;" class="shrinkable_groupbox"/>
+        <vbox id="pssgbvb">
+            <grid><columns><column/><column/></columns>
+                <rows id="patron_standing_penalties"/>
+            </grid>
+        </vbox>
+        <spacer/>
+       </groupbox>
+       <groupbox id="PatronSummaryStatus_groupbox" flex="0" class="status"/>
+       <!--
+       <groupbox id="PatronSummarySurvey_groupbox" flex="0">
+               <caption id="pdsgbc" label="Surveys" class="shrinkable_groupbox"/>
+               <vbox id="patron_surveys" />
+       </groupbox>
+       -->
+       <groupbox id="PatronSummaryContact_groupbox" flex="0" class="contact"/>
+</vbox>
+
+<groupbox id="PatronSummaryStatus_groupbox" orient="vertical">
+       <caption label="&staff.patron_display.status.caption;" class="shrinkable_groupbox" />
+       <grid style="border: solid thin"><columns><column/></columns><rows>
+               <row hidden="true">
+                       <label id="patron_standing" />
+               </row>
+               <row id="pdsgr1">
+                       <label id="patron_profile" class="profile value"/>
+               </row>
+               <row id="pdsgr5">
+                       <label id="patron_library" class="homelib value"/>
+               </row>
+               <row id="pdsgr5aa">
+                       <label id="patron_date_of_exp" class="expire_date value"/>
+               </row>
+       </rows></grid>
+       <grid id="PatronSummaryStatus_grid" flex="1"/>
+
+</groupbox>
+
+<grid id="PatronSummaryStatus_grid">
+       <columns id="pdsgc">
+               <column id="pdsgc1" />
+               <column id="pdsgc2" />
+               <column id="pdsgc3" />
+               <column id="pdsgc4" />
+       </columns>
+       <rows id="pdsgr" flex="1">
+               <row id="pdsgr4">
+                       <label id="PatronSummaryStatus_holds_label" class="text_left holds label"
+                               value="&staff.patron_display.holds.label;" />
+                       <label id="patron_holds" class="holds value"/>
+               </row><row>
+                       <label id="PatronSummaryStatus_holds_available_label" class="text_right holds_ready label"
+                               value="&staff.patron_display.holds_available.label;"  style="background: grey"/>
+                       <label id="patron_holds_available" class="holds_ready label" style="background: grey"/>
+               </row>
+               <row id="pdsgr2" class="hide_patron_credit" hidden="true">
+                       <label id="PatronSummaryStatus_credit_label" class="text_left credit label"
+                               value="&staff.patron_display.credit.label;" />
+                       <label id="patron_credit" class="credit value"/>
+               </row><row>
+                       <label id="PatronSummaryStatus_bills_label" class="text_left bill label"
+                               value="&staff.patron_display.bills.label;" />
+                       <label id="patron_bill" class="bill value"/>
+               </row>
+               <row id="pdsgr3">
+                       <label id="PatronSummaryStatus_checkouts_label" class="text_left items_out label"
+                               value="&staff.patron_display.checkouts.label;" />
+                       <label id="patron_checkouts" class="items_out value"/>
+               </row>
+               <row>
+                       <label id="PatronSummaryStatus_checkouts_overdue_label" class="text_right items_overdue label"
+                               value="&staff.patron_display.checkouts_overdue.label;" style="background: grey"/>
+                       <label id="patron_overdue" class="items_overdue value" style="background: grey"/>
+               </row>
+               <row id="pdsgr5">
+                       <label id="PatronSummaryStatus_long_overdue_label" value="&staff.patron.summary_overlay.overdue.value;" class="text_right items_long_overdue label" style="background: grey"/>
+                       <label id="patron_long_overdue" class="items_long_overdue value" style="background: grey"/>
+               </row>
+               <row id="pdsgr7">
+                       <label id="PatronSummaryStatus_claimed_returned_label" value="&staff.patron.summary_overlay.claimed_returned.value;" class="text_right items_long_overdue label" style="background: grey"/>
+                       <label id="patron_claimed_returned" class="items_claimed_returned value" style="background: grey"/>
+               </row>
+               <row id="pdsgr6">
+                       <label id="PatronSummaryStatus_lost_label" value="&staff.patron.summary_overlay.lost_label.value;" class="text_left items_lost label"/>
+                       <label id="patron_lost" class="items_lost value"/>
+               </row>
+               <row id="pdsgr6a">
+                       <label id="PatronSummaryStatus_noncat_label" value="&staff.patron.summary_overlay.noncat_label.value;" class="text_left items_noncat label"/>
+                       <label id="patron_noncat" class="items_noncat value"/>
+               </row>
+       </rows>
+</grid>
+
+<groupbox id="PatronSummaryContact_groupbox" orient="vertical">
+       <!--
+       <caption label="&staff.patron_display.contact.caption;"/>
+       -->
+       <caption id="PatronSummaryContact_caption" label="&staff.patron.summary_overlay.summary_contact.label;" class="shrinkable_groupbox" />
+       <hbox id="pdcgbhb1">
+               <grid id="PatronSummaryContact_grid" />
+               <spacer id="pdcgbhbs1" flex="1"/>
+               <image id="patron_photo_url" />
+       </hbox>
+       <grid id="PatronSummaryContact_grid_phone" />
+       <groupbox id="PatronSummaryContact_mailing_address" class="mailing_address"/>
+       <groupbox id="PatronSummaryContact_physical_address" class="physical_address"/>
+</groupbox>
+
+<grid id="PatronSummaryContact_grid">
+       <columns id="pdsgc">
+               <column id="pdsgc1" />
+               <column id="pdsgc2" />
+       </columns>
+       <rows id="pdsgr" flex="1">
+               <row id="pdsgr0">
+                       <label id="PatronSummaryContact_library_card_label" class="text_left card label"
+                               value="&staff.patron_display.library_card.label;"/>
+                       <label id="patron_card" class="card value click_link" onclick="try { copy_to_clipboard(event); } catch(E) { alert(E); }"/>
+               </row>
+               <row id="pdsgr1">
+                       <label id="PatronSummaryContact_ident_label" class="text_left"
+                               value="&staff.patron_display.ident1.label;"/>
+                       <vbox id="pdsgr0h">
+                               <label id="patron_ident_type_1" class="ident ident_type ident1 value"/>
+                               <label id="patron_ident_value_1" class="ident ident_value ident1 value"/>
+                       </vbox>
+               </row>
+               <row id="pdsgr2">
+                       <label id="PatronSummaryContact_ident_label2" class="text_left"
+                               value="&staff.patron_display.ident2.label;"/>
+                       <vbox id="pdsgr0ah">
+                               <label id="patron_ident_type_2" class="ident ident_type ident2 value"/>
+                               <label id="patron_ident_value_2" class="ident ident_value ident2 value"/>
+                       </vbox>
+               </row>
+               <row id="pdsgr4"><label id="pdsgr4l" value=" "/></row>
+       </rows>
+</grid>
+
+<grid id="PatronSummaryContact_grid_phone">
+       <columns id="pdcgpc">
+               <column id="pdcgpc1" />
+               <column id="pdcgpc2" />
+       </columns>
+       <rows id="pdcgpr" flex="1">
+               <row id="pdcgpr1">
+                       <label id="PatronSummaryContact_day_phone_label" class="text_left phone label day_phone"
+                               value="&staff.patron_display.day_phone.label;" />
+                       <label id="patron_day_phone" class="phone value day_phone"/> 
+               </row>
+               <row id="pdcgpr2">
+                       <label id="PatronSummaryContact_evening_phone_label" class="text_left phone label evening_phone"
+                               value="&staff.patron_display.evening_phone.label;" />
+                       <label id="patron_evening_phone" class="phone value evening_phone"/>
+               </row>
+               <row id="pdcgpr3">
+                       <label id="PatronSummaryContact_other_phone_label" class="text_left phone label other_phone"
+                               value="&staff.patron_display.other_phone.label;" />
+                       <label id="patron_other_phone" class="phone value other_phone"/> 
+               </row>
+               <row id="pdsgpr4"><label id="pdsgpr4l" value=" "/></row>
+               <row id="pdsgpr4a">
+                       <label id="PatronSummaryContact_usrname_label" class="text_left usrname label"
+                               value="&staff.patron.summary_overlay.opac_login.value;" />
+                       <label id="patron_usrname" class="usrname value"/>
+               </row>
+               <row id="pdcgpr5">
+                       <label id="PatronSummaryContact_email_label" class="text_left email label"
+                               value="&staff.patron_display.email.label;" />
+                       <label id="patron_email" class="email value" style="text-decoration: underline; color: blue; -moz-user-focus: normal;" onclick="copy_to_clipboard(event)"/>
+               </row>
+               <row id="pdsgpr6"><label id="pdsgpr6l" value=" "/></row>
+
+       </rows>
+</grid>
+
+<groupbox id="PatronSummaryContact_mailing_address" orient="vertical">
+       <caption id="pdcmac" label="&staff.patron_display.mailing_address;" class="shrinkable_groupbox"/>
+       <label id="patron_mailing_address_street1" tooltiptext="&staff.patron_display.mailing.street1.label;" class="address street street1 mailing"/>
+       <label id="patron_mailing_address_street2" tooltiptext="&staff.patron_display.mailing.street2.label;" class="address street street2 mailing"/>
+       <hbox id="pdcmah">
+               <label id="patron_mailing_address_city" tooltiptext="&staff.patron_display.mailing.city.label;" class="address city mailing"/>
+               <label id="patron_mailing_address_state" tooltiptext="&staff.patron_display.mailing.state.label;" class="address state mailing"/>
+               <label id="patron_mailing_address_post_code" tooltiptext="&staff.patron_display.mailing.post_code.label;" class="address post_code mailing"/>
+       </hbox>
+</groupbox>
+
+<groupbox id="PatronSummaryContact_physical_address" orient="vertical">
+       <caption id="pdcpac" label="&staff.patron_display.physical_address;" class="shrinkable_groupbox"/>
+       <label id="patron_physical_address_street1" tooltiptext="&staff.patron_display.physical.street1.label;" class="address street street1 physical" />
+       <label id="patron_physical_address_street2" tooltiptext="&staff.patron_display.physical.street2.label;"  class="address street street2 physical"/>
+       <hbox id="pdcpah">
+               <label id="patron_physical_address_city" tooltiptext="&staff.patron_display.physical.city.label;" class="address city physical"/>
+               <label id="patron_physical_address_state" tooltiptext="&staff.patron_display.physical.state.label;" class="address state physical"/>
+               <label id="patron_physical_address_post_code" tooltiptext="&staff.patron_display.physical.post_code.label;" class="address post_code physical"/>
+       </hbox>
+</groupbox>
+
+</overlay>
diff --git a/xul/server/patron/util.js b/xul/server/patron/util.js
new file mode 100644 (file)
index 0000000..3738fdc
--- /dev/null
@@ -0,0 +1,768 @@
+dump('entering patron/util.js\n');
+
+if (typeof patron == 'undefined') var patron = {};
+patron.util = {};
+
+patron.util.EXPORT_OK  = [ 
+       'columns', 'mbts_columns', 'mb_columns', 'mp_columns', /*'std_map_row_to_column',*/ 'std_map_row_to_columns',
+       'retrieve_au_via_id', 'retrieve_fleshed_au_via_id', 'retrieve_fleshed_au_via_barcode', 'set_penalty_css', 'retrieve_name_via_id',
+    'merge'
+];
+patron.util.EXPORT_TAGS        = { ':all' : patron.util.EXPORT_OK };
+
+patron.util.mbts_columns = function(modify,params) {
+
+       JSAN.use('OpenILS.data'); var data = new OpenILS.data(); data.init({'via':'stash'});
+       JSAN.use('util.money'); JSAN.use('util.date');
+
+    var commonStrings = document.getElementById('commonStrings');
+
+       var c = [
+               {
+                       'persist' : 'hidden width ordinal', 'id' : 'id', 'label' : commonStrings.getString('staff.mbts_id_label'), 'flex' : 1,
+                       'primary' : false, 'hidden' : false, 'render' : function(my) { return my.mbts.id(); }
+               },
+               {
+                       'persist' : 'hidden width ordinal', 'id' : 'usr', 'label' : commonStrings.getString('staff.mbts_usr_label'), 'flex' : 1,
+                       'primary' : false, 'hidden' : true, 'render' : function(my) { return my.mbts.usr() ? "Id = " + my.mbts.usr() : ""; }
+               },
+               {
+                       'persist' : 'hidden width ordinal', 'id' : 'xact_type', 'label' : commonStrings.getString('staff.mbts_xact_type_label'), 'flex' : 1,
+                       'primary' : false, 'hidden' : false, 'render' : function(my) { return my.mbts.xact_type(); }
+               },
+               {
+                       'persist' : 'hidden width ordinal', 'id' : 'balance_owed', 'label' : commonStrings.getString('staff.mbts_balance_owed_label'), 'flex' : 1,
+                       'primary' : false, 'hidden' : false, 'render' : function(my) { return util.money.sanitize( my.mbts.balance_owed() ); },
+                       'sort_type' : 'money'
+               },
+               {
+                       'persist' : 'hidden width ordinal', 'id' : 'total_owed', 'label' : commonStrings.getString('staff.mbts_total_owed_label'), 'flex' : 1,
+                       'primary' : false, 'hidden' : false, 'render' : function(my) { return util.money.sanitize( my.mbts.total_owed() ); },
+                       'sort_type' : 'money'
+               },
+               {
+                       'persist' : 'hidden width ordinal', 'id' : 'total_paid', 'label' : commonStrings.getString('staff.mbts_total_paid_label'), 'flex' : 1,
+                       'primary' : false, 'hidden' : false, 'render' : function(my) { return util.money.sanitize( my.mbts.total_paid() ); },
+                       'sort_type' : 'money'
+               },
+               {
+                       'persist' : 'hidden width ordinal', 'id' : 'last_billing_note', 'label' : commonStrings.getString('staff.mbts_last_billing_note_label'), 'flex' : 2,
+                       'primary' : false, 'hidden' : true, 'render' : function(my) { return my.mbts.last_billing_note(); }
+               },
+               {
+                       'persist' : 'hidden width ordinal', 'id' : 'last_billing_type', 'label' : commonStrings.getString('staff.mbts_last_billing_type_label'), 'flex' : 1,
+                       'primary' : false, 'hidden' : true, 'render' : function(my) { return my.mbts.last_billing_type(); }
+               },
+               {
+                       'persist' : 'hidden width ordinal', 'id' : 'last_billing_ts', 'label' : commonStrings.getString('staff.mbts_last_billing_timestamp_label'), 'flex' : 1,
+                       'primary' : false, 'hidden' : true, 'render' : function(my) { return util.date.formatted_date( my.mbts.last_billing_ts(), "" ); }
+               },
+               {
+                       'persist' : 'hidden width ordinal', 'id' : 'last_payment_note', 'label' : commonStrings.getString('staff.mbts_last_payment_note_label'), 'flex' : 2,
+                       'primary' : false, 'hidden' : true, 'render' : function(my) { return my.mbts.last_payment_note(); }
+               },
+               {
+                       'persist' : 'hidden width ordinal', 'id' : 'last_payment_type', 'label' : commonStrings.getString('staff.mbts_last_payment_type_label'), 'flex' : 1,
+                       'primary' : false, 'hidden' : true, 'render' : function(my) { return my.mbts.last_payment_type(); }
+               },
+               {
+                       'persist' : 'hidden width ordinal', 'id' : 'last_payment_ts', 'label' : commonStrings.getString('staff.mbts_last_payment_timestamp_label'), 'flex' : 1,
+                       'primary' : false, 'hidden' : true, 'render' : function(my) { return util.date.formatted_date( my.mbts.last_payment_ts(), "" ); }
+               },
+               {
+                       'persist' : 'hidden width ordinal', 'id' : 'xact_start', 'label' : commonStrings.getString('staff.mbts_xact_start_label'), 'flex' : 1,
+                       'primary' : false, 'hidden' : false, 'render' : function(my) { return my.mbts.xact_start() ? my.mbts.xact_start().toString().substr(0,10) : ""; }
+               },
+               {
+                       'persist' : 'hidden width ordinal', 'id' : 'xact_finish', 'label' : commonStrings.getString('staff.mbts_xact_finish_label'), 'flex' : 1,
+                       'primary' : false, 'hidden' : false, 'render' : function(my) { return my.mbts.xact_finish() ? my.mbts.xact_finish().toString().substr(0,10) : ""; }
+               },
+       ];
+       for (var i = 0; i < c.length; i++) {
+               if (modify[ c[i].id ]) {
+                       for (var j in modify[ c[i].id ]) {
+                               c[i][j] = modify[ c[i].id ][j];
+                       }
+               }
+       }
+       if (params) {
+               if (params.just_these) {
+                       JSAN.use('util.functional');
+                       var new_c = [];
+                       for (var i = 0; i < params.just_these.length; i++) {
+                               var x = util.functional.find_list(c,function(d){return(d.id==params.just_these[i]);});
+                               new_c.push( function(y){ return y; }( x ) );
+                       }
+                       c = new_c;
+               }
+               if (params.except_these) {
+                       JSAN.use('util.functional');
+                       var new_c = [];
+                       for (var i = 0; i < c.length; i++) {
+                               var x = util.functional.find_list(params.except_these,function(d){return(d==c[i].id);});
+                               if (!x) new_c.push(c[i]);
+                       }
+                       c = new_c;
+               }
+       }
+       return c.sort( function(a,b) { if (a.label < b.label) return -1; if (a.label > b.label) return 1; return 0; } );
+}
+
+patron.util.mb_columns = function(modify,params) {
+
+       JSAN.use('OpenILS.data'); var data = new OpenILS.data(); data.init({'via':'stash'});
+       JSAN.use('util.money'); JSAN.use('util.date');
+
+    var commonStrings = document.getElementById('commonStrings');
+
+       var c = [
+               {
+                       'persist' : 'hidden width ordinal', 'id' : 'id', 'label' : commonStrings.getString('staff.mb_id_label'), 'flex' : 1,
+                       'primary' : false, 'hidden' : true, 'render' : function(my) { return my.mb.id(); }
+               },
+               {
+                       'persist' : 'hidden width ordinal', 'id' : 'voided', 'label' : commonStrings.getString('staff.mb_voided_label'), 'flex' : 1,
+                       'primary' : false, 'hidden' : false, 'render' : function(my) { return get_bool( my.mb.voided() ) ? "Yes" : "No"; }
+               },
+               {
+                       'persist' : 'hidden width ordinal', 'id' : 'voider', 'label' : commonStrings.getString('staff.mb_voider_label'), 'flex' : 1,
+                       'primary' : false, 'hidden' : true, 'render' : function(my) { return my.mb.voider() ? "Id = " + my.mb.voider() : ""; }
+               },
+               {
+                       'persist' : 'hidden width ordinal', 'id' : 'void_time', 'label' : commonStrings.getString('staff.mb_void_time_label'), 'flex' : 1,
+                       'primary' : false, 'hidden' : true, 'render' : function(my) { return my.mb.void_time(); }
+               },
+               {
+                       'persist' : 'hidden width ordinal', 'id' : 'amount', 'label' : commonStrings.getString('staff.mb_amount_label'), 'flex' : 1,
+                       'primary' : false, 'hidden' : false, 'render' : function(my) { return util.money.sanitize( my.mb.amount() ); },
+                       'sort_type' : 'money'
+               },
+               {
+                       'persist' : 'hidden width ordinal', 'id' : 'billing_type', 'label' : commonStrings.getString('staff.mb_billing_type_label'), 'flex' : 1,
+                       'primary' : false, 'hidden' : false, 'render' : function(my) { return my.mb.billing_type(); }
+               },
+               {
+                       'persist' : 'hidden width ordinal', 'id' : 'billing_ts', 'label' : commonStrings.getString('staff.mb_billing_ts_label'), 'flex' : 1,
+                       'primary' : false, 'hidden' : false, 'render' : function(my) { return util.date.formatted_date( my.mb.billing_ts(), "" ); }
+               },
+               {
+                       'persist' : 'hidden width ordinal', 'id' : 'note', 'label' : commonStrings.getString('staff.mb_note_label'), 'flex' : 2,
+                       'primary' : false, 'hidden' : false, 'render' : function(my) { return my.mb.note(); }
+               },
+               {
+                       'persist' : 'hidden width ordinal', 'id' : 'xact', 'label' : commonStrings.getString('staff.mb_xact_label'), 'flex' : 1,
+                       'primary' : false, 'hidden' : true, 'render' : function(my) { return my.mb.xact(); }
+               },
+       ];
+       for (var i = 0; i < c.length; i++) {
+               if (modify[ c[i].id ]) {
+                       for (var j in modify[ c[i].id ]) {
+                               c[i][j] = modify[ c[i].id ][j];
+                       }
+               }
+       }
+       if (params) {
+               if (params.just_these) {
+                       JSAN.use('util.functional');
+                       var new_c = [];
+                       for (var i = 0; i < params.just_these.length; i++) {
+                               var x = util.functional.find_list(c,function(d){return(d.id==params.just_these[i]);});
+                               new_c.push( function(y){ return y; }( x ) );
+                       }
+                       c = new_c;
+               }
+               if (params.except_these) {
+                       JSAN.use('util.functional');
+                       var new_c = [];
+                       for (var i = 0; i < c.length; i++) {
+                               var x = util.functional.find_list(params.except_these,function(d){return(d==c[i].id);});
+                               if (!x) new_c.push(c[i]);
+                       }
+                       c = new_c;
+               }
+
+       }
+       return c.sort( function(a,b) { if (a.label < b.label) return -1; if (a.label > b.label) return 1; return 0; } );
+}
+
+patron.util.mp_columns = function(modify,params) {
+
+       JSAN.use('OpenILS.data'); var data = new OpenILS.data(); data.init({'via':'stash'});
+       JSAN.use('util.money'); JSAN.use('util.date'); JSAN.use('patron.util');
+
+    var commonStrings = document.getElementById('commonStrings');
+
+       var c = [
+               {
+                       'persist' : 'hidden width ordinal', 'id' : 'mp_id', 'label' : commonStrings.getString('staff.mp_id_label'), 'flex' : 1,
+                       'primary' : false, 'hidden' : true, 'render' : function(my) { return my.mp.id(); }
+               },
+               {
+                       'persist' : 'hidden width ordinal', 'id' : 'mp_amount', 'label' : commonStrings.getString('staff.mp_amount_label'), 'flex' : 1,
+                       'primary' : false, 'hidden' : false, 'render' : function(my) { return util.money.sanitize( my.mp.amount() ); },
+                       'sort_type' : 'money'
+               },
+               {
+                       'persist' : 'hidden width ordinal', 'id' : 'mp_payment_type', 'label' : commonStrings.getString('staff.mp_payment_type_label'), 'flex' : 1,
+                       'primary' : false, 'hidden' : false, 'render' : function(my) { return my.mp.payment_type(); }
+               },
+               {
+                       'persist' : 'hidden width ordinal', 'id' : 'mp_payment_ts', 'label' : commonStrings.getString('staff.mp_payment_timestamp_label'), 'flex' : 1,
+                       'primary' : false, 'hidden' : false, 'render' : function(my) { return util.date.formatted_date( my.mp.payment_ts(), "" ); }
+               },
+               {
+                       'persist' : 'hidden width ordinal', 'id' : 'mp_note', 'label' : commonStrings.getString('staff.mp_note_label'), 'flex' : 2,
+                       'primary' : false, 'hidden' : false, 'render' : function(my) { return my.mp.note(); }
+               },
+               {
+                       'persist' : 'hidden width ordinal', 'id' : 'mp_ws', 'label' : commonStrings.getString('staff.mp_cash_drawer_label'), 'flex' : 1,
+                       'primary' : false, 'hidden' : false, 'render' : function(my) { return my.mp.cash_drawer().name(); }
+               },
+               {
+                       'persist' : 'hidden width ordinal', 'id' : 'mp_staff', 'label' : commonStrings.getString('staff.mp_accepting_usr_label'), 'flex' : 1,
+                       'primary' : false, 'hidden' : false, 'render' : function(my) { var s = my.mp.accepting_usr(); if (s && typeof s != "object") s = patron.util.retrieve_fleshed_au_via_id(ses(),s); return s.family_name() + " (" + s.card().barcode() + ") @ " + data.hash.aou[ s.home_ou() ].shortname(); }
+               },
+               {
+                       'persist' : 'hidden width ordinal', 'id' : 'mp_xact', 'label' : commonStrings.getString('staff.mp_xact_label'), 'flex' : 1,
+                       'primary' : false, 'hidden' : true, 'render' : function(my) { return my.mp.xact(); }
+               },
+       ];
+       for (var i = 0; i < c.length; i++) {
+               if (modify[ c[i].id ]) {
+                       for (var j in modify[ c[i].id ]) {
+                               c[i][j] = modify[ c[i].id ][j];
+                       }
+               }
+       }
+       if (params) {
+               if (params.just_these) {
+                       JSAN.use('util.functional');
+                       var new_c = [];
+                       for (var i = 0; i < params.just_these.length; i++) {
+                               var x = util.functional.find_list(c,function(d){return(d.id==params.just_these[i]);});
+                               new_c.push( function(y){ return y; }( x ) );
+                       }
+                       c = new_c;
+               }
+               if (params.except_these) {
+                       JSAN.use('util.functional');
+                       var new_c = [];
+                       for (var i = 0; i < c.length; i++) {
+                               var x = util.functional.find_list(params.except_these,function(d){return(d==c[i].id);});
+                               if (!x) new_c.push(c[i]);
+                       }
+                       c = new_c;
+               }
+
+       }
+       return c.sort( function(a,b) { if (a.label < b.label) return -1; if (a.label > b.label) return 1; return 0; } );
+}
+
+patron.util.ausp_columns = function(modify,params) {
+
+       JSAN.use('OpenILS.data'); var data = new OpenILS.data(); data.init({'via':'stash'});
+    JSAN.use('util.functional');
+
+    var commonStrings = document.getElementById('commonStrings');
+
+       var c = [
+               {
+                       'persist' : 'hidden width ordinal', 'id' : 'csp_id', 'label' : commonStrings.getString('staff.csp_id_label'), 'flex' : 1,
+                       'primary' : false, 'hidden' : true, 'render' : function(my) { return my.csp.id(); }
+               },
+               {
+                       'persist' : 'hidden width ordinal', 'id' : 'csp_name', 'label' : commonStrings.getString('staff.csp_name_label'), 'flex' : 1,
+                       'primary' : false, 'hidden' : false, 'render' : function(my) { return my.csp.name(); }
+               },
+               {
+                       'persist' : 'hidden width ordinal', 'id' : 'csp_label', 'label' : commonStrings.getString('staff.csp_label_label'), 'flex' : 1,
+                       'primary' : false, 'hidden' : false, 'render' : function(my) { return my.csp.label(); }
+               },
+               {
+                       'persist' : 'hidden width ordinal', 'id' : 'csp_block_list', 'label' : commonStrings.getString('staff.csp_block_list_label'), 'flex' : 1,
+                       'primary' : false, 'hidden' : true, 'render' : function(my) { return my.csp.block_list(); }
+               },
+               {
+                       'persist' : 'hidden width ordinal', 'id' : 'csp_block_circ', 'label' : commonStrings.getString('staff.csp_block_circ_label'), 'flex' : 1,
+                       'primary' : false, 'hidden' : true, 'render' : function(my) { 
+                return String( my.csp.block_list() ).match('CIRC') ? commonStrings.getString('staff.csp_block_circ_yes') : commonStrings.getString('staff.csp_block_circ_no'); 
+            }
+               },
+               {
+                       'persist' : 'hidden width ordinal', 'id' : 'csp_block_renew', 'label' : commonStrings.getString('staff.csp_block_renew_label'), 'flex' : 1,
+                       'primary' : false, 'hidden' : true, 'render' : function(my) { 
+                return String( my.csp.block_list() ).match('RENEW') ? commonStrings.getString('staff.csp_block_renew_yes') : commonStrings.getString('staff.csp_block_renew_no'); 
+
+            }
+               },
+               {
+                       'persist' : 'hidden width ordinal', 'id' : 'csp_block_hold', 'label' : commonStrings.getString('staff.csp_block_hold_label'), 'flex' : 1,
+                       'primary' : false, 'hidden' : true, 'render' : function(my) { 
+                return String( my.csp.block_list() ).match('HOLD') ?  commonStrings.getString('staff.csp_block_hold_yes') : commonStrings.getString('staff.csp_block_hold_no'); 
+            }
+               },
+               {
+                       'persist' : 'hidden width ordinal', 'id' : 'ausp_staff', 'label' : commonStrings.getString('staff.ausp_staff_label'), 'flex' : 1,
+                       'primary' : false, 'hidden' : true, 'render' : function(my) { 
+                return my.ausp ? my.ausp.staff() : '';
+            }
+        },
+               {
+                       'persist' : 'hidden width ordinal', 'id' : 'ausp_set_date', 'label' : commonStrings.getString('staff.ausp_set_date_label'), 'flex' : 1,
+                       'primary' : false, 'hidden' : false, 'render' : function(my) { 
+                return my.ausp ? my.ausp.set_date() : '';
+            }
+        },
+               {
+                       'persist' : 'hidden width ordinal', 'id' : 'ausp_note', 'label' : commonStrings.getString('staff.ausp_note_label'), 'flex' : 1,
+                       'primary' : false, 'hidden' : false, 'render' : function(my) { 
+                return my.ausp ? my.ausp.note() : '';
+            }
+        },
+               {
+                       'persist' : 'hidden width ordinal', 'id' : 'ausp_org_unit', 'label' : commonStrings.getString('staff.ausp_org_unit_label'), 'flex' : 1,
+                       'primary' : false, 'hidden' : false, 'render' : function(my) { 
+                return my.ausp ? data.hash.aou[ my.ausp.org_unit() ].shortname() : '';
+            }
+        }
+       ];
+       for (var i = 0; i < c.length; i++) {
+               if (modify[ c[i].id ]) {
+                       for (var j in modify[ c[i].id ]) {
+                               c[i][j] = modify[ c[i].id ][j];
+                       }
+               }
+       }
+       if (params) {
+               if (params.just_these) {
+                       var new_c = [];
+                       for (var i = 0; i < params.just_these.length; i++) {
+                               var x = util.functional.find_list(c,function(d){return(d.id==params.just_these[i]);});
+                               new_c.push( function(y){ return y; }( x ) );
+                       }
+                       c = new_c;
+               }
+               if (params.except_these) {
+                       var new_c = [];
+                       for (var i = 0; i < c.length; i++) {
+                               var x = util.functional.find_list(params.except_these,function(d){return(d==c[i].id);});
+                               if (!x) new_c.push(c[i]);
+                       }
+                       c = new_c;
+               }
+
+       }
+       return c.sort( function(a,b) { if (a.label < b.label) return -1; if (a.label > b.label) return 1; return 0; } );
+}
+
+
+patron.util.columns = function(modify,params) {
+       
+       JSAN.use('OpenILS.data'); var data = new OpenILS.data(); data.init({'via':'stash'});
+
+    var commonStrings = document.getElementById('commonStrings');
+
+       var c = [
+               {
+                       'persist' : 'hidden width ordinal', 'id' : 'barcode', 'label' : commonStrings.getString('staff.card_barcode_label'), 'flex' : 1, 
+                       'primary' : false, 'hidden' : true, 'render' : function(my) { return my.au.card().barcode(); }
+               },
+               { 
+                       'persist' : 'hidden width ordinal', 'id' : 'usrname', 'label' : commonStrings.getString('staff.au_usrname_label'), 'flex' : 1, 
+                       'primary' : false, 'hidden' : true, 'render' : function(my) { return my.au.usrname(); }
+               },
+               { 
+                       'persist' : 'hidden width ordinal', 'id' : 'profile', 'label' : commonStrings.getString('staff.au_profile_label'), 'flex' : 1, 
+                       'primary' : false, 'hidden' : true, 'render' : function(my) { return data.hash.pgt[ my.au.profile() ].name(); }
+               },
+               { 
+                       'persist' : 'hidden width ordinal', 'id' : 'active', 'label' : commonStrings.getString('staff.au_active_label'), 'flex' : 1, 
+                       'primary' : false, 'hidden' : true, 'render' : function(my) { return get_bool( my.au.active() ) ? "Yes" : "No"; }
+               },
+               {
+                       'persist' : 'hidden width ordinal', 'id' : 'barred', 'label' : commonStrings.getString('staff.au_barred_label'), 'flex' : 1,
+                       'primary' : false, 'hidden' : true, 'render' : function(my) { return get_bool( my.au.barred() ) ? "Yes" : "No"; }
+               },
+               { 
+                       'persist' : 'hidden width ordinal', 'id' : 'id', 'label' : document.getElementById('commonStrings').getString('staff.au_id_label'), 'flex' : 1, 
+                       'primary' : false, 'hidden' : true, 'render' : function(my) { return my.au.id(); }
+               },
+               { 
+                       'persist' : 'hidden width ordinal', 'id' : 'prefix', 'label' : document.getElementById('commonStrings').getString('staff.au_name_prefix_label'), 'flex' : 1, 
+                       'primary' : false, 'hidden' : true, 'render' : function(my) { return my.au.prefix(); }
+               },
+               { 
+                       'persist' : 'hidden width ordinal', 'id' : 'family_name', 'label' : document.getElementById('commonStrings').getString('staff.au_family_name_label'), 'flex' : 1, 
+                       'primary' : false, 'hidden' : true, 'render' : function(my) { return my.au.family_name(); }
+               },
+               { 
+                       'persist' : 'hidden width ordinal', 'id' : 'first_given_name', 'label' : document.getElementById('commonStrings').getString('staff.au_first_given_name_label'), 'flex' : 1, 
+                       'primary' : false, 'hidden' : true, 'render' : function(my) { return my.au.first_given_name(); }
+               },
+               { 
+                       'persist' : 'hidden width ordinal', 'id' : 'second_given_name', 'label' : document.getElementById('commonStrings').getString('staff.au_second_given_name_label'), 'flex' : 1, 
+                       'primary' : false, 'hidden' : true, 'render' : function(my) { return my.au.second_given_name(); }
+               },
+               { 
+                       'persist' : 'hidden width ordinal', 'id' : 'suffix', 'label' : document.getElementById('commonStrings').getString('staff.au_name_suffix_label'), 'flex' : 1, 
+                       'primary' : false, 'hidden' : true, 'render' : function(my) { return my.au.suffix(); }
+               },
+               { 
+                       'persist' : 'hidden width ordinal', 'id' : 'alert_message', 'label' : commonStrings.getString('staff.au_alert_message_label'), 'flex' : 1, 
+                       'primary' : false, 'hidden' : true, 'render' : function(my) { return my.au.alert_message(); }
+               },
+               { 
+                       'persist' : 'hidden width ordinal', 'id' : 'claims_returned_count', 'label' : commonStrings.getString('staff.au_claims_returned_count_label'), 'flex' : 1, 
+                       'primary' : false, 'hidden' : true, 'render' : function(my) { return my.au.claims_returned_count(); },
+                       'sort_type' : 'number'
+               },
+               { 
+                       'persist' : 'hidden width ordinal', 'id' : 'create_date', 'label' : commonStrings.getString('staff.au_create_date_label'), 'flex' : 1, 
+                       'primary' : false, 'hidden' : true, 'render' : function(my) { return my.au.create_date(); }
+               },
+               { 
+                       'persist' : 'hidden width ordinal', 'id' : 'expire_date', 'label' : commonStrings.getString('staff.au_expire_date_label'), 'flex' : 1, 
+                       'primary' : false, 'hidden' : true, 'render' : function(my) { return my.au.expire_date().substr(0,10); }
+               },
+               { 
+                       'persist' : 'hidden width ordinal', 'id' : 'home_ou', 'label' : commonStrings.getString('staff.au_home_library_label'), 'flex' : 1, 
+                       'primary' : false, 'hidden' : true, 'render' : function(my) { return data.hash.aou[ my.au.home_ou() ].shortname(); }
+               },
+               { 
+                       'persist' : 'hidden width ordinal', 'id' : 'home_ou_fullname', 'label' : commonStrings.getString('staff.au_home_library_fullname_label'), 'flex' : 1, 
+                       'primary' : false, 'hidden' : true, 'render' : function(my) { return data.hash.aou[ my.au.home_ou() ].name(); }
+               },
+               { 
+                       'persist' : 'hidden width ordinal', 'id' : 'credit_forward_balance', 'label' : commonStrings.getString('staff.au_credit_forward_balance_label'), 'flex' : 1, 
+                       'primary' : false, 'hidden' : true, 'render' : function(my) { return my.au.credit_forward_balance(); },
+                       'sort_type' : 'money'
+               },
+               { 
+                       'persist' : 'hidden width ordinal', 'id' : 'day_phone', 'label' : commonStrings.getString('staff.au_day_phone_label'), 'flex' : 1, 
+                       'primary' : false, 'hidden' : true, 'render' : function(my) { return my.au.day_phone(); }
+               },
+               { 
+                       'persist' : 'hidden width ordinal', 'id' : 'evening_phone', 'label' : commonStrings.getString('staff.au_evening_phone_label'), 'flex' : 1, 
+                       'primary' : false, 'hidden' : true, 'render' : function(my) { return my.au.evening_phone(); }
+               },
+               { 
+                       'persist' : 'hidden width ordinal', 'id' : 'other_phone', 'label' : commonStrings.getString('staff.au_other_phone_label'), 'flex' : 1, 
+                       'primary' : false, 'hidden' : true, 'render' : function(my) { return my.au.other_phone(); }
+               },
+               { 
+                       'persist' : 'hidden width ordinal', 'id' : 'email', 'label' : commonStrings.getString('staff.au_email_label'), 'flex' : 1, 
+                       'primary' : false, 'hidden' : true, 'render' : function(my) { return my.au.email(); }
+               },
+               { 
+                       'persist' : 'hidden width ordinal', 'id' : 'alias', 'label' : commonStrings.getString('staff.au_alias_label'), 'flex' : 1, 
+                       'primary' : false, 'hidden' : true, 'render' : function(my) { return my.au.alias(); }
+               },
+               { 
+                       'persist' : 'hidden width ordinal', 'id' : 'dob', 'label' : commonStrings.getString('staff.au_birth_date_label'), 'flex' : 1, 
+                       'primary' : false, 'hidden' : true, 'render' : function(my) { return my.au.dob().substr(0,10); }
+               },
+               { 
+                       'persist' : 'hidden width ordinal', 'id' : 'ident_type', 'label' : commonStrings.getString('staff.au_ident_type_label'), 'flex' : 1, 
+                       'primary' : false, 'hidden' : true, 'render' : function(my) { return data.hash.cit[ my.au.ident_type() ].name(); }
+               },
+               { 
+                       'persist' : 'hidden width ordinal', 'id' : 'ident_value', 'label' : commonStrings.getString('staff.au_ident_value_label'), 'flex' : 1, 
+                       'primary' : false, 'hidden' : true, 'render' : function(my) { return my.au.ident_value(); }
+               },
+               { 
+                       'persist' : 'hidden width ordinal', 'id' : 'ident_type2', 'label' : commonStrings.getString('staff.au_ident_type2_label'), 'flex' : 1, 
+                       'primary' : false, 'hidden' : true, 'render' : function(my) { return data.hash.cit[ my.au.ident_type2() ].name(); }
+               },
+               { 
+                       'persist' : 'hidden width ordinal', 'id' : 'ident_value2', 'label' : commonStrings.getString('staff.au_ident_value2_label'), 'flex' : 1, 
+                       'primary' : false, 'hidden' : true, 'render' : function(my) { return my.au.ident_value2(); }
+               },
+               { 
+                       'persist' : 'hidden width ordinal', 'id' : 'net_access_level', 'label' : commonStrings.getString('staff.au_net_access_level_label'), 'flex' : 1, 
+                       'primary' : false, 'hidden' : true, 'render' : function(my) { return my.au.net_access_level(); }
+               },
+               { 
+                       'persist' : 'hidden width ordinal', 'id' : 'master_account', 'label' : commonStrings.getString('staff.au_master_account_label'), 'flex' : 1, 
+                       'primary' : false, 'hidden' : true, 'render' : function(my) { return get_bool( my.au.master_account() ) ? "Yes" : "No"; }
+               },
+               { 
+                       'persist' : 'hidden width ordinal', 'id' : 'usrgroup', 'label' : commonStrings.getString('staff.au_group_id_label'), 'flex' : 1, 
+                       'primary' : false, 'hidden' : true, 'render' : function(my) { return my.au.usrgroup(); }
+               },
+       ];
+       for (var i = 0; i < c.length; i++) {
+               if (modify[ c[i].id ]) {
+                       for (var j in modify[ c[i].id ]) {
+                               c[i][j] = modify[ c[i].id ][j];
+                       }
+               }
+       }
+       if (params) {
+               if (params.just_these) {
+                       JSAN.use('util.functional');
+                       var new_c = [];
+                       for (var i = 0; i < params.just_these.length; i++) {
+                               var x = util.functional.find_list(c,function(d){return(d.id==params.just_these[i]);});
+                               new_c.push( function(y){ return y; }( x ) );
+                       }
+                       c = new_c;
+               }
+               if (params.except_these) {
+                       JSAN.use('util.functional');
+                       var new_c = [];
+                       for (var i = 0; i < c.length; i++) {
+                               var x = util.functional.find_list(params.except_these,function(d){return(d==c[i].id);});
+                               if (!x) new_c.push(c[i]);
+                       }
+                       c = new_c;
+               }
+
+       }
+       return c.sort( function(a,b) { if (a.label < b.label) return -1; if (a.label > b.label) return 1; return 0; } );
+}
+
+patron.util.std_map_row_to_columns = function(error_value) {
+       return function(row,cols) {
+               // row contains { 'my' : { 'au' : {} } }
+               // cols contains all of the objects listed above in columns
+               
+               var obj = {}; obj.OpenILS = {}; 
+               JSAN.use('util.error'); obj.error = new util.error();
+               JSAN.use('OpenILS.data'); obj.OpenILS.data = new OpenILS.data(); obj.OpenILS.data.init({'via':'stash'});
+               JSAN.use('util.date'); JSAN.use('util.money');
+
+               var my = row.my;
+               var values = [];
+               var cmd = '';
+               try { 
+                       for (var i = 0; i < cols.length; i++) {
+                               switch (typeof cols[i].render) {
+                                       case 'function': try { values[i] = cols[i].render(my); } catch(E) { values[i] = error_value; obj.error.sdump('D_COLUMN_RENDER_ERROR',E); } break;
+                                       case 'string' : cmd += 'try { ' + cols[i].render + '; values['+i+'] = v; } catch(E) { values['+i+'] = error_value; }'; break;
+                                       default: cmd += 'values['+i+'] = "??? '+(typeof cols[i].render)+'"; ';
+                               }
+                       }
+                       if (cmd) eval( cmd );
+               } catch(E) {
+                       obj.error.sdump('D_WARN','map_row_to_column: ' + E);
+                       if (error_value) { value = error_value; } else { value = '   ' };
+               }
+               return values;
+       }
+}
+
+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',
+               [ session, id ],
+               f
+       );
+       return patron_obj;
+}
+
+patron.util.retrieve_name_via_id = function(session, id) {
+       JSAN.use('util.network');
+       var network = new util.network();
+       var parts = network.simple_request(
+               'BLOB_AU_PARTS_RETRIEVE',
+               [ session, id, ['family_name', 'first_given_name', 'second_given_name', 'home_ou' ] ]
+       );
+       return parts;
+}
+
+patron.util.retrieve_fleshed_au_via_id = function(session, id) {
+       JSAN.use('util.network');
+       var network = new util.network();
+       var patron_obj = network.simple_request(
+               'FM_AU_FLESHED_RETRIEVE_VIA_ID',
+               [ session, id ]
+       );
+       patron.util.set_penalty_css(patron_obj);
+       return patron_obj;
+}
+
+patron.util.retrieve_fleshed_au_via_barcode = function(session, id) {
+       JSAN.use('util.network');
+       var network = new util.network();
+       var patron_obj = network.simple_request(
+               'FM_AU_RETRIEVE_VIA_BARCODE.authoritative',
+               [ session, id ]
+       );
+       patron.util.set_penalty_css(patron_obj);
+       return patron_obj;
+}
+
+var TIME = { minute : 60, hour : 60*60, day : 60*60*24, year : 60*60*24*365 };
+
+patron.util.set_penalty_css = function(patron) {
+       try {
+                                                       removeCSSClass(document.documentElement,'PATRON_HAS_BILLS');
+                                                       removeCSSClass(document.documentElement,'PATRON_HAS_OVERDUES');
+                                                       removeCSSClass(document.documentElement,'PATRON_HAS_NOTES');
+                                                       removeCSSClass(document.documentElement,'PATRON_EXCEEDS_CHECKOUT_COUNT');
+                                                       removeCSSClass(document.documentElement,'PATRON_EXCEEDS_OVERDUE_COUNT');
+                                                       removeCSSClass(document.documentElement,'PATRON_EXCEEDS_FINES');
+                                                       removeCSSClass(document.documentElement,'NO_PENALTIES');
+                                                       removeCSSClass(document.documentElement,'ONE_PENALTY');
+                                                       removeCSSClass(document.documentElement,'MULTIPLE_PENALTIES');
+                                                       removeCSSClass(document.documentElement,'PATRON_HAS_ALERT');
+                                                       removeCSSClass(document.documentElement,'PATRON_BARRED');
+                                                       removeCSSClass(document.documentElement,'PATRON_INACTIVE');
+                                                       removeCSSClass(document.documentElement,'PATRON_EXPIRED');
+                                                       removeCSSClass(document.documentElement,'PATRON_HAS_INVALID_DOB');
+                                                       removeCSSClass(document.documentElement,'PATRON_HAS_INVALID_ADDRESS');
+                                                       removeCSSClass(document.documentElement,'PATRON_AGE_GE_65');
+                                                       removeCSSClass(document.documentElement,'PATRON_AGE_LT_65');
+                                                       removeCSSClass(document.documentElement,'PATRON_AGE_GE_24');
+                                                       removeCSSClass(document.documentElement,'PATRON_AGE_LT_24');
+                                                       removeCSSClass(document.documentElement,'PATRON_AGE_GE_21');
+                                                       removeCSSClass(document.documentElement,'PATRON_AGE_LT_21');
+                                                       removeCSSClass(document.documentElement,'PATRON_AGE_GE_18');
+                                                       removeCSSClass(document.documentElement,'PATRON_AGE_LT_18');
+                                                       removeCSSClass(document.documentElement,'PATRON_AGE_GE_13');
+                                                       removeCSSClass(document.documentElement,'PATRON_AGE_LT_13');
+                                                       removeCSSClass(document.documentElement,'PATRON_NET_ACCESS_1');
+                                                       removeCSSClass(document.documentElement,'PATRON_NET_ACCESS_2');
+                                                       removeCSSClass(document.documentElement,'PATRON_NET_ACCESS_3');
+
+               JSAN.use('util.network'); var net = new util.network();
+               net.simple_request('FM_MOUS_RETRIEVE.authoritative',[ ses(), patron.id() ], function(req) {
+                       if (req.getResultObject().balance_owed() > 0) addCSSClass(document.documentElement,'PATRON_HAS_BILLS');
+               });
+               net.simple_request('FM_CIRC_COUNT_RETRIEVE_VIA_USER.authoritative',[ ses(), patron.id() ], function(req) {
+                       try {
+                               var co = req.getResultObject();
+                               if (co.overdue > 0 || co.long_overdue > 0) addCSSClass(document.documentElement,'PATRON_HAS_OVERDUES');
+                       } catch(E) {
+                               alert(E);
+                       }
+               });
+               net.simple_request('FM_AUN_RETRIEVE_ALL.authoritative',[ ses(), { 'patronid' : patron.id() } ], function(req) {
+                       var notes = req.getResultObject();
+                       if (notes.length > 0) addCSSClass(document.documentElement,'PATRON_HAS_NOTES');
+               });
+
+               /*
+               JSAN.use('OpenILS.data'); var data = new OpenILS.data(); data.init({'via':'stash'});
+               data.last_patron = patron.id(); data.stash('last_patron');
+               */
+
+               var penalties = patron.standing_penalties();
+               for (var i = 0; i < penalties.length; i++) {
+                       /* this comes from /opac/common/js/utils.js */
+                       addCSSClass(document.documentElement,penalties[i].standing_penalty().name());
+               }
+
+               switch(penalties.length) {
+                       case 0: addCSSClass(document.documentElement,'NO_PENALTIES'); break;
+                       case 1: addCSSClass(document.documentElement,'ONE_PENALTY'); break;
+                       default: addCSSClass(document.documentElement,'MULTIPLE_PENALTIES'); break;
+               }
+
+               if (patron.alert_message()) {
+                       addCSSClass(document.documentElement,'PATRON_HAS_ALERT');
+               }
+
+               if (get_bool( patron.barred() )) {
+                       addCSSClass(document.documentElement,'PATRON_BARRED');
+               }
+
+               if (!get_bool( patron.active() )) {
+                       addCSSClass(document.documentElement,'PATRON_INACTIVE');
+               }
+
+               var now = new Date();
+               now = now.getTime()/1000;
+
+               var expire_parts = patron.expire_date().substr(0,10).split('-');
+               expire_parts[1] = expire_parts[1] - 1;
+
+               var expire = new Date();
+               expire.setFullYear(expire_parts[0], expire_parts[1], expire_parts[2]);
+               expire = expire.getTime()/1000
+
+               if (expire < now) addCSSClass(document.documentElement,'PATRON_EXPIRED');
+
+               if (patron.mailing_address()) {
+                       if (!get_bool(patron.mailing_address().valid())) {
+                               addCSSClass(document.documentElement,'PATRON_HAS_INVALID_ADDRESS');
+                       }
+               }
+               if (patron.billing_address()) {
+                       if (!get_bool(patron.billing_address().valid())) {
+                               addCSSClass(document.documentElement,'PATRON_HAS_INVALID_ADDRESS');
+                       }
+               }
+
+       } catch(E) {
+               dump('patron.util.set_penalty_css: ' + E + '\n');
+               alert('patron.util.set_penalty_css: ' + E + '\n');
+       }
+}
+
+patron.util.merge = function(record_ids) {
+    var error;
+    try {
+        netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect UniversalBrowserWrite');
+        JSAN.use('util.error'); error = new util.error();
+        var top_xml = '<vbox xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" flex="1" >';
+        top_xml += '<description>' + $("patronStrings").getString('staff.patron.usr_buckets.merge_records.merge_lead') + '</description>';
+        top_xml += '<hbox>';
+        top_xml += '<button id="lead" disabled="true" label="'
+                + $("patronStrings").getString('staff.patron.usr_buckets.merge_records.button.label') + '" name="fancy_submit"/>';
+        top_xml += '<button label="' + $("patronStrings").getString('staff.patron.usr_buckets.merge_records.cancel_button.label') +'" accesskey="'
+                + $("patronStrings").getString('staff.patron.usr_buckets.merge_records.cancel_button.accesskey') +'" name="fancy_cancel"/></hbox></vbox>';
+
+        var xml = '<form xmlns="http://www.w3.org/1999/xhtml">';
+        xml += '<table><tr valign="top">';
+        for (var i = 0; i < record_ids.length; i++) {
+            xml += '<td><input value="' + $("patronStrings").getString('staff.patron.usr_buckets.merge_records.lead')
+            xml += '" id="record_' + record_ids[i] + '" type="radio" name="lead"';
+            xml += ' onclick="' + "try { var x = $('lead'); x.setAttribute('value',";
+            xml += record_ids[i] + '); x.disabled = false; } catch(E) { alert(E); }">';
+            xml += '</input>' + $("patronStrings").getFormattedString('staff.patron.usr_buckets.merge_records.lead_record_number',[record_ids[i]]) + '</td>';
+        }
+        xml += '</tr><tr valign="top">';
+        for (var i = 0; i < record_ids.length; i++) {
+            xml += '<td nowrap="nowrap"><iframe style="min-height: 1000px; min-width: 300px" flex="1" src="' + urls.XUL_PATRON_SUMMARY; 
+            xml += '?id=' + record_ids[i] + '&amp;show_name=1"/></td>';
+        }
+        xml += '</tr></table></form>';
+        JSAN.use('util.window'); var win = new util.window();
+        var fancy_prompt_data = win.open(
+            urls.XUL_FANCY_PROMPT,
+            'fancy_prompt', 'chrome,resizable,modal,width=750,height=500',
+            {
+                'top_xml' : top_xml, 'xml' : xml, 'title' : $("patronStrings").getString('staff.patron.usr_buckets.merge_records.fancy_prompt_title')
+            }
+        );
+
+        if (typeof fancy_prompt_data.fancy_status == 'undefined' || fancy_prompt_data.fancy_status == 'incomplete') {
+            alert($("patronStrings").getString('staff.patron.usr_buckets.merge_records.fancy_prompt.alert'));
+            return false;
+        }
+
+        JSAN.use('util.functional'); JSAN.use('util.network'); var network = new util.network();
+        var robj = network.simple_request('FM_AU_MERGE', 
+            [ 
+                ses(), 
+                fancy_prompt_data.lead,
+                util.functional.filter_list( record_ids,
+                    function(o) {
+                        return o != fancy_prompt_data.lead;
+                    }
+                )
+            ]
+        );
+        if (Number(robj) != 1) { throw(robj); }
+        return fancy_prompt_data.lead;
+    } catch(E) {
+               dump('patron.util.merge: ' + js2JSON(E) + '\n');
+        try { error.standard_unexpected_error_alert('Error in patron.util.merge',E); } catch(F) { alert('patron.util.merge: ' + E + '\n'); }
+        return false;
+    }
+}
+
+dump('exiting patron/util.js\n');