Lines 32-38
use C4::Items;
Link Here
|
32 |
use C4::Biblio qw( GetMarcFromKohaField ModBiblio ); |
32 |
use C4::Biblio qw( GetMarcFromKohaField ModBiblio ); |
33 |
use C4::HoldsQueue; |
33 |
use C4::HoldsQueue; |
34 |
use C4::Members; |
34 |
use C4::Members; |
35 |
use C4::Reserves qw( AddReserve AlterPriority CheckReserves ModReserve ModReserveAffect ReserveSlip CalculatePriority CanReserveBeCanceledFromOpac CanBookBeReserved IsAvailableForItemLevelRequest MoveReserve ChargeReserveFee RevertWaitingStatus CanItemBeReserved MergeHolds ); |
35 |
use C4::Reserves |
|
|
36 |
qw( AddReserve AlterPriority CheckReserves ModReserve ModReserveAffect ReserveSlip CalculatePriority CanReserveBeCanceledFromOpac CanBookBeReserved IsAvailableForItemLevelRequest MoveReserve ChargeReserveFee RevertWaitingStatus CanItemBeReserved MergeHolds ); |
36 |
use Koha::ActionLogs; |
37 |
use Koha::ActionLogs; |
37 |
use Koha::Biblios; |
38 |
use Koha::Biblios; |
38 |
use Koha::Caches; |
39 |
use Koha::Caches; |
Lines 51-57
BEGIN {
Link Here
|
51 |
|
52 |
|
52 |
# Start transaction |
53 |
# Start transaction |
53 |
my $database = Koha::Database->new(); |
54 |
my $database = Koha::Database->new(); |
54 |
my $schema = $database->schema(); |
55 |
my $schema = $database->schema(); |
55 |
$schema->storage->txn_begin(); |
56 |
$schema->storage->txn_begin(); |
56 |
my $dbh = C4::Context->dbh; |
57 |
my $dbh = C4::Context->dbh; |
57 |
$dbh->do('DELETE FROM circulation_rules'); |
58 |
$dbh->do('DELETE FROM circulation_rules'); |
Lines 60-70
my $builder = t::lib::TestBuilder->new;
Link Here
|
60 |
|
61 |
|
61 |
my $frameworkcode = q//; |
62 |
my $frameworkcode = q//; |
62 |
|
63 |
|
63 |
|
64 |
t::lib::Mocks::mock_preference( 'ReservesNeedReturns', 1 ); |
64 |
t::lib::Mocks::mock_preference('ReservesNeedReturns', 1); |
|
|
65 |
|
65 |
|
66 |
# Somewhat arbitrary field chosen for age restriction unit tests. Must be added to db before the framework is cached |
66 |
# Somewhat arbitrary field chosen for age restriction unit tests. Must be added to db before the framework is cached |
67 |
$dbh->do("update marc_subfield_structure set kohafield='biblioitems.agerestriction' where tagfield='521' and tagsubfield='a' and frameworkcode=?", undef, $frameworkcode); |
67 |
$dbh->do( |
|
|
68 |
"update marc_subfield_structure set kohafield='biblioitems.agerestriction' where tagfield='521' and tagsubfield='a' and frameworkcode=?", |
69 |
undef, $frameworkcode |
70 |
); |
68 |
my $cache = Koha::Caches->get_instance; |
71 |
my $cache = Koha::Caches->get_instance; |
69 |
$cache->clear_from_cache("MarcStructure-0-$frameworkcode"); |
72 |
$cache->clear_from_cache("MarcStructure-0-$frameworkcode"); |
70 |
$cache->clear_from_cache("MarcStructure-1-$frameworkcode"); |
73 |
$cache->clear_from_cache("MarcStructure-1-$frameworkcode"); |
Lines 72-112
$cache->clear_from_cache("MarcSubfieldStructure-$frameworkcode");
Link Here
|
72 |
|
75 |
|
73 |
## Setup Test |
76 |
## Setup Test |
74 |
# Add branches |
77 |
# Add branches |
75 |
my $branch_1 = $builder->build({ source => 'Branch' })->{ branchcode }; |
78 |
my $branch_1 = $builder->build( { source => 'Branch' } )->{branchcode}; |
76 |
my $branch_2 = $builder->build({ source => 'Branch' })->{ branchcode }; |
79 |
my $branch_2 = $builder->build( { source => 'Branch' } )->{branchcode}; |
77 |
my $branch_3 = $builder->build({ source => 'Branch' })->{ branchcode }; |
80 |
my $branch_3 = $builder->build( { source => 'Branch' } )->{branchcode}; |
|
|
81 |
|
78 |
# Add categories |
82 |
# Add categories |
79 |
my $category_1 = $builder->build({ source => 'Category' })->{ categorycode }; |
83 |
my $category_1 = $builder->build( { source => 'Category' } )->{categorycode}; |
80 |
my $category_2 = $builder->build({ source => 'Category' })->{ categorycode }; |
84 |
my $category_2 = $builder->build( { source => 'Category' } )->{categorycode}; |
|
|
85 |
|
81 |
# Add an item type |
86 |
# Add an item type |
82 |
my $itemtype = $builder->build( |
87 |
my $itemtype = $builder->build( { source => 'Itemtype', value => { notforloan => undef } } )->{itemtype}; |
83 |
{ source => 'Itemtype', value => { notforloan => undef } } )->{itemtype}; |
|
|
84 |
|
88 |
|
85 |
t::lib::Mocks::mock_userenv({ branchcode => $branch_1 }); |
89 |
t::lib::Mocks::mock_userenv( { branchcode => $branch_1 } ); |
86 |
|
90 |
|
87 |
my $bibnum = $builder->build_sample_biblio({frameworkcode => $frameworkcode})->biblionumber; |
91 |
my $bibnum = $builder->build_sample_biblio( { frameworkcode => $frameworkcode } )->biblionumber; |
88 |
|
92 |
|
89 |
# Create a helper item instance for testing |
93 |
# Create a helper item instance for testing |
90 |
my $item = $builder->build_sample_item({ biblionumber => $bibnum, library => $branch_1, itype => $itemtype }); |
94 |
my $item = $builder->build_sample_item( { biblionumber => $bibnum, library => $branch_1, itype => $itemtype } ); |
91 |
|
95 |
|
92 |
my $biblio_with_no_item = $builder->build_sample_biblio; |
96 |
my $biblio_with_no_item = $builder->build_sample_biblio; |
93 |
|
97 |
|
94 |
# Modify item; setting barcode. |
98 |
# Modify item; setting barcode. |
95 |
my $testbarcode = '97531'; |
99 |
my $testbarcode = '97531'; |
96 |
$item->barcode($testbarcode)->store; # FIXME We should not hardcode a barcode! Also, what's the purpose of this? |
100 |
$item->barcode($testbarcode)->store; # FIXME We should not hardcode a barcode! Also, what's the purpose of this? |
97 |
|
|
|
98 |
|
101 |
|
99 |
# Create a borrower |
102 |
# Create a borrower |
100 |
my %data = ( |
103 |
my %data = ( |
101 |
firstname => 'my firstname', |
104 |
firstname => 'my firstname', |
102 |
surname => 'my surname', |
105 |
surname => 'my surname', |
103 |
categorycode => $category_1, |
106 |
categorycode => $category_1, |
104 |
branchcode => $branch_1, |
107 |
branchcode => $branch_1, |
105 |
); |
108 |
); |
106 |
Koha::Patron::Categories->find($category_1)->set({ enrolmentfee => 0})->store; |
109 |
Koha::Patron::Categories->find($category_1)->set( { enrolmentfee => 0 } )->store; |
107 |
my $borrowernumber = Koha::Patron->new(\%data)->store->borrowernumber; |
110 |
my $borrowernumber = Koha::Patron->new( \%data )->store->borrowernumber; |
108 |
my $patron = Koha::Patrons->find( $borrowernumber ); |
111 |
my $patron = Koha::Patrons->find($borrowernumber); |
109 |
my $borrower = $patron->unblessed; |
112 |
my $borrower = $patron->unblessed; |
110 |
my $biblionumber = $bibnum; |
113 |
my $biblionumber = $bibnum; |
111 |
|
114 |
|
112 |
my $branchcode = Koha::Libraries->search->next->branchcode; |
115 |
my $branchcode = Koha::Libraries->search->next->branchcode; |
Lines 120-160
AddReserve(
Link Here
|
120 |
} |
123 |
} |
121 |
); |
124 |
); |
122 |
|
125 |
|
123 |
my ($status, $reserve, $all_reserves) = CheckReserves( $item ); |
126 |
my ( $status, $reserve, $all_reserves ) = CheckReserves($item); |
124 |
|
127 |
|
125 |
is($status, "Reserved", "CheckReserves Test 1"); |
128 |
is( $status, "Reserved", "CheckReserves Test 1" ); |
126 |
|
129 |
|
127 |
ok(exists($reserve->{reserve_id}), 'CheckReserves() include reserve_id in its response'); |
130 |
ok( exists( $reserve->{reserve_id} ), 'CheckReserves() include reserve_id in its response' ); |
128 |
|
131 |
|
129 |
($status, $reserve, $all_reserves) = CheckReserves( $item ); |
132 |
( $status, $reserve, $all_reserves ) = CheckReserves($item); |
130 |
is($status, "Reserved", "CheckReserves Test 2"); |
133 |
is( $status, "Reserved", "CheckReserves Test 2" ); |
131 |
|
134 |
|
132 |
### |
135 |
### |
133 |
### Regression test for bug 10272 |
136 |
### Regression test for bug 10272 |
134 |
### |
137 |
### |
135 |
my %requesters = (); |
138 |
my %requesters = (); |
136 |
$requesters{$branch_1} = Koha::Patron->new({ |
139 |
$requesters{$branch_1} = Koha::Patron->new( |
137 |
branchcode => $branch_1, |
140 |
{ |
138 |
categorycode => $category_2, |
|
|
139 |
surname => "borrower from $branch_1", |
140 |
})->store->borrowernumber; |
141 |
for my $i ( 2 .. 5 ) { |
142 |
$requesters{"CPL$i"} = Koha::Patron->new({ |
143 |
branchcode => $branch_1, |
141 |
branchcode => $branch_1, |
144 |
categorycode => $category_2, |
142 |
categorycode => $category_2, |
145 |
surname => "borrower $i from $branch_1", |
143 |
surname => "borrower from $branch_1", |
146 |
})->store->borrowernumber; |
144 |
} |
|
|
145 |
)->store->borrowernumber; |
146 |
for my $i ( 2 .. 5 ) { |
147 |
$requesters{"CPL$i"} = Koha::Patron->new( |
148 |
{ |
149 |
branchcode => $branch_1, |
150 |
categorycode => $category_2, |
151 |
surname => "borrower $i from $branch_1", |
152 |
} |
153 |
)->store->borrowernumber; |
147 |
} |
154 |
} |
148 |
$requesters{$branch_2} = Koha::Patron->new({ |
155 |
$requesters{$branch_2} = Koha::Patron->new( |
149 |
branchcode => $branch_2, |
156 |
{ |
150 |
categorycode => $category_2, |
157 |
branchcode => $branch_2, |
151 |
surname => "borrower from $branch_2", |
158 |
categorycode => $category_2, |
152 |
})->store->borrowernumber; |
159 |
surname => "borrower from $branch_2", |
153 |
$requesters{$branch_3} = Koha::Patron->new({ |
160 |
} |
154 |
branchcode => $branch_3, |
161 |
)->store->borrowernumber; |
155 |
categorycode => $category_2, |
162 |
$requesters{$branch_3} = Koha::Patron->new( |
156 |
surname => "borrower from $branch_3", |
163 |
{ |
157 |
})->store->borrowernumber; |
164 |
branchcode => $branch_3, |
|
|
165 |
categorycode => $category_2, |
166 |
surname => "borrower from $branch_3", |
167 |
} |
168 |
)->store->borrowernumber; |
158 |
|
169 |
|
159 |
# Configure rules so that $branch_1 allows only $branch_1 patrons |
170 |
# Configure rules so that $branch_1 allows only $branch_1 patrons |
160 |
# to request its items, while $branch_2 will allow its items |
171 |
# to request its items, while $branch_2 will allow its items |
Lines 167-173
Koha::CirculationRules->set_rules(
Link Here
|
167 |
categorycode => undef, |
178 |
categorycode => undef, |
168 |
itemtype => undef, |
179 |
itemtype => undef, |
169 |
rules => { |
180 |
rules => { |
170 |
reservesallowed => 25, |
181 |
reservesallowed => 25, |
171 |
holds_per_record => 1, |
182 |
holds_per_record => 1, |
172 |
} |
183 |
} |
173 |
} |
184 |
} |
Lines 176-184
Koha::CirculationRules->set_rules(
Link Here
|
176 |
# CPL allows only its own patrons to request its items |
187 |
# CPL allows only its own patrons to request its items |
177 |
Koha::CirculationRules->set_rules( |
188 |
Koha::CirculationRules->set_rules( |
178 |
{ |
189 |
{ |
179 |
branchcode => $branch_1, |
190 |
branchcode => $branch_1, |
180 |
itemtype => undef, |
191 |
itemtype => undef, |
181 |
rules => { |
192 |
rules => { |
182 |
holdallowed => 'from_home_library', |
193 |
holdallowed => 'from_home_library', |
183 |
returnbranch => 'homebranch', |
194 |
returnbranch => 'homebranch', |
184 |
} |
195 |
} |
Lines 188-205
Koha::CirculationRules->set_rules(
Link Here
|
188 |
# ... while FPL allows anybody to request its items |
199 |
# ... while FPL allows anybody to request its items |
189 |
Koha::CirculationRules->set_rules( |
200 |
Koha::CirculationRules->set_rules( |
190 |
{ |
201 |
{ |
191 |
branchcode => $branch_2, |
202 |
branchcode => $branch_2, |
192 |
itemtype => undef, |
203 |
itemtype => undef, |
193 |
rules => { |
204 |
rules => { |
194 |
holdallowed => 'from_any_library', |
205 |
holdallowed => 'from_any_library', |
195 |
returnbranch => 'homebranch', |
206 |
returnbranch => 'homebranch', |
196 |
} |
207 |
} |
197 |
} |
208 |
} |
198 |
); |
209 |
); |
199 |
|
210 |
|
200 |
my $bibnum2 = $builder->build_sample_biblio({frameworkcode => $frameworkcode})->biblionumber; |
211 |
my $bibnum2 = $builder->build_sample_biblio( { frameworkcode => $frameworkcode } )->biblionumber; |
201 |
|
212 |
|
202 |
my ($itemnum_cpl, $itemnum_fpl); |
213 |
my ( $itemnum_cpl, $itemnum_fpl ); |
203 |
$itemnum_cpl = $builder->build_sample_item( |
214 |
$itemnum_cpl = $builder->build_sample_item( |
204 |
{ |
215 |
{ |
205 |
biblionumber => $bibnum2, |
216 |
biblionumber => $bibnum2, |
Lines 219-225
$itemnum_fpl = $builder->build_sample_item(
Link Here
|
219 |
|
230 |
|
220 |
# Ensure that priorities are numbered correcly when a hold is moved to waiting |
231 |
# Ensure that priorities are numbered correcly when a hold is moved to waiting |
221 |
# (bug 11947) |
232 |
# (bug 11947) |
222 |
$dbh->do("DELETE FROM reserves WHERE biblionumber=?",undef,($bibnum2)); |
233 |
$dbh->do( "DELETE FROM reserves WHERE biblionumber=?", undef, ($bibnum2) ); |
223 |
AddReserve( |
234 |
AddReserve( |
224 |
{ |
235 |
{ |
225 |
branchcode => $branch_3, |
236 |
branchcode => $branch_3, |
Lines 244-264
AddReserve(
Link Here
|
244 |
priority => 3, |
255 |
priority => 3, |
245 |
} |
256 |
} |
246 |
); |
257 |
); |
247 |
ModReserveAffect($itemnum_cpl, $requesters{$branch_3}, 0); |
258 |
ModReserveAffect( $itemnum_cpl, $requesters{$branch_3}, 0 ); |
248 |
|
259 |
|
249 |
# Now it should have different priorities. |
260 |
# Now it should have different priorities. |
250 |
my $biblio = Koha::Biblios->find( $bibnum2 ); |
261 |
my $biblio = Koha::Biblios->find($bibnum2); |
251 |
my $holds = $biblio->holds({}, { order_by => 'reserve_id' });; |
262 |
my $holds = $biblio->holds( {}, { order_by => 'reserve_id' } ); |
252 |
is($holds->next->priority, 0, 'Item is correctly waiting'); |
263 |
is( $holds->next->priority, 0, 'Item is correctly waiting' ); |
253 |
is($holds->next->priority, 1, 'Item is correctly priority 1'); |
264 |
is( $holds->next->priority, 1, 'Item is correctly priority 1' ); |
254 |
is($holds->next->priority, 2, 'Item is correctly priority 2'); |
265 |
is( $holds->next->priority, 2, 'Item is correctly priority 2' ); |
255 |
|
266 |
|
256 |
my @reserves = Koha::Holds->search({ borrowernumber => $requesters{$branch_3} })->waiting->as_list; |
267 |
my @reserves = Koha::Holds->search( { borrowernumber => $requesters{$branch_3} } )->waiting->as_list; |
257 |
is( @reserves, 1, 'GetWaiting got only the waiting reserve' ); |
268 |
is( @reserves, 1, 'GetWaiting got only the waiting reserve' ); |
258 |
is( $reserves[0]->borrowernumber(), $requesters{$branch_3}, 'GetWaiting got the reserve for the correct borrower' ); |
269 |
is( $reserves[0]->borrowernumber(), $requesters{$branch_3}, 'GetWaiting got the reserve for the correct borrower' ); |
259 |
|
270 |
|
260 |
|
271 |
$dbh->do( "DELETE FROM reserves WHERE biblionumber=?", undef, ($bibnum2) ); |
261 |
$dbh->do("DELETE FROM reserves WHERE biblionumber=?",undef,($bibnum2)); |
|
|
262 |
AddReserve( |
272 |
AddReserve( |
263 |
{ |
273 |
{ |
264 |
branchcode => $branch_3, |
274 |
branchcode => $branch_3, |
Lines 289-301
AddReserve(
Link Here
|
289 |
t::lib::Mocks::mock_preference( 'ReservesControlBranch', 'ItemHomeLibrary' ); |
299 |
t::lib::Mocks::mock_preference( 'ReservesControlBranch', 'ItemHomeLibrary' ); |
290 |
|
300 |
|
291 |
my $messages; |
301 |
my $messages; |
|
|
302 |
|
292 |
# Return the CPL item at FPL. The hold that should be triggered is |
303 |
# Return the CPL item at FPL. The hold that should be triggered is |
293 |
# the one placed by the CPL patron, as the other two patron's hold |
304 |
# the one placed by the CPL patron, as the other two patron's hold |
294 |
# requests cannot be filled by that item per policy. |
305 |
# requests cannot be filled by that item per policy. |
295 |
(undef, $messages, undef, undef) = AddReturn('bug10272_CPL', $branch_2); |
306 |
( undef, $messages, undef, undef ) = AddReturn( 'bug10272_CPL', $branch_2 ); |
296 |
is( $messages->{ResFound}->{borrowernumber}, |
307 |
is( |
|
|
308 |
$messages->{ResFound}->{borrowernumber}, |
297 |
$requesters{$branch_1}, |
309 |
$requesters{$branch_1}, |
298 |
'restrictive library\'s items only fill requests by own patrons (bug 10272)'); |
310 |
'restrictive library\'s items only fill requests by own patrons (bug 10272)' |
|
|
311 |
); |
299 |
|
312 |
|
300 |
# Return the FPL item at FPL. The hold that should be triggered is |
313 |
# Return the FPL item at FPL. The hold that should be triggered is |
301 |
# the one placed by the RPL patron, as that patron is first in line |
314 |
# the one placed by the RPL patron, as that patron is first in line |
Lines 304-323
is( $messages->{ResFound}->{borrowernumber},
Link Here
|
304 |
# Ensure that the preference 'LocalHoldsPriority' is not set (Bug 15244): |
317 |
# Ensure that the preference 'LocalHoldsPriority' is not set (Bug 15244): |
305 |
t::lib::Mocks::mock_preference( 'LocalHoldsPriority', '' ); |
318 |
t::lib::Mocks::mock_preference( 'LocalHoldsPriority', '' ); |
306 |
|
319 |
|
307 |
(undef, $messages, undef, undef) = AddReturn('bug10272_FPL', $branch_2); |
320 |
( undef, $messages, undef, undef ) = AddReturn( 'bug10272_FPL', $branch_2 ); |
308 |
is( $messages->{ResFound}->{borrowernumber}, |
321 |
is( |
|
|
322 |
$messages->{ResFound}->{borrowernumber}, |
309 |
$requesters{$branch_3}, |
323 |
$requesters{$branch_3}, |
310 |
'for generous library, its items fill first hold request in line (bug 10272)'); |
324 |
'for generous library, its items fill first hold request in line (bug 10272)' |
|
|
325 |
); |
311 |
|
326 |
|
312 |
$biblio = Koha::Biblios->find( $biblionumber ); |
327 |
$biblio = Koha::Biblios->find($biblionumber); |
313 |
$holds = $biblio->holds; |
328 |
$holds = $biblio->holds; |
314 |
is($holds->count, 1, "Only one reserves for this biblio"); |
329 |
is( $holds->count, 1, "Only one reserves for this biblio" ); |
315 |
$holds->next->reserve_id; |
330 |
$holds->next->reserve_id; |
316 |
|
331 |
|
317 |
# Tests for bug 9761 (ConfirmFutureHolds): new CheckReserves lookahead parameter, and corresponding change in AddReturn |
332 |
# Tests for bug 9761 (ConfirmFutureHolds): new CheckReserves lookahead parameter, and corresponding change in AddReturn |
318 |
# Note that CheckReserve uses its lookahead parameter and does not check ConfirmFutureHolds pref (it should be passed if needed like AddReturn does) |
333 |
# Note that CheckReserve uses its lookahead parameter and does not check ConfirmFutureHolds pref (it should be passed if needed like AddReturn does) |
319 |
# Test 9761a: Add a reserve without date, CheckReserve should return it |
334 |
# Test 9761a: Add a reserve without date, CheckReserve should return it |
320 |
$dbh->do("DELETE FROM reserves WHERE biblionumber=?",undef,($bibnum)); |
335 |
$dbh->do( "DELETE FROM reserves WHERE biblionumber=?", undef, ($bibnum) ); |
321 |
AddReserve( |
336 |
AddReserve( |
322 |
{ |
337 |
{ |
323 |
branchcode => $branch_1, |
338 |
branchcode => $branch_1, |
Lines 326-341
AddReserve(
Link Here
|
326 |
priority => 1, |
341 |
priority => 1, |
327 |
} |
342 |
} |
328 |
); |
343 |
); |
329 |
($status)=CheckReserves( $item ); |
344 |
($status) = CheckReserves($item); |
330 |
is( $status, 'Reserved', 'CheckReserves returns reserve without lookahead'); |
345 |
is( $status, 'Reserved', 'CheckReserves returns reserve without lookahead' ); |
331 |
($status)=CheckReserves( $item, 7 ); |
346 |
($status) = CheckReserves( $item, 7 ); |
332 |
is( $status, 'Reserved', 'CheckReserves also returns reserve with lookahead'); |
347 |
is( $status, 'Reserved', 'CheckReserves also returns reserve with lookahead' ); |
333 |
|
348 |
|
334 |
# Test 9761b: Add a reserve with future date, CheckReserve should not return it |
349 |
# Test 9761b: Add a reserve with future date, CheckReserve should not return it |
335 |
$dbh->do("DELETE FROM reserves WHERE biblionumber=?",undef,($bibnum)); |
350 |
$dbh->do( "DELETE FROM reserves WHERE biblionumber=?", undef, ($bibnum) ); |
336 |
t::lib::Mocks::mock_preference('AllowHoldDateInFuture', 1); |
351 |
t::lib::Mocks::mock_preference( 'AllowHoldDateInFuture', 1 ); |
337 |
my $resdate= dt_from_string(); |
352 |
my $resdate = dt_from_string(); |
338 |
$resdate->add_duration(DateTime::Duration->new(days => 4)); |
353 |
$resdate->add_duration( DateTime::Duration->new( days => 4 ) ); |
339 |
my $reserve_id = AddReserve( |
354 |
my $reserve_id = AddReserve( |
340 |
{ |
355 |
{ |
341 |
branchcode => $branch_1, |
356 |
branchcode => $branch_1, |
Lines 345-375
my $reserve_id = AddReserve(
Link Here
|
345 |
reservation_date => $resdate, |
360 |
reservation_date => $resdate, |
346 |
} |
361 |
} |
347 |
); |
362 |
); |
348 |
($status)=CheckReserves( $item ); |
363 |
($status) = CheckReserves($item); |
349 |
is( $status, '', 'CheckReserves returns no future reserve without lookahead'); |
364 |
is( $status, '', 'CheckReserves returns no future reserve without lookahead' ); |
350 |
|
365 |
|
351 |
# Test 9761c: Add a reserve with future date, CheckReserve should return it if lookahead is high enough |
366 |
# Test 9761c: Add a reserve with future date, CheckReserve should return it if lookahead is high enough |
352 |
($status)=CheckReserves( $item, 3 ); |
367 |
($status) = CheckReserves( $item, 3 ); |
353 |
is( $status, '', 'CheckReserves returns no future reserve with insufficient lookahead'); |
368 |
is( $status, '', 'CheckReserves returns no future reserve with insufficient lookahead' ); |
354 |
($status)=CheckReserves( $item, 4 ); |
369 |
($status) = CheckReserves( $item, 4 ); |
355 |
is( $status, 'Reserved', 'CheckReserves returns future reserve with sufficient lookahead'); |
370 |
is( $status, 'Reserved', 'CheckReserves returns future reserve with sufficient lookahead' ); |
356 |
|
371 |
|
357 |
# Test 9761d: Check ResFound message of AddReturn for future hold |
372 |
# Test 9761d: Check ResFound message of AddReturn for future hold |
358 |
# Note that AddReturn is in Circulation.pm, but this test really pertains to reserves; AddReturn uses the ConfirmFutureHolds pref when calling CheckReserves |
373 |
# Note that AddReturn is in Circulation.pm, but this test really pertains to reserves; AddReturn uses the ConfirmFutureHolds pref when calling CheckReserves |
359 |
# In this test we do not need an issued item; it is just a 'checkin' |
374 |
# In this test we do not need an issued item; it is just a 'checkin' |
360 |
t::lib::Mocks::mock_preference('ConfirmFutureHolds', 0); |
375 |
t::lib::Mocks::mock_preference( 'ConfirmFutureHolds', 0 ); |
361 |
(my $doreturn, $messages)= AddReturn($testbarcode,$branch_1); |
376 |
( my $doreturn, $messages ) = AddReturn( $testbarcode, $branch_1 ); |
362 |
is($messages->{ResFound}//'', '', 'AddReturn does not care about future reserve when ConfirmFutureHolds is off'); |
377 |
is( $messages->{ResFound} // '', '', 'AddReturn does not care about future reserve when ConfirmFutureHolds is off' ); |
363 |
t::lib::Mocks::mock_preference('ConfirmFutureHolds', 3); |
378 |
t::lib::Mocks::mock_preference( 'ConfirmFutureHolds', 3 ); |
364 |
($doreturn, $messages)= AddReturn($testbarcode,$branch_1); |
379 |
( $doreturn, $messages ) = AddReturn( $testbarcode, $branch_1 ); |
365 |
is(exists $messages->{ResFound}?1:0, 0, 'AddReturn ignores future reserve beyond ConfirmFutureHolds days'); |
380 |
is( exists $messages->{ResFound} ? 1 : 0, 0, 'AddReturn ignores future reserve beyond ConfirmFutureHolds days' ); |
366 |
t::lib::Mocks::mock_preference('ConfirmFutureHolds', 7); |
381 |
t::lib::Mocks::mock_preference( 'ConfirmFutureHolds', 7 ); |
367 |
($doreturn, $messages)= AddReturn($testbarcode,$branch_1); |
382 |
( $doreturn, $messages ) = AddReturn( $testbarcode, $branch_1 ); |
368 |
is(exists $messages->{ResFound}?1:0, 1, 'AddReturn considers future reserve within ConfirmFutureHolds days'); |
383 |
is( exists $messages->{ResFound} ? 1 : 0, 1, 'AddReturn considers future reserve within ConfirmFutureHolds days' ); |
369 |
|
384 |
|
370 |
my $now_holder = $builder->build_object({ class => 'Koha::Patrons', value => { |
385 |
my $now_holder = $builder->build_object( |
371 |
branchcode => $branch_1, |
386 |
{ |
372 |
}}); |
387 |
class => 'Koha::Patrons', |
|
|
388 |
value => { |
389 |
branchcode => $branch_1, |
390 |
} |
391 |
} |
392 |
); |
373 |
my $now_reserve_id = AddReserve( |
393 |
my $now_reserve_id = AddReserve( |
374 |
{ |
394 |
{ |
375 |
branchcode => $branch_1, |
395 |
branchcode => $branch_1, |
Lines 380-425
my $now_reserve_id = AddReserve(
Link Here
|
380 |
} |
400 |
} |
381 |
); |
401 |
); |
382 |
my $which_highest; |
402 |
my $which_highest; |
383 |
($status,$which_highest)=CheckReserves( $item, 3 ); |
403 |
( $status, $which_highest ) = CheckReserves( $item, 3 ); |
384 |
is( $which_highest->{reserve_id}, $now_reserve_id, 'CheckReserves returns lower priority current reserve with insufficient lookahead'); |
404 |
is( |
385 |
($status, $which_highest)=CheckReserves( $item, 4 ); |
405 |
$which_highest->{reserve_id}, $now_reserve_id, |
386 |
is( $which_highest->{reserve_id}, $reserve_id, 'CheckReserves returns higher priority future reserve with sufficient lookahead'); |
406 |
'CheckReserves returns lower priority current reserve with insufficient lookahead' |
387 |
ModReserve({ reserve_id => $now_reserve_id, rank => 'del', cancellation_reason => 'test reserve' }); |
407 |
); |
388 |
|
408 |
( $status, $which_highest ) = CheckReserves( $item, 4 ); |
|
|
409 |
is( |
410 |
$which_highest->{reserve_id}, $reserve_id, |
411 |
'CheckReserves returns higher priority future reserve with sufficient lookahead' |
412 |
); |
413 |
ModReserve( { reserve_id => $now_reserve_id, rank => 'del', cancellation_reason => 'test reserve' } ); |
389 |
|
414 |
|
390 |
# End of tests for bug 9761 (ConfirmFutureHolds) |
415 |
# End of tests for bug 9761 (ConfirmFutureHolds) |
391 |
|
416 |
|
392 |
|
|
|
393 |
# test marking a hold as captured |
417 |
# test marking a hold as captured |
394 |
my $hold_notice_count = count_hold_print_messages(); |
418 |
my $hold_notice_count = count_hold_print_messages(); |
395 |
ModReserveAffect($item->itemnumber, $requesters{$branch_1}, 0); |
419 |
ModReserveAffect( $item->itemnumber, $requesters{$branch_1}, 0 ); |
396 |
my $new_count = count_hold_print_messages(); |
420 |
my $new_count = count_hold_print_messages(); |
397 |
is($new_count, $hold_notice_count + 1, 'patron notified when item set to waiting'); |
421 |
is( $new_count, $hold_notice_count + 1, 'patron notified when item set to waiting' ); |
398 |
|
422 |
|
399 |
# test that duplicate notices aren't generated |
423 |
# test that duplicate notices aren't generated |
400 |
ModReserveAffect($item->itemnumber, $requesters{$branch_1}, 0); |
424 |
ModReserveAffect( $item->itemnumber, $requesters{$branch_1}, 0 ); |
401 |
$new_count = count_hold_print_messages(); |
425 |
$new_count = count_hold_print_messages(); |
402 |
is($new_count, $hold_notice_count + 1, 'patron not notified a second time (bug 11445)'); |
426 |
is( $new_count, $hold_notice_count + 1, 'patron not notified a second time (bug 11445)' ); |
403 |
|
427 |
|
404 |
# avoiding the not_same_branch error |
428 |
# avoiding the not_same_branch error |
405 |
t::lib::Mocks::mock_preference('IndependentBranches', 0); |
429 |
t::lib::Mocks::mock_preference( 'IndependentBranches', 0 ); |
406 |
$item = Koha::Items->find($item->itemnumber); |
430 |
$item = Koha::Items->find( $item->itemnumber ); |
407 |
is( |
431 |
is( |
408 |
@{$item->safe_delete->messages}[0]->message, |
432 |
@{ $item->safe_delete->messages }[0]->message, |
409 |
'book_reserved', |
433 |
'book_reserved', |
410 |
'item that is captured to fill a hold cannot be deleted', |
434 |
'item that is captured to fill a hold cannot be deleted', |
411 |
); |
435 |
); |
412 |
|
436 |
|
413 |
my $letter = ReserveSlip( { branchcode => $branch_1, reserve_id => $reserve_id } ); |
437 |
my $letter = ReserveSlip( { branchcode => $branch_1, reserve_id => $reserve_id } ); |
414 |
ok(defined($letter), 'can successfully generate hold slip (bug 10949)'); |
438 |
ok( defined($letter), 'can successfully generate hold slip (bug 10949)' ); |
415 |
|
439 |
|
416 |
# Tests for bug 9788: Does Koha::Item->current_holds return a future wait? |
440 |
# Tests for bug 9788: Does Koha::Item->current_holds return a future wait? |
417 |
# 9788a: current_holds does not return future next available hold |
441 |
# 9788a: current_holds does not return future next available hold |
418 |
$dbh->do("DELETE FROM reserves WHERE biblionumber=?",undef,($bibnum)); |
442 |
$dbh->do( "DELETE FROM reserves WHERE biblionumber=?", undef, ($bibnum) ); |
419 |
t::lib::Mocks::mock_preference('ConfirmFutureHolds', 2); |
443 |
t::lib::Mocks::mock_preference( 'ConfirmFutureHolds', 2 ); |
420 |
t::lib::Mocks::mock_preference('AllowHoldDateInFuture', 1); |
444 |
t::lib::Mocks::mock_preference( 'AllowHoldDateInFuture', 1 ); |
421 |
$resdate= dt_from_string(); |
445 |
$resdate = dt_from_string(); |
422 |
$resdate->add_duration(DateTime::Duration->new(days => 2)); |
446 |
$resdate->add_duration( DateTime::Duration->new( days => 2 ) ); |
423 |
AddReserve( |
447 |
AddReserve( |
424 |
{ |
448 |
{ |
425 |
branchcode => $branch_1, |
449 |
branchcode => $branch_1, |
Lines 431-441
AddReserve(
Link Here
|
431 |
); |
455 |
); |
432 |
|
456 |
|
433 |
$holds = $item->current_holds; |
457 |
$holds = $item->current_holds; |
434 |
my $dtf = Koha::Database->new->schema->storage->datetime_parser; |
458 |
my $dtf = Koha::Database->new->schema->storage->datetime_parser; |
435 |
my $future_holds = $holds->search({ reservedate => { '>' => $dtf->format_date( dt_from_string ) } } ); |
459 |
my $future_holds = $holds->search( { reservedate => { '>' => $dtf->format_date(dt_from_string) } } ); |
436 |
is( $future_holds->count, 0, 'current_holds does not return a future next available hold'); |
460 |
is( $future_holds->count, 0, 'current_holds does not return a future next available hold' ); |
|
|
461 |
|
437 |
# 9788b: current_holds does not return future item level hold |
462 |
# 9788b: current_holds does not return future item level hold |
438 |
$dbh->do("DELETE FROM reserves WHERE biblionumber=?",undef,($bibnum)); |
463 |
$dbh->do( "DELETE FROM reserves WHERE biblionumber=?", undef, ($bibnum) ); |
439 |
AddReserve( |
464 |
AddReserve( |
440 |
{ |
465 |
{ |
441 |
branchcode => $branch_1, |
466 |
branchcode => $branch_1, |
Lines 445-463
AddReserve(
Link Here
|
445 |
reservation_date => $resdate, |
470 |
reservation_date => $resdate, |
446 |
itemnumber => $item->itemnumber, |
471 |
itemnumber => $item->itemnumber, |
447 |
} |
472 |
} |
448 |
); #item level hold |
473 |
); #item level hold |
449 |
$future_holds = $holds->search({ reservedate => { '>' => $dtf->format_date( dt_from_string ) } } ); |
474 |
$future_holds = $holds->search( { reservedate => { '>' => $dtf->format_date(dt_from_string) } } ); |
450 |
is( $future_holds->count, 0, 'current_holds does not return a future item level hold' ); |
475 |
is( $future_holds->count, 0, 'current_holds does not return a future item level hold' ); |
|
|
476 |
|
451 |
# 9788c: current_holds returns future wait (confirmed future hold) |
477 |
# 9788c: current_holds returns future wait (confirmed future hold) |
452 |
ModReserveAffect( $item->itemnumber, $requesters{$branch_1} , 0); #confirm hold |
478 |
ModReserveAffect( $item->itemnumber, $requesters{$branch_1}, 0 ); #confirm hold |
453 |
$future_holds = $holds->search({ reservedate => { '>' => $dtf->format_date( dt_from_string ) } } ); |
479 |
$future_holds = $holds->search( { reservedate => { '>' => $dtf->format_date(dt_from_string) } } ); |
454 |
is( $future_holds->count, 1, 'current_holds returns a future wait (confirmed future hold)' ); |
480 |
is( $future_holds->count, 1, 'current_holds returns a future wait (confirmed future hold)' ); |
|
|
481 |
|
455 |
# End of tests for bug 9788 |
482 |
# End of tests for bug 9788 |
456 |
|
483 |
|
457 |
$dbh->do("DELETE FROM reserves WHERE biblionumber=?",undef,($bibnum)); |
484 |
$dbh->do( "DELETE FROM reserves WHERE biblionumber=?", undef, ($bibnum) ); |
|
|
485 |
|
458 |
# Tests for CalculatePriority (bug 8918) |
486 |
# Tests for CalculatePriority (bug 8918) |
459 |
my $p = C4::Reserves::CalculatePriority($bibnum2); |
487 |
my $p = C4::Reserves::CalculatePriority($bibnum2); |
460 |
is($p, 4, 'CalculatePriority should now return priority 4'); |
488 |
is( $p, 4, 'CalculatePriority should now return priority 4' ); |
461 |
AddReserve( |
489 |
AddReserve( |
462 |
{ |
490 |
{ |
463 |
branchcode => $branch_1, |
491 |
branchcode => $branch_1, |
Lines 467-477
AddReserve(
Link Here
|
467 |
} |
495 |
} |
468 |
); |
496 |
); |
469 |
$p = C4::Reserves::CalculatePriority($bibnum2); |
497 |
$p = C4::Reserves::CalculatePriority($bibnum2); |
470 |
is($p, 5, 'CalculatePriority should now return priority 5'); |
498 |
is( $p, 5, 'CalculatePriority should now return priority 5' ); |
|
|
499 |
|
471 |
#some tests on bibnum |
500 |
#some tests on bibnum |
472 |
$dbh->do("DELETE FROM reserves WHERE biblionumber=?",undef,($bibnum)); |
501 |
$dbh->do( "DELETE FROM reserves WHERE biblionumber=?", undef, ($bibnum) ); |
473 |
$p = C4::Reserves::CalculatePriority($bibnum); |
502 |
$p = C4::Reserves::CalculatePriority($bibnum); |
474 |
is($p, 1, 'CalculatePriority should now return priority 1'); |
503 |
is( $p, 1, 'CalculatePriority should now return priority 1' ); |
|
|
504 |
|
475 |
#add a new reserve and confirm it to waiting |
505 |
#add a new reserve and confirm it to waiting |
476 |
AddReserve( |
506 |
AddReserve( |
477 |
{ |
507 |
{ |
Lines 483-492
AddReserve(
Link Here
|
483 |
} |
513 |
} |
484 |
); |
514 |
); |
485 |
$p = C4::Reserves::CalculatePriority($bibnum); |
515 |
$p = C4::Reserves::CalculatePriority($bibnum); |
486 |
is($p, 2, 'CalculatePriority should now return priority 2'); |
516 |
is( $p, 2, 'CalculatePriority should now return priority 2' ); |
487 |
ModReserveAffect( $item->itemnumber, $requesters{$branch_1} , 0); |
517 |
ModReserveAffect( $item->itemnumber, $requesters{$branch_1}, 0 ); |
488 |
$p = C4::Reserves::CalculatePriority($bibnum); |
518 |
$p = C4::Reserves::CalculatePriority($bibnum); |
489 |
is($p, 1, 'CalculatePriority should now return priority 1'); |
519 |
is( $p, 1, 'CalculatePriority should now return priority 1' ); |
|
|
520 |
|
490 |
#add another biblio hold, no resdate |
521 |
#add another biblio hold, no resdate |
491 |
AddReserve( |
522 |
AddReserve( |
492 |
{ |
523 |
{ |
Lines 497-564
AddReserve(
Link Here
|
497 |
} |
528 |
} |
498 |
); |
529 |
); |
499 |
$p = C4::Reserves::CalculatePriority($bibnum); |
530 |
$p = C4::Reserves::CalculatePriority($bibnum); |
500 |
is($p, 2, 'CalculatePriority should now return priority 2'); |
531 |
is( $p, 2, 'CalculatePriority should now return priority 2' ); |
|
|
532 |
|
501 |
#add another future hold |
533 |
#add another future hold |
502 |
t::lib::Mocks::mock_preference('AllowHoldDateInFuture', 1); |
534 |
t::lib::Mocks::mock_preference( 'AllowHoldDateInFuture', 1 ); |
503 |
$resdate= dt_from_string(); |
535 |
$resdate = dt_from_string(); |
504 |
$resdate->add_duration(DateTime::Duration->new(days => 1)); |
536 |
$resdate->add_duration( DateTime::Duration->new( days => 1 ) ); |
505 |
AddReserve( |
537 |
AddReserve( |
506 |
{ |
538 |
{ |
507 |
branchcode => $branch_1, |
539 |
branchcode => $branch_1, |
508 |
borrowernumber => $requesters{'CPL2'}, |
540 |
borrowernumber => $requesters{'CPL2'}, |
509 |
biblionumber => $bibnum, |
541 |
biblionumber => $bibnum, |
510 |
priority => $p, |
542 |
priority => $p, |
511 |
reservation_date => $resdate, |
543 |
reservation_date => $resdate, |
512 |
} |
544 |
} |
513 |
); |
545 |
); |
514 |
$p = C4::Reserves::CalculatePriority($bibnum); |
546 |
$p = C4::Reserves::CalculatePriority($bibnum); |
515 |
is($p, 2, 'CalculatePriority should now still return priority 2'); |
547 |
is( $p, 2, 'CalculatePriority should now still return priority 2' ); |
|
|
548 |
|
516 |
#calc priority with future resdate |
549 |
#calc priority with future resdate |
517 |
$p = C4::Reserves::CalculatePriority($bibnum, $resdate); |
550 |
$p = C4::Reserves::CalculatePriority( $bibnum, $resdate ); |
518 |
is($p, 3, 'CalculatePriority should now return priority 3'); |
551 |
is( $p, 3, 'CalculatePriority should now return priority 3' ); |
|
|
552 |
|
519 |
# End of tests for bug 8918 |
553 |
# End of tests for bug 8918 |
520 |
|
554 |
|
521 |
# regression test for bug 12630 |
555 |
# regression test for bug 12630 |
522 |
# Now there are 2 reserves on $bibnum |
556 |
# Now there are 2 reserves on $bibnum |
523 |
t::lib::Mocks::mock_preference('AllowHoldDateInFuture', 1); |
557 |
t::lib::Mocks::mock_preference( 'AllowHoldDateInFuture', 1 ); |
524 |
my $bor_tmp_1 = $builder->build_object({ class => 'Koha::Patrons',value =>{ |
558 |
my $bor_tmp_1 = $builder->build_object( |
525 |
firstname => 'my firstname tmp 1', |
559 |
{ |
526 |
surname => 'my surname tmp 1', |
560 |
class => 'Koha::Patrons', |
527 |
categorycode => 'S', |
561 |
value => { |
528 |
branchcode => 'CPL', |
562 |
firstname => 'my firstname tmp 1', |
529 |
}}); |
563 |
surname => 'my surname tmp 1', |
530 |
my $bor_tmp_2 = $builder->build_object({ class => 'Koha::Patrons',value =>{ |
564 |
categorycode => 'S', |
531 |
firstname => 'my firstname tmp 2', |
565 |
branchcode => 'CPL', |
532 |
surname => 'my surname tmp 2', |
566 |
} |
533 |
categorycode => 'S', |
567 |
} |
534 |
branchcode => 'CPL', |
568 |
); |
535 |
}}); |
569 |
my $bor_tmp_2 = $builder->build_object( |
|
|
570 |
{ |
571 |
class => 'Koha::Patrons', |
572 |
value => { |
573 |
firstname => 'my firstname tmp 2', |
574 |
surname => 'my surname tmp 2', |
575 |
categorycode => 'S', |
576 |
branchcode => 'CPL', |
577 |
} |
578 |
} |
579 |
); |
536 |
my $borrowernumber_tmp_1 = $bor_tmp_1->borrowernumber; |
580 |
my $borrowernumber_tmp_1 = $bor_tmp_1->borrowernumber; |
537 |
my $borrowernumber_tmp_2 = $bor_tmp_2->borrowernumber; |
581 |
my $borrowernumber_tmp_2 = $bor_tmp_2->borrowernumber; |
538 |
my $date_in_future = dt_from_string(); |
582 |
my $date_in_future = dt_from_string(); |
539 |
$date_in_future = $date_in_future->add_duration(DateTime::Duration->new(days => 1)); |
583 |
$date_in_future = $date_in_future->add_duration( DateTime::Duration->new( days => 1 ) ); |
540 |
AddReserve({ |
584 |
AddReserve( |
541 |
branchcode => 'CPL', |
585 |
{ |
542 |
borrowernumber => $borrowernumber_tmp_1, |
586 |
branchcode => 'CPL', |
543 |
biblionumber => $bibnum, |
587 |
borrowernumber => $borrowernumber_tmp_1, |
544 |
priority => 3, |
588 |
biblionumber => $bibnum, |
545 |
reservation_date => $date_in_future |
589 |
priority => 3, |
546 |
}); |
590 |
reservation_date => $date_in_future |
547 |
AddReserve({ |
591 |
} |
548 |
branchcode => 'CPL', |
592 |
); |
549 |
borrowernumber => $borrowernumber_tmp_2, |
593 |
AddReserve( |
550 |
biblionumber => $bibnum, |
594 |
{ |
551 |
priority => 4, |
595 |
branchcode => 'CPL', |
552 |
reservation_date => $date_in_future |
596 |
borrowernumber => $borrowernumber_tmp_2, |
553 |
}); |
597 |
biblionumber => $bibnum, |
554 |
my @r1 = Koha::Holds->search({ borrowernumber => $borrowernumber_tmp_1 })->as_list; |
598 |
priority => 4, |
555 |
my @r2 = Koha::Holds->search({ borrowernumber => $borrowernumber_tmp_2 })->as_list; |
599 |
reservation_date => $date_in_future |
556 |
is( $r1[0]->priority, 3, 'priority for hold in future should be correct'); |
600 |
} |
557 |
is( $r2[0]->priority, 4, 'priority for hold not in future should be correct'); |
601 |
); |
|
|
602 |
my @r1 = Koha::Holds->search( { borrowernumber => $borrowernumber_tmp_1 } )->as_list; |
603 |
my @r2 = Koha::Holds->search( { borrowernumber => $borrowernumber_tmp_2 } )->as_list; |
604 |
is( $r1[0]->priority, 3, 'priority for hold in future should be correct' ); |
605 |
is( $r2[0]->priority, 4, 'priority for hold not in future should be correct' ); |
606 |
|
558 |
# end of tests for bug 12630 |
607 |
# end of tests for bug 12630 |
559 |
|
608 |
|
560 |
# Tests for cancel reserves by users from OPAC. |
609 |
# Tests for cancel reserves by users from OPAC. |
561 |
$dbh->do('DELETE FROM reserves', undef, ($bibnum)); |
610 |
$dbh->do( 'DELETE FROM reserves', undef, ($bibnum) ); |
562 |
AddReserve( |
611 |
AddReserve( |
563 |
{ |
612 |
{ |
564 |
branchcode => $branch_1, |
613 |
branchcode => $branch_1, |
Lines 567-575
AddReserve(
Link Here
|
567 |
priority => 1, |
616 |
priority => 1, |
568 |
} |
617 |
} |
569 |
); |
618 |
); |
570 |
my (undef, $canres, undef) = CheckReserves( $item ); |
619 |
my ( undef, $canres, undef ) = CheckReserves($item); |
571 |
|
620 |
|
572 |
is( CanReserveBeCanceledFromOpac(), undef, |
621 |
is( |
|
|
622 |
CanReserveBeCanceledFromOpac(), undef, |
573 |
'CanReserveBeCanceledFromOpac should return undef if called without any parameter' |
623 |
'CanReserveBeCanceledFromOpac should return undef if called without any parameter' |
574 |
); |
624 |
); |
575 |
is( |
625 |
is( |
Lines 583-601
is(
Link Here
|
583 |
'CanReserveBeCanceledFromOpac should return undef if called without borrowernumber' |
633 |
'CanReserveBeCanceledFromOpac should return undef if called without borrowernumber' |
584 |
); |
634 |
); |
585 |
|
635 |
|
586 |
my $cancancel = CanReserveBeCanceledFromOpac($canres->{reserve_id}, $requesters{$branch_1}); |
636 |
my $cancancel = CanReserveBeCanceledFromOpac( $canres->{reserve_id}, $requesters{$branch_1} ); |
587 |
is($cancancel, 1, 'Can user cancel its own reserve'); |
637 |
is( $cancancel, 1, 'Can user cancel its own reserve' ); |
588 |
|
638 |
|
589 |
$cancancel = CanReserveBeCanceledFromOpac($canres->{reserve_id}, $requesters{$branch_2}); |
639 |
$cancancel = CanReserveBeCanceledFromOpac( $canres->{reserve_id}, $requesters{$branch_2} ); |
590 |
is($cancancel, 0, 'Other user cant cancel reserve'); |
640 |
is( $cancancel, 0, 'Other user cant cancel reserve' ); |
591 |
|
641 |
|
592 |
ModReserveAffect($item->itemnumber, $requesters{$branch_1}, 1); |
642 |
ModReserveAffect( $item->itemnumber, $requesters{$branch_1}, 1 ); |
593 |
$cancancel = CanReserveBeCanceledFromOpac($canres->{reserve_id}, $requesters{$branch_1}); |
643 |
$cancancel = CanReserveBeCanceledFromOpac( $canres->{reserve_id}, $requesters{$branch_1} ); |
594 |
is($cancancel, 0, 'Reserve in transfer status cant be canceled'); |
644 |
is( $cancancel, 0, 'Reserve in transfer status cant be canceled' ); |
595 |
|
645 |
|
596 |
$dbh->do('DELETE FROM reserves', undef, ($bibnum)); |
646 |
$dbh->do( 'DELETE FROM reserves', undef, ($bibnum) ); |
597 |
is( CanReserveBeCanceledFromOpac($canres->{resserve_id}, $requesters{$branch_1}), undef, |
647 |
is( |
598 |
'Cannot cancel a deleted hold' ); |
648 |
CanReserveBeCanceledFromOpac( $canres->{resserve_id}, $requesters{$branch_1} ), undef, |
|
|
649 |
'Cannot cancel a deleted hold' |
650 |
); |
599 |
|
651 |
|
600 |
AddReserve( |
652 |
AddReserve( |
601 |
{ |
653 |
{ |
Lines 605-621
AddReserve(
Link Here
|
605 |
priority => 1, |
657 |
priority => 1, |
606 |
} |
658 |
} |
607 |
); |
659 |
); |
608 |
(undef, $canres, undef) = CheckReserves( $item ); |
660 |
( undef, $canres, undef ) = CheckReserves($item); |
609 |
|
661 |
|
610 |
ModReserveAffect($item->itemnumber, $requesters{$branch_1}, 0); |
662 |
ModReserveAffect( $item->itemnumber, $requesters{$branch_1}, 0 ); |
611 |
$cancancel = CanReserveBeCanceledFromOpac($canres->{reserve_id}, $requesters{$branch_1}); |
663 |
$cancancel = CanReserveBeCanceledFromOpac( $canres->{reserve_id}, $requesters{$branch_1} ); |
612 |
is($cancancel, 0, 'Reserve in waiting status cant be canceled'); |
664 |
is( $cancancel, 0, 'Reserve in waiting status cant be canceled' ); |
613 |
|
665 |
|
614 |
# End of tests for bug 12876 |
666 |
# End of tests for bug 12876 |
615 |
|
667 |
|
616 |
#### |
668 |
#### |
617 |
####### Testing Bug 13113 - Prevent juvenile/children from reserving ageRestricted material >>> |
669 |
####### Testing Bug 13113 - Prevent juvenile/children from reserving ageRestricted material >>> |
618 |
#### |
670 |
#### |
619 |
|
671 |
|
620 |
t::lib::Mocks::mock_preference( 'AgeRestrictionMarker', 'FSK|PEGI|Age|K' ); |
672 |
t::lib::Mocks::mock_preference( 'AgeRestrictionMarker', 'FSK|PEGI|Age|K' ); |
621 |
|
673 |
|
Lines 624-655
t::lib::Mocks::mock_preference( 'AgeRestrictionMarker', 'FSK|PEGI|Age|K' );
Link Here
|
624 |
#Set the ageRestriction for the Biblio |
676 |
#Set the ageRestriction for the Biblio |
625 |
$biblio = Koha::Biblios->find($bibnum); |
677 |
$biblio = Koha::Biblios->find($bibnum); |
626 |
my $record = $biblio->metadata->record; |
678 |
my $record = $biblio->metadata->record; |
627 |
my ( $ageres_tagid, $ageres_subfieldid ) = GetMarcFromKohaField( "biblioitems.agerestriction" ); |
679 |
my ( $ageres_tagid, $ageres_subfieldid ) = GetMarcFromKohaField("biblioitems.agerestriction"); |
628 |
$record->append_fields( MARC::Field->new($ageres_tagid, '', '', $ageres_subfieldid => 'PEGI 16') ); |
680 |
$record->append_fields( MARC::Field->new( $ageres_tagid, '', '', $ageres_subfieldid => 'PEGI 16' ) ); |
629 |
C4::Biblio::ModBiblio( $record, $bibnum, $frameworkcode ); |
681 |
C4::Biblio::ModBiblio( $record, $bibnum, $frameworkcode ); |
630 |
|
682 |
|
631 |
is( C4::Reserves::CanBookBeReserved($borrowernumber, $biblionumber)->{status} , 'OK', "Reserving an ageRestricted Biblio without a borrower dateofbirth succeeds" ); |
683 |
is( |
|
|
684 |
C4::Reserves::CanBookBeReserved( $borrowernumber, $biblionumber )->{status}, 'OK', |
685 |
"Reserving an ageRestricted Biblio without a borrower dateofbirth succeeds" |
686 |
); |
632 |
|
687 |
|
633 |
#Set the dateofbirth for the Borrower making them "too young". |
688 |
#Set the dateofbirth for the Borrower making them "too young". |
634 |
$borrower->{dateofbirth} = DateTime->now->add( years => -15 ); |
689 |
$borrower->{dateofbirth} = DateTime->now->add( years => -15 ); |
635 |
Koha::Patrons->find( $borrowernumber )->set({ dateofbirth => $borrower->{dateofbirth} })->store; |
690 |
Koha::Patrons->find($borrowernumber)->set( { dateofbirth => $borrower->{dateofbirth} } )->store; |
636 |
|
691 |
|
637 |
is( C4::Reserves::CanBookBeReserved($borrowernumber, $biblionumber)->{status} , 'ageRestricted', "Reserving a 'PEGI 16' Biblio by a 15 year old borrower fails"); |
692 |
is( |
|
|
693 |
C4::Reserves::CanBookBeReserved( $borrowernumber, $biblionumber )->{status}, 'ageRestricted', |
694 |
"Reserving a 'PEGI 16' Biblio by a 15 year old borrower fails" |
695 |
); |
638 |
|
696 |
|
639 |
#Set the dateofbirth for the Borrower making them "too old". |
697 |
#Set the dateofbirth for the Borrower making them "too old". |
640 |
$borrower->{dateofbirth} = DateTime->now->add( years => -30 ); |
698 |
$borrower->{dateofbirth} = DateTime->now->add( years => -30 ); |
641 |
Koha::Patrons->find( $borrowernumber )->set({ dateofbirth => $borrower->{dateofbirth} })->store; |
699 |
Koha::Patrons->find($borrowernumber)->set( { dateofbirth => $borrower->{dateofbirth} } )->store; |
642 |
|
700 |
|
643 |
is( C4::Reserves::CanBookBeReserved($borrowernumber, $biblionumber)->{status} , 'OK', "Reserving a 'PEGI 16' Biblio by a 30 year old borrower succeeds"); |
701 |
is( |
|
|
702 |
C4::Reserves::CanBookBeReserved( $borrowernumber, $biblionumber )->{status}, 'OK', |
703 |
"Reserving a 'PEGI 16' Biblio by a 30 year old borrower succeeds" |
704 |
); |
644 |
|
705 |
|
645 |
is( C4::Reserves::CanBookBeReserved($borrowernumber, $biblio_with_no_item->biblionumber)->{status} , '', "Biblio with no item. Status is empty"); |
706 |
is( |
646 |
#### |
707 |
C4::Reserves::CanBookBeReserved( $borrowernumber, $biblio_with_no_item->biblionumber )->{status}, '', |
|
|
708 |
"Biblio with no item. Status is empty" |
709 |
); |
710 |
#### |
647 |
####### EO Bug 13113 <<< |
711 |
####### EO Bug 13113 <<< |
648 |
#### |
712 |
#### |
649 |
|
713 |
|
650 |
ok( C4::Reserves::IsAvailableForItemLevelRequest($item, $patron), "Reserving a book on item level" ); |
714 |
ok( C4::Reserves::IsAvailableForItemLevelRequest( $item, $patron ), "Reserving a book on item level" ); |
651 |
|
715 |
|
652 |
my $pickup_branch = $builder->build({ source => 'Branch' })->{ branchcode }; |
716 |
my $pickup_branch = $builder->build( { source => 'Branch' } )->{branchcode}; |
653 |
t::lib::Mocks::mock_preference( 'UseBranchTransferLimits', '1' ); |
717 |
t::lib::Mocks::mock_preference( 'UseBranchTransferLimits', '1' ); |
654 |
t::lib::Mocks::mock_preference( 'BranchTransferLimitsType', 'itemtype' ); |
718 |
t::lib::Mocks::mock_preference( 'BranchTransferLimitsType', 'itemtype' ); |
655 |
my $limit = Koha::Item::Transfer::Limit->new( |
719 |
my $limit = Koha::Item::Transfer::Limit->new( |
Lines 659-675
my $limit = Koha::Item::Transfer::Limit->new(
Link Here
|
659 |
itemtype => $item->effective_itemtype, |
723 |
itemtype => $item->effective_itemtype, |
660 |
} |
724 |
} |
661 |
)->store(); |
725 |
)->store(); |
662 |
is( C4::Reserves::IsAvailableForItemLevelRequest($item, $patron, $pickup_branch), 0, "Item level request not available due to transfer limit" ); |
726 |
is( |
663 |
t::lib::Mocks::mock_preference( 'UseBranchTransferLimits', '0' ); |
727 |
C4::Reserves::IsAvailableForItemLevelRequest( $item, $patron, $pickup_branch ), 0, |
|
|
728 |
"Item level request not available due to transfer limit" |
729 |
); |
730 |
t::lib::Mocks::mock_preference( 'UseBranchTransferLimits', '0' ); |
664 |
|
731 |
|
665 |
my $categorycode = $borrower->{categorycode}; |
732 |
my $categorycode = $borrower->{categorycode}; |
666 |
my $holdingbranch = $item->{holdingbranch}; |
733 |
my $holdingbranch = $item->{holdingbranch}; |
667 |
Koha::CirculationRules->set_rules( |
734 |
Koha::CirculationRules->set_rules( |
668 |
{ |
735 |
{ |
669 |
categorycode => $categorycode, |
736 |
categorycode => $categorycode, |
670 |
itemtype => $item->effective_itemtype, |
737 |
itemtype => $item->effective_itemtype, |
671 |
branchcode => $holdingbranch, |
738 |
branchcode => $holdingbranch, |
672 |
rules => { |
739 |
rules => { |
673 |
onshelfholds => 1, |
740 |
onshelfholds => 1, |
674 |
} |
741 |
} |
675 |
} |
742 |
} |
Lines 677-685
Koha::CirculationRules->set_rules(
Link Here
|
677 |
|
744 |
|
678 |
# tests for MoveReserve in relation to ConfirmFutureHolds (BZ 14526) |
745 |
# tests for MoveReserve in relation to ConfirmFutureHolds (BZ 14526) |
679 |
# hold from A pos 1, today, no fut holds: MoveReserve should fill it |
746 |
# hold from A pos 1, today, no fut holds: MoveReserve should fill it |
680 |
$dbh->do('DELETE FROM reserves', undef, ($bibnum)); |
747 |
$dbh->do( 'DELETE FROM reserves', undef, ($bibnum) ); |
681 |
t::lib::Mocks::mock_preference('ConfirmFutureHolds', 0); |
748 |
t::lib::Mocks::mock_preference( 'ConfirmFutureHolds', 0 ); |
682 |
t::lib::Mocks::mock_preference('AllowHoldDateInFuture', 1); |
749 |
t::lib::Mocks::mock_preference( 'AllowHoldDateInFuture', 1 ); |
683 |
AddReserve( |
750 |
AddReserve( |
684 |
{ |
751 |
{ |
685 |
branchcode => $branch_1, |
752 |
branchcode => $branch_1, |
Lines 689-698
AddReserve(
Link Here
|
689 |
} |
756 |
} |
690 |
); |
757 |
); |
691 |
MoveReserve( $item->itemnumber, $borrowernumber ); |
758 |
MoveReserve( $item->itemnumber, $borrowernumber ); |
692 |
($status)=CheckReserves( $item ); |
759 |
($status) = CheckReserves($item); |
693 |
is( $status, '', 'MoveReserve filled hold'); |
760 |
is( $status, '', 'MoveReserve filled hold' ); |
|
|
761 |
|
694 |
# hold from A waiting, today, no fut holds: MoveReserve should fill it |
762 |
# hold from A waiting, today, no fut holds: MoveReserve should fill it |
695 |
my $other_item = $builder->build_sample_item({ biblionumber => $biblio->id }); |
763 |
my $other_item = $builder->build_sample_item( { biblionumber => $biblio->id } ); |
696 |
AddReserve( |
764 |
AddReserve( |
697 |
{ |
765 |
{ |
698 |
branchcode => $branch_1, |
766 |
branchcode => $branch_1, |
Lines 704-770
AddReserve(
Link Here
|
704 |
} |
772 |
} |
705 |
); |
773 |
); |
706 |
MoveReserve( $item->itemnumber, $borrowernumber ); |
774 |
MoveReserve( $item->itemnumber, $borrowernumber ); |
707 |
($status)=CheckReserves( $item ); |
775 |
($status) = CheckReserves($item); |
708 |
is( $status, '', 'MoveReserve filled waiting hold'); |
776 |
is( $status, '', 'MoveReserve filled waiting hold' ); |
|
|
777 |
|
709 |
# hold from A pos 1, tomorrow, no fut holds: not filled |
778 |
# hold from A pos 1, tomorrow, no fut holds: not filled |
710 |
$resdate= dt_from_string(); |
779 |
$resdate = dt_from_string(); |
711 |
$resdate->add_duration(DateTime::Duration->new(days => 1)); |
780 |
$resdate->add_duration( DateTime::Duration->new( days => 1 ) ); |
712 |
AddReserve( |
781 |
AddReserve( |
713 |
{ |
782 |
{ |
714 |
branchcode => $branch_1, |
783 |
branchcode => $branch_1, |
715 |
borrowernumber => $borrowernumber, |
784 |
borrowernumber => $borrowernumber, |
716 |
biblionumber => $bibnum, |
785 |
biblionumber => $bibnum, |
717 |
priority => 1, |
786 |
priority => 1, |
718 |
reservation_date => $resdate, |
787 |
reservation_date => $resdate, |
719 |
} |
788 |
} |
720 |
); |
789 |
); |
721 |
MoveReserve( $item->itemnumber, $borrowernumber ); |
790 |
MoveReserve( $item->itemnumber, $borrowernumber ); |
722 |
($status)=CheckReserves( $item, 1 ); |
791 |
($status) = CheckReserves( $item, 1 ); |
723 |
is( $status, 'Reserved', 'MoveReserve did not fill future hold'); |
792 |
is( $status, 'Reserved', 'MoveReserve did not fill future hold' ); |
724 |
$dbh->do('DELETE FROM reserves', undef, ($bibnum)); |
793 |
$dbh->do( 'DELETE FROM reserves', undef, ($bibnum) ); |
|
|
794 |
|
725 |
# hold from A pos 1, tomorrow, fut holds=2: MoveReserve should fill it |
795 |
# hold from A pos 1, tomorrow, fut holds=2: MoveReserve should fill it |
726 |
t::lib::Mocks::mock_preference('ConfirmFutureHolds', 2); |
796 |
t::lib::Mocks::mock_preference( 'ConfirmFutureHolds', 2 ); |
727 |
AddReserve( |
797 |
AddReserve( |
728 |
{ |
798 |
{ |
729 |
branchcode => $branch_1, |
799 |
branchcode => $branch_1, |
730 |
borrowernumber => $borrowernumber, |
800 |
borrowernumber => $borrowernumber, |
731 |
biblionumber => $bibnum, |
801 |
biblionumber => $bibnum, |
732 |
priority => 1, |
802 |
priority => 1, |
733 |
reservation_date => $resdate, |
803 |
reservation_date => $resdate, |
734 |
} |
804 |
} |
735 |
); |
805 |
); |
736 |
MoveReserve( $item->itemnumber, $borrowernumber ); |
806 |
MoveReserve( $item->itemnumber, $borrowernumber ); |
737 |
($status)=CheckReserves( $item, undef, 2 ); |
807 |
($status) = CheckReserves( $item, undef, 2 ); |
738 |
is( $status, '', 'MoveReserve filled future hold now'); |
808 |
is( $status, '', 'MoveReserve filled future hold now' ); |
|
|
809 |
|
739 |
# hold from A waiting, tomorrow, fut holds=2: MoveReserve should fill it |
810 |
# hold from A waiting, tomorrow, fut holds=2: MoveReserve should fill it |
740 |
AddReserve( |
811 |
AddReserve( |
741 |
{ |
812 |
{ |
742 |
branchcode => $branch_1, |
813 |
branchcode => $branch_1, |
743 |
borrowernumber => $borrowernumber, |
814 |
borrowernumber => $borrowernumber, |
744 |
biblionumber => $bibnum, |
815 |
biblionumber => $bibnum, |
745 |
priority => 1, |
816 |
priority => 1, |
746 |
reservation_date => $resdate, |
817 |
reservation_date => $resdate, |
747 |
} |
818 |
} |
748 |
); |
819 |
); |
749 |
MoveReserve( $item->itemnumber, $borrowernumber ); |
820 |
MoveReserve( $item->itemnumber, $borrowernumber ); |
750 |
($status)=CheckReserves( $item, undef, 2 ); |
821 |
($status) = CheckReserves( $item, undef, 2 ); |
751 |
is( $status, '', 'MoveReserve filled future waiting hold now'); |
822 |
is( $status, '', 'MoveReserve filled future waiting hold now' ); |
|
|
823 |
|
752 |
# hold from A pos 1, today+3, fut holds=2: MoveReserve should not fill it |
824 |
# hold from A pos 1, today+3, fut holds=2: MoveReserve should not fill it |
753 |
$resdate= dt_from_string(); |
825 |
$resdate = dt_from_string(); |
754 |
$resdate->add_duration(DateTime::Duration->new(days => 3)); |
826 |
$resdate->add_duration( DateTime::Duration->new( days => 3 ) ); |
755 |
AddReserve( |
827 |
AddReserve( |
756 |
{ |
828 |
{ |
757 |
branchcode => $branch_1, |
829 |
branchcode => $branch_1, |
758 |
borrowernumber => $borrowernumber, |
830 |
borrowernumber => $borrowernumber, |
759 |
biblionumber => $bibnum, |
831 |
biblionumber => $bibnum, |
760 |
priority => 1, |
832 |
priority => 1, |
761 |
reservation_date => $resdate, |
833 |
reservation_date => $resdate, |
762 |
} |
834 |
} |
763 |
); |
835 |
); |
764 |
MoveReserve( $item->itemnumber, $borrowernumber ); |
836 |
MoveReserve( $item->itemnumber, $borrowernumber ); |
765 |
($status)=CheckReserves( $item, 3 ); |
837 |
($status) = CheckReserves( $item, 3 ); |
766 |
is( $status, 'Reserved', 'MoveReserve did not fill future hold of 3 days'); |
838 |
is( $status, 'Reserved', 'MoveReserve did not fill future hold of 3 days' ); |
767 |
$dbh->do('DELETE FROM reserves', undef, ($bibnum)); |
839 |
$dbh->do( 'DELETE FROM reserves', undef, ($bibnum) ); |
768 |
|
840 |
|
769 |
$cache->clear_from_cache("MarcStructure-0-$frameworkcode"); |
841 |
$cache->clear_from_cache("MarcStructure-0-$frameworkcode"); |
770 |
$cache->clear_from_cache("MarcStructure-1-$frameworkcode"); |
842 |
$cache->clear_from_cache("MarcStructure-1-$frameworkcode"); |
Lines 774-836
subtest '_koha_notify_reserve() tests' => sub {
Link Here
|
774 |
|
846 |
|
775 |
plan tests => 3; |
847 |
plan tests => 3; |
776 |
|
848 |
|
777 |
my $branch = $builder->build_object({ |
849 |
my $branch = $builder->build_object( |
778 |
class => 'Koha::Libraries', |
850 |
{ |
779 |
value => { |
851 |
class => 'Koha::Libraries', |
780 |
branchemail => 'branch@e.mail', |
852 |
value => { |
781 |
branchreplyto => 'branch@reply.to', |
853 |
branchemail => 'branch@e.mail', |
782 |
pickup_location => 1 |
854 |
branchreplyto => 'branch@reply.to', |
|
|
855 |
pickup_location => 1 |
856 |
} |
783 |
} |
857 |
} |
784 |
}); |
858 |
); |
785 |
my $item = $builder->build_sample_item({ |
859 |
my $item = $builder->build_sample_item( |
786 |
homebranch => $branch->branchcode, |
860 |
{ |
787 |
holdingbranch => $branch->branchcode |
861 |
homebranch => $branch->branchcode, |
788 |
}); |
862 |
holdingbranch => $branch->branchcode |
|
|
863 |
} |
864 |
); |
789 |
|
865 |
|
790 |
my $wants_hold_and_email = { |
866 |
my $wants_hold_and_email = { |
791 |
wants_digest => '0', |
867 |
wants_digest => '0', |
792 |
transports => { |
868 |
transports => { |
793 |
sms => 'HOLD', |
869 |
sms => 'HOLD', |
794 |
email => 'HOLD', |
870 |
email => 'HOLD', |
795 |
}, |
871 |
}, |
796 |
letter_code => 'HOLD' |
872 |
letter_code => 'HOLD' |
797 |
}; |
873 |
}; |
798 |
|
874 |
|
799 |
my $mp = Test::MockModule->new( 'C4::Members::Messaging' ); |
875 |
my $mp = Test::MockModule->new('C4::Members::Messaging'); |
800 |
|
876 |
|
801 |
$mp->mock("GetMessagingPreferences",$wants_hold_and_email); |
877 |
$mp->mock( "GetMessagingPreferences", $wants_hold_and_email ); |
802 |
|
878 |
|
803 |
$dbh->do('DELETE FROM letter'); |
879 |
$dbh->do('DELETE FROM letter'); |
804 |
|
880 |
|
805 |
my $email_hold_notice = $builder->build({ |
881 |
my $email_hold_notice = $builder->build( |
|
|
882 |
{ |
806 |
source => 'Letter', |
883 |
source => 'Letter', |
807 |
value => { |
884 |
value => { |
808 |
message_transport_type => 'email', |
885 |
message_transport_type => 'email', |
809 |
branchcode => '', |
886 |
branchcode => '', |
810 |
code => 'HOLD', |
887 |
code => 'HOLD', |
811 |
module => 'reserves', |
888 |
module => 'reserves', |
812 |
lang => 'default', |
889 |
lang => 'default', |
813 |
} |
890 |
} |
814 |
}); |
891 |
} |
|
|
892 |
); |
815 |
|
893 |
|
816 |
my $sms_hold_notice = $builder->build({ |
894 |
my $sms_hold_notice = $builder->build( |
|
|
895 |
{ |
817 |
source => 'Letter', |
896 |
source => 'Letter', |
818 |
value => { |
897 |
value => { |
819 |
message_transport_type => 'sms', |
898 |
message_transport_type => 'sms', |
820 |
branchcode => '', |
899 |
branchcode => '', |
821 |
code => 'HOLD', |
900 |
code => 'HOLD', |
822 |
module => 'reserves', |
901 |
module => 'reserves', |
823 |
lang=>'default', |
902 |
lang => 'default', |
824 |
} |
903 |
} |
825 |
}); |
904 |
} |
|
|
905 |
); |
826 |
|
906 |
|
827 |
my $hold_borrower = $builder->build({ |
907 |
my $hold_borrower = $builder->build( |
|
|
908 |
{ |
828 |
source => 'Borrower', |
909 |
source => 'Borrower', |
829 |
value => { |
910 |
value => { |
830 |
smsalertnumber=>'5555555555', |
911 |
smsalertnumber => '5555555555', |
831 |
email=>'a@b.com', |
912 |
email => 'a@b.com', |
832 |
} |
913 |
} |
833 |
})->{borrowernumber}; |
914 |
} |
|
|
915 |
)->{borrowernumber}; |
834 |
|
916 |
|
835 |
C4::Reserves::AddReserve( |
917 |
C4::Reserves::AddReserve( |
836 |
{ |
918 |
{ |
Lines 840-881
subtest '_koha_notify_reserve() tests' => sub {
Link Here
|
840 |
} |
922 |
} |
841 |
); |
923 |
); |
842 |
|
924 |
|
843 |
ModReserveAffect($item->itemnumber, $hold_borrower, 0); |
925 |
ModReserveAffect( $item->itemnumber, $hold_borrower, 0 ); |
844 |
my $sms_message_address = $schema->resultset('MessageQueue')->search({ |
926 |
my $sms_message_address = $schema->resultset('MessageQueue')->search( |
845 |
letter_code => 'HOLD', |
927 |
{ |
|
|
928 |
letter_code => 'HOLD', |
846 |
message_transport_type => 'sms', |
929 |
message_transport_type => 'sms', |
847 |
borrowernumber => $hold_borrower, |
930 |
borrowernumber => $hold_borrower, |
848 |
})->next()->to_address(); |
931 |
} |
849 |
is($sms_message_address, undef ,"We should not populate the sms message with the sms number, sending will do so"); |
932 |
)->next()->to_address(); |
|
|
933 |
is( $sms_message_address, undef, "We should not populate the sms message with the sms number, sending will do so" ); |
850 |
|
934 |
|
851 |
my $email = $schema->resultset('MessageQueue')->search({ |
935 |
my $email = $schema->resultset('MessageQueue')->search( |
852 |
letter_code => 'HOLD', |
936 |
{ |
|
|
937 |
letter_code => 'HOLD', |
853 |
message_transport_type => 'email', |
938 |
message_transport_type => 'email', |
854 |
borrowernumber => $hold_borrower, |
939 |
borrowernumber => $hold_borrower, |
855 |
})->next(); |
940 |
} |
|
|
941 |
)->next(); |
856 |
my $email_to_address = $email->to_address(); |
942 |
my $email_to_address = $email->to_address(); |
857 |
is($email_to_address, undef ,"We should not populate the hold message with the email address, sending will do so"); |
943 |
is( |
|
|
944 |
$email_to_address, undef, |
945 |
"We should not populate the hold message with the email address, sending will do so" |
946 |
); |
858 |
my $email_from_address = $email->from_address(); |
947 |
my $email_from_address = $email->from_address(); |
859 |
is($email_from_address,'branch@e.mail',"Library's from address is used for sending"); |
948 |
is( $email_from_address, 'branch@e.mail', "Library's from address is used for sending" ); |
860 |
|
949 |
|
861 |
}; |
950 |
}; |
862 |
|
951 |
|
863 |
subtest 'ReservesNeedReturns' => sub { |
952 |
subtest 'ReservesNeedReturns' => sub { |
864 |
plan tests => 18; |
953 |
plan tests => 18; |
865 |
|
954 |
|
866 |
my $library = $builder->build_object( { class => 'Koha::Libraries' } ); |
955 |
my $library = $builder->build_object( { class => 'Koha::Libraries' } ); |
867 |
my $item_info = { |
956 |
my $item_info = { |
868 |
homebranch => $library->branchcode, |
957 |
homebranch => $library->branchcode, |
869 |
holdingbranch => $library->branchcode, |
958 |
holdingbranch => $library->branchcode, |
870 |
}; |
959 |
}; |
871 |
my $item = $builder->build_sample_item($item_info); |
960 |
my $item = $builder->build_sample_item($item_info); |
872 |
my $patron = $builder->build_object( |
961 |
my $patron = $builder->build_object( |
873 |
{ |
962 |
{ |
874 |
class => 'Koha::Patrons', |
963 |
class => 'Koha::Patrons', |
875 |
value => { branchcode => $library->branchcode, } |
964 |
value => { branchcode => $library->branchcode, } |
876 |
} |
965 |
} |
877 |
); |
966 |
); |
878 |
my $patron_2 = $builder->build_object( |
967 |
my $patron_2 = $builder->build_object( |
879 |
{ |
968 |
{ |
880 |
class => 'Koha::Patrons', |
969 |
class => 'Koha::Patrons', |
881 |
value => { branchcode => $library->branchcode, } |
970 |
value => { branchcode => $library->branchcode, } |
Lines 884-899
subtest 'ReservesNeedReturns' => sub {
Link Here
|
884 |
|
973 |
|
885 |
my $priority = 1; |
974 |
my $priority = 1; |
886 |
|
975 |
|
887 |
t::lib::Mocks::mock_preference('ReservesNeedReturns', 1); # Test with feature disabled |
976 |
t::lib::Mocks::mock_preference( 'ReservesNeedReturns', 1 ); # Test with feature disabled |
888 |
my $hold = place_item_hold( $patron, $item, $library, $priority ); |
977 |
my $hold = place_item_hold( $patron, $item, $library, $priority ); |
889 |
is( $hold->priority, $priority, 'If ReservesNeedReturns is 1, priority must not have been set to changed' ); |
978 |
is( $hold->priority, $priority, 'If ReservesNeedReturns is 1, priority must not have been set to changed' ); |
890 |
is( $hold->found, undef, 'If ReservesNeedReturns is 1, found must not have been set waiting' ); |
979 |
is( $hold->found, undef, 'If ReservesNeedReturns is 1, found must not have been set waiting' ); |
891 |
$hold->delete; |
980 |
$hold->delete; |
892 |
|
981 |
|
893 |
t::lib::Mocks::mock_preference('ReservesNeedReturns', 0); # '0' means 'Automatically mark a hold as found and waiting' |
982 |
t::lib::Mocks::mock_preference( 'ReservesNeedReturns', 0 ) |
|
|
983 |
; # '0' means 'Automatically mark a hold as found and waiting' |
894 |
$hold = place_item_hold( $patron, $item, $library, $priority ); |
984 |
$hold = place_item_hold( $patron, $item, $library, $priority ); |
895 |
is( $hold->priority, 0, 'If ReservesNeedReturns is 0 and no other status, priority must have been set to 0' ); |
985 |
is( $hold->priority, 0, 'If ReservesNeedReturns is 0 and no other status, priority must have been set to 0' ); |
896 |
is( $hold->found, 'W', 'If ReservesNeedReturns is 0 and no other status, found must have been set waiting' ); |
986 |
is( $hold->found, 'W', 'If ReservesNeedReturns is 0 and no other status, found must have been set waiting' ); |
897 |
$hold->delete; |
987 |
$hold->delete; |
898 |
|
988 |
|
899 |
$item->onloan('2010-01-01')->store; |
989 |
$item->onloan('2010-01-01')->store; |
Lines 901-963
subtest 'ReservesNeedReturns' => sub {
Link Here
|
901 |
is( $hold->priority, 1, 'If ReservesNeedReturns is 0 but item onloan priority must be set to 1' ); |
991 |
is( $hold->priority, 1, 'If ReservesNeedReturns is 0 but item onloan priority must be set to 1' ); |
902 |
$hold->delete; |
992 |
$hold->delete; |
903 |
|
993 |
|
904 |
t::lib::Mocks::mock_preference('AllowHoldsOnDamagedItems', 0); # '0' means damaged holds not allowed |
994 |
t::lib::Mocks::mock_preference( 'AllowHoldsOnDamagedItems', 0 ); # '0' means damaged holds not allowed |
905 |
$item->onloan(undef)->damaged(1)->store; |
995 |
$item->onloan(undef)->damaged(1)->store; |
906 |
$hold = place_item_hold( $patron, $item, $library, $priority ); |
996 |
$hold = place_item_hold( $patron, $item, $library, $priority ); |
907 |
is( $hold->priority, 1, 'If ReservesNeedReturns is 0 but item damaged and not allowed holds on damaged items priority must be set to 1' ); |
997 |
is( |
|
|
998 |
$hold->priority, 1, |
999 |
'If ReservesNeedReturns is 0 but item damaged and not allowed holds on damaged items priority must be set to 1' |
1000 |
); |
908 |
$hold->delete; |
1001 |
$hold->delete; |
909 |
t::lib::Mocks::mock_preference('AllowHoldsOnDamagedItems', 1); # '0' means damaged holds not allowed |
1002 |
t::lib::Mocks::mock_preference( 'AllowHoldsOnDamagedItems', 1 ); # '0' means damaged holds not allowed |
910 |
$hold = place_item_hold( $patron, $item, $library, $priority ); |
1003 |
$hold = place_item_hold( $patron, $item, $library, $priority ); |
911 |
is( $hold->priority, 0, 'If ReservesNeedReturns is 0 and damaged holds allowed, priority must have been set to 0' ); |
1004 |
is( $hold->priority, 0, 'If ReservesNeedReturns is 0 and damaged holds allowed, priority must have been set to 0' ); |
912 |
is( $hold->found, 'W', 'If ReservesNeedReturns is 0 and damaged holds allowed, found must have been set waiting' ); |
1005 |
is( $hold->found, 'W', 'If ReservesNeedReturns is 0 and damaged holds allowed, found must have been set waiting' ); |
913 |
$hold->delete; |
1006 |
$hold->delete; |
914 |
|
1007 |
|
915 |
my $hold_1 = place_item_hold( $patron, $item, $library, $priority ); |
1008 |
my $hold_1 = place_item_hold( $patron, $item, $library, $priority ); |
916 |
is( $hold_1->found, 'W', 'First hold on item is set to waiting with ReservesNeedReturns set to 0' ); |
1009 |
is( $hold_1->found, 'W', 'First hold on item is set to waiting with ReservesNeedReturns set to 0' ); |
917 |
is( $hold_1->priority, 0, 'First hold on item is set to waiting with ReservesNeedReturns set to 0' ); |
1010 |
is( $hold_1->priority, 0, 'First hold on item is set to waiting with ReservesNeedReturns set to 0' ); |
918 |
$hold = place_item_hold( $patron_2, $item, $library, $priority ); |
1011 |
$hold = place_item_hold( $patron_2, $item, $library, $priority ); |
919 |
is( $hold->priority, 1, 'If ReservesNeedReturns is 0 but item already on hold priority must be set to 1' ); |
1012 |
is( $hold->priority, 1, 'If ReservesNeedReturns is 0 but item already on hold priority must be set to 1' ); |
920 |
$hold->delete; |
1013 |
$hold->delete; |
921 |
$hold_1->delete; |
1014 |
$hold_1->delete; |
922 |
|
1015 |
|
923 |
my $transfer = $builder->build_object({ |
1016 |
my $transfer = $builder->build_object( |
924 |
class => "Koha::Item::Transfers", |
1017 |
{ |
925 |
value => { |
1018 |
class => "Koha::Item::Transfers", |
926 |
itemnumber => $item->itemnumber, |
1019 |
value => { |
927 |
datearrived => undef, |
1020 |
itemnumber => $item->itemnumber, |
928 |
datecancelled => undef |
1021 |
datearrived => undef, |
|
|
1022 |
datecancelled => undef |
1023 |
} |
929 |
} |
1024 |
} |
930 |
}); |
1025 |
); |
931 |
$item->damaged(0)->store; |
1026 |
$item->damaged(0)->store; |
932 |
$hold = place_item_hold( $patron, $item, $library, $priority ); |
1027 |
$hold = place_item_hold( $patron, $item, $library, $priority ); |
933 |
is( $hold->found, undef, 'If ReservesNeedReturns is 0 but item in transit the hold must not be set to waiting' ); |
1028 |
is( $hold->found, undef, 'If ReservesNeedReturns is 0 but item in transit the hold must not be set to waiting' ); |
934 |
is( $hold->priority, 1, 'If ReservesNeedReturns is 0 but item in transit the hold must not be set to waiting' ); |
1029 |
is( $hold->priority, 1, 'If ReservesNeedReturns is 0 but item in transit the hold must not be set to waiting' ); |
935 |
$hold->delete; |
1030 |
$hold->delete; |
936 |
$transfer->delete; |
1031 |
$transfer->delete; |
937 |
|
1032 |
|
938 |
$hold = place_item_hold( $patron, $item, $library, $priority ); |
1033 |
$hold = place_item_hold( $patron, $item, $library, $priority ); |
939 |
is( $hold->priority, 0, 'If ReservesNeedReturns is 0 and no other status, priority must have been set to 0' ); |
1034 |
is( $hold->priority, 0, 'If ReservesNeedReturns is 0 and no other status, priority must have been set to 0' ); |
940 |
is( $hold->found, 'W', 'If ReservesNeedReturns is 0 and no other status, found must have been set waiting' ); |
1035 |
is( $hold->found, 'W', 'If ReservesNeedReturns is 0 and no other status, found must have been set waiting' ); |
941 |
$hold_1 = place_item_hold( $patron, $item, $library, $priority ); |
1036 |
$hold_1 = place_item_hold( $patron, $item, $library, $priority ); |
942 |
is( $hold_1->priority, 1, 'If ReservesNeedReturns is 0 but item has a hold priority is 1' ); |
1037 |
is( $hold_1->priority, 1, 'If ReservesNeedReturns is 0 but item has a hold priority is 1' ); |
943 |
$hold_1->suspend(1)->store; # We suspend the hold |
1038 |
$hold_1->suspend(1)->store; # We suspend the hold |
944 |
$hold->delete; # Delete the waiting hold |
1039 |
$hold->delete; # Delete the waiting hold |
945 |
$hold = place_item_hold( $patron, $item, $library, $priority ); |
1040 |
$hold = place_item_hold( $patron, $item, $library, $priority ); |
946 |
is( $hold->priority, 0, 'If ReservesNeedReturns is 0 and other hold(s) suspended, priority must have been set to 0' ); |
1041 |
is( |
947 |
is( $hold->found, 'W', 'If ReservesNeedReturns is 0 and other hold(s) suspended, found must have been set waiting' ); |
1042 |
$hold->priority, 0, |
948 |
|
1043 |
'If ReservesNeedReturns is 0 and other hold(s) suspended, priority must have been set to 0' |
949 |
|
1044 |
); |
950 |
|
1045 |
is( |
|
|
1046 |
$hold->found, 'W', |
1047 |
'If ReservesNeedReturns is 0 and other hold(s) suspended, found must have been set waiting' |
1048 |
); |
951 |
|
1049 |
|
952 |
t::lib::Mocks::mock_preference('ReservesNeedReturns', 1); # Don't affect other tests |
1050 |
t::lib::Mocks::mock_preference( 'ReservesNeedReturns', 1 ); # Don't affect other tests |
953 |
}; |
1051 |
}; |
954 |
|
1052 |
|
955 |
subtest 'ChargeReserveFee tests' => sub { |
1053 |
subtest 'ChargeReserveFee tests' => sub { |
956 |
|
1054 |
|
957 |
plan tests => 8; |
1055 |
plan tests => 8; |
958 |
|
1056 |
|
959 |
my $library = $builder->build_object({ class => 'Koha::Libraries' }); |
1057 |
my $library = $builder->build_object( { class => 'Koha::Libraries' } ); |
960 |
my $patron = $builder->build_object({ class => 'Koha::Patrons' }); |
1058 |
my $patron = $builder->build_object( { class => 'Koha::Patrons' } ); |
961 |
|
1059 |
|
962 |
my $fee = 20; |
1060 |
my $fee = 20; |
963 |
my $title = 'A title'; |
1061 |
my $title = 'A title'; |
Lines 967-987
subtest 'ChargeReserveFee tests' => sub {
Link Here
|
967 |
|
1065 |
|
968 |
my $line = C4::Reserves::ChargeReserveFee( $patron->id, $fee, $title ); |
1066 |
my $line = C4::Reserves::ChargeReserveFee( $patron->id, $fee, $title ); |
969 |
|
1067 |
|
970 |
is( ref($line), 'Koha::Account::Line' , 'Returns a Koha::Account::Line object'); |
1068 |
is( ref($line), 'Koha::Account::Line', 'Returns a Koha::Account::Line object' ); |
971 |
ok( $line->is_debit, 'Generates a debit line' ); |
1069 |
ok( $line->is_debit, 'Generates a debit line' ); |
972 |
is( $line->debit_type_code, 'RESERVE' , 'generates RESERVE debit_type'); |
1070 |
is( $line->debit_type_code, 'RESERVE', 'generates RESERVE debit_type' ); |
973 |
is( $line->borrowernumber, $patron->id , 'generated line belongs to the passed patron'); |
1071 |
is( $line->borrowernumber, $patron->id, 'generated line belongs to the passed patron' ); |
974 |
is( $line->amount, $fee , 'amount set correctly'); |
1072 |
is( $line->amount, $fee, 'amount set correctly' ); |
975 |
is( $line->amountoutstanding, $fee , 'amountoutstanding set correctly'); |
1073 |
is( $line->amountoutstanding, $fee, 'amountoutstanding set correctly' ); |
976 |
is( $line->description, "$title" , 'description is title of reserved item'); |
1074 |
is( $line->description, "$title", 'description is title of reserved item' ); |
977 |
is( $line->branchcode, $library->id , "Library id is picked from userenv and stored correctly" ); |
1075 |
is( $line->branchcode, $library->id, "Library id is picked from userenv and stored correctly" ); |
978 |
}; |
1076 |
}; |
979 |
|
1077 |
|
980 |
subtest 'reserves.item_level_hold' => sub { |
1078 |
subtest 'reserves.item_level_hold' => sub { |
981 |
plan tests => 4; |
1079 |
plan tests => 4; |
982 |
|
1080 |
|
983 |
my $item = $builder->build_sample_item; |
1081 |
my $item = $builder->build_sample_item; |
984 |
my $patron = $builder->build_object({ class => "Koha::Patrons" }); |
1082 |
my $patron = $builder->build_object( { class => "Koha::Patrons" } ); |
985 |
$patron->branchcode( $item->homebranch ); |
1083 |
$patron->branchcode( $item->homebranch ); |
986 |
|
1084 |
|
987 |
subtest 'item level hold' => sub { |
1085 |
subtest 'item level hold' => sub { |
Lines 1003-1016
subtest 'reserves.item_level_hold' => sub {
Link Here
|
1003 |
ModReserveAffect( $item->itemnumber, $patron->id, 1 ); |
1101 |
ModReserveAffect( $item->itemnumber, $patron->id, 1 ); |
1004 |
|
1102 |
|
1005 |
my $mock = Test::MockModule->new('Koha::BackgroundJob::BatchUpdateBiblioHoldsQueue'); |
1103 |
my $mock = Test::MockModule->new('Koha::BackgroundJob::BatchUpdateBiblioHoldsQueue'); |
1006 |
$mock->mock( 'enqueue', sub { |
1104 |
$mock->mock( |
1007 |
my ( $self, $args ) = @_; |
1105 |
'enqueue', |
1008 |
is_deeply( |
1106 |
sub { |
1009 |
$args->{biblio_ids}, |
1107 |
my ( $self, $args ) = @_; |
1010 |
[ $hold->biblionumber ], |
1108 |
is_deeply( |
1011 |
"AlterPriority triggers a holds queue update for the related biblio" |
1109 |
$args->{biblio_ids}, |
1012 |
); |
1110 |
[ $hold->biblionumber ], |
1013 |
} ); |
1111 |
"AlterPriority triggers a holds queue update for the related biblio" |
|
|
1112 |
); |
1113 |
} |
1114 |
); |
1014 |
|
1115 |
|
1015 |
t::lib::Mocks::mock_preference( 'RealTimeHoldsQueue', 1 ); |
1116 |
t::lib::Mocks::mock_preference( 'RealTimeHoldsQueue', 1 ); |
1016 |
t::lib::Mocks::mock_preference( 'HoldsLog', 1 ); |
1117 |
t::lib::Mocks::mock_preference( 'HoldsLog', 1 ); |
Lines 1060-1066
subtest 'reserves.item_level_hold' => sub {
Link Here
|
1060 |
); |
1161 |
); |
1061 |
|
1162 |
|
1062 |
my $hold = Koha::Holds->find($reserve_id); |
1163 |
my $hold = Koha::Holds->find($reserve_id); |
1063 |
is( $hold->item_level_hold, 0, 'item_level_hold should not be set when AddReserve is called without a specific item' ); |
1164 |
is( |
|
|
1165 |
$hold->item_level_hold, 0, |
1166 |
'item_level_hold should not be set when AddReserve is called without a specific item' |
1167 |
); |
1064 |
|
1168 |
|
1065 |
# Mark it waiting |
1169 |
# Mark it waiting |
1066 |
ModReserveAffect( $item->itemnumber, $patron->borrowernumber, 1 ); |
1170 |
ModReserveAffect( $item->itemnumber, $patron->borrowernumber, 1 ); |
Lines 1087-1107
subtest 'reserves.item_level_hold' => sub {
Link Here
|
1087 |
itemtype => undef, |
1191 |
itemtype => undef, |
1088 |
rules => { |
1192 |
rules => { |
1089 |
reservesallowed => 25, |
1193 |
reservesallowed => 25, |
1090 |
opacitemholds => 'F', |
1194 |
opacitemholds => 'F', |
1091 |
} |
1195 |
} |
1092 |
} |
1196 |
} |
1093 |
); |
1197 |
); |
1094 |
|
1198 |
|
1095 |
my $canreserve = C4::Reserves::CanBookBeReserved( $patron->id, $item->biblionumber ); |
1199 |
my $canreserve = C4::Reserves::CanBookBeReserved( $patron->id, $item->biblionumber ); |
1096 |
|
1200 |
|
1097 |
is( $canreserve->{status}, |
1201 |
is( |
|
|
1202 |
$canreserve->{status}, |
1098 |
'recordHoldNotAllowed', |
1203 |
'recordHoldNotAllowed', |
1099 |
'record-level holds should not be possible with opacitemholds set to "Force"' ); |
1204 |
'record-level holds should not be possible with opacitemholds set to "Force"' |
|
|
1205 |
); |
1100 |
|
1206 |
|
1101 |
$canreserve = C4::Reserves::CanItemBeReserved( $patron, $item ); |
1207 |
$canreserve = C4::Reserves::CanItemBeReserved( $patron, $item ); |
1102 |
|
1208 |
|
1103 |
is( $canreserve->{status}, 'OK', |
1209 |
is( |
1104 |
'item-level holds should be possible with opacitemholds set to "Force"' ); |
1210 |
$canreserve->{status}, 'OK', |
|
|
1211 |
'item-level holds should be possible with opacitemholds set to "Force"' |
1212 |
); |
1105 |
|
1213 |
|
1106 |
Koha::CirculationRules->set_rules( |
1214 |
Koha::CirculationRules->set_rules( |
1107 |
{ |
1215 |
{ |
Lines 1110-1129
subtest 'reserves.item_level_hold' => sub {
Link Here
|
1110 |
itemtype => undef, |
1218 |
itemtype => undef, |
1111 |
rules => { |
1219 |
rules => { |
1112 |
reservesallowed => 25, |
1220 |
reservesallowed => 25, |
1113 |
opacitemholds => 'N', |
1221 |
opacitemholds => 'N', |
1114 |
} |
1222 |
} |
1115 |
} |
1223 |
} |
1116 |
); |
1224 |
); |
1117 |
|
1225 |
|
1118 |
$canreserve = C4::Reserves::CanBookBeReserved( $patron->id, $item->biblionumber ); |
1226 |
$canreserve = C4::Reserves::CanBookBeReserved( $patron->id, $item->biblionumber ); |
1119 |
|
1227 |
|
1120 |
is( $canreserve->{status}, 'OK', |
1228 |
is( |
1121 |
'record-level holds should be possible with opacitemholds set to "No"' ); |
1229 |
$canreserve->{status}, 'OK', |
|
|
1230 |
'record-level holds should be possible with opacitemholds set to "No"' |
1231 |
); |
1122 |
|
1232 |
|
1123 |
$canreserve = C4::Reserves::CanItemBeReserved( $patron, $item ); |
1233 |
$canreserve = C4::Reserves::CanItemBeReserved( $patron, $item ); |
1124 |
|
1234 |
|
1125 |
is( $canreserve->{status}, 'recordHoldsOnly', |
1235 |
is( |
1126 |
'item-level holds should not be possible with opacitemholds set to "No"' ); |
1236 |
$canreserve->{status}, 'recordHoldsOnly', |
|
|
1237 |
'item-level holds should not be possible with opacitemholds set to "No"' |
1238 |
); |
1127 |
|
1239 |
|
1128 |
Koha::CirculationRules->set_rules( |
1240 |
Koha::CirculationRules->set_rules( |
1129 |
{ |
1241 |
{ |
Lines 1132-1151
subtest 'reserves.item_level_hold' => sub {
Link Here
|
1132 |
itemtype => undef, |
1244 |
itemtype => undef, |
1133 |
rules => { |
1245 |
rules => { |
1134 |
reservesallowed => 25, |
1246 |
reservesallowed => 25, |
1135 |
opacitemholds => 'Y', |
1247 |
opacitemholds => 'Y', |
1136 |
} |
1248 |
} |
1137 |
} |
1249 |
} |
1138 |
); |
1250 |
); |
1139 |
|
1251 |
|
1140 |
$canreserve = C4::Reserves::CanBookBeReserved( $patron->id, $item->biblionumber ); |
1252 |
$canreserve = C4::Reserves::CanBookBeReserved( $patron->id, $item->biblionumber ); |
1141 |
|
1253 |
|
1142 |
is( $canreserve->{status}, 'OK', |
1254 |
is( |
1143 |
'record-level holds should be possible with opacitemholds set to "Yes"' ); |
1255 |
$canreserve->{status}, 'OK', |
|
|
1256 |
'record-level holds should be possible with opacitemholds set to "Yes"' |
1257 |
); |
1144 |
|
1258 |
|
1145 |
$canreserve = C4::Reserves::CanItemBeReserved( $patron, $item ); |
1259 |
$canreserve = C4::Reserves::CanItemBeReserved( $patron, $item ); |
1146 |
|
1260 |
|
1147 |
is( $canreserve->{status}, 'OK', |
1261 |
is( |
1148 |
'item-level holds should be possible with opacitemholds set to "Yes"' ); |
1262 |
$canreserve->{status}, 'OK', |
|
|
1263 |
'item-level holds should be possible with opacitemholds set to "Yes"' |
1264 |
); |
1149 |
}; |
1265 |
}; |
1150 |
|
1266 |
|
1151 |
subtest 'test opacitemholds rules in staff context' => sub { |
1267 |
subtest 'test opacitemholds rules in staff context' => sub { |
Lines 1159-1188
subtest 'reserves.item_level_hold' => sub {
Link Here
|
1159 |
itemtype => undef, |
1275 |
itemtype => undef, |
1160 |
rules => { |
1276 |
rules => { |
1161 |
reservesallowed => 25, |
1277 |
reservesallowed => 25, |
1162 |
opacitemholds => 'N', |
1278 |
opacitemholds => 'N', |
1163 |
} |
1279 |
} |
1164 |
} |
1280 |
} |
1165 |
); |
1281 |
); |
1166 |
|
1282 |
|
1167 |
my $canreserve = C4::Reserves::CanBookBeReserved( $patron->id, $item->biblionumber ); |
1283 |
my $canreserve = C4::Reserves::CanBookBeReserved( $patron->id, $item->biblionumber ); |
1168 |
|
1284 |
|
1169 |
is( $canreserve->{status}, 'OK', |
1285 |
is( |
1170 |
'record-level holds should be possible with opacitemholds set to "No"' ); |
1286 |
$canreserve->{status}, 'OK', |
|
|
1287 |
'record-level holds should be possible with opacitemholds set to "No"' |
1288 |
); |
1171 |
|
1289 |
|
1172 |
$canreserve = C4::Reserves::CanItemBeReserved( $patron, $item ); |
1290 |
$canreserve = C4::Reserves::CanItemBeReserved( $patron, $item ); |
1173 |
|
1291 |
|
1174 |
is( $canreserve->{status}, 'OK', |
1292 |
is( |
1175 |
'item-level holds should still be possible in staff context, even with opacitemholds set to "No"' ); |
1293 |
$canreserve->{status}, 'OK', |
|
|
1294 |
'item-level holds should still be possible in staff context, even with opacitemholds set to "No"' |
1295 |
); |
1176 |
}; |
1296 |
}; |
1177 |
|
1297 |
|
1178 |
Koha::CirculationRules->set_rules( |
1298 |
Koha::CirculationRules->set_rules( |
1179 |
{ |
1299 |
{ |
1180 |
branchcode => undef, |
1300 |
branchcode => undef, |
1181 |
categorycode => undef, |
1301 |
categorycode => undef, |
1182 |
itemtype => undef, |
1302 |
itemtype => undef, |
1183 |
rules => { |
1303 |
rules => { |
1184 |
opacitemholds => undef, |
1304 |
opacitemholds => undef, |
1185 |
} |
1305 |
} |
1186 |
} |
1306 |
} |
1187 |
); |
1307 |
); |
1188 |
}; |
1308 |
}; |
Lines 1193-1203
subtest 'MoveReserve additional test' => sub {
Link Here
|
1193 |
|
1313 |
|
1194 |
# Create the items and patrons we need |
1314 |
# Create the items and patrons we need |
1195 |
my $biblio = $builder->build_sample_biblio(); |
1315 |
my $biblio = $builder->build_sample_biblio(); |
1196 |
my $itype = $builder->build_object({ class => "Koha::ItemTypes", value => { notforloan => 0 } }); |
1316 |
my $itype = $builder->build_object( { class => "Koha::ItemTypes", value => { notforloan => 0 } } ); |
1197 |
my $item_1 = $builder->build_sample_item({ biblionumber => $biblio->biblionumber,notforloan => 0, itype => $itype->itemtype }); |
1317 |
my $item_1 = $builder->build_sample_item( |
1198 |
my $item_2 = $builder->build_sample_item({ biblionumber => $biblio->biblionumber, notforloan => 0, itype => $itype->itemtype }); |
1318 |
{ biblionumber => $biblio->biblionumber, notforloan => 0, itype => $itype->itemtype } ); |
1199 |
my $patron_1 = $builder->build_object({ class => "Koha::Patrons" }); |
1319 |
my $item_2 = $builder->build_sample_item( |
1200 |
my $patron_2 = $builder->build_object({ class => "Koha::Patrons" }); |
1320 |
{ biblionumber => $biblio->biblionumber, notforloan => 0, itype => $itype->itemtype } ); |
|
|
1321 |
my $patron_1 = $builder->build_object( { class => "Koha::Patrons" } ); |
1322 |
my $patron_2 = $builder->build_object( { class => "Koha::Patrons" } ); |
1201 |
|
1323 |
|
1202 |
# Place a hold on the title for both patrons |
1324 |
# Place a hold on the title for both patrons |
1203 |
my $reserve_1 = AddReserve( |
1325 |
my $reserve_1 = AddReserve( |
Lines 1218-1233
subtest 'MoveReserve additional test' => sub {
Link Here
|
1218 |
itemnumber => $item_1->itemnumber, |
1340 |
itemnumber => $item_1->itemnumber, |
1219 |
} |
1341 |
} |
1220 |
); |
1342 |
); |
1221 |
is($patron_1->holds->next()->reserve_id, $reserve_1, "The 1st patron has a hold"); |
1343 |
is( $patron_1->holds->next()->reserve_id, $reserve_1, "The 1st patron has a hold" ); |
1222 |
is($patron_2->holds->next()->reserve_id, $reserve_2, "The 2nd patron has a hold"); |
1344 |
is( $patron_2->holds->next()->reserve_id, $reserve_2, "The 2nd patron has a hold" ); |
1223 |
|
1345 |
|
1224 |
# Fake the holds queue |
1346 |
# Fake the holds queue |
1225 |
$dbh->do(q{INSERT INTO hold_fill_targets VALUES (?, ?, ?, ?, ?,?)},undef,($patron_1->borrowernumber,$biblio->biblionumber,$item_1->itemnumber,$item_1->homebranch,0,$reserve_1)); |
1347 |
$dbh->do( |
|
|
1348 |
q{INSERT INTO hold_fill_targets VALUES (?, ?, ?, ?, ?,?)}, undef, |
1349 |
( $patron_1->borrowernumber, $biblio->biblionumber, $item_1->itemnumber, $item_1->homebranch, 0, $reserve_1 ) |
1350 |
); |
1226 |
|
1351 |
|
1227 |
# The 2nd hold should be filed even if the item is preselected for the first hold |
1352 |
# The 2nd hold should be filed even if the item is preselected for the first hold |
1228 |
MoveReserve($item_1->itemnumber,$patron_2->borrowernumber); |
1353 |
MoveReserve( $item_1->itemnumber, $patron_2->borrowernumber ); |
1229 |
is($patron_2->holds->count, 0, "The 2nd patrons no longer has a hold"); |
1354 |
is( $patron_2->holds->count, 0, "The 2nd patrons no longer has a hold" ); |
1230 |
is($patron_2->old_holds->next()->reserve_id, $reserve_2, "The 2nd patrons hold was filled and moved to old holds"); |
1355 |
is( |
|
|
1356 |
$patron_2->old_holds->next()->reserve_id, $reserve_2, |
1357 |
"The 2nd patrons hold was filled and moved to old holds" |
1358 |
); |
1231 |
|
1359 |
|
1232 |
}; |
1360 |
}; |
1233 |
|
1361 |
|
Lines 1238-1246
subtest 'RevertWaitingStatus' => sub {
Link Here
|
1238 |
# Create the items and patrons we need |
1366 |
# Create the items and patrons we need |
1239 |
my $biblio = $builder->build_sample_biblio(); |
1367 |
my $biblio = $builder->build_sample_biblio(); |
1240 |
my $library = $builder->build_object( { class => 'Koha::Libraries' } ); |
1368 |
my $library = $builder->build_object( { class => 'Koha::Libraries' } ); |
1241 |
my $itype = $builder->build_object( |
1369 |
my $itype = $builder->build_object( { class => "Koha::ItemTypes", value => { notforloan => 0 } } ); |
1242 |
{ class => "Koha::ItemTypes", value => { notforloan => 0 } } ); |
1370 |
my $item_1 = $builder->build_sample_item( |
1243 |
my $item_1 = $builder->build_sample_item( |
|
|
1244 |
{ |
1371 |
{ |
1245 |
biblionumber => $biblio->biblionumber, |
1372 |
biblionumber => $biblio->biblionumber, |
1246 |
itype => $itype->itemtype, |
1373 |
itype => $itype->itemtype, |
Lines 1254-1263
subtest 'RevertWaitingStatus' => sub {
Link Here
|
1254 |
|
1381 |
|
1255 |
# Place a hold on the title for both patrons |
1382 |
# Place a hold on the title for both patrons |
1256 |
my $priority = 1; |
1383 |
my $priority = 1; |
1257 |
my $hold_1 = place_item_hold( $patron_1, $item_1, $library, $priority ); |
1384 |
my $hold_1 = place_item_hold( $patron_1, $item_1, $library, $priority ); |
1258 |
my $hold_2 = place_item_hold( $patron_2, $item_1, $library, $priority ); |
1385 |
my $hold_2 = place_item_hold( $patron_2, $item_1, $library, $priority ); |
1259 |
my $hold_3 = place_item_hold( $patron_3, $item_1, $library, $priority ); |
1386 |
my $hold_3 = place_item_hold( $patron_3, $item_1, $library, $priority ); |
1260 |
my $hold_4 = place_item_hold( $patron_4, $item_1, $library, $priority ); |
1387 |
my $hold_4 = place_item_hold( $patron_4, $item_1, $library, $priority ); |
1261 |
|
1388 |
|
1262 |
$hold_1->set_waiting; |
1389 |
$hold_1->set_waiting; |
1263 |
AddIssue( $patron_3, $item_1->barcode, undef, 'revert' ); |
1390 |
AddIssue( $patron_3, $item_1->barcode, undef, 'revert' ); |
Lines 1278-1284
subtest 'CheckReserves additional tests' => sub {
Link Here
|
1278 |
|
1405 |
|
1279 |
plan tests => 8; |
1406 |
plan tests => 8; |
1280 |
|
1407 |
|
1281 |
my $item = $builder->build_sample_item; |
1408 |
my $item = $builder->build_sample_item; |
1282 |
my $reserve1 = $builder->build_object( |
1409 |
my $reserve1 = $builder->build_object( |
1283 |
{ |
1410 |
{ |
1284 |
class => "Koha::Holds", |
1411 |
class => "Koha::Holds", |
Lines 1340-1379
subtest 'CheckReserves additional tests' => sub {
Link Here
|
1340 |
} |
1467 |
} |
1341 |
); |
1468 |
); |
1342 |
|
1469 |
|
1343 |
ModReserveAffect( $item->itemnumber, $reserve1->borrowernumber, 1, |
1470 |
ModReserveAffect( |
1344 |
$reserve1->reserve_id ); |
1471 |
$item->itemnumber, $reserve1->borrowernumber, 1, |
1345 |
my ( $status, $matched_reserve, $possible_reserves ) = |
1472 |
$reserve1->reserve_id |
1346 |
CheckReserves( $item ); |
1473 |
); |
|
|
1474 |
my ( $status, $matched_reserve, $possible_reserves ) = CheckReserves($item); |
1347 |
|
1475 |
|
1348 |
is( $status, 'Transferred', "We found a reserve" ); |
1476 |
is( $status, 'Transferred', "We found a reserve" ); |
1349 |
is( $matched_reserve->{reserve_id}, |
1477 |
is( |
1350 |
$reserve1->reserve_id, "We got the Transit reserve" ); |
1478 |
$matched_reserve->{reserve_id}, |
|
|
1479 |
$reserve1->reserve_id, "We got the Transit reserve" |
1480 |
); |
1351 |
is( scalar @$possible_reserves, 2, 'We do get both reserves' ); |
1481 |
is( scalar @$possible_reserves, 2, 'We do get both reserves' ); |
1352 |
|
1482 |
|
1353 |
my $patron_B = $builder->build_object({ class => "Koha::Patrons" }); |
1483 |
my $patron_B = $builder->build_object( { class => "Koha::Patrons" } ); |
1354 |
my $item_A = $builder->build_sample_item; |
1484 |
my $item_A = $builder->build_sample_item; |
1355 |
my $item_B = $builder->build_sample_item({ |
1485 |
my $item_B = $builder->build_sample_item( |
1356 |
homebranch => $patron_B->branchcode, |
1486 |
{ |
1357 |
biblionumber => $item_A->biblionumber, |
1487 |
homebranch => $patron_B->branchcode, |
1358 |
itype => $item_A->itype |
1488 |
biblionumber => $item_A->biblionumber, |
1359 |
}); |
1489 |
itype => $item_A->itype |
|
|
1490 |
} |
1491 |
); |
1360 |
Koha::CirculationRules->set_rules( |
1492 |
Koha::CirculationRules->set_rules( |
1361 |
{ |
1493 |
{ |
1362 |
branchcode => undef, |
1494 |
branchcode => undef, |
1363 |
categorycode => undef, |
1495 |
categorycode => undef, |
1364 |
itemtype => $item_A->itype, |
1496 |
itemtype => $item_A->itype, |
1365 |
rules => { |
1497 |
rules => { |
1366 |
reservesallowed => 25, |
1498 |
reservesallowed => 25, |
1367 |
holds_per_record => 1, |
1499 |
holds_per_record => 1, |
1368 |
} |
1500 |
} |
1369 |
} |
1501 |
} |
1370 |
); |
1502 |
); |
1371 |
Koha::CirculationRules->set_rule({ |
1503 |
Koha::CirculationRules->set_rule( |
1372 |
branchcode => undef, |
1504 |
{ |
1373 |
itemtype => $item_A->itype, |
1505 |
branchcode => undef, |
1374 |
rule_name => 'holdallowed', |
1506 |
itemtype => $item_A->itype, |
1375 |
rule_value => 'from_home_library' |
1507 |
rule_name => 'holdallowed', |
1376 |
}); |
1508 |
rule_value => 'from_home_library' |
|
|
1509 |
} |
1510 |
); |
1377 |
my $reserve_id = AddReserve( |
1511 |
my $reserve_id = AddReserve( |
1378 |
{ |
1512 |
{ |
1379 |
branchcode => $patron_B->branchcode, |
1513 |
branchcode => $patron_B->branchcode, |
Lines 1384-1415
subtest 'CheckReserves additional tests' => sub {
Link Here
|
1384 |
} |
1518 |
} |
1385 |
); |
1519 |
); |
1386 |
|
1520 |
|
1387 |
ok( $reserve_id, "We can place a record level hold because one item is owned by patron's home library"); |
1521 |
ok( $reserve_id, "We can place a record level hold because one item is owned by patron's home library" ); |
1388 |
t::lib::Mocks::mock_preference('ReservesControlBranch', 'ItemHomeLibrary'); |
1522 |
t::lib::Mocks::mock_preference( 'ReservesControlBranch', 'ItemHomeLibrary' ); |
1389 |
( $status, $matched_reserve, $possible_reserves ) = CheckReserves( $item_A ); |
1523 |
( $status, $matched_reserve, $possible_reserves ) = CheckReserves($item_A); |
1390 |
is( $status, "", "We do not fill the hold with item A because it is not from the patron's homebranch"); |
1524 |
is( $status, "", "We do not fill the hold with item A because it is not from the patron's homebranch" ); |
1391 |
Koha::CirculationRules->set_rule({ |
1525 |
Koha::CirculationRules->set_rule( |
1392 |
branchcode => $item_A->homebranch, |
1526 |
{ |
1393 |
itemtype => $item_A->itype, |
1527 |
branchcode => $item_A->homebranch, |
1394 |
rule_name => 'holdallowed', |
1528 |
itemtype => $item_A->itype, |
1395 |
rule_value => 'from_any_library' |
1529 |
rule_name => 'holdallowed', |
1396 |
}); |
1530 |
rule_value => 'from_any_library' |
1397 |
( $status, $matched_reserve, $possible_reserves ) = CheckReserves( $item_A ); |
1531 |
} |
1398 |
is( $status, "Reserved", "We fill the hold with item A because item's branch rule says allow any"); |
1532 |
); |
1399 |
|
1533 |
( $status, $matched_reserve, $possible_reserves ) = CheckReserves($item_A); |
|
|
1534 |
is( $status, "Reserved", "We fill the hold with item A because item's branch rule says allow any" ); |
1400 |
|
1535 |
|
1401 |
# Changing the control branch should change only the rule we get |
1536 |
# Changing the control branch should change only the rule we get |
1402 |
t::lib::Mocks::mock_preference('ReservesControlBranch', 'PatronLibrary'); |
1537 |
t::lib::Mocks::mock_preference( 'ReservesControlBranch', 'PatronLibrary' ); |
1403 |
( $status, $matched_reserve, $possible_reserves ) = CheckReserves( $item_A ); |
1538 |
( $status, $matched_reserve, $possible_reserves ) = CheckReserves($item_A); |
1404 |
is( $status, "", "We do not fill the hold with item A because it is not from the patron's homebranch"); |
1539 |
is( $status, "", "We do not fill the hold with item A because it is not from the patron's homebranch" ); |
1405 |
Koha::CirculationRules->set_rule({ |
1540 |
Koha::CirculationRules->set_rule( |
1406 |
branchcode => $patron_B->branchcode, |
1541 |
{ |
1407 |
itemtype => $item_A->itype, |
1542 |
branchcode => $patron_B->branchcode, |
1408 |
rule_name => 'holdallowed', |
1543 |
itemtype => $item_A->itype, |
1409 |
rule_value => 'from_any_library' |
1544 |
rule_name => 'holdallowed', |
1410 |
}); |
1545 |
rule_value => 'from_any_library' |
1411 |
( $status, $matched_reserve, $possible_reserves ) = CheckReserves( $item_A ); |
1546 |
} |
1412 |
is( $status, "Reserved", "We fill the hold with item A because patron's branch rule says allow any"); |
1547 |
); |
|
|
1548 |
( $status, $matched_reserve, $possible_reserves ) = CheckReserves($item_A); |
1549 |
is( $status, "Reserved", "We fill the hold with item A because patron's branch rule says allow any" ); |
1413 |
|
1550 |
|
1414 |
}; |
1551 |
}; |
1415 |
|
1552 |
|
Lines 1419-1464
subtest 'AllowHoldOnPatronPossession test' => sub {
Link Here
|
1419 |
|
1556 |
|
1420 |
# Create the items and patrons we need |
1557 |
# Create the items and patrons we need |
1421 |
my $biblio = $builder->build_sample_biblio(); |
1558 |
my $biblio = $builder->build_sample_biblio(); |
1422 |
my $itype = $builder->build_object({ class => "Koha::ItemTypes", value => { notforloan => 0 } }); |
1559 |
my $itype = $builder->build_object( { class => "Koha::ItemTypes", value => { notforloan => 0 } } ); |
1423 |
my $item = $builder->build_sample_item({ biblionumber => $biblio->biblionumber,notforloan => 0, itype => $itype->itemtype }); |
1560 |
my $item = $builder->build_sample_item( |
1424 |
my $patron = $builder->build_object({ class => "Koha::Patrons", |
1561 |
{ biblionumber => $biblio->biblionumber, notforloan => 0, itype => $itype->itemtype } ); |
1425 |
value => { branchcode => $item->homebranch }}); |
1562 |
my $patron = $builder->build_object( |
1426 |
|
1563 |
{ |
1427 |
C4::Circulation::AddIssue($patron, |
1564 |
class => "Koha::Patrons", |
1428 |
$item->barcode); |
1565 |
value => { branchcode => $item->homebranch } |
1429 |
t::lib::Mocks::mock_preference('AllowHoldsOnPatronsPossessions', 0); |
1566 |
} |
1430 |
|
1567 |
); |
1431 |
is(C4::Reserves::CanBookBeReserved($patron->borrowernumber, |
1568 |
|
1432 |
$item->biblionumber)->{status}, |
1569 |
C4::Circulation::AddIssue( |
1433 |
'alreadypossession', |
1570 |
$patron, |
1434 |
'Patron cannot place hold on a book loaned to itself'); |
1571 |
$item->barcode |
1435 |
|
1572 |
); |
1436 |
is(C4::Reserves::CanItemBeReserved( $patron, $item )->{status}, |
1573 |
t::lib::Mocks::mock_preference( 'AllowHoldsOnPatronsPossessions', 0 ); |
1437 |
'alreadypossession', |
1574 |
|
1438 |
'Patron cannot place hold on an item loaned to itself'); |
1575 |
is( |
1439 |
|
1576 |
C4::Reserves::CanBookBeReserved( |
1440 |
t::lib::Mocks::mock_preference('AllowHoldsOnPatronsPossessions', 1); |
1577 |
$patron->borrowernumber, |
1441 |
|
1578 |
$item->biblionumber |
1442 |
is(C4::Reserves::CanBookBeReserved($patron->borrowernumber, |
1579 |
)->{status}, |
1443 |
$item->biblionumber)->{status}, |
1580 |
'alreadypossession', |
1444 |
'OK', |
1581 |
'Patron cannot place hold on a book loaned to itself' |
1445 |
'Patron can place hold on a book loaned to itself'); |
1582 |
); |
1446 |
|
1583 |
|
1447 |
is(C4::Reserves::CanItemBeReserved( $patron, $item )->{status}, |
1584 |
is( |
1448 |
'OK', |
1585 |
C4::Reserves::CanItemBeReserved( $patron, $item )->{status}, |
1449 |
'Patron can place hold on an item loaned to itself'); |
1586 |
'alreadypossession', |
|
|
1587 |
'Patron cannot place hold on an item loaned to itself' |
1588 |
); |
1589 |
|
1590 |
t::lib::Mocks::mock_preference( 'AllowHoldsOnPatronsPossessions', 1 ); |
1591 |
|
1592 |
is( |
1593 |
C4::Reserves::CanBookBeReserved( |
1594 |
$patron->borrowernumber, |
1595 |
$item->biblionumber |
1596 |
)->{status}, |
1597 |
'OK', |
1598 |
'Patron can place hold on a book loaned to itself' |
1599 |
); |
1600 |
|
1601 |
is( |
1602 |
C4::Reserves::CanItemBeReserved( $patron, $item )->{status}, |
1603 |
'OK', |
1604 |
'Patron can place hold on an item loaned to itself' |
1605 |
); |
1450 |
}; |
1606 |
}; |
1451 |
|
1607 |
|
1452 |
subtest 'MergeHolds' => sub { |
1608 |
subtest 'MergeHolds' => sub { |
1453 |
|
1609 |
|
1454 |
plan tests => 1; |
1610 |
plan tests => 1; |
1455 |
|
1611 |
|
1456 |
my $biblio_1 = $builder->build_sample_biblio(); |
1612 |
my $biblio_1 = $builder->build_sample_biblio(); |
1457 |
my $biblio_2 = $builder->build_sample_biblio(); |
1613 |
my $biblio_2 = $builder->build_sample_biblio(); |
1458 |
my $library = $builder->build_object( { class => 'Koha::Libraries' } ); |
1614 |
my $library = $builder->build_object( { class => 'Koha::Libraries' } ); |
1459 |
my $itype = $builder->build_object( |
1615 |
my $itype = $builder->build_object( { class => "Koha::ItemTypes", value => { notforloan => 0 } } ); |
1460 |
{ class => "Koha::ItemTypes", value => { notforloan => 0 } } ); |
1616 |
my $item_1 = $builder->build_sample_item( |
1461 |
my $item_1 = $builder->build_sample_item( |
|
|
1462 |
{ |
1617 |
{ |
1463 |
biblionumber => $biblio_1->biblionumber, |
1618 |
biblionumber => $biblio_1->biblionumber, |
1464 |
itype => $itype->itemtype, |
1619 |
itype => $itype->itemtype, |
Lines 1472-1478
subtest 'MergeHolds' => sub {
Link Here
|
1472 |
place_item_hold( $patron_1, $item_1, $library, $priority ); |
1627 |
place_item_hold( $patron_1, $item_1, $library, $priority ); |
1473 |
|
1628 |
|
1474 |
# Move and make sure hold is now on $biblio_2 |
1629 |
# Move and make sure hold is now on $biblio_2 |
1475 |
C4::Reserves::MergeHolds($dbh, $biblio_2->biblionumber, $biblio_1->biblionumber); |
1630 |
C4::Reserves::MergeHolds( $dbh, $biblio_2->biblionumber, $biblio_1->biblionumber ); |
1476 |
is( $biblio_2->holds->count, 1, 'Hold has been transferred' ); |
1631 |
is( $biblio_2->holds->count, 1, 'Hold has been transferred' ); |
1477 |
}; |
1632 |
}; |
1478 |
|
1633 |
|
Lines 1480-1486
subtest 'ModReserveAffect logging' => sub {
Link Here
|
1480 |
|
1635 |
|
1481 |
plan tests => 4; |
1636 |
plan tests => 4; |
1482 |
|
1637 |
|
1483 |
my $item = $builder->build_sample_item; |
1638 |
my $item = $builder->build_sample_item; |
1484 |
my $patron = $builder->build_object( |
1639 |
my $patron = $builder->build_object( |
1485 |
{ |
1640 |
{ |
1486 |
class => "Koha::Patrons", |
1641 |
class => "Koha::Patrons", |
Lines 1488-1495
subtest 'ModReserveAffect logging' => sub {
Link Here
|
1488 |
} |
1643 |
} |
1489 |
); |
1644 |
); |
1490 |
|
1645 |
|
1491 |
t::lib::Mocks::mock_userenv({ patron => $patron }); |
1646 |
t::lib::Mocks::mock_userenv( { patron => $patron } ); |
1492 |
t::lib::Mocks::mock_preference('HoldsLog', 1); |
1647 |
t::lib::Mocks::mock_preference( 'HoldsLog', 1 ); |
1493 |
|
1648 |
|
1494 |
my $reserve_id = AddReserve( |
1649 |
my $reserve_id = AddReserve( |
1495 |
{ |
1650 |
{ |
Lines 1501-1507
subtest 'ModReserveAffect logging' => sub {
Link Here
|
1501 |
} |
1656 |
} |
1502 |
); |
1657 |
); |
1503 |
|
1658 |
|
1504 |
my $hold = Koha::Holds->find($reserve_id); |
1659 |
my $hold = Koha::Holds->find($reserve_id); |
1505 |
my $previous_timestamp = '1970-01-01 12:34:56'; |
1660 |
my $previous_timestamp = '1970-01-01 12:34:56'; |
1506 |
$hold->timestamp($previous_timestamp)->store; |
1661 |
$hold->timestamp($previous_timestamp)->store; |
1507 |
|
1662 |
|
Lines 1519-1541
subtest 'ModReserveAffect logging' => sub {
Link Here
|
1519 |
ok( $hold->is_waiting, 'Hold has been set waiting' ); |
1674 |
ok( $hold->is_waiting, 'Hold has been set waiting' ); |
1520 |
isnt( $hold->timestamp, $previous_timestamp, 'The timestamp has been modified' ); |
1675 |
isnt( $hold->timestamp, $previous_timestamp, 'The timestamp has been modified' ); |
1521 |
|
1676 |
|
1522 |
my $log = Koha::ActionLogs->search({ module => 'HOLDS', action => 'MODIFY', object => $hold->reserve_id })->next; |
1677 |
my $log = Koha::ActionLogs->search( { module => 'HOLDS', action => 'MODIFY', object => $hold->reserve_id } )->next; |
1523 |
my $expected = sprintf q{'timestamp' => '%s'}, $hold->timestamp; |
1678 |
my $expected = sprintf q{'timestamp' => '%s'}, $hold->timestamp; |
1524 |
like( $log->info, qr{$expected}, 'Timestamp logged is the current one' ); |
1679 |
like( $log->info, qr{$expected}, 'Timestamp logged is the current one' ); |
1525 |
}; |
1680 |
}; |
1526 |
|
1681 |
|
1527 |
sub count_hold_print_messages { |
1682 |
sub count_hold_print_messages { |
1528 |
my $message_count = $dbh->selectall_arrayref(q{ |
1683 |
my $message_count = $dbh->selectall_arrayref( |
|
|
1684 |
q{ |
1529 |
SELECT COUNT(*) |
1685 |
SELECT COUNT(*) |
1530 |
FROM message_queue |
1686 |
FROM message_queue |
1531 |
WHERE letter_code = 'HOLD' |
1687 |
WHERE letter_code = 'HOLD' |
1532 |
AND message_transport_type = 'print' |
1688 |
AND message_transport_type = 'print' |
1533 |
}); |
1689 |
} |
|
|
1690 |
); |
1534 |
return $message_count->[0]->[0]; |
1691 |
return $message_count->[0]->[0]; |
1535 |
} |
1692 |
} |
1536 |
|
1693 |
|
1537 |
sub place_item_hold { |
1694 |
sub place_item_hold { |
1538 |
my ($patron,$item,$library,$priority) = @_; |
1695 |
my ( $patron, $item, $library, $priority ) = @_; |
1539 |
|
1696 |
|
1540 |
my $hold_id = C4::Reserves::AddReserve( |
1697 |
my $hold_id = C4::Reserves::AddReserve( |
1541 |
{ |
1698 |
{ |
Lines 1620-1633
subtest 'AddReserve() tests' => sub {
Link Here
|
1620 |
my $biblio = $builder->build_sample_biblio; |
1777 |
my $biblio = $builder->build_sample_biblio; |
1621 |
|
1778 |
|
1622 |
my $mock = Test::MockModule->new('Koha::BackgroundJob::BatchUpdateBiblioHoldsQueue'); |
1779 |
my $mock = Test::MockModule->new('Koha::BackgroundJob::BatchUpdateBiblioHoldsQueue'); |
1623 |
$mock->mock( 'enqueue', sub { |
1780 |
$mock->mock( |
1624 |
my ( $self, $args ) = @_; |
1781 |
'enqueue', |
1625 |
is_deeply( |
1782 |
sub { |
1626 |
$args->{biblio_ids}, |
1783 |
my ( $self, $args ) = @_; |
1627 |
[ $biblio->id ], |
1784 |
is_deeply( |
1628 |
"AddReserve triggers a holds queue update for the related biblio" |
1785 |
$args->{biblio_ids}, |
1629 |
); |
1786 |
[ $biblio->id ], |
1630 |
} ); |
1787 |
"AddReserve triggers a holds queue update for the related biblio" |
|
|
1788 |
); |
1789 |
} |
1790 |
); |
1631 |
|
1791 |
|
1632 |
t::lib::Mocks::mock_preference( 'RealTimeHoldsQueue', 1 ); |
1792 |
t::lib::Mocks::mock_preference( 'RealTimeHoldsQueue', 1 ); |
1633 |
|
1793 |
|
Lines 1661-1671
subtest 'AlterPriorty() tests' => sub {
Link Here
|
1661 |
|
1821 |
|
1662 |
$schema->storage->txn_begin; |
1822 |
$schema->storage->txn_begin; |
1663 |
|
1823 |
|
1664 |
my $library = $builder->build_object({ class => 'Koha::Libraries' }); |
1824 |
my $library = $builder->build_object( { class => 'Koha::Libraries' } ); |
1665 |
my $patron_1 = $builder->build_object({ class => 'Koha::Patrons' }); |
1825 |
my $patron_1 = $builder->build_object( { class => 'Koha::Patrons' } ); |
1666 |
my $patron_2 = $builder->build_object({ class => 'Koha::Patrons' }); |
1826 |
my $patron_2 = $builder->build_object( { class => 'Koha::Patrons' } ); |
1667 |
my $patron_3 = $builder->build_object({ class => 'Koha::Patrons' }); |
1827 |
my $patron_3 = $builder->build_object( { class => 'Koha::Patrons' } ); |
1668 |
my $biblio = $builder->build_sample_biblio; |
1828 |
my $biblio = $builder->build_sample_biblio; |
1669 |
|
1829 |
|
1670 |
my $reserve_id = AddReserve( |
1830 |
my $reserve_id = AddReserve( |
1671 |
{ |
1831 |
{ |
Lines 1690-1703
subtest 'AlterPriorty() tests' => sub {
Link Here
|
1690 |
); |
1850 |
); |
1691 |
|
1851 |
|
1692 |
my $mock = Test::MockModule->new('Koha::BackgroundJob::BatchUpdateBiblioHoldsQueue'); |
1852 |
my $mock = Test::MockModule->new('Koha::BackgroundJob::BatchUpdateBiblioHoldsQueue'); |
1693 |
$mock->mock( 'enqueue', sub { |
1853 |
$mock->mock( |
1694 |
my ( $self, $args ) = @_; |
1854 |
'enqueue', |
1695 |
is_deeply( |
1855 |
sub { |
1696 |
$args->{biblio_ids}, |
1856 |
my ( $self, $args ) = @_; |
1697 |
[ $biblio->id ], |
1857 |
is_deeply( |
1698 |
"AlterPriority triggers a holds queue update for the related biblio" |
1858 |
$args->{biblio_ids}, |
1699 |
); |
1859 |
[ $biblio->id ], |
1700 |
} ); |
1860 |
"AlterPriority triggers a holds queue update for the related biblio" |
|
|
1861 |
); |
1862 |
} |
1863 |
); |
1701 |
|
1864 |
|
1702 |
t::lib::Mocks::mock_preference( 'RealTimeHoldsQueue', 1 ); |
1865 |
t::lib::Mocks::mock_preference( 'RealTimeHoldsQueue', 1 ); |
1703 |
|
1866 |
|
Lines 1705-1711
subtest 'AlterPriorty() tests' => sub {
Link Here
|
1705 |
|
1868 |
|
1706 |
my $hold = Koha::Holds->find($reserve_id); |
1869 |
my $hold = Koha::Holds->find($reserve_id); |
1707 |
|
1870 |
|
1708 |
is($hold->priority,3,'Successfully altered priority to bottom'); |
1871 |
is( $hold->priority, 3, 'Successfully altered priority to bottom' ); |
1709 |
|
1872 |
|
1710 |
t::lib::Mocks::mock_preference( 'RealTimeHoldsQueue', 0 ); |
1873 |
t::lib::Mocks::mock_preference( 'RealTimeHoldsQueue', 0 ); |
1711 |
|
1874 |
|
Lines 1720-1735
subtest 'CanBookBeReserved() tests' => sub {
Link Here
|
1720 |
|
1883 |
|
1721 |
$schema->storage->txn_begin; |
1884 |
$schema->storage->txn_begin; |
1722 |
|
1885 |
|
1723 |
my $library = $builder->build_object( |
1886 |
my $library = $builder->build_object( { class => 'Koha::Libraries', value => { pickup_location => 1 } } ); |
1724 |
{ class => 'Koha::Libraries', value => { pickup_location => 1 } } ); |
1887 |
my $patron = $builder->build_object( { class => 'Koha::Patrons' } ); |
1725 |
my $patron = $builder->build_object( { class => 'Koha::Patrons' } ); |
1888 |
my $itype = $builder->build_object( { class => 'Koha::ItemTypes' } ); |
1726 |
my $itype = $builder->build_object( { class => 'Koha::ItemTypes' } ); |
|
|
1727 |
|
1889 |
|
1728 |
my $biblio = $builder->build_sample_biblio(); |
1890 |
my $biblio = $builder->build_sample_biblio(); |
1729 |
my $item_1 = $builder->build_sample_item( |
1891 |
my $item_1 = $builder->build_sample_item( { biblionumber => $biblio->id, itype => $itype->id } ); |
1730 |
{ biblionumber => $biblio->id, itype => $itype->id } ); |
1892 |
my $item_2 = $builder->build_sample_item( { biblionumber => $biblio->id, itype => $itype->id } ); |
1731 |
my $item_2 = $builder->build_sample_item( |
|
|
1732 |
{ biblionumber => $biblio->id, itype => $itype->id } ); |
1733 |
|
1893 |
|
1734 |
Koha::CirculationRules->delete; |
1894 |
Koha::CirculationRules->delete; |
1735 |
Koha::CirculationRules->set_rules( |
1895 |
Koha::CirculationRules->set_rules( |
Lines 1765-1774
subtest 'CanBookBeReserved() tests' => sub {
Link Here
|
1765 |
|
1925 |
|
1766 |
## Limit on item type is 2, only one hold, success tests |
1926 |
## Limit on item type is 2, only one hold, success tests |
1767 |
|
1927 |
|
1768 |
my $res = CanBookBeReserved( $patron->id, $biblio->id, $library->id, |
1928 |
my $res = CanBookBeReserved( |
1769 |
{ itemtype => $itype->id } ); |
1929 |
$patron->id, $biblio->id, $library->id, |
1770 |
is_deeply( $res, { status => 'OK' }, |
1930 |
{ itemtype => $itype->id } |
1771 |
'Holds on itemtype limit not reached' ); |
1931 |
); |
|
|
1932 |
is_deeply( |
1933 |
$res, { status => 'OK' }, |
1934 |
'Holds on itemtype limit not reached' |
1935 |
); |
1772 |
|
1936 |
|
1773 |
# Add a second hold, biblio-level and item type-constrained |
1937 |
# Add a second hold, biblio-level and item type-constrained |
1774 |
C4::Reserves::AddReserve( |
1938 |
C4::Reserves::AddReserve( |
Lines 1783-1790
subtest 'CanBookBeReserved() tests' => sub {
Link Here
|
1783 |
|
1947 |
|
1784 |
## Limit on item type is 2, two holds, one of them biblio-level/item type-constrained |
1948 |
## Limit on item type is 2, two holds, one of them biblio-level/item type-constrained |
1785 |
|
1949 |
|
1786 |
$res = CanBookBeReserved( $patron->id, $biblio->id, $library->id, |
1950 |
$res = CanBookBeReserved( |
1787 |
{ itemtype => $itype->id } ); |
1951 |
$patron->id, $biblio->id, $library->id, |
|
|
1952 |
{ itemtype => $itype->id } |
1953 |
); |
1788 |
is_deeply( $res, { status => '' }, 'Holds on itemtype limit reached' ); |
1954 |
is_deeply( $res, { status => '' }, 'Holds on itemtype limit reached' ); |
1789 |
|
1955 |
|
1790 |
$schema->storage->txn_rollback; |
1956 |
$schema->storage->txn_rollback; |
Lines 1801-1812
subtest 'CanItemBeReserved() tests' => sub {
Link Here
|
1801 |
my $itype = $builder->build_object( { class => 'Koha::ItemTypes' } ); |
1967 |
my $itype = $builder->build_object( { class => 'Koha::ItemTypes' } ); |
1802 |
|
1968 |
|
1803 |
my $biblio = $builder->build_sample_biblio(); |
1969 |
my $biblio = $builder->build_sample_biblio(); |
1804 |
my $item_1 = $builder->build_sample_item({ biblionumber => $biblio->id, itype => $itype->id }); |
1970 |
my $item_1 = $builder->build_sample_item( { biblionumber => $biblio->id, itype => $itype->id } ); |
1805 |
my $item_2 = $builder->build_sample_item({ biblionumber => $biblio->id, itype => $itype->id }); |
1971 |
my $item_2 = $builder->build_sample_item( { biblionumber => $biblio->id, itype => $itype->id } ); |
1806 |
|
1972 |
|
1807 |
Koha::CirculationRules->delete; |
1973 |
Koha::CirculationRules->delete; |
1808 |
Koha::CirculationRules->set_rules( |
1974 |
Koha::CirculationRules->set_rules( |
1809 |
{ branchcode => undef, |
1975 |
{ |
|
|
1976 |
branchcode => undef, |
1810 |
categorycode => undef, |
1977 |
categorycode => undef, |
1811 |
itemtype => undef, |
1978 |
itemtype => undef, |
1812 |
rules => { |
1979 |
rules => { |
Lines 1815-1821
subtest 'CanItemBeReserved() tests' => sub {
Link Here
|
1815 |
} |
1982 |
} |
1816 |
); |
1983 |
); |
1817 |
Koha::CirculationRules->set_rules( |
1984 |
Koha::CirculationRules->set_rules( |
1818 |
{ branchcode => undef, |
1985 |
{ |
|
|
1986 |
branchcode => undef, |
1819 |
categorycode => undef, |
1987 |
categorycode => undef, |
1820 |
itemtype => $itype->id, |
1988 |
itemtype => $itype->id, |
1821 |
rules => { |
1989 |
rules => { |
Lines 1862-1885
subtest 'DefaultHoldExpiration tests' => sub {
Link Here
|
1862 |
plan tests => 2; |
2030 |
plan tests => 2; |
1863 |
$schema->storage->txn_begin; |
2031 |
$schema->storage->txn_begin; |
1864 |
|
2032 |
|
1865 |
t::lib::Mocks::mock_preference( 'DefaultHoldExpirationdate', 1 ); |
2033 |
t::lib::Mocks::mock_preference( 'DefaultHoldExpirationdate', 1 ); |
1866 |
t::lib::Mocks::mock_preference( 'DefaultHoldExpirationdatePeriod', 365 ); |
2034 |
t::lib::Mocks::mock_preference( 'DefaultHoldExpirationdatePeriod', 365 ); |
1867 |
t::lib::Mocks::mock_preference( 'DefaultHoldExpirationUnitOfTime', 'days;' ); |
2035 |
t::lib::Mocks::mock_preference( 'DefaultHoldExpirationUnitOfTime', 'days;' ); |
1868 |
|
2036 |
|
1869 |
my $patron = $builder->build_object( { class => 'Koha::Patrons' } ); |
2037 |
my $patron = $builder->build_object( { class => 'Koha::Patrons' } ); |
1870 |
my $item = $builder->build_sample_item(); |
2038 |
my $item = $builder->build_sample_item(); |
1871 |
|
2039 |
|
1872 |
my $reserve_id = AddReserve({ |
2040 |
my $reserve_id = AddReserve( |
1873 |
branchcode => $item->homebranch, |
2041 |
{ |
1874 |
borrowernumber => $patron->id, |
2042 |
branchcode => $item->homebranch, |
1875 |
biblionumber => $item->biblionumber, |
2043 |
borrowernumber => $patron->id, |
1876 |
}); |
2044 |
biblionumber => $item->biblionumber, |
|
|
2045 |
} |
2046 |
); |
1877 |
|
2047 |
|
1878 |
my $today = dt_from_string(); |
2048 |
my $today = dt_from_string(); |
1879 |
my $hold = Koha::Holds->find( $reserve_id ); |
2049 |
my $hold = Koha::Holds->find($reserve_id); |
1880 |
|
2050 |
|
1881 |
is( $hold->reservedate, $today->ymd, "Hold created today" ); |
2051 |
is( $hold->reservedate, $today->ymd, "Hold created today" ); |
1882 |
is( $hold->expirationdate, $today->add( days => 365)->ymd, "Reserve date set 1 year from today" ); |
2052 |
is( $hold->expirationdate, $today->add( days => 365 )->ymd, "Reserve date set 1 year from today" ); |
1883 |
|
2053 |
|
1884 |
$schema->txn_rollback; |
2054 |
$schema->txn_rollback; |
1885 |
}; |
2055 |
}; |
Lines 1912-1919
subtest '_Findgroupreserves' => sub {
Link Here
|
1912 |
C4::HoldsQueue::AddToHoldTargetMap( |
2082 |
C4::HoldsQueue::AddToHoldTargetMap( |
1913 |
{ |
2083 |
{ |
1914 |
$item->id => { |
2084 |
$item->id => { |
1915 |
borrowernumber => $patron_1->id, biblionumber => $item->biblionumber, |
2085 |
borrowernumber => $patron_1->id, biblionumber => $item->biblionumber, |
1916 |
holdingbranch => $item->holdingbranch, item_level => 0, reserve_id => $reserve_id_1 |
2086 |
holdingbranch => $item->holdingbranch, item_level => 0, reserve_id => $reserve_id_1 |
1917 |
} |
2087 |
} |
1918 |
} |
2088 |
} |
1919 |
); |
2089 |
); |
Lines 1951-1958
subtest '_Findgroupreserves' => sub {
Link Here
|
1951 |
is( scalar @reserves, 1, "We should still only get the item level hold that is in the map" ); |
2121 |
is( scalar @reserves, 1, "We should still only get the item level hold that is in the map" ); |
1952 |
is( $reserves[0]->{reserve_id}, $reserve_id_1, "We got the expected reserve which has been updated" ); |
2122 |
is( $reserves[0]->{reserve_id}, $reserve_id_1, "We got the expected reserve which has been updated" ); |
1953 |
|
2123 |
|
1954 |
|
|
|
1955 |
|
1956 |
$schema->txn_rollback; |
2124 |
$schema->txn_rollback; |
1957 |
}; |
2125 |
}; |
1958 |
|
2126 |
|
1959 |
- |
|
|