Bug 25755: Add Koha::Item->request_transfer method
[koha.git] / t / db_dependent / Koha / Item.t
1 #!/usr/bin/perl
2
3 # Copyright 2019 Koha Development team
4 #
5 # This file is part of Koha
6 #
7 # Koha is free software; you can redistribute it and/or modify it
8 # under the terms of the GNU General Public License as published by
9 # the Free Software Foundation; either version 3 of the License, or
10 # (at your option) any later version.
11 #
12 # Koha is distributed in the hope that it will be useful, but
13 # WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 # GNU General Public License for more details.
16 #
17 # You should have received a copy of the GNU General Public License
18 # along with Koha; if not, see <http://www.gnu.org/licenses>.
19
20 use Modern::Perl;
21
22 use Test::More tests => 8;
23 use Test::Exception;
24
25 use C4::Biblio;
26 use C4::Circulation;
27
28 use Koha::Items;
29 use Koha::Database;
30 use Koha::DateUtils;
31 use Koha::Old::Items;
32
33 use List::MoreUtils qw(all);
34
35 use t::lib::TestBuilder;
36 use t::lib::Mocks;
37
38 my $schema  = Koha::Database->new->schema;
39 my $builder = t::lib::TestBuilder->new;
40
41 subtest 'hidden_in_opac() tests' => sub {
42
43     plan tests => 4;
44
45     $schema->storage->txn_begin;
46
47     my $item  = $builder->build_sample_item({ itemlost => 2 });
48     my $rules = {};
49
50     # disable hidelostitems as it interteres with OpachiddenItems for the calculation
51     t::lib::Mocks::mock_preference( 'hidelostitems', 0 );
52
53     ok( !$item->hidden_in_opac, 'No rules passed, shouldn\'t hide' );
54     ok( !$item->hidden_in_opac({ rules => $rules }), 'Empty rules passed, shouldn\'t hide' );
55
56     # enable hidelostitems to verify correct behaviour
57     t::lib::Mocks::mock_preference( 'hidelostitems', 1 );
58     ok( $item->hidden_in_opac, 'Even with no rules, item should hide because of hidelostitems syspref' );
59
60     # disable hidelostitems
61     t::lib::Mocks::mock_preference( 'hidelostitems', 0 );
62     my $withdrawn = $item->withdrawn + 1; # make sure this attribute doesn't match
63
64     $rules = { withdrawn => [$withdrawn], itype => [ $item->itype ] };
65
66     ok( $item->hidden_in_opac({ rules => $rules }), 'Rule matching itype passed, should hide' );
67
68
69
70     $schema->storage->txn_rollback;
71 };
72
73 subtest 'has_pending_hold() tests' => sub {
74
75     plan tests => 2;
76
77     $schema->storage->txn_begin;
78
79     my $dbh = C4::Context->dbh;
80     my $item  = $builder->build_sample_item({ itemlost => 0 });
81     my $itemnumber = $item->itemnumber;
82
83     $dbh->do("INSERT INTO tmp_holdsqueue (surname,borrowernumber,itemnumber) VALUES ('Clamp',42,$itemnumber)");
84     ok( $item->has_pending_hold, "Yes, we have a pending hold");
85     $dbh->do("DELETE FROM tmp_holdsqueue WHERE itemnumber=$itemnumber");
86     ok( !$item->has_pending_hold, "We don't have a pending hold if nothing in the tmp_holdsqueue");
87
88     $schema->storage->txn_rollback;
89 };
90
91 subtest "as_marc_field() tests" => sub {
92
93     my $mss = C4::Biblio::GetMarcSubfieldStructure( '' );
94
95     my @schema_columns = $schema->resultset('Item')->result_source->columns;
96     my @mapped_columns = grep { exists $mss->{'items.'.$_} } @schema_columns;
97
98     plan tests => 2 * (scalar @mapped_columns + 1) + 2;
99
100     $schema->storage->txn_begin;
101
102     my $item = $builder->build_sample_item;
103     # Make sure it has at least one undefined attribute
104     $item->set({ replacementprice => undef })->store->discard_changes;
105
106     # Tests with the mss parameter
107     my $marc_field = $item->as_marc_field({ mss => $mss });
108
109     is(
110         $marc_field->tag,
111         $mss->{'items.itemnumber'}[0]->{tagfield},
112         'Generated field set the right tag number'
113     );
114
115     foreach my $column ( @mapped_columns ) {
116         my $tagsubfield = $mss->{ 'items.' . $column }[0]->{tagsubfield};
117         is( $marc_field->subfield($tagsubfield),
118             $item->$column, "Value is mapped correctly for column $column" );
119     }
120
121     # Tests without the mss parameter
122     $marc_field = $item->as_marc_field();
123
124     is(
125         $marc_field->tag,
126         $mss->{'items.itemnumber'}[0]->{tagfield},
127         'Generated field set the right tag number'
128     );
129
130     foreach my $column (@mapped_columns) {
131         my $tagsubfield = $mss->{ 'items.' . $column }[0]->{tagsubfield};
132         is( $marc_field->subfield($tagsubfield),
133             $item->$column, "Value is mapped correctly for column $column" );
134     }
135
136     my $unmapped_subfield = Koha::MarcSubfieldStructure->new(
137         {
138             frameworkcode => '',
139             tagfield      => $mss->{'items.itemnumber'}[0]->{tagfield},
140             tagsubfield   => 'X',
141         }
142     )->store;
143
144     $mss = C4::Biblio::GetMarcSubfieldStructure( '' );
145     my @unlinked_subfields;
146     push @unlinked_subfields, X => 'Something weird';
147     $item->more_subfields_xml( C4::Items::_get_unlinked_subfields_xml( \@unlinked_subfields ) )->store;
148
149     $marc_field = $item->as_marc_field;
150
151     my @subfields = $marc_field->subfields;
152     my $result = all { defined $_->[1] } @subfields;
153     ok( $result, 'There are no undef subfields' );
154
155     is( scalar $marc_field->subfield('X'), 'Something weird', 'more_subfield_xml is considered' );
156
157     $schema->storage->txn_rollback;
158 };
159
160 subtest 'pickup_locations' => sub {
161     plan tests => 66;
162
163     $schema->storage->txn_begin;
164
165     my $dbh = C4::Context->dbh;
166
167     my $root1 = $builder->build_object( { class => 'Koha::Library::Groups', value => { ft_local_hold_group => 1, branchcode => undef } } );
168     my $root2 = $builder->build_object( { class => 'Koha::Library::Groups', value => { ft_local_hold_group => 1, branchcode => undef } } );
169     my $library1 = $builder->build_object( { class => 'Koha::Libraries', value => { pickup_location => 1, } } );
170     my $library2 = $builder->build_object( { class => 'Koha::Libraries', value => { pickup_location => 1, } } );
171     my $library3 = $builder->build_object( { class => 'Koha::Libraries', value => { pickup_location => 0, } } );
172     my $library4 = $builder->build_object( { class => 'Koha::Libraries', value => { pickup_location => 1, } } );
173     my $group1_1 = $builder->build_object( { class => 'Koha::Library::Groups', value => { parent_id => $root1->id, branchcode => $library1->branchcode } } );
174     my $group1_2 = $builder->build_object( { class => 'Koha::Library::Groups', value => { parent_id => $root1->id, branchcode => $library2->branchcode } } );
175
176     my $group2_1 = $builder->build_object( { class => 'Koha::Library::Groups', value => { parent_id => $root2->id, branchcode => $library3->branchcode } } );
177     my $group2_2 = $builder->build_object( { class => 'Koha::Library::Groups', value => { parent_id => $root2->id, branchcode => $library4->branchcode } } );
178
179     our @branchcodes = (
180         $library1->branchcode, $library2->branchcode,
181         $library3->branchcode, $library4->branchcode
182     );
183
184     my $item1 = $builder->build_sample_item(
185         {
186             homebranch    => $library1->branchcode,
187             holdingbranch => $library2->branchcode,
188             copynumber    => 1,
189             ccode         => 'Gollum'
190         }
191     )->store;
192
193     my $item3 = $builder->build_sample_item(
194         {
195             homebranch    => $library3->branchcode,
196             holdingbranch => $library4->branchcode,
197             copynumber    => 3,
198             itype         => $item1->itype,
199         }
200     )->store;
201
202     Koha::CirculationRules->set_rules(
203         {
204             categorycode => undef,
205             itemtype     => $item1->itype,
206             branchcode   => undef,
207             rules        => {
208                 reservesallowed => 25,
209             }
210         }
211     );
212
213
214     my $patron1 = $builder->build_object( { class => 'Koha::Patrons', value => { branchcode => $library1->branchcode, firstname => '1' } } );
215     my $patron4 = $builder->build_object( { class => 'Koha::Patrons', value => { branchcode => $library4->branchcode, firstname => '4' } } );
216
217     my $results = {
218         "1-1-1-any"           => 3,
219         "1-1-1-holdgroup"     => 2,
220         "1-1-1-patrongroup"   => 2,
221         "1-1-1-homebranch"    => 1,
222         "1-1-1-holdingbranch" => 1,
223         "1-1-2-any"           => 3,
224         "1-1-2-holdgroup"     => 2,
225         "1-1-2-patrongroup"   => 2,
226         "1-1-2-homebranch"    => 1,
227         "1-1-2-holdingbranch" => 1,
228         "1-1-3-any"           => 3,
229         "1-1-3-holdgroup"     => 2,
230         "1-1-3-patrongroup"   => 2,
231         "1-1-3-homebranch"    => 1,
232         "1-1-3-holdingbranch" => 1,
233         "1-4-1-any"           => 0,
234         "1-4-1-holdgroup"     => 0,
235         "1-4-1-patrongroup"   => 0,
236         "1-4-1-homebranch"    => 0,
237         "1-4-1-holdingbranch" => 0,
238         "1-4-2-any"           => 3,
239         "1-4-2-holdgroup"     => 2,
240         "1-4-2-patrongroup"   => 1,
241         "1-4-2-homebranch"    => 1,
242         "1-4-2-holdingbranch" => 1,
243         "1-4-3-any"           => 0,
244         "1-4-3-holdgroup"     => 0,
245         "1-4-3-patrongroup"   => 0,
246         "1-4-3-homebranch"    => 0,
247         "1-4-3-holdingbranch" => 0,
248         "3-1-1-any"           => 0,
249         "3-1-1-holdgroup"     => 0,
250         "3-1-1-patrongroup"   => 0,
251         "3-1-1-homebranch"    => 0,
252         "3-1-1-holdingbranch" => 0,
253         "3-1-2-any"           => 3,
254         "3-1-2-holdgroup"     => 1,
255         "3-1-2-patrongroup"   => 2,
256         "3-1-2-homebranch"    => 0,
257         "3-1-2-holdingbranch" => 1,
258         "3-1-3-any"           => 0,
259         "3-1-3-holdgroup"     => 0,
260         "3-1-3-patrongroup"   => 0,
261         "3-1-3-homebranch"    => 0,
262         "3-1-3-holdingbranch" => 0,
263         "3-4-1-any"           => 0,
264         "3-4-1-holdgroup"     => 0,
265         "3-4-1-patrongroup"   => 0,
266         "3-4-1-homebranch"    => 0,
267         "3-4-1-holdingbranch" => 0,
268         "3-4-2-any"           => 3,
269         "3-4-2-holdgroup"     => 1,
270         "3-4-2-patrongroup"   => 1,
271         "3-4-2-homebranch"    => 0,
272         "3-4-2-holdingbranch" => 1,
273         "3-4-3-any"           => 3,
274         "3-4-3-holdgroup"     => 1,
275         "3-4-3-patrongroup"   => 1,
276         "3-4-3-homebranch"    => 0,
277         "3-4-3-holdingbranch" => 1
278     };
279
280     sub _doTest {
281         my ( $item, $patron, $ha, $hfp, $results ) = @_;
282
283         Koha::CirculationRules->set_rules(
284             {
285                 branchcode => undef,
286                 itemtype   => undef,
287                 rules => {
288                     holdallowed => $ha,
289                     hold_fulfillment_policy => $hfp,
290                     returnbranch => 'any'
291                 }
292             }
293         );
294         my $ha_value=$ha==3?'holdgroup':($ha==2?'any':'homebranch');
295
296         my @pl = map {
297             my $pickup_location = $_;
298             grep { $pickup_location->branchcode eq $_ } @branchcodes
299         } $item->pickup_locations( { patron => $patron } )->as_list;
300
301         ok(
302             scalar(@pl) == $results->{
303                     $item->copynumber . '-'
304                   . $patron->firstname . '-'
305                   . $ha . '-'
306                   . $hfp
307             },
308             'item'
309               . $item->copynumber
310               . ', patron'
311               . $patron->firstname
312               . ', holdallowed: '
313               . $ha_value
314               . ', hold_fulfillment_policy: '
315               . $hfp
316               . ' should return '
317               . $results->{
318                     $item->copynumber . '-'
319                   . $patron->firstname . '-'
320                   . $ha . '-'
321                   . $hfp
322               }
323               . ' and returns '
324               . scalar(@pl)
325         );
326
327     }
328
329
330     foreach my $item ($item1, $item3) {
331         foreach my $patron ($patron1, $patron4) {
332             #holdallowed 1: homebranch, 2: any, 3: holdgroup
333             foreach my $ha (1, 2, 3) {
334                 foreach my $hfp ('any', 'holdgroup', 'patrongroup', 'homebranch', 'holdingbranch') {
335                     _doTest($item, $patron, $ha, $hfp, $results);
336                 }
337             }
338         }
339     }
340
341     # Now test that branchtransferlimits will further filter the pickup locations
342
343     my $item_no_ccode = $builder->build_sample_item(
344         {
345             homebranch    => $library1->branchcode,
346             holdingbranch => $library2->branchcode,
347             itype         => $item1->itype,
348         }
349     )->store;
350
351     t::lib::Mocks::mock_preference('UseBranchTransferLimits', 1);
352     t::lib::Mocks::mock_preference('BranchTransferLimitsType', 'itemtype');
353     Koha::CirculationRules->set_rules(
354         {
355             branchcode => undef,
356             itemtype   => $item1->itype,
357             rules      => {
358                 holdallowed             => 1,
359                 hold_fulfillment_policy => 1,
360                 returnbranch            => 'any'
361             }
362         }
363     );
364     $builder->build_object(
365         {
366             class => 'Koha::Item::Transfer::Limits',
367             value => {
368                 toBranch   => $library1->branchcode,
369                 fromBranch => $library2->branchcode,
370                 itemtype   => $item1->itype,
371                 ccode      => undef,
372             }
373         }
374     );
375
376     my @pickup_locations = map {
377         my $pickup_location = $_;
378         grep { $pickup_location->branchcode eq $_ } @branchcodes
379     } $item1->pickup_locations( { patron => $patron1 } )->as_list;
380
381     is( scalar @pickup_locations, 3 - 1, "With a transfer limits we get back the libraries that are pickup locations minus 1 limited library");
382
383     $builder->build_object(
384         {
385             class => 'Koha::Item::Transfer::Limits',
386             value => {
387                 toBranch   => $library4->branchcode,
388                 fromBranch => $library2->branchcode,
389                 itemtype   => $item1->itype,
390                 ccode      => undef,
391             }
392         }
393     );
394
395     @pickup_locations = map {
396         my $pickup_location = $_;
397         grep { $pickup_location->branchcode eq $_ } @branchcodes
398     } $item1->pickup_locations( { patron => $patron1 } )->as_list;
399
400     is( scalar @pickup_locations, 3 - 2, "With 2 transfer limits we get back the libraries that are pickup locations minus 2 limited libraries");
401
402     t::lib::Mocks::mock_preference('BranchTransferLimitsType', 'ccode');
403     @pickup_locations = map {
404         my $pickup_location = $_;
405         grep { $pickup_location->branchcode eq $_ } @branchcodes
406     } $item1->pickup_locations( { patron => $patron1 } )->as_list;
407     is( scalar @pickup_locations, 3, "With no transfer limits of type ccode we get back the libraries that are pickup locations");
408
409     @pickup_locations = map {
410         my $pickup_location = $_;
411         grep { $pickup_location->branchcode eq $_ } @branchcodes
412     } $item_no_ccode->pickup_locations( { patron => $patron1 } )->as_list;
413     is( scalar @pickup_locations, 3, "With no transfer limits of type ccode and an item with no ccode we get back the libraries that are pickup locations");
414
415     $builder->build_object(
416         {
417             class => 'Koha::Item::Transfer::Limits',
418             value => {
419                 toBranch   => $library2->branchcode,
420                 fromBranch => $library2->branchcode,
421                 itemtype   => undef,
422                 ccode      => $item1->ccode,
423             }
424         }
425     );
426
427     @pickup_locations = map {
428         my $pickup_location = $_;
429         grep { $pickup_location->branchcode eq $_ } @branchcodes
430     } $item1->pickup_locations( { patron => $patron1 } )->as_list;
431     is( scalar @pickup_locations, 3 - 1, "With a transfer limits we get back the libraries that are pickup locations minus 1 limited library");
432
433     $builder->build_object(
434         {
435             class => 'Koha::Item::Transfer::Limits',
436             value => {
437                 toBranch   => $library4->branchcode,
438                 fromBranch => $library2->branchcode,
439                 itemtype   => undef,
440                 ccode      => $item1->ccode,
441             }
442         }
443     );
444
445     @pickup_locations = map {
446         my $pickup_location = $_;
447         grep { $pickup_location->branchcode eq $_ } @branchcodes
448     } $item1->pickup_locations( { patron => $patron1 } )->as_list;
449     is( scalar @pickup_locations, 3 - 2, "With 2 transfer limits we get back the libraries that are pickup locations minus 2 limited libraries");
450
451     t::lib::Mocks::mock_preference('UseBranchTransferLimits', 0);
452
453     $schema->storage->txn_rollback;
454 };
455
456 subtest 'request_transfer' => sub {
457     plan tests => 7;
458     $schema->storage->txn_begin;
459
460     my $library1 = $builder->build_object( { class => 'Koha::Libraries' } );
461     my $library2 = $builder->build_object( { class => 'Koha::Libraries' } );
462     my $item     = $builder->build_sample_item(
463         {
464             homebranch    => $library1->branchcode,
465             holdingbranch => $library2->branchcode,
466         }
467     );
468
469     # Mandatory fields tests
470     throws_ok { $item->request_transfer( { to => $library1 } ) }
471     'Koha::Exceptions::MissingParameter',
472       'Exception thrown if `reason` parameter is missing';
473
474     throws_ok { $item->request_transfer( { reason => 'Manual' } ) }
475     'Koha::Exceptions::MissingParameter',
476       'Exception thrown if `to` parameter is missing';
477
478     # Successful request
479     my $transfer = $item->request_transfer({ to => $library1, reason => 'Manual' });
480     is( ref($transfer), 'Koha::Item::Transfer',
481         'Koha::Item->request_transfer should return a Koha::Item::Transfer object'
482     );
483
484     # Transfer already in progress
485     throws_ok { $item->request_transfer( { to => $library2, reason => 'Manual' } ) }
486     'Koha::Exceptions::Item::Transfer::Found',
487       'Exception thrown if transfer is already in progress';
488
489     my $exception = $@;
490     is( ref( $exception->transfer ),
491         'Koha::Item::Transfer',
492         'The exception contains the found Koha::Item::Transfer' );
493
494     $transfer->datearrived(dt_from_string)->store();
495
496     # BranchTransferLimits
497     t::lib::Mocks::mock_preference('UseBranchTransferLimits', 1);
498     t::lib::Mocks::mock_preference('BranchTransferLimitsType', 'itemtype');
499     my $limit = Koha::Item::Transfer::Limit->new({
500         fromBranch => $library2->branchcode,
501         toBranch => $library1->branchcode,
502         itemtype => $item->effective_itemtype,
503     })->store;
504
505     throws_ok { $item->request_transfer( { to => $library1, reason => 'Manual' } ) }
506     'Koha::Exceptions::Item::Transfer::Limit',
507       'Exception thrown if transfer is prevented by limits';
508
509     my $forced_transfer = $item->request_transfer( { to => $library1, reason => 'Manual', force => 1 } );
510     is( ref($forced_transfer), 'Koha::Item::Transfer',
511         'Koha::Item->request_transfer allowed when forced'
512     );
513
514     $schema->storage->txn_rollback;
515 };
516
517 subtest 'deletion' => sub {
518     plan tests => 12;
519
520     $schema->storage->txn_begin;
521
522     my $biblio = $builder->build_sample_biblio();
523
524     my $item = $builder->build_sample_item(
525         {
526             biblionumber => $biblio->biblionumber,
527         }
528     );
529
530     is( ref( $item->move_to_deleted ), 'Koha::Schema::Result::Deleteditem', 'Koha::Item->move_to_deleted should return the Deleted item' )
531       ;    # FIXME This should be Koha::Deleted::Item
532     is( Koha::Old::Items->search({itemnumber => $item->itemnumber})->count, 1, '->move_to_deleted must have moved the item to deleteditem' );
533     $item = $builder->build_sample_item(
534         {
535             biblionumber => $biblio->biblionumber,
536         }
537     );
538     $item->delete;
539     is( Koha::Old::Items->search({itemnumber => $item->itemnumber})->count, 0, '->move_to_deleted must not have moved the item to deleteditem' );
540
541
542     my $library   = $builder->build_object({ class => 'Koha::Libraries' });
543     my $library_2 = $builder->build_object({ class => 'Koha::Libraries' });
544     t::lib::Mocks::mock_userenv({ branchcode => $library->branchcode });
545
546     my $patron = $builder->build_object({class => 'Koha::Patrons'});
547     $item = $builder->build_sample_item({ library => $library->branchcode });
548
549     # book_on_loan
550     C4::Circulation::AddIssue( $patron->unblessed, $item->barcode );
551
552     is(
553         $item->safe_to_delete,
554         'book_on_loan',
555         'Koha::Item->safe_to_delete reports item on loan',
556     );
557
558     is(
559         $item->safe_delete,
560         'book_on_loan',
561         'item that is on loan cannot be deleted',
562     );
563
564     AddReturn( $item->barcode, $library->branchcode );
565
566     # book_reserved is tested in t/db_dependent/Reserves.t
567
568     # not_same_branch
569     t::lib::Mocks::mock_preference('IndependentBranches', 1);
570     my $item_2 = $builder->build_sample_item({ library => $library_2->branchcode });
571
572     is(
573         $item_2->safe_to_delete,
574         'not_same_branch',
575         'Koha::Item->safe_to_delete reports IndependentBranches restriction',
576     );
577
578     is(
579         $item_2->safe_delete,
580         'not_same_branch',
581         'IndependentBranches prevents deletion at another branch',
582     );
583
584     # linked_analytics
585
586     { # codeblock to limit scope of $module->mock
587
588         my $module = Test::MockModule->new('C4::Items');
589         $module->mock( GetAnalyticsCount => sub { return 1 } );
590
591         $item->discard_changes;
592         is(
593             $item->safe_to_delete,
594             'linked_analytics',
595             'Koha::Item->safe_to_delete reports linked analytics',
596         );
597
598         is(
599             $item->safe_delete,
600             'linked_analytics',
601             'Linked analytics prevents deletion of item',
602         );
603
604     }
605
606     { # last_item_for_hold
607         C4::Reserves::AddReserve({ branchcode => $patron->branchcode, borrowernumber => $patron->borrowernumber, biblionumber => $item->biblionumber });
608         is( $item->safe_to_delete, 'last_item_for_hold', 'Item cannot be deleted if a biblio-level is placed on the biblio and there is only 1 item attached to the biblio' );
609
610         # With another item attached to the biblio, the item can be deleted
611         $builder->build_sample_item({ biblionumber => $item->biblionumber });
612     }
613
614     is(
615         $item->safe_to_delete,
616         1,
617         'Koha::Item->safe_to_delete shows item safe to delete'
618     );
619
620     $item->safe_delete,
621
622     my $test_item = Koha::Items->find( $item->itemnumber );
623
624     is( $test_item, undef,
625         "Koha::Item->safe_delete should delete item if safe_to_delete returns true"
626     );
627
628     $schema->storage->txn_rollback;
629 };
630
631 subtest 'renewal_branchcode' => sub {
632     plan tests => 13;
633
634     $schema->storage->txn_begin;
635
636     my $item = $builder->build_sample_item();
637     my $branch = $builder->build_object({ class => 'Koha::Libraries' });
638     my $checkout = $builder->build_object({
639         class => 'Koha::Checkouts',
640         value => {
641             itemnumber => $item->itemnumber,
642         }
643     });
644
645
646     C4::Context->interface( 'intranet' );
647     t::lib::Mocks::mock_userenv({ branchcode => $branch->branchcode });
648
649     is( $item->renewal_branchcode, $branch->branchcode, "If interface not opac, we get the branch from context");
650     is( $item->renewal_branchcode({ branch => "PANDA"}), $branch->branchcode, "If interface not opac, we get the branch from context even if we pass one in");
651     C4::Context->set_userenv(51, 'userid4tests', undef, 'firstname', 'surname', undef, undef, 0, undef, undef, undef ); #mock userenv doesn't let us set null branch
652     is( $item->renewal_branchcode({ branch => "PANDA"}), "PANDA", "If interface not opac, we get the branch we pass one in if context not set");
653
654     C4::Context->interface( 'opac' );
655
656     t::lib::Mocks::mock_preference('OpacRenewalBranch', undef);
657     is( $item->renewal_branchcode, 'OPACRenew', "If interface opac and OpacRenewalBranch undef, we get OPACRenew");
658     is( $item->renewal_branchcode({branch=>'COW'}), 'OPACRenew', "If interface opac and OpacRenewalBranch undef, we get OPACRenew even if branch passed");
659
660     t::lib::Mocks::mock_preference('OpacRenewalBranch', 'none');
661     is( $item->renewal_branchcode, '', "If interface opac and OpacRenewalBranch is none, we get blank string");
662     is( $item->renewal_branchcode({branch=>'COW'}), '', "If interface opac and OpacRenewalBranch is none, we get blank string even if branch passed");
663
664     t::lib::Mocks::mock_preference('OpacRenewalBranch', 'checkoutbranch');
665     is( $item->renewal_branchcode, $checkout->branchcode, "If interface opac and OpacRenewalBranch set to checkoutbranch, we get branch of checkout");
666     is( $item->renewal_branchcode({branch=>'MONKEY'}), $checkout->branchcode, "If interface opac and OpacRenewalBranch set to checkoutbranch, we get branch of checkout even if branch passed");
667
668     t::lib::Mocks::mock_preference('OpacRenewalBranch','patronhomebranch');
669     is( $item->renewal_branchcode, $checkout->patron->branchcode, "If interface opac and OpacRenewalBranch set to patronbranch, we get branch of patron");
670     is( $item->renewal_branchcode({branch=>'TURKEY'}), $checkout->patron->branchcode, "If interface opac and OpacRenewalBranch set to patronbranch, we get branch of patron even if branch passed");
671
672     t::lib::Mocks::mock_preference('OpacRenewalBranch','itemhomebranch');
673     is( $item->renewal_branchcode, $item->homebranch, "If interface opac and OpacRenewalBranch set to itemhomebranch, we get homebranch of item");
674     is( $item->renewal_branchcode({branch=>'MANATEE'}), $item->homebranch, "If interface opac and OpacRenewalBranch set to itemhomebranch, we get homebranch of item even if branch passed");
675
676     $schema->storage->txn_rollback;
677 };
678
679 subtest 'Tests for itemtype' => sub {
680     plan tests => 2;
681     $schema->storage->txn_begin;
682
683     my $biblio = $builder->build_sample_biblio;
684     my $itemtype = $builder->build_object({ class => 'Koha::ItemTypes' });
685     my $item = $builder->build_sample_item({ biblionumber => $biblio->biblionumber, itype => $itemtype->itemtype });
686
687     t::lib::Mocks::mock_preference('item-level_itypes', 1);
688     is( $item->itemtype->itemtype, $item->itype, 'Pref enabled' );
689     t::lib::Mocks::mock_preference('item-level_itypes', 0);
690     is( $item->itemtype->itemtype, $biblio->biblioitem->itemtype, 'Pref disabled' );
691
692     $schema->storage->txn_rollback;
693 };