Bug 23012: (QA follow-up) Combine method to get both values
[koha.git] / t / db_dependent / ImportBatch.t
1 #!/usr/bin/perl
2
3 use Modern::Perl;
4 use Test::More tests => 18;
5 use utf8;
6 use File::Basename;
7 use File::Temp qw/tempfile/;
8
9 use t::lib::Mocks;
10 use t::lib::TestBuilder;
11
12 use Koha::Database;
13 use Koha::Import::Records;
14
15 BEGIN {
16     # Mock pluginsdir before loading Plugins module
17     my $path = dirname(__FILE__) . '/../lib/plugins';
18     t::lib::Mocks::mock_config( 'pluginsdir', $path );
19
20     use_ok('Koha::Plugins');
21     use_ok('C4::ImportBatch', qw( AddImportBatch GetImportBatch AddBiblioToBatch AddItemsToImportBiblio SetMatchedBiblionumber GetImportBiblios GetItemNumbersFromImportBatch CleanBatch DeleteBatch RecordsFromMarcPlugin ));
22 }
23
24 # Start transaction
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;
29
30 # clear
31 $dbh->do('DELETE FROM import_batches');
32
33 my $sample_import_batch1 = {
34     matcher_id => 1,
35     template_id => 1,
36     branchcode => 'QRT',
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',
43     comments => 'test',
44     record_type => 'auth',
45 };
46
47 my $sample_import_batch2 = {
48     matcher_id => 2,
49     template_id => 2,
50     branchcode => 'QRZ',
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',
57     comments => 'test',
58     record_type => 'auth',
59 };
60
61 my $id_import_batch1 = C4::ImportBatch::AddImportBatch($sample_import_batch1);
62 my $id_import_batch2 = C4::ImportBatch::AddImportBatch($sample_import_batch2);
63
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" );
66
67 #Test GetImportBatch
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};
75
76 is_deeply( $importbatch2, $sample_import_batch2,
77     "GetImportBatch returns the right informations about $sample_import_batch2" );
78
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};
86
87 is_deeply( $importbatch1, $sample_import_batch1,
88     "GetImportBatch returns the right informations about $sample_import_batch1" );
89
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' );
95 my @fields;
96 if (C4::Context->preference('marcflavour') eq 'UNIMARC') {
97     @fields = (
98         MARC::Field->new(
99             100, ' ', ' ',
100             a => '20220520d        u||y0frey50      ba',
101         ),
102         MARC::Field->new(
103             700, ' ', ' ',
104             a => 'Knuth, Donald Ervin',
105             f => '1938',
106         ),
107         MARC::Field->new(
108             200, ' ', ' ',
109             a => 'The art of computer programming',
110             f => 'Donald E. Knuth.',
111         ),
112         MARC::Field->new(
113             650, ' ', '0',
114             a => 'Computer programming.',
115             9 => '462',
116         ),
117         MARC::Field->new(
118             $item_tag, ' ', ' ',
119             e => 'my edition ❤',
120             i => 'my item part',
121         ),
122         MARC::Field->new(
123             $item_tag, ' ', ' ',
124             e => 'my edition 2',
125             i => 'my item part 2',
126         ),
127     );
128 } else {
129     @fields = (
130         MARC::Field->new(
131             100, '1', ' ',
132             a => 'Knuth, Donald Ervin',
133             d => '1938',
134         ),
135         MARC::Field->new(
136             245, '1', '4',
137             a => 'The art of computer programming',
138             c => 'Donald E. Knuth.',
139         ),
140         MARC::Field->new(
141             650, ' ', '0',
142             a => 'Computer programming.',
143             9 => '462',
144         ),
145         MARC::Field->new(
146             $item_tag, ' ', ' ',
147             e => 'my edition ❤',
148             i => 'my item part',
149         ),
150         MARC::Field->new(
151             $item_tag, ' ', ' ',
152             e => 'my edition 2',
153             i => 'my item part 2',
154         ),
155     );
156 }
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 );
161
162 my $import_record = Koha::Import::Records->find($import_record_id);
163 my $record_from_import_biblio = $import_record->get_marc_record();
164
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 ❤');
169
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' );
174
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
190
191 # fresh data
192 my $sample_import_batch3 = {
193     matcher_id => 3,
194     template_id => 3,
195     branchcode => 'QRT',
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',
202     comments => 'test',
203     record_type => 'auth',
204 };
205
206 my $id_import_batch3 = C4::ImportBatch::AddImportBatch($sample_import_batch3);
207
208 # Test CleanBatch
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" );
212
213 # Test DeleteBatch
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");
217
218 subtest "_batchCommitItems" => sub {
219     plan tests => 3;
220
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"?>
224 <collection
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">
228
229 <record>
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>
237   </datafield>
238 </record>
239 </collection>
240         },
241     }});
242
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' );
249 };
250
251 subtest "RecordsFromMarcPlugin" => sub {
252     plan tests => 5;
253
254     # Create a test file
255     my ( $fh, $name ) = tempfile();
256     if (C4::Context->preference('marcflavour') eq 'UNIMARC') {
257         print $fh q{
258 003 = NLAmRIJ
259 100,a = 20220520d        u||y0frey50      ba
260 700,a = Author
261 200,ind2 = 0
262 200,a = Silence in the library
263 500 , a= Some note
264
265 700,a = Another
266 245,a = Noise in the library};
267         close $fh;
268     } else {
269         print $fh q|
270 003 = NLAmRIJ
271 100,a = Author
272 245,ind2 = 0
273 245,a = Silence in the library
274 500 , a= Some note
275
276 100,a = Another
277 245,a = Noise in the library|;
278         close $fh;
279     }
280
281     t::lib::Mocks::mock_config( 'enable_plugins', 1 );
282
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' );
295     } else {
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' );
300     }
301 };
302
303 subtest "_get_commit_action" => sub {
304     plan tests => 24;
305     my $mock_import = Test::MockModule->new("C4::ImportBatch");
306
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");
314             }
315         }
316     }
317
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");
325             }
326         }
327     }
328
329 };
330
331 sub get_import_record {
332     my $id_import_batch = shift;
333     return $dbh->do('SELECT * FROM import_records WHERE import_batch_id = ?', undef, $id_import_batch);
334 }
335
336 $schema->storage->txn_rollback;