From 0b8e167739f5722524063de5bd9380a8118fb793 Mon Sep 17 00:00:00 2001 From: Bill Erickson Date: Wed, 7 Aug 2013 12:05:30 -0400 Subject: [PATCH] LP1209291 vandelay item import defaults Via org settings, support auto-generation of call numbers and barcodes for items imported via Vandelay's Item Import interface. Support settings for applying a local prefix string to auto-generated call numbers and barcodes. For both, the prefix defaults to "VAN". Similarly, support default copy location and circ modifiers. The new org unit settings: vandelay.item.barcode.auto vandelay.item.barcode.prefix vandelay.item.call_number.auto vandelay.item.call_number.prefix vandelay.item.copy_location.default vandelay.item.circ_modifier.default Signed-off-by: Bill Erickson Signed-off-by: Mike Rylander --- .../lib/OpenILS/Application/Vandelay.pm | 71 ++- Open-ILS/src/sql/Pg/950.data.seed-values.sql | 85 +++ Open-ILS/src/sql/Pg/999.functions.global.sql | 45 +- ...X.schema.vandelay-item-import-defaults.sql | 491 ++++++++++++++++++ 4 files changed, 688 insertions(+), 4 deletions(-) create mode 100644 Open-ILS/src/sql/Pg/upgrade/XXXX.schema.vandelay-item-import-defaults.sql diff --git a/Open-ILS/src/perlmods/lib/OpenILS/Application/Vandelay.pm b/Open-ILS/src/perlmods/lib/OpenILS/Application/Vandelay.pm index 0f0976b260..e7dbde788a 100644 --- a/Open-ILS/src/perlmods/lib/OpenILS/Application/Vandelay.pm +++ b/Open-ILS/src/perlmods/lib/OpenILS/Application/Vandelay.pm @@ -878,12 +878,18 @@ sub queued_records_with_matches { } +# cache of import item org unit settings. +# used in apply_import_item_defaults() below, +# but reset on each call to import_record_list_impl() +my %item_defaults_cache; + sub import_record_list_impl { my($self, $conn, $rec_ids, $requestor, $args) = @_; my $overlay_map = $args->{overlay_map} || {}; my $type = $self->{record_type}; my %queues; + %item_defaults_cache = (); my $report_args = { progress => 1, @@ -1603,15 +1609,20 @@ sub import_record_asset_list_impl { {idlist=>1} ); + # if any items have no call_number label and a value should be + # applied automatically (via org settings), we want to use the same + # call number label for every copy per org per record. + my $auto_callnumber = {}; + for my $item_id (@$item_ids) { my $e = new_editor(requestor => $requestor, xact => 1); my $item = $e->retrieve_vandelay_import_item($item_id); my ($copy, $vol, $evt); - $$report_args{import_item} = $item; $$report_args{e} = $e; - $$report_args{import_error} = undef; $$report_args{evt} = undef; + $$report_args{import_item} = $item; + $$report_args{import_error} = undef; if (my $copy_id = $item->internal_id) { # assignment # copy matches an existing copy. Overlay instead of create. @@ -1753,6 +1764,10 @@ sub import_record_asset_list_impl { # Creating a new copy $logger->info("vl: creating new copy in import"); + # appply defaults values from org settings as needed + # if $auto_callnumber is unset, it will be set within + apply_import_item_defaults($e, $item, $auto_callnumber); + # -------------------------------------------------------------------------------- # Find or create the volume # -------------------------------------------------------------------------------- @@ -1844,6 +1859,58 @@ sub import_record_asset_list_impl { return undef; } +sub apply_import_item_defaults { + my ($e, $item, $auto_cn) = @_; + my $org = $item->owning_lib || $item->circ_lib; + my %c = %item_defaults_cache; + + # fetch and cache the org unit setting value (unless + # it's already cached) and return the value to the caller + my $set = sub { + my $name = shift; + return $c{$org}{$name} if defined $c{$org}{$name}; + my $sname = "vandelay.item.$name"; + $c{$org}{$name} = $U->ou_ancestor_setting_value($org, $sname, $e); + $c{$org}{$name} = '' unless defined $c{$org}{$name}; + return $c{$org}{$name}; + }; + + if (!$item->barcode) { + + if ($set->('barcode.auto')) { + + my $pfx = $set->('barcode.prefix') || 'VAN'; + my $barcode = $pfx . $item->record . $item->id; + + $logger->info("vl: using auto barcode $barcode for ".$item->id); + $item->barcode($barcode); + + } else { + $logger->error("vl: no barcode (or defualt) for item ".$item->id); + } + } + + if (!$item->call_number) { + + if ($set->('call_number.auto')) { + + if (!$auto_cn->{$org}) { + my $pfx = $set->('call_number.prefix') || 'VAN'; + + # use the ID of the first item to differentiate this + # call number from others linked to the same record + $auto_cn->{$org} = $pfx . $item->record . $item->id; + } + + $logger->info("vl: using auto call number ".$auto_cn->{$org}); + $item->call_number($auto_cn->{$org}); + + } else { + $logger->error("vl: no call number or default for item ".$item->id); + } + } +} + sub respond_with_status { my $args = shift; diff --git a/Open-ILS/src/sql/Pg/950.data.seed-values.sql b/Open-ILS/src/sql/Pg/950.data.seed-values.sql index e571b8d4bd..801a29a8b8 100644 --- a/Open-ILS/src/sql/Pg/950.data.seed-values.sql +++ b/Open-ILS/src/sql/Pg/950.data.seed-values.sql @@ -13240,3 +13240,88 @@ VALUES ( 'description' ) ); + +-- vandelay item import defaults +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' +); + + diff --git a/Open-ILS/src/sql/Pg/999.functions.global.sql b/Open-ILS/src/sql/Pg/999.functions.global.sql index e419dae15c..c8f3f7c6c2 100644 --- a/Open-ILS/src/sql/Pg/999.functions.global.sql +++ b/Open-ILS/src/sql/Pg/999.functions.global.sql @@ -1870,6 +1870,10 @@ BEGIN 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'); @@ -1928,7 +1932,25 @@ BEGIN END IF; END IF; - IF tmp_attr_set.circ_mod != '' THEN + 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'; @@ -1946,7 +1968,23 @@ BEGIN END IF; END IF; - IF tmp_attr_set.cl != '' THEN + 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 ( @@ -2016,6 +2054,9 @@ BEGIN END; $$ LANGUAGE PLPGSQL; + + + CREATE OR REPLACE FUNCTION vandelay.ingest_bib_items ( ) RETURNS TRIGGER AS $func$ DECLARE attr_def BIGINT; 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 new file mode 100644 index 0000000000..905f9267d5 --- /dev/null +++ b/Open-ILS/src/sql/Pg/upgrade/XXXX.schema.vandelay-item-import-defaults.sql @@ -0,0 +1,491 @@ + +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; -- 2.43.2