4 use Test::More tests => 20;
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 BatchCommitRecords ));
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 my $original_record = MARC::Record->new;
92 $record->leader('03174nam a2200445 a 4500');
93 $original_record->leader('03174nam a2200445 a 4500');
94 my ($item_tag, $item_subfield) = C4::Biblio::GetMarcFromKohaField( 'items.itemnumber' );
96 if (C4::Context->preference('marcflavour') eq 'UNIMARC') {
100 a => '20220520d u||y0frey50 ba',
104 a => 'Knuth, Donald Ervin',
109 a => 'The art of computer programming',
110 f => 'Donald E. Knuth.',
114 a => 'Computer programming.',
125 i => 'my item part 2',
132 a => 'Knuth, Donald Ervin',
137 a => 'The art of computer programming',
138 c => 'Donald E. Knuth.',
142 a => 'Computer programming.',
153 i => 'my item part 2',
157 $record->append_fields(@fields);
158 $original_record->append_fields(@fields);
159 my $import_record_id = AddBiblioToBatch( $id_import_batch1, 0, $record, 'utf8', 0 );
160 AddItemsToImportBiblio( $id_import_batch1, $import_record_id, $record, 0 );
162 my $import_record = Koha::Import::Records->find($import_record_id);
163 my $record_from_import_biblio = $import_record->get_marc_record();
165 $original_record->leader($record_from_import_biblio->leader());
166 is_deeply( $record_from_import_biblio, $original_record, 'Koha::Import::Record::get_marc_record should return the record in original state' );
167 my $utf8_field = $record_from_import_biblio->subfield($item_tag, 'e');
168 is($utf8_field, 'my edition ❤');
170 my $another_biblio = $builder->build_sample_biblio;
171 C4::ImportBatch::SetMatchedBiblionumber( $import_record_id, $another_biblio->biblionumber );
172 my $import_biblios = GetImportBiblios( $import_record_id );
173 is( $import_biblios->[0]->{matched_biblionumber}, $another_biblio->biblionumber, 'SetMatchedBiblionumber should set the correct biblionumber' );
175 # Add a few tests for GetItemNumbersFromImportBatch
176 my @a = GetItemNumbersFromImportBatch( $id_import_batch1 );
177 is( @a, 0, 'No item numbers expected since we did not commit' );
178 my $itemno = $builder->build_sample_item->itemnumber;
179 # Link this item to the import item to fool GetItemNumbersFromImportBatch
180 my $sql = "UPDATE import_items SET itemnumber=? WHERE import_record_id=?";
181 $dbh->do( $sql, undef, $itemno, $import_record_id );
182 @a = GetItemNumbersFromImportBatch( $id_import_batch1 );
183 is( @a, 2, 'Expecting two items now' );
184 is( $a[0], $itemno, 'Check the first returned itemnumber' );
185 # Now delete the item and check again
186 $dbh->do( "DELETE FROM items WHERE itemnumber=?", undef, $itemno );
187 @a = GetItemNumbersFromImportBatch( $id_import_batch1 );
188 is( @a, 0, 'No item numbers expected since we deleted the item' );
189 $dbh->do( $sql, undef, undef, $import_record_id ); # remove link again
192 my $sample_import_batch3 = {
196 overlay_action => 'create_new',
197 nomatch_action => 'create_new',
198 item_action => 'always_add',
199 import_status => 'staged',
200 batch_type => 'z3950',
201 file_name => 'test.mrc',
203 record_type => 'auth',
206 my $id_import_batch3 = C4::ImportBatch::AddImportBatch($sample_import_batch3);
209 C4::ImportBatch::CleanBatch( $id_import_batch3 );
210 $import_record = get_import_record( $id_import_batch3 );
211 is( $import_record, "0E0", "Batch 3 has been cleaned" );
214 C4::ImportBatch::DeleteBatch( $id_import_batch3 );
215 my $import_batch = C4::ImportBatch::GetImportBatch( $id_import_batch3 );
216 is( $import_batch, undef, "Batch 3 has been deleted");
218 subtest "_batchCommitItems" => sub {
221 my $exist_item = $builder->build_sample_item;
222 my $import_item = $builder->build_object({ class => 'Koha::Import::Record::Items', value => {
223 marcxml => q{<?xml version="1.0" encoding="UTF-8"?>
225 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
226 xsi:schemaLocation="http://www.loc.gov/MARC21/slim http://www.loc.gov/standards/marcxml/schema/MARC21slim.xsd"
227 xmlns="http://www.loc.gov/MARC21/slim">
230 <leader>00000 a </leader>
231 <datafield tag="952" ind1=" " ind2=" ">
232 <subfield code="a">CPL</subfield>
233 <subfield code="b">CPL</subfield>
234 <subfield code="c">GEN</subfield>
235 <subfield code="p">}.$exist_item->barcode.q{</subfield>
236 <subfield code="y">BK</subfield>
243 my ( $num_items_added, $num_items_replaced, $num_items_errored ) =
244 C4::ImportBatch::_batchCommitItems( $import_item->import_record_id, 32, 'always_add',64 );
245 is( $num_items_errored, 1, "Item with duplicate barcode fails when action always_add" );
246 $import_item->discard_changes();
247 is( $import_item->status, 'error', "Import item marked as error when duplicate barcode and action always_add");
248 is( $import_item->import_error, 'duplicate item barcode', 'Error correctly set when import item has duplicate barcode and action always_add' );
251 subtest "RecordsFromMarcPlugin" => sub {
255 my ( $fh, $name ) = tempfile();
256 if (C4::Context->preference('marcflavour') eq 'UNIMARC') {
259 100,a = 20220520d u||y0frey50 ba
262 200,a = Silence in the library
266 245,a = Noise in the library};
273 245,a = Silence in the library
277 245,a = Noise in the library|;
281 t::lib::Mocks::mock_config( 'enable_plugins', 1 );
283 my $plugins = Koha::Plugins->new;
284 $plugins->InstallPlugins;
285 my ($plugin) = $plugins->GetPlugins({ all => 1, metadata => { name => 'MarcFieldValues' } });
286 isnt( $plugin, undef, "Plugin found" );
287 my $records = C4::ImportBatch::RecordsFromMarcPlugin( $name, ref $plugin, 'UTF-8' );
288 is( @$records, 2, 'Two results returned' );
289 is( ref $records->[0], 'MARC::Record', 'Returned MARC::Record object' );
290 if (C4::Context->preference('marcflavour') eq 'UNIMARC') {
291 is( $records->[0]->subfield('200', 'a'), 'Silence in the library',
292 'Checked one field in first record' );
293 is( $records->[1]->subfield('700', 'a'), 'Another',
294 'Checked one field in second record' );
296 is( $records->[0]->subfield('245', 'a'), 'Silence in the library',
297 'Checked one field in first record' );
298 is( $records->[1]->subfield('100', 'a'), 'Another',
299 'Checked one field in second record' );
303 subtest "_get_commit_action" => sub {
305 my $mock_import = Test::MockModule->new("C4::ImportBatch");
307 $mock_import->mock( GetBestRecordMatch => sub { return 5; } );
308 foreach my $record_type ( ('biblio','authority') ){
309 foreach my $match_action ( ('replace','create_new','ignore') ){
310 foreach my $no_match_action ( ('create_new','ignore') ){
311 my ($result, $match, $item_result) =
312 C4::ImportBatch::_get_commit_action($match_action, $no_match_action, 'always_add', 'auto_match', 42, $record_type);
313 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");
318 $mock_import->mock( GetBestRecordMatch => sub { my $matches = undef; return $matches; } );
319 foreach my $record_type ( ('biblio','authority') ){
320 foreach my $match_action ( ('replace','create_new','ignore') ){
321 foreach my $no_match_action ( ('create_new','ignore') ){
322 my ($result, $match, $item_result) =
323 C4::ImportBatch::_get_commit_action($match_action, $no_match_action, 'always_add', 'auto_match', 42, $record_type);
324 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");
331 subtest "BatchCommitRecords overlay into framework" => sub {
333 t::lib::Mocks::mock_config( 'enable_plugins', 0 );
334 my $mock_import = Test::MockModule->new("C4::ImportBatch");
335 my $biblio = $builder->build_sample_biblio;
336 $mock_import->mock( _get_commit_action => sub { return ('replace','ignore',$biblio->biblionumber); } );
342 overlay_action => 'replace',
343 nomatch_action => 'ignore',
344 item_action => 'ignore',
345 import_status => 'staged',
346 batch_type => 'z3950',
347 file_name => 'test.mrc',
349 record_type => 'auth',
351 my $id_import_batch = C4::ImportBatch::AddImportBatch($import_batch);
352 my $import_record_id = AddBiblioToBatch( $id_import_batch, 0, $biblio->metadata->record, 'utf8', 0 );
355 batch_id => $id_import_batch,
357 overlay_framework => "QQ",
359 $biblio->discard_changes;
360 is( $biblio->frameworkcode, "QQ", "Framework set on overlay" );
363 subtest "Do not adjust biblionumber when replacing items during import" => sub {
366 my $item1 = $builder->build_sample_item;
367 my $original_biblionumber = $item1->biblionumber;
368 my $original_biblioitemnumber = $item1->biblioitemnumber;
369 my $item2 = $builder->build_sample_item;
371 my $library = $builder->build_object({ class => 'Koha::Libraries' });
373 my $import_item = $builder->build_object({ class => 'Koha::Import::Record::Items', value => {
374 marcxml => qq{<?xml version="1.0" encoding="UTF-8"?>
376 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
377 xsi:schemaLocation="http://www.loc.gov/MARC21/slim http://www.loc.gov/standards/marcxml/schema/MARC21slim.xsd"
378 xmlns="http://www.loc.gov/MARC21/slim">
381 <leader>00000 a </leader>
382 <datafield tag="952" ind1=" " ind2=" ">
383 <subfield code="a">${\($library->branchcode)}</subfield>
384 <subfield code="b">${\($library->branchcode)}</subfield>
385 <subfield code="c">GEN</subfield>
386 <subfield code="p">${\($item1->barcode)}</subfield>
387 <subfield code="y">BK</subfield>
394 isnt( $item1->homebranch, $library->branchcode, "Item's homebranch is currently not the same as our created branch's branchcode" );
396 my ( $num_items_added, $num_items_replaced, $num_items_errored ) =
397 C4::ImportBatch::_batchCommitItems( $import_item->import_record_id, $item2->biblionumber, 'replace' );
399 $item1->discard_changes();
401 is( $num_items_errored, 0, 'Item was replaced' );
402 $import_item->discard_changes();
403 is( $import_item->status, 'imported', 'Import was successful');
404 is( $import_item->import_error, undef, 'No error was reported' );
406 is( $item1->biblionumber, $original_biblionumber, "Item's biblionumber has not changed" );
407 is( $item1->biblionumber, $original_biblioitemnumber, "Item's biblioitemnumber has not changed" );
408 is( $item1->homebranch, $library->branchcode, "Item was overlaid successfully" );
411 sub get_import_record {
412 my $id_import_batch = shift;
413 return $dbh->do('SELECT * FROM import_records WHERE import_batch_id = ?', undef, $id_import_batch);
416 $schema->storage->txn_rollback;