Bug 19382: Adjust comment in test
[koha.git] / t / db_dependent / Koha / Patron.t
blob1b0d24552a8e4481d68e30189c0c4c57d4c22e28
1 #!/usr/bin/perl
3 # Copyright 2019 Koha Development team
5 # This file is part of Koha
7 # Koha is free software; you can redistribute it and/or modify it
8 # under the terms of the GNU General Public License as published by
9 # the Free Software Foundation; either version 3 of the License, or
10 # (at your option) any later version.
12 # Koha is distributed in the hope that it will be useful, but
13 # WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 # GNU General Public License for more details.
17 # You should have received a copy of the GNU General Public License
18 # along with Koha; if not, see <http://www.gnu.org/licenses>.
20 use Modern::Perl;
22 use Test::More tests => 6;
23 use Test::Exception;
25 use Koha::Database;
26 use Koha::DateUtils qw(dt_from_string);
27 use Koha::Patrons;
28 use Koha::Patron::Relationships;
30 use t::lib::TestBuilder;
31 use t::lib::Mocks;
33 my $schema = Koha::Database->new->schema;
34 my $builder = t::lib::TestBuilder->new;
36 subtest 'add_guarantor() tests' => sub {
38 plan tests => 6;
40 $schema->storage->txn_begin;
42 t::lib::Mocks::mock_preference( 'borrowerRelationship', 'father1|father2' );
44 my $patron_1 = $builder->build_object({ class => 'Koha::Patrons' });
45 my $patron_2 = $builder->build_object({ class => 'Koha::Patrons' });
47 throws_ok
48 { $patron_1->add_guarantor({ guarantor_id => $patron_2->borrowernumber }); }
49 'Koha::Exceptions::Patron::Relationship::InvalidRelationship',
50 'Exception is thrown as no relationship passed';
52 is( $patron_1->guarantee_relationships->count, 0, 'No guarantors added' );
54 throws_ok
55 { $patron_1->add_guarantor({ guarantor_id => $patron_2->borrowernumber, relationship => 'father' }); }
56 'Koha::Exceptions::Patron::Relationship::InvalidRelationship',
57 'Exception is thrown as a wrong relationship was passed';
59 is( $patron_1->guarantee_relationships->count, 0, 'No guarantors added' );
61 $patron_1->add_guarantor({ guarantor_id => $patron_2->borrowernumber, relationship => 'father1' });
63 my $guarantors = $patron_1->guarantor_relationships;
65 is( $guarantors->count, 1, 'No guarantors added' );
68 local *STDERR;
69 open STDERR, '>', '/dev/null';
70 throws_ok
71 { $patron_1->add_guarantor({ guarantor_id => $patron_2->borrowernumber, relationship => 'father2' }); }
72 'Koha::Exceptions::Patron::Relationship::DuplicateRelationship',
73 'Exception is thrown for duplicated relationship';
74 close STDERR;
77 $schema->storage->txn_rollback;
80 subtest 'relationships_debt() tests' => sub {
82 plan tests => 168;
84 $schema->storage->txn_begin;
86 t::lib::Mocks::mock_preference( 'borrowerRelationship', 'parent' );
88 my $parent_1 = $builder->build_object({ class => 'Koha::Patrons', value => { firstname => "Parent 1" } });
89 my $parent_2 = $builder->build_object({ class => 'Koha::Patrons', value => { firstname => "Parent 2" } });
90 my $child_1 = $builder->build_object({ class => 'Koha::Patrons', value => { firstname => "Child 1" } });
91 my $child_2 = $builder->build_object({ class => 'Koha::Patrons', value => { firstname => "Child 2" } });
93 $child_1->add_guarantor({ guarantor_id => $parent_1->borrowernumber, relationship => 'parent' });
94 $child_1->add_guarantor({ guarantor_id => $parent_2->borrowernumber, relationship => 'parent' });
95 $child_2->add_guarantor({ guarantor_id => $parent_1->borrowernumber, relationship => 'parent' });
96 $child_2->add_guarantor({ guarantor_id => $parent_2->borrowernumber, relationship => 'parent' });
98 is( $child_1->guarantor_relationships->guarantors->count, 2, 'Child 1 has correct number of guarantors' );
99 is( $child_2->guarantor_relationships->guarantors->count, 2, 'Child 2 has correct number of guarantors' );
100 is( $parent_1->guarantee_relationships->guarantees->count, 2, 'Parent 1 has correct number of guarantees' );
101 is( $parent_2->guarantee_relationships->guarantees->count, 2, 'Parent 2 has correct number of guarantees' );
103 my $patrons = [ $parent_1, $parent_2, $child_1, $child_2 ];
105 # First test: No debt
106 my ($parent1_debt, $parent2_debt, $child1_debt, $child2_debt) = (0,0,0,0);
107 _test_combinations($patrons, $parent1_debt,$parent2_debt,$child1_debt,$child2_debt);
109 # Add debt to child_2
110 $child2_debt = 2;
111 $child_2->account->add_debit({ type => 'ACCOUNT', amount => $child2_debt, interface => 'commandline' });
112 is( $child_2->account->non_issues_charges, $child2_debt, 'Debt added to Child 2' );
113 _test_combinations($patrons, $parent1_debt,$parent2_debt,$child1_debt,$child2_debt);
115 $parent1_debt = 3;
116 $parent_1->account->add_debit({ type => 'ACCOUNT', amount => $parent1_debt, interface => 'commandline' });
117 is( $parent_1->account->non_issues_charges, $parent1_debt, 'Debt added to Parent 1' );
118 _test_combinations($patrons, $parent1_debt,$parent2_debt,$child1_debt,$child2_debt);
120 $parent2_debt = 5;
121 $parent_2->account->add_debit({ type => 'ACCOUNT', amount => $parent2_debt, interface => 'commandline' });
122 is( $parent_2->account->non_issues_charges, $parent2_debt, 'Parent 2 owes correct amount' );
123 _test_combinations($patrons, $parent1_debt,$parent2_debt,$child1_debt,$child2_debt);
125 $child1_debt = 7;
126 $child_1->account->add_debit({ type => 'ACCOUNT', amount => $child1_debt, interface => 'commandline' });
127 is( $child_1->account->non_issues_charges, $child1_debt, 'Child 1 owes correct amount' );
128 _test_combinations($patrons, $parent1_debt,$parent2_debt,$child1_debt,$child2_debt);
130 $schema->storage->txn_rollback;
133 sub _test_combinations {
134 my ( $patrons, $parent1_debt, $parent2_debt, $child1_debt, $child2_debt ) = @_;
136 # Options
137 # P1 => P1 + C1 + C2 ( - P1 ) ( + P2 )
138 # P2 => P2 + C1 + C2 ( - P2 ) ( + P1 )
139 # C1 => P1 + P2 + C1 + C2 ( - C1 )
140 # C2 => P1 + P2 + C1 + C2 ( - C2 )
142 # 3 params, count from 0 to 7 in binary ( 3 places ) to get the set of switches, then do that 4 times, one for each parent and child
143 for my $i ( 0 .. 7 ) {
144 my ( $only_this_guarantor, $include_guarantors, $include_this_patron )
145 = split '', sprintf( "%03b", $i );
146 for my $patron ( @$patrons ) {
147 if ( $only_this_guarantor
148 && !$patron->guarantee_relationships->count )
150 throws_ok {
151 $patron->relationships_debt(
153 only_this_guarantor => $only_this_guarantor,
154 include_guarantors => $include_guarantors,
155 include_this_patron => $include_this_patron
159 'Koha::Exceptions::BadParameter',
160 'Exception is thrown as patron is not a guarantor';
163 else {
165 my $debt = 0;
166 if ( $patron->firstname eq 'Parent 1' ) {
167 $debt += $parent1_debt if ($include_this_patron && $include_guarantors);
168 $debt += $child1_debt + $child2_debt;
169 $debt += $parent2_debt unless ($only_this_guarantor || !$include_guarantors);
171 elsif ( $patron->firstname eq 'Parent 2' ) {
172 $debt += $parent2_debt if ($include_this_patron & $include_guarantors);
173 $debt += $child1_debt + $child2_debt;
174 $debt += $parent1_debt unless ($only_this_guarantor || !$include_guarantors);
176 elsif ( $patron->firstname eq 'Child 1' ) {
177 $debt += $child1_debt if ($include_this_patron);
178 $debt += $child2_debt;
179 $debt += $parent1_debt + $parent2_debt if ($include_guarantors);
181 else {
182 $debt += $child2_debt if ($include_this_patron);
183 $debt += $child1_debt;
184 $debt += $parent1_debt + $parent2_debt if ($include_guarantors);
188 $patron->relationships_debt(
190 only_this_guarantor => $only_this_guarantor,
191 include_guarantors => $include_guarantors,
192 include_this_patron => $include_this_patron
195 $debt,
196 $patron->firstname
197 . " debt of $debt calculated correctly for ( only_this_guarantor: $only_this_guarantor, include_guarantors: $include_guarantors, include_this_patron: $include_this_patron)"
204 subtest 'add_enrolment_fee_if_needed() tests' => sub {
206 plan tests => 2;
208 subtest 'category has enrolment fee' => sub {
209 plan tests => 7;
211 $schema->storage->txn_begin;
213 my $category = $builder->build_object(
215 class => 'Koha::Patron::Categories',
216 value => {
217 enrolmentfee => 20
222 my $patron = $builder->build_object(
224 class => 'Koha::Patrons',
225 value => {
226 categorycode => $category->categorycode
231 my $enrollment_fee = $patron->add_enrolment_fee_if_needed();
232 is( $enrollment_fee * 1, 20, 'Enrolment fee amount is correct' );
233 my $account = $patron->account;
234 is( $patron->account->balance * 1, 20, 'Patron charged the enrolment fee' );
235 # second enrolment fee, new
236 $enrollment_fee = $patron->add_enrolment_fee_if_needed(0);
237 # third enrolment fee, renewal
238 $enrollment_fee = $patron->add_enrolment_fee_if_needed(1);
239 is( $patron->account->balance * 1, 60, 'Patron charged the enrolment fees' );
241 my @debits = $account->outstanding_debits;
242 is( scalar @debits, 3, '3 enrolment fees' );
243 is( $debits[0]->debit_type_code, 'ACCOUNT', 'Account type set correctly' );
244 is( $debits[1]->debit_type_code, 'ACCOUNT', 'Account type set correctly' );
245 is( $debits[2]->debit_type_code, 'ACCOUNT_RENEW', 'Account type set correctly' );
247 $schema->storage->txn_rollback;
250 subtest 'no enrolment fee' => sub {
252 plan tests => 3;
254 $schema->storage->txn_begin;
256 my $category = $builder->build_object(
258 class => 'Koha::Patron::Categories',
259 value => {
260 enrolmentfee => 0
265 my $patron = $builder->build_object(
267 class => 'Koha::Patrons',
268 value => {
269 categorycode => $category->categorycode
274 my $enrollment_fee = $patron->add_enrolment_fee_if_needed();
275 is( $enrollment_fee * 1, 0, 'No enrolment fee' );
276 my $account = $patron->account;
277 is( $patron->account->balance, 0, 'Patron not charged anything' );
279 my @debits = $account->outstanding_debits;
280 is( scalar @debits, 0, 'no debits' );
282 $schema->storage->txn_rollback;
286 subtest 'to_api() tests' => sub {
288 plan tests => 6;
290 $schema->storage->txn_begin;
292 my $patron_class = Test::MockModule->new('Koha::Patron');
293 $patron_class->mock(
294 'algo',
295 sub { return 'algo' }
298 my $patron = $builder->build_object(
300 class => 'Koha::Patrons',
301 value => {
302 debarred => undef
307 my $restricted = $patron->to_api->{restricted};
308 ok( defined $restricted, 'restricted is defined' );
309 ok( !$restricted, 'debarred is undef, restricted evaluates to false' );
311 $patron->debarred( dt_from_string->add( days => 1 ) )->store->discard_changes;
312 $restricted = $patron->to_api->{restricted};
313 ok( defined $restricted, 'restricted is defined' );
314 ok( $restricted, 'debarred is defined, restricted evaluates to true' );
316 my $patron_json = $patron->to_api({ embed => { algo => {} } });
317 ok( exists $patron_json->{algo} );
318 is( $patron_json->{algo}, 'algo' );
320 $schema->storage->txn_rollback;
323 subtest 'login_attempts tests' => sub {
324 plan tests => 1;
326 $schema->storage->txn_begin;
328 my $patron = $builder->build_object(
330 class => 'Koha::Patrons',
333 my $patron_info = $patron->unblessed;
334 $patron->delete;
335 delete $patron_info->{login_attempts};
336 my $new_patron = Koha::Patron->new($patron_info)->store;
337 is( $new_patron->discard_changes->login_attempts, 0, "login_attempts defaults to 0 as expected");
339 $schema->storage->txn_rollback;
342 subtest 'is_superlibrarian() tests' => sub {
344 plan tests => 3;
346 $schema->storage->txn_begin;
348 my $patron = $builder->build_object(
350 class => 'Koha::Patrons',
352 value => {
353 flags => 16
358 is( $patron->is_superlibrarian, 0, 'Patron is not a superlibrarian and the method returns the correct value' );
360 $patron->flags(1)->store->discard_changes;
361 is( $patron->is_superlibrarian, 1, 'Patron is a superlibrarian and the method returns the correct value' );
363 $patron->flags(0)->store->discard_changes;
364 is( $patron->is_superlibrarian, 0, 'Patron is not a superlibrarian and the method returns the correct value' );
366 $schema->storage->txn_rollback;