]> git.evergreen-ils.org Git - Evergreen.git/blob - Open-ILS/src/sql/Pg/upgrade/0059.schema.broken-circ-by-circ_mod-query.sql
LP#1947173: Clean up bad cataloging pot hole
[Evergreen.git] / Open-ILS / src / sql / Pg / upgrade / 0059.schema.broken-circ-by-circ_mod-query.sql
1
2 BEGIN;
3
4 INSERT INTO config.upgrade_log (version) VALUES ('0059'); -- miker
5
6 CREATE OR REPLACE FUNCTION action.item_user_circ_test( circ_ou INT, match_item BIGINT, match_user INT, renewal BOOL ) RETURNS SETOF action.matrix_test_result AS $func$
7 DECLARE
8     user_object        actor.usr%ROWTYPE;
9     standing_penalty    config.standing_penalty%ROWTYPE;
10     item_object        asset.copy%ROWTYPE;
11     item_status_object    config.copy_status%ROWTYPE;
12     item_location_object    asset.copy_location%ROWTYPE;
13     result            action.matrix_test_result;
14     circ_test        config.circ_matrix_matchpoint%ROWTYPE;
15     out_by_circ_mod        config.circ_matrix_circ_mod_test%ROWTYPE;
16     circ_mod_map        config.circ_matrix_circ_mod_test_map%ROWTYPE;
17     penalty_type         TEXT;
18     tmp_grp         INT;
19     items_out        INT;
20     context_org_list        INT[];
21     done            BOOL := FALSE;
22 BEGIN
23     result.success := TRUE;
24
25     -- Fail if the user is BARRED
26     SELECT INTO user_object * FROM actor.usr WHERE id = match_user;
27
28     -- Fail if we couldn't find a set of tests
29     IF user_object.id IS NULL THEN
30         result.fail_part := 'no_user';
31         result.success := FALSE;
32         done := TRUE;
33         RETURN NEXT result;
34         RETURN;
35     END IF;
36
37     IF user_object.barred IS TRUE THEN
38         result.fail_part := 'actor.usr.barred';
39         result.success := FALSE;
40         done := TRUE;
41         RETURN NEXT result;
42     END IF;
43
44     -- Fail if the item can't circulate
45     SELECT INTO item_object * FROM asset.copy WHERE id = match_item;
46     IF item_object.circulate IS FALSE THEN
47         result.fail_part := 'asset.copy.circulate';
48         result.success := FALSE;
49         done := TRUE;
50         RETURN NEXT result;
51     END IF;
52
53     -- Fail if the item isn't in a circulateable status on a non-renewal
54     IF NOT renewal AND item_object.status NOT IN ( 0, 7, 8 ) THEN 
55         result.fail_part := 'asset.copy.status';
56         result.success := FALSE;
57         done := TRUE;
58         RETURN NEXT result;
59     ELSIF renewal AND item_object.status <> 1 THEN
60         result.fail_part := 'asset.copy.status';
61         result.success := FALSE;
62         done := TRUE;
63         RETURN NEXT result;
64     END IF;
65
66     -- Fail if the item can't circulate because of the shelving location
67     SELECT INTO item_location_object * FROM asset.copy_location WHERE id = item_object.location;
68     IF item_location_object.circulate IS FALSE THEN
69         result.fail_part := 'asset.copy_location.circulate';
70         result.success := FALSE;
71         done := TRUE;
72         RETURN NEXT result;
73     END IF;
74
75     SELECT INTO circ_test * FROM action.find_circ_matrix_matchpoint(circ_ou, match_item, match_user, renewal);
76     result.matchpoint := circ_test.id;
77
78     SELECT INTO context_org_list ARRAY_ACCUM(id) FROM actor.org_unit_full_path( circ_test.org_unit );
79
80     -- Fail if we couldn't find a set of tests
81     IF result.matchpoint IS NULL THEN
82         result.fail_part := 'no_matchpoint';
83         result.success := FALSE;
84         done := TRUE;
85         RETURN NEXT result;
86     END IF;
87
88     -- Fail if the test is set to hard non-circulating
89     IF circ_test.circulate IS FALSE THEN
90         result.fail_part := 'config.circ_matrix_test.circulate';
91         result.success := FALSE;
92         done := TRUE;
93         RETURN NEXT result;
94     END IF;
95
96     IF renewal THEN
97         penalty_type = '%RENEW%';
98     ELSE
99         penalty_type = '%CIRC%';
100     END IF;
101
102     FOR standing_penalty IN
103         SELECT  DISTINCT csp.*
104           FROM  actor.usr_standing_penalty usp
105                 JOIN config.standing_penalty csp ON (csp.id = usp.standing_penalty)
106           WHERE usr = match_user
107                 AND usp.org_unit IN ( SELECT * FROM explode_array(context_org_list) )
108                 AND (usp.stop_date IS NULL or usp.stop_date > NOW())
109                 AND csp.block_list LIKE penalty_type LOOP
110
111         result.fail_part := standing_penalty.name;
112         result.success := FALSE;
113         done := TRUE;
114         RETURN NEXT result;
115     END LOOP;
116
117     -- Fail if the user has too many items with specific circ_modifiers checked out
118     FOR out_by_circ_mod IN SELECT * FROM config.circ_matrix_circ_mod_test WHERE matchpoint = circ_test.id LOOP
119         SELECT  INTO items_out COUNT(*)
120           FROM  action.circulation circ
121             JOIN asset.copy cp ON (cp.id = circ.target_copy)
122           WHERE circ.usr = match_user
123                AND circ.circ_lib IN ( SELECT * FROM explode_array(context_org_list) )
124             AND circ.checkin_time IS NULL
125             AND (circ.stop_fines IN ('MAXFINES','LONGOVERDUE') OR circ.stop_fines IS NULL)
126             AND cp.circ_modifier IN (SELECT circ_mod FROM config.circ_matrix_circ_mod_test_map WHERE circ_mod_test = out_by_circ_mod.id);
127         IF items_out >= out_by_circ_mod.items_out THEN
128             result.fail_part := 'config.circ_matrix_circ_mod_test';
129             result.success := FALSE;
130             done := TRUE;
131             RETURN NEXT result;
132         END IF;
133     END LOOP;
134
135     -- If we passed everything, return the successful matchpoint id
136     IF NOT done THEN
137         RETURN NEXT result;
138     END IF;
139
140     RETURN;
141 END;
142 $func$ LANGUAGE plpgsql;
143
144 COMMIT;
145