From: miker Date: Thu, 20 Nov 2008 05:57:55 +0000 (+0000) Subject: pushing in-db circ and hold to use directly calculated standing penalties where possible. X-Git-Url: https://old-git.evergreen-ils.org/?a=commitdiff_plain;h=dc8b219fe884443ea26d6216af2400efd5db66f8;p=Evergreen.git pushing in-db circ and hold to use directly calculated standing penalties where possible. git-svn-id: svn://svn.open-ils.org/ILS/trunk@11280 dcc99617-32d9-48b4-a31d-7c20da2025e4 --- diff --git a/Open-ILS/src/sql/Pg/006.schema.permissions.sql b/Open-ILS/src/sql/Pg/006.schema.permissions.sql index e0e9980e3a..99f8cbc185 100644 --- a/Open-ILS/src/sql/Pg/006.schema.permissions.sql +++ b/Open-ILS/src/sql/Pg/006.schema.permissions.sql @@ -39,6 +39,14 @@ CREATE TABLE permission.grp_tree ( ); CREATE INDEX grp_tree_parent_idx ON permission.grp_tree (parent); +CREATE TABLE permission.grp_penalty_threshold ( + id SERIAL PRIMARY KEY, + grp INT NOT NULL REFERENCES permission.grp_tree (id) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, + penalty INT NOT NULL REFERENCES config.standing_penalty (id) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, + threshold NUMERIC(8,2) NOT NULL, + CONSTRAINT penalty_grp_once UNIQUE (grp,penalty) +); + CREATE TABLE permission.grp_perm_map ( id SERIAL PRIMARY KEY, grp INT NOT NULL REFERENCES permission.grp_tree (id) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, diff --git a/Open-ILS/src/sql/Pg/100.circ_matrix.sql b/Open-ILS/src/sql/Pg/100.circ_matrix.sql index 33eecbb953..8fc9d98f33 100644 --- a/Open-ILS/src/sql/Pg/100.circ_matrix.sql +++ b/Open-ILS/src/sql/Pg/100.circ_matrix.sql @@ -117,8 +117,6 @@ CREATE TABLE config.circ_matrix_test ( matchpoint INT PRIMARY KEY NOT NULL REFERENCES config.circ_matrix_matchpoint (id) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, circulate BOOL NOT NULL DEFAULT TRUE, -- Hard "can't circ" flag requiring an override max_items_out INT, -- Total current active circulations must be less than this, NULL means skip (always pass) - max_overdue INT, -- Total overdue active circulations must be less than this, NULL means skip (always pass) - max_fines NUMERIC(8,2), -- Total fines owed must be less than this, NULL means skip (always pass) org_depth INT, -- Set to the top OU for the max-out applicability range script_test TEXT -- filename or javascript source ?? ); @@ -232,9 +230,13 @@ DECLARE result action.matrix_test_result; circ_test config.circ_matrix_test%ROWTYPE; out_by_circ_mod config.circ_matrix_circ_mod_test%ROWTYPE; + patron_penalties INT; + tmp_grp INT; items_out INT; + max_overdue INT; items_overdue INT; overdue_orgs INT[]; + max_fines NUMERIC(8,2) := 0.0; current_fines NUMERIC(8,2) := 0.0; tmp_fines NUMERIC(8,2); tmp_groc RECORD; @@ -318,6 +320,34 @@ BEGIN RETURN NEXT result; END IF; + SELECT INTO patron_penalties COUNT(*) + FROM actor.usr_standing_penalty usp + JOIN config.standing_penalty csp ON (csp.id = usp.penalty) + WHERE usr = match_user + AND csp.block_list LIKE '%RENEW%'; + + IF patron_penalties > 0 THEN + result.fail_part := 'config.circ_matrix_test.stop_blocked_user.circ'; + result.success := FALSE; + done := TRUE; + RETURN NEXT result; + END IF; + + patron_penalties := 0; + + SELECT INTO patron_penalties COUNT(*) + FROM actor.usr_standing_penalty usp + JOIN config.standing_penalty csp ON (csp.id = usp.penalty) + WHERE usr = match_user + AND csp.block_list LIKE '%CIRC%'; + + IF patron_penalties > 0 THEN + result.fail_part := 'config.circ_matrix_test.stop_blocked_user.renew'; + result.success := FALSE; + done := TRUE; + RETURN NEXT result; + END IF; + -- Fail if the user has too many items checked out IF circ_test.max_items_out IS NOT NULL THEN SELECT INTO items_out COUNT(*) @@ -327,7 +357,7 @@ BEGIN AND checkin_time IS NULL AND (stop_fines NOT IN ('LOST','CLAIMSRETURNED','LONGOVERDUE') OR stop_fines IS NULL); IF items_out >= circ_test.max_items_out THEN - result.fail_part := 'config.circ_matrix_test.max_items_out'; + result.fail_part := 'config.circ_matrix_test.max_items_out'; result.success := FALSE; done := TRUE; RETURN NEXT result; @@ -353,7 +383,21 @@ BEGIN END LOOP; -- Fail if the user has too many overdue items - IF circ_test.max_overdue IS NOT NULL THEN + tmp_grp := user_object.profile; + LOOP + SELECT pgpt.threshold::INT INTO max_overdue FROM permission.grp_penalty_threshold WHERE grp = tmp_grp AND penalty = 2; + IF max_overdue IS NULL THEN + SELECT parent INTO tmp_grp FROM permission.grp_tree WHERE id = tmp_grp; + ELSE + EXIT; + END IF; + + IF tmp_grp IS NULL THEN + EXIT; + END IF; + END LOOP; + + IF max_overdue IS NOT NULL THEN SELECT INTO items_overdue COUNT(*) FROM action.circulation WHERE usr = match_user @@ -361,7 +405,9 @@ BEGIN AND checkin_time IS NULL AND due_date < NOW() AND (stop_fines NOT IN ('LOST','CLAIMSRETURNED','LONGOVERDUE') OR stop_fines IS NULL); - IF items_overdue >= circ_test.max_overdue THEN + IF items_overdue >= max_overdue THEN + DELETE FROM actor.usr_standing_penalty WHERE usr = match_usr AND standing_penalty = 2; + INSERT INTO actor.usr_standing_penalty (usr, standing_penalty) VALUES (match_usr, 2); result.fail_part := 'config.circ_matrix_test.max_overdue'; result.success := FALSE; done := TRUE; @@ -370,7 +416,21 @@ BEGIN END IF; -- Fail if the user has a high fine balance - IF circ_test.max_fines IS NOT NULL THEN + tmp_grp := user_object.profile; + LOOP + SELECT pgpt.threshold INTO max_fines FROM permission.grp_penalty_threshold WHERE grp = tmp_grp AND penalty = 1; + IF max_overdue IS NULL THEN + SELECT parent INTO tmp_grp FROM permission.grp_tree WHERE id = tmp_grp; + ELSE + EXIT; + END IF; + + IF tmp_grp IS NULL THEN + EXIT; + END IF; + END LOOP; + + IF max_fines IS NOT NULL THEN FOR tmp_groc IN SELECT * FROM money.grocery WHERE usr = match_usr AND xact_finish IS NULL AND (circ_test.org_depth IS NULL OR (circ_test.org_depth IS NOT NULL AND billing_location IN ( SELECT * FROM explode_array(overdue_orgs) ))) LOOP SELECT INTO tmp_fines SUM( amount ) FROM money.billing WHERE xact = tmp_groc.id AND NOT voided; current_fines = current_fines + COALESCE(tmp_fines, 0.0); @@ -385,7 +445,9 @@ BEGIN current_fines = current_fines - COALESCE(tmp_fines, 0.0); END LOOP; - IF current_fines >= circ_test.max_fines THEN + IF current_fines >= max_fines THEN + DELETE FROM actor.usr_standing_penalty WHERE usr = match_usr AND standing_penalty = 1; + INSERT INTO actor.usr_standing_penalty (usr, standing_penalty) VALUES (match_usr, 1); result.fail_part := 'config.circ_matrix_test.max_fines'; result.success := FALSE; RETURN NEXT result; @@ -410,6 +472,8 @@ CREATE OR REPLACE FUNCTION action.item_user_renew_test( INT, BIGINT, INT ) RETUR SELECT * FROM action.item_user_circ_test( $1, $2, $3, TRUE ); $func$ LANGUAGE SQL; +CREATE OR REPLACE FUNCTION actor.refresh_auto_penalties( user INT ) RETURNS INT AS $func$ +$func$ LANGUAGE plpgsql; COMMIT; diff --git a/Open-ILS/src/sql/Pg/110.hold_matrix.sql b/Open-ILS/src/sql/Pg/110.hold_matrix.sql index 857f72e071..2e5861a794 100644 --- a/Open-ILS/src/sql/Pg/110.hold_matrix.sql +++ b/Open-ILS/src/sql/Pg/110.hold_matrix.sql @@ -252,13 +252,30 @@ BEGIN END IF; END IF; + SELECT INTO patron_penalties COUNT(*) + FROM actor.usr_standing_penalty usp + JOIN config.standing_penalty csp ON (csp.id = usp.penalty) + WHERE usr = match_user + AND csp.block_list LIKE '%HOLD%'; + + IF patron_penalties > 0 THEN + result.fail_part := 'config.hold_matrix_test.stop_blocked_user.hold'; + result.success := FALSE; + done := TRUE; + RETURN NEXT result; + END IF; + + patron_penalties := 0; + IF hold_test.stop_blocked_user IS TRUE THEN SELECT INTO patron_penalties COUNT(*) - FROM actor.usr_standing_penalty - WHERE usr = match_user; + FROM actor.usr_standing_penalty usp + JOIN config.standing_penalty csp ON (csp.id = usp.penalty) + WHERE usr = match_user + AND csp.block_list LIKE '%CIRC%'; - IF items_out > 0 THEN - result.fail_part := 'config.hold_matrix_test.stop_blocked_user'; + IF patron_penalties > 0 THEN + result.fail_part := 'config.hold_matrix_test.stop_blocked_user.circ'; result.success := FALSE; done := TRUE; RETURN NEXT result; @@ -273,7 +290,7 @@ BEGIN AND cancel_time IS NULL AND CASE WHEN hold_test.include_frozen_holds THEN TRUE ELSE frozen IS FALSE END; - IF items_out >= hold_test.max_holds THEN + IF hold_count >= hold_test.max_holds THEN result.fail_part := 'config.hold_matrix_test.max_holds'; result.success := FALSE; done := TRUE; diff --git a/Open-ILS/src/sql/Pg/950.data.seed-values.sql b/Open-ILS/src/sql/Pg/950.data.seed-values.sql index 43f410b3a1..404173351b 100644 --- a/Open-ILS/src/sql/Pg/950.data.seed-values.sql +++ b/Open-ILS/src/sql/Pg/950.data.seed-values.sql @@ -1293,6 +1293,13 @@ INSERT INTO permission.grp_tree (id, name, parent, description, perm_interval, u SELECT SETVAL('permission.grp_tree_id_seq'::TEXT, (SELECT MAX(id) FROM permission.grp_tree)); +INSERT INTO permission.grp_penalty_threshold (grp,penalty,threshold) + VALUES (1,1,10.0); +INSERT INTO permission.grp_penalty_threshold (grp,penalty,threshold) + VALUES (1,2,10.0); + +SELECT SETVAL('permission.grp_tree_id_seq'::TEXT, (SELECT MAX(id) FROM permission.grp_tree)); + -- XXX Incomplete base permission setup. A patch would be appreciated. INSERT INTO permission.grp_perm_map VALUES (57, 2, 15, 0, false); INSERT INTO permission.grp_perm_map VALUES (109, 2, 95, 0, false);