[open-ils-commits] [GIT] Evergreen ILS branch master updated. 007195f83beb33519d90133818a7d114ae82428b
Evergreen Git
git at git.evergreen-ils.org
Tue May 17 13:57:26 EDT 2011
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "Evergreen ILS".
The branch, master has been updated
via 007195f83beb33519d90133818a7d114ae82428b (commit)
via 29a874a1f9c99d2eb69b048631d4e5b0dc51a813 (commit)
from d6f8124b33f738bd06e0e83f7b2ba815ad3165bf (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit 007195f83beb33519d90133818a7d114ae82428b
Author: Mike Rylander <mrylander at gmail.com>
Date: Tue May 17 13:44:35 2011 -0400
Convert/move SQL script for Lazy Circ
Signed-off-by: Mike Rylander <mrylander at gmail.com>
diff --git a/Open-ILS/src/sql/Pg/002.schema.config.sql b/Open-ILS/src/sql/Pg/002.schema.config.sql
index 2f14205..741f4f1 100644
--- a/Open-ILS/src/sql/Pg/002.schema.config.sql
+++ b/Open-ILS/src/sql/Pg/002.schema.config.sql
@@ -86,7 +86,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 ('0535', :eg_version); -- dbs
+INSERT INTO config.upgrade_log (version, applied_to) VALUES ('0536', :eg_version); -- miker for tsbere
CREATE TABLE config.bib_source (
id SERIAL PRIMARY KEY,
diff --git a/Open-ILS/src/sql/Pg/upgrade/XXXX.lazy_circ.sql b/Open-ILS/src/sql/Pg/upgrade/0536.schema.lazy_circ-barcode_lookup.sql
similarity index 87%
rename from Open-ILS/src/sql/Pg/upgrade/XXXX.lazy_circ.sql
rename to Open-ILS/src/sql/Pg/upgrade/0536.schema.lazy_circ-barcode_lookup.sql
index ab4692a..5d86035 100644
--- a/Open-ILS/src/sql/Pg/upgrade/XXXX.lazy_circ.sql
+++ b/Open-ILS/src/sql/Pg/upgrade/0536.schema.lazy_circ-barcode_lookup.sql
@@ -1,20 +1,25 @@
+-- Evergreen DB patch 0536.schema.lazy_circ-barcode_lookup.sql
+--
+-- FIXME: insert description of change, if needed
+--
BEGIN;
-INSERT INTO config.upgrade_log (version) VALUES ('XXXX');
+-- check whether patch can be applied
+SELECT evergreen.update_deps_block_check('0536', :eg_version);
INSERT INTO config.org_unit_setting_type ( name, label, description, datatype) VALUES ( 'circ.staff_client.actor_on_checkout', 'Load patron from Checkout', 'When scanning barcodes into Checkout auto-detect if a new patron barcode is scanned and auto-load the new patron.', 'bool');
CREATE TABLE config.barcode_completion (
- id SERIAL PRIMARY KEY,
- active BOOL NOT NULL DEFAULT true,
- org_unit INT NOT NULL, -- REFERENCES actor.org_unit(id) DEFERRABLE INITIALLY DEFERRED,
+ id SERIAL PRIMARY KEY,
+ active BOOL NOT NULL DEFAULT true,
+ org_unit INT NOT NULL REFERENCES actor.org_unit (id) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED,
prefix TEXT,
suffix TEXT,
- length INT NOT NULL DEFAULT 0,
+ length INT NOT NULL DEFAULT 0,
padding TEXT,
- padding_end BOOL NOT NULL DEFAULT false,
- asset BOOL NOT NULL DEFAULT true,
- actor BOOL NOT NULL DEFAULT true
+ padding_end BOOL NOT NULL DEFAULT false,
+ asset BOOL NOT NULL DEFAULT true,
+ actor BOOL NOT NULL DEFAULT true
);
CREATE TYPE evergreen.barcode_set AS (type TEXT, id BIGINT, barcode TEXT);
@@ -108,6 +113,5 @@ Given user input, find an appropriate barcode in the proper class.
Will add prefix/suffix information to do so, and return all results.
$$;
-ALTER TABLE config.barcode_completion ADD CONSTRAINT config_barcode_completion_org_unit_fkey FOREIGN KEY (org_unit) REFERENCES actor.org_unit (id) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED;
-
COMMIT;
+
commit 29a874a1f9c99d2eb69b048631d4e5b0dc51a813
Author: Thomas Berezansky <tsbere at mvlc.org>
Date: Fri May 13 15:43:52 2011 -0400
Lazy Circ (AKA partial barcode lookup)
Database tables/access functions for prefix/suffix info
Table: config.barcode_completion
Function: evergreen.get_barcodes
Takes org unit, context, and input barcode
Context is a string and can contain:
asset - asset.copy barcodes
serial - serial.unit barcodes
actor - actor.usr (via actor.card) barcodes
booking - booking.resource barcodes
Special case: asset and serial both in context
Returns non-serial asset entries as asset
Returns serial entries as serial
Type for function return: evergreen.barcode_set
With editing interface: Admin->Local Admin->Barcode Completion
OpenSRF Call: open-ils.actor.get_barcodes
Basically a passthrough to the database function
Checks for permissions:
STAFF_LOGIN - To do anything
VIEW_USER - At home_ou of the user owning the returned
barcode when in actor context
Add get_barcode to menu.js and to xulG in a number of places
Takes a window handle, a context, and an input barcode
Passes the current OU, the context, and the input barcode to the db
If multiple results come back it pops up a dialog
Returns boolean false on no results
Returns "user_false" on dialog cancel
Returns an object with type, id, barcode on success
If dialog was brought up, returns data used to populate button
Add option for looking up actors at checkout
Org unit setting: Load patron from Checkout. Default: Don't.
Call sites for get_barcode:
Lookup Patron By Barcode (actor only)
OPAC's Staff Client Place Hold (actor only)
Checkout (asset only by default, with actor if above option set)
Checkin (asset only)
Item Status (asset only)
Signed-off-by: Thomas Berezansky <tsbere at mvlc.org>
Signed-off-by: Mike Rylander <mrylander at gmail.com>
diff --git a/Open-ILS/examples/fm_IDL.xml b/Open-ILS/examples/fm_IDL.xml
index 724e8f5..706ab89 100644
--- a/Open-ILS/examples/fm_IDL.xml
+++ b/Open-ILS/examples/fm_IDL.xml
@@ -8809,6 +8809,31 @@ SELECT usr,
</actions>
</permacrud>
</class>
+ <class id="cbc" controller="open-ils.cstore open-ils.pcrud" oils_obj:fieldmapper="config::barcode_completion" oils_persist:tablename="config.barcode_completion" reporter:label="Barcode Completions">
+ <fields oils_persist:primary="id" oils_persist:sequence="config.barcode_completion_id_seq">
+ <field reporter:label="ID" name="id" reporter:datatype="id"/>
+ <field reporter:label="Active" name="active" reporter:datatype="bool"/>
+ <field reporter:label="Owner" name="org_unit" reporter:datatype="org_unit"/>
+ <field reporter:label="Prefix" name="prefix" reporter:datatype="text"/>
+ <field reporter:label="Suffix" name="suffix" reporter:datatype="text"/>
+ <field reporter:label="Length" name="length" reporter:datatype="int"/>
+ <field reporter:label="Padding" name="padding" reporter:datatype="text"/>
+ <field reporter:label="Padding At End" name="padding_end" reporter:datatype="bool"/>
+ <field reporter:label="Applies to Items" name="asset" reporter:datatype="bool"/>
+ <field reporter:label="Applies to Users" name="actor" reporter:datatype="bool"/>
+ </fields>
+ <links>
+ <link field="org_unit" reltype="has_a" key="id" map="" class="aou"/>
+ </links>
+ <permacrud xmlns="http://open-ils.org/spec/opensrf/IDL/permacrud/v1">
+ <actions>
+ <create permission="UPDATE_ORG_UNIT_SETTING_ALL" context_field="org_unit"/>
+ <retrieve/>
+ <update permission="UPDATE_ORG_UNIT_SETTING_ALL" context_field="org_unit"/>
+ <delete permission="UPDATE_ORG_UNIT_SETTING_ALL" context_field="org_unit"/>
+ </actions>
+ </permacrud>
+ </class>
<!-- ********************************************************************************************************************* -->
diff --git a/Open-ILS/src/perlmods/lib/OpenILS/Application/Actor.pm b/Open-ILS/src/perlmods/lib/OpenILS/Application/Actor.pm
index 9b9bd13..8d6659e 100644
--- a/Open-ILS/src/perlmods/lib/OpenILS/Application/Actor.pm
+++ b/Open-ILS/src/perlmods/lib/OpenILS/Application/Actor.pm
@@ -4283,6 +4283,55 @@ sub user_saved_search_cud {
return $res;
}
+__PACKAGE__->register_method(
+ method => "get_barcodes",
+ api_name => "open-ils.actor.get_barcodes"
+);
+
+sub get_barcodes {
+ my( $self, $client, $auth, $org_id, $context, $barcode ) = @_;
+ my $e = new_editor(authtoken => $auth);
+ return $e->event unless $e->checkauth;
+ return $e->event unless $e->allowed('STAFF_LOGIN', $org_id);
+ my $db_result = $e->json_query(
+ { from => [
+ 'evergreen.get_barcodes',
+ $org_id, $context, $barcode,
+ ]
+ }
+ );
+ if($context =~ /actor/) {
+ my $filter_result = ();
+ my $patron;
+ foreach my $result (@$db_result) {
+ if($result->{type} eq 'actor') {
+ if($e->requestor->id != $result->{id}) {
+ $patron = $e->retrieve_actor_user($result->{id});
+ if(!$patron) {
+ push(@$filter_result, $e->event);
+ next;
+ }
+ if($e->allowed('VIEW_USER', $patron->home_ou)) {
+ push(@$filter_result, $result);
+ }
+ else {
+ push(@$filter_result, $e->event);
+ }
+ }
+ else {
+ push(@$filter_result, $result);
+ }
+ }
+ else {
+ push(@$filter_result, $result);
+ }
+ }
+ return $filter_result;
+ }
+ else {
+ return $db_result;
+ }
+}
1;
diff --git a/Open-ILS/src/sql/Pg/002.schema.config.sql b/Open-ILS/src/sql/Pg/002.schema.config.sql
index 4b7b0ef..2f14205 100644
--- a/Open-ILS/src/sql/Pg/002.schema.config.sql
+++ b/Open-ILS/src/sql/Pg/002.schema.config.sql
@@ -887,4 +887,19 @@ Upgrade script % can not be applied:
END;
$$ LANGUAGE PLPGSQL;
+CREATE TABLE config.barcode_completion (
+ id SERIAL PRIMARY KEY,
+ active BOOL NOT NULL DEFAULT true,
+ org_unit INT NOT NULL, -- REFERENCES actor.org_unit(id) DEFERRABLE INITIALLY DEFERRED,
+ prefix TEXT,
+ suffix TEXT,
+ length INT NOT NULL DEFAULT 0,
+ padding TEXT,
+ padding_end BOOL NOT NULL DEFAULT false,
+ asset BOOL NOT NULL DEFAULT true,
+ actor BOOL NOT NULL DEFAULT true
+);
+
+CREATE TYPE evergreen.barcode_set AS (type TEXT, id BIGINT, barcode TEXT);
+
COMMIT;
diff --git a/Open-ILS/src/sql/Pg/020.schema.functions.sql b/Open-ILS/src/sql/Pg/020.schema.functions.sql
index 981a364..f29239e 100644
--- a/Open-ILS/src/sql/Pg/020.schema.functions.sql
+++ b/Open-ILS/src/sql/Pg/020.schema.functions.sql
@@ -416,3 +416,92 @@ from an authority record. The primary purpose is to build a unique
index to defend against duplicated authority records from the same
thesaurus.
$$;
+
+CREATE OR REPLACE FUNCTION evergreen.get_barcodes(select_ou INT, type TEXT, in_barcode TEXT) RETURNS SETOF evergreen.barcode_set AS $$
+DECLARE
+ cur_barcode TEXT;
+ barcode_len INT;
+ completion_len INT;
+ asset_barcodes TEXT[];
+ actor_barcodes TEXT[];
+ do_asset BOOL = false;
+ do_serial BOOL = false;
+ do_booking BOOL = false;
+ do_actor BOOL = false;
+ completion_set config.barcode_completion%ROWTYPE;
+BEGIN
+
+ IF position('asset' in type) > 0 THEN
+ do_asset = true;
+ END IF;
+ IF position('serial' in type) > 0 THEN
+ do_serial = true;
+ END IF;
+ IF position('booking' in type) > 0 THEN
+ do_booking = true;
+ END IF;
+ IF do_asset OR do_serial OR do_booking THEN
+ asset_barcodes = asset_barcodes || in_barcode;
+ END IF;
+ IF position('actor' in type) > 0 THEN
+ do_actor = true;
+ actor_barcodes = actor_barcodes || in_barcode;
+ END IF;
+
+ barcode_len := length(in_barcode);
+
+ FOR completion_set IN
+ SELECT * FROM config.barcode_completion
+ WHERE active
+ AND org_unit IN (SELECT aou.id FROM actor.org_unit_ancestors(select_ou) aou)
+ LOOP
+ IF completion_set.prefix IS NULL THEN
+ completion_set.prefix := '';
+ END IF;
+ IF completion_set.suffix IS NULL THEN
+ completion_set.suffix := '';
+ END IF;
+ IF completion_set.length = 0 OR completion_set.padding IS NULL OR length(completion_set.padding) = 0 THEN
+ cur_barcode = completion_set.prefix || in_barcode || completion_set.suffix;
+ ELSE
+ completion_len = completion_set.length - length(completion_set.prefix) - length(completion_set.suffix);
+ IF completion_len >= barcode_len THEN
+ IF completion_set.padding_end THEN
+ cur_barcode = rpad(in_barcode, completion_len, completion_set.padding);
+ ELSE
+ cur_barcode = lpad(in_barcode, completion_len, completion_set.padding);
+ END IF;
+ cur_barcode = completion_set.prefix || cur_barcode || completion_set.suffix;
+ END IF;
+ END IF;
+ IF completion_set.actor THEN
+ actor_barcodes = actor_barcodes || cur_barcode;
+ END IF;
+ IF completion_set.asset THEN
+ asset_barcodes = asset_barcodes || cur_barcode;
+ END IF;
+ END LOOP;
+
+ IF do_asset AND do_serial THEN
+ RETURN QUERY SELECT 'asset'::TEXT, id, barcode FROM ONLY asset.copy WHERE barcode = ANY(asset_barcodes) AND deleted = false;
+ RETURN QUERY SELECT 'serial'::TEXT, id, barcode FROM serial.unit WHERE barcode = ANY(asset_barcodes) AND deleted = false;
+ ELSIF do_asset THEN
+ RETURN QUERY SELECT 'asset'::TEXT, id, barcode FROM asset.copy WHERE barcode = ANY(asset_barcodes) AND deleted = false;
+ ELSIF do_serial THEN
+ RETURN QUERY SELECT 'serial'::TEXT, id, barcode FROM serial.unit WHERE barcode = ANY(asset_barcodes) AND deleted = false;
+ END IF;
+ IF do_booking THEN
+ RETURN QUERY SELECT 'booking'::TEXT, id::BIGINT, barcode FROM booking.resource WHERE barcode = ANY(asset_barcodes);
+ END IF;
+ IF do_actor THEN
+ RETURN QUERY SELECT 'actor'::TEXT, c.usr::BIGINT, c.barcode FROM actor.card c JOIN actor.usr u ON c.usr = u.id WHERE c.barcode = ANY(actor_barcodes) AND c.active AND NOT u.deleted ORDER BY usr;
+ END IF;
+ RETURN;
+END;
+$$ LANGUAGE plpgsql;
+
+COMMENT ON FUNCTION evergreen.get_barcodes(INT, TEXT, TEXT) IS $$
+Given user input, find an appropriate barcode in the proper class.
+
+Will add prefix/suffix information to do so, and return all results.
+$$;
diff --git a/Open-ILS/src/sql/Pg/800.fkeys.sql b/Open-ILS/src/sql/Pg/800.fkeys.sql
index 619441d..d0ee887 100644
--- a/Open-ILS/src/sql/Pg/800.fkeys.sql
+++ b/Open-ILS/src/sql/Pg/800.fkeys.sql
@@ -115,6 +115,8 @@ ALTER TABLE config.remote_account ADD CONSTRAINT config_remote_account_owner_fke
ALTER TABLE config.org_unit_setting_type ADD CONSTRAINT view_perm_fkey FOREIGN KEY (view_perm) REFERENCES permission.perm_list (id) ON UPDATE CASCADE ON DELETE RESTRICT DEFERRABLE INITIALLY DEFERRED;
ALTER TABLE config.org_unit_setting_type ADD CONSTRAINT update_perm_fkey FOREIGN KEY (update_perm) REFERENCES permission.perm_list (id) ON UPDATE CASCADE DEFERRABLE INITIALLY DEFERRED;
+ALTER TABLE config.barcode_completion ADD CONSTRAINT config_barcode_completion_org_unit_fkey FOREIGN KEY (org_unit) REFERENCES actor.org_unit (id) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED;
+
CREATE INDEX by_heading_and_thesaurus ON authority.record_entry (authority.normalize_heading(marc)) WHERE deleted IS FALSE or deleted = FALSE;
COMMIT;
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 38b7b71..8daf489 100644
--- a/Open-ILS/src/sql/Pg/950.data.seed-values.sql
+++ b/Open-ILS/src/sql/Pg/950.data.seed-values.sql
@@ -2508,6 +2508,11 @@ INSERT into config.org_unit_setting_type
oils_i18n_gettext('circ.selfcheck.auto_override_checkout_events', 'List of checkout/renewal events that the selfcheck interface should automatically override instead instead of alerting and stopping the transaction', 'coust', 'description'),
'array'),
+( 'circ.staff_client.actor_on_checkout',
+ oils_i18n_gettext('circ.staff_client.actor_on_checkout', 'Load patron from Checkout', 'coust', 'label'),
+ oils_i18n_gettext('circ.staff_client.actor_on_checkout', 'When scanning barcodes into Checkout auto-detect if a new patron barcode is scanned and auto-load the new patron.', 'coust', 'description'),
+ 'bool'),
+
( 'circ.staff_client.do_not_auto_attempt_print',
oils_i18n_gettext('circ.staff_client.do_not_auto_attempt_print', 'Disable Automatic Print Attempt Type List', 'coust', 'label'),
oils_i18n_gettext('circ.staff_client.do_not_auto_attempt_print', 'Disable automatic print attempts from staff client interfaces for the receipt types in this list. Possible values: "Checkout", "Bill Pay", "Hold Slip", "Transit Slip", and "Hold/Transit Slip". This is different from the Auto-Print checkbox in the pertinent interfaces in that it disables automatic print attempts altogether, rather than encouraging silent printing by suppressing the print dialog. The Auto-Print checkbox in these interfaces have no effect on the behavior for this setting. In the case of the Hold, Transit, and Hold/Transit slips, this also suppresses the alert dialogs that precede the print dialog (the ones that offer Print and Do Not Print as options).', 'coust', 'description'),
diff --git a/Open-ILS/src/sql/Pg/upgrade/XXXX.lazy_circ.sql b/Open-ILS/src/sql/Pg/upgrade/XXXX.lazy_circ.sql
new file mode 100644
index 0000000..ab4692a
--- /dev/null
+++ b/Open-ILS/src/sql/Pg/upgrade/XXXX.lazy_circ.sql
@@ -0,0 +1,113 @@
+BEGIN;
+
+INSERT INTO config.upgrade_log (version) VALUES ('XXXX');
+
+INSERT INTO config.org_unit_setting_type ( name, label, description, datatype) VALUES ( 'circ.staff_client.actor_on_checkout', 'Load patron from Checkout', 'When scanning barcodes into Checkout auto-detect if a new patron barcode is scanned and auto-load the new patron.', 'bool');
+
+CREATE TABLE config.barcode_completion (
+ id SERIAL PRIMARY KEY,
+ active BOOL NOT NULL DEFAULT true,
+ org_unit INT NOT NULL, -- REFERENCES actor.org_unit(id) DEFERRABLE INITIALLY DEFERRED,
+ prefix TEXT,
+ suffix TEXT,
+ length INT NOT NULL DEFAULT 0,
+ padding TEXT,
+ padding_end BOOL NOT NULL DEFAULT false,
+ asset BOOL NOT NULL DEFAULT true,
+ actor BOOL NOT NULL DEFAULT true
+);
+
+CREATE TYPE evergreen.barcode_set AS (type TEXT, id BIGINT, barcode TEXT);
+
+CREATE OR REPLACE FUNCTION evergreen.get_barcodes(select_ou INT, type TEXT, in_barcode TEXT) RETURNS SETOF evergreen.barcode_set AS $$
+DECLARE
+ cur_barcode TEXT;
+ barcode_len INT;
+ completion_len INT;
+ asset_barcodes TEXT[];
+ actor_barcodes TEXT[];
+ do_asset BOOL = false;
+ do_serial BOOL = false;
+ do_booking BOOL = false;
+ do_actor BOOL = false;
+ completion_set config.barcode_completion%ROWTYPE;
+BEGIN
+
+ IF position('asset' in type) > 0 THEN
+ do_asset = true;
+ END IF;
+ IF position('serial' in type) > 0 THEN
+ do_serial = true;
+ END IF;
+ IF position('booking' in type) > 0 THEN
+ do_booking = true;
+ END IF;
+ IF do_asset OR do_serial OR do_booking THEN
+ asset_barcodes = asset_barcodes || in_barcode;
+ END IF;
+ IF position('actor' in type) > 0 THEN
+ do_actor = true;
+ actor_barcodes = actor_barcodes || in_barcode;
+ END IF;
+
+ barcode_len := length(in_barcode);
+
+ FOR completion_set IN
+ SELECT * FROM config.barcode_completion
+ WHERE active
+ AND org_unit IN (SELECT aou.id FROM actor.org_unit_ancestors(select_ou) aou)
+ LOOP
+ IF completion_set.prefix IS NULL THEN
+ completion_set.prefix := '';
+ END IF;
+ IF completion_set.suffix IS NULL THEN
+ completion_set.suffix := '';
+ END IF;
+ IF completion_set.length = 0 OR completion_set.padding IS NULL OR length(completion_set.padding) = 0 THEN
+ cur_barcode = completion_set.prefix || in_barcode || completion_set.suffix;
+ ELSE
+ completion_len = completion_set.length - length(completion_set.prefix) - length(completion_set.suffix);
+ IF completion_len >= barcode_len THEN
+ IF completion_set.padding_end THEN
+ cur_barcode = rpad(in_barcode, completion_len, completion_set.padding);
+ ELSE
+ cur_barcode = lpad(in_barcode, completion_len, completion_set.padding);
+ END IF;
+ cur_barcode = completion_set.prefix || cur_barcode || completion_set.suffix;
+ END IF;
+ END IF;
+ IF completion_set.actor THEN
+ actor_barcodes = actor_barcodes || cur_barcode;
+ END IF;
+ IF completion_set.asset THEN
+ asset_barcodes = asset_barcodes || cur_barcode;
+ END IF;
+ END LOOP;
+
+ IF do_asset AND do_serial THEN
+ RETURN QUERY SELECT 'asset'::TEXT, id, barcode FROM ONLY asset.copy WHERE barcode = ANY(asset_barcodes) AND deleted = false;
+ RETURN QUERY SELECT 'serial'::TEXT, id, barcode FROM serial.unit WHERE barcode = ANY(asset_barcodes) AND deleted = false;
+ ELSIF do_asset THEN
+ RETURN QUERY SELECT 'asset'::TEXT, id, barcode FROM asset.copy WHERE barcode = ANY(asset_barcodes) AND deleted = false;
+ ELSIF do_serial THEN
+ RETURN QUERY SELECT 'serial'::TEXT, id, barcode FROM serial.unit WHERE barcode = ANY(asset_barcodes) AND deleted = false;
+ END IF;
+ IF do_booking THEN
+ RETURN QUERY SELECT 'booking'::TEXT, id::BIGINT, barcode FROM booking.resource WHERE barcode = ANY(asset_barcodes);
+ END IF;
+ IF do_actor THEN
+ RETURN QUERY SELECT 'actor'::TEXT, c.usr::BIGINT, c.barcode FROM actor.card c JOIN actor.usr u ON c.usr = u.id WHERE c.barcode = ANY(actor_barcodes) AND c.active AND NOT u.deleted ORDER BY usr;
+ END IF;
+ RETURN;
+END;
+$$ LANGUAGE plpgsql;
+
+COMMENT ON FUNCTION evergreen.get_barcodes(INT, TEXT, TEXT) IS $$
+Given user input, find an appropriate barcode in the proper class.
+
+Will add prefix/suffix information to do so, and return all results.
+$$;
+
+ALTER TABLE config.barcode_completion ADD CONSTRAINT config_barcode_completion_org_unit_fkey FOREIGN KEY (org_unit) REFERENCES actor.org_unit (id) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED;
+
+COMMIT;
diff --git a/Open-ILS/web/js/ui/default/conify/global/config/barcode_completion.js b/Open-ILS/web/js/ui/default/conify/global/config/barcode_completion.js
new file mode 100644
index 0000000..0979c49
--- /dev/null
+++ b/Open-ILS/web/js/ui/default/conify/global/config/barcode_completion.js
@@ -0,0 +1,15 @@
+dojo.require('dijit.layout.ContentPane');
+dojo.require('dijit.form.Button');
+dojo.require('openils.widget.AutoGrid');
+dojo.require('openils.widget.AutoFieldWidget');
+dojo.require('openils.PermaCrud');
+dojo.require('openils.widget.ProgressDialog');
+
+function load(){
+ cmGrid.overrideWidgetArgs.prefix = {hrbefore : true};
+ cmGrid.overrideWidgetArgs.asset = {hrbefore: true};
+ cmGrid.loadAll({order_by:{cbc:'org_unit'}});
+}
+
+openils.Util.addOnLoad(load);
+
diff --git a/Open-ILS/web/opac/locale/en-US/lang.dtd b/Open-ILS/web/opac/locale/en-US/lang.dtd
index 9cf9140..38ae9a1 100644
--- a/Open-ILS/web/opac/locale/en-US/lang.dtd
+++ b/Open-ILS/web/opac/locale/en-US/lang.dtd
@@ -704,6 +704,7 @@
<!ENTITY staff.main.menu.admin.local_admin.conify.standing_penalty.label "Standing Penalties">
<!ENTITY staff.main.menu.admin.local_admin.conify.grp_penalty_threshold.label "Group Penalty Thresholds">
<!ENTITY staff.main.menu.admin.local_admin.conify.copy_location_order.label "Copy Location Order">
+<!ENTITY staff.main.menu.admin.local_admin.barcode_completion.label "Barcode Completion">
<!ENTITY staff.main.menu.admin.local_admin.circ_matrix_matchpoint.label "Circulation Policies">
<!ENTITY staff.main.menu.admin.local_admin.hold_matrix_matchpoint.label "Hold Policies">
<!ENTITY staff.main.menu.admin.local_admin.work_log.label "Work Log">
diff --git a/Open-ILS/web/opac/skin/default/js/holds.js b/Open-ILS/web/opac/skin/default/js/holds.js
index 73514c1..aaf7a2e 100644
--- a/Open-ILS/web/opac/skin/default/js/holds.js
+++ b/Open-ILS/web/opac/skin/default/js/holds.js
@@ -53,7 +53,24 @@ function _holdsHandleStaffMe() {
}
function _holdsHandleStaff() {
- var barcode = xulG.patron_barcode || $('xul_recipient_barcode').value;
+ var barcode = xulG.patron_barcode;
+ if(!barcode) {
+ barcode = $('xul_recipient_barcode').value;
+ if(xulG.get_barcode) {
+ // We have a "complete the barcode" function, call it (actor = users only)
+ var new_barcode = xulG.get_barcode(window, 'actor', barcode);
+ // If we got a result (boolean false is "no result") check it
+ if(new_barcode) {
+ // user_false string means they picked "None of the above"
+ // Abort before any other events can fire
+ if(new_barcode == "user_false") return;
+ // No error means we have a (hopefully valid) completed barcode to use.
+ // Otherwise, fall through to other methods of checking
+ if(typeof new_barcode.ilsevent == 'undefined')
+ barcode = new_barcode.barcode;
+ }
+ }
+ }
var user = grabUserByBarcode( G.user.session, barcode );
var evt;
diff --git a/Open-ILS/web/templates/default/conify/global/config/barcode_completion.tt2 b/Open-ILS/web/templates/default/conify/global/config/barcode_completion.tt2
new file mode 100644
index 0000000..fc81951
--- /dev/null
+++ b/Open-ILS/web/templates/default/conify/global/config/barcode_completion.tt2
@@ -0,0 +1,26 @@
+[% ctx.page_title = 'Barcode Completion Configuration' %]
+[% WRAPPER default/base.tt2 %]
+<script type="text/javascript" src='[% ctx.media_prefix %]/js/ui/default/conify/global/config/barcode_completion.js'> </script>
+<div dojoType="dijit.layout.ContentPane" layoutAlign="top" class='oils-header-panel'>
+ <div>Barcode Completion Configuration</div>
+ <div><button dojoType='dijit.form.Button' onClick='cmGrid.showCreatePane()'>New</button></div>
+</div>
+<div dojoType="dijit.layout.ContentPane" layoutAlign="client">
+ <table jsId="cmGrid"
+ style="height: 600px;"
+ dojoType="openils.widget.AutoGrid"
+ fieldOrder="['id', 'active', 'org_unit', 'prefix', 'suffix', 'length', 'padding', 'padding_end', 'asset', 'actor']"
+ defaultCellWidth='"auto"'
+ query="{id: '*'}"
+ fmClass='cbc'
+ editStyle='pane'
+ editOnEnter='true'
+ showColumnPicker='true'
+ columnPickerPrefix='"conify.config.barcode_completion"'>
+ </table>
+</div>
+
+<div class='hidden'><div dojoType='openils.widget.ProgressDialog' jsId='progressDialog'/></div>
+
+[% END %]
+
diff --git a/Open-ILS/xul/staff_client/chrome/content/cat/opac.js b/Open-ILS/xul/staff_client/chrome/content/cat/opac.js
index 2fbe422..9684740 100644
--- a/Open-ILS/xul/staff_client/chrome/content/cat/opac.js
+++ b/Open-ILS/xul/staff_client/chrome/content/cat/opac.js
@@ -105,7 +105,8 @@ function set_brief_view() {
["url_prefix", "new_tab", "set_tab", "close_tab", "new_patron_tab",
"set_patron_tab", "volume_item_creator", "get_new_session",
"holdings_maintenance_tab", "open_chrome_window", "url_prefix",
- "network_meter", "page_meter", "set_statusbar", "set_help_context"
+ "network_meter", "page_meter", "set_statusbar", "set_help_context",
+ "get_barcode"
].forEach(function(k) { content_params[k] = xulG[k]; });
top_pane.set_iframe(
@@ -300,7 +301,7 @@ function open_acq_orders() {
"set_patron_tab", "volume_item_creator", "get_new_session",
"holdings_maintenance_tab", "set_tab_name", "open_chrome_window",
"url_prefix", "network_meter", "page_meter", "set_statusbar",
- "set_help_context"
+ "set_help_context", "get_barcode"
].forEach(function(k) { content_params[k] = xulG[k]; });
var loc = urls.XUL_BROWSER + "?url=" + window.escape(
@@ -334,7 +335,7 @@ function open_alt_serial_mgmt() {
"set_patron_tab", "volume_item_creator", "get_new_session",
"holdings_maintenance_tab", "set_tab_name", "open_chrome_window",
"url_prefix", "network_meter", "page_meter", "set_statusbar",
- "set_help_context"
+ "set_help_context", "get_barcode"
].forEach(function(k) { content_params[k] = xulG[k]; });
var loc = urls.XUL_BROWSER + "?url=" + window.escape(
@@ -370,7 +371,8 @@ function set_opac() {
} catch(E) {
g.error.standard_unexpected_error_alert('window_open',E);
}
- }
+ },
+ 'get_barcode' : xulG.get_barcode
},
'on_url_load' : function(f) {
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
@@ -489,6 +491,7 @@ function set_opac() {
content_params.page_meter = xulG.page_meter;
content_params.set_statusbar = xulG.set_statusbar;
content_params.set_help_context = xulG.set_help_context;
+ content_params.get_barcode = xulG.get_barcode;
if (opac_url) { content_params.url = opac_url; } else { content_params.url = xulG.url_prefix( urls.browser ); }
browser_frame = bottom_pane.set_iframe( xulG.url_prefix(urls.XUL_BROWSER) + '?name=Catalog', {}, content_params);
@@ -616,6 +619,7 @@ function bib_in_new_tab() {
content_params.page_meter = xulG.page_meter;
content_params.set_statusbar = xulG.set_statusbar;
content_params.set_help_context = xulG.set_help_context;
+ content_params.get_barcode = xulG.get_barcode;
xulG.new_tab(xulG.url_prefix(urls.XUL_OPAC_WRAPPER), {}, content_params);
} catch(E) {
@@ -631,7 +635,7 @@ function batch_receive_in_new_tab() {
"set_patron_tab", "volume_item_creator", "get_new_session",
"holdings_maintenance_tab", "set_tab_name", "open_chrome_window",
"url_prefix", "network_meter", "page_meter", "set_statusbar",
- "set_help_context"
+ "set_help_context", "get_barcode"
].forEach(function(k) { content_params[k] = xulG[k]; });
xulG.new_tab(
diff --git a/Open-ILS/xul/staff_client/chrome/content/main/constants.js b/Open-ILS/xul/staff_client/chrome/content/main/constants.js
index 56ed059..9961357 100644
--- a/Open-ILS/xul/staff_client/chrome/content/main/constants.js
+++ b/Open-ILS/xul/staff_client/chrome/content/main/constants.js
@@ -357,7 +357,8 @@ var api = {
'RECALCULATE_STANDING_PENALTIES' : { 'app' : 'open-ils.actor', 'method' : 'open-ils.actor.user.penalties.update' },
'USER_ORG_UNIT_OPT_IN_FEATURE' : { 'app' : 'open-ils.actor', 'method' : 'open-ils.actor.user.org_unit_opt_in.enabled' },
'USER_ORG_UNIT_OPT_IN_CHECK' : { 'app' : 'open-ils.actor', 'method' : 'open-ils.actor.user.org_unit_opt_in.check' },
- 'USER_ORG_UNIT_OPT_IN_CREATE' : { 'app' : 'open-ils.actor', 'method' : 'open-ils.actor.user.org_unit_opt_in.create' }
+ 'USER_ORG_UNIT_OPT_IN_CREATE' : { 'app' : 'open-ils.actor', 'method' : 'open-ils.actor.user.org_unit_opt_in.create' },
+ 'GET_BARCODES' : { 'app' : 'open-ils.actor', 'method' : 'open-ils.actor.get_barcodes' }
}
var urls = {
diff --git a/Open-ILS/xul/staff_client/chrome/content/main/menu.js b/Open-ILS/xul/staff_client/chrome/content/main/menu.js
index bc8c11d..47fc718 100644
--- a/Open-ILS/xul/staff_client/chrome/content/main/menu.js
+++ b/Open-ILS/xul/staff_client/chrome/content/main/menu.js
@@ -51,6 +51,8 @@ main.menu.prototype = {
urls.remote = params['server'];
+ xulG.get_barcode = this.get_barcode;
+
// Pull in local customizations
var r = new XMLHttpRequest();
r.open("GET", obj.url_prefix('/xul/server/skin/custom.js'), false);
@@ -762,6 +764,11 @@ main.menu.prototype = {
['oncommand'],
function(event) { open_eg_web_page('conify/global/action/survey', null, event); }
],
+ 'cmd_local_admin_barcode_completion' : [
+ ['oncommand'],
+ function() { open_eg_web_page('conify/global/config/barcode_completion',
+ 'menu.local_admin.barcode_completion.tab'); }
+ ],
'cmd_local_admin_circ_matrix_matchpoint' : [
['oncommand'],
function() { open_eg_web_page('conify/global/config/circ_matrix_matchpoint',
@@ -2046,6 +2053,7 @@ commands:
content_params.url_prefix = function(url) { return obj.url_prefix(url); };
content_params.network_meter = obj.network_meter;
content_params.page_meter = obj.page_meter;
+ content_params.get_barcode = obj.get_barcode;
content_params.set_statusbar = function(slot,text,tooltiptext,click_handler) {
var e = document.getElementById('statusbarpanel'+slot);
if (e) {
@@ -2142,8 +2150,154 @@ commands:
}
return frame;
- }
+ },
+
+ 'get_barcode' : function(window, context, barcode) {
+ JSAN.use('util.network');
+ JSAN.use('util.sound');
+
+ // Depending on where we were called from data can be found in multiple ways
+ var data;
+ if(this.data) data = this.data;
+ else if(xulG.data) data = xulG.data;
+ else {
+ JSAN.use('util.data');
+ data = new util.data();
+ }
+ data.stash_retrieve();
+
+ var network = new util.network();
+ var sound = new util.sound();
+
+ // Should return an array. Or an error.
+ var r = network.simple_request('GET_BARCODES', [ ses(), data.list.au[0].ws_ou(), context, barcode ]);
+
+ if(!r) // Nothing?
+ return false;
+ // Top-level error, likely means bad session or no STAFF_LOGIN permission.
+ if(typeof r.ilsevent != 'undefined') {
+ // Hand it off to the caller.
+ return r;
+ }
+
+ // No results? Return false
+ if(r.length == 0) return false;
+
+ // One result?
+ if(r.length == 1) {
+ // Return it. If it is an error the caller should deal with it.
+ return r[0];
+ }
+
+ // At this point we have more than one result.
+ // Check to see what we got.
+ var result_filter = {};
+ var valid_r = [];
+ var unique_count = 0;
+ var found_errors = false;
+ var errors = '';
+ var len = r.length;
+
+ // Check each result.
+ for(var i = 0; i < len; ++i) {
+ // If it is an error
+ if(typeof r[i].ilsevent != 'undefined') {
+ // Make note that we found errors
+ found_errors = true;
+ // Grab the error into a string
+ errors += js2JSON(r[i]);
+ }
+ else {
+ // Otherwise, record the type/id combo for later
+ var type = r[i].type;
+ var id = r[i].id;
+ var barcode = r[i].barcode;
+ if(!result_filter[type]) result_filter[type] = {};
+ if(!result_filter[type][id]) {
+ unique_count++;
+ result_filter[type][id] = [];
+ }
+ result_filter[type][id].push(barcode);
+ valid_r.push(r[i]);
+ }
+ }
+
+ // Only errors? Return the first one.
+ if(unique_count == 0 && found_errors == true) {
+ return r[0];
+ }
+
+ // No errors, one (unique) result? Return it.
+ if(unique_count == 1 && found_errors == false) return valid_r[0];
+
+ // For possible debugging, dump the errors.
+ if(found_errors) dump(errors);
+
+ // Still here? Must need to have the user pick.
+ if(!xulG.url_prefix) xulG.url_prefix = url_prefix; // Make util.window happy
+ JSAN.use('util.window');
+ var win = new util.window();
+ var url = url_prefix(urls.XUL_FANCY_PROMPT);
+ var title = offlineStrings.getString('barcode_choice.title');
+ var xml = '<vbox xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" xmlns:html="http://www.w3.org/1999/xhtml" flex="1">';
+ xml += '<groupbox flex="1" style="overflow: auto; border: solid thin;"><caption label="' + title + '"/>';
+ xml += '<description style="-moz-user-select: text; -moz-user-focus: normal; font-size: large">' + offlineStrings.getString('barcode_choice.prompt') + '</description>';
+ if(found_errors) // Let the user know that one or more possible answers errored out.
+ xml += '<description style="-moz-user=select: text; -moz-user-focus: normal; font-size: large">' + offlineStrings.getString('barcode_choice.errors_found') + '</description>';
+ xml += '</groupbox><groupbox><caption label="' + offlineStrings.getString('barcode_choice.choice_label') + '"/><vbox>';
+
+ len = valid_r.length;
+ // Look at all the non-error answers we got
+ for(var i = 0; i < len; ++i) {
+ // If we still have a filtered answer, display a button.
+ if(result_filter[valid_r[i].type][valid_r[i].id]) {
+ var result_data = false;
+ var barcodes = result_filter[valid_r[i].type][valid_r[i].id];
+ var barcodes_assembled = barcodes.shift();
+ var button_label = '';
+ while(barcodes.length > 0) // Join any secondary barcodes found together
+ barcodes_assembled = offlineStrings.getFormattedString('barcode_choice.join_barcodes', [barcodes_assembled, barcodes.shift()]);
+ switch(r[i].type) {
+ case 'actor':
+ result_data = network.simple_request('BLOB_AU_PARTS_RETRIEVE',
+ [ ses() , valid_r[i].id, ['family_name', 'first_given_name', 'second_given_name', 'home_ou' ] ]);
+ button_label = offlineStrings.getFormattedString('barcode_choice.actor',
+ [barcodes_assembled, result_data[0], result_data[1] + (result_data[2] ? ' ' + result_data[2] : ''), data.hash.aou[ result_data[3] ].name(), data.hash.aou[ result_data[3] ].shortname()]);
+ break;
+ case 'booking':
+ result_data = network.simple_request('FM_ACP_DETAILS_VIA_BARCODE', [ ses(), valid_r[i].barcode ]);
+ // Note: This falls through intentionally.
+ case 'asset':
+ case 'serial':
+ if(!result_data) // If we fell through this should be set already.
+ result_data = network.simple_request('FM_ACP_DETAILS', [ ses(), valid_r[i].id ]);
+ button_label = offlineStrings.getFormattedString('barcode_choice.asset',
+ [barcodes_assembled, result_data.mvr.title(), data.hash.aou[ result_data.copy.circ_lib() ].name(), data.hash.aou[ result_data.copy.circ_lib() ].shortname()]);
+ break;
+ }
+ r[i].data = result_data;
+
+ // This ensures we only show each unique id once
+ delete result_filter[valid_r[i].type][valid_r[i].id];
+
+ // If we have more than one context this should label each entry with where it came from
+ // Likely most useful for distinguishing assets from bookings
+ if(context != valid_r[i].type && offlineStrings.testString('barcode_choice.' + valid_r[i].type + '_label'))
+ button_label = offlineStrings.getFormattedString('barcode_choice.' + valid_r[i].type + '_label', [button_label]);
+
+ xml += '<button label="' + button_label + '" name="fancy_submit" value="' + i + '"/>';
+ }
+ }
+ xml += '<button label="' + offlineStrings.getString('barcode_choice.none') + '" name="fancy_cancel"/>';
+ xml += '</vbox></groupbox></vbox>';
+ var fancy_prompt_data = win.open( url, 'fancy_prompt', 'chrome,resizable,modal,width=500,height=500', { 'xml' : xml, 'title' : title, 'sound' : 'bad' } );
+ if(fancy_prompt_data.fancy_status == 'complete')
+ return valid_r[fancy_prompt_data.fancy_submit];
+ else
+ // user_false is used to indicate the user said "None of the above" to avoid fall-through erroring later.
+ return "user_false";
+ }
}
dump('exiting main/menu.js\n');
diff --git a/Open-ILS/xul/staff_client/chrome/content/main/menu_frame_menus.xul b/Open-ILS/xul/staff_client/chrome/content/main/menu_frame_menus.xul
index 2dc7cb5..7fb34b1 100644
--- a/Open-ILS/xul/staff_client/chrome/content/main/menu_frame_menus.xul
+++ b/Open-ILS/xul/staff_client/chrome/content/main/menu_frame_menus.xul
@@ -124,6 +124,8 @@
<command id="cmd_local_admin_age_overdue_circulations_to_lost" />
<command id="cmd_local_admin_cash_reports" />
<command id="cmd_local_admin_transit_list" />
+ <command id="cmd_local_admin_barcode_completion"
+ perm="UPDATE_ORG_UNIT_SETTING_ALL" />
<command id="cmd_local_admin_circ_matrix_matchpoint"
perm="ADMIN_CIRC_MATRIX_MATCHPOINT VIEW_CIRC_MATRIX_MATCHPOINT"
/>
@@ -432,6 +434,7 @@
<menupopup id="main.menu.admin.local.popup">
<menuitem command="cmd_local_admin_age_overdue_circulations_to_lost" label="&staff.server.admin.index.age_overdue_circulations_to_lost.label;" accesskey="&staff.server.admin.index.age_overdue_circulations_to_lost.accesskey;"/>
<menuitem label="&staff.server.admin.index.cash_reports;" command="cmd_local_admin_cash_reports"/>
+ <menuitem label="&staff.main.menu.admin.local_admin.barcode_completion.label;" command="cmd_local_admin_barcode_completion"/>
<menuitem label="&staff.main.menu.admin.local_admin.circ_matrix_matchpoint.label;" command="cmd_local_admin_circ_matrix_matchpoint"/>
<menuitem label="&staff.server.admin.index.closed_dates;" command="cmd_local_admin_closed_dates"/>
<menuitem label="&staff.server.admin.index.copy_locations;" command="cmd_local_admin_copy_locations"/>
diff --git a/Open-ILS/xul/staff_client/chrome/locale/en-US/offline.properties b/Open-ILS/xul/staff_client/chrome/locale/en-US/offline.properties
index 06452b0..26bf180 100644
--- a/Open-ILS/xul/staff_client/chrome/locale/en-US/offline.properties
+++ b/Open-ILS/xul/staff_client/chrome/locale/en-US/offline.properties
@@ -250,6 +250,7 @@ menu.cmd_booking_reservation_pickup.tab=Reservation Pickup
menu.cmd_booking_reservation_return.tab=Reservation Return
menu.cmd_booking_pull_list.tab=Booking Pull List
menu.cmd_booking_capture.tab=Booking Capture
+menu.local_admin.barcode_completion.tab=Barcode Completion
menu.local_admin.circ_matrix_matchpoint.tab=Circulation Policies
menu.local_admin.hold_matrix_matchpoint.tab=Hold Policies
menu.local_admin.work_log.tab=Work Log
@@ -297,3 +298,15 @@ menu.logoff.unsaved_data_warning=This session may have unsaved data. Logoff anyw
menu.shutdown.unsaved_data_warning=This application may have unsaved data. Exit it anyway?
hotkeys.Default=Default
hotkeys.None=No Hotkeys
+barcode_choice.join_barcodes=%1$s / %2$s
+barcode_choice.actor=%1$s : %2$s, %3$s from %4$s (%5$s)
+barcode_choice.asset=%1$s : %2$s from %3$s (%4$s)
+barcode_choice.none=None of the above
+barcode_choice.prompt=After auto completion multiple barcodes may match your input. Please choose the barcode you intended below.
+barcode_choice.errors_found=In addition to the options below, one or more errors were encountered on items not shown.
+barcode_choice.title=Barcode Choice
+barcode_choice.choice_label=Found Barcodes:
+barcode_choice.actor_label=Patron : %1$s
+barcode_choice.asset_label=Item : %1$s
+barcode_choice.serial_label=Serial : %1$s
+barcode_choice.booking_label=Booking : %1$s
diff --git a/Open-ILS/xul/staff_client/server/circ/checkin.js b/Open-ILS/xul/staff_client/server/circ/checkin.js
index 9a36d7e..75c1edb 100644
--- a/Open-ILS/xul/staff_client/server/circ/checkin.js
+++ b/Open-ILS/xul/staff_client/server/circ/checkin.js
@@ -509,13 +509,17 @@ circ.checkin.prototype = {
var async_checkbox = document.getElementById('async_checkin');
if (async_checkbox) { async = async_checkbox.getAttribute('checked') == 'true'; }
var barcode = textbox.value;
+ // Auto-complete the barcode, items only
+ var barcode_object = xulG.get_barcode(window, 'asset', barcode);
if (async) {
textbox.value = ''; textbox.focus();
}
- if (!barcode) return;
- if (barcode) {
- if ( obj.test_barcode(barcode) ) { /* good */ } else { /* bad */ return; }
- }
+ // user_false means the user selected "None of the above", abort before other prompts/errors
+ if(barcode_object == "user_false") return;
+ // Got a barcode without an error? Use it. Otherwise fall through.
+ if(barcode_object && typeof barcode_object.ilsevent == 'undefined')
+ barcode = barcode_object.barcode;
+ if ( obj.test_barcode(barcode) ) { /* good */ } else { /* bad */ return; }
var placeholder_item = new acp();
placeholder_item.barcode( barcode );
var row_params = obj.list.append( {
diff --git a/Open-ILS/xul/staff_client/server/circ/checkout.js b/Open-ILS/xul/staff_client/server/circ/checkout.js
index 4227858..c7d3813 100644
--- a/Open-ILS/xul/staff_client/server/circ/checkout.js
+++ b/Open-ILS/xul/staff_client/server/circ/checkout.js
@@ -589,6 +589,27 @@ circ.checkout.prototype = {
if (! (params.barcode||params.noncat)) { return; }
if (params.barcode) {
+ // Default is "just items"
+ var barcode_context = 'asset';
+ // Add actor (can be any string that includes 'actor') if looking up patrons at checkout
+ if(String( obj.data.hash.aous['circ.staff_client.actor_on_checkout'] ) == 'true')
+ barcode_context += '-actor';
+ // Auto-complete the barcode
+ var in_barcode = xulG.get_barcode(window, barcode_context, params.barcode);
+ // user_false is "None of the above selected", don't error out/fall through as they already said no
+ if(in_barcode == "user_false") return;
+ // We have a barcode and there was no error?
+ if(in_barcode && typeof in_barcode.ilsevent == 'undefined') {
+ // Check if it was an actor barcode (will never happen unless actor was added above)
+ if(in_barcode.type == 'actor') {
+ // Go to new patron (do not pass go, do not collect $200, do not prompt user)
+ var horizontal_interface = String( obj.data.hash.aous['ui.circ.patron_summary.horizontal'] ) == 'true';
+ var loc = xulG.url_prefix( horizontal_interface ? urls.XUL_PATRON_HORIZ_DISPLAY : urls.XUL_PATRON_DISPLAY );
+ xulG.set_tab( loc, {}, { 'barcode' : in_barcode.barcode } );
+ return;
+ }
+ params.barcode = in_barcode.barcode;
+ }
if ( obj.test_barcode(params.barcode) ) { /* good */ } else { /* bad */ return; }
diff --git a/Open-ILS/xul/staff_client/server/circ/copy_status.js b/Open-ILS/xul/staff_client/server/circ/copy_status.js
index bff79af..ca91ad2 100644
--- a/Open-ILS/xul/staff_client/server/circ/copy_status.js
+++ b/Open-ILS/xul/staff_client/server/circ/copy_status.js
@@ -1049,7 +1049,15 @@ circ.copy_status.prototype = {
try {
try { document.getElementById('last_scanned').setAttribute('value',''); } catch(E) {}
if (!barcode) {
+ // No barcode provided = get barcode
barcode = obj.controller.view.copy_status_barcode_entry_textbox.value;
+ // Complete the barcode - just items
+ var barcode_object = xulG.get_barcode(window, 'asset', barcode);
+ // user_false is user said "None of the above" - Abort before other errors/prompts can result
+ if(barcode_object == "user_false") return;
+ // Got a barcode and no error? Use the barcode. Otherwise, fall through with entered barcode.
+ if(barcode_object && typeof barcode_object.ilsevent == 'undefined')
+ barcode = barcode_object.barcode;
}
if (!barcode) { return; }
if (barcode) {
diff --git a/Open-ILS/xul/staff_client/server/patron/barcode_entry.xul b/Open-ILS/xul/staff_client/server/patron/barcode_entry.xul
index 0de36de..557995a 100644
--- a/Open-ILS/xul/staff_client/server/patron/barcode_entry.xul
+++ b/Open-ILS/xul/staff_client/server/patron/barcode_entry.xul
@@ -93,60 +93,65 @@
tb.disabled = true;
document.getElementById('progress').setAttribute('hidden','false');
- net.simple_request('FM_AU_ID_RETRIEVE_VIA_BARCODE_OR_USERNAME',[ ses(), barcode, null ],
- function(req) {
- document.getElementById('progress').setAttribute('hidden','true');
- tb.disabled = false; tb.select(); tb.focus(); ;
- var robj = req.getResultObject();
- if (typeof robj.ilsevent != 'undefined') {
- sound.bad();
- switch(Number(robj.ilsevent)) {
- case 1002 /* ACTOR_USER_NOT_FOUND */:
- add_msg($("patronStrings").getFormattedString('staff.patron.barcode_entry.barcode_not_found', [barcode]));
- break;
- default:
- add_msg($("patronStrings").getFormattedString('staff.patron.barcode_entry.barcode_retrieval_problem', [barcode, js2JSON(robj)]));
- }
- return;
- }
+ // Auto-complete the barcode, users only. Handily, looks up all we need to know in the process.
+ var barcode_object = xulG.get_barcode(window, 'actor', barcode);
+ document.getElementById('progress').setAttribute('hidden','true');
+ tb.disabled = false; tb.select(); tb.focus(); ;
+ // user_false means the user said "None of the above", so abort without further prompts/actions
+ if(barcode_object == "user_false") return;
+ if(barcode_object == false) {
+ // Boolean false means the barcode was not found, and the user wasn't prompted.
+ sound.bad();
+ add_msg($("patronStrings").getFormattedString('staff.patron.barcode_entry.barcode_not_found', [barcode]));
+ return;
+ }
+ else if(typeof barcode_object.ilsevent != 'undefined') {
+ // Getting an ilsevent error otherwise means something, likely permissions issues, went wrong
+ sound.bad();
+ add_msg($("patronStrings").getFormattedString('staff.patron.barcode_entry.barcode_retrieval_problem', [barcode, js2JSON(barcode_object)]));
+ return;
+ }
- if (g.data.user_org_unit_opt_in_enabled) {
- var r = net.simple_request('USER_ORG_UNIT_OPT_IN_CHECK',[ ses(), robj ]);
- if (typeof r.ilsevent != 'undefined') {
- throw(r);
- } else {
+ if (g.data.user_org_unit_opt_in_enabled) {
+ var r = net.simple_request('USER_ORG_UNIT_OPT_IN_CHECK',[ ses(), barcode_object.id ]);
+ if (typeof r.ilsevent != 'undefined') {
+ throw(r);
+ } else {
- if (r == 0) {
+ if (r == 0) {
- JSAN.use('patron.util');
- var parts = patron.util.retrieve_name_via_id( ses(), robj );
+ JSAN.use('patron.util');
+ var parts;
+ // Handily, if the user was prompted, we should already have the user's name information returned from autocomplete
+ // Use it if there, as it saves us a network call.
+ if(barcode_object.request_data) parts = barcode_object.request_data;
+ // Otherwise, make the network call
+ else parts = patron.util.retrieve_name_via_id( ses(), barcode_object.id );
- if (0 != g.error.yns_alert(
- $("patronStrings").getFormattedString('staff.patron.barcode_entry.consent_from_patron',
- [parts[0], parts[1] + (parts[2] ? ' ' + parts[2] : ''), g.data.hash.aou[ parts[3] ].name(), g.data.hash.aou[ parts[3] ].shortname()]),
- $("patronStrings").getString('staff.patron.barcode_entry.patron_consent_title'),
- $("patronStrings").getString('staff.patron.barcode_entry.patron_consent_accept'),
- $("patronStrings").getString('staff.patron.barcode_entry.patron_consent_deny'), null,
- $("patronStrings").getString('staff.patron.barcode_entry.patron_consent_confirm')
- )
- ) {
- tb.select(); tb.focus();
- return;
- } else {
- var c = net.simple_request('USER_ORG_UNIT_OPT_IN_CREATE',[ ses(), robj ]);
- if (typeof c.ilsevent != 'undefined') throw(r);
- }
- }
-
- sound.good();
- spawn(barcode);
+ if (0 != g.error.yns_alert(
+ $("patronStrings").getFormattedString('staff.patron.barcode_entry.consent_from_patron',
+ [parts[0], parts[1] + (parts[2] ? ' ' + parts[2] : ''), g.data.hash.aou[ parts[3] ].name(), g.data.hash.aou[ parts[3] ].shortname()]),
+ $("patronStrings").getString('staff.patron.barcode_entry.patron_consent_title'),
+ $("patronStrings").getString('staff.patron.barcode_entry.patron_consent_accept'),
+ $("patronStrings").getString('staff.patron.barcode_entry.patron_consent_deny'), null,
+ $("patronStrings").getString('staff.patron.barcode_entry.patron_consent_confirm')
+ )
+ ) {
+ tb.select(); tb.focus();
+ return;
+ } else {
+ var c = net.simple_request('USER_ORG_UNIT_OPT_IN_CREATE',[ ses(), barcode_object.id ]);
+ if (typeof c.ilsevent != 'undefined') throw(r);
}
- } else {
- sound.good();
- spawn(barcode);
}
+
+ sound.good();
+ spawn(barcode_object.id, barcode_object.barcode);
}
- );
+ } else {
+ sound.good();
+ spawn(barcode_object.id, barcode_object.barcode);
+ }
} catch(E) {
tb.select(); tb.focus();
g.error.standard_unexpected_error_alert('barcode_entry.xul',E);
@@ -161,8 +166,8 @@
d.setAttribute('style','color: red');
}
- function spawn(barcode) {
- if (xul_param('perm_editor')) { spawn_perm_editor(barcode); } else { spawn_checkout(barcode); }
+ function spawn(id, barcode) {
+ if (xul_param('perm_editor')) { spawn_perm_editor(id); } else { spawn_checkout(barcode); }
}
function spawn_checkout(barcode) {
@@ -179,10 +184,9 @@
}
}
- function spawn_perm_editor(barcode) {
+ function spawn_perm_editor(id) {
try {
- JSAN.use('patron.util'); var patron_obj = patron.util.retrieve_fleshed_au_via_barcode( ses(), barcode );
- var loc = urls.XUL_USER_PERM_EDITOR + '?ses=' + window.escape(ses()) + '&usr=' + patron_obj.id();
+ var loc = urls.XUL_USER_PERM_EDITOR + '?ses=' + window.escape(ses()) + '&usr=' + id;
if (typeof window.xulG == 'object' && typeof window.xulG.set_tab == 'function') {
window.xulG.set_tab( loc, {}, {} );
} else {
diff --git a/Open-ILS/xul/staff_client/server/patron/display.js b/Open-ILS/xul/staff_client/server/patron/display.js
index 0f7f9ac..f927512 100644
--- a/Open-ILS/xul/staff_client/server/patron/display.js
+++ b/Open-ILS/xul/staff_client/server/patron/display.js
@@ -831,7 +831,9 @@ patron.display.prototype = {
}
)
}
- }
+ },
+ 'get_barcode' : xulG.get_barcode,
+ 'url_prefix' : xulG.url_prefix
}
);
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
-----------------------------------------------------------------------
Summary of changes:
Open-ILS/examples/fm_IDL.xml | 25 +++
.../src/perlmods/lib/OpenILS/Application/Actor.pm | 49 ++++++
Open-ILS/src/sql/Pg/002.schema.config.sql | 17 ++-
Open-ILS/src/sql/Pg/020.schema.functions.sql | 89 +++++++++++
Open-ILS/src/sql/Pg/800.fkeys.sql | 2 +
Open-ILS/src/sql/Pg/950.data.seed-values.sql | 5 +
.../0536.schema.lazy_circ-barcode_lookup.sql | 117 +++++++++++++++
.../conify/global/config/barcode_completion.js | 15 ++
Open-ILS/web/opac/locale/en-US/lang.dtd | 1 +
Open-ILS/web/opac/skin/default/js/holds.js | 19 +++-
.../conify/global/config/barcode_completion.tt2 | 26 ++++
.../xul/staff_client/chrome/content/cat/opac.js | 14 +-
.../staff_client/chrome/content/main/constants.js | 3 +-
.../xul/staff_client/chrome/content/main/menu.js | 156 +++++++++++++++++++-
.../chrome/content/main/menu_frame_menus.xul | 3 +
.../chrome/locale/en-US/offline.properties | 13 ++
Open-ILS/xul/staff_client/server/circ/checkin.js | 12 +-
Open-ILS/xul/staff_client/server/circ/checkout.js | 21 +++
.../xul/staff_client/server/circ/copy_status.js | 8 +
.../staff_client/server/patron/barcode_entry.xul | 108 +++++++-------
Open-ILS/xul/staff_client/server/patron/display.js | 4 +-
21 files changed, 641 insertions(+), 66 deletions(-)
create mode 100644 Open-ILS/src/sql/Pg/upgrade/0536.schema.lazy_circ-barcode_lookup.sql
create mode 100644 Open-ILS/web/js/ui/default/conify/global/config/barcode_completion.js
create mode 100644 Open-ILS/web/templates/default/conify/global/config/barcode_completion.tt2
hooks/post-receive
--
Evergreen ILS
More information about the open-ils-commits
mailing list