-
-
-
-
- Cancel selected ( )
+
[% SET hold_cancellation = AuthorisedValues.GetAuthValueDropbox('HOLD_CANCELLATION') %]
@@ -1360,137 +1356,75 @@
[% FOREACH biblioloo IN biblioloop %]
- [% IF ( biblioloo.reserveloop ) %]
+ [% IF ( biblioloo.total_holds ) %]
[% IF ( multi_hold ) %]
[% biblioloo.title | html %]
- [% biblioloo.reserveloop.size | html %] [% tn('Hold', 'Holds', biblioloo.reserveloop.size) | $raw %]
+ [% biblioloo.total_holds | html %] [% tn('Hold', 'Holds', biblioloo.total_holds) | $raw %]
[% END %]
[% IF Koha.Preference('HoldsSplitQueue') == 'branch' %]
-
- [% SET branchcodes = [] %]
-
- [% FOREACH h IN biblioloo.reserveloop %]
- [% branchcodes.push( h.branchcode ) %]
- [% END %]
- [% branchcodes = branchcodes.unique %]
- [% IF ( branchcodes.empty ) %]
-
There are no holds on this title.
+ [% IF biblioloo.hold_branches.empty %]
+
+
Any library
+ [% INCLUDE holds_table.inc biblio_id=biblioloo.biblionumber total_holds=biblioloo.total_holds split_data="any" %]
+
[% ELSE %]
-
- [% FOREACH b IN branchcodes.sort %]
- [% SET holds_by_branch = [] %]
- [% FOREACH h IN biblioloo.reserveloop %]
- [% IF h.branchcode == b %]
- [% holds_by_branch.push( h ) %]
- [% END %]
- [% END %]
+ [% FOREACH b IN biblioloo.hold_branches %]
[% Branches.GetName( b ) | html %]
- [% INCLUDE holds_table.inc holds=holds_by_branch %]
+ [% INCLUDE holds_table.inc biblio_id=biblioloo.biblionumber total_holds=biblioloo.total_holds split_data=b %]
- [% END # /FOREACh b %]
- [% END # /IF ( branchcodes.empty ) %]
+ [% END %]
+ [% END # /IF hold_branches.empty %]
[% ELSIF Koha.Preference('HoldsSplitQueue') == 'itemtype' %]
- [% SET itemtypes = [] %]
-
- [% FOREACH h IN biblioloo.reserveloop %]
- [% SET hold_itemtype = h.object.item.effective_itemtype || h.itemtype %]
- [% itemtypes.push( hold_itemtype ) %]
- [% END %]
- [% itemtypes = itemtypes.unique %]
- [% IF ( itemtypes.empty ) %]
-
There are no holds on this title.
+ [% IF biblioloo.hold_itemtypes.empty %]
+
+
Any item type
+ [% INCLUDE holds_table.inc biblio_id=biblioloo.biblionumber total_holds=biblioloo.total_holds split_data="any" %]
+
[% ELSE %]
-
- [% FOREACH i IN itemtypes.sort %]
- [% SET holds_by_itemtype = [] %]
- [% FOREACH h IN biblioloo.reserveloop %]
- [% SET hold_itemtype = h.object.item.effective_itemtype || h.itemtype %]
- [% IF hold_itemtype == i %]
- [% holds_by_itemtype.push( h ) %]
- [% END %]
- [% END %]
-
+ [% FOREACH i IN biblioloo.hold_itemtypes %]
- [% IF i %]
+ [% IF i && i != 'any' %]
[% ItemTypes.GetDescription( i ) | html %]
[% ELSE %]
Any item type
[% END %]
- [% INCLUDE holds_table.inc holds=holds_by_itemtype %]
+ [% INCLUDE holds_table.inc biblio_id=biblioloo.biblionumber total_holds=biblioloo.total_holds split_data=i %]
- [% END # /FOREACH i %]
- [% END # /IF ( itemtypes.empty ) %]
+ [% END %]
+ [% END # /IF hold_split.empty %]
[% ELSIF Koha.Preference('HoldsSplitQueue') == 'branch_itemtype' %]
- [% SET branchcodes = [] %]
- [% FOREACH h IN biblioloo.reserveloop %]
- [% branchcodes.push( h.branchcode ) %]
- [% END %]
- [% branchcodes = branchcodes.unique %]
- [% IF ( branchcodes.empty ) %]
-
There are no holds on this title.
- [% ELSE %]
-
- [% FOREACH b IN branchcodes.sort %]
-
-
[% Branches.GetName( b ) | html %]
- [% SET holds_by_branch = [] %]
- [% FOREACH h IN biblioloo.reserveloop %]
- [% IF h.branchcode == b %]
- [% holds_by_branch.push( h ) %]
+ [% FOREACH b IN biblioloo.hold_branches %]
+
+
[% Branches.GetName( b ) | html %]
+ [% FOREACH i IN biblioloo.hold_itemtypes %]
+
+ [% IF i && i != 'any' %]
+
[% ItemTypes.GetDescription( i ) | html %]
+ [% ELSE %]
+
Any item type
[% END %]
- [% END %]
-
- [% SET itemtypes = [] %]
- [% FOREACH h IN holds_by_branch %]
- [% SET hold_itemtype = h.object.item.effective_itemtype || h.itemtype %]
- [% itemtypes.push( hold_itemtype ) %]
- [% END %]
- [% itemtypes = itemtypes.unique %]
-
- [% FOREACH i IN itemtypes.sort %]
-
-
- [% IF i %]
- [% ItemTypes.GetDescription( i ) | html %]
- [% ELSE %]
- Any item type
- [% END %]
-
-
- [% SET holds_by_itemtype = [] %]
- [% FOREACH h IN holds_by_branch %]
- [% SET hold_itemtype = h.object.item.effective_itemtype || h.itemtype %]
- [% IF hold_itemtype == i %]
- [% holds_by_itemtype.push( h ) %]
- [% END %]
- [% END %]
- [% INCLUDE holds_table.inc holds=holds_by_itemtype %]
-
-
- [% END %]
-
-
- [% END # /FOREACH b %]
- [% END # /IF ( branchcodes.empty ) %]
- [% ELSE %]
-
- [% IF ( biblioloo.reserveloop.size ) %]
- [% INCLUDE holds_table.inc holds=biblioloo.reserveloop %]
- [% ELSE %]
-
There are no holds on this title.
+ [% SET split_data = b _ "_" _ i %]
+ [% INCLUDE holds_table.inc biblio_id=biblioloo.biblionumber total_holds=biblioloo.total_holds split_data=split_data %]
+
+ [% END %]
+
[% END %]
+ [% ELSE %]
+ [% INCLUDE holds_table.inc biblio_id=biblioloo.biblionumber total_holds=biblioloo.total_holds split_data="any" %]
[% END # /IF HoldsSplitQueue %]
- [% END # /IF biblioloo.reserveloop %]
+ [% ELSE %]
+
There are no holds on this title.
+ [% END # /IF ( biblioloo.total_holds ) %]
[% END # FOREACH biblioloo %]
@@ -1605,6 +1539,9 @@
[% INCLUDE 'datatables.inc' %]
[% INCLUDE 'calendar.inc' %]
[% INCLUDE 'select2.inc' %]
+
[% Asset.js("js/holds.js") | $raw %]
[% Asset.js("js/hold-group.js") | $raw %]
@@ -1613,8 +1550,16 @@
[% SET url_biblio_params = url_biblio_params _ "&multi_hold=1" %]
[% END %]
[% END %]
-
[% END %]
[% INCLUDE 'intranet-bottom.inc' %]
diff --git a/koha-tmpl/intranet-tmpl/prog/js/datatables.js b/koha-tmpl/intranet-tmpl/prog/js/datatables.js
index 7b6dde8a7c..b3cd2441d0 100644
--- a/koha-tmpl/intranet-tmpl/prog/js/datatables.js
+++ b/koha-tmpl/intranet-tmpl/prog/js/datatables.js
@@ -1456,6 +1456,9 @@ function update_search_description(
emptyTable: options.emptyTable
? options.emptyTable
: __("No data available in table"),
+ infoFiltered: options.infoFiltered
+ ? options.infoFiltered
+ : __("(filtered from _MAX_ total entries)"),
},
},
options
diff --git a/koha-tmpl/intranet-tmpl/prog/js/holds.js b/koha-tmpl/intranet-tmpl/prog/js/holds.js
index 5e6537fa72..e89bdc8d4d 100644
--- a/koha-tmpl/intranet-tmpl/prog/js/holds.js
+++ b/koha-tmpl/intranet-tmpl/prog/js/holds.js
@@ -791,13 +791,13 @@ $(document).ready(function () {
}
});
- if (!patron_page) {
- $(".holds_table .select_hold_all").each(function () {
- var table = $(this).parents(".holds_table");
- var count = $(".select_hold:not(:checked)", table).length;
- $(".select_hold_all", table).prop("checked", !count);
- });
- }
+ // if (!patron_page) {
+ // $(".holds_table .select_hold_all").each(function () {
+ // var table = $(this).parents(".holds_table");
+ // var count = $(".select_hold:not(:checked)", table).length;
+ // $(".select_hold_all", table).prop("checked", !count);
+ // });
+ // }
function updateSelectedHoldsButtonCounters() {
$(".move_selected_holds").html(
@@ -808,20 +808,15 @@ $(document).ready(function () {
$(".selected_holds_count").html(
$(".holds_table .select_hold:checked").length
);
- if (patron_page) {
- var selectedHolds = $(".holds_table .select_hold:checked");
- var hasSelectedHolds = selectedHolds.length > 0;
- var hasMultipleSelectedHolds = selectedHolds.length >= 2;
+ var selectedHolds = $(".holds_table .select_hold:checked");
+ var hasSelectedHolds = selectedHolds.length > 0;
+ var hasMultipleSelectedHolds = selectedHolds.length >= 2;
- $(".cancel_selected_holds, .suspend_selected_holds").prop(
- "disabled",
- !hasSelectedHolds
- );
- $(".group_selected_holds").prop(
- "disabled",
- !hasMultipleSelectedHolds
- );
- }
+ $(".cancel_selected_holds, .suspend_selected_holds").prop(
+ "disabled",
+ !hasSelectedHolds
+ );
+ $(".group_selected_holds").prop("disabled", !hasMultipleSelectedHolds);
}
function updateMoveButtons(table) {
@@ -841,96 +836,73 @@ $(document).ready(function () {
$(".move_selected_holds").prop("disabled", !checked_count);
}
- updateSelectedHoldsButtonCounters();
-
- $(".holds_table .select_hold_all").click(function () {
- var table;
- if (!patron_page) {
- table = $(this).parents(".holds_table");
- } else {
- table = $(".holds_table:not(.fixedHeader-floating)");
- }
-
- var checked_count = $(".select_hold:checked", table).length;
- $(".select_hold", table).prop("checked", !checked_count);
- $(this).prop("checked", !checked_count);
-
- updateMoveButtons(table);
-
+ if (holds_table_patron_page()) {
updateSelectedHoldsButtonCounters();
- $("#cancel_hold_alert").html(
- MSG_CANCEL_ALERT.format(
- $(".holds_table .select_hold:checked").length
- )
- );
- $("#cancel_hold_alert").show();
- localStorage.selectedHolds =
- "[" +
- $(".holds_table .select_hold:checked")
- .toArray()
- .map(el =>
- JSON.stringify({
- hold: $(el).data("id"),
- borrowernumber: $(el).data("borrowernumber"),
- biblionumber: $(el).data("biblionumber"),
- })
+
+ $(".holds_table .select_hold_all").click(function () {
+ var table = $(".holds_table:not(.fixedHeader-floating)");
+
+ var checked_count = $(".select_hold:checked", table).length;
+ $(".select_hold", table).prop("checked", !checked_count);
+ $(this).prop("checked", !checked_count);
+
+ updateMoveButtons(table);
+
+ updateSelectedHoldsButtonCounters();
+ $("#cancel_hold_alert").html(
+ MSG_CANCEL_ALERT.format(
+ $(".holds_table .select_hold:checked").length
)
- .join(",") +
- "]";
- });
-
- $(".holds_table").on("click", ".select_hold", function () {
- var table = $(this).parents(".holds_table");
- var count = $(".select_hold:not(:checked)", table).length;
- $(".select_hold_all", table).prop("checked", !count);
-
- updateMoveButtons(table);
-
- updateSelectedHoldsButtonCounters();
- $("#cancel_hold_alert").html(
- MSG_CANCEL_ALERT.format(
- $(".holds_table .select_hold:checked").length
- )
- );
- $("#cancel_hold_alert").show();
- localStorage.selectedHolds =
- "[" +
- $(".holds_table .select_hold:checked")
- .toArray()
- .map(el =>
- JSON.stringify({
- hold: $(el).data("id"),
- borrowernumber: $(el).data("borrowernumber"),
- biblionumber: $(el).data("biblionumber"),
- })
- )
- .join(",") +
- "]";
- });
-
- $(".cancel_selected_holds").click(function (e) {
- e.preventDefault();
- if ($(".holds_table .select_hold:checked").length) {
- $("#cancel_modal_form #inputs").empty();
- if (!patron_page) {
- biblionumbers.forEach(function (biblionumber) {
- $("#cancel_modal_form #inputs").append(
- '
'
- );
- });
- $("#cancel_modal_form #inputs").append(
- '
'
- );
- let hold_ids = $(".holds_table .select_hold:checked")
+ );
+ $("#cancel_hold_alert").show();
+ localStorage.selectedHolds =
+ "[" +
+ $(".holds_table .select_hold:checked")
.toArray()
- .map(el => $(el).data("id"))
- .join(",");
- $("#cancel_modal_form #inputs").append(
- '
'
- );
- } else {
+ .map(el =>
+ JSON.stringify({
+ hold: $(el).data("id"),
+ borrowernumber: $(el).data("borrowernumber"),
+ biblionumber: $(el).data("biblionumber"),
+ })
+ )
+ .join(",") +
+ "]";
+ });
+
+ $(".holds_table").on("click", ".select_hold", function () {
+ var table = $(this).parents(".holds_table");
+ var count = $(".select_hold:not(:checked)", table).length;
+ $(".select_hold_all", table).prop("checked", !count);
+
+ updateMoveButtons(table);
+
+ updateSelectedHoldsButtonCounters();
+ $("#cancel_hold_alert").html(
+ MSG_CANCEL_ALERT.format(
+ $(".holds_table .select_hold:checked").length
+ )
+ );
+ $("#cancel_hold_alert").show();
+ localStorage.selectedHolds =
+ "[" +
+ $(".holds_table .select_hold:checked")
+ .toArray()
+ .map(el =>
+ JSON.stringify({
+ hold: $(el).data("id"),
+ borrowernumber: $(el).data("borrowernumber"),
+ biblionumber: $(el).data("biblionumber"),
+ })
+ )
+ .join(",") +
+ "]";
+ });
+
+ $(".cancel_selected_holds").click(function (e) {
+ e.preventDefault();
+ if ($(".holds_table .select_hold:checked").length) {
+ $("#cancel_modal_form #inputs").empty();
$("#cancel_modal_form #inputs").append(
'
'
);
@@ -950,14 +922,12 @@ $(document).ready(function () {
JSON.parse(hold_data).forEach(function (hold) {
_append_patron_page_cancel_hold_modal_data(hold);
});
+ delete localStorage.selectedHolds;
+ $("#cancelModal").modal("show");
}
-
- delete localStorage.selectedHolds;
- $("#cancelModal").modal("show");
- }
- return false;
- });
-
+ return false;
+ });
+ }
$("#itemSearchForm").on("submit", function (event) {
event.preventDefault();
$("#move_hold_item_confirm").prop("disabled", true);
@@ -1076,18 +1046,26 @@ $(document).ready(function () {
$("#itemResultMessage").empty();
$("#move_hold_item_selection table tbody").empty();
$("#moveHoldItemModal").modal("show");
- $(".select_hold:checked").each(function () {
- let reserve_id = $(this).data("id");
- let reserve_biblionumber = $(this).data("biblionumber");
- let reserve_itemnumber = $(this).data("itemnumber");
- let item_level_hold = $(this).data("item_level_hold");
- let item_waiting = $(this).data("waiting");
- let item_intransit = $(this).data("intransit");
- let error_message = $(this).data("item_level_hold")
- ? ""
- : __(
- "Cannot move a waiting, in transit, or record level hold"
- );
+ const selectedHolds =
+ JSON.parse(localStorage.selectedHolds) ||
+ $(".select_hold:checked");
+ $(selectedHolds).each(function () {
+ let reserve_id = this.hold || $(this).data("id");
+ let reserve_biblionumber =
+ this.biblionumber || $(this).data("biblionumber");
+ let reserve_itemnumber =
+ this.itemnumber || $(this).data("itemnumber");
+ let item_level_hold =
+ this.item_level_hold || $(this).data("item_level_hold");
+ let item_waiting = this.waiting || $(this).data("waiting");
+ let item_intransit =
+ this.intransit || $(this).data("intransit");
+ let error_message =
+ this.item_level_hold || $(this).data("item_level_hold")
+ ? ""
+ : __(
+ "Cannot move a waiting, in transit, or record level hold"
+ );
let found_status = $(this).data("found");
if (item_level_hold && (!item_waiting || !item_intransit)) {
$("#move_hold_item_selection table").append(
@@ -1105,23 +1083,31 @@ $(document).ready(function () {
$(".move_hold_biblio").click(function (e) {
e.preventDefault();
$("#move_hold_biblio_confirm").prop("disabled", true);
- if ($(".holds_table .select_hold:checked").length) {
+ const selectedHolds =
+ JSON.parse(localStorage.selectedHolds || "[]") ||
+ $(".select_hold:checked");
+ if (selectedHolds.length) {
$("#biblioResultMessage").empty();
$("#move_hold_biblio_selection table tbody").empty();
$("#moveHoldBiblioModal").modal("show");
- $(".select_hold:checked").each(function () {
- let reserve_id = $(this).data("id");
- let reserve_biblionumber = $(this).data("biblionumber");
- let reserve_itemnumber = $(this).data("itemnumber");
- let item_level_hold = $(this).data("item_level_hold");
- let item_status = $(this).data("status");
- let item_waiting = $(this).data("waiting");
- let item_intransit = $(this).data("intransit");
- let error_message = $(this).data("item_level_hold")
- ? __(
- "Cannot move a waiting, in transit, or item level hold"
- )
- : "";
+ $(selectedHolds).each(function () {
+ let reserve_id = this.hold || $(this).data("id");
+ let reserve_biblionumber =
+ this.biblionumber || $(this).data("biblionumber");
+ let reserve_itemnumber =
+ this.itemnumber || $(this).data("itemnumber");
+ let item_level_hold =
+ this.item_level_hold || $(this).data("item_level_hold");
+ let item_status = this.status || $(this).data("status");
+ let item_waiting = this.waiting || $(this).data("waiting");
+ let item_intransit =
+ this.intransit || $(this).data("intransit");
+ let error_message =
+ this.item_level_hold || $(this).data("item_level_hold")
+ ? __(
+ "Cannot move a waiting, in transit, or item level hold"
+ )
+ : "";
let found_status = $(this).data("found");
if (!item_level_hold && (!item_waiting || !item_intransit)) {
$("#move_hold_biblio_selection table").append(
@@ -1226,12 +1212,15 @@ $(document).ready(function () {
}),
});
}
-
- $("#cancelModal").on("hidden.bs.modal", function () {
- $("#cancelModal .modal-body .alert-danger").remove();
- $("#cancelModalConfirmBtn").prop("disabled", false);
- holdsTable.api().ajax.reload();
- });
+ if (holds_table_patron_page()) {
+ $("#cancelModal").on("hidden.bs.modal", function () {
+ $("#cancelModal .modal-body .alert-danger").remove();
+ $("#cancelModalConfirmBtn").prop("disabled", false);
+ if (holdsTable) {
+ holdsTable.api().ajax.reload();
+ }
+ });
+ }
$("#group-modal-submit").click(function (e) {
e.preventDefault();
@@ -1303,3 +1292,1099 @@ $(document).ready(function () {
);
}
});
+
+async function load_patron_holds_table(biblio_id, split_data) {
+ const { name: split_name, value: split_value } = split_data;
+ let table_class = `patron_holds_table_${biblio_id}_${split_value}`;
+ const table_id = `#` + table_class;
+ let url = `/api/v1/holds/?q={"me.biblio_id":${biblio_id}`;
+
+ if (split_name === "branch" && split_value !== "any") {
+ url += `, "me.pickup_library_id":"${split_value}"`;
+ } else if (split_name === "itemtype" && split_value !== "any") {
+ url += `, "me.itemtype":"${split_value}"`;
+ } else if (split_name === "branch_itemtype") {
+ const [branch, itemtype] = split_value.split("_");
+ url +=
+ itemtype === "any"
+ ? `, "me.pickup_library_id":"${branch}"`
+ : `, "me.pickup_library_id":"${branch}", "me.itemtype":"${itemtype}"`;
+ }
+
+ url += "}";
+ const totalHolds = $(table_id).data("total-holds");
+ const totalHoldsSelect = parseInt(totalHolds) + 1;
+ var holdsQueueTable = $(table_id).kohaTable(
+ {
+ language: {
+ infoFiltered: "",
+ },
+ ajax: {
+ url: url,
+ },
+ embed: ["patron", "item", "item_group", "item_level_holds"],
+ columnDefs: [
+ {
+ targets: [2, 3],
+ className: "dt-body-nowrap",
+ },
+ {
+ targets: [3, 9],
+ visible: CAN_user_reserveforothers_modify_holds_priority
+ ? true
+ : false,
+ },
+ ],
+ columns: [
+ {
+ data: "hold_id",
+ orderable: false,
+ searchable: false,
+ render: function (data, type, row, meta) {
+ return (
+ '
'
+ );
+ },
+ },
+ {
+ data: "priority",
+ orderable: true,
+ searchable: false,
+ render: function (data, type, row, meta) {
+ let select =
+ '
';
+ selected = " selected='selected' ";
+ value = "T";
+ desc = "In transit";
+ } else if (data == i && row.status == "P") {
+ select += '" disabled="disabled">';
+ selected = " selected='selected' ";
+ value = "P";
+ desc = "In processing";
+ } else if (data == i && row.status == "W") {
+ select += '" disabled="disabled">';
+ selected = " selected='selected' ";
+ value = "W";
+ desc = "Waiting";
+ } else if (data == i && !row.status) {
+ select += '">';
+ selected = " selected='selected' ";
+ value = data;
+ desc = data;
+ } else {
+ if (i != 0) {
+ select += '">';
+ value = i;
+ desc = i;
+ } else {
+ select += '">';
+ }
+ }
+ if (value) {
+ select +=
+ '" +
+ desc +
+ " ";
+ }
+ }
+ } else {
+ if (row.status == "T") {
+ select +=
+ '" disabled="disabled">In transit ';
+ } else if (row.status == "P") {
+ select +=
+ '" disabled="disabled">
In processing ';
+ } else if (row.status == "W") {
+ select +=
+ '" disabled="disabled">
Waiting ';
+ } else {
+ if (
+ HoldsSplitQueue !== "nothing" &&
+ HoldsSplitQueueNumbering === "virtual"
+ ) {
+ let virtualPriority =
+ meta.settings._iDisplayStart +
+ meta.row +
+ 1;
+ select +=
+ '" disabled="disabled">
' +
+ virtualPriority +
+ " ";
+ } else {
+ select +=
+ '" disabled="disabled">
' +
+ data +
+ " ";
+ }
+ }
+ }
+ select += "";
+ return select;
+ },
+ },
+ {
+ data: "",
+ orderable: false,
+ searchable: false,
+ render: function (data, type, row, meta) {
+ if (row.status) {
+ return null;
+ }
+ let buttons =
+ '
';
+ buttons +=
+ '
';
+ buttons +=
+ '
';
+ buttons +=
+ '
';
+ return buttons;
+ },
+ },
+ {
+ data: "patron.cardnumber",
+ orderable: true,
+ searchable: true,
+ render: function (data, type, row, meta) {
+ if (data == null) {
+ let library = libraries.find(
+ library => library._id == row.pickup_library_id
+ );
+ return __("A patron from library %s").format(
+ library.name
+ );
+ } else {
+ return (
+ '
' +
+ data +
+ " "
+ );
+ }
+ },
+ },
+ {
+ data: "notes",
+ orderable: false,
+ searchable: false,
+ render: function (data, type, row, meta) {
+ return data;
+ },
+ },
+ {
+ data: "hold_date",
+ orderable: true,
+ searchable: false,
+ render: function (data, type, row, meta) {
+ if (AllowHoldDateInFuture) {
+ return (
+ '
'
+ );
+ } else {
+ return $date(data);
+ }
+ },
+ },
+ {
+ data: "expiration_date",
+ orderable: true,
+ searchable: false,
+ render: function (data, type, row, meta) {
+ return (
+ '
'
+ );
+ },
+ },
+ {
+ data: "pickup_library_id",
+ orderable: true,
+ searchable: false,
+ render: function (data, type, row, meta) {
+ var branchSelect =
+ "
';
+ var libraryname;
+ for (var i = 0; i < libraries.length; i++) {
+ var selectedbranch;
+ var setbranch;
+ if (libraries[i]._id == data) {
+ selectedbranch = " selected='selected' ";
+ setbranch = __(" (current) ");
+ libraryname = libraries[i]._str;
+ } else if (libraries[i].pickup_location == false) {
+ continue;
+ } else {
+ selectedbranch = "";
+ setbranch = "";
+ }
+ branchSelect +=
+ '" +
+ libraries[i]._str.escapeHtml() +
+ setbranch +
+ " ";
+ }
+ branchSelect += " ";
+ if (row.status == "T") {
+ return __(
+ "Item being transferred to
%s "
+ ).format(libraryname);
+ } else if (row.status == "P") {
+ return __(
+ "Item being processed at
%s "
+ ).format(libraryname);
+ } else if (row.status == "W") {
+ return __(
+ "Item waiting at
%s since %s"
+ ).format(libraryname, $date(row.waiting_date));
+ } else {
+ return branchSelect;
+ }
+ },
+ },
+ {
+ data: "",
+ orderable: false,
+ searchable: false,
+ render: function (data, type, row, meta) {
+ if (row.status) {
+ return (
+ '
' +
+ row.item.external_id +
+ " "
+ );
+ } else if (row.item_id && row.item_level) {
+ let barcode = row.item.external_id
+ ? row.item.external_id
+ : __("No barcode");
+ if (row.item_level_holds >= 2) {
+ let link =
+ '
' +
+ (row.item.external_id
+ ? row.item.external_id.escapeHtml()
+ : __("No barcode")) +
+ " ";
+ return __("Only item") + " " + link;
+ } else {
+ let select =
+ '
';
+ select +=
+ '' +
+ __("Only item") +
+ " " +
+ barcode +
+ " ";
+ select +=
+ '' +
+ __("Next available") +
+ " ";
+ select += " ";
+ return select;
+ }
+ } else if (row.item_group_id) {
+ return __(
+ "Next available item from group
%s "
+ ).format(row.item_group.description);
+ } else if (row.hold_group_id) {
+ return (
+ "
"
+ );
+ } else {
+ if (row.non_priority) {
+ return (
+ "
" +
+ __("Next available") +
+ " " +
+ __("Non priority hold") +
+ " "
+ );
+ } else {
+ return "
" + __("Next available") + " ";
+ }
+ }
+ },
+ },
+ {
+ data: "",
+ orderable: false,
+ searchable: false,
+ render: function (data, type, row, meta) {
+ if (row.item_id) {
+ return null;
+ } else {
+ if (row.lowest_priority) {
+ return (
+ '
'
+ );
+ } else {
+ return (
+ '
'
+ );
+ }
+ }
+ },
+ },
+ {
+ data: "hold_id",
+ orderable: false,
+ searchable: false,
+ render: function (data, type, row, meta) {
+ return (
+ '
'
+ );
+ },
+ },
+ {
+ data: "hold_id",
+ orderable: false,
+ searchable: false,
+ render: function (data, type, row, meta) {
+ if (row.status) {
+ var link_value =
+ row.status == "T"
+ ? __("Revert transit status")
+ : __("Revert waiting status");
+ return (
+ '
' +
+ link_value +
+ " "
+ );
+ } else {
+ let td = "";
+ if (SuspendHoldsIntranet) {
+ td +=
+ '
';
+ if (row.suspended) {
+ td +=
+ ' ' +
+ __("Unsuspend") +
+ " ";
+ } else {
+ td +=
+ '
' +
+ __("Suspend") +
+ "";
+ }
+ if (AutoResumeSuspendedHolds) {
+ if (row.suspended) {
+ td +=
+ '
' +
+ __("Suspend on") +
+ " ";
+ } else {
+ td +=
+ '
' +
+ __("Suspend until") +
+ " ";
+ }
+ td +=
+ '
';
+ }
+ return td;
+ } else {
+ return null;
+ }
+ }
+ },
+ },
+ {
+ data: "hold_id",
+ orderable: false,
+ searchable: false,
+ render: function (data, type, row, meta) {
+ if (row.status == "W" || row.status == "T") {
+ return (
+ '
' +
+ __("Print slip") +
+ " "
+ );
+ } else {
+ return "";
+ }
+ },
+ },
+ ],
+ },
+ hold_table_settings
+ );
+ holdsQueueTable.api().page(0).draw(false);
+ // Clear selectedHolds on page load
+ localStorage.removeItem("selectedHolds");
+ $(table_id).on("draw.dt", function () {
+ function updateMSGCounters() {
+ var MSG_CANCEL_SELECTED = __("Cancel selected (%s)");
+ var MSG_MOVE_SELECTED = __("Move selected (%s)");
+ var MSG_CANCEL_ALERT = __(
+ "This action will cancel
%s hold(s)."
+ );
+ var selectedCount = JSON.parse(
+ localStorage.selectedHolds || "[]"
+ ).length;
+ $(".cancel_selected_holds").html(
+ MSG_CANCEL_SELECTED.format(selectedCount)
+ );
+ $(".move_selected_holds").html(
+ MSG_MOVE_SELECTED.format(selectedCount)
+ );
+ $("#cancel_hold_alert").html(
+ MSG_CANCEL_ALERT.format(selectedCount)
+ );
+ if (selectedCount > 0) {
+ $("#cancel_hold_alert").show();
+ } else {
+ $("#cancel_hold_alert").hide();
+ }
+ }
+
+ function updateMoveButtons() {
+ var checked_holds = JSON.parse(localStorage.selectedHolds || "[]");
+ var checked_count = checked_holds.length;
+
+ var item_level_count = checked_holds.filter(function (hold) {
+ return hold.item_level_hold > 0;
+ }).length;
+
+ var record_level_count = checked_holds.filter(function (hold) {
+ return hold.item_level_hold === 0;
+ }).length;
+
+ $(".move_hold_item").toggleClass("disabled", item_level_count <= 0);
+ $(".move_hold_biblio").toggleClass(
+ "disabled",
+ record_level_count <= 0
+ );
+ $(".move_selected_holds").prop("disabled", !checked_count);
+ }
+
+ // Always deselect the "select all" checkbox when the page changes
+ $(".holds_table .select_hold_all").prop("checked", false);
+ updateMSGCounters();
+ $(".holds_table .select_hold." + table_class).each(function () {
+ const selected = JSON.parse(localStorage.selectedHolds || "[]");
+ const holdId = $(this).data("id");
+ if (selected.some(s => s.hold === holdId)) {
+ $(this).prop("checked", true);
+ $(this).parent().parent().addClass("selected");
+ var table = $(this).closest(".holds_table");
+ var count = $(
+ ".select_hold." + table_class + ":not(:checked)",
+ table
+ ).length;
+ $(".select_hold_all." + table_class, table).prop(
+ "checked",
+ !count
+ );
+ }
+ });
+ $(".holds_table .select_hold_all").on("click", function () {
+ var table = $(this).closest(".holds_table");
+ var isChecked = $(this).prop("checked");
+ var allCheckboxes = table
+ .DataTable()
+ .rows({ search: "applied" })
+ .nodes();
+ let selected = JSON.parse(localStorage.selectedHolds || "[]");
+ let pageHolds = [];
+
+ $("input.select_hold", allCheckboxes).each(function () {
+ let hold_data = {
+ hold: $(this).data("id"),
+ borrowernumber: $(this).data("borrowernumber"),
+ biblionumber: $(this).data("biblionumber"),
+ itemnumber: $(this).data("itemnumber"),
+ waiting: $(this).data("waiting"),
+ intransit: $(this).data("intransit"),
+ status: $(this).data("status"),
+ item_level_hold: $(this).data("item_level_hold"),
+ hold_group_id: $(this).data("hold-group-id"),
+ };
+ pageHolds.push(hold_data);
+ });
+
+ if (isChecked) {
+ // Add all page holds to the selection, avoiding duplicates
+ pageHolds.forEach(hold => {
+ if (!selected.some(s => s.hold === hold.hold)) {
+ selected.push(hold);
+ }
+ });
+ $("input.select_hold", allCheckboxes).prop("checked", true);
+ $("input.select_hold", allCheckboxes).each(function () {
+ $(this).parent().parent().addClass("selected");
+ });
+ } else {
+ // Remove all page holds from the selection
+ const pageIds = pageHolds.map(h => h.hold);
+ selected = selected.filter(s => !pageIds.includes(s.hold));
+ $("input.select_hold", allCheckboxes).prop("checked", false);
+ $("input.select_hold", allCheckboxes).each(function () {
+ $(this).parent().parent().removeClass("selected");
+ });
+ }
+
+ localStorage.selectedHolds = JSON.stringify(selected);
+ updateMoveButtons();
+ updateMSGCounters();
+ });
+ $(".holds_table .select_hold").on("click", function () {
+ let selected = JSON.parse(localStorage.selectedHolds || "[]");
+ const hold_data = {
+ hold: $(this).data("id"),
+ borrowernumber: $(this).data("borrowernumber"),
+ biblionumber: $(this).data("biblionumber"),
+ itemnumber: $(this).data("itemnumber"),
+ waiting: $(this).data("waiting"),
+ intransit: $(this).data("intransit"),
+ status: $(this).data("status"),
+ item_level_hold: $(this).data("item_level_hold"),
+ hold_group_id: $(this).data("hold-group-id"),
+ };
+ if ($(this).is(":checked")) {
+ if (!selected.some(s => s.hold === hold_data.hold)) {
+ selected.push(hold_data);
+ }
+ } else {
+ selected = selected.filter(s => s.hold !== hold_data.hold);
+ }
+ localStorage.selectedHolds = JSON.stringify(selected);
+ updateMoveButtons();
+ updateMSGCounters();
+ var table = $(this).parents(".holds_table");
+ var count = $(".select_hold:not(:checked)", table).length;
+ $(".select_hold_all", table).prop("checked", !count);
+ $(this).parent().parent().toggleClass("selected");
+ });
+ $(".cancel-hold." + table_class).on("click", function (e) {
+ e.preventDefault;
+ cancel_link = $(this);
+ $("#cancel_modal_form #inputs").empty();
+ let reserve_id = cancel_link.data("id");
+ let biblionumber = cancel_link.data("biblionumber");
+ _append_patron_page_cancel_hold_modal_data({
+ hold: reserve_id,
+ biblionumber: biblionumber,
+ borrowernumber: cancel_link.data("borrowernumber"),
+ });
+ $("#cancelModal").modal("show");
+ });
+ $(".cancel_selected_holds").click(function (e) {
+ e.preventDefault();
+ const selectedHolds = JSON.parse(
+ localStorage.selectedHolds || "[]"
+ );
+ if (selectedHolds.length) {
+ $("#cancel_modal_form #inputs").empty();
+
+ selectedHolds.forEach(function (hold) {
+ _append_patron_page_cancel_hold_modal_data(hold);
+ });
+
+ //delete localStorage.selectedHolds;
+ $("#cancelModal").modal("show");
+ }
+ return false;
+ });
+ function _append_patron_page_cancel_hold_modal_data(hold) {
+ $("#cancel_modal_form #inputs").append(
+ '
'
+ );
+ $("#cancel_modal_form #inputs").append(
+ '
'
+ );
+ $("#cancel_modal_form #inputs").append(
+ '
'
+ );
+ $("#cancel_modal_form #inputs").append(
+ '
'
+ );
+ }
+ // Remove any previously attached handlers
+ $("#cancelModalConfirmBtn").off("click");
+ // Attach the handler to the button
+ $("#cancelModalConfirmBtn").one("click", function (e) {
+ e.preventDefault();
+ let formInputs = {};
+ formInputs["reserve_id"] = $(
+ "#cancel_modal_form :input[name='reserve_id']"
+ )
+ .map(function () {
+ return $(this).val();
+ })
+ .get();
+ formInputs["cancellation-reason"] = $(
+ "#cancel_modal_form :input[name='cancellation-reason']"
+ ).val();
+ cancel_holds(
+ formInputs["reserve_id"],
+ formInputs["cancellation-reason"]
+ )
+ .success(function () {
+ holdsQueueTable.api().ajax.reload(null, false);
+ })
+ .fail(function (jqXHR) {
+ $("#cancelModal .modal-body").prepend(
+ '
' +
+ jqXHR.responseJSON.error +
+ "
"
+ );
+ $("#cancelModalConfirmBtn").prop("disabled", true);
+ })
+ .done(function () {
+ $("#cancelModal").modal("hide");
+ if ($(".select_hold_all").prop("checked")) {
+ $(".select_hold_all").click();
+ }
+ });
+ });
+ function cancel_holds(hold_ids, cancellation_reason) {
+ return $.ajax({
+ method: "DELETE",
+ url: "/api/v1/holds/cancellation_bulk",
+ contentType: "application/json",
+ data: JSON.stringify({
+ hold_ids: hold_ids,
+ cancellation_reason: cancellation_reason,
+ }),
+ });
+ }
+ $(
+ ".holddate." + table_class + ", .expirationdate." + table_class
+ ).flatpickr({
+ onReady: function (selectedDates, dateStr, instance) {
+ $(instance.altInput)
+ .wrap("
")
+ .after(
+ $("
")
+ .attr("href", "#")
+ .addClass("clear_date")
+ .addClass("fa fa-times")
+ .addClass("ps-2")
+ .on("click", function (e) {
+ e.preventDefault();
+ instance.clear();
+ })
+ .attr("aria-hidden", true)
+ );
+ },
+ onChange: function (selectedDates, dateStr, instance) {
+ let hold_id = $(instance.input).attr("data-id");
+ let fieldname = $(instance.input).attr("name");
+ let current_date = $(instance.input).attr("data-current-date");
+ dateStr = dateStr ? dateStr : null;
+ let req =
+ fieldname == "hold_date"
+ ? { hold_date: dateStr }
+ : { expiration_date: dateStr };
+ if (current_date != dateStr) {
+ $.ajax({
+ method: "PATCH",
+ url: "/api/v1/holds/" + encodeURIComponent(hold_id),
+ contentType: "application/json",
+ data: JSON.stringify(req),
+ success: function (data) {
+ holdsQueueTable.api().ajax.reload(null, false);
+ $(instance.input).attr(
+ "data-current-date",
+ dateStr
+ );
+ },
+ error: function (jqXHR, textStatus, errorThrown) {
+ holdsQueueTable.api().ajax.reload(null, false);
+ },
+ });
+ }
+ },
+ });
+ $(".suspenddate." + table_class).flatpickr({
+ onReady: function (selectedDates, dateStr, instance) {
+ $(instance.altInput)
+ .wrap("
")
+ .after(
+ $("
")
+ .attr("href", "#")
+ .addClass("clear_date")
+ .addClass("fa fa-times")
+ .addClass("ps-2")
+ .on("click", function (e) {
+ e.preventDefault();
+ instance.clear();
+ })
+ .attr("aria-hidden", true)
+ );
+ },
+ });
+ $(".toggle-suspend." + table_class).one("click", function (e) {
+ e.preventDefault();
+ const hold_id = $(this).data("id");
+ const suspended = $(this).attr("data-suspended");
+ const input = $(
+ `.suspenddate.` + table_class + `[data-id="${hold_id}"]`
+ );
+ const method = suspended == "true" ? "DELETE" : "POST";
+ let end_date = input.val() && method == "POST" ? input.val() : null;
+ let params =
+ end_date !== null && end_date !== ""
+ ? JSON.stringify({ end_date: end_date })
+ : null;
+ $.ajax({
+ method: method,
+ url:
+ "/api/v1/holds/" +
+ encodeURIComponent(hold_id) +
+ "/suspension",
+ contentType: "application/json",
+ data: params,
+ success: function (data) {
+ holdsQueueTable.api().ajax.reload(null, false);
+ },
+ error: function (jqXHR, textStatus, errorThrown) {
+ holdsQueueTable.api().ajax.reload(null, false);
+ alert(
+ "There was an error:" + textStatus + " " + errorThrown
+ );
+ },
+ });
+ });
+ $(".rank-request." + table_class).on("change", function (e) {
+ e.preventDefault();
+ const hold_id = $(this).data("id");
+ let priority = e.target.value;
+ // Replace select with spinner
+ const $select = $(this);
+ const $spinner = $(
+ '
'
+ );
+ $select.hide().after($spinner);
+ $.ajax({
+ method: "PUT",
+ url:
+ "/api/v1/holds/" +
+ encodeURIComponent(hold_id) +
+ "/priority",
+ data: JSON.stringify(priority),
+ success: function (data) {
+ holdsQueueTable.api().ajax.reload(null, false);
+ $spinner.remove();
+ },
+ error: function (jqXHR, textStatus, errorThrown) {
+ alert(
+ "There was an error:" + textStatus + " " + errorThrown
+ );
+ $select.show();
+ $spinner.remove();
+ },
+ });
+ });
+ $(".move-hold." + table_class).one("click", function (e) {
+ e.preventDefault();
+ let toPosition = $(this).attr("data-move-hold");
+ let priority = $(this).attr("data-priority");
+ var res_id = $(this).attr("reserve_id");
+ var moveTo;
+ if (toPosition == "up") {
+ moveTo = parseInt(priority) - 1;
+ }
+ if (toPosition == "down") {
+ moveTo = parseInt(priority) + 1;
+ }
+ if (toPosition == "top") {
+ moveTo = 1;
+ }
+ if (toPosition == "bottom") {
+ moveTo = totalHolds;
+ }
+ $.ajax({
+ method: "PUT",
+ url:
+ "/api/v1/holds/" + encodeURIComponent(res_id) + "/priority",
+ data: JSON.stringify(moveTo),
+ success: function (data) {
+ holdsQueueTable.api().ajax.reload(null, false);
+ },
+ error: function (jqXHR, textStatus, errorThrown) {
+ alert(
+ "There was an error:" + textStatus + " " + errorThrown
+ );
+ },
+ });
+ });
+ $(".toggle-lowest-priority." + table_class).one("click", function (e) {
+ e.preventDefault();
+ var res_id = $(this).attr("data-reserve_id");
+ $.ajax({
+ method: "PUT",
+ url:
+ "/api/v1/holds/" +
+ encodeURIComponent(res_id) +
+ "/lowest_priority",
+ success: function (data) {
+ holdsQueueTable.api().ajax.reload(null, false);
+ },
+ error: function (jqXHR, textStatus, errorThrown) {
+ alert(
+ "There was an error:" + textStatus + " " + errorThrown
+ );
+ },
+ });
+ });
+ $(".hold_location_select." + table_class).on("change", function () {
+ $(this).prop("disabled", true);
+ var cur_select = $(this);
+ var res_id = $(this).attr("reserve_id");
+ $(this).after(
+ '
'
+ );
+ let api_url =
+ "/api/v1/holds/" +
+ encodeURIComponent(res_id) +
+ "/pickup_location";
+ $.ajax({
+ method: "PUT",
+ url: api_url,
+ data: JSON.stringify({ pickup_library_id: $(this).val() }),
+ headers: { "x-koha-override": "any" },
+ success: function (data) {
+ holdsQueueTable.api().ajax.reload(null, false);
+ },
+ error: function (jqXHR, textStatus, errorThrown) {
+ alert(
+ "There was an error:" + textStatus + " " + errorThrown
+ );
+ cur_select.prop("disabled", false);
+ $("#updating_reserveno" + res_id).remove();
+ cur_select.val(
+ cur_select.children('option[selected="selected"]').val()
+ );
+ },
+ });
+ });
+ $(".change_hold_type." + table_class).on("change", function () {
+ $(this).prop("disabled", true);
+ var cur_select = $(this);
+ var hold_id = $(this).attr("data-id");
+ $(this).after(
+ '
'
+ );
+ let api_url = "/api/v1/holds/" + encodeURIComponent(hold_id);
+ $.ajax({
+ method: "PATCH",
+ url: api_url,
+ data: JSON.stringify({ item_id: null, item_level: false }),
+ headers: { "x-koha-override": "any" },
+ contentType: "application/json",
+ success: function (data) {
+ holdsQueueTable.api().ajax.reload(null, false);
+ },
+ error: function (jqXHR, textStatus, errorThrown) {
+ alert(
+ "There was an error:" + textStatus + " " + errorThrown
+ );
+ cur_select.prop("disabled", false);
+ $("#updating_holdno" + hold_id).remove();
+ cur_select.val(
+ cur_select.children('option[selected="selected"]').val()
+ );
+ },
+ });
+ });
+ $(".printholdslip." + table_class).one("click", function () {
+ var reserve_id = $(this).attr("data-reserve_id");
+ window.open(
+ "/cgi-bin/koha/circ/hold-transfer-slip.pl?reserve_id=" +
+ reserve_id
+ );
+ return false;
+ });
+ updateMSGCounters();
+ });
+}
diff --git a/reserve/request.pl b/reserve/request.pl
index fbc08a0826..9f0299ff77 100755
--- a/reserve/request.pl
+++ b/reserve/request.pl
@@ -669,9 +669,13 @@ if ( ( $findborrower && $borrowernumber_hold || $findclub && $club_hold )
# existingreserves building
my @reserveloop;
+ my $total_holds = 0;
+ my $hold_branches = [];
+ my $hold_itemtypes = [];
my $always_show_holds = $input->cookie('always_show_holds');
$template->param( always_show_holds => $always_show_holds );
my $show_holds_now = $input->param('show_holds_now');
+
unless ( ( defined $always_show_holds && $always_show_holds eq 'DONT' ) && !$show_holds_now ) {
my $holds_count_per_patron = {
map { $_->{borrowernumber} => $_->{hold_count} } @{ Koha::Holds->search(
@@ -684,64 +688,27 @@ if ( ( $findborrower && $borrowernumber_hold || $findclub && $club_hold )
)->unblessed
}
};
- my @reserves = Koha::Holds->search(
- { 'me.biblionumber' => $biblionumber },
- { prefetch => [ 'borrowernumber', 'itemnumber' ], order_by => 'priority' }
- )->as_list;
- foreach my $res (
- sort {
- my $a_found = $a->found() || '';
- my $b_found = $a->found() || '';
- $a_found cmp $b_found;
- } @reserves
- )
- {
- my %reserve;
- if ( $res->is_found() ) {
- $reserve{'holdingbranch'} = $res->item()->holdingbranch();
- $reserve{'biblionumber'} = $res->item()->biblionumber();
- $reserve{'barcodenumber'} = $res->item()->barcode();
- $reserve{'wbrcode'} = $res->branchcode();
- $reserve{'itemnumber'} = $res->itemnumber();
- $reserve{'wbrname'} = $res->branch()->branchname();
- $reserve{'atdestination'} = $res->is_at_destination();
- $reserve{'desk_name'} = ( $res->desk() ) ? $res->desk()->desk_name() : '';
- $reserve{'found'} = $res->is_found();
- $reserve{'inprocessing'} = $res->is_in_processing();
- $reserve{'intransit'} = $res->is_in_transit();
- } elsif ( $res->priority() > 0 ) {
- if ( my $item = $res->item() ) {
- $reserve{'itemnumber'} = $item->id();
- $reserve{'barcodenumber'} = $item->barcode();
- $reserve{'item_level_hold'} = 1;
- }
+ $total_holds = Koha::Holds->search( { biblionumber => $biblionumber } )->count;
+ my $branches = Koha::Holds->search(
+ {
+ biblionumber => $biblionumber,
+ },
+ {
+ select => [ { distinct => 'branchcode' } ],
+ as => [qw( branchcode )],
}
- $reserve{'expirationdate'} = $res->expirationdate;
- $reserve{'date'} = $res->reservedate;
- $reserve{'borrowernumber'} = $res->borrowernumber();
- $reserve{'biblionumber'} = $res->biblionumber();
- $reserve{'patron'} = $res->borrower;
- $reserve{'notes'} = $res->reservenotes();
- $reserve{'waiting_date'} = $res->waitingdate();
- $reserve{'ccode'} = $res->item() ? $res->item()->ccode() : undef;
- $reserve{'barcode'} = $res->item() ? $res->item()->barcode() : undef;
- $reserve{'priority'} = $res->priority();
- $reserve{'lowestPriority'} = $res->lowestPriority();
- $reserve{'suspend'} = $res->suspend();
- $reserve{'suspend_until'} = $res->suspend_until();
- $reserve{'reserve_id'} = $res->reserve_id();
- $reserve{itemtype} = $res->itemtype();
- $reserve{branchcode} = $res->branchcode();
- $reserve{non_priority} = $res->non_priority();
- $reserve{object} = $res;
- $reserve{hold_group_id} = $res->hold_group_id;
-
- if ( $holds_count_per_patron->{ $reserve{'borrowernumber'} } == 1 ) {
- $reserve{'change_hold_type_allowed'} = 1;
+ )->unblessed;
+ $hold_branches = [ map { $_->{branchcode} } @$branches ];
+ my $itemtypes = Koha::Holds->search(
+ {
+ biblionumber => $biblionumber,
+ },
+ {
+ select => [ { distinct => 'itemtype' } ],
+ as => [qw( itemtype )],
}
-
- push( @reserveloop, \%reserve );
- }
+ )->unblessed;
+ $hold_itemtypes = [ map { $_->{itemtype} ? $_->{itemtype} : 'any' } @$itemtypes ];
}
# get the time for the form name...
@@ -764,11 +731,14 @@ if ( ( $findborrower && $borrowernumber_hold || $findclub && $club_hold )
C4::Search::enabled_staff_search_views,
);
- $biblioloopiter{biblionumber} = $biblionumber;
- $biblioloopiter{title} = $biblio->title;
- $biblioloopiter{author} = $biblio->author;
- $biblioloopiter{rank} = $fixedRank;
- $biblioloopiter{reserveloop} = \@reserveloop;
+ $biblioloopiter{biblionumber} = $biblionumber;
+ $biblioloopiter{title} = $biblio->title;
+ $biblioloopiter{author} = $biblio->author;
+ $biblioloopiter{rank} = $fixedRank;
+ $biblioloopiter{reserveloop} = \@reserveloop;
+ $biblioloopiter{total_holds} = $total_holds;
+ $biblioloopiter{hold_branches} = $hold_branches;
+ $biblioloopiter{hold_itemtypes} = $hold_itemtypes;
# Pass through any reserve charge
if ($patron) {
@@ -791,6 +761,8 @@ if ( ( $findborrower && $borrowernumber_hold || $findclub && $club_hold )
$template->param( reserveloop => \@reserveloop );
}
+ $template->param( total_holds => $total_holds );
+
if ( $patron && $multi_hold ) {
# Add the valid pickup locations