Bug 33360: Add Koha::Notice::Util for mail domain limits
[koha.git] / t / db_dependent / Koha / Items / BatchUpdate.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 use Test::More tests=> 8;
20 use Test::Warn;
21 use utf8;
22
23 use Koha::Database;
24 use Koha::Caches;
25
26 use C4::Biblio;
27 use Koha::Item::Attributes;
28 use Koha::MarcSubfieldStructures;
29
30 use t::lib::TestBuilder;
31 use t::lib::Mocks;
32
33 my $schema = Koha::Database->new->schema;
34 $schema->storage->txn_begin;
35
36 my $builder = t::lib::TestBuilder->new;
37
38 Koha::Caches->get_instance->clear_from_cache( "MarcStructure-1-" );
39
40 # 952 $x $é $y are not linked with a kohafield
41 # $952$x $é repeatable
42 # $952$t is not repeatable
43 # 952$z is linked with items.itemnotes and is repeatable
44 # 952$t is linked with items.copynumber and is not repeatable
45 setup_mss();
46
47 my $biblio = $builder->build_sample_biblio({ frameworkcode => '' });
48 my $item = $builder->build_sample_item({ biblionumber => $biblio->biblionumber });
49
50 my $items = Koha::Items->search({itemnumber => $item->itemnumber});
51
52 subtest 'MARC subfield linked with kohafield' => sub {
53     plan tests => 9;
54
55     $items->batch_update({
56             new_values => {itemnotes => 'new note'}
57         });
58     $items->reset;
59
60     $item = $item->get_from_storage;
61     is( $item->itemnotes, 'new note' );
62     is( $item->as_marc_field->subfield('t'), undef );
63
64     is( $items->batch_update({
65             new_values => {itemnotes=> 'another note'}
66         })->count, 1, 'Can be chained');
67     $items->reset;
68
69     $items->batch_update({new_values => {itemnotes=> undef }})->reset;
70     $item = $item->get_from_storage;
71     is( $item->itemnotes, undef, "blank" );
72     is( $item->as_marc_field->subfield('t'), undef, '' );
73
74     $items->batch_update({new_values => {itemnotes=> 'new note', copynumber => 'new copynumber'}})->reset;
75     $item = $item->get_from_storage;
76     is( $item->itemnotes, 'new note', "multi" );
77     is( $item->as_marc_field->subfield('z'), 'new note', '' );
78     is( $item->copynumber, 'new copynumber', "multi" );
79     is( $item->as_marc_field->subfield('t'), 'new copynumber', '' );
80 };
81
82 subtest 'More marc subfields (no linked)' => sub {
83     plan tests => 1;
84
85     $items->batch_update({new_values => {x => 'new xxx' }})->reset;
86     is( $item->get_from_storage->as_marc_field->subfield('x'), 'new xxx' );
87 };
88
89 subtest 'repeatable' => sub {
90     plan tests => 2;
91
92     subtest 'linked' => sub {
93         plan tests => 4;
94
95         $items->batch_update({new_values => {itemnotes => 'new zzz 1|new zzz 2' }})->reset;
96         is( $item->get_from_storage->itemnotes, 'new zzz 1|new zzz 2');
97         is_deeply( [$item->get_from_storage->as_marc_field->subfield('z')], ['new zzz 1', 'new zzz 2'], 'z is repeatable' );
98
99         $items->batch_update({new_values => {copynumber => 'new ttt 1|new ttt 2' }})->reset;
100         is( $item->get_from_storage->copynumber, 'new ttt 1|new ttt 2');
101         is_deeply( [$item->get_from_storage->as_marc_field->subfield('t')], ['new ttt 1|new ttt 2'], 't is not repeatable' );
102     };
103
104     subtest 'not linked' => sub {
105         plan tests => 2;
106
107         $items->batch_update({new_values => {x => 'new xxx 1|new xxx 2' }})->reset;
108         is_deeply( [$item->get_from_storage->as_marc_field->subfield('x')], ['new xxx 1', 'new xxx 2'], 'i is repeatable' );
109
110         $items->batch_update({new_values => {y => 'new yyy 1|new yyy 2' }})->reset;
111         is_deeply( [$item->get_from_storage->as_marc_field->subfield('y')], ['new yyy 1|new yyy 2'], 'y is not repeatable' );
112     };
113 };
114
115 subtest 'blank' => sub {
116     plan tests => 5;
117
118     $items->batch_update(
119         {
120             new_values => {
121                 itemnotes  => 'new notes 1|new notes 2',
122                 copynumber => 'new cn 1|new cn 2',
123                 x          => 'new xxx 1|new xxx 2',
124                 y          => 'new yyy 1|new yyy 2',
125
126             }
127         }
128     )->reset;
129
130     $items->batch_update(
131         {
132             new_values => {
133                 itemnotes  => undef,
134                 copynumber => undef,
135                 x          => undef,
136             }
137         }
138     )->reset;
139
140     $item = $item->get_from_storage;
141     is( $item->itemnotes,                    undef );
142     is( $item->copynumber,                   undef );
143     is( $item->as_marc_field->subfield('x'), undef );
144     is_deeply( [ $item->as_marc_field->subfield('y') ],
145         ['new yyy 1|new yyy 2'] );
146
147     $items->batch_update(
148         {
149             new_values => {
150                 y => undef,
151             }
152         }
153     )->reset;
154
155     is( $item->get_from_storage->more_subfields_xml, undef );
156
157 };
158
159 subtest 'regex' => sub {
160     plan tests => 12;
161
162     $items->batch_update(
163         {
164             new_values => {
165                 itemnotes  => 'new notes 1|new notes 2',
166                 copynumber => 'new cn 1|new cn 2',
167                 x          => 'new xxx 1|new xxx 2',
168                 y          => 'new yyy 1|new yyy 2',
169
170             }
171         }
172     )->reset;
173
174     my $re = {
175         search    => 'new',
176         replace   => 'awesome',
177         modifiers => '',
178     };
179     $items->batch_update(
180         {
181             regex_mod =>
182               { itemnotes => $re, copynumber => $re, x => $re, y => $re }
183         }
184     )->reset;
185     $item = $item->get_from_storage;
186     is( $item->itemnotes, 'awesome notes 1|new notes 2' );
187     is_deeply(
188         [ $item->as_marc_field->subfield('z') ],
189         [ 'awesome notes 1', 'new notes 2' ],
190         'z is repeatable'
191     );
192
193     is( $item->copynumber, 'awesome cn 1|new cn 2' );
194     is_deeply( [ $item->as_marc_field->subfield('t') ],
195         ['awesome cn 1|new cn 2'], 't is not repeatable' );
196
197     is_deeply(
198         [ $item->as_marc_field->subfield('x') ],
199         [ 'awesome xxx 1', 'new xxx 2' ],
200         'i is repeatable'
201     );
202
203     is_deeply(
204         [ $item->as_marc_field->subfield('y') ],
205         ['awesome yyy 1|new yyy 2'],
206         'y is not repeatable'
207     );
208
209     $re = {
210         search    => '(awesome)',
211         replace   => '$1ness',
212         modifiers => '',
213     };
214     $items->batch_update(
215         {
216             regex_mod =>
217               { itemnotes => $re, copynumber => $re, x => $re, y => $re }
218         }
219     )->reset;
220     $item = $item->get_from_storage;
221     is( $item->itemnotes, 'awesomeness notes 1|new notes 2' );
222     is_deeply(
223         [ $item->as_marc_field->subfield('z') ],
224         [ 'awesomeness notes 1', 'new notes 2' ],
225         'z is repeatable'
226     );
227
228     is( $item->copynumber, 'awesomeness cn 1|new cn 2' );
229     is_deeply( [ $item->as_marc_field->subfield('t') ],
230         ['awesomeness cn 1|new cn 2'], 't is not repeatable' );
231
232     is_deeply(
233         [ $item->as_marc_field->subfield('x') ],
234         [ 'awesomeness xxx 1', 'new xxx 2' ],
235         'i is repeatable'
236     );
237
238     is_deeply(
239         [ $item->as_marc_field->subfield('y') ],
240         ['awesomeness yyy 1|new yyy 2'],
241         'y is not repeatable'
242     );
243 };
244
245 subtest 'encoding' => sub {
246     plan tests => 1;
247
248     $items->batch_update({
249             new_values => { 'é' => 'new note é'}
250         });
251     $items->reset;
252
253     $item = $item->get_from_storage;
254     is( $item->as_marc_field->subfield('é'), 'new note é', );
255 };
256
257 subtest 'mark_items_returned' => sub {
258     plan tests => 2;
259
260     my $circ = Test::MockModule->new( 'C4::Circulation' );
261     $circ->mock( 'MarkIssueReturned', sub {
262         warn "MarkIssueReturned";
263     });
264
265     my $issue = $builder->build_object({class => 'Koha::Checkouts'});
266     my $items = Koha::Items->search({ itemnumber => $issue->itemnumber });
267
268     warning_is
269         { $items->batch_update({new_values => {},mark_items_returned => 1}) }
270         qq{MarkIssueReturned},
271         "MarkIssueReturned called for item";
272
273     $items->reset;
274
275     warning_is
276         { $items->batch_update({new_values => {},mark_items_returned => 0}) }
277         qq{},
278         "MarkIssueReturned not called for item";
279
280 };
281
282 subtest 'report' => sub {
283     plan tests => 5;
284
285     my $item_1 =
286       $builder->build_sample_item( { biblionumber => $biblio->biblionumber } );
287     my $item_2 =
288       $builder->build_sample_item( { biblionumber => $biblio->biblionumber } );
289
290     my $items = Koha::Items->search(
291         { itemnumber => [ $item_1->itemnumber, $item_2->itemnumber ] } );
292
293     my ($report) = $items->batch_update(
294         {
295             new_values => { itemnotes => 'new note' }
296         }
297     );
298     $items->reset;
299     is_deeply(
300         $report,
301         {
302             modified_itemnumbers =>
303               [ $item_1->itemnumber, $item_2->itemnumber ],
304             modified_fields => 2
305         }
306     );
307
308     ($report) = $items->batch_update(
309         {
310             new_values => { itemnotes => 'new note', copynumber => 'new cn' }
311         }
312     );
313     $items->reset;
314
315     is_deeply(
316         $report,
317         {
318             modified_itemnumbers =>
319               [ $item_1->itemnumber, $item_2->itemnumber ],
320             modified_fields => 2
321         }
322     );
323
324     $item_1->get_from_storage->update( { itemnotes => 'not new note' } );
325     ($report) = $items->batch_update(
326         {
327             new_values => { itemnotes => 'new note', copynumber => 'new cn' }
328         }
329     );
330     $items->reset;
331
332     is_deeply(
333         $report,
334         {
335             modified_itemnumbers => [ $item_1->itemnumber ],
336             modified_fields      => 1
337         }
338     );
339
340     ($report) = $items->batch_update(
341         {
342             new_values => { x => 'new xxx', y => 'new yyy' }
343         }
344     );
345     $items->reset;
346
347     is_deeply(
348         $report,
349         {
350             modified_itemnumbers =>
351               [ $item_1->itemnumber, $item_2->itemnumber ],
352             modified_fields => 4
353         }
354     );
355
356     my $re = {
357         search    => 'new',
358         replace   => 'awesome',
359         modifiers => '',
360     };
361
362     $item_2->get_from_storage->update( { itemnotes => 'awesome note' } );
363     ($report) = $items->batch_update(
364         {
365             regex_mod =>
366               { itemnotes => $re, copynumber => $re, x => $re, y => $re }
367         }
368     );
369     $items->reset;
370
371     is_deeply(
372         $report,
373         {
374             modified_itemnumbers =>
375               [ $item_1->itemnumber, $item_2->itemnumber ],
376             modified_fields => 7
377         }
378     );
379
380 };
381
382 Koha::Caches->get_instance->clear_from_cache( "MarcStructure-1-" );
383
384 sub setup_mss {
385
386     my ( $itemtag, $itemsubfield ) = C4::Biblio::GetMarcFromKohaField( "items.itemnumber" );
387
388     Koha::MarcSubfieldStructures->search(
389         {
390             frameworkcode => '',
391             tagfield => $itemtag,
392             tagsubfield => 'é',
393         }
394     )->delete;    # In case it exist already
395
396     Koha::MarcSubfieldStructure->new(
397         {
398             frameworkcode => '',
399             tagfield      => $itemtag,
400             tagsubfield   => 'é',
401             kohafield     => undef,
402             repeatable    => 1,
403             tab           => 10,
404         }
405     )->store;
406
407     Koha::MarcSubfieldStructures->search(
408         {
409             frameworkcode => '',
410             tagfield      => $itemtag,
411             tagsubfield   => [ 'x', 'y' ]
412         }
413     )->update( { kohafield => undef } );
414
415     Koha::MarcSubfieldStructures->search(
416         {
417             frameworkcode => '',
418             tagfield => $itemtag,
419             tagsubfield => [ 'x', 'é' ],
420         }
421     )->update( { repeatable => 1 } );
422
423     Koha::MarcSubfieldStructures->search(
424         {
425             frameworkcode => '',
426             tagfield => $itemtag,
427             tagsubfield => ['t'],
428         }
429     )->update( { repeatable => 0 } );
430
431     Koha::MarcSubfieldStructures->search(
432         {
433             frameworkcode => '',
434             tagfield => $itemtag,
435             tagsubfield => ['z'],
436         }
437     )->update( { kohafield => 'items.itemnotes', repeatable => 1 } );
438
439     Koha::MarcSubfieldStructures->search(
440         {
441             frameworkcode => '',
442             tagfield => $itemtag,
443         }
444     )->update( { display_order => \['FLOOR( 1 + RAND( ) * 10 )'] } );
445 }