From: Thomas Berezansky Date: Sat, 17 Sep 2011 18:49:16 +0000 (-0400) Subject: Circ Statistical Archiving X-Git-Url: https://old-git.evergreen-ils.org/?a=commitdiff_plain;h=ee27d36a3121b409d17ba1016be93372a792c0d4;p=evergreen%2Fmasslnc.git Circ Statistical Archiving Copy Location Instead of only archiving the copy location with aged circs, do so with all circs, using the copy location at time of circ. This allows for running of reports on the copy location even after the item is no longer in it. Statistical Categories Add a flag to statistical categories to allow them to be archived with all circulations (at checkout). Reports can then be run on regular and aged circulations based on the contents of the statistical categories. This patch was inspired by Tim Spindler's submission to https://bugs.launchpad.net/evergreen/+bug/798255 - thanks Tim! Signed-off-by: Thomas Berezansky Signed-off-by: Dan Scott --- diff --git a/Open-ILS/examples/fm_IDL.xml b/Open-ILS/examples/fm_IDL.xml index 7e0b301081..57ef4091d4 100644 --- a/Open-ILS/examples/fm_IDL.xml +++ b/Open-ILS/examples/fm_IDL.xml @@ -3264,6 +3264,9 @@ SELECT usr, + + + @@ -3285,6 +3288,9 @@ SELECT usr, + + + @@ -3329,6 +3335,8 @@ SELECT usr, + + @@ -3350,6 +3358,8 @@ SELECT usr, + + @@ -3398,6 +3408,8 @@ SELECT usr, + + @@ -3423,6 +3435,8 @@ SELECT usr, + + @@ -4730,6 +4744,7 @@ SELECT usr, + @@ -4774,6 +4789,7 @@ SELECT usr, + @@ -9370,6 +9386,30 @@ SELECT usr, + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Open-ILS/src/perlmods/lib/OpenILS/Application/Storage/CDBI/action.pm b/Open-ILS/src/perlmods/lib/OpenILS/Application/Storage/CDBI/action.pm index 06094b40c1..2fbba741de 100644 --- a/Open-ILS/src/perlmods/lib/OpenILS/Application/Storage/CDBI/action.pm +++ b/Open-ILS/src/perlmods/lib/OpenILS/Application/Storage/CDBI/action.pm @@ -69,7 +69,7 @@ __PACKAGE__->columns(Essential => qw/xact_start usr target_copy circ_lib stop_fines xact_finish due_date opac_renewal checkin_staff circ_staff circ_lib checkin_lib stop_fines_time checkin_time desk_renewal - phone_renewal create_time/); + phone_renewal create_time copy_location/); #------------------------------------------------------------------------------- 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 89495fcb60..d95baa1e3c 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 sip_field sip_format/ ); +__PACKAGE__->columns( Essential => qw/owner name opac_visible usr_summary sip_field sip_format checkout_archive/ ); #------------------------------------------------------------------------------- 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 0fc1061eff..2b541cc95a 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 sip_field sip_format required/ ); +__PACKAGE__->columns( Essential => qw/owner name opac_visible sip_field sip_format required checkout_archive/ ); #------------------------------------------------------------------------------- package asset::stat_cat_entry; diff --git a/Open-ILS/src/sql/Pg/005.schema.actors.sql b/Open-ILS/src/sql/Pg/005.schema.actors.sql index 3a9f841e9e..fbe05048c5 100644 --- a/Open-ILS/src/sql/Pg/005.schema.actors.sql +++ b/Open-ILS/src/sql/Pg/005.schema.actors.sql @@ -187,6 +187,7 @@ CREATE TABLE actor.stat_cat ( 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, + checkout_archive BOOL NOT NULL DEFAULT FALSE, CONSTRAINT sc_once_per_owner UNIQUE (owner,name) ); COMMENT ON TABLE actor.stat_cat IS $$ diff --git a/Open-ILS/src/sql/Pg/040.schema.asset.sql b/Open-ILS/src/sql/Pg/040.schema.asset.sql index fef5ced149..3beb24e0bf 100644 --- a/Open-ILS/src/sql/Pg/040.schema.asset.sql +++ b/Open-ILS/src/sql/Pg/040.schema.asset.sql @@ -177,6 +177,7 @@ CREATE TABLE asset.stat_cat ( 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, + checkout_archive BOOL NOT NULL DEFAULT FALSE, CONSTRAINT sc_once_per_owner UNIQUE (owner,name) ); diff --git a/Open-ILS/src/sql/Pg/090.schema.action.sql b/Open-ILS/src/sql/Pg/090.schema.action.sql index 05c45add4d..eae256a8a2 100644 --- a/Open-ILS/src/sql/Pg/090.schema.action.sql +++ b/Open-ILS/src/sql/Pg/090.schema.action.sql @@ -101,6 +101,20 @@ CREATE TRIGGER action_survey_response_answer_date_fixup_tgr FOR EACH ROW EXECUTE PROCEDURE action.survey_response_answer_date_fixup (); +CREATE TABLE action.archive_actor_stat_cat ( + id BIGSERIAL PRIMARY KEY, + xact BIGINT NOT NULL, -- action.circulation (+aged/all) + stat_cat INT NOT NULL, + value TEXT NOT NULL +); + +CREATE TABLE action.archive_asset_stat_cat ( + id BIGSERIAL PRIMARY KEY, + xact BIGINT NOT NULL, -- action.circulation (+aged/all) + stat_cat INT NOT NULL, + value TEXT NOT NULL +); + CREATE TABLE action.circulation ( target_copy BIGINT NOT NULL, -- asset.copy.id @@ -132,6 +146,7 @@ CREATE TABLE action.circulation ( checkin_workstation INT REFERENCES actor.workstation(id) ON DELETE SET NULL DEFERRABLE INITIALLY DEFERRED, + copy_location INT NOT NULL DEFAULT 1 REFERENCES asset.copy_location (id) DEFERRABLE INITIALLY DEFERRED, checkin_scan_time TIMESTAMP WITH TIME ZONE ) INHERITS (money.billable_xact); ALTER TABLE action.circulation ADD PRIMARY KEY (id); @@ -169,13 +184,40 @@ $$ LANGUAGE PLPGSQL; CREATE TRIGGER push_due_date_tgr BEFORE INSERT OR UPDATE ON action.circulation FOR EACH ROW EXECUTE PROCEDURE action.push_circ_due_time(); +CREATE OR REPLACE FUNCTION action.fill_circ_copy_location () RETURNS TRIGGER AS $$ +BEGIN + SELECT INTO NEW.copy_location location FROM asset.copy WHERE id = NEW.target_copy; + RETURN NEW; +END; +$$ LANGUAGE PLPGSQL; + +CREATE TRIGGER fill_circ_copy_location_tgr BEFORE INSERT ON action.circulation FOR EACH ROW EXECUTE PROCEDURE action.fill_circ_copy_location(); + +CREATE OR REPLACE FUNCTION action.archive_stat_cats () RETURNS TRIGGER AS $$ +BEGIN + INSERT INTO action.archive_actor_stat_cat(xact, stat_cat, value) + SELECT NEW.id, asceum.stat_cat, asceum.stat_cat_entry + FROM actor.stat_cat_entry_usr_map asceum + JOIN actor.stat_cat sc ON asceum.stat_cat = sc.id + WHERE NEW.usr = asceum.target_usr AND sc.checkout_archive; + INSERT INTO action.archive_asset_stat_cat(xact, stat_cat, value) + SELECT NEW.id, ascecm.stat_cat, asce.value + FROM asset.stat_cat_entry_copy_map ascecm + JOIN asset.stat_cat sc ON ascecm.stat_cat = sc.id + JOIN asset.stat_cat_entry asce ON ascecm.stat_cat_entry = asce.id + WHERE NEW.target_copy = ascecm.owning_copy AND sc.checkout_archive; + RETURN NULL; +END; +$$ LANGUAGE PLPGSQL; + +CREATE TRIGGER archive_stat_cats_tgr AFTER INSERT ON action.circulation FOR EACH ROW EXECUTE PROCEDURE action.archive_stat_cats(); + CREATE TABLE action.aged_circulation ( usr_post_code TEXT, usr_home_ou INT NOT NULL, usr_profile INT NOT NULL, usr_birth_year INT, copy_call_number INT NOT NULL, - copy_location INT NOT NULL, copy_owning_lib INT NOT NULL, copy_circ_lib INT NOT NULL, copy_bib_record BIGINT NOT NULL, @@ -201,7 +243,7 @@ CREATE OR REPLACE VIEW action.all_circulation AS FROM action.aged_circulation UNION ALL SELECT DISTINCT circ.id,COALESCE(a.post_code,b.post_code) AS usr_post_code, p.home_ou AS usr_home_ou, p.profile AS usr_profile, EXTRACT(YEAR FROM p.dob)::INT AS usr_birth_year, - cp.call_number AS copy_call_number, cp.location AS copy_location, cn.owning_lib AS copy_owning_lib, cp.circ_lib AS copy_circ_lib, + cp.call_number AS copy_call_number, circ.copy_location, cn.owning_lib AS copy_owning_lib, cp.circ_lib AS copy_circ_lib, cn.record AS copy_bib_record, circ.xact_start, circ.xact_finish, circ.target_copy, circ.circ_lib, circ.circ_staff, circ.checkin_staff, circ.checkin_lib, circ.renewal_remaining, circ.grace_period, circ.due_date, circ.stop_fines_time, circ.checkin_time, circ.create_time, circ.duration, circ.fine_interval, circ.recurring_fine, circ.max_fine, circ.phone_renewal, circ.desk_renewal, circ.opac_renewal, circ.duration_rule, diff --git a/Open-ILS/src/sql/Pg/upgrade/XXXX.schema.statistical_archive.sql b/Open-ILS/src/sql/Pg/upgrade/XXXX.schema.statistical_archive.sql new file mode 100644 index 0000000000..886e28df40 --- /dev/null +++ b/Open-ILS/src/sql/Pg/upgrade/XXXX.schema.statistical_archive.sql @@ -0,0 +1,61 @@ +-- New tables + +CREATE TABLE action.archive_actor_stat_cat ( + id BIGSERIAL PRIMARY KEY, + xact BIGINT NOT NULL, + stat_cat INT NOT NULL, + value TEXT NOT NULL +); + +CREATE TABLE action.archive_asset_stat_cat ( + id BIGSERIAL PRIMARY KEY, + xact BIGINT NOT NULL, + stat_cat INT NOT NULL, + value TEXT NOT NULL +); + +-- Add columns to existing tables + +-- Archive Flag Columns +ALTER TABLE actor.stat_cat + ADD COLUMN checkout_archive BOOL NOT NULL DEFAULT FALSE; +ALTER TABLE asset.stat_cat + ADD COLUMN checkout_archive BOOL NOT NULL DEFAULT FALSE; + +-- Circulation copy column +ALTER TABLE action.circulation + ADD COLUMN copy_location INT NOT NULL DEFAULT 1 REFERENCES asset.copy_location(id) DEFERRABLE INITIALLY DEFERRED; + +-- Update action.circulation with real copy_location numbers instead of all "Stacks" +UPDATE action.circulation circ SET copy_location = ac.location FROM asset.copy ac WHERE ac.id = circ.target_copy; + +-- Create trigger function to auto-fill the copy_location field +CREATE OR REPLACE FUNCTION action.fill_circ_copy_location () RETURNS TRIGGER AS $$ +BEGIN + SELECT INTO NEW.copy_location location FROM asset.copy WHERE id = NEW.target_copy; + RETURN NEW; +END; +$$ LANGUAGE PLPGSQL; + +-- Create trigger function to auto-archive stat cat entries +CREATE OR REPLACE FUNCTION action.archive_stat_cats () RETURNS TRIGGER AS $$ +BEGIN + INSERT INTO action.archive_actor_stat_cat(xact, stat_cat, value) + SELECT NEW.id, asceum.stat_cat, asceum.stat_cat_entry + FROM actor.stat_cat_entry_usr_map asceum + JOIN actor.stat_cat sc ON asceum.stat_cat = sc.id + WHERE NEW.usr = asceum.target_usr AND sc.checkout_archive; + INSERT INTO action.archive_asset_stat_cat(xact, stat_cat, value) + SELECT NEW.id, ascecm.stat_cat, asce.value + FROM asset.stat_cat_entry_copy_map ascecm + JOIN asset.stat_cat sc ON ascecm.stat_cat = sc.id + JOIN asset.stat_cat_entry asce ON ascecm.stat_cat_entry = asce.id + WHERE NEW.target_copy = ascecm.owning_copy AND sc.checkout_archive; + RETURN NULL; +END; +$$ LANGUAGE PLPGSQL; + +-- Apply triggers +CREATE TRIGGER fill_circ_copy_location_tgr BEFORE INSERT ON action.circulation FOR EACH ROW EXECUTE PROCEDURE action.fill_circ_copy_location(); +CREATE TRIGGER archive_stat_cats_tgr AFTER INSERT ON action.circulation FOR EACH ROW EXECUTE PROCEDURE action.archive_stat_cats(); + diff --git a/Open-ILS/src/sql/Pg/upgrade/XXXY.schema.statistical_archive.all_circulation.sql b/Open-ILS/src/sql/Pg/upgrade/XXXY.schema.statistical_archive.all_circulation.sql new file mode 100644 index 0000000000..ff14cd4b57 --- /dev/null +++ b/Open-ILS/src/sql/Pg/upgrade/XXXY.schema.statistical_archive.all_circulation.sql @@ -0,0 +1,23 @@ +-- Update view to use circ's copy_location field instead of the copy's current copy_location field +CREATE OR REPLACE VIEW action.all_circulation AS + SELECT id,usr_post_code, usr_home_ou, usr_profile, usr_birth_year, copy_call_number, copy_location, + copy_owning_lib, copy_circ_lib, copy_bib_record, xact_start, xact_finish, target_copy, + circ_lib, circ_staff, checkin_staff, checkin_lib, renewal_remaining, grace_period, due_date, + stop_fines_time, checkin_time, create_time, duration, fine_interval, recurring_fine, + max_fine, phone_renewal, desk_renewal, opac_renewal, duration_rule, recurring_fine_rule, + max_fine_rule, stop_fines, workstation, checkin_workstation, checkin_scan_time, parent_circ + FROM action.aged_circulation + UNION ALL + SELECT DISTINCT circ.id,COALESCE(a.post_code,b.post_code) AS usr_post_code, p.home_ou AS usr_home_ou, p.profile AS usr_profile, EXTRACT(YEAR FROM p.dob)::INT AS usr_birth_year, + cp.call_number AS copy_call_number, circ.copy_location, cn.owning_lib AS copy_owning_lib, cp.circ_lib AS copy_circ_lib, + cn.record AS copy_bib_record, circ.xact_start, circ.xact_finish, circ.target_copy, circ.circ_lib, circ.circ_staff, circ.checkin_staff, + circ.checkin_lib, circ.renewal_remaining, circ.grace_period, circ.due_date, circ.stop_fines_time, circ.checkin_time, circ.create_time, circ.duration, + circ.fine_interval, circ.recurring_fine, circ.max_fine, circ.phone_renewal, circ.desk_renewal, circ.opac_renewal, circ.duration_rule, + circ.recurring_fine_rule, circ.max_fine_rule, circ.stop_fines, circ.workstation, circ.checkin_workstation, circ.checkin_scan_time, + circ.parent_circ + FROM action.circulation circ + JOIN asset.copy cp ON (circ.target_copy = cp.id) + JOIN asset.call_number cn ON (cp.call_number = cn.id) + JOIN actor.usr p ON (circ.usr = p.id) + LEFT JOIN actor.usr_address a ON (p.mailing_address = a.id) + LEFT JOIN actor.usr_address b ON (p.billing_address = b.id); diff --git a/Open-ILS/web/opac/locale/en-US/lang.dtd b/Open-ILS/web/opac/locale/en-US/lang.dtd index 9e9187073d..c26e5b8050 100644 --- a/Open-ILS/web/opac/locale/en-US/lang.dtd +++ b/Open-ILS/web/opac/locale/en-US/lang.dtd @@ -2196,6 +2196,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 f16761e7c8..8edabfdf10 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 @@ -202,6 +202,10 @@ function scInsertCat( tbody, cat, type ) { $n(row, 'sc_sip_format_td').appendChild( text( cat.sip_format() ) ); + if(isTrue(cat.checkout_archive())) + unHideMe($n(row, 'sc_checkout_archive_on')); + else + unHideMe($n(row, 'sc_checkout_archive')); if(type == ACTOR) { if(isTrue(cat.usr_summary())) @@ -350,9 +354,11 @@ function scNew() { var visible = 0; var required = 0; var usr_summary = 0; + var checkout_archive = 0; if( $('sc_make_opac_visible').checked) visible = 1; if( $('sc_make_required').checked) required = 1; if( $('sc_make_usr_summary').checked) usr_summary = 1; + if( $('sc_make_checkout_archive').checked) checkout_archive = 1; var cat; if( type == ACTOR ) { @@ -370,6 +376,7 @@ function scNew() { cat.opac_visible(visible); cat.name(name); + cat.checkout_archive(checkout_archive); cat.owner(getSelectorVal($('sc_owning_lib_selector'))); cat.isnew(1); @@ -439,6 +446,8 @@ function scEdit( tbody, type, cat ) { 'sc_edit_opac_visibility').checked = true; } + $n( row, 'sc_edit_checkout_archive' ).checked = isTrue(cat.checkout_archive()); + $n(row, 'sc_edit_submit').onclick = function() { scEditGo( type, cat, row, selector ); }; @@ -473,6 +482,7 @@ function scEditGo( type, cat, row, selector ) { cat.owner( newlib ); cat.entries(null); cat.opac_visible(0); + cat.checkout_archive($n(row, 'sc_edit_checkout_archive').checked ? 1 : 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); 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 c1d794bc23..0e98cba8cc 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 @@ -95,6 +95,13 @@ &staff.server.admin.stat_cat.off; + &staff.server.admin.stat_cat.checkout_archive; + + &staff.server.admin.stat_cat.on; + + &staff.server.admin.stat_cat.off; + + &staff.server.admin.stat_cat.sip_field; @@ -158,6 +165,7 @@ &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.checkout_archive.label; &staff.server.admin.stat_cat.entries.label; &staff.server.admin.stat_cat.add_entry; &staff.server.admin.stat_cat.edit; @@ -187,6 +195,10 @@ + &staff.server.admin.stat_cat.on; + &staff.server.admin.stat_cat.off; + + @@ -249,6 +261,9 @@ + + +