1 dojo.require('dijit.form.Button');
2 dojo.require('dijit.form.TextBox');
3 dojo.require('dijit.form.FilteringSelect');
4 dojo.require('dijit.ProgressBar');
5 dojo.require('openils.User');
6 dojo.require('openils.Util');
7 dojo.require('openils.acq.Lineitem');
8 dojo.require('openils.acq.PO');
9 dojo.require('openils.acq.Picklist');
10 dojo.require('openils.widget.AutoFieldWidget');
11 dojo.require('dojo.data.ItemFileReadStore');
12 dojo.require('openils.widget.ProgressDialog');
14 function AcqLiTable() {
18 this.toggleState = false;
19 this.tbody = dojo.byId('acq-lit-tbody');
21 this.authtoken = openils.User.authtoken;
22 this.rowTemplate = this.tbody.removeChild(dojo.byId('acq-lit-row'));
23 this.copyTbody = dojo.byId('acq-lit-li-details-tbody');
24 this.copyRow = this.copyTbody.removeChild(dojo.byId('acq-lit-li-details-row'));
25 this.copyBatchRow = dojo.byId('acq-lit-li-details-batch-row');
26 this.copyBatchWidgets = {};
28 dojo.connect(acqLitLiActionsSelector, 'onChange',
30 self.applySelectedLiAction(this.attr('value'))
31 acqLitLiActionsSelector.attr('value', '_');
34 acqLitCreatePoSubmit.onClick = function() {
35 acqLitPoCreateDialog.hide();
36 self._createPO(acqLitPoCreateDialog.getValues());
39 acqLitSavePlButton.onClick = function() {
40 acqLitSavePlDialog.hide();
41 self._savePl(acqLitSavePlDialog.getValues());
44 dojo.byId('acq-lit-select-toggle').onclick = function(){self.toggleSelect()};
45 dojo.byId('acq-lit-info-back-button').onclick = function(){self.show('list')};
46 dojo.byId('acq-lit-copies-back-button').onclick = function(){self.show('list')};
48 this.reset = function() {
49 while(self.tbody.childNodes[0])
50 self.tbody.removeChild(self.tbody.childNodes[0]);
54 this.setNext = function(handler) {
55 var link = dojo.byId('acq-lit-next');
57 dojo.style(link, 'visibility', 'visible');
58 link.onclick = handler;
60 dojo.style(link, 'visibility', 'hidden');
64 this.setPrev = function(handler) {
65 var link = dojo.byId('acq-lit-prev');
67 dojo.style(link, 'visibility', 'visible');
68 link.onclick = handler;
70 dojo.style(link, 'visibility', 'hidden');
74 this.show = function(div) {
75 openils.Util.hide('acq-lit-table-div');
76 openils.Util.hide('acq-lit-info-div');
77 openils.Util.hide('acq-lit-li-details');
80 openils.Util.show('acq-lit-table-div');
83 openils.Util.show('acq-lit-info-div');
86 openils.Util.show('acq-lit-li-details');
90 openils.Util.show(div);
94 this.hide = function() {
98 this.toggleSelect = function() {
100 dojo.forEach(self.selectors, function(i){i.checked = false});
102 dojo.forEach(self.selectors, function(i){i.checked = true});
103 self.toggleState = !self.toggleState;
107 /** @param all If true, assume all are selected */
108 this.getSelected = function(all) {
110 dojo.forEach(self.selectors,
113 selected.push(self.liCache[i.parentNode.parentNode.getAttribute('li')]);
119 this.setRowAttr = function(td, liWrapper, field, type) {
120 var val = liWrapper.findAttr(field, type || 'lineitem_marc_attr_definition') || '';
121 td.appendChild(document.createTextNode(val));
124 this.addLineitem = function(li) {
125 this.liCache[li.id()] = li;
126 var liWrapper = new openils.acq.Lineitem({lineitem:li});
127 var row = self.rowTemplate.cloneNode(true);
128 row.setAttribute('li', li.id());
129 var tds = dojo.query('[attr]', row);
130 dojo.forEach(tds, function(td) {self.setRowAttr(td, liWrapper, td.getAttribute('attr'), td.getAttribute('attr_type'));});
131 dojo.query('[name=source_label]', row)[0].appendChild(document.createTextNode(li.source_label()));
133 var isbn = liWrapper.findAttr('isbn', 'lineitem_marc_attr_definition');
135 // XXX media prefix for added content
136 dojo.query('[name=jacket]', row)[0].setAttribute('src', '/opac/extras/ac/jacket/small/' + isbn);
139 dojo.query('[attr=title]', row)[0].onclick = function() {self.drawInfo(li.id())};
140 dojo.query('[name=copieslink]', row)[0].onclick = function() {self.drawCopies(li.id())};
141 dojo.query('[name=count]', row)[0].appendChild(document.createTextNode(li.item_count()));
142 dojo.query('[name=estimated_price]', row)[0].value =
143 liWrapper.findAttr('estimated_price', 'lineitem_local_attr_definition');
145 self.tbody.appendChild(row);
146 self.selectors.push(dojo.query('[name=selectbox]', row)[0]);
149 this.removeLineitem = function(liId) {
150 this.tbody.removeChild(dojo.query('[li='+liId+']', this.tbody)[0]);
151 delete this.liCache[liId];
154 this.drawInfo = function(liId) {
156 openils.acq.Lineitem.fetchAttrDefs(
158 self._fetchLineitem(liId, function(li){self._drawInfo(li);});
163 this._fetchLineitem = function(liId, handler) {
165 var li = this.liCache[liId];
166 if(li && li.marc() && li.lineitem_details())
169 fieldmapper.standardRequest(
170 ['open-ils.acq', 'open-ils.acq.lineitem.retrieve'],
173 params: [self.authtoken, liId, {
175 flesh_li_details: true,
176 flesh_fund_debit: true }],
178 oncomplete: function(r) {
179 var li = openils.Util.readResponse(r);
186 this._drawInfo = function(li) {
188 acqLitEditMarc.onClick = function() { self.editMarc(li); }
189 this.drawMarcHTML(li);
190 this.infoTbody = dojo.byId('acq-lit-info-tbody');
193 this.infoRow = this.infoTbody.removeChild(dojo.byId('acq-lit-info-row'));
194 while(this.infoTbody.childNodes[0])
195 this.infoTbody.removeChild(this.infoTbody.childNodes[0]);
197 for(var i = 0; i < li.attributes().length; i++) {
198 var attr = li.attributes()[i];
199 var row = this.infoRow.cloneNode(true);
201 var type = attr.attr_type().replace(/lineitem_(.*)_attr_definition/, '$1');
202 var name = openils.acq.Lineitem.attrDefs[type].filter(
204 return (a.code() == attr.attr_name());
206 ).pop().description();
208 dojo.query('[name=label]', row)[0].appendChild(document.createTextNode(name));
209 dojo.query('[name=value]', row)[0].appendChild(document.createTextNode(attr.attr_value()));
210 this.infoTbody.appendChild(row);
214 this.drawMarcHTML = function(li) {
215 fieldmapper.standardRequest(
216 ['open-ils.search', 'open-ils.search.biblio.record.html'],
218 params: [null, true, li.marc()],
219 oncomplete: function(r) {
220 dojo.byId('acq-lit-marc-div').innerHTML =
221 openils.Util.readResponse(r);
227 this.drawCopies = function(liId) {
231 this.copyWidgetCache = {};
233 acqLitSaveCopies.onClick = function() { self.saveCopyChanges(liId) };
234 acqLitBatchUpdateCopies.onClick = function() { self.batchCopyUpdate() };
236 while(this.copyTbody.childNodes[0])
237 this.copyTbody.removeChild(this.copyTbody.childNodes[0]);
239 this._drawBatchCopyWidgets();
241 this._fetchDistribFormulas(
243 openils.acq.Lineitem.fetchAttrDefs(
245 self._fetchLineitem(liId, function(li){self._drawCopies(li);});
252 this._fetchDistribFormulas = function(onload) {
253 if(this.distribForms) {
257 fieldmapper.standardRequest(
258 ['open-ils.acq', 'open-ils.acq.distribution_formula.ranged.retrieve.atomic'],
260 params: [openils.User.authtoken],
261 oncomplete: function(r) {
262 self.distribForms = openils.Util.readResponse(r);
263 self.distribFormulaStore =
264 new dojo.data.ItemFileReadStore(
265 {data:acqdf.toStoreData(self.distribForms)});
273 this._drawBatchCopyWidgets = function() {
274 var row = this.copyBatchRow;
275 dojo.forEach(['fund', 'owning_lib', 'location'],
277 if(self.copyBatchRowDrawn) {
278 self.copyBatchWidgets[field].attr('value', null);
280 var widget = new openils.widget.AutoFieldWidget({
283 parentNode : dojo.query('[name='+field+']', row)[0],
284 orgLimitPerms : ['CREATE_PICKLIST'],
285 dijitArgs : {required:false}
288 self.copyBatchWidgets[field] = widget.widget;
292 this.copyBatchRowDrawn = true;
295 this.batchCopyUpdate = function() {
297 var fields = ['fund', 'owning_lib', 'location'];
298 for(var k in this.copyWidgetCache) {
299 var cache = this.copyWidgetCache[k];
300 dojo.forEach(fields, function(f) {
301 var newval = self.copyBatchWidgets[f].attr('value');
302 if(newval) cache[f].attr('value', newval);
307 this._drawCopies = function(li) {
308 acqLitAddCopyCount.onClick = function() {
309 var count = acqLitCopyCountInput.attr('value');
310 for(var i = 0; i < count; i++)
313 if(li.lineitem_details().length > 0) {
314 dojo.forEach(li.lineitem_details(),
316 self.addCopy(li, copy);
324 this.virtCopyId = -1;
325 this.addCopy = function(li, copy) {
326 var row = this.copyRow.cloneNode(true);
327 this.copyTbody.appendChild(row);
331 copy = new fieldmapper.acqlid();
333 copy.id(this.virtCopyId--);
334 copy.lineitem(li.id());
337 this.copyCache[copy.id()] = copy;
338 row.setAttribute('copy_id', copy.id());
339 self.copyWidgetCache[copy.id()] = {};
341 dojo.forEach(['fund', 'owning_lib', 'location', 'barcode', 'cn_label'],
343 var widget = new openils.widget.AutoFieldWidget({
347 parentNode : dojo.query('[name='+field+']', row)[0],
348 orgLimitPerms : ['CREATE_PICKLIST'],
352 // make sure we capture the value from any async widgets
353 function(w, ww) { copy[field](ww.getFormattedValue()) }
355 dojo.connect(widget.widget, 'onChange',
357 if(copy.isnew() || val != copy[field]()) {
358 // prevent setting ischanged() automatically on widget load for existing copies
359 copy[field](widget.getFormattedValue())
360 copy.ischanged(true);
364 self.copyWidgetCache[copy.id()][field] = widget.widget;
369 openils.Util.hide(dojo.query('[name=delete]', row)[0].parentNode);
371 dojo.query('[name=delete]', row)[0].onclick =
372 function() { self.deleteCopy(row) };
376 this.deleteCopy = function(row) {
377 var copy = this.copyCache[row.getAttribute('copy_id')];
378 copy.isdeleted(true);
380 delete this.copyCache[copy.id()];
381 this.copyTbody.removeChild(row);
384 this.saveCopyChanges = function(liId) {
388 openils.Util.show('acq-lit-update-copies-progress');
390 for(var id in this.copyCache) {
391 var c = this.copyCache[id];
392 if(c.isnew() || c.ischanged() || c.isdeleted()) {
393 if(c.id() < 0) c.id(null);
398 if(copies.length == 0)
401 fieldmapper.standardRequest(
402 ['open-ils.acq', 'open-ils.acq.lineitem_detail.cud.batch'],
404 params: [openils.User.authtoken, copies],
405 onresponse: function(r) {
406 var res = openils.Util.readResponse(r);
407 litUpdateCopiesProgress.update(res);
409 oncomplete: function() {
410 openils.Util.hide('acq-lit-update-copies-progress');
411 self.drawCopies(liId);
417 this.applySelectedLiAction = function(action) {
421 case 'delete_selected':
422 this._deleteLiList(self.getSelected());
427 if(!this.createPoProviderSelector) {
428 var widget = new openils.widget.AutoFieldWidget({
429 fmField : 'provider',
431 parentNode : dojo.byId('acq-lit-po-provider'),
432 orgLimitPerms : ['CREATE_PURCHASE_ORDER'],
435 function(w) { self.createPoProviderSelector = w; }
439 acqLitPoCreateDialog.show();
442 case 'save_picklist':
443 this._loadPLSelect();
444 acqLitSavePlDialog.show();
457 this.printPO = function() {
458 if(!this.isPO) return;
459 progressDialogInd.show();
460 fieldmapper.standardRequest(
461 ['open-ils.acq', 'open-ils.acq.purchase_order.format'],
463 params: [this.authtoken, this.isPO, 'html'],
464 oncomplete: function(r) {
465 progressDialogInd.hide();
466 var evt = openils.Util.readResponse(r);
467 if(evt && evt.template_output()) {
468 win = window.open('','', 'resizable,width=700,height=500,scrollbars=1');
469 win.document.body.innerHTML = evt.template_output().data();
477 this.receivePO = function() {
478 if(!this.isPO) return;
479 progressDialog.show();
481 dojo.forEach(this.liCache, function(){maximum += 1; });
482 dojo.forEach(this.copyCache, function(){maximum += 1; });
483 fieldmapper.standardRequest(
484 ['open-ils.acq', 'open-ils.acq.purchase_order.receive'],
486 params: [this.authtoken, this.isPO],
487 onresponse : function(r) {
488 var stat = openils.Util.readResponse(r);
490 // we don't know the total amount of items to be processed
491 // since we only have 1 page of data
492 if(stat.progress > maximum) maximum *= 2;
494 progressDialog.update({maximum:maximum, progress:stat.progress});
497 location.href = location.href;
505 this._createPO = function(fields) {
506 this.show('acq-lit-create-po-progress');
507 var po = new fieldmapper.acqpo();
508 po.provider(this.createPoProviderSelector.attr('value'));
510 var selected = this.getSelected( (fields.create_from == 'all') );
511 if(selected.length == 0) return;
513 var max = selected.length * 3;
515 fieldmapper.standardRequest(
516 ['open-ils.acq', 'open-ils.acq.purchase_order.create'],
519 openils.User.authtoken,
522 lineitems : selected.map(function(li) { return li.id() }),
523 create_assets : true,
524 create_debits : true,
525 circ_modifier : 'book', /* XXX */
528 onresponse : function(r) {
529 var resp = openils.Util.readResponse(r);
530 openils.Util.appendClear('acq-lit-po-encumbered', document.createTextNode(resp.total_debits));
531 openils.Util.appendClear('acq-lit-po-copies', document.createTextNode(resp.total_copies));
532 litPoTotalProgress.update({maximum:max, progress:resp.progress});
534 location.href = oilsBasePath + '/eg/acq/po/view/' + resp.purchase_order;
540 this._deleteLiList = function(list, idx) {
541 if(idx == null) idx = 0;
542 if(idx >= list.length) return;
543 var liId = list[idx].id();
544 fieldmapper.standardRequest(
545 ['open-ils.acq', 'open-ils.acq.lineitem.delete'],
547 params: [openils.User.authtoken, liId],
548 oncomplete: function(r) {
549 self.removeLineitem(liId);
550 self._deleteLiList(list, ++idx);
556 this.editMarc = function(li) {
558 /* To run in Firefox directly, must set signed.applets.codebase_principal_support
559 to true in about:config */
561 netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
562 win = window.open('/xul/server/cat/marcedit.xul'); // XXX version?
566 record : {marc : li.marc()},
568 label: 'Save Record', // XXX I18N
569 func: function(xmlString) {
571 fieldmapper.standardRequest(
572 ['open-ils.acq', 'open-ils.acq.lineitem.update'],
574 params: [openils.User.authtoken, li],
575 oncomplete: function(r) {
576 openils.Util.readResponse(r);
578 self.drawInfo(li.id())
588 this._savePl = function(values) {
590 var selected = this.getSelected( (values.which == 'all') );
591 openils.Util.show('acq-lit-generic-progress');
593 if(values.new_name) {
594 openils.acq.Picklist.create(
595 {name: values.new_name},
597 self._updateLiList(id, selected, 0,
599 location.href = oilsBasePath + '/eg/acq/picklist/view/' + id;
603 } else if(values.existing_pl) {
604 // update lineitems to use an existing picklist
605 self._updateLiList(values.existing_pl, selected, 0,
607 location.href = oilsBasePath + '/eg/acq/picklist/view/' + values.existing_pl;
612 this._updateLiList = function(pl, list, idx, oncomplete) {
613 if(idx >= list.length) return oncomplete();
616 litGenericProgress.update({maximum: list.length, progress: idx});
617 new openils.acq.Lineitem({lineitem:li}).update(
619 self._updateLiList(pl, list, ++idx, oncomplete);
624 this._loadPLSelect = function() {
625 if(this._plSelectLoaded) return;
627 function handleResponse(r) {
628 plList.push(r.recv().content());
630 var method = 'open-ils.acq.picklist.user.retrieve';
631 fieldmapper.standardRequest(
632 ['open-ils.acq', method],
634 params: [this.authtoken],
635 onresponse: handleResponse,
636 oncomplete: function() {
637 self._plSelectLoaded = true;
638 acqLitAddExistingSelect.store =
639 new dojo.data.ItemFileReadStore({data:acqpl.toStoreData(plList)});
640 acqLitAddExistingSelect.setValue();