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._add_lineitem_number_mode = function(details, li, preselect_count) {
122 var tr = dojo.create("tr", null, this.tbody);
123 var td = dojo.create("td", {
124 "colspan": 1 + this.columns.length,
125 "className": "spinner-cell"
128 var span_id = "number-mode-li-" + li.id();
130 td.innerHTML = localeStrings.COPIES_TO_RECEIVE;
131 dojo.create("span", {"id": span_id}, td);
133 var max = details.length;
134 var value = (preselect_count <= max ? preselect_count : max);
136 this.spinners[li.id()] = new dijit.form.NumberSpinner({
137 "constraints": {"min": 0, "max": max},
140 this.spinners[li.id()]._li = li;
143 this._add_lineitem_list_mode = function(details, li, preselect_count) {
146 dump("preselect_count "+ preselect_count+"\n");
147 self.add_lineitem_detail(
148 lid, li, Boolean(preselect_count-- > 0)
154 this.add_lineitem_detail = function(lid, li, precheck) {
155 var tr = dojo.create(
156 "tr", {"className": "copy-row"}, this.tbody
159 /* Make receive checkbox cell. */
160 this._create_receiver(lid, tr, precheck);
162 /* Make cells for all the other columns. Using a read-only
163 * AutoFieldWidget to show the value of each field on a lineitem
164 * detail is much easier than worrying about fleshing enough
165 * information to do the same ourselves. */
166 this.columns.forEach(
168 var td = dojo.create("td", null, tr);
169 new openils.widget.AutoFieldWidget({
170 "parentNode": dojo.create("div", null, td),
174 "dijitArgs": {"labelType": (column=='fund') ? "html" : null}
180 /* /maybe/ add a lineitem to the table, if it has any lineitem details
181 * that are still receivable, and preselect lineitem details up to the
182 * number specified in ie.phys_item_count() */
183 this.add_lineitem = function(ie, li, displayHTML) {
184 var receivable_details = this._get_receivable_details(li);
185 if (!receivable_details.length) return;
187 /* show lineitem overall description */
188 /* add rows for copies (lineitem details) */
191 "colspan": 1 + this.columns.length,
192 "innerHTML": displayHTML
193 }, dojo.create("tr", null, this.tbody)
196 /* build look-up table */
197 receivable_details.forEach(
198 function(lid) { self.li_by_lid[lid.id()] = li; }
201 /* Render something for receiving the lineitem details, depending
203 this["_add_lineitem_" + this.mode + "_mode"](
204 receivable_details, li, this._number_to_preselect(ie, li)
208 this.reset = function(mode) {
212 this.user_has_acked = [];
216 for (var key in this.spinners)
217 this.spinners[key].destroy();
222 this._configure_for_mode();
224 dojo.empty(this.tbody);
227 /* It's important to remember that an invoice doesn't actually have
228 * lineitems, but rather is made up of invoice entries and invoice items.
229 * Invoice entries usually link to lineitems, though (invoice items
230 * usually link to po_items).
232 this.load = function(inv_id) {
234 this.inv_id = inv_id;
237 progress_dialog.show(true);
240 this.invoice = this.pcrud.retrieve("acqinv", this.inv_id);
241 this._set_invoice_header();
244 this.pcrud.search("acqie", {"invoice": this.inv_id}).forEach(
246 if (entry.lineitem()) {
247 openils.acq.Lineitem.fetchAndRender(
249 {"flesh_li_details": true, "flesh_notes": true},
250 function(li, str) { self.add_lineitem(entry, li, str); }
256 if (openils.Util.objectProperties(this.li_by_lid).length) {
257 openils.Util.show("non-empty");
258 openils.Util.hide("empty");
260 openils.Util.hide("non-empty");
261 openils.Util.show("empty");
263 progress_dialog.hide();
266 /* returns an array of lineitem_detail IDs */
267 this.get_selected = function() {
268 return this["_get_selected_" + this.mode + "_mode"]();
271 this.receive_lineitem_detail = function(id_list, index) {
272 if (index >= id_list.length) {
273 progress_dialog.hide();
279 var lid_id = id_list[index];
280 var li = this.li_by_lid[lid_id];
282 if (!this.check_lineitem_alerts(li)) {
283 self.receive_lineitem_detail(id_list, ++index);
287 fieldmapper.standardRequest(
288 ["open-ils.acq", "open-ils.acq.lineitem_detail.receive"], {
290 "params": [openils.User.authtoken, lid_id],
291 "oncomplete": function(r) {
292 if (r = openils.Util.readResponse(r)) {
293 self.some_receiving_done = true;
294 /* receive the next lid in our list */
295 self.receive_lineitem_detail(id_list, ++index);
302 this.receive_selected = function() {
303 var lid_ids = this.get_selected();
305 progress_dialog.show(true);
307 this.receive_lineitem_detail(lid_ids, 0);
310 /* 1st of 2 functions all but copied from li_table.js. Refactor this and
311 * that to share code from a 3rd place.
313 this.check_lineitem_alerts = function(lineitem) {
314 var alert_notes = lineitem.lineitem_notes().filter(
315 function(o) { return Boolean(o.alert_text()); }
318 for (var i = 0; i < alert_notes.length; i++) {
319 if (this.user_has_acked[alert_notes[i].id()])
321 else if (!this.confirm_alert(li, alert_notes[i]))
324 this.user_has_acked[alert_notes[i].id()] = true;
330 /* 2nd of 2 functions all but copied from li_table.js. Refactor this and
331 * that to share code from a 3rd place.
333 this.confirm_alert = function(lineitem, note) {
335 dojo.string.substitute(
336 localeStrings.CONFIRM_LI_ALERT, [
337 (new openils.acq.Lineitem({"lineitem": lineitem})).findAttr(
338 "title", "lineitem_marc_attr_definition"
340 note.alert_text().code(),
341 note.alert_text().description() || "",
348 this._init.apply(this, arguments);
352 copy_table = new ReceivableCopyTable();
353 copy_table.load(inv_id);
356 openils.Util.addOnLoad(my_init);