Acq: Improved invoice-linking and -viewing features in LI, PO interfaces
authorsenator <senator@dcc99617-32d9-48b4-a31d-7c20da2025e4>
Fri, 9 Apr 2010 20:27:50 +0000 (20:27 +0000)
committersenator <senator@dcc99617-32d9-48b4-a31d-7c20da2025e4>
Fri, 9 Apr 2010 20:27:50 +0000 (20:27 +0000)
Additional miscellany: removed menu entries for deprecated lineitem search
interface, added uniqueness constraint around (provider, inv_ident) on the
acq.invoice table, and made subtle improvements to unified search interface

git-svn-id: svn://svn.open-ils.org/ILS/trunk@16197 dcc99617-32d9-48b4-a31d-7c20da2025e4

17 files changed:
Open-ILS/src/sql/Pg/002.schema.config.sql
Open-ILS/src/sql/Pg/200.schema.acq.sql
Open-ILS/src/sql/Pg/upgrade/0233.schema.acq-invoice-inv_ident-constraint.sql [new file with mode: 0644]
Open-ILS/web/css/skin/default/acq.css
Open-ILS/web/js/dojo/openils/acq/nls/acq.js
Open-ILS/web/js/ui/default/acq/common/inv_dialog.js [new file with mode: 0644]
Open-ILS/web/js/ui/default/acq/common/li_table.js
Open-ILS/web/js/ui/default/acq/po/view_po.js
Open-ILS/web/js/ui/default/acq/search/unified.js
Open-ILS/web/opac/locale/en-US/lang.dtd
Open-ILS/web/templates/default/acq/common/inv_dialog.tt2 [new file with mode: 0644]
Open-ILS/web/templates/default/acq/common/li_table.tt2
Open-ILS/web/templates/default/acq/po/view.tt2
Open-ILS/web/templates/default/acq/search/unified.tt2
Open-ILS/xul/staff_client/chrome/content/main/menu.js
Open-ILS/xul/staff_client/chrome/content/main/menu_frame_menus.xul
Open-ILS/xul/staff_client/chrome/locale/en-US/offline.properties

index 8832aa2..0238984 100644 (file)
@@ -60,7 +60,7 @@ CREATE TABLE config.upgrade_log (
     install_date    TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW()
 );
 
-INSERT INTO config.upgrade_log (version) VALUES ('0232'); -- Scott McKellar
+INSERT INTO config.upgrade_log (version) VALUES ('0233'); -- senator
 
 CREATE TABLE config.bib_source (
        id              SERIAL  PRIMARY KEY,
index 7df769d..42291df 100644 (file)
@@ -802,7 +802,8 @@ CREATE TABLE acq.invoice (
        payment_auth TEXT,
        payment_method TEXT     REFERENCES acq.invoice_payment_method (code)
                                DEFERRABLE INITIALLY DEFERRED,
-       note        TEXT
+       note        TEXT,
+    CONSTRAINT  inv_ident_once_per_provider UNIQUE(provider, inv_ident)
 );
 
 CREATE TABLE acq.invoice_entry (
diff --git a/Open-ILS/src/sql/Pg/upgrade/0233.schema.acq-invoice-inv_ident-constraint.sql b/Open-ILS/src/sql/Pg/upgrade/0233.schema.acq-invoice-inv_ident-constraint.sql
new file mode 100644 (file)
index 0000000..f2a90bd
--- /dev/null
@@ -0,0 +1,8 @@
+BEGIN;
+
+INSERT INTO config.upgrade_log (version) VALUES ('0233'); -- senator
+
+ALTER TABLE acq.invoice
+    ADD CONSTRAINT inv_ident_once_per_provider UNIQUE(provider, inv_ident);
+
+COMMIT;
index ffdb200..6cbc1fa 100644 (file)
@@ -222,4 +222,4 @@ option[disabled="disabled"] { font-style: italic; }
 .acq-inoice-item-info { font-weight: bold; }
 .acq-invoice-row td { border-bottom: 1px solid #e0e0e0; }
 .acq-invoice-invalid-amount input { color: red; font-weight: bold; }
-
+.acq-link-invoice-dialog td,.acq-link-invoice-dialog th {padding-top: 10px;}
index 6911122..dca18f6 100644 (file)
@@ -61,5 +61,6 @@
     'INVOICE_CONFIRM_ENTRY_DETACH' : "Remove $${0} charge for item '${1}, ${2} [${3}] from the invoice?",
     'INVOICE_TITLE_DETAILS' : "<div class='acq-inoice-item-info'>${0}, by ${1} (${2})</div><div class='acq-inoice-item-extra-info'><a style='padding-right: 10px;' href='${9}/acq/po/view/${10}'>PO: ${11}</a>${3} Ordered, ${4} Received, ${7} Invoiced</div><div class='acq-inoice-item-extra-info'> Estimated Cost Per Item $${5} / Total Estimated Cost $${6}</div>",
     'INVOICE_CONFIRM_PRORATE' : "Prorate charges?\n\nAny subsequent changes to the invoice that would affect prorated amounts should be resolved manually.",
-    'UNNAMED': "Unnamed"
+    'UNNAMED': "Unnamed",
+    'NO_FIND_INVOICE': "Could not find that invoice.\nNote that the Invoice # field is case-sensitive."
 }
diff --git a/Open-ILS/web/js/ui/default/acq/common/inv_dialog.js b/Open-ILS/web/js/ui/default/acq/common/inv_dialog.js
new file mode 100644 (file)
index 0000000..b76aa97
--- /dev/null
@@ -0,0 +1,46 @@
+function InvoiceLinkDialogManager(which, target) {
+    var self = this;
+    this.inv = null;
+
+    this.linkFoundInvoice = function(r) {
+        self.inv = openils.Util.readResponse(r);
+        location.href = oilsBasePath + "/acq/invoice/view/" + self.inv.id() +
+            "?attach_" + self.which + "=" + self.target.id();
+    };
+
+    this.which = which;
+    if (target)
+        this.target = target;
+
+    new openils.widget.AutoFieldWidget({
+        "fmField": "provider",
+        "fmClass": "acqinv",
+        "parentNode": dojo.byId("acq-" + this.which + "-link-invoice-provider"),
+        "orgLimitPerms": ["VIEW_INVOICE"],
+        "forceSync": true
+    }).build();
+
+    dijit.byId("acq-" + this.which + "-link-invoice-link").onClick =
+        function() {
+            self.inv = null;
+            pcrud.search(
+                "acqinv", {
+                    "provider": dijit.byId(
+                            "acq-" + self.which + "-link-invoice-provider"
+                        ).attr("value"),
+                    "inv_ident":
+                        dijit.byId(
+                            "acq-" + self.which + "-link-invoice-inv_ident"
+                        ).attr("value")
+                }, {
+                    "async": true,
+                    "streaming": true,
+                    "onresponse": self.linkFoundInvoice,
+                    "oncomplete": function() {
+                        if (!self.inv)
+                            alert(localeStrings.NO_FIND_INVOICE);
+                    }
+                }
+            );
+        };
+}
index 21020b8..7fcaaf3 100644 (file)
@@ -6,8 +6,6 @@ dojo.require('dijit.form.FilteringSelect');
 dojo.require('dijit.form.Textarea');
 dojo.require('dijit.Tooltip');
 dojo.require('dijit.ProgressBar');
-dojo.require('openils.User');
-dojo.require('openils.Util');
 dojo.require('openils.acq.Lineitem');
 dojo.require('openils.acq.PO');
 dojo.require('openils.acq.Picklist');
@@ -15,7 +13,6 @@ dojo.require('openils.widget.AutoFieldWidget');
 dojo.require('dojo.data.ItemFileReadStore');
 dojo.require('openils.widget.ProgressDialog');
 dojo.require('openils.PermaCrud');
-dojo.require('openils.XUL');
 
 dojo.requireLocalization('openils.acq', 'acq');
 var localeStrings = dojo.i18n.getLocalization('openils.acq', 'acq');
@@ -68,6 +65,7 @@ function AcqLiTable() {
     this.realCopiesTbody = dojo.byId('acq-lit-real-copies-tbody');
     this.realCopiesRow = this.realCopiesTbody.removeChild(dojo.byId('acq-lit-real-copies-row'));
     this._copy_fields_for_acqdf = ['owning_lib', 'location'];
+    this.invoiceLinkDialogManager = new InvoiceLinkDialogManager("li");
 
     dojo.connect(acqLitLiActionsSelector, 'onChange', 
         function() { 
@@ -380,11 +378,15 @@ function AcqLiTable() {
                         nodeByName("action_none", row).selected = true;
                     };
                     actLinkInvoice.onclick = function() {
-                        // TODO: show inv #/vendor entry then relocate to invoice attach page
+                        self.invoiceLinkDialogManager.target = li;
+                        acqLitLinkInvoiceDialog.show();
                         nodeByName("action_none", row).selected = true;
                     };
                     actViewInvoice.onclick = function() {
-                        // TODO: go to invoice search page, with lineitem filter = li.id()
+                        location.href = oilsBasePath +
+                            "/acq/search/unified?so=" +
+                            base64Encode({"jub":[{"id": li.id()}]}) +
+                            "&rt=invoice";
                         nodeByName("action_none", row).selected = true;
                     };
 
index dbf2790..2ca7de2 100644 (file)
@@ -1,13 +1,12 @@
 dojo.require("dojo.string");
 dojo.require('dijit.layout.ContentPane');
-dojo.require('openils.User');
-dojo.require('openils.Util');
 dojo.require('openils.PermaCrud');
 
 var pcrud = new openils.PermaCrud();
 var PO = null;
 var liTable;
 var poNoteTable;
+var invoiceLinkDialogManager;
 
 function AcqPoNoteTable() {
     var self = this;
@@ -260,6 +259,44 @@ function makeCancelWidget(node, labelnode) {
     }
 }
 
+function prepareInvoiceFeatures() {
+    /* show the count of related invoices on the "view invoices" button */
+    fieldmapper.standardRequest(
+        ["open-ils.acq", "open-ils.acq.invoice.unified_search.atomic"], {
+            "params": [
+                openils.User.authtoken,
+                {"acqpo":[{"id": PO.id()}]},
+                null,
+                null,
+                {"id_list": true}
+            ],
+            "async": true,
+            "oncomplete": function(r) {
+                dojo.byId("acq-po-view-invoice-count").innerHTML =
+                    openils.Util.readResponse(r).length;
+            }
+        }
+    );
+
+    /* view invoices button */
+    dijit.byId("acq-po-view-invoice-link").onClick = function() {
+        location.href = oilsBasePath + "/acq/search/unified?so=" +
+            base64Encode({"jub":[{"purchase_order": PO.id()}]}) +
+            "&rt=invoice";
+    };
+
+    /* create invoice button */
+    dijit.byId("acq-po-create-invoice-link").onClick = function() {
+        location.href = oilsBasePath +
+            "/acq/invoice/view?create=1&attach_po=" + PO.id();
+    };
+
+    if (!invoiceLinkDialogManager)
+        invoiceLinkDialogManager = new InvoiceLinkDialogManager("po", PO);
+
+    openils.Util.show("acq-po-view-invoices", "table-row");
+}
+
 function renderPo() {
     dojo.byId("acq-po-view-id").innerHTML = PO.id();
     dojo.byId("acq-po-view-name").innerHTML = PO.name();
@@ -288,17 +325,7 @@ function renderPo() {
             openils.Util.show("acq-po-split");
     }
 
-    dojo.byId('acq-po-create-invoice-link').onclick = 
-        function() {
-            location.href = oilsBasePath + '/acq/invoice/view?create=1&attach_po=' + poId;
-        };
-
-    dojo.byId("acq-po-view-invoice-link").onclick =
-        function() {
-            location.href = oilsBasePath + "/acq/search/unified?so=" +
-                base64Encode({"jub":[{"purchase_order": PO.id()}]}) +
-                "&rt=invoice";
-        };
+    prepareInvoiceFeatures();
 }
 
 
index 0a85646..1413238 100644 (file)
@@ -299,14 +299,18 @@ function TermManager() {
 
         var selector = this.selectorFactory.make(uniq);
         dojo.attr(
-            selector,
-            "onchange",
-            function() { self.updateRowWidget(uniq); }
+            selector, "onchange", function() { self.updateRowWidget(uniq); }
         );
 
         var match_how = dojo.query("select", nodeByName("match", row))[0];
         dojo.attr(match_how, "id", "term-match-" + uniq);
         dojo.attr(match_how, "selectedIndex", 0);
+        dojo.attr(
+            match_how, "onchange",
+            function() {
+                if (self.widgets[uniq]) self.widgets[uniq].focus();
+            }
+        );
 
         nodeByName("selector", row).appendChild(selector);
         nodeByName("remove", row).appendChild(this.removerButton(uniq));
@@ -564,14 +568,15 @@ openils.Util.addOnLoad(
             dijit.byId("acq-unified-inv-grid")
         );
 
-        openils.Util.show("acq-unified-body");
-
         uriManager = new URIManager();
         if (uriManager.search_object) {
+            hideForm();
+            openils.Util.show("acq-unified-body");
             termManager.reflect(uriManager.search_object);
             resultManager.search(uriManager.search_object);
         } else {
             termManager.addRow();
+            openils.Util.show("acq-unified-body");
         }
     }
 );
index 4788f83..49c9f42 100644 (file)
 <!ENTITY staff.main.menu.acq.picklist.accesskey "L">
 <!ENTITY staff.main.menu.acq.bib_search.label "Title Search">
 <!ENTITY staff.main.menu.acq.bib_search.accesskey "T">
-<!ENTITY staff.main.menu.acq.li_search.label "Lineitem Search">
-<!ENTITY staff.main.menu.acq.li_search.accesskey "I">
 <!ENTITY staff.main.menu.acq.unified_search.label "Acquisitions Search">
 <!ENTITY staff.main.menu.acq.unified_search.accesskey "A">
 <!ENTITY staff.main.menu.acq.brief_record.label "New Brief Record">
diff --git a/Open-ILS/web/templates/default/acq/common/inv_dialog.tt2 b/Open-ILS/web/templates/default/acq/common/inv_dialog.tt2
new file mode 100644 (file)
index 0000000..e83214b
--- /dev/null
@@ -0,0 +1,30 @@
+<script src="[% ctx.media_prefix %]/js/ui/default/acq/common/inv_dialog.js">
+</script>
+<big><strong>Choose invoice</big></strong>
+<table class="acq-link-invoice-dialog">
+    <tr>
+        <th>
+            <label for="acq-[% which %]-link-invoice-provider">Provider</label>
+        </th>
+        <td>
+            <span id="acq-[% which %]-link-invoice-provider"></span>
+        </td>
+    </tr>
+    <tr>
+        <th>
+            <label for="acq-[% which %]-link-invoice-inv_ident">
+                Invoice #
+            </label>
+        </th>
+        <td>
+            <input id="acq-[% which %]-link-invoice-inv_ident"
+                dojoType="dijit.form.TextBox" />
+        </td>
+    </tr>
+    <tr>
+        <td colspan="2" style="text-align: center;">
+            <button id="acq-[% which %]-link-invoice-link"
+                dojoType="dijit.form.Button" type="submit">Link</button>
+        </td>
+    </tr>
+</table>
index 1a559cd..4d42f38 100644 (file)
@@ -1,3 +1,4 @@
+<script src="[% ctx.media_prefix %]/js/ui/default/acq/common/base64.js"> </script>
 <script src='[% ctx.media_prefix %]/js/ui/default/acq/common/li_table.js'> </script>
 <div id='acq-lit-table-container'>
     <div id='acq-lit-table-div' class='hidden'>
         <table id='acq-lit-li-details-table'>
             <tbody style='background-color:#ddd;'>
                 <tr id='acq-lit-li-details-batch-row'>
-                    <td><div name='owning_lib'/></td>
-                    <td><div name='location'/></td>
-                    <td><div name='collection_code'/></td>
-                    <td><div name='fund'/></td>
-                    <td><div name='circ_modifier'/></td>
-                    <td><div name='cn_label'/></td>
+                    <td><div name='owning_lib'></div></td>
+                    <td><div name='location'></div></td>
+                    <td><div name='collection_code'></div></td>
+                    <td><div name='fund'></div></td>
+                    <td><div name='circ_modifier'></div></td>
+                    <td><div name='cn_label'></div></td>
                     <td colspan='3' style='text-align:left;'>
                         <div dojoType='dijit.form.Button' jsId='acqLitBatchUpdateCopies'>Batch Update</div>
                     </td>
             </tbody>
             <tbody id='acq-lit-li-details-tbody' class='oils-generic-table'>
                 <tr id='acq-lit-li-details-row'>
-                    <td><div name='owning_lib'/></td>
-                    <td><div name='location'/></td>
-                    <td><div name='collection_code'/></td>
-                    <td><div name='fund'/></td>
-                    <td><div name='circ_modifier'/></td>
-                    <td><div name='cn_label'/></td>
-                    <td><div name='barcode'/></td>
-                    <td><div name='note'/></td>
+                    <td><div name='owning_lib'></div></td>
+                    <td><div name='location'></div></td>
+                    <td><div name='collection_code'></div></td>
+                    <td><div name='fund'></div></td>
+                    <td><div name='circ_modifier'></div></td>
+                    <td><div name='cn_label'></div></td>
+                    <td><div name='barcode'></div></td>
+                    <td><div name='note'></div></td>
                     <td><a href='javascript:void(0);' name='receive'>Mark&nbsp;Received</a><a href='javascript:void(0);' name='unreceive'>Un-Receive</a>&nbsp;<a href="javascript:void(0);" name='cancel'>Cancel</a><span class="hidden" name='cancel_reason'></span></td>
                     <td><div name='delete' dojoType='dijit.form.Button' style='color:red;'>X</div></td>
                 </tr>
             </tbody>
             <tbody id='acq-lit-real-copies-tbody' class='oils-generic-table'>
                 <tr id='acq-lit-real-copies-row'>
-                    <td><div name='owning_lib'/></td>
-                    <td><div name='location'/></td>
-                    <td><div name='circ_modifier'/></td>
-                    <td><div name='label'/></td>
-                    <td><div name='barcode'/></td>
+                    <td><div name='owning_lib'></div></td>
+                    <td><div name='location'></div></td>
+                    <td><div name='circ_modifier'></div></td>
+                    <td><div name='label'></div></td>
+                    <td><div name='barcode'></div></td>
                 </tr>
             </tbody>
         </table>
     </div>
 
+    <div jsId="acqLitLinkInvoiceDialog" dojoType="dijit.Dialog">
+        [% INCLUDE "default/acq/common/inv_dialog.tt2" which = "li" %]
+    </div>
+
     <div class='hidden' id='acq-lit-progress-numbers'>
         <table class='oils-generic-table'>
             <tbody>
             <table class='oils-generic-table'>
                 <tr>
                     <td>Ordering Agency</td>
-                    <td><div name='ordering_agency' id='acq-lit-po-agency'/></td>
+                    <td><div name='ordering_agency' id='acq-lit-po-agency'></div></td>
                 </tr>
                 <tr>
                     <td>Provider</td>
-                    <td><div name='provider' id='acq-lit-po-provider'/></td>
+                    <td><div name='provider' id='acq-lit-po-provider'></div></td>
                 </tr>
                 <tr>
                     <td>Prepayment Required</td>
 
 
     <div class='hidden'>
-        <div dojoType='openils.widget.ProgressDialog' jsId='progressDialog'/>
+        <div dojoType='openils.widget.ProgressDialog' jsId='progressDialog'></div>
     </div>
 
 </div>
index 6bbeefc..f485c11 100644 (file)
                     </td>
                 </tr>
                 <tr><td><a class="hidden" id="acq-po-split" href="javascript:void(0);" onclick="if (confirm(localeStrings.CONFIRM_SPLIT_PO)) splitPo();">Split Order by Lineitems</a></td></tr>
-                <tr id='acq-po-view-invoices'> <!-- TODO: hidden until applicable -->
+                <tr id="acq-po-view-invoices" class="hidden"><!-- TODO: only reveal when really applicable -->
                     <td>Invoicing</td>
                     <td>
-                        <a href="javascript:void(0);" id="acq-po-view-invoice-link">View Invoices</a> / 
-                        <a href="javascript:void(0);" id="acq-po-create-invoice-link">Create Invoice</a> / 
-                        <a href="javascript:void(0);" id="acq-po-link-invoice-link">Link Invoice</a>
+                        <button dojoType="dijit.form.Button"
+                            id="acq-po-view-invoice-link">
+                            View Invoices
+                            (<span id="acq-po-view-invoice-count"></span>)
+                        </button> &nbsp;
+                        <button dojoType="dijit.form.Button"
+                            id="acq-po-create-invoice-link">
+                            Create Invoice
+                        </button> &nbsp;
+                        <button dojoType="dijit.form.DropDownButton">
+                            <span>Link Invoice</span>
+                            <div dojoType="dijit.TooltipDialog"
+                                id="acq-po-link-invoice">
+                                [% INCLUDE "default/acq/common/inv_dialog.tt2"
+                                    which = "po" %]
+                            </div>
+                        </button>
                     </td>
                 </tr>
             </table>
index 6e8721f..dcc14fc 100644 (file)
@@ -87,8 +87,8 @@
             </select>
             <label for="acq-unified-conjunction">matching</label>
             <select id="acq-unified-conjunction">
-                <option value="or">any</option>
                 <option value="and">all</option>
+                <option value="or">any</option>
             </select>
             <label for="acq-unified-conjunction">
                 of the following terms:
index 7f9a1fb..51f1c4c 100644 (file)
@@ -735,10 +735,6 @@ main.menu.prototype = {
                 ['oncommand'],
                 function() { open_eg_web_page('acq/search/unified', 'menu.cmd_acq_unified_search.tab'); }
             ],
-            'cmd_acq_li_search' : [
-                ['oncommand'],
-                function() { open_eg_web_page('acq/lineitem/search', 'menu.cmd_acq_li_search.tab'); }
-            ],
             'cmd_acq_new_brief_record' : [
                 ['oncommand'],
                 function() { open_eg_web_page('acq/picklist/brief_record', 'menu.cmd_acq_new_brief_record.tab'); }
index c8175f3..52bf257 100644 (file)
@@ -84,7 +84,6 @@
     <command id="cmd_acq_view_po_events" />
     <command id="cmd_acq_user_requests" />
     <command id="cmd_acq_bib_search" />
-    <command id="cmd_acq_li_search" />
     <command id="cmd_acq_unified_search" />
     <command id="cmd_acq_new_brief_record" />
     <command id="cmd_acq_view_fund" />
     <menupopup id="main.menu.acq.popup">
         <menuitem label="&staff.main.menu.acq.unified_search.label;" accesskey="&staff.main.menu.acq.unified_search.accesskey;" command="cmd_acq_unified_search"/>
         <menuitem label="&staff.main.menu.acq.bib_search.label;" accesskey="&staff.main.menu.acq.bib_search.accesskey;" command="cmd_acq_bib_search"/>
-        <menuitem label="&staff.main.menu.acq.li_search.label;" accesskey="&staff.main.menu.acq.li_search.accesskey;" command="cmd_acq_li_search"/>
         <menuitem label="&staff.main.menu.acq.po.label;" accesskey="&staff.main.menu.acq.po.accesskey;" command="cmd_acq_view_po" />
         <menuitem label="&staff.main.menu.acq.picklist.label;" accesskey="&staff.main.menu.acq.picklist.accesskey;" command="cmd_acq_view_picklist"/>
         <menuseparator />
index 0cf279d..4869aca 100644 (file)
@@ -226,7 +226,6 @@ menu.cmd_acq_create_invoice.tab=New Invoice
 menu.cmd_acq_view_picklist.tab=Selection Lists
 menu.cmd_acq_bib_search.tab=Title Search
 menu.cmd_acq_unified_search.tab=Acquisitions Search
-menu.cmd_acq_li_search.tab=Lineitem Search
 menu.cmd_acq_upload.tab=Load Order Record
 menu.cmd_acq_new_brief_record.tab=New Brief Record
 menu.cmd_acq_view_po.tab=Purchase Orders