Wire up the Clear Shelf functionality into the Hold Shelf Browser.
authorphasefx <phasefx@dcc99617-32d9-48b4-a31d-7c20da2025e4>
Thu, 8 Apr 2010 21:51:21 +0000 (21:51 +0000)
committerphasefx <phasefx@dcc99617-32d9-48b4-a31d-7c20da2025e4>
Thu, 8 Apr 2010 21:51:21 +0000 (21:51 +0000)
The button for this enables when the View Expired On-Shelf Holds checkbox is activated.  The Clear Shelf process will cancel these holds, optionally set the status for the affected items according to an org unit setting,  and report back the needed actions for the affected items.

TODO: the ML clear_shelf_process method needs fixing where it's jumping to storage within a transaction

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

Open-ILS/web/opac/locale/en-US/lang.dtd
Open-ILS/xul/staff_client/chrome/content/main/constants.js
Open-ILS/xul/staff_client/server/circ/util.js
Open-ILS/xul/staff_client/server/locale/en-US/circ.properties
Open-ILS/xul/staff_client/server/patron/holds.js
Open-ILS/xul/staff_client/server/patron/holds_overlay.xul

index 9caa041..4788f83 100644 (file)
 <!ENTITY staff.circ.holds.set_top_of_queue.accesskey "Q">
 <!ENTITY staff.circ.holds.title_transfer.label "Transfer to Marked Title">
 <!ENTITY staff.circ.holds.title_transfer.accesskey "">
+<!ENTITY staff.circ.holds.view_expired_onshelf_holds.label "View Shelf-Expired Holds">
+<!ENTITY staff.circ.holds.view_expired_onshelf_holds.accesskey "x">
+<!ENTITY staff.circ.holds.clear_expired_onshelf_holds.label "Clear these Holds">
+<!ENTITY staff.circ.holds.clear_expired_onshelf_holds.accesskey "">
 <!ENTITY staff.circ.holds.mark_item_damaged "Mark Item Damaged">
 <!ENTITY staff.circ.holds.mark_item_damaged.accesskey "D">
 <!ENTITY staff.circ.holds.mark_item_missing "Mark Item Missing">
index c67546c..f608862 100644 (file)
@@ -66,6 +66,7 @@ const api = {
     'CHECKOUT_PERMIT' : { 'app' : 'open-ils.circ', 'method' : 'open-ils.circ.checkout.permit' },
     'CHECKOUT_RENEW' : { 'app' : 'open-ils.circ', 'method' : 'open-ils.circ.renew' },
     'CIRC_MODIFIER_LIST' : { 'app' : 'open-ils.circ', 'method' : 'open-ils.circ.circ_modifier.retrieve.all' },
+    'CLEAR_HOLD_SHELF' : { 'app' : 'open-ils.circ', 'method' : 'open-ils.circ.hold.clear_shelf.process', 'secure' : false },
     'FM_ACN_RETRIEVE' : { 'app' : 'open-ils.search', 'method' : 'open-ils.search.callnumber.retrieve', 'secure' : false },
     'FM_ACN_RETRIEVE.authoritative' : { 'app' : 'open-ils.search', 'method' : 'open-ils.search.callnumber.retrieve.authoritative', 'secure' : false },
     'FM_ACN_TREE_UPDATE' : { 'app' : 'open-ils.cat', 'method' : 'open-ils.cat.asset.volume.fleshed.batch.update' },
@@ -116,6 +117,7 @@ const api = {
     'FM_AHR_ID_LIST_PULL_LIST' : { 'app' : 'open-ils.circ', 'method' : 'open-ils.circ.hold_pull_list.id_list.retrieve', 'secure' : false },
     'FM_AHR_ONSHELF_RETRIEVE' : { 'app' : 'open-ils.circ', 'method' : 'open-ils.circ.captured_holds.on_shelf.retrieve' },
     'FM_AHR_ID_LIST_ONSHELF_RETRIEVE' : { 'app' : 'open-ils.circ', 'method' : 'open-ils.circ.captured_holds.id_list.on_shelf.retrieve', 'secure' : false },
+    'FM_AHR_ID_LIST_EXPIRED_ONSHELF_RETRIEVE' : { 'app' : 'open-ils.circ', 'method' : 'open-ils.circ.captured_holds.id_list.expired_on_shelf.retrieve', 'secure' : false },
     'FM_AHR_COUNT_RETRIEVE' : { 'app' : 'open-ils.actor', 'method' : 'open-ils.actor.user.hold_requests.count', 'cacheable' : true, 'ttl' : 60000  },
     'FM_AHR_COUNT_RETRIEVE.authoritative' : { 'app' : 'open-ils.actor', 'method' : 'open-ils.actor.user.hold_requests.count.authoritative', 'cacheable' : true, 'ttl' : 60000  },
     'FM_AHR_CANCEL' : { 'app' : 'open-ils.circ', 'method' : 'open-ils.circ.hold.cancel' },
index 0880622..ebb5082 100644 (file)
@@ -1503,6 +1503,14 @@ circ.util.hold_columns = function(modify,params) {
 
     var c = [
         {
+            'id' : 'post_clear_shelf_action',
+            'flex' : 1, 'primary' : false, 'hidden' : true, 'editable' : false, 
+            'label' : document.getElementById('circStrings').getString('staff.circ.utils.hold_post_clear_shelf_action.label'),
+            'render' : function(my) { 
+                return my.post_clear_shelf_action ? document.getElementById('circStrings').getString('staff.circ.utils.hold_post_clear_shelf_action.' + my.post_clear_shelf_action) : '';
+            }
+        },
+        {
             'persist' : 'hidden width ordinal',
             'id' : 'cancel_time',
             'label' : document.getElementById('circStrings').getString('staff.circ.utils.hold_cancel_time'),
index f7f2a08..becfa55 100644 (file)
@@ -314,6 +314,10 @@ staff.circ.utils.hold_status.2=Waiting for capture
 staff.circ.utils.hold_status.3=In-Transit
 staff.circ.utils.hold_status.4=Ready for pickup
 staff.circ.utils.hold_status.5=Reserved/Pending
+staff.circ.utils.hold_post_clear_shelf_action.label=Post-Clear
+staff.circ.utils.hold_post_clear_shelf_action.hold=Need for Hold
+staff.circ.utils.hold_post_clear_shelf_action.transit=Need for Transit
+staff.circ.utils.hold_post_clear_shelf_action.shelf=Reshelve
 staff.circ.utils.frozen=Frozen?
 staff.circ.utils.active=Active?
 staff.circ.utils.thaw_date=Activation Date
index d6aab62..13a86d8 100644 (file)
@@ -21,6 +21,9 @@ patron.holds.prototype = {
 
     'filter_lib' : null,
 
+    'expired' : false,
+    'post_clear_shelf_hold_action_map' : {},
+
     'retrieve_ids' : [],
 
     'holds_map' : {},
@@ -55,7 +58,8 @@ patron.holds.prototype = {
                 'notify_count' : { 'hidden' : false },
                 'cancel_cause' : { 'hidden' : ! ( obj.data.hash.aous['circ.holds.canceled.display_count'] || obj.data.hash.aous['circ.holds.canceled.display_age'] ) },
                 'cancel_note' : { 'hidden' :  ! ( obj.data.hash.aous['circ.holds.canceled.display_count'] || obj.data.hash.aous['circ.holds.canceled.display_age'] ) },
-                'cancel_time' : { 'hidden' :  ! ( obj.data.hash.aous['circ.holds.canceled.display_count'] || obj.data.hash.aous['circ.holds.canceled.display_age'] ) }
+                'cancel_time' : { 'hidden' :  ! ( obj.data.hash.aous['circ.holds.canceled.display_count'] || obj.data.hash.aous['circ.holds.canceled.display_age'] ) },
+                'post_clear_shelf_action' : { 'hidden' : obj.shelf ? false : true }
             }
         );
 
@@ -102,7 +106,7 @@ patron.holds.prototype = {
                                     params.row_node.setAttribute('retrieve_id',
                                         js2JSON({
                                             'copy_id':copy_id,
-                                                                                        'barcode':row.my.acp ? row.my.acp.barcode() : null,
+                                            'barcode':row.my.acp ? row.my.acp.barcode() : null,
                                             'id':row.my.ahr.id(),
                                             'type':row.my.ahr.hold_type(),
                                             'target':row.my.ahr.target(),
@@ -1158,6 +1162,56 @@ patron.holds.prototype = {
                             ev.target.setAttribute('checked',ev.target.checked);
                         }
                     ],
+                    'cmd_view_expired_onshelf_holds' : [
+                        ['command'],
+                        function(ev) {
+                            var x = document.getElementById('expired_checkbox'); // can't trust ev.explicitOriginalTarget, sometimes gives a "button"
+                            obj.expired = x.checked;
+                            obj.controller.view.cmd_clear_expired_onshelf_holds.setAttribute('disabled', !obj.expired);
+                            obj.clear_and_retrieve();
+                        }
+                    ],
+                    'cmd_clear_expired_onshelf_holds' : [
+                        ['command'],
+                        function(ev) {
+                            try {
+                                // I could put this with the "retrieval" methods, but since it has side effects, seems cleaner to invoke it here
+                                var robj = obj.network.simple_request( 'CLEAR_HOLD_SHELF', [ ses(), obj.filter_lib || obj.data.list.au[0].ws_ou() ] );
+                                if (robj == null) { robj = []; }
+                                if (typeof robj.ilsevent != 'undefined') { throw(robj); }
+                                if (typeof robj.length == 'undefined') { robj = [ robj ]; }
+
+                                // Disable anything such as filters that can have us accidentally lose these non-repeatable results
+                                var x_lib_filter_checkbox = document.getElementById('lib_filter_checkbox');
+                                if (x_lib_filter_checkbox) { x_lib_filter_checkbox.checked = false; }
+                                var x_lib_type_menu = document.getElementById('lib_type_menu');
+                                if (x_lib_type_menu) { x_lib_type_menu.disabled = true; }
+                                var x_lib_menu_placeholder = document.getElementById('lib_menu_placeholder');
+                                if (x_lib_menu_placeholder) { x_lib_menu_placeholder.firstChild.disabled = true; }
+                                obj.controller.view.cmd_view_expired_onshelf_holds.setAttribute('disabled', 'true');
+                                obj.controller.view.cmd_clear_expired_onshelf_holds.setAttribute('disabled', 'true');
+
+                                // id's in xulG.holds will prevent the normal retrieval method from firing
+                                JSAN.use('util.functional');
+                                xulG.holds = util.functional.map_list(
+                                    robj.sort(function(a,b) {
+                                        if (a.action > b.action) { return 1; }
+                                        if (a.action < b.action) { return -1; }
+                                        return 0;
+                                    }),
+                                    function (element, idx) {
+                                        obj.post_clear_shelf_hold_action_map[ element.hold_id ] = element.action; // necessary side-effect
+                                        return element.hold_id;
+                                    }
+                                );
+                                obj.clear_and_retrieve();
+                            } catch(E) {
+                                if (E.ilsevent == 5000 /* PERM_FAILURE */ ) { return; /* handled by network.js */ }
+                                obj.error.standard_unexpected_error_alert('Error in holds.js, cmd_clear_expired_onshelf_holds', E);
+                            }
+                        }
+                    ],
+
                     'cmd_search_opac' : [
                         ['command'],
                         function(ev) {
@@ -1216,12 +1270,15 @@ patron.holds.prototype = {
         var x_lib_menu_placeholder = document.getElementById('lib_menu_placeholder');
         var x_lib_filter_checkbox = document.getElementById('lib_filter_checkbox');
         var x_show_cancelled_deck = document.getElementById('show_cancelled_deck');
+        var x_clear_shelf_widgets = document.getElementById('clear_shelf_widgets');
+        var x_expired_checkbox = document.getElementById('expired_checkbox');
         switch(obj.hold_interface_type) {
             case 'shelf':
                 obj.render_lib_menus({'pickup_lib':true});
                 if (x_lib_filter_checkbox) x_lib_filter_checkbox.checked = true;
                 if (x_lib_type_menu) x_lib_type_menu.hidden = false;
                 if (x_lib_menu_placeholder) x_lib_menu_placeholder.hidden = false;
+                if (x_clear_shelf_widgets) x_clear_shelf_widgets.hidden = false;
             break;
             case 'pull' :
                 if (x_fetch_more) x_fetch_more.hidden = false;
@@ -1343,7 +1400,11 @@ patron.holds.prototype = {
                     obj.controller.view.cmd_retrieve_patron.setAttribute('hidden','false');
                 break;
                 case 'shelf' :
-                    method = 'FM_AHR_ID_LIST_ONSHELF_RETRIEVE';
+                    if (obj.expired) {
+                        method = 'FM_AHR_ID_LIST_EXPIRED_ONSHELF_RETRIEVE';
+                    } else {
+                        method = 'FM_AHR_ID_LIST_ONSHELF_RETRIEVE';
+                    }
                     params.push( obj.filter_lib || obj.data.list.au[0].ws_ou() );
                     obj.controller.view.cmd_retrieve_patron.setAttribute('hidden','false');
                 break;
@@ -1411,7 +1472,8 @@ patron.holds.prototype = {
                     {
                         'row' : {
                             'my' : {
-                                'hold_id' : hold_id
+                                'hold_id' : hold_id,
+                                'post_clear_shelf_action' : obj.post_clear_shelf_hold_action_map[ hold_id ]
                             }
                         }
                     }
index db4e5c0..c958c56 100644 (file)
         <command id="cmd_alt_view" />
         <command id="cmd_cancelled_holds_view" />
         <command id="cmd_uncancelled_holds_view" />
+        <command id="cmd_view_expired_onshelf_holds"
+            label="&staff.circ.holds.view_expired_onshelf_holds.label;"
+            accesskey="&staff.circ.holds.view_expired_onshelf_holds.accesskey;" />
+        <command id="cmd_clear_expired_onshelf_holds" disabled="true"
+            label="&staff.circ.holds.clear_expired_onshelf_holds.label;"
+            accesskey="&staff.circ.holds.clear_expired_onshelf_holds.accesskey;" />
     </commandset>
 
     <popupset id="holds_popupset">
             </menupopup>
         </menulist>
         <vbox id="lib_menu_placeholder" hidden="true"/>
+        <hbox id="clear_shelf_widgets" hidden="true">
+            <checkbox id="expired_checkbox" command="cmd_view_expired_onshelf_holds" />
+            <button id="clear_expired_btn" command="cmd_clear_expired_onshelf_holds" />
+        </hbox>
         <deck id="show_cancelled_deck" hidden="true">
             <button command="cmd_cancelled_holds_view" label="&staff.patron.holds_overlay.show_cancelled_holds.label;" accesskey="&staff.patron.holds_overlay.show_cancelled_holds.accesskey;"/>
             <button command="cmd_uncancelled_holds_view" label="&staff.patron.holds_overlay.show_uncancelled_holds.label;" accesskey="&staff.patron.holds_overlay.show_uncancelled_holds.accesskey;"/>