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

(-)a/admin/columns_settings.yml (-12 / +48 lines)
Lines 231-237 modules: Link Here
231
    moremember:
231
    moremember:
232
      issues-table:
232
      issues-table:
233
        -
233
        -
234
          columnname: sort_order
234
          columnname: group_order
235
          cannot_be_toggled: 1
235
          cannot_be_toggled: 1
236
          cannot_be_modified: 1
236
          cannot_be_modified: 1
237
          is_hidden: 1
237
          is_hidden: 1
Lines 240-250 modules: Link Here
240
          cannot_be_toggled: 1
240
          cannot_be_toggled: 1
241
          cannot_be_modified: 1
241
          cannot_be_modified: 1
242
          is_hidden: 1
242
          is_hidden: 1
243
        -
244
          columnname: due_date_unformatted
245
          cannot_be_toggled: 1
246
          cannot_be_modified: 1
247
          is_hidden: 1
248
        -
243
        -
249
          columnname: due_date
244
          columnname: due_date
250
        -
245
        -
Lines 279-284 modules: Link Here
279
          columnname: export
274
          columnname: export
280
          cannot_be_toggled: 1
275
          cannot_be_toggled: 1
281
          cannot_be_modified: 1
276
          cannot_be_modified: 1
277
      relatives-issues-table:
278
        -
279
          columnname: due_date
280
        -
281
          columnname: title
282
        -
283
          columnname: item_type
284
        -
285
          columnname: location
286
        -
287
          columnname: checkout_on
288
        -
289
          columnname: checkout_from
290
        -
291
          columnname: callno
292
        -
293
          columnname: charge
294
        -
295
          columnname: fine
296
        -
297
          columnname: price
298
        -
299
          columnname: patron
282
300
283
    holdshistory:
301
    holdshistory:
284
      holdshistory-table:
302
      holdshistory-table:
Lines 388-394 modules: Link Here
388
    circulation:
406
    circulation:
389
      issues-table:
407
      issues-table:
390
        -
408
        -
391
          columnname: sort_order
409
          columnname: group_order
392
          cannot_be_toggled: 1
410
          cannot_be_toggled: 1
393
          cannot_be_modified: 1
411
          cannot_be_modified: 1
394
          is_hidden: 1
412
          is_hidden: 1
Lines 397-407 modules: Link Here
397
          cannot_be_toggled: 1
415
          cannot_be_toggled: 1
398
          cannot_be_modified: 1
416
          cannot_be_modified: 1
399
          is_hidden: 1
417
          is_hidden: 1
400
        -
401
          columnname: due_date_unformatted
402
          cannot_be_toggled: 1
403
          cannot_be_modified: 1
404
          is_hidden: 1
405
        -
418
        -
406
          columnname: due_date
419
          columnname: due_date
407
        -
420
        -
Lines 436-441 modules: Link Here
436
          columnname: export
449
          columnname: export
437
          cannot_be_toggled: 1
450
          cannot_be_toggled: 1
438
          cannot_be_modified: 1
451
          cannot_be_modified: 1
452
      relatives-issues-table:
453
        -
454
          columnname: due_date
455
        -
456
          columnname: title
457
        -
458
          columnname: item_type
459
        -
460
          columnname: location
461
        -
462
          columnname: checkout_on
463
        -
464
          columnname: checkout_from
465
        -
466
          columnname: callno
467
        -
468
          columnname: charge
469
        -
470
          columnname: fine
471
        -
472
          columnname: price
473
        -
474
          columnname: patron
439
475
440
    returns:
476
    returns:
441
      checkedintable:
477
      checkedintable:
(-)a/installer/data/mysql/atomicupdate/bug_15219.sql (+2 lines)
Line 0 Link Here
1
INSERT IGNORE INTO systempreferences (variable,value,explanation,options,type)
2
VALUES ('ServerSideCheckoutsTables','0',NULL,'If enabled, use the "server-side processing" feature for checkouts tables. Can improve performance when there is a big number of checkouts to display.','YesNo');
(-)a/installer/data/mysql/sysprefs.sql (+1 lines)
Lines 497-502 INSERT INTO systempreferences ( `variable`, `value`, `options`, `explanation`, ` Link Here
497
('SelfCheckTimeout','120','','Define the number of seconds before the Web-based Self Checkout times out a patron','Integer'),
497
('SelfCheckTimeout','120','','Define the number of seconds before the Web-based Self Checkout times out a patron','Integer'),
498
('SeparateHoldings','0',NULL,'Separate current branch holdings from other holdings','YesNo'),
498
('SeparateHoldings','0',NULL,'Separate current branch holdings from other holdings','YesNo'),
499
('SeparateHoldingsBranch','homebranch','homebranch|holdingbranch','Branch used to separate holdings','Choice'),
499
('SeparateHoldingsBranch','homebranch','homebranch|holdingbranch','Branch used to separate holdings','Choice'),
500
('ServerSideCheckoutsTables','0',NULL,'If enabled, use the "server-side processing" feature for checkouts tables. Can improve performance when there is a big number of checkouts per patron.','YesNo'),
500
('SessionRestrictionByIP','1','Check for change in remote IP address for session security. Disable only when remote IP address changes frequently.','','YesNo'),
501
('SessionRestrictionByIP','1','Check for change in remote IP address for session security. Disable only when remote IP address changes frequently.','','YesNo'),
501
('SessionStorage','mysql','mysql|Pg|tmp','Use database or a temporary file for storing session data','Choice'),
502
('SessionStorage','mysql','mysql|Pg|tmp','Use database or a temporary file for storing session data','Choice'),
502
('ShelfBrowserUsesCcode','1','0','Use the item collection code when finding items for the shelf browser.','YesNo'),
503
('ShelfBrowserUsesCcode','1','0','Use the item collection code when finding items for the shelf browser.','YesNo'),
(-)a/koha-tmpl/intranet-tmpl/lib/jquery/plugins/jquery.dataTables.rowGrouping.js (-5 / +5 lines)
Lines 608-622 Link Here
608
608
609
                      }
609
                      }
610
610
611
            oTable.fnSetColumnVis(properties.iGroupingColumnIndex, !properties.bHideGroupingColumn);
611
            oTable.fnSetColumnVis(properties.iGroupingColumnIndex, !properties.bHideGroupingColumn, false);
612
            if (properties.bCustomColumnOrdering) {
612
            if (properties.bCustomColumnOrdering) {
613
                oTable.fnSetColumnVis(properties.iGroupingOrderByColumnIndex, !properties.bHideGroupingOrderByColumn);
613
                oTable.fnSetColumnVis(properties.iGroupingOrderByColumnIndex, !properties.bHideGroupingOrderByColumn, false);
614
            }
614
            }
615
            if (properties.iGroupingColumnIndex2 != -1) {
615
            if (properties.iGroupingColumnIndex2 != -1) {
616
                oTable.fnSetColumnVis(properties.iGroupingColumnIndex2, !properties.bHideGroupingColumn2);
616
                oTable.fnSetColumnVis(properties.iGroupingColumnIndex2, !properties.bHideGroupingColumn2, false);
617
            }
617
            }
618
            if (properties.bCustomColumnOrdering2) {
618
            if (properties.bCustomColumnOrdering2) {
619
                oTable.fnSetColumnVis(properties.iGroupingOrderByColumnIndex2, !properties.bHideGroupingOrderByColumn2);
619
                oTable.fnSetColumnVis(properties.iGroupingOrderByColumnIndex2, !properties.bHideGroupingOrderByColumn2, false);
620
            }
620
            }
621
            oTable.fnSettings().aoDrawCallback.push({
621
            oTable.fnSettings().aoDrawCallback.push({
622
                "fn": _fnDrawCallBackWithGrouping,
622
                "fn": _fnDrawCallBackWithGrouping,
Lines 687-690 Link Here
687
687
688
        });
688
        });
689
    };
689
    };
690
})(jQuery);
690
})(jQuery);
(-)a/koha-tmpl/intranet-tmpl/prog/en/includes/checkouts-table-footer.inc (-1 / +1 lines)
Lines 1-6 Link Here
1
<tfoot>
1
<tfoot>
2
	<tr>
2
	<tr>
3
        <td colspan="11" style="text-align: right; font-weight:bold;">Totals:</td>
3
        <td colspan="10" style="text-align: right; font-weight:bold;">Totals:</td>
4
        <td id="totaldue" style="text-align: right;">[% totaldue | html %]</td>
4
        <td id="totaldue" style="text-align: right;">[% totaldue | html %]</td>
5
        <td id="totalfine" style="text-align: right;">[% finetotal | html %]</td>
5
        <td id="totalfine" style="text-align: right;">[% finetotal | html %]</td>
6
        <td id="totalprice" style="text-align: right;">[% totalprice | html %]</td>
6
        <td id="totalprice" style="text-align: right;">[% totalprice | html %]</td>
(-)a/koha-tmpl/intranet-tmpl/prog/en/includes/checkouts-table.inc (-1 lines)
Lines 13-19 Link Here
13
                        <th scope="col">&nbsp;</th>
13
                        <th scope="col">&nbsp;</th>
14
                        <th scope="col">&nbsp;</th>
14
                        <th scope="col">&nbsp;</th>
15
                        <th scope="col">Due date</th>
15
                        <th scope="col">Due date</th>
16
                        <th scope="col">Due date</th>
17
                        <th scope="col">Title</th>
16
                        <th scope="col">Title</th>
18
                        <th scope="col">Item type</th>
17
                        <th scope="col">Item type</th>
19
                        <th scope="col">Collection</th>
18
                        <th scope="col">Collection</th>
(-)a/koha-tmpl/intranet-tmpl/prog/en/includes/checkouts.js.inc (+26 lines)
Line 0 Link Here
1
[% USE Asset %]
2
[% USE Koha %]
3
[% USE raw %]
4
5
<script>
6
  [% IF Koha.Preference('ServerSideCheckoutsTables') %]
7
    var ServerSideCheckoutsTables = true;
8
  [% ELSE %]
9
    var ServerSideCheckoutsTables = false;
10
  [% END %]
11
  var AllowCirculate = [% (CAN_user_circulate_circulate_remaining_permissions)? 1 : 0 %];
12
  var AllowRenewalLimitOverride = [% (CAN_user_circulate_override_renewals && Koha.Preference('AllowRenewalLimitOverride'))? 1 : 0 %];
13
14
  var MSG_DT_LOADING_RECORDS = _("Loading... you may continue scanning.");
15
16
  var borrowernumber = "[% borrowernumber | $raw %]";
17
  var relatives_borrowernumbers = new Array();
18
  [% FOREACH b IN relatives_borrowernumbers %]
19
    relatives_borrowernumbers.push("[% b | $raw %]");
20
  [% END %]
21
22
  var columns_settings = [% ColumnsSettings.GetColumns( 'circ', 'circulation', 'issues-table', 'json' ) | $raw %];
23
  var relatives_columns_settings = [% ColumnsSettings.GetColumns( 'circ', 'circulation', 'relatives-issues-table', 'json' ) | $raw %];
24
</script>
25
26
[% Asset.js('js/checkouts.js') | $raw %]
(-)a/koha-tmpl/intranet-tmpl/prog/en/includes/columns_settings.inc (-1 / +1 lines)
Lines 71-77 function KohaTable(id_selector, dt_parameters, columns_settings, add_filters) { Link Here
71
    table.dataTable($.extend(true, {}, dataTablesDefaults, dt_parameters));
71
    table.dataTable($.extend(true, {}, dataTablesDefaults, dt_parameters));
72
72
73
    $(hidden_ids).each(function(index, value) {
73
    $(hidden_ids).each(function(index, value) {
74
        table.fnSetColumnVis( value, false );
74
        table.fnSetColumnVis( value, false, false );
75
    });
75
    });
76
76
77
    if ( add_filters ) {
77
    if ( add_filters ) {
(-)a/koha-tmpl/intranet-tmpl/prog/en/includes/strings.inc (+1 lines)
Lines 46-50 Link Here
46
    var CURRENT = _(" (current) ");
46
    var CURRENT = _(" (current) ");
47
    var MSG_NO_ITEMTYPE = _("No itemtype");
47
    var MSG_NO_ITEMTYPE = _("No itemtype");
48
    var MSG_CHECKOUTS_BY_ITEMTYPE = _("Number of checkouts by item type");
48
    var MSG_CHECKOUTS_BY_ITEMTYPE = _("Number of checkouts by item type");
49
    var GROUP_TODAYS_CHECKOUTS = _("Group today's checkouts");
49
//]]>
50
//]]>
50
</script>
51
</script>
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/circulation.pref (+6 lines)
Lines 52-57 Circulation: Link Here
52
                  asc: earliest to latest
52
                  asc: earliest to latest
53
                  desc: latest to earliest
53
                  desc: latest to earliest
54
            - due date.
54
            - due date.
55
        -
56
            - pref: ServerSideCheckoutsTables
57
              choices:
58
                  yes: Enable
59
                  no: Do not enable
60
            - server-side processing on checkouts tables. It can improve performance when there is a big number of checkouts to display.
55
        -
61
        -
56
            - pref: SpecifyDueDate
62
            - pref: SpecifyDueDate
57
              choices:
63
              choices:
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/circ/circulation.tt (-12 / +1 lines)
Lines 848-854 No patron matched <span class="ex">[% message | html %]</span> Link Here
848
        <table id="relatives-issues-table">
848
        <table id="relatives-issues-table">
849
            <thead>
849
            <thead>
850
                <tr>
850
                <tr>
851
                    <th scope="col">Due date (unformatted, hidden)</th>
852
                    <th scope="col">Due date</th>
851
                    <th scope="col">Due date</th>
853
                    <th scope="col">Title</th>
852
                    <th scope="col">Title</th>
854
                    <th scope="col">Item type</th>
853
                    <th scope="col">Item type</th>
Lines 983-1012 No patron matched <span class="ex">[% message | html %]</span> Link Here
983
    [% INCLUDE 'timepicker.inc' %]
982
    [% INCLUDE 'timepicker.inc' %]
984
    [% Asset.js("lib/jquery/plugins/jquery.dataTables.rowGrouping.js") | $raw %]
983
    [% Asset.js("lib/jquery/plugins/jquery.dataTables.rowGrouping.js") | $raw %]
985
    [% Asset.js("js/pages/circulation.js") | $raw %]
984
    [% Asset.js("js/pages/circulation.js") | $raw %]
986
    [% Asset.js("js/checkouts.js") | $raw %]
985
    [% INCLUDE 'checkouts.js.inc' %]
987
    [% Asset.js("js/holds.js") | $raw %]
986
    [% Asset.js("js/holds.js") | $raw %]
988
    [% Asset.js("js/circ-patron-search-results.js") | $raw %]
987
    [% Asset.js("js/circ-patron-search-results.js") | $raw %]
989
    <script type="text/javascript">
988
    <script type="text/javascript">
990
        /* Set some variable needed in circulation.js */
989
        /* Set some variable needed in circulation.js */
991
        var MSG_DT_LOADING_RECORDS = _("Loading... you may continue scanning.");
992
        var interface = "[% interface | html %]";
990
        var interface = "[% interface | html %]";
993
        var theme = "[% theme | html %]";
991
        var theme = "[% theme | html %]";
994
        var borrowernumber = "[% patron.borrowernumber | html %]";
995
        var branchcode = "[% branch | html %]";
992
        var branchcode = "[% branch | html %]";
996
        var exports_enabled = "[% Koha.Preference('ExportCircHistory') | html %]";
993
        var exports_enabled = "[% Koha.Preference('ExportCircHistory') | html %]";
997
        var AllowRenewalLimitOverride = [% (CAN_user_circulate_override_renewals && Koha.Preference('AllowRenewalLimitOverride') )? 1: 0 | html %];
998
        var AllowCirculate = [% (CAN_user_circulate_circulate_remaining_permissions)? 1 : 0 | html %];
999
        var script = "circulation";
994
        var script = "circulation";
1000
        var relatives_borrowernumbers = new Array();
1001
        [% FOREACH b IN relatives_borrowernumbers %]
1002
            relatives_borrowernumbers.push("[% b | html %]");
1003
        [% END %]
1004
995
1005
        var MSG_EXPORT_SELECT_CHECKOUTS = _("You must select checkout(s) to export");
996
        var MSG_EXPORT_SELECT_CHECKOUTS = _("You must select checkout(s) to export");
1006
        var MSG_CONFIRM_DELETE_MESSAGE = _("Are you sure you want to delete this message? This cannot be undone.");
997
        var MSG_CONFIRM_DELETE_MESSAGE = _("Are you sure you want to delete this message? This cannot be undone.");
1007
998
1008
        columns_settings = [% ColumnsSettings.GetColumns( 'circ', 'circulation', 'issues-table', 'json' ) | $raw %]
1009
1010
        [% IF borrowernumber and patron %]
999
        [% IF borrowernumber and patron %]
1011
            if($.cookie("holdfor") != [% patron.borrowernumber | html %]){
1000
            if($.cookie("holdfor") != [% patron.borrowernumber | html %]){
1012
                $.removeCookie("holdfor", { path: '/' });
1001
                $.removeCookie("holdfor", { path: '/' });
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/members/moremember.tt (-11 / +1 lines)
Lines 687-693 Link Here
687
                                <table id="relatives-issues-table" style="width: 100% !Important;">
687
                                <table id="relatives-issues-table" style="width: 100% !Important;">
688
                                    <thead>
688
                                    <thead>
689
                                        <tr>
689
                                        <tr>
690
                                            <th scope="col">Due date hidden not formatted</th>
691
                                            <th scope="col">Due date</th>
690
                                            <th scope="col">Due date</th>
692
                                            <th scope="col">Title</th>
691
                                            <th scope="col">Title</th>
693
                                            <th scope="col">Item type</th>
692
                                            <th scope="col">Item type</th>
Lines 801-807 Link Here
801
    [% INCLUDE 'timepicker.inc' %]
800
    [% INCLUDE 'timepicker.inc' %]
802
    [% Asset.js("lib/jquery/plugins/jquery.dataTables.rowGrouping.js") | $raw %]
801
    [% Asset.js("lib/jquery/plugins/jquery.dataTables.rowGrouping.js") | $raw %]
803
    [% Asset.js("js/pages/circulation.js") | $raw %]
802
    [% Asset.js("js/pages/circulation.js") | $raw %]
804
    [% Asset.js("js/checkouts.js") | $raw %]
803
    [% INCLUDE 'checkouts.js.inc' %]
805
    [% Asset.js("js/holds.js") | $raw %]
804
    [% Asset.js("js/holds.js") | $raw %]
806
    [% INCLUDE 'str/members-menu.inc' %]
805
    [% INCLUDE 'str/members-menu.inc' %]
807
    [% Asset.js("js/members-menu.js") | $raw %]
806
    [% Asset.js("js/members-menu.js") | $raw %]
Lines 810-831 Link Here
810
        /* Set some variable needed in circulation.js */
809
        /* Set some variable needed in circulation.js */
811
        var interface = "[% interface | html %]";
810
        var interface = "[% interface | html %]";
812
        var theme = "[% theme | html %]";
811
        var theme = "[% theme | html %]";
813
        var borrowernumber = "[% patron.borrowernumber | html %]";
814
        var branchcode = "[% Branches.GetLoggedInBranchcode() | html %]";
812
        var branchcode = "[% Branches.GetLoggedInBranchcode() | html %]";
815
        var exports_enabled = "[% Koha.Preference('ExportCircHistory') | html %]";
813
        var exports_enabled = "[% Koha.Preference('ExportCircHistory') | html %]";
816
        var AllowCirculate = [% (CAN_user_circulate_circulate_remaining_permissions)? 1 : 0 | html %]
817
        var AllowRenewalLimitOverride = [% (CAN_user_circulate_override_renewals && Koha.Preference('AllowRenewalLimitOverride') )? 1: 0 | html %];
818
        var script = "moremember";
814
        var script = "moremember";
819
        var relatives_borrowernumbers = new Array();
820
        [% FOREACH b IN relatives_borrowernumbers %]
821
            relatives_borrowernumbers.push("[% b | html %]");
822
        [% END %]
823
815
824
        var MSG_EXPORT_SELECT_CHECKOUTS = _("You must select checkout(s) to export");
816
        var MSG_EXPORT_SELECT_CHECKOUTS = _("You must select checkout(s) to export");
825
        var MSG_CONFIRM_DELETE_MESSAGE = _("Are you sure you want to delete this message? This cannot be undone.");
817
        var MSG_CONFIRM_DELETE_MESSAGE = _("Are you sure you want to delete this message? This cannot be undone.");
826
818
827
        columns_settings = [% ColumnsSettings.GetColumns( 'members', 'moremember', 'issues-table', 'json' ) | $raw %]
828
829
        $(document).ready(function() {
819
        $(document).ready(function() {
830
            if ( $('#clubs-tab').length ) {
820
            if ( $('#clubs-tab').length ) {
831
                $('#clubs-tab-link').on('click', function() {
821
                $('#clubs-tab-link').on('click', function() {
(-)a/koha-tmpl/intranet-tmpl/prog/js/checkouts.js (-419 / +415 lines)
Lines 1-3 Link Here
1
(function($) {
2
3
var ymd = $.datepicker.formatDate('yy-mm-dd', new Date());
4
5
function enableGrouping(datatable) {
6
    datatable.rowGrouping({
7
        iGroupingColumnIndex: 1,
8
        iGroupingOrderByColumnIndex: 0,
9
        sGroupingColumnSortDirection: "desc"
10
    });
11
}
12
13
function disableGrouping(datatable) {
14
    var oSettings = datatable.fnSettings();
15
    for (f = 0; f < oSettings.aoDrawCallback.length; f++) {
16
        if (oSettings.aoDrawCallback[f].sName == 'fnRowGrouping') {
17
            oSettings.aoDrawCallback.splice(f, 1);
18
            oSettings.aaSortingFixed = null;
19
            datatable.fnDraw();
20
            break;
21
        }
22
    }
23
}
24
25
var mRenders = {
26
    groupOrder: function (oData, sType, oObj) {
27
        if ( oObj.issued_today ) {
28
            return "1";
29
        } else {
30
            return "0";
31
        }
32
    },
33
    groupName: function (oData, sType, oObj) {
34
        if (oObj.issued_today) {
35
            return "<strong>" + TODAYS_CHECKOUTS + "</strong>";
36
        } else {
37
            return "<strong>" + PREVIOUS_CHECKOUTS + "</strong>";
38
        }
39
    },
40
    dateDueFormatted: function (oData, sType, oObj) {
41
        var due = oObj.date_due_formatted;
42
43
        if ( oObj.date_due_overdue ) {
44
            due = "<span class='overdue'>" + due + "</span>";
45
        }
46
47
        due = "<span id='date_due_" + oObj.itemnumber + "' class='date_due'>" + due + "</span>";
48
49
        if ( oObj.lost ) {
50
            due += "<span class='lost'>" + oObj.lost.escapeHtml() + "</span>";
51
        }
52
53
        if ( oObj.damaged ) {
54
            due += "<span class='dmg'>" + oObj.damaged.escapeHtml() + "</span>";
55
        }
56
57
        return due;
58
    },
59
    title: function (oData, sType, oObj) {
60
        var title = "<span id='title_" + oObj.itemnumber + "' class='strong'><a href='/cgi-bin/koha/catalogue/detail.pl?biblionumber="
61
              + oObj.biblionumber
62
              + "'>"
63
              + oObj.title.escapeHtml();
64
65
        $.each(oObj.subtitle, function( index, value ) {
66
                  title += " " + value.subfield.escapeHtml();
67
        });
68
69
        if ( oObj.enumchron ) {
70
            title += " (" + oObj.enumchron.escapeHtml() + ")";
71
        }
72
73
        title += "</a></span>";
74
75
        if ( oObj.author ) {
76
            title += " " + BY.replace( "_AUTHOR_",  " " + oObj.author.escapeHtml() );
77
        }
78
79
        if ( oObj.itemnotes ) {
80
            var span_class = "text-muted";
81
            if ( $.datepicker.formatDate('yy-mm-dd', new Date(oObj.issuedate) ) == ymd ) {
82
                span_class = "circ-hlt";
83
            }
84
            title += " - <span class='" + span_class + " item-note-public'>" + oObj.itemnotes.escapeHtml() + "</span>";
85
        }
86
87
        if ( oObj.itemnotes_nonpublic ) {
88
            var span_class = "text-danger";
89
            if ( $.datepicker.formatDate('yy-mm-dd', new Date(oObj.issuedate) ) == ymd ) {
90
                span_class = "circ-hlt";
91
            }
92
            title += " - <span class='" + span_class + " item-note-nonpublic'>" + oObj.itemnotes_nonpublic.escapeHtml() + "</span>";
93
        }
94
95
        var onsite_checkout = '';
96
        if ( oObj.onsite_checkout == 1 ) {
97
            onsite_checkout += " <span class='onsite_checkout'>(" + INHOUSE_USE + ")</span>";
98
        }
99
100
        title += " "
101
              + "<a href='/cgi-bin/koha/catalogue/moredetail.pl?biblionumber="
102
              + oObj.biblionumber
103
              + "&itemnumber="
104
              + oObj.itemnumber
105
              + "#"
106
              + oObj.itemnumber
107
              + "'>"
108
              + oObj.barcode.escapeHtml()
109
              + "</a>"
110
              + onsite_checkout
111
112
        return title;
113
    },
114
    itemtype: function (oData, sType, oObj) {
115
        return oObj.itemtype_description.escapeHtml();
116
    },
117
    collection: function (oData, sType, oObj) {
118
        return oObj.collection.escapeHtml();
119
    },
120
    location: function (oData, sType, oObj) {
121
        return oObj.location.escapeHtml();
122
    },
123
    homebranch: function (oData, sType, oObj) {
124
        return oObj.homebranch.escapeHtml();
125
    },
126
    issuedate: function (oData, sType, oObj) {
127
        return oObj.issuedate_formatted;
128
    },
129
    branch: function (oData, sType, oObj) {
130
        return oObj.branchname.escapeHtml();
131
    },
132
    itemcallnumber: function (oData, sType, oObj) {
133
        return oObj.itemcallnumber.escapeHtml();
134
    },
135
    charge: function (oData, sType, oObj) {
136
        if (!oObj.charge) oObj.charge = 0;
137
        return '<span style="text-align: right; display: block;">' + parseFloat(oObj.charge).toFixed(2) + '<span>';
138
    },
139
    fine: function (oData, sType, oObj) {
140
        if (!oObj.fine) oObj.fine = 0;
141
        return '<span style="text-align: right; display: block;">' + parseFloat(oObj.fine).toFixed(2)  + '<span>';
142
    },
143
    price: function (oData, sType, oObj) {
144
        if (!oObj.price) oObj.price = 0;
145
        return parseFloat(oObj.price).toFixed(2);
146
    },
147
    renew: function (oData, sType, oObj) {
148
        var content = "";
149
        var span_style = "";
150
        var span_class = "";
151
152
        content += "<span>";
153
        content += "<span style='padding: 0 1em;'>" + oObj.renewals_count + "</span>";
154
155
        if ( oObj.can_renew ) {
156
            // Do nothing
157
        } else if ( oObj.can_renew_error == "on_reserve" ) {
158
            content += "<span class='renewals-disabled-no-override'>"
159
                    + "<a href='/cgi-bin/koha/reserve/request.pl?biblionumber=" + oObj.biblionumber + "'>" + ON_HOLD + "</a>"
160
                    + "</span>";
161
162
            span_style = "display: none";
163
            span_class = "renewals-allowed";
164
        } else if ( oObj.can_renew_error == "too_many" ) {
165
            content += "<span class='renewals-disabled'>"
166
                    + NOT_RENEWABLE
167
                    + "</span>";
168
169
            span_style = "display: none";
170
            span_class = "renewals-allowed";
171
        } else if ( oObj.can_renew_error == "restriction" ) {
172
            content += "<span class='renewals-disabled'>"
173
                    + NOT_RENEWABLE_RESTRICTION
174
                    + "</span>";
175
176
            span_style = "display: none";
177
            span_class = "renewals-allowed";
178
        } else if ( oObj.can_renew_error == "overdue" ) {
179
            content += "<span class='renewals-disabled'>"
180
                    + NOT_RENEWABLE_OVERDUE
181
                    + "</span>";
182
183
            span_style = "display: none";
184
            span_class = "renewals-allowed";
185
        } else if ( oObj.can_renew_error == "too_soon" ) {
186
            content += "<span class='renewals-disabled'>"
187
                    + NOT_RENEWABLE_TOO_SOON.format( oObj.can_renew_date )
188
                    + "</span>";
189
190
            span_style = "display: none";
191
            span_class = "renewals-allowed";
192
        } else if ( oObj.can_renew_error == "auto_too_soon" ) {
193
            content += "<span class='renewals-disabled'>"
194
                    + NOT_RENEWABLE_AUTO_TOO_SOON
195
                    + "</span>";
196
197
            span_style = "display: none";
198
            span_class = "renewals-allowed";
199
        } else if ( oObj.can_renew_error == "auto_too_late" ) {
200
            content += "<span class='renewals-disabled'>"
201
                    + NOT_RENEWABLE_AUTO_TOO_LATE
202
                    + "</span>";
203
204
            span_style = "display: none";
205
            span_class = "renewals-allowed";
206
        } else if ( oObj.can_renew_error == "auto_too_much_oweing" ) {
207
            content += "<span class='renewals-disabled'>"
208
                    + NOT_RENEWABLE_AUTO_TOO_MUCH_OWEING
209
                    + "</span>";
210
211
            span_style = "display: none";
212
            span_class = "renewals-allowed";
213
        } else if ( oObj.can_renew_error == "auto_account_expired" ) {
214
            content += "<span class='renewals-disabled'>"
215
                    + NOT_RENEWABLE_AUTO_ACCOUNT_EXPIRED
216
                    + "</span>";
217
218
            span_style = "display: none";
219
            span_class = "renewals-allowed";
220
        } else if ( oObj.can_renew_error == "auto_renew" ) {
221
            content += "<span class='renewals-disabled'>"
222
                    + NOT_RENEWABLE_AUTO_RENEW
223
                    + "</span>";
224
225
            span_style = "display: none";
226
            span_class = "renewals-allowed";
227
        } else if ( oObj.can_renew_error == "onsite_checkout" ) {
228
            // Don't display something if it's an onsite checkout
229
        } else {
230
            content += "<span class='renewals-disabled'>"
231
                    + oObj.can_renew_error
232
                    + "</span>";
233
234
            span_style = "display: none";
235
            span_class = "renewals-allowed";
236
        }
237
238
        var can_force_renew = ( oObj.onsite_checkout == 0 ) && ( oObj.can_renew_error != "on_reserve" );
239
        var can_renew = ( oObj.renewals_remaining > 0  && !oObj.can_renew_error );
240
        if ( can_renew || can_force_renew ) {
241
            content += "<span class='" + span_class + "' style='" + span_style + "'>"
242
                    +  "<input type='checkbox' ";
243
            if ( oObj.date_due_overdue && can_renew ) {
244
                content += "checked='checked' ";
245
            }
246
            content += "class='renew' id='renew_" + oObj.itemnumber + "' name='renew' value='" + oObj.itemnumber +"'/>"
247
                    +  "</span>";
248
249
            content += "<span class='renewals'>("
250
                    + RENEWALS_REMAINING.format( oObj.renewals_remaining, oObj.renewals_allowed )
251
                    + ")</span>";
252
        }
253
254
        content += "</span>";
255
256
        return content;
257
    },
258
    checkin: function (oData, sType, oObj) {
259
        if (oObj.can_renew_error == "on_reserve") {
260
            return "<a href='/cgi-bin/koha/reserve/request.pl?biblionumber=" + oObj.biblionumber + "'>" + ON_HOLD + "</a>";
261
        } else {
262
            return "<input type='checkbox' class='checkin' id='checkin_" + oObj.itemnumber + "' name='checkin' value='" + oObj.itemnumber +"'></input>";
263
        }
264
    },
265
    export: function (oData, sType, oObj) {
266
        var s = "<input type='checkbox' name='itemnumbers' value='" + oObj.itemnumber + "' style='visibility:hidden;' />";
267
268
        s += "<input type='checkbox' class='export' id='export_" + oObj.biblionumber + "' name='biblionumbers' value='" + oObj.biblionumber + "' />";
269
        return s;
270
    },
271
    patron: function (oData, sType, oObj) {
272
        return "<a href='/cgi-bin/koha/members/moremember.pl?borrowernumber=" + oObj.borrowernumber + "'>"
273
             + oObj.borrower.firstname.escapeHtml()
274
             + " "
275
             + oObj.borrower.surname.escapeHtml()
276
             + " (" + oObj.borrower.cardnumber.escapeHtml() + ")</a>"
277
    }
278
};
279
1
$(document).ready(function() {
280
$(document).ready(function() {
2
    $.ajaxSetup ({ cache: false });
281
    $.ajaxSetup ({ cache: false });
3
282
Lines 152-159 $(document).ready(function() { Link Here
152
        return false;
431
        return false;
153
    });
432
    });
154
433
155
    var ymd = $.datepicker.formatDate('yy-mm-dd', new Date());
156
157
    $('#issues-table').hide();
434
    $('#issues-table').hide();
158
    $('#issues-table-actions').hide();
435
    $('#issues-table-actions').hide();
159
    $('#issues-table-load-immediately').change(function(){
436
    $('#issues-table-load-immediately').change(function(){
Lines 187-202 $(document).ready(function() { Link Here
187
                "sProcessing": MSG_DT_LOADING_RECORDS,
464
                "sProcessing": MSG_DT_LOADING_RECORDS,
188
            },
465
            },
189
            "bAutoWidth": false,
466
            "bAutoWidth": false,
190
            "dom": 'B<"clearfix">rt',
467
            "bProcessing": true,
468
            "bServerSide": ServerSideCheckoutsTables,
469
            "sAjaxSource": "/cgi-bin/koha/svc/checkouts",
470
            "fnServerParams": function (aoData) {
471
                aoData.push({ "name": "borrowernumber", "value": borrowernumber });
472
            },
473
            "fnInitComplete": function(oSettings, json) {
474
                // Build a summary of checkouts grouped by itemtype
475
                var checkoutsByItype = json.aaData.reduce(function (obj, row) {
476
                    obj[row.itemtype_description] = (obj[row.itemtype_description] || 0) + 1;
477
                    return obj;
478
                }, {});
479
                var ul = $('<ul>');
480
                Object.keys(checkoutsByItype).sort().forEach(function (itype) {
481
                    var li = $('<li>')
482
                        .append($('<strong>').html(itype || MSG_NO_ITEMTYPE))
483
                        .append(': ' + checkoutsByItype[itype]);
484
                    ul.append(li);
485
                })
486
                $('<details>')
487
                    .addClass('checkouts-by-itemtype')
488
                    .append($('<summary>').html(MSG_CHECKOUTS_BY_ITEMTYPE))
489
                    .append(ul)
490
                    .insertBefore(oSettings.nTableWrapper)
491
            },
492
            "bPaginate": true,
493
            "sPaginationType": "four_button",
494
            "dom": 'B<"clearfix"><"top pager"ilp>rt',
495
            "aaSorting": [],
191
            "aoColumns": [
496
            "aoColumns": [
192
                {
497
                {
193
                    "mDataProp": function( oObj ) {
498
                    "mData": "issued_today",
194
                        return oObj.sort_order;
499
                    "mRender": mRenders.groupOrder
195
                    }
196
                },
500
                },
197
                {
501
                {
198
                    "mDataProp": function( oObj ) {
502
                    "mData": function (oObj) {
199
                        if ( oObj.issued_today ) {
503
                        if (oObj.issued_today) {
200
                            return "<strong>" + TODAYS_CHECKOUTS + "</strong>";
504
                            return "<strong>" + TODAYS_CHECKOUTS + "</strong>";
201
                        } else {
505
                        } else {
202
                            return "<strong>" + PREVIOUS_CHECKOUTS + "</strong>";
506
                            return "<strong>" + PREVIOUS_CHECKOUTS + "</strong>";
Lines 204-479 $(document).ready(function() { Link Here
204
                    }
508
                    }
205
                },
509
                },
206
                {
510
                {
207
                    "mDataProp": "date_due",
511
                    "mData": "date_due",
208
                    "bVisible": false,
512
                    "mRender": mRenders.dateDueFormatted
209
                },
513
                },
210
                {
514
                {
211
                    "iDataSort": 2, // Sort on hidden unformatted date due column
515
                    "mData": "title",
212
                    "mDataProp": function( oObj ) {
516
                    "mRender": mRenders.title
213
                        var due = oObj.date_due_formatted;
214
215
                        if ( oObj.date_due_overdue ) {
216
                            due = "<span class='overdue'>" + due + "</span>";
217
                        }
218
219
                        due = "<span id='date_due_" + oObj.itemnumber + "' class='date_due'>" + due + "</span>";
220
221
                        if ( oObj.lost ) {
222
                            due += "<span class='lost'>" + oObj.lost.escapeHtml() + "</span>";
223
                        }
224
225
                        if ( oObj.damaged ) {
226
                            due += "<span class='dmg'>" + oObj.damaged.escapeHtml() + "</span>";
227
                        }
228
229
                        var patron_note = " <span class='patron_note_" + oObj.itemnumber + "'></span>";
230
                        due +="<br>" + patron_note;
231
232
                        return due;
233
                    }
234
                },
517
                },
235
                {
518
                {
236
                    "mDataProp": function ( oObj ) {
519
                    "mData": "itemtype",
237
                        title = "<span id='title_" + oObj.itemnumber + "' class='strong'><a href='/cgi-bin/koha/catalogue/detail.pl?biblionumber="
520
                    "mRender": mRenders.itemtype
238
                              + oObj.biblionumber
239
                              + "'>"
240
                              + oObj.title.escapeHtml();
241
242
                        $.each(oObj.subtitle, function( index, value ) {
243
                                  title += " " + value.subfield.escapeHtml();
244
                        });
245
246
                        if ( oObj.enumchron ) {
247
                            title += " (" + oObj.enumchron.escapeHtml() + ")";
248
                        }
249
250
                        title += "</a></span>";
251
252
                        if ( oObj.author ) {
253
                            title += " " + BY.replace( "_AUTHOR_",  " " + oObj.author.escapeHtml() );
254
                        }
255
256
                        if ( oObj.itemnotes ) {
257
                            var span_class = "text-muted";
258
                            if ( $.datepicker.formatDate('yy-mm-dd', new Date(oObj.issuedate) ) == ymd ) {
259
                                span_class = "circ-hlt";
260
                            }
261
                            title += " - <span class='" + span_class + " item-note-public'>" + oObj.itemnotes.escapeHtml() + "</span>";
262
                        }
263
264
                        if ( oObj.itemnotes_nonpublic ) {
265
                            var span_class = "text-danger";
266
                            if ( $.datepicker.formatDate('yy-mm-dd', new Date(oObj.issuedate) ) == ymd ) {
267
                                span_class = "circ-hlt";
268
                            }
269
                            title += " - <span class='" + span_class + " item-note-nonpublic'>" + oObj.itemnotes_nonpublic.escapeHtml() + "</span>";
270
                        }
271
272
                        var onsite_checkout = '';
273
                        if ( oObj.onsite_checkout == 1 ) {
274
                            onsite_checkout += " <span class='onsite_checkout'>(" + INHOUSE_USE + ")</span>";
275
                        }
276
277
                        title += " "
278
                              + "<a href='/cgi-bin/koha/catalogue/moredetail.pl?biblionumber="
279
                              + oObj.biblionumber
280
                              + "&itemnumber="
281
                              + oObj.itemnumber
282
                              + "#"
283
                              + oObj.itemnumber
284
                              + "'>"
285
                              + oObj.barcode.escapeHtml()
286
                              + "</a>"
287
                              + onsite_checkout
288
289
                        return title;
290
                    },
291
                    "sType": "anti-the"
292
                },
521
                },
293
                {
522
                {
294
                    "mDataProp": function ( oObj ) {
523
                    "mData": "ccode",
295
                        return oObj.itemtype_description.escapeHtml();
524
                    "mRender": mRenders.collection
296
                    }
297
                },
525
                },
298
                {
526
                {
299
                    "mDataProp": function ( oObj ) {
527
                    "mData": "location",
300
                        return oObj.collection.escapeHtml();
528
                    "mRender": mRenders.location
301
                    }
302
                },
529
                },
303
                {
530
                {
304
                    "mDataProp": function ( oObj ) {
531
                    "mData": "homebranch",
305
                        return oObj.location.escapeHtml();
532
                    "mRender": mRenders.homebranch
306
                    }
307
                },
533
                },
308
                {
534
                {
309
                    "mDataProp": function ( oObj ) {
535
                    "mData": "issuedate",
310
                        return oObj.homebranch.escapeHtml();
536
                    "mRender": mRenders.issuedate
311
                    }
312
                },
537
                },
313
                { "mDataProp": "issuedate_formatted" },
314
                {
538
                {
315
                    "mDataProp": function ( oObj ) {
539
                    "mData": "branchcode",
316
                        return oObj.branchname.escapeHtml();
540
                    "mRender": mRenders.branch
317
                    }
318
                },
541
                },
319
                {
542
                {
320
                    "mDataProp": function ( oObj ) {
543
                    "mData": "itemcallnumber",
321
                        return oObj.itemcallnumber.escapeHtml();
544
                    "mRender": mRender.itemcallnumber
322
                    }
323
                },
545
                },
324
                {
546
                {
325
                    "mDataProp": function ( oObj ) {
547
                    "mData": "charge",
326
                        if ( ! oObj.charge ) oObj.charge = 0;
548
                    "mRender": mRenders.charge,
327
                        return '<span style="text-align: right; display: block;">' + parseFloat(oObj.charge).toFixed(2) + '<span>';
549
                    "bSortable": ServerSideCheckoutsTables ? false : true
328
                    }
329
                },
550
                },
330
                {
551
                {
331
                    "mDataProp": function ( oObj ) {
552
                    "mData": "fine",
332
                        if ( ! oObj.fine ) oObj.fine = 0;
553
                    "mRender": mRenders.fine,
333
                        return '<span style="text-align: right; display: block;">' + parseFloat(oObj.fine).toFixed(2)  + '<span>';
554
                    "bSortable": ServerSideCheckoutsTables ? false : true
334
                    }
335
                },
555
                },
336
                {
556
                {
337
                    "mDataProp": function ( oObj ) {
557
                    "mData": "replacementprice",
338
                        if ( ! oObj.price ) oObj.price = 0;
558
                    "mRender": mRenders.price,
339
                        return '<span style="text-align: right; display: block;">' + parseFloat(oObj.price).toFixed(2) + '<span>';
559
                    "bSortable": ServerSideCheckoutsTables ? false : true
340
                    }
341
                },
560
                },
342
                {
561
                {
343
                    "bSortable": false,
344
                    "bVisible": AllowCirculate ? true : false,
562
                    "bVisible": AllowCirculate ? true : false,
345
                    "mDataProp": function ( oObj ) {
563
                    "mRender": mRenders.renew,
346
                        var content = "";
564
                    "bSortable": false
347
                        var span_style = "";
348
                        var span_class = "";
349
350
                        content += "<span>";
351
                        content += "<span style='padding: 0 1em;'>" + oObj.renewals_count + "</span>";
352
353
                        if ( oObj.can_renew ) {
354
                            // Do nothing
355
                        } else if ( oObj.can_renew_error == "on_reserve" ) {
356
                            content += "<span class='renewals-disabled-no-override'>"
357
                                    + "<a href='/cgi-bin/koha/reserve/request.pl?biblionumber=" + oObj.biblionumber + "'>" + ON_HOLD + "</a>"
358
                                    + "</span>";
359
360
                            span_style = "display: none";
361
                            span_class = "renewals-allowed";
362
                        } else if ( oObj.can_renew_error == "too_many" ) {
363
                            content += "<span class='renewals-disabled'>"
364
                                    + NOT_RENEWABLE
365
                                    + "</span>";
366
367
                            span_style = "display: none";
368
                            span_class = "renewals-allowed";
369
                        } else if ( oObj.can_renew_error == "restriction" ) {
370
                            content += "<span class='renewals-disabled'>"
371
                                    + NOT_RENEWABLE_RESTRICTION
372
                                    + "</span>";
373
374
                            span_style = "display: none";
375
                            span_class = "renewals-allowed";
376
                        } else if ( oObj.can_renew_error == "overdue" ) {
377
                            content += "<span class='renewals-disabled'>"
378
                                    + NOT_RENEWABLE_OVERDUE
379
                                    + "</span>";
380
381
                            span_style = "display: none";
382
                            span_class = "renewals-allowed";
383
                        } else if ( oObj.can_renew_error == "too_soon" ) {
384
                            content += "<span class='renewals-disabled'>"
385
                                    + NOT_RENEWABLE_TOO_SOON.format( oObj.can_renew_date )
386
                                    + "</span>";
387
388
                            span_style = "display: none";
389
                            span_class = "renewals-allowed";
390
                        } else if ( oObj.can_renew_error == "auto_too_soon" ) {
391
                            content += "<span class='renewals-disabled'>"
392
                                    + NOT_RENEWABLE_AUTO_TOO_SOON
393
                                    + "</span>";
394
395
                            span_style = "display: none";
396
                            span_class = "renewals-allowed";
397
                        } else if ( oObj.can_renew_error == "auto_too_late" ) {
398
                            content += "<span class='renewals-disabled'>"
399
                                    + NOT_RENEWABLE_AUTO_TOO_LATE
400
                                    + "</span>";
401
402
                            span_style = "display: none";
403
                            span_class = "renewals-allowed";
404
                        } else if ( oObj.can_renew_error == "auto_too_much_oweing" ) {
405
                            content += "<span class='renewals-disabled'>"
406
                                    + NOT_RENEWABLE_AUTO_TOO_MUCH_OWEING
407
                                    + "</span>";
408
409
                            span_style = "display: none";
410
                            span_class = "renewals-allowed";
411
                        } else if ( oObj.can_renew_error == "auto_account_expired" ) {
412
                            content += "<span class='renewals-disabled'>"
413
                                    + NOT_RENEWABLE_AUTO_ACCOUNT_EXPIRED
414
                                    + "</span>";
415
416
                            span_style = "display: none";
417
                            span_class = "renewals-allowed";
418
                        } else if ( oObj.can_renew_error == "auto_renew" ) {
419
                            content += "<span class='renewals-disabled'>"
420
                                    + NOT_RENEWABLE_AUTO_RENEW
421
                                    + "</span>";
422
423
                            span_style = "display: none";
424
                            span_class = "renewals-allowed";
425
                        } else if ( oObj.can_renew_error == "onsite_checkout" ) {
426
                            // Don't display something if it's an onsite checkout
427
                        } else {
428
                            content += "<span class='renewals-disabled'>"
429
                                    + oObj.can_renew_error
430
                                    + "</span>";
431
432
                            span_style = "display: none";
433
                            span_class = "renewals-allowed";
434
                        }
435
436
                        var can_force_renew = ( oObj.onsite_checkout == 0 ) && ( oObj.can_renew_error != "on_reserve" );
437
                        var can_renew = ( oObj.renewals_remaining > 0  && !oObj.can_renew_error );
438
                        if ( can_renew || can_force_renew ) {
439
                            content += "<span class='" + span_class + "' style='" + span_style + "'>"
440
                                    +  "<input type='checkbox' ";
441
                            if ( oObj.date_due_overdue && can_renew ) {
442
                                content += "checked='checked' ";
443
                            }
444
                            content += "class='renew' id='renew_" + oObj.itemnumber + "' name='renew' value='" + oObj.itemnumber +"'/>"
445
                                    +  "</span>";
446
447
                            content += "<span class='renewals'>("
448
                                    + RENEWALS_REMAINING.format( oObj.renewals_remaining, oObj.renewals_allowed )
449
                                    + ")</span>";
450
                        }
451
452
                        content += "</span>";
453
454
                        return content;
455
                    }
456
                },
565
                },
457
                {
566
                {
458
                    "bSortable": false,
459
                    "bVisible": AllowCirculate ? true : false,
567
                    "bVisible": AllowCirculate ? true : false,
460
                    "mDataProp": function ( oObj ) {
568
                    "mRender": mRenders.checkin,
461
                        if ( oObj.can_renew_error == "on_reserve" ) {
569
                    "bSortable": false
462
                            return "<a href='/cgi-bin/koha/reserve/request.pl?biblionumber=" + oObj.biblionumber + "'>" + ON_HOLD + "</a>";
463
                        } else {
464
                            return "<input type='checkbox' class='checkin' id='checkin_" + oObj.itemnumber + "' name='checkin' value='" + oObj.itemnumber +"'></input>";
465
                        }
466
                    }
467
                },
570
                },
468
                {
571
                {
469
                    "bVisible": exports_enabled == 1 ? true : false,
572
                    "bVisible": exports_enabled == 1 ? true : false,
470
                    "bSortable": false,
573
                    "bSortable": false,
471
                    "mDataProp": function ( oObj ) {
574
                    "mRender": mRenders.export
472
                        var s = "<input type='checkbox' name='itemnumbers' value='" + oObj.itemnumber + "' style='visibility:hidden;' />";
473
474
                        s += "<input type='checkbox' class='export' id='export_" + oObj.biblionumber + "' name='biblionumbers' value='" + oObj.biblionumber + "' />";
475
                        return s;
476
                    }
477
                }
575
                }
478
            ],
576
            ],
479
            "fnFooterCallback": function ( nRow, aaData, iStart, iEnd, aiDisplay ) {
577
            "fnFooterCallback": function ( nRow, aaData, iStart, iEnd, aiDisplay ) {
Lines 488-544 $(document).ready(function() { Link Here
488
                $("#totaldue").html(total_charge.toFixed(2));
586
                $("#totaldue").html(total_charge.toFixed(2));
489
                $("#totalfine").html(total_fine.toFixed(2));
587
                $("#totalfine").html(total_fine.toFixed(2));
490
                $("#totalprice").html(total_price.toFixed(2));
588
                $("#totalprice").html(total_price.toFixed(2));
491
            },
492
            "bPaginate": false,
493
            "bProcessing": true,
494
            "bServerSide": false,
495
            "sAjaxSource": '/cgi-bin/koha/svc/checkouts',
496
            "fnServerData": function ( sSource, aoData, fnCallback ) {
497
                aoData.push( { "name": "borrowernumber", "value": borrowernumber } );
498
499
                $.getJSON( sSource, aoData, function (json) {
500
                    fnCallback(json)
501
                } );
502
            },
503
            "fnInitComplete": function(oSettings, json) {
504
                // Disable rowGrouping plugin after first use
505
                // so any sorting on the table doesn't use it
506
                var oSettings = issuesTable.fnSettings();
507
508
                for (f = 0; f < oSettings.aoDrawCallback.length; f++) {
509
                    if (oSettings.aoDrawCallback[f].sName == 'fnRowGrouping') {
510
                        oSettings.aoDrawCallback.splice(f, 1);
511
                        break;
512
                    }
513
                }
514
515
                oSettings.aaSortingFixed = null;
516
517
                // Build a summary of checkouts grouped by itemtype
518
                var checkoutsByItype = json.aaData.reduce(function (obj, row) {
519
                    obj[row.itemtype_description] = (obj[row.itemtype_description] || 0) + 1;
520
                    return obj;
521
                }, {});
522
                var ul = $('<ul>');
523
                Object.keys(checkoutsByItype).sort().forEach(function (itype) {
524
                    var li = $('<li>')
525
                        .append($('<strong>').html(itype || MSG_NO_ITEMTYPE))
526
                        .append(': ' + checkoutsByItype[itype]);
527
                    ul.append(li);
528
                })
529
                $('<details>')
530
                    .addClass('checkouts-by-itemtype')
531
                    .append($('<summary>').html(MSG_CHECKOUTS_BY_ITEMTYPE))
532
                    .append(ul)
533
                    .insertBefore(oSettings.nTableWrapper)
534
            },
535
        }, columns_settings).rowGrouping(
536
            {
537
                iGroupingColumnIndex: 1,
538
                iGroupingOrderByColumnIndex: 0,
539
                sGroupingColumnSortDirection: "asc"
540
            }
589
            }
541
        );
590
        }, columns_settings);
591
592
        enableGrouping(issuesTable);
593
594
        var groupingSwitch = $('<input type="checkbox">')
595
          .attr('id', 'issues-table-row-grouping-switch')
596
          .attr('checked', 'checked')
597
          .css('vertical-align', 'middle')
598
          .change(function() {
599
              if ($(this).is(':checked')) {
600
                  enableGrouping(issuesTable);
601
              } else {
602
                  disableGrouping(issuesTable);
603
              }
604
          });
605
        $('<div></div>')
606
          .css('float', 'left')
607
          .css('padding', '0.3em 0.5em')
608
          .css('line-height', '1.9em')
609
          .append(groupingSwitch)
610
          .append('&nbsp;')
611
          .append('<label for="issues-table-row-grouping-switch">' + GROUP_TODAYS_CHECKOUTS + '</label>')
612
          .appendTo('#issues-table_wrapper .top.pager');
542
613
543
        if ( $("#issues-table").length ) {
614
        if ( $("#issues-table").length ) {
544
            $("#issues-table_processing").position({
615
            $("#issues-table_processing").position({
Lines 552-704 $(document).ready(function() { Link Here
552
    var relativesIssuesTable;
623
    var relativesIssuesTable;
553
    $("#relatives-issues-tab").click( function() {
624
    $("#relatives-issues-tab").click( function() {
554
        if ( ! relativesIssuesTable ) {
625
        if ( ! relativesIssuesTable ) {
555
            relativesIssuesTable = $("#relatives-issues-table").dataTable({
626
            relativesIssuesTable = KohaTable("#relatives-issues-table", {
556
                "bAutoWidth": false,
627
                "bAutoWidth": false,
557
                "sDom": "rt",
628
                "sDom": 'C<"top pager"ilp>rt',
558
                "aaSorting": [],
629
                "aaSorting": [[4, "desc"]],
630
                "bProcessing": true,
631
                "bServerSide": ServerSideCheckoutsTables,
632
                "sAjaxSource": "/cgi-bin/koha/svc/checkouts",
633
                "fnServerParams": function (aoData) {
634
                    for (i in relatives_borrowernumbers) {
635
                        var borrowernumber = relatives_borrowernumbers[i];
636
                        aoData.push({ "name": "borrowernumber", "value": borrowernumber });
637
                    }
638
                },
639
                "bPaginate": true,
640
                "sPaginationType": "four_button",
559
                "aoColumns": [
641
                "aoColumns": [
560
                    {
642
                    {
561
                        "mDataProp": "date_due",
643
                        "mData": "date_due",
562
                        "bVisible": false,
644
                        "mRender": mRenders.dateDueFormatted
563
                    },
645
                    },
564
                    {
646
                    {
565
                        "iDataSort": 1, // Sort on hidden unformatted date due column
647
                        "mData": "title",
566
                        "mDataProp": function( oObj ) {
648
                        "mRender": mRenders.title,
567
                            var today = new Date();
568
                            var due = new Date( oObj.date_due );
569
                            if ( today > due ) {
570
                                return "<span class='overdue'>" + oObj.date_due_formatted + "</span>";
571
                            } else {
572
                                return oObj.date_due_formatted;
573
                            }
574
                        }
575
                    },
649
                    },
576
                    {
650
                    {
577
                        "mDataProp": function ( oObj ) {
651
                        "mData": "itemtype",
578
                            title = "<span class='strong'><a href='/cgi-bin/koha/catalogue/detail.pl?biblionumber="
652
                        "mRender": mRenders.itemtype
579
                                  + oObj.biblionumber
580
                                  + "'>"
581
                                  + oObj.title.escapeHtml();
582
583
                            $.each(oObj.subtitle, function( index, value ) {
584
                                      title += " " + value.subfield.escapeHtml();
585
                            });
586
587
                            if ( oObj.enumchron ) {
588
                                title += " (" + oObj.enumchron.escapeHtml() + ")";
589
                            }
590
591
                            title += "</a></span>";
592
593
                            if ( oObj.author ) {
594
                                title += " " + BY.replace( "_AUTHOR_", " " + oObj.author.escapeHtml() );
595
                            }
596
597
                            if ( oObj.itemnotes ) {
598
                                var span_class = "";
599
                                if ( $.datepicker.formatDate('yy-mm-dd', new Date(oObj.issuedate) ) == ymd ) {
600
                                    span_class = "circ-hlt";
601
                                }
602
                                title += " - <span class='" + span_class + "'>" + oObj.itemnotes.escapeHtml() + "</span>"
603
                            }
604
605
                            if ( oObj.itemnotes_nonpublic ) {
606
                                var span_class = "";
607
                                if ( $.datepicker.formatDate('yy-mm-dd', new Date(oObj.issuedate) ) == ymd ) {
608
                                    span_class = "circ-hlt";
609
                                }
610
                                title += " - <span class='" + span_class + "'>" + oObj.itemnotes_nonpublic.escapeHtml() + "</span>"
611
                            }
612
613
                            var onsite_checkout = '';
614
                            if ( oObj.onsite_checkout == 1 ) {
615
                                onsite_checkout += " <span class='onsite_checkout'>(" + INHOUSE_USE + ")</span>";
616
                            }
617
618
                            title += " "
619
                                  + "<a href='/cgi-bin/koha/catalogue/moredetail.pl?biblionumber="
620
                                  + oObj.biblionumber
621
                                  + "&itemnumber="
622
                                  + oObj.itemnumber
623
                                  + "#"
624
                                  + oObj.itemnumber
625
                                  + "'>"
626
                                  + oObj.barcode.escapeHtml()
627
                                  + "</a>"
628
                                  + onsite_checkout;
629
630
                            return title;
631
                        },
632
                        "sType": "anti-the"
633
                    },
653
                    },
634
                    {
654
                    {
635
                        "mDataProp": function ( oObj ) {
655
                        "mData": "ccode",
636
                            return oObj.itemtype_description.escapeHtml();
656
                        "mRender": mRenders.collection
637
                        }
638
                    },
657
                    },
639
                    {
658
                    {
640
                        "mDataProp": function ( oObj ) {
659
                        "mData": "location",
641
                            return oObj.collection.escapeHtml();
660
                        "mRender": mRenders.location
642
                        }
643
                    },
661
                    },
644
                    {
662
                    {
645
                        "mDataProp": function ( oObj ) {
663
                        "mData": "issuedate",
646
                            return oObj.location.escapeHtml();
664
                        "mRender": mRenders.issuedate
647
                        }
648
                    },
665
                    },
649
                    { "mDataProp": "issuedate_formatted" },
650
                    {
666
                    {
651
                        "mDataProp": function ( oObj ) {
667
                        "mData": "branchcode",
652
                            return oObj.branchname.escapeHtml();
668
                        "mRender": mRenders.branch
653
                        }
654
                    },
669
                    },
655
                    {
670
                    {
656
                        "mDataProp": function ( oObj ) {
671
                        "mData": "itemcallnumber",
657
                            return oObj.itemcallnumber.escapeHtml();
672
                        "mRender": mRenders.itemcallnumber
658
                        }
659
                    },
673
                    },
660
                    {
674
                    {
661
                        "mDataProp": function ( oObj ) {
675
                        "mData": "charge",
662
                            if ( ! oObj.charge ) oObj.charge = 0;
676
                        "mRender": mRenders.charge,
663
                            return parseFloat(oObj.charge).toFixed(2);
677
                        "bSortable": ServerSideCheckoutsTables ? false : true
664
                        }
665
                    },
678
                    },
666
                    {
679
                    {
667
                        "mDataProp": function ( oObj ) {
680
                        "mData": "fine",
668
                            if ( ! oObj.fine ) oObj.fine = 0;
681
                        "mRender": mRenders.fine,
669
                            return parseFloat(oObj.fine).toFixed(2);
682
                        "bSortable": ServerSideCheckoutsTables ? false : true
670
                        }
671
                    },
683
                    },
672
                    {
684
                    {
673
                        "mDataProp": function ( oObj ) {
685
                        "mData": "replacementprice",
674
                            if ( ! oObj.price ) oObj.price = 0;
686
                        "mRender": mRenders.price,
675
                            return parseFloat(oObj.price).toFixed(2);
687
                        "bSortable": ServerSideCheckoutsTables ? false : true
676
                        }
677
                    },
688
                    },
678
                    {
689
                    {
679
                        "mDataProp": function( oObj ) {
690
                        "mData": "borrowernumber",
680
                            return "<a href='/cgi-bin/koha/members/moremember.pl?borrowernumber=" + oObj.borrowernumber + "'>"
691
                        "mRender": mRenders.patron,
681
                                + oObj.borrower.firstname.escapeHtml()
692
                        "bSortable": ServerSideCheckoutsTables ? false : true
682
                                + " " +
693
                    }
683
                                oObj.borrower.surname.escapeHtml()
694
                ]
684
                                + " (" + oObj.borrower.cardnumber.escapeHtml() + ")</a>"
695
            }, relatives_columns_settings);
685
                        }
686
                    },
687
                ],
688
                "bPaginate": false,
689
                "bProcessing": true,
690
                "bServerSide": false,
691
                "sAjaxSource": '/cgi-bin/koha/svc/checkouts',
692
                "fnServerData": function ( sSource, aoData, fnCallback ) {
693
                    $.each(relatives_borrowernumbers, function( index, value ) {
694
                        aoData.push( { "name": "borrowernumber", "value": value } );
695
                    });
696
697
                    $.getJSON( sSource, aoData, function (json) {
698
                        fnCallback(json)
699
                    } );
700
                },
701
            });
702
        }
696
        }
703
    });
697
    });
704
698
Lines 718-721 $(document).ready(function() { Link Here
718
            }
712
            }
719
        } ).prop('checked', false);
713
        } ).prop('checked', false);
720
    }
714
    }
721
 });
715
});
716
717
})(jQuery);
(-)a/svc/checkouts (-52 / +54 lines)
Lines 27-32 use C4::Biblio qw(GetMarcBiblio GetFrameworkCode GetRecordValue ); Link Here
27
use C4::Circulation qw(GetIssuingCharges CanBookBeRenewed GetRenewCount GetSoonestRenewDate);
27
use C4::Circulation qw(GetIssuingCharges CanBookBeRenewed GetRenewCount GetSoonestRenewDate);
28
use C4::Overdues qw(GetFine);
28
use C4::Overdues qw(GetFine);
29
use C4::Context;
29
use C4::Context;
30
use C4::Utils::DataTables;
30
31
31
use Koha::AuthorisedValues;
32
use Koha::AuthorisedValues;
32
use Koha::DateUtils;
33
use Koha::DateUtils;
Lines 45-70 unless (haspermission($userid, { circulate => 'circulate_remaining_permissions' Link Here
45
    exit 0;
46
    exit 0;
46
}
47
}
47
48
48
my @sort_columns = qw/date_due title itype issuedate branchcode itemcallnumber/;
49
50
my @borrowernumber   = $input->multi_param('borrowernumber');
49
my @borrowernumber   = $input->multi_param('borrowernumber');
51
my $offset           = $input->param('iDisplayStart');
50
my $offset = $input->param('iDisplayStart');
52
my $results_per_page = $input->param('iDisplayLength') || -1;
51
my $count = $input->param('iDisplayLength');
53
52
54
my $sorting_column = $input->param('iSortCol_0') || q{};
53
my %params = dt_get_params($input);
55
$sorting_column = ( $sorting_column && $sort_columns[$sorting_column] ) ? $sort_columns[$sorting_column] : 'issuedate';
54
my $orderby = dt_build_orderby(\%params);
56
55
57
my $sorting_direction = $input->param('sSortDir_0') || q{};
56
my $todaysIssuesDefaultSortOrder =
58
$sorting_direction = $sorting_direction eq 'asc' ? 'asc' : 'desc';
57
  C4::Context->preference('todaysIssuesDefaultSortOrder');
59
58
my $previousIssuesDefaultSortOrder =
60
$results_per_page = undef if ( $results_per_page == -1 );
59
  C4::Context->preference('previousIssuesDefaultSortOrder');
61
60
62
binmode STDOUT, ":encoding(UTF-8)";
61
# Default sort when user hasn't clicked on a column header yet.
63
print $input->header( -type => 'text/plain', -charset => 'UTF-8' );
62
# When row grouping is enabled, DataTables ask to sort on issued_today column,
63
# so we need to treat this case the same as the "no sorting" case
64
if (!$orderby || $orderby =~ m/ORDER BY issued_today desc\s*$/) {
65
    $orderby = qq{
66
        ORDER BY
67
        issued_today DESC,
68
        CASE WHEN issued_today = 0 THEN date_due END $previousIssuesDefaultSortOrder,
69
        CASE WHEN issued_today != 0 THEN date_due END $todaysIssuesDefaultSortOrder
70
    };
71
}
64
72
65
my @parameters;
73
my @parameters;
66
my $sql = '
74
my $sql = '
67
    SELECT
75
    SELECT SQL_CALC_FOUND_ROWS
68
        issuedate,
76
        issuedate,
69
        date_due,
77
        date_due,
70
        date_due < now() as date_due_overdue,
78
        date_due < now() as date_due_overdue,
Lines 102-108 my $sql = ' Link Here
102
        location,
110
        location,
103
        items.enumchron,
111
        items.enumchron,
104
112
105
        DATEDIFF( issuedate, CURRENT_DATE() ) AS not_issued_today
113
        DATEDIFF( issuedate, CURRENT_DATE() ) = 0 AS issued_today
106
    FROM issues
114
    FROM issues
107
        LEFT JOIN items USING ( itemnumber )
115
        LEFT JOIN items USING ( itemnumber )
108
        LEFT JOIN biblio USING ( biblionumber )
116
        LEFT JOIN biblio USING ( biblionumber )
Lines 110-136 my $sql = ' Link Here
110
        LEFT JOIN borrowers USING ( borrowernumber )
118
        LEFT JOIN borrowers USING ( borrowernumber )
111
        LEFT JOIN branches ON ( issues.branchcode = branches.branchcode )
119
        LEFT JOIN branches ON ( issues.branchcode = branches.branchcode )
112
        LEFT JOIN branches branches2 ON ( items.homebranch = branches2.branchcode )
120
        LEFT JOIN branches branches2 ON ( items.homebranch = branches2.branchcode )
113
    WHERE borrowernumber
121
    WHERE
114
';
122
';
115
123
124
my $borrowernumber_sql = 'borrowernumber';
116
if ( @borrowernumber == 1 ) {
125
if ( @borrowernumber == 1 ) {
117
    $sql .= '= ?';
126
    $borrowernumber_sql .= ' = ?';
118
}
127
} else {
119
else {
128
    $borrowernumber_sql .= ' IN (' . join( ',', ('?') x @borrowernumber ) . ') ';
120
    $sql .= ' IN (' . join( ',', ('?') x @borrowernumber ) . ') ';
121
}
129
}
130
$sql .= $borrowernumber_sql;
122
push( @parameters, @borrowernumber );
131
push( @parameters, @borrowernumber );
123
132
124
$sql .= " ORDER BY $sorting_column $sorting_direction ";
133
$sql .= " $orderby";
134
135
if ($count && $count > 0) {
136
    $sql .= " LIMIT ?,?";
137
    push @parameters, $offset, $count;
138
}
125
139
126
my $dbh = C4::Context->dbh();
140
my $dbh = C4::Context->dbh();
127
my $sth = $dbh->prepare($sql);
141
my $sth = $dbh->prepare($sql);
128
$sth->execute(@parameters);
142
$sth->execute(@parameters);
143
my ($iTotalDisplayRecords) = $dbh->selectrow_array('SELECT FOUND_ROWS()');
129
144
130
my $item_level_itypes = C4::Context->preference('item-level_itypes');
145
my $item_level_itypes = C4::Context->preference('item-level_itypes');
131
146
132
my @checkouts_today;
147
my @checkouts;
133
my @checkouts_previous;
134
while ( my $c = $sth->fetchrow_hashref() ) {
148
while ( my $c = $sth->fetchrow_hashref() ) {
135
    my ($charge) = GetIssuingCharges( $c->{itemnumber}, $c->{borrowernumber} );
149
    my ($charge) = GetIssuingCharges( $c->{itemnumber}, $c->{borrowernumber} );
136
    my $fine = GetFine( $c->{itemnumber}, $c->{borrowernumber} );
150
    my $fine = GetFine( $c->{itemnumber}, $c->{borrowernumber} );
Lines 227-262 while ( my $c = $sth->fetchrow_hashref() ) { Link Here
227
            firstname  => $c->{firstname},
241
            firstname  => $c->{firstname},
228
            cardnumber => $c->{cardnumber},
242
            cardnumber => $c->{cardnumber},
229
        },
243
        },
230
        issued_today => !$c->{not_issued_today},
244
        issued_today => $c->{issued_today} ? JSON::true : JSON::false,
231
    };
245
    };
232
246
233
    if ( $c->{not_issued_today} ) {
247
    push @checkouts, $checkout;
234
        push( @checkouts_previous, $checkout );
235
    }
236
    else {
237
        push( @checkouts_today, $checkout );
238
    }
239
}
248
}
240
249
250
binmode STDOUT, ":encoding(UTF-8)";
251
print $input->header( -type => 'application/json', -charset => 'UTF-8' );
241
252
242
@checkouts_today = sort { $a->{timestamp} cmp $b->{timestamp} } @checkouts_today;
253
my $sEcho = $input->param('sEcho');
243
@checkouts_today = reverse(@checkouts_today)
254
my ($iTotalRecords) = $dbh->selectrow_array(
244
  unless ( C4::Context->preference('todaysIssuesDefaultSortOrder') eq 'desc' );
255
    "SELECT COUNT(*) FROM issues WHERE $borrowernumber_sql", undef,
245
256
    @borrowernumber);
246
@checkouts_previous = sort { $a->{date_due} cmp $b->{date_due} } @checkouts_previous;
247
@checkouts_previous = reverse(@checkouts_previous)
248
  if ( C4::Context->preference('previousIssuesDefaultSortOrder') eq 'desc' );
249
250
my @checkouts = ( @checkouts_today, @checkouts_previous );
251
252
my $i = 1;
253
map { $_->{sort_order} = $i++ } @checkouts;
254
255
257
256
my $data;
258
my $response = {
257
$data->{'iTotalRecords'}        = scalar @checkouts;
259
    iTotalRecords => $iTotalRecords,
258
$data->{'iTotalDisplayRecords'} = scalar @checkouts;
260
    iTotalDisplayRecords => $iTotalDisplayRecords,
259
$data->{'sEcho'}                = $input->param('sEcho') || undef;
261
    sEcho => $sEcho,
260
$data->{'aaData'}               = \@checkouts;
262
    aaData => \@checkouts,
263
};
261
264
262
print to_json($data);
265
print to_json($response);
263
- 

Return to bug 15219