View | Details | Raw Unified | Return to bug 14962
Collapse All | Expand All

(-)a/C4/Circulation.pm (-7 / +81 lines)
Lines 118-123 use Koha::Config::SysPrefs; Link Here
118
use Koha::Charges::Fees;
118
use Koha::Charges::Fees;
119
use Koha::Config::SysPref;
119
use Koha::Config::SysPref;
120
use Koha::Checkouts::ReturnClaims;
120
use Koha::Checkouts::ReturnClaims;
121
use Koha::DisplayItems;
121
use Koha::SearchEngine::Indexer;
122
use Koha::SearchEngine::Indexer;
122
use Koha::Exceptions::Checkout;
123
use Koha::Exceptions::Checkout;
123
use Koha::Plugins;
124
use Koha::Plugins;
Lines 2784-2789 sub AddReturn { Link Here
2784
    my $indexer = Koha::SearchEngine::Indexer->new( { index => $Koha::SearchEngine::BIBLIOS_INDEX } );
2785
    my $indexer = Koha::SearchEngine::Indexer->new( { index => $Koha::SearchEngine::BIBLIOS_INDEX } );
2785
    $indexer->index_records( $item->biblionumber, "specialUpdate", "biblioserver" );
2786
    $indexer->index_records( $item->biblionumber, "specialUpdate", "biblioserver" );
2786
2787
2788
    if ( my $display_item = $item->active_display_item ) {
2789
        my $display       = $display_item->display;
2790
        my $return_over   = $display->display_return_over;
2791
        my $should_remove = 0;
2792
2793
        if ( $return_over eq 'yes - any library' ) {
2794
            $should_remove = 1;
2795
        } elsif ( $return_over eq 'yes - except at home library' ) {
2796
            my $homebranch = $item->homebranch;
2797
            $should_remove = 1 if $branch ne $homebranch;
2798
        }
2799
2800
        if ($should_remove) {
2801
            $display_item->delete;
2802
            $messages->{RemovedFromDisplay} = {
2803
                display_id   => $display->display_id,
2804
                display_name => $display->display_name,
2805
            };
2806
        }
2807
    }
2808
2787
    if ( $doreturn and $issue ) {
2809
    if ( $doreturn and $issue ) {
2788
        my $checkin = Koha::Old::Checkouts->find( $issue->id );
2810
        my $checkin = Koha::Old::Checkouts->find( $issue->id );
2789
2811
Lines 4811-4818 sub GetAgeRestriction { Link Here
4811
4833
4812
sub GetPendingOnSiteCheckouts {
4834
sub GetPendingOnSiteCheckouts {
4813
    my $dbh = C4::Context->dbh;
4835
    my $dbh = C4::Context->dbh;
4814
    return $dbh->selectall_arrayref(
4836
4815
        q|
4837
    my $use_display_module = C4::Context->preference('UseDisplayModule');
4838
4839
    my $sql = q|
4816
        SELECT
4840
        SELECT
4817
          items.barcode,
4841
          items.barcode,
4818
          items.biblionumber,
4842
          items.biblionumber,
Lines 4828-4841 sub GetPendingOnSiteCheckouts { Link Here
4828
          borrowers.firstname,
4852
          borrowers.firstname,
4829
          borrowers.surname,
4853
          borrowers.surname,
4830
          borrowers.cardnumber,
4854
          borrowers.cardnumber,
4831
          borrowers.borrowernumber
4855
          borrowers.borrowernumber|;
4856
4857
    if ($use_display_module) {
4858
        $sql .= q|,
4859
          COALESCE(active_display.display_location, items.location) AS effective_location,
4860
          active_display.display_name,
4861
          active_display.display_location AS raw_display_location|;
4862
    } else {
4863
        $sql .= q|,
4864
          items.location AS effective_location,
4865
          NULL AS display_name,
4866
          NULL AS raw_display_location|;
4867
    }
4868
4869
    $sql .= q|
4832
        FROM items
4870
        FROM items
4833
        LEFT JOIN issues ON items.itemnumber = issues.itemnumber
4871
        LEFT JOIN issues ON items.itemnumber = issues.itemnumber
4834
        LEFT JOIN biblio ON items.biblionumber = biblio.biblionumber
4872
        LEFT JOIN biblio ON items.biblionumber = biblio.biblionumber
4835
        LEFT JOIN borrowers ON issues.borrowernumber = borrowers.borrowernumber
4873
        LEFT JOIN borrowers ON issues.borrowernumber = borrowers.borrowernumber|;
4836
        WHERE issues.onsite_checkout = 1
4874
4837
    |, { Slice => {} }
4875
    if ($use_display_module) {
4838
    );
4876
        $sql .= q|
4877
        LEFT JOIN (
4878
          SELECT
4879
            di.itemnumber,
4880
            d.display_location,
4881
            d.display_name,
4882
            ROW_NUMBER() OVER (PARTITION BY di.itemnumber ORDER BY di.date_added DESC) as rn
4883
          FROM display_items di
4884
          JOIN displays d ON di.display_id = d.display_id
4885
          WHERE d.enabled = 1
4886
            AND (d.start_date IS NULL OR d.start_date <= CURDATE())
4887
            AND (d.end_date IS NULL OR d.end_date >= CURDATE())
4888
            AND (di.date_remove IS NULL OR di.date_remove >= CURDATE())
4889
        ) active_display ON items.itemnumber = active_display.itemnumber AND active_display.rn = 1|;
4890
    }
4891
4892
    $sql .= q|
4893
        WHERE issues.onsite_checkout = 1|;
4894
4895
    my $results = $dbh->selectall_arrayref( $sql, { Slice => {} } );
4896
4897
    # Add effective location description for each item
4898
    foreach my $checkout (@$results) {
4899
        if ( $checkout->{display_name} && !$checkout->{raw_display_location} ) {
4900
4901
            # Item is on display with no specific display location
4902
            $checkout->{effective_location_description} = "DISPLAY: " . $checkout->{display_name};
4903
        } else {
4904
4905
            # Use AuthorisedValues to get effective location description
4906
            my $av = Koha::AuthorisedValues->get_description_by_koha_field(
4907
                { kohafield => 'items.location', authorised_value => $checkout->{effective_location} } );
4908
            $checkout->{effective_location_description} = $av->{lib} || '';
4909
        }
4910
    }
4911
4912
    return $results;
4839
}
4913
}
4840
4914
4841
=head2 GetTopIssues
4915
=head2 GetTopIssues
(-)a/C4/Search.pm (-16 / +171 lines)
Lines 46-51 use C4::XSLT qw( XSLTParse4Display ); Link Here
46
use C4::Reserves qw( GetReserveStatus );
46
use C4::Reserves qw( GetReserveStatus );
47
use C4::Charset  qw( SetUTF8Flag );
47
use C4::Charset  qw( SetUTF8Flag );
48
use Koha::AuthorisedValues;
48
use Koha::AuthorisedValues;
49
use Koha::Displays;
50
use Koha::Items;
49
use Koha::ItemTypes;
51
use Koha::ItemTypes;
50
use Koha::Libraries;
52
use Koha::Libraries;
51
use Koha::Logger;
53
use Koha::Logger;
Lines 1683-1693 sub searchResults { Link Here
1683
    # FIXME - We build an authorised values hash here, using the default framework
1685
    # FIXME - We build an authorised values hash here, using the default framework
1684
    # though it is possible to have different authvals for different fws.
1686
    # though it is possible to have different authvals for different fws.
1685
1687
1688
    ## get metadatas
1689
    my $collections = {
1690
        map { $_->{authorised_value} => $_->{lib} } Koha::AuthorisedValues->get_descriptions_by_koha_field(
1691
            { frameworkcode => '', kohafield => 'items.ccode' }
1692
        )
1693
    };
1686
    my $shelflocations = {
1694
    my $shelflocations = {
1687
        map { $_->{authorised_value} => $_->{lib} } Koha::AuthorisedValues->get_descriptions_by_koha_field(
1695
        map { $_->{authorised_value} => $_->{lib} } Koha::AuthorisedValues->get_descriptions_by_koha_field(
1688
            { frameworkcode => '', kohafield => 'items.location' }
1696
            { frameworkcode => '', kohafield => 'items.location' }
1689
        )
1697
        )
1690
    };
1698
    };
1699
    my $itemtypes = Koha::ItemTypes->search_with_localization;
1700
    my %itemtypes = map { $_->{itemtype} => $_ } @{ $itemtypes->unblessed };
1701
1702
    # Cache for display lookups to avoid repeated queries
1703
    my $display_cache = {};
1704
1705
    # Helper function to get effective location for search results
1706
    my $get_effective_collection_code = sub {
1707
        my ($item) = @_;
1708
        return $collections->{ $item->{ccode} } unless C4::Context->preference('UseDisplayModule');
1709
1710
        my $item_obj = Koha::Items->find( $item->{itemnumber} );
1711
        return $collections->{ $item->{ccode} } unless $item_obj;
1712
1713
        my $effective_collection_code = $item_obj->effective_collection_code;
1714
1715
        # If it starts with "DISPLAY:", validate against displays table
1716
        if ( $effective_collection_code =~ /^DISPLAY:\s*(.+)$/ ) {
1717
            my $display_name = $1;
1718
1719
            # Use cache to avoid repeated database queries
1720
            if ( !exists $display_cache->{$display_name} ) {
1721
                my $display = Koha::Displays->search( { display_name => $display_name } )->next;
1722
                $display_cache->{$display_name} = $display ? $display->display_name : undef;
1723
            }
1724
            return $display_cache->{$display_name}
1725
                ? "DISPLAY: " . $display_cache->{$display_name}
1726
                : $effective_collection_code;
1727
        } else {
1728
            return $collections->{$effective_collection_code};
1729
        }
1730
    };
1731
    my $get_effective_itemtype = sub {
1732
        my ($item) = @_;
1733
        return $itemtypes{ $item->{itype} }{translated_description} unless C4::Context->preference('UseDisplayModule');
1734
1735
        my $item_obj = Koha::Items->find( $item->{itemnumber} );
1736
        return $itemtypes{ $item->{itype} }{translated_description} unless $item_obj;
1737
1738
        my $effective_itemtype = $item_obj->effective_itemtype;
1739
1740
        # If it starts with "DISPLAY:", validate against displays table
1741
        if ( $effective_itemtype =~ /^DISPLAY:\s*(.+)$/ ) {
1742
            my $display_name = $1;
1743
1744
            # Use cache to avoid repeated database queries
1745
            if ( !exists $display_cache->{$display_name} ) {
1746
                my $display = Koha::Displays->search( { display_name => $display_name } )->next;
1747
                $display_cache->{$display_name} = $display ? $display->display_name : undef;
1748
            }
1749
            return $display_cache->{$display_name}
1750
                ? "DISPLAY: " . $display_cache->{$display_name}
1751
                : $effective_itemtype;
1752
        } else {
1753
            return $itemtypes{$effective_itemtype}{translated_description};
1754
        }
1755
    };
1756
    my $get_effective_location = sub {
1757
        my ($item) = @_;
1758
        return $shelflocations->{ $item->{location} } unless C4::Context->preference('UseDisplayModule');
1759
1760
        my $item_obj = Koha::Items->find( $item->{itemnumber} );
1761
        return $shelflocations->{ $item->{location} } unless $item_obj;
1762
1763
        my $effective_loc = $shelflocations->{ $item_obj->effective_location };
1764
1765
        # If it starts with "DISPLAY:", validate against displays table
1766
        if ( $effective_loc =~ /^DISPLAY:\s*(.+)$/ ) {
1767
            my $display_name = $1;
1768
1769
            # Use cache to avoid repeated database queries
1770
            if ( !exists $display_cache->{$display_name} ) {
1771
                my $display = Koha::Displays->search( { display_name => $display_name } )->next;
1772
                $display_cache->{$display_name} = $display ? $display->display_name : undef;
1773
            }
1774
            return $display_cache->{$display_name} ? "DISPLAY: " . $display_cache->{$display_name} : $effective_loc;
1775
        } else {
1776
            return $effective_loc;
1777
        }
1778
    };
1779
    my $get_effective_homebranch = sub {
1780
        my ($item) = @_;
1781
        return $item->{homebranch} unless C4::Context->preference('UseDisplayModule');
1782
1783
        my $item_obj = Koha::Items->find( $item->{itemnumber} );
1784
        return $item->{homebranch} unless $item_obj;
1785
1786
        my $effective_homebranch = $item_obj->effective_homebranch->branchcode;
1787
1788
        # If it starts with "DISPLAY:", validate against displays table
1789
        if ( $effective_homebranch =~ /^DISPLAY:\s*(.+)$/ ) {
1790
            my $display_name = $1;
1791
1792
            # Use cache to avoid repeated database queries
1793
            if ( !exists $display_cache->{$display_name} ) {
1794
                my $display = Koha::Displays->search( { display_name => $display_name } )->next;
1795
                $display_cache->{$display_name} = $display ? $display->display_name : undef;
1796
            }
1797
            return $display_cache->{$display_name}
1798
                ? "DISPLAY: " . $display_cache->{$display_name}
1799
                : $effective_homebranch;
1800
        } else {
1801
            return $effective_homebranch;
1802
        }
1803
    };
1804
    my $get_effective_holdingbranch = sub {
1805
        my ($item) = @_;
1806
        return $item->{holdingbranch} unless C4::Context->preference('UseDisplayModule');
1807
1808
        my $item_obj = Koha::Items->find( $item->{itemnumber} );
1809
        return $item->{holdingbranch} unless $item_obj;
1810
1811
        my $effective_holdingbranch = $item_obj->effective_holdingbranch->branchcode;
1812
1813
        # If it starts with "DISPLAY:", validate against displays table
1814
        if ( $effective_holdingbranch =~ /^DISPLAY:\s*(.+)$/ ) {
1815
            my $display_name = $1;
1816
1817
            # Use cache to avoid repeated database queries
1818
            if ( !exists $display_cache->{$display_name} ) {
1819
                my $display = Koha::Displays->search( { display_name => $display_name } )->next;
1820
                $display_cache->{$display_name} = $display ? $display->display_name : undef;
1821
            }
1822
            return $display_cache->{$display_name}
1823
                ? "DISPLAY: " . $display_cache->{$display_name}
1824
                : $effective_holdingbranch;
1825
        } else {
1826
            return $effective_holdingbranch;
1827
        }
1828
    };
1691
1829
1692
    # get notforloan authorised value list (see $shelflocations  FIXME)
1830
    # get notforloan authorised value list (see $shelflocations  FIXME)
1693
    my $av = Koha::MarcSubfieldStructures->search(
1831
    my $av = Koha::MarcSubfieldStructures->search(
Lines 1698-1707 sub searchResults { Link Here
1698
    );
1836
    );
1699
    my $notforloan_authorised_value = $av->count ? $av->next->authorised_value : undef;
1837
    my $notforloan_authorised_value = $av->count ? $av->next->authorised_value : undef;
1700
1838
1701
    #Get itemtype hash
1702
    my $itemtypes = Koha::ItemTypes->search_with_localization;
1703
    my %itemtypes = map { $_->{itemtype} => $_ } @{ $itemtypes->unblessed };
1704
1705
    #search item field code
1839
    #search item field code
1706
    my ( $itemtag, undef ) = &GetMarcFromKohaField("items.itemnumber");
1840
    my ( $itemtag, undef ) = &GetMarcFromKohaField("items.itemnumber");
1707
1841
Lines 1866-1872 sub searchResults { Link Here
1866
                next;
2000
                next;
1867
            }
2001
            }
1868
2002
1869
            $item->{description} = $itemtypes{ $item->{itype} }{translated_description} if $item->{itype};
2003
            $item->{collectioncode} = $get_effective_collection_code->($item) if $item->{ccode};
2004
            $item->{description}    = $get_effective_itemtype->($item)        if $item->{itype};
2005
            $item->{location}       = $get_effective_location->($item)        if $item->{location};
2006
2007
            $item->{homebranch}    = $get_effective_homebranch->($item)    if $item->{homebranch};
2008
            $item->{holdingbranch} = $get_effective_holdingbranch->($item) if $item->{holdingbranch};
1870
2009
1871
            # OPAC hidden items
2010
            # OPAC hidden items
1872
            if ($is_opac) {
2011
            if ($is_opac) {
Lines 1893-1898 sub searchResults { Link Here
1893
                $item->{'branchcode'} = $item->{$otherbranch};
2032
                $item->{'branchcode'} = $item->{$otherbranch};
1894
            }
2033
            }
1895
2034
2035
            if ( C4::Context->preference('UseDisplayModule') ) {
2036
                my @displays;
2037
                my @display_items = Koha::DisplayItems->search(
2038
                    { itemnumber => $item->{itemnumber} },
2039
                    {
2040
                        order_by => { '-desc' => 'date_added' },
2041
                    }
2042
                )->as_list;
2043
2044
                foreach my $display_item (@display_items) {
2045
                    push @displays, $display_item->display;
2046
                }
2047
2048
                $item->{display_items} = \@display_items if @display_items;
2049
                $item->{displays}      = \@displays      if @displays;
2050
            }
2051
1896
            my $prefix =
2052
            my $prefix =
1897
                  ( $item->{$hbranch}       ? $item->{$hbranch} . '--' : q{} )
2053
                  ( $item->{$hbranch}       ? $item->{$hbranch} . '--' : q{} )
1898
                . ( $item->{location}       ? $item->{location}        : q{} )
2054
                . ( $item->{location}       ? $item->{location}        : q{} )
Lines 1914-1928 sub searchResults { Link Here
1914
                $onloan_items->{$key}->{count}++ if $item->{$hbranch};
2070
                $onloan_items->{$key}->{count}++ if $item->{$hbranch};
1915
                $onloan_items->{$key}->{branchname}     = $item->{branchname};
2071
                $onloan_items->{$key}->{branchname}     = $item->{branchname};
1916
                $onloan_items->{$key}->{branchcode}     = $item->{branchcode};
2072
                $onloan_items->{$key}->{branchcode}     = $item->{branchcode};
1917
                $onloan_items->{$key}->{location}       = $shelflocations->{ $item->{location} } if $item->{location};
2073
                $onloan_items->{$key}->{location}       = $item->{location};
1918
                $onloan_items->{$key}->{itemcallnumber} = $item->{itemcallnumber};
2074
                $onloan_items->{$key}->{itemcallnumber} = $item->{itemcallnumber};
1919
                $onloan_items->{$key}->{description}    = $item->{description};
2075
                $onloan_items->{$key}->{description}    = $item->{description};
1920
                $onloan_items->{$key}->{imageurl}       = getitemtypeimagelocation(
2076
                $onloan_items->{$key}->{imageurl}       = getitemtypeimagelocation(
1921
                    $search_context->{'interface'},
2077
                    $search_context->{'interface'},
1922
                    $itemtypes{ $item->{itype} }->{imageurl}
2078
                    $itemtypes{ $item->{itype} }->{imageurl}
1923
                );
2079
                );
1924
                $onloan_items->{$key}->{collectioncode} =
2080
                $onloan_items->{$key}->{collectioncode} = $item->{collectioncode};
1925
                    GetAuthorisedValueDesc( '', '', $item->{ccode}, '', '', 'CCODE' );
2081
                $onloan_items->{$key}->{displays}       = $item->{displays};
1926
2082
1927
                # if something's checked out and lost, mark it as 'long overdue'
2083
                # if something's checked out and lost, mark it as 'long overdue'
1928
                if ( $item->{itemlost} ) {
2084
                if ( $item->{itemlost} ) {
Lines 2032-2045 sub searchResults { Link Here
2032
                        GetAuthorisedValueDesc( '', '', $item->{notforloan}, '', '', $notforloan_authorised_value )
2188
                        GetAuthorisedValueDesc( '', '', $item->{notforloan}, '', '', $notforloan_authorised_value )
2033
                        if $notforloan_authorised_value and $item->{notforloan};
2189
                        if $notforloan_authorised_value and $item->{notforloan};
2034
                    $other_items->{$key}->{count}++ if $item->{$hbranch};
2190
                    $other_items->{$key}->{count}++ if $item->{$hbranch};
2035
                    $other_items->{$key}->{location}    = $shelflocations->{ $item->{location} } if $item->{location};
2191
                    $other_items->{$key}->{location}    = $item->{location};
2036
                    $other_items->{$key}->{description} = $item->{description};
2192
                    $other_items->{$key}->{description} = $item->{description};
2037
                    $other_items->{$key}->{imageurl}    = getitemtypeimagelocation(
2193
                    $other_items->{$key}->{imageurl}    = getitemtypeimagelocation(
2038
                        $search_context->{'interface'},
2194
                        $search_context->{'interface'},
2039
                        $itemtypes{ $item->{itype} // q{} }->{imageurl}
2195
                        $itemtypes{ $item->{itype} // q{} }->{imageurl}
2040
                    );
2196
                    );
2041
                    $other_items->{$key}->{collectioncode} =
2197
                    $other_items->{$key}->{collectioncode} = $item->{collectioncode};
2042
                        GetAuthorisedValueDesc( '', '', $item->{ccode}, '', '', 'CCODE' );
2198
                    $other_items->{$key}->{displays}       = $item->{displays};
2043
                }
2199
                }
2044
2200
2045
                # item is available
2201
                # item is available
Lines 2053-2066 sub searchResults { Link Here
2053
                    }
2209
                    }
2054
                    $available_items->{$prefix}->{branchavailablecount} = $branch_available_count;
2210
                    $available_items->{$prefix}->{branchavailablecount} = $branch_available_count;
2055
                    $available_items->{$prefix}->{branchcode}           = $item->{branchcode};
2211
                    $available_items->{$prefix}->{branchcode}           = $item->{branchcode};
2056
                    $available_items->{$prefix}->{location}             = $shelflocations->{ $item->{location} }
2212
                    $available_items->{$prefix}->{location}             = $item->{location};
2057
                        if $item->{location};
2213
                    $available_items->{$prefix}->{imageurl}             = getitemtypeimagelocation(
2058
                    $available_items->{$prefix}->{imageurl} = getitemtypeimagelocation(
2059
                        $search_context->{'interface'},
2214
                        $search_context->{'interface'},
2060
                        $itemtypes{ $item->{itype} // q{} }->{imageurl}
2215
                        $itemtypes{ $item->{itype} // q{} }->{imageurl}
2061
                    );
2216
                    );
2062
                    $available_items->{$prefix}->{collectioncode} =
2217
                    $available_items->{$prefix}->{collectioncode} = $item->{collectioncode};
2063
                        GetAuthorisedValueDesc( '', '', $item->{ccode}, '', '', 'CCODE' );
2218
                    $available_items->{$prefix}->{displays}       = $item->{displays};
2064
                }
2219
                }
2065
            }
2220
            }
2066
        }    # notforloan, item level and biblioitem level
2221
        }    # notforloan, item level and biblioitem level
(-)a/C4/XSLT.pm (-7 / +10 lines)
Lines 414-429 sub buildKohaItemsNamespace { Link Here
414
        } else {
414
        } else {
415
            $status = "available";
415
            $status = "available";
416
        }
416
        }
417
        my $homebranch    = C4::Koha::xml_escape( $branches{ $item->homebranch } );
417
        my $homebranch    = C4::Koha::xml_escape( $branches{ $item->effective_homebranch } );
418
        my $holdingbranch = C4::Koha::xml_escape( $branches{ $item->holdingbranch } );
418
        my $holdingbranch = C4::Koha::xml_escape( $branches{ $item->effective_holdingbranch } );
419
        my $resultbranch = C4::Context->preference('OPACResultsLibrary') eq 'homebranch' ? $homebranch : $holdingbranch;
419
        my $resultbranch = C4::Context->preference('OPACResultsLibrary') eq 'homebranch' ? $homebranch : $holdingbranch;
420
        my $location     = C4::Koha::xml_escape(
420
        my $location     = C4::Koha::xml_escape(
421
              $item->location && exists $shelflocations->{ $item->location }
421
              $item->effective_location && exists $shelflocations->{ $item->effective_location }
422
            ? $shelflocations->{ $item->location }
422
            ? $shelflocations->{ $item->effective_location }
423
            : $item->location
423
            : $item->effective_location
424
        );
425
        my $ccode = C4::Koha::xml_escape(
426
              $item->effective_collection_code && exists $ccodes->{ $item->effective_collection_code }
427
            ? $ccodes->{ $item->effective_collection_code }
428
            : $item->effective_collection_code
424
        );
429
        );
425
        my $ccode = C4::Koha::xml_escape( $item->ccode
426
                && exists $ccodes->{ $item->ccode } ? $ccodes->{ $item->ccode } : $item->ccode );
427
        my $itemcallnumber = C4::Koha::xml_escape( $item->itemcallnumber );
430
        my $itemcallnumber = C4::Koha::xml_escape( $item->itemcallnumber );
428
        my $stocknumber    = C4::Koha::xml_escape( $item->stocknumber );
431
        my $stocknumber    = C4::Koha::xml_escape( $item->stocknumber );
429
        $xml .=
432
        $xml .=
(-)a/Koha/Item.pm (-5 / +338 lines)
Lines 31-36 use C4::Reserves; Link Here
31
use C4::ClassSource qw( GetClassSort );
31
use C4::ClassSource qw( GetClassSort );
32
use C4::Log         qw( logaction );
32
use C4::Log         qw( logaction );
33
33
34
use Koha::AuthorisedValues;
34
use Koha::BackgroundJob::BatchUpdateBiblioHoldsQueue;
35
use Koha::BackgroundJob::BatchUpdateBiblioHoldsQueue;
35
use Koha::Biblio::ItemGroups;
36
use Koha::Biblio::ItemGroups;
36
use Koha::Checkouts;
37
use Koha::Checkouts;
Lines 58-63 use Koha::StockRotationItem; Link Here
58
use Koha::StockRotationRotas;
59
use Koha::StockRotationRotas;
59
use Koha::TrackedLinks;
60
use Koha::TrackedLinks;
60
use Koha::Policy::Holds;
61
use Koha::Policy::Holds;
62
use Koha::DisplayItems;
61
63
62
use base qw(Koha::Object);
64
use base qw(Koha::Object);
63
65
Lines 417-422 Returns the itemtype for the item based on whether item level itemtypes are set Link Here
417
sub effective_itemtype {
419
sub effective_itemtype {
418
    my ($self) = @_;
420
    my ($self) = @_;
419
421
422
    if ( my $display = $self->active_display ) {
423
        return $display->get_column('display_itype') || $self->_result()->effective_itemtype();
424
    }
425
420
    return $self->_result()->effective_itemtype();
426
    return $self->_result()->effective_itemtype();
421
}
427
}
422
428
Lines 783-788 sub check_booking { Link Here
783
    return $bookings_count ? 0 : 1;
789
    return $bookings_count ? 0 : 1;
784
}
790
}
785
791
792
=head3 active_display_item
793
794
    my $display_item = $item->active_display_item;
795
796
Returns the Koha::DisplayItem object if this item is part of an active display, undef otherwise.
797
An active display is one where enabled = 1 and the current date falls within the start_date and end_date range (if set).
798
799
=cut
800
801
sub active_display_item {
802
    my ($self) = @_;
803
804
    return unless C4::Context->preference('UseDisplayModule');
805
806
    my $dtf   = Koha::Database->new->schema->storage->datetime_parser;
807
    my $today = dt_from_string();
808
809
    my $display_item = Koha::DisplayItems->search(
810
        {
811
            itemnumber        => $self->itemnumber,
812
            'display.enabled' => 1,
813
            -and              => [
814
                -or => [
815
                    { 'display.start_date' => undef },
816
                    { 'display.start_date' => { '<=' => $dtf->format_date($today) } }
817
                ],
818
                -or => [
819
                    { 'display.end_date' => undef },
820
                    { 'display.end_date' => { '>=' => $dtf->format_date($today) } }
821
                ]
822
            ]
823
        },
824
        { join => 'display' }
825
    )->next;
826
827
    return $display_item;
828
}
829
786
=head3 request_transfer
830
=head3 request_transfer
787
831
788
  my $transfer = $item->request_transfer(
832
  my $transfer = $item->request_transfer(
Lines 2058-2063 sub to_api { Link Here
2058
    $overrides->{effective_item_type_id}        = $self->effective_itemtype;
2102
    $overrides->{effective_item_type_id}        = $self->effective_itemtype;
2059
    $overrides->{effective_not_for_loan_status} = $self->effective_not_for_loan_status;
2103
    $overrides->{effective_not_for_loan_status} = $self->effective_not_for_loan_status;
2060
    $overrides->{effective_bookable}            = $self->effective_bookable;
2104
    $overrides->{effective_bookable}            = $self->effective_bookable;
2105
    $overrides->{effective_location}            = $self->effective_location;
2106
    $overrides->{effective_collection_code}     = $self->effective_collection_code;
2107
    $overrides->{effective_home_library_id}     = $self->effective_homebranch;
2108
    $overrides->{effective_holding_library_id}  = $self->effective_holdingbranch;
2061
2109
2062
    return { %$response, %$overrides };
2110
    return { %$response, %$overrides };
2063
}
2111
}
Lines 2178-2183 sub effective_bookable { Link Here
2178
    return $self->bookable // $self->itemtype->bookable;
2226
    return $self->bookable // $self->itemtype->bookable;
2179
}
2227
}
2180
2228
2229
=head3 effective_location
2230
2231
  my $location = $item->effective_location;
2232
2233
Returns the effective location of the item. If the item is on an active display
2234
with a display_location, returns the display_location. Otherwise, returns
2235
the item's location.
2236
2237
=cut
2238
2239
sub effective_location {
2240
    my ($self) = @_;
2241
2242
    if ( my $display = $self->active_display ) {
2243
        return $display->display_location
2244
            if ( $display->display_location );
2245
2246
        return "DISPLAY: " . $display->display_name;
2247
    }
2248
2249
    return $self->location;
2250
}
2251
2252
=head3 effective_collection_code
2253
2254
    my $ccode = $item->effective_collection_code;
2255
2256
Returns the effective collection code for the item. If the item is part of an active display
2257
with a display_code set, returns that code. Otherwise returns the item's regular ccode.
2258
2259
=cut
2260
2261
sub effective_collection_code {
2262
    my ($self) = @_;
2263
2264
    if ( my $display = $self->active_display ) {
2265
        return $display->display_code;
2266
    }
2267
2268
    return $self->ccode;
2269
}
2270
2271
=head3 effective_home_library
2272
2273
=cut
2274
2275
sub effective_home_library {
2276
    my ($self) = @_;
2277
2278
    return Koha::Libraries->find( $self->effective_homebranch );
2279
}
2280
2281
=head3 effective_home_branch
2282
2283
=cut
2284
2285
sub effective_home_branch {
2286
    return shift->effective_home_library(@_);
2287
}
2288
2289
=head3 effective_homebranch
2290
2291
    my $homebranch = $item->effective_homebranch;
2292
2293
Returns the effective home branch for the item. If the item is part of an active display
2294
with a display_branch set, returns that branch. Otherwise returns the item's regular homebranch.
2295
2296
=cut
2297
2298
sub effective_homebranch {
2299
    my ($self) = @_;
2300
2301
    if ( my $display = $self->active_display ) {
2302
        return $display->get_column('display_branch');
2303
    }
2304
2305
    return $self->get_column('homebranch');
2306
}
2307
2308
=head3 effective_holding_library
2309
2310
=cut
2311
2312
sub effective_holding_library {
2313
    my ($self) = @_;
2314
2315
    return Koha::Libraries->find( $self->effective_holdingbranch );
2316
}
2317
2318
=head3 effective_holding_branch
2319
2320
=cut
2321
2322
sub effective_holding_branch {
2323
    return shift->effective_holding_library(@_);
2324
}
2325
2326
=head3 effective_holdingbranch
2327
2328
    my $holdingbranch = $item->effective_holdingbranch;
2329
2330
Returns the effective holding branch for the item. If the item is part of an active display
2331
with a display_holding_branch set, returns that branch. Otherwise returns the item's regular holdingbranch.
2332
2333
=cut
2334
2335
sub effective_holdingbranch {
2336
    my ($self) = @_;
2337
2338
    if ( my $display = $self->active_display ) {
2339
        return $display->get_column('display_holding_branch');
2340
    }
2341
2342
    return $self->get_column('holdingbranch');
2343
}
2344
2345
=head3 active_display
2346
2347
    my $display = $item->active_display;
2348
2349
Returns the active display for this item, if any. Returns undef if the item is not
2350
currently in an active display.
2351
2352
An active display is one that:
2353
- Is enabled
2354
- Has a start_date that is today or in the past (or no start_date)
2355
- Has an end_date that is today or in the future (or no end_date)
2356
- Has a date_remove on the display_item that is today or in the future (or no date_remove)
2357
2358
=cut
2359
2360
sub active_display {
2361
    my ($self) = @_;
2362
2363
    return unless C4::Context->preference('UseDisplayModule');
2364
2365
    my $display_item_rs = $self->_result->display_items(
2366
        {
2367
            'display.enabled' => 1,
2368
            '-or'             => [
2369
                'display.start_date' => { '<=', \'CURDATE()' },
2370
                'display.start_date' => undef
2371
            ],
2372
            '-and' => [
2373
                '-or' => [
2374
                    'display.end_date' => { '>=', \'CURDATE()' },
2375
                    'display.end_date' => undef
2376
                ],
2377
                '-or' => [
2378
                    'date_remove' => { '>=', \'CURDATE()' },
2379
                    'date_remove' => undef
2380
                ]
2381
            ]
2382
        },
2383
        {
2384
            join     => 'display',
2385
            order_by => { -desc => 'date_added' }
2386
        }
2387
    );
2388
2389
    if ( my $display_item = $display_item_rs->first ) {
2390
        return $display_item->display;
2391
    }
2392
2393
    return;
2394
}
2395
2396
=head3 location_description
2397
2398
    my $description = $item->location_description();
2399
2400
Returns the human-readable description for the item's location from authorised values.
2401
2402
=cut
2403
2404
sub location_description {
2405
    my ($self) = @_;
2406
2407
    return '' unless $self->location;
2408
2409
    my $av = Koha::AuthorisedValues->get_description_by_koha_field(
2410
        { kohafield => 'items.location', authorised_value => $self->location } );
2411
    return $av->{lib} || $self->location;
2412
}
2413
2181
=head3 orders
2414
=head3 orders
2182
2415
2183
  my $orders = $item->orders();
2416
  my $orders = $item->orders();
Lines 2830-2839 sub strings_map { Link Here
2830
    # Handle not null and default values for integers and dates
3063
    # Handle not null and default values for integers and dates
2831
    my $strings = {};
3064
    my $strings = {};
2832
3065
2833
    foreach my $col ( @{ $self->_columns } ) {
3066
    my $get_av_desc = sub {
2834
3067
        my ( $col, $field ) = @_;
2835
        # By now, we are done with known columns, now check the framework for mappings
2836
        my $field = $self->_result->result_source->name . '.' . $col;
2837
3068
2838
        # Check there's an entry in the MARC subfield structure for the field
3069
        # Check there's an entry in the MARC subfield structure for the field
2839
        if (   exists $mss->{$field}
3070
        if (   exists $mss->{$field}
Lines 2848-2860 sub strings_map { Link Here
2848
                undef, $params->{public}
3079
                undef, $params->{public}
2849
            );
3080
            );
2850
            my $type = exists $code_to_type->{$code} ? $code_to_type->{$code} : 'av';
3081
            my $type = exists $code_to_type->{$code} ? $code_to_type->{$code} : 'av';
2851
            $strings->{$col} = {
3082
3083
            return {
2852
                str  => $str,
3084
                str  => $str,
2853
                type => $type,
3085
                type => $type,
2854
                ( $type eq 'av' ? ( category => $code ) : () ),
3086
                ( $type eq 'av' ? ( category => $code ) : () ),
2855
            };
3087
            };
2856
        }
3088
        }
2857
3089
3090
        return;
3091
    };
3092
3093
    my @cols = @{ $self->_columns };
3094
    push @cols, 'effective_collection_code';
3095
    push @cols, 'effective_holding_library_id';
3096
    push @cols, 'effective_home_library_id';
3097
    push @cols, 'effective_item_type_id';
3098
    push @cols, 'effective_location';
3099
3100
    foreach my $col (@cols) {
3101
3102
        # By now, we are done with known columns, now check the framework for mappings
3103
        my $field = $self->_result->result_source->name . '.' . $col;
3104
2858
        if ( $col eq 'booksellerid' ) {
3105
        if ( $col eq 'booksellerid' ) {
2859
            my $booksellerid = $self->booksellerid;
3106
            my $booksellerid = $self->booksellerid;
2860
            if ($booksellerid) {
3107
            if ($booksellerid) {
Lines 2865-2871 sub strings_map { Link Here
2865
                    type => 'acquisition_source'
3112
                    type => 'acquisition_source'
2866
                } if $bookseller;
3113
                } if $bookseller;
2867
            }
3114
            }
3115
3116
            next;
3117
        }
3118
3119
        if ( $col eq 'effective_collection_code' ) {
3120
            my $ccode = $self->effective_collection_code;
3121
3122
            if ($ccode) {
3123
                my $av = Koha::AuthorisedValues->get_description_by_koha_field(
3124
                    { kohafield => 'items.ccode', authorised_value => $ccode } );
3125
                my $description = $av->{lib} || $ccode;
3126
3127
                $strings->{$col} = {
3128
                    category => 'CCODE',
3129
                    str      => $description,
3130
                    type     => 'av',
3131
                } if $description;
3132
            }
3133
3134
            next;
3135
        }
3136
3137
        if ( $col eq 'effective_holding_library_id' ) {
3138
            my $holding_library = $self->effective_holding_library;
3139
3140
            if ($holding_library) {
3141
                my $description = $holding_library->branchname ? $holding_library->branchname : $holding_library;
3142
3143
                $strings->{$col} = {
3144
                    str  => $description,
3145
                    type => 'library',
3146
                } if $description;
3147
            }
3148
3149
            next;
2868
        }
3150
        }
3151
3152
        if ( $col eq 'effective_home_library_id' ) {
3153
            my $home_library = $self->effective_home_library;
3154
3155
            if ($home_library) {
3156
                my $description = $home_library->branchname ? $home_library->branchname : $home_library;
3157
3158
                $strings->{$col} = {
3159
                    str  => $description,
3160
                    type => 'library',
3161
                } if $description;
3162
            }
3163
3164
            next;
3165
        }
3166
3167
        if ( $col eq 'effective_item_type_id' ) {
3168
            my $itemtype = Koha::ItemTypes->find( $self->effective_itemtype );
3169
3170
            if ($itemtype) {
3171
                my $description = $itemtype->translated_description ? $itemtype->translated_description : $itemtype;
3172
3173
                $strings->{$col} = {
3174
                    str  => $description,
3175
                    type => 'item_type',
3176
                } if $description;
3177
            }
3178
3179
            next;
3180
        }
3181
3182
        if ( $col eq 'effective_location' ) {
3183
            my $location = $self->effective_location;
3184
3185
            if ($location) {
3186
                my $av = Koha::AuthorisedValues->get_description_by_koha_field(
3187
                    { kohafield => 'items.location', authorised_value => $location } );
3188
                my $description = $av->{lib} || $location;
3189
3190
                $strings->{$col} = {
3191
                    category => 'LOC',
3192
                    str      => $description,
3193
                    type     => 'av',
3194
                } if $description;
3195
            }
3196
3197
            next;
3198
        }
3199
3200
        my $av_desc = $get_av_desc->( $col, $field );
3201
        $strings->{$col} = $av_desc if $av_desc;
2869
    }
3202
    }
2870
3203
2871
    return $strings;
3204
    return $strings;
(-)a/Koha/Patron.pm (-1 / +24 lines)
Lines 2246-2251 sub libraries_where_can_see_patrons { Link Here
2246
    );
2246
    );
2247
}
2247
}
2248
2248
2249
=head3 libraries_where_can_edit_displays
2250
2251
    my $libraries = $patron->libraries_where_can_edit_displays;
2252
2253
Return the list of branchcodes(!) of libraries the patron is allowed to edit
2254
displays for. The branchcodes are arbitrarily returned sorted.
2255
2256
If the patron has the 'add_items_to_display_from_any_libraries' permission,
2257
an empty list is returned as a signal they have access to all libraries.
2258
2259
=cut
2260
2261
sub libraries_where_can_edit_displays {
2262
    my ($self) = @_;
2263
2264
    return $self->libraries_where_can_see_things(
2265
        {
2266
            permission    => 'displays',
2267
            subpermission => 'add_items_to_display_from_any_libraries',
2268
            group_feature => 'ft_display_group',
2269
        }
2270
    );
2271
}
2272
2249
=head3 can_see_things_from
2273
=head3 can_see_things_from
2250
2274
2251
    my $can_see = $patron->can_see_things_from(
2275
    my $can_see = $patron->can_see_things_from(
2252
- 

Return to bug 14962