From 053195c3f909dc457441fe3488ecc419be677a9b Mon Sep 17 00:00:00 2001
From: Julian Maurice <julian.maurice@biblibre.com>
Date: Wed, 18 Nov 2015 15:52:14 +0100
Subject: [PATCH] Bug 15219: Server-side processing and pagination on checkouts
tables
Some libraries have patrons with more than 1000 checkouts. Loading all
of them at once can be very long, and sometimes can cause timeout
errors.
This patch prevent that by enabling server-side processing and
pagination on checkouts tables.
This affects patron's checkouts and patron's relatives' checkouts tables
on pages circ/circulation.pl and members/moremember.pl.
As server-side processing can be useless and cumbersome with small
sets of data, a new system preference is introduced to control this
behaviour (server-side processing is disabled by default).
Additionally, this patch:
- adds a switch to turn off and on row grouping (today's checkouts vs
previous checkouts) (on by default)
- adds "column settings" for relatives' checkouts tables
- factorize some code that was duplicated across the two DataTables
configurations (mDataProp)
Test plan:
1. Find (or create) a patron that have at least 10 checkouts and where
the relatives checkouts table contain at least 10 checkouts.
2. Go to the patron's detail page and check everything works fine
in both tables (sorting, pagination, the data itself, ...)
3. Do the same on circulation page (circulation.pl)
4. Enable system preference ServerSideCheckoutsTable
5. Repeat steps 2 and 3
Signed-off-by: Eric Gosselin <eric.gosselin@inlibro.com>
---
admin/columns_settings.yml | 60 +-
.../data/mysql/atomicupdate/bug_15219.sql | 2 +
installer/data/mysql/sysprefs.sql | 1 +
.../plugins/jquery.dataTables.rowGrouping.js | 10 +-
.../en/includes/checkouts-table-footer.inc | 2 +-
.../prog/en/includes/checkouts-table.inc | 1 -
.../prog/en/includes/checkouts.js.inc | 26 +
.../prog/en/includes/columns_settings.inc | 2 +-
.../prog/en/includes/strings.inc | 1 +
.../admin/preferences/circulation.pref | 6 +
.../prog/en/modules/circ/circulation.tt | 13 +-
.../prog/en/modules/members/moremember.tt | 12 +-
koha-tmpl/intranet-tmpl/prog/js/checkouts.js | 834 +++++++++---------
svc/checkouts | 105 +--
14 files changed, 562 insertions(+), 513 deletions(-)
create mode 100644 installer/data/mysql/atomicupdate/bug_15219.sql
create mode 100644 koha-tmpl/intranet-tmpl/prog/en/includes/checkouts.js.inc
diff --git a/admin/columns_settings.yml b/admin/columns_settings.yml
index 3e2a6723e5..5ac9f5fd1a 100644
--- a/admin/columns_settings.yml
+++ b/admin/columns_settings.yml
@@ -231,7 +231,7 @@ modules:
moremember:
issues-table:
-
- columnname: sort_order
+ columnname: group_order
cannot_be_toggled: 1
cannot_be_modified: 1
is_hidden: 1
@@ -240,11 +240,6 @@ modules:
cannot_be_toggled: 1
cannot_be_modified: 1
is_hidden: 1
- -
- columnname: due_date_unformatted
- cannot_be_toggled: 1
- cannot_be_modified: 1
- is_hidden: 1
-
columnname: due_date
-
@@ -279,6 +274,29 @@ modules:
columnname: export
cannot_be_toggled: 1
cannot_be_modified: 1
+ relatives-issues-table:
+ -
+ columnname: due_date
+ -
+ columnname: title
+ -
+ columnname: item_type
+ -
+ columnname: location
+ -
+ columnname: checkout_on
+ -
+ columnname: checkout_from
+ -
+ columnname: callno
+ -
+ columnname: charge
+ -
+ columnname: fine
+ -
+ columnname: price
+ -
+ columnname: patron
holdshistory:
holdshistory-table:
@@ -388,7 +406,7 @@ modules:
circulation:
issues-table:
-
- columnname: sort_order
+ columnname: group_order
cannot_be_toggled: 1
cannot_be_modified: 1
is_hidden: 1
@@ -397,11 +415,6 @@ modules:
cannot_be_toggled: 1
cannot_be_modified: 1
is_hidden: 1
- -
- columnname: due_date_unformatted
- cannot_be_toggled: 1
- cannot_be_modified: 1
- is_hidden: 1
-
columnname: due_date
-
@@ -436,6 +449,29 @@ modules:
columnname: export
cannot_be_toggled: 1
cannot_be_modified: 1
+ relatives-issues-table:
+ -
+ columnname: due_date
+ -
+ columnname: title
+ -
+ columnname: item_type
+ -
+ columnname: location
+ -
+ columnname: checkout_on
+ -
+ columnname: checkout_from
+ -
+ columnname: callno
+ -
+ columnname: charge
+ -
+ columnname: fine
+ -
+ columnname: price
+ -
+ columnname: patron
returns:
checkedintable:
diff --git a/installer/data/mysql/atomicupdate/bug_15219.sql b/installer/data/mysql/atomicupdate/bug_15219.sql
new file mode 100644
index 0000000000..a186d45abe
--- /dev/null
+++ b/installer/data/mysql/atomicupdate/bug_15219.sql
@@ -0,0 +1,2 @@
+INSERT IGNORE INTO systempreferences (variable,value,explanation,options,type)
+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');
diff --git a/installer/data/mysql/sysprefs.sql b/installer/data/mysql/sysprefs.sql
index 753bc57d0a..8a2064883b 100644
--- a/installer/data/mysql/sysprefs.sql
+++ b/installer/data/mysql/sysprefs.sql
@@ -497,6 +497,7 @@ INSERT INTO systempreferences ( `variable`, `value`, `options`, `explanation`, `
('SelfCheckTimeout','120','','Define the number of seconds before the Web-based Self Checkout times out a patron','Integer'),
('SeparateHoldings','0',NULL,'Separate current branch holdings from other holdings','YesNo'),
('SeparateHoldingsBranch','homebranch','homebranch|holdingbranch','Branch used to separate holdings','Choice'),
+('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'),
('SessionRestrictionByIP','1','Check for change in remote IP address for session security. Disable only when remote IP address changes frequently.','','YesNo'),
('SessionStorage','mysql','mysql|Pg|tmp','Use database or a temporary file for storing session data','Choice'),
('ShelfBrowserUsesCcode','1','0','Use the item collection code when finding items for the shelf browser.','YesNo'),
diff --git a/koha-tmpl/intranet-tmpl/lib/jquery/plugins/jquery.dataTables.rowGrouping.js b/koha-tmpl/intranet-tmpl/lib/jquery/plugins/jquery.dataTables.rowGrouping.js
index 126ff63357..12a88e4dba 100644
--- a/koha-tmpl/intranet-tmpl/lib/jquery/plugins/jquery.dataTables.rowGrouping.js
+++ b/koha-tmpl/intranet-tmpl/lib/jquery/plugins/jquery.dataTables.rowGrouping.js
@@ -608,15 +608,15 @@
}
- oTable.fnSetColumnVis(properties.iGroupingColumnIndex, !properties.bHideGroupingColumn);
+ oTable.fnSetColumnVis(properties.iGroupingColumnIndex, !properties.bHideGroupingColumn, false);
if (properties.bCustomColumnOrdering) {
- oTable.fnSetColumnVis(properties.iGroupingOrderByColumnIndex, !properties.bHideGroupingOrderByColumn);
+ oTable.fnSetColumnVis(properties.iGroupingOrderByColumnIndex, !properties.bHideGroupingOrderByColumn, false);
}
if (properties.iGroupingColumnIndex2 != -1) {
- oTable.fnSetColumnVis(properties.iGroupingColumnIndex2, !properties.bHideGroupingColumn2);
+ oTable.fnSetColumnVis(properties.iGroupingColumnIndex2, !properties.bHideGroupingColumn2, false);
}
if (properties.bCustomColumnOrdering2) {
- oTable.fnSetColumnVis(properties.iGroupingOrderByColumnIndex2, !properties.bHideGroupingOrderByColumn2);
+ oTable.fnSetColumnVis(properties.iGroupingOrderByColumnIndex2, !properties.bHideGroupingOrderByColumn2, false);
}
oTable.fnSettings().aoDrawCallback.push({
"fn": _fnDrawCallBackWithGrouping,
@@ -687,4 +687,4 @@
});
};
-})(jQuery);
\ No newline at end of file
+})(jQuery);
diff --git a/koha-tmpl/intranet-tmpl/prog/en/includes/checkouts-table-footer.inc b/koha-tmpl/intranet-tmpl/prog/en/includes/checkouts-table-footer.inc
index b831c1e507..0da60c5930 100644
--- a/koha-tmpl/intranet-tmpl/prog/en/includes/checkouts-table-footer.inc
+++ b/koha-tmpl/intranet-tmpl/prog/en/includes/checkouts-table-footer.inc
@@ -1,6 +1,6 @@
<tfoot>
<tr>
- <td colspan="11" style="text-align: right; font-weight:bold;">Totals:</td>
+ <td colspan="10" style="text-align: right; font-weight:bold;">Totals:</td>
<td id="totaldue" style="text-align: right;">[% totaldue | html %]</td>
<td id="totalfine" style="text-align: right;">[% finetotal | html %]</td>
<td id="totalprice" style="text-align: right;">[% totalprice | html %]</td>
diff --git a/koha-tmpl/intranet-tmpl/prog/en/includes/checkouts-table.inc b/koha-tmpl/intranet-tmpl/prog/en/includes/checkouts-table.inc
index f9265dc8ad..696ff67bd1 100644
--- a/koha-tmpl/intranet-tmpl/prog/en/includes/checkouts-table.inc
+++ b/koha-tmpl/intranet-tmpl/prog/en/includes/checkouts-table.inc
@@ -13,7 +13,6 @@
<th scope="col"> </th>
<th scope="col"> </th>
<th scope="col">Due date</th>
- <th scope="col">Due date</th>
<th scope="col">Title</th>
<th scope="col">Item type</th>
<th scope="col">Collection</th>
diff --git a/koha-tmpl/intranet-tmpl/prog/en/includes/checkouts.js.inc b/koha-tmpl/intranet-tmpl/prog/en/includes/checkouts.js.inc
new file mode 100644
index 0000000000..fea263e555
--- /dev/null
+++ b/koha-tmpl/intranet-tmpl/prog/en/includes/checkouts.js.inc
@@ -0,0 +1,26 @@
+[% USE Asset %]
+[% USE Koha %]
+[% USE raw %]
+
+<script>
+ [% IF Koha.Preference('ServerSideCheckoutsTables') %]
+ var ServerSideCheckoutsTables = true;
+ [% ELSE %]
+ var ServerSideCheckoutsTables = false;
+ [% END %]
+ var AllowCirculate = [% (CAN_user_circulate_circulate_remaining_permissions)? 1 : 0 %];
+ var AllowRenewalLimitOverride = [% (CAN_user_circulate_override_renewals && Koha.Preference('AllowRenewalLimitOverride'))? 1 : 0 %];
+
+ var MSG_DT_LOADING_RECORDS = _("Loading... you may continue scanning.");
+
+ var borrowernumber = "[% borrowernumber | $raw %]";
+ var relatives_borrowernumbers = new Array();
+ [% FOREACH b IN relatives_borrowernumbers %]
+ relatives_borrowernumbers.push("[% b | $raw %]");
+ [% END %]
+
+ var columns_settings = [% ColumnsSettings.GetColumns( 'circ', 'circulation', 'issues-table', 'json' ) | $raw %];
+ var relatives_columns_settings = [% ColumnsSettings.GetColumns( 'circ', 'circulation', 'relatives-issues-table', 'json' ) | $raw %];
+</script>
+
+[% Asset.js('js/checkouts.js') | $raw %]
diff --git a/koha-tmpl/intranet-tmpl/prog/en/includes/columns_settings.inc b/koha-tmpl/intranet-tmpl/prog/en/includes/columns_settings.inc
index 636cc5a562..bf1bbdec6f 100644
--- a/koha-tmpl/intranet-tmpl/prog/en/includes/columns_settings.inc
+++ b/koha-tmpl/intranet-tmpl/prog/en/includes/columns_settings.inc
@@ -71,7 +71,7 @@ function KohaTable(id_selector, dt_parameters, columns_settings, add_filters) {
table.dataTable($.extend(true, {}, dataTablesDefaults, dt_parameters));
$(hidden_ids).each(function(index, value) {
- table.fnSetColumnVis( value, false );
+ table.fnSetColumnVis( value, false, false );
});
if ( add_filters ) {
diff --git a/koha-tmpl/intranet-tmpl/prog/en/includes/strings.inc b/koha-tmpl/intranet-tmpl/prog/en/includes/strings.inc
index bd513293dd..2f03dbbe5e 100644
--- a/koha-tmpl/intranet-tmpl/prog/en/includes/strings.inc
+++ b/koha-tmpl/intranet-tmpl/prog/en/includes/strings.inc
@@ -46,5 +46,6 @@
var CURRENT = _(" (current) ");
var MSG_NO_ITEMTYPE = _("No itemtype");
var MSG_CHECKOUTS_BY_ITEMTYPE = _("Number of checkouts by item type");
+ var GROUP_TODAYS_CHECKOUTS = _("Group today's checkouts");
//]]>
</script>
diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/circulation.pref b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/circulation.pref
index c7193dfb0e..74d2e4f07e 100644
--- a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/circulation.pref
+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/circulation.pref
@@ -52,6 +52,12 @@ Circulation:
asc: earliest to latest
desc: latest to earliest
- due date.
+ -
+ - pref: ServerSideCheckoutsTables
+ choices:
+ yes: Enable
+ no: Do not enable
+ - server-side processing on checkouts tables. It can improve performance when there is a big number of checkouts to display.
-
- pref: SpecifyDueDate
choices:
diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/circ/circulation.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/circ/circulation.tt
index dbf3e2d37e..4fba41c019 100644
--- a/koha-tmpl/intranet-tmpl/prog/en/modules/circ/circulation.tt
+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/circ/circulation.tt
@@ -848,7 +848,6 @@ No patron matched <span class="ex">[% message | html %]</span>
<table id="relatives-issues-table">
<thead>
<tr>
- <th scope="col">Due date (unformatted, hidden)</th>
<th scope="col">Due date</th>
<th scope="col">Title</th>
<th scope="col">Item type</th>
@@ -983,30 +982,20 @@ No patron matched <span class="ex">[% message | html %]</span>
[% INCLUDE 'timepicker.inc' %]
[% Asset.js("lib/jquery/plugins/jquery.dataTables.rowGrouping.js") | $raw %]
[% Asset.js("js/pages/circulation.js") | $raw %]
- [% Asset.js("js/checkouts.js") | $raw %]
+ [% INCLUDE 'checkouts.js.inc' %]
[% Asset.js("js/holds.js") | $raw %]
[% Asset.js("js/circ-patron-search-results.js") | $raw %]
<script type="text/javascript">
/* Set some variable needed in circulation.js */
- var MSG_DT_LOADING_RECORDS = _("Loading... you may continue scanning.");
var interface = "[% interface | html %]";
var theme = "[% theme | html %]";
- var borrowernumber = "[% patron.borrowernumber | html %]";
var branchcode = "[% branch | html %]";
var exports_enabled = "[% Koha.Preference('ExportCircHistory') | html %]";
- var AllowRenewalLimitOverride = [% (CAN_user_circulate_override_renewals && Koha.Preference('AllowRenewalLimitOverride') )? 1: 0 | html %];
- var AllowCirculate = [% (CAN_user_circulate_circulate_remaining_permissions)? 1 : 0 | html %];
var script = "circulation";
- var relatives_borrowernumbers = new Array();
- [% FOREACH b IN relatives_borrowernumbers %]
- relatives_borrowernumbers.push("[% b | html %]");
- [% END %]
var MSG_EXPORT_SELECT_CHECKOUTS = _("You must select checkout(s) to export");
var MSG_CONFIRM_DELETE_MESSAGE = _("Are you sure you want to delete this message? This cannot be undone.");
- columns_settings = [% ColumnsSettings.GetColumns( 'circ', 'circulation', 'issues-table', 'json' ) | $raw %]
-
[% IF borrowernumber and patron %]
if($.cookie("holdfor") != [% patron.borrowernumber | html %]){
$.removeCookie("holdfor", { path: '/' });
diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/members/moremember.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/members/moremember.tt
index a88a98ee88..458af27760 100644
--- a/koha-tmpl/intranet-tmpl/prog/en/modules/members/moremember.tt
+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/members/moremember.tt
@@ -687,7 +687,6 @@
<table id="relatives-issues-table" style="width: 100% !Important;">
<thead>
<tr>
- <th scope="col">Due date hidden not formatted</th>
<th scope="col">Due date</th>
<th scope="col">Title</th>
<th scope="col">Item type</th>
@@ -801,7 +800,7 @@
[% INCLUDE 'timepicker.inc' %]
[% Asset.js("lib/jquery/plugins/jquery.dataTables.rowGrouping.js") | $raw %]
[% Asset.js("js/pages/circulation.js") | $raw %]
- [% Asset.js("js/checkouts.js") | $raw %]
+ [% INCLUDE 'checkouts.js.inc' %]
[% Asset.js("js/holds.js") | $raw %]
[% INCLUDE 'str/members-menu.inc' %]
[% Asset.js("js/members-menu.js") | $raw %]
@@ -810,22 +809,13 @@
/* Set some variable needed in circulation.js */
var interface = "[% interface | html %]";
var theme = "[% theme | html %]";
- var borrowernumber = "[% patron.borrowernumber | html %]";
var branchcode = "[% Branches.GetLoggedInBranchcode() | html %]";
var exports_enabled = "[% Koha.Preference('ExportCircHistory') | html %]";
- var AllowCirculate = [% (CAN_user_circulate_circulate_remaining_permissions)? 1 : 0 | html %]
- var AllowRenewalLimitOverride = [% (CAN_user_circulate_override_renewals && Koha.Preference('AllowRenewalLimitOverride') )? 1: 0 | html %];
var script = "moremember";
- var relatives_borrowernumbers = new Array();
- [% FOREACH b IN relatives_borrowernumbers %]
- relatives_borrowernumbers.push("[% b | html %]");
- [% END %]
var MSG_EXPORT_SELECT_CHECKOUTS = _("You must select checkout(s) to export");
var MSG_CONFIRM_DELETE_MESSAGE = _("Are you sure you want to delete this message? This cannot be undone.");
- columns_settings = [% ColumnsSettings.GetColumns( 'members', 'moremember', 'issues-table', 'json' ) | $raw %]
-
$(document).ready(function() {
if ( $('#clubs-tab').length ) {
$('#clubs-tab-link').on('click', function() {
diff --git a/koha-tmpl/intranet-tmpl/prog/js/checkouts.js b/koha-tmpl/intranet-tmpl/prog/js/checkouts.js
index 2525f567c7..6c36781aac 100644
--- a/koha-tmpl/intranet-tmpl/prog/js/checkouts.js
+++ b/koha-tmpl/intranet-tmpl/prog/js/checkouts.js
@@ -1,3 +1,282 @@
+(function($) {
+
+var ymd = $.datepicker.formatDate('yy-mm-dd', new Date());
+
+function enableGrouping(datatable) {
+ datatable.rowGrouping({
+ iGroupingColumnIndex: 1,
+ iGroupingOrderByColumnIndex: 0,
+ sGroupingColumnSortDirection: "desc"
+ });
+}
+
+function disableGrouping(datatable) {
+ var oSettings = datatable.fnSettings();
+ for (f = 0; f < oSettings.aoDrawCallback.length; f++) {
+ if (oSettings.aoDrawCallback[f].sName == 'fnRowGrouping') {
+ oSettings.aoDrawCallback.splice(f, 1);
+ oSettings.aaSortingFixed = null;
+ datatable.fnDraw();
+ break;
+ }
+ }
+}
+
+var mRenders = {
+ groupOrder: function (oData, sType, oObj) {
+ if ( oObj.issued_today ) {
+ return "1";
+ } else {
+ return "0";
+ }
+ },
+ groupName: function (oData, sType, oObj) {
+ if (oObj.issued_today) {
+ return "<strong>" + TODAYS_CHECKOUTS + "</strong>";
+ } else {
+ return "<strong>" + PREVIOUS_CHECKOUTS + "</strong>";
+ }
+ },
+ dateDueFormatted: function (oData, sType, oObj) {
+ var due = oObj.date_due_formatted;
+
+ if ( oObj.date_due_overdue ) {
+ due = "<span class='overdue'>" + due + "</span>";
+ }
+
+ due = "<span id='date_due_" + oObj.itemnumber + "' class='date_due'>" + due + "</span>";
+
+ if ( oObj.lost ) {
+ due += "<span class='lost'>" + oObj.lost.escapeHtml() + "</span>";
+ }
+
+ if ( oObj.damaged ) {
+ due += "<span class='dmg'>" + oObj.damaged.escapeHtml() + "</span>";
+ }
+
+ return due;
+ },
+ title: function (oData, sType, oObj) {
+ var title = "<span id='title_" + oObj.itemnumber + "' class='strong'><a href='/cgi-bin/koha/catalogue/detail.pl?biblionumber="
+ + oObj.biblionumber
+ + "'>"
+ + oObj.title.escapeHtml();
+
+ $.each(oObj.subtitle, function( index, value ) {
+ title += " " + value.subfield.escapeHtml();
+ });
+
+ if ( oObj.enumchron ) {
+ title += " (" + oObj.enumchron.escapeHtml() + ")";
+ }
+
+ title += "</a></span>";
+
+ if ( oObj.author ) {
+ title += " " + BY.replace( "_AUTHOR_", " " + oObj.author.escapeHtml() );
+ }
+
+ if ( oObj.itemnotes ) {
+ var span_class = "text-muted";
+ if ( $.datepicker.formatDate('yy-mm-dd', new Date(oObj.issuedate) ) == ymd ) {
+ span_class = "circ-hlt";
+ }
+ title += " - <span class='" + span_class + " item-note-public'>" + oObj.itemnotes.escapeHtml() + "</span>";
+ }
+
+ if ( oObj.itemnotes_nonpublic ) {
+ var span_class = "text-danger";
+ if ( $.datepicker.formatDate('yy-mm-dd', new Date(oObj.issuedate) ) == ymd ) {
+ span_class = "circ-hlt";
+ }
+ title += " - <span class='" + span_class + " item-note-nonpublic'>" + oObj.itemnotes_nonpublic.escapeHtml() + "</span>";
+ }
+
+ var onsite_checkout = '';
+ if ( oObj.onsite_checkout == 1 ) {
+ onsite_checkout += " <span class='onsite_checkout'>(" + INHOUSE_USE + ")</span>";
+ }
+
+ title += " "
+ + "<a href='/cgi-bin/koha/catalogue/moredetail.pl?biblionumber="
+ + oObj.biblionumber
+ + "&itemnumber="
+ + oObj.itemnumber
+ + "#"
+ + oObj.itemnumber
+ + "'>"
+ + oObj.barcode.escapeHtml()
+ + "</a>"
+ + onsite_checkout
+
+ return title;
+ },
+ itemtype: function (oData, sType, oObj) {
+ return oObj.itemtype_description.escapeHtml();
+ },
+ collection: function (oData, sType, oObj) {
+ return oObj.collection.escapeHtml();
+ },
+ location: function (oData, sType, oObj) {
+ return oObj.location.escapeHtml();
+ },
+ homebranch: function (oData, sType, oObj) {
+ return oObj.homebranch.escapeHtml();
+ },
+ issuedate: function (oData, sType, oObj) {
+ return oObj.issuedate_formatted;
+ },
+ branch: function (oData, sType, oObj) {
+ return oObj.branchname.escapeHtml();
+ },
+ itemcallnumber: function (oData, sType, oObj) {
+ return oObj.itemcallnumber.escapeHtml();
+ },
+ charge: function (oData, sType, oObj) {
+ if (!oObj.charge) oObj.charge = 0;
+ return '<span style="text-align: right; display: block;">' + parseFloat(oObj.charge).toFixed(2) + '<span>';
+ },
+ fine: function (oData, sType, oObj) {
+ if (!oObj.fine) oObj.fine = 0;
+ return '<span style="text-align: right; display: block;">' + parseFloat(oObj.fine).toFixed(2) + '<span>';
+ },
+ price: function (oData, sType, oObj) {
+ if (!oObj.price) oObj.price = 0;
+ return parseFloat(oObj.price).toFixed(2);
+ },
+ renew: function (oData, sType, oObj) {
+ var content = "";
+ var span_style = "";
+ var span_class = "";
+
+ content += "<span>";
+ content += "<span style='padding: 0 1em;'>" + oObj.renewals_count + "</span>";
+
+ if ( oObj.can_renew ) {
+ // Do nothing
+ } else if ( oObj.can_renew_error == "on_reserve" ) {
+ content += "<span class='renewals-disabled-no-override'>"
+ + "<a href='/cgi-bin/koha/reserve/request.pl?biblionumber=" + oObj.biblionumber + "'>" + ON_HOLD + "</a>"
+ + "</span>";
+
+ span_style = "display: none";
+ span_class = "renewals-allowed";
+ } else if ( oObj.can_renew_error == "too_many" ) {
+ content += "<span class='renewals-disabled'>"
+ + NOT_RENEWABLE
+ + "</span>";
+
+ span_style = "display: none";
+ span_class = "renewals-allowed";
+ } else if ( oObj.can_renew_error == "restriction" ) {
+ content += "<span class='renewals-disabled'>"
+ + NOT_RENEWABLE_RESTRICTION
+ + "</span>";
+
+ span_style = "display: none";
+ span_class = "renewals-allowed";
+ } else if ( oObj.can_renew_error == "overdue" ) {
+ content += "<span class='renewals-disabled'>"
+ + NOT_RENEWABLE_OVERDUE
+ + "</span>";
+
+ span_style = "display: none";
+ span_class = "renewals-allowed";
+ } else if ( oObj.can_renew_error == "too_soon" ) {
+ content += "<span class='renewals-disabled'>"
+ + NOT_RENEWABLE_TOO_SOON.format( oObj.can_renew_date )
+ + "</span>";
+
+ span_style = "display: none";
+ span_class = "renewals-allowed";
+ } else if ( oObj.can_renew_error == "auto_too_soon" ) {
+ content += "<span class='renewals-disabled'>"
+ + NOT_RENEWABLE_AUTO_TOO_SOON
+ + "</span>";
+
+ span_style = "display: none";
+ span_class = "renewals-allowed";
+ } else if ( oObj.can_renew_error == "auto_too_late" ) {
+ content += "<span class='renewals-disabled'>"
+ + NOT_RENEWABLE_AUTO_TOO_LATE
+ + "</span>";
+
+ span_style = "display: none";
+ span_class = "renewals-allowed";
+ } else if ( oObj.can_renew_error == "auto_too_much_oweing" ) {
+ content += "<span class='renewals-disabled'>"
+ + NOT_RENEWABLE_AUTO_TOO_MUCH_OWEING
+ + "</span>";
+
+ span_style = "display: none";
+ span_class = "renewals-allowed";
+ } else if ( oObj.can_renew_error == "auto_account_expired" ) {
+ content += "<span class='renewals-disabled'>"
+ + NOT_RENEWABLE_AUTO_ACCOUNT_EXPIRED
+ + "</span>";
+
+ span_style = "display: none";
+ span_class = "renewals-allowed";
+ } else if ( oObj.can_renew_error == "auto_renew" ) {
+ content += "<span class='renewals-disabled'>"
+ + NOT_RENEWABLE_AUTO_RENEW
+ + "</span>";
+
+ span_style = "display: none";
+ span_class = "renewals-allowed";
+ } else if ( oObj.can_renew_error == "onsite_checkout" ) {
+ // Don't display something if it's an onsite checkout
+ } else {
+ content += "<span class='renewals-disabled'>"
+ + oObj.can_renew_error
+ + "</span>";
+
+ span_style = "display: none";
+ span_class = "renewals-allowed";
+ }
+
+ var can_force_renew = ( oObj.onsite_checkout == 0 ) && ( oObj.can_renew_error != "on_reserve" );
+ var can_renew = ( oObj.renewals_remaining > 0 && !oObj.can_renew_error );
+ if ( can_renew || can_force_renew ) {
+ content += "<span class='" + span_class + "' style='" + span_style + "'>"
+ + "<input type='checkbox' ";
+ if ( oObj.date_due_overdue && can_renew ) {
+ content += "checked='checked' ";
+ }
+ content += "class='renew' id='renew_" + oObj.itemnumber + "' name='renew' value='" + oObj.itemnumber +"'/>"
+ + "</span>";
+
+ content += "<span class='renewals'>("
+ + RENEWALS_REMAINING.format( oObj.renewals_remaining, oObj.renewals_allowed )
+ + ")</span>";
+ }
+
+ content += "</span>";
+
+ return content;
+ },
+ checkin: function (oData, sType, oObj) {
+ if (oObj.can_renew_error == "on_reserve") {
+ return "<a href='/cgi-bin/koha/reserve/request.pl?biblionumber=" + oObj.biblionumber + "'>" + ON_HOLD + "</a>";
+ } else {
+ return "<input type='checkbox' class='checkin' id='checkin_" + oObj.itemnumber + "' name='checkin' value='" + oObj.itemnumber +"'></input>";
+ }
+ },
+ export: function (oData, sType, oObj) {
+ var s = "<input type='checkbox' name='itemnumbers' value='" + oObj.itemnumber + "' style='visibility:hidden;' />";
+
+ s += "<input type='checkbox' class='export' id='export_" + oObj.biblionumber + "' name='biblionumbers' value='" + oObj.biblionumber + "' />";
+ return s;
+ },
+ patron: function (oData, sType, oObj) {
+ return "<a href='/cgi-bin/koha/members/moremember.pl?borrowernumber=" + oObj.borrowernumber + "'>"
+ + oObj.borrower.firstname.escapeHtml()
+ + " "
+ + oObj.borrower.surname.escapeHtml()
+ + " (" + oObj.borrower.cardnumber.escapeHtml() + ")</a>"
+ }
+};
+
$(document).ready(function() {
$.ajaxSetup ({ cache: false });
@@ -152,8 +431,6 @@ $(document).ready(function() {
return false;
});
- var ymd = $.datepicker.formatDate('yy-mm-dd', new Date());
-
$('#issues-table').hide();
$('#issues-table-actions').hide();
$('#issues-table-load-immediately').change(function(){
@@ -187,16 +464,43 @@ $(document).ready(function() {
"sProcessing": MSG_DT_LOADING_RECORDS,
},
"bAutoWidth": false,
- "dom": 'B<"clearfix">rt',
+ "bProcessing": true,
+ "bServerSide": ServerSideCheckoutsTables,
+ "sAjaxSource": "/cgi-bin/koha/svc/checkouts",
+ "fnServerParams": function (aoData) {
+ aoData.push({ "name": "borrowernumber", "value": borrowernumber });
+ },
+ "fnInitComplete": function(oSettings, json) {
+ // Build a summary of checkouts grouped by itemtype
+ var checkoutsByItype = json.aaData.reduce(function (obj, row) {
+ obj[row.itemtype_description] = (obj[row.itemtype_description] || 0) + 1;
+ return obj;
+ }, {});
+ var ul = $('<ul>');
+ Object.keys(checkoutsByItype).sort().forEach(function (itype) {
+ var li = $('<li>')
+ .append($('<strong>').html(itype || MSG_NO_ITEMTYPE))
+ .append(': ' + checkoutsByItype[itype]);
+ ul.append(li);
+ })
+ $('<details>')
+ .addClass('checkouts-by-itemtype')
+ .append($('<summary>').html(MSG_CHECKOUTS_BY_ITEMTYPE))
+ .append(ul)
+ .insertBefore(oSettings.nTableWrapper)
+ },
+ "bPaginate": true,
+ "sPaginationType": "four_button",
+ "dom": 'B<"clearfix"><"top pager"ilp>rt',
+ "aaSorting": [],
"aoColumns": [
{
- "mDataProp": function( oObj ) {
- return oObj.sort_order;
- }
+ "mData": "issued_today",
+ "mRender": mRenders.groupOrder
},
{
- "mDataProp": function( oObj ) {
- if ( oObj.issued_today ) {
+ "mData": function (oObj) {
+ if (oObj.issued_today) {
return "<strong>" + TODAYS_CHECKOUTS + "</strong>";
} else {
return "<strong>" + PREVIOUS_CHECKOUTS + "</strong>";
@@ -204,276 +508,70 @@ $(document).ready(function() {
}
},
{
- "mDataProp": "date_due",
- "bVisible": false,
+ "mData": "date_due",
+ "mRender": mRenders.dateDueFormatted
},
{
- "iDataSort": 2, // Sort on hidden unformatted date due column
- "mDataProp": function( oObj ) {
- var due = oObj.date_due_formatted;
-
- if ( oObj.date_due_overdue ) {
- due = "<span class='overdue'>" + due + "</span>";
- }
-
- due = "<span id='date_due_" + oObj.itemnumber + "' class='date_due'>" + due + "</span>";
-
- if ( oObj.lost ) {
- due += "<span class='lost'>" + oObj.lost.escapeHtml() + "</span>";
- }
-
- if ( oObj.damaged ) {
- due += "<span class='dmg'>" + oObj.damaged.escapeHtml() + "</span>";
- }
-
- var patron_note = " <span class='patron_note_" + oObj.itemnumber + "'></span>";
- due +="<br>" + patron_note;
-
- return due;
- }
+ "mData": "title",
+ "mRender": mRenders.title
},
{
- "mDataProp": function ( oObj ) {
- title = "<span id='title_" + oObj.itemnumber + "' class='strong'><a href='/cgi-bin/koha/catalogue/detail.pl?biblionumber="
- + oObj.biblionumber
- + "'>"
- + oObj.title.escapeHtml();
-
- $.each(oObj.subtitle, function( index, value ) {
- title += " " + value.subfield.escapeHtml();
- });
-
- if ( oObj.enumchron ) {
- title += " (" + oObj.enumchron.escapeHtml() + ")";
- }
-
- title += "</a></span>";
-
- if ( oObj.author ) {
- title += " " + BY.replace( "_AUTHOR_", " " + oObj.author.escapeHtml() );
- }
-
- if ( oObj.itemnotes ) {
- var span_class = "text-muted";
- if ( $.datepicker.formatDate('yy-mm-dd', new Date(oObj.issuedate) ) == ymd ) {
- span_class = "circ-hlt";
- }
- title += " - <span class='" + span_class + " item-note-public'>" + oObj.itemnotes.escapeHtml() + "</span>";
- }
-
- if ( oObj.itemnotes_nonpublic ) {
- var span_class = "text-danger";
- if ( $.datepicker.formatDate('yy-mm-dd', new Date(oObj.issuedate) ) == ymd ) {
- span_class = "circ-hlt";
- }
- title += " - <span class='" + span_class + " item-note-nonpublic'>" + oObj.itemnotes_nonpublic.escapeHtml() + "</span>";
- }
-
- var onsite_checkout = '';
- if ( oObj.onsite_checkout == 1 ) {
- onsite_checkout += " <span class='onsite_checkout'>(" + INHOUSE_USE + ")</span>";
- }
-
- title += " "
- + "<a href='/cgi-bin/koha/catalogue/moredetail.pl?biblionumber="
- + oObj.biblionumber
- + "&itemnumber="
- + oObj.itemnumber
- + "#"
- + oObj.itemnumber
- + "'>"
- + oObj.barcode.escapeHtml()
- + "</a>"
- + onsite_checkout
-
- return title;
- },
- "sType": "anti-the"
+ "mData": "itemtype",
+ "mRender": mRenders.itemtype
},
{
- "mDataProp": function ( oObj ) {
- return oObj.itemtype_description.escapeHtml();
- }
+ "mData": "ccode",
+ "mRender": mRenders.collection
},
{
- "mDataProp": function ( oObj ) {
- return oObj.collection.escapeHtml();
- }
+ "mData": "location",
+ "mRender": mRenders.location
},
{
- "mDataProp": function ( oObj ) {
- return oObj.location.escapeHtml();
- }
+ "mData": "homebranch",
+ "mRender": mRenders.homebranch
},
{
- "mDataProp": function ( oObj ) {
- return oObj.homebranch.escapeHtml();
- }
+ "mData": "issuedate",
+ "mRender": mRenders.issuedate
},
- { "mDataProp": "issuedate_formatted" },
{
- "mDataProp": function ( oObj ) {
- return oObj.branchname.escapeHtml();
- }
+ "mData": "branchcode",
+ "mRender": mRenders.branch
},
{
- "mDataProp": function ( oObj ) {
- return oObj.itemcallnumber.escapeHtml();
- }
+ "mData": "itemcallnumber",
+ "mRender": mRender.itemcallnumber
},
{
- "mDataProp": function ( oObj ) {
- if ( ! oObj.charge ) oObj.charge = 0;
- return '<span style="text-align: right; display: block;">' + parseFloat(oObj.charge).toFixed(2) + '<span>';
- }
+ "mData": "charge",
+ "mRender": mRenders.charge,
+ "bSortable": ServerSideCheckoutsTables ? false : true
},
{
- "mDataProp": function ( oObj ) {
- if ( ! oObj.fine ) oObj.fine = 0;
- return '<span style="text-align: right; display: block;">' + parseFloat(oObj.fine).toFixed(2) + '<span>';
- }
+ "mData": "fine",
+ "mRender": mRenders.fine,
+ "bSortable": ServerSideCheckoutsTables ? false : true
},
{
- "mDataProp": function ( oObj ) {
- if ( ! oObj.price ) oObj.price = 0;
- return '<span style="text-align: right; display: block;">' + parseFloat(oObj.price).toFixed(2) + '<span>';
- }
+ "mData": "replacementprice",
+ "mRender": mRenders.price,
+ "bSortable": ServerSideCheckoutsTables ? false : true
},
{
- "bSortable": false,
"bVisible": AllowCirculate ? true : false,
- "mDataProp": function ( oObj ) {
- var content = "";
- var span_style = "";
- var span_class = "";
-
- content += "<span>";
- content += "<span style='padding: 0 1em;'>" + oObj.renewals_count + "</span>";
-
- if ( oObj.can_renew ) {
- // Do nothing
- } else if ( oObj.can_renew_error == "on_reserve" ) {
- content += "<span class='renewals-disabled-no-override'>"
- + "<a href='/cgi-bin/koha/reserve/request.pl?biblionumber=" + oObj.biblionumber + "'>" + ON_HOLD + "</a>"
- + "</span>";
-
- span_style = "display: none";
- span_class = "renewals-allowed";
- } else if ( oObj.can_renew_error == "too_many" ) {
- content += "<span class='renewals-disabled'>"
- + NOT_RENEWABLE
- + "</span>";
-
- span_style = "display: none";
- span_class = "renewals-allowed";
- } else if ( oObj.can_renew_error == "restriction" ) {
- content += "<span class='renewals-disabled'>"
- + NOT_RENEWABLE_RESTRICTION
- + "</span>";
-
- span_style = "display: none";
- span_class = "renewals-allowed";
- } else if ( oObj.can_renew_error == "overdue" ) {
- content += "<span class='renewals-disabled'>"
- + NOT_RENEWABLE_OVERDUE
- + "</span>";
-
- span_style = "display: none";
- span_class = "renewals-allowed";
- } else if ( oObj.can_renew_error == "too_soon" ) {
- content += "<span class='renewals-disabled'>"
- + NOT_RENEWABLE_TOO_SOON.format( oObj.can_renew_date )
- + "</span>";
-
- span_style = "display: none";
- span_class = "renewals-allowed";
- } else if ( oObj.can_renew_error == "auto_too_soon" ) {
- content += "<span class='renewals-disabled'>"
- + NOT_RENEWABLE_AUTO_TOO_SOON
- + "</span>";
-
- span_style = "display: none";
- span_class = "renewals-allowed";
- } else if ( oObj.can_renew_error == "auto_too_late" ) {
- content += "<span class='renewals-disabled'>"
- + NOT_RENEWABLE_AUTO_TOO_LATE
- + "</span>";
-
- span_style = "display: none";
- span_class = "renewals-allowed";
- } else if ( oObj.can_renew_error == "auto_too_much_oweing" ) {
- content += "<span class='renewals-disabled'>"
- + NOT_RENEWABLE_AUTO_TOO_MUCH_OWEING
- + "</span>";
-
- span_style = "display: none";
- span_class = "renewals-allowed";
- } else if ( oObj.can_renew_error == "auto_account_expired" ) {
- content += "<span class='renewals-disabled'>"
- + NOT_RENEWABLE_AUTO_ACCOUNT_EXPIRED
- + "</span>";
-
- span_style = "display: none";
- span_class = "renewals-allowed";
- } else if ( oObj.can_renew_error == "auto_renew" ) {
- content += "<span class='renewals-disabled'>"
- + NOT_RENEWABLE_AUTO_RENEW
- + "</span>";
-
- span_style = "display: none";
- span_class = "renewals-allowed";
- } else if ( oObj.can_renew_error == "onsite_checkout" ) {
- // Don't display something if it's an onsite checkout
- } else {
- content += "<span class='renewals-disabled'>"
- + oObj.can_renew_error
- + "</span>";
-
- span_style = "display: none";
- span_class = "renewals-allowed";
- }
-
- var can_force_renew = ( oObj.onsite_checkout == 0 ) && ( oObj.can_renew_error != "on_reserve" );
- var can_renew = ( oObj.renewals_remaining > 0 && !oObj.can_renew_error );
- if ( can_renew || can_force_renew ) {
- content += "<span class='" + span_class + "' style='" + span_style + "'>"
- + "<input type='checkbox' ";
- if ( oObj.date_due_overdue && can_renew ) {
- content += "checked='checked' ";
- }
- content += "class='renew' id='renew_" + oObj.itemnumber + "' name='renew' value='" + oObj.itemnumber +"'/>"
- + "</span>";
-
- content += "<span class='renewals'>("
- + RENEWALS_REMAINING.format( oObj.renewals_remaining, oObj.renewals_allowed )
- + ")</span>";
- }
-
- content += "</span>";
-
- return content;
- }
+ "mRender": mRenders.renew,
+ "bSortable": false
},
{
- "bSortable": false,
"bVisible": AllowCirculate ? true : false,
- "mDataProp": function ( oObj ) {
- if ( oObj.can_renew_error == "on_reserve" ) {
- return "<a href='/cgi-bin/koha/reserve/request.pl?biblionumber=" + oObj.biblionumber + "'>" + ON_HOLD + "</a>";
- } else {
- return "<input type='checkbox' class='checkin' id='checkin_" + oObj.itemnumber + "' name='checkin' value='" + oObj.itemnumber +"'></input>";
- }
- }
+ "mRender": mRenders.checkin,
+ "bSortable": false
},
{
"bVisible": exports_enabled == 1 ? true : false,
"bSortable": false,
- "mDataProp": function ( oObj ) {
- var s = "<input type='checkbox' name='itemnumbers' value='" + oObj.itemnumber + "' style='visibility:hidden;' />";
-
- s += "<input type='checkbox' class='export' id='export_" + oObj.biblionumber + "' name='biblionumbers' value='" + oObj.biblionumber + "' />";
- return s;
- }
+ "mRender": mRenders.export
}
],
"fnFooterCallback": function ( nRow, aaData, iStart, iEnd, aiDisplay ) {
@@ -488,57 +586,30 @@ $(document).ready(function() {
$("#totaldue").html(total_charge.toFixed(2));
$("#totalfine").html(total_fine.toFixed(2));
$("#totalprice").html(total_price.toFixed(2));
- },
- "bPaginate": false,
- "bProcessing": true,
- "bServerSide": false,
- "sAjaxSource": '/cgi-bin/koha/svc/checkouts',
- "fnServerData": function ( sSource, aoData, fnCallback ) {
- aoData.push( { "name": "borrowernumber", "value": borrowernumber } );
-
- $.getJSON( sSource, aoData, function (json) {
- fnCallback(json)
- } );
- },
- "fnInitComplete": function(oSettings, json) {
- // Disable rowGrouping plugin after first use
- // so any sorting on the table doesn't use it
- var oSettings = issuesTable.fnSettings();
-
- for (f = 0; f < oSettings.aoDrawCallback.length; f++) {
- if (oSettings.aoDrawCallback[f].sName == 'fnRowGrouping') {
- oSettings.aoDrawCallback.splice(f, 1);
- break;
- }
- }
-
- oSettings.aaSortingFixed = null;
-
- // Build a summary of checkouts grouped by itemtype
- var checkoutsByItype = json.aaData.reduce(function (obj, row) {
- obj[row.itemtype_description] = (obj[row.itemtype_description] || 0) + 1;
- return obj;
- }, {});
- var ul = $('<ul>');
- Object.keys(checkoutsByItype).sort().forEach(function (itype) {
- var li = $('<li>')
- .append($('<strong>').html(itype || MSG_NO_ITEMTYPE))
- .append(': ' + checkoutsByItype[itype]);
- ul.append(li);
- })
- $('<details>')
- .addClass('checkouts-by-itemtype')
- .append($('<summary>').html(MSG_CHECKOUTS_BY_ITEMTYPE))
- .append(ul)
- .insertBefore(oSettings.nTableWrapper)
- },
- }, columns_settings).rowGrouping(
- {
- iGroupingColumnIndex: 1,
- iGroupingOrderByColumnIndex: 0,
- sGroupingColumnSortDirection: "asc"
}
- );
+ }, columns_settings);
+
+ enableGrouping(issuesTable);
+
+ var groupingSwitch = $('<input type="checkbox">')
+ .attr('id', 'issues-table-row-grouping-switch')
+ .attr('checked', 'checked')
+ .css('vertical-align', 'middle')
+ .change(function() {
+ if ($(this).is(':checked')) {
+ enableGrouping(issuesTable);
+ } else {
+ disableGrouping(issuesTable);
+ }
+ });
+ $('<div></div>')
+ .css('float', 'left')
+ .css('padding', '0.3em 0.5em')
+ .css('line-height', '1.9em')
+ .append(groupingSwitch)
+ .append(' ')
+ .append('<label for="issues-table-row-grouping-switch">' + GROUP_TODAYS_CHECKOUTS + '</label>')
+ .appendTo('#issues-table_wrapper .top.pager');
if ( $("#issues-table").length ) {
$("#issues-table_processing").position({
@@ -552,153 +623,76 @@ $(document).ready(function() {
var relativesIssuesTable;
$("#relatives-issues-tab").click( function() {
if ( ! relativesIssuesTable ) {
- relativesIssuesTable = $("#relatives-issues-table").dataTable({
+ relativesIssuesTable = KohaTable("#relatives-issues-table", {
"bAutoWidth": false,
- "sDom": "rt",
- "aaSorting": [],
+ "sDom": 'C<"top pager"ilp>rt',
+ "aaSorting": [[4, "desc"]],
+ "bProcessing": true,
+ "bServerSide": ServerSideCheckoutsTables,
+ "sAjaxSource": "/cgi-bin/koha/svc/checkouts",
+ "fnServerParams": function (aoData) {
+ for (i in relatives_borrowernumbers) {
+ var borrowernumber = relatives_borrowernumbers[i];
+ aoData.push({ "name": "borrowernumber", "value": borrowernumber });
+ }
+ },
+ "bPaginate": true,
+ "sPaginationType": "four_button",
"aoColumns": [
{
- "mDataProp": "date_due",
- "bVisible": false,
+ "mData": "date_due",
+ "mRender": mRenders.dateDueFormatted
},
{
- "iDataSort": 1, // Sort on hidden unformatted date due column
- "mDataProp": function( oObj ) {
- var today = new Date();
- var due = new Date( oObj.date_due );
- if ( today > due ) {
- return "<span class='overdue'>" + oObj.date_due_formatted + "</span>";
- } else {
- return oObj.date_due_formatted;
- }
- }
+ "mData": "title",
+ "mRender": mRenders.title,
},
{
- "mDataProp": function ( oObj ) {
- title = "<span class='strong'><a href='/cgi-bin/koha/catalogue/detail.pl?biblionumber="
- + oObj.biblionumber
- + "'>"
- + oObj.title.escapeHtml();
-
- $.each(oObj.subtitle, function( index, value ) {
- title += " " + value.subfield.escapeHtml();
- });
-
- if ( oObj.enumchron ) {
- title += " (" + oObj.enumchron.escapeHtml() + ")";
- }
-
- title += "</a></span>";
-
- if ( oObj.author ) {
- title += " " + BY.replace( "_AUTHOR_", " " + oObj.author.escapeHtml() );
- }
-
- if ( oObj.itemnotes ) {
- var span_class = "";
- if ( $.datepicker.formatDate('yy-mm-dd', new Date(oObj.issuedate) ) == ymd ) {
- span_class = "circ-hlt";
- }
- title += " - <span class='" + span_class + "'>" + oObj.itemnotes.escapeHtml() + "</span>"
- }
-
- if ( oObj.itemnotes_nonpublic ) {
- var span_class = "";
- if ( $.datepicker.formatDate('yy-mm-dd', new Date(oObj.issuedate) ) == ymd ) {
- span_class = "circ-hlt";
- }
- title += " - <span class='" + span_class + "'>" + oObj.itemnotes_nonpublic.escapeHtml() + "</span>"
- }
-
- var onsite_checkout = '';
- if ( oObj.onsite_checkout == 1 ) {
- onsite_checkout += " <span class='onsite_checkout'>(" + INHOUSE_USE + ")</span>";
- }
-
- title += " "
- + "<a href='/cgi-bin/koha/catalogue/moredetail.pl?biblionumber="
- + oObj.biblionumber
- + "&itemnumber="
- + oObj.itemnumber
- + "#"
- + oObj.itemnumber
- + "'>"
- + oObj.barcode.escapeHtml()
- + "</a>"
- + onsite_checkout;
-
- return title;
- },
- "sType": "anti-the"
+ "mData": "itemtype",
+ "mRender": mRenders.itemtype
},
{
- "mDataProp": function ( oObj ) {
- return oObj.itemtype_description.escapeHtml();
- }
+ "mData": "ccode",
+ "mRender": mRenders.collection
},
{
- "mDataProp": function ( oObj ) {
- return oObj.collection.escapeHtml();
- }
+ "mData": "location",
+ "mRender": mRenders.location
},
{
- "mDataProp": function ( oObj ) {
- return oObj.location.escapeHtml();
- }
+ "mData": "issuedate",
+ "mRender": mRenders.issuedate
},
- { "mDataProp": "issuedate_formatted" },
{
- "mDataProp": function ( oObj ) {
- return oObj.branchname.escapeHtml();
- }
+ "mData": "branchcode",
+ "mRender": mRenders.branch
},
{
- "mDataProp": function ( oObj ) {
- return oObj.itemcallnumber.escapeHtml();
- }
+ "mData": "itemcallnumber",
+ "mRender": mRenders.itemcallnumber
},
{
- "mDataProp": function ( oObj ) {
- if ( ! oObj.charge ) oObj.charge = 0;
- return parseFloat(oObj.charge).toFixed(2);
- }
+ "mData": "charge",
+ "mRender": mRenders.charge,
+ "bSortable": ServerSideCheckoutsTables ? false : true
},
{
- "mDataProp": function ( oObj ) {
- if ( ! oObj.fine ) oObj.fine = 0;
- return parseFloat(oObj.fine).toFixed(2);
- }
+ "mData": "fine",
+ "mRender": mRenders.fine,
+ "bSortable": ServerSideCheckoutsTables ? false : true
},
{
- "mDataProp": function ( oObj ) {
- if ( ! oObj.price ) oObj.price = 0;
- return parseFloat(oObj.price).toFixed(2);
- }
+ "mData": "replacementprice",
+ "mRender": mRenders.price,
+ "bSortable": ServerSideCheckoutsTables ? false : true
},
{
- "mDataProp": function( oObj ) {
- return "<a href='/cgi-bin/koha/members/moremember.pl?borrowernumber=" + oObj.borrowernumber + "'>"
- + oObj.borrower.firstname.escapeHtml()
- + " " +
- oObj.borrower.surname.escapeHtml()
- + " (" + oObj.borrower.cardnumber.escapeHtml() + ")</a>"
- }
- },
- ],
- "bPaginate": false,
- "bProcessing": true,
- "bServerSide": false,
- "sAjaxSource": '/cgi-bin/koha/svc/checkouts',
- "fnServerData": function ( sSource, aoData, fnCallback ) {
- $.each(relatives_borrowernumbers, function( index, value ) {
- aoData.push( { "name": "borrowernumber", "value": value } );
- });
-
- $.getJSON( sSource, aoData, function (json) {
- fnCallback(json)
- } );
- },
- });
+ "mData": "borrowernumber",
+ "mRender": mRenders.patron,
+ "bSortable": ServerSideCheckoutsTables ? false : true
+ }
+ ]
+ }, relatives_columns_settings);
}
});
@@ -718,4 +712,6 @@ $(document).ready(function() {
}
} ).prop('checked', false);
}
- });
+});
+
+})(jQuery);
diff --git a/svc/checkouts b/svc/checkouts
index 9a1b3a5648..e97fc4afc3 100755
--- a/svc/checkouts
+++ b/svc/checkouts
@@ -27,6 +27,7 @@ use C4::Biblio qw(GetMarcBiblio GetFrameworkCode GetRecordValue );
use C4::Circulation qw(GetIssuingCharges CanBookBeRenewed GetRenewCount GetSoonestRenewDate);
use C4::Overdues qw(GetFine);
use C4::Context;
+use C4::Utils::DataTables;
use Koha::AuthorisedValues;
use Koha::DateUtils;
@@ -45,26 +46,33 @@ unless (haspermission($userid, { circulate => 'circulate_remaining_permissions'
exit 0;
}
-my @sort_columns = qw/date_due title itype issuedate branchcode itemcallnumber/;
-
my @borrowernumber = $input->multi_param('borrowernumber');
-my $offset = $input->param('iDisplayStart');
-my $results_per_page = $input->param('iDisplayLength') || -1;
-
-my $sorting_column = $input->param('iSortCol_0') || q{};
-$sorting_column = ( $sorting_column && $sort_columns[$sorting_column] ) ? $sort_columns[$sorting_column] : 'issuedate';
-
-my $sorting_direction = $input->param('sSortDir_0') || q{};
-$sorting_direction = $sorting_direction eq 'asc' ? 'asc' : 'desc';
-
-$results_per_page = undef if ( $results_per_page == -1 );
-
-binmode STDOUT, ":encoding(UTF-8)";
-print $input->header( -type => 'text/plain', -charset => 'UTF-8' );
+my $offset = $input->param('iDisplayStart');
+my $count = $input->param('iDisplayLength');
+
+my %params = dt_get_params($input);
+my $orderby = dt_build_orderby(\%params);
+
+my $todaysIssuesDefaultSortOrder =
+ C4::Context->preference('todaysIssuesDefaultSortOrder');
+my $previousIssuesDefaultSortOrder =
+ C4::Context->preference('previousIssuesDefaultSortOrder');
+
+# Default sort when user hasn't clicked on a column header yet.
+# When row grouping is enabled, DataTables ask to sort on issued_today column,
+# so we need to treat this case the same as the "no sorting" case
+if (!$orderby || $orderby =~ m/ORDER BY issued_today desc\s*$/) {
+ $orderby = qq{
+ ORDER BY
+ issued_today DESC,
+ CASE WHEN issued_today = 0 THEN date_due END $previousIssuesDefaultSortOrder,
+ CASE WHEN issued_today != 0 THEN date_due END $todaysIssuesDefaultSortOrder
+ };
+}
my @parameters;
my $sql = '
- SELECT
+ SELECT SQL_CALC_FOUND_ROWS
issuedate,
date_due,
date_due < now() as date_due_overdue,
@@ -102,7 +110,7 @@ my $sql = '
location,
items.enumchron,
- DATEDIFF( issuedate, CURRENT_DATE() ) AS not_issued_today
+ DATEDIFF( issuedate, CURRENT_DATE() ) = 0 AS issued_today
FROM issues
LEFT JOIN items USING ( itemnumber )
LEFT JOIN biblio USING ( biblionumber )
@@ -110,27 +118,33 @@ my $sql = '
LEFT JOIN borrowers USING ( borrowernumber )
LEFT JOIN branches ON ( issues.branchcode = branches.branchcode )
LEFT JOIN branches branches2 ON ( items.homebranch = branches2.branchcode )
- WHERE borrowernumber
+ WHERE
';
+my $borrowernumber_sql = 'borrowernumber';
if ( @borrowernumber == 1 ) {
- $sql .= '= ?';
-}
-else {
- $sql .= ' IN (' . join( ',', ('?') x @borrowernumber ) . ') ';
+ $borrowernumber_sql .= ' = ?';
+} else {
+ $borrowernumber_sql .= ' IN (' . join( ',', ('?') x @borrowernumber ) . ') ';
}
+$sql .= $borrowernumber_sql;
push( @parameters, @borrowernumber );
-$sql .= " ORDER BY $sorting_column $sorting_direction ";
+$sql .= " $orderby";
+
+if ($count && $count > 0) {
+ $sql .= " LIMIT ?,?";
+ push @parameters, $offset, $count;
+}
my $dbh = C4::Context->dbh();
my $sth = $dbh->prepare($sql);
$sth->execute(@parameters);
+my ($iTotalDisplayRecords) = $dbh->selectrow_array('SELECT FOUND_ROWS()');
my $item_level_itypes = C4::Context->preference('item-level_itypes');
-my @checkouts_today;
-my @checkouts_previous;
+my @checkouts;
while ( my $c = $sth->fetchrow_hashref() ) {
my ($charge) = GetIssuingCharges( $c->{itemnumber}, $c->{borrowernumber} );
my $fine = GetFine( $c->{itemnumber}, $c->{borrowernumber} );
@@ -227,36 +241,25 @@ while ( my $c = $sth->fetchrow_hashref() ) {
firstname => $c->{firstname},
cardnumber => $c->{cardnumber},
},
- issued_today => !$c->{not_issued_today},
+ issued_today => $c->{issued_today} ? JSON::true : JSON::false,
};
- if ( $c->{not_issued_today} ) {
- push( @checkouts_previous, $checkout );
- }
- else {
- push( @checkouts_today, $checkout );
- }
+ push @checkouts, $checkout;
}
+binmode STDOUT, ":encoding(UTF-8)";
+print $input->header( -type => 'application/json', -charset => 'UTF-8' );
-@checkouts_today = sort { $a->{timestamp} cmp $b->{timestamp} } @checkouts_today;
-@checkouts_today = reverse(@checkouts_today)
- unless ( C4::Context->preference('todaysIssuesDefaultSortOrder') eq 'desc' );
-
-@checkouts_previous = sort { $a->{date_due} cmp $b->{date_due} } @checkouts_previous;
-@checkouts_previous = reverse(@checkouts_previous)
- if ( C4::Context->preference('previousIssuesDefaultSortOrder') eq 'desc' );
-
-my @checkouts = ( @checkouts_today, @checkouts_previous );
-
-my $i = 1;
-map { $_->{sort_order} = $i++ } @checkouts;
-
+my $sEcho = $input->param('sEcho');
+my ($iTotalRecords) = $dbh->selectrow_array(
+ "SELECT COUNT(*) FROM issues WHERE $borrowernumber_sql", undef,
+ @borrowernumber);
-my $data;
-$data->{'iTotalRecords'} = scalar @checkouts;
-$data->{'iTotalDisplayRecords'} = scalar @checkouts;
-$data->{'sEcho'} = $input->param('sEcho') || undef;
-$data->{'aaData'} = \@checkouts;
+my $response = {
+ iTotalRecords => $iTotalRecords,
+ iTotalDisplayRecords => $iTotalDisplayRecords,
+ sEcho => $sEcho,
+ aaData => \@checkouts,
+};
-print to_json($data);
+print to_json($response);
--
2.17.1