pushing in-db circ and hold to use directly calculated standing penalties where possible.
authormiker <miker@dcc99617-32d9-48b4-a31d-7c20da2025e4>
Thu, 20 Nov 2008 05:57:55 +0000 (05:57 +0000)
committermiker <miker@dcc99617-32d9-48b4-a31d-7c20da2025e4>
Thu, 20 Nov 2008 05:57:55 +0000 (05:57 +0000)
git-svn-id: svn://svn.open-ils.org/ILS/trunk@11280 dcc99617-32d9-48b4-a31d-7c20da2025e4

Open-ILS/src/sql/Pg/006.schema.permissions.sql
Open-ILS/src/sql/Pg/100.circ_matrix.sql
Open-ILS/src/sql/Pg/110.hold_matrix.sql
Open-ILS/src/sql/Pg/950.data.seed-values.sql

index e0e9980..99f8cbc 100644 (file)
@@ -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,
index 33eecbb..8fc9d98 100644 (file)
@@ -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;
 
index 857f72e..2e5861a 100644 (file)
@@ -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;
index 43f410b..4041733 100644 (file)
@@ -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);