1 dojo.require("dijit.form.Button");
2 dojo.require("dijit.form.NumberSpinner");
3 dojo.require("openils.PermaCrud");
4 dojo.require("openils.acq.Lineitem");
5 dojo.require("openils.widget.AutoFieldWidget");
6 dojo.require("openils.widget.ProgressDialog");
7 dojo.requireLocalization("openils.acq", "acq");
10 var localeStrings = dojo.i18n.getLocalization("openils.acq", "acq");
12 function ReceivableCopyTable() {
15 this._init = function() {
16 this.columns = ["owning_lib", "location", "collection_code",
17 "circ_modifier", "fund", "cn_label", "barcode"];
19 this.tbody = dojo.byId("rows-here");
20 this.pcrud = new openils.PermaCrud();
22 this.mode = "number"; /* can be "number" or "list" */
23 this.some_receiving_done = false;
25 this._init_select_all();
28 this._init_select_all = function() {
29 dojo.byId("select_all").onchange = function() {
30 var checked = this.checked;
31 dojo.query("input[type='checkbox']", self.tbody).forEach(
32 function(cb) { cb.checked = checked; }
37 this._set_invoice_header = function() {
38 dojo.byId("inv-header").innerHTML = dojo.string.substitute(
39 localeStrings.INVOICE_NUMBER, [this.invoice.inv_ident()]
43 this._configure_for_mode = function() {
44 if (this.mode == "list") {
45 openils.Util.show("list-mode-headings", "table-header-group");
46 openils.Util.hide("set-list-mode");
47 openils.Util.show("set-number-mode");
48 dojo.byId("set-number-mode-link").onclick = function() {
53 openils.Util.hide("list-mode-headings");
54 openils.Util.show("set-list-mode");
55 openils.Util.hide("set-number-mode");
56 dojo.byId("set-list-mode-link").onclick = function() {
63 this._get_receivable_details = function(li) {
64 return li.lineitem_details().filter(
65 function(lid) { return (!lid.recv_time() && !lid.cancel_reason()); }
69 this._create_receiver = function(lid, tr, precheck) {
76 if (precheck) args.checked = "checked";
78 dojo.create("input", args, dojo.create("td", null, tr));
81 this._get_selected_list_mode = function() {
82 return dojo.query("input[type=checkbox]", this.tbody).filter(
83 function(cb) { return cb.checked; }
85 function(cb) { return cb.value; }
89 this._get_selected_number_mode = function() {
91 for (var li_id in this.spinners) {
92 var spinner = this.spinners[li_id];
95 var number = spinner.attr("value");
97 this._get_receivable_details(li).slice(0, number)
100 return list.map(function(lid) { return lid.id(); });
103 /* The first time this interface is loaded, use the phys_item_count field
104 * (the "# paid" column on an invoice) to determing how man items to
105 * preselect. Otherwise use 0.
107 this._number_to_preselect = function(ie, li) {
108 return (this.some_receiving_done) ? 0 :
109 Number(ie.phys_item_count() || 0);
111 // var n = Number(ie.phys_item_count() || 0) -
112 // li.lineitem_details().filter(
114 // return lid.recv_time() || lid.cancel_reason()
118 // return n > 0 ? n : 0;
121 this._render_copy_count_info = function() {
122 dojo.byId("inv-copy-count-info").innerHTML =
123 dojo.string.substitute(
124 localeStrings.INVOICE_COPY_COUNT_INFO,
125 [this.copy_number_received, this.copy_number_total]
129 this._increment_copy_count_info = function(li) {
130 var all_uncanceled = li.lineitem_details().filter(
131 function(lid) { return !lid.cancel_reason(); }
133 this.copy_number_total += all_uncanceled.length;
134 this.copy_number_received += all_uncanceled.filter(
135 function(lid) { return Boolean(lid.recv_time()); }
139 this._add_lineitem_number_mode = function(details, li, preselect_count) {
140 var tr = dojo.create("tr", null, this.tbody);
141 var td = dojo.create("td", {
142 "colspan": 1 + this.columns.length,
143 "className": "spinner-cell"
146 var span_id = "number-mode-li-" + li.id();
148 td.innerHTML = localeStrings.COPIES_TO_RECEIVE;
149 dojo.create("span", {"id": span_id}, td);
151 var max = details.length;
152 var value = (preselect_count <= max ? preselect_count : max);
154 this.spinners[li.id()] = new dijit.form.NumberSpinner({
155 "constraints": {"min": 0, "max": max},
158 this.spinners[li.id()]._li = li;
161 this._add_lineitem_list_mode = function(details, li, preselect_count) {
164 //dump("preselect_count "+ preselect_count+"\n");
165 self.add_lineitem_detail(
166 lid, li, Boolean(preselect_count-- > 0)
172 this.add_lineitem_detail = function(lid, li, precheck) {
173 var tr = dojo.create(
174 "tr", {"className": "copy-row"}, this.tbody
177 /* Make receive checkbox cell. */
178 this._create_receiver(lid, tr, precheck);
180 /* Make cells for all the other columns. Using a read-only
181 * AutoFieldWidget to show the value of each field on a lineitem
182 * detail is much easier than worrying about fleshing enough
183 * information to do the same ourselves. */
184 this.columns.forEach(
186 var td = dojo.create("td", null, tr);
187 new openils.widget.AutoFieldWidget({
188 "parentNode": dojo.create("div", null, td),
192 "dijitArgs": {"labelType": (column=='fund') ? "html" : null}
198 /* /maybe/ add a lineitem to the table, if it has any lineitem details
199 * that are still receivable, and preselect lineitem details up to the
200 * number specified in ie.phys_item_count() */
201 this.add_lineitem = function(ie, li, displayHTML) {
202 /* This call only affects the blurb about received vs. total copies
203 * on the invoice near the top of the display. */
204 this._increment_copy_count_info(li);
206 var receivable_details = this._get_receivable_details(li);
207 if (!receivable_details.length) return;
209 /* show lineitem overall description */
210 /* add rows for copies (lineitem details) */
213 "colspan": 1 + this.columns.length,
214 "innerHTML": displayHTML
215 }, dojo.create("tr", null, this.tbody)
218 /* build look-up table */
219 receivable_details.forEach(
220 function(lid) { self.li_by_lid[lid.id()] = li; }
223 /* Render something for receiving the lineitem details, depending
225 this["_add_lineitem_" + this.mode + "_mode"](
226 receivable_details, li, this._number_to_preselect(ie, li)
230 this.reset = function(mode) {
234 this.user_has_acked = [];
236 this.copy_number_received = 0;
237 this.copy_number_total = 0;
240 for (var key in this.spinners)
241 this.spinners[key].destroy();
246 this._configure_for_mode();
248 dojo.empty(this.tbody);
251 /* It's important to remember that an invoice doesn't actually have
252 * lineitems, but rather is made up of invoice entries and invoice items.
253 * Invoice entries usually link to lineitems, though (invoice items
254 * usually link to po_items).
256 this.load = function(inv_id) {
258 this.inv_id = inv_id;
261 progress_dialog.show(true);
264 this.invoice = this.pcrud.retrieve("acqinv", this.inv_id);
265 this._set_invoice_header();
268 this.pcrud.search("acqie", {"invoice": this.inv_id}).forEach(
270 if (entry.lineitem()) {
271 openils.acq.Lineitem.fetchAndRender(
273 {"flesh_li_details": true, "flesh_notes": true},
274 function(li, str) { self.add_lineitem(entry, li, str); }
280 this._render_copy_count_info();
282 if (openils.Util.objectProperties(this.li_by_lid).length) {
283 openils.Util.show("non-empty");
284 openils.Util.hide("empty");
286 openils.Util.hide("non-empty");
287 openils.Util.show("empty");
289 progress_dialog.hide();
292 /* returns an array of lineitem_detail IDs */
293 this.get_selected = function() {
294 return this["_get_selected_" + this.mode + "_mode"]();
297 this.receive_lineitem_detail = function(id_list, index) {
298 if (index >= id_list.length) {
299 progress_dialog.hide();
305 var lid_id = id_list[index];
306 var li = this.li_by_lid[lid_id];
308 if (!this.check_lineitem_alerts(li)) {
309 self.receive_lineitem_detail(id_list, ++index);
313 fieldmapper.standardRequest(
314 ["open-ils.acq", "open-ils.acq.lineitem_detail.receive"], {
316 "params": [openils.User.authtoken, lid_id],
317 "oncomplete": function(r) {
318 if (r = openils.Util.readResponse(r)) {
319 self.some_receiving_done = true;
320 /* receive the next lid in our list */
321 self.receive_lineitem_detail(id_list, ++index);
328 this.receive_selected = function() {
329 var lid_ids = this.get_selected();
331 progress_dialog.show(true);
333 this.receive_lineitem_detail(lid_ids, 0);
336 /* 1st of 2 functions all but copied from li_table.js. Refactor this and
337 * that to share code from a 3rd place.
339 this.check_lineitem_alerts = function(lineitem) {
340 var alert_notes = lineitem.lineitem_notes().filter(
341 function(o) { return Boolean(o.alert_text()); }
344 for (var i = 0; i < alert_notes.length; i++) {
345 if (this.user_has_acked[alert_notes[i].id()])
347 else if (!this.confirm_alert(li, alert_notes[i]))
350 this.user_has_acked[alert_notes[i].id()] = true;
356 /* 2nd of 2 functions all but copied from li_table.js. Refactor this and
357 * that to share code from a 3rd place.
359 this.confirm_alert = function(lineitem, note) {
361 dojo.string.substitute(
362 localeStrings.CONFIRM_LI_ALERT, [
363 (new openils.acq.Lineitem({"lineitem": lineitem})).findAttr(
364 "title", "lineitem_marc_attr_definition"
366 note.alert_text().code(),
367 note.alert_text().description() || "",
374 this.back_to_invoice = function() {
375 location.href = oilsBasePath + "/acq/invoice/view/" + this.inv_id;
378 this._init.apply(this, arguments);
382 copy_table = new ReceivableCopyTable();
383 copy_table.load(inv_id);
386 openils.Util.addOnLoad(my_init);