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