]> git.evergreen-ils.org Git - working/Evergreen.git/blob - Open-ILS/src/sql/Pg/upgrade/0277.schema.address_schema_drift.sql
Allow combined search to be optional per class
[working/Evergreen.git] / Open-ILS / src / sql / Pg / upgrade / 0277.schema.address_schema_drift.sql
1 BEGIN;
2
3 INSERT INTO config.upgrade_log (version) VALUES ('0277'); -- miker
4
5 -- Use oils_xpath_table instead of pgxml's xpath_table
6 CREATE OR REPLACE FUNCTION acq.extract_holding_attr_table (lineitem int, tag text) RETURNS SETOF acq.flat_lineitem_holding_subfield AS $$
7 DECLARE
8     counter INT;
9     lida    acq.flat_lineitem_holding_subfield%ROWTYPE;
10 BEGIN
11
12     SELECT  COUNT(*) INTO counter
13       FROM  oils_xpath_table(
14                 'id',
15                 'marc',
16                 'acq.lineitem',
17                 '//*[@tag="' || tag || '"]',
18                 'id=' || lineitem
19             ) as t(i int,c text);
20
21     FOR i IN 1 .. counter LOOP
22         FOR lida IN
23             SELECT  *
24               FROM  (   SELECT  id,i,t,v
25                           FROM  oils_xpath_table(
26                                     'id',
27                                     'marc',
28                                     'acq.lineitem',
29                                     '//*[@tag="' || tag || '"][position()=' || i || ']/*/@code|' ||
30                                         '//*[@tag="' || tag || '"][position()=' || i || ']/*[@code]',
31                                     'id=' || lineitem
32                                 ) as t(id int,t text,v text)
33                     )x
34         LOOP
35             RETURN NEXT lida;
36         END LOOP;
37     END LOOP;
38
39     RETURN;
40 END;
41 $$ LANGUAGE PLPGSQL;
42
43 -- Use the identifier search class tsconfig
44 DROP TRIGGER metabib_identifier_field_entry_fti_trigger ON metabib.identifier_field_entry;
45 CREATE TRIGGER metabib_identifier_field_entry_fti_trigger
46     BEFORE INSERT OR UPDATE ON metabib.identifier_field_entry
47     FOR EACH ROW
48     EXECUTE PROCEDURE public.oils_tsearch2('identifier');
49
50 -- Return the correct fail_part when the item can't be found
51 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$
52 DECLARE
53     user_object        actor.usr%ROWTYPE;
54     standing_penalty    config.standing_penalty%ROWTYPE;
55     item_object        asset.copy%ROWTYPE;
56     item_status_object    config.copy_status%ROWTYPE;
57     item_location_object    asset.copy_location%ROWTYPE;
58     result            action.matrix_test_result;
59     circ_test        config.circ_matrix_matchpoint%ROWTYPE;
60     out_by_circ_mod        config.circ_matrix_circ_mod_test%ROWTYPE;
61     circ_mod_map        config.circ_matrix_circ_mod_test_map%ROWTYPE;
62     hold_ratio          action.hold_stats%ROWTYPE;
63     penalty_type         TEXT;
64     tmp_grp         INT;
65     items_out        INT;
66     context_org_list        INT[];
67     done            BOOL := FALSE;
68 BEGIN
69     result.success := TRUE;
70
71     -- Fail if the user is BARRED
72     SELECT INTO user_object * FROM actor.usr WHERE id = match_user;
73
74     -- Fail if we couldn't find the user 
75     IF user_object.id IS NULL THEN
76         result.fail_part := 'no_user';
77         result.success := FALSE;
78         done := TRUE;
79         RETURN NEXT result;
80         RETURN;
81     END IF;
82
83     SELECT INTO item_object * FROM asset.copy WHERE id = match_item;
84
85     -- Fail if we couldn't find the item 
86     IF item_object.id IS NULL THEN
87         result.fail_part := 'no_item';
88         result.success := FALSE;
89         done := TRUE;
90         RETURN NEXT result;
91         RETURN;
92     END IF;
93
94     SELECT INTO circ_test * FROM action.find_circ_matrix_matchpoint(circ_ou, match_item, match_user, renewal);
95     result.matchpoint := circ_test.id;
96
97     -- Fail if we couldn't find a matchpoint
98     IF result.matchpoint IS NULL THEN
99         result.fail_part := 'no_matchpoint';
100         result.success := FALSE;
101         done := TRUE;
102         RETURN NEXT result;
103     END IF;
104
105     IF user_object.barred IS TRUE THEN
106         result.fail_part := 'actor.usr.barred';
107         result.success := FALSE;
108         done := TRUE;
109         RETURN NEXT result;
110     END IF;
111
112     -- Fail if the item can't circulate
113     IF item_object.circulate IS FALSE THEN
114         result.fail_part := 'asset.copy.circulate';
115         result.success := FALSE;
116         done := TRUE;
117         RETURN NEXT result;
118     END IF;
119
120     -- Fail if the item isn't in a circulateable status on a non-renewal
121     IF NOT renewal AND item_object.status NOT IN ( 0, 7, 8 ) THEN
122         result.fail_part := 'asset.copy.status';
123         result.success := FALSE;
124         done := TRUE;
125         RETURN NEXT result;
126     ELSIF renewal AND item_object.status <> 1 THEN
127         result.fail_part := 'asset.copy.status';
128         result.success := FALSE;
129         done := TRUE;
130         RETURN NEXT result;
131     END IF;
132
133     -- Fail if the item can't circulate because of the shelving location
134     SELECT INTO item_location_object * FROM asset.copy_location WHERE id = item_object.location;
135     IF item_location_object.circulate IS FALSE THEN
136         result.fail_part := 'asset.copy_location.circulate';
137         result.success := FALSE;
138         done := TRUE;
139         RETURN NEXT result;
140     END IF;
141
142     SELECT INTO context_org_list ARRAY_ACCUM(id) FROM actor.org_unit_full_path( circ_test.org_unit );
143
144     -- Fail if the test is set to hard non-circulating
145     IF circ_test.circulate IS FALSE THEN
146         result.fail_part := 'config.circ_matrix_test.circulate';
147         result.success := FALSE;
148         done := TRUE;
149         RETURN NEXT result;
150     END IF;
151
152     -- Fail if the total copy-hold ratio is too low
153     IF circ_test.total_copy_hold_ratio IS NOT NULL THEN
154         SELECT INTO hold_ratio * FROM action.copy_related_hold_stats(match_item);
155         IF hold_ratio.total_copy_ratio IS NOT NULL AND hold_ratio.total_copy_ratio < circ_test.total_copy_hold_ratio THEN
156             result.fail_part := 'config.circ_matrix_test.total_copy_hold_ratio';
157             result.success := FALSE;
158             done := TRUE;
159             RETURN NEXT result;
160         END IF;
161     END IF;
162
163     -- Fail if the available copy-hold ratio is too low
164     IF circ_test.available_copy_hold_ratio IS NOT NULL THEN
165         SELECT INTO hold_ratio * FROM action.copy_related_hold_stats(match_item);
166         IF hold_ratio.available_copy_ratio IS NOT NULL AND hold_ratio.available_copy_ratio < circ_test.available_copy_hold_ratio THEN
167             result.fail_part := 'config.circ_matrix_test.available_copy_hold_ratio';
168             result.success := FALSE;
169             done := TRUE;
170             RETURN NEXT result;
171         END IF;
172     END IF;
173
174     IF renewal THEN
175         penalty_type = '%RENEW%';
176     ELSE
177         penalty_type = '%CIRC%';
178     END IF;
179
180     FOR standing_penalty IN
181         SELECT  DISTINCT csp.*
182           FROM  actor.usr_standing_penalty usp
183                 JOIN config.standing_penalty csp ON (csp.id = usp.standing_penalty)
184           WHERE usr = match_user
185                 AND usp.org_unit IN ( SELECT * FROM explode_array(context_org_list) )
186                 AND (usp.stop_date IS NULL or usp.stop_date > NOW())
187                 AND csp.block_list LIKE penalty_type LOOP
188
189         result.fail_part := standing_penalty.name;
190         result.success := FALSE;
191         done := TRUE;
192         RETURN NEXT result;
193     END LOOP;
194
195     -- Fail if the user has too many items with specific circ_modifiers checked out
196     FOR out_by_circ_mod IN SELECT * FROM config.circ_matrix_circ_mod_test WHERE matchpoint = circ_test.id LOOP
197         SELECT  INTO items_out COUNT(*)
198           FROM  action.circulation circ
199             JOIN asset.copy cp ON (cp.id = circ.target_copy)
200           WHERE circ.usr = match_user
201                AND circ.circ_lib IN ( SELECT * FROM explode_array(context_org_list) )
202             AND circ.checkin_time IS NULL
203             AND (circ.stop_fines IN ('MAXFINES','LONGOVERDUE') OR circ.stop_fines IS NULL)
204             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);
205         IF items_out >= out_by_circ_mod.items_out THEN
206             result.fail_part := 'config.circ_matrix_circ_mod_test';
207             result.success := FALSE;
208             done := TRUE;
209             RETURN NEXT result;
210         END IF;
211     END LOOP;
212
213     -- If we passed everything, return the successful matchpoint id
214     IF NOT done THEN
215         RETURN NEXT result;
216     END IF;
217
218     RETURN;
219 END;
220 $func$ LANGUAGE plpgsql;
221
222 COMMIT;