]> git.evergreen-ils.org Git - Evergreen.git/blob - Open-ILS/web/js/ui/default/acq/common/li_table.js
clean up the lineitem notes handling. clean up actions dropdown
[Evergreen.git] / Open-ILS / web / js / ui / default / acq / common / li_table.js
1 dojo.require('dojo.date.locale');
2 dojo.require('dojo.date.stamp');
3 dojo.require('dijit.form.Button');
4 dojo.require('dijit.form.TextBox');
5 dojo.require('dijit.form.FilteringSelect');
6 dojo.require('dijit.form.Textarea');
7 dojo.require('dijit.ProgressBar');
8 dojo.require('openils.User');
9 dojo.require('openils.Util');
10 dojo.require('openils.acq.Lineitem');
11 dojo.require('openils.acq.PO');
12 dojo.require('openils.acq.Picklist');
13 dojo.require('openils.widget.AutoFieldWidget');
14 dojo.require('dojo.data.ItemFileReadStore');
15 dojo.require('openils.widget.ProgressDialog');
16 dojo.require('openils.PermaCrud');
17
18 dojo.requireLocalization('openils.acq', 'acq');
19 var localeStrings = dojo.i18n.getLocalization('openils.acq', 'acq');
20
21 function AcqLiTable() {
22
23     var self = this;
24     this.liCache = {};
25     this.toggleState = false;
26     this.tbody = dojo.byId('acq-lit-tbody');
27     this.selectors = [];
28     this.authtoken = openils.User.authtoken;
29     this.rowTemplate = this.tbody.removeChild(dojo.byId('acq-lit-row'));
30     this.copyTbody = dojo.byId('acq-lit-li-details-tbody');
31     this.copyRow = this.copyTbody.removeChild(dojo.byId('acq-lit-li-details-row'));
32     this.copyBatchRow = dojo.byId('acq-lit-li-details-batch-row');
33     this.copyBatchWidgets = {};
34     this.liNotesTbody = dojo.byId('acq-lit-notes-tbody');
35     this.liNotesRow = this.liNotesTbody.removeChild(dojo.byId('acq-lit-notes-row'));
36
37     dojo.connect(acqLitLiActionsSelector, 'onChange', 
38         function() { 
39             self.applySelectedLiAction(this.attr('value')) 
40             acqLitLiActionsSelector.attr('value', '_');
41         });
42
43     acqLitCreatePoSubmit.onClick = function() {
44         acqLitPoCreateDialog.hide();
45         self._createPO(acqLitPoCreateDialog.getValues());
46     }
47
48     acqLitSavePlButton.onClick = function() {
49         acqLitSavePlDialog.hide();
50         self._savePl(acqLitSavePlDialog.getValues());
51     }
52
53     //dojo.byId('acq-lit-notes-new-button').onclick = function(){acqLitCreateLiNoteDialog.show();}
54
55     dojo.byId('acq-lit-select-toggle').onclick = function(){self.toggleSelect()};
56     dojo.byId('acq-lit-info-back-button').onclick = function(){self.show('list')};
57     dojo.byId('acq-lit-copies-back-button').onclick = function(){self.show('list')};
58     dojo.byId('acq-lit-notes-back-button').onclick = function(){self.show('list')};
59
60     this.reset = function() {
61         while(self.tbody.childNodes[0])
62             self.tbody.removeChild(self.tbody.childNodes[0]);
63         self.selectors = [];
64     };
65     
66     this.setNext = function(handler) {
67         var link = dojo.byId('acq-lit-next');
68         if(handler) {
69             dojo.style(link, 'visibility', 'visible');
70             link.onclick = handler;
71         } else {
72             dojo.style(link, 'visibility', 'hidden');
73         }
74     };
75
76     this.setPrev = function(handler) {
77         var link = dojo.byId('acq-lit-prev');
78         if(handler) {
79             dojo.style(link, 'visibility', 'visible'); 
80             link.onclick = handler; 
81         } else {
82             dojo.style(link, 'visibility', 'hidden');
83         }
84     };
85
86     this.show = function(div) {
87         openils.Util.hide('acq-lit-table-div');
88         openils.Util.hide('acq-lit-info-div');
89         openils.Util.hide('acq-lit-li-details');
90         openils.Util.hide('acq-lit-notes-div');
91         switch(div) {
92             case 'list':
93                 openils.Util.show('acq-lit-table-div');
94                 break;
95             case 'info':
96                 openils.Util.show('acq-lit-info-div');
97                 break;
98             case 'copies':
99                 openils.Util.show('acq-lit-li-details');
100                 break;
101             case 'notes':
102                 openils.Util.show('acq-lit-notes-div');
103                 break;
104             default:
105                 if(div) 
106                     openils.Util.show(div);
107         }
108     }
109
110     this.hide = function() {
111         this.show(null);
112     }
113
114     this.toggleSelect = function() {
115         if(self.toggleState) 
116             dojo.forEach(self.selectors, function(i){i.checked = false});
117         else 
118             dojo.forEach(self.selectors, function(i){i.checked = true});
119         self.toggleState = !self.toggleState;
120     };
121
122
123     /** @param all If true, assume all are selected */
124     this.getSelected = function(all) {
125         var selected = [];
126         dojo.forEach(self.selectors, 
127             function(i) { 
128                 if(i.checked || all)
129                     selected.push(self.liCache[i.parentNode.parentNode.getAttribute('li')]);
130             }
131         );
132         return selected;
133     };
134
135     this.setRowAttr = function(td, liWrapper, field, type) {
136         var val = liWrapper.findAttr(field, type || 'lineitem_marc_attr_definition') || '';
137         td.appendChild(document.createTextNode(val));
138     };
139
140     this.addLineitem = function(li) {
141         this.liCache[li.id()] = li;
142
143         // sort the lineitem notes on edit_time
144         if(!li.lineitem_notes()) li.lineitem_notes([]);
145
146         var liWrapper = new openils.acq.Lineitem({lineitem:li});
147         var row = self.rowTemplate.cloneNode(true);
148         row.setAttribute('li', li.id());
149         var tds = dojo.query('[attr]', row);
150         dojo.forEach(tds, function(td) {self.setRowAttr(td, liWrapper, td.getAttribute('attr'), td.getAttribute('attr_type'));});
151         dojo.query('[name=source_label]', row)[0].appendChild(document.createTextNode(li.source_label()));
152
153         var isbn = liWrapper.findAttr('isbn', 'lineitem_marc_attr_definition');
154         if(isbn) {
155             // XXX media prefix for added content
156             dojo.query('[name=jacket]', row)[0].setAttribute('src', '/opac/extras/ac/jacket/small/' + isbn);
157         }
158
159         dojo.query('[attr=title]', row)[0].onclick = function() {self.drawInfo(li.id())};
160         dojo.query('[name=copieslink]', row)[0].onclick = function() {self.drawCopies(li.id())};
161         dojo.query('[name=count]', row)[0].innerHTML = li.item_count() || 0;
162         dojo.query('[name=notes_count]', row)[0].innerHTML = li.lineitem_notes().length;
163         dojo.query('[name=noteslink]', row)[0].onclick = function() {self.drawLiNotes(li)};
164
165         var priceInput = dojo.query('[name=price]', row)[0];
166         var priceData = liWrapper.getPrice();
167         priceInput.value = (priceData) ? priceData.price : '';
168         priceInput.onchange = function() { self.updateLiPrice(priceInput, li) };
169
170         var recv_link = dojo.query('[name=receive_link]', row)[0];
171         if(li.state() == 'received') {
172             openils.Util.hide(recv_link)
173         } else {
174             recv_link.onclick = function() {
175                 self.receiveLi(li);
176                 openils.Util.hide(recv_link)
177             }
178         }
179
180         self.tbody.appendChild(row);
181         self.selectors.push(dojo.query('[name=selectbox]', row)[0]);
182     };
183
184     this.drawLiNotes = function(li) {
185         var self = this;
186
187         li.lineitem_notes(
188             li.lineitem_notes().sort(
189                 function(a, b) { 
190                     if(a.edit_time() < b.edit_time()) return 1;
191                     return -1;
192                 }
193             )
194         );
195
196         while(this.liNotesTbody.childNodes[0])
197             this.liNotesTbody.removeChild(this.liNotesTbody.childNodes[0]);
198         this.show('notes');
199
200         acqLitCreateLiNoteSubmit.onClick = function() {
201             var value = acqLitCreateNoteText.attr('value');
202             if(!value) return;
203             var note = new fieldmapper.acqlin();
204             note.isnew(true);
205             note.value(value);
206             note.lineitem(li.id());
207             self.updateLiNotes(li, note);
208         }
209
210         dojo.byId('acq-lit-notes-save-button').onclick = function() {
211             self.updateLiNotes(li);
212         }
213
214         dojo.forEach(li.lineitem_notes(), function(note) { self.addLiNote(li, note) });
215     }
216
217     this.addLiNote = function(li, note) {
218         if(note.isdeleted()) return;
219         var self = this;
220         var row = self.liNotesRow.cloneNode(true);
221         dojo.query('[name=value]', row)[0].innerHTML = note.value();
222
223         dojo.query('[name=delete]', row)[0].onclick = function() {
224             note.isdeleted(true);
225             self.liNotesTbody.removeChild(row);
226         };
227
228         if(note.edit_time()) {
229             dojo.query('[name=edit_time]', row)[0].innerHTML = 
230                 dojo.date.locale.format(
231                     dojo.date.stamp.fromISOString(note.edit_time()), 
232                     {formatLength:'short'});
233         }
234
235         self.liNotesTbody.appendChild(row);
236     }
237
238     this.updateLiNotes = function(li, newNote) {
239
240         var notes;
241         if(newNote) {
242             notes = [newNote];
243         } else {
244             notes = li.lineitem_notes().filter(
245                 function(note) {
246                     if(note.ischanged() || note.isnew() || note.isdeleted())
247                         return note;
248                 }
249             );
250         }
251
252         if(notes.length == 0) return;
253         progressDialog.show();
254
255         fieldmapper.standardRequest(
256             ['open-ils.acq', 'open-ils.acq.lineitem_note.cud.batch'],
257             {   async : true,
258                 params : [this.authtoken, notes],
259                 onresponse : function(r) {
260                     var resp = openils.Util.readResponse(r);
261
262                     if(resp.complete) {
263
264                         if(!newNote) {
265                             // remove the old changed notes
266                             var list = [];
267                             dojo.forEach(li.lineitem_notes(), 
268                                 function(note) {
269                                     if(!(note.ischanged() || note.isnew() || note.isdeleted()))
270                                         list.push(note);
271                                 }
272                             );
273                             li.lineitem_notes(list);
274                         }
275
276                         progressDialog.hide();
277                         self.drawLiNotes(li);
278                         return;
279                     }
280
281                     progressDialog.update(resp);
282                     var newnote = resp.note;
283
284                     if(!newnote.isdeleted()) {
285                         newnote.isnew(false);
286                         newnote.ischanged(false);
287                         li.lineitem_notes().push(newnote);
288                     }
289                 },
290             }
291         );
292     }
293
294     this.updateLiPrice = function(input, li) {
295
296         var price = input.value;
297         var liWrapper = new openils.acq.Lineitem({lineitem:li});
298         var oldPrice = liWrapper.getPrice() || null;
299
300         if(oldPrice) oldPrice = oldPrice.price;
301         if(price == oldPrice) return;
302
303         fieldmapper.standardRequest(
304             ['open-ils.acq', 'open-ils.acq.lineitem.price.set'],
305             {   async : true,
306                 params : [this.authtoken, li.id(), price],
307                 oncomplete : function(r) {
308                     openils.Util.readResponse(r);
309                 }
310             }
311         );
312     }
313
314     this.removeLineitem = function(liId) {
315         this.tbody.removeChild(dojo.query('[li='+liId+']', this.tbody)[0]);
316         delete this.liCache[liId];
317     }
318
319     this.drawInfo = function(liId) {
320         this.show('info');
321         openils.acq.Lineitem.fetchAttrDefs(
322             function() { 
323                 self._fetchLineitem(liId, function(li){self._drawInfo(li);}); 
324             } 
325         );
326     };
327
328     this._fetchLineitem = function(liId, handler) {
329
330         var li = this.liCache[liId];
331         if(li && li.marc() && li.lineitem_details())
332             return handler(li);
333         
334         fieldmapper.standardRequest(
335             ['open-ils.acq', 'open-ils.acq.lineitem.retrieve'],
336             {   async: true,
337
338                 params: [self.authtoken, liId, {
339                     flesh_attrs: true,
340                     flesh_li_details: true,
341                     flesh_fund_debit: true }],
342
343                 oncomplete: function(r) {
344                     var li = openils.Util.readResponse(r);
345                     handler(li)
346                 }
347             }
348         );
349     };
350
351     this._drawInfo = function(li) {
352
353         acqLitEditOrderMarc.onClick = function() { self.editOrderMarc(li); }
354         acqLitEditILSMarc.onClick = function() { self.editILSMarc(li); }
355
356         if(li.eg_bib_id()) {
357             openils.Util.hide('acq-lit-marc-order-record-label');
358             openils.Util.hide(acqLitEditOrderMarc.domNode);
359             openils.Util.show('acq-lit-marc-real-record-label');
360             openils.Util.show(acqLitEditILSMarc.domNode);
361         } else {
362             openils.Util.show('acq-lit-marc-order-record-label');
363             openils.Util.show(acqLitEditOrderMarc.domNode);
364             openils.Util.hide('acq-lit-marc-real-record-label');
365             openils.Util.hide(acqLitEditILSMarc.domNode);
366         }
367
368         this.drawMarcHTML(li);
369         this.infoTbody = dojo.byId('acq-lit-info-tbody');
370
371         if(!this.infoRow)
372             this.infoRow = this.infoTbody.removeChild(dojo.byId('acq-lit-info-row'));
373         while(this.infoTbody.childNodes[0])
374             this.infoTbody.removeChild(this.infoTbody.childNodes[0]);
375
376         for(var i = 0; i < li.attributes().length; i++) {
377             var attr = li.attributes()[i];
378             var row = this.infoRow.cloneNode(true);
379
380             var type = attr.attr_type().replace(/lineitem_(.*)_attr_definition/, '$1');
381             var name = openils.acq.Lineitem.attrDefs[type].filter(
382                 function(a) {
383                     return (a.code() == attr.attr_name());
384                 }
385             ).pop().description();
386
387             dojo.query('[name=label]', row)[0].appendChild(document.createTextNode(name));
388             dojo.query('[name=value]', row)[0].appendChild(document.createTextNode(attr.attr_value()));
389             this.infoTbody.appendChild(row);
390         }
391
392         if(li.eg_bib_id()) {
393             openils.Util.show('acq-lit-info-cat-link');
394             var link = dojo.byId('acq-lit-info-cat-link').getElementsByTagName('a')[0];
395             var href = link.getAttribute('href');
396             if(href.match(/=$/))
397                 link.setAttribute('href',  href + li.eg_bib_id());
398         } else {
399             openils.Util.hide('acq-lit-info-cat-link');
400         }
401     };
402
403     this.drawMarcHTML = function(li) {
404         var params = [null, true, li.marc()];
405         if(li.eg_bib_id()) 
406             params = [li.eg_bib_id(), true];
407
408         fieldmapper.standardRequest(
409             ['open-ils.search', 'open-ils.search.biblio.record.html'],
410             {   async: true,
411                 params: params,
412                 oncomplete: function(r) {
413                     dojo.byId('acq-lit-marc-div').innerHTML = 
414                         openils.Util.readResponse(r);
415                 }
416             }
417         );
418
419         if(li.eg_bib_id()) {
420             if(this.canEditILSMarc === true) {
421                 acqLitEditILSMarc.attr('disabled', false);
422             } else {
423                 if(this.canEditILSMarc === false) {
424                     acqLitEditILSMarc.attr('disabled', true);
425                 } else {
426                     var self = this;
427                     new openils.User().getPermOrgList('UPDATE_RECORD', 
428                         function(list) { 
429                             if(list.length > 0) {
430                                 self.canEditILSMarc = true;
431                                 acqLitEditILSMarc.attr('disabled', false);
432                             } else {
433                                 self.canEditILSMarc = false;
434                                 acqLitEditILSMarc.attr('disabled', true);
435                             }
436                         }
437                     );
438                 }
439             }
440         }
441     }
442
443     this.drawCopies = function(liId) {
444         this.show('copies');
445         var self = this;
446         this.copyCache = {};
447         this.copyWidgetCache = {};
448
449         acqLitSaveCopies.onClick = function() { self.saveCopyChanges(liId) };
450         acqLitBatchUpdateCopies.onClick = function() { self.batchCopyUpdate() };
451
452         while(this.copyTbody.childNodes[0])
453             this.copyTbody.removeChild(this.copyTbody.childNodes[0]);
454
455         this._drawBatchCopyWidgets();
456
457         this._fetchDistribFormulas(
458             function() {
459                 openils.acq.Lineitem.fetchAttrDefs(
460                     function() { 
461                         self._fetchLineitem(liId, function(li){self._drawCopies(li);}); 
462                     } 
463                 );
464             }
465         );
466     };
467
468     this._fetchDistribFormulas = function(onload) {
469         if(this.distribForms) {
470             onload();
471         } else {
472             var self = this;
473             fieldmapper.standardRequest(
474                 ['open-ils.acq', 'open-ils.acq.distribution_formula.ranged.retrieve.atomic'],
475                 {   async: true,
476                     params: [openils.User.authtoken],
477                     oncomplete: function(r) {
478                         self.distribForms = openils.Util.readResponse(r);
479                         self.distribFormulaStore = 
480                             new dojo.data.ItemFileReadStore(
481                                 {data:acqdf.toStoreData(self.distribForms)});
482                         onload();
483                     }
484                 }
485             );
486         }
487     }
488
489     this._drawBatchCopyWidgets = function() {
490         var row = this.copyBatchRow;
491         dojo.forEach(['fund', 'owning_lib', 'location', 'circ_modifier', 'cn_label'],
492             function(field) {
493                 if(self.copyBatchRowDrawn) {
494                     self.copyBatchWidgets[field].attr('value', null);
495                 } else {
496                     var widget = new openils.widget.AutoFieldWidget({
497                         fmField : field,
498                         fmClass : 'acqlid',
499                         parentNode : dojo.query('[name='+field+']', row)[0],
500                         orgLimitPerms : ['CREATE_PICKLIST'],
501                         dijitArgs : {required:false}
502                     });
503                     widget.build();
504                     self.copyBatchWidgets[field] = widget.widget;
505                 }
506             }
507         );
508         this.copyBatchRowDrawn = true;
509     };
510
511     this.batchCopyUpdate = function() {
512         var self = this;
513         var fields = ['fund', 'owning_lib', 'location', 'circ_modifier', 'cn_label'];
514         for(var k in this.copyWidgetCache) {
515             var cache = this.copyWidgetCache[k];
516             dojo.forEach(fields, function(f) {
517                 var newval = self.copyBatchWidgets[f].attr('value');
518                 if(newval) cache[f].attr('value', newval);
519             });
520         }
521     };
522
523     this._drawCopies = function(li) {
524         acqLitAddCopyCount.onClick = function() { 
525             var count = acqLitCopyCountInput.attr('value');
526             for(var i = 0; i < count; i++)
527                 self.addCopy(li); 
528         }
529         if(li.lineitem_details().length > 0) {
530             dojo.forEach(li.lineitem_details(),
531                 function(copy) {
532                     self.addCopy(li, copy);
533                 }
534             );
535         } else {
536             self.addCopy(li);
537         }
538     };
539
540     this.virtCopyId = -1;
541     this.addCopy = function(li, copy) {
542         var row = this.copyRow.cloneNode(true);
543         this.copyTbody.appendChild(row);
544         var self = this;
545
546         if(!copy) {
547             copy = new fieldmapper.acqlid();
548             copy.isnew(true);
549             copy.id(this.virtCopyId--);
550             copy.lineitem(li.id());
551         }
552
553         this.copyCache[copy.id()] = copy;
554         row.setAttribute('copy_id', copy.id());
555         self.copyWidgetCache[copy.id()] = {};
556
557         dojo.forEach(['fund', 'owning_lib', 'location', 'barcode', 'cn_label', 'circ_modifier', 'note'],
558             function(field) {
559                 var widget = new openils.widget.AutoFieldWidget({
560                     fmObject : copy,
561                     fmField : field,
562                     fmClass : 'acqlid',
563                     parentNode : dojo.query('[name='+field+']', row)[0],
564                     orgLimitPerms : ['CREATE_PICKLIST'],
565                     readOnly : self.isPO
566                 });
567                 widget.build(
568                     // make sure we capture the value from any async widgets
569                     function(w, ww) { copy[field](ww.getFormattedValue()) }
570                 );
571                 dojo.connect(widget.widget, 'onChange', 
572                     function(val) { 
573                         if(copy.isnew() || val != copy[field]()) {
574                             // prevent setting ischanged() automatically on widget load for existing copies
575                             copy[field](widget.getFormattedValue()) 
576                             copy.ischanged(true);
577                         }
578                     }
579                 );
580                 self.copyWidgetCache[copy.id()][field] = widget.widget;
581             }
582         );
583
584         var recv_link = dojo.query('[name=receive]', row)[0];
585         if(copy.recv_time()) {
586             openils.Util.hide(recv_link);
587         } else {
588             recv_link.onclick = function() {
589                 self.receiveLid(copy);
590                 openils.Util.hide(recv_link);
591             }
592         }
593
594         if(this.isPO) {
595             openils.Util.hide(dojo.query('[name=delete]', row)[0].parentNode);
596         } else {
597             dojo.query('[name=delete]', row)[0].onclick = 
598                 function() { self.deleteCopy(row) };
599         }
600     };
601
602     this.deleteCopy = function(row) {
603         var copy = this.copyCache[row.getAttribute('copy_id')];
604         copy.isdeleted(true);
605         if(copy.isnew())
606             delete this.copyCache[copy.id()];
607         this.copyTbody.removeChild(row);
608     }
609
610     this.saveCopyChanges = function(liId) {
611         var self = this;
612         var copies = [];
613
614         openils.Util.show('acq-lit-update-copies-progress');
615
616         for(var id in this.copyCache) {
617             var c = this.copyCache[id];
618             if(c.isnew() || c.ischanged() || c.isdeleted()) {
619                 if(c.id() < 0) c.id(null);
620                 copies.push(c);
621             }
622         }
623
624         if(copies.length == 0)
625             return;
626
627         fieldmapper.standardRequest(
628             ['open-ils.acq', 'open-ils.acq.lineitem_detail.cud.batch'],
629             {   async: true,
630                 params: [openils.User.authtoken, copies],
631                 onresponse: function(r) {
632                     var res = openils.Util.readResponse(r);
633                     litUpdateCopiesProgress.update(res);
634                 },
635                 oncomplete: function() {
636                     openils.Util.hide('acq-lit-update-copies-progress');
637                     self.drawCopies(liId); 
638                 }
639             }
640         );
641     }
642
643     this.applySelectedLiAction = function(action) {
644         var self = this;
645         switch(action) {
646
647             case 'delete_selected':
648                 this._deleteLiList(self.getSelected());
649                 break;
650
651             case 'create_order':
652
653                 if(!this.createPoProviderSelector) {
654                     var widget = new openils.widget.AutoFieldWidget({
655                         fmField : 'provider',
656                         fmClass : 'acqpo',
657                         parentNode : dojo.byId('acq-lit-po-provider'),
658                         orgLimitPerms : ['CREATE_PURCHASE_ORDER'],
659                     });
660                     widget.build(
661                         function(w) { self.createPoProviderSelector = w; }
662                     );
663                 }
664          
665                 acqLitPoCreateDialog.show();
666                 break;
667
668             case 'save_picklist':
669                 this._loadPLSelect();
670                 acqLitSavePlDialog.show();
671                 break;
672
673             case 'print_po':
674                 this.printPO();
675                 break;
676
677             case 'receive_po':
678                 this.receivePO();
679                 break;
680
681             case 'rollback_receive_po':
682                 this.rollbackPoReceive();
683                 break;
684
685             case 'create_assets':
686                 this.createAssets();
687                 break;
688         }
689     }
690
691     this.createAssets = function() {
692         if(!this.isPO) return;
693         if(!confirm(localeStrings.CREATE_PO_ASSETS_CONFIRM)) return;
694         this.show('acq-lit-progress-numbers');
695         var self = this;
696         fieldmapper.standardRequest(
697             ['open-ils.acq', 'open-ils.acq.purchase_order.assets.create'],
698             {   async: true,
699                 params: [this.authtoken, this.isPO],
700                 onresponse: function(r) {
701                     var resp = openils.Util.readResponse(r);
702                     self._updateProgressNumbers(resp, true);
703                 }
704             }
705         );
706     }
707
708     this.printPO = function() {
709         if(!this.isPO) return;
710         progressDialog.show(true);
711         fieldmapper.standardRequest(
712             ['open-ils.acq', 'open-ils.acq.purchase_order.format'],
713             {   async: true,
714                 params: [this.authtoken, this.isPO, 'html'],
715                 oncomplete: function(r) {
716                     progressDialog.hide();
717                     var evt = openils.Util.readResponse(r);
718                     if(evt && evt.template_output()) {
719                         win = window.open('','', 'resizable,width=800,height=600,scrollbars=1');
720                         win.document.body.innerHTML = evt.template_output().data();
721                     }
722                 }
723             }
724         );
725     }
726
727
728     this.receivePO = function() {
729         if(!this.isPO) return;
730         this.show('acq-lit-progress-numbers');
731         var self = this;
732         fieldmapper.standardRequest(
733             ['open-ils.acq', 'open-ils.acq.purchase_order.receive'],
734             {   async: true,
735                 params: [this.authtoken, this.isPO],
736                 onresponse : function(r) {
737                     var resp = openils.Util.readResponse(r);
738                     self._updateProgressNumbers(resp, true);
739                 },
740             }
741         );
742     }
743
744     this.receiveLi = function(li) {
745         if(!this.isPO) return;
746         progressDialog.show(true);
747         fieldmapper.standardRequest(
748             ['open-ils.acq', 'open-ils.acq.lineitem.receive'],
749             {   async: true,
750                 params: [this.authtoken, li.id()],
751                 onresponse : function(r) {
752                     var resp = openils.Util.readResponse(r);
753                     progressDialog.hide();
754                 },
755             }
756         );
757     }
758
759     this.receiveLid = function(li) {
760         if(!this.isPO) return;
761         progressDialog.show(true);
762         fieldmapper.standardRequest(
763             ['open-ils.acq', 'open-ils.acq.lineitem_detail.receive'],
764             {   async: true,
765                 params: [this.authtoken, li.id()],
766                 onresponse : function(r) {
767                     var resp = openils.Util.readResponse(r);
768                     progressDialog.hide();
769                 },
770             }
771         );
772     }
773
774     this.rollbackPoReceive = function() {
775         if(!this.isPO) return;
776         if(!confirm(localeStrings.ROLLBACK_PO_RECEIVE_CONFIRM)) return;
777         this.show('acq-lit-progress-numbers');
778         var self = this;
779         fieldmapper.standardRequest(
780             ['open-ils.acq', 'open-ils.acq.purchase_order.receive.rollback'],
781             {   async: true,
782                 params: [this.authtoken, this.isPO],
783                 onresponse : function(r) {
784                     var resp = openils.Util.readResponse(r);
785                     self._updateProgressNumbers(resp, true);
786                 },
787             }
788         );
789     }
790
791     this._updateProgressNumbers = function(resp, reloadOnComplete) {
792         if(!resp) return;
793         dojo.byId('acq-pl-lit-li-processed').innerHTML = resp.li;
794         dojo.byId('acq-pl-lit-lid-processed').innerHTML = resp.lid;
795         dojo.byId('acq-pl-lit-debits-processed').innerHTML = resp.debits_accrued;
796         dojo.byId('acq-pl-lit-bibs-processed').innerHTML = resp.bibs;
797         dojo.byId('acq-pl-lit-indexed-processed').innerHTML = resp.indexed;
798         dojo.byId('acq-pl-lit-copies-processed').innerHTML = resp.copies;
799         if(resp.complete && reloadOnComplete) 
800             location.href = location.href;
801     }
802
803
804     this._createPO = function(fields) {
805         this.show('acq-lit-progress-numbers');
806         var po = new fieldmapper.acqpo();
807         po.provider(this.createPoProviderSelector.attr('value'));
808
809         var selected = this.getSelected( (fields.create_from == 'all') );
810         if(selected.length == 0) return;
811
812         var max = selected.length * 3;
813
814         var self = this;
815         fieldmapper.standardRequest(
816             ['open-ils.acq', 'open-ils.acq.purchase_order.create'],
817             {   async: true,
818                 params: [
819                     openils.User.authtoken, 
820                     po, 
821                     {
822                         lineitems : selected.map(function(li) { return li.id() }),
823                         create_assets : fields.create_assets[0],
824                     }
825                 ],
826
827                 onresponse : function(r) {
828                     var resp = openils.Util.readResponse(r);
829                     self._updateProgressNumbers(resp);
830                     if(resp.complete) 
831                         location.href = oilsBasePath + '/eg/acq/po/view/' + resp.purchase_order.id();
832                 }
833             }
834         );
835     }
836
837     this._deleteLiList = function(list, idx) {
838         if(idx == null) idx = 0;
839         if(idx >= list.length) return;
840         var liId = list[idx].id();
841         fieldmapper.standardRequest(
842             ['open-ils.acq', 'open-ils.acq.lineitem.delete'],
843             {   async: true,
844                 params: [openils.User.authtoken, liId],
845                 oncomplete: function(r) {
846                     self.removeLineitem(liId);
847                     self._deleteLiList(list, ++idx);
848                 }
849             }
850         );
851     }
852
853     this.editOrderMarc = function(li) {
854
855         /*  To run in Firefox directly, must set signed.applets.codebase_principal_support
856             to true in about:config */
857
858         netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
859         win = window.open('/xul/server/cat/marcedit.xul'); // XXX version?
860
861         var self = this;
862         win.xulG = {
863             record : {marc : li.marc()},
864             save : {
865                 label: 'Save Record', // XXX I18N
866                 func: function(xmlString) {
867                     li.marc(xmlString);
868                     fieldmapper.standardRequest(
869                         ['open-ils.acq', 'open-ils.acq.lineitem.update'],
870                         {   async: true,
871                             params: [openils.User.authtoken, li],
872                             oncomplete: function(r) {
873                                 openils.Util.readResponse(r);
874                                 win.close();
875                                 self.drawInfo(li.id())
876                             }
877                         }
878                     );
879                 },
880             }
881         };
882     }
883
884
885     this.editILSMarc = function(li) {
886
887         /*  To run in Firefox directly, must set signed.applets.codebase_principal_support
888             to true in about:config */
889
890         netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
891         win = window.open('/xul/server/cat/marcedit.xul'); // XXX version?
892
893         var bib = new openils.PermaCrud().retrieve('bre', li.eg_bib_id());
894
895         var self = this;
896         win.xulG = {
897             record : {marc : li.marc()},
898             save : {
899                 label: 'Save Record', // XXX I18N
900                 func: function(xmlString) {
901                     bib.marc(xmlString);
902                     fieldmapper.standardRequest(
903                         ['open-ils.cat', 'open-ils.cat.biblio.record_entry.update'],
904                         {   async: true,
905                             params: [openils.User.authtoken, bib],
906                             oncomplete: function(r) {
907                                 openils.Util.readResponse(r);
908                                 win.close();
909                                 self.drawInfo(li.id())
910                             }
911                         }
912                     );
913                 },
914             }
915         };
916     }
917
918     this._savePl = function(values) {
919         var self = this;
920         var selected = this.getSelected( (values.which == 'all') );
921         openils.Util.show('acq-lit-generic-progress');
922
923         if(values.new_name) {
924             openils.acq.Picklist.create(
925                 {name: values.new_name}, 
926                 function(id) {
927                     self._updateLiList(id, selected, 0, 
928                         function(){
929                             location.href = oilsBasePath + '/eg/acq/picklist/view/' + id;
930                         });
931                 }
932             );
933         } else if(values.existing_pl) {
934             // update lineitems to use an existing picklist
935             self._updateLiList(values.existing_pl, selected, 0, 
936                 function(){
937                     location.href = oilsBasePath + '/eg/acq/picklist/view/' + values.existing_pl;
938                 });
939         }
940     }
941
942     this._updateLiList = function(pl, list, idx, oncomplete) {
943         if(idx >= list.length) return oncomplete();
944         var li = list[idx];
945         li.picklist(pl);
946         litGenericProgress.update({maximum: list.length, progress: idx});
947         new openils.acq.Lineitem({lineitem:li}).update(
948             function(r) {
949                 self._updateLiList(pl, list, ++idx, oncomplete);
950             }
951         );
952     }
953
954     this._loadPLSelect = function() {
955         if(this._plSelectLoaded) return;
956         var plList = [];
957         function handleResponse(r) {
958             plList.push(r.recv().content());
959         }
960         var method = 'open-ils.acq.picklist.user.retrieve';
961         fieldmapper.standardRequest(
962             ['open-ils.acq', method],
963             {   async: true,
964                 params: [this.authtoken],
965                 onresponse: handleResponse,
966                 oncomplete: function() {
967                     self._plSelectLoaded = true;
968                     acqLitAddExistingSelect.store = 
969                         new dojo.data.ItemFileReadStore({data:acqpl.toStoreData(plList)});
970                     acqLitAddExistingSelect.setValue();
971                 }
972             }
973         );
974     }
975 }
976
977
978