]> git.evergreen-ils.org Git - working/Evergreen.git/blob - Open-ILS/xul/staff_client/server/serial/manage_items.js
Merge branch 'template-toolkit-opac' of git.evergreen-ils.org:evergreen/equinox into...
[working/Evergreen.git] / Open-ILS / xul / staff_client / server / serial / manage_items.js
1 dump('entering manage_items.js\n');
2
3 function $(id) { return document.getElementById(id); }
4
5 if (typeof serial == 'undefined') serial = {};
6 serial.manage_items = function (params) {
7
8         JSAN.use('util.error'); this.error = new util.error();
9         JSAN.use('util.network'); this.network = new util.network();
10         JSAN.use('OpenILS.data'); this.data = new OpenILS.data(); this.data.init({'via':'stash'});
11
12     this.current_sunit_id = -1; //default to **AUTO**
13     this.mode = 'receive';
14
15 }
16
17 serial.manage_items.prototype = {
18
19         'list_sitem_map' : {},
20
21     'set_sdist_ids' : function () {
22                 var obj = this;
23
24         try {
25             obj.lib = $('serial_item_lib_menu').value;
26             var sdist_retrieve_params = {"+ssub":{"record_entry" : obj.docid}};
27             if (obj.mode == 'receive') {
28                 sdist_retrieve_params["+ssub"].owning_lib = obj.lib;
29             } else {
30                 sdist_retrieve_params.holding_lib = obj.lib;
31             }
32             var robj = obj.network.request(
33                 'open-ils.pcrud',
34                 'open-ils.pcrud.id_list.sdist',
35                 [ ses(), sdist_retrieve_params, {"join":"ssub"} ]
36             );
37             if (robj != null) {
38                 if (typeof robj.ilsevent != 'undefined') throw(robj);
39                 obj.sdist_ids = robj.length ? robj : [robj];
40             } else {
41                 obj.sdist_ids = [];
42             }
43         } catch(E) {
44             obj.error.standard_unexpected_error_alert('set_sdist_ids failed!',E);
45         }
46     },
47
48     'build_menus' : function () {
49                 var obj = this;
50
51         // draw library drop-down
52         obj.org_ids = obj.network.simple_request('FM_SSUB_AOU_IDS_RETRIEVE_VIA_RECORD_ID.authoritative',[ obj.docid ]);
53         if (typeof obj.org_ids.ilsevent != 'undefined') throw(obj.org_ids);
54         JSAN.use('util.functional');
55         obj.org_ids = util.functional.map_list( obj.org_ids, function (o) { return Number(o); });
56
57         var org = obj.data.hash.aou[ obj.data.list.au[0].ws_ou() ];
58
59         JSAN.use('util.file'); JSAN.use('util.widgets');
60
61         var file; var list_data; var ml;
62
63         file = new util.file('offline_ou_list');
64         if (file._file.exists()) {
65             list_data = file.get_object(); file.close();
66             ml = util.widgets.make_menulist( list_data[0], list_data[1] );
67             ml.setAttribute('id','serial_item_lib_menu'); document.getElementById('serial_item_lib_menu_box').appendChild(ml);
68             //TODO: class this menu properly
69             for (var i = 0; i < obj.org_ids.length; i++) {
70                 ml.getElementsByAttribute('value',obj.org_ids[i])[0].setAttribute('class','has_distributions');
71             }
72             /*TODO: add/enable this legend?
73             ml.firstChild.addEventListener(
74                 'popupshown',
75                 function(ev) {
76                     document.getElementById('legend').setAttribute('hidden','false');
77                 },
78                 false
79             );
80             ml.firstChild.addEventListener(
81                 'popuphidden',
82                 function(ev) {
83                     document.getElementById('legend').setAttribute('hidden','true');
84                 },
85                 false
86             );*/
87             ml.addEventListener(
88                 'command',
89                 function(ev) {
90                     //if (document.getElementById('serial_item_refresh_button')) document.getElementById('serial_item_refresh_button').focus();
91                     obj.save_settings();
92                     // get latest sdist id list based on library drowdown
93                     obj.set_sdist_ids();
94                     obj.refresh_list('main');
95                     obj.refresh_list('workarea');
96                 },
97                 false
98             );
99
100         } else {
101             throw(document.getElementById('catStrings').getString('staff.cat.copy_browser.missing_library') + '\n');
102         }
103         file = new util.file('serial_items_prefs.'+obj.data.server_unadorned);
104         util.widgets.load_attributes(file);
105         ml.value = ml.getAttribute('value');
106         if (! ml.value) {
107             ml.value = org.id();
108             ml.setAttribute('value',ml.value);
109         }
110         
111         // deal with mode radio selectedIndex, as load_attributes is setting a "read-only" value
112         if ($('mode_receive').getAttribute('selected')) {
113             $('serial_manage_items_mode').selectedIndex = 0;
114         } else if ($('mode_advanced_receive').getAttribute('selected')) {
115             $('serial_manage_items_mode').selectedIndex = 1;
116         } else {
117             $('serial_manage_items_mode').selectedIndex = 2;
118         }
119
120         // setup recent sunits list
121         var recent_sunits_file = new util.file('serial_items_recent_sunits_'+obj.docid+'.'+obj.data.server_unadorned);
122         util.widgets.load_attributes(recent_sunits_file);
123         var recent_sunits_popup = $('serial_items_recent_sunits');
124         obj.sunit_entries = JSON2js(recent_sunits_popup.getAttribute('sunit_json'));
125         for (i = 0; i < obj.sunit_entries.length; i++) {
126             var sunit_info = obj.sunit_entries[i];
127             var new_menu_item = recent_sunits_popup.appendItem(sunit_info.label);
128             new_menu_item.setAttribute('id', 'serial_items_recent_sunits_entry_'+sunit_info.id);
129             new_menu_item.setAttribute('sunit_id', sunit_info.id);
130             new_menu_item.setAttribute('command', 'cmd_set_sunit');
131         }
132     },
133
134         'init' : function( params ) {
135                 var obj = this;
136
137                 obj.docid = params['docid'];
138
139         obj.build_menus();
140         obj.set_sunit($('serial_items_current_sunit').getAttribute('sunit_id'), $('serial_items_current_sunit').getAttribute('sunit_label'), $('serial_items_current_sunit').getAttribute('sdist_id'), $('serial_items_current_sunit').getAttribute('sstr_id'));
141         obj.set_sdist_ids();
142                 obj.init_lists();
143
144         var mode_radio_group = $('serial_manage_items_mode');
145         obj.set_mode(mode_radio_group.selectedItem.id.substr(5));
146         mode_radio_group.addEventListener(
147             'command',
148             function(ev) {
149                 obj.save_settings();
150                 var mode = ev.target.id.substr(5); //strip out 'mode_'
151                 obj.set_mode(mode);
152                 obj.refresh_list('main');
153                 obj.refresh_list('workarea');
154             },
155             false
156         );
157         $('serial_manage_items_show_all').addEventListener(
158             'command',
159             function(ev) {
160                 obj.save_settings();
161                 obj.set_mode();
162                 obj.refresh_list('main');
163                 obj.refresh_list('workarea');
164             },
165             false
166         );
167
168                 JSAN.use('util.controller'); obj.controller = new util.controller();
169                 obj.controller.init(
170                         {
171                                 'control_map' : {
172                                         'save_columns' : [ [ 'command' ], function() { obj.lists.main.save_columns(); } ],
173                                         'cmd_broken' : [ ['command'], function() { alert('Not Yet Implemented'); } ],
174                                         'sel_clip' : [ ['command'], function() { obj.lists.main.clipboard(); } ],
175                     'cmd_add_item' : [
176                         ['command'],
177                         function() {
178                             try {
179                                 var new_item = new sitem();
180                                 new_item.issuance(new siss());
181                                 new_item.stream(1); //FIXME: hard-coded stream
182                                 new_item.issuance().subscription(1); //FIXME: hard-coded subscription
183                                 new_item.isnew(1);
184                                 new_item.issuance().isnew(1);
185                                 spawn_sitem_editor( {'sitems' : [new_item], 'do_edit' : 1 } );
186
187                                 obj.refresh_list('main');
188
189                             } catch(E) {
190                                 obj.error.standard_unexpected_error_alert(document.getElementById('catStrings').getString('staff.cat.copy_browser.edit_items.error'),E);
191                             }
192                         }
193                     ],
194                     'cmd_edit_items' : [
195                         ['command'],
196                         function() {
197                             try {
198                                 if (!obj.retrieve_ids || obj.retrieve_ids.length == 0) return;
199
200                                 JSAN.use('util.functional');
201                                 var list = util.functional.map_list(
202                                         obj.retrieve_ids,
203                                         function (o) {
204                                             return o.sitem_id;
205                                         }
206                                     );
207
208                                 spawn_sitem_editor( { 'sitem_ids' : list, 'do_edit' : 1 } );
209
210                                 obj.refresh_list(obj.selected_list);
211
212                             } catch(E) {
213                                 obj.error.standard_unexpected_error_alert(document.getElementById('catStrings').getString('staff.cat.copy_browser.edit_items.error'),E);
214                             }
215                         }
216                     ],
217                     'cmd_reset_items' : [
218                         ['command'],
219                         function() {
220                             try {
221                                 if (!obj.retrieve_ids || obj.retrieve_ids.length == 0) return;
222
223                                 JSAN.use('util.functional');
224                                 var list = util.functional.map_list(
225                                         obj.retrieve_ids,
226                                         function (o) {
227                                             return o.sitem_id;
228                                         }
229                                     );
230
231                                 var robj = obj.network.request(
232                                             'open-ils.serial',
233                                             'open-ils.serial.reset_items',
234                                             [ ses(), list ]
235                                         );
236                                 if (typeof robj.ilsevent != 'undefined') throw(robj);
237
238                                 alert('Successfully reset '+robj.num_items+' item(s)');
239
240                                 obj.refresh_list('main');
241                                 obj.refresh_list('workarea');
242                             } catch(E) {
243                                 obj.error.standard_unexpected_error_alert('staff.serial.manage_items.reset_items.error',E);
244                             }
245                         }
246                     ],
247                     'cmd_delete_items' : [
248                         ['command'],
249                         function() {
250                             try {
251                                 JSAN.use('util.functional');
252                                 var list = util.functional.map_list(
253                                         obj.retrieve_ids,
254                                         function (o) {
255                                             return obj.list_sitem_map[o.sitem_id];
256                                         }
257                                     );
258                                 var delete_msg;
259                                 if (list.length != 1) {
260                                     delete_msg = document.getElementById('catStrings').getFormattedString('staff.cat.copy_browser.delete_items.confirm.plural', [list.length]);
261                                 } else {
262                                     delete_msg = document.getElementById('catStrings').getString('staff.cat.copy_browser.delete_items.confirm');
263                                 }
264                                 var r = obj.error.yns_alert(
265                                         delete_msg,
266                                         document.getElementById('catStrings').getString('staff.cat.copy_browser.delete_items.title'),
267                                         document.getElementById('catStrings').getString('staff.cat.copy_browser.delete_items.delete'),
268                                         document.getElementById('catStrings').getString('staff.cat.copy_browser.delete_items.cancel'),
269                                         null,
270                                         document.getElementById('commonStrings').getString('common.confirm')
271                                 );
272
273                                 if (r == 0) {
274                                     for (var i = 0; i < list.length; i++) {
275                                         list[i].isdeleted('1');
276                                     }
277                                     var robj = obj.network.request(
278                                             'open-ils.serial',
279                                             'open-ils.serial.item.fleshed.batch.update',
280                                         [ ses(), list, true ],
281                                         null,
282                                         {
283                                             'title' : document.getElementById('catStrings').getString('staff.cat.copy_browser.delete_items.override'),
284                                             'overridable_events' : [ // FIXME: replace or delete these events
285                                                 1208 /* TITLE_LAST_COPY */,
286                                                 1227 /* COPY_DELETE_WARNING */,
287                                             ]
288                                         }
289                                     );
290                                     if (robj == null) throw(robj);
291                                     if (typeof robj.ilsevent != 'undefined') {
292                                         if ( (robj.ilsevent != 0) && (robj.ilsevent != 1227 /* COPY_DELETE_WARNING */) && (robj.ilsevent != 1208 /* TITLE_LAST_COPY */) ) throw(robj);
293                                     }
294                                     obj.refresh_list(obj.selected_list);
295                                 }
296
297
298                             } catch(E) {
299                                 obj.error.standard_unexpected_error_alert('staff.serial.manage_items.delete_items.error',E);
300                                 obj.refresh_list();
301                             }
302                         }
303                     ],
304                     'cmd_set_sunit' : [
305                         ['command'],
306                         function(evt) {
307                             try {
308                                 var target = evt.explicitOriginalTarget;
309                                 obj.process_unit_selection(target);
310                             } catch(E) {
311                                 obj.error.standard_unexpected_error_alert('cmd_set_sunit failed!',E);
312                             }
313                         }
314                     ],
315                     'cmd_set_other_sunit' : [
316                         ['command'],
317                         function() {
318                             obj.set_other_sunit();
319                             if (obj.mode == 'bind') {
320                                 obj.refresh_list('main');
321                                 obj.refresh_list('workarea');
322                             }
323                         }
324                     ],
325                     'cmd_predict_items' : [
326                         ['command'],
327                         function() {
328                             alert('Subscription selection needed here'); //FIXME: make this prompt, or discard this feature
329                         }
330                     ],
331                     'cmd_receive_items' : [
332                         ['command'],
333                         function() {
334                             try {
335                                 JSAN.use('util.functional');
336                                 var donor_unit_ids = {};
337                                 var list = util.functional.map_list(
338                                         obj.retrieve_ids,
339                                         function (o) {
340                                             var item = obj.list_sitem_map[o.sitem_id];
341                                             if (item.unit()) {
342                                                 donor_unit_ids[item.unit().id()] = 1;
343                                             }
344                                             item.unit(obj.current_sunit_id);
345                                             return item;
346                                         }
347                                     );
348
349                                 var mode = obj.mode;
350                                 if (mode == 'advanced_receive') mode = 'receive';
351
352                                 var method; var success_label;
353                                 if (mode == 'receive') {
354                                     method = 'open-ils.serial.receive_items';
355                                     success_label = 'received';
356                                 } else { // bind mode
357                                     method = 'open-ils.serial.bind_items';
358                                     success_label = 'bound';
359                                 } 
360
361                                 // deal with barcodes and call numbers for *NEW* units
362                                 var barcodes = {};
363                                 var call_numbers = {};
364                                 var call_numbers_by_siss_and_sdist = {};
365
366                                 if (obj.current_sunit_id < 0) { // **AUTO** or **NEW** units
367                                     var new_unit_barcode = '';
368                                     var new_unit_call_number = '';
369                                     for (var i = 0; i < list.length; i++) {
370                                         var item = list[i];
371                                         if (new_unit_barcode) {
372                                             barcodes[item.id()] = new_unit_barcode;
373                                             call_numbers[item.id()] = new_unit_call_number;
374                                             continue;
375                                         }
376                                         var prompt_text;
377                                         if (obj.current_sunit_id == -1) {
378                                             prompt_text = 'for '+item.issuance().label()+ ' from Distribution: '+item.stream().distribution().label()+'/'+item.stream().id()+':';
379                                         } else { // must be -2
380                                             prompt_text = 'for the new unit:';
381                                         }
382
383                                         // first barcodes
384                                         var barcode = window.prompt('Please enter a barcode ' + prompt_text,
385                                             '@@AUTO',
386                                             'Unit Barcode Prompt');
387                                         barcode = String( barcode ).replace(/\s/g,'');
388                                         /* Casting a possibly null input value to a String turns it into "null" */
389                                         if (!barcode || barcode == 'null') {
390                                             alert('Invalid barcode entered, defaulting to system-generated.');
391                                             barcode = '@@AUTO';
392                                         } else {
393                                             // disable alarm sound temporarily
394                                             var sound_setting = obj.data.no_sound;
395                                             if (!sound_setting) { // undefined or false
396                                                 obj.data.no_sound = true; obj.data.stash('no_sound');
397                                             }
398                                             var test = obj.network.simple_request('FM_ACP_RETRIEVE_VIA_BARCODE',[ barcode ]);
399                                             if (typeof test.ilsevent == 'undefined') {
400                                                 alert('Another copy has barcode "' + barcode + '", defaulting to system-generated.');
401                                                 barcode = '@@AUTO';
402                                             }
403                                             if (!sound_setting) {
404                                                 obj.data.no_sound = sound_setting; obj.data.stash('no_sound');
405                                             }
406                                         }
407                                         barcodes[item.id()] = barcode;
408
409                                         // now call numbers
410                                         if (typeof call_numbers_by_siss_and_sdist[item.issuance().id() + '@' + item.stream().distribution().id()] == 'undefined') {
411                                             var default_cn = 'DEFAULT';
412                                             // if they defined a *_call_number, honor it as the default
413                                             var preset_cn_id = item.stream().distribution()[mode + '_call_number']();
414                                             if (preset_cn_id) {
415                                                 var preset_default_cn = obj.network.request(
416                                                         'open-ils.pcrud',
417                                                         'open-ils.pcrud.retrieve.acn',
418                                                         [ ses(), preset_cn_id ]
419                                                 );
420                                                 if (preset_default_cn) {
421                                                     default_cn = preset_default_cn.label();
422                                                 }
423                                             } else {
424                                                 // for now, let's default to the last created call number if there is one
425                                                 var acn_list = obj.network.request(
426                                                         'open-ils.pcrud',
427                                                         'open-ils.pcrud.search.acn',
428                                                         [ ses(), {"record" : obj.docid, "owning_lib" : item.stream().distribution().holding_lib(), "deleted" : 'f' }, {"order_by" : {"acn" : "create_date DESC"}, "limit" : "1" } ]
429                                                 );
430
431                                                 if (acn_list) {
432                                                     default_cn = acn_list.label();
433                                                 }
434                                             }
435                                             var call_number = window.prompt('Please enter/adjust a call number ' + prompt_text,
436                                                 default_cn, //TODO: real default by setting
437                                                 'Unit Call Number Prompt');
438                                             call_number = String( call_number ).replace(/^\s+/,'').replace(/\s$/,'');
439                                             /* Casting a possibly null input value to a String turns it into "null" */
440                                             if (!call_number || call_number == 'null') {
441                                                 alert('Invalid call number entered, setting to "DEFAULT".');
442                                                 call_number = 'DEFAULT'; //TODO: real default by setting
443                                             }
444                                             call_numbers[item.id()] = call_number;
445                                             call_numbers_by_siss_and_sdist[item.issuance().id() + '@' + item.stream().distribution().id()] = call_number;
446                                         } else {
447                                             // we have already seen this same issuance and distribution combo, so use the same call number
448                                             call_numbers[item.id()] = call_numbers_by_siss_and_sdist[item.issuance().id() + '@' + item.stream().distribution().id()];
449                                         }
450
451                                         if (obj.current_sunit_id == -2) {
452                                             new_unit_barcode = barcode;
453                                             new_unit_call_number = call_number;
454                                         }
455                                     }
456                                 }
457
458                                 var robj = obj.network.request(
459                                             'open-ils.serial',
460                                             method,
461                                             [ ses(), list, barcodes, call_numbers, donor_unit_ids ]
462                                         );
463                                 if (typeof robj.ilsevent != 'undefined') throw(robj); //TODO: catch for override
464
465                                 alert('Successfully '+success_label+' '+robj.num_items+' item(s)');
466
467                                 if (obj.current_sunit_id == -2) {
468                                     obj.current_sunit_id = robj.new_unit_id;
469                                 }
470
471                                 obj.rebuild_current_sunit(list[0].stream().distribution().label(), list[0].stream().distribution().id(), list[0].stream().id());
472                                 obj.refresh_list('main');
473                                 obj.refresh_list('workarea');
474                                 
475                             } catch(E) {
476                                 obj.error.standard_unexpected_error_alert('cmd_receive_items failed!',E);
477                             }
478                         }
479                     ],
480                     'cmd_edit_sunit' : [
481                         ['command'],
482                         function() {
483                             try {
484                                 /*if (!obj.retrieve_ids || obj.retrieve_ids.length == 0) return;
485
486                                 JSAN.use('util.functional');
487                                 var list = util.functional.map_list(
488                                         obj.retrieve_ids,
489                                         function (o) {
490                                             return o.sitem_id;
491                                         }
492                                     );
493 */
494                                 spawn_sunit_editor( { 'sunit_ids' : [1], 'edit' : 1 } ); //FIXME: hard-coded sunit
495
496                             } catch(E) {
497                                 obj.error.standard_unexpected_error_alert('cmd_edit_sunit failed!',E);
498                             }
499                         }
500                     ],
501
502                     'cmd_items_print' : [ ['command'], function() { obj.items_print(obj.selected_list); } ],
503                                         'cmd_items_export' : [ ['command'], function() { obj.items_export(obj.selected_list); } ],
504                                         'cmd_refresh_list' : [ ['command'], function() { obj.set_sdist_ids(); obj.refresh_list('main'); obj.refresh_list('workarea'); } ]
505                                 }
506                         }
507                 );
508         
509                 obj.retrieve('main'); // retrieve main list
510         obj.retrieve('workarea'); // retrieve shelving unit list
511
512                 obj.controller.view.sel_clip.setAttribute('disabled','true');
513
514         },
515
516         'items_print' : function(which) {
517                 var obj = this;
518                 try {
519                         var list = obj.lists[which];
520 /* FIXME: serial items print template?                  JSAN.use('patron.util');
521                         var params = { 
522                                 'patron' : patron.util.retrieve_fleshed_au_via_id(ses(),obj.patron_id), 
523                                 'template' : 'items_out'
524                         }; */
525                         list.print( params );
526                 } catch(E) {
527                         obj.error.standard_unexpected_error_alert('manage_items printing',E);
528                 }
529         },
530
531         'items_export' : function(which) {
532                 var obj = this;
533                 try {
534                         var list = obj.lists[which];
535                         list.dump_csv_to_clipboard();
536                 } catch(E) {
537                         obj.error.standard_unexpected_error_alert('manage_items export',E);
538                 }
539         },
540
541         'rebuild_current_sunit' : function(sdist_label, sdist_id, sstr_id) {
542                 var obj = this;
543         if (!obj.current_sunit_id) return; // current sunit is NONE
544                 try {
545             var robj = obj.network.request(
546                 'open-ils.pcrud',
547                 'open-ils.pcrud.retrieve.sunit',
548                 [ ses(),  obj.current_sunit_id]
549             );
550             if (!robj) return; // current sunit is NEW or AUTO
551
552             var label = '[' + sdist_label + '/' + sstr_id + ' #' + obj.current_sunit_id + '] ' + robj.summary_contents();
553             obj.set_sunit(obj.current_sunit_id, label, sdist_id, sstr_id);
554             obj.save_sunit(obj.current_sunit_id, label, sdist_id, sstr_id);
555                 } catch(E) {
556                         obj.error.standard_unexpected_error_alert('serial items set_sunit',E);
557                 }
558         },
559
560         'set_sunit' : function(sunit_id, label, sdist_id, sstr_id) {
561                 var obj = this;
562                 try {
563             obj.current_sunit_id = sunit_id;
564             obj.current_sunit_sdist_id = sdist_id;
565             obj.current_sunit_sstr_id = sstr_id;
566             if (sunit_id < 0  || sunit_id === '') {
567                 $('serial_workarea_sunit_desc').firstChild.nodeValue = '**' + label + '**';
568             } else {
569                 $('serial_workarea_sunit_desc').firstChild.nodeValue = label;
570                 obj.add_sunit_to_menu(sunit_id, label, sdist_id, sstr_id);
571             }
572                 } catch(E) {
573                         obj.error.standard_unexpected_error_alert('serial items set_sunit',E);
574                 }
575         },
576
577         'save_sunit' : function(sunit_id, label, sdist_id, sstr_id) {
578                 var obj = this;
579                 try {
580             $('serial_items_current_sunit').setAttribute('sunit_id', sunit_id);
581             $('serial_items_current_sunit').setAttribute('sunit_label', label);
582             if (sunit_id > 0) {
583                 $('serial_items_current_sunit').setAttribute('sdist_id', sdist_id);
584                 $('serial_items_current_sunit').setAttribute('sstr_id', sstr_id);
585             }
586             var recent_sunits_file = new util.file('serial_items_recent_sunits_'+obj.docid+'.'+obj.data.server_unadorned);
587             util.widgets.save_attributes(recent_sunits_file, { 'serial_items_recent_sunits' : [ 'sunit_json' ], 'serial_items_current_sunit' : [ 'sunit_id', 'sunit_label', 'sdist_id', 'sstr_id' ] });
588                 } catch(E) {
589                         obj.error.standard_unexpected_error_alert('serial items save_sunit',E);
590                 }
591         },
592
593         'set_other_sunit' : function() {
594                 var obj = this;
595                 try {
596             JSAN.use('util.window'); var win = new util.window();
597             var select_unit_window = win.open(
598                 xulG.url_prefix(urls.XUL_SERIAL_SELECT_UNIT),
599                 '_blank',
600                 'chrome,resizable,modal,centerscreen',
601                 {'sdist_ids' : obj.sdist_ids}
602             );
603             if (!select_unit_window.sunit_selection) {
604                 return;
605             }
606
607             var selection = select_unit_window.sunit_selection;
608             var sunit_id = selection.sunit;
609             var sdist_id = selection.sdist;
610             var sstr_id = selection.sstr;
611             var label = selection.label;
612
613             obj.set_sunit(sunit_id, label, sdist_id, sstr_id);
614             obj.save_sunit(sunit_id, label, sdist_id, sstr_id);
615                 } catch(E) {
616                         obj.error.standard_unexpected_error_alert('serial items set_other_sunit',E);
617                 }
618         },
619
620         'add_sunit_to_menu' : function(sunit_id, label, sdist_id, sstr_id) {
621                 var obj = this;
622                 try {
623             if (sunit_id > 0) {
624                 // check if it is already in sunit_entries, remove it
625                 for (i = 0; i < obj.sunit_entries.length; i++) {
626                     if (obj.sunit_entries[i].id == sunit_id) {
627                         obj.sunit_entries.splice(i,1);
628                         var menu_item = $('serial_items_recent_sunits_entry_'+sunit_id);
629                         menu_item.parentNode.removeChild(menu_item);
630                         i--;
631                     }
632                 }
633                 // add to front of array
634                 obj.sunit_entries.unshift({"id" : sunit_id, "label" : label, "sdist_id" : sdist_id, "sstr_id" : sstr_id});
635                 var recent_sunits_popup = $('serial_items_recent_sunits');
636                 var new_menu_item = recent_sunits_popup.insertItemAt(0,label);
637                 new_menu_item.setAttribute('id', 'serial_items_recent_sunits_entry_'+sunit_id);
638                 new_menu_item.setAttribute('sunit_id', sunit_id);
639                 new_menu_item.setAttribute('sdist_id', sdist_id);
640                 new_menu_item.setAttribute('sstr_id', sstr_id);
641                 new_menu_item.setAttribute('command', 'cmd_set_sunit');
642
643                 // pop off from sunit_entries if it already has 10 sunits
644                 if (obj.sunit_entries.length > 10) {
645                     var sunit_info = obj.sunit_entries.pop();
646                     var menu_item = $('serial_items_recent_sunits_entry_'+sunit_info.id);
647                     menu_item.parentNode.removeChild(menu_item);
648                 }
649
650                 recent_sunits_popup.setAttribute('sunit_json', js2JSON(obj.sunit_entries));
651             }
652                 } catch(E) {
653                         obj.error.standard_unexpected_error_alert('serial items add_sunit_to_menu',E);
654                 }
655         },
656
657         'set_mode' : function(mode) {
658                 var obj = this;
659
660         if (!mode) {
661             mode = obj.mode;
662         } else {
663             obj.mode = mode;
664         }
665
666         obj.set_sdist_ids();
667
668         if (mode == 'receive' || mode == 'advanced_receive') {
669             $('serial_workarea_mode_label').value = 'Recently Received';
670             if ($('serial_manage_items_show_all').checked) {
671                 obj.lists.main.sitem_retrieve_params = {};
672             } else {
673                 obj.lists.main.sitem_retrieve_params = {'date_received' : null };
674             }
675             obj.lists.main.sitem_extra_params ={'order_by' : {'sitem' : 'date_expected ASC, stream ASC'}};
676
677             obj.lists.workarea.sitem_retrieve_params = {'date_received' : {"!=" : null}};
678             obj.lists.workarea.sitem_extra_params ={'order_by' : {'sitem' : 'date_received DESC'}, 'limit' : 30};
679             if (mode == 'receive') {
680                 $('serial_manage_items_context').value = $('serialStrings').getString('staff.serial.manage_items.subscriber.label') + ':';
681                 $('cmd_set_other_sunit').setAttribute('disabled','true');
682                 $('serial_items_recent_sunits').disabled = true;
683                 obj.process_unit_selection($('serial_items_auto_per_item_menuitem'));
684                 //obj.set_sunit(obj.current_sunit_id, label, sdist_id, sstr_id);
685             } else {
686                 $('serial_manage_items_context').value = $('serialStrings').getString('staff.serial.manage_items.holder.label') + ':';
687                 $('cmd_set_other_sunit').setAttribute('disabled','false');
688                 $('serial_items_recent_sunits').disabled = false;
689             }    
690         } else { // bind mode
691             $('serial_workarea_mode_label').value = 'Bound Items in Current Working Unit';
692             $('serial_manage_items_context').value = $('serialStrings').getString('staff.serial.manage_items.holder.label') + ':';
693             if ($('serial_manage_items_show_all').checked) {
694                 obj.lists.main.sitem_retrieve_params = {};
695             } else {
696                 obj.lists.main.sitem_retrieve_params = {'date_received' : {'!=' : null}}; // unit set dynamically in 'retrieve'
697             }
698             obj.lists.main.sitem_extra_params ={'order_by' : {'sitem' : 'date_expected ASC, stream ASC'}};
699
700             obj.lists.workarea.sitem_retrieve_params = {}; // unit set dynamically in 'retrieve'
701             obj.lists.workarea.sitem_extra_params ={'order_by' : {'sitem' : 'date_received DESC'}};
702
703             $('cmd_set_other_sunit').setAttribute('disabled','false');
704             $('serial_items_recent_sunits').disabled = false;
705             // default to **NEW UNIT**
706             // For now, keep the unit static.  TODO: Eventually, keep track of and store the last used unit value for both receive and bind separately
707             // obj.set_sunit(-2, 'New Unit', '', '');
708         }
709     },
710
711         'save_settings' : function() {
712                 var obj = this;
713
714         JSAN.use('util.file'); var file = new util.file('serial_items_prefs.'+obj.data.server_unadorned);
715         util.widgets.save_attributes(file, { 'serial_item_lib_menu' : [ 'value' ], 'mode_receive' : [ 'selected' ], 'mode_advanced_receive' : [ 'selected' ], 'mode_bind' : [ 'selected' ], 'serial_manage_items_show_all' : [ 'checked' ] });
716     },
717
718         'init_lists' : function() {
719                 var obj = this;
720
721                 JSAN.use('circ.util');
722         var columns = item_columns({});
723
724         function retrieve_row(params) {
725                         try { 
726                                 var row = params.row;
727                 obj.network.simple_request(
728                     'FM_SITEM_FLESHED_BATCH_RETRIEVE.authoritative',
729                     [[row.my.sitem_id]],
730                     //[ ses(), row.my.sitem_id, {"flesh":2,"flesh_fields":{"sitem":["creator","editor","issuance","stream","unit","notes"], "sunit":["call_number"], "sstr":["distribution"]}}],
731                     function(req) {
732                         try {
733                             var robj = req.getResultObject();
734                             if (typeof robj.ilsevent != 'undefined') throw(robj);
735                             if (typeof robj.ilsevent == 'null') throw('null result');
736                             var sitem = robj[0];
737                             obj.list_sitem_map[sitem.id()] = sitem;
738                             row.my.sitem = sitem;
739                             //params.row_node.setAttribute( 'retrieve_id', js2JSON({'copy_id':copy_id,'circ_id':row.my.circ.id(),'barcode':row.my.acp.barcode(),'doc_id': ( row.my.record ? row.my.record.id() : null ) }) );
740                             params.row_node.setAttribute( 'retrieve_id', js2JSON({'sitem_id':sitem.id()}) );
741                             dump('dumping... ' + js2JSON(obj.list_sitem_map[sitem.id()]));
742                             if (typeof params.on_retrieve == 'function') {
743                                 params.on_retrieve(row);
744                             }
745
746                         } catch(E) {
747                             obj.error.standard_unexpected_error_alert('staff.serial.manage_items.retrieve_row.callback_error', E);
748                         }
749                     }
750                 );
751                                 return row;
752                         } catch(E) {
753                                 obj.error.standard_unexpected_error_alert('staff.serial.manage_items.retrieve_row.error_in_retrieve_row',E);
754                                 return params.row;
755                         }
756                 }
757
758                 JSAN.use('util.list');
759
760         obj.lists = {};
761         obj.lists.main = new util.list('item_tree');
762                 obj.lists.main.init(
763                         {
764                                 'columns' : columns,
765                                 'map_row_to_columns' : circ.util.std_map_row_to_columns(),
766                                 'retrieve_row' : retrieve_row,
767                                 'on_select' : function(ev) {
768                     obj.selected_list = 'main';
769                                         JSAN.use('util.functional');
770                                         var sel = obj.lists.main.retrieve_selection();
771                                         obj.controller.view.sel_clip.setAttribute('disabled',sel.length < 1);
772                                         var list = util.functional.map_list(
773                                                 sel,
774                                                 function(o) { return JSON2js( o.getAttribute('retrieve_id') ); }
775                                         );
776                                         if (typeof obj.on_select == 'function') {
777                                                 obj.on_select(list);
778                                         }
779                                         if (typeof window.xulG == 'object' && typeof window.xulG.on_select == 'function') {
780                                                 obj.error.sdump('D_CAT','manage_items: Calling external .on_select()\n');
781                                                 window.xulG.on_select(list);
782                                         }
783                                 }
784                         }
785                 );
786
787         obj.lists.workarea = new util.list('workarea_tree');
788                 obj.lists.workarea.init(
789                         {
790                                 'columns' : columns,
791                                 'map_row_to_columns' : circ.util.std_map_row_to_columns(),
792                                 'retrieve_row' : retrieve_row,
793                                 'on_select' : function(ev) {
794                     obj.selected_list = 'workarea';
795                                         JSAN.use('util.functional');
796                                         var sel = obj.lists.workarea.retrieve_selection();
797                                         obj.controller.view.sel_clip.setAttribute('disabled',sel.length < 1);
798                                         var list = util.functional.map_list(
799                                                 sel,
800                                                 function(o) { return JSON2js( o.getAttribute('retrieve_id') ); }
801                                         );
802                                         if (typeof obj.on_select == 'function') {
803                                                 obj.on_select(list);
804                                         }
805                                         if (typeof window.xulG == 'object' && typeof window.xulG.on_select == 'function') {
806                                                 obj.error.sdump('D_CAT','serctrl: Calling external .on_select()\n');
807                                                 window.xulG.on_select(list);
808                                         } else {
809                                                 obj.error.sdump('D_CAT','serctrl: No external .on_select()\n');
810                                         }
811                                 }
812                         }
813                 );
814     },
815
816         'refresh_list' : function(list_name) {
817         var obj = this;
818
819         //TODO Optimize this?
820         obj.retrieve(list_name);
821     },
822
823         'retrieve' : function(list_name) {
824                 var obj = this;
825         var list = obj.lists[list_name];
826         
827                 list.clear();
828
829         if (!obj.sdist_ids.length) { // no sdists to retrieve items for
830             return;
831         }
832
833         var rparams = list.sitem_retrieve_params;
834         var robj;
835         rparams['+sstr'] = { "distribution" : obj.sdist_ids };
836
837         if (obj.mode == 'bind') {
838             if (list_name == 'workarea') {
839                 rparams['unit'] = obj.current_sunit_id;
840             } else if (!$('serial_manage_items_show_all').checked){
841                 rparams['unit'] = {"<>" : obj.current_sunit_id};
842             }
843         }
844
845         var other_params = list.sitem_extra_params;
846         other_params.join = 'sstr';
847
848         robj = obj.network.simple_request(
849             'FM_SITEM_ID_LIST',
850             [ ses(), rparams, other_params ]
851         );
852         if (!robj) {
853             robj = [];
854         } else if (typeof robj.ilsevent!='undefined') {
855             obj.error.standard_unexpected_error_alert('Failed to retrieve serial item ID list',E);
856         } else if (!robj.length) {
857             robj = [robj];
858         }
859
860         for (i = 0; i < robj.length; i++) {
861             list.append( { 'row' : { 'my' : { 'sitem_id' : robj[i] } }, 'to_bottom' : true, 'no_auto_select' : true } );
862         }
863         },
864
865         'on_select' : function(list) {
866
867                 dump('manage_items.on_select list = ' + js2JSON(list) + '\n');
868
869                 var obj = this;
870
871                 /*obj.controller.view.cmd_items_claimed_returned.setAttribute('disabled','false');
872                 obj.controller.view.sel_mark_items_missing.setAttribute('disabled','false');*/
873
874                 obj.retrieve_ids = list;
875         },
876
877     'process_unit_selection' : function(menuitem) {
878         var obj = this;
879
880         var label = menuitem.label;
881         var sunit_id = menuitem.getAttribute('sunit_id');
882         var sdist_id = menuitem.getAttribute('sdist_id');
883         var sstr_id = menuitem.getAttribute('sstr_id');
884         obj.set_sunit(sunit_id, label, sdist_id, sstr_id);
885         obj.save_sunit(sunit_id, label, sdist_id, sstr_id);
886         if (obj.mode == 'bind') {
887             obj.refresh_list('main');
888             obj.refresh_list('workarea');
889         }
890     }
891 }
892
893 function item_columns(modify,params) {
894
895     JSAN.use('OpenILS.data'); var data = new OpenILS.data(); data.init({'via':'stash'});
896     //JSAN.use('util.network'); var network = new util.network();
897
898     var c = [
899         {
900             'id' : 'sitem_id',
901             'label' : 'Item ID',
902             'flex' : 1,
903             'primary' : false,
904             'hidden' : false,
905             'render' : function(my) { return my.sitem.id(); },
906             'persist' : 'hidden width ordinal'
907         },
908         {
909             'id' : 'label',
910             'label' : 'Issuance Label',
911             'flex' : 1,
912             'primary' : false,
913             'hidden' : false,
914             'render' : function(my) { return my.sitem.issuance().label(); },
915             'persist' : 'hidden width ordinal'
916         },
917         {
918             'id' : 'distribution',
919             'label' : 'Distribution',
920             'flex' : 1,
921             'primary' : false,
922             'hidden' : false,
923             'persist' : 'hidden width ordinal',
924             'render' : function(my) { return my.sitem.stream().distribution().label(); }
925         },        {
926             'id' : 'distribution_ou',
927             'label' : $('serialStrings').getString('staff.serial.manage_items.holder.label'),
928             'flex' : 1,
929             'primary' : false,
930             'hidden' : false,
931             'persist' : 'hidden width ordinal',
932             'render' : function(my) { return data.hash.aou[ my.sitem.stream().distribution().holding_lib() ].shortname(); }
933         },
934         {
935             'id' : 'stream_id',
936             'label' : 'Stream ID',
937             'flex' : 1,
938             'primary' : false,
939             'hidden' : false,
940             'persist' : 'hidden width ordinal',
941             'render' : function(my) { return my.sitem.stream().id(); }
942         },
943         {
944             'id' : 'date_published',
945             'label' : 'Date Published',
946             'flex' : 1,
947             'primary' : false,
948             'hidden' : false,
949             'render' : function(my) { return my.sitem.issuance().date_published().substr(0,10); },
950             'persist' : 'hidden width ordinal'
951         },
952         {
953             'id' : 'date_expected',
954             'label' : 'Date Expected',
955             'flex' : 1,
956             'primary' : false,
957             'hidden' : false,
958             'render' : function(my) { return my.sitem.date_expected().substr(0,10); },
959             'persist' : 'hidden width ordinal'
960         },
961         {
962             'id' : 'date_received',
963             'label' : 'Date Received',
964             'flex' : 1,
965             'primary' : false,
966             'hidden' : false,
967             'render' : function(my) { return my.sitem.date_received().substr(0,10); },
968             'persist' : 'hidden width ordinal'
969         },
970         {
971             'id' : 'notes',
972             'label' : 'Notes',
973             'flex' : 1,
974             'primary' : false,
975             'hidden' : false,
976             'render' : function(my) { return my.sitem.notes().length; },
977             'persist' : 'hidden width ordinal'
978         },
979         {
980             'id' : 'call_number',
981             'label' : 'Call Number',
982             'flex' : 1,
983             'primary' : false,
984             'hidden' : false,
985             'persist' : 'hidden width ordinal',
986             'render' : function(my) { return my.sitem.unit().call_number().label(); }
987         },
988         {
989             'id' : 'unit_id_contents',
990             'label' : 'Unit ID / Contents',
991             'flex' : 1,
992             'primary' : false,
993             'hidden' : false,
994             'render' : function(my) { return '[' + my.sitem.unit().id() + '] ' + my.sitem.unit().summary_contents() ; },
995             'persist' : 'hidden width ordinal'
996         },
997         {
998             'id' : 'creator',
999             'label' : 'Creator',
1000             'flex' : 1,
1001             'primary' : false,
1002             'hidden' : true,
1003             'persist' : 'hidden width ordinal',
1004             'render' : function(my) { return my.sitem.creator().usrname(); }
1005         },
1006         {
1007             'id' : 'create_date',
1008             'label' : document.getElementById('circStrings').getString('staff.circ.utils.create_date'),
1009             'flex' : 1,
1010             'primary' : false,
1011             'hidden' : true,
1012             'persist' : 'hidden width ordinal',
1013             'render' : function(my) { return my.sitem.create_date().substr(0,10); }
1014         },
1015         {
1016             'id' : 'editor',
1017             'label' : 'Editor',
1018             'flex' : 1,
1019             'primary' : false,
1020             'hidden' : true,
1021             'persist' : 'hidden width ordinal',
1022             'render' : function(my) { return my.sitem.editor().usrname(); }
1023         },
1024         {
1025             'id' : 'edit_date',
1026             'label' : document.getElementById('circStrings').getString('staff.circ.utils.edit_date'),
1027             'flex' : 1,
1028             'primary' : false,
1029             'hidden' : false,
1030             'persist' : 'hidden width ordinal',
1031             'render' : function(my) { return my.sitem.edit_date().substr(0,10); }
1032         },
1033         {
1034             'id' : 'holding_code',
1035             'label' : 'Holding Code',
1036             'flex' : 1,
1037             'primary' : false,
1038             'hidden' : true,
1039             'render' : function(my) { return my.sitem.issuance().holding_code(); },
1040             'persist' : 'hidden width ordinal'
1041         },
1042         {
1043             'id' : 'holding_type',
1044             'label' : 'Holding Type',
1045             'flex' : 1,
1046             'primary' : false,
1047             'hidden' : true,
1048             'render' : function(my) { return my.sitem.issuance().holding_type(); },
1049             'persist' : 'hidden width ordinal'
1050         },
1051         {
1052             'id' : 'holding_link_id',
1053             'label' : 'Holding Link ID',
1054             'flex' : 1,
1055             'primary' : false,
1056             'hidden' : true,
1057             'render' : function(my) { return my.sitem.issuance().holding_link_id(); },
1058             'persist' : 'hidden width ordinal'
1059         }
1060     ];
1061     for (var i = 0; i < c.length; i++) {
1062         if (modify[ c[i].id ]) {
1063             for (var j in modify[ c[i].id ]) {
1064                 c[i][j] = modify[ c[i].id ][j];
1065             }
1066         }
1067     }
1068     if (params) {
1069         if (params.just_these) {
1070             JSAN.use('util.functional');
1071             var new_c = [];
1072             for (var i = 0; i < params.just_these.length; i++) {
1073                 var x = util.functional.find_list(c,function(d){return(d.id==params.just_these[i]);});
1074                 new_c.push( function(y){ return y; }( x ) );
1075             }
1076             c = new_c;
1077         }
1078         if (params.except_these) {
1079             JSAN.use('util.functional');
1080             var new_c = [];
1081             for (var i = 0; i < c.length; i++) {
1082                 var x = util.functional.find_list(params.except_these,function(d){return(d==c[i].id);});
1083                 if (!x) new_c.push(c[i]);
1084             }
1085             c = new_c;
1086         }
1087     }
1088     //return c.sort( function(a,b) { if (a.label < b.label) return -1; if (a.label > b.label) return 1; return 0; } );
1089     return c;
1090 };
1091
1092 spawn_sitem_editor = function(params) {
1093     try {
1094         if (!params.sitem_ids && !params.sitems) return;
1095         if (params.sitem_ids && params.sitem_ids.length == 0) return;
1096         if (params.sitems && params.sitems.length == 0) return;
1097         if (params.sitem_ids) params.sitem_ids = js2JSON(params.sitem_ids); // legacy
1098         if (!params.caller_handles_update) params.handle_update = 1; // legacy
1099
1100         var obj = {};
1101         JSAN.use('util.network'); obj.network = new util.network();
1102         JSAN.use('util.error'); obj.error = new util.error();
1103
1104         var title = '';
1105         if (params.sitem_ids && params.sitem_ids.length > 1 && params.do_edit == 1)
1106             title = 'Batch Edit Items';
1107         else /* if(params.sitems && params.sitems.length > 1 && params.do_edit == 1)
1108             title = 'Batch View Items';
1109         else if(params.sitem_ids && params.sitem_ids.length == 1) */
1110             title = 'Edit Item';/*
1111         else
1112             title = 'View Item';*/
1113
1114         JSAN.use('util.window'); var win = new util.window();
1115         params.in_modal = true;
1116         var my_xulG = win.open(
1117             (urls.XUL_SERIAL_ITEM_EDITOR),
1118             title,
1119             'chrome,modal,resizable',
1120             params
1121         );
1122         if (my_xulG.sitems && params.do_edit) {
1123             return my_xulG.sitems;
1124         } else {
1125             return [];
1126         }
1127     } catch(E) {
1128         JSAN.use('util.error'); var error = new util.error();
1129         error.standard_unexpected_error_alert('error in spawn_sitem_editor',E);
1130     }
1131 }
1132
1133 dump('exiting manage_items.js\n');