688749fb7a47b436990a07d5b2c7b17463f82c4a
[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 => 48;
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}, undef, 'NewSubscription should not set subscriptionhistory opacnotes' );
96 is( $subscription_history->{librariannote}, undef, '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", "routingnotes" );
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 is(C4::Serials::check_routing($subscriptionid), 0, 'There should not have any routing list for the subscription');
266 # TODO really test this check_routing subroutine
267
268 is(C4::Serials::addroutingmember(),undef, 'test adding route member');
269
270
271 # Unit tests for statuses management (Bug 11689)
272 $subscriptionid = NewSubscription(
273     undef,      "",     undef, undef, $budget_id, $biblionumber,
274     '2013-01-01', $frequency_id, undef, undef,  undef,
275     undef,      undef,  undef, undef, undef, undef,
276     1,          $notes,undef, '2013-01-01', undef, $pattern_id,
277     undef,       undef,  0,    $internalnotes,  0,
278     undef, undef, 0,          undef,         '2013-12-31', 0
279 );
280 my $total_issues;
281 ( $total_issues, @serials ) = C4::Serials::GetSerials( $subscriptionid );
282 is( $total_issues, 1, "NewSubscription created a first serial" );
283 is( @serials, 1, "GetSerials returns the serial" );
284 my $subscription = C4::Serials::GetSubscription($subscriptionid);
285 my $pattern = C4::Serials::Numberpattern::GetSubscriptionNumberpattern($subscription->{numberpattern});
286 ( $total_issues, @serials ) = C4::Serials::GetSerials( $subscriptionid );
287 my $publisheddate = output_pref({ dt => dt_from_string, dateformat => 'iso', dateonly => 1 });
288 ( $total_issues, @serials ) = C4::Serials::GetSerials( $subscriptionid );
289 $frequency = C4::Serials::Frequency::GetSubscriptionFrequency($subscription->{periodicity});
290 my $nextpublisheddate = C4::Serials::GetNextDate($subscription, $publisheddate, $frequency, 1);
291 my @statuses = qw( 2 2 3 3 3 3 3 4 4 41 42 43 44 5 );
292 # Add 14 serials
293 my $counter = 0;
294 for my $status ( @statuses ) {
295     my $serialseq = "No.".$counter;
296     my ( $expected_serial ) = GetSerials2( $subscriptionid, [1] );
297     C4::Serials::ModSerialStatus( $expected_serial->{serialid}, $serialseq, $publisheddate, $publisheddate, $publisheddate, $statuses[$counter], 'an useless note' );
298     $counter++;
299 }
300 # 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
301 my @serialsByStatus = C4::Serials::findSerialsByStatus(2,$subscriptionid);
302 is(@serialsByStatus,2,"findSerialsByStatus returns all serials with chosen status");
303 ( $total_issues, @serials ) = C4::Serials::GetSerials( $subscriptionid );
304 is( $total_issues, @statuses + 1, "GetSerials returns total_issues" );
305 my @arrived_missing = map { my $status = $_->{status}; ( grep { /^$status$/ } qw( 2 4 41 42 43 44 5 ) ) ? $_ : () } @serials;
306 my @others = map { my $status = $_->{status}; ( grep { /^$status$/ } qw( 2 4 41 42 43 44 5 ) ) ? () : $_ } @serials;
307 is( @arrived_missing, 5, "GetSerials returns 5 arrived/missing by default" );
308 is( @others, 6, "GetSerials returns all serials not arrived and not missing" );
309
310 ( $total_issues, @serials ) = C4::Serials::GetSerials( $subscriptionid, 10 );
311 is( $total_issues, @statuses + 1, "GetSerials returns total_issues" );
312 @arrived_missing = map { my $status = $_->{status}; ( grep { /^$status$/ } qw( 2 4 41 42 43 44 5 ) ) ? $_ : () } @serials;
313 @others = map { my $status = $_->{status}; ( grep { /^$status$/ } qw( 2 4 41 42 43 44 5 ) ) ? () : $_ } @serials;
314 is( @arrived_missing, 9, "GetSerials returns all arrived/missing if count given" );
315 is( @others, 6, "GetSerials returns all serials not arrived and not missing if count given" );
316
317 $subscription = C4::Serials::GetSubscription($subscriptionid); # Retrieve the updated subscription
318
319 my @serialseqs;
320 for my $am ( @arrived_missing ) {
321     if ( grep {/^$am->{status}$/} qw( 4 41 42 43 44 ) ) {
322         push @serialseqs, $am->{serialseq}
323     } elsif ( grep {/^$am->{status}$/} qw( 5 ) ) {
324         push @serialseqs, 'not issued ' . $am->{serialseq};
325     }
326 }
327 is( $subscription->{missinglist}, join('; ', @serialseqs), "subscription missinglist is updated after ModSerialStatus" );
328
329 subtest "Do not generate an expected if one already exists" => sub {
330     plan tests => 2;
331     my ($expected_serial) = GetSerials2( $subscriptionid, [1] );
332
333     #Find serialid for serial with status Expected
334     my $serialexpected = ( C4::Serials::findSerialsByStatus( 1, $subscriptionid ) )[0];
335
336     #delete serial with status Expected
337     C4::Serials::ModSerialStatus( $serialexpected->{serialid}, $serialexpected->{serialseq}, $publisheddate, $publisheddate, $publisheddate, '1', 'an useless note' );
338     @serialsByStatus = C4::Serials::findSerialsByStatus( 1, $subscriptionid );
339     is( @serialsByStatus, 1, "ModSerialStatus delete corectly serial expected and create another if not exist" );
340
341     # add 1 serial with status=Expected 1
342     C4::Serials::ModSerialStatus( $expected_serial->{serialid}, 'NO.20', $publisheddate, $publisheddate, $publisheddate, '1', 'an useless note' );
343
344     #Now we have two serials it have status expected
345     #put status delete for last serial
346     C4::Serials::ModSerialStatus( $serialexpected->{serialid}, $serialexpected->{serialseq}, $publisheddate, $publisheddate, $publisheddate, '1', 'an useless note' );
347
348     #try if create or not another serial with status is expected
349     @serialsByStatus = C4::Serials::findSerialsByStatus( 1, $subscriptionid );
350     is( @serialsByStatus, 1, "ModSerialStatus delete corectly serial expected and not create another if exists" );
351 };
352
353 subtest "NewSubscription" => sub {
354     plan tests => 1;
355     my $subscriptionid = NewSubscription(
356         "",      "",     "", "", $budget_id, $biblionumber,
357         '2013-01-01', $frequency_id, "", "",  "",
358         "",      "",  "", "", "", "",
359         1,          $notes,"", '2013-01-01', "", $pattern_id,
360         "",       "",  0,    $internalnotes,  0,
361         "", "", 0,          "",         '2013-12-31', 0
362     );
363     ok($subscriptionid, "Sending empty string instead of undef to reflect use of the interface");
364 };