diff --git a/Koha/REST/V1/Biblios.pm b/Koha/REST/V1/Biblios.pm
index 18e29d6b14..49f1443397 100644
--- a/Koha/REST/V1/Biblios.pm
+++ b/Koha/REST/V1/Biblios.pm
@@ -256,6 +256,9 @@ sub get_items {
# Deletion of parameter to avoid filtering on the items table in the case of bookings on 'itemtype'
$c->req->params->remove('bookable');
+ my $group_by_status = $c->param('group_by_status');
+ $c->req->params->remove('group_by_status');
+
return $c->render_resource_not_found("Bibliographic record")
unless $biblio;
@@ -267,6 +270,22 @@ sub get_items {
my $items_rs = $biblio->items( { host_items => 1 } )->search_ordered( {}, { join => 'biblioitem' } );
$items_rs = $items_rs->filter_by_bookable if $bookable_only;
+ if ($group_by_status) {
+ my @item_ids;
+ for my $status (
+ qw( available checked_out local_use in_transit lost withdrawn damaged not_for_loan on_hold recalled in_bundle restricted )
+ )
+ {
+ push @item_ids, $items_rs->search( { _status => $status } )->get_column('itemnumber');
+ }
+ $items_rs = $items_rs->search(
+ {},
+ {
+ order_by => [ \[ sprintf( "field(me.itemnumber, %s)", join( ', ', map { qq{'$_'} } @item_ids ) ) ] ]
+ }
+ );
+ }
+
# FIXME We need to order_by serial.publisheddate if we have _order_by=+me.serial_issue_number
my $items = $c->objects->search($items_rs);
diff --git a/api/v1/swagger/paths/biblios.yaml b/api/v1/swagger/paths/biblios.yaml
index 94a5092c93..6d334ee9d1 100644
--- a/api/v1/swagger/paths/biblios.yaml
+++ b/api/v1/swagger/paths/biblios.yaml
@@ -504,6 +504,11 @@
description: Limit to items that are bookable
required: false
type: boolean
+ - name: group_by_status
+ in: query
+ description: Return the items grouped by status
+ required: false
+ type: boolean
consumes:
- application/json
produces:
diff --git a/koha-tmpl/intranet-tmpl/prog/en/includes/html_helpers/tables/items/catalogue_detail.inc b/koha-tmpl/intranet-tmpl/prog/en/includes/html_helpers/tables/items/catalogue_detail.inc
index da0bd970b3..710af5395a 100644
--- a/koha-tmpl/intranet-tmpl/prog/en/includes/html_helpers/tables/items/catalogue_detail.inc
+++ b/koha-tmpl/intranet-tmpl/prog/en/includes/html_helpers/tables/items/catalogue_detail.inc
@@ -61,6 +61,7 @@
+
| Actions:
[% IF CAN_user_tools_items_batchdel %]
@@ -303,7 +304,6 @@
// FIXME The X-Base-Total-Count will be the number of items of the biblios
// In case or SeparateHoldings we may need to display the number of biblios in each tab
// Do we need separate/new endpoints or do we hack the somewhere client-side?
- let item_table_url = `/api/v1/biblios/${biblionumber}/items?`;
let embed = ["+strings,_status,home_library,holding_library,checkout,checkout.patron,transfer,transfer+strings,first_hold,first_hold+strings,first_hold.patron,first_hold.desk"];
if (Koha.prefs.LocalCoverImages) {
embed.push("cover_image_ids");
@@ -334,7 +334,26 @@
embed.push("analytics_count");
}
- let user_colvis = { holdings: {}, otherholdings: {} };
+ let group_by_status_values = {
+ holdings: false,
+ otherholdings: false,
+ };
+ $(".GroupByStatus").on("click",function(e){
+ e.preventDefault();
+ let tab_id = $(this).data("tab");
+ let was_grouped = group_by_status_values[tab_id];
+ group_by_status_values[tab_id] = !was_grouped;
+
+ build_items_table(tab_id, true, { destroy: true }, build_items_table_drawncallback );
+
+ if ( was_grouped ) {
+ $(this).html('' + _("Group by status") + '');
+ } else {
+ $(this).html('' + _("Ungroup by status") + '');
+ }
+ });
+
+ let user_colvis = {holdings: {}, otherholdings: {}};
function build_items_table(tab_id, add_filters, dt_options, drawcallback) {
let table_dt;
if (dt_options && dt_options.hasOwnProperty("destroy")) {
@@ -369,6 +388,13 @@
return $("#" + tab_id + "_status select").val();
};
+ let group_by_status = function(){
+ if ( group_by_status_values[tab_id] ) {
+ return 'group_by_status=1';
+ }
+ return '';
+ }
+
var columns = [
{
data: "me.item_id",
@@ -921,7 +947,7 @@
];
var items_table = $("#" + tab_id + "_table").kohaTable(
{
- ajax: { url: item_table_url },
+ ajax: { url: "/api/v1/biblios/[% biblio.biblionumber | uri %]/items?" + group_by_status() },
order: [],
embed,
autoWidth: false,