]> git.evergreen-ils.org Git - Evergreen.git/blob - Open-ILS/src/sql/Pg/upgrade/0596.schema.vandelay-item-import-error-detail.sql
LP#1838995: (follow-up) adjust ID for new permission
[Evergreen.git] / Open-ILS / src / sql / Pg / upgrade / 0596.schema.vandelay-item-import-error-detail.sql
1 -- Evergreen DB patch 0596.schema.vandelay-item-import-error-detail.sql
2 BEGIN;
3
4 -- check whether patch can be applied
5 SELECT evergreen.upgrade_deps_block_check('0596', :eg_version);
6
7 INSERT INTO vandelay.import_error ( code, description ) VALUES ( 
8     'import.item.invalid.status', oils_i18n_gettext('import.item.invalid.status', 'Invalid value for "status"', 'vie', 'description') );
9 INSERT INTO vandelay.import_error ( code, description ) VALUES ( 
10     'import.item.invalid.price', oils_i18n_gettext('import.item.invalid.price', 'Invalid value for "price"', 'vie', 'description') );
11 INSERT INTO vandelay.import_error ( code, description ) VALUES ( 
12     'import.item.invalid.deposit_amount', oils_i18n_gettext('import.item.invalid.deposit_amount', 'Invalid value for "deposit_amount"', 'vie', 'description') );
13 INSERT INTO vandelay.import_error ( code, description ) VALUES ( 
14     'import.item.invalid.owning_lib', oils_i18n_gettext('import.item.invalid.owning_lib', 'Invalid value for "owning_lib"', 'vie', 'description') );
15 INSERT INTO vandelay.import_error ( code, description ) VALUES ( 
16     'import.item.invalid.circ_lib', oils_i18n_gettext('import.item.invalid.circ_lib', 'Invalid value for "circ_lib"', 'vie', 'description') );
17 INSERT INTO vandelay.import_error ( code, description ) VALUES ( 
18     'import.item.invalid.copy_number', oils_i18n_gettext('import.item.invalid.copy_number', 'Invalid value for "copy_number"', 'vie', 'description') );
19 INSERT INTO vandelay.import_error ( code, description ) VALUES ( 
20     'import.item.invalid.circ_as_type', oils_i18n_gettext('import.item.invalid.circ_as_type', 'Invalid value for "circ_as_type"', 'vie', 'description') );
21
22 CREATE OR REPLACE FUNCTION vandelay.ingest_items ( import_id BIGINT, attr_def_id BIGINT ) RETURNS SETOF vandelay.import_item AS $$
23 DECLARE
24
25     owning_lib      TEXT;
26     circ_lib        TEXT;
27     call_number     TEXT;
28     copy_number     TEXT;
29     status          TEXT;
30     location        TEXT;
31     circulate       TEXT;
32     deposit         TEXT;
33     deposit_amount  TEXT;
34     ref             TEXT;
35     holdable        TEXT;
36     price           TEXT;
37     barcode         TEXT;
38     circ_modifier   TEXT;
39     circ_as_type    TEXT;
40     alert_message   TEXT;
41     opac_visible    TEXT;
42     pub_note        TEXT;
43     priv_note       TEXT;
44
45     attr_def        RECORD;
46     tmp_attr_set    RECORD;
47     attr_set        vandelay.import_item%ROWTYPE;
48
49     xpath           TEXT;
50     tmp_str         TEXT;
51
52 BEGIN
53
54     SELECT * INTO attr_def FROM vandelay.import_item_attr_definition WHERE id = attr_def_id;
55
56     IF FOUND THEN
57
58         attr_set.definition := attr_def.id;
59
60         -- Build the combined XPath
61
62         owning_lib :=
63             CASE
64                 WHEN attr_def.owning_lib IS NULL THEN 'null()'
65                 WHEN LENGTH( attr_def.owning_lib ) = 1 THEN '//*[@tag="' || attr_def.tag || '"]/*[@code="' || attr_def.owning_lib || '"]'
66                 ELSE '//*[@tag="' || attr_def.tag || '"]/*' || attr_def.owning_lib
67             END;
68
69         circ_lib :=
70             CASE
71                 WHEN attr_def.circ_lib IS NULL THEN 'null()'
72                 WHEN LENGTH( attr_def.circ_lib ) = 1 THEN '//*[@tag="' || attr_def.tag || '"]/*[@code="' || attr_def.circ_lib || '"]'
73                 ELSE '//*[@tag="' || attr_def.tag || '"]/*' || attr_def.circ_lib
74             END;
75
76         call_number :=
77             CASE
78                 WHEN attr_def.call_number IS NULL THEN 'null()'
79                 WHEN LENGTH( attr_def.call_number ) = 1 THEN '//*[@tag="' || attr_def.tag || '"]/*[@code="' || attr_def.call_number || '"]'
80                 ELSE '//*[@tag="' || attr_def.tag || '"]/*' || attr_def.call_number
81             END;
82
83         copy_number :=
84             CASE
85                 WHEN attr_def.copy_number IS NULL THEN 'null()'
86                 WHEN LENGTH( attr_def.copy_number ) = 1 THEN '//*[@tag="' || attr_def.tag || '"]/*[@code="' || attr_def.copy_number || '"]'
87                 ELSE '//*[@tag="' || attr_def.tag || '"]/*' || attr_def.copy_number
88             END;
89
90         status :=
91             CASE
92                 WHEN attr_def.status IS NULL THEN 'null()'
93                 WHEN LENGTH( attr_def.status ) = 1 THEN '//*[@tag="' || attr_def.tag || '"]/*[@code="' || attr_def.status || '"]'
94                 ELSE '//*[@tag="' || attr_def.tag || '"]/*' || attr_def.status
95             END;
96
97         location :=
98             CASE
99                 WHEN attr_def.location IS NULL THEN 'null()'
100                 WHEN LENGTH( attr_def.location ) = 1 THEN '//*[@tag="' || attr_def.tag || '"]/*[@code="' || attr_def.location || '"]'
101                 ELSE '//*[@tag="' || attr_def.tag || '"]/*' || attr_def.location
102             END;
103
104         circulate :=
105             CASE
106                 WHEN attr_def.circulate IS NULL THEN 'null()'
107                 WHEN LENGTH( attr_def.circulate ) = 1 THEN '//*[@tag="' || attr_def.tag || '"]/*[@code="' || attr_def.circulate || '"]'
108                 ELSE '//*[@tag="' || attr_def.tag || '"]/*' || attr_def.circulate
109             END;
110
111         deposit :=
112             CASE
113                 WHEN attr_def.deposit IS NULL THEN 'null()'
114                 WHEN LENGTH( attr_def.deposit ) = 1 THEN '//*[@tag="' || attr_def.tag || '"]/*[@code="' || attr_def.deposit || '"]'
115                 ELSE '//*[@tag="' || attr_def.tag || '"]/*' || attr_def.deposit
116             END;
117
118         deposit_amount :=
119             CASE
120                 WHEN attr_def.deposit_amount IS NULL THEN 'null()'
121                 WHEN LENGTH( attr_def.deposit_amount ) = 1 THEN '//*[@tag="' || attr_def.tag || '"]/*[@code="' || attr_def.deposit_amount || '"]'
122                 ELSE '//*[@tag="' || attr_def.tag || '"]/*' || attr_def.deposit_amount
123             END;
124
125         ref :=
126             CASE
127                 WHEN attr_def.ref IS NULL THEN 'null()'
128                 WHEN LENGTH( attr_def.ref ) = 1 THEN '//*[@tag="' || attr_def.tag || '"]/*[@code="' || attr_def.ref || '"]'
129                 ELSE '//*[@tag="' || attr_def.tag || '"]/*' || attr_def.ref
130             END;
131
132         holdable :=
133             CASE
134                 WHEN attr_def.holdable IS NULL THEN 'null()'
135                 WHEN LENGTH( attr_def.holdable ) = 1 THEN '//*[@tag="' || attr_def.tag || '"]/*[@code="' || attr_def.holdable || '"]'
136                 ELSE '//*[@tag="' || attr_def.tag || '"]/*' || attr_def.holdable
137             END;
138
139         price :=
140             CASE
141                 WHEN attr_def.price IS NULL THEN 'null()'
142                 WHEN LENGTH( attr_def.price ) = 1 THEN '//*[@tag="' || attr_def.tag || '"]/*[@code="' || attr_def.price || '"]'
143                 ELSE '//*[@tag="' || attr_def.tag || '"]/*' || attr_def.price
144             END;
145
146         barcode :=
147             CASE
148                 WHEN attr_def.barcode IS NULL THEN 'null()'
149                 WHEN LENGTH( attr_def.barcode ) = 1 THEN '//*[@tag="' || attr_def.tag || '"]/*[@code="' || attr_def.barcode || '"]'
150                 ELSE '//*[@tag="' || attr_def.tag || '"]/*' || attr_def.barcode
151             END;
152
153         circ_modifier :=
154             CASE
155                 WHEN attr_def.circ_modifier IS NULL THEN 'null()'
156                 WHEN LENGTH( attr_def.circ_modifier ) = 1 THEN '//*[@tag="' || attr_def.tag || '"]/*[@code="' || attr_def.circ_modifier || '"]'
157                 ELSE '//*[@tag="' || attr_def.tag || '"]/*' || attr_def.circ_modifier
158             END;
159
160         circ_as_type :=
161             CASE
162                 WHEN attr_def.circ_as_type IS NULL THEN 'null()'
163                 WHEN LENGTH( attr_def.circ_as_type ) = 1 THEN '//*[@tag="' || attr_def.tag || '"]/*[@code="' || attr_def.circ_as_type || '"]'
164                 ELSE '//*[@tag="' || attr_def.tag || '"]/*' || attr_def.circ_as_type
165             END;
166
167         alert_message :=
168             CASE
169                 WHEN attr_def.alert_message IS NULL THEN 'null()'
170                 WHEN LENGTH( attr_def.alert_message ) = 1 THEN '//*[@tag="' || attr_def.tag || '"]/*[@code="' || attr_def.alert_message || '"]'
171                 ELSE '//*[@tag="' || attr_def.tag || '"]/*' || attr_def.alert_message
172             END;
173
174         opac_visible :=
175             CASE
176                 WHEN attr_def.opac_visible IS NULL THEN 'null()'
177                 WHEN LENGTH( attr_def.opac_visible ) = 1 THEN '//*[@tag="' || attr_def.tag || '"]/*[@code="' || attr_def.opac_visible || '"]'
178                 ELSE '//*[@tag="' || attr_def.tag || '"]/*' || attr_def.opac_visible
179             END;
180
181         pub_note :=
182             CASE
183                 WHEN attr_def.pub_note IS NULL THEN 'null()'
184                 WHEN LENGTH( attr_def.pub_note ) = 1 THEN '//*[@tag="' || attr_def.tag || '"]/*[@code="' || attr_def.pub_note || '"]'
185                 ELSE '//*[@tag="' || attr_def.tag || '"]/*' || attr_def.pub_note
186             END;
187         priv_note :=
188             CASE
189                 WHEN attr_def.priv_note IS NULL THEN 'null()'
190                 WHEN LENGTH( attr_def.priv_note ) = 1 THEN '//*[@tag="' || attr_def.tag || '"]/*[@code="' || attr_def.priv_note || '"]'
191                 ELSE '//*[@tag="' || attr_def.tag || '"]/*' || attr_def.priv_note
192             END;
193
194
195         xpath :=
196             owning_lib      || '|' ||
197             circ_lib        || '|' ||
198             call_number     || '|' ||
199             copy_number     || '|' ||
200             status          || '|' ||
201             location        || '|' ||
202             circulate       || '|' ||
203             deposit         || '|' ||
204             deposit_amount  || '|' ||
205             ref             || '|' ||
206             holdable        || '|' ||
207             price           || '|' ||
208             barcode         || '|' ||
209             circ_modifier   || '|' ||
210             circ_as_type    || '|' ||
211             alert_message   || '|' ||
212             pub_note        || '|' ||
213             priv_note       || '|' ||
214             opac_visible;
215
216         FOR tmp_attr_set IN
217                 SELECT  *
218                   FROM  oils_xpath_table( 'id', 'marc', 'vandelay.queued_bib_record', xpath, 'id = ' || import_id )
219                             AS t( id INT, ol TEXT, clib TEXT, cn TEXT, cnum TEXT, cs TEXT, cl TEXT, circ TEXT,
220                                   dep TEXT, dep_amount TEXT, r TEXT, hold TEXT, pr TEXT, bc TEXT, circ_mod TEXT,
221                                   circ_as TEXT, amessage TEXT, note TEXT, pnote TEXT, opac_vis TEXT )
222         LOOP
223
224             attr_set.import_error := NULL;
225             attr_set.error_detail := NULL;
226             attr_set.deposit_amount := NULL;
227             attr_set.copy_number := NULL;
228             attr_set.price := NULL;
229
230             IF tmp_attr_set.pr != '' THEN
231                 tmp_str = REGEXP_REPLACE(tmp_attr_set.pr, E'[^0-9\\.]', '', 'g');
232                 IF tmp_str = '' THEN 
233                     attr_set.import_error := 'import.item.invalid.price';
234                     attr_set.error_detail := tmp_attr_set.pr; -- original value
235                     RETURN NEXT attr_set; CONTINUE; 
236                 END IF;
237                 attr_set.price := tmp_str::NUMERIC(8,2); 
238             END IF;
239
240             IF tmp_attr_set.dep_amount != '' THEN
241                 tmp_str = REGEXP_REPLACE(tmp_attr_set.dep_amount, E'[^0-9\\.]', '', 'g');
242                 IF tmp_str = '' THEN 
243                     attr_set.import_error := 'import.item.invalid.deposit_amount';
244                     attr_set.error_detail := tmp_attr_set.dep_amount; 
245                     RETURN NEXT attr_set; CONTINUE; 
246                 END IF;
247                 attr_set.deposit_amount := tmp_str::NUMERIC(8,2); 
248             END IF;
249
250             IF tmp_attr_set.cnum != '' THEN
251                 tmp_str = REGEXP_REPLACE(tmp_attr_set.cnum, E'[^0-9]', '', 'g');
252                 IF tmp_str = '' THEN 
253                     attr_set.import_error := 'import.item.invalid.copy_number';
254                     attr_set.error_detail := tmp_attr_set.cnum; 
255                     RETURN NEXT attr_set; CONTINUE; 
256                 END IF;
257                 attr_set.copy_number := tmp_str::INT; 
258             END IF;
259
260             IF tmp_attr_set.ol != '' THEN
261                 SELECT id INTO attr_set.owning_lib FROM actor.org_unit WHERE shortname = UPPER(tmp_attr_set.ol); -- INT
262                 IF NOT FOUND THEN
263                     attr_set.import_error := 'import.item.invalid.owning_lib';
264                     attr_set.error_detail := tmp_attr_set.ol;
265                     RETURN NEXT attr_set; CONTINUE; 
266                 END IF;
267             END IF;
268
269             IF tmp_attr_set.clib != '' THEN
270                 SELECT id INTO attr_set.circ_lib FROM actor.org_unit WHERE shortname = UPPER(tmp_attr_set.clib); -- INT
271                 IF NOT FOUND THEN
272                     attr_set.import_error := 'import.item.invalid.circ_lib';
273                     attr_set.error_detail := tmp_attr_set.clib;
274                     RETURN NEXT attr_set; CONTINUE; 
275                 END IF;
276             END IF;
277
278             IF tmp_attr_set.cs != '' THEN
279                 SELECT id INTO attr_set.status FROM config.copy_status WHERE LOWER(name) = LOWER(tmp_attr_set.cs); -- INT
280                 IF NOT FOUND THEN
281                     attr_set.import_error := 'import.item.invalid.status';
282                     attr_set.error_detail := tmp_attr_set.cs;
283                     RETURN NEXT attr_set; CONTINUE; 
284                 END IF;
285             END IF;
286
287             IF tmp_attr_set.circ_mod != '' THEN
288                 SELECT code INTO attr_set.circ_modifier FROM config.circ_modifier WHERE code = tmp_attr_set.circ_mod;
289                 IF NOT FOUND THEN
290                     attr_set.import_error := 'import.item.invalid.circ_modifier';
291                     attr_set.error_detail := tmp_attr_set.circ_mod;
292                     RETURN NEXT attr_set; CONTINUE; 
293                 END IF;
294             END IF;
295
296             IF tmp_attr_set.circ_as != '' THEN
297                 SELECT code INTO attr_set.circ_as_type FROM config.coded_value_map WHERE ctype = 'item_type' AND code = tmp_attr_set.circ_as;
298                 IF NOT FOUND THEN
299                     attr_set.import_error := 'import.item.invalid.circ_as_type';
300                     attr_set.error_detail := tmp_attr_set.circ_as;
301                     RETURN NEXT attr_set; CONTINUE; 
302                 END IF;
303             END IF;
304
305             IF tmp_attr_set.cl != '' THEN
306
307                 -- search up the org unit tree for a matching copy location
308                 WITH RECURSIVE anscestor_depth AS (
309                     SELECT  ou.id,
310                         out.depth AS depth,
311                         ou.parent_ou
312                     FROM  actor.org_unit ou
313                         JOIN actor.org_unit_type out ON (out.id = ou.ou_type)
314                     WHERE ou.id = COALESCE(attr_set.owning_lib, attr_set.circ_lib)
315                         UNION ALL
316                     SELECT  ou.id,
317                         out.depth,
318                         ou.parent_ou
319                     FROM  actor.org_unit ou
320                         JOIN actor.org_unit_type out ON (out.id = ou.ou_type)
321                         JOIN anscestor_depth ot ON (ot.parent_ou = ou.id)
322                 ) SELECT  cpl.id INTO attr_set.location
323                     FROM  anscestor_depth a
324                         JOIN asset.copy_location cpl ON (cpl.owning_lib = a.id)
325                     WHERE LOWER(cpl.name) = LOWER(tmp_attr_set.cl)
326                     ORDER BY a.depth DESC
327                     LIMIT 1; 
328
329                 IF NOT FOUND THEN
330                     attr_set.import_error := 'import.item.invalid.location';
331                     attr_set.error_detail := tmp_attr_set.cs;
332                     RETURN NEXT attr_set; CONTINUE; 
333                 END IF;
334             END IF;
335
336             attr_set.circulate      :=
337                 LOWER( SUBSTRING( tmp_attr_set.circ, 1, 1)) IN ('t','y','1')
338                 OR LOWER(tmp_attr_set.circ) = 'circulating'; -- BOOL
339
340             attr_set.deposit        :=
341                 LOWER( SUBSTRING( tmp_attr_set.dep, 1, 1 ) ) IN ('t','y','1')
342                 OR LOWER(tmp_attr_set.dep) = 'deposit'; -- BOOL
343
344             attr_set.holdable       :=
345                 LOWER( SUBSTRING( tmp_attr_set.hold, 1, 1 ) ) IN ('t','y','1')
346                 OR LOWER(tmp_attr_set.hold) = 'holdable'; -- BOOL
347
348             attr_set.opac_visible   :=
349                 LOWER( SUBSTRING( tmp_attr_set.opac_vis, 1, 1 ) ) IN ('t','y','1')
350                 OR LOWER(tmp_attr_set.opac_vis) = 'visible'; -- BOOL
351
352             attr_set.ref            :=
353                 LOWER( SUBSTRING( tmp_attr_set.r, 1, 1 ) ) IN ('t','y','1')
354                 OR LOWER(tmp_attr_set.r) = 'reference'; -- BOOL
355
356             attr_set.call_number    := tmp_attr_set.cn; -- TEXT
357             attr_set.barcode        := tmp_attr_set.bc; -- TEXT,
358             attr_set.alert_message  := tmp_attr_set.amessage; -- TEXT,
359             attr_set.pub_note       := tmp_attr_set.note; -- TEXT,
360             attr_set.priv_note      := tmp_attr_set.pnote; -- TEXT,
361             attr_set.alert_message  := tmp_attr_set.amessage; -- TEXT,
362
363             RETURN NEXT attr_set;
364
365         END LOOP;
366
367     END IF;
368
369     RETURN;
370
371 END;
372 $$ LANGUAGE PLPGSQL;
373
374 CREATE OR REPLACE FUNCTION vandelay.ingest_bib_items ( ) RETURNS TRIGGER AS $func$
375 DECLARE
376     attr_def    BIGINT;
377     item_data   vandelay.import_item%ROWTYPE;
378 BEGIN
379
380     IF TG_OP IN ('INSERT','UPDATE') AND NEW.imported_as IS NOT NULL THEN
381         RETURN NEW;
382     END IF;
383
384     SELECT item_attr_def INTO attr_def FROM vandelay.bib_queue WHERE id = NEW.queue;
385
386     FOR item_data IN SELECT * FROM vandelay.ingest_items( NEW.id::BIGINT, attr_def ) LOOP
387         INSERT INTO vandelay.import_item (
388             record,
389             definition,
390             owning_lib,
391             circ_lib,
392             call_number,
393             copy_number,
394             status,
395             location,
396             circulate,
397             deposit,
398             deposit_amount,
399             ref,
400             holdable,
401             price,
402             barcode,
403             circ_modifier,
404             circ_as_type,
405             alert_message,
406             pub_note,
407             priv_note,
408             opac_visible,
409             import_error,
410             error_detail
411         ) VALUES (
412             NEW.id,
413             item_data.definition,
414             item_data.owning_lib,
415             item_data.circ_lib,
416             item_data.call_number,
417             item_data.copy_number,
418             item_data.status,
419             item_data.location,
420             item_data.circulate,
421             item_data.deposit,
422             item_data.deposit_amount,
423             item_data.ref,
424             item_data.holdable,
425             item_data.price,
426             item_data.barcode,
427             item_data.circ_modifier,
428             item_data.circ_as_type,
429             item_data.alert_message,
430             item_data.pub_note,
431             item_data.priv_note,
432             item_data.opac_visible,
433             item_data.import_error,
434             item_data.error_detail
435         );
436     END LOOP;
437
438     RETURN NULL;
439 END;
440 $func$ LANGUAGE PLPGSQL;
441
442 COMMIT;