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