Bugzilla – Attachment 189928 Details for
Bug 41254
The filter for item status in item tables should be improved
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
Bug 41254: Allow filtering by all authorised values for multi-valued statuses
e9ba9fb.patch (text/plain), 8.17 KB, created by
Jonathan Druart
on 2025-11-25 14:54:01 UTC
(
hide
)
Description:
Bug 41254: Allow filtering by all authorised values for multi-valued statuses
Filename:
MIME Type:
Creator:
Jonathan Druart
Created:
2025-11-25 14:54:01 UTC
Size:
8.17 KB
patch
obsolete
>From e9ba9fb60a16c7048b101ea0c61827c5e78b3bb5 Mon Sep 17 00:00:00 2001 >From: Jonathan Druart <jonathan.druart@bugs.koha-community.org> >Date: Tue, 25 Nov 2025 15:45:13 +0100 >Subject: [PATCH] Bug 41254: Allow filtering by all authorised values for > multi-valued statuses > >Some item statuses can correspond to multiple authorised values: Not for loan, Withdrawn, Lost and Damaged. >Until now, only a single entry could be selected, and filtering applied to all values at once. > >This change introduces finer-grained filtering by exposing each authorised value individually in the filter. > >Test plan: >Assign multiple authorised values to items on a bibliographic record for the four affected attributes: Not for loan, Withdrawn, Lost and Damaged. >Use the "Status" filter and verify that each value behaves as expected. > >Display note: >The current dropdown presentation is not ideal. >Suggestions for improvement are welcome, although avoiding optgroup would be preferable to keep the scope small. >--- > Koha/Items.pm | 15 ++++ > .../tables/items/catalogue_detail.inc | 31 +++++++- > t/db_dependent/Koha/Items.t | 71 ++++++++++++++++++- > 3 files changed, 113 insertions(+), 4 deletions(-) > >diff --git a/Koha/Items.pm b/Koha/Items.pm >index 830bfc3914b..952a7d7deb5 100644 >--- a/Koha/Items.pm >+++ b/Koha/Items.pm >@@ -671,17 +671,32 @@ sub search { > if ( $status eq 'lost' ) { > $self = $self->search( { itemlost => { '!=' => 0 } } ); > } >+ if ( $status =~ '^lost-(.*)' ) { >+ $self = $self->search( { itemlost => $1 } ); >+ } > if ( $status eq 'withdrawn' ) { > $self = $self->search( { withdrawn => { '!=' => 0 } } ); > } >+ if ( $status =~ '^withdrawn-(.*)' ) { >+ $self = $self->search( { withdrawn => $1 } ); >+ } > if ( $status eq 'damaged' ) { > $self = $self->search( { damaged => { '!=' => 0 } } ); > } >+ if ( $status =~ '^damaged-(.*)' ) { >+ $self = $self->search( { damaged => $1 } ); >+ } > if ( $status eq 'not_for_loan' ) { > my @item_types_notforloan = > Koha::ItemTypes->search( { notforloan => { '!=' => 0 } } )->get_column('itemtype'); > $self = $self->search( [ { notforloan => { '!=' => 0 } }, { 'me.itype' => \@item_types_notforloan } ] ); > } >+ if ( $status =~ '^not_for_loan-(.*)' ) { >+ my $av_not_for_loan = $1; >+ my @item_types_notforloan = >+ Koha::ItemTypes->search( { notforloan => $av_not_for_loan } )->get_column('itemtype'); >+ $self = $self->search( [ { notforloan => $av_not_for_loan }, { 'me.itype' => \@item_types_notforloan } ] ); >+ } > if ( $status eq 'on_hold' ) { > $self = $self->filter_by_has_holds; > } >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 003a1d37803..04569371012 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 >@@ -220,9 +220,6 @@ > }); > const item_types_notforloan = new Map(all_item_types.map( it => [it.itemtype, it.notforloan] )); > >- const statuses = {checked_out: _("Checked out"), local_use: _("On-site checkout"), in_transit: _("In transit"), lost: _("Lost"), withdrawn: _("Withdrawn"), damaged:_("Damaged"), not_for_loan: _("Not for loan"), on_hold: _("On hold"), recalled: _("Recalled"), available: _("Available"), restricted: _("Restricted"), in_bundle: _("In bundle")}; >- const all_statuses = Object.keys(statuses).map(k => {return {_id: k, _str: statuses[k]}}); >- > const can_edit_items_from = [% To.json(can_edit_items_from || []) | $raw %]; > const item_type_image_locations = [% To.json(item_type_image_locations) | $raw %]; > const av_loc = new Map([% To.json(AuthorisedValues.Get('LOC')) | $raw %].map( av => [av.authorised_value, av.lib])); >@@ -242,6 +239,34 @@ > location: new Map([% To.json(AuthorisedValues.GetDescriptionsByKohaField({ kohafield => 'items.location' })) | $raw %].map( av => [av.lib, av.authorised_value])), > }; > >+ const statuses = { >+ checked_out: _("Checked out"), >+ local_use: _("On-site checkout"), >+ in_transit: _("In transit"), >+ lost: _("Lost"), >+ ...Object.fromEntries( >+ [...av_lost].map(([k, v]) => [`lost-${k}`, `* ${v}`]) >+ ), >+ withdrawn: _("Withdrawn"), >+ ...Object.fromEntries( >+ [...av_withdrawn].map(([k, v]) => [`withdrawn-${k}`, `* ${v}`]) >+ ), >+ damaged:_("Damaged"), >+ ...Object.fromEntries( >+ [...av_damaged].map(([k, v]) => [`damaged-${k}`, `* ${v}`]) >+ ), >+ not_for_loan: _("Not for loan"), >+ ...Object.fromEntries( >+ [...av_not_for_loan].map(([k, v]) => [`not_for_loan-${k}`, `* ${v}`]) >+ ), >+ on_hold: _("On hold"), >+ recalled: _("Recalled"), >+ available: _("Available"), >+ restricted: _("Restricted"), >+ in_bundle: _("In bundle"), >+ }; >+ const all_statuses = Object.keys(statuses).map(k => {return {_id: k, _str: statuses[k]}}); >+ > [% IF Koha.Preference('URLLinkText') %] > const url_link_text = "[% Koha.Preference('URLLinkText') | html %]"; > [% ELSE %] >diff --git a/t/db_dependent/Koha/Items.t b/t/db_dependent/Koha/Items.t >index 29a29a50e3d..6ba655d4b41 100755 >--- a/t/db_dependent/Koha/Items.t >+++ b/t/db_dependent/Koha/Items.t >@@ -75,7 +75,7 @@ is( $retrieved_item_1->barcode, $new_item_1->barcode, 'Find a item by id should > > subtest 'search' => sub { > >- plan tests => 9; >+ plan tests => 15; > $schema->storage->txn_begin; > > my $patron = $builder->build_object( { class => 'Koha::Patrons' } ); >@@ -160,6 +160,75 @@ subtest 'search' => sub { > ok( $withdrawn_items->count == 1, "Filtered to 1 withdrawn item" ); > ok( $notforloan_items->count == 1, "Filtered to 1 notforloan item" ); > >+ $item_6->notforloan(-1)->store; >+ is_deeply( >+ [ >+ Koha::Items->search( >+ { >+ _status => 'not_for_loan', >+ biblionumber => $biblio->biblionumber, >+ } >+ )->get_column('itemnumber') >+ ], >+ [ $item_6->itemnumber ] >+ ); >+ is_deeply( >+ [ >+ Koha::Items->search( >+ { >+ _status => 'not_for_loan-1', >+ biblionumber => $biblio->biblionumber, >+ } >+ )->get_column('itemnumber') >+ ], >+ [] >+ ); >+ is_deeply( >+ [ >+ Koha::Items->search( >+ { >+ _status => 'not_for_loan--1', >+ biblionumber => $biblio->biblionumber, >+ } >+ )->get_column('itemnumber') >+ ], >+ [ $item_6->itemnumber ] >+ ); >+ $item_6->notforloan(2)->store; >+ is_deeply( >+ [ >+ Koha::Items->search( >+ { >+ _status => 'not_for_loan', >+ biblionumber => $biblio->biblionumber, >+ } >+ )->get_column('itemnumber') >+ ], >+ [ $item_6->itemnumber ] >+ ); >+ is_deeply( >+ [ >+ Koha::Items->search( >+ { >+ _status => 'not_for_loan-1', >+ biblionumber => $biblio->biblionumber, >+ } >+ )->get_column('itemnumber') >+ ], >+ [] >+ ); >+ is_deeply( >+ [ >+ Koha::Items->search( >+ { >+ _status => 'not_for_loan-2', >+ biblionumber => $biblio->biblionumber, >+ } >+ )->get_column('itemnumber') >+ ], >+ [ $item_6->itemnumber ] >+ ); >+ > C4::Circulation::AddIssue( $patron, $item_1->barcode ); > > my $checked_out_items = Koha::Items->search( >-- >2.43.0 >
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
|
Splinter Review
Attachments on
bug 41254
:
189928
|
190051
|
190052
|
190345
|
190346
|
190347
|
190427
|
190428
|
190429