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');
13 dojo.requireLocalization('openils.acq', 'acq');
14 var localeStrings = dojo.i18n.getLocalization('openils.acq', 'acq');
16 function AcqLiTable() {
20 this.toggleState = false;
21 this.tbody = dojo.byId('acq-lit-tbody');
23 this.authtoken = openils.User.authtoken;
24 this.rowTemplate = this.tbody.removeChild(dojo.byId('acq-lit-row'));
25 this.copyTbody = dojo.byId('acq-lit-li-details-tbody');
26 this.copyRow = this.copyTbody.removeChild(dojo.byId('acq-lit-li-details-row'));
27 this.copyBatchRow = dojo.byId('acq-lit-li-details-batch-row');
28 this.copyBatchWidgets = {};
30 dojo.connect(acqLitLiActionsSelector, 'onChange',
32 self.applySelectedLiAction(this.attr('value'))
33 acqLitLiActionsSelector.attr('value', '_');
36 acqLitCreatePoSubmit.onClick = function() {
37 acqLitPoCreateDialog.hide();
38 self._createPO(acqLitPoCreateDialog.getValues());
41 acqLitSavePlButton.onClick = function() {
42 acqLitSavePlDialog.hide();
43 self._savePl(acqLitSavePlDialog.getValues());
46 dojo.byId('acq-lit-select-toggle').onclick = function(){self.toggleSelect()};
47 dojo.byId('acq-lit-info-back-button').onclick = function(){self.show('list')};
48 dojo.byId('acq-lit-copies-back-button').onclick = function(){self.show('list')};
50 this.reset = function() {
51 while(self.tbody.childNodes[0])
52 self.tbody.removeChild(self.tbody.childNodes[0]);
56 this.setNext = function(handler) {
57 var link = dojo.byId('acq-lit-next');
59 dojo.style(link, 'visibility', 'visible');
60 link.onclick = handler;
62 dojo.style(link, 'visibility', 'hidden');
66 this.setPrev = function(handler) {
67 var link = dojo.byId('acq-lit-prev');
69 dojo.style(link, 'visibility', 'visible');
70 link.onclick = handler;
72 dojo.style(link, 'visibility', 'hidden');
76 this.show = function(div) {
77 openils.Util.hide('acq-lit-table-div');
78 openils.Util.hide('acq-lit-info-div');
79 openils.Util.hide('acq-lit-li-details');
82 openils.Util.show('acq-lit-table-div');
85 openils.Util.show('acq-lit-info-div');
88 openils.Util.show('acq-lit-li-details');
92 openils.Util.show(div);
96 this.hide = function() {
100 this.toggleSelect = function() {
102 dojo.forEach(self.selectors, function(i){i.checked = false});
104 dojo.forEach(self.selectors, function(i){i.checked = true});
105 self.toggleState = !self.toggleState;
109 /** @param all If true, assume all are selected */
110 this.getSelected = function(all) {
112 dojo.forEach(self.selectors,
115 selected.push(self.liCache[i.parentNode.parentNode.getAttribute('li')]);
121 this.setRowAttr = function(td, liWrapper, field, type) {
122 var val = liWrapper.findAttr(field, type || 'lineitem_marc_attr_definition') || '';
123 td.appendChild(document.createTextNode(val));
126 this.addLineitem = function(li) {
127 this.liCache[li.id()] = li;
128 var liWrapper = new openils.acq.Lineitem({lineitem:li});
129 var row = self.rowTemplate.cloneNode(true);
130 row.setAttribute('li', li.id());
131 var tds = dojo.query('[attr]', row);
132 dojo.forEach(tds, function(td) {self.setRowAttr(td, liWrapper, td.getAttribute('attr'), td.getAttribute('attr_type'));});
133 dojo.query('[name=source_label]', row)[0].appendChild(document.createTextNode(li.source_label()));
135 var isbn = liWrapper.findAttr('isbn', 'lineitem_marc_attr_definition');
137 // XXX media prefix for added content
138 dojo.query('[name=jacket]', row)[0].setAttribute('src', '/opac/extras/ac/jacket/small/' + isbn);
141 dojo.query('[attr=title]', row)[0].onclick = function() {self.drawInfo(li.id())};
142 dojo.query('[name=copieslink]', row)[0].onclick = function() {self.drawCopies(li.id())};
143 dojo.query('[name=count]', row)[0].appendChild(document.createTextNode(li.item_count()));
145 var priceInput = dojo.query('[name=estimated_price]', row)[0];
146 var priceData = liWrapper.getPrice();
147 priceInput.value = (priceData) ? priceData.price : '';
148 priceInput.onchange = function() { self.updateLiPrice(priceInput, li) };
150 self.tbody.appendChild(row);
151 self.selectors.push(dojo.query('[name=selectbox]', row)[0]);
154 self.updateLiPrice = function(input, li) {
156 var price = input.value;
157 var liWrapper = new openils.acq.Lineitem({lineitem:li});
158 var oldPrice = liWrapper.getPrice() || null;
160 if(oldPrice) oldPrice = oldPrice.price;
161 if(price == oldPrice) return;
163 fieldmapper.standardRequest(
164 ['open-ils.acq', 'open-ils.acq.lineitem_local_attr.set'],
166 params : [this.authtoken, li.id(), 'estimated_price', price],
167 oncomplete : function(r) {
168 openils.Util.readResponse(r);
174 this.removeLineitem = function(liId) {
175 this.tbody.removeChild(dojo.query('[li='+liId+']', this.tbody)[0]);
176 delete this.liCache[liId];
179 this.drawInfo = function(liId) {
181 openils.acq.Lineitem.fetchAttrDefs(
183 self._fetchLineitem(liId, function(li){self._drawInfo(li);});
188 this._fetchLineitem = function(liId, handler) {
190 var li = this.liCache[liId];
191 if(li && li.marc() && li.lineitem_details())
194 fieldmapper.standardRequest(
195 ['open-ils.acq', 'open-ils.acq.lineitem.retrieve'],
198 params: [self.authtoken, liId, {
200 flesh_li_details: true,
201 flesh_fund_debit: true }],
203 oncomplete: function(r) {
204 var li = openils.Util.readResponse(r);
211 this._drawInfo = function(li) {
213 acqLitEditMarc.onClick = function() { self.editMarc(li); }
214 this.drawMarcHTML(li);
215 this.infoTbody = dojo.byId('acq-lit-info-tbody');
218 this.infoRow = this.infoTbody.removeChild(dojo.byId('acq-lit-info-row'));
219 while(this.infoTbody.childNodes[0])
220 this.infoTbody.removeChild(this.infoTbody.childNodes[0]);
222 for(var i = 0; i < li.attributes().length; i++) {
223 var attr = li.attributes()[i];
224 var row = this.infoRow.cloneNode(true);
226 var type = attr.attr_type().replace(/lineitem_(.*)_attr_definition/, '$1');
227 var name = openils.acq.Lineitem.attrDefs[type].filter(
229 return (a.code() == attr.attr_name());
231 ).pop().description();
233 dojo.query('[name=label]', row)[0].appendChild(document.createTextNode(name));
234 dojo.query('[name=value]', row)[0].appendChild(document.createTextNode(attr.attr_value()));
235 this.infoTbody.appendChild(row);
239 openils.Util.show('acq-lit-info-cat-link');
240 var link = dojo.byId('acq-lit-info-cat-link').getElementsByTagName('a')[0];
241 link.setAttribute('href', link.getAttribute('href') + li.eg_bib_id());
243 openils.Util.hide('acq-lit-info-cat-link');
247 this.drawMarcHTML = function(li) {
248 fieldmapper.standardRequest(
249 ['open-ils.search', 'open-ils.search.biblio.record.html'],
251 params: [null, true, li.marc()],
252 oncomplete: function(r) {
253 dojo.byId('acq-lit-marc-div').innerHTML =
254 openils.Util.readResponse(r);
260 this.drawCopies = function(liId) {
264 this.copyWidgetCache = {};
266 acqLitSaveCopies.onClick = function() { self.saveCopyChanges(liId) };
267 acqLitBatchUpdateCopies.onClick = function() { self.batchCopyUpdate() };
269 while(this.copyTbody.childNodes[0])
270 this.copyTbody.removeChild(this.copyTbody.childNodes[0]);
272 this._drawBatchCopyWidgets();
274 this._fetchDistribFormulas(
276 openils.acq.Lineitem.fetchAttrDefs(
278 self._fetchLineitem(liId, function(li){self._drawCopies(li);});
285 this._fetchDistribFormulas = function(onload) {
286 if(this.distribForms) {
290 fieldmapper.standardRequest(
291 ['open-ils.acq', 'open-ils.acq.distribution_formula.ranged.retrieve.atomic'],
293 params: [openils.User.authtoken],
294 oncomplete: function(r) {
295 self.distribForms = openils.Util.readResponse(r);
296 self.distribFormulaStore =
297 new dojo.data.ItemFileReadStore(
298 {data:acqdf.toStoreData(self.distribForms)});
306 this._drawBatchCopyWidgets = function() {
307 var row = this.copyBatchRow;
308 dojo.forEach(['fund', 'owning_lib', 'location', 'circ_modifier', 'cn_label'],
310 if(self.copyBatchRowDrawn) {
311 self.copyBatchWidgets[field].attr('value', null);
313 var widget = new openils.widget.AutoFieldWidget({
316 parentNode : dojo.query('[name='+field+']', row)[0],
317 orgLimitPerms : ['CREATE_PICKLIST'],
318 dijitArgs : {required:false}
321 self.copyBatchWidgets[field] = widget.widget;
325 this.copyBatchRowDrawn = true;
328 this.batchCopyUpdate = function() {
330 var fields = ['fund', 'owning_lib', 'location', 'circ_modifier', 'cn_label'];
331 for(var k in this.copyWidgetCache) {
332 var cache = this.copyWidgetCache[k];
333 dojo.forEach(fields, function(f) {
334 var newval = self.copyBatchWidgets[f].attr('value');
335 if(newval) cache[f].attr('value', newval);
340 this._drawCopies = function(li) {
341 acqLitAddCopyCount.onClick = function() {
342 var count = acqLitCopyCountInput.attr('value');
343 for(var i = 0; i < count; i++)
346 if(li.lineitem_details().length > 0) {
347 dojo.forEach(li.lineitem_details(),
349 self.addCopy(li, copy);
357 this.virtCopyId = -1;
358 this.addCopy = function(li, copy) {
359 var row = this.copyRow.cloneNode(true);
360 this.copyTbody.appendChild(row);
364 copy = new fieldmapper.acqlid();
366 copy.id(this.virtCopyId--);
367 copy.lineitem(li.id());
370 this.copyCache[copy.id()] = copy;
371 row.setAttribute('copy_id', copy.id());
372 self.copyWidgetCache[copy.id()] = {};
374 dojo.forEach(['fund', 'owning_lib', 'location', 'barcode', 'cn_label', 'circ_modifier', 'note'],
376 var widget = new openils.widget.AutoFieldWidget({
380 parentNode : dojo.query('[name='+field+']', row)[0],
381 orgLimitPerms : ['CREATE_PICKLIST'],
385 // make sure we capture the value from any async widgets
386 function(w, ww) { copy[field](ww.getFormattedValue()) }
388 dojo.connect(widget.widget, 'onChange',
390 if(copy.isnew() || val != copy[field]()) {
391 // prevent setting ischanged() automatically on widget load for existing copies
392 copy[field](widget.getFormattedValue())
393 copy.ischanged(true);
397 self.copyWidgetCache[copy.id()][field] = widget.widget;
402 openils.Util.hide(dojo.query('[name=delete]', row)[0].parentNode);
404 dojo.query('[name=delete]', row)[0].onclick =
405 function() { self.deleteCopy(row) };
409 this.deleteCopy = function(row) {
410 var copy = this.copyCache[row.getAttribute('copy_id')];
411 copy.isdeleted(true);
413 delete this.copyCache[copy.id()];
414 this.copyTbody.removeChild(row);
417 this.saveCopyChanges = function(liId) {
421 openils.Util.show('acq-lit-update-copies-progress');
423 for(var id in this.copyCache) {
424 var c = this.copyCache[id];
425 if(c.isnew() || c.ischanged() || c.isdeleted()) {
426 if(c.id() < 0) c.id(null);
431 if(copies.length == 0)
434 fieldmapper.standardRequest(
435 ['open-ils.acq', 'open-ils.acq.lineitem_detail.cud.batch'],
437 params: [openils.User.authtoken, copies],
438 onresponse: function(r) {
439 var res = openils.Util.readResponse(r);
440 litUpdateCopiesProgress.update(res);
442 oncomplete: function() {
443 openils.Util.hide('acq-lit-update-copies-progress');
444 self.drawCopies(liId);
450 this.applySelectedLiAction = function(action) {
454 case 'delete_selected':
455 this._deleteLiList(self.getSelected());
460 if(!this.createPoProviderSelector) {
461 var widget = new openils.widget.AutoFieldWidget({
462 fmField : 'provider',
464 parentNode : dojo.byId('acq-lit-po-provider'),
465 orgLimitPerms : ['CREATE_PURCHASE_ORDER'],
468 function(w) { self.createPoProviderSelector = w; }
472 acqLitPoCreateDialog.show();
475 case 'save_picklist':
476 this._loadPLSelect();
477 acqLitSavePlDialog.show();
488 case 'rollback_receive_po':
489 this.rollbackPoReceive();
492 case 'create_assets':
498 this.createAssets = function() {
499 if(!this.isPO) return;
500 if(!confirm(localeStrings.CREATE_PO_ASSETS_CONFIRM)) return;
501 this.show('acq-lit-progress-numbers');
503 fieldmapper.standardRequest(
504 ['open-ils.acq', 'open-ils.acq.purchase_order.assets.create'],
506 params: [this.authtoken, this.isPO],
507 onresponse: function(r) {
508 var resp = openils.Util.readResponse(r);
509 self._updateProgressNumbers(resp, true);
515 this.printPO = function() {
516 if(!this.isPO) return;
517 progressDialogInd.show();
518 fieldmapper.standardRequest(
519 ['open-ils.acq', 'open-ils.acq.purchase_order.format'],
521 params: [this.authtoken, this.isPO, 'html'],
522 oncomplete: function(r) {
523 progressDialogInd.hide();
524 var evt = openils.Util.readResponse(r);
525 if(evt && evt.template_output()) {
526 win = window.open('','', 'resizable,width=800,height=600,scrollbars=1');
527 win.document.body.innerHTML = evt.template_output().data();
535 this.receivePO = function() {
536 if(!this.isPO) return;
537 this.show('acq-lit-progress-numbers');
539 fieldmapper.standardRequest(
540 ['open-ils.acq', 'open-ils.acq.purchase_order.receive'],
542 params: [this.authtoken, this.isPO],
543 onresponse : function(r) {
544 var resp = openils.Util.readResponse(r);
545 self._updateProgressNumbers(resp, true);
551 this.rollbackPoReceive = function() {
552 if(!this.isPO) return;
553 if(!confirm(localeStrings.ROLLBACK_PO_RECEIVE_CONFIRM)) return;
554 this.show('acq-lit-progress-numbers');
556 fieldmapper.standardRequest(
557 ['open-ils.acq', 'open-ils.acq.purchase_order.receive.rollback'],
559 params: [this.authtoken, this.isPO],
560 onresponse : function(r) {
561 var resp = openils.Util.readResponse(r);
562 self._updateProgressNumbers(resp, true);
568 this._updateProgressNumbers = function(resp, reloadOnComplete) {
570 dojo.byId('acq-pl-lit-li-processed').innerHTML = resp.li;
571 dojo.byId('acq-pl-lit-lid-processed').innerHTML = resp.lid;
572 dojo.byId('acq-pl-lit-debits-processed').innerHTML = resp.debits_accrued;
573 dojo.byId('acq-pl-lit-bibs-processed').innerHTML = resp.bibs;
574 dojo.byId('acq-pl-lit-indexed-processed').innerHTML = resp.indexed;
575 dojo.byId('acq-pl-lit-copies-processed').innerHTML = resp.copies;
576 if(resp.complete && reloadOnComplete)
577 location.href = location.href;
581 this._createPO = function(fields) {
582 this.show('acq-lit-progress-numbers');
583 var po = new fieldmapper.acqpo();
584 po.provider(this.createPoProviderSelector.attr('value'));
586 var selected = this.getSelected( (fields.create_from == 'all') );
587 if(selected.length == 0) return;
589 var max = selected.length * 3;
592 fieldmapper.standardRequest(
593 ['open-ils.acq', 'open-ils.acq.purchase_order.create'],
596 openils.User.authtoken,
599 lineitems : selected.map(function(li) { return li.id() }),
600 create_assets : fields.create_assets[0],
604 onresponse : function(r) {
605 var resp = openils.Util.readResponse(r);
606 self._updateProgressNumbers(resp);
608 location.href = oilsBasePath + '/eg/acq/po/view/' + resp.purchase_order.id();
614 this._deleteLiList = function(list, idx) {
615 if(idx == null) idx = 0;
616 if(idx >= list.length) return;
617 var liId = list[idx].id();
618 fieldmapper.standardRequest(
619 ['open-ils.acq', 'open-ils.acq.lineitem.delete'],
621 params: [openils.User.authtoken, liId],
622 oncomplete: function(r) {
623 self.removeLineitem(liId);
624 self._deleteLiList(list, ++idx);
630 this.editMarc = function(li) {
632 /* To run in Firefox directly, must set signed.applets.codebase_principal_support
633 to true in about:config */
635 netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
636 win = window.open('/xul/server/cat/marcedit.xul'); // XXX version?
640 record : {marc : li.marc()},
642 label: 'Save Record', // XXX I18N
643 func: function(xmlString) {
645 fieldmapper.standardRequest(
646 ['open-ils.acq', 'open-ils.acq.lineitem.update'],
648 params: [openils.User.authtoken, li],
649 oncomplete: function(r) {
650 openils.Util.readResponse(r);
652 self.drawInfo(li.id())
662 this._savePl = function(values) {
664 var selected = this.getSelected( (values.which == 'all') );
665 openils.Util.show('acq-lit-generic-progress');
667 if(values.new_name) {
668 openils.acq.Picklist.create(
669 {name: values.new_name},
671 self._updateLiList(id, selected, 0,
673 location.href = oilsBasePath + '/eg/acq/picklist/view/' + id;
677 } else if(values.existing_pl) {
678 // update lineitems to use an existing picklist
679 self._updateLiList(values.existing_pl, selected, 0,
681 location.href = oilsBasePath + '/eg/acq/picklist/view/' + values.existing_pl;
686 this._updateLiList = function(pl, list, idx, oncomplete) {
687 if(idx >= list.length) return oncomplete();
690 litGenericProgress.update({maximum: list.length, progress: idx});
691 new openils.acq.Lineitem({lineitem:li}).update(
693 self._updateLiList(pl, list, ++idx, oncomplete);
698 this._loadPLSelect = function() {
699 if(this._plSelectLoaded) return;
701 function handleResponse(r) {
702 plList.push(r.recv().content());
704 var method = 'open-ils.acq.picklist.user.retrieve';
705 fieldmapper.standardRequest(
706 ['open-ils.acq', method],
708 params: [this.authtoken],
709 onresponse: handleResponse,
710 oncomplete: function() {
711 self._plSelectLoaded = true;
712 acqLitAddExistingSelect.store =
713 new dojo.data.ItemFileReadStore({data:acqpl.toStoreData(plList)});
714 acqLitAddExistingSelect.setValue();