[open-ils-commits] r15593 - in trunk/Open-ILS: src/perlmods/OpenILS/Application/Acq web/js/dojo/openils web/js/dojo/openils/acq/nls web/js/ui/default/acq/common web/js/ui/default/acq/po web/templates/default/acq/common (senator)

svn at svn.open-ils.org svn at svn.open-ils.org
Thu Feb 18 19:41:39 EST 2010


Author: senator
Date: 2010-02-18 19:41:38 -0500 (Thu, 18 Feb 2010)
New Revision: 15593

Modified:
   trunk/Open-ILS/src/perlmods/OpenILS/Application/Acq/Order.pm
   trunk/Open-ILS/web/js/dojo/openils/Util.js
   trunk/Open-ILS/web/js/dojo/openils/acq/nls/acq.js
   trunk/Open-ILS/web/js/ui/default/acq/common/li_table.js
   trunk/Open-ILS/web/js/ui/default/acq/po/view_po.js
   trunk/Open-ILS/web/templates/default/acq/common/li_table.tt2
Log:
Acq: Towards slick integration of granular un-receive in the PO interface.

This adds good UI support for lineitem unreceive.  The bulk of this commit,
however, is in middle-layer rearrangements to make it easier to keep track
of changing lineitems and the POs that they belong to in a long-lived client
side interface.  In other words, when you receive an LI in a PO, the LI table
doesn't only hide the receive button, but keeps track of the LI's state
(received or something else) and shows you the proper controls in any case.
Same for unreceive.

Similar thing coming very soon for lineitem details (copies).



Modified: trunk/Open-ILS/src/perlmods/OpenILS/Application/Acq/Order.pm
===================================================================
--- trunk/Open-ILS/src/perlmods/OpenILS/Application/Acq/Order.pm	2010-02-18 22:43:55 UTC (rev 15592)
+++ trunk/Open-ILS/src/perlmods/OpenILS/Application/Acq/Order.pm	2010-02-19 00:41:38 UTC (rev 15593)
@@ -214,7 +214,8 @@
     $li->edit_time('now');
     $li->editor($mgr->editor->requestor->id);
     $mgr->add_li;
-    return $li if $mgr->editor->update_acq_lineitem($li); 
+    return $mgr->editor->retrieve_acq_lineitem($mgr->editor->data) if
+        $mgr->editor->update_acq_lineitem($li);
     return undef;
 }
 
@@ -353,13 +354,21 @@
 
     $mgr->add_li;
     $li->state('received');
-    update_lineitem($mgr, $li) or return 0;
 
+    $li = update_lineitem($mgr, $li) or return 0;
     $mgr->post_process( sub { create_lineitem_status_events($mgr, $li_id, 'aur.received'); });
 
-    return 1 if $skip_complete_check;
+    my $po;
+    my $result = {"li" => {$li->id => {"state" => $li->state}}};
+    return 0 unless
+        $skip_complete_check or (
+            $po = check_purchase_order_received($mgr, $li->purchase_order)
+        );
 
-    return check_purchase_order_received($mgr, $li->purchase_order);
+    if (ref $po) {
+        $result->{"po"} = {$po->id => {"state" => $li->state}};
+    }
+    return $result;
 }
 
 sub rollback_receive_lineitem {
@@ -488,7 +497,9 @@
     my $li = check_lineitem_received($mgr, $lid->lineitem) or return 0;
     return 1 if $li == 1; # li not received
 
-    return check_purchase_order_received($mgr, $li->purchase_order);
+    my $po = check_purchase_order_received($mgr, $li->purchase_order) or return 0;
+    return $li if $po == 1;
+    return $po;
 }
 
 
@@ -791,7 +802,8 @@
     $po->editor($mgr->editor->requestor->id);
     $po->edit_time('now');
     $mgr->purchase_order($po);
-    return $po if $mgr->editor->update_acq_purchase_order($po);
+    return $mgr->editor->retrieve_acq_purchase_order($mgr->editor->data)
+        if $mgr->editor->update_acq_purchase_order($po);
     return undef;
 }
 
@@ -1576,9 +1588,31 @@
     return $e->die_event unless $e->allowed(
         'RECEIVE_PURCHASE_ORDER', $lid->lineitem->purchase_order->ordering_agency);
 
-    receive_lineitem_detail($mgr, $lid_id) or return $e->die_event;
+    my $recvd = receive_lineitem_detail($mgr, $lid_id) or return $e->die_event;
+
+    # What's this business, you ask? We basically want to return a minimal
+    # set of information about what has changed as a result of the "receive
+    # lineitem detail" operation; remember: not only does the lineitem detail
+    # change state, but so might an LI and even a PO, and a good UI will want
+    # to reflect those changes.
+    $lid = $e->retrieve_acq_lineitem_detail(
+        [$lid_id, {"flesh" => 1, "flesh_fields" => {"acqlid" => ["lineitem"]}}]
+    );
+    my $result = {"lid" => {$lid->id => {"recv_time" => $lid->recv_time}}};
+
+    if (ref $recvd) {
+        if ($recvd->class_name =~ /::purchase_order/) {
+            $result->{"po"} = {"id" => $recvd->id, "state" => $recvd->state};
+            $result->{"li"} = {
+                $lid->lineitem->id => {"state" => $lid->lineitem->state}
+            };
+        } elsif ($recvd->class_name =~ /::lineitem/) {
+            $result->{"li"} = {$recvd->id => {"state" => $recvd->state}};
+        }
+    }
+
     $e->commit;
-    return 1;
+    return $result;
 }
 
 __PACKAGE__->register_method(
@@ -1590,7 +1624,10 @@
             {desc => 'Authentication token', type => 'string'},
             {desc => 'lineitem detail ID', type => 'number'}
         ],
-        return => {desc => '1 on success, Event on error'}
+        return => {desc =>
+            "on success, object containing an LI and possibly a PO; " .
+            "on error, event"
+        }
     }
 );
 
@@ -1613,12 +1650,10 @@
     return $e->die_event unless $e->allowed(
         'RECEIVE_PURCHASE_ORDER', $li->purchase_order->ordering_agency);
 
-    receive_lineitem($mgr, $li_id) or return $e->die_event;
-
+    my $res = receive_lineitem($mgr, $li_id) or return $e->die_event;
     $e->commit;
-    $conn->respond_complete(1);
+    $conn->respond_complete($res);
     $mgr->run_post_response_hooks;
-    return undef;
 }
 
 
@@ -1655,7 +1690,7 @@
 	method => 'rollback_receive_lineitem_detail_api',
 	api_name	=> 'open-ils.acq.lineitem_detail.receive.rollback',
 	signature => {
-        desc => 'Mark a lineitem_detail as received',
+        desc => 'Mark a lineitem_detail as Un-received',
         params => [
             {desc => 'Authentication token', type => 'string'},
             {desc => 'lineitem detail ID', type => 'number'}
@@ -1684,15 +1719,31 @@
     my $po = $li->purchase_order;
 
     return $e->die_event unless $e->allowed('RECEIVE_PURCHASE_ORDER', $po->ordering_agency);
-    rollback_receive_lineitem_detail($mgr, $lid_id) or return $e->die_event;
 
-    $li->state('on-order');
-    $po->state('on-order');
-    udpate_lineitem($mgr, $li) or return $e->die_event;
-    udpate_purchase_order($mgr, $po) or return $e->die_event;
+    my $result = {};
 
-    $e->commit;
-    return 1;
+    my $recvd = rollback_receive_lineitem_detail($mgr, $lid_id)
+        or return $e->die_event;
+
+    if (ref $recvd) {
+        $result->{"lid"} = {$recvd->id => {"recv_time" => $recvd->recv_time}};
+    } else {
+        $result->{"lid"} = {$lid->id => {"recv_time" => $lid->recv_time}};
+    }
+
+    if ($li->state eq "received") {
+        $li->state("on-order");
+        $li = update_lineitem($mgr, $li) or return $e->die_event;
+        $result->{"li"} = {$li->id => {"state" => $li->state}};
+    }
+
+    if ($po->state eq "received") {
+        $po->state("on-order");
+        $po = update_purchase_order($mgr, $po) or return $e->die_event;
+        $result->{"po"} = {$po->id => {"state" => $po->state}};
+    }
+
+    $e->commit and return $result or return $e->die_event;
 }
 
 __PACKAGE__->register_method(
@@ -1704,7 +1755,7 @@
             {desc => 'Authentication token', type => 'string'},
             {desc => 'lineitem detail ID', type => 'number'}
         ],
-        return => {desc => '1 on success, Event on error'}
+        return => {desc => 'altered objects on success, event on error'}
     }
 );
 
@@ -1715,25 +1766,25 @@
     return $e->die_event unless $e->checkauth;
     my $mgr = OpenILS::Application::Acq::BatchManager->new(editor => $e, conn => $conn);
 
-    my $li = $e->retrieve_acq_lineitem_detail([
+    my $li = $e->retrieve_acq_lineitem([
         $li_id, {
-            flesh => 1,
-            flesh_fields => {
-                jub => ['purchase_order']
-            }
+            "flesh" => 1, "flesh_fields" => {"jub" => ["purchase_order"]}
         }
     ]);
     my $po = $li->purchase_order;
 
     return $e->die_event unless $e->allowed('RECEIVE_PURCHASE_ORDER', $po->ordering_agency);
 
-    rollback_receive_lineitem($mgr, $li_id) or return $e->die_event;
+    $li = rollback_receive_lineitem($mgr, $li_id) or return $e->die_event;
 
-    $po->state('on-order');
-    update_purchase_order($mgr, $po) or return $e->die_event;
+    my $result = {"li" => {$li->id => {"state" => $li->state}}};
+    if ($po->state eq "received") {
+        $po->state("on-order");
+        $po = update_purchase_order($mgr, $po) or return $e->die_event;
+        $result->{"po"} = {$po->id => {"state" => $po->state}};
+    }
 
-    $e->commit;
-    return 1;
+    $e->commit and return $result or return $e->die_event;
 }
 
 

Modified: trunk/Open-ILS/web/js/dojo/openils/Util.js
===================================================================
--- trunk/Open-ILS/web/js/dojo/openils/Util.js	2010-02-18 22:43:55 UTC (rev 15592)
+++ trunk/Open-ILS/web/js/dojo/openils/Util.js	2010-02-19 00:41:38 UTC (rev 15593)
@@ -158,11 +158,20 @@
         var classList = node.className.split(/\s+/);
         var className = '';
         for(var i = 0; i < classList.length; i++) {
-            if (classList[i] != cls) {
-                if(i == 0)
-                    className = classList[i];
-                else 
-                    className += ' ' + classList[i];
+            if (typeof(cls) == "object") { /* assume regex */
+                if (!cls.test(classList[i])) {
+                    if(i == 0)
+                        className = classList[i];
+                    else
+                        className += ' ' + classList[i];
+                }
+            } else {
+                if (classList[i] != cls) {
+                    if(i == 0)
+                        className = classList[i];
+                    else
+                        className += ' ' + classList[i];
+                }
             }
         }
         node.className = className;
@@ -264,5 +273,14 @@
         document.body.removeChild(audio);
     }
 
+    /**
+     * Return the properties of an object as a list. Saves typing.
+     */
+    openils.Util.objectProperties = function(obj) {
+        var K = [];
+        for (var k in obj) K.push(k);
+        return K;
+    }
+
 }
 

Modified: trunk/Open-ILS/web/js/dojo/openils/acq/nls/acq.js
===================================================================
--- trunk/Open-ILS/web/js/dojo/openils/acq/nls/acq.js	2010-02-18 22:43:55 UTC (rev 15592)
+++ trunk/Open-ILS/web/js/dojo/openils/acq/nls/acq.js	2010-02-19 00:41:38 UTC (rev 15593)
@@ -17,5 +17,6 @@
     'NO_RESULTS': "No results.",
     'EXPORT_SAVE_DIALOG_TITLE': "Save field values to a file",
     'EXPORT_SHORT_LIST': "Not all of the selected items had the attribute '${0}'.\nChoose OK to save those values that could be found.",
-    'EXPORT_EMPTY_LIST': "No values for attribute '${0}' found."
+    'EXPORT_EMPTY_LIST': "No values for attribute '${0}' found.",
+    'UNRECEIVE_LI': "Are you sure you want to mark this lineitem as UN-received?"
 }

Modified: trunk/Open-ILS/web/js/ui/default/acq/common/li_table.js
===================================================================
--- trunk/Open-ILS/web/js/ui/default/acq/common/li_table.js	2010-02-18 22:43:55 UTC (rev 15592)
+++ trunk/Open-ILS/web/js/ui/default/acq/common/li_table.js	2010-02-19 00:41:38 UTC (rev 15593)
@@ -244,35 +244,15 @@
 
         // lineitem state
         nodeByName('li_state', row).innerHTML = li.state(); // TODO i18n state labels
-        openils.Util.addCSSClass(row, 'oils-acq-li-state-' + li.state());
-
         // lineitem price
         var priceInput = dojo.query('[name=price]', row)[0];
         var priceData = liWrapper.getPrice();
         priceInput.value = (priceData) ? priceData.price : '';
         priceInput.onchange = function() { self.updateLiPrice(priceInput, li) };
 
-        var recv_link = dojo.query('[name=receive_link]', row)[0];
+        // show either "mark received" or "unreceive" as appropriate
+        this.updateReceivedness(li, row);
 
-        if(li.state() == 'on-order') {
-            recv_link.onclick = function() {
-                self.receiveLi(li);
-                openils.Util.hide(recv_link)
-            }
-        } else {
-            openils.Util.hide(recv_link);
-        }
-
-        // TODO we should allow editing before receipt, in which case the
-        // test should be "if 1 or more real (acp) copies exist
-        if(li.state() == 'received') {
-            var real_copies_link = dojo.query('[name=real_copies_link]', row)[0];
-            openils.Util.show(real_copies_link);
-            real_copies_link.onclick = function() {
-                self.showRealCopies(li);
-            }
-        }
-
         if (!skip_final_placement) {
             self.tbody.appendChild(row);
             self.selectors.push(dojo.query('[name=selectbox]', row)[0]);
@@ -281,6 +261,54 @@
         }
     };
 
+    this.updateReceivedness = function(li, row) {
+        if (typeof(row) == "undefined")
+            row = dojo.query('tr[li="' + li.id() + '"]', "acq-lit-tbody")[0];
+
+        var recv_link = nodeByName("receive_link", row);
+        var unrecv_link = nodeByName("unreceive_link", row);
+        var real_copies_link = nodeByName("real_copies_link", row);
+
+        /* handle row coloring for based on LI state */
+        openils.Util.removeCSSClass(row, /^oils-acq-li-state-/);
+        openils.Util.addCSSClass(row, "oils-acq-li-state-" + li.state());
+
+        /* handle links that appear/disappear based on whether LI is received */
+        if (this.isPO) {
+            var self = this;
+            switch(li.state()) {
+                case "on-order":
+                    openils.Util.hide(real_copies_link);
+                    openils.Util.hide(unrecv_link);
+                    openils.Util.show(recv_link, "inline");
+                    if (typeof(recv_link.onclick) != "function")
+                        recv_link.onclick = function() { self.receiveLi(li); };
+                    return;
+                case "received":
+                    openils.Util.hide(recv_link);
+                    openils.Util.show(unrecv_link, "inline");
+                    if (typeof(unrecv_link.onclick) != "function") {
+                        unrecv_link.onclick = function() {
+                            if (confirm(localeStrings.UNRECEIVE_LI))
+                                self.unReceiveLi(li);
+                        };
+                    }
+                    // TODO we should allow editing before receipt, in which case the
+                    // test should be "if 1 or more real (acp) copies exist
+                    openils.Util.show(real_copies_link);
+                    real_copies_link.onclick = function() {
+                        self.showRealCopies(li);
+                    }
+                    return;
+            }
+        }
+
+        openils.Util.hide(recv_link);
+        openils.Util.hide(unrecv_link);
+        openils.Util.hide(real_copies_link);
+    };
+
+
     /**
      * Draws and shows the lineitem notes pane
      */
@@ -1148,16 +1176,59 @@
     }
 
     this.receiveLi = function(li) {
-        if(!this.isPO) return;
+        /* (For now) there shall be no marking LIs received except from the
+         * actual "view PO" interface. */
+        if (!this.isPO) return;
+
+        var self = this;
         progressDialog.show(true);
         fieldmapper.standardRequest(
-            ['open-ils.acq', 'open-ils.acq.lineitem.receive'],
-            {   async: true,
-                params: [this.authtoken, li.id()],
-                onresponse : function(r) {
-                    var resp = openils.Util.readResponse(r);
+            ["open-ils.acq", "open-ils.acq.lineitem.receive"], {
+                "async": true,
+                "params": [this.authtoken, li.id()],
+                "onresponse": function(r) {
+                    self.handleReceiveOrRollback(openils.Util.readResponse(r));
+                },
+                "oncomplete": function() {
                     progressDialog.hide();
+                }
+            }
+        );
+    }
+
+    this.handleReceiveOrRollback = function(resp) {
+        if (resp) {
+            if (resp.li) {
+                for (var li_id in resp.li) {
+                    for (var key in resp.li[li_id])
+                        self.liCache[li_id][key](resp.li[li_id][key]);
+                    self.updateReceivedness(self.liCache[li_id]);
+                }
+            }
+            if (resp.po) {
+                if (typeof(self.poUpdateCallback) == "function")
+                    self.poUpdateCallback(resp.po);
+            }
+        }
+    }
+
+    this.unReceiveLi = function(li) {
+        /* (For now) there shall be no marking LIs un-received except from the
+         * actual "view PO" interface. */
+        if (!this.isPO) return;
+
+        var self = this;
+        progressDialog.show(true);
+        fieldmapper.standardRequest(
+            ["open-ils.acq", "open-ils.acq.lineitem.receive.rollback"], {
+                "async": true,
+                "params": [this.authtoken, li.id()],
+                "onresponse": function(r) {
+                    self.handleReceiveOrRollback(openils.Util.readResponse(r));
                 },
+                "oncomplete": function() {
+                    progressDialog.hide();
+                }
             }
         );
     }

Modified: trunk/Open-ILS/web/js/ui/default/acq/po/view_po.js
===================================================================
--- trunk/Open-ILS/web/js/ui/default/acq/po/view_po.js	2010-02-18 22:43:55 UTC (rev 15592)
+++ trunk/Open-ILS/web/js/ui/default/acq/po/view_po.js	2010-02-19 00:41:38 UTC (rev 15593)
@@ -6,10 +6,19 @@
 var PO = null;
 var liTable;
 
+function updatePoState(po_info) {
+    var data = po_info[PO.id()];
+    if (data && data.state) {
+        PO.state(data.state);
+        dojo.byId("acq-po-view-state").innerHTML = PO.state(); // TODO i18n
+    }
+}
+
 function init() {
     liTable = new AcqLiTable();
     liTable.reset();
     liTable.isPO = poId;
+    liTable.poUpdateCallback = updatePoState;
 
     fieldmapper.standardRequest(
         ['open-ils.acq', 'open-ils.acq.purchase_order.retrieve'],

Modified: trunk/Open-ILS/web/templates/default/acq/common/li_table.tt2
===================================================================
--- trunk/Open-ILS/web/templates/default/acq/common/li_table.tt2	2010-02-18 22:43:55 UTC (rev 15592)
+++ trunk/Open-ILS/web/templates/default/acq/common/li_table.tt2	2010-02-19 00:41:38 UTC (rev 15593)
@@ -92,7 +92,8 @@
                         </table>
                     </td>
                     <td><a class='hidden' name='real_copies_link' href='javascript:void(0);'>Update&nbsp;Barcodes</a></td>
-                    <td><a name='receive_link' href='javascript:void(0);'>Mark&nbsp;Received</a></td>
+                    <td><a name='receive_link' href='javascript:void(0);'>Mark&nbsp;Received</a><a name='unreceive_link' href='javascript:void(0);'>Unreceive</a></td>
+                    </td>
                     <td><a name='copieslink' href='javascript:void(0);'>Copies(<span name='count'>0</span>)</a></td>
                     <td>
                         <a name='noteslink' href='javascript:void(0);' 



More information about the open-ils-commits mailing list