Bug 20486: Add --marc_conditions option to export_records.pl
[koha.git] / t / db_dependent / Exporter / Record.t
1 #!/usr/bin/perl
2
3 # This file is part of Koha.
4 #
5 # Koha is free software; you can redistribute it and/or modify it
6 # under the terms of the GNU General Public License as published by
7 # the Free Software Foundation; either version 3 of the License, or
8 # (at your option) any later version.
9 #
10 # Koha is distributed in the hope that it will be useful, but
11 # WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # GNU General Public License for more details.
14 #
15 # You should have received a copy of the GNU General Public License
16 # along with Koha; if not, see <http://www.gnu.org/licenses>.
17
18 use Modern::Perl;
19
20 use Test::More tests => 6;
21 use Test::Warn;
22 use t::lib::TestBuilder;
23
24 use MARC::Record;
25 use MARC::File::USMARC;
26 use MARC::File::XML;
27 use MARC::Batch;
28 use File::Slurp;
29 use Encode;
30
31 use C4::Biblio;
32 use C4::Context;
33 use Koha::Database;
34 use Koha::Biblio;
35 use Koha::Biblioitem;
36 use Koha::Exporter::Record;
37 use Koha::Biblio::Metadata;
38
39 my $schema  = Koha::Database->new->schema;
40 $schema->storage->txn_begin;
41
42 my $dbh = C4::Context->dbh;
43
44 my $biblio_1_title = 'Silence in the library';
45 my $biblio_2_title = 'The art of computer programming ກ ຂ ຄ ງ ຈ ຊ ຍ é';
46 my $biblio_1 = MARC::Record->new();
47 $biblio_1->leader('00266nam a22001097a 4500');
48 $biblio_1->append_fields(
49     MARC::Field->new('100', ' ', ' ', a => 'Moffat, Steven'),
50     MARC::Field->new('245', ' ', ' ', a => $biblio_1_title),
51 );
52 my ($biblionumber_1, $biblioitemnumber_1) = AddBiblio($biblio_1, '');
53 my $biblio_2 = MARC::Record->new();
54 $biblio_2->leader('00266nam a22001097a 4500');
55 $biblio_2->append_fields(
56     MARC::Field->new('100', ' ', ' ', a => 'Knuth, Donald Ervin'),
57     MARC::Field->new('245', ' ', ' ', a => $biblio_2_title),
58 );
59 my ($biblionumber_2, $biblioitemnumber_2) = AddBiblio($biblio_2, '');
60
61 my $bad_biblio = Koha::Biblio->new()->store();
62 Koha::Biblio::Metadata->new( { biblionumber => $bad_biblio->id, format => 'marcxml', metadata => 'something wrong', marcflavour => C4::Context->preference('marcflavour') } )->store();
63 my $bad_biblionumber = $bad_biblio->id;
64
65 my $builder = t::lib::TestBuilder->new;
66 my $item_1_1 = $builder->build({
67     source => 'Item',
68     value => {
69         biblionumber => $biblionumber_1,
70         more_subfields_xml => '',
71     }
72 });
73 my $item_1_2 = $builder->build({
74     source => 'Item',
75     value => {
76         biblionumber => $biblionumber_1,
77         more_subfields_xml => '',
78     }
79 });
80 my $item_2_1 = $builder->build({
81     source => 'Item',
82     value => {
83         biblionumber => $biblionumber_2,
84         more_subfields_xml => '',
85     }
86 });
87 my $bad_item = $builder->build({
88     source => 'Item',
89     value => {
90         biblionumber => $bad_biblionumber,
91         more_subfields_xml => '',
92     }
93 });
94
95 subtest 'export csv' => sub {
96     plan tests => 3;
97     my $csv_content = q{Title=245$a|Barcode=952$p};
98     $dbh->do(q|INSERT INTO export_format(profile, description, content, csv_separator, field_separator, subfield_separator, encoding, type) VALUES (?, ?, ?, ?, ?, ?, ?, ?)|, {}, "TEST_PROFILE_Records.t", "my useless desc", $csv_content, '|', ';', ',', 'utf8', 'marc');
99     my $csv_profile_id = $dbh->last_insert_id( undef, undef, 'export_format', undef );
100     my $generated_csv_file = '/tmp/test_export_1.csv';
101
102     # Get all item infos
103     warning_like {
104         Koha::Exporter::Record::export(
105             {   record_type     => 'bibs',
106                 record_ids      => [ $biblionumber_1, $bad_biblionumber, $biblionumber_2 ],
107                 format          => 'csv',
108                 csv_profile_id  => $csv_profile_id,
109                 output_filepath => $generated_csv_file,
110             }
111         );
112     }
113     qr|.*Start tag expected.*|, "Export csv with wrong marcxml should raise a warning";
114     my $expected_csv = <<EOF;
115 Title|Barcode
116 "$biblio_1_title"|$item_1_1->{barcode},$item_1_2->{barcode}
117 "$biblio_2_title"|$item_2_1->{barcode}
118 EOF
119     my $generated_csv_content = read_file( $generated_csv_file );
120     is( $generated_csv_content, $expected_csv, "Export CSV: All item's infos should have been retrieved" );
121
122     $generated_csv_file = '/tmp/test_export.csv';
123     # Get only 1 item info
124     Koha::Exporter::Record::export(
125         {
126             record_type => 'bibs',
127             record_ids => [ $biblionumber_1, $biblionumber_2 ],
128             itemnumbers => [ $item_1_1->{itemnumber}, $item_2_1->{itemnumber} ],
129             format => 'csv',
130             csv_profile_id => $csv_profile_id,
131             output_filepath => $generated_csv_file,
132         }
133     );
134     $expected_csv = <<EOF;
135 Title|Barcode
136 "$biblio_1_title"|$item_1_1->{barcode}
137 "$biblio_2_title"|$item_2_1->{barcode}
138 EOF
139     $generated_csv_content = read_file( $generated_csv_file );
140     is( $generated_csv_content, $expected_csv, "Export CSV: Only 1 item info should have been retrieved" );
141 };
142
143 subtest 'export xml' => sub {
144     plan tests => 3;
145     my $generated_xml_file = '/tmp/test_export.xml';
146     warning_like {
147         Koha::Exporter::Record::export(
148             {   record_type     => 'bibs',
149                 record_ids      => [ $biblionumber_1, $bad_biblionumber, $biblionumber_2 ],
150                 format          => 'xml',
151                 output_filepath => $generated_xml_file,
152             }
153         );
154     }
155     qr|.*Start tag expected.*|, "Export xml with wrong marcxml should raise a warning";
156
157     my $generated_xml_content = read_file( $generated_xml_file );
158     $MARC::File::XML::_load_args{BinaryEncoding} = 'utf-8';
159     open my $fh, '<', $generated_xml_file;
160     my $records = MARC::Batch->new( 'XML', $fh );
161     my @records;
162     # The following statement produces
163     # Use of uninitialized value in concatenation (.) or string at /usr/share/perl5/MARC/File/XML.pm line 398, <$fh> chunk 5.
164     # Why?
165     while ( my $record = $records->next ) {
166         push @records, $record;
167     }
168     is( scalar( @records ), 2, 'Export XML: 2 records should have been exported' );
169     my $second_record = $records[1];
170     my $title = $second_record->subfield(245, 'a');
171     $title = Encode::encode('UTF-8', $title);
172     is( $title, $biblio_2_title, 'Export XML: The title is correctly encoded' );
173 };
174
175 subtest 'export iso2709' => sub {
176     plan tests => 3;
177     my $generated_mrc_file = '/tmp/test_export.mrc';
178     # Get all item infos
179     warning_like {
180         Koha::Exporter::Record::export(
181             {   record_type     => 'bibs',
182                 record_ids      => [ $biblionumber_1, $bad_biblionumber, $biblionumber_2 ],
183                 format          => 'iso2709',
184                 output_filepath => $generated_mrc_file,
185             }
186         );
187     }
188     qr|.*Start tag expected.*|, "Export iso2709 with wrong marcxml should raise a warning";
189
190     my $records = MARC::File::USMARC->in( $generated_mrc_file );
191     my @records;
192     while ( my $record = $records->next ) {
193         push @records, $record;
194     }
195     is( scalar( @records ), 2, 'Export ISO2709: 2 records should have been exported' );
196     my $second_record = $records[1];
197     my $title = $second_record->subfield(245, 'a');
198     $title = Encode::encode('UTF-8', $title);
199     is( $title, $biblio_2_title, 'Export ISO2709: The title is correctly encoded' );
200 };
201
202 subtest 'export without record_type' => sub {
203     plan tests => 1;
204
205     my $rv = Koha::Exporter::Record::export({
206             record_ids => [ $biblionumber_1, $biblionumber_2 ],
207             format => 'iso2709',
208             output_filepath => 'does_not_matter_here',
209     });
210     is( $rv, undef, 'export returns undef' );
211     #Depending on your logger config, you might have a warn in your logs
212 };
213
214 subtest '_get_biblio_for_export' => sub {
215     plan tests => 4;
216
217     my $biblio = MARC::Record->new();
218     $biblio->leader('00266nam a22001097a 4500');
219     $biblio->append_fields(
220         MARC::Field->new( '100', ' ', ' ', a => 'Thurber, James' ),
221         MARC::Field->new( '245', ' ', ' ', a => "The 13 Clocks" ),
222     );
223     my ( $biblionumber, $biblioitemnumber ) = AddBiblio( $biblio, '' );
224     my $branch_a = $builder->build({source => 'Branch',});
225     my $branch_b = $builder->build({source => 'Branch',});
226     my $item_branch_a = $builder->build(
227         {
228             source => 'Item',
229             value  => {
230                 biblionumber       => $biblionumber,
231                 homebranch         => $branch_a->{branchcode},
232                 more_subfields_xml => '',
233             }
234         }
235     );
236     my $item_branch_b = $builder->build(
237         {
238             source => 'Item',
239             value  => {
240                 biblionumber       => $biblionumber,
241                 homebranch         => $branch_b->{branchcode},
242                 more_subfields_xml => '',
243             }
244         }
245     );
246
247     my $record = Koha::Exporter::Record::_get_biblio_for_export(
248         {
249             biblionumber                   => $biblionumber,
250             export_items                   => 1,
251             only_export_items_for_branches => undef
252         }
253     );
254     my @items = $record->field('952');
255     is( scalar @items, 2, "We should retrieve all items if we don't pass specific branches and request items" );
256
257     $record = Koha::Exporter::Record::_get_biblio_for_export(
258         {
259             biblionumber                   => $biblionumber,
260             export_items                   => 1,
261             only_export_items_for_branches => [ $branch_b->{branchcode} ]
262         }
263     );
264     @items = $record->field('952');
265     is( scalar @items, 1, "We should retrieve only item for branch_b item if we request items and pass branch" );
266     is(
267         $items[0]->subfield('a'),
268         $branch_b->{branchcode},
269         "And the homebranch for that item should be branch_b branchcode"
270     );
271
272     $record = Koha::Exporter::Record::_get_biblio_for_export(
273         {
274             biblionumber                   => $biblionumber,
275             export_items                   => 0,
276             only_export_items_for_branches => [ $branch_b->{branchcode} ]
277         }
278     );
279     @items = $record->field('952');
280     is( scalar @items, 0, "We should not have any items if we don't request items and pass a branch");
281
282 };
283
284 subtest '_get_record_for_export MARC field conditions' => sub {
285     plan tests => 11;
286
287     my $biblio = MARC::Record->new();
288     $biblio->leader('00266nam a22001097a 4500');
289     $biblio->append_fields(
290         MARC::Field->new( '100', ' ', ' ', a => 'Thurber, James' ),
291         MARC::Field->new( '245', ' ', ' ', a => 'The 13 Clocks' ),
292         MARC::Field->new( '080', ' ', ' ', a => '12345' ),
293         MARC::Field->new( '035', ' ', ' ', a => '(TEST)123' ),
294         MARC::Field->new( '035', ' ', ' ', a => '(TEST)1234' ),
295     );
296     my ( $biblionumber ) = AddBiblio( $biblio, '' );
297     my $record;
298
299     $record = Koha::Exporter::Record::_get_record_for_export(
300         {
301             record_id => $biblionumber,
302             record_conditions => [['080', 'a', '=', '12345']],
303             record_type => 'bibs',
304         }
305     );
306     ok( $record, "Record condition \"080a=12345\" should match" );
307
308     $record = Koha::Exporter::Record::_get_record_for_export(
309         {
310             record_id => $biblionumber,
311             record_conditions => [['080', 'a', '!=', '12345']],
312             record_type => 'bibs',
313         }
314     );
315     is( $record, undef, "Record condition \"080a!=12345\" should not match" );
316
317     $record = Koha::Exporter::Record::_get_record_for_export(
318         {
319             record_id => $biblionumber,
320             record_conditions => [['080', 'a', '>', '1234']],
321             record_type => 'bibs',
322         }
323     );
324     ok( $record, "Record condition \"080a>1234\" should match" );
325
326     $record = Koha::Exporter::Record::_get_record_for_export(
327         {
328             record_id => $biblionumber,
329             record_conditions => [['080', 'a', '<', '123456']],
330             record_type => 'bibs',
331         }
332     );
333     ok( $record, "Record condition \"080a<123456\" should match" );
334
335     $record = Koha::Exporter::Record::_get_record_for_export(
336         {
337             record_id => $biblionumber,
338             record_conditions => [['080', 'a', '>', '123456']],
339             record_type => 'bibs',
340         }
341     );
342     is( $record, undef, "Record condition \"080a>123456\" should not match" );
343
344
345     ## Multiple subfields
346
347     $record = Koha::Exporter::Record::_get_record_for_export(
348         {
349             record_id => $biblionumber,
350             record_conditions => [['035', 'a', '!=', 'TEST(12345)']],
351             record_type => 'bibs',
352         }
353     );
354     ok( $record, "Record condition \"035a!=TEST(12345)\" should match" );
355
356     $record = Koha::Exporter::Record::_get_record_for_export(
357         {
358             record_id => $biblionumber,
359             record_conditions => [['035', 'a', '=', 'TEST(1234)']],
360             record_type => 'bibs',
361         }
362     );
363     is( $record, undef, "Record condition \"035a=TEST(1234)\" should not match" ); # Since matching all subfields required
364
365
366     ## Multiple conditions
367
368     $record = Koha::Exporter::Record::_get_record_for_export(
369         {
370             record_id => $biblionumber,
371             record_conditions => [['035', 'a', '!=', 'TEST(12345)'], ['080', 'a', '>', '1234']],
372             record_type => 'bibs',
373         }
374     );
375     ok( $record, "Record condition \"035a!=TEST(12345),080a>1234\" should match" );
376
377     $record = Koha::Exporter::Record::_get_record_for_export(
378         {
379             record_id => $biblionumber,
380             record_conditions => [['035', 'a', '!=', 'TEST(12345)'], ['080', 'a', '<', '1234']],
381             record_type => 'bibs',
382         }
383     );
384     is( $record, undef, "Record condition \"035a!=TEST(12345),080a<1234\" should not match" );
385
386
387     ## exists/not_exists
388
389     $record = Koha::Exporter::Record::_get_record_for_export(
390         {
391             record_id => $biblionumber,
392             record_conditions => [['035', 'a', '?']],
393             record_type => 'bibs',
394         }
395     );
396     ok( $record, "Record condition \"exists(035a)\" should match" );
397
398     $record = Koha::Exporter::Record::_get_record_for_export(
399         {
400             record_id => $biblionumber,
401             record_conditions => [['035', 'a', '!?']],
402             record_type => 'bibs',
403             record_type => 'bibs',
404         }
405     );
406     is( $record, undef, "Record condition \"not_exists(035a)\" should not match" );
407 };
408
409 $schema->storage->txn_rollback;