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

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

Return to bug 15219