]> git.evergreen-ils.org Git - working/Evergreen.git/blob - Open-ILS/web/js/ui/default/acq/po/view_po.js
Acq: you can now back up to old search results
[working/Evergreen.git] / Open-ILS / web / js / ui / default / acq / po / view_po.js
1 dojo.require("dojo.string");
2 dojo.require('dijit.layout.ContentPane');
3 dojo.require('openils.User');
4 dojo.require('openils.Util');
5 dojo.require('openils.PermaCrud');
6
7 var pcrud = new openils.PermaCrud();
8 var PO = null;
9 var liTable;
10 var poNoteTable;
11
12 function AcqPoNoteTable() {
13     var self = this;
14
15     this.notesTbody = dojo.byId("acq-po-notes-tbody");
16     this.notesRow = this.notesTbody.removeChild(dojo.byId("acq-po-notes-row"));
17
18     dojo.byId("acq-po-notes-back-button").onclick = function() { self.hide(); };
19     dojo.byId("acq-po-view-notes").onclick = function() { self.show(); };
20
21     /* widgets' event properties are cased likeThis */
22     acqPoCreateNoteSubmit.onClick = function() {
23         if (!acqPoCreateNoteText.attr("value")) return;
24
25         /* prep new note */
26         var note = new acqpon();
27         note.vendor_public(
28             Boolean(acqPoCreateNoteVendorPublic.attr('checked'))
29         );
30         note.value(acqPoCreateNoteText.attr("value"));
31         note.purchase_order(PO.id());
32         note.isnew(true);
33
34         /* save it */
35         self.updatePoNotes(note);
36
37         /* reset fields for next use */
38         acqPoCreateNoteText.attr("value", "");
39         acqPoCreateNoteVendorPublic.attr("checked", false);
40     };
41
42     this.drawPoNote = function(note) {
43         if (note.isdeleted())
44             return;
45
46         var row = dojo.clone(this.notesRow);
47
48         nodeByName("value", row).innerHTML = note.value();
49
50         if (openils.Util.isTrue(note.vendor_public()))
51             nodeByName("vendor_public", row).innerHTML =
52                 localeStrings.VENDOR_PUBLIC;
53
54         nodeByName("delete", row).onclick = function() {
55             note.isdeleted(true);
56             self.notesTbody.removeChild(row);
57             self.updatePoNotes();
58         };
59
60         if (note.edit_time()) {
61             nodeByName("edit_time", row).innerHTML =
62                 dojo.date.locale.format(
63                     dojo.date.stamp.fromISOString(note.edit_time()),
64                     {"formatLength": "short"}
65                 );
66         }
67
68         self.notesTbody.appendChild(row);
69     };
70
71     this.drawPoNotes = function() {
72         /* sort */
73         PO.notes(
74             PO.notes().sort(
75                 function(a, b) {
76                     return (a.edit_time() < b.edit_time()) ? 1 : -1;
77                 }
78             )
79         );
80
81         /* remove old renderings of notes */
82         dojo.empty(this.notesTbody);
83
84         PO.notes().forEach(function(o) { self.drawPoNote(o); });
85     };
86
87     this.updatePoNotesCount = function() {
88         dojo.byId("acq-po-view-notes").innerHTML = PO.notes().length;
89     };
90
91     this.updatePoNotes = function(newNote) {
92         var notes = newNote ?
93             [newNote] :
94             PO.notes().filter(
95                 function(o) {
96                     if (o.ischanged() || o.isnew() || o.isdeleted())
97                         return o;
98                 }
99             );
100
101         if (notes.length < 1)
102             return;
103
104         progressDialog.show();
105
106         fieldmapper.standardRequest(
107             ["open-ils.acq", "open-ils.acq.po_note.cud.batch"], {
108                 "async": true,
109                 "params": [openils.User.authtoken, notes],
110                 "onresponse": function(r) {
111                     var resp = openils.Util.readResponse(r);
112                     if (resp) {
113                         progressDialog.update(resp);
114
115                         if (!resp.note.isdeleted()) {
116                             resp.note.isnew(false);
117                             resp.note.ischanged(false);
118                             PO.notes().push(resp.note);
119                         }
120                     }
121                 },
122                 "oncomplete": function() {
123                     if (!newNote) {
124                         /* remove the old changed notes */
125                         var list = [];
126                         PO.notes(
127                             PO.notes().filter(
128                                 function(o) {
129                                     return (!(
130                                         o.ischanged() || o.isnew() ||
131                                         o.isdeleted()
132                                     ));
133                                 }
134                             )
135                         );
136                     }
137
138                     progressDialog.hide();
139                     self.updatePoNotesCount();
140                     self.drawPoNotes();
141                 }
142             }
143         );
144     };
145
146     this.hide = function() {
147         openils.Util.hide("acq-po-notes-div");
148         liTable.show("list");
149     };
150
151     this.show = function() {
152         liTable.hide();
153         self.drawPoNotes();
154         openils.Util.show("acq-po-notes-div");
155     };
156 }
157
158 function updatePoState(po_info) {
159     var data = po_info[PO.id()];
160     if (data) {
161         for (var key in data)
162             PO[key](data[key]);
163         renderPo();
164     }
165 }
166
167 function cancellationUpdater(r) {
168     var r = openils.Util.readResponse(r);
169     if (r) {
170         if (r.po) updatePoState(r.po);
171         if (r.li) {
172             for (var id in r.li) {
173                 liTable.liCache[id].state(r.li[id].state);
174                 liTable.liCache[id].cancel_reason(r.li[id].cancel_reason);
175                 liTable.updateLiState(liTable.liCache[id]);
176             }
177         }
178         if (r.lid && liTable.copyCache) {
179             for (var id in r.lid) {
180                 if (liTable.copyCache[id]) {
181                     liTable.copyCache[id].cancel_reason(
182                         r.lid[id].cancel_reason
183                     );
184                     liTable.updateLidState(liTable.copyCache[id]);
185                 }
186             }
187         }
188     }
189 }
190
191 function makeProviderLink(node, provider) {
192     return dojo.create(
193         "a", {
194             "href": "/eg/conify/global/acq/provider/" + provider.id(),
195             "innerHTML": provider.name() + " (" + provider.code() + ")",
196         },
197         node,
198         "only"
199     );
200 }
201 function makePrepayWidget(node, prepay) {
202     if (prepay) {
203         openils.Util.addCSSClass(node, "oils-acq-po-prepay");
204         node.innerHTML = localeStrings.YES;
205     } else {
206         openils.Util.removeCSSClass(node, "oils-acq-po-prepay");
207         node.innerHTML = localeStrings.NO;
208     }
209 }
210
211 function makeCancelWidget(node, labelnode) {
212     openils.Util.hide("acq-po-choose-cancel-reason");
213
214     if (PO.cancel_reason()) {
215         labelnode.innerHTML = localeStrings.CANCEL_REASON;
216         node.innerHTML = PO.cancel_reason().description() + " (" +
217             PO.cancel_reason().label() + ")";
218     } else if (["on-order", "pending"].indexOf(PO.state()) == -1) {
219         dojo.destroy(this.oldTip);
220         labelnode.innerHTML = "";
221         node.innerHTML = "";
222     } else {
223         dojo.destroy(this.oldTip);
224         labelnode.innerHTML = localeStrings.CANCEL;
225         node.innerHTML = "";
226         if (!acqPoCancelReasonSubmit._prepared) {
227             var widget = new openils.widget.AutoFieldWidget({
228                 "fmField": "cancel_reason",
229                 "fmClass": "acqpo",
230                 "parentNode": dojo.byId("acq-po-cancel-reason"),
231                 "orgLimitPerms": ["CREATE_PURCHASE_ORDER"],
232                 "forceSync": true
233             });
234             widget.build(
235                 function(w, ww) {
236                     acqPoCancelReasonSubmit.onClick = function() {
237                         if (w.attr("value")) {
238                             if (confirm(localeStrings.PO_CANCEL_CONFIRM)) {
239                                 fieldmapper.standardRequest(
240                                     ["open-ils.acq",
241                                         "open-ils.acq.purchase_order.cancel"],
242                                     {
243                                         "params": [
244                                             openils.User.authtoken,
245                                             PO.id(), 
246                                             w.attr("value")
247                                         ],
248                                         "async": true,
249                                         "oncomplete": cancellationUpdater
250                                     }
251                                 );
252                             }
253                         }
254                     };
255                     acqPoCancelReasonSubmit._prepared = true;
256                 }
257             );
258         }
259         openils.Util.show("acq-po-choose-cancel-reason", "inline");
260     }
261 }
262
263 function renderPo() {
264     dojo.byId("acq-po-view-id").innerHTML = PO.id();
265     dojo.byId("acq-po-view-name").innerHTML = PO.name();
266     makeProviderLink(
267         dojo.byId("acq-po-view-provider"),
268         PO.provider()
269     );
270     dojo.byId("acq-po-view-total-li").innerHTML = PO.lineitem_count();
271     dojo.byId("acq-po-view-total-enc").innerHTML = PO.amount_encumbered();
272     dojo.byId("acq-po-view-total-spent").innerHTML = PO.amount_spent();
273     dojo.byId("acq-po-view-state").innerHTML = PO.state(); // TODO i18n
274     makePrepayWidget(
275         dojo.byId("acq-po-view-prepay"),
276         openils.Util.isTrue(PO.prepayment_required())
277     );
278     makeCancelWidget(
279         dojo.byId("acq-po-view-cancel-reason"),
280         dojo.byId("acq-po-cancel-label")
281     );
282     dojo.byId("acq-po-view-notes").innerHTML = PO.notes().length;
283
284     if(PO.state() == "pending") {
285         openils.Util.show("acq-po-activate", "table-row");
286         checkCouldActivatePo();
287         if (PO.lineitem_count() > 1)
288             openils.Util.show("acq-po-split");
289     }
290
291     dojo.byId('acq-po-create-invoice-link').onclick = 
292         function() {
293             location.href = oilsBasePath + '/acq/invoice/view?create=1&attach_po=' + poId;
294         };
295
296     dojo.byId("acq-po-view-invoice-link").onclick =
297         function() {
298             location.href = oilsBasePath + "/acq/search/unified?so=" +
299                 base64Encode({"jub":[{"purchase_order": PO.id()}]}) +
300                 "&rt=invoice";
301         };
302 }
303
304
305 function init() {
306     /* set up li table */
307     liTable = new AcqLiTable();
308     liTable.reset();
309     liTable.isPO = poId;
310     liTable.poUpdateCallback = updatePoState;
311
312     /* set up po notes table */
313     poNoteTable = new AcqPoNoteTable();
314
315     /* retrieve data and populate */
316     fieldmapper.standardRequest(
317         ['open-ils.acq', 'open-ils.acq.purchase_order.retrieve'],
318         {   async: true,
319             params: [openils.User.authtoken, poId, {
320                 "flesh_provider": true,
321                 "flesh_price_summary": true,
322                 "flesh_lineitem_count": true,
323                 "flesh_notes": true
324             }],
325             oncomplete: function(r) {
326                 PO = openils.Util.readResponse(r); /* save PO globally */
327                 renderPo();
328             }
329         }
330     );
331
332     fieldmapper.standardRequest(
333         ['open-ils.acq', 'open-ils.acq.lineitem.search'],
334         {   async: true,
335 params: [openils.User.authtoken, {purchase_order:poId}, {flesh_attrs:true, flesh_notes:true, flesh_cancel_reason:true}],
336             onresponse: function(r) {
337                 liTable.show('list');
338                 liTable.addLineitem(openils.Util.readResponse(r));
339             }
340         }
341     );
342 }
343
344 function checkCouldActivatePo() {
345     var d = dojo.byId("acq-po-activate-checking");
346     var a = dojo.byId("acq-po-activate-link");
347     d.innerHTML = localeStrings.PO_CHECKING;
348     var warnings = [];
349     var stops = [];
350
351     fieldmapper.standardRequest(
352         ["open-ils.acq", "open-ils.acq.purchase_order.activate.dry_run"], {
353             "params": [openils.User.authtoken, PO.id()],
354             "async": true,
355             "onresponse": function(r) {
356                 if ((r = openils.Util.readResponse(r, true /* eventOk */))) {
357                     if (typeof(r.textcode) != "undefined") {
358                         switch(r.textcode) {
359                             case "ACQ_FUND_EXCEEDS_STOP_PERCENT":
360                                 stops.push(r);
361                                 break;
362                             case "ACQ_FUND_EXCEEDS_WARN_PERCENT":
363                                 warnings.push(r);
364                                 break;
365                         }
366                     }
367                 }
368             },
369             "oncomplete": function() {
370                 /* XXX in the future, this might be tweaked to display info
371                  * about more than one stop or warning event from the ML. */
372                 if (!(warnings.length || stops.length)) {
373                     d.innerHTML = localeStrings.PO_COULD_ACTIVATE;
374                     openils.Util.show(a, "inline");
375                 } else {
376                     if (stops.length) {
377                         d.innerHTML =
378                             dojo.string.substitute(
379                                 localeStrings.PO_STOP_BLOCKS_ACTIVATION, [
380                                     stops[0].payload.fund.code(),
381                                     stops[0].payload.fund.year()
382                                 ]
383                             );
384                         openils.Util.hide(a);
385                     } else {
386                         PO._warning_hack = true;
387                         d.innerHTML =
388                             dojo.string.substitute(
389                                 localeStrings.PO_WARNING_NO_BLOCK_ACTIVATION, [
390                                     warnings[0].payload.fund.code(),
391                                     warnings[0].payload.fund.year()
392                                 ]
393                             );
394                         openils.Util.show(a, "inline");
395                     }
396                 }
397             }
398         }
399     );
400 }
401
402 function activatePo() {
403     if (openils.Util.isTrue(PO.prepayment_required())) {
404         if (!confirm(localeStrings.PREPAYMENT_REQUIRED_REMINDER))
405             return false;
406     }
407
408     if (PO._warning_hack) {
409         if (!confirm(localeStrings.PO_FUND_WARNING_CONFIRM))
410             return false;
411     }
412
413     progressDialog.show(true);
414     try {
415         fieldmapper.standardRequest(
416             ['open-ils.acq', 'open-ils.acq.purchase_order.activate'],
417             {   async: true,
418                 params: [openils.User.authtoken, PO.id()],
419                 oncomplete : function() {
420                     location.href = location.href;
421                 }
422             }
423         );
424     } catch(E) {
425         progressDialog.hide();
426     }
427 }
428
429 function splitPo() {
430     progressDialog.show(true);
431     try {
432         var list;
433         fieldmapper.standardRequest(
434             ['open-ils.acq', 'open-ils.acq.purchase_order.split_by_lineitems'],
435             {   async: true,
436                 params: [openils.User.authtoken, PO.id()],
437                 onresponse : function(r) {
438                     list = openils.Util.readResponse(r);
439                 },
440                 oncomplete : function() {
441                     progressDialog.hide();
442                     if (list) {
443                         location.href = oilsBasePath + '/eg/acq/po/search/' +
444                             list.join(",");
445                     }
446                 }
447             }
448         );
449     } catch(E) {
450         progressDialog.hide();
451         alert(E);
452     }
453 }
454
455 function updatePoName() {
456     var value = prompt('Enter new purchase order name:', PO.name()); // TODO i18n
457     if(!value || value == PO.name()) return;
458     PO.name(value);
459     pcrud.update(PO, {
460         oncomplete : function(r, cudResults) {
461             var stat = cudResults[0];
462             if(stat)
463                 dojo.byId('acq-po-view-name').innerHTML = value;
464         }
465     });
466 }
467
468 openils.Util.addOnLoad(init);