View | Details | Raw Unified | Return to bug 35506
Collapse All | Expand All

(-)a/koha-tmpl/intranet-tmpl/prog/js/checkouts.js (-467 / +468 lines)
Lines 1-9 Link Here
1
/* global __ */
1
/* global __ */
2
2
3
$(document).ready(function() {
3
function RefreshIssuesTable() {
4
    var loadIssuesTableDelayTimeoutId;
4
    var table = $('#issues-table').DataTable();
5
    var renewchecked = $('input[name=renew]:checked').map(function(){
6
        return this.value;
7
    }).get();
8
    var checkinchecked = $('input[name=checkin]:checked').map(function(){
9
        return this.value;
10
    }).get();
11
    table.ajax.reload( function() {
12
        $('#RenewChecked, #CheckinChecked').prop('disabled' , true );
13
        if ( renewchecked.length ) {
14
            $('#RenewChecked').prop('disabled' , false );
15
            renewchecked.forEach( function(checked) {
16
                $('.renew[value="'+checked+'"]').prop('checked' , true );
17
            });
18
        }
19
        if ( checkinchecked.length ) {
20
            $('#CheckinChecked').prop('disabled' , false );
21
            checkinchecked.forEach( function(checked) {
22
                $('.checkin[value="'+checked+'"]').prop('checked' , true );
23
            });
24
        }
25
    var checkout_count = table.page.info().recordsTotal;
26
    $('.checkout_count').text(checkout_count);
27
    });
28
}
29
30
function LoadIssuesTable() {
31
    $('#issues-table-loading-message').hide();
32
    $('#issues-table').show();
33
    $('#issues-table-actions').show();
34
    var msg_loading = __('Loading... you may continue scanning.');
35
    issuesTable = KohaTable("issues-table", {
36
        "oLanguage": {
37
            "sEmptyTable" : msg_loading,
38
            "sProcessing": msg_loading,
39
        },
40
        "bAutoWidth": false,
41
        "dom": '<"table_controls"B>rt',
42
        "aoColumns": [
43
            {
44
                "mDataProp": function( oObj ) {
45
                    return oObj.sort_order;
46
                }
47
            },
48
            {
49
                "mDataProp": function( oObj ) {
50
                    if ( oObj.issued_today ) {
51
                        return "<strong>" + __("Today's checkouts") + "</strong>";
52
                    } else {
53
                        return "<strong>" + __("Previous checkouts") + "</strong>";
54
                    }
55
                }
56
            },
57
            {
58
                "mDataProp": "date_due",
59
                "bVisible": false,
60
            },
61
            {
62
                "iDataSort": 2, // Sort on hidden unformatted date due column
63
                "mDataProp": function( oObj ) {
64
                    let date_due_formatted = $datetime(oObj.date_due, { as_due_date: true, no_tz_adjust: true });
65
                    var due = oObj.date_due_overdue
66
                        ? "<span class='overdue'>" + date_due_formatted + "</span>"
67
                        : date_due_formatted;
68
69
                    due = "<span id='date_due_" + oObj.itemnumber + "' class='date_due'>" + due + "</span>";
70
71
                    if ( oObj.lost && oObj.claims_returned ) {
72
                        due += "<span class='lost claims_returned'>" + oObj.lost.escapeHtml() + "</span>";
73
                    } else if ( oObj.lost ) {
74
                        due += "<span class='lost'>" + oObj.lost.escapeHtml() + "</span>";
75
                    }
76
77
                    if ( oObj.damaged ) {
78
                        due += "<span class='dmg'>" + oObj.damaged.escapeHtml() + "</span>";
79
                    }
80
81
                    var patron_note = " <span class='patron_note_" + oObj.itemnumber + "'></span>";
82
                    due +="<br>" + patron_note;
83
84
                    return due;
85
                }
86
            },
87
            {
88
                "mDataProp": function ( oObj ) {
89
                    let title = "<span id='title_" + oObj.itemnumber + "' class='strong'><a href='/cgi-bin/koha/catalogue/detail.pl?biblionumber="
90
                          + oObj.biblionumber
91
                          + "'>"
92
                          + (oObj.title ? oObj.title.escapeHtml() : '' );
93
94
                    $.each(oObj.subtitle, function( index, value ) {
95
                              title += " " + value.escapeHtml();
96
                    });
97
98
                    title += " " + oObj.part_number + " " + oObj.part_name;
99
100
                    if ( oObj.enumchron ) {
101
                        title += " <span class='item_enumeration'>(" + oObj.enumchron.escapeHtml() + ")</span>";
102
                    }
103
104
                    title += "</a></span>";
105
106
                    if ( oObj.author ) {
107
                        title += " " + __("by _AUTHOR_").replace( "_AUTHOR_",  " " + oObj.author.escapeHtml() );
108
                    }
109
110
                    if ( oObj.itemnotes ) {
111
                        var span_class = "text-muted";
112
                        if ( flatpickr.formatDate( new Date(oObj.issuedate), "Y-m-d" ) == ymd ){
113
                            span_class = "circ-hlt";
114
                        }
115
                        title += "<span class='divider-dash'> - </span><span class='" + span_class + " item-note-public'>" + oObj.itemnotes.escapeHtml() + "</span>";
116
                    }
117
118
                    if ( oObj.itemnotes_nonpublic ) {
119
                        var span_class = "text-danger";
120
                        if ( flatpickr.formatDate( new Date(oObj.issuedate), "Y-m-d" ) == ymd ){
121
                            span_class = "circ-hlt";
122
                        }
123
                        title += "<span class='divider-dash'> - </span><span class='" + span_class + " item-note-nonpublic'>" + oObj.itemnotes_nonpublic.escapeHtml() + "</span>";
124
                    }
125
126
                    var onsite_checkout = '';
127
                    if ( oObj.onsite_checkout == 1 ) {
128
                        onsite_checkout += " <span class='onsite_checkout'>(" + __("On-site checkout") + ")</span>";
129
                    }
130
131
                    if ( oObj.recalled == 1 ) {
132
                         title += "<span class='divider-dash'> - </span><span class='circ-hlt item-recalled'>" +  __("This item has been recalled and the due date updated") + ".</span>";
133
                    }
134
135
                    title += " "
136
                          + "<a href='/cgi-bin/koha/catalogue/moredetail.pl?biblionumber="
137
                          + oObj.biblionumber
138
                          + "&itemnumber="
139
                          + oObj.itemnumber
140
                          + "#"
141
                          + oObj.itemnumber
142
                          + "'>"
143
                          + (oObj.barcode ? oObj.barcode.escapeHtml() : "")
144
                          + "</a>"
145
                          + onsite_checkout
146
147
                    return title;
148
                },
149
                "sType": "anti-the"
150
            },
151
            {
152
                "mDataProp": function ( oObj ) {
153
                    return oObj.recordtype_description.escapeHtml();
154
                }
155
            },
156
            {
157
                "mDataProp": function ( oObj ) {
158
                    return oObj.itemtype_description.escapeHtml();
159
                }
160
            },
161
            {
162
                "mDataProp": function ( oObj ) {
163
                    return ( oObj.collection ? oObj.collection.escapeHtml() : '' );
164
                }
165
            },
166
            {
167
                "mDataProp": function ( oObj ) {
168
                    return ( oObj.location ? oObj.location.escapeHtml() : '' );
169
                }
170
            },
171
            {
172
                "mDataProp": function ( oObj ) {
173
                    return (oObj.homebranch ? oObj.homebranch.escapeHtml() : '' );
174
                }
175
            },
176
            {
177
                "mDataProp": "issuedate",
178
                "bVisible": false,
179
            },
180
            {
181
                "iDataSort": 10, // Sort on hidden unformatted issuedate column
182
                "mDataProp": function( oObj ) {
183
                    return $datetime(oObj.issuedate, { no_tz_adjust: true });
184
                }
185
            },
186
            {
187
                "mDataProp": function ( oObj ) {
188
                    return (oObj.branchname ? oObj.branchname.escapeHtml() : '' );
189
                }
190
            },
191
            {
192
                "mDataProp": function ( oObj ) {
193
                    return ( oObj.itemcallnumber ? oObj.itemcallnumber.escapeHtml() : '' );
194
                }
195
            },
196
            {
197
                "mDataProp": function ( oObj ) {
198
                    return ( oObj.copynumber ? oObj.copynumber.escapeHtml() : '' );
199
                }
200
            },
201
            {
202
                "mDataProp": function ( oObj ) {
203
                    if ( ! oObj.charge ) oObj.charge = 0;
204
                    return '<span style="text-align: right; display: block;">' + parseFloat(oObj.charge).format_price() + '<span>';
205
                },
206
                "sClass": "nowrap"
207
            },
208
            {
209
                "mDataProp": function ( oObj ) {
210
                    if ( ! oObj.fine ) oObj.fine = 0;
211
                    return '<span style="text-align: right; display: block;">' + parseFloat(oObj.fine).format_price()   + '<span>';
212
                },
213
                "sClass": "nowrap"
214
            },
215
            {
216
                "mDataProp": function ( oObj ) {
217
                    if ( ! oObj.price ) oObj.price = 0;
218
                    return '<span style="text-align: right; display: block;">' + parseFloat(oObj.price).format_price()  + '<span>';
219
                },
220
                "sClass": "nowrap"
221
            },
222
            {
223
                "bSortable": false,
224
                "bVisible": AllowCirculate ? true : false,
225
                "mDataProp": function ( oObj ) {
226
                    var content = "";
227
                    var msg = "";
228
                    var span_style = "";
229
                    var span_class = "";
230
231
                    if ( oObj.can_renew ) {
232
                        // Do nothing
233
                    } else if ( oObj.can_renew_error == "recalled" ) {
234
                        msg += "<span>"
235
                                + "<a href='/cgi-bin/koha/recalls/request.pl?biblionumber=" + oObj.biblionumber + "'>" + __("Recalled") + "</a>"
236
                                + "</span>";
237
238
                        span_style = "display: none";
239
                        span_class = "renewals-allowed-recalled";
240
                    } else if ( oObj.can_renew_error == "on_reserve" ) {
241
                        msg += "<span>"
242
                                +"<a href='/cgi-bin/koha/reserve/request.pl?biblionumber=" + oObj.biblionumber + "'>" + __("On hold") + "</a>"
243
                                + "</span>";
244
245
                        span_style = "display: none";
246
                        span_class = "renewals-allowed-on_reserve";
247
                    } else if ( oObj.can_renew_error == "too_many" ) {
248
                        msg += "<span class='renewals-disabled'>"
249
                                + __("Not renewable")
250
                                + "</span>";
251
252
                        span_style = "display: none";
253
                        span_class = "renewals-allowed";
254
                    } else if ( oObj.can_renew_error == "too_unseen" ) {
255
                        msg += "<span>"
256
                                + __("Must be renewed at the library")
257
                                + "</span>";
258
                        span_class = "renewals-allowed";
259
                    } else if ( oObj.can_renew_error == "restriction" ) {
260
                        msg += "<span class='renewals-disabled'>"
261
                                + __("Not allowed: patron restricted")
262
                                + "</span>";
263
264
                        span_style = "display: none";
265
                        span_class = "renewals-allowed";
266
                    } else if ( oObj.can_renew_error == "overdue" ) {
267
                        msg += "<span class='renewals-disabled'>"
268
                                + __("Not allowed: overdue")
269
                                + "</span>";
270
271
                        span_style = "display: none";
272
                        span_class = "renewals-allowed";
273
                    } else if ( oObj.can_renew_error == "too_soon" ) {
274
                        msg += "<span class='renewals-disabled'>"
275
                                + __("No renewal before %s").format(oObj.can_renew_date)
276
                                + "</span>";
277
278
                        span_style = "display: none";
279
                        span_class = "renewals-allowed";
280
                    } else if ( oObj.can_renew_error == "auto_too_late" ) {
281
                        msg += "<span class='renewals-disabled'>"
282
                                + __("Can no longer be auto-renewed - number of checkout days exceeded")
283
                                + "</span>";
284
285
                        span_style = "display: none";
286
                        span_class = "renewals-allowed";
287
                    } else if ( oObj.can_renew_error == "auto_too_much_oweing" ) {
288
                        msg += "<span class='renewals-disabled'>"
289
                                + __("Automatic renewal failed, patron has unpaid fines")
290
                                + "</span>";
291
292
                        span_style = "display: none";
293
                        span_class = "renewals-allowed";
294
                    } else if ( oObj.can_renew_error == "auto_account_expired" ) {
295
                        msg += "<span class='renewals-disabled'>"
296
                                + __("Automatic renewal failed, account expired")
297
                                + "</span>";
298
299
                        span_style = "display: none";
300
                        span_class = "renewals-allowed";
301
                    } else if ( oObj.can_renew_error == "onsite_checkout" ) {
302
                        // Don't display something if it's an onsite checkout
303
                    } else if ( oObj.can_renew_error == "item_denied_renewal" ) {
304
                        content += "<span class='renewals-disabled'>"
305
                                + __("Renewal denied by syspref")
306
                                + "</span>";
307
308
                        span_style = "display: none";
309
                        span_class = "renewals-allowed";
310
                    } else {
311
                        msg += "<span class='renewals-disabled'>"
312
                                + oObj.can_renew_error
313
                                + "</span>";
5
314
6
    var barcodefield = $("#barcode");
315
                        span_style = "display: none";
316
                        span_class = "renewals-allowed";
317
                    }
318
319
                    var can_force_renew = ( oObj.onsite_checkout == 0 ) &&
320
                        ( oObj.can_renew_error != "on_reserve" || (oObj.can_renew_error == "on_reserve" && AllowRenewalOnHoldOverride))
321
                        ? true : false;
322
                    var can_renew = ( oObj.renewals_remaining > 0 && ( !oObj.can_renew_error || oObj.can_renew_error == "too_unseen" ));
323
                    content += "<span>";
324
                    if ( can_renew || can_force_renew ) {
325
                        content += "<span style='padding: 0 1em;'>" + oObj.renewals_count + "</span>";
326
                        content += "<span class='" + span_class + "' style='" + span_style + "'>"
327
                                +  "<input type='checkbox' ";
328
                        if ( oObj.date_due_overdue && can_renew ) {
329
                            content += "checked='checked' ";
330
                        }
331
                        if (oObj.can_renew_error == "on_reserve") {
332
                            content += "data-on-reserve ";
333
                        }
334
                        content += "class='renew' id='renew_" + oObj.itemnumber + "' name='renew' value='" + oObj.itemnumber +"'/>"
335
                                +  "</span>";
336
                    }
337
                    content += msg;
338
                    if ( can_renew || can_force_renew ) {
339
                        content += "<span class='renewals-info'>(";
340
                        content += __("%s of %s renewals remaining").format(oObj.renewals_remaining, oObj.renewals_allowed);
341
                        if (UnseenRenewals && oObj.unseen_allowed) {
342
                            content += __(" and %s of %s unseen renewals remaining").format(oObj.unseen_remaining, oObj.unseen_allowed);
343
                        }
344
                        content += ")</span>";
345
                    }
346
                    if(oObj.auto_renew){
347
                        content += "<span class='renewals-info'>(";
348
                        content += __("Scheduled for automatic renewal");
349
                        content += ")</span>";
350
                    }
351
352
                    return content;
353
                }
354
            },
355
            {
356
                "bSortable": false,
357
                "bVisible": AllowCirculate ? true : false,
358
                "mDataProp": function ( oObj ) {
359
                    if ( oObj.can_renew_error == "recalled" ) {
360
                        return "<a href='/cgi-bin/koha/recalls/request.pl?biblionumber=" + oObj.biblionumber + "'>" + __("Recalled") + "</a>";
361
                    } else if ( oObj.can_renew_error == "on_reserve" ) {
362
                        return "<a href='/cgi-bin/koha/reserve/request.pl?biblionumber=" + oObj.biblionumber + "'>" + __("On hold") + "</a>";
363
                    } else if ( oObj.materials ) {
364
                        return "<input type='checkbox' class='confirm' id='confirm_" + oObj.itemnumber + "' name='confirm' value='" + oObj.itemnumber + "' data-materials='" + oObj.materials.escapeHtml() + "'></input>";
365
                    } else {
366
                        return "<input type='checkbox' class='checkin' id='checkin_" + oObj.itemnumber + "' name='checkin' value='" + oObj.itemnumber +"'></input>";
367
                    }
368
                }
369
            },
370
            {
371
                "bVisible": ClaimReturnedLostValue ? true : false,
372
                "bSortable": false,
373
                "mDataProp": function ( oObj ) {
374
                    let content = "";
375
376
                    if ( oObj.return_claim_id ) {
377
                      content = '<span class="badge">' + oObj.return_claim_created_on_formatted + '</span>';
378
                    } else if ( ClaimReturnedLostValue ) {
379
                      content = '<a class="btn btn-default btn-xs claim-returned-btn" data-itemnumber="' + oObj.itemnumber + '"><i class="fa fa-exclamation-circle"></i> ' + __("Claim returned") + '</a>';
380
                    } else {
381
                      content = '<a class="btn btn-default btn-xs" disabled="disabled" title="ClaimReturnedLostValue is not set, this feature is disabled"><i class="fa fa-exclamation-circle"></i> ' + __("Claim returned") + '</a>';
382
                    }
383
                    return content;
384
                }
385
            },
386
            {
387
                "bVisible": exports_enabled == 1 ? true : false,
388
                "bSortable": false,
389
                "mDataProp": function ( oObj ) {
390
                    var s = "<input type='checkbox' name='itemnumbers' value='" + oObj.itemnumber + "' style='visibility:hidden;' />";
391
392
                    s += "<input type='checkbox' class='export' id='export_" + oObj.biblionumber + "' name='biblionumbers' value='" + oObj.biblionumber + "' />";
393
                    return s;
394
                }
395
            }
396
        ],
397
        "fnFooterCallback": function ( nRow, aaData, iStart, iEnd, aiDisplay ) {
398
            var total_charge = 0;
399
            var total_fine  = 0;
400
            var total_price = 0;
401
            for ( var i=0; i < aaData.length; i++ ) {
402
                total_charge += aaData[i]['charge'] * 1;
403
                total_fine += aaData[i]['fine'] * 1;
404
                total_price  += aaData[i]['price'] * 1;
405
            }
406
            $("#totaldue").html(total_charge.format_price() );
407
            $("#totalfine").html(total_fine.format_price() );
408
            $("#totalprice").html(total_price.format_price() );
409
        },
410
        "bPaginate": false,
411
        "bProcessing": true,
412
        "bServerSide": false,
413
        "sAjaxSource": '/cgi-bin/koha/svc/checkouts',
414
        "fnServerData": function ( sSource, aoData, fnCallback ) {
415
            aoData.push( { "name": "borrowernumber", "value": borrowernumber } );
416
417
            $.getJSON( sSource, aoData, function (json) {
418
                fnCallback(json)
419
            } );
420
        },
421
        "rowGroup":{
422
            "dataSrc": "issued_today",
423
            "startRender": function ( rows, group ) {
424
                if ( group ) {
425
                    return __("Today's checkouts");
426
                } else {
427
                    return __("Previous checkouts");
428
                }
429
            }
430
        },
431
        "fnInitComplete": function(oSettings, json) {
432
            // Build a summary of checkouts grouped by itemtype
433
            var checkoutsByItype = json.aaData.reduce(function (obj, row) {
434
                obj[row.type_for_stat] = (obj[row.type_for_stat] || 0) + 1;
435
                return obj;
436
            }, {});
437
            var ul = $('<ul>');
438
            Object.keys(checkoutsByItype).sort().forEach(function (itype) {
439
                var li = $('<li>')
440
                    .append($('<strong>').html(itype || __("No itemtype")))
441
                    .append(': ' + checkoutsByItype[itype]);
442
                ul.append(li);
443
            })
444
            $('<details>')
445
                .addClass('checkouts-by-itemtype')
446
                .append($('<summary>').html( __("Number of checkouts by item type") ))
447
                .append(ul)
448
                .insertBefore(oSettings.nTableWrapper)
449
        },
450
    }, table_settings_issues_table);
451
452
    if ( $("#issues-table").length ) {
453
        $("#issues-table_processing").position({
454
            of: $( "#issues-table" ),
455
            collision: "none"
456
        });
457
    }
458
}
459
460
461
var loadIssuesTableDelayTimeoutId;
462
var barcodefield = $("#barcode");
463
464
$('#issues-table-load-now-button').click(function(){
465
    if ( loadIssuesTableDelayTimeoutId ) clearTimeout(loadIssuesTableDelayTimeoutId);
466
    LoadIssuesTable();
467
    barcodefield.focus();
468
    return false;
469
});
470
471
$(document).ready(function() {
7
472
8
    var onHoldDueDateSet = false;
473
    var onHoldDueDateSet = false;
9
474
Lines 271-282 $(document).ready(function() { Link Here
271
        }
736
        }
272
        barcodefield.focus();
737
        barcodefield.focus();
273
    });
738
    });
274
    $('#issues-table-load-now-button').click(function(){
275
        if ( loadIssuesTableDelayTimeoutId ) clearTimeout(loadIssuesTableDelayTimeoutId);
276
        LoadIssuesTable();
277
        barcodefield.focus();
278
        return false;
279
    });
280
739
281
    if ( Cookies.get("issues-table-load-immediately-" + script) == "true" ) {
740
    if ( Cookies.get("issues-table-load-immediately-" + script) == "true" ) {
282
        if ( LoadCheckoutsTableDelay ) {
741
        if ( LoadCheckoutsTableDelay ) {
Lines 292-754 $(document).ready(function() { Link Here
292
        Cookies.set("issues-table-load-immediately-" + script, $(this).is(':checked'), { expires: 365, sameSite: 'Lax'  });
751
        Cookies.set("issues-table-load-immediately-" + script, $(this).is(':checked'), { expires: 365, sameSite: 'Lax'  });
293
    });
752
    });
294
753
295
    function RefreshIssuesTable() {
296
        var table = $('#issues-table').DataTable();
297
        var renewchecked = $('input[name=renew]:checked').map(function(){
298
            return this.value;
299
        }).get();
300
        var checkinchecked = $('input[name=checkin]:checked').map(function(){
301
            return this.value;
302
        }).get();
303
        table.ajax.reload( function() {
304
            $('#RenewChecked, #CheckinChecked').prop('disabled' , true );
305
            if ( renewchecked.length ) {
306
                $('#RenewChecked').prop('disabled' , false );
307
                renewchecked.forEach( function(checked) {
308
                    $('.renew[value="'+checked+'"]').prop('checked' , true );
309
                });
310
            }
311
            if ( checkinchecked.length ) {
312
                $('#CheckinChecked').prop('disabled' , false );
313
                checkinchecked.forEach( function(checked) {
314
                    $('.checkin[value="'+checked+'"]').prop('checked' , true );
315
                });
316
            }
317
        var checkout_count = table.page.info().recordsTotal;
318
        $('.checkout_count').text(checkout_count);
319
        });
320
    }
321
322
    function LoadIssuesTable() {
323
        $('#issues-table-loading-message').hide();
324
        $('#issues-table').show();
325
        $('#issues-table-actions').show();
326
        var msg_loading = __('Loading... you may continue scanning.');
327
        issuesTable = KohaTable("issues-table", {
328
            "oLanguage": {
329
                "sEmptyTable" : msg_loading,
330
                "sProcessing": msg_loading,
331
            },
332
            "bAutoWidth": false,
333
            "dom": '<"table_controls"B>rt',
334
            "aoColumns": [
335
                {
336
                    "mDataProp": function( oObj ) {
337
                        return oObj.sort_order;
338
                    }
339
                },
340
                {
341
                    "mDataProp": function( oObj ) {
342
                        if ( oObj.issued_today ) {
343
                            return "<strong>" + __("Today's checkouts") + "</strong>";
344
                        } else {
345
                            return "<strong>" + __("Previous checkouts") + "</strong>";
346
                        }
347
                    }
348
                },
349
                {
350
                    "mDataProp": "date_due",
351
                    "bVisible": false,
352
                },
353
                {
354
                    "iDataSort": 2, // Sort on hidden unformatted date due column
355
                    "mDataProp": function( oObj ) {
356
                        let date_due_formatted = $datetime(oObj.date_due, { as_due_date: true, no_tz_adjust: true });
357
                        var due = oObj.date_due_overdue
358
                            ? "<span class='overdue'>" + date_due_formatted + "</span>"
359
                            : date_due_formatted;
360
361
                        due = "<span id='date_due_" + oObj.itemnumber + "' class='date_due'>" + due + "</span>";
362
363
                        if ( oObj.lost && oObj.claims_returned ) {
364
                            due += "<span class='lost claims_returned'>" + oObj.lost.escapeHtml() + "</span>";
365
                        } else if ( oObj.lost ) {
366
                            due += "<span class='lost'>" + oObj.lost.escapeHtml() + "</span>";
367
                        }
368
369
                        if ( oObj.damaged ) {
370
                            due += "<span class='dmg'>" + oObj.damaged.escapeHtml() + "</span>";
371
                        }
372
373
                        var patron_note = " <span class='patron_note_" + oObj.itemnumber + "'></span>";
374
                        due +="<br>" + patron_note;
375
376
                        return due;
377
                    }
378
                },
379
                {
380
                    "mDataProp": function ( oObj ) {
381
                        let title = "<span id='title_" + oObj.itemnumber + "' class='strong'><a href='/cgi-bin/koha/catalogue/detail.pl?biblionumber="
382
                              + oObj.biblionumber
383
                              + "'>"
384
                              + (oObj.title ? oObj.title.escapeHtml() : '' );
385
386
                        $.each(oObj.subtitle, function( index, value ) {
387
                                  title += " " + value.escapeHtml();
388
                        });
389
390
                        title += " " + oObj.part_number + " " + oObj.part_name;
391
392
                        if ( oObj.enumchron ) {
393
                            title += " <span class='item_enumeration'>(" + oObj.enumchron.escapeHtml() + ")</span>";
394
                        }
395
396
                        title += "</a></span>";
397
398
                        if ( oObj.author ) {
399
                            title += " " + __("by _AUTHOR_").replace( "_AUTHOR_",  " " + oObj.author.escapeHtml() );
400
                        }
401
402
                        if ( oObj.itemnotes ) {
403
                            var span_class = "text-muted";
404
                            if ( flatpickr.formatDate( new Date(oObj.issuedate), "Y-m-d" ) == ymd ){
405
                                span_class = "circ-hlt";
406
                            }
407
                            title += "<span class='divider-dash'> - </span><span class='" + span_class + " item-note-public'>" + oObj.itemnotes.escapeHtml() + "</span>";
408
                        }
409
410
                        if ( oObj.itemnotes_nonpublic ) {
411
                            var span_class = "text-danger";
412
                            if ( flatpickr.formatDate( new Date(oObj.issuedate), "Y-m-d" ) == ymd ){
413
                                span_class = "circ-hlt";
414
                            }
415
                            title += "<span class='divider-dash'> - </span><span class='" + span_class + " item-note-nonpublic'>" + oObj.itemnotes_nonpublic.escapeHtml() + "</span>";
416
                        }
417
418
                        var onsite_checkout = '';
419
                        if ( oObj.onsite_checkout == 1 ) {
420
                            onsite_checkout += " <span class='onsite_checkout'>(" + __("On-site checkout") + ")</span>";
421
                        }
422
423
                        if ( oObj.recalled == 1 ) {
424
                             title += "<span class='divider-dash'> - </span><span class='circ-hlt item-recalled'>" +  __("This item has been recalled and the due date updated") + ".</span>";
425
                        }
426
427
                        title += " "
428
                              + "<a href='/cgi-bin/koha/catalogue/moredetail.pl?biblionumber="
429
                              + oObj.biblionumber
430
                              + "&itemnumber="
431
                              + oObj.itemnumber
432
                              + "#"
433
                              + oObj.itemnumber
434
                              + "'>"
435
                              + (oObj.barcode ? oObj.barcode.escapeHtml() : "")
436
                              + "</a>"
437
                              + onsite_checkout
438
439
                        return title;
440
                    },
441
                    "sType": "anti-the"
442
                },
443
                {
444
                    "mDataProp": function ( oObj ) {
445
                        return oObj.recordtype_description.escapeHtml();
446
                    }
447
                },
448
                {
449
                    "mDataProp": function ( oObj ) {
450
                        return oObj.itemtype_description.escapeHtml();
451
                    }
452
                },
453
                {
454
                    "mDataProp": function ( oObj ) {
455
                        return ( oObj.collection ? oObj.collection.escapeHtml() : '' );
456
                    }
457
                },
458
                {
459
                    "mDataProp": function ( oObj ) {
460
                        return ( oObj.location ? oObj.location.escapeHtml() : '' );
461
                    }
462
                },
463
                {
464
                    "mDataProp": function ( oObj ) {
465
                        return (oObj.homebranch ? oObj.homebranch.escapeHtml() : '' );
466
                    }
467
                },
468
                {
469
                    "mDataProp": "issuedate",
470
                    "bVisible": false,
471
                },
472
                {
473
                    "iDataSort": 10, // Sort on hidden unformatted issuedate column
474
                    "mDataProp": function( oObj ) {
475
                        return $datetime(oObj.issuedate, { no_tz_adjust: true });
476
                    }
477
                },
478
                {
479
                    "mDataProp": function ( oObj ) {
480
                        return (oObj.branchname ? oObj.branchname.escapeHtml() : '' );
481
                    }
482
                },
483
                {
484
                    "mDataProp": function ( oObj ) {
485
                        return ( oObj.itemcallnumber ? oObj.itemcallnumber.escapeHtml() : '' );
486
                    }
487
                },
488
                {
489
                    "mDataProp": function ( oObj ) {
490
                        return ( oObj.copynumber ? oObj.copynumber.escapeHtml() : '' );
491
                    }
492
                },
493
                {
494
                    "mDataProp": function ( oObj ) {
495
                        if ( ! oObj.charge ) oObj.charge = 0;
496
                        return '<span style="text-align: right; display: block;">' + parseFloat(oObj.charge).format_price() + '<span>';
497
                    },
498
                    "sClass": "nowrap"
499
                },
500
                {
501
                    "mDataProp": function ( oObj ) {
502
                        if ( ! oObj.fine ) oObj.fine = 0;
503
                        return '<span style="text-align: right; display: block;">' + parseFloat(oObj.fine).format_price()   + '<span>';
504
                    },
505
                    "sClass": "nowrap"
506
                },
507
                {
508
                    "mDataProp": function ( oObj ) {
509
                        if ( ! oObj.price ) oObj.price = 0;
510
                        return '<span style="text-align: right; display: block;">' + parseFloat(oObj.price).format_price()  + '<span>';
511
                    },
512
                    "sClass": "nowrap"
513
                },
514
                {
515
                    "bSortable": false,
516
                    "bVisible": AllowCirculate ? true : false,
517
                    "mDataProp": function ( oObj ) {
518
                        var content = "";
519
                        var msg = "";
520
                        var span_style = "";
521
                        var span_class = "";
522
523
                        if ( oObj.can_renew ) {
524
                            // Do nothing
525
                        } else if ( oObj.can_renew_error == "recalled" ) {
526
                            msg += "<span>"
527
                                    + "<a href='/cgi-bin/koha/recalls/request.pl?biblionumber=" + oObj.biblionumber + "'>" + __("Recalled") + "</a>"
528
                                    + "</span>";
529
530
                            span_style = "display: none";
531
                            span_class = "renewals-allowed-recalled";
532
                        } else if ( oObj.can_renew_error == "on_reserve" ) {
533
                            msg += "<span>"
534
                                    +"<a href='/cgi-bin/koha/reserve/request.pl?biblionumber=" + oObj.biblionumber + "'>" + __("On hold") + "</a>"
535
                                    + "</span>";
536
537
                            span_style = "display: none";
538
                            span_class = "renewals-allowed-on_reserve";
539
                        } else if ( oObj.can_renew_error == "too_many" ) {
540
                            msg += "<span class='renewals-disabled'>"
541
                                    + __("Not renewable")
542
                                    + "</span>";
543
544
                            span_style = "display: none";
545
                            span_class = "renewals-allowed";
546
                        } else if ( oObj.can_renew_error == "too_unseen" ) {
547
                            msg += "<span>"
548
                                    + __("Must be renewed at the library")
549
                                    + "</span>";
550
                            span_class = "renewals-allowed";
551
                        } else if ( oObj.can_renew_error == "restriction" ) {
552
                            msg += "<span class='renewals-disabled'>"
553
                                    + __("Not allowed: patron restricted")
554
                                    + "</span>";
555
556
                            span_style = "display: none";
557
                            span_class = "renewals-allowed";
558
                        } else if ( oObj.can_renew_error == "overdue" ) {
559
                            msg += "<span class='renewals-disabled'>"
560
                                    + __("Not allowed: overdue")
561
                                    + "</span>";
562
563
                            span_style = "display: none";
564
                            span_class = "renewals-allowed";
565
                        } else if ( oObj.can_renew_error == "too_soon" ) {
566
                            msg += "<span class='renewals-disabled'>"
567
                                    + __("No renewal before %s").format(oObj.can_renew_date)
568
                                    + "</span>";
569
570
                            span_style = "display: none";
571
                            span_class = "renewals-allowed";
572
                        } else if ( oObj.can_renew_error == "auto_too_late" ) {
573
                            msg += "<span class='renewals-disabled'>"
574
                                    + __("Can no longer be auto-renewed - number of checkout days exceeded")
575
                                    + "</span>";
576
577
                            span_style = "display: none";
578
                            span_class = "renewals-allowed";
579
                        } else if ( oObj.can_renew_error == "auto_too_much_oweing" ) {
580
                            msg += "<span class='renewals-disabled'>"
581
                                    + __("Automatic renewal failed, patron has unpaid fines")
582
                                    + "</span>";
583
584
                            span_style = "display: none";
585
                            span_class = "renewals-allowed";
586
                        } else if ( oObj.can_renew_error == "auto_account_expired" ) {
587
                            msg += "<span class='renewals-disabled'>"
588
                                    + __("Automatic renewal failed, account expired")
589
                                    + "</span>";
590
591
                            span_style = "display: none";
592
                            span_class = "renewals-allowed";
593
                        } else if ( oObj.can_renew_error == "onsite_checkout" ) {
594
                            // Don't display something if it's an onsite checkout
595
                        } else if ( oObj.can_renew_error == "item_denied_renewal" ) {
596
                            content += "<span class='renewals-disabled'>"
597
                                    + __("Renewal denied by syspref")
598
                                    + "</span>";
599
600
                            span_style = "display: none";
601
                            span_class = "renewals-allowed";
602
                        } else {
603
                            msg += "<span class='renewals-disabled'>"
604
                                    + oObj.can_renew_error
605
                                    + "</span>";
606
607
                            span_style = "display: none";
608
                            span_class = "renewals-allowed";
609
                        }
610
611
                        var can_force_renew = ( oObj.onsite_checkout == 0 ) &&
612
                            ( oObj.can_renew_error != "on_reserve" || (oObj.can_renew_error == "on_reserve" && AllowRenewalOnHoldOverride))
613
                            ? true : false;
614
                        var can_renew = ( oObj.renewals_remaining > 0 && ( !oObj.can_renew_error || oObj.can_renew_error == "too_unseen" ));
615
                        content += "<span>";
616
                        if ( can_renew || can_force_renew ) {
617
                            content += "<span style='padding: 0 1em;'>" + oObj.renewals_count + "</span>";
618
                            content += "<span class='" + span_class + "' style='" + span_style + "'>"
619
                                    +  "<input type='checkbox' ";
620
                            if ( oObj.date_due_overdue && can_renew ) {
621
                                content += "checked='checked' ";
622
                            }
623
                            if (oObj.can_renew_error == "on_reserve") {
624
                                content += "data-on-reserve ";
625
                            }
626
                            content += "class='renew' id='renew_" + oObj.itemnumber + "' name='renew' value='" + oObj.itemnumber +"'/>"
627
                                    +  "</span>";
628
                        }
629
                        content += msg;
630
                        if ( can_renew || can_force_renew ) {
631
                            content += "<span class='renewals-info'>(";
632
                            content += __("%s of %s renewals remaining").format(oObj.renewals_remaining, oObj.renewals_allowed);
633
                            if (UnseenRenewals && oObj.unseen_allowed) {
634
                                content += __(" and %s of %s unseen renewals remaining").format(oObj.unseen_remaining, oObj.unseen_allowed);
635
                            }
636
                            content += ")</span>";
637
                        }
638
                        if(oObj.auto_renew){
639
                            content += "<span class='renewals-info'>(";
640
                            content += __("Scheduled for automatic renewal");
641
                            content += ")</span>";
642
                        }
643
644
                        return content;
645
                    }
646
                },
647
                {
648
                    "bSortable": false,
649
                    "bVisible": AllowCirculate ? true : false,
650
                    "mDataProp": function ( oObj ) {
651
                        if ( oObj.can_renew_error == "recalled" ) {
652
                            return "<a href='/cgi-bin/koha/recalls/request.pl?biblionumber=" + oObj.biblionumber + "'>" + __("Recalled") + "</a>";
653
                        } else if ( oObj.can_renew_error == "on_reserve" ) {
654
                            return "<a href='/cgi-bin/koha/reserve/request.pl?biblionumber=" + oObj.biblionumber + "'>" + __("On hold") + "</a>";
655
                        } else if ( oObj.materials ) {
656
                            return "<input type='checkbox' class='confirm' id='confirm_" + oObj.itemnumber + "' name='confirm' value='" + oObj.itemnumber + "' data-materials='" + oObj.materials.escapeHtml() + "'></input>";
657
                        } else {
658
                            return "<input type='checkbox' class='checkin' id='checkin_" + oObj.itemnumber + "' name='checkin' value='" + oObj.itemnumber +"'></input>";
659
                        }
660
                    }
661
                },
662
                {
663
                    "bVisible": ClaimReturnedLostValue ? true : false,
664
                    "bSortable": false,
665
                    "mDataProp": function ( oObj ) {
666
                        let content = "";
667
668
                        if ( oObj.return_claim_id ) {
669
                          content = '<span class="badge">' + oObj.return_claim_created_on_formatted + '</span>';
670
                        } else if ( ClaimReturnedLostValue ) {
671
                          content = '<a class="btn btn-default btn-xs claim-returned-btn" data-itemnumber="' + oObj.itemnumber + '"><i class="fa fa-exclamation-circle"></i> ' + __("Claim returned") + '</a>';
672
                        } else {
673
                          content = '<a class="btn btn-default btn-xs" disabled="disabled" title="ClaimReturnedLostValue is not set, this feature is disabled"><i class="fa fa-exclamation-circle"></i> ' + __("Claim returned") + '</a>';
674
                        }
675
                        return content;
676
                    }
677
                },
678
                {
679
                    "bVisible": exports_enabled == 1 ? true : false,
680
                    "bSortable": false,
681
                    "mDataProp": function ( oObj ) {
682
                        var s = "<input type='checkbox' name='itemnumbers' value='" + oObj.itemnumber + "' style='visibility:hidden;' />";
683
684
                        s += "<input type='checkbox' class='export' id='export_" + oObj.biblionumber + "' name='biblionumbers' value='" + oObj.biblionumber + "' />";
685
                        return s;
686
                    }
687
                }
688
            ],
689
            "fnFooterCallback": function ( nRow, aaData, iStart, iEnd, aiDisplay ) {
690
                var total_charge = 0;
691
                var total_fine  = 0;
692
                var total_price = 0;
693
                for ( var i=0; i < aaData.length; i++ ) {
694
                    total_charge += aaData[i]['charge'] * 1;
695
                    total_fine += aaData[i]['fine'] * 1;
696
                    total_price  += aaData[i]['price'] * 1;
697
                }
698
                $("#totaldue").html(total_charge.format_price() );
699
                $("#totalfine").html(total_fine.format_price() );
700
                $("#totalprice").html(total_price.format_price() );
701
            },
702
            "bPaginate": false,
703
            "bProcessing": true,
704
            "bServerSide": false,
705
            "sAjaxSource": '/cgi-bin/koha/svc/checkouts',
706
            "fnServerData": function ( sSource, aoData, fnCallback ) {
707
                aoData.push( { "name": "borrowernumber", "value": borrowernumber } );
708
709
                $.getJSON( sSource, aoData, function (json) {
710
                    fnCallback(json)
711
                } );
712
            },
713
            "rowGroup":{
714
                "dataSrc": "issued_today",
715
                "startRender": function ( rows, group ) {
716
                    if ( group ) {
717
                        return __("Today's checkouts");
718
                    } else {
719
                        return __("Previous checkouts");
720
                    }
721
                }
722
            },
723
            "fnInitComplete": function(oSettings, json) {
724
                // Build a summary of checkouts grouped by itemtype
725
                var checkoutsByItype = json.aaData.reduce(function (obj, row) {
726
                    obj[row.type_for_stat] = (obj[row.type_for_stat] || 0) + 1;
727
                    return obj;
728
                }, {});
729
                var ul = $('<ul>');
730
                Object.keys(checkoutsByItype).sort().forEach(function (itype) {
731
                    var li = $('<li>')
732
                        .append($('<strong>').html(itype || __("No itemtype")))
733
                        .append(': ' + checkoutsByItype[itype]);
734
                    ul.append(li);
735
                })
736
                $('<details>')
737
                    .addClass('checkouts-by-itemtype')
738
                    .append($('<summary>').html( __("Number of checkouts by item type") ))
739
                    .append(ul)
740
                    .insertBefore(oSettings.nTableWrapper)
741
            },
742
        }, table_settings_issues_table);
743
744
        if ( $("#issues-table").length ) {
745
            $("#issues-table_processing").position({
746
                of: $( "#issues-table" ),
747
                collision: "none"
748
            });
749
        }
750
    }
751
752
    // Don't load relatives' issues table unless it is clicked on
754
    // Don't load relatives' issues table unless it is clicked on
753
    var relativesIssuesTable;
755
    var relativesIssuesTable;
754
    $("#relatives-issues-tab").click( function() {
756
    $("#relatives-issues-tab").click( function() {
755
- 

Return to bug 35506