remove date stamp in logging, leave for development, no luck on opening script file...
authorartunit <artunit@6d9bc8c9-1ec2-4278-b937-99fde70a366f>
Thu, 1 Oct 2009 03:34:28 +0000 (03:34 +0000)
committerartunit <artunit@6d9bc8c9-1ec2-4278-b937-99fde70a366f>
Thu, 1 Oct 2009 03:34:28 +0000 (03:34 +0000)
git-svn-id: svn://svn.open-ils.org/ILS-Contrib/conifer/trunk@693 6d9bc8c9-1ec2-4278-b937-99fde70a366f

circ/circ_duration.js
circ/circ_duration_OSTMA.js
circ/circ_duration_OWA.js
circ/circ_duration_OWAL.js
circ/circ_lib.js

index 58d47bc..9a6d469 100755 (executable)
@@ -1,84 +1,87 @@
-function go(){\r
-\r
-load_lib('circ/circ_item_config.js');\r
-load_lib('JSON_v1.js');\r
-log_vars('circ_duration');\r
-\r
-var currentTime = new Date();\r
-var debugStamp = "circ" + (currentTime.getMonth() + 1) + "" +\r
-       "" + currentTime.getDate() + "" + currentTime.getFullYear() +\r
-       ": ";\r
-\r
-\r
-log_info(debugStamp + "location identified as " + currentLocation.shortname);\r
-\r
-try {   \r
-       /* load circ rules for specific institutions */\r
-       var circ_duration_institution_file = 'circ/circ_duration_' + currentLocation.shortname + '.js';\r
-       load_lib(circ_duration_institution_file);\r
-\r
-       log_error(circ_duration_institution_file);\r
-\r
-       /* if an institution specific script was loaded, then stop */\r
-       if (result.durationRule) return;\r
-} catch (e) {\r
-       // fall through to system-wide defaults\r
-       log_info("circ0814: error loading " + e);\r
-}\r
-\r
-/* treat pre-cat copies like vanilla books */\r
-if( isTrue(isPrecat) ) {\r
-       log_info("pre-cat copy getting duration defaults...");\r
-       result.durationRule                     = 'default';\r
-       result.recurringFinesRule       = 'default';\r
-       result.maxFine                          = 'default'\r
-       return;\r
-}\r
-\r
-\r
-/* grab the config from the config script */\r
-var config = getItemConfig();\r
-var itemForm   = (marcXMLDoc) ? extractFixedField(marcXMLDoc,'Form') : "";\r
-\r
-\r
-/* ----------------------------------------------------------------------------- \r
-       Now set the rule values based on the config.  If there is no configured info\r
-       on this copy, fall back on defaults.\r
-       ----------------------------------------------------------------------------- */\r
-if( config ) {\r
-\r
-       log_info("config exists");\r
-       log_debug("circ_duration found a config for the copy");\r
-       result.durationRule                     = config.durationRule;\r
-       result.recurringFinesRule       = config.recurringFinesRule;\r
-       result.maxFine                      = config.maxFine;\r
-\r
-} else {\r
-       log_info("falling back to default");\r
-\r
-       result.durationRule = 'default';\r
-       result.recurringFinesRule = 'default';\r
-       result.maxFine = 'default';\r
-}\r
-\r
-if (patronProfile == 'Faculty') {\r
-       result.durationRule = '120_days_2_renew';\r
-}\r
-if (patronProfile == 'Graduate') {\r
-       result.durationRule = '120_days_2_renew';\r
-}\r
-if (patronProfile == 'Undergraduate') {\r
-       result.durationRule = '3_weeks_2_renew';\r
-}\r
-if (patronProfile == 'Staff members') {\r
-       result.durationRule = '3_weeks_2_renew';\r
-}\r
-if (patronProfile == 'Readers') {\r
-       result.durationRule = '3_weeks_2_renew';\r
-}\r
-\r
-\r
-log_info('final duration results: ' + \r
-    result.durationRule + ' : ' + result.recurringFinesRule + ' : ' + result.maxFine );\r
-\r
-} go();\r
+function go(){
+
+load_lib('circ/circ_item_config.js');
+load_lib('JSON_v1.js');
+log_vars('circ_duration');
+
+/*
+var currentTime = new Date();
+var debugStamp = "circ" + (currentTime.getMonth() + 1) + "" +
+       "" + currentTime.getDate() + "" + currentTime.getFullYear() +
+       ": ";
+*/
+
+
+//log_info(debugStamp + "location identified as " + currentLocation.shortname);
+
+try {   
+       /* load circ rules for specific institutions */
+       var circ_duration_institution_file = 'circ/circ_duration_' + currentLocation.shortname + '.js';
+       log_info('loading ' + circ_duration_institution_file);
+       load_lib(circ_duration_institution_file);
+
+       log_error(circ_duration_institution_file);
+
+       /* if an institution specific script was loaded, then stop */
+       if (result.durationRule) return;
+} catch (e) {
+       // fall through to system-wide defaults
+       log_info("error loading " + e);
+}
+
+/* treat pre-cat copies like vanilla books */
+if( isTrue(isPrecat) ) {
+       //log_info("pre-cat copy getting duration defaults...");
+       result.durationRule                     = 'default';
+       result.recurringFinesRule       = 'default';
+       result.maxFine                          = 'default'
+       return;
+}
+
+
+/* grab the config from the config script */
+var config = getItemConfig();
+var itemForm   = (marcXMLDoc) ? extractFixedField(marcXMLDoc,'Form') : "";
+
+
+/* ----------------------------------------------------------------------------- 
+       Now set the rule values based on the config.  If there is no configured info
+       on this copy, fall back on defaults.
+       ----------------------------------------------------------------------------- */
+if( config ) {
+
+       //log_info("config exists");
+       log_debug("circ_duration found a config for the copy");
+       result.durationRule                     = config.durationRule;
+       result.recurringFinesRule       = config.recurringFinesRule;
+       result.maxFine                      = config.maxFine;
+
+} else {
+       //log_info("falling back to default");
+
+       result.durationRule = 'default';
+       result.recurringFinesRule = 'default';
+       result.maxFine = 'default';
+}
+
+if (patronProfile == 'Faculty') {
+       result.durationRule = '120_days_2_renew';
+}
+if (patronProfile == 'Graduate') {
+       result.durationRule = '120_days_2_renew';
+}
+if (patronProfile == 'Undergraduate') {
+       result.durationRule = '3_weeks_2_renew';
+}
+if (patronProfile == 'Staff members') {
+       result.durationRule = '3_weeks_2_renew';
+}
+if (patronProfile == 'Readers') {
+       result.durationRule = '3_weeks_2_renew';
+}
+
+
+log_info('final duration results: ' + 
+    result.durationRule + ' : ' + result.recurringFinesRule + ' : ' + result.maxFine );
+
+} go();
index 800684e..7b9c26c 100644 (file)
@@ -1,9 +1,11 @@
+/*
 var currentTime = new Date();
 var debugStamp = "circ_duraction_test" + (currentTime.getMonth() + 1) + "" +
         "" + currentTime.getDate() + "" + currentTime.getFullYear() +
         ": ";
+*/
 
-log_info(debugStamp + "here for OSTMA");
+log_info("here for OSTMA");
 
 /* grab the config from the config script */
 var config = getItemConfig();
index d3e6657..883e833 100644 (file)
@@ -1,97 +1,99 @@
-// circ duration rules for Windsor Leddy (OWA)\r
-\r
-/* we use a date based identifier to pick up values in the log */\r
-var currentTime = new Date();\r
-var debugStamp = "circ" + (currentTime.getMonth() + 1) + "" +\r
-        "" + currentTime.getDate() + "" + currentTime.getFullYear() +\r
-        ": ";\r
-\r
-/* set item type defaults - if the either the patron group or the circ modifier\r
-   is missing or invalid, these settings will be used */\r
-\r
-// do these first two have any significance for us?\r
-result.SIPMediaType = '001';\r
-result.magneticMedia = 'f';\r
-\r
-/* if result.durationRule is not modified for a patron group, set default\r
- * this value will be used for all circ overrides! */\r
-result.durationRule = 'non_circ';\r
-\r
-// for fines, set the most common value here\r
-result.recurringFinesRule = 'OWA_daily';\r
-result.maxFine = 'OWA_normal';\r
-\r
-/* adjust rules by patron group and circ modifier */\r
-\r
-log_info(debugStamp + 'patronProfile is ' + patronProfile + ' - modifier ' + copy.circ_modifier);\r
-\r
-if (isValidPatron(patronProfile)) {\r
-    var temp_array = patronProfile.split(" ");\r
-    var profileFirst = temp_array[0];\r
-    \r
-    switch(copy.circ_modifier) {\r
-        case 'CD MUSIC':\r
-            result.durationRule = 'OWA_audiovisual';\r
-            break;\r
-        case 'CIRC':\r
-            result.durationRule = 'OWA_' + profileFirst;\r
-            break;\r
-        case 'CIRC SHORT':\r
-            result.durationRule = 'OWA_short';\r
-            result.recurringFinesRule = 'OWA_daily_short';\r
-            result.maxFine = 'OWA_short';\r
-            break;\r
-        case 'CRC MEDIA':\r
-            result.durationRule = 'OWA_sevenday';\r
-            break;\r
-        case 'CRC SPEC':\r
-            result.durationRule = 'OWA_' + profileFirst;\r
-            break;\r
-        case 'CRC TEXT':\r
-            result.durationRule = 'OWA_' + profileFirst;\r
-            break;\r
-        case 'DOC':\r
-            result.durationRule = 'OWA_' + profileFirst;\r
-            break;\r
-        case 'DVD VIDEO':\r
-            result.durationRule = 'OWA_audiovisual';\r
-            break;\r
-        case 'MEDIA':\r
-            result.durationRule = 'OWA_' + profileFirst;\r
-            break;\r
-        case 'MFORM':\r
-            result.durationRule = 'OWA_' + profileFirst;\r
-            break;\r
-        case 'REF':\r
-            result.durationRule = 'OWA_sevenday';\r
-            break;\r
-        case 'RSV1':\r
-            result.durationRule = 'OWA_rsv_oneday';\r
-            result.recurringFinesRule = 'OWA_daily_rsv';\r
-            result.maxFine = 'OWA_rsv';\r
-            break;\r
-        case 'RSV2':\r
-            result.durationRule = 'OWA_rsv_twohour';\r
-            result.recurringFinesRule = 'OWA_hourly_rsv';\r
-            result.maxFine = 'OWA_rsv';\r
-            break;\r
-        case 'RSV3':\r
-            result.durationRule = 'OWA_rsv_threeday';\r
-            result.recurringFinesRule = 'OWA_daily_rsv';\r
-            result.maxFine = 'OWA_rsv';\r
-            break;\r
-        case 'RSV7':\r
-            result.durationRule = 'OWA_rsv_sevenday';\r
-            result.recurringFinesRule = 'OWA_daily_rsv';\r
-            result.maxFine = 'OWA_rsv';\r
-            break;\r
-        case 'SER':\r
-            result.durationRule = 'OWA_serials';\r
-            result.recurringFinesRule = 'OWA_daily_serials';\r
-            break;\r
-        case 'THESIS':\r
-            result.durationRule = 'OWA_' + profileFirst;\r
-            break;\r
-    }\r
-}\r
-log_info("circ0814 - results: " + result.durationRule);\r
+// circ duration rules for Windsor Leddy (OWA)
+
+/* we use a date based identifier to pick up values in the log */
+/*
+var currentTime = new Date();
+var debugStamp = "circ" + (currentTime.getMonth() + 1) + "" +
+        "" + currentTime.getDate() + "" + currentTime.getFullYear() +
+        ": ";
+*/
+
+/* set item type defaults - if the either the patron group or the circ modifier
+   is missing or invalid, these settings will be used */
+
+// do these first two have any significance for us?
+result.SIPMediaType = '001';
+result.magneticMedia = 'f';
+
+/* if result.durationRule is not modified for a patron group, set default
+ * this value will be used for all circ overrides! */
+result.durationRule = 'non_circ';
+
+// for fines, set the most common value here
+result.recurringFinesRule = 'OWA_daily';
+result.maxFine = 'OWA_normal';
+
+/* adjust rules by patron group and circ modifier */
+
+log_info('patronProfile is ' + patronProfile + ' - modifier ' + copy.circ_modifier);
+
+if (isValidPatron(patronProfile)) {
+    var temp_array = patronProfile.split(" ");
+    var profileFirst = temp_array[0];
+    
+    switch(copy.circ_modifier) {
+        case 'CD MUSIC':
+            result.durationRule = 'OWA_audiovisual';
+            break;
+        case 'CIRC':
+            result.durationRule = 'OWA_' + profileFirst;
+            break;
+        case 'CIRC SHORT':
+            result.durationRule = 'OWA_short';
+            result.recurringFinesRule = 'OWA_daily_short';
+            result.maxFine = 'OWA_short';
+            break;
+        case 'CRC MEDIA':
+            result.durationRule = 'OWA_sevenday';
+            break;
+        case 'CRC SPEC':
+            result.durationRule = 'OWA_' + profileFirst;
+            break;
+        case 'CRC TEXT':
+            result.durationRule = 'OWA_' + profileFirst;
+            break;
+        case 'DOC':
+            result.durationRule = 'OWA_' + profileFirst;
+            break;
+        case 'DVD VIDEO':
+            result.durationRule = 'OWA_audiovisual';
+            break;
+        case 'MEDIA':
+            result.durationRule = 'OWA_' + profileFirst;
+            break;
+        case 'MFORM':
+            result.durationRule = 'OWA_' + profileFirst;
+            break;
+        case 'REF':
+            result.durationRule = 'OWA_sevenday';
+            break;
+        case 'RSV1':
+            result.durationRule = 'OWA_rsv_oneday';
+            result.recurringFinesRule = 'OWA_daily_rsv';
+            result.maxFine = 'OWA_rsv';
+            break;
+        case 'RSV2':
+            result.durationRule = 'OWA_rsv_twohour';
+            result.recurringFinesRule = 'OWA_hourly_rsv';
+            result.maxFine = 'OWA_rsv';
+            break;
+        case 'RSV3':
+            result.durationRule = 'OWA_rsv_threeday';
+            result.recurringFinesRule = 'OWA_daily_rsv';
+            result.maxFine = 'OWA_rsv';
+            break;
+        case 'RSV7':
+            result.durationRule = 'OWA_rsv_sevenday';
+            result.recurringFinesRule = 'OWA_daily_rsv';
+            result.maxFine = 'OWA_rsv';
+            break;
+        case 'SER':
+            result.durationRule = 'OWA_serials';
+            result.recurringFinesRule = 'OWA_daily_serials';
+            break;
+        case 'THESIS':
+            result.durationRule = 'OWA_' + profileFirst;
+            break;
+    }
+}
+log_info("circ0814 - results: " + result.durationRule);
index 6e15bfb..7ea3254 100644 (file)
@@ -1,78 +1,80 @@
-// circ duration rules for Windsor Law (OWAL)\r
-\r
-/* we use a date based identifier to pick up values in the log */\r
-var currentTime = new Date();\r
-var debugStamp = "circ" + (currentTime.getMonth() + 1) + "" +\r
-        "" + currentTime.getDate() + "" + currentTime.getFullYear() +\r
-        ": ";\r
-\r
-/* set item type defaults - if the either the patron group or the circ modifier\r
- * is missing or invalid, these settings will be used */\r
-\r
-// do these first two have any significance for us?\r
-result.SIPMediaType = '001';\r
-result.magneticMedia = 'f';\r
-\r
-/* if result.durationRule is not modified for a patron group, set default\r
- * this value will be used for all circ overrides! */\r
-result.durationRule = 'non_circ';\r
-\r
-// for fines, set the most common value here\r
-result.recurringFinesRule = 'OWAL_daily';\r
-result.maxFine = 'OWAL_normal';\r
-\r
-/* adjust rules by patron group and circ modifier */\r
-\r
-log_info(debugStamp + 'patronProfile is ' + patronProfile + ' - modifier ' + copy.circ_modifier);\r
-\r
-if (isValidPatron(patronProfile)) {\r
-    var temp_array = patronProfile.split(" ");\r
-    var profileFirst = temp_array[0];\r
-\r
-    if (patronProfile == 'Readers' && patron.home_ou.shortname != 'OWAL') {\r
-        // use override value - Non-Law Readers can borrow nothing\r
-    } else if (patronProfile == 'Readers' && copy.circ_modifier == 'LAW_MONO') {\r
-        result.durationRule = 'OWAL_' + profileFirst;  // Law Readers can only borrow LAW_MONO items\r
-    } else {\r
-        switch(copy.circ_modifier) {\r
-            case 'LAW MONO':\r
-                result.durationRule = 'OWAL_' + profileFirst;\r
-                break;\r
-            case 'LAW NOCIRC':\r
-                // use override value\r
-                break;\r
-            case 'LAW RES1D':\r
-                result.durationRule = 'OWAL_rsv_oneday';\r
-                result.recurringFinesRule = 'OWAL_hourly';\r
-                break;\r
-            case 'LAW RES3D':\r
-                result.durationRule = 'OWAL_rsv_threeday';\r
-                result.recurringFinesRule = 'OWAL_hourly';\r
-                break;\r
-            case 'LAW RES3H':\r
-                result.durationRule = 'OWAL_rsv_threehour';\r
-                result.recurringFinesRule = 'OWAL_hourly';\r
-                break;\r
-            case 'LAW RES5H':\r
-                result.durationRule = 'OWAL_rsv_fivehour';\r
-                result.recurringFinesRule = 'OWAL_hourly';\r
-                break;\r
-            case 'LAW SERIAL':\r
-                // Faculty exceptions handled below\r
-                break;\r
-        }\r
-    }\r
-    //exceptions for Faculty\r
-    if (patronProfile == "Faculty") {\r
-        if (copy.circ_modifier == 'LAW SERIAL') {\r
-            result.durationRule = 'OWAL_Faculty_serials';       // all Faculty can borrow serials\r
-        }\r
-        if (patron.home_ou.shortname == 'OWAL') {\r
-            result.recurringFinesRule = 'free';                // Law Faculty pay no fines\r
-            if (copy.circ_modifier.slice(0, 6) == 'LAW RES') { \r
-                result.durationRule = 'OWAL_rsv_threeday';      // Law Faculty get all reserve items for three days\r
-            }\r
-        }\r
-    }\r
-}\r
-log_info("circ0814 - results: " + result.durationRule);\r
+// circ duration rules for Windsor Law (OWAL)
+
+/* we use a date based identifier to pick up values in the log */
+/*
+var currentTime = new Date();
+var debugStamp = "circ" + (currentTime.getMonth() + 1) + "" +
+        "" + currentTime.getDate() + "" + currentTime.getFullYear() +
+        ": ";
+*/
+
+/* set item type defaults - if the either the patron group or the circ modifier
+ * is missing or invalid, these settings will be used */
+
+// do these first two have any significance for us?
+result.SIPMediaType = '001';
+result.magneticMedia = 'f';
+
+/* if result.durationRule is not modified for a patron group, set default
+ * this value will be used for all circ overrides! */
+result.durationRule = 'non_circ';
+
+// for fines, set the most common value here
+result.recurringFinesRule = 'OWAL_daily';
+result.maxFine = 'OWAL_normal';
+
+/* adjust rules by patron group and circ modifier */
+
+log_info('patronProfile is ' + patronProfile + ' - modifier ' + copy.circ_modifier);
+
+if (isValidPatron(patronProfile)) {
+    var temp_array = patronProfile.split(" ");
+    var profileFirst = temp_array[0];
+
+    if (patronProfile == 'Readers' && patron.home_ou.shortname != 'OWAL') {
+        // use override value - Non-Law Readers can borrow nothing
+    } else if (patronProfile == 'Readers' && copy.circ_modifier == 'LAW_MONO') {
+        result.durationRule = 'OWAL_' + profileFirst;  // Law Readers can only borrow LAW_MONO items
+    } else {
+        switch(copy.circ_modifier) {
+            case 'LAW MONO':
+                result.durationRule = 'OWAL_' + profileFirst;
+                break;
+            case 'LAW NOCIRC':
+                // use override value
+                break;
+            case 'LAW RES1D':
+                result.durationRule = 'OWAL_rsv_oneday';
+                result.recurringFinesRule = 'OWAL_hourly';
+                break;
+            case 'LAW RES3D':
+                result.durationRule = 'OWAL_rsv_threeday';
+                result.recurringFinesRule = 'OWAL_hourly';
+                break;
+            case 'LAW RES3H':
+                result.durationRule = 'OWAL_rsv_threehour';
+                result.recurringFinesRule = 'OWAL_hourly';
+                break;
+            case 'LAW RES5H':
+                result.durationRule = 'OWAL_rsv_fivehour';
+                result.recurringFinesRule = 'OWAL_hourly';
+                break;
+            case 'LAW SERIAL':
+                // Faculty exceptions handled below
+                break;
+        }
+    }
+    //exceptions for Faculty
+    if (patronProfile == "Faculty") {
+        if (copy.circ_modifier == 'LAW SERIAL') {
+            result.durationRule = 'OWAL_Faculty_serials';       // all Faculty can borrow serials
+        }
+        if (patron.home_ou.shortname == 'OWAL') {
+            result.recurringFinesRule = 'free';                // Law Faculty pay no fines
+            if (copy.circ_modifier.slice(0, 6) == 'LAW RES') { 
+                result.durationRule = 'OWAL_rsv_threeday';      // Law Faculty get all reserve items for three days
+            }
+        }
+    }
+}
+log_info("circ0814 - results: " + result.durationRule);
index 99ffb13..fafbc0d 100644 (file)
-load_lib('catalog/record_type.js');\r
-load_lib('circ/circ_groups.js');\r
-load_lib('JSON_v1.js');\r
-\r
-\r
-try {\r
-       if( environment.copy ) {\r
-               environment.copy.fetchBestHold = function() {\r
-                       var key = scratchKey();\r
-                       environment.copy.__OILS_FUNC_fetch_best_hold(scratchPad(key));\r
-                       var val = getScratch(key);\r
-                       return (val) ? val : null;\r
-               }\r
-       }\r
-} catch(e) {}\r
-\r
-\r
-/* ----------------------------------------------------------------------------- \r
-       Collect all of the global variables\r
-       ----------------------------------------------------------------------------- */\r
-\r
-/* the global result object.  Any data returned to the \r
-       caller must be put into this object.  */\r
-var result                             = environment.result = {};\r
-result.event                   = 'SUCCESS';\r
-result.events                  = [];\r
-result.fatalEvents     = [];\r
-result.infoEvents              = [];\r
-\r
-\r
-/* Pull in any variables passed in from the calling process */\r
-var copy                                       = environment.copy;\r
-var volume                             = environment.volume;\r
-var title                              = environment.title;\r
-var recDescriptor              = environment.titleDescriptor;\r
-var patron                             = environment.patron;\r
-var patronItemsOut     = environment.patronItemsOut;\r
-var patronOverdueCount = environment.patronOverdueCount;\r
-var patronFines                = environment.patronFines;\r
-var isRenewal                  = environment.isRenewal;\r
-var isPrecat                   = environment.isPrecat;\r
-var currentLocation    = environment.location;\r
-var holdRequestLib     = environment.requestLib;\r
-var holdPickupLib       = environment.pickupLib; /* hold pickup lib */\r
-var requestor = environment.requestor || patron;\r
-var newHold = environment.newHold;\r
-\r
-\r
-\r
-/* create some new vars based on the data we have wherever possible */\r
-var patronProfile;\r
-var copyStatus;\r
-var marcXMLDoc;\r
-\r
-if( patron && patron.profile ) \r
-       patronProfile = patron.profile.name;\r
-if( copy && copy.status ) \r
-       copyStatus = copy.status.name;\r
-if( title && title.marc )\r
-       marcXMLDoc = new XML(title.marc);\r
-\r
-\r
-\r
-/* copy the group tree into some other useful data structures */\r
-var groupTree          = environment.groupTree;\r
-var groupList          = {};\r
-var groupIDList        = {};\r
-flattenGroupTree(groupTree);\r
-\r
-\r
-\r
-\r
-\r
-\r
-/* ----------------------------------------------------------------------------- \r
-       Define all of the utility functions\r
-       ----------------------------------------------------------------------------- */\r
-\r
-\r
-\r
-/* useful functions for creating wrappers around system functions */\r
-var __scratchKey = 0;\r
-var __SCRATCH = {};\r
-function scratchKey()          { return '_' + __scratchKey++; };\r
-function scratchPad(key)       { return '__SCRATCH.'+ key; }\r
-function getScratch(key)       { return __SCRATCH[ key ]; }\r
-function scratchClear()                { for( var o in __SCRATCH ) __SCRATCH[o] = null; }\r
-\r
-\r
-/* note: returns false if the value is 'f' or 'F' ... */\r
-function isTrue(d) {\r
-       if(     d && \r
-                       d != "0" && \r
-                       d != "f" &&\r
-                       d != "F" )\r
-                       return true;\r
-       return false;\r
-}\r
-\r
-/* Utility function for iterating over array */\r
-function iterate( arr, callback ) {\r
-       for( var i = 0; i < arr.length; i++ ) \r
-               callback(arr[i]);\r
-}\r
-\r
-\r
-/**\r
-  * returns a list of items that when passed to the callback \r
-  * 'func' returned true returns null if none were found\r
-  */\r
-function grep( arr, func ) {\r
-       var results = [];\r
-       iterate( arr, \r
-               function(d) {\r
-                       if( func(d) ) \r
-                               results.push(d);\r
-               }\r
-       );\r
-       if(results.length > 0)  \r
-               return results;\r
-       return null;\r
-}\r
-\r
-\r
-\r
-function flattenGroupTree(node) {\r
-       if(!node) return null;\r
-       groupList[node.name] = node;\r
-       groupIDList[node.id] = node;\r
-       iterate( node.children,\r
-               function(n) {\r
-                       flattenGroupTree(n);\r
-               }\r
-       );\r
-}\r
-\r
-\r
-\r
-/**\r
-  * Returns true if 'child' is equal or descends from 'parent'\r
-  * @param parent The name of the parent group\r
-  * @param child The name of the child group\r
-  */\r
-function isGroupDescendant( parent, child ) {\r
-       log_debug("checking descendant p="+parent + " c=" + child);\r
-       return __isGroupDescendant(\r
-               groupList[parent],\r
-               groupList[child]);\r
-}\r
-\r
-function isGroupDescendantId( parentName, childId ) {\r
-       log_debug("checking descendant ID p="+parentName + " c=" + childId);\r
-       return __isGroupDescendant(\r
-               groupList[parentName],\r
-               groupIDList[childId]);\r
-}\r
-\r
-\r
-/**\r
-  * Returns true if 'child' is equal or descends from 'parent'\r
-  * @param parent The node of the parent group\r
-  * @param child The node of the child group\r
-  */\r
-function __isGroupDescendant( parent, child ) {\r
-    if(!(parent && child)) return false;\r
-       if (parent.id == child.id) return true;\r
-       var node = child;\r
-       while( (node = groupIDList[node.parent]) ) {\r
-               if( node.id == parent.id ) \r
-                       return true;\r
-       }\r
-       return false;\r
-}\r
-\r
-\r
-function getMARCItemType() {\r
-       if(     copy &&\r
-                       copy.circ_as_type &&\r
-                       copy.circ_as_type != 'undef' )\r
-               return copy.circ_as_type;\r
-       \r
-       return (marcXMLDoc) ? extractFixedField(marcXMLDoc, 'Type') : "";\r
-}\r
-\r
-\r
-function isOrgDescendent( parentName, childId ) {\r
-       var key = scratchKey();\r
-       __OILS_FUNC_isOrgDescendent(scratchPad(key), parentName, childId);\r
-       var val = getScratch(key);\r
-       if( val == '1' ) return true;\r
-       return false;\r
-}\r
-\r
-/* returns the number of unfulfilled holds open on this user */\r
-function userHoldCount(userid) {\r
-   var key = scratchKey();\r
-   __OILS_FUNC_userHoldCount(scratchPad(key), userid);\r
-   return getScratch(key);\r
-}\r
-\r
-function hasCommonAncestor( org1, org2, depth ) {\r
-       var key = scratchKey();\r
-       __OILS_FUNC_hasCommonAncestor(scratchPad(key), org1, org2, depth);\r
-       var val = getScratch(key);\r
-       if( val == '1' ) return true;\r
-       return false;\r
-}\r
-\r
-/* returns a dictionary of circmod : count for checked out items */\r
-function checkoutsByCircModifier(userid) {\r
-    var key = scratchKey();\r
-    __OILS_FUNC_userCircsByCircmod(scratchPad(key), userid);\r
-    var val = getScratch(key);\r
-    return (val) ? val : {};\r
-}\r
-\r
-/* useful for testing */\r
-function die(msg) {\r
-       log_error("die(): "+msg);\r
-       log_stderr("die(): "+msg);\r
-       var foo = null;\r
-       var baz = foo.bar;\r
-}\r
-\r
-\r
-\r
-/* logs a load of info */\r
-function log_vars( prefix ) {\r
-       var str = prefix + ' : ';\r
-\r
-       if(patron) {\r
-               str += ' Patron=' + patron.id;\r
-               str += ', Patron_Username='+ patron.usrname;\r
-               str += ', Patron_Profile_Group='+ patronProfile;\r
-               str += ', Patron_Fines='        + patronFines;\r
-               str += ', Patron_OverdueCount=' + patronOverdueCount;\r
-               str += ', Patron_Items_Out=' + patronItemsOut;\r
-\r
-               try {\r
-                       str += ', Patron_Barcode='      + patron.card.barcode;\r
-                       str += ', Patron_Library='      + patron.home_ou.name;\r
-               } catch(e) {}\r
-       }\r
-\r
-    if(requestor.id != patron.id) \r
-        str+= ' Requestor='+requestor.usrname;\r
-\r
-       if(copy)        {\r
-               str += ', Copy=' + copy.id;\r
-               str += ', Copy_Barcode=' + copy.barcode;\r
-               str += ', Copy_status=' + copyStatus;\r
-      str += (copy.circ_modifier) ? ', Circ_Mod=' + copy.circ_modifier : '';\r
-\r
-               try {\r
-                       str += ', Circ_Lib=' + copy.circ_lib.shortname;\r
-                       str += ', Copy_location=' + copy.location.name;\r
-               } catch(e) {}\r
-       }\r
-\r
-       if(volume) {\r
-        str += ', Item_Owning_lib=' + volume.owning_lib;\r
-        str += ', Volume='     + volume.id;\r
-    }\r
-\r
-       if(title) str += ', Record='    + title.id;\r
-\r
-       if(recDescriptor)       {\r
-               str += ', Record_Descriptor=' + recDescriptor.id;\r
-               str += ', Item_Type='                   + recDescriptor.item_type;\r
-               str += ', Item_Form='                   + recDescriptor.item_form;\r
-               str += ', Item_Lang='                   + recDescriptor.item_lang;\r
-               str += ', Item_Audience='               + recDescriptor.audience;\r
-       }\r
-\r
-       str += ', Is_Renewal: ' + ( (isTrue(isRenewal)) ? "yes" : "no" );\r
-       str += ', Is_Precat: '  + ( (isTrue(isPrecat)) ? "yes" : "no" );\r
-       str += (holdRequestLib) ? ', Hold_request_lib=' + holdRequestLib.shortname : '';\r
-    str += (holdPickupLib) ? ', Hold_Pickup_Lib=' + holdPickupLib : '';\r
-\r
-       log_info(str);\r
-}\r
-\r
-\r
-\r
-/**\r
-  * Returns config information for the requested group.  If \r
-  * no config info exists for the requested group, then this\r
-  * function searches up the tree to find the config info \r
-  * for the nearest ancestor\r
-  * @param The name of the group who's config info to return\r
-  */\r
-function findGroupConfig(name) {\r
-       if(!name) return null;\r
-       var node = groupList[name];\r
-       do {\r
-               if( GROUP_CONFIG[node.name] ) {\r
-                       debugGroupConfig(name, node.name, GROUP_CONFIG[node.name]);\r
-                       return GROUP_CONFIG[node.name];\r
-               }\r
-       } while( (node = groupIDList[node.parent]) );\r
-       return null;\r
-}\r
-\r
-\r
-/** prints out the settings for the given group config **/\r
-function debugGroupConfig(name, foundName, config) {\r
-       if(!config) return;\r
-       var str = "findGroupConfig('"+name+"'): returning config info for '"+ foundName +"': ";\r
-       for( var i in config ) \r
-               str += i + '=' + config[i] + '  ';\r
-       log_debug(str);\r
-}\r
-\r
-\r
-/* custom functions for Windsor libraries */\r
-\r
-function isValidPatron(patronProfile) {\r
-    var valid_patrons = ['Faculty', 'Graduate', 'Undergraduate', 'Staff members', 'Readers'];\r
-    for (var i = 0; i < valid_patrons.length; i++) {\r
-        if (valid_patrons[i] == patronProfile) {\r
-            return true;\r
-        }\r
-    }\r
-    return false;\r
-}\r
-\r
+load_lib('catalog/record_type.js');
+load_lib('circ/circ_groups.js');
+load_lib('JSON_v1.js');
+
+
+try {
+       if( environment.copy ) {
+               environment.copy.fetchBestHold = function() {
+                       var key = scratchKey();
+                       environment.copy.__OILS_FUNC_fetch_best_hold(scratchPad(key));
+                       var val = getScratch(key);
+                       return (val) ? val : null;
+               }
+       }
+} catch(e) {}
+
+
+/* ----------------------------------------------------------------------------- 
+       Collect all of the global variables
+       ----------------------------------------------------------------------------- */
+
+/* the global result object.  Any data returned to the 
+       caller must be put into this object.  */
+var result                             = environment.result = {};
+result.event                   = 'SUCCESS';
+result.events                  = [];
+result.fatalEvents     = [];
+result.infoEvents              = [];
+
+
+/* Pull in any variables passed in from the calling process */
+var copy                                       = environment.copy;
+var volume                             = environment.volume;
+var title                              = environment.title;
+var recDescriptor              = environment.titleDescriptor;
+var patron                             = environment.patron;
+var patronItemsOut     = environment.patronItemsOut;
+var patronOverdueCount = environment.patronOverdueCount;
+var patronFines                = environment.patronFines;
+var isRenewal                  = environment.isRenewal;
+var isPrecat                   = environment.isPrecat;
+var currentLocation    = environment.location;
+var holdRequestLib     = environment.requestLib;
+var holdPickupLib       = environment.pickupLib; /* hold pickup lib */
+var requestor = environment.requestor || patron;
+var newHold = environment.newHold;
+
+
+
+/* create some new vars based on the data we have wherever possible */
+var patronProfile;
+var copyStatus;
+var marcXMLDoc;
+
+if( patron && patron.profile ) 
+       patronProfile = patron.profile.name;
+if( copy && copy.status ) 
+       copyStatus = copy.status.name;
+if( title && title.marc )
+       marcXMLDoc = new XML(title.marc);
+
+
+
+/* copy the group tree into some other useful data structures */
+var groupTree          = environment.groupTree;
+var groupList          = {};
+var groupIDList        = {};
+flattenGroupTree(groupTree);
+
+
+
+
+
+
+/* ----------------------------------------------------------------------------- 
+       Define all of the utility functions
+       ----------------------------------------------------------------------------- */
+
+
+
+/* useful functions for creating wrappers around system functions */
+var __scratchKey = 0;
+var __SCRATCH = {};
+function scratchKey()          { return '_' + __scratchKey++; };
+function scratchPad(key)       { return '__SCRATCH.'+ key; }
+function getScratch(key)       { return __SCRATCH[ key ]; }
+function scratchClear()                { for( var o in __SCRATCH ) __SCRATCH[o] = null; }
+
+
+/* note: returns false if the value is 'f' or 'F' ... */
+function isTrue(d) {
+       if(     d && 
+                       d != "0" && 
+                       d != "f" &&
+                       d != "F" )
+                       return true;
+       return false;
+}
+
+/* Utility function for iterating over array */
+function iterate( arr, callback ) {
+       for( var i = 0; i < arr.length; i++ ) 
+               callback(arr[i]);
+}
+
+
+/**
+  * returns a list of items that when passed to the callback 
+  * 'func' returned true returns null if none were found
+  */
+function grep( arr, func ) {
+       var results = [];
+       iterate( arr, 
+               function(d) {
+                       if( func(d) ) 
+                               results.push(d);
+               }
+       );
+       if(results.length > 0)  
+               return results;
+       return null;
+}
+
+
+
+function flattenGroupTree(node) {
+       if(!node) return null;
+       groupList[node.name] = node;
+       groupIDList[node.id] = node;
+       iterate( node.children,
+               function(n) {
+                       flattenGroupTree(n);
+               }
+       );
+}
+
+
+
+/**
+  * Returns true if 'child' is equal or descends from 'parent'
+  * @param parent The name of the parent group
+  * @param child The name of the child group
+  */
+function isGroupDescendant( parent, child ) {
+       log_debug("checking descendant p="+parent + " c=" + child);
+       return __isGroupDescendant(
+               groupList[parent],
+               groupList[child]);
+}
+
+function isGroupDescendantId( parentName, childId ) {
+       log_debug("checking descendant ID p="+parentName + " c=" + childId);
+       return __isGroupDescendant(
+               groupList[parentName],
+               groupIDList[childId]);
+}
+
+
+/**
+  * Returns true if 'child' is equal or descends from 'parent'
+  * @param parent The node of the parent group
+  * @param child The node of the child group
+  */
+function __isGroupDescendant( parent, child ) {
+    if(!(parent && child)) return false;
+       if (parent.id == child.id) return true;
+       var node = child;
+       while( (node = groupIDList[node.parent]) ) {
+               if( node.id == parent.id ) 
+                       return true;
+       }
+       return false;
+}
+
+
+function getMARCItemType() {
+       if(     copy &&
+                       copy.circ_as_type &&
+                       copy.circ_as_type != 'undef' )
+               return copy.circ_as_type;
+       
+       return (marcXMLDoc) ? extractFixedField(marcXMLDoc, 'Type') : "";
+}
+
+
+function isOrgDescendent( parentName, childId ) {
+       var key = scratchKey();
+       __OILS_FUNC_isOrgDescendent(scratchPad(key), parentName, childId);
+       var val = getScratch(key);
+       if( val == '1' ) return true;
+       return false;
+}
+
+/* returns the number of unfulfilled holds open on this user */
+function userHoldCount(userid) {
+   var key = scratchKey();
+   __OILS_FUNC_userHoldCount(scratchPad(key), userid);
+   return getScratch(key);
+}
+
+function hasCommonAncestor( org1, org2, depth ) {
+       var key = scratchKey();
+       __OILS_FUNC_hasCommonAncestor(scratchPad(key), org1, org2, depth);
+       var val = getScratch(key);
+       if( val == '1' ) return true;
+       return false;
+}
+
+/* returns a dictionary of circmod : count for checked out items */
+function checkoutsByCircModifier(userid) {
+    var key = scratchKey();
+    __OILS_FUNC_userCircsByCircmod(scratchPad(key), userid);
+    var val = getScratch(key);
+    return (val) ? val : {};
+}
+
+/* useful for testing */
+function die(msg) {
+       log_error("die(): "+msg);
+       log_stderr("die(): "+msg);
+       var foo = null;
+       var baz = foo.bar;
+}
+
+
+
+/* logs a load of info */
+function log_vars( prefix ) {
+       var str = prefix + ' : ';
+
+       if(patron) {
+               str += ' Patron=' + patron.id;
+               str += ', Patron_Username='+ patron.usrname;
+               str += ', Patron_Profile_Group='+ patronProfile;
+               str += ', Patron_Fines='        + patronFines;
+               str += ', Patron_OverdueCount=' + patronOverdueCount;
+               str += ', Patron_Items_Out=' + patronItemsOut;
+
+               try {
+                       str += ', Patron_Barcode='      + patron.card.barcode;
+                       str += ', Patron_Library='      + patron.home_ou.name;
+               } catch(e) {}
+       }
+
+    if(requestor.id != patron.id) 
+        str+= ' Requestor='+requestor.usrname;
+
+       if(copy)        {
+               str += ', Copy=' + copy.id;
+               str += ', Copy_Barcode=' + copy.barcode;
+               str += ', Copy_status=' + copyStatus;
+      str += (copy.circ_modifier) ? ', Circ_Mod=' + copy.circ_modifier : '';
+
+               try {
+                       str += ', Circ_Lib=' + copy.circ_lib.shortname;
+                       str += ', Copy_location=' + copy.location.name;
+               } catch(e) {}
+       }
+
+       if(volume) {
+        str += ', Item_Owning_lib=' + volume.owning_lib;
+        str += ', Volume='     + volume.id;
+    }
+
+       if(title) str += ', Record='    + title.id;
+
+       if(recDescriptor)       {
+               str += ', Record_Descriptor=' + recDescriptor.id;
+               str += ', Item_Type='                   + recDescriptor.item_type;
+               str += ', Item_Form='                   + recDescriptor.item_form;
+               str += ', Item_Lang='                   + recDescriptor.item_lang;
+               str += ', Item_Audience='               + recDescriptor.audience;
+       }
+
+       str += ', Is_Renewal: ' + ( (isTrue(isRenewal)) ? "yes" : "no" );
+       str += ', Is_Precat: '  + ( (isTrue(isPrecat)) ? "yes" : "no" );
+       str += (holdRequestLib) ? ', Hold_request_lib=' + holdRequestLib.shortname : '';
+    str += (holdPickupLib) ? ', Hold_Pickup_Lib=' + holdPickupLib : '';
+
+       log_info(str);
+}
+
+
+
+/**
+  * Returns config information for the requested group.  If 
+  * no config info exists for the requested group, then this
+  * function searches up the tree to find the config info 
+  * for the nearest ancestor
+  * @param The name of the group who's config info to return
+  */
+function findGroupConfig(name) {
+       if(!name) return null;
+       var node = groupList[name];
+       do {
+               if( GROUP_CONFIG[node.name] ) {
+                       debugGroupConfig(name, node.name, GROUP_CONFIG[node.name]);
+                       return GROUP_CONFIG[node.name];
+               }
+       } while( (node = groupIDList[node.parent]) );
+       return null;
+}
+
+
+/** prints out the settings for the given group config **/
+function debugGroupConfig(name, foundName, config) {
+       if(!config) return;
+       var str = "findGroupConfig('"+name+"'): returning config info for '"+ foundName +"': ";
+       for( var i in config ) 
+               str += i + '=' + config[i] + '  ';
+       log_debug(str);
+}
+
+
+/* custom functions for Windsor libraries */
+
+function isValidPatron(patronProfile) {
+    var valid_patrons = ['Faculty', 'Graduate', 'Undergraduate', 'Staff members', 'Readers'];
+    for (var i = 0; i < valid_patrons.length; i++) {
+        if (valid_patrons[i] == patronProfile) {
+            return true;
+        }
+    }
+    return false;
+}
+