From: Lebbeous Fogle-Weekley <lebbeous@esilibrary.com>
Date: Tue, 5 Jun 2012 21:44:37 +0000 (-0400)
Subject: Address LP #983487: Avoid clobbering bib records at authority merge
X-Git-Url: https://old-git.evergreen-ils.org/?a=commitdiff_plain;h=522d8d8292e5b5255c14dd7900597b27e2d4720b;p=evergreen%2Fmasslnc.git

Address LP #983487: Avoid clobbering bib records at authority merge

If you've set up a relationship between bib record and authority records
based on arbitrary sets of controlling and controlled fields, but your
authority records don't have the right Subj fixed field value
corresponding to a control set that defines the controlling and
controlled fields you're using, authority merge operations may wipe out
lots of bib data.

Yamil Suarez encountered this bug in testing, and in his case what he
needed to do was set the Subj fixed field in his authority records to
'A' to match his Song Title Index (see the launchpad bug referened
above).

Previously, you could not actually save the Subj fixed field in the MARC
editor (which showed HeadSubj instead of Subj for authority records, and
didn't work).  Now you can.

Thanks to Mike Rylander for help in figuring out the above.

To provide additional protection against merging authority records when
they might not be linked with the right control set, the Manage
Authorities interface will now also show you the linked control set for
any given records.

The implementation of that last bit incidentally meant making sure flesh
and flesh_fields get passed through to PermaCrud for retrieve() calls via
the Javascript openils.PermaCrud wrapper.

Signed-off-by: Lebbeous Fogle-Weekley <lebbeous@esilibrary.com>
Signed-off-by: Bill Erickson <berick@esilibrary.com>
---

diff --git a/Open-ILS/src/templates/cat/authority/list.tt2 b/Open-ILS/src/templates/cat/authority/list.tt2
index c58040b4a7..216a4cb8a7 100644
--- a/Open-ILS/src/templates/cat/authority/list.tt2
+++ b/Open-ILS/src/templates/cat/authority/list.tt2
@@ -2,7 +2,14 @@
 [% WRAPPER base.tt2 %]
 
 <script type="text/javascript" src='[% ctx.media_prefix %]/js/ui/default/cat/authority/list.js'> </script>
-
+<style type="text/css">
+    .authEntry { clear: both; }
+    .authEntry > *:first-child { float: left; width: 20%; }
+    .authEntry > .text { float: left; width: 46%; }
+    .authEntry > .authority-control-set { float: right; width: 33%; ; font-style: italic; }
+    .authority-control-set .acs-name { font-weight: bold; }
+    .authority-control-set .acs-id { }
+</style>
 <div dojoType="dijit.form.Form" id="myForm" jsId="myForm" encType="multipart/form-data" action="" method="">
     <span style="white-space: nowrap;">
         <label for="authTerm">Search term: </label>
diff --git a/Open-ILS/web/js/dojo/openils/PermaCrud.js b/Open-ILS/web/js/dojo/openils/PermaCrud.js
index ca3835772e..c284c65fb1 100644
--- a/Open-ILS/web/js/dojo/openils/PermaCrud.js
+++ b/Open-ILS/web/js/dojo/openils/PermaCrud.js
@@ -106,10 +106,14 @@ if(!dojo._hasResource["openils.PermaCrud"]) {
 
         retrieve : function ( fm_class /* Fieldmapper class hint */, id /* Fieldmapper object primary key value */,  opts /* Option hash */) {
             if(!opts) opts = {};
+            var ffj = {};
+            if (opts.join) ffj.join = opts.join;
+            if (opts.flesh) ffj.flesh = opts.flesh;
+            if (opts.flesh_fields) ffj.flesh_fields = opts.flesh_fields;
             var req_hash = dojo.mixin(
                 opts, 
                 { method : 'open-ils.pcrud.retrieve.' + fm_class,
-                  params : [ this.auth(), id ]
+                  params : [ this.auth(), id, ffj ]
                 }
             );
 
diff --git a/Open-ILS/web/js/ui/default/cat/authority/list.js b/Open-ILS/web/js/ui/default/cat/authority/list.js
index 591bfb8d6d..7486427d13 100644
--- a/Open-ILS/web/js/ui/default/cat/authority/list.js
+++ b/Open-ILS/web/js/ui/default/cat/authority/list.js
@@ -15,10 +15,24 @@ dojo.require('openils.PermaCrud');
 dojo.require('openils.XUL');
 dojo.require('openils.widget.OrgUnitFilteringSelect');
 dojo.require("openils.widget.PCrudAutocompleteBox");
+dojo.require("MARC.FixedFields");
 dojo.requireLocalization("openils.authority", "authority");
 var auth_strings = dojo.i18n.getLocalization("openils.authority", "authority");
 
 var cgi = new openils.CGI();
+var pcrud = new openils.PermaCrud();
+
+var _acs_cache_by_at = {};
+function fetch_control_set(thesaurus) {
+    if (!_acs_cache_by_at[thesaurus]) {
+        var at = pcrud.retrieve(
+            "at", thesaurus,
+            {"flesh": 1, "flesh_fields": {"at": ["control_set"]}}
+        );
+        _acs_cache_by_at[thesaurus] = at.control_set();
+    }
+    return _acs_cache_by_at[thesaurus];
+}
 
 /*
 // OrgUnits do not currently affect the retrieval of authority records,
@@ -40,6 +54,7 @@ function displayAuthorities(data) {
     dojo.query("record", data).forEach(function(node) {
         var auth = {};
         auth.text = '';
+        auth.thesaurus = '|';
         auth.id = 0;
 
         // Grab each authority record field from the authority record
@@ -56,17 +71,38 @@ function displayAuthorities(data) {
             auth.id = dojox.xml.parser.textContent(dfNode); 
         });
 
+        /* I wrap this in try/catch only because:
+         *  a) this interface hasn't hitherto relied on MARC.Record, and
+         *  b) the functionality we need it for is optional
+         */
+        try {
+            var marc = new MARC.Record({"rtype": "AUT", "xml": node});
+            auth.thesaurus = marc.extractFixedField("Subj", "|");
+        } catch (E) {
+            console.warn(
+                "MARC.Record didn't work for authority record " +
+                auth.id + ": " + E
+            );
+        }
+
         idArr.push(parseInt(auth.id));
 
-        // Create the authority record listing entry
-        dojo.place('<div class="authEntry" id="auth' + auth.id + '"><span class="text" id="authLabel' + auth.id + '">' + auth.text + '</span></div>', "authlist-div", "last");
+        // Create the authority record listing entry. XXX i18n
+        dojo.place(
+            '<div class="authEntry" id="auth' + auth.id + '">' +
+            '<div class="text" id="authLabel' + auth.id + '">' + auth.text + '</div>' +
+            '<div class="authority-control-set">Control Set: <span class="acs-name">' +
+            fetch_control_set(auth.thesaurus).name() +
+            '</span> <span class="acs-id">(#' +
+            fetch_control_set(auth.thesaurus).id() + ')</span></div></div>',
+            "authlist-div", "last"
+        );
 
         // Add the menu of new/edit/delete/mark-for-merge options
         var auth_menu = new dijit.Menu({});
 
         // "Edit" menu item
         new dijit.MenuItem({"id": "edit_" + auth.id, "onClick": function(){
-            var pcrud = new openils.PermaCrud();
             var auth_rec = pcrud.retrieve("are", auth.id);
             if (auth_rec) {
                 loadMarcEditor(pcrud, auth_rec);
@@ -100,7 +136,6 @@ function displayAuthorities(data) {
             "onClick":function(){
                 auth.text = '';
 
-                var pcrud = new openils.PermaCrud();
                 var auth_rec = pcrud.retrieve("are", auth.id);
 
                 // Bit of a hack to get the linked bib count until an explicit ID
@@ -145,7 +180,7 @@ function displayAuthorities(data) {
         }, "label":auth_strings.DELETE}).placeAt(auth_menu, "last");
 
         auth_mb = new dijit.form.DropDownButton({dropDown: auth_menu, label: auth_strings.ACTIONS, id:"menu" + auth.id});
-        auth_mb.placeAt("auth" + auth.id, "first");
+        auth_mb.placeAt(dojo.create("div", null, "auth" + auth.id, "first"), "first");
         auth_menu.startup();
     });
 
@@ -194,7 +229,6 @@ function cancelDelete(recId) {
 }
 
 function confirmDelete(recId) {
-    var pcrud = new openils.PermaCrud();
     var auth_rec = pcrud.retrieve("are", recId);
     if (auth_rec) {
         pcrud.eliminate(auth_rec);
@@ -214,7 +248,7 @@ function showBibCount(authIds) {
         var msg = r.recv().content();
         dojo.forEach(msg, function(auth) {
                 linkedIds.push(auth.authority);
-                dojo.place('<span class="bibcount">' + auth.bibs + '</span>', 'authLabel' + auth.authority, 'before');
+                dojo.place('<span class="bibcount">' + auth.bibs + '</span> ', 'authLabel' + auth.authority, 'first');
             }
         );
 
@@ -227,7 +261,7 @@ function showBibCount(authIds) {
                 }
             });
             if (!found) {
-                dojo.place('<span class="bibcount">0</span>', 'authLabel' + id, 'before');
+                dojo.place('<span class="bibcount">0</span> ', 'authLabel' + id, 'first');
             }
         });
     }
diff --git a/Open-ILS/xul/staff_client/server/cat/marcedit.xul b/Open-ILS/xul/staff_client/server/cat/marcedit.xul
index 7204883616..195edaea6a 100644
--- a/Open-ILS/xul/staff_client/server/cat/marcedit.xul
+++ b/Open-ILS/xul/staff_client/server/cat/marcedit.xul
@@ -209,8 +209,8 @@
                             <textbox id="HeadMain_tb" context="clipboard" class="plain" name="HeadMain" maxlength="1" size="1" onkeypress="netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect'); if (!(event.altKey || event.ctrlKey || event.metaKey)) { oils_lock_page(); }" oninput="updateFixedFields(this);" onfocus="this.select();"/>
                         </row>
                         <row>
-                            <label name="HeadSubj" control="HeadSubj_tb" set="AUT" value="HeadSubj" />
-                            <textbox id="HeadSubj_tb" context="clipboard" class="plain" name="HeadSubj" maxlength="1" size="1" onkeypress="netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect'); if (!(event.altKey || event.ctrlKey || event.metaKey)) { oils_lock_page(); }" oninput="updateFixedFields(this);" onfocus="this.select();"/>
+                            <label name="Subj" control="Subj_tb" set="AUT" value="Subj" />
+                            <textbox id="Subj_tb" context="clipboard" class="plain" name="Subj" maxlength="1" size="1" onkeypress="netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect'); if (!(event.altKey || event.ctrlKey || event.metaKey)) { oils_lock_page(); }" oninput="updateFixedFields(this);" onfocus="this.select();"/>
                             <label name="HeadSer" control="HeadSer_tb" set="AUT" value="HeadSer" />
                             <textbox id="HeadSer_tb" context="clipboard" class="plain" name="HeadSer" maxlength="1" size="1" onkeypress="netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect'); if (!(event.altKey || event.ctrlKey || event.metaKey)) { oils_lock_page(); }" oninput="updateFixedFields(this);" onfocus="this.select();"/>
                             <label name="TypeSubd" control="TypeSubd_tb" set="AUT" value="TypeSubd" />