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

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

Return to bug 15219