Acq: users can now claim individual copies from the LI copy table
authorsenator <senator@dcc99617-32d9-48b4-a31d-7c20da2025e4>
Mon, 3 May 2010 18:05:27 +0000 (18:05 +0000)
committersenator <senator@dcc99617-32d9-48b4-a31d-7c20da2025e4>
Mon, 3 May 2010 18:05:27 +0000 (18:05 +0000)
Also included, small bugfix to unified search (bug had caused atomic version
of the API call to include an extra, undesired result), and an improvement
to the decision to show or not show the "mark received" link on the LI copy
table.

Also made using the claiming dialog update the LI table to reflect the new
claims / changes in eligibility.

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

Open-ILS/src/perlmods/OpenILS/Application/Acq/Search.pm
Open-ILS/web/js/dojo/openils/acq/nls/acq.js
Open-ILS/web/js/ui/default/acq/common/claim_dialog.js
Open-ILS/web/js/ui/default/acq/common/li_table.js
Open-ILS/web/templates/default/acq/common/li_table.tt2

index 1969754..164cd21 100644 (file)
@@ -436,7 +436,7 @@ sub unified_search {
     }
 
     $e->disconnect;
-    $conn->respond_complete;
+    undef;
 }
 
 __PACKAGE__->register_method(
@@ -504,7 +504,7 @@ sub bib_search {
 
     $ses->disconnect;
     $e->commit;
-    $conn->respond_complete;
+    undef;
 }
 
 1;
index cc51639..1177fd6 100644 (file)
@@ -79,5 +79,6 @@
     'RECVD': "Recv'd",
     'NOT_RECVD': "Not recv'd",
     'PRINT': "Print",
-    'INVOICES': "Invoices"
+    'INVOICES': "Invoices",
+    'NUM_CLAIMS_EXISTING': "Claims (${0} existing)"
 }
index b13edfd..ede0aff 100644 (file)
@@ -1,4 +1,6 @@
-function ClaimDialogManager(dialog, finalDialog, eligibleLidByLi) {
+function ClaimDialogManager(
+    dialog, finalDialog, eligibleLidByLi, claimCallback
+) {
     var self = this;
 
     this.anyLids = false;
@@ -8,6 +10,7 @@ function ClaimDialogManager(dialog, finalDialog, eligibleLidByLi) {
     this.dialog = dialog;
     this.finalDialog = finalDialog;
     this.eligibleLidByLi = eligibleLidByLi;
+    this.claimCallback = claimCallback;
 
     this.showingList = dojo.byId("acq-lit-li-claim-dia-lid-list");
     this.eligibleList = dojo.byId("acq-lit-li-claim-dia-lid-list-init");
@@ -47,6 +50,7 @@ function ClaimDialogManager(dialog, finalDialog, eligibleLidByLi) {
 
     this.reset = function(li) {
         this.anyLids = false;
+        this.anyEligible = false;
         this.showingLidNodes = {};
 
         openils.Util.hide("acq-lit-li-claim-dia-initiate");
@@ -56,15 +60,17 @@ function ClaimDialogManager(dialog, finalDialog, eligibleLidByLi) {
         dojo.empty(this.eligibleList);
     };
 
-    this.show = function(li) {
+    this.show = function(li, preselected) {
         this.reset();
-        this.prepare(li);
+        this.prepare(li, preselected);
         this.dialog.show();
     };
 
     this.hide = function() { this.dialog.hide(); };
 
-    this.prepare = function(li) {
+    this.prepare = function(li, preselected) {
+        this.workingLi = li;
+
         dojo.byId("acq-lit-li-claim-dia-li-title").innerHTML =
             li.attributes().filter(
                 function(o) { return Boolean(o.attr_name() == "title"); }
@@ -77,7 +83,7 @@ function ClaimDialogManager(dialog, finalDialog, eligibleLidByLi) {
                     function(claim) { self.addClaim(lid, claim); }
                 );
                 if (self.eligibleLidByLi[li.id()].indexOf(lid.id()) != -1) {
-                    self.addEligible(lid);
+                    self.addEligible(lid, preselected == lid.id());
                 }
             }
         );
@@ -144,21 +150,20 @@ function ClaimDialogManager(dialog, finalDialog, eligibleLidByLi) {
         );
     };
 
-    this.addEligible = function(lid) {
+    this.addEligible = function(lid, preselect) {
         if (!this.anyEligible)
             openils.Util.show("acq-lit-li-claim-dia-initiate");
         this.anyEligible = true;
 
         var eligibleNode = dojo.clone(this.eligibleTemplate);
-        nodeByName("claimable_lid", eligibleNode).value = lid.id();
-        dojo.attr(
-            nodeByName("claimable_lid", eligibleNode),
-            "id", "claim-lid-" + lid.id()
-        );
-        dojo.attr(
-            nodeByName("claimable_lid_label", eligibleNode),
-            "for", "claim-lid-" + lid.id()
-        );
+        var checkbox = nodeByName("claimable_lid", eligibleNode);
+
+        checkbox.value = lid.id();
+        dojo.attr(checkbox, "id", "claim-lid-" + lid.id());
+        dojo.attr(checkbox, "for", "claim-lid-" + lid.id());
+        if (preselect)
+            dojo.attr(checkbox, "checked", true);
+
         nodeByName("barcode", eligibleNode).innerHTML = lid.barcode();
         nodeByName("recvd", eligibleNode).innerHTML = this._reprReceived(lid);
 
@@ -199,6 +204,7 @@ function ClaimDialogManager(dialog, finalDialog, eligibleLidByLi) {
                     dojo.byId("print", win.document).innerHTML =
                         localeStrings.PRINT;
                     dojo.byId("print", win.document).disabled = false;
+                    self.claimCallback(self.workingLi);
                 }
             }
         );
index 4961b3a..73c5cb5 100644 (file)
@@ -50,6 +50,7 @@ function AcqLiTable() {
     this.virtDfaId = -1;
     this.dfeOffset = 0;
     this.claimEligibleLidByLi = {};
+    this.claimEligibleLid = {};
     this.toggleState = false;
     this.tbody = dojo.byId('acq-lit-tbody');
     this.selectors = [];
@@ -68,7 +69,10 @@ function AcqLiTable() {
     this._copy_fields_for_acqdf = ['owning_lib', 'location'];
     this.invoiceLinkDialogManager = new InvoiceLinkDialogManager("li");
     this.claimDialog = new ClaimDialogManager(
-        liClaimDialog, finalClaimDialog, this.claimEligibleLidByLi
+        liClaimDialog, finalClaimDialog, this.claimEligibleLidByLi,
+        function(li) {    /* callback that fires when claims are made */
+            self.fetchClaimInfo(li.id(), /* force update */ true);
+        }
     );
 
     dojo.connect(acqLitLiActionsSelector, 'onChange', 
@@ -203,8 +207,7 @@ function AcqLiTable() {
             }).build(function(w) { self.claimPolicyPicker = w; });
         }
 
-        if (typeof(row) == "undefined")
-            row = dojo.query('tr[li="' + li.id() + '"]', "acq-lit-tbody")[0];
+        if (!row) row = this._findLiRow(li);
 
         var actViewPolicy = nodeByName("action_view_claim_policy", row);
         if (li.claim_policy())
@@ -228,6 +231,15 @@ function AcqLiTable() {
         }
     };
 
+    this.fetchClaimInfo = function(liId, force, callback, row) {
+        this._fetchLineitem(
+            liId, function(full) {
+                self.liCache[full.id()] = full;
+                self.checkClaimEligibility(full, callback, row);
+            }, force
+        );
+    }
+
     /**
      * Inserts a single lineitem into the growing table of lineitems
      * @param {Object} li The lineitem object to insert
@@ -258,15 +270,7 @@ function AcqLiTable() {
         dojo.query('[name=copieslink]', row)[0].onclick = function() {self.drawCopies(li.id())};
         dojo.query('[name=noteslink]', row)[0].onclick = function() {self.drawLiNotes(li)};
 
-        /* XXX note how checkClaimEligibility() is getting called once per LI
-         * when in some use cases we should be able to do that job with one
-         * call per PO or per PL or whatever... */
-        this._fetchLineitem(
-            li.id(), function(full) {
-                self.liCache[full.id()] = full;
-                self.checkClaimEligibility(full, row);
-            }
-        );
+        this.fetchClaimInfo(li.id(), false, null, row);
 
         this.updateLiNotesCount(li, row);
 
@@ -340,26 +344,45 @@ function AcqLiTable() {
         return total;
     };
 
+    this._findLiRow = function(li) {
+        return dojo.query('tr[li="' + li.id() + '"]', "acq-lit-tbody")[0];
+    };
+
     this.reconsiderClaimControl = function(li, row) {
         var option = nodeByName("action_manage_claims", row);
         var eligible = this.claimEligibleLidByLi[li.id()].length;
         var count = this._liCountClaims(li);
+        if (!row) row = this._findLiRow(li);
 
         option.disabled = !(count || eligible);
-
-        /* of course I'd rather just populate a <span> element inside the
-         * option element, but it seems you can't actually have any elements
-         * inside option elements 
-         * TODO: move to dojo/i18n
-         * */
-        option.innerHTML = option.innerHTML.replace(
-            /(^.+)(.*)( existing.+$)/, "$1" + String(count) + "$3"
-        );
+        option.innerHTML =
+            dojo.string.substitute(localeStrings.NUM_CLAIMS_EXISTING, [count]);
         option.onclick = function() { self.claimDialog.show(li); };
     };
 
-    this.checkClaimEligibility = function(li, row) {
+    this.clearEligibility = function(li) {
         this.claimEligibleLidByLi[li.id()] = [];
+
+        if (li.lineitem_details()) {
+            li.lineitem_details().forEach(
+                function(lid) { delete self.claimEligibleLid[lid.id()]; }
+            );
+        }
+
+        if (this.copyCache) {
+            var to_del = [];
+            for (var k in this.copyCache) {
+                if (this.copyCache[k].lineitem() == li.id())
+                    to_del.push(k);
+            }
+            to_del.forEach(
+                function(k) { delete self.claimEligibleLid[k]; }
+            );
+        }
+    };
+
+    this.checkClaimEligibility = function(li, callback, row) {
+        this.clearEligibility(li);
         fieldmapper.standardRequest(
             ["open-ils.acq", "open-ils.acq.claim.eligible.lineitem_detail"], {
                 "params": [openils.User.authtoken, {"lineitem": li.id()}],
@@ -369,18 +392,20 @@ function AcqLiTable() {
                         self.claimEligibleLidByLi[li.id()].push(
                             r.lineitem_detail()
                         );
+                        self.claimEligibleLid[r.lineitem_detail()] = true;
                     }
                 },
                 "oncomplete": function() {
                     self.reconsiderClaimControl(li, row);
+                    if (typeof(callback) == "function")
+                        callback();
                 }
             }
         );
     };
 
     this.updateLiNotesCount = function(li, row) {
-        if (typeof(row) == "undefined")
-            row = dojo.query('tr[li="' + li.id() + '"]', "acq-lit-tbody")[0];
+        if (!row) row = this._findLiRow(li);
 
         var has_notes = (li.lineitem_notes().filter(
                 function(o) { return Boolean (o.alert_text()); }
@@ -396,8 +421,7 @@ function AcqLiTable() {
 
     /* XXX NOT related to _updateLiState(). rethink */
     this.updateLiState = function(li, row) {
-        if (typeof(row) == "undefined")
-            row = dojo.query('tr[li="' + li.id() + '"]', "acq-lit-tbody")[0];
+        if (!row) row = this._findLiRow(li);
 
         var actReceive = nodeByName("action_mark_recv", row);
         var actUnRecv = nodeByName("action_mark_unrecv", row);
@@ -729,10 +753,10 @@ function AcqLiTable() {
         );
     };
 
-    this._fetchLineitem = function(liId, handler) {
+    this._fetchLineitem = function(liId, handler, force) {
 
         var li = this.liCache[liId];
-        if(li && li.marc() && li.lineitem_details())
+        if(li && li.marc() && li.lineitem_details() && !force)
             return handler(li);
         
         fieldmapper.standardRequest(
@@ -743,6 +767,7 @@ function AcqLiTable() {
                     flesh_attrs: true,
                     flesh_cancel_reason: true,
                     flesh_li_details: true,
+                    flesh_notes: true,
                     flesh_fund_debit: true }],
 
                 oncomplete: function(r) {
@@ -1489,6 +1514,7 @@ function AcqLiTable() {
         var unrecv_link = nodeByName("unreceive", row);
         var del_link = nodeByName("delete", row);
         var cxl_link = nodeByName("cancel", row);
+        var claim_link = nodeByName("claim", row);
         var cxl_reason_link = nodeByName("cancel_reason", row);
 
         if (copy.cancel_reason()) {
@@ -1496,6 +1522,7 @@ function AcqLiTable() {
             openils.Util.hide(recv_link);
             openils.Util.hide(unrecv_link);
             openils.Util.hide(cxl_link);
+            openils.Util.hide(claim_link);
 
             /* XXX the following may leak memory in a long lived table: dijits may not get destroyed... not positive. revisit. */
             var holds_reason = dojo.create(
@@ -1513,14 +1540,20 @@ function AcqLiTable() {
             );
             openils.Util.show(cxl_reason_link, "inline");
         } else if (this.isPO) {
+            /* Only using this in one place so far, but may want it for better
+             * decisions on when to display certain controls. */
+            var li_state = this.liCache[copy.lineitem()].state();
+
             openils.Util.hide(del_link.parentNode);
             openils.Util.hide(cxl_reason_link);
 
             /* Avoid showing (un)receive links, cancel links, for virt copies */
             if (copy.id() > 0) {
-                if(copy.recv_time()) {
+                if (copy.recv_time()) {
                     openils.Util.hide(cxl_link);
                     openils.Util.hide(recv_link);
+                    openils.Util.hide(claim_link);
+
                     openils.Util.show(unrecv_link, "inline");
                     unrecv_link.onclick = function() {
                         if (confirm(localeStrings.UNRECEIVE_LID))
@@ -1528,7 +1561,21 @@ function AcqLiTable() {
                     };
                 } else {
                     openils.Util.hide(unrecv_link);
-                    openils.Util.show(recv_link, "inline");
+
+                    if (this.claimEligibleLid[copy.id()]) {
+                        openils.Util.show(claim_link, "inline");
+                        claim_link.onclick = function() {
+                            self.claimDialog.show(
+                                self.liCache[copy.lineitem()], copy.id()
+                            );
+                        };
+                    } else {
+                        openils.Util.hide(claim_link);
+                    }
+
+                    openils.Util[li_state == "on-order" ? "show" : "hide"](
+                        recv_link, "inline"
+                    );
                     openils.Util.show(cxl_link, "inline");
                     recv_link.onclick = function() {
                         if (self.checkLiAlerts(copy.lineitem()))
@@ -1542,11 +1589,13 @@ function AcqLiTable() {
                 openils.Util.hide(cxl_link);
                 openils.Util.hide(unrecv_link);
                 openils.Util.hide(recv_link);
+                openils.Util.hide(claim_link);
             }
         } else {
             openils.Util.hide(unrecv_link);
             openils.Util.hide(recv_link);
             openils.Util.hide(cxl_reason_link);
+            openils.Util.hide(claim_link);
 
             del_link.onclick = function() { self.deleteCopy(row) };
             openils.Util.show(del_link.parentNode);
@@ -2080,8 +2129,14 @@ function AcqLiTable() {
                 "async": true,
                 "params": [this.authtoken, obj.id()],
                 "onresponse": function(r) {
-                    self.handleReceive(openils.Util.readResponse(r));
-                    progressDialog.hide();
+                    if (r = openils.Util.readResponse(r)) {
+                        self.fetchClaimInfo(
+                            part == "lineitem" ? obj.id() : obj.lineitem(),
+                            /* force */ true,
+                            function() { self.handleReceive(r); }
+                        );
+                        progressDialog.hide();
+                    }
                 }
             }
         );
index 2e90632..5cacf1d 100644 (file)
                             <option name='action_link_invoice' disabled='disabled'>Link to Invoice</option>
                             <option name='action_view_invoice' disabled='disabled'>View Invoice(s)</option>
                             <option name='action_view_claim_policy'>Apply Claim Policy</option>
-                            <option name='action_manage_claims' disabled='disabled'>Claims ( existing)</option>
+                            <option name='action_manage_claims' disabled='disabled'>Claims</option>
                         </select>
                     </td>
                     <td><span name='li_state'></span></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><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>&nbsp;<a href="javascript:void(0);" name="claim">Claim</a></td>
                     <td><div name='delete' dojoType='dijit.form.Button' style='color:red;'>X</div></td>
                 </tr>
             </tbody>