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