[open-ils-commits] [GIT] Evergreen ILS branch master updated. 3fc982940370c3123ca8af637775cd7958532c00

Evergreen Git git at git.evergreen-ils.org
Mon Mar 19 11:16:12 EDT 2012


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  3fc982940370c3123ca8af637775cd7958532c00 (commit)
       via  6d647953b58410f2c81631a7649b994aeb331c78 (commit)
       via  c4adaa799de5ca2adb1aaf35fe54db9f9fd59598 (commit)
       via  ae3d839360b76c0eebb6aa0be028857390c229f6 (commit)
       via  78b597ef43fc087b35901f8d7e46f723b9ad796c (commit)
       via  919ed841c147e89fa45d8cf940ff06f21b34475d (commit)
       via  07041e84572200111e28795ac10247ace36dc712 (commit)
       via  6d9dd49bd16f2181e07bef95f73fb09d891be9b6 (commit)
       via  51334478294eec5bddfde4b7e83a858dc98e4f6d (commit)
       via  349e7ed4608dd9cbf3b836867b743139e9e9dd1c (commit)
       via  bf43e8670e2971d96888fb4e57fc64b47ee46c74 (commit)
       via  1ec10b00946dd331742d04bba676dc0a640325ea (commit)
       via  0a5fa7ee518678a0e576001ff76f3763560f7ad0 (commit)
       via  21af7aa110578896b9c40e10b8c9a4f86cf52e95 (commit)
       via  49517bdf0da4502c626e7e28b2240bf42a782dc7 (commit)
       via  4d0050739339b0b26dc85b982d068e8e225170a9 (commit)
       via  02da33f95b81c806b656a7759dd14a421a03cbdf (commit)
       via  23b04db5a14931a395fc505be061c1c8a7784c68 (commit)
       via  e65acab943a624c57673cd2b80ea483c63ed934b (commit)
       via  12757f3d4e0767e9d23bf2c4172553360f0842cd (commit)
       via  845c858bcdd2dfb6df33239f90af990f5d219a93 (commit)
       via  468ee3248766650d468b4ff629e0a06f54ce4dd5 (commit)
       via  c8b172c0ebaa2434b70b996edfdf7b2271d19622 (commit)
      from  a01c7230dd455189b791c258a13f36c77cacbaaf (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 3fc982940370c3123ca8af637775cd7958532c00
Author: Mike Rylander <mrylander at gmail.com>
Date:   Mon Mar 19 11:21:49 2012 -0400

    Stamping upgrade script for ACQ/Vandelay integration branch
    
    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 6c5851f..c2fee1c 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 ('0683', :eg_version); -- tsbere/berick
+INSERT INTO config.upgrade_log (version, applied_to) VALUES ('0684', :eg_version); -- berick/miker
 
 CREATE TABLE config.bib_source (
 	id		SERIAL	PRIMARY KEY,
diff --git a/Open-ILS/src/sql/Pg/upgrade/XXXX.schema.acq-vandelay-integration.sql b/Open-ILS/src/sql/Pg/upgrade/0684.schema.acq-vandelay-integration.sql
similarity index 96%
rename from Open-ILS/src/sql/Pg/upgrade/XXXX.schema.acq-vandelay-integration.sql
rename to Open-ILS/src/sql/Pg/upgrade/0684.schema.acq-vandelay-integration.sql
index f5ce14e..b2ca16d 100644
--- a/Open-ILS/src/sql/Pg/upgrade/XXXX.schema.acq-vandelay-integration.sql
+++ b/Open-ILS/src/sql/Pg/upgrade/0684.schema.acq-vandelay-integration.sql
@@ -1,8 +1,8 @@
--- Evergreen DB patch XXXX.schema.acq-vandelay-integration.sql
+-- Evergreen DB patch 0684.schema.acq-vandelay-integration.sql
 BEGIN;
 
 -- check whether patch can be applied
-SELECT evergreen.upgrade_deps_block_check('XXXX', :eg_version);
+SELECT evergreen.upgrade_deps_block_check('0684', :eg_version);
 
 -- schema --
 

commit 6d647953b58410f2c81631a7649b994aeb331c78
Merge: a01c723 c4adaa7
Author: Mike Rylander <mrylander at gmail.com>
Date:   Mon Mar 19 11:15:24 2012 -0400

    Vandelay-based record matching and import for Acquisitions
    
    From the Lauchpad description:
    
    In its current form, Acquisitions record importing is inflexible and
    unforgiving. The user is given practically no control over how inbound
    records match against existing records nor how to deal with record
    collisions. This proposal attempts to resolve this problem by leveraging
    Vandelay for matching, merging, overlaying, and importing acquisitions
    records.
    
    Suggested work flow:
    
    1. Any time an ACQ record should be loaded into the catalog or simply
       linked to an existing catalog record, the user is presented with an
       additional set of Vandelay upload options to control the matching and
       import behavior. This would include the vendor file upload UI, PO
       activation, and PO "Load Bibs and Items". The Vandelay options would
       include the full set of Match Sets, Merge Profiles, import options, etc.
       the user normally has.
    
    2. Once options are selected and, when applicable, the MARC file is uploaded,
       the acquisitions records are added to a new type of ACQ Vandelay queue and
       processed like any other Vandelay records.
    
    3. Vandelay will be taught to recognize ACQ records and update the lineitems
       to reflect any imported/linked catalog records.
    
    4. Any records that fail to import will be available for manual inspection
       within the Vandelay interface an can be re-imported from there.
    
    Signed-off-by: Mike Rylander <mrylander at gmail.com>


commit c4adaa799de5ca2adb1aaf35fe54db9f9fd59598
Author: Bill Erickson <berick at esilibrary.com>
Date:   Wed Feb 29 18:12:41 2012 -0500

    Acq+Vandelay : minor label change
    
    Replace "View Upload Queue" with "View Import Queue", which is less
    technically specific (in a good way).
    
    Signed-off-by: Bill Erickson <berick at esilibrary.com>
    Signed-off-by: Ben Shum <bshum at biblio.org>

diff --git a/Open-ILS/src/templates/acq/picklist/upload.tt2 b/Open-ILS/src/templates/acq/picklist/upload.tt2
index da9d8dc..fcd79cd 100644
--- a/Open-ILS/src/templates/acq/picklist/upload.tt2
+++ b/Open-ILS/src/templates/acq/picklist/upload.tt2
@@ -59,7 +59,7 @@
             <div>Upload Complete!</div><br/>
             <div><a id='acq-pl-upload-complete-po'>[% l('View Purchase Order') %]</a></div><br/>
             <div><a id='acq-pl-upload-complete-pl'>[% l('View Selection List') %]</a></div><br/>
-            <div><a id='acq-pl-upload-complete-q'>[% l('View Upload Queue') %]</a></div><br/>
+            <div><a id='acq-pl-upload-complete-q'>[% l('View Import Queue') %]</a></div><br/>
         </div>
     </div>
 </form>

commit ae3d839360b76c0eebb6aa0be028857390c229f6
Author: Bill Erickson <berick at esilibrary.com>
Date:   Wed Feb 29 18:06:21 2012 -0500

    Acq+Vandelay : consistent post-upload link names
    
    For consistency with POs and selection lists, label the newly created
    Vandelay queue link as "View Upload Queue" instead of showing the queue
    name.  While we're in there, let's i18n-ize those 3 labels.
    
    Signed-off-by: Bill Erickson <berick at esilibrary.com>
    Signed-off-by: Ben Shum <bshum at biblio.org>

diff --git a/Open-ILS/src/templates/acq/picklist/upload.tt2 b/Open-ILS/src/templates/acq/picklist/upload.tt2
index fc03106..da9d8dc 100644
--- a/Open-ILS/src/templates/acq/picklist/upload.tt2
+++ b/Open-ILS/src/templates/acq/picklist/upload.tt2
@@ -57,9 +57,9 @@
         [% PROCESS vlagent_results %]
         <div id='acq-pl-upload-complete' class='hidden'>
             <div>Upload Complete!</div><br/>
-            <div><a id='acq-pl-upload-complete-po'>View Purchase Order</a></div><br/>
-            <div><a id='acq-pl-upload-complete-pl'>View Selection List</a></div><br/>
-            <div><a id='acq-pl-upload-complete-q'></a></div><br/>
+            <div><a id='acq-pl-upload-complete-po'>[% l('View Purchase Order') %]</a></div><br/>
+            <div><a id='acq-pl-upload-complete-pl'>[% l('View Selection List') %]</a></div><br/>
+            <div><a id='acq-pl-upload-complete-q'>[% l('View Upload Queue') %]</a></div><br/>
         </div>
     </div>
 </form>
diff --git a/Open-ILS/web/js/ui/default/acq/picklist/upload.js b/Open-ILS/web/js/ui/default/acq/picklist/upload.js
index 27f448f..1a6653a 100644
--- a/Open-ILS/web/js/ui/default/acq/picklist/upload.js
+++ b/Open-ILS/web/js/ui/default/acq/picklist/upload.js
@@ -152,7 +152,7 @@ function acqHandlePostUpload(key, plId) {
                         }
 
                         if (res.queue_url) {
-                            activateLink('acq-pl-upload-complete-q', res.queue_url, resp.queue.name());
+                            activateLink('acq-pl-upload-complete-q', res.queue_url);
                         }
                     }
                 );

commit 78b597ef43fc087b35901f8d7e46f723b9ad796c
Author: Bill Erickson <berick at esilibrary.com>
Date:   Wed Feb 29 18:03:08 2012 -0500

    Acq+Vandelay: post-upload links open in embedded browser
    
    This change causes the picklist, PO, and queue links which appear after
    a vendor file upload to open their respective pages with the xul browser
    wrapper.  Without this, the existing page CSS is ignored and everything,
    including href's, are grey and washed out.
    
    Signed-off-by: Bill Erickson <berick at esilibrary.com>
    Signed-off-by: Ben Shum <bshum at biblio.org>

diff --git a/Open-ILS/web/js/dojo/openils/XUL.js b/Open-ILS/web/js/dojo/openils/XUL.js
index 9d93f2e..6bf2c3b 100644
--- a/Open-ILS/web/js/dojo/openils/XUL.js
+++ b/Open-ILS/web/js/dojo/openils/XUL.js
@@ -57,7 +57,7 @@ if(!dojo._hasResource["openils.XUL"]) {
         var loc = xulG.url_prefix(url);
 
         if (wrap_in_browser) {
-            loc = urls.XUL_BROWSER + "?url=" + window.escape(loc);
+            loc = xulG.urls.XUL_BROWSER + "?url=" + window.escape(loc);
             content_params = dojo.mixin(
                 {
                     "no_xulG": false, "show_print_button": true,
diff --git a/Open-ILS/web/js/ui/default/acq/picklist/upload.js b/Open-ILS/web/js/ui/default/acq/picklist/upload.js
index c6b83d5..27f448f 100644
--- a/Open-ILS/web/js/ui/default/acq/picklist/upload.js
+++ b/Open-ILS/web/js/ui/default/acq/picklist/upload.js
@@ -131,7 +131,7 @@ function acqHandlePostUpload(key, plId) {
                                 link.setAttribute('href', url); 
                             } else {
                                 link.setAttribute('href', 'javascript:;'); // for linky-ness
-                                link.onclick = function() { openils.XUL.newTabEasy(url) };
+                                link.onclick = function() { openils.XUL.newTabEasy(url, null, null, true) };
                             }
                         }
                             

commit 919ed841c147e89fa45d8cf940ff06f21b34475d
Author: Bill Erickson <berick at esilibrary.com>
Date:   Wed Feb 29 17:34:14 2012 -0500

    Acq+Vandelay : skip unneeded vandeley forms
    
    If all lineitems in question are linked to catalog records, avoid
    showing the unnecessary vandelay form.  This was already true from the
    PO activation action, but this patch adds the same check to the
    create-po action from a selection list and PO 'load bibs and items'.
    
    Minor label change for consistency in li_table (Queue -> queue).
    
    Signed-off-by: Bill Erickson <berick at esilibrary.com>
    Signed-off-by: Ben Shum <bshum at biblio.org>

diff --git a/Open-ILS/src/templates/acq/common/li_table.tt2 b/Open-ILS/src/templates/acq/common/li_table.tt2
index 3a23351..3628b88 100644
--- a/Open-ILS/src/templates/acq/common/li_table.tt2
+++ b/Open-ILS/src/templates/acq/common/li_table.tt2
@@ -108,7 +108,7 @@
                                         <span name='po' class='hidden'> | <a title='Purchase Order' name='po_link' href='javascript:void(0);'>&#x2318; </a></span>
                                         <span name="show_requests"> | <a title='Patron Requests' name="show_requests_link" href="javascript:void(0);">requests</a></span> 
                                         <span name='pro' class='hidden'> | <a title='[% l('Provider') %]' name='pro_link' href='javascript:void(0);'>&#x235F; </a></span>
-                                        <span name='queue' class='hidden'> | <a title='[% l('Import Queue') %]' name='queue_link' href='javascript:void(0);'>&#x27AC; Queue</a></span>
+                                        <span name='queue' class='hidden'> | <a title='[% l('Import Queue') %]' name='queue_link' href='javascript:void(0);'>[% l('&#x27AC; queue') %]</a></span>
                                     </td>
                                 </tr>
                             </tbody>
diff --git a/Open-ILS/web/js/ui/default/acq/common/li_table.js b/Open-ILS/web/js/ui/default/acq/common/li_table.js
index f2585a1..860f82a 100644
--- a/Open-ILS/web/js/ui/default/acq/common/li_table.js
+++ b/Open-ILS/web/js/ui/default/acq/common/li_table.js
@@ -2124,21 +2124,40 @@ function AcqLiTable() {
 
     this.showAssetCreator = function(onAssetsCreated) {
         if(!this.isPO) return;
-        this.show('asset-creator');
-        if(!this.vlAgent.loaded)
-            this.vlAgent.init();
         var self = this;
-        dojo.connect(assetCreatorButton, 'onClick', 
-            function() { self.createAssets(onAssetsCreated) });
+    
+        // first, let's see if this PO has any LI's that need to be merged/imported
+        self.pcrud.search('jub', {purchase_order : this.isPO, eg_bib_id : null}, {
+            id_list : true,
+            oncomplete : function(r) {
+                var resp = openils.Util.readResponse(r);
+                if (resp && resp.length) {
+                    // PO has some non-linked jubs.  
+                    
+                    self.show('asset-creator');
+                    if(!self.vlAgent.loaded)
+                        self.vlAgent.init();
+
+                    dojo.connect(assetCreatorButton, 'onClick', 
+                        function() { self.createAssets(onAssetsCreated) });
+
+                } else {
+
+                    // all jubs linked, move on to asset creation
+                    self.createAssets(onAssetsCreated, true); 
+                }
+            }
+        });
     }
 
-    this.createAssets = function(onAssetsCreated) {
+    this.createAssets = function(onAssetsCreated, noVl) {
         this.show('acq-lit-progress-numbers');
         var self = this;
+        var vlArgs = (noVl) ? {} : {vandelay : this.vlAgent.values()};
         fieldmapper.standardRequest(
             ['open-ils.acq', 'open-ils.acq.purchase_order.assets.create'],
             {   async: true,
-                params: [this.authtoken, this.isPO, {vandelay : this.vlAgent.values()}],
+                params: [this.authtoken, this.isPO, vlArgs],
                 onresponse: function(r) {
                     var resp = openils.Util.readResponse(r);
                     self._updateProgressNumbers(resp, !Boolean(onAssetsCreated), onAssetsCreated);
diff --git a/Open-ILS/web/js/ui/default/acq/po/view_po.js b/Open-ILS/web/js/ui/default/acq/po/view_po.js
index 6c08ce1..07c29e7 100644
--- a/Open-ILS/web/js/ui/default/acq/po/view_po.js
+++ b/Open-ILS/web/js/ui/default/acq/po/view_po.js
@@ -513,19 +513,7 @@ function activatePo() {
             return false;
     }
 
-    // first, let's see if this PO has any LI's that need to be merged/imported
-    pcrud.search('jub', {purchase_order : poId, eg_bib_id : null}, {
-        id_list : true,
-        oncomplete : function(r) {
-            var resp = openils.Util.readResponse(r);
-            if (resp && resp.length) {
-                // kick off the merge/import process
-                liTable.showAssetCreator(activatePoStage2);
-            } else {
-                activatePoStage2();
-            }
-        }
-    });
+    liTable.showAssetCreator(activatePoStage2);
 }
 
 function activatePoStage2() {

commit 07041e84572200111e28795ac10247ace36dc712
Author: Bill Erickson <berick at esilibrary.com>
Date:   Wed Feb 29 16:06:55 2012 -0500

    Acq + Vandelay : exit early for 'load bibs and items' in picklist
    
    The ACQ UI does not support loading bibs and items directly from the
    picklist interface.  If the user selects "load bibs and items" from the
    picklist page they will be presented with the vandelay options, but the
    actual upload/merge/etc will not do anything.  This change prevents the
    vandelay options from showing in this case.
    
    Signed-off-by: Bill Erickson <berick at esilibrary.com>
    Signed-off-by: Ben Shum <bshum at biblio.org>

diff --git a/Open-ILS/web/js/ui/default/acq/common/li_table.js b/Open-ILS/web/js/ui/default/acq/common/li_table.js
index fc7e2e6..f2585a1 100644
--- a/Open-ILS/web/js/ui/default/acq/common/li_table.js
+++ b/Open-ILS/web/js/ui/default/acq/common/li_table.js
@@ -2123,6 +2123,7 @@ function AcqLiTable() {
     };
 
     this.showAssetCreator = function(onAssetsCreated) {
+        if(!this.isPO) return;
         this.show('asset-creator');
         if(!this.vlAgent.loaded)
             this.vlAgent.init();
@@ -2132,7 +2133,6 @@ function AcqLiTable() {
     }
 
     this.createAssets = function(onAssetsCreated) {
-        if(!this.isPO) return;
         this.show('acq-lit-progress-numbers');
         var self = this;
         fieldmapper.standardRequest(

commit 6d9dd49bd16f2181e07bef95f73fb09d891be9b6
Author: Bill Erickson <berick at esilibrary.com>
Date:   Tue Feb 21 10:56:38 2012 -0500

    Acq+Vandelay : more aggressive streamed response throttling
    
    With the addition of Vandelay processing, the server now wants to
    respond with status information a lot more often when uploading /
    process ACQ records.  This patch applies the level of throttling to ACQ
    processing as Vandelay uses natively, which starts verbose and quickly
    cuts back on chatter as processing continues up to (currently) a
    throttle window of 1 delivered response per 256 responses.  Apart from
    saving bandwith, this helps alleviate a known problem in the staff
    client where long-running, dense streams of multipart responses
    eventually stop bubbling up from the browser to the application.
    Making the responses more sparse seems to help this a lot.
    
    Signed-off-by: Bill Erickson <berick at esilibrary.com>
    Signed-off-by: Ben Shum <bshum at biblio.org>

diff --git a/Open-ILS/src/perlmods/lib/OpenILS/Application/Acq/Order.pm b/Open-ILS/src/perlmods/lib/OpenILS/Application/Acq/Order.pm
index 9b4b71f..8a754f0 100644
--- a/Open-ILS/src/perlmods/lib/OpenILS/Application/Acq/Order.pm
+++ b/Open-ILS/src/perlmods/lib/OpenILS/Application/Acq/Order.pm
@@ -23,7 +23,7 @@ sub new {
         total => 0
     };
     $self->{cache} = {};
-    $self->throttle(5) unless $self->throttle;
+    $self->throttle(4) unless $self->throttle;
     $self->{post_proc_queue} = [];
     $self->{last_respond_progress} = 0;
     return $self;
@@ -48,6 +48,7 @@ sub respond {
     }
     $self->conn->respond({ %{$self->{args}}, %other_args });
     $self->{last_respond_progress} = $self->{args}->{progress};
+    $self->throttle($self->throttle * 2) unless $self->throttle >= 256;
 }
 sub respond_complete {
     my($self, %other_args) = @_;

commit 51334478294eec5bddfde4b7e83a858dc98e4f6d
Author: Bill Erickson <berick at esilibrary.com>
Date:   Tue Feb 14 11:29:30 2012 -0500

    Acq+Vandelay avoid premature asset creation
    
    The presence of Vandelay parameters in API calls does not mean the user
    necessarily wants to create PO assets (real copies/callnumbers).  That's
    controlled by a different, existing API parameter.  This adds support
    for processing bib data only in the presence of Vandelay parameters when
    the user has not explicitly chosen to create assets.
    
    Signed-off-by: Bill Erickson <berick at esilibrary.com>
    Signed-off-by: Ben Shum <bshum at biblio.org>

diff --git a/Open-ILS/src/perlmods/lib/OpenILS/Application/Acq/Order.pm b/Open-ILS/src/perlmods/lib/OpenILS/Application/Acq/Order.pm
index 2d94c8d..9b4b71f 100644
--- a/Open-ILS/src/perlmods/lib/OpenILS/Application/Acq/Order.pm
+++ b/Open-ILS/src/perlmods/lib/OpenILS/Application/Acq/Order.pm
@@ -294,8 +294,9 @@ sub delete_lineitem {
 }
 
 # begins and commit transactions as it goes
+# bib_only exits before creation of copies and callnumbers
 sub create_lineitem_list_assets {
-    my($mgr, $li_ids, $vandelay) = @_;
+    my($mgr, $li_ids, $vandelay, $bib_only) = @_;
 
     if (check_import_li_marc_perms($mgr, $li_ids)) { # event on error
         $logger->error("acq-vl: user does not have permission to import acq records");
@@ -304,6 +305,7 @@ sub create_lineitem_list_assets {
 
     my $res = import_li_bibs_via_vandelay($mgr, $li_ids, $vandelay);
     return undef unless $res;
+    return $res if $bib_only;
 
     # create the bibs/volumes/copies for the successfully imported records
     for my $li_id (@{$res->{li_ids}}) {
@@ -1417,7 +1419,7 @@ sub upload_records {
 
     } elsif ($vandelay) {
         $vandelay->{new_rec_perm} = 'IMPORT_ACQ_LINEITEM_BIB_RECORD_UPLOAD';
-        create_lineitem_list_assets($mgr, \@li_list, $vandelay) or return $e->die_event;
+        create_lineitem_list_assets($mgr, \@li_list, $vandelay, 1) or return $e->die_event;
     }
 
     return $mgr->respond_complete;
@@ -1675,7 +1677,7 @@ sub create_purchase_order_api {
     $e->xact_commit;
 
     if($li_ids and $vandelay) {
-        create_lineitem_list_assets($mgr, $li_ids, $vandelay) or return $e->die_event;
+        create_lineitem_list_assets($mgr, $li_ids, $vandelay, !$$args{create_assets}) or return $e->die_event;
     }
 
     return $mgr->respond_complete;

commit 349e7ed4608dd9cbf3b836867b743139e9e9dd1c
Author: Bill Erickson <berick at esilibrary.com>
Date:   Fri Feb 10 10:42:24 2012 -0500

    Acq+Vandelay form re-use new queue
    
    In the Vandelay agent form, if a user creates a new destination queue
    for the uploaded records, allow the user to re-use the new queue without
    having to refresh the interface.  This is primarily useful in the ACQ
    upload UI, where re-using the pre-filled form is possible.
    
    Signed-off-by: Bill Erickson <berick at esilibrary.com>
    Signed-off-by: Ben Shum <bshum at biblio.org>

diff --git a/Open-ILS/web/js/ui/default/acq/common/vlagent.js b/Open-ILS/web/js/ui/default/acq/common/vlagent.js
index 7e307c6..dbfc70f 100644
--- a/Open-ILS/web/js/ui/default/acq/common/vlagent.js
+++ b/Open-ILS/web/js/ui/default/acq/common/vlagent.js
@@ -1,4 +1,5 @@
 dojo.require('openils.widget.AutoFieldWidget');
+dojo.require('openils.PermaCrud');
 
 function VLAgent(args) {
     args = args || {};
@@ -34,7 +35,8 @@ function VLAgent(args) {
                         selfReference : true,
                         orgLimitPerms : [self.limitPerm || 'CREATE_PURCHASE_ORDER'],
                         parentNode : dojo.byId('acq_vl:' + widg.key),
-                        searchFilter : (widg.cls == 'vbq') ? {queue_type : 'acq'} : null
+                        searchFilter : (widg.cls == 'vbq') ? {queue_type : 'acq'} : null,
+                        useWriteStore :  (widg.cls == 'vbq')
                     }).build(function(dijit) { 
                         widg.dijit = dijit; 
                         self.attachOnChange(widg);
@@ -161,7 +163,20 @@ function VLAgent(args) {
             }
 
             if (resp.queue) {
-                res.queue_url = oilsBasePath + '/vandelay/vandelay?qtype=bib&qid=' + resp.queue.id();
+                var newQid = resp.queue.id();
+                res.queue_url = oilsBasePath + '/vandelay/vandelay?qtype=bib&qid=' + newQid;
+
+                var qInput = this.getDijit('queue_name');
+
+                if (newQName = qInput.attr('value')) {
+                    // user created a new queue.  Fetch the new queue object,
+                    // replace the ReadStore with a WriteStore and insert.
+                    qInput.attr('value', '');
+                    var qSelector = this.getDijit('existing_queue');
+                    var newQ = new openils.PermaCrud().retrieve('vbq', newQid);
+                    qSelector.store.newItem(newQ.toStoreItem());
+                    qSelector.attr('value', newQid);
+                }
             }
 
             if (oncomplete) 

commit bf43e8670e2971d96888fb4e57fc64b47ee46c74
Author: Bill Erickson <berick at esilibrary.com>
Date:   Fri Feb 10 10:40:17 2012 -0500

    AutoFieldWidget gets new useWriteStore option
    
    If the useWriteStore attribute is set to true, the underlying data store
    for dynamically create data will live in an ItemFileWriteStore instead
    of a ReadStore, which allows the caller to modify the data after the
    widget is rendered.  It's useful for in-place additions of newly created
    items.
    
    Signed-off-by: Bill Erickson <berick at esilibrary.com>
    Signed-off-by: Ben Shum <bshum at biblio.org>

diff --git a/Open-ILS/web/js/dojo/openils/widget/AutoFieldWidget.js b/Open-ILS/web/js/dojo/openils/widget/AutoFieldWidget.js
index 41f5b29..ad5d92b 100644
--- a/Open-ILS/web/js/dojo/openils/widget/AutoFieldWidget.js
+++ b/Open-ILS/web/js/dojo/openils/widget/AutoFieldWidget.js
@@ -46,6 +46,9 @@ if(!dojo._hasResource['openils.widget.AutoFieldWidget']) {
          *      The fetched objects should be passed to the callback as an array
          *  disableQuery : dojo.data query passed to FilteringTreeSelect-based widgets to disable
          *      (but leave visible) certain options.  
+         *  useWriteStore : tells AFW to use a dojo.data.ItemFileWriteStore instead of a ReadStore for
+         *      data stores created with dynamic data.  This allows the caller to add/remove items from 
+         *      the store.
          */
         constructor : function(args) {
             for(var k in args)
@@ -102,6 +105,13 @@ if(!dojo._hasResource['openils.widget.AutoFieldWidget']) {
             this.cache[this.auth] = this.cache[this.auth] || {};
             this.cache[this.auth].single = this.cache[this.auth].single || {};
             this.cache[this.auth].list = this.cache[this.auth].list || {};
+
+            if (this.useWriteStore) {
+                dojo.require('dojo.data.ItemFileWriteStore');
+                this.storeConstructor = dojo.data.ItemFileWriteStore;
+            } else {
+                this.storeConstructor = dojo.data.ItemFileReadStore;
+            }
         },
 
         /**
@@ -521,7 +531,7 @@ if(!dojo._hasResource['openils.widget.AutoFieldWidget']) {
                         );
                     }
 
-                    self.widget.store = new dojo.data.ItemFileReadStore(storeData);
+                    self.widget.store = new self.storeConstructor(storeData);
                     self.cache[self.auth].list[linkClass] = self.widget.store;
 
                 } else {
@@ -703,7 +713,7 @@ if(!dojo._hasResource['openils.widget.AutoFieldWidget']) {
                     var list = openils.Util.readResponse(r, false, true);
                     if(!list) return;
                     self.widget.store = 
-                        new dojo.data.ItemFileReadStore({data:fieldmapper.acpl.toStoreData(list)});
+                        new self.storeConstructor({data:fieldmapper.acpl.toStoreData(list)});
                     self.cache.copyLocStore = self.widget.store;
                     self.widget.startup();
                     self._widgetLoaded();

commit 1ec10b00946dd331742d04bba676dc0a640325ea
Author: Bill Erickson <berick at esilibrary.com>
Date:   Fri Feb 10 10:37:52 2012 -0500

    Acq upload UI re-use new picklist
    
    In the ACQ file upload UI, if the user loads the records into a new
    selection list, this change allows the user to continue using the new
    list without having to refresh the page.
    
    Without this change, re-using the new list would result in the system
    trying to create a new list with the same name, which fails.
    
    Signed-off-by: Bill Erickson <berick at esilibrary.com>
    Signed-off-by: Ben Shum <bshum at biblio.org>

diff --git a/Open-ILS/web/js/ui/default/acq/picklist/upload.js b/Open-ILS/web/js/ui/default/acq/picklist/upload.js
index 667e272..c6b83d5 100644
--- a/Open-ILS/web/js/ui/default/acq/picklist/upload.js
+++ b/Open-ILS/web/js/ui/default/acq/picklist/upload.js
@@ -1,4 +1,5 @@
 dojo.require('dojo.data.ItemFileReadStore');
+dojo.require('dojo.data.ItemFileWriteStore');
 dojo.require('dijit.ProgressBar');
 dojo.require('dijit.form.CheckBox');
 dojo.require('dijit.form.TextBox');
@@ -10,11 +11,13 @@ dojo.require('openils.User');
 dojo.require('openils.widget.AutoFieldWidget');
 dojo.require('openils.acq.Picklist');
 dojo.require('openils.XUL');
+dojo.require('openils.PermaCrud');
 
 var VANDELAY_URL = '/vandelay-upload';
 var providerWidget;
 var orderAgencyWidget;
 var vlAgent;
+var usingNewPl = false;
 
 function init() {
     dojo.byId('acq-pl-upload-ses').value = openils.User.authtoken;
@@ -47,7 +50,7 @@ function init() {
             oncomplete : function(r) {
                 var list = openils.Util.readResponse(r);
                 acqPlUploadPlSelector.store = 
-                    new dojo.data.ItemFileReadStore({data:acqpl.toStoreData(list)});
+                    new dojo.data.ItemFileWriteStore({data:acqpl.toStoreData(list)});
             }
         }
     );
@@ -64,11 +67,13 @@ function acqUploadRecords() {
             onComplete : function(items) {
                 if(items.length == 0) {
                     // create a new picklist for these items
+                    usingNewPl = true;
                     openils.acq.Picklist.create(
                         {name:picklist, org_unit: orderAgencyWidget.attr('value')},
                         function(plId) { acqSendUploadForm({picklist:plId}) }
                     );
                 } else {
+                    usingNewPl = false;
                     acqSendUploadForm({picklist:items[0].id[0]});
                 }
             }
@@ -132,6 +137,14 @@ function acqHandlePostUpload(key, plId) {
                             
                         if(res.picklist_url) {
                             activateLink('acq-pl-upload-complete-pl', res.picklist_url);
+
+                            // if the user entered a new picklist, refetch the set to pick
+                            // up the ID and redraw the list with the new one selected
+                            if (usingNewPl) {
+                                var newPl = new openils.PermaCrud().retrieve('acqpl', resp.picklist.id());
+                                acqPlUploadPlSelector.store.newItem(newPl.toStoreItem());
+                                acqPlUploadPlSelector.attr('value', newPl.name());
+                            }
                         } 
 
                         if(res.po_url) {

commit 0a5fa7ee518678a0e576001ff76f3763560f7ad0
Author: Bill Erickson <berick at esilibrary.com>
Date:   Wed Feb 8 14:37:44 2012 -0500

    ACQ+Vandelay open picklist/PO/queue in new tab
    
    In the staff client, after a file upload, if a picklist, queue, or PO
    are created, make the links open their respective pages in new tabs.
    When not running inside the staff client, allow the links be regular
    href's.
    
    Signed-off-by: Bill Erickson <berick at esilibrary.com>
    Signed-off-by: Ben Shum <bshum at biblio.org>

diff --git a/Open-ILS/web/js/ui/default/acq/picklist/upload.js b/Open-ILS/web/js/ui/default/acq/picklist/upload.js
index d857b62..667e272 100644
--- a/Open-ILS/web/js/ui/default/acq/picklist/upload.js
+++ b/Open-ILS/web/js/ui/default/acq/picklist/upload.js
@@ -9,6 +9,7 @@ dojo.require("dojo.io.iframe");
 dojo.require('openils.User');
 dojo.require('openils.widget.AutoFieldWidget');
 dojo.require('openils.acq.Picklist');
+dojo.require('openils.XUL');
 
 var VANDELAY_URL = '/vandelay-upload';
 var providerWidget;
@@ -117,21 +118,28 @@ function acqHandlePostUpload(key, plId) {
                         openils.Util.hide('acq-pl-upload-progress-bar');
                         openils.Util.show('acq-pl-upload-complete');
 
+                        function activateLink(link, url, name) {
+                            link = dojo.byId(link);
+                            openils.Util.show(link);
+                            if (name) link.innerHTML = name;
+                            if (typeof xulG == 'undefined') { // browser
+                                link.setAttribute('href', url); 
+                            } else {
+                                link.setAttribute('href', 'javascript:;'); // for linky-ness
+                                link.onclick = function() { openils.XUL.newTabEasy(url) };
+                            }
+                        }
+                            
                         if(res.picklist_url) {
-                            openils.Util.show('acq-pl-upload-complete-pl');
-                            dojo.byId('acq-pl-upload-complete-pl').setAttribute('href', res.picklist_url);
+                            activateLink('acq-pl-upload-complete-pl', res.picklist_url);
                         } 
 
                         if(res.po_url) {
-                            openils.Util.show('acq-pl-upload-complete-po');
-                            dojo.byId('acq-pl-upload-complete-po').setAttribute('href', res.po_url);
+                            activateLink('acq-pl-upload-complete-po', res.po_url);
                         }
 
                         if (res.queue_url) {
-                            link = dojo.byId('acq-pl-upload-complete-q');
-                            openils.Util.show(link);
-                            link.setAttribute('href', res.queue_url);
-                            link.innerHTML = resp.queue.name();
+                            activateLink('acq-pl-upload-complete-q', res.queue_url, resp.queue.name());
                         }
                     }
                 );

commit 21af7aa110578896b9c40e10b8c9a4f86cf52e95
Author: Bill Erickson <berick at esilibrary.com>
Date:   Wed Feb 1 09:12:23 2012 -0500

    ACQ+Vandelay detect existing queue with same name
    
    Within the acq/vandelay agent, detect when a user has entered the name
    of one of their existing queues.  When detected, update the queue
    selector to match the found queue (which updates the linked match set
    and clears the queue selector input).  Otherwise, users may not realize
    they are adding items to an existing queue (with a pre-linked match
    set).
    
    Signed-off-by: Bill Erickson <berick at esilibrary.com>
    Signed-off-by: Ben Shum <bshum at biblio.org>

diff --git a/Open-ILS/web/js/ui/default/acq/common/vlagent.js b/Open-ILS/web/js/ui/default/acq/common/vlagent.js
index 8444b9c..7e307c6 100644
--- a/Open-ILS/web/js/ui/default/acq/common/vlagent.js
+++ b/Open-ILS/web/js/ui/default/acq/common/vlagent.js
@@ -84,13 +84,33 @@ function VLAgent(args) {
         }
 
         qInputChange = function(val) {
-            // TODO: user may enter the name of an existing queue.  
-            // Detect this and disable/update match_set accordingly
-            self.getDijit('match_set').attr('disabled', false);
+
             var qSelector = self.getDijit('existing_queue');
-            dojo.disconnect(qSelector._onchange);
-            qSelector.attr('value', '');
-            qSelector._onchange = dojo.connect(qSelector, 'onChange', qSelChange);
+            var matchSetSelector = self.getDijit('match_set');
+            var foundMatch = false;
+
+            if (val) {
+
+                // if the user entered the name of an existing queue, update the 
+                // queue selector to match the value (and clear the text input 
+                // via qselector onchange)
+                qSelector.store.fetch({
+                    query:{name:val},
+                    onComplete:function(items) {
+                        if(items.length == 0) return;
+                        var item = items[0];
+                        qSelector.attr('value', item.id);
+                        foundMatch = true;
+                    }
+                });
+            }
+
+            if (!foundMatch) {
+                self.getDijit('match_set').attr('disabled', false);
+                dojo.disconnect(qSelector._onchange);
+                qSelector.attr('value', '');
+                qSelector._onchange = dojo.connect(qSelector, 'onChange', qSelChange);
+            }
         }
 
         if (widg.key == 'existing_queue') {
@@ -103,9 +123,7 @@ function VLAgent(args) {
     }
 
     this.getDijit = function(key) {
-        return this.widgets.filter( 
-            function(w) {return (w.key == key)}
-        )[0].dijit;
+        return this.widgets.filter(function(w) {return (w.key == key)})[0].dijit;
     }
 
     this.values = function() {

commit 49517bdf0da4502c626e7e28b2240bf42a782dc7
Author: Bill Erickson <berick at esilibrary.com>
Date:   Tue Jan 31 15:59:41 2012 -0500

    ACQ+Vandelay limit upload queue selector to ACQ queues
    
    When uploading bibs to vandelay queues from ACQ interfaces, only allow
    records to be added to queues tagged as 'acq' queues (or to new 'acq'
    queues).
    
    Signed-off-by: Bill Erickson <berick at esilibrary.com>
    Signed-off-by: Ben Shum <bshum at biblio.org>

diff --git a/Open-ILS/web/js/ui/default/acq/common/vlagent.js b/Open-ILS/web/js/ui/default/acq/common/vlagent.js
index e7c5b05..8444b9c 100644
--- a/Open-ILS/web/js/ui/default/acq/common/vlagent.js
+++ b/Open-ILS/web/js/ui/default/acq/common/vlagent.js
@@ -33,7 +33,8 @@ function VLAgent(args) {
                         fmClass : widg.cls,
                         selfReference : true,
                         orgLimitPerms : [self.limitPerm || 'CREATE_PURCHASE_ORDER'],
-                        parentNode : dojo.byId('acq_vl:' + widg.key)
+                        parentNode : dojo.byId('acq_vl:' + widg.key),
+                        searchFilter : (widg.cls == 'vbq') ? {queue_type : 'acq'} : null
                     }).build(function(dijit) { 
                         widg.dijit = dijit; 
                         self.attachOnChange(widg);

commit 4d0050739339b0b26dc85b982d068e8e225170a9
Author: Bill Erickson <berick at esilibrary.com>
Date:   Tue Jan 31 12:17:20 2012 -0500

    ACQ+Vandelay disallow match_set change on selected queue
    
    Consistent with Vandelay, if a queue is selected, show the linked
    match_set and disable the match_set selector.  Existing queues are
    already linked to a match set, so allowing the user to select one has no
    effect, which is confusing.
    
    Signed-off-by: Bill Erickson <berick at esilibrary.com>
    Signed-off-by: Ben Shum <bshum at biblio.org>

diff --git a/Open-ILS/web/js/ui/default/acq/common/vlagent.js b/Open-ILS/web/js/ui/default/acq/common/vlagent.js
index 1af1f77..e7c5b05 100644
--- a/Open-ILS/web/js/ui/default/acq/common/vlagent.js
+++ b/Open-ILS/web/js/ui/default/acq/common/vlagent.js
@@ -36,10 +36,12 @@ function VLAgent(args) {
                         parentNode : dojo.byId('acq_vl:' + widg.key)
                     }).build(function(dijit) { 
                         widg.dijit = dijit; 
+                        self.attachOnChange(widg);
                     }); 
 
                 } else { // bools
                     widg.dijit = dijit.byId('acq_vl:' + widg.key);
+                    self.attachOnChange(widg);
                 }
             }
         );
@@ -49,6 +51,62 @@ function VLAgent(args) {
         this.loaded = true;
     }
 
+    this.attachOnChange = function(widg) {
+        var self = this;
+        var qInputChange;
+
+        var qSelChange = function(val) {
+            // user selected a queue from the selector;  clear the text input 
+            // and set the item import profile already defined for the queue
+
+            var qInput = self.getDijit('queue_name');
+            var matchSetSelector = self.getDijit('match_set');
+            var qSelector = self.getDijit('existing_queue');
+
+            if(val) {
+                qSelector.store.fetch({
+                    query : {id : val+''},
+                    onComplete : function(items) {
+                        matchSetSelector.attr('value', items[0].match_set[0] || '');
+                        matchSetSelector.attr('disabled', true);
+                    }
+                });
+            } else {
+                matchSetSelector.attr('value', '');
+                matchSetSelector.attr('disabled', false);
+            }
+
+            // detach and reattach to avoid onchange firing while when we clear
+            dojo.disconnect(qInput._onchange);
+            qInput.attr('value', '');
+            qInput._onchange = dojo.connect(qInput, 'onChange', qInputChange);
+        }
+
+        qInputChange = function(val) {
+            // TODO: user may enter the name of an existing queue.  
+            // Detect this and disable/update match_set accordingly
+            self.getDijit('match_set').attr('disabled', false);
+            var qSelector = self.getDijit('existing_queue');
+            dojo.disconnect(qSelector._onchange);
+            qSelector.attr('value', '');
+            qSelector._onchange = dojo.connect(qSelector, 'onChange', qSelChange);
+        }
+
+        if (widg.key == 'existing_queue') {
+            var qSelector = self.getDijit('existing_queue');
+            qSelector._onchange = dojo.connect(qSelector, 'onChange', qSelChange);
+        } else if(widg.key == 'queue_name') {
+            var qInput = self.getDijit('queue_name');
+            qInput._onchange = dojo.connect(qInput, 'onChange', qInputChange);
+        }
+    }
+
+    this.getDijit = function(key) {
+        return this.widgets.filter( 
+            function(w) {return (w.key == key)}
+        )[0].dijit;
+    }
+
     this.values = function() {
         var values = {};
         dojo.forEach(this.widgets,

commit 02da33f95b81c806b656a7759dd14a421a03cbdf
Author: Bill Erickson <berick at esilibrary.com>
Date:   Tue Jan 31 10:49:14 2012 -0500

    ACQ+Vandelay API support for queue-and-match only from ACQ
    
    Allow users to load ACQ records into Vandelay queues and apply a
    match_set at queue creation time, without requiring the user to
    import/merge the ACQ records.
    
    Signed-off-by: Bill Erickson <berick at esilibrary.com>
    Signed-off-by: Ben Shum <bshum at biblio.org>

diff --git a/Open-ILS/src/perlmods/lib/OpenILS/Application/Acq/Order.pm b/Open-ILS/src/perlmods/lib/OpenILS/Application/Acq/Order.pm
index 33fe2b9..2d94c8d 100644
--- a/Open-ILS/src/perlmods/lib/OpenILS/Application/Acq/Order.pm
+++ b/Open-ILS/src/perlmods/lib/OpenILS/Application/Acq/Order.pm
@@ -316,7 +316,7 @@ sub create_lineitem_list_assets {
     return $res;
 }
 
-sub verify_vandelay_import_args {
+sub test_vandelay_import_args {
     my $vandelay = shift;
 
     # we need a queue
@@ -324,16 +324,16 @@ sub verify_vandelay_import_args {
         ($vandelay->{queue_name} or $vandelay->{existing_queue});
 
     # match-based merge/overlay import
-    return 1 if $vandelay->{merge_profile} and (
+    return 2 if $vandelay->{merge_profile} and (
         $vandelay->{auto_overlay_exact} or
         $vandelay->{auto_overlay_1match} or
         $vandelay->{auto_overlay_best_match}
     );
 
     # no-match import
-    return 1 if $vandelay->{import_no_match};
+    return 2 if $vandelay->{import_no_match};
 
-    return 0;
+    return 1; # queue only
 }
 
 sub find_or_create_vandelay_queue {
@@ -394,8 +394,9 @@ sub import_li_bibs_via_vandelay {
 
     $logger->info("acq-vl: processing recs via Vandelay with args: ".Dumper($vandelay));
 
-    if (!verify_vandelay_import_args($vandelay)) {
-        $logger->error("acq-vl: invalid vandelay arguments for acq import");
+    my $vl_stat = test_vandelay_import_args($vandelay);
+    if ($vl_stat == 0) {
+        $logger->error("acq-vl: invalid vandelay arguments for acq import (queue needed)");
         return $res;
     }
 
@@ -430,6 +431,8 @@ sub import_li_bibs_via_vandelay {
     # vandelay uses its own transactions.
     $e->commit;
 
+    return $res if $vl_stat == 1; # queue only
+
     # Import the bibs via vandelay.  Note: Vandely will 
     # update acq.lineitem.eg_bib_id on successful import.
 

commit 23b04db5a14931a395fc505be061c1c8a7784c68
Author: Bill Erickson <berick at esilibrary.com>
Date:   Tue Jan 31 10:01:01 2012 -0500

    ACQ+Vandelay ACQ Records in vandelay queue selector
    
    Adds a new type of record to select from the Vandelay queue selector.
    Selecting "Acquisitions Records" will show queues with type 'acq'.
    Selecting the existing "Bibliographic Records" selector will only show
    queues with queue_type 'bib' (i.e. non-acq queues).
    
    Signed-off-by: Bill Erickson <berick at esilibrary.com>
    Signed-off-by: Ben Shum <bshum at biblio.org>

diff --git a/Open-ILS/src/templates/vandelay/inc/queueselect.tt2 b/Open-ILS/src/templates/vandelay/inc/queueselect.tt2
index e72633b..91416c9 100644
--- a/Open-ILS/src/templates/vandelay/inc/queueselect.tt2
+++ b/Open-ILS/src/templates/vandelay/inc/queueselect.tt2
@@ -6,6 +6,7 @@
         <td>
             <select jsId='vlQueueSelectType' dojoType='dijit.form.FilteringSelect' onchange='vlShowQueueSelect();'>
                 <option value='bib' selected='selected'>[% l('Bibliographic Records') %]</option>
+                <option value='bib-acq'>[% l('Acquisitions Records') %]</option>
                 <option value='auth'>[% l('Authority Records') %]</option>
             </select>
         </td>
diff --git a/Open-ILS/web/js/ui/default/vandelay/vandelay.js b/Open-ILS/web/js/ui/default/vandelay/vandelay.js
index 24b2a0d..c7ed37c 100644
--- a/Open-ILS/web/js/ui/default/vandelay/vandelay.js
+++ b/Open-ILS/web/js/ui/default/vandelay/vandelay.js
@@ -1354,7 +1354,26 @@ function batchUpload() {
 
 
 function vlFleshQueueSelect(selector, type) {
-    var data = (type == 'bib') ? vbq.toStoreData(allUserBibQueues) : vaq.toStoreData(allUserAuthQueues);
+    var data;
+    if (type == 'bib') {
+        var bibList = allUserBibQueues.filter(
+            function(q) {
+                return (q.queue_type() == 'bib');
+            }
+        );
+        data = vbq.toStoreData(bibList);
+    } else if (type == 'bib-acq') {
+        // ACQ queues are a special type of bib queue
+        var acqList = allUserBibQueues.filter(
+            function(q) {
+                return (q.queue_type() == 'acq');
+            }
+        );
+        data = vbq.toStoreData(acqList);
+    } else {
+        data = vaq.toStoreData(allUserAuthQueues);
+    }
+
     selector.store = new dojo.data.ItemFileReadStore({data:data});
     selector.setValue(null);
     selector.setDisplayedValue('');
@@ -1455,7 +1474,7 @@ function vlShowMatchSetEditor() {
 }
 
 function vlFetchQueueFromForm() {
-    currentType = vlQueueSelectType.getValue();
+    currentType = vlQueueSelectType.attr('value').replace(/-.*/, ''); // trim bib-acq
     currentQueueId = vlQueueSelectQueueList.getValue();
     retrieveQueuedRecords(currentType, currentQueueId, handleRetrieveRecords);
 }

commit e65acab943a624c57673cd2b80ea483c63ed934b
Author: Bill Erickson <berick at esilibrary.com>
Date:   Thu Jan 19 14:02:32 2012 -0500

    ACQ+Vandelay permission improvements
    
    Be more vigilant about enforcing permissions for various ACQ and
    Vandelay actions.
    
    1. Using vandelay to create new bib records now requres the IMPORT_MARC
    permission (same as open-ils.cat.biblio.record.xml.import).  If the
    permission fails, the queued record will fail import and be stamped with
    a new "import.record.perm_failure" vandelay import error.
    
    2. Added suport for testing additional permissions before a new record
    is created via vandelay.  This allows interfaces leveraging vandelay
    (e.g. ACQ) to create a higher barrier to entry.  Added an ACQ perm
    IMPORT_ACQ_LINEITEM_BIB_RECORD_UPLOAD that prevents users from creating
    new bib records directly from the ACQ vendor MARC file upload interface.
    
    The secondary permission is not meant as a security enhancement, per se,
    since the user is required to have the IMPORT_MARC permission to get this
    far in the process.  It's more of a feature-specific precautionary
    permission to prevent unintended record creation within certain
    permission groups.
    
    3. Checking the CREATE_PURCHASE_ORDER permission during the ACQ vendor
    file upload process.  It's absence appears to have been an oversight.
    
    Signed-off-by: Bill Erickson <berick at esilibrary.com>
    Signed-off-by: Ben Shum <bshum at biblio.org>

diff --git a/Open-ILS/src/perlmods/lib/OpenILS/Application/Acq/Order.pm b/Open-ILS/src/perlmods/lib/OpenILS/Application/Acq/Order.pm
index 5fa0bc2..33fe2b9 100644
--- a/Open-ILS/src/perlmods/lib/OpenILS/Application/Acq/Order.pm
+++ b/Open-ILS/src/perlmods/lib/OpenILS/Application/Acq/Order.pm
@@ -1316,8 +1316,8 @@ sub upload_records {
     my $picklist        = $args->{picklist};
     my $create_po       = $args->{create_po};
     my $activate_po     = $args->{activate_po};
-    my $ordering_agency = $args->{ordering_agency};
     my $vandelay        = $args->{vandelay};
+    my $ordering_agency = $args->{ordering_agency} || $e->requestor->ws_ou;
     my $po;
     my $evt;
 
@@ -1339,6 +1339,8 @@ sub upload_records {
     }
 
     if($create_po) {
+        return $e->die_event unless 
+            $e->allowed('CREATE_PURCHASE_ORDER', $ordering_agency);
 
         $po = create_purchase_order($mgr, 
             ordering_agency => $ordering_agency,
@@ -1411,6 +1413,7 @@ sub upload_records {
         return $die_event if $die_event;
 
     } elsif ($vandelay) {
+        $vandelay->{new_rec_perm} = 'IMPORT_ACQ_LINEITEM_BIB_RECORD_UPLOAD';
         create_lineitem_list_assets($mgr, \@li_list, $vandelay) or return $e->die_event;
     }
 
diff --git a/Open-ILS/src/perlmods/lib/OpenILS/Application/Vandelay.pm b/Open-ILS/src/perlmods/lib/OpenILS/Application/Vandelay.pm
index 8502d51..5c06e96 100644
--- a/Open-ILS/src/perlmods/lib/OpenILS/Application/Vandelay.pm
+++ b/Open-ILS/src/perlmods/lib/OpenILS/Application/Vandelay.pm
@@ -915,6 +915,7 @@ sub import_record_list_impl {
         $rec_class = 'vqar';
     }
 
+    my $new_rec_perm_cache;
     my @success_rec_ids;
     for my $rec_id (@$rec_ids) {
 
@@ -1059,26 +1060,54 @@ sub import_record_list_impl {
             if(!$imported and !$error and $import_no_match and scalar(@{$rec->matches}) == 0) {
             
                 # No overlay / merge occurred.  Do a traditional record import by creating a new record
-            
-                $logger->info("vl: creating new $type record for queued record $rec_id");
-                if($type eq 'bib') {
-                    $record = OpenILS::Application::Cat::BibCommon->biblio_record_xml_import(
-                        $e, $rec->marc, $bib_sources{$rec->bib_source}, undef, 1);
-                } else {
 
-                    $record = OpenILS::Application::Cat::AuthCommon->import_authority_record($e, $rec->marc); #$source);
+                if (!$new_rec_perm_cache) {
+                    $new_rec_perm_cache = {};
+
+                    # all users creating new records are required to have the basic permission.
+                    # if the client requests, we can enforce extra permissions for creating new records.
+                    # for speed, check the permissions the first time then cache the result.
+
+                    my $perm = ($type eq 'bib') ? 'IMPORT_MARC' : 'IMPORT_AUTHORITY_MARC';
+                    my $xperm = $$args{new_rec_perm};
+                    my $rec_ou = $e->requestor->ws_ou;
+
+                    $new_rec_perm_cache->{evt} = $e->die_event
+                        if !$e->allowed($perm, $rec_ou) || ($xperm and !$e->allowed($xperm, $rec_ou));
                 }
 
-                if($U->event_code($record)) {
-                    $$report_args{import_error} = 'import.duplicate.tcn' 
-                        if $record->{textcode} eq 'OPEN_TCN_NOT_FOUND';
-                    $$report_args{evt} = $record;
+                if ($new_rec_perm_cache->{evt}) {
 
-                } else {
+                    # a cached event won't roll back the transaction (a la die_event), but
+                    # the transaction will get rolled back in finish_rec_import_attempt() below
+                    $$report_args{evt} = $new_rec_perm_cache->{evt};
+                    $$report_args{import_error} = 'import.record.perm_failure';
 
-                    $logger->info("vl: successfully imported new $type record");
-                    $rec->imported_as($record->id);
-                    $imported = 1;
+                } else { # perm checks succeeded
+
+                    $logger->info("vl: creating new $type record for queued record $rec_id");
+
+                    if ($type eq 'bib') {
+
+                        $record = OpenILS::Application::Cat::BibCommon->biblio_record_xml_import(
+                            $e, $rec->marc, $bib_sources{$rec->bib_source}, undef, 1);
+
+                    } else { # authority record
+
+                        $record = OpenILS::Application::Cat::AuthCommon->import_authority_record($e, $rec->marc); #$source);
+                    }
+
+                    if($U->event_code($record)) {
+                        $$report_args{import_error} = 'import.duplicate.tcn' 
+                            if $record->{textcode} eq 'OPEN_TCN_NOT_FOUND';
+                        $$report_args{evt} = $record;
+
+                    } else {
+
+                        $logger->info("vl: successfully imported new $type record");
+                        $rec->imported_as($record->id);
+                        $imported = 1;
+                    }
                 }
             }
         }
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 94e7626..45fead3 100644
--- a/Open-ILS/src/sql/Pg/950.data.seed-values.sql
+++ b/Open-ILS/src/sql/Pg/950.data.seed-values.sql
@@ -1529,7 +1529,11 @@ INSERT INTO permission.perm_list ( id, code, description ) VALUES
  ( 519, 'ADMIN_SMS_CARRIER', oils_i18n_gettext( 519,
     'Allows a user to add/create/delete SMS Carrier entries.', 'ppl', 'description' )),
  ( 520, 'COPY_DELETE_WARNING.override', oils_i18n_gettext( 520,
-    'Allow a user to override warnings about deleting copies in problematic situations.', 'ppl', 'description' ));
+    'Allow a user to override warnings about deleting copies in problematic situations.', 'ppl', 'description' )),
+ ( 521, 'IMPORT_ACQ_LINEITEM_BIB_RECORD_UPLOAD', oils_i18n_gettext( 521,
+    'Allows a user to create new bibs directly from an ACQ MARC file upload', 'ppl', 'description' )),
+ ( 522, 'IMPORT_AUTHORITY_MARC', oils_i18n_gettext( 522,
+    'Allows a user to create new authority records', 'ppl', 'description' ));
 
 
 SELECT SETVAL('permission.perm_list_id_seq'::TEXT, 1000);
@@ -1766,6 +1770,7 @@ INSERT INTO permission.grp_perm_map (grp, perm, depth, grantable)
 			'DELETE_TITLE_NOTE',
 			'IMPORT_ACQ_LINEITEM_BIB_RECORD',
 			'IMPORT_MARC',
+            'IMPORT_AUTHORITY_MARC',
 			'MERGE_AUTH_RECORDS',
 			'MERGE_BIB_RECORDS',
 			'UPDATE_AUTHORITY_IMPORT_QUEUE',
@@ -9160,6 +9165,8 @@ INSERT INTO vandelay.import_error ( code, description ) VALUES (
     'import.item.invalid.copy_number', oils_i18n_gettext('import.item.invalid.copy_number', 'Invalid value for "copy_number"', 'vie', 'description') );
 INSERT INTO vandelay.import_error ( code, description ) VALUES ( 
     'import.item.invalid.circ_as_type', oils_i18n_gettext('import.item.invalid.circ_as_type', 'Invalid value for "circ_as_type"', 'vie', 'description') );
+INSERT INTO vandelay.import_error ( code, description ) VALUES ( 
+    'import.record.perm_failure', oils_i18n_gettext('import.record.perm_failure', 'Perm failure creating a record', 'vie', 'description') );
 
 -- Event def for email notice for hold cancelled due to lack of target -----
 
diff --git a/Open-ILS/src/sql/Pg/upgrade/XXXX.schema.acq-vandelay-integration.sql b/Open-ILS/src/sql/Pg/upgrade/XXXX.schema.acq-vandelay-integration.sql
index 213c7ac..f5ce14e 100644
--- a/Open-ILS/src/sql/Pg/upgrade/XXXX.schema.acq-vandelay-integration.sql
+++ b/Open-ILS/src/sql/Pg/upgrade/XXXX.schema.acq-vandelay-integration.sql
@@ -44,6 +44,30 @@ ALTER TABLE acq.acq_lineitem_history ADD COLUMN queued_record BIGINT
     REFERENCES vandelay.queued_bib_record (id) 
     ON DELETE SET NULL DEFERRABLE INITIALLY DEFERRED;
 
+-- seed data --
+
+INSERT INTO permission.perm_list ( id, code, description ) 
+    VALUES ( 
+        521, 
+        'IMPORT_ACQ_LINEITEM_BIB_RECORD_UPLOAD', 
+        oils_i18n_gettext( 
+            521,
+            'Allows a user to create new bibs directly from an ACQ MARC file upload', 
+            'ppl', 
+            'description' 
+        )
+    );
+
+
+INSERT INTO vandelay.import_error ( code, description ) 
+    VALUES ( 
+        'import.record.perm_failure', 
+        oils_i18n_gettext(
+            'import.record.perm_failure', 
+            'Perm failure creating a record', 'vie', 'description') 
+    );
+
+
 COMMIT;
 
 /* UNDO SQL

commit 12757f3d4e0767e9d23bf2c4172553360f0842cd
Author: Bill Erickson <berick at esilibrary.com>
Date:   Fri Jan 6 16:31:22 2012 -0500

    ACQ+Vandelay link to vandelay queue from lineitem list UI
    
    In the general purpose lineitem interface (li_table), there is now a
    link to the Vandelay queue which contains the queued bib record used to
    load/merge/link the lineitem.  Queue opens in a new staff client tab.
    
    Signed-off-by: Bill Erickson <berick at esilibrary.com>
    Signed-off-by: Ben Shum <bshum at biblio.org>

diff --git a/Open-ILS/src/templates/acq/common/li_table.tt2 b/Open-ILS/src/templates/acq/common/li_table.tt2
index 374e816..3a23351 100644
--- a/Open-ILS/src/templates/acq/common/li_table.tt2
+++ b/Open-ILS/src/templates/acq/common/li_table.tt2
@@ -108,6 +108,7 @@
                                         <span name='po' class='hidden'> | <a title='Purchase Order' name='po_link' href='javascript:void(0);'>&#x2318; </a></span>
                                         <span name="show_requests"> | <a title='Patron Requests' name="show_requests_link" href="javascript:void(0);">requests</a></span> 
                                         <span name='pro' class='hidden'> | <a title='[% l('Provider') %]' name='pro_link' href='javascript:void(0);'>&#x235F; </a></span>
+                                        <span name='queue' class='hidden'> | <a title='[% l('Import Queue') %]' name='queue_link' href='javascript:void(0);'>&#x27AC; Queue</a></span>
                                     </td>
                                 </tr>
                             </tbody>
diff --git a/Open-ILS/web/js/ui/default/acq/common/li_table.js b/Open-ILS/web/js/ui/default/acq/common/li_table.js
index b05bd41..fc7e2e6 100644
--- a/Open-ILS/web/js/ui/default/acq/common/li_table.js
+++ b/Open-ILS/web/js/ui/default/acq/common/li_table.js
@@ -366,6 +366,24 @@ function AcqLiTable() {
             nodeByName("link_to_catalog_link", row).onclick = function() { self.drawBibFinder(li) };
         }
 
+        if (li.queued_record()) {
+            this.pcrud.retrieve('vqbr', li.queued_record(),
+                {   async : true, 
+                    oncomplete : function(r) {
+                        var qrec = openils.Util.readResponse(r);
+                        openils.Util.show(nodeByName('queue', row), 'inline');
+                        var link = nodeByName("queue_link", row);
+                        link.onclick = function() { 
+                            // open a new tab to the vandelay queue for this record
+                            openils.XUL.newTabEasy(
+                                oilsBasePath + '/vandelay/vandelay?qtype=bib&qid=' + qrec.queue()
+                            );
+                        }
+                    }
+                }
+            );
+        }
+
         nodeByName("worksheet_link", row).href =
             oilsBasePath + "/acq/lineitem/worksheet/" + li.id();
 

commit 845c858bcdd2dfb6df33239f90af990f5d219a93
Author: Bill Erickson <berick at esilibrary.com>
Date:   Tue Dec 6 13:50:29 2011 -0500

    ACQ+Vandelay import/merge user interface components
    
    Acquisitions support for leveraging Vandelay import/merge controls
    for loading ACQ records and/or linking ACQ records to existing
    catalog records.
    
    Dev includes:
    
    * General purpose Vandelay input form and merge progress indicator (VLAgent)
    * VLAgent is now shown in the following interfaces when a bib load/merge/link action is required:
     * Vendor record upload interface
     * PO creation
     * PO "load bibs and items" action
     * PO activation
    
    Signed-off-by: Bill Erickson <berick at esilibrary.com>
    Signed-off-by: Ben Shum <bshum at biblio.org>

diff --git a/Open-ILS/examples/fm_IDL.xml b/Open-ILS/examples/fm_IDL.xml
index b0ab837..1c92c2e 100644
--- a/Open-ILS/examples/fm_IDL.xml
+++ b/Open-ILS/examples/fm_IDL.xml
@@ -533,7 +533,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
 
 	<class id="vms" controller="open-ils.cstore open-ils.pcrud" oils_obj:fieldmapper="vandelay::match_set" oils_persist:tablename="vandelay.match_set" reporter:label="Record Matching Definition Set">
 		<fields oils_persist:primary="id" oils_persist:sequence="vandelay.match_set_id_seq">
-			<field reporter:label="Match Set ID" name="id" reporter:datatype="id"/>
+			<field reporter:label="Match Set ID" name="id" reporter:datatype="id" reporter:selector="name"/>
 			<field reporter:label="Name" name="name" reporter:datatype="text"/>
 			<field reporter:label="Owning Library" name="owner" reporter:datatype="link"/>
 			<field reporter:label="Match Set Type" name="mtype" reporter:datatype="text"/>
diff --git a/Open-ILS/src/templates/acq/common/li_table.tt2 b/Open-ILS/src/templates/acq/common/li_table.tt2
index 7b10181..374e816 100644
--- a/Open-ILS/src/templates/acq/common/li_table.tt2
+++ b/Open-ILS/src/templates/acq/common/li_table.tt2
@@ -1,4 +1,5 @@
 <script type="text/javascript" src="[% ctx.media_prefix %]/js/ui/default/acq/common/base64.js"> </script>
+<script type="text/javascript" src='[% ctx.media_prefix %]/js/ui/default/acq/common/vlagent.js'> </script>
 <script type="text/javascript" src='[% ctx.media_prefix %]/js/ui/default/acq/common/li_table.js'> </script>
 <script type="text/javascript" src='[% ctx.media_prefix %]/js/ui/default/acq/financial/claim_voucher.js'> </script>
 <div id='acq-lit-table-container'>
@@ -309,37 +310,27 @@
         </div>
     </div>
 
-    <div class='hidden' id='acq-lit-progress-numbers'>
+
+    [% PROCESS 'acq/common/vlagent.tt2' %]
+    <div class='hidden' id='acq-lit-asset-creator'>
         <table class='oils-generic-table'>
             <tbody>
+                [% PROCESS vlagent_form %]
                 <tr>
-                    <td>Lineitems Processed</td>
-                    <td><span id='acq-pl-lit-li-processed'>0</span></td>
-                </tr>
-                <tr>
-                    <td>Items Processed</td>
-                    <td><span id='acq-pl-lit-lid-processed'>0</span></td>
-                </tr>
-                <tr>
-                    <td>Debits Encumbered</td>
-                    <td><span id='acq-pl-lit-debits-processed'>0</span></td>
-                </tr>
-                <tr>
-                    <td>Bib Records Imported</td>
-                    <td><span id='acq-pl-lit-bibs-processed'>0</span></td>
-                </tr>
-                <tr>
-                    <td>Bib Records Indexed</td>
-                    <td><span id='acq-pl-lit-indexed-processed'>0</span></td>
-                </tr>
-                <tr>
-                    <td>Copies Processed</td>
-                    <td><span id='acq-pl-lit-copies-processed'>0</span></td>
+                    <td>
+                        <span style='margin-left:10px;'>
+                            <button dojoType="dijit.form.Button" jsId='assetCreatorButton'>[% l('Submit') %]</button>
+                        </span>
+                    </td>
                 </tr>
             </tbody>
         </table>
     </div>
 
+    <div class='hidden' id='acq-lit-progress-numbers'>
+        [% PROCESS vlagent_results %]
+    </div>
+
     <div class='hidden'>
         <div dojoType='dijit.Dialog' jsId='acqLitPoCreateDialog'>
             <table class='oils-generic-table'>
diff --git a/Open-ILS/src/templates/acq/common/vlagent.tt2 b/Open-ILS/src/templates/acq/common/vlagent.tt2
new file mode 100644
index 0000000..7c8ee66
--- /dev/null
+++ b/Open-ILS/src/templates/acq/common/vlagent.tt2
@@ -0,0 +1,78 @@
+[% BLOCK vlagent_form %]
+    <tr>
+        <td>[% l('Upload to Queue') %]</td>
+        <td><div id='acq_vl:existing_queue'></div></td>
+        <td>
+            <span>[% l('Or create a new queue') %]</span>
+            <input dojoType='dijit.form.TextBox' id='acq_vl:queue_name' size='32'></input>
+        </td>
+    </tr>
+    <tr>
+        <td>[% l('Record Match Set') %]</td>
+        <td><div id='acq_vl:match_set'></div></td>
+    </tr>
+    <tr>
+        <td>[% l('Merge Profile') %]</td>
+        <td><div id='acq_vl:merge_profile'></div></td>
+    </tr>
+    <tr>
+        <td>[% l('Import Non-Matching Records') %]</td>
+        <td><input dojoType='dijit.form.CheckBox' id='acq_vl:import_no_match'></input></td>
+        <td><span style='padding-right:10px;'>[% l('Record Source') %]</span> <div id='acq_vl:bib_source'></div></td>
+    </tr>
+    <tr>
+        <td>[% l('Merge On Exact Match (901c)') %]</td>
+        <td><input dojoType='dijit.form.CheckBox' id='acq_vl:auto_overlay_exact'></input></td>
+    </tr>
+    <tr>
+        <td>[% l('Merge On Single Match') %]</td>
+        <td><input dojoType='dijit.form.CheckBox' id='acq_vl:auto_overlay_1match'></input></td>
+    </tr>
+    <tr>
+        <td>[% l('Merge On Best Match') %]</td>
+        <td><input dojoType='dijit.form.CheckBox' id='acq_vl:auto_overlay_best_match'></input></td>
+    </tr>
+    <tr>
+        <td>[% l('Best/Single Match Minimum Quality Ratio') %]</td>
+        <td colspan='4'>
+            <input style='width:3em' value='0.0' id='acq_vl:match_quality_ratio' dojoType='dijit.form.TextBox'/>
+            <span style='padding-left: 10px; font-size:90%'>[% l('New Record Quality / Quality of Best Match') %]</span>
+        </td>
+    </tr>
+    <tr>
+        <td>[% l('Insufficient Quality Fall-Through Profile') %]</td>
+        <td><div id='acq_vl:fall_through_merge_profile'></div></td>
+    </tr>
+[% END %]
+
+[% BLOCK vlagent_results %]
+    <table class='oils-generic-table'>
+        <tbody>
+            <tr>
+                <td>[% l('Lineitems Processed') %]</td>
+                <td><span id='acq_vl:li-processed'>0</span></td>
+            </tr>
+            <tr>
+                <td>[% l('Vandelay Records Processed') %]</td>
+                <td><span id='acq_vl:vqbr-processed'>0</span></td>
+            </tr>
+            <tr>
+                <td>[% l('Bib Records Merged/Imported') %]</td>
+                <td><span id='acq_vl:bibs-processed'>0</span></td>
+            </tr>
+            <tr>
+                <td>[% l('ACQ Copies Processed') %]</td>
+                <td><span id='acq_vl:lid-processed'>0</span></td>
+            </tr>
+            <tr>
+                <td>[% l('Debits Encumbered') %]</td>
+                <td><span id='acq_vl:debits-processed'>0</span></td>
+            </tr>
+            <tr>
+                <td>[% l('Real Copies Processed') %]</td>
+                <td><span id='acq_vl:copies-processed'>0</span></td>
+            </tr>
+        </tbody>
+    </table>
+[% END %]
+
diff --git a/Open-ILS/src/templates/acq/picklist/upload.tt2 b/Open-ILS/src/templates/acq/picklist/upload.tt2
index 31b7620..fc03106 100644
--- a/Open-ILS/src/templates/acq/picklist/upload.tt2
+++ b/Open-ILS/src/templates/acq/picklist/upload.tt2
@@ -1,4 +1,5 @@
 [% WRAPPER 'base.tt2' %]
+[% PROCESS 'acq/common/vlagent.tt2' %]
 
 <h1>Upload</h1><br/>
 <form id="acq-pl-upload-form" enctype="multipart/form-data">
@@ -8,20 +9,13 @@
             <tr>
                 <td>Create Purchase Order</td>
                 <td>
-                    <input dojoType='dijit.form.CheckBox' name='create_po'></input>
+                    <input dojoType='dijit.form.CheckBox' jsId='acqPlUploadCreatePo'></input>
                 </td>
             </tr>
             <tr>
                 <td>Activate Purchase Order</td>
                 <td>
-                    <input dojoType='dijit.form.CheckBox' name='activate_po'></input>
-                </td>
-            </tr>
-            <tr>
-                <!-- XXX CHECK IMPORT PERMS TO ENABLE -->
-                <td>Load Bibs and Items into the ILS</td>
-                <td>
-                    <input dojoType='dijit.form.CheckBox' name='create_assets'></input>
+                    <input dojoType='dijit.form.CheckBox' jsId='acqPlUploadActivatePo'></input>
                 </td>
             </tr>
             <tr>
@@ -38,15 +32,19 @@
                     <select jsId='acqPlUploadPlSelector' dojoType='dijit.form.ComboBox'></select>
                 </td>
             </tr>
+
+            <tr><td colspan='2'><hr/></td></tr>
+            [% PROCESS vlagent_form %]
+            <tr><td colspan='2'><hr/></td></tr>
+
             <tr>
-                <td>Records File</td>
-                <td><input size='36' type="file" name="marc_upload"></input></td>
-            </tr>
-            <tr>
-                <td align='center' colspan='2'>
-                    <button dojoType="dijit.form.Button" onClick="acqUploadRecords()">Upload</button>
+                <td colspan='5'>
+                    <span id="vl-file-label">[% l('File to Upload:') %]</span>
+                    <input size='48' style='border:1px solid #888;' type="file" name="marc_upload"/>
+                    <span style='margin-left:10px;'><button dojoType="dijit.form.Button" onclick="acqUploadRecords()">[% l('Upload') %]</button></span>
                 </td>
             </tr>
+
         </tbody>
     </table>
 
@@ -56,42 +54,15 @@
         <div id='acq-pl-upload-progress-bar'>
             <div dojoType="dijit.ProgressBar" style="width:300px" indeterminate="true"></div>
         </div>
-        <div>
-            <table class='oils-generic-table'>
-                <tbody>
-                    <tr>
-                        <td>Lineitems Processed</td>
-                        <td><span id='acq-pl-upload-li-processed'>0</span></td>
-                    </tr>
-                    <tr>
-                        <td>Items Processed</td>
-                        <td><span id='acq-pl-upload-lid-processed'>0</span></td>
-                    </tr>
-                    <tr>
-                        <td>Debits Encumbered</td>
-                        <td><span id='acq-pl-upload-debits-processed'>0</span></td>
-                    </tr>
-                    <tr>
-                        <td>Bib Records Imported</td>
-                        <td><span id='acq-pl-upload-bibs-processed'>0</span></td>
-                    </tr>
-                    <tr>
-                        <td>Bib Records Indexed</td>
-                        <td><span id='acq-pl-upload-indexed-processed'>0</span></td>
-                    </tr>
-                    <tr>
-                        <td>Copies Created</td>
-                        <td><span id='acq-pl-upload-copies-processed'>0</span></td>
-                    </tr>
-                </tbody>
-                <tbody id='acq-pl-upload-complete' class='hidden'>
-                    <tr><td colspan='2'>Upload Complete!</td></tr>
-                    <tr><td colspan='2'><a id='acq-pl-upload-complete-po'>View Purchase Order</a></td></tr>
-                    <tr><td colspan='2'><a id='acq-pl-upload-complete-pl'>View Selection List</a></td></tr>
-                </tbody>
-            </table>
+        [% PROCESS vlagent_results %]
+        <div id='acq-pl-upload-complete' class='hidden'>
+            <div>Upload Complete!</div><br/>
+            <div><a id='acq-pl-upload-complete-po'>View Purchase Order</a></div><br/>
+            <div><a id='acq-pl-upload-complete-pl'>View Selection List</a></div><br/>
+            <div><a id='acq-pl-upload-complete-q'></a></div><br/>
         </div>
     </div>
 </form>
+<script type="text/javascript" src='[% ctx.media_prefix %]/js/ui/default/acq/common/vlagent.js'> </script>
 <script type="text/javascript" src='[% ctx.media_prefix %]/js/ui/default/acq/picklist/upload.js'> </script>
 [% END %]
diff --git a/Open-ILS/web/js/ui/default/acq/common/li_table.js b/Open-ILS/web/js/ui/default/acq/common/li_table.js
index 6ee88d2..b05bd41 100644
--- a/Open-ILS/web/js/ui/default/acq/common/li_table.js
+++ b/Open-ILS/web/js/ui/default/acq/common/li_table.js
@@ -79,6 +79,7 @@ function AcqLiTable() {
             self.fetchClaimInfo(li.id(), /* force update */ true);
         }
     );
+    this.vlAgent = new VLAgent();
 
     dojo.byId("acq-lit-li-actions-selector").onchange = function() { 
         self.applySelectedLiAction(this.options[this.selectedIndex].value);
@@ -154,6 +155,7 @@ function AcqLiTable() {
         openils.Util.hide('acq-lit-li-details');
         openils.Util.hide('acq-lit-notes-div');
         openils.Util.hide('acq-lit-real-copies-div');
+        openils.Util.hide('acq-lit-asset-creator');
         switch(div) {
             case 'list':
                 openils.Util.show('acq-lit-table-div');
@@ -170,6 +172,9 @@ function AcqLiTable() {
             case 'notes':
                 openils.Util.show('acq-lit-notes-div');
                 break;
+            case 'asset-creator':
+                openils.Util.show('acq-lit-asset-creator');
+                break;
             default:
                 if(div) 
                     openils.Util.show(div);
@@ -2037,7 +2042,7 @@ function AcqLiTable() {
                 break;
 
             case 'create_assets':
-                this.createAssets();
+                this.showAssetCreator();
                 break;
 
             case 'export_attr_list':
@@ -2099,18 +2104,26 @@ function AcqLiTable() {
         );
     };
 
-    this.createAssets = function() {
+    this.showAssetCreator = function(onAssetsCreated) {
+        this.show('asset-creator');
+        if(!this.vlAgent.loaded)
+            this.vlAgent.init();
+        var self = this;
+        dojo.connect(assetCreatorButton, 'onClick', 
+            function() { self.createAssets(onAssetsCreated) });
+    }
+
+    this.createAssets = function(onAssetsCreated) {
         if(!this.isPO) return;
-        if(!confirm(localeStrings.CREATE_PO_ASSETS_CONFIRM)) return;
         this.show('acq-lit-progress-numbers');
         var self = this;
         fieldmapper.standardRequest(
             ['open-ils.acq', 'open-ils.acq.purchase_order.assets.create'],
             {   async: true,
-                params: [this.authtoken, this.isPO],
+                params: [this.authtoken, this.isPO, {vandelay : this.vlAgent.values()}],
                 onresponse: function(r) {
                     var resp = openils.Util.readResponse(r);
-                    self._updateProgressNumbers(resp, true);
+                    self._updateProgressNumbers(resp, !Boolean(onAssetsCreated), onAssetsCreated);
                 }
             }
         );
@@ -2347,16 +2360,15 @@ function AcqLiTable() {
         );
     }
 
-    this._updateProgressNumbers = function(resp, reloadOnComplete) {
-        if(!resp) return;
-        dojo.byId('acq-pl-lit-li-processed').innerHTML = resp.li;
-        dojo.byId('acq-pl-lit-lid-processed').innerHTML = resp.lid;
-        dojo.byId('acq-pl-lit-debits-processed').innerHTML = resp.debits_accrued;
-        dojo.byId('acq-pl-lit-bibs-processed').innerHTML = resp.bibs;
-        dojo.byId('acq-pl-lit-indexed-processed').innerHTML = resp.indexed;
-        dojo.byId('acq-pl-lit-copies-processed').innerHTML = resp.copies;
-        if(resp.complete && reloadOnComplete) 
-            location.href = location.href;
+    this._updateProgressNumbers = function(resp, reloadOnComplete, onComplete) {
+        this.vlAgent.handleResponse(resp,
+            function(resp, res) {
+                if(reloadOnComplete)
+                     location.href = location.href;
+                if (onComplete)
+                    onComplete(resp, res);
+            }
+        );
     }
 
 
@@ -2383,30 +2395,37 @@ function AcqLiTable() {
 
     this._createPOFromLineitems = function(fields, selected) {
         if (selected.length == 0) return;
+        var self = this;
 
-        this.show("acq-lit-progress-numbers");
         var po = new fieldmapper.acqpo();
         po.provider(this.createPoProviderSelector.attr("value"));
         po.ordering_agency(this.createPoAgencySelector.attr("value"));
         po.prepayment_required(fields.prepayment_required[0] ? true : false);
 
+        // if we're creating assets, delay the asset creation 
+        // until after the PO is created.  This will allow us to 
+        // use showAssetCreator() directly.
+
         fieldmapper.standardRequest(
             ["open-ils.acq", "open-ils.acq.purchase_order.create"],
             {   async: true,
                 params: [
                     openils.User.authtoken, 
-                    po, {
-                        lineitems : selected,
-                        create_assets : fields.create_assets[0],
-                    }
+                    po, {lineitems : selected}
                 ],
-
                 onresponse : function(r) {
                     var resp = openils.Util.readResponse(r);
-                    self._updateProgressNumbers(resp);
                     if (resp.complete) {
-                        location.href = oilsBasePath + "/acq/po/view/" +
-                            resp.purchase_order.id();
+                        // self.isPO is needed for showAssetCreator();
+                        self.isPO = resp.purchase_order.id(); 
+                        var redir = oilsBasePath + "/acq/po/view/" + self.isPO;
+                        if (fields.create_assets[0]) {
+                            self.showAssetCreator(
+                                function() {location.href = redir}
+                            );
+                        } else {
+                           location.href = redir;
+                        }
                     }
                 }
             }
diff --git a/Open-ILS/web/js/ui/default/acq/common/vlagent.js b/Open-ILS/web/js/ui/default/acq/common/vlagent.js
new file mode 100644
index 0000000..1af1f77
--- /dev/null
+++ b/Open-ILS/web/js/ui/default/acq/common/vlagent.js
@@ -0,0 +1,98 @@
+dojo.require('openils.widget.AutoFieldWidget');
+
+function VLAgent(args) {
+    args = args || {};
+    for (var key in args) { 
+        this[key] = args[key]; 
+    }
+
+    this.widgets = [  
+        {key : 'import_no_match'},
+        {key : 'auto_overlay_exact'},
+        {key : 'auto_overlay_1match'},
+        {key : 'auto_overlay_best_match'},
+        {key : 'match_quality_ratio'},
+        {key : 'queue_name'},
+        {key : 'match_set', cls : 'vms'},
+        {key : 'bib_source', cls : 'cbs'},
+        {key : 'merge_profile', cls : 'vmp'},
+        {key : 'fall_through_merge_profile', cls : 'vmp'},
+        {key : 'existing_queue', cls : 'vbq'}
+    ];
+    
+    this.loaded = false;
+
+    this.init = function() {
+        var self = this;
+
+        dojo.forEach(this.widgets,
+            function(widg) {
+                if (widg.cls) { // selectors
+
+                    new openils.widget.AutoFieldWidget({
+                        fmClass : widg.cls,
+                        selfReference : true,
+                        orgLimitPerms : [self.limitPerm || 'CREATE_PURCHASE_ORDER'],
+                        parentNode : dojo.byId('acq_vl:' + widg.key)
+                    }).build(function(dijit) { 
+                        widg.dijit = dijit; 
+                    }); 
+
+                } else { // bools
+                    widg.dijit = dijit.byId('acq_vl:' + widg.key);
+                }
+            }
+        );
+        
+        // loaded != all widgets are done rendering,
+        // only that init() has been called.
+        this.loaded = true;
+    }
+
+    this.values = function() {
+        var values = {};
+        dojo.forEach(this.widgets,
+            function(widg) {
+                values[widg.key] = widg.dijit.attr('value');
+            }
+        );
+        return values;
+    }
+
+    this.handleResponse = function(resp, oncomplete) {
+        if(!resp) return;
+        var res = {}
+
+        console.log('vandelay import returned : ' + js2JSON(resp));
+
+        // update the display counts
+        dojo.byId('acq_vl:li-processed').innerHTML = resp.li;
+        dojo.byId('acq_vl:vqbr-processed').innerHTML = resp.vqbr;
+        dojo.byId('acq_vl:bibs-processed').innerHTML = resp.bibs;
+        dojo.byId('acq_vl:lid-processed').innerHTML = resp.lid;
+        dojo.byId('acq_vl:debits-processed').innerHTML = resp.debits_accrued;
+        dojo.byId('acq_vl:copies-processed').innerHTML = resp.copies;
+
+        if (resp.complete) {
+
+            if(resp.picklist) {
+                res.picklist_url = oilsBasePath + '/acq/picklist/view/' + resp.picklist.id();
+            } 
+
+            if(resp.purchase_order) {
+                res.po_url = oilsBasePath + '/acq/po/view/' + resp.purchase_order.id();
+            }
+
+            if (resp.queue) {
+                res.queue_url = oilsBasePath + '/vandelay/vandelay?qtype=bib&qid=' + resp.queue.id();
+            }
+
+            if (oncomplete) 
+                oncomplete(resp, res);
+
+            return res;
+        }
+
+        return false; // not yet complete
+    }
+}
diff --git a/Open-ILS/web/js/ui/default/acq/picklist/upload.js b/Open-ILS/web/js/ui/default/acq/picklist/upload.js
index 62a7145..d857b62 100644
--- a/Open-ILS/web/js/ui/default/acq/picklist/upload.js
+++ b/Open-ILS/web/js/ui/default/acq/picklist/upload.js
@@ -13,6 +13,7 @@ dojo.require('openils.acq.Picklist');
 var VANDELAY_URL = '/vandelay-upload';
 var providerWidget;
 var orderAgencyWidget;
+var vlAgent;
 
 function init() {
     dojo.byId('acq-pl-upload-ses').value = openils.User.authtoken;
@@ -35,6 +36,9 @@ function init() {
         function(w) { orderAgencyWidget = w }
     );
 
+    vlAgent = new VLAgent();
+    vlAgent.init();
+
     fieldmapper.standardRequest(
         ['open-ils.acq', 'open-ils.acq.picklist.user.retrieve.atomic'],
         {   async: true,
@@ -64,7 +68,7 @@ function acqUploadRecords() {
                         function(plId) { acqSendUploadForm({picklist:plId}) }
                     );
                 } else {
-                    acqSendUploadForm({picklist:items[0].id});
+                    acqSendUploadForm({picklist:items[0].id[0]});
                 }
             }
         });
@@ -79,53 +83,58 @@ function acqSendUploadForm(args) {
         method: "post",
         handleAs: "html",
         form: dojo.byId('acq-pl-upload-form'),
-        content : {
-            picklist : args.picklist,
-            provider : providerWidget.attr('value'),
-            ordering_agency : orderAgencyWidget.attr('value')
-        },
         handle: function(data, ioArgs){
-            acqHandlePostUpload(data.documentElement.textContent);
+            acqHandlePostUpload(data.documentElement.textContent, args.picklist);
         }
     });
 }
 
 
-function acqHandlePostUpload(key) {
+function acqHandlePostUpload(key, plId) {
+
+    var args = {
+        picklist : plId,
+        provider : providerWidget.attr('value'),
+        ordering_agency : orderAgencyWidget.attr('value'),
+        create_po : acqPlUploadCreatePo.attr('value'),
+        activate_po : acqPlUploadActivatePo.attr('value'),
+        vandelay : vlAgent.values()
+    };
+
     fieldmapper.standardRequest(
         ['open-ils.acq', 'open-ils.acq.process_upload_records'],
         {   async: true,
-            params: [openils.User.authtoken, key],
+            params: [openils.User.authtoken, key, args],
             onresponse : function(r) {
-                var resp = openils.Util.readResponse(r);
-                console.log(js2JSON(resp));
-                if(!resp) return;
-                if(resp.complete) {
-                    openils.Util.hide('acq-pl-upload-complete-pl');
-                    openils.Util.hide('acq-pl-upload-complete-po');
-                    openils.Util.hide('acq-pl-upload-progress-bar');
-                    openils.Util.show('acq-pl-upload-complete');
-
-                    if(resp.picklist) {
-                        openils.Util.show('acq-pl-upload-complete-pl');
-                        dojo.byId('acq-pl-upload-complete-pl').setAttribute(
-                            'href', oilsBasePath + '/acq/picklist/view/' + resp.picklist.id());
-                    } 
-
-                    if(resp.purchase_order) {
-                        openils.Util.show('acq-pl-upload-complete-po');
-                        dojo.byId('acq-pl-upload-complete-po').setAttribute(
-                            'href', oilsBasePath + '/acq/po/view/' + resp.purchase_order.id());
-                    }
 
-                } else {
-                    dojo.byId('acq-pl-upload-li-processed').innerHTML = resp.li;
-                    dojo.byId('acq-pl-upload-lid-processed').innerHTML = resp.lid;
-                    dojo.byId('acq-pl-upload-debits-processed').innerHTML = resp.debits_accrued;
-                    dojo.byId('acq-pl-upload-bibs-processed').innerHTML = resp.bibs;
-                    dojo.byId('acq-pl-upload-indexed-processed').innerHTML = resp.indexed;
-                    dojo.byId('acq-pl-upload-copies-processed').innerHTML = resp.copies;
-                }
+                vlAgent.handleResponse(
+                    openils.Util.readResponse(r),
+                    function(resp, res) {
+
+                        openils.Util.hide('acq-pl-upload-complete-pl');
+                        openils.Util.hide('acq-pl-upload-complete-po');
+                        openils.Util.hide('acq-pl-upload-complete-q');
+                        openils.Util.hide('acq-pl-upload-progress-bar');
+                        openils.Util.show('acq-pl-upload-complete');
+
+                        if(res.picklist_url) {
+                            openils.Util.show('acq-pl-upload-complete-pl');
+                            dojo.byId('acq-pl-upload-complete-pl').setAttribute('href', res.picklist_url);
+                        } 
+
+                        if(res.po_url) {
+                            openils.Util.show('acq-pl-upload-complete-po');
+                            dojo.byId('acq-pl-upload-complete-po').setAttribute('href', res.po_url);
+                        }
+
+                        if (res.queue_url) {
+                            link = dojo.byId('acq-pl-upload-complete-q');
+                            openils.Util.show(link);
+                            link.setAttribute('href', res.queue_url);
+                            link.innerHTML = resp.queue.name();
+                        }
+                    }
+                );
             },
         }
     );
diff --git a/Open-ILS/web/js/ui/default/acq/po/view_po.js b/Open-ILS/web/js/ui/default/acq/po/view_po.js
index 8e510f9..6c08ce1 100644
--- a/Open-ILS/web/js/ui/default/acq/po/view_po.js
+++ b/Open-ILS/web/js/ui/default/acq/po/view_po.js
@@ -513,6 +513,23 @@ function activatePo() {
             return false;
     }
 
+    // first, let's see if this PO has any LI's that need to be merged/imported
+    pcrud.search('jub', {purchase_order : poId, eg_bib_id : null}, {
+        id_list : true,
+        oncomplete : function(r) {
+            var resp = openils.Util.readResponse(r);
+            if (resp && resp.length) {
+                // kick off the merge/import process
+                liTable.showAssetCreator(activatePoStage2);
+            } else {
+                activatePoStage2();
+            }
+        }
+    });
+}
+
+function activatePoStage2() {
+
     var want_refresh = false;
     progressDialog.show(true);
     fieldmapper.standardRequest(

commit 468ee3248766650d468b4ff629e0a06f54ce4dd5
Author: Bill Erickson <berick at esilibrary.com>
Date:   Wed Nov 30 15:42:30 2011 -0500

    ACQ+Vandelay API to support Vandelay-mediated imports
    
    Adds support for merging, overlaying, importing, and linking (a no-op
    merge) acquisitions lineitems to catalog records via Vandelay.
    
    All non-imported lineitems will now be processed through Vandelay during
    record upload and asset creation (load bibs and items), based on the
    Vandelay import parameters provided by the caller.  Each processed
    lineitem will also be linked to its queued Vandelay record.  In the case
    of a failed import, such records can be subsequently imported manually
    from the Vandelay interface using the manual record overlay options.
    
    ACQ API calls affected now report on the progress of Vandelay record
    import in addition to lineitem creation, copy creation, etc.
    
    Signed-off-by: Bill Erickson <berick at esilibrary.com>
    Signed-off-by: Ben Shum <bshum at biblio.org>

diff --git a/Open-ILS/src/perlmods/lib/OpenILS/Application/Acq/Order.pm b/Open-ILS/src/perlmods/lib/OpenILS/Application/Acq/Order.pm
index b0290a5..5fa0bc2 100644
--- a/Open-ILS/src/perlmods/lib/OpenILS/Application/Acq/Order.pm
+++ b/Open-ILS/src/perlmods/lib/OpenILS/Application/Acq/Order.pm
@@ -10,6 +10,7 @@ sub new {
     $self->{args} = {
         lid => 0,
         li => 0,
+        vqbr => 0,
         copies => 0,
         bibs => 0,
         progress => 0,
@@ -18,9 +19,9 @@ sub new {
         picklist => undef,
         complete => 0,
         indexed => 0,
+        queue => undef,
         total => 0
     };
-    $self->{ingest_queue} = [];
     $self->{cache} = {};
     $self->throttle(5) unless $self->throttle;
     $self->{post_proc_queue} = [];
@@ -96,6 +97,12 @@ sub add_li {
     $self->{args}->{progress} += 1;
     return $self;
 }
+sub add_vqbr {
+    my $self = shift;
+    $self->{args}->{vqbr} += 1;
+    $self->{args}->{progress} += 1;
+    return $self;
+}
 sub add_copy {
     my $self = shift;
     $self->{args}->{copies} += 1;
@@ -125,41 +132,6 @@ sub complete {
     return $self;
 }
 
-sub ingest_ses {
-    my($self, $val) = @_;
-    $self->{ingest_ses} = $val if $val;
-    return $self->{ingest_ses};
-}
-
-sub push_ingest_queue {
-    my($self, $rec_id) = @_;
-
-    $self->ingest_ses(OpenSRF::AppSession->connect('open-ils.ingest'))
-        unless $self->ingest_ses;
-
-    my $req = $self->ingest_ses->request('open-ils.ingest.full.biblio.record', $rec_id);
-
-    push(@{$self->{ingest_queue}}, $req);
-}
-
-sub process_ingest_records {
-    my $self = shift;
-    return unless @{$self->{ingest_queue}};
-
-    for my $req (@{$self->{ingest_queue}}) {
-
-        try { 
-            $req->gather(1); 
-            $self->{args}->{indexed} += 1;
-            $self->{args}->{progress} += 1;
-        } otherwise {};
-
-        $self->respond;
-    }
-    $self->ingest_ses->disconnect;
-}
-
-
 sub cache {
     my($self, $org, $key, $val) = @_;
     $self->{cache}->{$org} = {} unless $self->{cache}->{org};
@@ -190,6 +162,9 @@ use OpenILS::Application::Cat::AssetCommon;
 use MARC::Record;
 use MARC::Batch;
 use MARC::File::XML (BinaryEncoding => 'UTF-8');
+use Digest::MD5 qw(md5_hex);
+use Data::Dumper;
+$Data::Dumper::Indent = 0;
 my $U = 'OpenILS::Application::AppUtils';
 
 
@@ -320,20 +295,186 @@ sub delete_lineitem {
 
 # begins and commit transactions as it goes
 sub create_lineitem_list_assets {
-    my($mgr, $li_ids) = @_;
-    return undef if check_import_li_marc_perms($mgr, $li_ids);
+    my($mgr, $li_ids, $vandelay) = @_;
 
-    # create the bibs/volumes/copies and ingest the records
-    for my $li_id (@$li_ids) {
+    if (check_import_li_marc_perms($mgr, $li_ids)) { # event on error
+        $logger->error("acq-vl: user does not have permission to import acq records");
+        return undef;
+    }
+
+    my $res = import_li_bibs_via_vandelay($mgr, $li_ids, $vandelay);
+    return undef unless $res;
+
+    # create the bibs/volumes/copies for the successfully imported records
+    for my $li_id (@{$res->{li_ids}}) {
         $mgr->editor->xact_begin;
         my $data = create_lineitem_assets($mgr, $li_id) or return undef;
         $mgr->editor->xact_commit;
-        # XXX ingest is in-db now
-        #$mgr->push_ingest_queue($data->{li}->eg_bib_id) if $data->{new_bib};
         $mgr->respond;
     }
-    $mgr->process_ingest_records;
-    return 1;
+
+    return $res;
+}
+
+sub verify_vandelay_import_args {
+    my $vandelay = shift;
+
+    # we need a queue
+    return 0 unless $vandelay and 
+        ($vandelay->{queue_name} or $vandelay->{existing_queue});
+
+    # match-based merge/overlay import
+    return 1 if $vandelay->{merge_profile} and (
+        $vandelay->{auto_overlay_exact} or
+        $vandelay->{auto_overlay_1match} or
+        $vandelay->{auto_overlay_best_match}
+    );
+
+    # no-match import
+    return 1 if $vandelay->{import_no_match};
+
+    return 0;
+}
+
+sub find_or_create_vandelay_queue {
+    my ($e, $vandelay) = @_;
+
+    my $queue;
+    if (my $name = $vandelay->{queue_name}) {
+
+        # first, see if a queue w/ this name already exists
+        # for this user.  If so, use that instead.
+
+        $queue = $e->search_vandelay_bib_queue(
+            {name => $name, owner => $e->requestor->id})->[0];
+
+        if ($queue) {
+
+            $logger->info("acq-vl: using existing queue $name");
+
+        } else {
+
+            $logger->info("acq-vl: creating new vandelay queue $name");
+
+            $queue = new Fieldmapper::vandelay::bib_queue;
+            $queue->name($name); 
+            $queue->queue_type('acq');
+            $queue->owner($e->requestor->id);
+            $queue->match_set($vandelay->{match_set} || undef); # avoid ''
+            $queue = $e->create_vandelay_bib_queue($queue) or return undef;
+        }
+
+    } else {
+        $queue = $e->retrieve_vandelay_bib_queue($vandelay->{existing_queue})
+            or return undef;
+    }
+    
+    return $queue;
+}
+
+
+sub import_li_bibs_via_vandelay {
+    my ($mgr, $li_ids, $vandelay) = @_;
+    my $res = {li_ids => []};
+    my $e = $mgr->editor;
+    $e->xact_begin;
+
+    my $needs_importing = $e->search_acq_lineitem(
+        {id => $li_ids, eg_bib_id => undef}, 
+        {idlist => 1}
+    );
+
+    if (!@$needs_importing) {
+        $logger->info("acq-vl: all records already imported.  no Vandelay work to do");
+        return {li_ids => $li_ids};
+    }
+
+    # add the already-imported records to the response list
+    push(@{$res->{li_ids}}, grep { $_ != @$needs_importing } @$li_ids);
+
+    $logger->info("acq-vl: processing recs via Vandelay with args: ".Dumper($vandelay));
+
+    if (!verify_vandelay_import_args($vandelay)) {
+        $logger->error("acq-vl: invalid vandelay arguments for acq import");
+        return $res;
+    }
+
+    my $queue = find_or_create_vandelay_queue($e, $vandelay) or return $res;
+    $mgr->{args}->{queue} = $queue;
+
+    # load the lineitems into the queue for merge processing
+    my @vqbr_ids;
+    my @lis;
+    for my $li_id (@$needs_importing) {
+
+        my $li = $e->retrieve_acq_lineitem($li_id) or return $res;
+
+        my $vqbr = Fieldmapper::vandelay::queued_bib_record->new;
+        $vqbr->marc($li->marc);
+        $vqbr->queue($queue->id);
+        $vqbr->bib_source($vandelay->{bib_source} || undef); # avoid ''
+        $vqbr = $e->create_vandelay_queued_bib_record($vqbr) or return $res;
+        push(@vqbr_ids, $vqbr->id);
+        $mgr->add_vqbr;
+        $mgr->respond;
+
+        # tell the acq record which vandelay record it's linked to
+        $li->queued_record($vqbr->id);
+        $e->update_acq_lineitem($li) or return $res;
+        push(@lis, $li);
+    }
+
+    $logger->info("acq-vl: created vandelay records [@vqbr_ids]");
+
+    # we have to commit the transaction now since 
+    # vandelay uses its own transactions.
+    $e->commit;
+
+    # Import the bibs via vandelay.  Note: Vandely will 
+    # update acq.lineitem.eg_bib_id on successful import.
+
+    $vandelay->{report_all} = 1;
+    my $ses = OpenSRF::AppSession->create('open-ils.vandelay');
+    my $req = $ses->request(
+        'open-ils.vandelay.bib_record.list.import',
+        $e->authtoken, \@vqbr_ids, $vandelay);
+
+    # pull the responses, noting all that were successfully imported
+    my @success_lis;
+    while (my $resp = $req->recv(timeout => 600)) {
+        my $stat = $resp->content;
+
+        if(!$stat or $U->event_code($stat)) { # import failure
+            $logger->error("acq-vl: error importing vandelay record " . Dumper($stat));
+            next;
+        }
+
+        # "imported" refers to the vqbr id, not the 
+        # success/failure of the vqbr merge attempt
+        next unless $stat->{imported};
+
+        my ($imported) = grep {$_->queued_record eq $stat->{imported}} @lis;
+        my $li_id = $imported->id;
+
+        if ($stat->{no_import}) {
+            $logger->info("acq-vl: acq lineitem $li_id did not import"); 
+
+        } else { # successful import
+
+            push(@success_lis, $li_id);
+            $mgr->add_bib;
+            $mgr->respond;
+            $logger->info("acq-vl: acq lineitem $li_id successfully merged/imported");
+        } 
+    }
+
+    $ses->kill_me;
+    $logger->info("acq-vl: successfully imported lineitems [@success_lis]");
+
+    # add the successfully imported lineitems to the already-imported lineitems
+    push (@{$res->{li_ids}}, @success_lis);
+
+    return $res;
 }
 
 # returns event on error, undef on success
@@ -965,15 +1106,7 @@ sub create_lineitem_assets {
         }
     ]) or return 0;
 
-    # -----------------------------------------------------------------
-    # first, create the bib record if necessary
-    # -----------------------------------------------------------------
-    my $new_bib = 0;
-    unless($li->eg_bib_id) {
-        create_bib($mgr, $li) or return 0;
-        $new_bib = 1;
-    }
-
+    # note: at this point, the bib record this LI links to should already be created
 
     # -----------------------------------------------------------------
     # The lineitem is going live, promote user request holds to real holds
@@ -1012,29 +1145,7 @@ sub create_lineitem_assets {
         create_copy($mgr, $volume, $lid, $li) or return 0;
     }
 
-    return { li => $li, new_bib => $new_bib };
-}
-
-sub create_bib {
-    my($mgr, $li) = @_;
-
-    my $record = OpenILS::Application::Cat::BibCommon->biblio_record_xml_import(
-        $mgr->editor, 
-        $li->marc, 
-        undef, # bib source
-        undef, 
-        1, # override tcn collisions
-    ); 
-
-    if($U->event_code($record)) {
-        $mgr->editor->event($record);
-        $mgr->editor->rollback;
-        return 0;
-    }
-
-    $li->eg_bib_id($record->id);
-    $mgr->add_bib;
-    return update_lineitem($mgr, $li);
+    return { li => $li };
 }
 
 sub create_volume {
@@ -1186,10 +1297,12 @@ __PACKAGE__->register_method(
     method   => 'upload_records',
     api_name => 'open-ils.acq.process_upload_records',
     stream   => 1,
+    max_chunk_count => 1
 );
 
 sub upload_records {
-    my($self, $conn, $auth, $key) = @_;
+    my($self, $conn, $auth, $key, $args) = @_;
+    $args ||= {};
 
 	my $e = new_editor(authtoken => $auth, xact => 1);
     return $e->die_event unless $e->checkauth;
@@ -1198,14 +1311,13 @@ sub upload_records {
     my $cache = OpenSRF::Utils::Cache->new;
 
     my $data = $cache->get_cache("vandelay_import_spool_$key");
-    my $purpose         = $data->{purpose};
     my $filename        = $data->{path};
-    my $provider        = $data->{provider};
-    my $picklist        = $data->{picklist};
-    my $create_po       = $data->{create_po};
-    my $activate_po     = $data->{activate_po};
-    my $ordering_agency = $data->{ordering_agency};
-    my $create_assets   = $data->{create_assets};
+    my $provider        = $args->{provider};
+    my $picklist        = $args->{picklist};
+    my $create_po       = $args->{create_po};
+    my $activate_po     = $args->{activate_po};
+    my $ordering_agency = $args->{ordering_agency};
+    my $vandelay        = $args->{vandelay};
     my $po;
     my $evt;
 
@@ -1290,15 +1402,16 @@ sub upload_records {
         $mgr->respond;
 	}
 
-    my $die_event = activate_purchase_order_impl($mgr, $po->id) if $po and $activate_po;
-    return $die_event if $die_event;
-
 	$e->commit;
     unlink($filename);
     $cache->delete_cache('vandelay_import_spool_' . $key);
 
-    if ($create_assets) {
-        create_lineitem_list_assets($mgr, \@li_list) or return $e->die_event;
+    if ($po and $activate_po) {
+        my $die_event = activate_purchase_order_impl($mgr, $po->id, $vandelay);
+        return $die_event if $die_event;
+
+    } elsif ($vandelay) {
+        create_lineitem_list_assets($mgr, \@li_list, $vandelay) or return $e->die_event;
     }
 
     return $mgr->respond_complete;
@@ -1456,11 +1569,13 @@ __PACKAGE__->register_method(
             {desc => 'The purchase order id', type => 'number'},
         ],
         return => {desc => 'Streams a total versus completed counts object, event on error'}
-    }
+    },
+    max_chunk_count => 1
 );
 
 sub create_po_assets {
-    my($self, $conn, $auth, $po_id) = @_;
+    my($self, $conn, $auth, $po_id, $args) = @_;
+    $args ||= {};
 
     my $e = new_editor(authtoken=>$auth, xact=>1);
     return $e->die_event unless $e->checkauth;
@@ -1487,7 +1602,8 @@ sub create_po_assets {
 
     $mgr->total(scalar(@$li_ids) + $lid_total);
 
-    create_lineitem_list_assets($mgr, $li_ids) or return $e->die_event;
+    create_lineitem_list_assets($mgr, $li_ids, $args->{vandelay}) 
+        or return $e->die_event;
 
     $e->xact_begin;
     update_purchase_order($mgr, $po) or return $e->die_event;
@@ -1508,7 +1624,8 @@ __PACKAGE__->register_method(
             {desc => 'purchase_order to create', type => 'object'}
         ],
         return => {desc => 'The purchase order id, Event on failure'}
-    }
+    },
+    max_chunk_count => 1
 );
 
 sub create_purchase_order_api {
@@ -1525,6 +1642,7 @@ sub create_purchase_order_api {
     $pargs{provider}            = $po->provider            if $po->provider;
     $pargs{ordering_agency}     = $po->ordering_agency     if $po->ordering_agency;
     $pargs{prepayment_required} = $po->prepayment_required if $po->prepayment_required;
+    my $vandelay = $args->{vandelay};
         
     $po = create_purchase_order($mgr, %pargs) or return $e->die_event;
 
@@ -1550,8 +1668,8 @@ sub create_purchase_order_api {
     # commit before starting the asset creation
     $e->xact_commit;
 
-    if($li_ids and $$args{create_assets}) {
-        create_lineitem_list_assets($mgr, $li_ids) or return $e->die_event;
+    if($li_ids and $vandelay) {
+        create_lineitem_list_assets($mgr, $li_ids, $vandelay) or return $e->die_event;
     }
 
     return $mgr->respond_complete;
@@ -1842,7 +1960,7 @@ sub receive_lineitem_api {
     my $res = receive_lineitem($mgr, $li_id) or return $e->die_event;
     $e->commit;
     $conn->respond_complete($res);
-    $mgr->run_post_response_hooks;
+    $mgr->run_post_response_hooks
 }
 
 
@@ -2174,54 +2292,58 @@ __PACKAGE__->register_method(
 );
 
 sub activate_purchase_order {
-    my($self, $conn, $auth, $po_id) = @_;
+    my($self, $conn, $auth, $po_id, $vandelay) = @_;
 
     my $dry_run = ($self->api_name =~ /\.dry_run/) ? 1 : 0;
-    my $e = new_editor(xact=>1, authtoken=>$auth);
+    my $e = new_editor(authtoken=>$auth);
     return $e->die_event unless $e->checkauth;
     my $mgr = OpenILS::Application::Acq::BatchManager->new(editor => $e, conn => $conn);
-    my $die_event = activate_purchase_order_impl($mgr, $po_id, $dry_run);
+    my $die_event = activate_purchase_order_impl($mgr, $po_id, $vandelay, $dry_run);
     return $e->die_event if $die_event;
-    if ($dry_run) {
-        $e->rollback;
-    } else {
-        $e->commit;
-    }
     $conn->respond_complete(1);
-    $mgr->run_post_response_hooks;
+    $mgr->run_post_response_hooks unless $dry_run;
     return undef;
 }
 
+# xacts managed within
 sub activate_purchase_order_impl {
-    my ($mgr, $po_id, $dry_run) = @_;
+    my ($mgr, $po_id, $vandelay, $dry_run) = @_;
+
+    # read-only until lineitem asset creation
     my $e = $mgr->editor;
+    $e->xact_begin;
 
     my $po = $e->retrieve_acq_purchase_order($po_id) or return $e->die_event;
     return $e->die_event unless $e->allowed('CREATE_PURCHASE_ORDER', $po->ordering_agency);
-
     my $provider = $e->retrieve_acq_provider($po->provider);
 
-    $po->state('on-order');
-    $po->order_date('now');
-    update_purchase_order($mgr, $po) or return $e->die_event;
+    # find lineitems and create assets for all
 
-    my $query = [
-        {
-            purchase_order => $po_id, 
-            state => [qw/pending-order new order-ready/]
-        },
-        {limit => 1}
-    ];
+    my $query = {   
+        purchase_order => $po_id, 
+        state => [qw/pending-order new order-ready/]
+    };
 
-    while( my $li_id = $e->search_acq_lineitem($query, {idlist => 1})->[0] ) {
+    my $li_ids = $e->search_acq_lineitem($query, {idlist => 1});
 
-        my $li;
-        if($dry_run) {
-            $li = $e->retrieve_acq_lineitem($li_id);
-        } else {
-            # can't activate a PO w/o assets.  Create lineitem assets as necessary
-            my $data = create_lineitem_assets($mgr, $li_id) or return $e->die_event;
-            $li = $data->{li};
+    my $vl_resp; # imported li's and the queue the managing queue
+    if (!$dry_run) {
+        $e->rollback; # read-only thus far
+        $vl_resp = create_lineitem_list_assets($mgr, $li_ids, $vandelay)
+            or return OpenILS::Event->new('ACQ_LI_IMPORT_FAILED');
+        $e->xact_begin;
+    }
+
+    # create fund debits for lineitems 
+
+    for my $li_id (@$li_ids) {
+        my $li = $e->retrieve_acq_lineitem($li_id);
+        
+        if (!$li->eg_bib_id and !$dry_run) {
+            # we encountered a lineitem that was not successfully imported.
+            # we cannot continue.  rollback and report.
+            $e->rollback;
+            return OpenILS::Event->new('ACQ_LI_IMPORT_FAILED', {queue => $vl_resp->{queue}});
         }
 
         $li->state('on-order');
@@ -2233,6 +2355,8 @@ sub activate_purchase_order_impl {
         $mgr->respond;
     }
 
+    # create po-item debits
+
     for my $po_item (@{$e->search_acq_po_item({purchase_order => $po_id})}) {
 
         my $debit = create_fund_debit(
@@ -2249,6 +2373,15 @@ sub activate_purchase_order_impl {
         $mgr->respond;
     }
 
+    # mark PO as ordered
+
+    $po->state('on-order');
+    $po->order_date('now');
+    update_purchase_order($mgr, $po) or return $e->die_event;
+
+    # clean up the xact
+    $dry_run and $e->rollback or $e->commit;
+
     # tell the world we activated a PO
     $U->create_events_for_hook('acqpo.activated', $po, $po->ordering_agency) unless $dry_run;
 
diff --git a/Open-ILS/src/perlmods/lib/OpenILS/Application/Vandelay.pm b/Open-ILS/src/perlmods/lib/OpenILS/Application/Vandelay.pm
index c4d4332..8502d51 100644
--- a/Open-ILS/src/perlmods/lib/OpenILS/Application/Vandelay.pm
+++ b/Open-ILS/src/perlmods/lib/OpenILS/Application/Vandelay.pm
@@ -875,6 +875,8 @@ sub import_record_list_impl {
         report_all => $$args{report_all}
     };
 
+    $conn->max_chunk_count(1) if $$args{report_all};
+
     my $auto_overlay_exact = $$args{auto_overlay_exact};
     my $auto_overlay_1match = $$args{auto_overlay_1match};
     my $auto_overlay_best = $$args{auto_overlay_best_match};
@@ -892,6 +894,7 @@ sub import_record_list_impl {
     my $search_func = 'search_vandelay_queued_bib_record';
     my $retrieve_queue_func = 'retrieve_vandelay_bib_queue';
     my $update_queue_func = 'update_vandelay_bib_queue';
+    my $delete_queue_func = 'delete_vandelay_bib_queue';
     my $rec_class = 'vqbr';
 
     my $editor = new_editor();
@@ -908,6 +911,7 @@ sub import_record_list_impl {
         $update_queue_func =~ s/bib/authority/o;
         $update_func =~ s/bib/authority/o;
         $search_func =~ s/bib/authority/o;
+        $delete_queue_func =~ s/bib/authority/o;
         $rec_class = 'vqar';
     }
 
@@ -923,6 +927,7 @@ sub import_record_list_impl {
         $$report_args{e} = $e;
         $$report_args{evt} = undef;
         $$report_args{import_error} = undef;
+        $$report_args{no_import} = 0;
 
         my $rec = $e->$retrieve_func([
             $rec_id,
@@ -1086,6 +1091,19 @@ sub import_record_list_impl {
 
             if($e->$update_func($rec)) {
 
+                if($type eq 'bib') {
+
+                    # see if this record is linked from an acq record.
+                    my $li = $e->search_acq_lineitem(
+                        {queued_record => $rec->id, state => {'!=' => 'canceled'}})->[0];
+
+                    if ($li) { 
+                        # if so, update the acq lineitem to point to the imported record
+                        $li->eg_bib_id($rec->imported_as);
+                        $$report_args{evt} = $e->die_event unless $e->update_acq_lineitem($li);
+                    }
+                }
+
                 push @success_rec_ids, $rec_id;
                 finish_rec_import_attempt($report_args);
 
@@ -1097,6 +1115,7 @@ sub import_record_list_impl {
         if(!$imported) {
             $logger->info("vl: record $rec_id was not imported");
             $$report_args{evt} = $e->event unless $$report_args{evt};
+            $$report_args{no_import} = 1;
             finish_rec_import_attempt($report_args);
         }
     }
@@ -1110,7 +1129,6 @@ sub import_record_list_impl {
 
         unless(@$remaining) {
             my $queue = $e->$retrieve_queue_func($q_id);
-
             unless($U->is_true($queue->complete)) {
                 $queue->complete('t');
                 $e->$update_queue_func($queue) or return $e->die_event;
@@ -1279,6 +1297,8 @@ sub finish_rec_import_attempt {
             total => $$args{total}, 
             progress => $$args{progress}, 
             imported => ($rec) ? $rec->id : undef,
+            import_error => $error,
+            no_import => $$args{no_import},
             err_event => $evt
         });
         $$args{step} *= 2 unless $$args{step} == 256;
diff --git a/Open-ILS/src/perlmods/lib/OpenILS/WWW/Vandelay.pm b/Open-ILS/src/perlmods/lib/OpenILS/WWW/Vandelay.pm
index f5cb956..0cdc41d 100644
--- a/Open-ILS/src/perlmods/lib/OpenILS/WWW/Vandelay.pm
+++ b/Open-ILS/src/perlmods/lib/OpenILS/WWW/Vandelay.pm
@@ -66,15 +66,8 @@ sub spool_marc {
 	my $purpose = $cgi->param('purpose') || '';
 	my $infile = $cgi->param('marc_upload') || '';
     my $bib_source = $cgi->param('bib_source') || '';
-    my $provider = $cgi->param('provider') || '';
-    my $picklist = $cgi->param('picklist') || '';
-    my $create_po = $cgi->param('create_po') || '';
-    my $activate_po = $cgi->param('activate_po') || '';
-    my $ordering_agency = $cgi->param('ordering_agency') || '';
-    my $create_assets = $cgi->param('create_assets') || '';
 
-    $logger->debug("purpose = $purpose, infile = $infile, bib_source = $bib_source ".
-        "provider = $provider, picklist = $picklist, create_po = $create_po, ordering_agency = $ordering_agency");
+    $logger->debug("purpose = $purpose, infile = $infile, bib_source = $bib_source");
 
 	my $conf = OpenSRF::Utils::SettingsClient->new;
 	my $dir = $conf->config_value(
@@ -113,11 +106,6 @@ sub spool_marc {
 		    {   purpose => $purpose, 
                 path => $outfile,
                 bib_source => $bib_source,
-                provider => $provider,
-                picklist => $picklist,
-                create_po => $create_po,
-                create_assets => $create_assets,
-                ordering_agency => $ordering_agency
             }
 	    );
     }

commit c8b172c0ebaa2434b70b996edfdf7b2271d19622
Author: Bill Erickson <berick at esilibrary.com>
Date:   Wed Nov 30 14:54:41 2011 -0500

    ACQ+Vandelay schema and IDL changes w/ upgrade script
    
    Adds a queued_record link from acq lineitems to vandelay queued record.
    Ditto acq_lineitem_history.  This will be used to link vandelay-mediated
    acq lineitems to the vandelay record used for their import.
    
    For ease of future changes, port the queue_type column from bib and
    authority queues to ENUMs and drop the constraint, which is implicit in
    the ENUM.
    
    Signed-off-by: Bill Erickson <berick at esilibrary.com>
    Signed-off-by: Ben Shum <bshum at biblio.org>

diff --git a/Open-ILS/examples/fm_IDL.xml b/Open-ILS/examples/fm_IDL.xml
index 94e1aa2..b0ab837 100644
--- a/Open-ILS/examples/fm_IDL.xml
+++ b/Open-ILS/examples/fm_IDL.xml
@@ -7156,6 +7156,7 @@ SELECT  usr,
 			<field reporter:label="Claim Policy" name="claim_policy" reporter:datatype="link" />
 			<field reporter:label="Cancel Reason" name="cancel_reason" reporter:datatype="link" />
 			<field reporter:label="Estimated Unit Price" name="estimated_unit_price" reporter:datatype="money" />
+			<field reporter:label="Queued Vandelay Record" name="queued_record" reporter:datatype="link" />
 			<field reporter:label="Item Count" name="item_count" oils_persist:virtual="true" reporter:datatype="int" />
 			<field reporter:label="Descriptive Attributes" name="attributes" oils_persist:virtual="true" reporter:datatype="link" />
 			<field reporter:label="Line Item Details" name="lineitem_details" oils_persist:virtual="true" reporter:datatype="link" />
@@ -7180,6 +7181,7 @@ SELECT  usr,
 			<link field="claim_policy" reltype="has_a" key="id" map="" class="acqclp"/>
 			<link field="invoice_entries" reltype="has_many" key="lineitem" map="" class="acqie"/>
 			<link field="order_summary" reltype="might_have" key="lineitem" map="" class="acqlisum"/>
+			<link field="queued_record" reltype="has_a" key="id" map="" class="vqbr"/>
 		</links>
 		<permacrud xmlns="http://open-ils.org/spec/opensrf/IDL/permacrud/v1">
 			<actions>
@@ -7213,6 +7215,7 @@ SELECT  usr,
 			<field reporter:label="Claim Policy" name="claim_policy" reporter:datatype="link"/>
 			<field reporter:label="Cancel Reason" name="cancel_reason" reporter:datatype="link"/>
 			<field reporter:label="Estimated Unit Price" name="estimated_unit_price" reporter:datatype="money" />
+			<field reporter:label="Queued Vandelay Record" name="queued_record" reporter:datatype="link" />
 		</fields>
 		<links>
 			<link field="id" reltype="has_a" key="id" map="" class="jub"/>
@@ -7225,6 +7228,7 @@ SELECT  usr,
 			<link field="eg_bib_id" reltype="has_a" key="id" map="" class="bre"/>
 			<link field="cancel_reason" reltype="has_a" key="id" map="" class="acqcr"/>
 			<link field="claim_policy" reltype="has_a" key="id" map="" class="acqclp"/>
+			<link field="queued_record" reltype="has_a" key="id" map="" class="vqbr"/>
 		</links>
 		<permacrud xmlns="http://open-ils.org/spec/opensrf/IDL/permacrud/v1">
 			<actions>
diff --git a/Open-ILS/src/sql/Pg/012.schema.vandelay.sql b/Open-ILS/src/sql/Pg/012.schema.vandelay.sql
index 4b6c525..65e2ca7 100644
--- a/Open-ILS/src/sql/Pg/012.schema.vandelay.sql
+++ b/Open-ILS/src/sql/Pg/012.schema.vandelay.sql
@@ -50,9 +50,7 @@ CREATE TABLE vandelay.queue (
 	owner			INT			NOT NULL REFERENCES actor.usr (id) DEFERRABLE INITIALLY DEFERRED,
 	name			TEXT		NOT NULL,
 	complete		BOOL		NOT NULL DEFAULT FALSE,
-	queue_type		TEXT		NOT NULL DEFAULT 'bib' CHECK (queue_type IN ('bib','authority')),
-    match_set       INT         REFERENCES vandelay.match_set (id) ON UPDATE CASCADE ON DELETE SET NULL DEFERRABLE INITIALLY DEFERRED,
-	CONSTRAINT vand_queue_name_once_per_owner_const UNIQUE (owner,name,queue_type)
+    match_set       INT         REFERENCES vandelay.match_set (id) ON UPDATE CASCADE ON DELETE SET NULL DEFERRABLE INITIALLY DEFERRED
 );
 
 CREATE TABLE vandelay.queued_record (
@@ -114,8 +112,10 @@ CREATE TABLE vandelay.import_error (
     description TEXT    NOT NULL -- i18n
 );
 
+CREATE TYPE vandelay.bib_queue_queue_type AS ENUM ('bib', 'acq');
+
 CREATE TABLE vandelay.bib_queue (
-	queue_type	    TEXT	NOT NULL DEFAULT 'bib' CHECK (queue_type = 'bib'),
+	queue_type	    vandelay.bib_queue_queue_type	NOT NULL DEFAULT 'bib',
 	item_attr_def	BIGINT REFERENCES vandelay.import_item_attr_definition (id) ON DELETE SET NULL DEFERRABLE INITIALLY DEFERRED,
 	CONSTRAINT vand_bib_queue_name_once_per_owner_const UNIQUE (owner,name,queue_type)
 ) INHERITS (vandelay.queue);
@@ -1518,8 +1518,9 @@ CREATE TABLE vandelay.authority_attr_definition (
 	remove		TEXT	NOT NULL DEFAULT ''
 );
 
+CREATE TYPE vandelay.authority_queue_queue_type AS ENUM ('authority');
 CREATE TABLE vandelay.authority_queue (
-	queue_type	TEXT		NOT NULL DEFAULT 'authority' CHECK (queue_type = 'authority'),
+	queue_type	vandelay.authority_queue_queue_type NOT NULL DEFAULT 'authority',
 	CONSTRAINT vand_authority_queue_name_once_per_owner_const UNIQUE (owner,name,queue_type)
 ) INHERITS (vandelay.queue);
 ALTER TABLE vandelay.authority_queue ADD PRIMARY KEY (id);
diff --git a/Open-ILS/src/sql/Pg/200.schema.acq.sql b/Open-ILS/src/sql/Pg/200.schema.acq.sql
index 8765c4a..2263898 100644
--- a/Open-ILS/src/sql/Pg/200.schema.acq.sql
+++ b/Open-ILS/src/sql/Pg/200.schema.acq.sql
@@ -486,6 +486,8 @@ CREATE TABLE acq.lineitem (
 	estimated_unit_price NUMERIC,
 	claim_policy        INT                         REFERENCES acq.claim_policy
 			                                        DEFERRABLE INITIALLY DEFERRED,
+    queued_record       BIGINT                      REFERENCES vandelay.queued_bib_record (id)
+                                                        ON DELETE SET NULL DEFERRABLE INITIALLY DEFERRED,
     CONSTRAINT picklist_or_po CHECK (picklist IS NOT NULL OR purchase_order IS NOT NULL)
 );
 CREATE INDEX li_po_idx ON acq.lineitem (purchase_order);
diff --git a/Open-ILS/src/sql/Pg/upgrade/XXXX.schema.acq-vandelay-integration.sql b/Open-ILS/src/sql/Pg/upgrade/XXXX.schema.acq-vandelay-integration.sql
new file mode 100644
index 0000000..213c7ac
--- /dev/null
+++ b/Open-ILS/src/sql/Pg/upgrade/XXXX.schema.acq-vandelay-integration.sql
@@ -0,0 +1,72 @@
+-- Evergreen DB patch XXXX.schema.acq-vandelay-integration.sql
+BEGIN;
+
+-- check whether patch can be applied
+SELECT evergreen.upgrade_deps_block_check('XXXX', :eg_version);
+
+-- schema --
+
+-- Replace the constraints with more flexible ENUM's
+ALTER TABLE vandelay.queue DROP CONSTRAINT queue_queue_type_check;
+ALTER TABLE vandelay.bib_queue DROP CONSTRAINT bib_queue_queue_type_check;
+ALTER TABLE vandelay.authority_queue DROP CONSTRAINT authority_queue_queue_type_check;
+
+CREATE TYPE vandelay.bib_queue_queue_type AS ENUM ('bib', 'acq');
+CREATE TYPE vandelay.authority_queue_queue_type AS ENUM ('authority');
+
+-- dropped column is also implemented by the child tables
+ALTER TABLE vandelay.queue DROP COLUMN queue_type; 
+
+-- to recover after using the undo sql from below
+-- alter table vandelay.bib_queue  add column queue_type text default 'bib' not null;
+-- alter table vandelay.authority_queue  add column queue_type text default 'authority' not null;
+
+-- modify the child tables to use the ENUMs
+ALTER TABLE vandelay.bib_queue 
+    ALTER COLUMN queue_type DROP DEFAULT,
+    ALTER COLUMN queue_type TYPE vandelay.bib_queue_queue_type 
+        USING (queue_type::vandelay.bib_queue_queue_type),
+    ALTER COLUMN queue_type SET DEFAULT 'bib';
+
+ALTER TABLE vandelay.authority_queue 
+    ALTER COLUMN queue_type DROP DEFAULT,
+    ALTER COLUMN queue_type TYPE vandelay.authority_queue_queue_type 
+        USING (queue_type::vandelay.authority_queue_queue_type),
+    ALTER COLUMN queue_type SET DEFAULT 'authority';
+
+-- give lineitems a pointer to their vandelay queued_record
+
+ALTER TABLE acq.lineitem ADD COLUMN queued_record BIGINT
+    REFERENCES vandelay.queued_bib_record (id) 
+    ON DELETE SET NULL DEFERRABLE INITIALLY DEFERRED;
+
+ALTER TABLE acq.acq_lineitem_history ADD COLUMN queued_record BIGINT
+    REFERENCES vandelay.queued_bib_record (id) 
+    ON DELETE SET NULL DEFERRABLE INITIALLY DEFERRED;
+
+COMMIT;
+
+/* UNDO SQL
+-- XXX this does not exactly recover the state.  The bib/auth queue_type colum is
+-- directly inherited instead of overridden, which will fail with some of the sql above.
+ALTER TABLE acq.lineitem DROP COLUMN queued_record;
+ALTER TABLE acq.acq_lineitem_history DROP COLUMN queued_record;
+ALTER TABLE vandelay.authority_queue DROP COLUMN queue_type;
+ALTER TABLE vandelay.bib_queue DROP COLUMN queue_type;
+
+DROP TYPE vandelay.bib_queue_queue_type;
+DROP TYPE vandelay.authority_queue_queue_type;
+
+ALTER TABLE vandelay.bib_queue DROP CONSTRAINT vand_bib_queue_name_once_per_owner_const;
+ALTER TABLE vandelay.authority_queue DROP CONSTRAINT vand_authority_queue_name_once_per_owner_const;
+
+ALTER TABLE vandelay.queue ADD COLUMN queue_type TEXT NOT NULL DEFAULT 'bib' CHECK (queue_type IN ('bib','authority'));
+UPDATE vandelay.authority_queue SET queue_type = 'authority';
+ALTER TABLE vandelay.bib_queue ADD CONSTRAINT bib_queue_queue_type_check CHECK (queue_type IN ('bib'));
+ALTER TABLE vandelay.authority_queue ADD CONSTRAINT authority_queue_queue_type_check CHECK (queue_type IN ('authority'));
+
+DELETE FROM permission.perm_list WHERE code = 'IMPORT_ACQ_LINEITEM_BIB_RECORD_UPLOAD';
+DELETE FROM vandelay.import_error WHERE code = 'import.record.perm_failure';
+*/
+
+

-----------------------------------------------------------------------

Summary of changes:
 Open-ILS/examples/fm_IDL.xml                       |    6 +-
 .../perlmods/lib/OpenILS/Application/Acq/Order.pm  |  394 +++++++++++++-------
 .../perlmods/lib/OpenILS/Application/Vandelay.pm   |   81 ++++-
 Open-ILS/src/perlmods/lib/OpenILS/WWW/Vandelay.pm  |   14 +-
 Open-ILS/src/sql/Pg/002.schema.config.sql          |    2 +-
 Open-ILS/src/sql/Pg/012.schema.vandelay.sql        |   11 +-
 Open-ILS/src/sql/Pg/200.schema.acq.sql             |    2 +
 Open-ILS/src/sql/Pg/950.data.seed-values.sql       |    9 +-
 .../0684.schema.acq-vandelay-integration.sql       |   96 +++++
 Open-ILS/src/templates/acq/common/li_table.tt2     |   38 +--
 Open-ILS/src/templates/acq/common/vlagent.tt2      |   78 ++++
 Open-ILS/src/templates/acq/picklist/upload.tt2     |   69 +---
 .../src/templates/vandelay/inc/queueselect.tt2     |    1 +
 Open-ILS/web/js/dojo/openils/XUL.js                |    2 +-
 .../web/js/dojo/openils/widget/AutoFieldWidget.js  |   14 +-
 Open-ILS/web/js/ui/default/acq/common/li_table.js  |  104 ++++--
 Open-ILS/web/js/ui/default/acq/common/vlagent.js   |  190 ++++++++++
 Open-ILS/web/js/ui/default/acq/picklist/upload.js  |  106 ++++--
 Open-ILS/web/js/ui/default/acq/po/view_po.js       |    5 +
 Open-ILS/web/js/ui/default/vandelay/vandelay.js    |   23 +-
 20 files changed, 943 insertions(+), 302 deletions(-)
 create mode 100644 Open-ILS/src/sql/Pg/upgrade/0684.schema.acq-vandelay-integration.sql
 create mode 100644 Open-ILS/src/templates/acq/common/vlagent.tt2
 create mode 100644 Open-ILS/web/js/ui/default/acq/common/vlagent.js


hooks/post-receive
-- 
Evergreen ILS


More information about the open-ils-commits mailing list