[open-ils-commits] [GIT] Evergreen ILS branch master updated. 6a83b31d3129d82aff77d1b1ca95af1cca8c331a

Evergreen Git git at git.evergreen-ils.org
Mon Sep 19 11:36:19 EDT 2011


This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "Evergreen ILS".

The branch, master has been updated
       via  6a83b31d3129d82aff77d1b1ca95af1cca8c331a (commit)
      from  9f273271093aa9226c5a27613bb5f7f1d3f0e7db (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 6a83b31d3129d82aff77d1b1ca95af1cca8c331a
Author: Lebbeous Fogle-Weekley <lebbeous at esilibrary.com>
Date:   Wed Aug 3 16:05:21 2011 -0400

    It's a lineitem detail (copy) batch receiver
    
    You can get to it via a button in the upper right-hand corner of
    the view-invoice interface, assuming you're looking at an invoice that's
    already been created/saved (and which has acqlid objects in a receivable
    state), not one you're just now creating.
    
    Signed-off-by: Lebbeous Fogle-Weekley <lebbeous at esilibrary.com>
    Signed-off-by: Mike Rylander <mrylander at gmail.com>

diff --git a/Open-ILS/src/templates/acq/invoice/receive.tt2 b/Open-ILS/src/templates/acq/invoice/receive.tt2
new file mode 100644
index 0000000..6a2abb9
--- /dev/null
+++ b/Open-ILS/src/templates/acq/invoice/receive.tt2
@@ -0,0 +1,64 @@
+[% WRAPPER "base.tt2" %]
+[% ctx.page_title = "Acquisitions Invoice Receiving" %]
+<script type="text/javascript">var inv_id = "[% ctx.page_args.0 %]";</script>
+<script type="text/javascript"
+    src="[% ctx.media_prefix %]/js/ui/default/acq/invoice/receive.js"></script>
+<style type="text/css">
+    #copy_table thead tr th {
+        font-weight: bold;
+        font-size: 110%;
+        text-align: left;
+        background-color: #e2e2e2;
+    }
+    #copy_table tbody { margin: 1ex; }
+    #copy_table tbody tr { background-color: #aaa; }
+    #copy_table tbody tr.copy-row { background-color: #ccc; }
+    #copy_table tbody tr.copy-row:nth-child(odd) { background-color: #ddd; }
+    #copy_table tbody tr.copy-row td { padding: 2px; }
+    .receive-button { margin: 1ex 0; }
+    .spinner-cell { padding: 1ex; background-color: #ddd; }
+</style>
+<div>
+    <p><big>[% ctx.page_title %]</big></p>
+    <p><strong id="inv-header"></strong></p>
+    <div id="non-empty">
+        <p>
+            <span id="set-list-mode">[ <a id="set-list-mode-link" href="javascript:void(0);">Use List Mode</a> ]</span>
+            <span id="set-number-mode">[ <a id="set-number-mode-link" href="javascript:void(0);">Use Numeric Mode</a> ]</span>
+        </p>
+        <div class="receive-button">
+            <button onclick="copy_table.receive_selected();">Receive Selected
+                Copies</button>
+        </div>
+        <table id="copy_table" width="100%">
+            <thead id="list-mode-headings">
+                <tr>
+                    <th>
+                        <input type="checkbox" checked="checked" id="select_all"
+                            /><label for="select_all"> Select All</label>
+                    </th>
+                    <th>Owning Branch</th>
+                    <th>Shelving Location</th>
+                    <th>Collection Code</th>
+                    <th>Fund</th>
+                    <th>Circ Modifier</th>
+                    <th>Callnumber</th>
+                    <th>Barcode</th>
+                </tr>
+            </thead>
+            <tbody id="rows-here">
+            </tbody>
+        </table>
+        <div class="receive-button">
+            <button onclick="copy_table.receive_selected();">Receive Selected
+                Copies</button>
+        </div>
+    </div>
+    <div class="hidden" id="empty">
+        This invoice has no more copies to receive.
+    </div>
+    <div class="hidden">
+        <div dojoType="openils.widget.ProgressDialog" jsId="progress_dialog"></div>
+    </div>
+</div>
+[% END %]
diff --git a/Open-ILS/src/templates/acq/invoice/view.tt2 b/Open-ILS/src/templates/acq/invoice/view.tt2
index 0ddca25..a6289e3 100644
--- a/Open-ILS/src/templates/acq/invoice/view.tt2
+++ b/Open-ILS/src/templates/acq/invoice/view.tt2
@@ -5,7 +5,7 @@
 
     <div dojoType="dijit.layout.ContentPane" layoutAlign="client" class='oils-header-panel'>
         <div> Invoice </div>
-        <div> </div>
+        <div id="acq-view-invoice-receive" class="hidden"><button id="acq-view-invoice-receive-link">Receive Items</button></div>
     </div>
 
     <div dojoType="dijit.layout.ContentPane" layoutAlign="client">
diff --git a/Open-ILS/web/js/dojo/openils/acq/nls/acq.js b/Open-ILS/web/js/dojo/openils/acq/nls/acq.js
index 0525d48..395f79e 100644
--- a/Open-ILS/web/js/dojo/openils/acq/nls/acq.js
+++ b/Open-ILS/web/js/dojo/openils/acq/nls/acq.js
@@ -80,6 +80,7 @@
     "LIBRARY_INITIATED": "Library Initiated",
     "DEL_LI_FROM_PO": "That item has already been ordered!  Deleting it now will not revoke or modify any order that has been placed with a vendor.  Deleting the item may put the system's idea of your purchase order in a state that is inconsistent with reality.  Are you sure you mean to do this?",
     "ADD_LI_TO_PO_BAD_PO_STATE" : "The selected PO has already been activated",
-    "ADD_LI_TO_PO_BAD_LI_STATE" : "The selected lineitem is not in a state that can be added to a purchase order"
-
+    "ADD_LI_TO_PO_BAD_LI_STATE" : "The selected lineitem is not in a state that can be added to a purchase order",
+    "INVOICE_NUMBER": "Invoice #${0}",
+    "COPIES_TO_RECEIVE": "Number of copies to receive: "
 }
diff --git a/Open-ILS/web/js/ui/default/acq/invoice/receive.js b/Open-ILS/web/js/ui/default/acq/invoice/receive.js
new file mode 100644
index 0000000..3930b52
--- /dev/null
+++ b/Open-ILS/web/js/ui/default/acq/invoice/receive.js
@@ -0,0 +1,356 @@
+dojo.require("dijit.form.Button");
+dojo.require("dijit.form.NumberSpinner");
+dojo.require("openils.PermaCrud");
+dojo.require("openils.acq.Lineitem");
+dojo.require("openils.widget.AutoFieldWidget");
+dojo.require("openils.widget.ProgressDialog");
+dojo.requireLocalization("openils.acq", "acq");
+
+var copy_table;
+var localeStrings = dojo.i18n.getLocalization("openils.acq", "acq");
+
+function ReceivableCopyTable() {
+    var self = this;
+
+    this._init = function() {
+        this.columns = ["owning_lib", "location", "collection_code",
+            "circ_modifier", "fund", "cn_label", "barcode"];
+
+        this.tbody = dojo.byId("rows-here");
+        this.pcrud = new openils.PermaCrud();
+
+        this.mode = "number";   /* can be "number" or "list" */
+        this.some_receiving_done = false;
+
+        this._init_select_all();
+    };
+
+    this._init_select_all = function() {
+        dojo.byId("select_all").onchange = function() {
+            var checked = this.checked;
+            dojo.query("input[type='checkbox']", self.tbody).forEach(
+                function(cb) { cb.checked = checked; }
+            );
+        };
+    };
+
+    this._set_invoice_header = function() {
+        dojo.byId("inv-header").innerHTML = dojo.string.substitute(
+            localeStrings.INVOICE_NUMBER, [this.invoice.inv_ident()]
+        );
+    };
+
+    this._configure_for_mode = function() {
+        if (this.mode == "list") {
+            openils.Util.show("list-mode-headings", "table-header-group");
+            openils.Util.hide("set-list-mode");
+            openils.Util.show("set-number-mode");
+            dojo.byId("set-number-mode-link").onclick = function() {
+                self.reset("number");
+                self.load();
+            };
+        } else { /* number */
+            openils.Util.hide("list-mode-headings");
+            openils.Util.show("set-list-mode");
+            openils.Util.hide("set-number-mode");
+            dojo.byId("set-list-mode-link").onclick = function() {
+                self.reset("list");
+                self.load();
+            };
+        }
+    };
+
+    this._get_receivable_details = function(li) {
+        return li.lineitem_details().filter(
+            function(lid) { return (!lid.recv_time() && !lid.cancel_reason()); }
+        );
+    };
+
+    this._create_receiver = function(lid, tr, precheck) {
+        var args = {
+            "type": "checkbox",
+            "name": "receive",
+            "value": lid.id()
+        };
+
+        if (precheck) args.checked = "checked";
+
+        dojo.create("input", args, dojo.create("td", null, tr));
+    };
+
+    this._get_selected_list_mode = function() {
+        return dojo.query("input[type=checkbox]", this.tbody).filter(
+            function(cb) { return cb.checked; }
+        ).map(
+            function(cb) { return cb.value; }
+        );
+    };
+
+    this._get_selected_number_mode = function() {
+        var list = [];
+        for (var li_id in this.spinners) {
+            var spinner = this.spinners[li_id];
+            var li = spinner._li;
+
+            var number = spinner.attr("value");
+            list = list.concat(
+                this._get_receivable_details(li).slice(0, number)
+            );
+        }
+        return list.map(function(lid) { return lid.id(); });
+    };
+
+    /* The first time this interface is loaded, use the phys_item_count field
+     * (the "# paid" column on an invoice) to determing how man items to
+     * preselect.  Otherwise use 0.
+     */
+    this._number_to_preselect = function(ie, li) {
+        return (this.some_receiving_done) ? 0 :
+            Number(ie.phys_item_count() || 0);
+
+//        var n = Number(ie.phys_item_count() || 0) -
+//            li.lineitem_details().filter(
+//                function(lid) {
+//                    return lid.recv_time() || lid.cancel_reason()
+//                }
+//            ).length;
+//
+//        return n > 0 ? n : 0;
+    };
+
+    this._add_lineitem_number_mode = function(details, li, preselect_count) {
+        var tr = dojo.create("tr", null, this.tbody);
+        var td = dojo.create("td", {
+            "colspan": 1 + this.columns.length,
+            "className": "spinner-cell"
+        }, tr);
+
+        var span_id = "number-mode-li-" + li.id();
+
+        td.innerHTML = localeStrings.COPIES_TO_RECEIVE;
+        dojo.create("span", {"id": span_id}, td);
+
+        var max = details.length;
+        var value = (preselect_count <= max ? preselect_count : max);
+
+        this.spinners[li.id()] = new dijit.form.NumberSpinner({
+            "constraints": {"min": 0, "max": max},
+            "value": value
+        }, span_id);
+        this.spinners[li.id()]._li = li;
+    };
+
+    this._add_lineitem_list_mode = function(details, li, preselect_count) {
+        details.forEach(
+            function(lid) {
+                dump("preselect_count "+ preselect_count+"\n");
+                self.add_lineitem_detail(
+                    lid, li, Boolean(preselect_count-- > 0)
+                );
+            }
+        );
+    };
+
+    this.add_lineitem_detail = function(lid, li, precheck) {
+        var tr = dojo.create(
+            "tr", {"className": "copy-row"}, this.tbody
+        );
+
+        /* Make receive checkbox cell. */
+        this._create_receiver(lid, tr, precheck);
+
+        /* Make cells for all the other columns.  Using a read-only
+         * AutoFieldWidget to show the value of each field on a lineitem
+         * detail is much easier than worrying about fleshing enough
+         * information to do the same ourselves. */
+        this.columns.forEach(
+            function(column) {
+                var td = dojo.create("td", null, tr);
+                new openils.widget.AutoFieldWidget({
+                    "parentNode": dojo.create("div", null, td),
+                    "fmField": column,
+                    "fmObject": lid,
+                    "readOnly": true,
+                    "dijitArgs": {"labelType": (column=='fund') ? "html" : null}
+                }).build();
+            }
+        );
+    };
+
+    /* /maybe/ add a lineitem to the table, if it has any lineitem details
+     * that are still receivable, and preselect lineitem details up to the
+     * number specified in ie.phys_item_count() */
+    this.add_lineitem = function(ie, li, displayHTML) {
+        var receivable_details = this._get_receivable_details(li);
+        if (!receivable_details.length) return;
+
+        /* show lineitem overall description */
+        /* add rows for copies (lineitem details) */
+        dojo.create(
+            "td", {
+                "colspan": 1 + this.columns.length,
+                "innerHTML": displayHTML
+            }, dojo.create("tr", null, this.tbody)
+        );
+
+        /* build look-up table */
+        receivable_details.forEach(
+            function(lid) { self.li_by_lid[lid.id()] = li; }
+        );
+
+        /* Render something for receiving the lineitem details, depending
+         * on mode. */
+        this["_add_lineitem_" + this.mode + "_mode"](
+            receivable_details, li, this._number_to_preselect(ie, li)
+        );
+    };
+
+    this.reset = function(mode) {
+        if (mode)
+            this.mode = mode;
+
+        this.user_has_acked = [];
+        this.li_by_lid = {};
+
+        if (this.spinners) {
+            for (var key in this.spinners)
+                this.spinners[key].destroy();
+        }
+
+        this.spinners = {};
+
+        this._configure_for_mode();
+
+        dojo.empty(this.tbody);
+    };
+
+    /* It's important to remember that an invoice doesn't actually have
+     * lineitems, but rather is made up of invoice entries and invoice items.
+     * Invoice entries usually link to lineitems, though (invoice items
+     * usually link to po_items).
+     */
+    this.load = function(inv_id) {
+        if (inv_id)
+            this.inv_id = inv_id;
+
+        this.reset();
+        progress_dialog.show(true);
+
+        if (!this.invoice) {
+            this.invoice = this.pcrud.retrieve("acqinv", this.inv_id);
+            this._set_invoice_header();
+        }
+
+        this.pcrud.search("acqie", {"invoice": this.inv_id}).forEach(
+            function(entry) {
+                if (entry.lineitem()) {
+                    openils.acq.Lineitem.fetchAndRender(
+                        entry.lineitem(),
+                        {"flesh_li_details": true, "flesh_notes": true},
+                        function(li, str) { self.add_lineitem(entry, li, str); }
+                    );
+                }
+            }
+        );
+
+        if (openils.Util.objectProperties(this.li_by_lid).length) {
+            openils.Util.show("non-empty");
+            openils.Util.hide("empty");
+        } else {
+            openils.Util.hide("non-empty");
+            openils.Util.show("empty");
+        }
+        progress_dialog.hide();
+    };
+
+    /* returns an array of lineitem_detail IDs */
+    this.get_selected = function() {
+        return this["_get_selected_" + this.mode + "_mode"]();
+    };
+
+    this.receive_lineitem_detail = function(id_list, index) {
+        if (index >= id_list.length) {
+            progress_dialog.hide();
+            this.load();
+
+            return;
+        }
+
+        var lid_id = id_list[index];
+        var li = this.li_by_lid[lid_id];
+
+        if (!this.check_lineitem_alerts(li)) {
+            self.receive_lineitem_detail(id_list, ++index);
+            return;
+        }
+
+        fieldmapper.standardRequest(
+            ["open-ils.acq", "open-ils.acq.lineitem_detail.receive"], {
+                "async": false,
+                "params": [openils.User.authtoken, lid_id],
+                "oncomplete": function(r) {
+                    if (r = openils.Util.readResponse(r)) {
+                        self.some_receiving_done = true;
+                        /* receive the next lid in our list */
+                        self.receive_lineitem_detail(id_list, ++index);
+                    }
+                }
+            }
+        );
+    };
+
+    this.receive_selected = function() {
+        var lid_ids = this.get_selected();
+
+        progress_dialog.show(true);
+
+        this.receive_lineitem_detail(lid_ids, 0);
+    };
+
+    /* 1st of 2 functions all but copied from li_table.js. Refactor this and
+     * that to share code from a 3rd place.
+     */
+    this.check_lineitem_alerts = function(lineitem) {
+        var alert_notes = lineitem.lineitem_notes().filter(
+            function(o) { return Boolean(o.alert_text()); }
+        );
+
+        for (var i = 0; i < alert_notes.length; i++) {
+            if (this.user_has_acked[alert_notes[i].id()])
+                continue;
+            else if (!this.confirm_alert(li, alert_notes[i]))
+                return false;
+            else
+                this.user_has_acked[alert_notes[i].id()] = true;
+        }
+
+        return true;
+    };
+
+    /* 2nd of 2 functions all but copied from li_table.js. Refactor this and
+     * that to share code from a 3rd place.
+     */
+    this.confirm_alert = function(lineitem, note) {
+        return confirm(
+            dojo.string.substitute(
+                localeStrings.CONFIRM_LI_ALERT, [
+                    (new openils.acq.Lineitem({"lineitem": lineitem})).findAttr(
+                        "title", "lineitem_marc_attr_definition"
+                    ),
+                    note.alert_text().code(),
+                    note.alert_text().description() || "",
+                    note.value()
+                ]
+            )
+        );
+    };
+
+    this._init.apply(this, arguments);
+}
+
+function my_init() {
+    copy_table = new ReceivableCopyTable();
+    copy_table.load(inv_id);
+}
+
+openils.Util.addOnLoad(my_init);
diff --git a/Open-ILS/web/js/ui/default/acq/invoice/view.js b/Open-ILS/web/js/ui/default/acq/invoice/view.js
index e7068b1..a326299 100644
--- a/Open-ILS/web/js/ui/default/acq/invoice/view.js
+++ b/Open-ILS/web/js/ui/default/acq/invoice/view.js
@@ -414,6 +414,22 @@ function addInvoiceItem(item) {
     updateTotalCost();
 }
 
+function updateReceiveLink(li) {
+    if (!invoiceId)
+        return; /* can't do this with unsaved invoices */
+
+    var link = dojo.byId("acq-view-invoice-receive-link");
+    if (link.onclick) return; /* only need to do this once */
+
+    /* don't do this if there's nothing receivable on the lineitem */
+    if (li.order_summary().recv_count() + li.order_summary().cancel_count() >=
+        li.order_summary().item_count())
+        return;
+
+    openils.Util.show("acq-view-invoice-receive");
+    link.onclick = function() { location.href =  oilsBasePath + '/acq/invoice/receive/' + invoiceId; };
+}
+
 function addInvoiceEntry(entry) {
 
     openils.Util.removeCSSClass(dojo.byId('acq-invoice-entry-header'), 'hidden');
@@ -439,6 +455,8 @@ function addInvoiceEntry(entry) {
             entry.purchase_order(li.purchase_order());
             nodeByName('title_details', row).innerHTML = html;
 
+            updateReceiveLink(li);
+
             dojo.forEach(
                 ['inv_item_count', 'phys_item_count', 'cost_billed', 'amount_paid'],
                 function(field) {

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

Summary of changes:
 Open-ILS/src/templates/acq/invoice/receive.tt2    |   64 ++++
 Open-ILS/src/templates/acq/invoice/view.tt2       |    2 +-
 Open-ILS/web/js/dojo/openils/acq/nls/acq.js       |    5 +-
 Open-ILS/web/js/ui/default/acq/invoice/receive.js |  356 +++++++++++++++++++++
 Open-ILS/web/js/ui/default/acq/invoice/view.js    |   18 +
 5 files changed, 442 insertions(+), 3 deletions(-)
 create mode 100644 Open-ILS/src/templates/acq/invoice/receive.tt2
 create mode 100644 Open-ILS/web/js/ui/default/acq/invoice/receive.js


hooks/post-receive
-- 
Evergreen ILS


More information about the open-ils-commits mailing list