Bugzilla – Attachment 194290 Details for
Bug 14962
Temp Shelving Location / On Display Module
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
Bug 14962: On Display code for existing Koha modules
28047e4.patch (text/plain), 32.56 KB, created by
Martin Renvoize (ashimema)
on 2026-03-02 10:22:54 UTC
(
hide
)
Description:
Bug 14962: On Display code for existing Koha modules
Filename:
MIME Type:
Creator:
Martin Renvoize (ashimema)
Created:
2026-03-02 10:22:54 UTC
Size:
32.56 KB
patch
obsolete
>From 28047e46e439f27af1bbe7a349263c63ebb71250 Mon Sep 17 00:00:00 2001 >From: Jake Deery <jake.deery@openfifth.co.uk> >Date: Mon, 1 Dec 2025 13:06:40 +0000 >Subject: [PATCH] Bug 14962: On Display code for existing Koha modules > >This patch adds code for the On Display module, found in the existing Koha modules. >Please see the test files commit for instructions on how to test this bundle of patches. > >Sponsored-by: ByWater Solutions >Signed-of-by: Martin Renvoize <martin.renvoize@openfifth.co.uk> >--- > C4/Circulation.pm | 88 +++++++++++- > C4/Search.pm | 187 ++++++++++++++++++++++--- > C4/XSLT.pm | 17 ++- > Koha/Item.pm | 343 +++++++++++++++++++++++++++++++++++++++++++++- > Koha/Patron.pm | 24 ++++ > 5 files changed, 624 insertions(+), 35 deletions(-) > >diff --git a/C4/Circulation.pm b/C4/Circulation.pm >index 1223afceca4..6a634cf1bfb 100644 >--- a/C4/Circulation.pm >+++ b/C4/Circulation.pm >@@ -118,6 +118,7 @@ use Koha::Config::SysPrefs; > use Koha::Charges::Fees; > use Koha::Config::SysPref; > use Koha::Checkouts::ReturnClaims; >+use Koha::DisplayItems; > use Koha::SearchEngine::Indexer; > use Koha::Exceptions::Checkout; > use Koha::Plugins; >@@ -2784,6 +2785,27 @@ sub AddReturn { > my $indexer = Koha::SearchEngine::Indexer->new( { index => $Koha::SearchEngine::BIBLIOS_INDEX } ); > $indexer->index_records( $item->biblionumber, "specialUpdate", "biblioserver" ); > >+ if ( my $display_item = $item->active_display_item ) { >+ my $display = $display_item->display; >+ my $return_over = $display->display_return_over; >+ my $should_remove = 0; >+ >+ if ( $return_over eq 'yes - any library' ) { >+ $should_remove = 1; >+ } elsif ( $return_over eq 'yes - except at home library' ) { >+ my $homebranch = $item->homebranch; >+ $should_remove = 1 if $branch ne $homebranch; >+ } >+ >+ if ($should_remove) { >+ $display_item->delete; >+ $messages->{RemovedFromDisplay} = { >+ display_id => $display->display_id, >+ display_name => $display->display_name, >+ }; >+ } >+ } >+ > if ( $doreturn and $issue ) { > my $checkin = Koha::Old::Checkouts->find( $issue->id ); > >@@ -4838,8 +4860,10 @@ sub GetAgeRestriction { > > sub GetPendingOnSiteCheckouts { > my $dbh = C4::Context->dbh; >- return $dbh->selectall_arrayref( >- q| >+ >+ my $use_display_module = C4::Context->preference('UseDisplayModule'); >+ >+ my $sql = q| > SELECT > items.barcode, > items.biblionumber, >@@ -4855,14 +4879,64 @@ sub GetPendingOnSiteCheckouts { > borrowers.firstname, > borrowers.surname, > borrowers.cardnumber, >- borrowers.borrowernumber >+ borrowers.borrowernumber|; >+ >+ if ($use_display_module) { >+ $sql .= q|, >+ COALESCE(active_display.display_location, items.location) AS effective_location, >+ active_display.display_name, >+ active_display.display_location AS raw_display_location|; >+ } else { >+ $sql .= q|, >+ items.location AS effective_location, >+ NULL AS display_name, >+ NULL AS raw_display_location|; >+ } >+ >+ $sql .= q| > FROM items > LEFT JOIN issues ON items.itemnumber = issues.itemnumber > LEFT JOIN biblio ON items.biblionumber = biblio.biblionumber >- LEFT JOIN borrowers ON issues.borrowernumber = borrowers.borrowernumber >- WHERE issues.onsite_checkout = 1 >- |, { Slice => {} } >- ); >+ LEFT JOIN borrowers ON issues.borrowernumber = borrowers.borrowernumber|; >+ >+ if ($use_display_module) { >+ $sql .= q| >+ LEFT JOIN ( >+ SELECT >+ di.itemnumber, >+ d.display_location, >+ d.display_name, >+ ROW_NUMBER() OVER (PARTITION BY di.itemnumber ORDER BY di.date_added DESC) as rn >+ FROM display_items di >+ JOIN displays d ON di.display_id = d.display_id >+ WHERE d.enabled = 1 >+ AND (d.start_date IS NULL OR d.start_date <= CURDATE()) >+ AND (d.end_date IS NULL OR d.end_date >= CURDATE()) >+ AND (di.date_remove IS NULL OR di.date_remove >= CURDATE()) >+ ) active_display ON items.itemnumber = active_display.itemnumber AND active_display.rn = 1|; >+ } >+ >+ $sql .= q| >+ WHERE issues.onsite_checkout = 1|; >+ >+ my $results = $dbh->selectall_arrayref( $sql, { Slice => {} } ); >+ >+ # Add effective location description for each item >+ foreach my $checkout (@$results) { >+ if ( $checkout->{display_name} && !$checkout->{raw_display_location} ) { >+ >+ # Item is on display with no specific display location >+ $checkout->{effective_location_description} = "DISPLAY: " . $checkout->{display_name}; >+ } else { >+ >+ # Use AuthorisedValues to get effective location description >+ my $av = Koha::AuthorisedValues->get_description_by_koha_field( >+ { kohafield => 'items.location', authorised_value => $checkout->{effective_location} } ); >+ $checkout->{effective_location_description} = $av->{lib} || ''; >+ } >+ } >+ >+ return $results; > } > > =head2 GetTopIssues >diff --git a/C4/Search.pm b/C4/Search.pm >index de8162cb721..ffe49a7a6b6 100644 >--- a/C4/Search.pm >+++ b/C4/Search.pm >@@ -46,6 +46,8 @@ use C4::XSLT qw( XSLTParse4Display ); > use C4::Reserves qw( GetReserveStatus ); > use C4::Charset qw( SetUTF8Flag ); > use Koha::AuthorisedValues; >+use Koha::Displays; >+use Koha::Items; > use Koha::ItemTypes; > use Koha::Libraries; > use Koha::Logger; >@@ -1683,11 +1685,147 @@ sub searchResults { > # FIXME - We build an authorised values hash here, using the default framework > # though it is possible to have different authvals for different fws. > >+ ## get metadatas >+ my $collections = { >+ map { $_->{authorised_value} => $_->{lib} } Koha::AuthorisedValues->get_descriptions_by_koha_field( >+ { frameworkcode => '', kohafield => 'items.ccode' } >+ ) >+ }; > my $shelflocations = { > map { $_->{authorised_value} => $_->{lib} } Koha::AuthorisedValues->get_descriptions_by_koha_field( > { frameworkcode => '', kohafield => 'items.location' } > ) > }; >+ my $itemtypes = Koha::ItemTypes->search_with_localization; >+ my %itemtypes = map { $_->{itemtype} => $_ } @{ $itemtypes->unblessed }; >+ >+ # Cache for display lookups to avoid repeated queries >+ my $display_cache = {}; >+ >+ # Helper function to get effective location for search results >+ my $get_effective_collection_code = sub { >+ my ($item) = @_; >+ return $collections->{ $item->{ccode} } unless C4::Context->preference('UseDisplayModule'); >+ >+ my $item_obj = Koha::Items->find( $item->{itemnumber} ); >+ return $collections->{ $item->{ccode} } unless $item_obj; >+ >+ my $effective_collection_code = $item_obj->effective_collection_code; >+ >+ # If it starts with "DISPLAY:", validate against displays table >+ if ( $effective_collection_code =~ /^DISPLAY:\s*(.+)$/ ) { >+ my $display_name = $1; >+ >+ # Use cache to avoid repeated database queries >+ if ( !exists $display_cache->{$display_name} ) { >+ my $display = Koha::Displays->search( { display_name => $display_name } )->next; >+ $display_cache->{$display_name} = $display ? $display->display_name : undef; >+ } >+ return $display_cache->{$display_name} >+ ? "DISPLAY: " . $display_cache->{$display_name} >+ : $effective_collection_code; >+ } else { >+ return $collections->{$effective_collection_code}; >+ } >+ }; >+ my $get_effective_itemtype = sub { >+ my ($item) = @_; >+ return $itemtypes{ $item->{itype} }{translated_description} unless C4::Context->preference('UseDisplayModule'); >+ >+ my $item_obj = Koha::Items->find( $item->{itemnumber} ); >+ return $itemtypes{ $item->{itype} }{translated_description} unless $item_obj; >+ >+ my $effective_itemtype = $item_obj->effective_itemtype; >+ >+ # If it starts with "DISPLAY:", validate against displays table >+ if ( $effective_itemtype =~ /^DISPLAY:\s*(.+)$/ ) { >+ my $display_name = $1; >+ >+ # Use cache to avoid repeated database queries >+ if ( !exists $display_cache->{$display_name} ) { >+ my $display = Koha::Displays->search( { display_name => $display_name } )->next; >+ $display_cache->{$display_name} = $display ? $display->display_name : undef; >+ } >+ return $display_cache->{$display_name} >+ ? "DISPLAY: " . $display_cache->{$display_name} >+ : $effective_itemtype; >+ } else { >+ return $itemtypes{$effective_itemtype}{translated_description}; >+ } >+ }; >+ my $get_effective_location = sub { >+ my ($item) = @_; >+ return $shelflocations->{ $item->{location} } unless C4::Context->preference('UseDisplayModule'); >+ >+ my $item_obj = Koha::Items->find( $item->{itemnumber} ); >+ return $shelflocations->{ $item->{location} } unless $item_obj; >+ >+ my $effective_loc = $shelflocations->{ $item_obj->effective_location }; >+ >+ # If it starts with "DISPLAY:", validate against displays table >+ if ( $effective_loc =~ /^DISPLAY:\s*(.+)$/ ) { >+ my $display_name = $1; >+ >+ # Use cache to avoid repeated database queries >+ if ( !exists $display_cache->{$display_name} ) { >+ my $display = Koha::Displays->search( { display_name => $display_name } )->next; >+ $display_cache->{$display_name} = $display ? $display->display_name : undef; >+ } >+ return $display_cache->{$display_name} ? "DISPLAY: " . $display_cache->{$display_name} : $effective_loc; >+ } else { >+ return $effective_loc; >+ } >+ }; >+ my $get_effective_homebranch = sub { >+ my ($item) = @_; >+ return $item->{homebranch} unless C4::Context->preference('UseDisplayModule'); >+ >+ my $item_obj = Koha::Items->find( $item->{itemnumber} ); >+ return $item->{homebranch} unless $item_obj; >+ >+ my $effective_homebranch = $item_obj->effective_homebranch->branchcode; >+ >+ # If it starts with "DISPLAY:", validate against displays table >+ if ( $effective_homebranch =~ /^DISPLAY:\s*(.+)$/ ) { >+ my $display_name = $1; >+ >+ # Use cache to avoid repeated database queries >+ if ( !exists $display_cache->{$display_name} ) { >+ my $display = Koha::Displays->search( { display_name => $display_name } )->next; >+ $display_cache->{$display_name} = $display ? $display->display_name : undef; >+ } >+ return $display_cache->{$display_name} >+ ? "DISPLAY: " . $display_cache->{$display_name} >+ : $effective_homebranch; >+ } else { >+ return $effective_homebranch; >+ } >+ }; >+ my $get_effective_holdingbranch = sub { >+ my ($item) = @_; >+ return $item->{holdingbranch} unless C4::Context->preference('UseDisplayModule'); >+ >+ my $item_obj = Koha::Items->find( $item->{itemnumber} ); >+ return $item->{holdingbranch} unless $item_obj; >+ >+ my $effective_holdingbranch = $item_obj->effective_holdingbranch->branchcode; >+ >+ # If it starts with "DISPLAY:", validate against displays table >+ if ( $effective_holdingbranch =~ /^DISPLAY:\s*(.+)$/ ) { >+ my $display_name = $1; >+ >+ # Use cache to avoid repeated database queries >+ if ( !exists $display_cache->{$display_name} ) { >+ my $display = Koha::Displays->search( { display_name => $display_name } )->next; >+ $display_cache->{$display_name} = $display ? $display->display_name : undef; >+ } >+ return $display_cache->{$display_name} >+ ? "DISPLAY: " . $display_cache->{$display_name} >+ : $effective_holdingbranch; >+ } else { >+ return $effective_holdingbranch; >+ } >+ }; > > # get notforloan authorised value list (see $shelflocations FIXME) > my $av = Koha::MarcSubfieldStructures->search( >@@ -1698,10 +1836,6 @@ sub searchResults { > ); > my $notforloan_authorised_value = $av->count ? $av->next->authorised_value : undef; > >- #Get itemtype hash >- my $itemtypes = Koha::ItemTypes->search_with_localization; >- my %itemtypes = map { $_->{itemtype} => $_ } @{ $itemtypes->unblessed }; >- > #search item field code > my ( $itemtag, undef ) = &GetMarcFromKohaField("items.itemnumber"); > >@@ -1866,7 +2000,12 @@ sub searchResults { > next; > } > >- $item->{description} = $itemtypes{ $item->{itype} }{translated_description} if $item->{itype}; >+ $item->{collectioncode} = $get_effective_collection_code->($item) if $item->{ccode}; >+ $item->{description} = $get_effective_itemtype->($item) if $item->{itype}; >+ $item->{location} = $get_effective_location->($item) if $item->{location}; >+ >+ $item->{homebranch} = $get_effective_homebranch->($item) if $item->{homebranch}; >+ $item->{holdingbranch} = $get_effective_holdingbranch->($item) if $item->{holdingbranch}; > > # OPAC hidden items > if ($is_opac) { >@@ -1893,6 +2032,23 @@ sub searchResults { > $item->{'branchcode'} = $item->{$otherbranch}; > } > >+ if ( C4::Context->preference('UseDisplayModule') ) { >+ my @displays; >+ my @display_items = Koha::DisplayItems->search( >+ { itemnumber => $item->{itemnumber} }, >+ { >+ order_by => { '-desc' => 'date_added' }, >+ } >+ )->as_list; >+ >+ foreach my $display_item (@display_items) { >+ push @displays, $display_item->display; >+ } >+ >+ $item->{display_items} = \@display_items if @display_items; >+ $item->{displays} = \@displays if @displays; >+ } >+ > my $prefix = > ( $item->{$hbranch} ? $item->{$hbranch} . '--' : q{} ) > . ( $item->{location} ? $item->{location} : q{} ) >@@ -1914,15 +2070,15 @@ sub searchResults { > $onloan_items->{$key}->{count}++ if $item->{$hbranch}; > $onloan_items->{$key}->{branchname} = $item->{branchname}; > $onloan_items->{$key}->{branchcode} = $item->{branchcode}; >- $onloan_items->{$key}->{location} = $shelflocations->{ $item->{location} } if $item->{location}; >+ $onloan_items->{$key}->{location} = $item->{location}; > $onloan_items->{$key}->{itemcallnumber} = $item->{itemcallnumber}; > $onloan_items->{$key}->{description} = $item->{description}; > $onloan_items->{$key}->{imageurl} = getitemtypeimagelocation( > $search_context->{'interface'}, > $itemtypes{ $item->{itype} }->{imageurl} > ); >- $onloan_items->{$key}->{collectioncode} = >- GetAuthorisedValueDesc( '', '', $item->{ccode}, '', '', 'CCODE' ); >+ $onloan_items->{$key}->{collectioncode} = $item->{collectioncode}; >+ $onloan_items->{$key}->{displays} = $item->{displays}; > > # if something's checked out and lost, mark it as 'long overdue' > if ( $item->{itemlost} ) { >@@ -2032,14 +2188,14 @@ sub searchResults { > GetAuthorisedValueDesc( '', '', $item->{notforloan}, '', '', $notforloan_authorised_value ) > if $notforloan_authorised_value and $item->{notforloan}; > $other_items->{$key}->{count}++ if $item->{$hbranch}; >- $other_items->{$key}->{location} = $shelflocations->{ $item->{location} } if $item->{location}; >+ $other_items->{$key}->{location} = $item->{location}; > $other_items->{$key}->{description} = $item->{description}; > $other_items->{$key}->{imageurl} = getitemtypeimagelocation( > $search_context->{'interface'}, > $itemtypes{ $item->{itype} // q{} }->{imageurl} > ); >- $other_items->{$key}->{collectioncode} = >- GetAuthorisedValueDesc( '', '', $item->{ccode}, '', '', 'CCODE' ); >+ $other_items->{$key}->{collectioncode} = $item->{collectioncode}; >+ $other_items->{$key}->{displays} = $item->{displays}; > } > > # item is available >@@ -2053,14 +2209,13 @@ sub searchResults { > } > $available_items->{$prefix}->{branchavailablecount} = $branch_available_count; > $available_items->{$prefix}->{branchcode} = $item->{branchcode}; >- $available_items->{$prefix}->{location} = $shelflocations->{ $item->{location} } >- if $item->{location}; >- $available_items->{$prefix}->{imageurl} = getitemtypeimagelocation( >+ $available_items->{$prefix}->{location} = $item->{location}; >+ $available_items->{$prefix}->{imageurl} = getitemtypeimagelocation( > $search_context->{'interface'}, > $itemtypes{ $item->{itype} // q{} }->{imageurl} > ); >- $available_items->{$prefix}->{collectioncode} = >- GetAuthorisedValueDesc( '', '', $item->{ccode}, '', '', 'CCODE' ); >+ $available_items->{$prefix}->{collectioncode} = $item->{collectioncode}; >+ $available_items->{$prefix}->{displays} = $item->{displays}; > } > } > } # notforloan, item level and biblioitem level >diff --git a/C4/XSLT.pm b/C4/XSLT.pm >index be3ac7d41f5..14ae2d01ee3 100644 >--- a/C4/XSLT.pm >+++ b/C4/XSLT.pm >@@ -414,16 +414,19 @@ sub buildKohaItemsNamespace { > } else { > $status = "available"; > } >- my $homebranch = C4::Koha::xml_escape( $branches{ $item->homebranch } ); >- my $holdingbranch = C4::Koha::xml_escape( $branches{ $item->holdingbranch } ); >+ my $homebranch = C4::Koha::xml_escape( $branches{ $item->effective_homebranch } ); >+ my $holdingbranch = C4::Koha::xml_escape( $branches{ $item->effective_holdingbranch } ); > my $resultbranch = C4::Context->preference('OPACResultsLibrary') eq 'homebranch' ? $homebranch : $holdingbranch; > my $location = C4::Koha::xml_escape( >- $item->location && exists $shelflocations->{ $item->location } >- ? $shelflocations->{ $item->location } >- : $item->location >+ $item->effective_location && exists $shelflocations->{ $item->effective_location } >+ ? $shelflocations->{ $item->effective_location } >+ : $item->effective_location >+ ); >+ my $ccode = C4::Koha::xml_escape( >+ $item->effective_collection_code && exists $ccodes->{ $item->effective_collection_code } >+ ? $ccodes->{ $item->effective_collection_code } >+ : $item->effective_collection_code > ); >- my $ccode = C4::Koha::xml_escape( $item->ccode >- && exists $ccodes->{ $item->ccode } ? $ccodes->{ $item->ccode } : $item->ccode ); > my $itemcallnumber = C4::Koha::xml_escape( $item->itemcallnumber ); > my $stocknumber = C4::Koha::xml_escape( $item->stocknumber ); > $xml .= >diff --git a/Koha/Item.pm b/Koha/Item.pm >index ed175d3ced5..a5620dc2971 100644 >--- a/Koha/Item.pm >+++ b/Koha/Item.pm >@@ -31,6 +31,7 @@ use C4::Reserves; > use C4::ClassSource qw( GetClassSort ); > use C4::Log qw( logaction ); > >+use Koha::AuthorisedValues; > use Koha::BackgroundJob::BatchUpdateBiblioHoldsQueue; > use Koha::Biblio::ItemGroups; > use Koha::Checkouts; >@@ -58,6 +59,7 @@ use Koha::StockRotationItem; > use Koha::StockRotationRotas; > use Koha::TrackedLinks; > use Koha::Policy::Holds; >+use Koha::DisplayItems; > > use base qw(Koha::Object); > >@@ -417,6 +419,10 @@ Returns the itemtype for the item based on whether item level itemtypes are set > sub effective_itemtype { > my ($self) = @_; > >+ if ( my $display = $self->active_display ) { >+ return $display->get_column('display_itype') || $self->_result()->effective_itemtype(); >+ } >+ > return $self->_result()->effective_itemtype(); > } > >@@ -783,6 +789,44 @@ sub check_booking { > return $bookings_count ? 0 : 1; > } > >+=head3 active_display_item >+ >+ my $display_item = $item->active_display_item; >+ >+Returns the Koha::DisplayItem object if this item is part of an active display, undef otherwise. >+An active display is one where enabled = 1 and the current date falls within the start_date and end_date range (if set). >+ >+=cut >+ >+sub active_display_item { >+ my ($self) = @_; >+ >+ return unless C4::Context->preference('UseDisplayModule'); >+ >+ my $dtf = Koha::Database->new->schema->storage->datetime_parser; >+ my $today = dt_from_string(); >+ >+ my $display_item = Koha::DisplayItems->search( >+ { >+ itemnumber => $self->itemnumber, >+ 'display.enabled' => 1, >+ -and => [ >+ -or => [ >+ { 'display.start_date' => undef }, >+ { 'display.start_date' => { '<=' => $dtf->format_date($today) } } >+ ], >+ -or => [ >+ { 'display.end_date' => undef }, >+ { 'display.end_date' => { '>=' => $dtf->format_date($today) } } >+ ] >+ ] >+ }, >+ { join => 'display' } >+ )->next; >+ >+ return $display_item; >+} >+ > =head3 request_transfer > > my $transfer = $item->request_transfer( >@@ -2058,6 +2102,10 @@ sub to_api { > $overrides->{effective_item_type_id} = $self->effective_itemtype; > $overrides->{effective_not_for_loan_status} = $self->effective_not_for_loan_status; > $overrides->{effective_bookable} = $self->effective_bookable; >+ $overrides->{effective_location} = $self->effective_location; >+ $overrides->{effective_collection_code} = $self->effective_collection_code; >+ $overrides->{effective_home_library_id} = $self->effective_homebranch; >+ $overrides->{effective_holding_library_id} = $self->effective_holdingbranch; > > return { %$response, %$overrides }; > } >@@ -2178,6 +2226,191 @@ sub effective_bookable { > return $self->bookable // $self->itemtype->bookable; > } > >+=head3 effective_location >+ >+ my $location = $item->effective_location; >+ >+Returns the effective location of the item. If the item is on an active display >+with a display_location, returns the display_location. Otherwise, returns >+the item's location. >+ >+=cut >+ >+sub effective_location { >+ my ($self) = @_; >+ >+ if ( my $display = $self->active_display ) { >+ return $display->display_location >+ if ( $display->display_location ); >+ >+ return "DISPLAY: " . $display->display_name; >+ } >+ >+ return $self->location; >+} >+ >+=head3 effective_collection_code >+ >+ my $ccode = $item->effective_collection_code; >+ >+Returns the effective collection code for the item. If the item is part of an active display >+with a display_code set, returns that code. Otherwise returns the item's regular ccode. >+ >+=cut >+ >+sub effective_collection_code { >+ my ($self) = @_; >+ >+ if ( my $display = $self->active_display ) { >+ return $display->display_code; >+ } >+ >+ return $self->ccode; >+} >+ >+=head3 effective_home_library >+ >+=cut >+ >+sub effective_home_library { >+ my ($self) = @_; >+ >+ return Koha::Libraries->find( $self->effective_homebranch ); >+} >+ >+=head3 effective_home_branch >+ >+=cut >+ >+sub effective_home_branch { >+ return shift->effective_home_library(@_); >+} >+ >+=head3 effective_homebranch >+ >+ my $homebranch = $item->effective_homebranch; >+ >+Returns the effective home branch for the item. If the item is part of an active display >+with a display_branch set, returns that branch. Otherwise returns the item's regular homebranch. >+ >+=cut >+ >+sub effective_homebranch { >+ my ($self) = @_; >+ >+ if ( my $display = $self->active_display ) { >+ return $display->get_column('display_branch'); >+ } >+ >+ return $self->get_column('homebranch'); >+} >+ >+=head3 effective_holding_library >+ >+=cut >+ >+sub effective_holding_library { >+ my ($self) = @_; >+ >+ return Koha::Libraries->find( $self->effective_holdingbranch ); >+} >+ >+=head3 effective_holding_branch >+ >+=cut >+ >+sub effective_holding_branch { >+ return shift->effective_holding_library(@_); >+} >+ >+=head3 effective_holdingbranch >+ >+ my $holdingbranch = $item->effective_holdingbranch; >+ >+Returns the effective holding branch for the item. If the item is part of an active display >+with a display_holding_branch set, returns that branch. Otherwise returns the item's regular holdingbranch. >+ >+=cut >+ >+sub effective_holdingbranch { >+ my ($self) = @_; >+ >+ if ( my $display = $self->active_display ) { >+ return $display->get_column('display_holding_branch'); >+ } >+ >+ return $self->get_column('holdingbranch'); >+} >+ >+=head3 active_display >+ >+ my $display = $item->active_display; >+ >+Returns the active display for this item, if any. Returns undef if the item is not >+currently in an active display. >+ >+An active display is one that: >+- Is enabled >+- Has a start_date that is today or in the past (or no start_date) >+- Has an end_date that is today or in the future (or no end_date) >+- Has a date_remove on the display_item that is today or in the future (or no date_remove) >+ >+=cut >+ >+sub active_display { >+ my ($self) = @_; >+ >+ return unless C4::Context->preference('UseDisplayModule'); >+ >+ my $display_item_rs = $self->_result->display_items( >+ { >+ 'display.enabled' => 1, >+ '-or' => [ >+ 'display.start_date' => { '<=', \'CURDATE()' }, >+ 'display.start_date' => undef >+ ], >+ '-and' => [ >+ '-or' => [ >+ 'display.end_date' => { '>=', \'CURDATE()' }, >+ 'display.end_date' => undef >+ ], >+ '-or' => [ >+ 'date_remove' => { '>=', \'CURDATE()' }, >+ 'date_remove' => undef >+ ] >+ ] >+ }, >+ { >+ join => 'display', >+ order_by => { -desc => 'date_added' } >+ } >+ ); >+ >+ if ( my $display_item = $display_item_rs->first ) { >+ return $display_item->display; >+ } >+ >+ return; >+} >+ >+=head3 location_description >+ >+ my $description = $item->location_description(); >+ >+Returns the human-readable description for the item's location from authorised values. >+ >+=cut >+ >+sub location_description { >+ my ($self) = @_; >+ >+ return '' unless $self->location; >+ >+ my $av = Koha::AuthorisedValues->get_description_by_koha_field( >+ { kohafield => 'items.location', authorised_value => $self->location } ); >+ return $av->{lib} || $self->location; >+} >+ > =head3 orders > > my $orders = $item->orders(); >@@ -2830,10 +3063,8 @@ sub strings_map { > # Handle not null and default values for integers and dates > my $strings = {}; > >- foreach my $col ( @{ $self->_columns } ) { >- >- # By now, we are done with known columns, now check the framework for mappings >- my $field = $self->_result->result_source->name . '.' . $col; >+ my $get_av_desc = sub { >+ my ( $col, $field ) = @_; > > # Check there's an entry in the MARC subfield structure for the field > if ( exists $mss->{$field} >@@ -2848,13 +3079,29 @@ sub strings_map { > undef, $params->{public} > ); > my $type = exists $code_to_type->{$code} ? $code_to_type->{$code} : 'av'; >- $strings->{$col} = { >+ >+ return { > str => $str, > type => $type, > ( $type eq 'av' ? ( category => $code ) : () ), > }; > } > >+ return; >+ }; >+ >+ my @cols = @{ $self->_columns }; >+ push @cols, 'effective_collection_code'; >+ push @cols, 'effective_holding_library_id'; >+ push @cols, 'effective_home_library_id'; >+ push @cols, 'effective_item_type_id'; >+ push @cols, 'effective_location'; >+ >+ foreach my $col (@cols) { >+ >+ # By now, we are done with known columns, now check the framework for mappings >+ my $field = $self->_result->result_source->name . '.' . $col; >+ > if ( $col eq 'booksellerid' ) { > my $booksellerid = $self->booksellerid; > if ($booksellerid) { >@@ -2865,7 +3112,93 @@ sub strings_map { > type => 'acquisition_source' > } if $bookseller; > } >+ >+ next; >+ } >+ >+ if ( $col eq 'effective_collection_code' ) { >+ my $ccode = $self->effective_collection_code; >+ >+ if ($ccode) { >+ my $av = Koha::AuthorisedValues->get_description_by_koha_field( >+ { kohafield => 'items.ccode', authorised_value => $ccode } ); >+ my $description = $av->{lib} || $ccode; >+ >+ $strings->{$col} = { >+ category => 'CCODE', >+ str => $description, >+ type => 'av', >+ } if $description; >+ } >+ >+ next; >+ } >+ >+ if ( $col eq 'effective_holding_library_id' ) { >+ my $holding_library = $self->effective_holding_library; >+ >+ if ($holding_library) { >+ my $description = $holding_library->branchname ? $holding_library->branchname : $holding_library; >+ >+ $strings->{$col} = { >+ str => $description, >+ type => 'library', >+ } if $description; >+ } >+ >+ next; > } >+ >+ if ( $col eq 'effective_home_library_id' ) { >+ my $home_library = $self->effective_home_library; >+ >+ if ($home_library) { >+ my $description = $home_library->branchname ? $home_library->branchname : $home_library; >+ >+ $strings->{$col} = { >+ str => $description, >+ type => 'library', >+ } if $description; >+ } >+ >+ next; >+ } >+ >+ if ( $col eq 'effective_item_type_id' ) { >+ my $itemtype = Koha::ItemTypes->find( $self->effective_itemtype ); >+ >+ if ($itemtype) { >+ my $description = $itemtype->translated_description ? $itemtype->translated_description : $itemtype; >+ >+ $strings->{$col} = { >+ str => $description, >+ type => 'item_type', >+ } if $description; >+ } >+ >+ next; >+ } >+ >+ if ( $col eq 'effective_location' ) { >+ my $location = $self->effective_location; >+ >+ if ($location) { >+ my $av = Koha::AuthorisedValues->get_description_by_koha_field( >+ { kohafield => 'items.location', authorised_value => $location } ); >+ my $description = $av->{lib} || $location; >+ >+ $strings->{$col} = { >+ category => 'LOC', >+ str => $description, >+ type => 'av', >+ } if $description; >+ } >+ >+ next; >+ } >+ >+ my $av_desc = $get_av_desc->( $col, $field ); >+ $strings->{$col} = $av_desc if $av_desc; > } > > return $strings; >diff --git a/Koha/Patron.pm b/Koha/Patron.pm >index c0ef6e292c5..85f90dd8806 100644 >--- a/Koha/Patron.pm >+++ b/Koha/Patron.pm >@@ -2246,6 +2246,30 @@ sub libraries_where_can_see_patrons { > ); > } > >+=head3 libraries_where_can_edit_displays >+ >+ my $libraries = $patron->libraries_where_can_edit_displays; >+ >+Return the list of branchcodes(!) of libraries the patron is allowed to edit >+displays for. The branchcodes are arbitrarily returned sorted. >+ >+If the patron has the 'add_items_to_display_from_any_libraries' permission, >+an empty list is returned as a signal they have access to all libraries. >+ >+=cut >+ >+sub libraries_where_can_edit_displays { >+ my ($self) = @_; >+ >+ return $self->libraries_where_can_see_things( >+ { >+ permission => 'displays', >+ subpermission => 'add_items_to_display_from_any_libraries', >+ group_feature => 'ft_display_group', >+ } >+ ); >+} >+ > =head3 can_see_things_from > > my $can_see = $patron->can_see_things_from( >-- >2.53.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 14962
:
190216
|
190217
|
190218
|
190219
|
190220
|
190221
|
190222
|
190223
|
190224
|
190225
|
190226
|
190227
|
190228
|
190229
|
190230
|
190231
|
190232
|
190571
|
190572
|
193719
|
193720
|
193721
|
193722
|
193723
|
193724
|
193725
|
193726
|
193727
|
193728
|
193729
|
193730
|
193731
|
193732
|
193733
|
193734
|
193735
|
193736
|
193737
|
193738
|
193739
|
193740
|
193741
|
193742
|
193743
|
193744
|
193745
|
193746
|
193747
|
193748
|
193749
|
193750
|
193751
|
193752
|
193753
|
193754
|
193755
|
194285
|
194286
|
194287
|
194288
|
194289
| 194290 |
194291
|
194292
|
194293
|
194294
|
194295
|
194296
|
194297
|
194298
|
194299
|
194300
|
194301
|
194302
|
194303
|
194304
|
194305
|
194306
|
194307
|
194308
|
194309
|
194310
|
194311
|
194312
|
194313
|
194314
|
194315
|
194316
|
194317
|
194318
|
194320
|
194321
|
194322