Lines 149-283
unless ( $enddate ) {
Link Here
|
149 |
$enddate = $today + DateTime::Duration->new( days => C4::Context->preference('ConfirmFutureHolds') || 0 ); |
149 |
$enddate = $today + DateTime::Duration->new( days => C4::Context->preference('ConfirmFutureHolds') || 0 ); |
150 |
} |
150 |
} |
151 |
|
151 |
|
152 |
my @reservedata; |
152 |
# building query parameters |
153 |
my $dbh = C4::Context->dbh; |
153 |
my %where = ( |
154 |
my $sqldatewhere = ""; |
154 |
'reserve.found' => undef, |
|
|
155 |
'reserve.suspend' => 0, |
156 |
'itembib.itemlost' => 0, |
157 |
'itembib.withdrawn' => 0, |
158 |
'itembib.notforloan' => 0, |
159 |
'itembib.itemnumber' => { -not_in => \'SELECT itemnumber FROM branchtransfers WHERE datearrived IS NULL' } |
160 |
); |
161 |
|
162 |
# date boundaries |
155 |
my $startdate_iso = output_pref({ dt => $startdate, dateformat => 'iso', dateonly => 1 }); |
163 |
my $startdate_iso = output_pref({ dt => $startdate, dateformat => 'iso', dateonly => 1 }); |
156 |
my $enddate_iso = output_pref({ dt => $enddate, dateformat => 'iso', dateonly => 1 }); |
164 |
my $enddate_iso = output_pref({ dt => $enddate, dateformat => 'iso', dateonly => 1 }); |
157 |
|
165 |
if ( $startdate_iso && $enddate_iso ){ |
158 |
$debug and warn $startdate_iso. "\n" . $enddate_iso; |
166 |
$where{'reserve.reservedate'} = [ -and => { '>=', $startdate_iso }, { '<=', $enddate_iso } ]; |
159 |
|
167 |
} elsif ( $startdate_iso ){ |
160 |
my @query_params = (); |
168 |
$where{'reserve.reservedate'} = { '>=', $startdate_iso }; |
161 |
|
169 |
} elsif ( $enddate_iso ){ |
162 |
if ($startdate_iso) { |
170 |
$where{'reserve.reservedate'} = { '<=', $enddate_iso }; |
163 |
$sqldatewhere .= " AND reservedate >= ?"; |
|
|
164 |
push @query_params, $startdate_iso; |
165 |
} |
166 |
if ($enddate_iso) { |
167 |
$sqldatewhere .= " AND reservedate <= ?"; |
168 |
push @query_params, $enddate_iso; |
169 |
} |
171 |
} |
170 |
|
172 |
|
171 |
my $item_type = C4::Context->preference('item-level_itypes') ? "items.itype" : "biblioitems.itemtype"; |
|
|
172 |
|
173 |
# Bug 21320 |
173 |
# Bug 21320 |
174 |
if ( ! C4::Context->preference('AllowHoldsOnDamagedItems') ) { |
174 |
if ( !C4::Context->preference('AllowHoldsOnDamagedItems') ){ |
175 |
$sqldatewhere .= " AND damaged = 0"; |
175 |
$where{'itembib.damaged'} = 0; |
176 |
} |
176 |
} |
177 |
|
177 |
|
178 |
my $strsth = |
178 |
if ( C4::Context->preference('IndependentBranches') ){ |
179 |
"SELECT min(reservedate) as l_reservedate, |
179 |
$where{'itembib.holdingbranch'} = C4::Context->userenv->{'branch'}; |
180 |
reserves.reserve_id, |
|
|
181 |
reserves.borrowernumber as borrowernumber, |
182 |
|
183 |
GROUP_CONCAT(DISTINCT items.holdingbranch |
184 |
ORDER BY items.itemnumber SEPARATOR '|') l_holdingbranch, |
185 |
reserves.biblionumber, |
186 |
reserves.branchcode as l_branch, |
187 |
reserves.itemnumber, |
188 |
items.holdingbranch, |
189 |
items.homebranch, |
190 |
GROUP_CONCAT(DISTINCT $item_type |
191 |
ORDER BY items.itemnumber SEPARATOR '|') l_item_type, |
192 |
GROUP_CONCAT(DISTINCT items.location |
193 |
ORDER BY items.itemnumber SEPARATOR '|') l_location, |
194 |
GROUP_CONCAT(DISTINCT items.itemcallnumber |
195 |
ORDER BY items.itemnumber SEPARATOR '|') l_itemcallnumber, |
196 |
GROUP_CONCAT(DISTINCT items.enumchron |
197 |
ORDER BY items.itemnumber SEPARATOR '|') l_enumchron, |
198 |
GROUP_CONCAT(DISTINCT items.copynumber |
199 |
ORDER BY items.itemnumber SEPARATOR '|') l_copynumber, |
200 |
biblio.title, |
201 |
biblio.subtitle, |
202 |
biblio.medium, |
203 |
biblio.part_number, |
204 |
biblio.part_name, |
205 |
biblio.author, |
206 |
count(DISTINCT items.itemnumber) as icount, |
207 |
count(DISTINCT reserves.borrowernumber) as rcount, |
208 |
borrowers.firstname, |
209 |
borrowers.surname |
210 |
FROM reserves |
211 |
LEFT JOIN items ON items.biblionumber=reserves.biblionumber |
212 |
LEFT JOIN biblio ON reserves.biblionumber=biblio.biblionumber |
213 |
LEFT JOIN biblioitems ON biblio.biblionumber=biblioitems.biblionumber |
214 |
LEFT JOIN branchtransfers ON items.itemnumber=branchtransfers.itemnumber |
215 |
LEFT JOIN issues ON items.itemnumber=issues.itemnumber |
216 |
LEFT JOIN borrowers ON reserves.borrowernumber=borrowers.borrowernumber |
217 |
LEFT JOIN circulation_rules ON ( items.itype=circulation_rules.itemtype AND rule_name = 'holdallowed' AND circulation_rules.branchcode IS NULL AND circulation_rules.categorycode IS NULL ) |
218 |
WHERE |
219 |
reserves.found IS NULL |
220 |
$sqldatewhere |
221 |
AND (reserves.itemnumber IS NULL OR reserves.itemnumber = items.itemnumber) |
222 |
AND items.itemnumber NOT IN (SELECT itemnumber FROM branchtransfers where datearrived IS NULL) |
223 |
AND items.itemnumber NOT IN (select itemnumber FROM reserves where found IS NOT NULL) |
224 |
AND issues.itemnumber IS NULL |
225 |
AND reserves.priority <> 0 |
226 |
AND reserves.suspend = 0 |
227 |
AND notforloan = 0 AND itemlost = 0 AND withdrawn = 0 |
228 |
AND ( circulation_rules.rule_value IS NULL OR circulation_rules.rule_value != 0 ) |
229 |
"; |
230 |
# GROUP BY reserves.biblionumber allows only items that are not checked out, else multiples occur when |
231 |
# multiple patrons have a hold on an item |
232 |
|
233 |
|
234 |
if (C4::Context->preference('IndependentBranches')){ |
235 |
$strsth .= " AND items.holdingbranch=? "; |
236 |
push @query_params, C4::Context->userenv->{'branch'}; |
237 |
} |
180 |
} |
238 |
$strsth .= " GROUP BY reserves.biblionumber ORDER BY biblio.title "; |
181 |
|
239 |
|
182 |
# get all distinct unfulfilled reserves |
240 |
my $sth = $dbh->prepare($strsth); |
183 |
my @distinct_holds = Koha::Holds->search( |
241 |
$sth->execute(@query_params); |
184 |
{ %where }, |
242 |
|
185 |
{ join => 'itembib', group_by => 'reserve.biblionumber', alias => 'reserve' } |
243 |
while ( my $data = $sth->fetchrow_hashref ) { |
186 |
); |
244 |
push( |
187 |
|
245 |
@reservedata, { |
188 |
# make final reserves hash and fill with info |
246 |
reservedate => $data->{l_reservedate}, |
189 |
my $reserves; |
247 |
firstname => $data->{firstname} || '', |
190 |
foreach my $dh ( @distinct_holds ){ |
248 |
surname => $data->{surname}, |
191 |
|
249 |
title => $data->{title}, |
192 |
my $bibnum = $dh->biblionumber; |
250 |
subtitle => $data->{subtitle}, |
193 |
|
251 |
medium => $data->{medium}, |
194 |
# get available item types for each biblio |
252 |
part_number => $data->{part_number}, |
195 |
my $res_itemtypes; |
253 |
part_name => $data->{part_name}, |
196 |
if ( C4::Context->preference('item-level_itypes') ){ |
254 |
author => $data->{author}, |
197 |
$res_itemtypes = Koha::Items->search( |
255 |
borrowernumber => $data->{borrowernumber}, |
198 |
{ biblionumber => $bibnum, itype => { '!=', undef } }, |
256 |
biblionumber => $data->{biblionumber}, |
199 |
{ group_by => 'itype' } |
257 |
holdingbranches => [split('\|', $data->{l_holdingbranch})], |
200 |
); |
258 |
branch => $data->{l_branch}, |
201 |
} else { |
259 |
itemcallnumber => [split('\|', $data->{l_itemcallnumber})], |
202 |
$res_itemtypes = Koha::Biblioitems->search( |
260 |
enumchron => [split('\|', $data->{l_enumchron})], |
203 |
{ biblionumber => $bibnum, itemtype => { '!=', undef } }, |
261 |
copyno => [split('\|', $data->{l_copynumber})], |
204 |
{ group_by => 'itemtype' } |
262 |
count => $data->{icount}, |
205 |
); |
263 |
rcount => $data->{rcount}, |
206 |
} |
264 |
pullcount => $data->{icount} <= $data->{rcount} ? $data->{icount} : $data->{rcount}, |
207 |
$reserves->{$bibnum}->{itemtypes} = $res_itemtypes; |
265 |
itemTypes => [split('\|', $data->{l_item_type})], |
208 |
|
266 |
locations => [split('\|', $data->{l_location})], |
209 |
# get available locations for each biblio |
267 |
reserve_id => $data->{reserve_id}, |
210 |
my $res_locations = Koha::Items->search( |
268 |
holdingbranch => $data->{holdingbranch}, |
211 |
{ biblionumber => $bibnum, location => { '!=', undef } }, |
269 |
homebranch => $data->{homebranch}, |
212 |
{ group_by => 'location' } |
270 |
itemnumber => $data->{itemnumber}, |
213 |
); |
271 |
} |
214 |
$reserves->{$bibnum}->{locations} = $res_locations; |
|
|
215 |
|
216 |
# get available callnumbers for each biblio |
217 |
my $res_callnumbers = Koha::Items->search( |
218 |
{ biblionumber => $bibnum, itemcallnumber => { '!=', undef } }, |
219 |
{ group_by => 'itemcallnumber' } |
220 |
); |
221 |
$reserves->{$bibnum}->{callnumbers} = $res_callnumbers; |
222 |
|
223 |
# get available enumchrons for each biblio |
224 |
my $res_enumchrons = Koha::Items->search( |
225 |
{ biblionumber => $bibnum, enumchron => { '!=', undef } }, |
226 |
{ group_by => 'enumchron' } |
227 |
); |
228 |
$reserves->{$bibnum}->{enumchrons} = $res_enumchrons; |
229 |
|
230 |
# get available copynumbers for each biblio |
231 |
my $res_copynumbers = Koha::Items->search( |
232 |
{ biblionumber => $bibnum, copynumber => { '!=', undef } }, |
233 |
{ group_by => 'copynumber' } |
272 |
); |
234 |
); |
|
|
235 |
$reserves->{$bibnum}->{copynumbers} = $res_copynumbers; |
236 |
|
237 |
# get available holding branches for each biblio |
238 |
my $res_holdingbranches = Koha::Items->search( |
239 |
{ biblionumber => $bibnum, holdingbranch => { '!=', undef } }, |
240 |
{ group_by => 'holdingbranch' } |
241 |
); |
242 |
$reserves->{$bibnum}->{holdingbranches} = $res_holdingbranches; |
243 |
|
244 |
# items available |
245 |
my $items_count = Koha::Items->search( |
246 |
{ biblionumber => $bibnum }, |
247 |
{ select => [ { distinct => 'itemnumber' } ] } |
248 |
)->count; |
249 |
$reserves->{$bibnum}->{items_count} = $items_count; |
250 |
|
251 |
# patrons with holds |
252 |
my $patrons_count = Koha::Holds->search( |
253 |
{ biblionumber => $bibnum }, |
254 |
{ select => [ { distinct => 'borrowernumber' } ] } |
255 |
)->count; |
256 |
$reserves->{$bibnum}->{patrons_count} = $patrons_count; |
257 |
|
258 |
my $pull_count = $items_count <= $patrons_count ? $items_count : $patrons_count; |
259 |
$reserves->{$bibnum}->{pull_count} = $pull_count; |
260 |
|
261 |
# get other relevant information |
262 |
my $res_info = Koha::Holds->search( |
263 |
{ 'reserve.biblionumber' => $bibnum, %where }, |
264 |
{ prefetch => [ 'borrowernumber', 'itembib', 'biblio' ], |
265 |
order_by => 'reserve.reservedate', |
266 |
alias => 'reserve' |
267 |
} |
268 |
)->next; # get first item in results |
269 |
$reserves->{$bibnum}->{borrower} = $res_info->borrower; |
270 |
$reserves->{$bibnum}->{item} = $res_info->item; |
271 |
$reserves->{$bibnum}->{biblio} = $res_info->biblio; |
272 |
$reserves->{$bibnum}->{reserve} = $res_info; |
273 |
} |
273 |
} |
274 |
$sth->finish; |
|
|
275 |
|
274 |
|
276 |
$template->param( |
275 |
$template->param( |
277 |
todaysdate => $today, |
276 |
todaysdate => $today, |
278 |
from => $startdate, |
277 |
from => $startdate, |
279 |
to => $enddate, |
278 |
to => $enddate, |
280 |
reserveloop => \@reservedata, |
279 |
reserves => $reserves, |
281 |
"BiblioDefaultView".C4::Context->preference("BiblioDefaultView") => 1, |
280 |
"BiblioDefaultView".C4::Context->preference("BiblioDefaultView") => 1, |
282 |
HoldsToPullStartDate => C4::Context->preference('HoldsToPullStartDate') || PULL_INTERVAL, |
281 |
HoldsToPullStartDate => C4::Context->preference('HoldsToPullStartDate') || PULL_INTERVAL, |
283 |
HoldsToPullEndDate => C4::Context->preference('ConfirmFutureHolds') || 0, |
282 |
HoldsToPullEndDate => C4::Context->preference('ConfirmFutureHolds') || 0, |