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