4 use Test::More tests => 19;
7 use File::Temp qw/tempfile/;
10 use t::lib::TestBuilder;
13 use Koha::Import::Records;
16 # Mock pluginsdir before loading Plugins module
17 my $path = dirname(__FILE__) . '/../lib/plugins';
18 t::lib::Mocks::mock_config( 'pluginsdir', $path );
20 use_ok('Koha::Plugins');
21 use_ok('C4::ImportBatch', qw( AddImportBatch GetImportBatch AddBiblioToBatch AddItemsToImportBiblio SetMatchedBiblionumber GetImportBiblios GetItemNumbersFromImportBatch CleanBatch DeleteBatch RecordsFromMarcPlugin ));
25 my $schema = Koha::Database->new->schema;
26 $schema->storage->txn_begin;
27 my $builder = t::lib::TestBuilder->new;
28 my $dbh = C4::Context->dbh;
31 $dbh->do('DELETE FROM import_batches');
33 my $sample_import_batch1 = {
37 overlay_action => 'create_new',
38 nomatch_action => 'create_new',
39 item_action => 'always_add',
40 import_status => 'staged',
41 batch_type => 'z3950',
42 file_name => 'test.mrc',
44 record_type => 'auth',
47 my $sample_import_batch2 = {
51 overlay_action => 'create_new',
52 nomatch_action => 'create_new',
53 item_action => 'always_add',
54 import_status => 'staged',
55 batch_type => 'z3950',
56 file_name => 'test.mrc',
58 record_type => 'auth',
61 my $id_import_batch1 = C4::ImportBatch::AddImportBatch($sample_import_batch1);
62 my $id_import_batch2 = C4::ImportBatch::AddImportBatch($sample_import_batch2);
64 like( $id_import_batch1, '/^\d+$/', "AddImportBatch for sample_import_batch1 return an id" );
65 like( $id_import_batch2, '/^\d+$/', "AddImportBatch for sample_import_batch2 return an id" );
68 my $importbatch2 = C4::ImportBatch::GetImportBatch( $id_import_batch2 );
69 delete $importbatch2->{upload_timestamp};
70 delete $importbatch2->{import_batch_id};
71 delete $importbatch2->{num_records};
72 delete $importbatch2->{num_items};
73 delete $importbatch2->{profile_id};
74 delete $importbatch2->{profile};
76 is_deeply( $importbatch2, $sample_import_batch2,
77 "GetImportBatch returns the right informations about $sample_import_batch2" );
79 my $importbatch1 = C4::ImportBatch::GetImportBatch( $id_import_batch1 );
80 delete $importbatch1->{upload_timestamp};
81 delete $importbatch1->{import_batch_id};
82 delete $importbatch1->{num_records};
83 delete $importbatch1->{num_items};
84 delete $importbatch1->{profile_id};
85 delete $importbatch1->{profile};
87 is_deeply( $importbatch1, $sample_import_batch1,
88 "GetImportBatch returns the right informations about $sample_import_batch1" );
90 my $record = MARC::Record->new;
91 # FIXME Create another MARC::Record which won't be modified
92 # AddItemsToImportBiblio will remove the items field from the record passed in parameter.
93 my $original_record = MARC::Record->new;
94 $record->leader('03174nam a2200445 a 4500');
95 $original_record->leader('03174nam a2200445 a 4500');
96 my ($item_tag, $item_subfield) = C4::Biblio::GetMarcFromKohaField( 'items.itemnumber' );
98 if (C4::Context->preference('marcflavour') eq 'UNIMARC') {
102 a => '20220520d u||y0frey50 ba',
106 a => 'Knuth, Donald Ervin',
111 a => 'The art of computer programming',
112 f => 'Donald E. Knuth.',
116 a => 'Computer programming.',
127 i => 'my item part 2',
134 a => 'Knuth, Donald Ervin',
139 a => 'The art of computer programming',
140 c => 'Donald E. Knuth.',
144 a => 'Computer programming.',
155 i => 'my item part 2',
159 $record->append_fields(@fields);
160 $original_record->append_fields(@fields);
161 my $import_record_id = AddBiblioToBatch( $id_import_batch1, 0, $record, 'utf8', int(rand(99999)), 0 );
162 AddItemsToImportBiblio( $id_import_batch1, $import_record_id, $record, 0 );
164 my $import_record = Koha::Import::Records->find($import_record_id);
165 my $record_from_import_biblio_with_items = $import_record->get_marc_record({ embed_items => 1 });
166 $original_record->leader($record_from_import_biblio_with_items->leader());
167 is_deeply( $record_from_import_biblio_with_items, $original_record, 'Koha::Import::Record::get_marc_record should return the record with items if specified' );
168 my $utf8_field = $record_from_import_biblio_with_items->subfield($item_tag, 'e');
169 is($utf8_field, 'my edition ❤');
170 $original_record->delete_fields($original_record->field($item_tag)); #Remove items fields
171 my $record_from_import_biblio_without_items = $import_record->get_marc_record();
172 $original_record->leader($record_from_import_biblio_without_items->leader());
173 is_deeply( $record_from_import_biblio_without_items, $original_record, 'Koha::Import::Record::get_marc_record should return the record without items by default' );
175 my $another_biblio = $builder->build_sample_biblio;
176 C4::ImportBatch::SetMatchedBiblionumber( $import_record_id, $another_biblio->biblionumber );
177 my $import_biblios = GetImportBiblios( $import_record_id );
178 is( $import_biblios->[0]->{matched_biblionumber}, $another_biblio->biblionumber, 'SetMatchedBiblionumber should set the correct biblionumber' );
180 # Add a few tests for GetItemNumbersFromImportBatch
181 my @a = GetItemNumbersFromImportBatch( $id_import_batch1 );
182 is( @a, 0, 'No item numbers expected since we did not commit' );
183 my $itemno = $builder->build_sample_item->itemnumber;
184 # Link this item to the import item to fool GetItemNumbersFromImportBatch
185 my $sql = "UPDATE import_items SET itemnumber=? WHERE import_record_id=?";
186 $dbh->do( $sql, undef, $itemno, $import_record_id );
187 @a = GetItemNumbersFromImportBatch( $id_import_batch1 );
188 is( @a, 2, 'Expecting two items now' );
189 is( $a[0], $itemno, 'Check the first returned itemnumber' );
190 # Now delete the item and check again
191 $dbh->do( "DELETE FROM items WHERE itemnumber=?", undef, $itemno );
192 @a = GetItemNumbersFromImportBatch( $id_import_batch1 );
193 is( @a, 0, 'No item numbers expected since we deleted the item' );
194 $dbh->do( $sql, undef, undef, $import_record_id ); # remove link again
197 my $sample_import_batch3 = {
201 overlay_action => 'create_new',
202 nomatch_action => 'create_new',
203 item_action => 'always_add',
204 import_status => 'staged',
205 batch_type => 'z3950',
206 file_name => 'test.mrc',
208 record_type => 'auth',
211 my $id_import_batch3 = C4::ImportBatch::AddImportBatch($sample_import_batch3);
214 C4::ImportBatch::CleanBatch( $id_import_batch3 );
215 $import_record = get_import_record( $id_import_batch3 );
216 is( $import_record, "0E0", "Batch 3 has been cleaned" );
219 C4::ImportBatch::DeleteBatch( $id_import_batch3 );
220 my $import_batch = C4::ImportBatch::GetImportBatch( $id_import_batch3 );
221 is( $import_batch, undef, "Batch 3 has been deleted");
223 subtest "_batchCommitItems" => sub {
226 my $exist_item = $builder->build_sample_item;
227 my $import_item = $builder->build_object({ class => 'Koha::Import::Record::Items', value => {
228 marcxml => q{<?xml version="1.0" encoding="UTF-8"?>
230 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
231 xsi:schemaLocation="http://www.loc.gov/MARC21/slim http://www.loc.gov/standards/marcxml/schema/MARC21slim.xsd"
232 xmlns="http://www.loc.gov/MARC21/slim">
235 <leader>00000 a </leader>
236 <datafield tag="952" ind1=" " ind2=" ">
237 <subfield code="a">CPL</subfield>
238 <subfield code="b">CPL</subfield>
239 <subfield code="c">GEN</subfield>
240 <subfield code="p">}.$exist_item->barcode.q{</subfield>
241 <subfield code="y">BK</subfield>
248 my ( $num_items_added, $num_items_replaced, $num_items_errored ) =
249 C4::ImportBatch::_batchCommitItems( $import_item->import_record_id, 32, 'always_add',64 );
250 is( $num_items_errored, 1, "Item with duplicate barcode fails when action always_add" );
251 $import_item->discard_changes();
252 is( $import_item->status, 'error', "Import item marked as error when duplicate barcode and action always_add");
253 is( $import_item->import_error, 'duplicate item barcode', 'Error correctly set when import item has duplicate barcode and action always_add' );
256 subtest "RecordsFromMarcPlugin" => sub {
260 my ( $fh, $name ) = tempfile();
261 if (C4::Context->preference('marcflavour') eq 'UNIMARC') {
264 100,a = 20220520d u||y0frey50 ba
267 200,a = Silence in the library
271 245,a = Noise in the library};
278 245,a = Silence in the library
282 245,a = Noise in the library|;
286 t::lib::Mocks::mock_config( 'enable_plugins', 1 );
288 my $plugins = Koha::Plugins->new;
289 $plugins->InstallPlugins;
290 my ($plugin) = $plugins->GetPlugins({ all => 1, metadata => { name => 'MarcFieldValues' } });
291 isnt( $plugin, undef, "Plugin found" );
292 my $records = C4::ImportBatch::RecordsFromMarcPlugin( $name, ref $plugin, 'UTF-8' );
293 is( @$records, 2, 'Two results returned' );
294 is( ref $records->[0], 'MARC::Record', 'Returned MARC::Record object' );
295 if (C4::Context->preference('marcflavour') eq 'UNIMARC') {
296 is( $records->[0]->subfield('200', 'a'), 'Silence in the library',
297 'Checked one field in first record' );
298 is( $records->[1]->subfield('700', 'a'), 'Another',
299 'Checked one field in second record' );
301 is( $records->[0]->subfield('245', 'a'), 'Silence in the library',
302 'Checked one field in first record' );
303 is( $records->[1]->subfield('100', 'a'), 'Another',
304 'Checked one field in second record' );
308 subtest "_get_commit_action" => sub {
310 my $mock_import = Test::MockModule->new("C4::ImportBatch");
312 $mock_import->mock( GetBestRecordMatch => sub { return 5; } );
313 foreach my $record_type ( ('biblio','authority') ){
314 foreach my $match_action ( ('replace','create_new','ignore') ){
315 foreach my $no_match_action ( ('create_new','ignore') ){
316 my ($result, $match, $item_result) =
317 C4::ImportBatch::_get_commit_action($match_action, $no_match_action, 'always_add', 'auto_match', 42, $record_type);
318 is( $result, $match_action, "When match found amd chosen we return the match_action for $record_type records with match action $match_action and no match action $no_match_action");
323 $mock_import->mock( GetBestRecordMatch => sub { my $matches = undef; return $matches; } );
324 foreach my $record_type ( ('biblio','authority') ){
325 foreach my $match_action ( ('replace','create_new','ignore') ){
326 foreach my $no_match_action ( ('create_new','ignore') ){
327 my ($result, $match, $item_result) =
328 C4::ImportBatch::_get_commit_action($match_action, $no_match_action, 'always_add', 'auto_match', 42, $record_type);
329 is( $result, $no_match_action, "When no match found or chosen we return the match_action for $record_type records with match action $match_action and no match action $no_match_action");
336 sub get_import_record {
337 my $id_import_batch = shift;
338 return $dbh->do('SELECT * FROM import_records WHERE import_batch_id = ?', undef, $id_import_batch);
341 $schema->storage->txn_rollback;