3 # Copyright 2015 Koha Development team
5 # This file is part of Koha
7 # Koha is free software; you can redistribute it and/or modify it
8 # under the terms of the GNU General Public License as published by
9 # the Free Software Foundation; either version 3 of the License, or
10 # (at your option) any later version.
12 # Koha is distributed in the hope that it will be useful, but
13 # WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 # GNU General Public License for more details.
17 # You should have received a copy of the GNU General Public License
18 # along with Koha; if not, see <http://www.gnu.org/licenses>.
22 use Test::More tests => 9;
29 use Koha::Item::Transfer::Limits;
34 use Koha::CirculationRules;
37 use t::lib::TestBuilder;
39 my $schema = Koha::Database->new->schema;
40 $schema->storage->txn_begin;
42 # Cleanup default_branch_item_rules
43 my $dbh = C4::Context->dbh;
44 $dbh->do('DELETE FROM circulation_rules');
46 my $builder = t::lib::TestBuilder->new;
47 my $nb_of_libraries = Koha::Libraries->search->count;
48 my $new_library_1 = Koha::Library->new({
49 branchcode => 'my_bc_1',
50 branchname => 'my_branchname_1',
51 branchnotes => 'my_branchnotes_1',
52 marcorgcode => 'US-MyLib',
54 my $new_library_2 = Koha::Library->new({
55 branchcode => 'my_bc_2',
56 branchname => 'my_branchname_2',
57 branchnotes => 'my_branchnotes_2',
60 is( Koha::Libraries->search->count, $nb_of_libraries + 2, 'The 2 libraries should have been added' );
62 my $retrieved_library_1 = Koha::Libraries->find( $new_library_1->branchcode );
63 is( $retrieved_library_1->branchname, $new_library_1->branchname, 'Find a library by branchcode should return the correct library' );
65 $retrieved_library_1->delete;
66 is( Koha::Libraries->search->count, $nb_of_libraries + 1, 'Delete should have deleted the library' );
68 # Stockrotation relationship testing
70 my $new_library_sr = $builder->build({ source => 'Branch' });
73 source => 'Stockrotationstage',
74 value => { branchcode_id => $new_library_sr->{branchcode} },
77 source => 'Stockrotationstage',
78 value => { branchcode_id => $new_library_sr->{branchcode} },
81 source => 'Stockrotationstage',
82 value => { branchcode_id => $new_library_sr->{branchcode} },
85 my $srstages = Koha::Libraries->find($new_library_sr->{branchcode})
86 ->stockrotationstages;
87 is( $srstages->count, 3, 'Correctly fetched stockrotationstages associated with this branch');
89 isa_ok( $srstages->next, 'Koha::StockRotationStage', "Relationship correctly creates Koha::Objects." );
91 subtest 'pickup_locations' => sub {
94 Koha::CirculationRules->set_rules(
98 categorycode => undef,
101 hold_fulfillment_policy => 'any',
102 returnbranch => 'any'
107 my $from = Koha::Library->new({
108 branchcode => 'zzzfrom',
109 branchname => 'zzzfrom',
110 branchnotes => 'zzzfrom',
112 my $to = Koha::Library->new({
113 branchcode => 'zzzto',
114 branchname => 'zzzto',
115 branchnotes => 'zzzto',
119 my $biblio = $builder->build_sample_biblio({ itemtype => 'DUMMY' });
120 my $itemtype = $biblio->itemtype;
122 biblionumber => $biblio->biblionumber,
123 library => $from->branchcode,
126 my $item1 = $builder->build_sample_item({%$item_info});
127 my $item2 = $builder->build_sample_item({%$item_info});
128 my $item3 = $builder->build_sample_item({%$item_info});
129 my $patron1 = $builder->build_object( { class => 'Koha::Patrons', value => { branchcode => $from->branchcode } } );
131 subtest 'UseBranchTransferLimits = OFF' => sub {
134 t::lib::Mocks::mock_preference('UseBranchTransferLimits', 0);
135 t::lib::Mocks::mock_preference('BranchTransferLimitsType', 'itemtype');
136 t::lib::Mocks::mock_preference('item-level_itypes', 1);
137 Koha::Item::Transfer::Limits->delete;
138 Koha::Item::Transfer::Limit->new({
139 fromBranch => $from->branchcode,
140 toBranch => $to->branchcode,
141 itemtype => $biblio->itemtype,
143 my $total_pickup = Koha::Libraries->search({
146 my $pickup = Koha::Libraries->pickup_locations({ biblio => $biblio->biblionumber, patron => $patron1 });
147 is(C4::Context->preference('UseBranchTransferLimits'), 0, 'Given system '
148 .'preference UseBranchTransferLimits is switched OFF,');
149 is(@{$pickup}, $total_pickup, 'Then the total number of pickup locations '
150 .'equal number of libraries with pickup_location => 1');
152 t::lib::Mocks::mock_preference('BranchTransferLimitsType', 'itemtype');
153 t::lib::Mocks::mock_preference('item-level_itypes', 1);
154 $pickup = Koha::Libraries->pickup_locations({ biblio => $biblio->biblionumber, patron => $patron1 });
155 is(@{$pickup}, $total_pickup, '...when '
156 .'BranchTransferLimitsType = itemtype and item-level_itypes = 1');
157 t::lib::Mocks::mock_preference('item-level_itypes', 0);
158 $pickup = Koha::Libraries->pickup_locations({ biblio => $biblio->biblionumber, patron => $patron1 });
159 is(@{$pickup}, $total_pickup, '...as well as when '
160 .'BranchTransferLimitsType = itemtype and item-level_itypes = 0');
161 t::lib::Mocks::mock_preference('BranchTransferLimitsType', 'ccode');
162 $pickup = Koha::Libraries->pickup_locations({ biblio => $biblio->biblionumber, patron => $patron1 });
163 is(@{$pickup}, $total_pickup, '...as well as when '
164 .'BranchTransferLimitsType = ccode');
165 t::lib::Mocks::mock_preference('item-level_itypes', 1);
168 subtest 'UseBranchTransferLimits = ON' => sub {
170 t::lib::Mocks::mock_preference('UseBranchTransferLimits', 1);
172 is(C4::Context->preference('UseBranchTransferLimits'), 1, 'Given system '
173 .'preference UseBranchTransferLimits is switched ON,');
175 subtest 'Given BranchTransferLimitsType = itemtype and '
176 .'item-level_itypes = ON' => sub {
179 t::lib::Mocks::mock_preference('BranchTransferLimitsType','itemtype');
180 t::lib::Mocks::mock_preference('item-level_itypes', 1);
181 Koha::Item::Transfer::Limits->delete;
182 my $limit = Koha::Item::Transfer::Limit->new({
183 fromBranch => $from->branchcode,
184 toBranch => $to->branchcode,
185 itemtype => $item1->effective_itemtype,
187 ok($item1->effective_itemtype eq $item2->effective_itemtype
188 && $item1->effective_itemtype eq $item3->effective_itemtype,
189 'Given all items of a biblio have same the itemtype,');
190 is($limit->itemtype, $item1->effective_itemtype, 'and given there '
191 .'is an existing transfer limit for that itemtype,');
192 my $pickup = Koha::Libraries->pickup_locations({ biblio => $biblio->biblionumber, patron => $patron1 });
194 foreach my $lib (@{$pickup}) {
195 if ($lib->branchcode eq $limit->toBranch) {
199 is($found, 0, 'Then the to-library of which the limit applies for, '
200 .'is not included in the list of pickup libraries.');
201 $pickup = Koha::Libraries->pickup_locations({ item => $item1, patron => $patron1 });
203 foreach my $lib (@{$pickup}) {
204 if ($lib->branchcode eq $limit->toBranch) {
208 is($found, 0, 'The same applies when asking pickup locations of '
210 my $others = Koha::Libraries->search({
211 pickup_location => 1,
212 branchcode => { 'not in' => [$limit->toBranch] }})->count;
213 is(@{$pickup}, $others, 'However, the number of other pickup '
214 .'libraries is correct.');
215 $item2->itype('BK')->store;
216 ok($item1->effective_itemtype ne $item2->effective_itemtype,
217 'Given one of the item in this biblio has a different itemtype,');
218 is(Koha::Item::Transfer::Limits->search({
219 itemtype => $item2->effective_itemtype })->count, 0, 'and it is'
220 .' not restricted by transfer limits,');
221 $pickup = Koha::Libraries->pickup_locations({ biblio => $biblio->biblionumber, patron => $patron1 });
223 foreach my $lib (@{$pickup}) {
224 if ($lib->branchcode eq $limit->toBranch) {
228 is($found, 1, 'Then the to-library of which the limit applies for, '
229 .'is included in the list of pickup libraries.');
230 $pickup = Koha::Libraries->pickup_locations({ item => $item2, patron => $patron1 });
232 foreach my $lib (@{$pickup}) {
233 if ($lib->branchcode eq $limit->toBranch) {
237 is($found, 1, 'The same applies when asking pickup locations of '
238 .'a that particular item.');
239 Koha::Item::Transfer::Limits->delete;
240 $pickup = Koha::Libraries->pickup_locations({ biblio => $biblio->biblionumber, patron => $patron1 });
242 foreach my $lib (@{$pickup}) {
243 if ($lib->branchcode eq $limit->toBranch) {
247 is($found, 1, 'Given we deleted transfer limit, the previously '
248 .'transfer-limited library is included in the list.');
249 $pickup = Koha::Libraries->pickup_locations({ item => $item1, patron => $patron1 });
251 foreach my $lib (@{$pickup}) {
252 if ($lib->branchcode eq $limit->toBranch) {
256 is($found, 1, 'The same applies when asking pickup locations of '
260 subtest 'Given BranchTransferLimitsType = itemtype and '
261 .'item-level_itypes = OFF' => sub {
264 t::lib::Mocks::mock_preference('BranchTransferLimitsType','itemtype');
265 t::lib::Mocks::mock_preference('item-level_itypes', 0);
266 $biblio->biblioitem->itemtype('BK')->store;
267 Koha::Item::Transfer::Limits->delete;
268 my $limit = Koha::Item::Transfer::Limit->new({
269 fromBranch => $from->branchcode,
270 toBranch => $to->branchcode,
271 itemtype => $item1->effective_itemtype,
274 ok($item1->effective_itemtype eq 'BK',
275 'Given items use biblio-level itemtype,');
276 is($limit->itemtype, $item1->effective_itemtype, 'and given there '
277 .'is an existing transfer limit for that itemtype,');
278 my $pickup = Koha::Libraries->pickup_locations({ biblio => $biblio->biblionumber, patron => $patron1 });
280 foreach my $lib (@{$pickup}) {
281 if ($lib->branchcode eq $limit->toBranch) {
285 is($found, 0, 'Then the to-library of which the limit applies for, '
286 .'is not included in the list of pickup libraries.');
287 $pickup = Koha::Libraries->pickup_locations({ item => $item1, patron => $patron1 });
289 foreach my $lib (@{$pickup}) {
290 if ($lib->branchcode eq $limit->toBranch) {
294 is($found, 0, 'The same applies when asking pickup locations of '
296 my $others = Koha::Libraries->search({
297 pickup_location => 1,
298 branchcode => { 'not in' => [$limit->toBranch] }})->count;
299 is(@{$pickup}, $others, 'However, the number of other pickup '
300 .'libraries is correct.');
301 Koha::Item::Transfer::Limits->delete;
302 $pickup = Koha::Libraries->pickup_locations({ biblio => $biblio->biblionumber, patron => $patron1 });
304 foreach my $lib (@{$pickup}) {
305 if ($lib->branchcode eq $limit->toBranch) {
309 is($found, 1, 'Given we deleted transfer limit, the previously '
310 .'transfer-limited library is included in the list.');
311 $limit = Koha::Item::Transfer::Limit->new({
312 fromBranch => $from->branchcode,
313 toBranch => $to->branchcode,
314 itemtype => $item1->itype,
316 ok($item1->itype ne $item1->effective_itemtype
317 && $limit->itemtype eq $item1->itype, 'Given we have added a limit'
318 .' matching ITEM-level itemtype,');
319 $pickup = Koha::Libraries->pickup_locations({ biblio => $biblio->biblionumber, patron => $patron1 });
321 foreach my $lib (@{$pickup}) {
322 if ($lib->branchcode eq $limit->toBranch) {
326 is($found, 1, 'Then the limited branch is still included as a pickup'
328 $pickup = Koha::Libraries->pickup_locations({ item => $item1, patron => $patron1 });
330 foreach my $lib (@{$pickup}) {
331 if ($lib->branchcode eq $limit->toBranch) {
335 is($found, 1, 'The same applies when asking pickup locations of '
339 subtest 'Given BranchTransferLimitsType = ccode' => sub {
342 t::lib::Mocks::mock_preference('BranchTransferLimitsType', 'ccode');
343 $item1->ccode('hi')->store;
344 $item2->ccode('hi')->store;
345 $item3->ccode('hi')->store;
346 Koha::Item::Transfer::Limits->delete;
347 my $limit = Koha::Item::Transfer::Limit->new({
348 fromBranch => $from->branchcode,
349 toBranch => $to->branchcode,
350 ccode => $item1->ccode,
353 is($limit->ccode, $item1->ccode, 'Given there '
354 .'is an existing transfer limit for that ccode,');
355 my $pickup = Koha::Libraries->pickup_locations({ biblio => $biblio->biblionumber, patron => $patron1 });
357 foreach my $lib (@{$pickup}) {
358 if ($lib->branchcode eq $limit->toBranch) {
362 is($found, 0, 'Then the to-library of which the limit applies for, '
363 .'is not included in the list of pickup libraries.');
364 $pickup = Koha::Libraries->pickup_locations({ item => $item1, patron => $patron1 });
366 foreach my $lib (@{$pickup}) {
367 if ($lib->branchcode eq $limit->toBranch) {
371 is($found, 0, 'The same applies when asking pickup locations of '
373 my $others = Koha::Libraries->search({
374 pickup_location => 1,
375 branchcode => { 'not in' => [$limit->toBranch] }})->count;
376 is(@{$pickup}, $others, 'However, the number of other pickup '
377 .'libraries is correct.');
378 $item3->ccode('yo')->store;
379 ok($item1->ccode ne $item3->ccode,
380 'Given one of the item in this biblio has a different ccode,');
381 is(Koha::Item::Transfer::Limits->search({
382 ccode => $item3->ccode })->count, 0, 'and it is'
383 .' not restricted by transfer limits,');
384 $pickup = Koha::Libraries->pickup_locations({ biblio => $biblio->biblionumber, patron => $patron1 });
386 foreach my $lib (@{$pickup}) {
387 if ($lib->branchcode eq $limit->toBranch) {
391 is($found, 1, 'Then the to-library of which the limit applies for, '
392 .'is included in the list of pickup libraries.');
393 $pickup = Koha::Libraries->pickup_locations({ item => $item3, patron => $patron1 });
395 foreach my $lib (@{$pickup}) {
396 if ($lib->branchcode eq $limit->toBranch) {
400 is($found, 1, 'The same applies when asking pickup locations of '
401 .'a that particular item.');
402 Koha::Item::Transfer::Limits->delete;
403 $pickup = Koha::Libraries->pickup_locations({ biblio => $biblio->biblionumber, patron => $patron1 });
405 foreach my $lib (@{$pickup}) {
406 if ($lib->branchcode eq $limit->toBranch) {
410 is($found, 1, 'Given we deleted transfer limit, the previously '
411 .'transfer-limited library is included in the list.');
412 $pickup = Koha::Libraries->pickup_locations({ item => $item1, patron => $patron1 });
414 foreach my $lib (@{$pickup}) {
415 if ($lib->branchcode eq $limit->toBranch) {
419 is($found, 1, 'The same applies when asking pickup locations of '
425 $schema->storage->txn_rollback;
427 subtest '->get_effective_marcorgcode' => sub {
431 $schema->storage->txn_begin;
433 my $library_1 = $builder->build_object({ class => 'Koha::Libraries',
434 value => { marcorgcode => 'US-MyLib' } });
435 my $library_2 = $builder->build_object({ class => 'Koha::Libraries',
436 value => { marcorgcode => undef } });
438 t::lib::Mocks::mock_preference('MARCOrgCode', 'US-Default');
440 is( $library_1->get_effective_marcorgcode, 'US-MyLib',
441 'If defined, use library\'s own marc org code');
442 is( $library_2->get_effective_marcorgcode, 'US-Default',
443 'If not defined library\' marc org code, use the one from system preferences');
445 t::lib::Mocks::mock_preference('MARCOrgCode', 'Blah');
446 is( $library_2->get_effective_marcorgcode, 'Blah',
447 'Fallback is always MARCOrgCode syspref');
449 $library_2->marcorgcode('ThisIsACode')->store();
450 is( $library_2->get_effective_marcorgcode, 'ThisIsACode',
451 'Pick library_2 code');
453 $schema->storage->txn_rollback;
456 subtest 'cash_registers' => sub {
459 $schema->storage->txn_begin;
461 my $library = $builder->build_object( { class => 'Koha::Libraries' } );
462 my $register1 = $builder->build_object(
464 class => 'Koha::Cash::Registers',
465 value => { branch => $library->branchcode },
468 my $register2 = $builder->build_object(
470 class => 'Koha::Cash::Registers',
471 value => { branch => $library->branchcode },
475 my $registers = $library->cash_registers;
476 is( ref($registers), 'Koha::Cash::Registers',
477 'Koha::Library->cash_registers should return a set of Koha::Cash::Registers'
479 is( $registers->count, 2,
480 'Koha::Library->cash_registers should return the correct cash registers'
484 is( $library->cash_registers->next->id, $register2->id,
485 'Koha::Library->cash_registers should return the correct cash registers'
488 $schema->storage->txn_rollback;
491 subtest 'get_hold_libraries and validate_hold_sibling' => sub {
495 $schema->storage->txn_begin;
497 my $library1 = $builder->build_object( { class => 'Koha::Libraries' } );
498 my $library2 = $builder->build_object( { class => 'Koha::Libraries' } );
499 my $library3 = $builder->build_object( { class => 'Koha::Libraries' } );
501 my $root = $builder->build_object( { class => 'Koha::Library::Groups', value => { ft_local_hold_group => 1 } } );
502 my $g1 = $builder->build_object( { class => 'Koha::Library::Groups', value => { parent_id => $root->id, branchcode => $library1->branchcode } } );
503 my $g2 = $builder->build_object( { class => 'Koha::Library::Groups', value => { parent_id => $root->id, branchcode => $library2->branchcode } } );
505 my @hold_libraries = ($library1, $library2);
507 my @result = $library1->get_hold_libraries();
509 ok(scalar(@result) == 2, 'get_hold_libraries returns 2 libraries');
511 my %map = map {$_->branchcode, 1} @result;
513 foreach my $hold_library ( @hold_libraries ) {
514 ok(exists $map{$hold_library->branchcode}, 'library in hold group');
517 ok($library1->validate_hold_sibling( { branchcode => $library2->branchcode } ), 'Library 2 is a valid hold sibling');
518 ok(!$library1->validate_hold_sibling( { branchcode => $library3->branchcode } ), 'Library 3 is not a valid hold sibling');
520 $schema->storage->txn_rollback;