Bug 22061: (follow-up) set_password expects a hashref
[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     ( $biblionumber, $biblioitemnumber ) = get_biblio();
147     my ( $icn_tag, $icn_sf ) = GetMarcFromKohaField( 'items.itemcallnumber', '' );
148     my ( $it_tag, $it_sf )   = GetMarcFromKohaField( 'items.itype', '' );
149
150     my $itemtype = $builder->build( { source => 'Itemtype' } )->{itemtype};
151     my $itemcallnumber = 'XXXmy itemcallnumberXXX';
152
153     my $item_record    = new MARC::Record;
154
155     $item_record->append_fields(
156         MARC::Field->new( '080', '', '', "a" => "default" ),
157         MARC::Field->new(
158             $icn_tag, '', '',
159             $icn_sf => $itemcallnumber,
160             $it_sf  => $itemtype
161         )
162     );
163     my ( undef, undef, $itemnumber ) = C4::Items::AddItemFromMarc( $item_record, $biblionumber );
164     my $serialid = C4::Serials::NewIssue( "serialseq", $subscriptionid, $biblionumber,
165                                           1, undef, undef, "publisheddatetext", "notes" );
166     C4::Serials::AddItem2Serial( $serialid, $itemnumber );
167     my $serial_info = C4::Serials::GetSerialInformation($serialid);
168     my ($itemcallnumber_info) = grep { $_->{kohafield} eq 'items.itemcallnumber' }
169                                      @{ $serial_info->{items}[0]->{iteminformation} };
170     like( $itemcallnumber_info->{marc_value}, qr|value="$itemcallnumber"| );
171 };
172
173 # Delete created frequency
174 if ($old_frequency) {
175     my $freq_to_delete = $subscriptioninformation->{periodicity};
176     $subscriptioninformation->{periodicity} = $old_frequency;
177
178     ModSubscription( @$subscriptioninformation{qw(
179         librarian branchcode aqbooksellerid cost aqbudgetid startdate
180         periodicity firstacquidate irregularity numberpattern locale
181         numberlength weeklength monthlength lastvalue1 innerloop1 lastvalue2
182         innerloop2 lastvalue3 innerloop3 status biblionumber callnumber notes
183         letter manualhistory internalnotes serialsadditems staffdisplaycount
184         opacdisplaycount graceperiod location enddate subscriptionid
185         skip_serialseq
186     )} );
187
188     DelSubscriptionFrequency($freq_to_delete);
189 }
190
191 # Test calling subs without parameters
192 is(C4::Serials::AddItem2Serial(), undef, 'test adding item to serial');
193 is(C4::Serials::GetFullSubscription(), undef, 'test getting full subscription');
194 is(C4::Serials::PrepareSerialsData(), undef, 'test preparing serial data');
195 is(C4::Serials::GetSubscriptionsFromBiblionumber(), undef, 'test getting subscriptions form biblio number');
196
197 is(C4::Serials::GetSerials(), undef, 'test getting serials when you enter nothing');
198 is(C4::Serials::GetSerials2(), undef, 'test getting serials when you enter nothing');
199
200 is(C4::Serials::GetLatestSerials(), undef, 'test getting lastest serials');
201
202 is(C4::Serials::GetNextSeq(), undef, 'test getting next seq when you enter nothing');
203
204 is(C4::Serials::GetSeq(), undef, 'test getting seq when you enter nothing');
205
206 is(C4::Serials::CountSubscriptionFromBiblionumber(), undef, 'test counting subscription when nothing is entered');
207
208 is(C4::Serials::ModSubscriptionHistory(), undef, 'test modding subscription history');
209
210 is(C4::Serials::ModSerialStatus(),undef, 'test modding serials');
211
212 is(C4::Serials::findSerialsByStatus(), 0, 'test finding serial by status with no parameters');
213
214 is(C4::Serials::NewIssue(), undef, 'test getting 0 when nothing is entered');
215
216 is(C4::Serials::HasSubscriptionStrictlyExpired(), undef, 'test if the subscriptions has expired');
217 is(C4::Serials::HasSubscriptionExpired(), undef, 'test if the subscriptions has expired');
218
219 is(C4::Serials::GetLateOrMissingIssues(), undef, 'test getting last or missing issues');
220
221 subtest 'test_updateClaim' => sub {
222     plan tests => 11;
223
224     my $today = output_pref({ dt => dt_from_string, dateonly => 1 });
225     # Given ... nothing much
226     # When ... Then ...
227     my $result_0 = C4::Serials::updateClaim(undef);
228     is($result_0, undef, 'Got the expected undef from update claim with nothin');
229
230     # Given ... 3 serial. 2 of them updated.
231     my $serialids_1   = [90980, 90981];
232     my $claimdate_1   = dt_from_string('2001-01-13'); # arbitrary date some time in the past.
233     my $claim_count_1 = 5;
234     Koha::Serial->new( { serialid => $serialids_1->[0], serialseq => 'serialseq', subscriptionid => $subscriptionid, status => 3,
235                          biblionumber => 12345, claimdate => $claimdate_1, claims_count => $claim_count_1, } )->store();
236     Koha::Serial->new( { serialid => $serialids_1->[1], serialseq => 'serialseq', subscriptionid => $subscriptionid, status => 3,
237                          biblionumber => 12345, claimdate => $claimdate_1, claims_count => $claim_count_1,  } )->store();
238     Koha::Serial->new( { serialid => 90982, serialseq => 'serialseq', subscriptionid => $subscriptionid, status => 3,
239                          biblionumber => 12345, claimdate => $claimdate_1, claims_count => $claim_count_1,  } )->store();
240
241     # When ...
242     my $result_1 = C4::Serials::updateClaim($serialids_1);
243
244     # Then ...
245     is($result_1, 2, 'Got the expected 2 from update claim with 2 serial ids');
246
247     my @late_or_missing_issues_1_0 = C4::Serials::GetLateOrMissingIssues(undef, $serialids_1->[0]);
248     is($late_or_missing_issues_1_0[0]->{claimdate}, $today, 'Got the expected first different claim date from update claim');
249     is($late_or_missing_issues_1_0[0]->{claims_count}, $claim_count_1+1, 'Got the expected first claim count from update claim');
250     is($late_or_missing_issues_1_0[0]->{status}, 7, 'Got the expected first claim status from update claim');
251
252     my @late_or_missing_issues_1_1 = C4::Serials::GetLateOrMissingIssues(undef, $serialids_1->[1]);
253     is($late_or_missing_issues_1_1[0]->{claimdate}, $today, 'Got the expected second different claim date from update claim');
254     is($late_or_missing_issues_1_1[0]->{claims_count}, $claim_count_1+1, 'Got the expected second claim count from update claim');
255     is($late_or_missing_issues_1_1[0]->{status}, 7, 'Got the expected second claim status from update claim');
256
257     my @late_or_missing_issues_1_2 = C4::Serials::GetLateOrMissingIssues(undef, 90982);
258     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');
259     is($late_or_missing_issues_1_2[0]->{claims_count}, $claim_count_1, 'Got the expected unchanged claim count from update claim');
260     is($late_or_missing_issues_1_2[0]->{status}, 3, 'Got the expected unchanged claim status from update claim');
261 };
262
263 is(C4::Serials::check_routing(), undef, 'test checking route');
264
265 is(C4::Serials::addroutingmember(),undef, 'test adding route member');
266
267
268 # Unit tests for statuses management (Bug 11689)
269 $subscriptionid = NewSubscription(
270     undef,      "",     undef, undef, $budget_id, $biblionumber,
271     '2013-01-01', $frequency_id, undef, undef,  undef,
272     undef,      undef,  undef, undef, undef, undef,
273     1,          $notes,undef, '2013-01-01', undef, $pattern_id,
274     undef,       undef,  0,    $internalnotes,  0,
275     undef, undef, 0,          undef,         '2013-12-31', 0
276 );
277 my $total_issues;
278 ( $total_issues, @serials ) = C4::Serials::GetSerials( $subscriptionid );
279 is( $total_issues, 1, "NewSubscription created a first serial" );
280 is( @serials, 1, "GetSerials returns the serial" );
281 my $subscription = C4::Serials::GetSubscription($subscriptionid);
282 my $pattern = C4::Serials::Numberpattern::GetSubscriptionNumberpattern($subscription->{numberpattern});
283 ( $total_issues, @serials ) = C4::Serials::GetSerials( $subscriptionid );
284 my $publisheddate = output_pref({ dt => dt_from_string, dateformat => 'iso', dateonly => 1 });
285 ( $total_issues, @serials ) = C4::Serials::GetSerials( $subscriptionid );
286 $frequency = C4::Serials::Frequency::GetSubscriptionFrequency($subscription->{periodicity});
287 my $nextpublisheddate = C4::Serials::GetNextDate($subscription, $publisheddate, $frequency, 1);
288 my @statuses = qw( 2 2 3 3 3 3 3 4 4 41 42 43 44 5 );
289 # Add 14 serials
290 my $counter = 0;
291 for my $status ( @statuses ) {
292     my $serialseq = "No.".$counter;
293     my ( $expected_serial ) = GetSerials2( $subscriptionid, [1] );
294     C4::Serials::ModSerialStatus( $expected_serial->{serialid}, $serialseq, $publisheddate, $publisheddate, $publisheddate, $statuses[$counter], 'an useless note' );
295     $counter++;
296 }
297 # 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
298 my @serialsByStatus = C4::Serials::findSerialsByStatus(2,$subscriptionid);
299 is(@serialsByStatus,2,"findSerialsByStatus returns all serials with chosen status");
300 ( $total_issues, @serials ) = C4::Serials::GetSerials( $subscriptionid );
301 is( $total_issues, @statuses + 1, "GetSerials returns total_issues" );
302 my @arrived_missing = map { my $status = $_->{status}; ( grep { /^$status$/ } qw( 2 4 41 42 43 44 5 ) ) ? $_ : () } @serials;
303 my @others = map { my $status = $_->{status}; ( grep { /^$status$/ } qw( 2 4 41 42 43 44 5 ) ) ? () : $_ } @serials;
304 is( @arrived_missing, 5, "GetSerials returns 5 arrived/missing by default" );
305 is( @others, 6, "GetSerials returns all serials not arrived and not missing" );
306
307 ( $total_issues, @serials ) = C4::Serials::GetSerials( $subscriptionid, 10 );
308 is( $total_issues, @statuses + 1, "GetSerials returns total_issues" );
309 @arrived_missing = map { my $status = $_->{status}; ( grep { /^$status$/ } qw( 2 4 41 42 43 44 5 ) ) ? $_ : () } @serials;
310 @others = map { my $status = $_->{status}; ( grep { /^$status$/ } qw( 2 4 41 42 43 44 5 ) ) ? () : $_ } @serials;
311 is( @arrived_missing, 9, "GetSerials returns all arrived/missing if count given" );
312 is( @others, 6, "GetSerials returns all serials not arrived and not missing if count given" );
313
314 $subscription = C4::Serials::GetSubscription($subscriptionid); # Retrieve the updated subscription
315
316 my @serialseqs;
317 for my $am ( @arrived_missing ) {
318     if ( grep {/^$am->{status}$/} qw( 4 41 42 43 44 ) ) {
319         push @serialseqs, $am->{serialseq}
320     } elsif ( grep {/^$am->{status}$/} qw( 5 ) ) {
321         push @serialseqs, 'not issued ' . $am->{serialseq};
322     }
323 }
324 is( $subscription->{missinglist}, join('; ', @serialseqs), "subscription missinglist is updated after ModSerialStatus" );
325
326 subtest "Do not generate an expected if one already exists" => sub {
327     plan tests => 2;
328     my ($expected_serial) = GetSerials2( $subscriptionid, [1] );
329
330     #Find serialid for serial with status Expected
331     my $serialexpected = ( C4::Serials::findSerialsByStatus( 1, $subscriptionid ) )[0];
332
333     #delete serial with status Expected
334     C4::Serials::ModSerialStatus( $serialexpected->{serialid}, $serialexpected->{serialseq}, $publisheddate, $publisheddate, $publisheddate, '1', 'an useless note' );
335     @serialsByStatus = C4::Serials::findSerialsByStatus( 1, $subscriptionid );
336     is( @serialsByStatus, 1, "ModSerialStatus delete corectly serial expected and create another if not exist" );
337
338     # add 1 serial with status=Expected 1
339     C4::Serials::ModSerialStatus( $expected_serial->{serialid}, 'NO.20', $publisheddate, $publisheddate, $publisheddate, '1', 'an useless note' );
340
341     #Now we have two serials it have status expected
342     #put status delete for last serial
343     C4::Serials::ModSerialStatus( $serialexpected->{serialid}, $serialexpected->{serialseq}, $publisheddate, $publisheddate, $publisheddate, '1', 'an useless note' );
344
345     #try if create or not another serial with status is expected
346     @serialsByStatus = C4::Serials::findSerialsByStatus( 1, $subscriptionid );
347     is( @serialsByStatus, 1, "ModSerialStatus delete corectly serial expected and not create another if exists" );
348 };
349
350 sub get_biblio {
351     my $bib = MARC::Record->new();
352     $bib->append_fields(
353         MARC::Field->new('100', ' ', ' ', a => 'Moffat, Steven'),
354         MARC::Field->new('245', ' ', ' ', a => 'Silence in the library'),
355     );
356     my ($bibnum, $bibitemnum) = AddBiblio($bib, '');
357     return ($bibnum, $bibitemnum);
358 }