Bug 22827: Add age dependency on other fields than dateaccessioned
[koha.git] / t / db_dependent / Items / AutomaticItemModificationByAge.t
1 #!/usr/bin/perl
2
3 use Modern::Perl;
4 use Test::More tests => 19;
5 use MARC::Record;
6 use MARC::Field;
7 use DateTime;
8 use DateTime::Duration;
9
10 use C4::Items qw( GetMarcItem ToggleNewStatus );
11 use C4::Biblio qw( AddBiblio GetMarcFromKohaField );
12 use C4::Context;
13 use Koha::DateUtils qw( dt_from_string );
14 use Koha::Items;
15 use t::lib::Mocks;
16 use t::lib::TestBuilder;
17
18 my $schema = Koha::Database->new->schema;
19 $schema->storage->txn_begin;
20 my $dbh = C4::Context->dbh;
21
22 my $builder = t::lib::TestBuilder->new;
23
24 # create two branches
25 my $library = $builder->build( { source => 'Branch' })->{branchcode};
26 my $library2 = $builder->build( { source => 'Branch' })->{branchcode};
27
28 my $frameworkcode = ''; # Use Default for Koha to MARC mappings
29 $dbh->do(q|
30     DELETE FROM marc_subfield_structure
31     WHERE ( kohafield = 'items.new_status' OR kohafield = 'items.stocknumber' )
32     AND frameworkcode = ?
33 |, undef, $frameworkcode);
34
35 my $new_tagfield = 'i';
36 $dbh->do(qq|
37     INSERT INTO marc_subfield_structure(tagfield, tagsubfield, kohafield, frameworkcode)
38     VALUES ( 952, ?, 'items.new_status', ? )
39 |, undef, $new_tagfield, $frameworkcode);
40
41 # Clear cache
42 my $cache = Koha::Caches->get_instance();
43 $cache->clear_from_cache("MarcStructure-0-$frameworkcode");
44 $cache->clear_from_cache("MarcStructure-1-$frameworkcode");
45 $cache->clear_from_cache("default_value_for_mod_marc-");
46 $cache->clear_from_cache("MarcSubfieldStructure-$frameworkcode");
47
48 my $record = MARC::Record->new();
49 $record->append_fields(
50     MARC::Field->new('100', ' ', ' ', a => 'Moffat, Steven'),
51     MARC::Field->new('245', ' ', ' ', a => 'Silence in the library'),
52     MARC::Field->new('942', ' ', ' ', c => 'ITEMTYPE_T'),
53 );
54 my ($biblionumber, undef) = C4::Biblio::AddBiblio($record, $frameworkcode);
55
56 my $item = $builder->build_sample_item(
57     {
58         biblionumber => $biblionumber,
59         library      => $library,
60         new_status   => 'new_value',
61         ccode        => 'FIC',
62     }
63 );
64 my $itemnumber = $item->itemnumber;
65 is ( $item->new_status, 'new_value', q|AddItem insert the 'new_status' field| );
66
67 my ( $tagfield, undef ) = GetMarcFromKohaField( 'items.itemnumber' );
68 my $marc_item = C4::Items::GetMarcItem( $biblionumber, $itemnumber );
69 is( $marc_item->subfield($tagfield, $new_tagfield), 'new_value', q|Koha mapping is correct|);
70
71 # Update the items.new_status field if items.ccode eq 'FIC' => should be updated
72 my @rules = (
73     {
74         conditions => [
75             {
76                 field => 'items.ccode',
77                 value => 'FIC',
78             },
79         ],
80         substitutions => [
81             {
82                 field => 'items.new_status',
83                 value => 'updated_value',
84              },
85         ],
86         age => '0',
87     },
88 );
89
90 C4::Items::ToggleNewStatus( { rules => \@rules } );
91
92 my $modified_item = Koha::Items->find( $itemnumber );
93 is( $modified_item->new_status, 'updated_value', q|ToggleNewStatus: The new_status value is updated|);
94 $marc_item = C4::Items::GetMarcItem( $biblionumber, $itemnumber );
95 is( $marc_item->subfield($tagfield, $new_tagfield), 'updated_value', q|ToggleNewStatus: The new_status value is updated| );
96
97 # Update the items.new_status field if items.ccode eq 'DONT_EXIST' => should not be updated
98 @rules = (
99     {
100         conditions => [
101             {
102                 field => 'items.ccode',
103                 value => 'DONT_EXIST',
104             },
105         ],
106         substitutions => [
107             {
108                 field => 'items.new_status',
109                 value => 'new_updated_value',
110              },
111         ],
112         age => '0',
113     },
114 );
115
116 C4::Items::ToggleNewStatus( { rules => \@rules } );
117
118 $modified_item = Koha::Items->find( $itemnumber );
119 is( $modified_item->new_status, 'updated_value', q|ToggleNewStatus: The new_status value is not updated|);
120 $marc_item = C4::Items::GetMarcItem( $biblionumber, $itemnumber );
121 is( $marc_item->subfield($tagfield, $new_tagfield), 'updated_value', q|ToggleNewStatus: The new_status value is not updated| );
122
123 # Play with age
124 my $dt_today = dt_from_string;
125 my $days5ago = $dt_today->add_duration( DateTime::Duration->new( days => -5 ) );
126
127 $modified_item->dateaccessioned($days5ago)->store;
128
129 @rules = (
130     {
131         conditions => [
132             {
133                 field => 'items.ccode',
134                 value => 'FIC',
135             },
136         ],
137         substitutions => [
138             {
139                 field => 'items.new_status',
140                 value => 'new_updated_value',
141              },
142         ],
143         age => '10', # Confirm not defining agefield, will default to using items.dateaccessioned
144     },
145 );
146 C4::Items::ToggleNewStatus( { rules => \@rules } );
147 $modified_item = Koha::Items->find( $itemnumber );
148 is( $modified_item->new_status, 'updated_value', q|ToggleNewStatus: Age = 10 : The new_status value is not updated|);
149
150 $rules[0]->{age} = 5;
151 $rules[0]->{substitutions}[0]{value} = 'new_updated_value5';
152 C4::Items::ToggleNewStatus( { rules => \@rules } );
153 $modified_item = Koha::Items->find( $itemnumber );
154 is( $modified_item->new_status, 'new_updated_value5', q|ToggleNewStatus: Age = 5 : The new_status value is updated|);
155
156 $rules[0]->{age} = '';
157 $rules[0]->{substitutions}[0]{value} = 'new_updated_value_empty_string';
158 C4::Items::ToggleNewStatus( { rules => \@rules } );
159 $modified_item = Koha::Items->find( $itemnumber );
160 is( $modified_item->new_status, 'new_updated_value_empty_string', q|ToggleNewStatus: Age = '' : The new_status value is updated|);
161
162 $rules[0]->{age} = undef;
163 $rules[0]->{substitutions}[0]{value} = 'new_updated_value_undef';
164 C4::Items::ToggleNewStatus( { rules => \@rules } );
165 $modified_item = Koha::Items->find( $itemnumber );
166 is( $modified_item->new_status, 'new_updated_value_undef', q|ToggleNewStatus: Age = undef : The new_status value is updated|);
167
168 # Field deletion
169 @rules = (
170     {
171         conditions => [
172             {
173                 field => 'items.ccode',
174                 value => 'FIC',
175             },
176         ],
177         substitutions => [
178             {
179                 field => 'items.new_status',
180                 value => '',
181              },
182         ],
183         age => '0',
184     },
185 );
186
187 C4::Items::ToggleNewStatus( { rules => \@rules } );
188
189 $modified_item = Koha::Items->find( $itemnumber );
190 is( $modified_item->new_status, '', q|ToggleNewStatus: The new_status value is empty|);
191 $marc_item = C4::Items::GetMarcItem( $biblionumber, $itemnumber );
192 is( $marc_item->subfield($tagfield, $new_tagfield), undef, q|ToggleNewStatus: The new_status field is removed from the item marc| );
193
194 # conditions multiple
195 @rules = (
196     {
197         conditions => [
198             {
199                 field => 'items.ccode',
200                 value => 'FIC',
201             },
202             {
203                 field => 'items.homebranch',
204                 value => $library,
205             },
206         ],
207         substitutions => [
208             {
209                 field => 'items.new_status',
210                 value => 'new_value',
211              },
212         ],
213         age => '0',
214     },
215 );
216
217 C4::Items::ToggleNewStatus( { rules => \@rules } );
218
219 $modified_item = Koha::Items->find( $itemnumber );
220 is( $modified_item->new_status, 'new_value', q|ToggleNewStatus: conditions multiple: all match, the new_status value is updated|);
221
222 @rules = (
223     {
224         conditions => [
225             {
226                 field => 'items.ccode',
227                 value => 'FIC',
228             },
229             {
230                 field => 'items.homebranch',
231                 value => 'DONT_EXIST',
232             },
233         ],
234         substitutions => [
235             {
236                 field => 'items.new_status',
237                 value => 'new_updated_value',
238              },
239         ],
240         age => '0',
241     },
242 );
243
244 C4::Items::ToggleNewStatus( { rules => \@rules } );
245
246 $modified_item = Koha::Items->find( $itemnumber );
247 is( $modified_item->new_status, 'new_value', q|ToggleNewStatus: conditions multiple: at least 1 condition does not match, the new_status value is not updated|);
248
249 @rules = (
250     {
251         conditions => [
252             {
253                 field => 'items.ccode',
254                 value => 'FIC|NFIC',
255             },
256             {
257                 field => 'items.homebranch',
258                 value => "$library|$library2",
259             },
260         ],
261         substitutions => [
262             {
263                 field => 'items.new_status',
264                 value => 'new_updated_value',
265              },
266         ],
267         age => '0',
268     },
269 );
270
271 C4::Items::ToggleNewStatus( { rules => \@rules } );
272
273 $modified_item = Koha::Items->find( $itemnumber );
274 is( $modified_item->new_status, 'new_updated_value', q|ToggleNewStatus: conditions multiple: the 2 conditions match, the new_status value is updated|);
275
276 @rules = (
277     {
278         # does not exist
279         conditions => [
280             {
281                 field => 'biblioitems.itemtype',
282                 value => 'ITEMTYPE_T',
283             },
284         ],
285         substitutions => [
286             {
287                 field => 'items.new_status',
288                 value => 'another_new_updated_value',
289              },
290         ],
291         age => '0',
292     },
293 );
294
295 C4::Items::ToggleNewStatus( { rules => \@rules } );
296
297 $modified_item = Koha::Items->find( $itemnumber );
298 is( $modified_item->new_status, 'another_new_updated_value', q|ToggleNewStatus: conditions on biblioitems|);
299
300 # Play with the 'Age field'
301 my $days2ago = $dt_today->add_duration( DateTime::Duration->new( days => -10 ) );
302 my $days20ago = $dt_today->add_duration( DateTime::Duration->new( days => -20 ) );
303 $modified_item->datelastseen($days2ago)->store;
304 $modified_item->dateaccessioned($days20ago)->store;
305
306 # When agefield='items.datelastseen'
307 @rules = (
308     {
309         conditions => [
310             {
311                 field => 'biblioitems.itemtype',
312                 value => 'ITEMTYPE_T',
313             },
314         ],
315         substitutions => [
316             {
317                 field => 'items.new_status',
318                 value => 'agefield_new_value',
319              },
320         ],
321         age => '5',
322         agefield => 'items.datelastseen' # Confirm defining agefield => 'items.datelastseen' will use items.datelastseen
323     },
324 );
325 C4::Items::ToggleNewStatus( { rules => \@rules } );
326 $modified_item = Koha::Items->find( $itemnumber );
327 is( $modified_item->new_status, 'agefield_new_value', q|ToggleNewStatus: Age = 5, agefield = 'items.datelastseen' : The new_status value is not updated|);
328
329 $rules[0]->{age} = 2;
330 C4::Items::ToggleNewStatus( { rules => \@rules } );
331 $modified_item = Koha::Items->find( $itemnumber );
332 is( $modified_item->new_status, 'agefield_new_value', q|ToggleNewStatus: Age = 2, agefield = 'items.datelastseen' : The new_status value is updated|);
333
334 # Run twice
335 t::lib::Mocks::mock_preference('CataloguingLog', 1);
336 my $actions_nb = $schema->resultset('ActionLog')->count();
337 C4::Items::ToggleNewStatus( { rules => \@rules } );
338 is( $schema->resultset('ActionLog')->count(), $actions_nb, q|ToggleNewStatus: no substitution does not generate action logs|);
339
340 # Cleanup
341 $cache = Koha::Caches->get_instance();
342 $cache->clear_from_cache("MarcStructure-0-$frameworkcode");
343 $cache->clear_from_cache("MarcStructure-1-$frameworkcode");
344 $cache->clear_from_cache("default_value_for_mod_marc-");
345 $cache->clear_from_cache("MarcSubfieldStructure-$frameworkcode");
346 $schema->storage->txn_rollback;