Bug 29788: Fix batch delete item
[koha.git] / Koha / UI / Table / Builder / Items.pm
1 package Koha::UI::Table::Builder::Items;
2
3 # This file is part of Koha.
4 #
5 # Koha is free software; you can redistribute it and/or modify it
6 # under the terms of the GNU General Public License as published by
7 # the Free Software Foundation; either version 3 of the License, or
8 # (at your option) any later version.
9 #
10 # Koha is distributed in the hope that it will be useful, but
11 # WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # GNU General Public License for more details.
14 #
15 # You should have received a copy of the GNU General Public License
16 # along with Koha; if not, see <http://www.gnu.org/licenses>.
17
18 use Modern::Perl;
19 use List::MoreUtils qw( uniq );
20 use C4::Biblio qw( GetMarcStructure GetMarcFromKohaField IsMarcStructureInternal );
21 use Koha::Items;
22
23 =head1 NAME
24
25 Koha::UI::Table::Builder::Items
26
27 Helper to build a table with a list of items with all their information.
28
29 Items' attributes that are mapped and not mapped will be listed in the table.
30
31 Only attributes that have been defined only once will be displayed (empty string is considered as not defined).
32
33 =head1 API
34
35 =head2 Class methods
36
37 =cut
38
39 =head3 new
40
41     my $table = Koha::UI::Table::Builder::Items->new( { itemnumbers => \@itemnumbers } );
42
43 Constructor.
44
45 =cut
46
47 sub new {
48     my ( $class, $params ) = @_;
49
50     my $self;
51     $self->{itemnumbers} = $params->{itemnumbers} || [];
52
53     bless $self, $class;
54     return $self;
55 }
56
57 =head3 build_table
58
59     my $items_table = Koha::UI::Table::Builder::Items->new( { itemnumbers => \@itemnumbers } )
60                                                      ->build_table;
61
62     my $items   = $items_table->{items};
63     my $headers = $items_table->{headers};
64
65 Build the headers and rows for the table.
66
67 Use it with:
68     [% PROCESS items_table_batchmod headers => headers, items => items %]
69
70 =cut
71
72 sub build_table {
73     my ( $self, $params ) = @_;
74
75     my $items = Koha::Items->search( { itemnumber => $self->{itemnumbers} } );
76
77     my @items;
78     while ( my $item = $items->next ) {
79         my $item_info = $item->columns_to_str;
80         $item_info = {
81             %$item_info,
82             biblio         => $item->biblio,
83             safe_to_delete => $item->safe_to_delete,
84             holds          => $item->biblio->holds->count,
85             item_holds     => $item->holds->count,
86             is_checked_out => $item->checkout || 0,
87         };
88         push @items, $item_info;
89     }
90
91     $self->{headers} = $self->_build_headers( \@items );
92     $self->{items}   = \@items;
93     return $self;
94 }
95
96 =head2 Internal methods
97
98 =cut
99
100 =head3 _build_headers
101
102 Build the headers given the items' info.
103
104 =cut
105
106 sub _build_headers {
107     my ( $self, $items ) = @_;
108
109     my @witness_attributes = uniq map {
110         my $item = $_;
111         map {
112             defined $item->{$_}
113               && !ref( $item->{$_} ) # biblio and safe_to_delete are objects
114               && $item->{$_} ne ""
115               ? $_
116               : ()
117           } keys %$item
118     } @$items;
119
120     my ( $itemtag, $itemsubfield ) =
121       C4::Biblio::GetMarcFromKohaField("items.itemnumber");
122     my $tagslib = C4::Biblio::GetMarcStructure(1);
123     my $subfieldcode_attribute_mappings;
124     for my $subfield_code ( keys %{ $tagslib->{$itemtag} } ) {
125
126         my $subfield = $tagslib->{$itemtag}->{$subfield_code};
127
128         next if IsMarcStructureInternal($subfield);
129         next unless $subfield->{tab} eq 10;    # Is this really needed?
130
131         my $attribute;
132         if ( $subfield->{kohafield} ) {
133             ( $attribute = $subfield->{kohafield} ) =~ s|^items\.||;
134         }
135         else {
136             $attribute = $subfield_code;       # It's in more_subfields_xml
137         }
138         next unless grep { $attribute eq $_ } @witness_attributes;
139         $subfieldcode_attribute_mappings->{$subfield_code} = $attribute;
140     }
141
142     return [
143         map {
144             {
145                 header_value  => $tagslib->{$itemtag}->{$_}->{lib},
146                 attribute     => $subfieldcode_attribute_mappings->{$_},
147                 subfield_code => $_,
148             }
149         } sort keys %$subfieldcode_attribute_mappings
150     ];
151 }
152
153 1