468 lines
17 KiB
Perl
Executable File
468 lines
17 KiB
Perl
Executable File
use Modern::Perl;
|
|
|
|
use Test::NoWarnings;
|
|
use Test::More tests => 8;
|
|
use Test::Warn;
|
|
|
|
use Koha::Items;
|
|
use Koha::Database::DataInconsistency;
|
|
|
|
use t::lib::TestBuilder;
|
|
use t::lib::Mocks;
|
|
|
|
my $builder = t::lib::TestBuilder->new;
|
|
|
|
my $schema = Koha::Database->new()->schema();
|
|
|
|
subtest 'invalid_item_library' => sub {
|
|
|
|
plan tests => 4;
|
|
|
|
$schema->storage->txn_begin();
|
|
|
|
my $biblio_ok = $builder->build_sample_biblio;
|
|
my $item_ok = $builder->build_sample_item( { biblionumber => $biblio_ok->biblionumber } );
|
|
my $biblio_ko = $builder->build_sample_biblio;
|
|
my $item_ko = $builder->build_sample_item( { biblionumber => $biblio_ko->biblionumber } );
|
|
|
|
my $items = Koha::Items->search( { biblionumber => [ $biblio_ok->biblionumber, $biblio_ko->biblionumber ] } );
|
|
|
|
subtest 'ok' => sub {
|
|
plan tests => 1;
|
|
|
|
my @errors = Koha::Database::DataInconsistency->invalid_item_library($items);
|
|
is_deeply( \@errors, [] );
|
|
|
|
};
|
|
subtest 'no homebranch, no holdingbranch' => sub {
|
|
plan tests => 1;
|
|
$item_ko->set( { homebranch => undef, holdingbranch => undef } )->store;
|
|
|
|
my @errors = Koha::Database::DataInconsistency->invalid_item_library($items);
|
|
is_deeply(
|
|
\@errors,
|
|
[ sprintf "Item with itemnumber=%s does not have home and holding library defined", $item_ko->itemnumber ]
|
|
);
|
|
};
|
|
|
|
subtest 'no homebranch' => sub {
|
|
plan tests => 1;
|
|
$item_ko->set( { homebranch => undef, holdingbranch => $item_ok->holdingbranch } )->store;
|
|
|
|
my @errors = Koha::Database::DataInconsistency->invalid_item_library($items);
|
|
is_deeply(
|
|
\@errors,
|
|
[ sprintf "Item with itemnumber=%s does not have a home library defined", $item_ko->itemnumber ]
|
|
);
|
|
};
|
|
|
|
subtest 'no holdingbranch' => sub {
|
|
plan tests => 1;
|
|
$item_ko->set( { homebranch => $item_ok->homebranch, holdingbranch => undef } )->store;
|
|
|
|
my @errors = Koha::Database::DataInconsistency->invalid_item_library($items);
|
|
is_deeply(
|
|
\@errors,
|
|
[ sprintf "Item with itemnumber=%s does not have a holding library defined", $item_ko->itemnumber ]
|
|
);
|
|
};
|
|
|
|
$schema->storage->txn_rollback();
|
|
};
|
|
|
|
subtest 'no_item_type' => sub {
|
|
|
|
plan tests => 2;
|
|
|
|
$schema->storage->txn_begin();
|
|
|
|
my $biblio_ok = $builder->build_sample_biblio;
|
|
my $item_ok = $builder->build_sample_item( { biblionumber => $biblio_ok->biblionumber } );
|
|
my $biblio_ko = $builder->build_sample_biblio;
|
|
my $item_ko = $builder->build_sample_item( { biblionumber => $biblio_ko->biblionumber } );
|
|
|
|
my $biblios = Koha::Biblios->search( { biblionumber => [ $biblio_ok->biblionumber, $biblio_ko->biblionumber ] } );
|
|
|
|
subtest 'item-level_itypes = 1' => sub {
|
|
plan tests => 3;
|
|
t::lib::Mocks::mock_preference( 'item-level_itypes', 1 );
|
|
subtest 'ok' => sub {
|
|
plan tests => 1;
|
|
my @errors = Koha::Database::DataInconsistency->no_item_type($biblios);
|
|
is_deeply( \@errors, [] );
|
|
};
|
|
subtest 'itype => undef' => sub {
|
|
plan tests => 2;
|
|
$item_ko->set( { itype => undef } );
|
|
Koha::Object::store($item_ko); # Do not call Koha::Item->store, it will set itype
|
|
$biblio_ko->biblioitem->set( { itemtype => $item_ok->itype } )->store;
|
|
|
|
my @errors = Koha::Database::DataInconsistency->no_item_type($biblios);
|
|
is_deeply(
|
|
\@errors,
|
|
[
|
|
sprintf
|
|
"Item with itemnumber=%s does not have an itype value, biblio's item type will be used (%s)",
|
|
$item_ko->itemnumber, $biblio_ko->itemtype
|
|
]
|
|
);
|
|
|
|
$biblio_ko->biblioitem->set( { itemtype => undef } )->store;
|
|
@errors = Koha::Database::DataInconsistency->no_item_type($biblios);
|
|
is_deeply(
|
|
\@errors,
|
|
[
|
|
sprintf
|
|
"Item with itemnumber=%s does not have an itype value, additionally no item type defined for biblionumber=%s",
|
|
$item_ko->itemnumber, $biblio_ko->biblionumber
|
|
]
|
|
);
|
|
};
|
|
subtest 'itype => ""' => sub {
|
|
plan tests => 2;
|
|
$item_ko->set( { itype => "" } );
|
|
Koha::Object::store($item_ko); # Do not call Koha::Item->store, it will set itype
|
|
$biblio_ko->biblioitem->set( { itemtype => $item_ok->itype } )->store;
|
|
|
|
my @errors = Koha::Database::DataInconsistency->no_item_type($biblios);
|
|
is_deeply(
|
|
\@errors,
|
|
[
|
|
sprintf
|
|
"Item with itemnumber=%s does not have an itype value, biblio's item type will be used (%s)",
|
|
$item_ko->itemnumber, $biblio_ko->itemtype
|
|
]
|
|
);
|
|
|
|
$biblio_ko->biblioitem->set( { itemtype => undef } )->store;
|
|
@errors = Koha::Database::DataInconsistency->no_item_type($biblios);
|
|
is_deeply(
|
|
\@errors,
|
|
[
|
|
sprintf
|
|
"Item with itemnumber=%s does not have an itype value, additionally no item type defined for biblionumber=%s",
|
|
$item_ko->itemnumber, $biblio_ko->biblionumber
|
|
]
|
|
);
|
|
};
|
|
};
|
|
|
|
subtest 'item-level_itypes = 0' => sub {
|
|
plan tests => 3;
|
|
t::lib::Mocks::mock_preference( 'item-level_itypes', 0 );
|
|
subtest 'ok' => sub {
|
|
plan tests => 1;
|
|
$biblio_ko->biblioitem->set( { itemtype => $item_ok->itype } )->store;
|
|
my @errors = Koha::Database::DataInconsistency->no_item_type($biblios);
|
|
is_deeply( \@errors, [] );
|
|
};
|
|
subtest 'itemtype => undef' => sub {
|
|
plan tests => 1;
|
|
$biblio_ko->biblioitem->set( { itemtype => undef } )->store;
|
|
|
|
my @errors = Koha::Database::DataInconsistency->no_item_type($biblios);
|
|
is_deeply(
|
|
\@errors,
|
|
[
|
|
sprintf "Biblioitem with biblioitemnumber=%s does not have an itemtype value",
|
|
$biblio_ko->biblioitem->biblioitemnumber
|
|
]
|
|
);
|
|
};
|
|
subtest 'itemtype => ""' => sub {
|
|
plan tests => 1;
|
|
$biblio_ko->biblioitem->set( { itemtype => '' } )->store;
|
|
|
|
my @errors = Koha::Database::DataInconsistency->no_item_type($biblios);
|
|
is_deeply(
|
|
\@errors,
|
|
[
|
|
sprintf "Biblioitem with biblioitemnumber=%s does not have an itemtype value",
|
|
$biblio_ko->biblioitem->biblioitemnumber
|
|
]
|
|
);
|
|
};
|
|
};
|
|
$schema->storage->txn_rollback();
|
|
};
|
|
|
|
subtest 'invalid_item_type' => sub {
|
|
|
|
plan tests => 2;
|
|
|
|
$schema->storage->txn_begin();
|
|
|
|
my $biblio_ok = $builder->build_sample_biblio;
|
|
my $item_ok = $builder->build_sample_item( { biblionumber => $biblio_ok->biblionumber } );
|
|
my $biblio_ko = $builder->build_sample_biblio;
|
|
my $item_ko = $builder->build_sample_item( { biblionumber => $biblio_ko->biblionumber } );
|
|
|
|
my $biblios = Koha::Biblios->search( { biblionumber => [ $biblio_ok->biblionumber, $biblio_ko->biblionumber ] } );
|
|
|
|
my $itemtype = $builder->build_object( { class => 'Koha::ItemTypes' } );
|
|
my $deleted_itemtype = $itemtype->itemtype;
|
|
$itemtype->delete;
|
|
|
|
subtest 'item-level_itypes = 1' => sub {
|
|
plan tests => 2;
|
|
t::lib::Mocks::mock_preference( 'item-level_itypes', 1 );
|
|
subtest 'ok' => sub {
|
|
plan tests => 1;
|
|
my @errors = Koha::Database::DataInconsistency->invalid_item_type($biblios);
|
|
is_deeply( \@errors, [] );
|
|
};
|
|
subtest 'itype is invalid' => sub {
|
|
plan tests => 2;
|
|
$item_ko->set( { itype => $deleted_itemtype } );
|
|
Koha::Object::store($item_ko); # Do not call Koha::Item->store, it will set itype
|
|
|
|
my @errors = Koha::Database::DataInconsistency->invalid_item_type($biblios);
|
|
is_deeply(
|
|
\@errors,
|
|
[
|
|
sprintf "Item with itemnumber=%s, biblionumber=%s does not have a valid itype value (%s)",
|
|
$item_ko->itemnumber, $item_ko->biblionumber, $item_ko->itype
|
|
]
|
|
);
|
|
|
|
$item_ko->set( { itype => '' } );
|
|
Koha::Object::store($item_ko); # Do not call Koha::Item->store, it will set itype
|
|
@errors = Koha::Database::DataInconsistency->invalid_item_type($biblios);
|
|
|
|
# Does not alert here, it's caught already in no_item_type
|
|
is_deeply( \@errors, [] );
|
|
};
|
|
};
|
|
|
|
subtest 'item-level_itypes = 0' => sub {
|
|
plan tests => 2;
|
|
t::lib::Mocks::mock_preference( 'item-level_itypes', 0 );
|
|
subtest 'ok' => sub {
|
|
plan tests => 1;
|
|
my @errors = Koha::Database::DataInconsistency->invalid_item_type($biblios);
|
|
is_deeply( \@errors, [] );
|
|
};
|
|
subtest 'itemtype is invalid' => sub {
|
|
plan tests => 2;
|
|
$biblio_ko->biblioitem->set( { itemtype => $deleted_itemtype } )->store;
|
|
|
|
my @errors = Koha::Database::DataInconsistency->invalid_item_type($biblios);
|
|
is_deeply(
|
|
\@errors,
|
|
[
|
|
sprintf "Biblioitem with biblioitemnumber=%s does not have a valid itemtype value (%s)",
|
|
$biblio_ko->biblioitem->biblioitemnumber, $biblio_ko->biblioitem->itemtype
|
|
]
|
|
);
|
|
|
|
$biblio_ko->biblioitem->set( { itemtype => ' ' } )->store;
|
|
@errors = Koha::Database::DataInconsistency->invalid_item_type($biblios);
|
|
|
|
# Does not alert here, it's caught already in no_item_type
|
|
is_deeply( \@errors, [] );
|
|
};
|
|
};
|
|
|
|
$schema->storage->txn_rollback();
|
|
};
|
|
|
|
subtest 'errors_in_marc' => sub {
|
|
|
|
plan tests => 4;
|
|
|
|
$schema->storage->txn_begin();
|
|
|
|
my $biblio_ok = $builder->build_sample_biblio;
|
|
my $item_ok = $builder->build_sample_item( { biblionumber => $biblio_ok->biblionumber } );
|
|
my $biblio_ko = $builder->build_sample_biblio;
|
|
my $item_ko = $builder->build_sample_item( { biblionumber => $biblio_ko->biblionumber } );
|
|
|
|
my $biblios = Koha::Biblios->search( { biblionumber => [ $biblio_ok->biblionumber, $biblio_ko->biblionumber ] } );
|
|
|
|
my $itemtype = $builder->build_object( { class => 'Koha::ItemTypes' } );
|
|
my $deleted_itemtype = $itemtype->itemtype;
|
|
$itemtype->delete;
|
|
|
|
subtest 'ok' => sub {
|
|
plan tests => 3;
|
|
my $errors = Koha::Database::DataInconsistency->errors_in_marc($biblios);
|
|
ok( !exists $errors->{decoding_errors} );
|
|
ok( !exists $errors->{ids_not_in_marc} );
|
|
ok( !exists $errors->{item_fields_in_marc} );
|
|
};
|
|
|
|
subtest 'ids_not_in_marc' => sub {
|
|
plan tests => 2;
|
|
$schema->storage->txn_begin();
|
|
my ( $biblio_tag, $biblio_subfield ) = C4::Biblio::GetMarcFromKohaField("biblio.biblionumber");
|
|
my ( $biblioitem_tag, $biblioitem_subfield ) = C4::Biblio::GetMarcFromKohaField("biblioitems.biblioitemnumber");
|
|
my $record = $biblio_ko->metadata->record;
|
|
if ( my $field = $record->field($biblio_tag) ) {
|
|
$field->update( $biblio_subfield => '-42' );
|
|
}
|
|
$biblio_ko->metadata->metadata( $record->as_xml )->store;
|
|
|
|
my $errors = Koha::Database::DataInconsistency->errors_in_marc($biblios);
|
|
is_deeply(
|
|
$errors->{ids_not_in_marc},
|
|
[
|
|
sprintf q{Biblionumber %s has '%s' in %s$%s}, $biblio_ko->biblionumber, '-42', $biblio_tag,
|
|
$biblio_subfield
|
|
]
|
|
);
|
|
|
|
$record = $biblio_ko->metadata->record;
|
|
if ( my $field = $record->field($biblioitem_tag) ) {
|
|
$field->update( $biblioitem_subfield => '-42' );
|
|
}
|
|
$biblio_ko->metadata->metadata( $record->as_xml )->store;
|
|
|
|
$errors = Koha::Database::DataInconsistency->errors_in_marc($biblios);
|
|
is_deeply(
|
|
$errors->{ids_not_in_marc},
|
|
[
|
|
sprintf(
|
|
q{Biblionumber %s has '%s' in %s$%s}, $biblio_ko->biblionumber, '-42', $biblio_tag,
|
|
$biblio_subfield
|
|
),
|
|
sprintf(
|
|
q{Biblionumber %s has biblioitemnumber '%s' but should be '%s' in %s$%s}, $biblio_ko->biblionumber,
|
|
'-42', $biblio_ko->biblioitem->biblioitemnumber, $biblioitem_tag, $biblioitem_subfield
|
|
)
|
|
]
|
|
);
|
|
|
|
$schema->storage->txn_rollback();
|
|
};
|
|
|
|
subtest 'item_fields_in_marc' => sub {
|
|
plan tests => 1;
|
|
$schema->storage->txn_begin();
|
|
my ( $item_tag, $item_subfield ) = C4::Biblio::GetMarcFromKohaField("items.itemnumber");
|
|
my $record = $biblio_ko->metadata->record;
|
|
$record->append_fields( MARC::Field->new( $item_tag, '', '', $item_subfield => 'booh' ) );
|
|
$biblio_ko->metadata->metadata( $record->as_xml )->store;
|
|
|
|
my $errors = Koha::Database::DataInconsistency->errors_in_marc($biblios);
|
|
is_deeply(
|
|
$errors->{item_fields_in_marc},
|
|
[ sprintf q{Biblionumber %s has item fields (%s) in the marc record}, $biblio_ko->biblionumber, $item_tag ]
|
|
);
|
|
|
|
$schema->storage->txn_rollback();
|
|
};
|
|
|
|
subtest 'decoding_errors' => sub {
|
|
plan tests => 2;
|
|
$schema->storage->txn_begin();
|
|
my $biblio_metadata = $biblio_ko->metadata;
|
|
$biblio_metadata->metadata('oops');
|
|
Koha::Object::store($biblio_metadata);
|
|
my $errors;
|
|
warning_like {
|
|
$errors = Koha::Database::DataInconsistency->errors_in_marc($biblios);
|
|
}
|
|
qr{parser error};
|
|
like( $errors->{decoding_errors}->[0], qr{Invalid data, cannot decode metadata object} );
|
|
$schema->storage->txn_rollback();
|
|
};
|
|
|
|
$schema->storage->txn_rollback();
|
|
};
|
|
|
|
subtest 'nonexistent_AV' => sub {
|
|
|
|
plan tests => 2;
|
|
|
|
$schema->storage->txn_begin();
|
|
|
|
my $biblio_ok = $builder->build_sample_biblio;
|
|
my $item_ok = $builder->build_sample_item( { biblionumber => $biblio_ok->biblionumber } );
|
|
my $biblio_ko = $builder->build_sample_biblio;
|
|
my $item_ko = $builder->build_sample_item( { biblionumber => $biblio_ko->biblionumber } );
|
|
|
|
my $biblios = Koha::Biblios->search( { biblionumber => [ $biblio_ok->biblionumber, $biblio_ko->biblionumber ] } );
|
|
|
|
subtest 'ok' => sub {
|
|
plan tests => 1;
|
|
my @errors = Koha::Database::DataInconsistency->nonexistent_AV($biblios);
|
|
is_deeply( \@errors, [] );
|
|
};
|
|
|
|
subtest 'ccode not an AV' => sub {
|
|
plan tests => 1;
|
|
$item_ko->set( { withdrawn => -1 } )->store;
|
|
my @errors = Koha::Database::DataInconsistency->nonexistent_AV($biblios);
|
|
is( scalar(@errors), 1 );
|
|
};
|
|
};
|
|
|
|
subtest 'empty_title' => sub {
|
|
|
|
plan tests => 3;
|
|
|
|
$schema->storage->txn_begin();
|
|
|
|
my $biblio_ok = $builder->build_sample_biblio;
|
|
my $item_ok = $builder->build_sample_item( { biblionumber => $biblio_ok->biblionumber } );
|
|
my $biblio_ko = $builder->build_sample_biblio;
|
|
my $item_ko = $builder->build_sample_item( { biblionumber => $biblio_ko->biblionumber } );
|
|
|
|
my $biblios = Koha::Biblios->search( { biblionumber => [ $biblio_ok->biblionumber, $biblio_ko->biblionumber ] } );
|
|
|
|
subtest 'ok' => sub {
|
|
plan tests => 1;
|
|
my @errors = Koha::Database::DataInconsistency->empty_title($biblios);
|
|
is_deeply( \@errors, [] );
|
|
};
|
|
|
|
subtest 'title => undef' => sub {
|
|
plan tests => 1;
|
|
$biblio_ko->set( { title => undef } )->store;
|
|
my @errors = Koha::Database::DataInconsistency->empty_title($biblios);
|
|
is_deeply(
|
|
\@errors,
|
|
[ sprintf 'Biblio with biblionumber=%s does not have title defined', $biblio_ko->biblionumber ]
|
|
);
|
|
};
|
|
|
|
subtest 'title => ""' => sub {
|
|
plan tests => 1;
|
|
$biblio_ko->set( { title => q{} } )->store;
|
|
my @errors = Koha::Database::DataInconsistency->empty_title($biblios);
|
|
is_deeply(
|
|
\@errors,
|
|
[ sprintf 'Biblio with biblionumber=%s does not have title defined', $biblio_ko->biblionumber ]
|
|
);
|
|
};
|
|
};
|
|
|
|
subtest 'for_biblio' => sub {
|
|
|
|
plan tests => 1;
|
|
|
|
$schema->storage->txn_begin();
|
|
|
|
my $biblio_ok = $builder->build_sample_biblio;
|
|
my $item_ok = $builder->build_sample_item( { biblionumber => $biblio_ok->biblionumber } );
|
|
|
|
subtest 'ok' => sub {
|
|
plan tests => 1;
|
|
my $errors = Koha::Database::DataInconsistency->for_biblio($biblio_ok);
|
|
is_deeply(
|
|
$errors,
|
|
{
|
|
decoding_errors => [],
|
|
empty_title => [],
|
|
ids_not_in_marc => [],
|
|
invalid_item_library => [],
|
|
invalid_item_type => [],
|
|
item_fields_in_marc => [],
|
|
no_item_type => [],
|
|
nonexistent_AV => []
|
|
}
|
|
);
|
|
};
|
|
|
|
};
|