Bug 23349: Add batch operations to staff interface catalog search results
[koha.git] / t / db_dependent / Serials.t
blob53bfed49e1dcd697b243b948f06655ea7b57da96
1 #!/usr/bin/perl
3 # This Koha test module is a stub!
4 # Add more tests here!!!
6 use Modern::Perl;
7 use YAML;
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 => 49;
23 BEGIN {
24 use_ok('C4::Serials');
27 my $schema = Koha::Database->new->schema;
28 $schema->storage->txn_begin;
29 my $dbh = C4::Context->dbh;
31 my $builder = t::lib::TestBuilder->new();
33 # This could/should be used for all untested methods
34 my @methods = ('updateClaim');
35 can_ok('C4::Serials', @methods);
37 $dbh->do(q|UPDATE marc_subfield_structure SET value_builder="callnumber.pl" where kohafield="items.itemcallnumber" and frameworkcode=''|);
39 my $bookseller = Koha::Acquisition::Bookseller->new(
41 name => "my vendor",
42 address1 => "bookseller's address",
43 phone => "0123456",
44 active => 1
48 my ($biblionumber, $biblioitemnumber) = AddBiblio(MARC::Record->new, '');
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 });
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 });
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 });
78 my $notes = "a\nnote\non\nseveral\nlines";
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
89 my $subscriptioninformation = GetSubscription( $subscriptionid );
91 is( $subscriptioninformation->{notes}, $notes, 'NewSubscription should set notes' );
92 is( $subscriptioninformation->{internalnotes}, $internalnotes, 'NewSubscription should set internalnotes' );
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' );
98 my @subscriptions = SearchSubscriptions({string => $subscriptioninformation->{bibliotitle}, orderby => 'title' });
99 isa_ok( \@subscriptions, 'ARRAY' );
101 @subscriptions = SearchSubscriptions({ issn => $subscriptioninformation->{issn}, orderby => 'title' });
102 isa_ok( \@subscriptions, 'ARRAY' );
104 @subscriptions = SearchSubscriptions({ ean => $subscriptioninformation->{ean}, orderby => 'title' });
105 isa_ok( \@subscriptions, 'ARRAY' );
107 @subscriptions = SearchSubscriptions({ biblionumber => $subscriptioninformation->{bibnum}, orderby => 'title' });
108 isa_ok( \@subscriptions, 'ARRAY' );
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;
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 )} );
131 my $expirationdate = GetExpirationDate($subscriptionid) ;
132 ok( $expirationdate, "expiration date is not NULL" );
134 ok(C4::Serials::GetSubscriptionHistoryFromSubscriptionId($subscriptionid), 'test getting history from sub-scription');
136 my ($serials_count, @serials) = GetSerials($subscriptionid);
137 ok($serials_count > 0, 'Subscription has at least one serial');
138 my $serial = $serials[0];
140 isa_ok(C4::Serials::GetSerialInformation($serial->{serialid}), 'HASH', 'test getting Serial Information');
142 subtest 'Values should not be erased on editing' => sub {
144 plan tests => 1;
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' );
151 my $itemtype = $builder->build( { source => 'Itemtype' } )->{itemtype};
152 my $itemcallnumber = 'XXXmy itemcallnumberXXX';
154 my $item_record = new MARC::Record;
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
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"| );
174 # Delete created frequency
175 if ($old_frequency) {
176 my $freq_to_delete = $subscriptioninformation->{periodicity};
177 $subscriptioninformation->{periodicity} = $old_frequency;
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 )} );
189 DelSubscriptionFrequency($freq_to_delete);
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');
197 subtest 'GetSubscriptionsFromBiblionumber' => sub {
198 plan tests => 4;
200 is( C4::Serials::GetSubscriptionsFromBiblionumber(),
201 undef, 'test getting subscriptions form biblio number' );
203 my $subscriptions = C4::Serials::GetSubscriptionsFromBiblionumber($biblionumber);
204 ModSubscriptionHistory( $subscriptions->[0]->{subscriptionid},
205 undef, undef, $notes, $notes, $notes );
207 $subscriptions = C4::Serials::GetSubscriptionsFromBiblionumber($biblionumber);
208 is( $subscriptions->[0]->{opacnote}, $notes,
209 'GetSubscriptionsFromBiblionumber should have returned the opacnote as it is in DB, ie. without br tags'
211 is( $subscriptions->[0]->{recievedlist}, $notes,
212 'GetSubscriptionsFromBiblionumber should have returned recievedlist as it is in DB, ie. without br tags'
214 is( $subscriptions->[0]->{missinglist}, $notes,
215 'GetSubscriptionsFromBiblionumber should have returned missinglist as it is in DB, ie. without br tags'
219 is(C4::Serials::GetSerials(), undef, 'test getting serials when you enter nothing');
220 is(C4::Serials::GetSerials2(), undef, 'test getting serials when you enter nothing');
222 is(C4::Serials::GetLatestSerials(), undef, 'test getting lastest serials');
224 is(C4::Serials::GetNextSeq(), undef, 'test getting next seq when you enter nothing');
226 is(C4::Serials::GetSeq(), undef, 'test getting seq when you enter nothing');
228 is(C4::Serials::CountSubscriptionFromBiblionumber(), undef, 'test counting subscription when nothing is entered');
230 is(C4::Serials::ModSubscriptionHistory(), undef, 'test modding subscription history');
232 is(C4::Serials::ModSerialStatus(),undef, 'test modding serials');
234 is(C4::Serials::findSerialsByStatus(), 0, 'test finding serial by status with no parameters');
236 is(C4::Serials::NewIssue(), undef, 'test getting 0 when nothing is entered');
238 is(C4::Serials::HasSubscriptionStrictlyExpired(), undef, 'test if the subscriptions has expired');
239 is(C4::Serials::HasSubscriptionExpired(), undef, 'test if the subscriptions has expired');
241 is(C4::Serials::GetLateOrMissingIssues(), undef, 'test getting last or missing issues');
243 subtest 'test_updateClaim' => sub {
244 plan tests => 11;
246 my $today = output_pref({ dt => dt_from_string, dateonly => 1 });
247 # Given ... nothing much
248 # When ... Then ...
249 my $result_0 = C4::Serials::updateClaim(undef);
250 is($result_0, undef, 'Got the expected undef from update claim with nothin');
252 # Given ... 3 serial. 2 of them updated.
253 my $claimdate_1 = dt_from_string('2001-01-13'); # arbitrary date some time in the past.
254 my $claim_count_1 = 5;
255 my $biblio = $builder->build_sample_biblio;
256 my $serial1 = $builder->build_object(
258 class => 'Koha::Serials',
259 value => {
260 serialseq => 'serialseq',
261 subscriptionid => $subscriptionid,
262 status => 3,
263 biblionumber => $biblio->biblionumber,
264 claimdate => $claimdate_1,
265 claims_count => $claim_count_1,
269 my $serial2 = $builder->build_object(
271 class => 'Koha::Serials',
272 value => {
273 serialseq => 'serialseq',
274 subscriptionid => $subscriptionid,
275 status => 3,
276 biblionumber => $biblio->biblionumber,
277 claimdate => $claimdate_1,
278 claims_count => $claim_count_1,
282 my $serial3 = $builder->build_object(
284 class => 'Koha::Serials',
285 value => {
286 serialseq => 'serialseq',
287 subscriptionid => $subscriptionid,
288 status => 3,
289 biblionumber => $biblio->biblionumber,
290 claimdate => $claimdate_1,
291 claims_count => $claim_count_1,
296 # When ...
297 my $result_1 = C4::Serials::updateClaim([$serial1->serialid, $serial2->serialid]);
299 # Then ...
300 is($result_1, 2, 'Got the expected 2 from update claim with 2 serial ids');
302 my @late_or_missing_issues_1_0 = C4::Serials::GetLateOrMissingIssues(undef, $serial1->serialid);
303 is($late_or_missing_issues_1_0[0]->{claimdate}, $today, 'Got the expected first different claim date from update claim');
304 is($late_or_missing_issues_1_0[0]->{claims_count}, $claim_count_1+1, 'Got the expected first claim count from update claim');
305 is($late_or_missing_issues_1_0[0]->{status}, 7, 'Got the expected first claim status from update claim');
307 my @late_or_missing_issues_1_1 = C4::Serials::GetLateOrMissingIssues(undef, $serial2->serialid);
308 is($late_or_missing_issues_1_1[0]->{claimdate}, $today, 'Got the expected second different claim date from update claim');
309 is($late_or_missing_issues_1_1[0]->{claims_count}, $claim_count_1+1, 'Got the expected second claim count from update claim');
310 is($late_or_missing_issues_1_1[0]->{status}, 7, 'Got the expected second claim status from update claim');
312 my @late_or_missing_issues_1_2 = C4::Serials::GetLateOrMissingIssues(undef, $serial3->serialid);
313 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');
314 is($late_or_missing_issues_1_2[0]->{claims_count}, $claim_count_1, 'Got the expected unchanged claim count from update claim');
315 is($late_or_missing_issues_1_2[0]->{status}, 3, 'Got the expected unchanged claim status from update claim');
318 is(C4::Serials::check_routing(), undef, 'test checking route');
319 is(C4::Serials::check_routing($subscriptionid), 0, 'There should not have any routing list for the subscription');
320 # TODO really test this check_routing subroutine
322 is(C4::Serials::addroutingmember(),undef, 'test adding route member');
325 # Unit tests for statuses management (Bug 11689)
326 $subscriptionid = NewSubscription(
327 undef, "", undef, undef, $budget_id, $biblionumber,
328 '2013-01-01', $frequency_id, undef, undef, undef,
329 undef, undef, undef, undef, undef, undef,
330 1, $notes,undef, '2013-01-01', undef, $pattern_id,
331 undef, undef, 0, $internalnotes, 0,
332 undef, undef, 0, undef, '2013-12-31', 0
334 my $total_issues;
335 ( $total_issues, @serials ) = C4::Serials::GetSerials( $subscriptionid );
336 is( $total_issues, 1, "NewSubscription created a first serial" );
337 is( @serials, 1, "GetSerials returns the serial" );
338 my $subscription = C4::Serials::GetSubscription($subscriptionid);
339 my $pattern = C4::Serials::Numberpattern::GetSubscriptionNumberpattern($subscription->{numberpattern});
340 ( $total_issues, @serials ) = C4::Serials::GetSerials( $subscriptionid );
341 my $publisheddate = output_pref({ dt => dt_from_string, dateformat => 'iso', dateonly => 1 });
342 ( $total_issues, @serials ) = C4::Serials::GetSerials( $subscriptionid );
343 $frequency = C4::Serials::Frequency::GetSubscriptionFrequency($subscription->{periodicity});
344 my $nextpublisheddate = C4::Serials::GetNextDate($subscription, $publisheddate, $frequency, 1);
345 my @statuses = qw( 2 2 3 3 3 3 3 4 4 41 42 43 44 5 );
346 # Add 14 serials
347 my $counter = 0;
348 for my $status ( @statuses ) {
349 my $serialseq = "No.".$counter;
350 my ( $expected_serial ) = GetSerials2( $subscriptionid, [1] );
351 C4::Serials::ModSerialStatus( $expected_serial->{serialid}, $serialseq, $publisheddate, $publisheddate, $publisheddate, $statuses[$counter], 'an useless note' );
352 $counter++;
354 # 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
355 my @serialsByStatus = C4::Serials::findSerialsByStatus(2,$subscriptionid);
356 is(@serialsByStatus,2,"findSerialsByStatus returns all serials with chosen status");
357 ( $total_issues, @serials ) = C4::Serials::GetSerials( $subscriptionid );
358 is( $total_issues, @statuses + 1, "GetSerials returns total_issues" );
359 my @arrived_missing = map { my $status = $_->{status}; ( grep { /^$status$/ } qw( 2 4 41 42 43 44 5 ) ) ? $_ : () } @serials;
360 my @others = map { my $status = $_->{status}; ( grep { /^$status$/ } qw( 2 4 41 42 43 44 5 ) ) ? () : $_ } @serials;
361 is( @arrived_missing, 5, "GetSerials returns 5 arrived/missing by default" );
362 is( @others, 6, "GetSerials returns all serials not arrived and not missing" );
364 ( $total_issues, @serials ) = C4::Serials::GetSerials( $subscriptionid, 10 );
365 is( $total_issues, @statuses + 1, "GetSerials returns total_issues" );
366 @arrived_missing = map { my $status = $_->{status}; ( grep { /^$status$/ } qw( 2 4 41 42 43 44 5 ) ) ? $_ : () } @serials;
367 @others = map { my $status = $_->{status}; ( grep { /^$status$/ } qw( 2 4 41 42 43 44 5 ) ) ? () : $_ } @serials;
368 is( @arrived_missing, 9, "GetSerials returns all arrived/missing if count given" );
369 is( @others, 6, "GetSerials returns all serials not arrived and not missing if count given" );
371 $subscription = C4::Serials::GetSubscription($subscriptionid); # Retrieve the updated subscription
373 my @serialseqs;
374 for my $am ( @arrived_missing ) {
375 if ( grep {/^$am->{status}$/} qw( 4 41 42 43 44 ) ) {
376 push @serialseqs, $am->{serialseq}
377 } elsif ( grep {/^$am->{status}$/} qw( 5 ) ) {
378 push @serialseqs, 'not issued ' . $am->{serialseq};
381 is( $subscription->{missinglist}, join('; ', @serialseqs), "subscription missinglist is updated after ModSerialStatus" );
383 subtest "Do not generate an expected if one already exists" => sub {
384 plan tests => 2;
385 my ($expected_serial) = GetSerials2( $subscriptionid, [1] );
387 #Find serialid for serial with status Expected
388 my $serialexpected = ( C4::Serials::findSerialsByStatus( 1, $subscriptionid ) )[0];
390 #delete serial with status Expected
391 C4::Serials::ModSerialStatus( $serialexpected->{serialid}, $serialexpected->{serialseq}, $publisheddate, $publisheddate, $publisheddate, '1', 'an useless note' );
392 @serialsByStatus = C4::Serials::findSerialsByStatus( 1, $subscriptionid );
393 is( @serialsByStatus, 1, "ModSerialStatus delete corectly serial expected and create another if not exist" );
395 # add 1 serial with status=Expected 1
396 C4::Serials::ModSerialStatus( $expected_serial->{serialid}, 'NO.20', $publisheddate, $publisheddate, $publisheddate, '1', 'an useless note' );
398 #Now we have two serials it have status expected
399 #put status delete for last serial
400 C4::Serials::ModSerialStatus( $serialexpected->{serialid}, $serialexpected->{serialseq}, $publisheddate, $publisheddate, $publisheddate, '1', 'an useless note' );
402 #try if create or not another serial with status is expected
403 @serialsByStatus = C4::Serials::findSerialsByStatus( 1, $subscriptionid );
404 is( @serialsByStatus, 1, "ModSerialStatus delete corectly serial expected and not create another if exists" );
407 subtest "PreserveSerialNotes preference" => sub {
408 plan tests => 2;
409 my ($expected_serial) = GetSerials2( $subscriptionid, [1] );
411 t::lib::Mocks::mock_preference( 'PreserveSerialNotes', 1 );
413 C4::Serials::ModSerialStatus( $expected_serial->{serialid}, 'NO.20', $publisheddate, $publisheddate, $publisheddate, '1', 'an useless note' );
414 @serialsByStatus = C4::Serials::findSerialsByStatus( 1, $subscriptionid );
415 is( $serialsByStatus[0]->{note},$expected_serial->{note}, "note passed through if supposed to");
417 t::lib::Mocks::mock_preference( 'PreserveSerialNotes', 0 );
418 $expected_serial = $serialsByStatus[0];
419 C4::Serials::ModSerialStatus( $expected_serial->{serialid}, 'NO.20', $publisheddate, $publisheddate, $publisheddate, '1', 'an useless note' );
420 is( $serialsByStatus[0]->{note},$expected_serial->{note}, "note not passed through if not supposed to");
424 subtest "NewSubscription" => sub {
425 plan tests => 1;
426 my $subscriptionid = NewSubscription(
427 "", "", "", "", $budget_id, $biblionumber,
428 '2013-01-01', $frequency_id, "", "", "",
429 "", "", "", "", "", "",
430 1, $notes,"", '2013-01-01', "", $pattern_id,
431 "", "", 0, $internalnotes, 0,
432 "", "", 0, "", '2013-12-31', 0
434 ok($subscriptionid, "Sending empty string instead of undef to reflect use of the interface");