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