3 # This Koha test module is a stub!
4 # Add more tests here!!!
9 use C4::Serials::Frequency;
10 use C4::Serials::Numberpattern;
16 use Koha::Acquisition::Booksellers;
18 use t::lib::TestBuilder;
19 use Test::More tests => 49;
22 use_ok('C4::Serials');
25 my $schema = Koha::Database->new->schema;
26 $schema->storage->txn_begin;
27 my $dbh = C4::Context->dbh;
29 my $builder = t::lib::TestBuilder->new();
31 # This could/should be used for all untested methods
32 my @methods = ('updateClaim');
33 can_ok('C4::Serials', @methods);
35 $dbh->do(q|UPDATE marc_subfield_structure SET value_builder="callnumber.pl" where kohafield="items.itemcallnumber" and frameworkcode=''|);
37 my $bookseller = Koha::Acquisition::Bookseller->new(
40 address1 => "bookseller's address",
46 my ($biblionumber, $biblioitemnumber) = AddBiblio(MARC::Record->new, '');
48 my $bpid = AddBudgetPeriod({
49 budget_period_startdate => '2015-01-01',
50 budget_period_enddate => '2015-12-31',
51 budget_period_description => "budget desc"
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
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}',
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
86 my $subscriptioninformation = GetSubscription( $subscriptionid );
88 is( $subscriptioninformation->{notes}, $notes, 'NewSubscription should set notes' );
89 is( $subscriptioninformation->{internalnotes}, $internalnotes, 'NewSubscription should set internalnotes' );
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' );
95 my @subscriptions = SearchSubscriptions({string => $subscriptioninformation->{bibliotitle}, orderby => 'title' });
96 isa_ok( \@subscriptions, 'ARRAY' );
98 @subscriptions = SearchSubscriptions({ issn => $subscriptioninformation->{issn}, orderby => 'title' });
99 isa_ok( \@subscriptions, 'ARRAY' );
101 @subscriptions = SearchSubscriptions({ ean => $subscriptioninformation->{ean}, orderby => 'title' });
102 isa_ok( \@subscriptions, 'ARRAY' );
104 @subscriptions = SearchSubscriptions({ biblionumber => $subscriptioninformation->{bibnum}, orderby => 'title' });
105 isa_ok( \@subscriptions, 'ARRAY' );
107 my $frequency = GetSubscriptionFrequency($subscriptioninformation->{periodicity});
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;
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
128 my $expirationdate = GetExpirationDate($subscriptionid) ;
129 ok( $expirationdate, "expiration date is not NULL" );
131 ok(C4::Serials::GetSubscriptionHistoryFromSubscriptionId($subscriptionid), 'test getting history from sub-scription');
133 my ($serials_count, @serials) = GetSerials($subscriptionid);
134 ok($serials_count > 0, 'Subscription has at least one serial');
135 my $serial = $serials[0];
137 isa_ok(C4::Serials::GetSerialInformation($serial->{serialid}), 'HASH', 'test getting Serial Information');
139 subtest 'Values should not be erased on editing' => sub {
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' );
148 my $itemtype = $builder->build( { source => 'Itemtype' } )->{itemtype};
149 my $itemcallnumber = 'XXXmy itemcallnumberXXX';
151 my $item_record = MARC::Record->new;
153 $item_record->append_fields(
154 MARC::Field->new( '080', '', '', "a" => "default" ),
157 $icn_sf => $itemcallnumber,
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"| );
171 # Delete created frequency
172 if ($old_frequency) {
173 my $freq_to_delete = $subscriptioninformation->{periodicity};
174 $subscriptioninformation->{periodicity} = $old_frequency;
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
186 DelSubscriptionFrequency($freq_to_delete);
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');
194 subtest 'GetSubscriptionsFromBiblionumber' => sub {
197 is( C4::Serials::GetSubscriptionsFromBiblionumber(),
198 undef, 'test getting subscriptions form biblio number' );
200 my $subscriptions = C4::Serials::GetSubscriptionsFromBiblionumber($biblionumber);
201 ModSubscriptionHistory( $subscriptions->[0]->{subscriptionid},
202 undef, undef, $notes, $notes, $notes );
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'
208 is( $subscriptions->[0]->{recievedlist}, $notes,
209 'GetSubscriptionsFromBiblionumber should have returned recievedlist as it is in DB, ie. without br tags'
211 is( $subscriptions->[0]->{missinglist}, $notes,
212 'GetSubscriptionsFromBiblionumber should have returned missinglist as it is in DB, ie. without br tags'
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');
219 is(C4::Serials::GetLatestSerials(), undef, 'test getting lastest serials');
221 is(C4::Serials::GetNextSeq(), undef, 'test getting next seq when you enter nothing');
223 is(C4::Serials::GetSeq(), undef, 'test getting seq when you enter nothing');
225 is(C4::Serials::CountSubscriptionFromBiblionumber(), undef, 'test counting subscription when nothing is entered');
227 is(C4::Serials::ModSubscriptionHistory(), undef, 'test modding subscription history');
229 is(C4::Serials::ModSerialStatus(),undef, 'test modding serials');
231 is(C4::Serials::findSerialsByStatus(), 0, 'test finding serial by status with no parameters');
233 is(C4::Serials::NewIssue(), undef, 'test getting 0 when nothing is entered');
235 is(C4::Serials::HasSubscriptionStrictlyExpired(), undef, 'test if the subscriptions has expired');
236 is(C4::Serials::HasSubscriptionExpired(), undef, 'test if the subscriptions has expired');
238 is(C4::Serials::GetLateOrMissingIssues(), undef, 'test getting last or missing issues');
240 subtest 'test_updateClaim' => sub {
243 my $today = output_pref({ dt => dt_from_string, dateonly => 1 });
244 # Given ... nothing much
246 my $result_0 = C4::Serials::updateClaim(undef);
247 is($result_0, undef, 'Got the expected undef from update claim with nothin');
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(
255 class => 'Koha::Serials',
257 serialseq => 'serialseq',
258 subscriptionid => $subscriptionid,
260 biblionumber => $biblio->biblionumber,
261 claimdate => $claimdate_1,
262 claims_count => $claim_count_1,
266 my $serial2 = $builder->build_object(
268 class => 'Koha::Serials',
270 serialseq => 'serialseq',
271 subscriptionid => $subscriptionid,
273 biblionumber => $biblio->biblionumber,
274 claimdate => $claimdate_1,
275 claims_count => $claim_count_1,
279 my $serial3 = $builder->build_object(
281 class => 'Koha::Serials',
283 serialseq => 'serialseq',
284 subscriptionid => $subscriptionid,
286 biblionumber => $biblio->biblionumber,
287 claimdate => $claimdate_1,
288 claims_count => $claim_count_1,
294 my $result_1 = C4::Serials::updateClaim([$serial1->serialid, $serial2->serialid]);
297 is($result_1, 2, 'Got the expected 2 from update claim with 2 serial ids');
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');
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');
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');
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
319 is(C4::Serials::addroutingmember(),undef, 'test adding route member');
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
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 );
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' );
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" );
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" );
368 $subscription = C4::Serials::GetSubscription($subscriptionid); # Retrieve the updated subscription
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};
378 is( $subscription->{missinglist}, join('; ', @serialseqs), "subscription missinglist is updated after ModSerialStatus" );
380 subtest "Do not generate an expected if one already exists" => sub {
382 my ($expected_serial) = GetSerials2( $subscriptionid, [1] );
384 #Find serialid for serial with status Expected
385 my $serialexpected = ( C4::Serials::findSerialsByStatus( 1, $subscriptionid ) )[0];
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" );
392 # add 1 serial with status=Expected 1
393 C4::Serials::ModSerialStatus( $expected_serial->{serialid}, 'NO.20', $publisheddate, $publisheddate, $publisheddate, '1', 'an useless note' );
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' );
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" );
404 subtest "PreserveSerialNotes preference" => sub {
406 my ($expected_serial) = GetSerials2( $subscriptionid, [1] );
408 t::lib::Mocks::mock_preference( 'PreserveSerialNotes', 1 );
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");
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");
421 subtest "NewSubscription|ModSubscription" => sub {
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
431 ok($subscriptionid, "Sending empty string instead of undef to reflect use of the interface");
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" );
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
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');