Bug 20473: Whitespace
[koha.git] / Koha / Holds.pm
1 package Koha::Holds;
2
3 # Copyright ByWater Solutions 2014
4 #
5 # This file is part of Koha.
6 #
7 # Koha is free software; you can redistribute it and/or modify it
8 # under the terms of the GNU General Public License as published by
9 # the Free Software Foundation; either version 3 of the License, or
10 # (at your option) any later version.
11 #
12 # Koha is distributed in the hope that it will be useful, but
13 # WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 # GNU General Public License for more details.
16 #
17 # You should have received a copy of the GNU General Public License
18 # along with Koha; if not, see <http://www.gnu.org/licenses>.
19
20 use Modern::Perl;
21
22
23 use Koha::Database;
24
25 use Koha::Hold;
26
27 use base qw(Koha::Objects);
28
29 =head1 NAME
30
31 Koha::Holds - Koha Hold object set class
32
33 =head1 API
34
35 =head2 Class methods
36
37 =head3 filter_by_found
38
39     my $found_holds = $holds->filter_by_found;
40
41 Returns a filtered resultset without holds that are considered I<found>.
42 i.e. 'P', 'T' and 'W'.
43
44 =cut
45
46 sub filter_by_found {
47     my ($self) = @_;
48
49     return $self->search( { found => [ 'P', 'T', 'W' ] } );
50 }
51
52 =head3 waiting
53
54 returns a set of holds that are waiting from an existing set
55
56 =cut
57
58 sub waiting {
59     my ( $self ) = @_;
60
61     return $self->search( { found => 'W' } );
62 }
63
64 =head3 processing
65
66 returns a set of holds that are processing from an existing set
67
68 =cut
69
70 sub processing {
71     my ( $self ) = @_;
72
73     return $self->search( { found => 'P' } );
74 }
75
76 =head3 unfilled
77
78 returns a set of holds that are unfilled from an existing set
79
80 =cut
81
82 sub unfilled {
83     my ( $self ) = @_;
84
85     return $self->search( { found => undef } );
86 }
87
88 =head3 forced_hold_level
89
90 If a patron has multiple holds for a single record,
91 those holds must be either all record level holds,
92 or they must all be item level holds.
93
94 This method should be used with Hold sets where all
95 Hold objects share the same patron and record.
96
97 This method will return 'item' if the patron has
98 at least one item level hold. It will return 'record'
99 if the patron has holds but none are item level,
100 Finally, if the patron has no holds, it will return
101 undef which indicates the patron may select either
102 record or item level holds, barring any other rules
103 that would prevent one or the other.
104
105 =cut
106
107 sub forced_hold_level {
108     my ($self) = @_;
109
110     my $item_level_count = $self->search( { itemnumber => { '!=' => undef } } )->count();
111     return 'item' if $item_level_count > 0;
112
113     my $item_group_level_count = $self->search( { item_group_id => { '!=' => undef } } )->count();
114     return 'item_group' if $item_group_level_count > 0;
115
116     my $record_level_count = $self->search( { itemnumber => undef } )->count();
117     return 'record' if $record_level_count > 0;
118
119     return;
120 }
121
122 =head3 get_items_that_can_fill
123
124     my $items = $holds->get_items_that_can_fill();
125
126 Return the list of items that can fill the hold set.
127
128 Items that are not:
129
130   in transit
131   waiting
132   lost
133   widthdrawn
134   not for loan
135   not on loan
136
137 =cut
138
139 sub get_items_that_can_fill {
140     my ( $self ) = @_;
141
142     return Koha::Items->new->empty()
143       unless $self->count() > 0;
144
145     my @itemnumbers = $self->search({ 'me.itemnumber' => { '!=' => undef } })->get_column('itemnumber');
146     my @biblionumbers = $self->search({ 'me.itemnumber' => undef })->get_column('biblionumber');
147     my @bibs_or_items;
148     push @bibs_or_items, 'me.itemnumber' => { in => \@itemnumbers } if @itemnumbers;
149     push @bibs_or_items, 'me.biblionumber' => { in => \@biblionumbers } if @biblionumbers;
150
151     my @branchtransfers = Koha::Item::Transfers->filter_by_current->search({}, {
152             columns  => ['itemnumber'],
153             collapse => 1,
154         }
155     )->get_column('itemnumber');
156     my @waiting_holds = Koha::Holds->search(
157         { 'found' => 'W' },
158         {
159             columns  => ['itemnumber'],
160             collapse => 1,
161         }
162     )->get_column('itemnumber');
163
164     return Koha::Items->search(
165         {
166             -or => \@bibs_or_items,
167             itemnumber   => { -not_in => [ @branchtransfers, @waiting_holds ] },
168             onloan       => undef,
169             notforloan   => 0,
170         }
171     )->filter_by_for_hold();
172 }
173
174 =head3 filter_by_has_cancellation_requests
175
176     my $with_cancellation_reqs = $holds->filter_by_has_cancellation_requests;
177
178 Returns a filtered resultset only containing holds that have cancellation requests.
179
180 =cut
181
182 sub filter_by_has_cancellation_requests {
183     my ($self) = @_;
184
185     return $self->search( { 'hold_cancellation_request_id' => { '!=' => undef } },
186         { join => 'cancellation_requests' } );
187 }
188
189 =head3 filter_out_has_cancellation_requests
190
191     my $holds_without_cancellation_requests = $holds->filter_out_has_cancellation_requests;
192
193 Returns a filtered resultset without holds with cancellation requests.
194
195 =cut
196
197 sub filter_out_has_cancellation_requests {
198     my ($self) = @_;
199
200     return $self->search( { 'hold_cancellation_request_id' => { '=' => undef } },
201         { join => 'cancellation_requests' } );
202 }
203
204 =head2 Internal methods
205
206 =head3 _type
207
208 =cut
209
210 sub _type {
211     return 'Reserve';
212 }
213
214 =head3 object_class
215
216 =cut
217
218 sub object_class {
219     return 'Koha::Hold';
220 }
221
222 =head1 AUTHOR
223
224 Kyle M Hall <kyle@bywatersolutions.com>
225
226 =cut
227
228 1;