+ my $cpl_items_after = SearchItemsByField( 'homebranch', $library1->{branchcode});
+ is( ( scalar( @$cpl_items_after ) - scalar ( @$cpl_items_before ) ), 1, 'SearchItemsByField should return something' );
+
+ $schema->storage->txn_rollback;
+};
+
+subtest 'Koha::Item(s) tests' => sub {
+
+ plan tests => 5;
+
+ $schema->storage->txn_begin();
+
+ my $builder = t::lib::TestBuilder->new;
+ my $library1 = $builder->build({
+ source => 'Branch',
+ });
+ my $library2 = $builder->build({
+ source => 'Branch',
+ });
+ my $itemtype = $builder->build({
+ source => 'Itemtype',
+ });
+
+ # Create a biblio and item for testing
+ t::lib::Mocks::mock_preference('marcflavour', 'MARC21');
+ my ($bibnum, $bibitemnum) = get_biblio();
+ my ( $item_bibnum, $item_bibitemnum, $itemnumber ) = AddItem(
+ {
+ homebranch => $library1->{branchcode},
+ holdingbranch => $library2->{branchcode},
+ itype => $itemtype->{itemtype},
+ },
+ $bibnum
+ );
+
+ # Get item.
+ my $item = Koha::Items->find( $itemnumber );
+ is( ref($item), 'Koha::Item', "Got Koha::Item" );
+
+ my $homebranch = $item->home_branch();
+ is( ref($homebranch), 'Koha::Library', "Got Koha::Library from home_branch method" );
+ is( $homebranch->branchcode(), $library1->{branchcode}, "Home branch code matches homebranch" );
+
+ my $holdingbranch = $item->holding_branch();
+ is( ref($holdingbranch), 'Koha::Library', "Got Koha::Library from holding_branch method" );
+ is( $holdingbranch->branchcode(), $library2->{branchcode}, "Home branch code matches holdingbranch" );
+
+ $schema->storage->txn_rollback;
+};
+
+subtest 'C4::Biblio::EmbedItemsInMarcBiblio' => sub {
+ plan tests => 8;
+
+ $schema->storage->txn_begin();
+
+ my $builder = t::lib::TestBuilder->new;
+ my $library1 = $builder->build({
+ source => 'Branch',
+ });
+ my $library2 = $builder->build({
+ source => 'Branch',
+ });
+ my $itemtype = $builder->build({
+ source => 'Itemtype',
+ });
+
+ my ( $biblionumber, $biblioitemnumber ) = get_biblio();
+ my $item_infos = [
+ { homebranch => $library1->{branchcode}, holdingbranch => $library1->{branchcode} },
+ { homebranch => $library1->{branchcode}, holdingbranch => $library1->{branchcode} },
+ { homebranch => $library1->{branchcode}, holdingbranch => $library1->{branchcode} },
+ { homebranch => $library2->{branchcode}, holdingbranch => $library2->{branchcode} },
+ { homebranch => $library2->{branchcode}, holdingbranch => $library2->{branchcode} },
+ { homebranch => $library1->{branchcode}, holdingbranch => $library2->{branchcode} },
+ { homebranch => $library1->{branchcode}, holdingbranch => $library2->{branchcode} },
+ { homebranch => $library1->{branchcode}, holdingbranch => $library2->{branchcode} },
+ ];
+ my $number_of_items = scalar @$item_infos;
+ my $number_of_items_with_homebranch_is_CPL =
+ grep { $_->{homebranch} eq $library1->{branchcode} } @$item_infos;
+
+ my @itemnumbers;
+ for my $item_info (@$item_infos) {
+ my ( undef, undef, $itemnumber ) = AddItem(
+ {
+ homebranch => $item_info->{homebranch},
+ holdingbranch => $item_info->{holdingbanch},
+ itype => $itemtype->{itemtype},
+ },
+ $biblionumber
+ );
+ push @itemnumbers, $itemnumber;
+ }
+
+ # Emptied the OpacHiddenItems pref
+ t::lib::Mocks::mock_preference( 'OpacHiddenItems', '' );
+
+ my ($itemfield) =
+ C4::Biblio::GetMarcFromKohaField( 'items.itemnumber', '' );
+ my $record = C4::Biblio::GetMarcBiblio({ biblionumber => $biblionumber });
+ warning_is { C4::Biblio::EmbedItemsInMarcBiblio() }
+ { carped => 'EmbedItemsInMarcBiblio: No MARC record passed' },
+ 'Should carp is no record passed.';
+
+ C4::Biblio::EmbedItemsInMarcBiblio({
+ marc_record => $record,
+ biblionumber => $biblionumber });
+ my @items = $record->field($itemfield);
+ is( scalar @items, $number_of_items, 'Should return all items' );
+
+ my $marc_with_items = C4::Biblio::GetMarcBiblio({
+ biblionumber => $biblionumber,
+ embed_items => 1 });
+ is_deeply( $record, $marc_with_items, 'A direct call to GetMarcBiblio with items matches');
+
+ C4::Biblio::EmbedItemsInMarcBiblio({
+ marc_record => $record,
+ biblionumber => $biblionumber,
+ item_numbers => [ $itemnumbers[1], $itemnumbers[3] ] });
+ @items = $record->field($itemfield);
+ is( scalar @items, 2, 'Should return all items present in the list' );
+
+ C4::Biblio::EmbedItemsInMarcBiblio({
+ marc_record => $record,
+ biblionumber => $biblionumber,
+ opac => 1 });
+ @items = $record->field($itemfield);
+ is( scalar @items, $number_of_items, 'Should return all items for opac' );
+
+ my $opachiddenitems = "
+ homebranch: ['$library1->{branchcode}']";
+ t::lib::Mocks::mock_preference( 'OpacHiddenItems', $opachiddenitems );
+
+ C4::Biblio::EmbedItemsInMarcBiblio({
+ marc_record => $record,
+ biblionumber => $biblionumber });
+ @items = $record->field($itemfield);
+ is( scalar @items,
+ $number_of_items,
+ 'Even with OpacHiddenItems set, all items should have been embedded' );
+
+ C4::Biblio::EmbedItemsInMarcBiblio({
+ marc_record => $record,
+ biblionumber => $biblionumber,
+ opac => 1 });
+ @items = $record->field($itemfield);
+ is(
+ scalar @items,
+ $number_of_items - $number_of_items_with_homebranch_is_CPL,
+'For OPAC, the pref OpacHiddenItems should have been take into account. Only items with homebranch ne CPL should have been embedded'
+ );
+
+ $opachiddenitems = "
+ homebranch: ['$library1->{branchcode}', '$library2->{branchcode}']";
+ t::lib::Mocks::mock_preference( 'OpacHiddenItems', $opachiddenitems );
+ C4::Biblio::EmbedItemsInMarcBiblio({
+ marc_record => $record,
+ biblionumber => $biblionumber,
+ opac => 1 });
+ @items = $record->field($itemfield);
+ is(
+ scalar @items,
+ 0,
+'For OPAC, If all items are hidden, no item should have been embedded'
+ );
+
+ $schema->storage->txn_rollback;
+};
+
+
+subtest 'C4::Items::_build_default_values_for_mod_marc' => sub {
+ plan tests => 4;
+
+ $schema->storage->txn_begin();
+
+ my $builder = t::lib::TestBuilder->new;
+ my $framework = $builder->build({ source => 'BiblioFramework' });
+
+ # Link biblio.biblionumber and biblioitems.biblioitemnumber to avoid _koha_marc_update_bib_ids to fail with 'no biblio[item]number tag for framework"
+ Koha::MarcSubfieldStructures->search({ frameworkcode => '', tagfield => '999', tagsubfield => [ 'c', 'd' ] })->delete;
+ Koha::MarcSubfieldStructure->new({ frameworkcode => '', tagfield => '999', tagsubfield => 'c', kohafield => 'biblio.biblionumber' })->store;
+ Koha::MarcSubfieldStructure->new({ frameworkcode => '', tagfield => '999', tagsubfield => 'd', kohafield => 'biblioitems.biblioitemnumber' })->store;
+
+ # Same for item fields: itemnumber, barcode, itype
+ Koha::MarcSubfieldStructures->search({ frameworkcode => '', tagfield => '952', tagsubfield => [ '9', 'p', 'y' ] })->delete;
+ Koha::MarcSubfieldStructure->new({ frameworkcode => '', tagfield => '952', tagsubfield => '9', kohafield => 'items.itemnumber' })->store;
+ Koha::MarcSubfieldStructure->new({ frameworkcode => '', tagfield => '952', tagsubfield => 'p', kohafield => 'items.barcode' })->store;
+ Koha::MarcSubfieldStructure->new({ frameworkcode => '', tagfield => '952', tagsubfield => 'y', kohafield => 'items.itype' })->store;
+ Koha::Caches->get_instance->clear_from_cache( "MarcSubfieldStructure-" );
+
+ my $itemtype = $builder->build({ source => 'Itemtype' })->{itemtype};
+
+ # Create a record with a barcode
+ my ($biblionumber) = get_biblio( $framework->{frameworkcode} );
+ my $item_record = new MARC::Record;
+ my $a_barcode = 'a barcode';
+ my $barcode_field = MARC::Field->new(
+ '952', ' ', ' ',
+ p => $a_barcode,
+ y => $itemtype
+ );
+ my $itemtype_field = MARC::Field->new(
+ '952', ' ', ' ',
+ y => $itemtype
+ );
+ $item_record->append_fields( $barcode_field );
+ my (undef, undef, $item_itemnumber) = AddItemFromMarc($item_record, $biblionumber);
+
+ # Make sure everything has been set up
+ my $item = GetItem($item_itemnumber);
+ is( $item->{barcode}, $a_barcode, 'Everything has been set up correctly, the barcode is defined as expected' );
+
+ # Delete the barcode field and save the record
+ $item_record->delete_fields( $barcode_field );
+ $item_record->append_fields( $itemtype_field ); # itemtype is mandatory
+ ModItemFromMarc($item_record, $biblionumber, $item_itemnumber);
+ $item = GetItem($item_itemnumber);
+ is( $item->{barcode}, undef, 'The default value should have been set to the barcode, the field is mapped to a kohafield' );
+
+ # Re-add the barcode field and save the record
+ $item_record->append_fields( $barcode_field );
+ ModItemFromMarc($item_record, $biblionumber, $item_itemnumber);
+ $item = GetItem($item_itemnumber);
+ is( $item->{barcode}, $a_barcode, 'Everything has been set up correctly, the barcode is defined as expected' );
+
+ # Remove the mapping for barcode
+ Koha::MarcSubfieldStructures->search({ frameworkcode => '', tagfield => '952', tagsubfield => 'p' })->delete;
+
+ # And make sure the caches are cleared
+ my $cache = Koha::Caches->get_instance();
+ $cache->clear_from_cache("default_value_for_mod_marc-");
+ $cache->clear_from_cache("MarcSubfieldStructure-");
+
+ # Update the MARC field with another value
+ $item_record->delete_fields( $barcode_field );
+ my $another_barcode = 'another_barcode';
+ my $another_barcode_field = MARC::Field->new(
+ '952', ' ', ' ',
+ p => $another_barcode,
+ );
+ $item_record->append_fields( $another_barcode_field );
+ # The DB value should not have been updated
+ ModItemFromMarc($item_record, $biblionumber, $item_itemnumber);
+ $item = GetItem($item_itemnumber);
+ is ( $item->{barcode}, $a_barcode, 'items.barcode is not mapped anymore, so the DB column has not been updated' );
+
+ $cache->clear_from_cache("default_value_for_mod_marc-");
+ $cache->clear_from_cache( "MarcSubfieldStructure-" );
+ $schema->storage->txn_rollback;
+};
+
+subtest '_mod_item_dates' => sub {
+ plan tests => 11;
+
+ is( C4::Items::_mod_item_dates(), undef, 'Call without parameters' );
+ is( C4::Items::_mod_item_dates(1), undef, 'Call without hashref' );
+
+ my $orgitem;
+ my $item = {
+ itemcallnumber => 'V II 149 1963',
+ barcode => '109304',
+ };
+ $orgitem = { %$item };
+ C4::Items::_mod_item_dates($item);
+ is_deeply( $item, $orgitem, 'No dates passed to _mod_item_dates' );
+
+ # add two correct dates
+ t::lib::Mocks::mock_preference('dateformat', 'us');
+ $item->{dateaccessioned} = '01/31/2016';
+ $item->{onloan} = $item->{dateaccessioned};
+ $orgitem = { %$item };
+ C4::Items::_mod_item_dates($item);
+ is( $item->{dateaccessioned}, '2016-01-31', 'dateaccessioned is fine' );
+ is( $item->{onloan}, '2016-01-31', 'onloan is fine too' );
+
+
+ # add some invalid dates
+ $item->{notexistingcolumndate} = '13/1/2015'; # wrong format
+ $item->{anotherdate} = 'tralala'; # even worse
+ $item->{myzerodate} = '0000-00-00'; # wrong too
+ C4::Items::_mod_item_dates($item);
+ is( $item->{notexistingcolumndate}, undef, 'Invalid date became NULL' );
+ is( $item->{anotherdate}, undef, 'Second invalid date became NULL too' );
+ is( $item->{myzerodate}, undef, '0000-00-00 became NULL too' );
+
+ # check if itemlost_on was not touched
+ $item->{itemlost_on} = '12345678';
+ $item->{withdrawn_on} = '12/31/2015 23:59:00';
+ $item->{damaged_on} = '01/20/2017 09:00:00';
+ $orgitem = { %$item };
+ C4::Items::_mod_item_dates($item);
+ is_deeply( $item, $orgitem, 'Colums with _on are not touched' );
+
+ t::lib::Mocks::mock_preference('dateformat', 'metric');
+ $item->{dateaccessioned} = '01/31/2016'; #wrong
+ $item->{yetanotherdatetime} = '20/01/2016 13:58:00'; #okay
+ C4::Items::_mod_item_dates($item);
+ is( $item->{dateaccessioned}, undef, 'dateaccessioned wrong format' );
+ is( $item->{yetanotherdatetime}, '2016-01-20 13:58:00',
+ 'yetanotherdatetime is ok' );
+};
+
+subtest 'get_hostitemnumbers_of' => sub {
+ plan tests => 1;
+
+ $schema->storage->txn_begin;
+
+ my $bib = MARC::Record->new();
+ $bib->append_fields(
+ MARC::Field->new('100', ' ', ' ', a => 'Moffat, Steven'),
+ MARC::Field->new('245', ' ', ' ', a => 'Silence in the library'),
+ MARC::Field->new('773', ' ', ' ', b => 'b without 0 or 9'),
+ );
+ my ($biblionumber, $bibitemnum) = AddBiblio($bib, '');
+
+ my @itemnumbers = C4::Items::get_hostitemnumbers_of( $biblionumber );
+ is( @itemnumbers, 0, );
+
+ $schema->storage->txn_rollback;
+};
+
+subtest 'Test logging for ModItem' => sub {
+
+ plan tests => 3;
+
+ t::lib::Mocks::mock_preference('CataloguingLog', 1);
+
+ $schema->storage->txn_begin;
+
+ my $builder = t::lib::TestBuilder->new;
+ my $library = $builder->build({
+ source => 'Branch',
+ });
+ my $itemtype = $builder->build({
+ source => 'Itemtype',
+ });
+
+ # Create a biblio instance for testing
+ t::lib::Mocks::mock_preference('marcflavour', 'MARC21');
+ my ($bibnum, $bibitemnum) = get_biblio();
+
+ # Add an item.
+ my ($item_bibnum, $item_bibitemnum, $itemnumber) = AddItem({ homebranch => $library->{branchcode}, holdingbranch => $library->{branchcode}, location => $location, itype => $itemtype->{itemtype} } , $bibnum);
+
+ # False means no logging
+ $schema->resultset('ActionLog')->search()->delete();
+ ModItem({ location => $location }, $bibnum, $itemnumber, { log_action => 0 });
+ is( $schema->resultset('ActionLog')->count(), 0, 'False value does not trigger logging' );
+
+ # True means logging
+ $schema->resultset('ActionLog')->search()->delete();
+ ModItem({ location => $location }, $bibnum, $itemnumber, { log_action => 1 });
+ is( $schema->resultset('ActionLog')->count(), 1, 'True value does trigger logging' );
+
+ # Undefined defaults to true
+ $schema->resultset('ActionLog')->search()->delete();
+ ModItem({ location => $location }, $bibnum, $itemnumber);
+ is( $schema->resultset('ActionLog')->count(), 1, 'Undefined value defaults to true, triggers logging' );
+
+ $schema->storage->txn_rollback;
+};
+
+subtest 'Check stockrotationitem relationship' => sub {
+ plan tests => 1;
+
+ $schema->storage->txn_begin();
+
+ my $builder = t::lib::TestBuilder->new;
+ my $item = $builder->build({ source => 'Item' });
+
+ $builder->build({
+ source => 'Stockrotationitem',
+ value => { itemnumber_id => $item->{itemnumber} }
+ });
+
+ my $sritem = Koha::Items->find($item->{itemnumber})->stockrotationitem;
+ isa_ok( $sritem, 'Koha::StockRotationItem', "Relationship works and correctly creates Koha::Object." );
+
+ $schema->storage->txn_rollback;
+};
+
+subtest 'Check add_to_rota method' => sub {
+ plan tests => 2;
+
+ $schema->storage->txn_begin();
+
+ my $builder = t::lib::TestBuilder->new;
+ my $item = $builder->build({ source => 'Item' });
+ my $rota = $builder->build({ source => 'Stockrotationrota' });
+ my $srrota = Koha::StockRotationRotas->find($rota->{rota_id});
+
+ $builder->build({
+ source => 'Stockrotationstage',
+ value => { rota_id => $rota->{rota_id} },
+ });
+
+ my $sritem = Koha::Items->find($item->{itemnumber});
+ $sritem->add_to_rota($rota->{rota_id});
+
+ is(
+ Koha::StockRotationItems->find($item->{itemnumber})->stage_id,
+ $srrota->stockrotationstages->next->stage_id,
+ "Adding to a rota a new sritem item being assigned to its first stage."
+ );
+
+ my $newrota = $builder->build({ source => 'Stockrotationrota' });
+
+ my $srnewrota = Koha::StockRotationRotas->find($newrota->{rota_id});
+
+ $builder->build({
+ source => 'Stockrotationstage',
+ value => { rota_id => $newrota->{rota_id} },
+ });
+
+ $sritem->add_to_rota($newrota->{rota_id});
+
+ is(
+ Koha::StockRotationItems->find($item->{itemnumber})->stage_id,
+ $srnewrota->stockrotationstages->next->stage_id,
+ "Moving an item results in that sritem being assigned to the new first stage."
+ );
+
+ $schema->storage->txn_rollback;