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