]> git.evergreen-ils.org Git - working/Evergreen.git/blob - Open-ILS/xul/staff_client/server/cat/util.js
entry point and function stub for Mark Item as Missing Pieces
[working/Evergreen.git] / Open-ILS / xul / staff_client / server / cat / util.js
1 dump('entering cat/util.js\n');
2
3 function $(id) { return document.getElementById(id); }
4
5 if (typeof cat == 'undefined') var cat = {};
6 cat.util = {};
7
8 cat.util.EXPORT_OK    = [ 
9     'spawn_copy_editor', 'add_copies_to_bucket', 'show_in_opac', 'spawn_spine_editor', 'transfer_copies', 
10     'transfer_title_holds', 'mark_item_missing', 'mark_item_damaged', 'replace_barcode', 'fast_item_add', 
11     'make_bookable', 'edit_new_brsrc', 'edit_new_bresv', 'batch_edit_volumes', 'render_fine_level',
12     'render_loan_duration', 'mark_item_as_missing_pieces'
13 ];
14 cat.util.EXPORT_TAGS    = { ':all' : cat.util.EXPORT_OK };
15
16 cat.util.replace_barcode = function(old_bc) {
17     try {
18         JSAN.use('util.network');
19         var network = new util.network();
20
21         if (!old_bc) old_bc = window.prompt($("catStrings").getString('staff.cat.util.replace_barcode.old_bc_window_prompt.prompt'),
22             '',
23             $("catStrings").getString('staff.cat.util.replace_barcode.old_bc_window_prompt.title'));
24         if (!old_bc) return;
25
26         var copy;
27         try {
28             copy = network.simple_request('FM_ACP_RETRIEVE_VIA_BARCODE',[ old_bc ]);
29             if (typeof copy.ilsevent != 'undefined') throw(copy); 
30             if (!copy) throw(copy);
31         } catch(E) {
32             alert($("catStrings").getFormattedString('staff.cat.util.replace_barcode.error_alert', [old_bc]) + '\n');
33             return old_bc;
34         }
35     
36         // Why did I want to do this twice?  Because this copy is more fleshed?
37         try {
38             copy = network.simple_request('FM_ACP_RETRIEVE',[ copy.id() ]);
39             if (typeof copy.ilsevent != 'undefined') throw(copy);
40             if (!copy) throw(copy);
41         } catch(E) {
42             try {
43                 alert($("catStrings").getFormattedString('staff.cat.util.replace_barcode.error_alert', [old_bc]) +
44                      '\n' + (typeof E.ilsevent == 'undefined' ? '' : E.textcode + ' : ' + E.desc));
45             } catch(F) {
46                 alert(E + '\n' + F);
47             }
48             return old_bc;
49         }
50     
51         var new_bc = window.prompt($("catStrings").getString('staff.cat.util.replace_barcode.new_bc_window_prompt.prompt'),
52             '',
53             $("catStrings").getString('staff.cat.util.replace_barcode.new_bc_window_prompt.title'));
54         new_bc = String( new_bc ).replace(/\s/g,'');
55         /* Casting a possibly null input value to a String turns it into "null" */
56         if (!new_bc || new_bc == 'null') {
57             alert($("catStrings").getString('staff.cat.util.replace_barcode.new_bc.failed'));
58             return old_bc;
59         }
60     
61         var test = network.simple_request('FM_ACP_RETRIEVE_VIA_BARCODE',[ new_bc ]);
62         if (typeof test.ilsevent == 'undefined') {
63             alert('Rename aborted.  Another copy has barcode "' + new_bc + '".');
64             return old_bc;
65         } else {
66             if (test.ilsevent != 1502 /* ASSET_COPY_NOT_FOUND */) {
67                 obj.error.standard_unexpected_error_alert($("catStrings").getFormattedString('staff.cat.util.replace_barcode.testing_error', [new_bc]), test);
68                 return old_bc;
69             }    
70         }
71
72         copy.barcode(new_bc); copy.ischanged('1');
73         var r = network.simple_request('FM_ACP_FLESHED_BATCH_UPDATE', [ ses(), [ copy ] ]);
74         if (typeof r.ilsevent != 'undefined') { 
75             if (r.ilsevent != 0) {
76                 if (r.ilsevent == 5000 /* PERM_FAILURE */) {
77                     alert($("catStrings").getString('staff.cat.util.replace_barcode.insufficient_permission_for_rename'));
78                     return old_bc;
79                 } else {
80                     obj.error.standard_unexpected_error_alert($("catStrings").getString('staff.cat.util.replace_barcode.item_rename_error'),r);
81                     return old_bc;
82                 }
83             }
84         }
85
86         return new_bc;
87     } catch(E) {
88         JSAN.use('util.error'); var error = new util.error();
89         error.standard_unexpected_error_alert($("catStrings").getString('staff.cat.util.replace_barcode.rename_error'),E);
90         return old_bc;
91     }
92 }
93
94 cat.util.transfer_title_holds = function(old_targets) {
95     JSAN.use('OpenILS.data'); var data = new OpenILS.data();
96     JSAN.use('util.network'); var network = new util.network();
97     try {
98         data.stash_retrieve();
99         var target = data.marked_record_for_hold_transfer;
100         if (!target) {
101             var m = $("catStrings").getString('staff.cat.opac.title_for_hold_transfer.destination_needed.label');
102             alert(m);
103             return;
104         }
105         var robj = network.simple_request('TRANSFER_TITLE_HOLDS',[ ses(), target, old_targets ]);
106         if (robj == 1) {
107             var m = $("catStrings").getString('staff.cat.opac.title_for_hold_transfer.success.label');
108             alert(m);
109         } else {
110             var m = $("catStrings").getString('staff.cat.opac.title_for_hold_transfer.failure.label');
111             alert(m);
112         }
113     } catch(E) {
114         alert('Error in cat.util.transfer_title.holds(): ' + E);
115     }
116 }
117
118 cat.util.transfer_copies = function(params) {
119     JSAN.use('util.error'); var error = new util.error();
120     JSAN.use('OpenILS.data'); var data = new OpenILS.data();
121     JSAN.use('util.network'); var network = new util.network();
122     try {
123         data.stash_retrieve();
124         if (!data.marked_volume) {
125             alert($("catStrings").getString('staff.cat.util.transfer_copies.unmarked_volume_alert'));
126             return;
127         }
128         netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect UniversalBrowserWrite');
129         var xml = '<vbox xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" flex="1" style="overflow: auto">';
130         if (!params.message) {
131             params.message = $("catStrings").getFormattedString('staff.cat.util.transfer_copies.params_message', [data.hash.aou[ params.owning_lib ].shortname(), params.volume_label]);
132             //params.message = 'Transfer items from their original volumes to ';
133             //params.message += data.hash.aou[ params.owning_lib ].shortname() + "'s volume labelled ";
134             //params.message += '"' + params.volume_label + '" on the following record (and change their circ libs to match)?';
135         }
136
137         xml += '<description>' + params.message.replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;') + '</description>';
138         xml += '<hbox><button label="' + $("catStrings").getString('staff.cat.util.transfer_copies.transfer.label')+ '" name="fancy_submit"/>';
139         xml += '<button label="' + $("catStrings").getString('staff.cat.util.transfer_copies.cancel.label');
140         xml += '" accesskey="'+ $("catStrings").getString('staff.cat.util.transfer_copies.cancel.accesskey') +'" name="fancy_cancel"/></hbox>';
141         xml += '<iframe style="overflow: scroll" flex="1" src="' + urls.XUL_BIB_BRIEF + '?docid=' + params.docid + '"/>';
142         xml += '</vbox>';
143         //data.temp_transfer = xml; data.stash('temp_transfer');
144         JSAN.use('util.window'); var win = new util.window();
145         var fancy_prompt_data = win.open(
146             urls.XUL_FANCY_PROMPT,
147             //+ '?xml_in_stash=temp_transfer'
148             //+ '&title=' + window.escape('Item Transfer'),
149             'fancy_prompt', 'chrome,resizable,modal,width=500,height=300',
150             { 'xml' : xml, 'title' : $("catStrings").getString('staff.cat.util.transfer_copies.window_title') }
151         );
152         if (fancy_prompt_data.fancy_status == 'incomplete') { alert($("catStrings").getString('staff.cat.util.transfer_copies.aborted_transfer')); return; }
153
154         JSAN.use('util.functional');
155
156         var copies = network.simple_request('FM_ACP_FLESHED_BATCH_RETRIEVE.authoritative', [ params.copy_ids ]);
157
158         for (var i = 0; i < copies.length; i++) {
159             copies[i].call_number( data.marked_volume );
160             copies[i].circ_lib( params.owning_lib );
161             copies[i].ischanged( 1 );
162         }
163
164         var robj = network.simple_request(
165             'FM_ACP_FLESHED_BATCH_UPDATE', 
166             [ ses(), copies, true ], 
167             null,
168             {
169                 'title' : $("catStrings").getString('staff.cat.util.transfer_copies.override_transfer_failure'),
170                 'overridable_events' : [
171                     1208 /* TITLE_LAST_COPY */,
172                     1227 /* COPY_DELETE_WARNING */,
173                 ]
174             }
175         );
176         
177         if (typeof robj.ilsevent != 'undefined') {
178             throw(robj);
179         } else {
180             alert($("catStrings").getString('staff.cat.util.transfer_copies.successful_transfer'));
181         }
182
183     } catch(E) {
184         error.standard_unexpected_error_alert($("catStrings").getString('staff.cat.util.transfer_copies.transfer_error'),E);
185     }
186 }
187
188 cat.util.spawn_spine_editor = function(selection_list) {
189     JSAN.use('util.error'); var error = new util.error();
190     try {
191         JSAN.use('util.functional');
192         JSAN.use('OpenILS.data'); var data = new OpenILS.data(); data.stash_retrieve();
193         data.temp_barcodes_for_labels = util.functional.map_list( selection_list, function(o){return o.barcode;}) ; 
194         data.stash('temp_barcodes_for_labels');
195         xulG.new_tab(
196             xulG.url_prefix( urls.XUL_SPINE_LABEL ),
197             { 'tab_name' : $("catStrings").getString('staff.cat.util.spine_editor.tab_name') },
198             {}
199         );
200     } catch(E) {
201         error.standard_unexpected_error_alert($("catStrings").getString('staff.cat.util.spine_editor.spine_editor_error'),E);
202     }
203 }
204
205 cat.util.show_in_opac = function(selection_list) {
206     JSAN.use('util.error'); var error = new util.error();
207     JSAN.use('util.network'); var network = new util.network();
208     var doc_id; var seen = {};
209     try {
210         for (var i = 0; i < selection_list.length; i++) {
211             doc_id = selection_list[i].doc_id;
212             if (!doc_id) {
213                 var barcode = selection_list[i].barcode;
214                 doc_id = network.simple_request('FM_BRE_ID_VIA_BARCODE',[barcode]);
215                 if (typeof doc_id.ilsevent != 'undefined' || doc_id == -1) {
216                     alert($("catStrings").getFormattedString('staff.cat.util.show_in_opac.unknown_barcode', [barcode]));
217                     continue;
218                 }
219             }
220             if (doc_id == -1 ) {
221                 continue; /* pre-cat */
222             }
223             if (typeof seen[doc_id] != 'undefined') {
224                 continue;
225             }
226             seen[doc_id] = true;
227             var opac_url = xulG.url_prefix( urls.opac_rdetail ) + '?r=' + doc_id;
228             var content_params = { 
229                 'session' : ses(),
230                 'authtime' : ses('authtime'),
231                 'opac_url' : opac_url,
232             };
233             xulG.new_tab(
234                 xulG.url_prefix(urls.XUL_OPAC_WRAPPER), 
235                 {'tab_name':'Retrieving title...'}, 
236                 content_params
237             );
238         }
239     } catch(E) {
240         error.standard_unexpected_error_alert($("catStrings").getFormattedString('staff.cat.util.show_in_opac.catalog_error_for_doc_id', [doc_id]),E);
241     }
242 }
243
244 cat.util.add_copies_to_bucket = function(selection_list) {
245     JSAN.use('util.functional');
246     JSAN.use('util.window'); var win = new util.window();
247     JSAN.use('OpenILS.data'); var data = new OpenILS.data(); data.init({'via':'stash'});
248     data.cb_temp_copy_ids = js2JSON(
249         util.functional.map_list(
250             selection_list,
251             function (o) {
252                 if (typeof o.copy_id != 'undefined' && o.copy_id != null) {
253                     return o.copy_id;
254                 } else {
255                     return o;
256                 }
257             }
258         )
259     );
260     data.stash('cb_temp_copy_ids');
261     win.open( 
262         xulG.url_prefix(urls.XUL_COPY_BUCKETS_QUICK),
263         'sel_bucket_win' + win.window_name_increment(),
264         'chrome,resizable,center'
265     );
266 }
267
268 cat.util.add_titles_to_bucket = function(record_ids) {
269     JSAN.use('util.window'); var win = new util.window();
270     win.open(
271         xulG.url_prefix(urls.XUL_RECORD_BUCKETS_QUICK),
272         'sel_bucket_win' + win.window_name_increment(),
273         'chrome,resizable,modal,center',
274         {
275             record_ids: record_ids 
276         }
277     );
278 }
279
280 cat.util.spawn_copy_editor = function(params) {
281     try {
282         if (!params.copy_ids && !params.copies) return;
283         if (params.copy_ids && params.copy_ids.length == 0) return;
284         if (params.copies && params.copies.length == 0) return;
285         if (params.copy_ids) params.copy_ids = js2JSON(params.copy_ids); // legacy
286         if (!params.caller_handles_update) params.handle_update = 1; // legacy
287
288         var obj = {};
289         JSAN.use('util.network'); obj.network = new util.network();
290         JSAN.use('util.error'); obj.error = new util.error();
291     
292         var title = '';
293         if (params.copy_ids && params.copy_ids.length > 1 && params.edit == 1)
294             title = $("catStrings").getString('staff.cat.util.copy_editor.batch_edit');
295         else if(params.copies && params.copies.length > 1 && params.edit == 1)
296             title = $("catStrings").getString('staff.cat.util.copy_editor.batch_view');
297         else if(params.copy_ids && params.copy_ids.length == 1)
298             title = $("catStrings").getString('staff.cat.util.copy_editor.edit');
299         else
300             title = $("catStrings").getString('staff.cat.util.copy_editor.view');
301
302         JSAN.use('util.window'); var win = new util.window();
303         var my_xulG = win.open(
304             (urls.XUL_COPY_EDITOR),
305             title,
306             'chrome,modal,resizable',
307             params
308         );
309         if (!my_xulG.copies && params.edit) {
310         } else {
311             return my_xulG.copies;
312         }
313         return [];
314     } catch(E) {
315         JSAN.use('util.error'); var error = new util.error();
316         error.standard_unexpected_error_alert('error in cat.util.spawn_copy_editor',E);
317     }
318 }
319
320 cat.util.mark_item_damaged = function(copy_ids) {
321     var error;
322     try {
323         JSAN.use('util.error'); error = new util.error();
324         JSAN.use('util.functional'); JSAN.use('util.date');
325         JSAN.use('util.network'); var network = new util.network();
326         var copies = network.simple_request('FM_ACP_FLESHED_BATCH_RETRIEVE.authoritative', [ copy_ids ]);
327         if (typeof copies.ilsevent != 'undefined') throw(copies);
328         var magic_status = false;
329         for (var i = 0; i < copies.length; i++) {
330             var status = copies[i].status(); if (typeof status == 'object') status = status.id();
331             if (typeof my_constants.magical_statuses[ status ] != 'undefined') 
332                 if (my_constants.magical_statuses[ status ].block_mark_item_damaged) magic_status = true;
333         }
334         if (magic_status) {
335         
336             error.yns_alert($("catStrings").getString('staff.cat.util.mark_item_damaged.af_message'),
337                 $("catStrings").getString('staff.cat.util.mark_item_damaged.af_title'),
338                 $("catStrings").getString('staff.cat.util.mark_item_damaged.af_ok_label'), null, null,
339                 $("catStrings").getString('staff.cat.util.mark_item_damaged.af_confirm_action'));
340
341         } else {
342
343             var r = error.yns_alert($("catStrings").getFormattedString('staff.cat.util.mark_item_damaged.md_message', [util.functional.map_list( copies, function(o) { return o.barcode(); } ).join(", ")]),
344                 $("catStrings").getString('staff.cat.util.mark_item_damaged.md_title'),
345                 $("catStrings").getString('staff.cat.util.mark_item_damaged.md_ok_label'),
346                 $("catStrings").getString('staff.cat.util.mark_item_damaged.md_cancel_label'), null,
347                 $("catStrings").getString('staff.cat.util.mark_item_damaged.md_confirm_action'));
348
349             if (r == 0) {
350                 var count = 0;
351                 for (var i = 0; i < copies.length; i++) {
352                     try {
353
354                         var my_circ = network.simple_request('FM_CIRC_RETRIEVE_VIA_COPY',[ses(),copies[i].id(),1]);
355                         if (typeof my_circ.ilsevent == 'undefined') { 
356                             JSAN.use('OpenILS.data'); var data = new OpenILS.data(); data.stash_retrieve();
357                             my_circ = my_circ[0];
358                             if (typeof my_circ != 'undefined') {
359                                 if (! my_circ.checkin_time() ) {
360                                     var due_date = my_circ.due_date() ? util.date.formatted_date( my_circ.due_date(), '%F' ) : null;
361                                     var auto_checkin = String( data.hash.aous['circ.auto_checkin_on_mark_damage'] ) == 'true';
362                                     /* short-circuit this behavior.  We don't want to mark an item damaged and still have it circulating.  At least for now.  Wait until someone asks for it. */
363                                     auto_checkin = true; 
364                                     JSAN.use('patron.util');
365                                     var patron_obj = patron.util.retrieve_fleshed_au_via_id( ses(), my_circ.usr() );
366                                     var patron_name = patron.util.format_name( patron_obj ) + ' : ' + patron_obj.card().barcode();
367                                     var msg = $("catStrings").getFormattedString('staff.cat.util.mark_item_damaged.item_circulating_to_patron', [ 
368                                         copies[i].barcode(),
369                                         patron_name,
370                                         util.date.formatted_date( my_circ.due_date(), '%{localized}' )]);
371                                     JSAN.use('util.date'); var today = util.date.formatted_date(new Date(),'%F');
372                                     var r2 = auto_checkin ? 1 : error.yns_alert(
373                                         msg,
374                                         document.getElementById('catStrings').getString('staff.cat.util.mark_item_damaged.checkin.title'),
375                                         document.getElementById('catStrings').getString('staff.cat.util.mark_item_damaged.checkin.no_checkin'),
376                                         document.getElementById('catStrings').getString('staff.cat.util.mark_item_damaged.checkin.normal_checkin'),
377                                         due_date ? (today > due_date ? document.getElementById('catStrings').getString('staff.cat.util.mark_item_damaged.checkin.forgiving_checkin') : null) : null,
378                                         document.getElementById('catStrings').getString('staff.cat.util.mark_item_damaged.checkin.confirm_action')
379                                     );
380                                     JSAN.use('circ.util');
381                                     switch(r2) {
382                                         case 1:
383                                             circ.util.checkin_via_barcode( ses(), { 'barcode' : copies[i].barcode(), 'noop' : 1 } );
384                                         break;
385                                         case 2:
386                                             circ.util.checkin_via_barcode( ses(), { 'barcode' : copies[i].barcode(), 'noop' : 1 }, due_date );
387                                         break;
388                                     }
389                                 }
390                             }
391                         }
392
393                         var robj = network.simple_request('MARK_ITEM_DAMAGED',[ses(),copies[i].id()]);
394                         if (typeof robj.ilsevent != 'undefined') {
395                             switch(robj.textcode) {
396                                 case 'DAMAGE_CHARGE' :
397                                     var params = {};
398                                     JSAN.use('util.money');
399                                     var circ_obj = robj.payload.circ;
400                                     var patron_obj = circ_obj.usr();
401                                     JSAN.use('patron.util'); 
402                                     var patron_name = patron.util.format_name( patron_obj ) + ' : ' + patron_obj.card().barcode(); 
403                                     var r1 = error.yns_alert( 
404                                         $("catStrings").getFormattedString('staff.cat.util.mark_item_damaged.charge_patron_prompt.message', [  
405                                             copies[i].barcode(),  
406                                             patron_name,  
407                                             util.date.formatted_date( circ_obj.checkin_time(), '%{localized}' ),
408                                             util.money.sanitize(robj.payload.charge) ]), 
409                                         $("catStrings").getString('staff.cat.util.mark_item_damaged.charge_patron_prompt.title'), 
410                                         $("catStrings").getString('staff.cat.util.mark_item_damaged.charge_patron_prompt.ok_label'), 
411                                         $("catStrings").getString('staff.cat.util.mark_item_damaged.charge_patron_prompt.change_amount_label'), 
412                                         $("catStrings").getString('staff.cat.util.mark_item_damaged.charge_patron_prompt.cancel_label'), 
413                                         $("catStrings").getString('staff.cat.util.mark_item_damaged.charge_patron_prompt.confirm_action')); 
414                                     if (r1 == 0) {
415                                         params.apply_fines = 'apply';
416                                     } else if (r1 == 1) { 
417                                         JSAN.use('util.window'); var win = new util.window();
418                                         var my_xulG = win.open(
419                                             urls.XUL_PATRON_BILL_WIZARD,
420                                             'billwizard',
421                                             'chrome,resizable,modal',
422                                             { 
423                                                 'patron' : patron_obj, 
424                                                 'patron_id' : patron_obj.id(), 
425                                                 'circ' : circ_obj, 
426                                                 'xact_id' : circ_obj.id(), 
427                                                 'do_not_process_bill' : true,
428                                                 /* 'override_default_billing_type' : 7, FIXME: maybe reintroduce this with an org setting for the specific btype? */
429                                                 'override_default_price' : util.money.sanitize( robj.payload.charge ) 
430                                             }
431                                         );
432
433                                         params.apply_fines = my_xulG.proceed ? 'apply' : 'noapply';
434                                         if (my_xulG.proceed) {
435                                             params.override_amount = my_xulG.amount;
436                                             params.override_btype = my_xulG.cbt_id;
437                                             params.override_note = my_xulG.note;
438                                         }
439                                     } else {
440                                         params.apply_fines = 'noapply';
441                                     }
442                                     robj = network.simple_request('MARK_ITEM_DAMAGED',[ ses(), copies[i].id(), params ]);
443                                     if (typeof robj.ilsevent != 'undefined') { throw(robj); }
444                                     break;
445                                 default: throw(robj);
446                             }
447                         }
448                         count++;
449                     } catch(E) {
450                         error.standard_unexpected_error_alert($("catStrings").getFormattedString('staff.cat.util.mark_item_damaged.marking_error', [copies[i].barcode()]),E);
451                     }
452                 }
453                 alert(count == 1 ? $("catStrings").getString('staff.cat.util.mark_item_damaged.one_item_damaged') :
454                     $("catStrings").getFormattedString('staff.cat.util.mark_item_damaged.multiple_item_damaged', [count]));
455             }
456         }
457
458     } catch(E) {
459         if (error) error.standard_unexpected_error_alert('cat.util.mark_item_damaged',E); else alert('FIXME: ' + E);
460     }
461 }
462
463 cat.util.mark_item_missing = function(copy_ids) {
464     var error;
465     try {
466         JSAN.use('util.error'); error = new util.error();
467         JSAN.use('util.functional');
468         JSAN.use('util.network'); var network = new util.network();
469         var copies = network.simple_request('FM_ACP_FLESHED_BATCH_RETRIEVE.authoritative', [ copy_ids ]);
470         if (typeof copies.ilsevent != 'undefined') throw(copies);
471         var magic_status = false;
472         for (var i = 0; i < copies.length; i++) {
473             var status = copies[i].status(); if (typeof status == 'object') status = status.id();
474             if (typeof my_constants.magical_statuses[ status ] != 'undefined') 
475                 if (my_constants.magical_statuses[ status ].block_mark_item_action) magic_status = true;
476         }
477         if (magic_status) {
478         
479             error.yns_alert($("catStrings").getString('staff.cat.util.mark_item_missing.af_message'),
480                 $("catStrings").getString('staff.cat.util.mark_item_missing.af_title'),
481                 $("catStrings").getString('staff.cat.util.mark_item_missing.af_ok_label'), null, null,
482                 $("catStrings").getString('staff.cat.util.mark_item_missing.af_confirm_action'));
483
484         } else {
485
486             var r = error.yns_alert($("catStrings").getFormattedString('staff.cat.util.mark_item_missing.ms_message', [util.functional.map_list( copies, function(o) { return o.barcode(); } ).join(", ")]),
487                 $("catStrings").getString('staff.cat.util.mark_item_missing.ms_title'),
488                 $("catStrings").getString('staff.cat.util.mark_item_missing.ms_ok_label'),
489                 $("catStrings").getString('staff.cat.util.mark_item_missing.ms_cancel_label'), null,
490                 $("catStrings").getString('staff.cat.util.mark_item_missing.ms_confirm_action'));
491
492             if (r == 0) {
493                 var count = 0;
494                 for (var i = 0; i < copies.length; i++) {
495                     try {
496                         var robj = network.simple_request('MARK_ITEM_MISSING',[ses(),copies[i].id()]);
497                         if (typeof robj.ilsevent != 'undefined') throw(robj);
498                         count++;
499                     } catch(E) {
500                         error.standard_unexpected_error_alert($("catStrings").getFormattedString('staff.cat.util.mark_item_missing.marking_error', [copies[i].barcode()]),E);
501                     }
502                 }
503                 alert(count == 1 ? $("catStrings").getString('staff.cat.util.mark_item_missing.one_item_missing') :
504                     $("catStrings").getFormattedString('staff.cat.util.mark_item_missing.multiple_item_missing', [count]));
505             }
506         }
507
508     } catch(E) {
509         if (error) error.standard_unexpected_error_alert('cat.util.mark_item_missing',E); else alert('FIXME: ' + E);
510     }
511 }
512
513 cat.util.fast_item_add = function(doc_id,cn_label,cp_barcode) {
514     var error;
515     try {
516
517         JSAN.use('util.error'); error = new util.error();
518         JSAN.use('util.network'); var network = new util.network();
519
520         var acn_id = network.simple_request(
521             'FM_ACN_FIND_OR_CREATE',
522             [ ses(), cn_label, doc_id, ses('ws_ou') ]
523         );
524
525         if (typeof acn_id.ilsevent != 'undefined') {
526             error.standard_unexpected_error_alert($("catStrings").getFormattedString('staff.cat.volume_copy_creator.stash_and_close.problem_with_volume', [cn]), acn_id);
527             return;
528         }
529
530         var copy_obj = new acp();
531         copy_obj.id( -1 );
532         copy_obj.isnew('1');
533         copy_obj.barcode( cp_barcode );
534         copy_obj.call_number( acn_id );
535         copy_obj.circ_lib( ses('ws_ou') );
536         /* FIXME -- use constants */
537         copy_obj.deposit(0);
538         copy_obj.price(0);
539         copy_obj.deposit_amount(0);
540         copy_obj.fine_level(2);
541         copy_obj.loan_duration(2);
542         copy_obj.location(1);
543         copy_obj.status(0);
544         copy_obj.circulate(get_db_true());
545         copy_obj.holdable(get_db_true());
546         copy_obj.opac_visible(get_db_true());
547         copy_obj.ref(get_db_false());
548
549         JSAN.use('util.window'); var win = new util.window();
550         JSAN.use('cat.util');
551         return cat.util.spawn_copy_editor( { 'handle_update' : 1, 'edit' : 1, 'docid' : doc_id, 'copies' : [ copy_obj ] });
552
553     } catch(E) {
554         if (error) error.standard_unexpected_error_alert('cat.util.fast_item_add',E); else alert('FIXME: ' + E);
555     }
556 }
557
558 cat.util.make_bookable = function(copy_ids) {
559     var results = fieldmapper.standardRequest(
560         ["open-ils.booking", "open-ils.booking.resources.create_from_copies"],
561         [ses(), copy_ids]
562     );
563     if (results == null) {
564         alert(document.getElementById("catStrings").getString(
565             "staff.cat.copy_browser.make_bookable.create_failed_silent"
566         ));
567     }
568     else if (typeof results.ilsevent != "undefined") {
569         alert(document.getElementById("catStrings").getFormattedString(
570             "staff.cat.copy_browser.make_bookable.create_failed",
571             [results.ilsevent, results.textcode, results.desc, results.debug]
572         ));
573     }
574     return results;
575 }
576
577 cat.util.edit_new_brsrc = function(brsrc_list) {
578     /* Spawn new tab to allow editing new resources. */
579     try {
580         xulG.resultant_brsrc = brsrc_list.map(function(o) { return o[0]; });
581         xulG.new_tab(
582             urls.XUL_BROWSER + "?url=" + window.escape(
583                 xulG.url_prefix("/eg/conify/global/booking/resource")
584             ), {
585                 "tab_name": offlineStrings.getString(
586                     "menu.cmd_booking_resource.tab"
587                  ),
588                 "browser" : true
589             }, {
590                 "no_xulG": false,
591                 "show_print_button": false,
592                 "show_nav_buttons": true,
593                 "passthru_content_params": xulG
594             }
595         );
596     } catch(E) {
597         alert(
598             document.getElementById("catStrings").getFormattedString(
599                 "staff.cat.copy_browser.make_bookable.newtab_failed"
600             ), E
601         );
602     }
603 }
604
605 cat.util.edit_new_bresv = function(booking_results) {
606     /* Spawn new tab to allow editing new reservations. */
607     try {
608         if (xulG.auth == undefined) {
609             xulG.auth = {"session": {"key": ses()}};
610         }
611         xulG.bresv_interface_opts = {"booking_results": booking_results};
612         xulG.new_tab(
613             xulG.url_prefix("/eg/booking/reservation"),
614             {
615                 "tab_name": offlineStrings.getString(
616                     "menu.cmd_booking_reservation.tab"
617                  ),
618                 "browser" : false
619             }, xulG
620         );
621     } catch(E) {
622         alert(
623             document.getElementById("catStrings").getString(
624                 "staff.cat.copy_browser.make_bookable.newtab_failed"
625             ) + E
626         );
627     }
628 }
629
630 cat.util.batch_edit_volumes = function(fleshed_volumes) {
631     try {
632         if (!fleshed_volumes || fleshed_volumes.length < 1) { return false; }
633
634         JSAN.use('util.functional');
635         JSAN.use('util.network'); var net = new util.network();
636         JSAN.use('util.window'); var win = new util.window();
637
638         var can_edit = net.simple_request(
639             'PERM_MULTI_ORG_CHECK',
640             [
641                 ses(),
642                 ses('staff_id'),
643                 util.functional.map_list(
644                     fleshed_volumes,
645                     function(v) {
646                         return v.owning_lib();
647                     }
648                 ),
649                 ['UPDATE_VOLUME']
650             ]
651         );
652         if (!can_edit) {
653             alert(document.getElementById('catStrings').getString('staff.cat.edit_volume.permission_error'));
654             return false;
655         }
656         var title;
657         if (fleshed_volumes.length == 1) {
658             title = document.getElementById('catStrings').getString('staff.cat.edit_volume.title');
659         } else {
660             title = document.getElementById('catStrings').getString('staff.cat.edit_volume.title.plural');
661         }
662
663         function clone_list(o) {
664             var list = JSON2js( js2JSON( o ) );
665             // now that it is safe to clear copies, let's do so, otherwise may get an error from volume edit method
666             for (var i = 0; i < list.length; i++) { list[i].copies( [] ); } 
667             return list;
668         }
669
670         var my_xulG = win.open(
671             xulG.url_prefix(urls.XUL_VOLUME_EDITOR),
672             title,
673             'chrome,modal,resizable',
674             { 'volumes' : clone_list( fleshed_volumes ) }
675         );
676
677         if (typeof my_xulG.update_these_volumes == 'undefined') { return false; }
678
679         var volumes = util.functional.filter_list(
680             my_xulG.volumes,
681             function(v) {
682                 return get_bool( v.ischanged() );
683             }
684         );
685
686         if (volumes.length < 1) { return false; }
687
688         var r = net.simple_request(
689             'FM_ACN_TREE_UPDATE',
690             [ ses(), volumes, false, { 'auto_merge_vols' : my_xulG.auto_merge } ],
691             null,
692             {
693                 'title' : document.getElementById('catStrings').getString('staff.cat.edit_volumes.override.confirm'),
694                 'overridable_events' : [
695                     1705 /* VOLUME_LABEL_EXISTS */
696                 ],
697                 'text' : {
698                     '1705' : function(r) {
699                         var payload_acn = util.functional.find_id_object_in_list( volumes, r.payload );
700                         return document.getElementById('catStrings').getFormattedString('staff.cat.edit_volumes.label_exists.details',[payload_acn.label()]);
701                     }
702                 }
703             }
704         );
705         if (!r) { throw('Update method returned null or false.'); }
706         if (typeof r.ilsevent != 'undefined') {
707             if (r.ilsevent == 1705 /* VOLUME_LABEL_EXISTS */) {
708                /* not overriden, but otherwise handled, so ignore */
709                 return false;
710             } else {
711                 throw(r);
712             }
713         }
714
715         return true;
716
717     } catch(E) {
718         alert('Error in cat.util.batch_edit_volumes: ' + E);
719         return false;
720     }
721 }
722
723 cat.util.render_fine_level = function(value) {
724     var text;
725     switch(Number(value)){
726         case 1: text = document.getElementById("catStrings").getString("staff.cat.copy_editor.field.fine_level.low"); break;
727         case 2: text = document.getElementById("catStrings").getString("staff.cat.copy_editor.field.fine_level.normal"); break;
728         case 3: text = document.getElementById("catStrings").getString("staff.cat.copy_editor.field.fine_level.high"); break; 
729     }
730     return text;
731 }
732 cat.util.render_loan_duration = function(value) {
733     var text;
734     switch(Number(value)){
735         case 1: text = document.getElementById("catStrings").getString("staff.cat.copy_editor.field.loan_duration.short"); break;
736         case 2: text = document.getElementById("catStrings").getString("staff.cat.copy_editor.field.loan_duration.normal"); break;
737         case 3: text = document.getElementById("catStrings").getString("staff.cat.copy_editor.field.loan_duration.extended"); break;
738     }
739     return text;
740 }
741
742 cat.util.mark_item_as_missing_pieces = function(copy_ids) {
743 }
744
745 dump('exiting cat/util.js\n');