To teach the "Add volumes" dialog in the staff client how to show the correct
set of call numbers based on the workstation OU's default classification
scheme, this commit:
* Adds a column "field" to the asset.call_number_class table that specifies
the list of tag/subfield combinations to search for a candidate call number
for a given classification scheme
* Adds a new OU setting, 'cat.default_classification_scheme', that points
to the asset.call_number_class ID
* Extends the open-ils.cat.biblio.record.marc_cn.retrieve method to support
a second argument, identifying the classification scheme for the call
number extraction
* Fixes the IDL for asset.call_number_class to include the ID as an explicit
field
* Makes the "Add volumes" dialog look up the 'cat.default_classification_scheme'
setting for the workstation OU and apply that to the call to the
open-ils.cat.biblio.record.marc_cn.retrieve method
TODO:
* Provide a means of switching the classification scheme for the current volume,
repopulating the call number selector widget
* Save the chosen scheme as part of the acn object
git-svn-id: svn://svn.open-ils.org/ILS/trunk@17141
dcc99617-32d9-48b4-a31d-
7c20da2025e4
</class>
<class id="acnc" controller="open-ils.cstore" oils_obj:fieldmapper="asset::call_number_class" oils_persist:tablename="asset.call_number_class" reporter:label="Call number classification scheme">
<fields oils_persist:primary="id" oils_persist:sequence="asset.call_number_class_id_seq">
+ <field reporter:label="Call number class ID" name="id" reporter_datatype="id"/>
<field reporter:label="Name" name="name" reporter:datatype="text"/>
<field reporter:label="Normalizer function" name="normalizer" reporter:datatype="text"/>
+ <field reporter:label="Call number fields" name="field" reporter:datatype="text"/>
</fields>
</class>
<class id="acn" controller="open-ils.cstore open-ils.pcrud" oils_obj:fieldmapper="asset::call_number" oils_persist:tablename="asset.call_number" reporter:label="Call Number/Volume">
__PACKAGE__->register_method(
- method => "biblio_record_marc_cn",
- api_name => "open-ils.cat.biblio.record.marc_cn.retrieve",
- argc => 1, #(bib id )
+ method => "biblio_record_marc_cn",
+ api_name => "open-ils.cat.biblio.record.marc_cn.retrieve",
+ argc => 1, #(bib id )
+ signature => {
+ desc => 'Extracts call number candidates from a bibliographic record',
+ params => [
+ {desc => 'Record ID', type => 'number'},
+ {desc => '(Optional) Classification scheme ID', type => 'number'},
+ ]
+ },
+ return => {desc => 'Hash of candidate call numbers identified by tag' }
);
sub biblio_record_marc_cn {
- my( $self, $client, $id ) = @_;
+ my( $self, $client, $id, $class ) = @_;
- my $session = OpenSRF::AppSession->create("open-ils.cstore");
- my $marc = $session
- ->request("open-ils.cstore.direct.biblio.record_entry.retrieve", $id )
- ->gather(1)
- ->marc;
+ my $e = new_editor();
+ my $marc = $e->retrieve_biblio_record_entry($id)->marc;
- my $doc = XML::LibXML->new->parse_string($marc);
- $doc->documentElement->setNamespace( "http://www.loc.gov/MARC21/slim", "marc", 1 );
-
- my @res;
- for my $tag ( qw/050 055 060 070 080 082 086 088 090 092 096 098 099/ ) {
- my @node = $doc->findnodes("//marc:datafield[\@tag='$tag']");
- for my $x (@node) {
- my $cn = $x->findvalue("marc:subfield[\@code='a' or \@code='b']");
- push @res, {$tag => $cn} if ($cn);
- }
- }
+ my $doc = XML::LibXML->new->parse_string($marc);
+ $doc->documentElement->setNamespace( "http://www.loc.gov/MARC21/slim", "marc", 1 );
+
+ my @fields;
+ my @res;
+ if ($class) {
+ @fields = split(/,/, $e->retrieve_asset_call_number_class($class)->field);
+ } else {
+ @fields = qw/050ab 055ab 060ab 070ab 080ab 082ab 086ab 088ab 090 092 096 098 099/;
+ }
+
+ # Get field/subfield combos based on acnc value; for example "050ab,055ab"
+
+ foreach my $field (@fields) {
+ my $tag = substr($field, 0, 3);
+ $logger->debug("Tag = $tag");
+ my @node = $doc->findnodes("//marc:datafield[\@tag='$tag']");
+
+ # Now parse the subfields and build up the subfield XPath
+ my @subfields = split(//, substr($field, 3));
+
+ # If they give us no subfields to parse, default to just the 'a'
+ if (!@subfields) {
+ @subfields = ('a');
+ }
+ my $subxpath;
+ foreach my $sf (@subfields) {
+ $subxpath .= "\@code='$sf' or ";
+ }
+ $subxpath = substr($subxpath, 0, -4);
+ $logger->debug("subxpath = $subxpath");
+
+ # Find the contents of the specified subfields
+ foreach my $x (@node) {
+ my $cn = $x->findvalue("marc:subfield[$subxpath]");
+ push @res, {$tag => $cn} if ($cn);
+ }
+ }
- return \@res
+ return \@res;
}
__PACKAGE__->register_method(
__PACKAGE__->columns( Essential => qw/location org position/ );
#-------------------------------------------------------------------------------
+package asset::call_number_class;
+use base qw/asset/;
+
+__PACKAGE__->table( 'asset_call_number_class' );
+__PACKAGE__->columns( Primary => qw/id/ );
+__PACKAGE__->columns( Essential => qw/name normalizer field/ );
+
+#-------------------------------------------------------------------------------
package asset::call_number;
use base qw/asset/;
asset::call_number->sequence( 'asset.call_number_id_seq' );
#---------------------------------------------------------------------
+ package asset::call_number_class;
+
+ asset::call_number->table( 'asset.call_number_class' );
+ asset::call_number->sequence( 'asset.call_number_class_id_seq' );
+
+ #---------------------------------------------------------------------
package asset::copy_location_order;
asset::copy_location_order->table( 'asset.copy_location_order' );
install_date TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW()
);
-INSERT INTO config.upgrade_log (version) VALUES ('0364'); -- dbs
+INSERT INTO config.upgrade_log (version) VALUES ('0365'); -- dbs
CREATE TABLE config.bib_source (
id SERIAL PRIMARY KEY,
CREATE TABLE asset.call_number_class (
id bigserial PRIMARY KEY,
name TEXT NOT NULL,
- normalizer TEXT NOT NULL DEFAULT 'asset.normalize_generic'
+ normalizer TEXT NOT NULL DEFAULT 'asset.normalize_generic',
+ field TEXT NOT NULL DEFAULT '050ab,055ab,060ab,070ab,080ab,082ab,086ab,088ab,090,092,096,098,099'
);
+COMMENT ON TABLE asset.call_number_class IS $$
+Defines the call number normalization database functions in the "normalizer"
+column and the tag/subfield combinations to use to lookup the call number in
+the "field" column for a given classification scheme. Tag/subfield combinations
+are delimited by commas.
+$$;
CREATE OR REPLACE FUNCTION asset.label_normalizer() RETURNS TRIGGER AS $func$
DECLARE
$func$ LANGUAGE PLPERLU;
INSERT INTO asset.call_number_class (name, normalizer) VALUES
- ('Generic', 'asset.label_normalizer_generic'),
- ('Dewey (DDC)', 'asset.label_normalizer_dewey'),
- ('Library of Congress (LC)', 'asset.label_normalizer_lc')
+ ('Generic', 'asset.label_normalizer_generic', '050ab,055ab,060ab,070ab,080ab,082ab,086ab,088ab,090,092,096,098,099'),
+ ('Dewey (DDC)', 'asset.label_normalizer_dewey', '080ab,082ab'),
+ ('Library of Congress (LC)', 'asset.label_normalizer_lc', '050ab,055ab')
;
CREATE TABLE asset.call_number (
'acpl'
);
+INSERT INTO config.org_unit_setting_type ( name, label, description, datatype, fm_class )
+VALUES (
+ 'cat.default_classification_scheme',
+ oils_i18n_gettext(
+ 'setting.name',
+ 'Cataloging: Default Classification Scheme',
+ 'coust',
+ 'label'
+ ),
+ oils_i18n_gettext(
+ 'setting.name',
+ 'Defines the default classification scheme for new call numbers: 1 = Generic; 2 = Dewey; 3 = LC',
+ 'coust',
+ 'descripton'
+ ),
+ 'link',
+ 'acnc'
+);
+
+
-- 0355.data.missing_pieces_format.sql
INSERT INTO action_trigger.hook (key,core_type,description,passive) VALUES
--- /dev/null
+BEGIN;
+
+INSERT INTO config.upgrade_log (version) VALUES ('0365'); -- dbs
+
+ALTER TABLE asset.call_number_class ADD COLUMN field TEXT NOT NULL DEFAULT '050ab,055ab,060ab,070ab,080ab,082ab,086ab,088ab,090,092,096,098,099';
+
+COMMENT ON TABLE asset.call_number_class IS $$
+Defines the call number normalization database functions in the "normalizer"
+column and the tag/subfield combinations to use to lookup the call number in
+the "field" column for a given classification scheme. Tag/subfield combinations
+are delimited by commas.
+$$;
+
+-- Generic fields
+UPDATE asset.call_number_class
+ SET field = '050ab,055ab,060ab,070ab,080ab,082ab,086ab,088ab,090,092,096,098,099'
+ WHERE id = 1
+;
+
+-- Dewey fields
+UPDATE asset.call_number_class
+ SET field = '080ab,082ab'
+ WHERE id = 2
+;
+
+-- LC fields
+UPDATE asset.call_number_class
+ SET field = '050ab,055ab'
+ WHERE id = 3
+;
+
+COMMIT;
var ou_ids = xul_param('ou_ids',{'concat' : true}) || [];
+ // Get the default callnumber classification scheme from OU settings
+ dojo.require('fieldmapper.OrgUtils');
+ var label_class = fieldmapper.aou.fetchOrgSettingDefault(ses('ws_ou'), 'cat.default_classification_scheme');
+
+ // Assign a default value if none was returned
+ if (!label_class.value) {
+ label_class.value = 1;
+ }
+
/***********************************************************************************************************/
/* If we're passed existing_copies, rig up a copy_shortcut object to leverage existing code for rendering the volume labels, etc.
* Also make a lookup object for existing copies keyed on org id and callnumber label, and another keyed on copy id. */
/* For the call number drop down */
if (!g.copy_shortcut) {
- var cn_blob;
- try {
- cn_blob = g.network.simple_request('BLOB_MARC_CALLNUMBERS_RETRIEVE',[g.doc_id]);
- } catch(E) {
- cn_blob = [];
- }
- var hbox = document.getElementById('marc_cn');
- var ml = util.widgets.make_menulist(
- util.functional.map_list(
- cn_blob,
- function(o) {
- for (var i in o) {
- return [ o[i], i ];
- }
- }
- ).sort(
- function(a,b) {
- a = a[1]; b = b[1];
- if (a == '082') return -1;
- if (b == '082') return 1;
- if (a == '092') return -1;
- if (b == '092') return 1;
- if (a < b) return -1;
- if (a > b) return 1;
- return 0;
- }
- )
- ); hbox.appendChild(ml);
- ml.setAttribute('editable','true');
- ml.setAttribute('width', '200');
- var btn = document.createElement('button');
- btn.setAttribute('label',$('catStrings').getString('staff.cat.volume_copy_creator.my_init.btn.label'));
- btn.setAttribute('accesskey',$('catStrings').getString('staff.cat.volume_copy_creator.my_init.btn.accesskey'));
- btn.setAttribute('image','/xul/server/skin/media/images/down_arrow.gif');
- hbox.appendChild(btn);
- btn.addEventListener(
- 'command',
- function() {
- var nl = document.getElementsByTagName('textbox');
- for (var i = 0; i < nl.length; i++) {
- if (nl[i].getAttribute('rel_vert_pos')==2
- && !nl[i].disabled) nl[i].value = ml.value;
- }
- if (g.last_focus) setTimeout( function() { g.last_focus.focus(); }, 0 );
- },
- false
- );
+ g.list_callnumbers(g.doc_id, label_class.value);
}
/***********************************************************************************************************/
}
}
-
+g.list_callnumbers = function(doc_id, label_class) {
+ var cn_blob;
+ try {
+ cn_blob = g.network.simple_request('BLOB_MARC_CALLNUMBERS_RETRIEVE',[g.doc_id, label_class]);
+ } catch(E) {
+ cn_blob = [];
+ }
+ var hbox = document.getElementById('marc_cn');
+ var ml = util.widgets.make_menulist(
+ util.functional.map_list(
+ cn_blob,
+ function(o) {
+ for (var i in o) {
+ return [ o[i], i ];
+ }
+ }
+ ).sort(
+ function(a,b) {
+ a = a[1]; b = b[1];
+ if (a == '082') return -1;
+ if (b == '082') return 1;
+ if (a == '092') return -1;
+ if (b == '092') return 1;
+ if (a < b) return -1;
+ if (a > b) return 1;
+ return 0;
+ }
+ )
+ ); hbox.appendChild(ml);
+ ml.setAttribute('editable','true');
+ ml.setAttribute('width', '200');
+ var btn = document.createElement('button');
+ btn.setAttribute('label',$('catStrings').getString('staff.cat.volume_copy_creator.my_init.btn.label'));
+ btn.setAttribute('accesskey',$('catStrings').getString('staff.cat.volume_copy_creator.my_init.btn.accesskey'));
+ btn.setAttribute('image','/xul/server/skin/media/images/down_arrow.gif');
+ hbox.appendChild(btn);
+ btn.addEventListener(
+ 'command',
+ function() {
+ var nl = document.getElementsByTagName('textbox');
+ for (var i = 0; i < nl.length; i++) {
+ if (nl[i].getAttribute('rel_vert_pos')==2
+ && !nl[i].disabled) nl[i].value = ml.value;
+ }
+ if (g.last_focus) setTimeout( function() { g.last_focus.focus(); }, 0 );
+ },
+ false
+ );
+}