From b3fa2158d6c92191f0b3ee2319d17170017cf53e Mon Sep 17 00:00:00 2001 From: Thomas Berezansky Date: Sat, 28 May 2011 21:44:35 -0400 Subject: [PATCH] Sip Statcats - Actor/Asset Statcats via SIP2 Stat cats can now have a sip_field and sip_format. sip_field is the field identifier code, sip_format is one of the following: 1 - Null/Empty, places stat cat value in as-is 2 - A plain string, placed in value as-is when stat cat has value 3 - A plain string with a %s, 1 and 2 combined, where the stat cat value replaces the %s 4 - A regular expression surrounded by | characters (ex, |([0-9]*) -|): If the regular expression does not match the value, nothing If the regular expression matches and has a capture group, the captured group If the regular expression matches and does not have a capture group, the entire match The | was used because it would otherwise be stripped from the final result anyway. Signed-off-by: Thomas Berezansky Signed-off-by: Bill Erickson --- Open-ILS/examples/fm_IDL.xml | 39 +++++++++++++++++- .../lib/OpenILS/Application/Storage/CDBI/actor.pm | 2 +- .../lib/OpenILS/Application/Storage/CDBI/asset.pm | 2 +- Open-ILS/src/perlmods/lib/OpenILS/SIP/Item.pm | 37 ++++++++++++++++- Open-ILS/src/perlmods/lib/OpenILS/SIP/Patron.pm | 37 +++++++++++++++++ Open-ILS/src/sql/Pg/005.schema.actors.sql | 35 ++++++++++++++++ Open-ILS/src/sql/Pg/040.schema.asset.sql | 36 +++++++++++++++++ Open-ILS/web/opac/locale/en-US/lang.dtd | 9 +++++ .../conify/global/config/actor_sip_fields.tt2 | 28 +++++++++++++ .../conify/global/config/asset_sip_fields.tt2 | 28 +++++++++++++ .../xul/staff_client/chrome/content/main/menu.js | 8 ++++ .../chrome/content/main/menu_frame_menus.xul | 8 ++++ .../staff_client/server/admin/stat_cat_editor.js | 46 ++++++++++++++++++++++ .../server/admin/stat_cat_editor.xhtml | 27 ++++++++++++- 14 files changed, 337 insertions(+), 5 deletions(-) create mode 100644 Open-ILS/web/templates/default/conify/global/config/actor_sip_fields.tt2 create mode 100644 Open-ILS/web/templates/default/conify/global/config/asset_sip_fields.tt2 diff --git a/Open-ILS/examples/fm_IDL.xml b/Open-ILS/examples/fm_IDL.xml index 706ab89bd2..e41464ecff 100644 --- a/Open-ILS/examples/fm_IDL.xml +++ b/Open-ILS/examples/fm_IDL.xml @@ -4348,10 +4348,13 @@ SELECT usr, + + + @@ -4366,6 +4369,22 @@ SELECT usr, + + + + + + + + + + + + + + + + @@ -4374,9 +4393,12 @@ SELECT usr, + + + @@ -5290,7 +5312,22 @@ SELECT usr, - + + + + + + + + + + + + + + + + diff --git a/Open-ILS/src/perlmods/lib/OpenILS/Application/Storage/CDBI/actor.pm b/Open-ILS/src/perlmods/lib/OpenILS/Application/Storage/CDBI/actor.pm index 392febe999..89495fcb60 100644 --- a/Open-ILS/src/perlmods/lib/OpenILS/Application/Storage/CDBI/actor.pm +++ b/Open-ILS/src/perlmods/lib/OpenILS/Application/Storage/CDBI/actor.pm @@ -118,7 +118,7 @@ use base qw/actor/; __PACKAGE__->table( 'actor_stat_cat' ); __PACKAGE__->columns( Primary => qw/id/ ); -__PACKAGE__->columns( Essential => qw/owner name opac_visible usr_summary/ ); +__PACKAGE__->columns( Essential => qw/owner name opac_visible usr_summary sip_field sip_format/ ); #------------------------------------------------------------------------------- package actor::stat_cat_entry; diff --git a/Open-ILS/src/perlmods/lib/OpenILS/Application/Storage/CDBI/asset.pm b/Open-ILS/src/perlmods/lib/OpenILS/Application/Storage/CDBI/asset.pm index b464de57f1..6cecb8da92 100644 --- a/Open-ILS/src/perlmods/lib/OpenILS/Application/Storage/CDBI/asset.pm +++ b/Open-ILS/src/perlmods/lib/OpenILS/Application/Storage/CDBI/asset.pm @@ -88,7 +88,7 @@ use base qw/asset/; __PACKAGE__->table( 'asset_stat_cat' ); __PACKAGE__->columns( Primary => qw/id/ ); -__PACKAGE__->columns( Essential => qw/owner name opac_visible required/ ); +__PACKAGE__->columns( Essential => qw/owner name opac_visible sip_field sip_format required/ ); #------------------------------------------------------------------------------- package asset::stat_cat_entry; diff --git a/Open-ILS/src/perlmods/lib/OpenILS/SIP/Item.pm b/Open-ILS/src/perlmods/lib/OpenILS/SIP/Item.pm index 7eb815c9eb..91302a140c 100644 --- a/Open-ILS/src/perlmods/lib/OpenILS/SIP/Item.pm +++ b/Open-ILS/src/perlmods/lib/OpenILS/SIP/Item.pm @@ -88,8 +88,9 @@ sub new { { flesh => 3, flesh_fields => { - acp => [ 'circ_lib', 'call_number', 'status' ], + acp => [ 'circ_lib', 'call_number', 'status', 'stat_cat_entry_copy_maps' ], acn => [ 'owning_lib', 'record' ], + ascecm => [ 'stat_cat', 'stat_cat_entry' ], } } ] @@ -483,6 +484,40 @@ sub available { return 0; } +sub extra_fields { + my( $self ) = @_; + my $extra_fields = {}; + my $c = $self->{copy}; + foreach my $stat_cat_entry (@{$c->stat_cat_entry_copy_maps}) { + my $stat_cat = $stat_cat_entry->stat_cat; + next unless ($stat_cat->sip_field); + my $value = $stat_cat_entry->stat_cat_entry->value; + if(defined $stat_cat->sip_format && length($stat_cat->sip_format) > 0) { # Has a format string? + if($stat_cat->sip_format =~ /^\|(.*)\|$/) { # Regex match? + if($value =~ /($1)/) { # If we have a match + if(defined $2) { # Check to see if they embedded a capture group + $value = $2; # If so, use it + } + else { # No embedded capture group? + $value = $1; # Use our outer one + } + } + else { # No match? + $value = ''; # Empty string. Will be checked for below. + } + } + else { # Not a regex match - Try sprintf match (looking for a %s, if any) + $value = sprintf($stat_cat->sip_format, $value); + } + } + next unless length($value) > 0; # No value = no export + $value =~ s/\|//g; # Remove all lingering pipe chars for sane output purposes + $extra_fields->{ $stat_cat->sip_field } = [] unless (defined $extra_fields->{$stat_cat->sip_field}); + push(@{$extra_fields->{ $stat_cat->sip_field}}, $value); + } + return $extra_fields; +} + 1; __END__ diff --git a/Open-ILS/src/perlmods/lib/OpenILS/SIP/Patron.pm b/Open-ILS/src/perlmods/lib/OpenILS/SIP/Patron.pm index c628820a2d..c3dbb2133f 100644 --- a/Open-ILS/src/perlmods/lib/OpenILS/SIP/Patron.pm +++ b/Open-ILS/src/perlmods/lib/OpenILS/SIP/Patron.pm @@ -66,6 +66,10 @@ sub new { "billing_address", "mailing_address", 'profile', + "stat_cat_entries", + ], + actscecm => [ + "stat_cat", ], } }; @@ -721,5 +725,38 @@ sub inet_privileges { return $name; } +sub extra_fields { + my( $self ) = @_; + my $extra_fields = {}; + my $u = $self->{user}; + foreach my $stat_cat_entry (@{$u->stat_cat_entries}) { + my $stat_cat = $stat_cat_entry->stat_cat; + next unless ($stat_cat->sip_field); + my $value = $stat_cat_entry->stat_cat_entry; + if(defined $stat_cat->sip_format && length($stat_cat->sip_format) > 0) { # Has a format string? + if($stat_cat->sip_format =~ /^\|(.*)\|$/) { # Regex match? + if($value =~ /($1)/) { # If we have a match + if(defined $2) { # Check to see if they embedded a capture group + $value = $2; # If so, use it + } + else { # No embedded capture group? + $value = $1; # Use our outer one + } + } + else { # No match? + $value = ''; # Empty string. Will be checked for below. + } + } + else { # Not a regex match - Try sprintf match (looking for a %s, if any) + $value = sprintf($stat_cat->sip_format, $value); + } + } + next unless length($value) > 0; # No value = no export + $value =~ s/\|//g; # Remove all lingering pipe chars for sane output purposes + $extra_fields->{ $stat_cat->sip_field } = [] unless (defined $extra_fields->{$stat_cat->sip_field}); + push(@{$extra_fields->{ $stat_cat->sip_field}}, $value); + } + return $extra_fields; +} 1; diff --git a/Open-ILS/src/sql/Pg/005.schema.actors.sql b/Open-ILS/src/sql/Pg/005.schema.actors.sql index d56e6442f4..058387cddc 100644 --- a/Open-ILS/src/sql/Pg/005.schema.actors.sql +++ b/Open-ILS/src/sql/Pg/005.schema.actors.sql @@ -154,6 +154,17 @@ $$; CREATE INDEX actor_usr_setting_usr_idx ON actor.usr_setting (usr); +CREATE TABLE actor.stat_cat_sip_fields ( + field CHAR(2) PRIMARY KEY, + name TEXT NOT NULL, + one_only BOOL NOT NULL DEFAULT FALSE +); +COMMENT ON TABLE actor.stat_cat_sip_fields IS $$ +Actor Statistical Category SIP Fields + +Contains the list of valid SIP Field identifiers for +Statistical Categories. +$$; CREATE TABLE actor.stat_cat ( id SERIAL PRIMARY KEY, @@ -161,6 +172,8 @@ CREATE TABLE actor.stat_cat ( name TEXT NOT NULL, opac_visible BOOL NOT NULL DEFAULT FALSE, usr_summary BOOL NOT NULL DEFAULT FALSE, + sip_field CHAR(2) REFERENCES actor.stat_cat_sip_fields(field) ON UPDATE CASCADE ON DELETE SET NULL DEFERRABLE INITIALLY DEFERRED, + sip_format TEXT, CONSTRAINT sc_once_per_owner UNIQUE (owner,name) ); COMMENT ON TABLE actor.stat_cat IS $$ @@ -202,6 +215,28 @@ $$; CREATE INDEX actor_stat_cat_entry_usr_idx ON actor.stat_cat_entry_usr_map (target_usr); +CREATE FUNCTION actor.stat_cat_check() RETURNS trigger AS $func$ +DECLARE + sipfield actor.stat_cat_sip_fields%ROWTYPE; + use_count INT; +BEGIN + IF NEW.sip_field IS NOT NULL THEN + SELECT INTO sipfield * FROM actor.stat_cat_sip_fields WHERE field = NEW.sip_field; + IF sipfield.one_only THEN + SELECT INTO use_count count(id) FROM actor.stat_cat WHERE sip_field = NEW.sip_field AND id != NEW.id; + IF use_count > 0 THEN + RAISE EXCEPTION 'Sip field cannot be used twice'; + END IF; + END IF; + END IF; + RETURN NEW; +END; +$func$ LANGUAGE PLPGSQL; + +CREATE TRIGGER actor_stat_cat_sip_update_trigger + BEFORE INSERT OR UPDATE ON actor.stat_cat FOR EACH ROW + EXECUTE PROCEDURE actor.stat_cat_check(); + CREATE TABLE actor.card ( id SERIAL PRIMARY KEY, usr INT NOT NULL REFERENCES actor.usr (id) DEFERRABLE INITIALLY DEFERRED, diff --git a/Open-ILS/src/sql/Pg/040.schema.asset.sql b/Open-ILS/src/sql/Pg/040.schema.asset.sql index 735cc64050..010c3bcc56 100644 --- a/Open-ILS/src/sql/Pg/040.schema.asset.sql +++ b/Open-ILS/src/sql/Pg/040.schema.asset.sql @@ -127,6 +127,18 @@ CREATE TRIGGER acp_status_changed_trig BEFORE UPDATE ON asset.copy FOR EACH ROW EXECUTE PROCEDURE asset.acp_status_changed(); +CREATE TABLE asset.stat_cat_sip_fields ( + field CHAR(2) PRIMARY KEY, + name TEXT NOT NULL, + one_only BOOL NOT NULL DEFAULT FALSE +); +COMMENT ON TABLE asset.stat_cat_sip_fields IS $$ +Asset Statistical Category SIP Fields + +Contains the list of valid SIP Field identifiers for +Statistical Categories. +$$; + CREATE TABLE asset.stat_cat_entry_transparency_map ( id BIGSERIAL PRIMARY KEY, stat_cat INT NOT NULL, -- needs ON DELETE CASCADE @@ -141,6 +153,8 @@ CREATE TABLE asset.stat_cat ( opac_visible BOOL NOT NULL DEFAULT FALSE, name TEXT NOT NULL, required BOOL NOT NULL DEFAULT FALSE, + sip_field CHAR(2) REFERENCES asset.stat_cat_sip_fields(field) ON UPDATE CASCADE ON DELETE SET NULL DEFERRABLE INITIALLY DEFERRED, + sip_format TEXT, CONSTRAINT sc_once_per_owner UNIQUE (owner,name) ); @@ -161,6 +175,28 @@ CREATE TABLE asset.stat_cat_entry_copy_map ( ); CREATE INDEX scecm_owning_copy_idx ON asset.stat_cat_entry_copy_map(owning_copy); +CREATE FUNCTION asset.stat_cat_check() RETURNS trigger AS $func$ +DECLARE + sipfield asset.stat_cat_sip_fields%ROWTYPE; + use_count INT; +BEGIN + IF NEW.sip_field IS NOT NULL THEN + SELECT INTO sipfield * FROM asset.stat_cat_sip_fields WHERE field = NEW.sip_field; + IF sipfield.one_only THEN + SELECT INTO use_count count(id) FROM asset.stat_cat WHERE sip_field = NEW.sip_field AND id != NEW.id; + IF use_count > 0 THEN + RAISE EXCEPTION 'Sip field cannot be used twice'; + END IF; + END IF; + END IF; + RETURN NEW; +END; +$func$ LANGUAGE PLPGSQL; + +CREATE TRIGGER asset_stat_cat_sip_update_trigger + BEFORE INSERT OR UPDATE ON asset.stat_cat FOR EACH ROW + EXECUTE PROCEDURE asset.stat_cat_check(); + CREATE TABLE asset.copy_note ( id BIGSERIAL PRIMARY KEY, owning_copy BIGINT NOT NULL, diff --git a/Open-ILS/web/opac/locale/en-US/lang.dtd b/Open-ILS/web/opac/locale/en-US/lang.dtd index 99debd5c7a..0440099b92 100644 --- a/Open-ILS/web/opac/locale/en-US/lang.dtd +++ b/Open-ILS/web/opac/locale/en-US/lang.dtd @@ -737,6 +737,8 @@ + + @@ -2124,6 +2126,7 @@ + @@ -2147,6 +2150,12 @@ + + + + + + diff --git a/Open-ILS/web/templates/default/conify/global/config/actor_sip_fields.tt2 b/Open-ILS/web/templates/default/conify/global/config/actor_sip_fields.tt2 new file mode 100644 index 0000000000..5a0c897462 --- /dev/null +++ b/Open-ILS/web/templates/default/conify/global/config/actor_sip_fields.tt2 @@ -0,0 +1,28 @@ +[% WRAPPER default/base.tt2 %] +[% ctx.page_title = 'Actor Stat Cat Sip Fields' %] +
+
+
Actor Stat Cat Sip Fields
+
+ + +
+
+
+ + + + +[% END %] + + diff --git a/Open-ILS/web/templates/default/conify/global/config/asset_sip_fields.tt2 b/Open-ILS/web/templates/default/conify/global/config/asset_sip_fields.tt2 new file mode 100644 index 0000000000..bdf6e7ecef --- /dev/null +++ b/Open-ILS/web/templates/default/conify/global/config/asset_sip_fields.tt2 @@ -0,0 +1,28 @@ +[% WRAPPER default/base.tt2 %] +[% ctx.page_title = 'Asset Stat Cat Sip Fields' %] +
+
+
Asset Stat Cat Sip Fields
+
+ + +
+
+
+
+ + + +[% END %] + + diff --git a/Open-ILS/xul/staff_client/chrome/content/main/menu.js b/Open-ILS/xul/staff_client/chrome/content/main/menu.js index 47fc718770..3c3818af4e 100644 --- a/Open-ILS/xul/staff_client/chrome/content/main/menu.js +++ b/Open-ILS/xul/staff_client/chrome/content/main/menu.js @@ -737,6 +737,14 @@ main.menu.prototype = { ['oncommand'], function(event) { open_eg_web_page('conify/global/config/weight_assoc', null, event); } ], + 'cmd_server_admin_config_actor_sip_fields' : [ + ['oncommand'], + function(event) { open_eg_web_page('conify/global/config/actor_sip_fields', null, event); } + ], + 'cmd_server_admin_config_asset_sip_fields' : [ + ['oncommand'], + function(event) { open_eg_web_page('conify/global/config/asset_sip_fields', null, event); } + ], 'cmd_local_admin_external_text_editor' : [ ['oncommand'], function() { diff --git a/Open-ILS/xul/staff_client/chrome/content/main/menu_frame_menus.xul b/Open-ILS/xul/staff_client/chrome/content/main/menu_frame_menus.xul index 7fb34b1d18..1f85b6ecd6 100644 --- a/Open-ILS/xul/staff_client/chrome/content/main/menu_frame_menus.xul +++ b/Open-ILS/xul/staff_client/chrome/content/main/menu_frame_menus.xul @@ -211,6 +211,12 @@ + + @@ -481,6 +487,8 @@ + + diff --git a/Open-ILS/xul/staff_client/server/admin/stat_cat_editor.js b/Open-ILS/xul/staff_client/server/admin/stat_cat_editor.js index 55bad5853c..f16761e7c8 100644 --- a/Open-ILS/xul/staff_client/server/admin/stat_cat_editor.js +++ b/Open-ILS/xul/staff_client/server/admin/stat_cat_editor.js @@ -1,4 +1,5 @@ var SC_FETCH_ALL = 'open-ils.circ:open-ils.circ.stat_cat.TYPE.retrieve.all'; +var SC_FETCH_SF = 'open-ils.pcrud:open-ils.pcrud.search.PCRUD.atomic'; var SC_CREATE = 'open-ils.circ:open-ils.circ.stat_cat.TYPE.create'; var SC_UPDATE = 'open-ils.circ:open-ils.circ.stat_cat.TYPE.update'; var SC_DELETE = 'open-ils.circ:open-ils.circ.stat_cat.TYPE.delete'; @@ -16,6 +17,12 @@ var PERMS = {}; PERMS[ACTOR] = {}; PERMS[ASSET] = {}; +var PCRUD_CLASS = {}; +PCRUD_CLASS[ACTOR] = 'actscsf'; +PCRUD_CLASS[ASSET] = 'ascsf'; + +scSFCache = {}; + var currentlyVisible; var opacVisible = false; var cgi; @@ -84,6 +91,21 @@ function scEditorInit() { }, 20 ); } +function scPopSipFields( selector, type ) { + while(selector.lastChild.value != '') selector.removeChild(selector.lastChild); + if(!scSFCache[type]) { + var req = new Request( + SC_FETCH_SF.replace(/PCRUD/, PCRUD_CLASS[type]) , session, { 'field' : { '!=' : null } } ); + req.send(true); + scSFCache[type] = req.result(); + } + for(var f in scSFCache[type]) { + var option = document.createElement('option'); + option.value = scSFCache[type][f].field(); + option.appendChild(text(scSFCache[type][f].name() + ' (' + scSFCache[type][f].field() + ')' + (isTrue(scSFCache[type][f].one_only()) ? '**' : ''))); + selector.appendChild(option); + } +} function scGo() { var show = cgi.param('show'); @@ -171,6 +193,16 @@ function scInsertCat( tbody, cat, type ) { else unHideMe($n(row, 'sc_opac_invisible')); + if(cat.sip_field().length != 2) + unHideMe($n(row, 'sc_sip_field_none')); + else { + $n(row, 'sc_sip_field_value').appendChild( text( cat.sip_field() ) ); + unHideMe($n(row, 'sc_sip_field_value')); + } + + $n(row, 'sc_sip_format_td').appendChild( text( cat.sip_format() ) ); + + if(type == ACTOR) { if(isTrue(cat.usr_summary())) unHideMe($n(row, 'sc_usr_summary_on')); @@ -285,10 +317,12 @@ function scBuildNew() { hideMe($('required_td2')); unHideMe($('usr_summary_td1')); unHideMe($('usr_summary_td2')); + unHideMe($('sip_tr')); break; case ASSET: hideMe($('usr_summary_td1')); hideMe($('usr_summary_td2')); + hideMe($('sip_tr')); unHideMe($('required_td1')); unHideMe($('required_td2')); break; @@ -304,6 +338,7 @@ function scBuildNew() { libSel.disabled = false; } buildMergedOrgSel(libSel, org_list, 0, 'shortname'); + scPopSipFields($('sc_sip_field'),type); } @@ -328,6 +363,10 @@ function scNew() { cat = new asc(); cat.required( required ); } + var field = getSelectorVal($('sc_sip_field')); + if(field.length == 2) cat.sip_field(field); + else cat.sip_field(null); + cat.sip_format($('sc_sip_format').value); cat.opac_visible(visible); cat.name(name); @@ -354,7 +393,10 @@ function scEdit( tbody, type, cat ) { if(r.nextSibling) { tbody.insertBefore( row, r.nextSibling ); } else{ tbody.appendChild(row); } + scPopSipFields($n(row, 'sc_edit_sip_field'), type); $n(row, 'sc_edit_name').value = cat.name(); + setSelector($n(row, 'sc_edit_sip_field'), cat.sip_field()); + $n(row, 'sc_edit_sip_format').value = cat.sip_format(); if(type == ACTOR) { var cb = $n(row, 'sc_edit_usr_summary'); @@ -425,11 +467,15 @@ function scEditGo( type, cat, row, selector ) { var usr_summary = $n(row, 'sc_edit_usr_summary').checked; var required = $n(row, 'sc_edit_required').checked; + var sip_field = getSelectorVal( $n(row, 'sc_edit_sip_field') ); cat.name( name ); cat.owner( newlib ); cat.entries(null); cat.opac_visible(0); + if(sip_field.length == 2) cat.sip_field( sip_field ); + else cat.sip_field(null); + cat.sip_format($n(row, 'sc_edit_sip_format').value); if( visible ) cat.opac_visible(1); switch(type) { case ACTOR: diff --git a/Open-ILS/xul/staff_client/server/admin/stat_cat_editor.xhtml b/Open-ILS/xul/staff_client/server/admin/stat_cat_editor.xhtml index b468a97c93..8c706a7ea1 100644 --- a/Open-ILS/xul/staff_client/server/admin/stat_cat_editor.xhtml +++ b/Open-ILS/xul/staff_client/server/admin/stat_cat_editor.xhtml @@ -96,7 +96,16 @@ &staff.server.admin.stat_cat.off; - + + + + + + + + @@ -171,6 +183,11 @@ &staff.server.admin.stat_cat.off; + + +
&staff.server.admin.stat_cat.sip_field; + + &staff.server.admin.stat_cat.sip_format;
@@ -132,6 +141,7 @@
&staff.server.admin.stat_cat.info_prompt;
+
&staff.server.admin.stat_cat.sip_field_warning;

&staff.server.admin.stat_cat.none_defined;
@@ -147,6 +157,8 @@
&staff.server.admin.stat_cat.opac_visibility.label; &staff.server.admin.stat_cat.required.label; &staff.server.admin.stat_cat.usr_summary.label;&staff.server.admin.stat_cat.sip_field.label;&staff.server.admin.stat_cat.sip_format.label; &staff.server.admin.stat_cat.entries.label; &staff.server.admin.stat_cat.add_entry; &staff.server.admin.stat_cat.edit; + &staff.server.admin.stat_cat.sip_field.none.label; + + + @@ -225,6 +242,14 @@ + + + + -- 2.11.0