Bug 20144: [sql_modes] Set default value for biblio.datecreated in tests
[koha.git] / t / db_dependent / Serials.t
1 #!/usr/bin/perl
2 #
3 # This Koha test module is a stub!
4 # Add more tests here!!!
5
6 use Modern::Perl;
7 use YAML;
8
9 use CGI qw ( -utf8 );
10 use C4::Serials;
11 use C4::Serials::Frequency;
12 use C4::Serials::Numberpattern;
13 use C4::Debug;
14 use C4::Biblio;
15 use C4::Budgets;
16 use C4::Items;
17 use Koha::DateUtils;
18 use Koha::Acquisition::Booksellers;
19 use t::lib::Mocks;
20 use t::lib::TestBuilder;
21 use Test::More tests => 48;
22
23 BEGIN {
24     use_ok('C4::Serials');
25 }
26
27 my $dbh = C4::Context->dbh;
28
29 # Start transaction
30 $dbh->{AutoCommit} = 0;
31 $dbh->{RaiseError} = 1;
32
33 my $builder = t::lib::TestBuilder->new();
34
35 # This could/should be used for all untested methods
36 my @methods = ('updateClaim');
37 can_ok('C4::Serials', @methods);
38
39 $dbh->do(q|UPDATE marc_subfield_structure SET value_builder="callnumber.pl" where kohafield="items.itemcallnumber" and frameworkcode=''|);
40
41 my $bookseller = Koha::Acquisition::Bookseller->new(
42     {
43         name => "my vendor",
44         address1 => "bookseller's address",
45         phone => "0123456",
46         active => 1
47     }
48 );
49
50 my ($biblionumber, $biblioitemnumber) = AddBiblio(MARC::Record->new, '');
51
52 my $budgetid;
53 my $bpid = AddBudgetPeriod({
54     budget_period_startdate   => '2015-01-01',
55     budget_period_enddate     => '2015-12-31',
56     budget_period_description => "budget desc"
57 });
58
59 my $budget_id = AddBudget({
60     budget_code        => "ABCD",
61     budget_amount      => "123.132",
62     budget_name        => "Périodiques",
63     budget_notes       => "This is a note",
64     budget_period_id   => $bpid
65 });
66
67 my $frequency_id = AddSubscriptionFrequency({ description => "Test frequency 1" });
68 my $pattern_id = AddSubscriptionNumberpattern({
69     label => 'Test numberpattern 1',
70     description => 'Description for numberpattern 1',
71     numberingmethod => '{X}',
72     label1 => q{},
73     add1 => 1,
74     every1 => 1,
75     every1 => 1,
76     numbering1 => 1,
77     whenmorethan1 => 1,
78 });
79
80 my $notes = 'notes';
81 my $internalnotes = 'intnotes';
82 my $subscriptionid = NewSubscription(
83     undef,      "",     undef, undef, $budget_id, $biblionumber,
84     '2013-01-01', $frequency_id, undef, undef,  undef,
85     undef,      undef,  undef, undef, undef, undef,
86     1,          $notes,undef, '2013-01-01', undef, $pattern_id,
87     undef,       undef,  0,    $internalnotes,  0,
88     undef, undef, 0,          undef,         '2013-12-31', 0
89 );
90
91 my $subscriptioninformation = GetSubscription( $subscriptionid );
92
93 is( $subscriptioninformation->{notes}, $notes, 'NewSubscription should set notes' );
94 is( $subscriptioninformation->{internalnotes}, $internalnotes, 'NewSubscription should set internalnotes' );
95
96 my $subscription_history = C4::Serials::GetSubscriptionHistoryFromSubscriptionId($subscriptionid);
97 is( $subscription_history->{opacnote}, '', 'NewSubscription should not set subscriptionhistory opacnotes' );
98 is( $subscription_history->{librariannote}, '', 'NewSubscription should not set subscriptionhistory librariannotes' );
99
100 my @subscriptions = SearchSubscriptions({string => $subscriptioninformation->{bibliotitle}, orderby => 'title' });
101 isa_ok( \@subscriptions, 'ARRAY' );
102
103 @subscriptions = SearchSubscriptions({ issn => $subscriptioninformation->{issn}, orderby => 'title' });
104 isa_ok( \@subscriptions, 'ARRAY' );
105
106 @subscriptions = SearchSubscriptions({ ean => $subscriptioninformation->{ean}, orderby => 'title' });
107 isa_ok( \@subscriptions, 'ARRAY' );
108
109 @subscriptions = SearchSubscriptions({ biblionumber => $subscriptioninformation->{bibnum}, orderby => 'title' });
110 isa_ok( \@subscriptions, 'ARRAY' );
111
112 my $frequency = GetSubscriptionFrequency($subscriptioninformation->{periodicity});
113 my $old_frequency;
114 if (not $frequency->{unit}) {
115     $old_frequency = $frequency->{id};
116     $frequency->{unit} = "month";
117     $frequency->{unitsperissue} = 1;
118     $frequency->{issuesperunit} = 1;
119     $frequency->{description} = "Frequency created by t/db_dependant/Serials.t";
120     $subscriptioninformation->{periodicity} = AddSubscriptionFrequency($frequency);
121     $subscriptioninformation->{serialsadditems} = 1;
122
123     ModSubscription( @$subscriptioninformation{qw(
124         librarian branchcode aqbooksellerid cost aqbudgetid startdate
125         periodicity firstacquidate irregularity numberpattern locale
126         numberlength weeklength monthlength lastvalue1 innerloop1 lastvalue2
127         innerloop2 lastvalue3 innerloop3 status biblionumber callnumber notes
128         letter manualhistory internalnotes serialsadditems staffdisplaycount
129         opacdisplaycount graceperiod location enddate subscriptionid
130         skip_serialseq
131     )} );
132 }
133 my $expirationdate = GetExpirationDate($subscriptionid) ;
134 ok( $expirationdate, "expiration date is not NULL" );
135
136 ok(C4::Serials::GetSubscriptionHistoryFromSubscriptionId($subscriptionid), 'test getting history from sub-scription');
137
138 my ($serials_count, @serials) = GetSerials($subscriptionid);
139 ok($serials_count > 0, 'Subscription has at least one serial');
140 my $serial = $serials[0];
141
142 ok(C4::Serials::GetSerialStatusFromSerialId($serial->{serialid}), 'test getting Serial Status From Serial Id');
143
144 isa_ok(C4::Serials::GetSerialInformation($serial->{serialid}), 'HASH', 'test getting Serial Information');
145
146 subtest 'Values should not be erased on editing' => sub {
147
148     plan tests => 1;
149
150     ( $biblionumber, $biblioitemnumber ) = get_biblio();
151     my ( $icn_tag, $icn_sf ) = GetMarcFromKohaField( 'items.itemcallnumber', '' );
152     my ( $it_tag, $it_sf )   = GetMarcFromKohaField( 'items.itype', '' );
153
154     my $itemtype = $builder->build( { source => 'Itemtype' } )->{itemtype};
155     my $itemcallnumber = 'XXXmy itemcallnumberXXX';
156
157     my $item_record    = new MARC::Record;
158
159     $item_record->append_fields(
160         MARC::Field->new( '080', '', '', "a" => "default" ),
161         MARC::Field->new(
162             $icn_tag, '', '',
163             $icn_sf => $itemcallnumber,
164             $it_sf  => $itemtype
165         )
166     );
167     my ( undef, undef, $itemnumber ) = C4::Items::AddItemFromMarc( $item_record, $biblionumber );
168     my $serialid = C4::Serials::NewIssue( "serialseq", $subscriptionid, $biblionumber,
169                                           1, undef, undef, "publisheddatetext", "notes" );
170     C4::Serials::AddItem2Serial( $serialid, $itemnumber );
171     my $serial_info = C4::Serials::GetSerialInformation($serialid);
172     my ($itemcallnumber_info) = grep { $_->{kohafield} eq 'items.itemcallnumber' }
173                                      @{ $serial_info->{items}[0]->{iteminformation} };
174     like( $itemcallnumber_info->{marc_value}, qr|value="$itemcallnumber"| );
175 };
176
177 # Delete created frequency
178 if ($old_frequency) {
179     my $freq_to_delete = $subscriptioninformation->{periodicity};
180     $subscriptioninformation->{periodicity} = $old_frequency;
181
182     ModSubscription( @$subscriptioninformation{qw(
183         librarian branchcode aqbooksellerid cost aqbudgetid startdate
184         periodicity firstacquidate irregularity numberpattern locale
185         numberlength weeklength monthlength lastvalue1 innerloop1 lastvalue2
186         innerloop2 lastvalue3 innerloop3 status biblionumber callnumber notes
187         letter manualhistory internalnotes serialsadditems staffdisplaycount
188         opacdisplaycount graceperiod location enddate subscriptionid
189         skip_serialseq
190     )} );
191
192     DelSubscriptionFrequency($freq_to_delete);
193 }
194
195 # Test calling subs without parameters
196 is(C4::Serials::AddItem2Serial(), undef, 'test adding item to serial');
197 is(C4::Serials::GetFullSubscription(), undef, 'test getting full subscription');
198 is(C4::Serials::PrepareSerialsData(), undef, 'test preparing serial data');
199 is(C4::Serials::GetSubscriptionsFromBiblionumber(), undef, 'test getting subscriptions form biblio number');
200
201 is(C4::Serials::GetSerials(), undef, 'test getting serials when you enter nothing');
202 is(C4::Serials::GetSerials2(), undef, 'test getting serials when you enter nothing');
203
204 is(C4::Serials::GetLatestSerials(), undef, 'test getting lastest serials');
205
206 is(C4::Serials::GetDistributedTo(), undef, 'test getting distributed when nothing is entered');
207
208 is(C4::Serials::GetNextSeq(), undef, 'test getting next seq when you enter nothing');
209
210 is(C4::Serials::GetSeq(), undef, 'test getting seq when you enter nothing');
211
212 is(C4::Serials::CountSubscriptionFromBiblionumber(), undef, 'test counting subscription when nothing is entered');
213
214 is(C4::Serials::ModSubscriptionHistory(), undef, 'test modding subscription history');
215
216 is(C4::Serials::ModSerialStatus(),undef, 'test modding serials');
217
218 is(C4::Serials::findSerialsByStatus(), 0, 'test finding serial by status with no parameters');
219
220 is(C4::Serials::NewIssue(), undef, 'test getting 0 when nothing is entered');
221
222 is(C4::Serials::HasSubscriptionStrictlyExpired(), undef, 'test if the subscriptions has expired');
223 is(C4::Serials::HasSubscriptionExpired(), undef, 'test if the subscriptions has expired');
224
225 is(C4::Serials::GetLateOrMissingIssues(), undef, 'test getting last or missing issues');
226
227 subtest 'test_updateClaim' => sub {
228     plan tests => 11;
229
230     my $today = output_pref({ dt => dt_from_string, dateonly => 1 });
231     # Given ... nothing much
232     # When ... Then ...
233     my $result_0 = C4::Serials::updateClaim(undef);
234     is($result_0, undef, 'Got the expected undef from update claim with nothin');
235
236     # Given ... 3 serial. 2 of them updated.
237     my $serialids_1   = [90980, 90981];
238     my $claimdate_1   = dt_from_string('2001-01-13'); # arbitrary date some time in the past.
239     my $claim_count_1 = 5;
240     Koha::Serial->new( { serialid => $serialids_1->[0], serialseq => 'serialseq', subscriptionid => $subscriptionid, status => 3,
241                          biblionumber => 12345, claimdate => $claimdate_1, claims_count => $claim_count_1, } )->store();
242     Koha::Serial->new( { serialid => $serialids_1->[1], serialseq => 'serialseq', subscriptionid => $subscriptionid, status => 3,
243                          biblionumber => 12345, claimdate => $claimdate_1, claims_count => $claim_count_1,  } )->store();
244     Koha::Serial->new( { serialid => 90982, serialseq => 'serialseq', subscriptionid => $subscriptionid, status => 3,
245                          biblionumber => 12345, claimdate => $claimdate_1, claims_count => $claim_count_1,  } )->store();
246
247     # When ...
248     my $result_1 = C4::Serials::updateClaim($serialids_1);
249
250     # Then ...
251     is($result_1, 2, 'Got the expected 2 from update claim with 2 serial ids');
252
253     my @late_or_missing_issues_1_0 = C4::Serials::GetLateOrMissingIssues(undef, $serialids_1->[0]);
254     is($late_or_missing_issues_1_0[0]->{claimdate}, $today, 'Got the expected first different claim date from update claim');
255     is($late_or_missing_issues_1_0[0]->{claims_count}, $claim_count_1+1, 'Got the expected first claim count from update claim');
256     is($late_or_missing_issues_1_0[0]->{status}, 7, 'Got the expected first claim status from update claim');
257
258     my @late_or_missing_issues_1_1 = C4::Serials::GetLateOrMissingIssues(undef, $serialids_1->[1]);
259     is($late_or_missing_issues_1_1[0]->{claimdate}, $today, 'Got the expected second different claim date from update claim');
260     is($late_or_missing_issues_1_1[0]->{claims_count}, $claim_count_1+1, 'Got the expected second claim count from update claim');
261     is($late_or_missing_issues_1_1[0]->{status}, 7, 'Got the expected second claim status from update claim');
262
263     my @late_or_missing_issues_1_2 = C4::Serials::GetLateOrMissingIssues(undef, 90982);
264     is($late_or_missing_issues_1_2[0]->{claimdate}, output_pref({ dt => $claimdate_1, dateonly => 1}), 'Got the expected unchanged claim date from update claim');
265     is($late_or_missing_issues_1_2[0]->{claims_count}, $claim_count_1, 'Got the expected unchanged claim count from update claim');
266     is($late_or_missing_issues_1_2[0]->{status}, 3, 'Got the expected unchanged claim status from update claim');
267 };
268
269 is(C4::Serials::check_routing(), undef, 'test checking route');
270
271 is(C4::Serials::addroutingmember(),undef, 'test adding route member');
272
273
274 # Unit tests for statuses management (Bug 11689)
275 $subscriptionid = NewSubscription(
276     undef,      "",     undef, undef, $budget_id, $biblionumber,
277     '2013-01-01', $frequency_id, undef, undef,  undef,
278     undef,      undef,  undef, undef, undef, undef,
279     1,          $notes,undef, '2013-01-01', undef, $pattern_id,
280     undef,       undef,  0,    $internalnotes,  0,
281     undef, undef, 0,          undef,         '2013-12-31', 0
282 );
283 my $total_issues;
284 ( $total_issues, @serials ) = C4::Serials::GetSerials( $subscriptionid );
285 is( $total_issues, 1, "NewSubscription created a first serial" );
286 is( @serials, 1, "GetSerials returns the serial" );
287 my $subscription = C4::Serials::GetSubscription($subscriptionid);
288 my $pattern = C4::Serials::Numberpattern::GetSubscriptionNumberpattern($subscription->{numberpattern});
289 ( $total_issues, @serials ) = C4::Serials::GetSerials( $subscriptionid );
290 my $publisheddate = output_pref({ dt => dt_from_string, dateformat => 'iso', dateonly => 1 });
291 ( $total_issues, @serials ) = C4::Serials::GetSerials( $subscriptionid );
292 my $nextpublisheddate = C4::Serials::GetNextDate($subscription, $publisheddate, 1);
293 my @statuses = qw( 2 2 3 3 3 3 3 4 4 41 42 43 44 5 );
294 # Add 14 serials
295 my $counter = 0;
296 for my $status ( @statuses ) {
297     my $serialseq = "No.".$counter;
298     my ( $expected_serial ) = GetSerials2( $subscriptionid, [1] );
299     C4::Serials::ModSerialStatus( $expected_serial->{serialid}, $serialseq, $publisheddate, $publisheddate, $publisheddate, $statuses[$counter], 'an useless note' );
300     $counter++;
301 }
302 # Here we have 15 serials with statuses : 2*2 + 5*3 + 2*4 + 1*41 + 1*42 + 1*43 + 1*44 + 1*5 + 1*1
303 my @serialsByStatus = C4::Serials::findSerialsByStatus(2,$subscriptionid);
304 is(@serialsByStatus,2,"findSerialsByStatus returns all serials with chosen status");
305 ( $total_issues, @serials ) = C4::Serials::GetSerials( $subscriptionid );
306 is( $total_issues, @statuses + 1, "GetSerials returns total_issues" );
307 my @arrived_missing = map { my $status = $_->{status}; ( grep { /^$status$/ } qw( 2 4 41 42 43 44 5 ) ) ? $_ : () } @serials;
308 my @others = map { my $status = $_->{status}; ( grep { /^$status$/ } qw( 2 4 41 42 43 44 5 ) ) ? () : $_ } @serials;
309 is( @arrived_missing, 5, "GetSerials returns 5 arrived/missing by default" );
310 is( @others, 6, "GetSerials returns all serials not arrived and not missing" );
311
312 ( $total_issues, @serials ) = C4::Serials::GetSerials( $subscriptionid, 10 );
313 is( $total_issues, @statuses + 1, "GetSerials returns total_issues" );
314 @arrived_missing = map { my $status = $_->{status}; ( grep { /^$status$/ } qw( 2 4 41 42 43 44 5 ) ) ? $_ : () } @serials;
315 @others = map { my $status = $_->{status}; ( grep { /^$status$/ } qw( 2 4 41 42 43 44 5 ) ) ? () : $_ } @serials;
316 is( @arrived_missing, 9, "GetSerials returns all arrived/missing if count given" );
317 is( @others, 6, "GetSerials returns all serials not arrived and not missing if count given" );
318
319 $subscription = C4::Serials::GetSubscription($subscriptionid); # Retrieve the updated subscription
320
321 my @serialseqs;
322 for my $am ( @arrived_missing ) {
323     if ( grep {/^$am->{status}$/} qw( 4 41 42 43 44 ) ) {
324         push @serialseqs, $am->{serialseq}
325     } elsif ( grep {/^$am->{status}$/} qw( 5 ) ) {
326         push @serialseqs, 'not issued ' . $am->{serialseq};
327     }
328 }
329 is( $subscription->{missinglist}, join('; ', @serialseqs), "subscription missinglist is updated after ModSerialStatus" );
330
331 subtest "Do not generate an expected if one already exists" => sub {
332     plan tests => 2;
333     my ($expected_serial) = GetSerials2( $subscriptionid, [1] );
334
335     #Find serialid for serial with status Expected
336     my $serialexpected = ( C4::Serials::findSerialsByStatus( 1, $subscriptionid ) )[0];
337
338     #delete serial with status Expected
339     C4::Serials::ModSerialStatus( $serialexpected->{serialid}, $serialexpected->{serialseq}, $publisheddate, $publisheddate, $publisheddate, '1', 'an useless note' );
340     @serialsByStatus = C4::Serials::findSerialsByStatus( 1, $subscriptionid );
341     is( @serialsByStatus, 1, "ModSerialStatus delete corectly serial expected and create another if not exist" );
342
343     # add 1 serial with status=Expected 1
344     C4::Serials::ModSerialStatus( $expected_serial->{serialid}, 'NO.20', $publisheddate, $publisheddate, $publisheddate, '1', 'an useless note' );
345
346     #Now we have two serials it have status expected
347     #put status delete for last serial
348     C4::Serials::ModSerialStatus( $serialexpected->{serialid}, $serialexpected->{serialseq}, $publisheddate, $publisheddate, $publisheddate, '1', 'an useless note' );
349
350     #try if create or not another serial with status is expected
351     @serialsByStatus = C4::Serials::findSerialsByStatus( 1, $subscriptionid );
352     is( @serialsByStatus, 1, "ModSerialStatus delete corectly serial expected and not create another if exists" );
353 };
354
355 $dbh->rollback;
356
357 sub get_biblio {
358     my $bib = MARC::Record->new();
359     $bib->append_fields(
360         MARC::Field->new('100', ' ', ' ', a => 'Moffat, Steven'),
361         MARC::Field->new('245', ' ', ' ', a => 'Silence in the library'),
362     );
363     my ($bibnum, $bibitemnum) = AddBiblio($bib, '');
364     return ($bibnum, $bibitemnum);
365 }