Stamping upgrade script for Vandelay item import defaults
authorMike Rylander <mrylander@gmail.com>
Fri, 30 Aug 2013 13:32:02 +0000 (09:32 -0400)
committerMike Rylander <mrylander@gmail.com>
Fri, 30 Aug 2013 13:32:02 +0000 (09:32 -0400)
Signed-off-by: Mike Rylander <mrylander@gmail.com>
Open-ILS/src/sql/Pg/002.schema.config.sql
Open-ILS/src/sql/Pg/upgrade/0824.schema.vandelay-item-import-defaults.sql [new file with mode: 0644]
Open-ILS/src/sql/Pg/upgrade/XXXX.schema.vandelay-item-import-defaults.sql [deleted file]

index cb7fb8c..9d6b1e4 100644 (file)
@@ -91,7 +91,7 @@ CREATE TRIGGER no_overlapping_deps
     BEFORE INSERT OR UPDATE ON config.db_patch_dependencies
     FOR EACH ROW EXECUTE PROCEDURE evergreen.array_overlap_check ('deprecates');
 
-INSERT INTO config.upgrade_log (version, applied_to) VALUES ('0823', :eg_version); -- berick/dbwells
+INSERT INTO config.upgrade_log (version, applied_to) VALUES ('0824', :eg_version); -- berick/miker
 
 CREATE TABLE config.bib_source (
        id              SERIAL  PRIMARY KEY,
diff --git a/Open-ILS/src/sql/Pg/upgrade/0824.schema.vandelay-item-import-defaults.sql b/Open-ILS/src/sql/Pg/upgrade/0824.schema.vandelay-item-import-defaults.sql
new file mode 100644 (file)
index 0000000..62cb914
--- /dev/null
@@ -0,0 +1,491 @@
+
+BEGIN;
+
+SELECT evergreen.upgrade_deps_block_check('0824', :eg_version);
+
+INSERT INTO config.org_unit_setting_type
+    (grp, name, label, description, datatype, fm_class)
+VALUES (
+    'vandelay',
+    'vandelay.item.barcode.auto',
+    oils_i18n_gettext(
+        'vandelay.item.barcode.auto',
+        'Vandelay Generate Default Barcodes',
+        'coust', 'label'),
+    oils_i18n_gettext(
+        'vandelay.item.barcode.auto',
+        'Auto-generate deault item barcodes when no item barcode is present',
+        'coust', 'label'),
+    'bool',
+    NULL
+), (
+    'vandelay',
+    'vandelay.item.barcode.prefix',
+    oils_i18n_gettext(
+        'vandelay.item.barcode.prefix',
+        'Vandelay Default Barcode Prefix',
+        'coust', 'label'),
+    oils_i18n_gettext(
+        'vandelay.item.barcode.prefix',
+        'Apply this prefix to any auto-generated item barcodes',
+        'coust', 'label'),
+    'string',
+    NULL
+), (
+    'vandelay',
+    'vandelay.item.call_number.auto',
+    oils_i18n_gettext(
+        'vandelay.item.call_number.auto',
+        'Vandelay Generate Default Call Numbers',
+        'coust', 'label'),
+    oils_i18n_gettext(
+        'vandelay.item.call_number.auto',
+        'Auto-generate default item call numbers when no item call number is present',
+        'coust', 'label'),
+    'bool',
+    NULL
+), (
+    'vandelay',
+    'vandelay.item.call_number.prefix',
+    oils_i18n_gettext(
+        'vandelay.item.call_number.prefix',
+        'Vandelay Default Call Number Prefix',
+        'coust', 'label'),
+    oils_i18n_gettext(
+        'vandelay.item.call_number.prefix',
+        'Apply this prefix to any auto-generated item call numbers',
+        'coust', 'label'),
+    'string',
+    NULL
+), (
+    'vandelay',
+    'vandelay.item.copy_location.default',
+    oils_i18n_gettext(
+        'vandelay.item.copy_location.default',
+        'Vandelay Default Copy Location',
+        'coust', 'label'),
+    oils_i18n_gettext(
+        'vandelay.item.copy_location.default',
+        'Default copy location value for imported items',
+        'coust', 'label'),
+    'link',
+    'acpl'
+), (
+    'vandelay',
+    'vandelay.item.circ_modifier.default',
+    oils_i18n_gettext(
+        'vandelay.item.circ_modifier.default',
+        'Vandelay Default Circulation Modifier',
+        'coust', 'label'),
+    oils_i18n_gettext(
+        'vandelay.item.circ_modifier.default',
+        'Default circulation modifier value for imported items',
+        'coust', 'label'),
+    'link',
+    'ccm'
+);
+
+
+CREATE OR REPLACE FUNCTION vandelay.ingest_items ( import_id BIGINT, attr_def_id BIGINT ) RETURNS SETOF vandelay.import_item AS $$
+DECLARE
+
+    owning_lib      TEXT;
+    circ_lib        TEXT;
+    call_number     TEXT;
+    copy_number     TEXT;
+    status          TEXT;
+    location        TEXT;
+    circulate       TEXT;
+    deposit         TEXT;
+    deposit_amount  TEXT;
+    ref             TEXT;
+    holdable        TEXT;
+    price           TEXT;
+    barcode         TEXT;
+    circ_modifier   TEXT;
+    circ_as_type    TEXT;
+    alert_message   TEXT;
+    opac_visible    TEXT;
+    pub_note        TEXT;
+    priv_note       TEXT;
+    internal_id     TEXT;
+
+    attr_def        RECORD;
+    tmp_attr_set    RECORD;
+    attr_set        vandelay.import_item%ROWTYPE;
+
+    xpath           TEXT;
+    tmp_str         TEXT;
+
+BEGIN
+
+    SELECT * INTO attr_def FROM vandelay.import_item_attr_definition WHERE id = attr_def_id;
+
+    IF FOUND THEN
+
+        attr_set.definition := attr_def.id;
+
+        -- Build the combined XPath
+
+        owning_lib :=
+            CASE
+                WHEN attr_def.owning_lib IS NULL THEN 'null()'
+                WHEN LENGTH( attr_def.owning_lib ) = 1 THEN '//*[@tag="' || attr_def.tag || '"]/*[@code="' || attr_def.owning_lib || '"]'
+                ELSE '//*[@tag="' || attr_def.tag || '"]/*' || attr_def.owning_lib
+            END;
+
+        circ_lib :=
+            CASE
+                WHEN attr_def.circ_lib IS NULL THEN 'null()'
+                WHEN LENGTH( attr_def.circ_lib ) = 1 THEN '//*[@tag="' || attr_def.tag || '"]/*[@code="' || attr_def.circ_lib || '"]'
+                ELSE '//*[@tag="' || attr_def.tag || '"]/*' || attr_def.circ_lib
+            END;
+
+        call_number :=
+            CASE
+                WHEN attr_def.call_number IS NULL THEN 'null()'
+                WHEN LENGTH( attr_def.call_number ) = 1 THEN '//*[@tag="' || attr_def.tag || '"]/*[@code="' || attr_def.call_number || '"]'
+                ELSE '//*[@tag="' || attr_def.tag || '"]/*' || attr_def.call_number
+            END;
+
+        copy_number :=
+            CASE
+                WHEN attr_def.copy_number IS NULL THEN 'null()'
+                WHEN LENGTH( attr_def.copy_number ) = 1 THEN '//*[@tag="' || attr_def.tag || '"]/*[@code="' || attr_def.copy_number || '"]'
+                ELSE '//*[@tag="' || attr_def.tag || '"]/*' || attr_def.copy_number
+            END;
+
+        status :=
+            CASE
+                WHEN attr_def.status IS NULL THEN 'null()'
+                WHEN LENGTH( attr_def.status ) = 1 THEN '//*[@tag="' || attr_def.tag || '"]/*[@code="' || attr_def.status || '"]'
+                ELSE '//*[@tag="' || attr_def.tag || '"]/*' || attr_def.status
+            END;
+
+        location :=
+            CASE
+                WHEN attr_def.location IS NULL THEN 'null()'
+                WHEN LENGTH( attr_def.location ) = 1 THEN '//*[@tag="' || attr_def.tag || '"]/*[@code="' || attr_def.location || '"]'
+                ELSE '//*[@tag="' || attr_def.tag || '"]/*' || attr_def.location
+            END;
+
+        circulate :=
+            CASE
+                WHEN attr_def.circulate IS NULL THEN 'null()'
+                WHEN LENGTH( attr_def.circulate ) = 1 THEN '//*[@tag="' || attr_def.tag || '"]/*[@code="' || attr_def.circulate || '"]'
+                ELSE '//*[@tag="' || attr_def.tag || '"]/*' || attr_def.circulate
+            END;
+
+        deposit :=
+            CASE
+                WHEN attr_def.deposit IS NULL THEN 'null()'
+                WHEN LENGTH( attr_def.deposit ) = 1 THEN '//*[@tag="' || attr_def.tag || '"]/*[@code="' || attr_def.deposit || '"]'
+                ELSE '//*[@tag="' || attr_def.tag || '"]/*' || attr_def.deposit
+            END;
+
+        deposit_amount :=
+            CASE
+                WHEN attr_def.deposit_amount IS NULL THEN 'null()'
+                WHEN LENGTH( attr_def.deposit_amount ) = 1 THEN '//*[@tag="' || attr_def.tag || '"]/*[@code="' || attr_def.deposit_amount || '"]'
+                ELSE '//*[@tag="' || attr_def.tag || '"]/*' || attr_def.deposit_amount
+            END;
+
+        ref :=
+            CASE
+                WHEN attr_def.ref IS NULL THEN 'null()'
+                WHEN LENGTH( attr_def.ref ) = 1 THEN '//*[@tag="' || attr_def.tag || '"]/*[@code="' || attr_def.ref || '"]'
+                ELSE '//*[@tag="' || attr_def.tag || '"]/*' || attr_def.ref
+            END;
+
+        holdable :=
+            CASE
+                WHEN attr_def.holdable IS NULL THEN 'null()'
+                WHEN LENGTH( attr_def.holdable ) = 1 THEN '//*[@tag="' || attr_def.tag || '"]/*[@code="' || attr_def.holdable || '"]'
+                ELSE '//*[@tag="' || attr_def.tag || '"]/*' || attr_def.holdable
+            END;
+
+        price :=
+            CASE
+                WHEN attr_def.price IS NULL THEN 'null()'
+                WHEN LENGTH( attr_def.price ) = 1 THEN '//*[@tag="' || attr_def.tag || '"]/*[@code="' || attr_def.price || '"]'
+                ELSE '//*[@tag="' || attr_def.tag || '"]/*' || attr_def.price
+            END;
+
+        barcode :=
+            CASE
+                WHEN attr_def.barcode IS NULL THEN 'null()'
+                WHEN LENGTH( attr_def.barcode ) = 1 THEN '//*[@tag="' || attr_def.tag || '"]/*[@code="' || attr_def.barcode || '"]'
+                ELSE '//*[@tag="' || attr_def.tag || '"]/*' || attr_def.barcode
+            END;
+
+        circ_modifier :=
+            CASE
+                WHEN attr_def.circ_modifier IS NULL THEN 'null()'
+                WHEN LENGTH( attr_def.circ_modifier ) = 1 THEN '//*[@tag="' || attr_def.tag || '"]/*[@code="' || attr_def.circ_modifier || '"]'
+                ELSE '//*[@tag="' || attr_def.tag || '"]/*' || attr_def.circ_modifier
+            END;
+
+        circ_as_type :=
+            CASE
+                WHEN attr_def.circ_as_type IS NULL THEN 'null()'
+                WHEN LENGTH( attr_def.circ_as_type ) = 1 THEN '//*[@tag="' || attr_def.tag || '"]/*[@code="' || attr_def.circ_as_type || '"]'
+                ELSE '//*[@tag="' || attr_def.tag || '"]/*' || attr_def.circ_as_type
+            END;
+
+        alert_message :=
+            CASE
+                WHEN attr_def.alert_message IS NULL THEN 'null()'
+                WHEN LENGTH( attr_def.alert_message ) = 1 THEN '//*[@tag="' || attr_def.tag || '"]/*[@code="' || attr_def.alert_message || '"]'
+                ELSE '//*[@tag="' || attr_def.tag || '"]/*' || attr_def.alert_message
+            END;
+
+        opac_visible :=
+            CASE
+                WHEN attr_def.opac_visible IS NULL THEN 'null()'
+                WHEN LENGTH( attr_def.opac_visible ) = 1 THEN '//*[@tag="' || attr_def.tag || '"]/*[@code="' || attr_def.opac_visible || '"]'
+                ELSE '//*[@tag="' || attr_def.tag || '"]/*' || attr_def.opac_visible
+            END;
+
+        pub_note :=
+            CASE
+                WHEN attr_def.pub_note IS NULL THEN 'null()'
+                WHEN LENGTH( attr_def.pub_note ) = 1 THEN '//*[@tag="' || attr_def.tag || '"]/*[@code="' || attr_def.pub_note || '"]'
+                ELSE '//*[@tag="' || attr_def.tag || '"]/*' || attr_def.pub_note
+            END;
+        priv_note :=
+            CASE
+                WHEN attr_def.priv_note IS NULL THEN 'null()'
+                WHEN LENGTH( attr_def.priv_note ) = 1 THEN '//*[@tag="' || attr_def.tag || '"]/*[@code="' || attr_def.priv_note || '"]'
+                ELSE '//*[@tag="' || attr_def.tag || '"]/*' || attr_def.priv_note
+            END;
+
+        internal_id :=
+            CASE
+                WHEN attr_def.internal_id IS NULL THEN 'null()'
+                WHEN LENGTH( attr_def.internal_id ) = 1 THEN '//*[@tag="' || attr_def.tag || '"]/*[@code="' || attr_def.internal_id || '"]'
+                ELSE '//*[@tag="' || attr_def.tag || '"]/*' || attr_def.internal_id
+            END;
+
+
+
+        xpath :=
+            owning_lib      || '|' ||
+            circ_lib        || '|' ||
+            call_number     || '|' ||
+            copy_number     || '|' ||
+            status          || '|' ||
+            location        || '|' ||
+            circulate       || '|' ||
+            deposit         || '|' ||
+            deposit_amount  || '|' ||
+            ref             || '|' ||
+            holdable        || '|' ||
+            price           || '|' ||
+            barcode         || '|' ||
+            circ_modifier   || '|' ||
+            circ_as_type    || '|' ||
+            alert_message   || '|' ||
+            pub_note        || '|' ||
+            priv_note       || '|' ||
+            internal_id     || '|' ||
+            opac_visible;
+
+        FOR tmp_attr_set IN
+                SELECT  *
+                  FROM  oils_xpath_table( 'id', 'marc', 'vandelay.queued_bib_record', xpath, 'id = ' || import_id )
+                            AS t( id INT, ol TEXT, clib TEXT, cn TEXT, cnum TEXT, cs TEXT, cl TEXT, circ TEXT,
+                                  dep TEXT, dep_amount TEXT, r TEXT, hold TEXT, pr TEXT, bc TEXT, circ_mod TEXT,
+                                  circ_as TEXT, amessage TEXT, note TEXT, pnote TEXT, internal_id TEXT, opac_vis TEXT )
+        LOOP
+
+            attr_set.import_error := NULL;
+            attr_set.error_detail := NULL;
+            attr_set.deposit_amount := NULL;
+            attr_set.copy_number := NULL;
+            attr_set.price := NULL;
+            attr_set.circ_modifier := NULL;
+            attr_set.location := NULL;
+            attr_set.barcode := NULL;
+            attr_set.call_number := NULL;
+
+            IF tmp_attr_set.pr != '' THEN
+                tmp_str = REGEXP_REPLACE(tmp_attr_set.pr, E'[^0-9\\.]', '', 'g');
+                IF tmp_str = '' THEN 
+                    attr_set.import_error := 'import.item.invalid.price';
+                    attr_set.error_detail := tmp_attr_set.pr; -- original value
+                    RETURN NEXT attr_set; CONTINUE; 
+                END IF;
+                attr_set.price := tmp_str::NUMERIC(8,2); 
+            END IF;
+
+            IF tmp_attr_set.dep_amount != '' THEN
+                tmp_str = REGEXP_REPLACE(tmp_attr_set.dep_amount, E'[^0-9\\.]', '', 'g');
+                IF tmp_str = '' THEN 
+                    attr_set.import_error := 'import.item.invalid.deposit_amount';
+                    attr_set.error_detail := tmp_attr_set.dep_amount; 
+                    RETURN NEXT attr_set; CONTINUE; 
+                END IF;
+                attr_set.deposit_amount := tmp_str::NUMERIC(8,2); 
+            END IF;
+
+            IF tmp_attr_set.cnum != '' THEN
+                tmp_str = REGEXP_REPLACE(tmp_attr_set.cnum, E'[^0-9]', '', 'g');
+                IF tmp_str = '' THEN 
+                    attr_set.import_error := 'import.item.invalid.copy_number';
+                    attr_set.error_detail := tmp_attr_set.cnum; 
+                    RETURN NEXT attr_set; CONTINUE; 
+                END IF;
+                attr_set.copy_number := tmp_str::INT; 
+            END IF;
+
+            IF tmp_attr_set.ol != '' THEN
+                SELECT id INTO attr_set.owning_lib FROM actor.org_unit WHERE shortname = UPPER(tmp_attr_set.ol); -- INT
+                IF NOT FOUND THEN
+                    attr_set.import_error := 'import.item.invalid.owning_lib';
+                    attr_set.error_detail := tmp_attr_set.ol;
+                    RETURN NEXT attr_set; CONTINUE; 
+                END IF;
+            END IF;
+
+            IF tmp_attr_set.clib != '' THEN
+                SELECT id INTO attr_set.circ_lib FROM actor.org_unit WHERE shortname = UPPER(tmp_attr_set.clib); -- INT
+                IF NOT FOUND THEN
+                    attr_set.import_error := 'import.item.invalid.circ_lib';
+                    attr_set.error_detail := tmp_attr_set.clib;
+                    RETURN NEXT attr_set; CONTINUE; 
+                END IF;
+            END IF;
+
+            IF tmp_attr_set.cs != '' THEN
+                SELECT id INTO attr_set.status FROM config.copy_status WHERE LOWER(name) = LOWER(tmp_attr_set.cs); -- INT
+                IF NOT FOUND THEN
+                    attr_set.import_error := 'import.item.invalid.status';
+                    attr_set.error_detail := tmp_attr_set.cs;
+                    RETURN NEXT attr_set; CONTINUE; 
+                END IF;
+            END IF;
+
+            IF COALESCE(tmp_attr_set.circ_mod, '') = '' THEN
+
+                -- no circ mod defined, see if we should apply a default
+                SELECT INTO attr_set.circ_modifier TRIM(BOTH '"' FROM value) 
+                    FROM actor.org_unit_ancestor_setting(
+                        'vandelay.item.circ_modifier.default', 
+                        attr_set.owning_lib
+                    );
+
+                -- make sure the value from the org setting is still valid
+                PERFORM 1 FROM config.circ_modifier WHERE code = attr_set.circ_modifier;
+                IF NOT FOUND THEN
+                    attr_set.import_error := 'import.item.invalid.circ_modifier';
+                    attr_set.error_detail := tmp_attr_set.circ_mod;
+                    RETURN NEXT attr_set; CONTINUE; 
+                END IF;
+
+            ELSE 
+
+                SELECT code INTO attr_set.circ_modifier FROM config.circ_modifier WHERE code = tmp_attr_set.circ_mod;
+                IF NOT FOUND THEN
+                    attr_set.import_error := 'import.item.invalid.circ_modifier';
+                    attr_set.error_detail := tmp_attr_set.circ_mod;
+                    RETURN NEXT attr_set; CONTINUE; 
+                END IF;
+            END IF;
+
+            IF tmp_attr_set.circ_as != '' THEN
+                SELECT code INTO attr_set.circ_as_type FROM config.coded_value_map WHERE ctype = 'item_type' AND code = tmp_attr_set.circ_as;
+                IF NOT FOUND THEN
+                    attr_set.import_error := 'import.item.invalid.circ_as_type';
+                    attr_set.error_detail := tmp_attr_set.circ_as;
+                    RETURN NEXT attr_set; CONTINUE; 
+                END IF;
+            END IF;
+
+            IF COALESCE(tmp_attr_set.cl, '') = '' THEN
+                -- no location specified, see if we should apply a default
+
+                SELECT INTO attr_set.location TRIM(BOTH '"' FROM value) 
+                    FROM actor.org_unit_ancestor_setting(
+                        'vandelay.item.copy_location.default', 
+                        attr_set.owning_lib
+                    );
+
+                -- make sure the value from the org setting is still valid
+                PERFORM 1 FROM asset.copy_location WHERE id = attr_set.location;
+                IF NOT FOUND THEN
+                    attr_set.import_error := 'import.item.invalid.location';
+                    attr_set.error_detail := tmp_attr_set.cs;
+                    RETURN NEXT attr_set; CONTINUE; 
+                END IF;
+            ELSE
+
+                -- search up the org unit tree for a matching copy location
+                WITH RECURSIVE anscestor_depth AS (
+                    SELECT  ou.id,
+                        out.depth AS depth,
+                        ou.parent_ou
+                    FROM  actor.org_unit ou
+                        JOIN actor.org_unit_type out ON (out.id = ou.ou_type)
+                    WHERE ou.id = COALESCE(attr_set.owning_lib, attr_set.circ_lib)
+                        UNION ALL
+                    SELECT  ou.id,
+                        out.depth,
+                        ou.parent_ou
+                    FROM  actor.org_unit ou
+                        JOIN actor.org_unit_type out ON (out.id = ou.ou_type)
+                        JOIN anscestor_depth ot ON (ot.parent_ou = ou.id)
+                ) SELECT  cpl.id INTO attr_set.location
+                    FROM  anscestor_depth a
+                        JOIN asset.copy_location cpl ON (cpl.owning_lib = a.id)
+                    WHERE LOWER(cpl.name) = LOWER(tmp_attr_set.cl)
+                    ORDER BY a.depth DESC
+                    LIMIT 1; 
+
+                IF NOT FOUND THEN
+                    attr_set.import_error := 'import.item.invalid.location';
+                    attr_set.error_detail := tmp_attr_set.cs;
+                    RETURN NEXT attr_set; CONTINUE; 
+                END IF;
+            END IF;
+
+            attr_set.circulate      :=
+                LOWER( SUBSTRING( tmp_attr_set.circ, 1, 1)) IN ('t','y','1')
+                OR LOWER(tmp_attr_set.circ) = 'circulating'; -- BOOL
+
+            attr_set.deposit        :=
+                LOWER( SUBSTRING( tmp_attr_set.dep, 1, 1 ) ) IN ('t','y','1')
+                OR LOWER(tmp_attr_set.dep) = 'deposit'; -- BOOL
+
+            attr_set.holdable       :=
+                LOWER( SUBSTRING( tmp_attr_set.hold, 1, 1 ) ) IN ('t','y','1')
+                OR LOWER(tmp_attr_set.hold) = 'holdable'; -- BOOL
+
+            attr_set.opac_visible   :=
+                LOWER( SUBSTRING( tmp_attr_set.opac_vis, 1, 1 ) ) IN ('t','y','1')
+                OR LOWER(tmp_attr_set.opac_vis) = 'visible'; -- BOOL
+
+            attr_set.ref            :=
+                LOWER( SUBSTRING( tmp_attr_set.r, 1, 1 ) ) IN ('t','y','1')
+                OR LOWER(tmp_attr_set.r) = 'reference'; -- BOOL
+
+            attr_set.call_number    := tmp_attr_set.cn; -- TEXT
+            attr_set.barcode        := tmp_attr_set.bc; -- TEXT,
+            attr_set.alert_message  := tmp_attr_set.amessage; -- TEXT,
+            attr_set.pub_note       := tmp_attr_set.note; -- TEXT,
+            attr_set.priv_note      := tmp_attr_set.pnote; -- TEXT,
+            attr_set.alert_message  := tmp_attr_set.amessage; -- TEXT,
+            attr_set.internal_id    := tmp_attr_set.internal_id::BIGINT;
+
+            RETURN NEXT attr_set;
+
+        END LOOP;
+
+    END IF;
+
+    RETURN;
+
+END;
+$$ LANGUAGE PLPGSQL;
+
+
+COMMIT;
diff --git a/Open-ILS/src/sql/Pg/upgrade/XXXX.schema.vandelay-item-import-defaults.sql b/Open-ILS/src/sql/Pg/upgrade/XXXX.schema.vandelay-item-import-defaults.sql
deleted file mode 100644 (file)
index 905f926..0000000
+++ /dev/null
@@ -1,491 +0,0 @@
-
-BEGIN;
-
---SELECT evergreen.upgrade_deps_block_check('XXXX', :eg_version);
-
-INSERT INTO config.org_unit_setting_type
-    (grp, name, label, description, datatype, fm_class)
-VALUES (
-    'vandelay',
-    'vandelay.item.barcode.auto',
-    oils_i18n_gettext(
-        'vandelay.item.barcode.auto',
-        'Vandelay Generate Default Barcodes',
-        'coust', 'label'),
-    oils_i18n_gettext(
-        'vandelay.item.barcode.auto',
-        'Auto-generate deault item barcodes when no item barcode is present',
-        'coust', 'label'),
-    'bool',
-    NULL
-), (
-    'vandelay',
-    'vandelay.item.barcode.prefix',
-    oils_i18n_gettext(
-        'vandelay.item.barcode.prefix',
-        'Vandelay Default Barcode Prefix',
-        'coust', 'label'),
-    oils_i18n_gettext(
-        'vandelay.item.barcode.prefix',
-        'Apply this prefix to any auto-generated item barcodes',
-        'coust', 'label'),
-    'string',
-    NULL
-), (
-    'vandelay',
-    'vandelay.item.call_number.auto',
-    oils_i18n_gettext(
-        'vandelay.item.call_number.auto',
-        'Vandelay Generate Default Call Numbers',
-        'coust', 'label'),
-    oils_i18n_gettext(
-        'vandelay.item.call_number.auto',
-        'Auto-generate default item call numbers when no item call number is present',
-        'coust', 'label'),
-    'bool',
-    NULL
-), (
-    'vandelay',
-    'vandelay.item.call_number.prefix',
-    oils_i18n_gettext(
-        'vandelay.item.call_number.prefix',
-        'Vandelay Default Call Number Prefix',
-        'coust', 'label'),
-    oils_i18n_gettext(
-        'vandelay.item.call_number.prefix',
-        'Apply this prefix to any auto-generated item call numbers',
-        'coust', 'label'),
-    'string',
-    NULL
-), (
-    'vandelay',
-    'vandelay.item.copy_location.default',
-    oils_i18n_gettext(
-        'vandelay.item.copy_location.default',
-        'Vandelay Default Copy Location',
-        'coust', 'label'),
-    oils_i18n_gettext(
-        'vandelay.item.copy_location.default',
-        'Default copy location value for imported items',
-        'coust', 'label'),
-    'link',
-    'acpl'
-), (
-    'vandelay',
-    'vandelay.item.circ_modifier.default',
-    oils_i18n_gettext(
-        'vandelay.item.circ_modifier.default',
-        'Vandelay Default Circulation Modifier',
-        'coust', 'label'),
-    oils_i18n_gettext(
-        'vandelay.item.circ_modifier.default',
-        'Default circulation modifier value for imported items',
-        'coust', 'label'),
-    'link',
-    'ccm'
-);
-
-
-CREATE OR REPLACE FUNCTION vandelay.ingest_items ( import_id BIGINT, attr_def_id BIGINT ) RETURNS SETOF vandelay.import_item AS $$
-DECLARE
-
-    owning_lib      TEXT;
-    circ_lib        TEXT;
-    call_number     TEXT;
-    copy_number     TEXT;
-    status          TEXT;
-    location        TEXT;
-    circulate       TEXT;
-    deposit         TEXT;
-    deposit_amount  TEXT;
-    ref             TEXT;
-    holdable        TEXT;
-    price           TEXT;
-    barcode         TEXT;
-    circ_modifier   TEXT;
-    circ_as_type    TEXT;
-    alert_message   TEXT;
-    opac_visible    TEXT;
-    pub_note        TEXT;
-    priv_note       TEXT;
-    internal_id     TEXT;
-
-    attr_def        RECORD;
-    tmp_attr_set    RECORD;
-    attr_set        vandelay.import_item%ROWTYPE;
-
-    xpath           TEXT;
-    tmp_str         TEXT;
-
-BEGIN
-
-    SELECT * INTO attr_def FROM vandelay.import_item_attr_definition WHERE id = attr_def_id;
-
-    IF FOUND THEN
-
-        attr_set.definition := attr_def.id;
-
-        -- Build the combined XPath
-
-        owning_lib :=
-            CASE
-                WHEN attr_def.owning_lib IS NULL THEN 'null()'
-                WHEN LENGTH( attr_def.owning_lib ) = 1 THEN '//*[@tag="' || attr_def.tag || '"]/*[@code="' || attr_def.owning_lib || '"]'
-                ELSE '//*[@tag="' || attr_def.tag || '"]/*' || attr_def.owning_lib
-            END;
-
-        circ_lib :=
-            CASE
-                WHEN attr_def.circ_lib IS NULL THEN 'null()'
-                WHEN LENGTH( attr_def.circ_lib ) = 1 THEN '//*[@tag="' || attr_def.tag || '"]/*[@code="' || attr_def.circ_lib || '"]'
-                ELSE '//*[@tag="' || attr_def.tag || '"]/*' || attr_def.circ_lib
-            END;
-
-        call_number :=
-            CASE
-                WHEN attr_def.call_number IS NULL THEN 'null()'
-                WHEN LENGTH( attr_def.call_number ) = 1 THEN '//*[@tag="' || attr_def.tag || '"]/*[@code="' || attr_def.call_number || '"]'
-                ELSE '//*[@tag="' || attr_def.tag || '"]/*' || attr_def.call_number
-            END;
-
-        copy_number :=
-            CASE
-                WHEN attr_def.copy_number IS NULL THEN 'null()'
-                WHEN LENGTH( attr_def.copy_number ) = 1 THEN '//*[@tag="' || attr_def.tag || '"]/*[@code="' || attr_def.copy_number || '"]'
-                ELSE '//*[@tag="' || attr_def.tag || '"]/*' || attr_def.copy_number
-            END;
-
-        status :=
-            CASE
-                WHEN attr_def.status IS NULL THEN 'null()'
-                WHEN LENGTH( attr_def.status ) = 1 THEN '//*[@tag="' || attr_def.tag || '"]/*[@code="' || attr_def.status || '"]'
-                ELSE '//*[@tag="' || attr_def.tag || '"]/*' || attr_def.status
-            END;
-
-        location :=
-            CASE
-                WHEN attr_def.location IS NULL THEN 'null()'
-                WHEN LENGTH( attr_def.location ) = 1 THEN '//*[@tag="' || attr_def.tag || '"]/*[@code="' || attr_def.location || '"]'
-                ELSE '//*[@tag="' || attr_def.tag || '"]/*' || attr_def.location
-            END;
-
-        circulate :=
-            CASE
-                WHEN attr_def.circulate IS NULL THEN 'null()'
-                WHEN LENGTH( attr_def.circulate ) = 1 THEN '//*[@tag="' || attr_def.tag || '"]/*[@code="' || attr_def.circulate || '"]'
-                ELSE '//*[@tag="' || attr_def.tag || '"]/*' || attr_def.circulate
-            END;
-
-        deposit :=
-            CASE
-                WHEN attr_def.deposit IS NULL THEN 'null()'
-                WHEN LENGTH( attr_def.deposit ) = 1 THEN '//*[@tag="' || attr_def.tag || '"]/*[@code="' || attr_def.deposit || '"]'
-                ELSE '//*[@tag="' || attr_def.tag || '"]/*' || attr_def.deposit
-            END;
-
-        deposit_amount :=
-            CASE
-                WHEN attr_def.deposit_amount IS NULL THEN 'null()'
-                WHEN LENGTH( attr_def.deposit_amount ) = 1 THEN '//*[@tag="' || attr_def.tag || '"]/*[@code="' || attr_def.deposit_amount || '"]'
-                ELSE '//*[@tag="' || attr_def.tag || '"]/*' || attr_def.deposit_amount
-            END;
-
-        ref :=
-            CASE
-                WHEN attr_def.ref IS NULL THEN 'null()'
-                WHEN LENGTH( attr_def.ref ) = 1 THEN '//*[@tag="' || attr_def.tag || '"]/*[@code="' || attr_def.ref || '"]'
-                ELSE '//*[@tag="' || attr_def.tag || '"]/*' || attr_def.ref
-            END;
-
-        holdable :=
-            CASE
-                WHEN attr_def.holdable IS NULL THEN 'null()'
-                WHEN LENGTH( attr_def.holdable ) = 1 THEN '//*[@tag="' || attr_def.tag || '"]/*[@code="' || attr_def.holdable || '"]'
-                ELSE '//*[@tag="' || attr_def.tag || '"]/*' || attr_def.holdable
-            END;
-
-        price :=
-            CASE
-                WHEN attr_def.price IS NULL THEN 'null()'
-                WHEN LENGTH( attr_def.price ) = 1 THEN '//*[@tag="' || attr_def.tag || '"]/*[@code="' || attr_def.price || '"]'
-                ELSE '//*[@tag="' || attr_def.tag || '"]/*' || attr_def.price
-            END;
-
-        barcode :=
-            CASE
-                WHEN attr_def.barcode IS NULL THEN 'null()'
-                WHEN LENGTH( attr_def.barcode ) = 1 THEN '//*[@tag="' || attr_def.tag || '"]/*[@code="' || attr_def.barcode || '"]'
-                ELSE '//*[@tag="' || attr_def.tag || '"]/*' || attr_def.barcode
-            END;
-
-        circ_modifier :=
-            CASE
-                WHEN attr_def.circ_modifier IS NULL THEN 'null()'
-                WHEN LENGTH( attr_def.circ_modifier ) = 1 THEN '//*[@tag="' || attr_def.tag || '"]/*[@code="' || attr_def.circ_modifier || '"]'
-                ELSE '//*[@tag="' || attr_def.tag || '"]/*' || attr_def.circ_modifier
-            END;
-
-        circ_as_type :=
-            CASE
-                WHEN attr_def.circ_as_type IS NULL THEN 'null()'
-                WHEN LENGTH( attr_def.circ_as_type ) = 1 THEN '//*[@tag="' || attr_def.tag || '"]/*[@code="' || attr_def.circ_as_type || '"]'
-                ELSE '//*[@tag="' || attr_def.tag || '"]/*' || attr_def.circ_as_type
-            END;
-
-        alert_message :=
-            CASE
-                WHEN attr_def.alert_message IS NULL THEN 'null()'
-                WHEN LENGTH( attr_def.alert_message ) = 1 THEN '//*[@tag="' || attr_def.tag || '"]/*[@code="' || attr_def.alert_message || '"]'
-                ELSE '//*[@tag="' || attr_def.tag || '"]/*' || attr_def.alert_message
-            END;
-
-        opac_visible :=
-            CASE
-                WHEN attr_def.opac_visible IS NULL THEN 'null()'
-                WHEN LENGTH( attr_def.opac_visible ) = 1 THEN '//*[@tag="' || attr_def.tag || '"]/*[@code="' || attr_def.opac_visible || '"]'
-                ELSE '//*[@tag="' || attr_def.tag || '"]/*' || attr_def.opac_visible
-            END;
-
-        pub_note :=
-            CASE
-                WHEN attr_def.pub_note IS NULL THEN 'null()'
-                WHEN LENGTH( attr_def.pub_note ) = 1 THEN '//*[@tag="' || attr_def.tag || '"]/*[@code="' || attr_def.pub_note || '"]'
-                ELSE '//*[@tag="' || attr_def.tag || '"]/*' || attr_def.pub_note
-            END;
-        priv_note :=
-            CASE
-                WHEN attr_def.priv_note IS NULL THEN 'null()'
-                WHEN LENGTH( attr_def.priv_note ) = 1 THEN '//*[@tag="' || attr_def.tag || '"]/*[@code="' || attr_def.priv_note || '"]'
-                ELSE '//*[@tag="' || attr_def.tag || '"]/*' || attr_def.priv_note
-            END;
-
-        internal_id :=
-            CASE
-                WHEN attr_def.internal_id IS NULL THEN 'null()'
-                WHEN LENGTH( attr_def.internal_id ) = 1 THEN '//*[@tag="' || attr_def.tag || '"]/*[@code="' || attr_def.internal_id || '"]'
-                ELSE '//*[@tag="' || attr_def.tag || '"]/*' || attr_def.internal_id
-            END;
-
-
-
-        xpath :=
-            owning_lib      || '|' ||
-            circ_lib        || '|' ||
-            call_number     || '|' ||
-            copy_number     || '|' ||
-            status          || '|' ||
-            location        || '|' ||
-            circulate       || '|' ||
-            deposit         || '|' ||
-            deposit_amount  || '|' ||
-            ref             || '|' ||
-            holdable        || '|' ||
-            price           || '|' ||
-            barcode         || '|' ||
-            circ_modifier   || '|' ||
-            circ_as_type    || '|' ||
-            alert_message   || '|' ||
-            pub_note        || '|' ||
-            priv_note       || '|' ||
-            internal_id     || '|' ||
-            opac_visible;
-
-        FOR tmp_attr_set IN
-                SELECT  *
-                  FROM  oils_xpath_table( 'id', 'marc', 'vandelay.queued_bib_record', xpath, 'id = ' || import_id )
-                            AS t( id INT, ol TEXT, clib TEXT, cn TEXT, cnum TEXT, cs TEXT, cl TEXT, circ TEXT,
-                                  dep TEXT, dep_amount TEXT, r TEXT, hold TEXT, pr TEXT, bc TEXT, circ_mod TEXT,
-                                  circ_as TEXT, amessage TEXT, note TEXT, pnote TEXT, internal_id TEXT, opac_vis TEXT )
-        LOOP
-
-            attr_set.import_error := NULL;
-            attr_set.error_detail := NULL;
-            attr_set.deposit_amount := NULL;
-            attr_set.copy_number := NULL;
-            attr_set.price := NULL;
-            attr_set.circ_modifier := NULL;
-            attr_set.location := NULL;
-            attr_set.barcode := NULL;
-            attr_set.call_number := NULL;
-
-            IF tmp_attr_set.pr != '' THEN
-                tmp_str = REGEXP_REPLACE(tmp_attr_set.pr, E'[^0-9\\.]', '', 'g');
-                IF tmp_str = '' THEN 
-                    attr_set.import_error := 'import.item.invalid.price';
-                    attr_set.error_detail := tmp_attr_set.pr; -- original value
-                    RETURN NEXT attr_set; CONTINUE; 
-                END IF;
-                attr_set.price := tmp_str::NUMERIC(8,2); 
-            END IF;
-
-            IF tmp_attr_set.dep_amount != '' THEN
-                tmp_str = REGEXP_REPLACE(tmp_attr_set.dep_amount, E'[^0-9\\.]', '', 'g');
-                IF tmp_str = '' THEN 
-                    attr_set.import_error := 'import.item.invalid.deposit_amount';
-                    attr_set.error_detail := tmp_attr_set.dep_amount; 
-                    RETURN NEXT attr_set; CONTINUE; 
-                END IF;
-                attr_set.deposit_amount := tmp_str::NUMERIC(8,2); 
-            END IF;
-
-            IF tmp_attr_set.cnum != '' THEN
-                tmp_str = REGEXP_REPLACE(tmp_attr_set.cnum, E'[^0-9]', '', 'g');
-                IF tmp_str = '' THEN 
-                    attr_set.import_error := 'import.item.invalid.copy_number';
-                    attr_set.error_detail := tmp_attr_set.cnum; 
-                    RETURN NEXT attr_set; CONTINUE; 
-                END IF;
-                attr_set.copy_number := tmp_str::INT; 
-            END IF;
-
-            IF tmp_attr_set.ol != '' THEN
-                SELECT id INTO attr_set.owning_lib FROM actor.org_unit WHERE shortname = UPPER(tmp_attr_set.ol); -- INT
-                IF NOT FOUND THEN
-                    attr_set.import_error := 'import.item.invalid.owning_lib';
-                    attr_set.error_detail := tmp_attr_set.ol;
-                    RETURN NEXT attr_set; CONTINUE; 
-                END IF;
-            END IF;
-
-            IF tmp_attr_set.clib != '' THEN
-                SELECT id INTO attr_set.circ_lib FROM actor.org_unit WHERE shortname = UPPER(tmp_attr_set.clib); -- INT
-                IF NOT FOUND THEN
-                    attr_set.import_error := 'import.item.invalid.circ_lib';
-                    attr_set.error_detail := tmp_attr_set.clib;
-                    RETURN NEXT attr_set; CONTINUE; 
-                END IF;
-            END IF;
-
-            IF tmp_attr_set.cs != '' THEN
-                SELECT id INTO attr_set.status FROM config.copy_status WHERE LOWER(name) = LOWER(tmp_attr_set.cs); -- INT
-                IF NOT FOUND THEN
-                    attr_set.import_error := 'import.item.invalid.status';
-                    attr_set.error_detail := tmp_attr_set.cs;
-                    RETURN NEXT attr_set; CONTINUE; 
-                END IF;
-            END IF;
-
-            IF COALESCE(tmp_attr_set.circ_mod, '') = '' THEN
-
-                -- no circ mod defined, see if we should apply a default
-                SELECT INTO attr_set.circ_modifier TRIM(BOTH '"' FROM value) 
-                    FROM actor.org_unit_ancestor_setting(
-                        'vandelay.item.circ_modifier.default', 
-                        attr_set.owning_lib
-                    );
-
-                -- make sure the value from the org setting is still valid
-                PERFORM 1 FROM config.circ_modifier WHERE code = attr_set.circ_modifier;
-                IF NOT FOUND THEN
-                    attr_set.import_error := 'import.item.invalid.circ_modifier';
-                    attr_set.error_detail := tmp_attr_set.circ_mod;
-                    RETURN NEXT attr_set; CONTINUE; 
-                END IF;
-
-            ELSE 
-
-                SELECT code INTO attr_set.circ_modifier FROM config.circ_modifier WHERE code = tmp_attr_set.circ_mod;
-                IF NOT FOUND THEN
-                    attr_set.import_error := 'import.item.invalid.circ_modifier';
-                    attr_set.error_detail := tmp_attr_set.circ_mod;
-                    RETURN NEXT attr_set; CONTINUE; 
-                END IF;
-            END IF;
-
-            IF tmp_attr_set.circ_as != '' THEN
-                SELECT code INTO attr_set.circ_as_type FROM config.coded_value_map WHERE ctype = 'item_type' AND code = tmp_attr_set.circ_as;
-                IF NOT FOUND THEN
-                    attr_set.import_error := 'import.item.invalid.circ_as_type';
-                    attr_set.error_detail := tmp_attr_set.circ_as;
-                    RETURN NEXT attr_set; CONTINUE; 
-                END IF;
-            END IF;
-
-            IF COALESCE(tmp_attr_set.cl, '') = '' THEN
-                -- no location specified, see if we should apply a default
-
-                SELECT INTO attr_set.location TRIM(BOTH '"' FROM value) 
-                    FROM actor.org_unit_ancestor_setting(
-                        'vandelay.item.copy_location.default', 
-                        attr_set.owning_lib
-                    );
-
-                -- make sure the value from the org setting is still valid
-                PERFORM 1 FROM asset.copy_location WHERE id = attr_set.location;
-                IF NOT FOUND THEN
-                    attr_set.import_error := 'import.item.invalid.location';
-                    attr_set.error_detail := tmp_attr_set.cs;
-                    RETURN NEXT attr_set; CONTINUE; 
-                END IF;
-            ELSE
-
-                -- search up the org unit tree for a matching copy location
-                WITH RECURSIVE anscestor_depth AS (
-                    SELECT  ou.id,
-                        out.depth AS depth,
-                        ou.parent_ou
-                    FROM  actor.org_unit ou
-                        JOIN actor.org_unit_type out ON (out.id = ou.ou_type)
-                    WHERE ou.id = COALESCE(attr_set.owning_lib, attr_set.circ_lib)
-                        UNION ALL
-                    SELECT  ou.id,
-                        out.depth,
-                        ou.parent_ou
-                    FROM  actor.org_unit ou
-                        JOIN actor.org_unit_type out ON (out.id = ou.ou_type)
-                        JOIN anscestor_depth ot ON (ot.parent_ou = ou.id)
-                ) SELECT  cpl.id INTO attr_set.location
-                    FROM  anscestor_depth a
-                        JOIN asset.copy_location cpl ON (cpl.owning_lib = a.id)
-                    WHERE LOWER(cpl.name) = LOWER(tmp_attr_set.cl)
-                    ORDER BY a.depth DESC
-                    LIMIT 1; 
-
-                IF NOT FOUND THEN
-                    attr_set.import_error := 'import.item.invalid.location';
-                    attr_set.error_detail := tmp_attr_set.cs;
-                    RETURN NEXT attr_set; CONTINUE; 
-                END IF;
-            END IF;
-
-            attr_set.circulate      :=
-                LOWER( SUBSTRING( tmp_attr_set.circ, 1, 1)) IN ('t','y','1')
-                OR LOWER(tmp_attr_set.circ) = 'circulating'; -- BOOL
-
-            attr_set.deposit        :=
-                LOWER( SUBSTRING( tmp_attr_set.dep, 1, 1 ) ) IN ('t','y','1')
-                OR LOWER(tmp_attr_set.dep) = 'deposit'; -- BOOL
-
-            attr_set.holdable       :=
-                LOWER( SUBSTRING( tmp_attr_set.hold, 1, 1 ) ) IN ('t','y','1')
-                OR LOWER(tmp_attr_set.hold) = 'holdable'; -- BOOL
-
-            attr_set.opac_visible   :=
-                LOWER( SUBSTRING( tmp_attr_set.opac_vis, 1, 1 ) ) IN ('t','y','1')
-                OR LOWER(tmp_attr_set.opac_vis) = 'visible'; -- BOOL
-
-            attr_set.ref            :=
-                LOWER( SUBSTRING( tmp_attr_set.r, 1, 1 ) ) IN ('t','y','1')
-                OR LOWER(tmp_attr_set.r) = 'reference'; -- BOOL
-
-            attr_set.call_number    := tmp_attr_set.cn; -- TEXT
-            attr_set.barcode        := tmp_attr_set.bc; -- TEXT,
-            attr_set.alert_message  := tmp_attr_set.amessage; -- TEXT,
-            attr_set.pub_note       := tmp_attr_set.note; -- TEXT,
-            attr_set.priv_note      := tmp_attr_set.pnote; -- TEXT,
-            attr_set.alert_message  := tmp_attr_set.amessage; -- TEXT,
-            attr_set.internal_id    := tmp_attr_set.internal_id::BIGINT;
-
-            RETURN NEXT attr_set;
-
-        END LOOP;
-
-    END IF;
-
-    RETURN;
-
-END;
-$$ LANGUAGE PLPGSQL;
-
-
-COMMIT;