View | Details | Raw Unified | Return to bug 12133
Collapse All | Expand All

(-)a/Koha/Exceptions/Patron/Relationship.pm (-2 / +9 lines)
Lines 32-39 use Exception::Class ( Link Here
32
    'Koha::Exceptions::Patron::Relationship::InvalidRelationship' => {
32
    'Koha::Exceptions::Patron::Relationship::InvalidRelationship' => {
33
        isa         => 'Koha::Exceptions::Patron::Relationship',
33
        isa         => 'Koha::Exceptions::Patron::Relationship',
34
        description => 'The specified relationship is invalid',
34
        description => 'The specified relationship is invalid',
35
        fields      =>  ['relationship','no_relationship']
35
        fields => [ 'relationship', 'no_relationship', 'invalid_guarantor' ]
36
    }
36
    },
37
    'Koha::Exceptions::Patron::Relationship::NoGuarantor' => {
38
        isa         => 'Koha::Exceptions::Patron::Relationship',
39
        description => 'Child patron needs a guarantor',
40
    },
37
);
41
);
38
42
39
sub full_message {
43
sub full_message {
Lines 46-51 sub full_message { Link Here
46
            if ( $self->no_relationship ) {
50
            if ( $self->no_relationship ) {
47
                $msg = sprintf( "No relationship passed." );
51
                $msg = sprintf( "No relationship passed." );
48
            }
52
            }
53
            elsif ( $self->invalid_guarantor ) {
54
                $msg = sprintf("Child patron cannot be a guarantor.");
55
            }
49
            else {
56
            else {
50
                $msg = sprintf("Invalid relationship passed, '%s' is not defined.", $self->relationship );
57
                $msg = sprintf("Invalid relationship passed, '%s' is not defined.", $self->relationship );
51
            }
58
            }
(-)a/Koha/Patron.pm (-1 / +37 lines)
Lines 185-191 to db Link Here
185
=cut
185
=cut
186
186
187
sub store {
187
sub store {
188
    my ($self) = @_;
188
    my $self = shift;
189
    my $params = @_ ? shift : {};
190
191
    my $guarantors = $params->{guarantors} // [];
189
192
190
    $self->_result->result_source->schema->txn_do(
193
    $self->_result->result_source->schema->txn_do(
191
        sub {
194
        sub {
Lines 282-287 sub store { Link Here
282
285
283
                $self->borrowernumber(undef);
286
                $self->borrowernumber(undef);
284
287
288
                if ( C4::Context->preference('ChildNeedsGuarantor')
289
                    and ( $self->is_child or $self->category->can_be_guarantee )
290
                    and $self->contactname eq ""
291
                    and !@$guarantors )
292
                {
293
                    Koha::Exceptions::Patron::Relationship::NoGuarantor->throw();
294
                }
295
296
                foreach my $guarantor (@$guarantors) {
297
                    if ( $guarantor->is_child or $guarantor->category->can_be_guarantee) {
298
                        Koha::Exceptions::Patron::Relationship::InvalidRelationship
299
                        ->throw( invalid_guarantor => 1 );
300
                    }
301
                }
302
285
                $self = $self->SUPER::store;
303
                $self = $self->SUPER::store;
286
304
287
                $self->add_enrolment_fee_if_needed(0);
305
                $self->add_enrolment_fee_if_needed(0);
Lines 327-332 sub store { Link Here
327
345
328
                }
346
                }
329
347
348
                my @existing_guarantors = $self->guarantor_relationships()->guarantors->as_list;
349
                push @$guarantors, @existing_guarantors;
350
351
                if ( C4::Context->preference('ChildNeedsGuarantor')
352
                    and ( $self->is_child or $self->category->can_be_guarantee )
353
                    and $self->contactname eq ""
354
                    and !@$guarantors )
355
                {
356
                    Koha::Exceptions::Patron::Relationship::NoGuarantor->throw();
357
                }
358
359
                foreach my $guarantor (@$guarantors) {
360
                    if ( $guarantor->is_child or $guarantor->category->can_be_guarantee) {
361
                        Koha::Exceptions::Patron::Relationship::InvalidRelationship
362
                        ->throw( invalid_guarantor => 1 );
363
                    }
364
                }
365
330
                # Actionlogs
366
                # Actionlogs
331
                if ( C4::Context->preference("BorrowersLog") ) {
367
                if ( C4::Context->preference("BorrowersLog") ) {
332
                    my $info;
368
                    my $info;
(-)a/installer/data/mysql/atomicupdate/bug_12133.pl (+17 lines)
Line 0 Link Here
1
use Modern::Perl;
2
3
return {
4
    bug_number => "12133",
5
    description => "Add system preference ChildNeedsGuarantor",
6
    up => sub {
7
        my ($args) = @_;
8
        my ($dbh, $out) = @$args{qw(dbh out)};
9
10
        $dbh->do( q{
11
            INSERT IGNORE INTO systempreferences (variable,value,explanation,options,type)
12
            VALUES('ChildNeedsGuarantor', 0, 'If ON, a child patron must have a guarantor when adding the patron.', '', 'YesNo');
13
        } );
14
15
        say $out "Added new system preference 'ChildNeedsGuarantor')\n";
16
    },
17
};
(-)a/installer/data/mysql/mandatory/sysprefs.sql (+1 lines)
Lines 138-143 INSERT INTO systempreferences ( `variable`, `value`, `options`, `explanation`, ` Link Here
138
('ChargeFinesOnClosedDays','0',NULL,'Charge fines on days the library is closed.','YesNo'),
138
('ChargeFinesOnClosedDays','0',NULL,'Charge fines on days the library is closed.','YesNo'),
139
('CheckPrevCheckout','hardno','hardyes|softyes|softno|hardno','By default, for every item checked out, should we warn if the patron has borrowed that item in the past?','Choice'),
139
('CheckPrevCheckout','hardno','hardyes|softyes|softno|hardno','By default, for every item checked out, should we warn if the patron has borrowed that item in the past?','Choice'),
140
('CheckPrevCheckoutDelay','0', NULL,'Maximum number of days that will trigger a warning if the patron has borrowed that item in the past when CheckPrevCheckout is enabled.','free'),
140
('CheckPrevCheckoutDelay','0', NULL,'Maximum number of days that will trigger a warning if the patron has borrowed that item in the past when CheckPrevCheckout is enabled.','free'),
141
('ChildNeedsGuarantor', 0, 'If ON, a child patron must have a guarantor when adding the patron.', '', 'YesNo'),
141
('CircAutoPrintQuickSlip','qslip',NULL,'Choose what should happen when an empty barcode field is submitted in circulation: Display a print quick slip window, Display a print slip window or Clear the screen.','Choice'),
142
('CircAutoPrintQuickSlip','qslip',NULL,'Choose what should happen when an empty barcode field is submitted in circulation: Display a print quick slip window, Display a print slip window or Clear the screen.','Choice'),
142
('CircConfirmItemParts', '0', NULL, 'Require staff to confirm that all parts of an item are present at checkin/checkout.', 'Yes/No'),
143
('CircConfirmItemParts', '0', NULL, 'Require staff to confirm that all parts of an item are present at checkin/checkout.', 'Yes/No'),
143
('CircControl','ItemHomeLibrary','PickupLibrary|PatronLibrary|ItemHomeLibrary','Specify the agency that controls the circulation and fines policy','Choice'),
144
('CircControl','ItemHomeLibrary','PickupLibrary|PatronLibrary|ItemHomeLibrary','Specify the agency that controls the circulation and fines policy','Choice'),
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/patrons.pref (+7 lines)
Lines 363-368 Patrons: Link Here
363
               1: Allow
363
               1: Allow
364
               0: "Don't allow"
364
               0: "Don't allow"
365
         - staff to set the ability for a patron's charges to be viewed by linked patrons in the OPAC.
365
         - staff to set the ability for a patron's charges to be viewed by linked patrons in the OPAC.
366
     -
367
         - "A child patron"
368
         - pref: "ChildNeedsGuarantor"
369
           choices:
370
               1: "must have"
371
               0: "doesn't need"
372
         - a guarantor when adding the patron.
366
373
367
    Privacy:
374
    Privacy:
368
     -
375
     -
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/members/memberentrygen.tt (+9 lines)
Lines 181-186 legend:hover { Link Here
181
                                    [% IF ERROR_bad_email_alternative %]
181
                                    [% IF ERROR_bad_email_alternative %]
182
                                        <li id="ERROR_bad_email_alternative">The alternative email is invalid.</li>
182
                                        <li id="ERROR_bad_email_alternative">The alternative email is invalid.</li>
183
                                    [% END %]
183
                                    [% END %]
184
                                    [% IF ( ERROR_child_no_guarantor ) %]
185
                                        <li id="ERROR_child_no_guarantor">A child patron needs a guarantor.</li>
186
                                    [% END %]
187
                                    [% IF ( ERROR_guarantor_is_guarantee ) %]
188
                                        <li id="ERROR_guarantor_is_guarantee">A guarantor cannot be a guarantee.</li>
189
                                    [% END %]
190
                                    [% IF ( ERROR_cannot_delete_guarantor ) %]
191
                                        <li id="ERROR_cannot_delete_guarantor">Cannot delete guarantor(s). A child patron needs a guarantor.</li>
192
                                    [% END %]
184
                                </ul>
193
                                </ul>
185
                            </div>
194
                            </div>
186
                        [% END %]
195
                        [% END %]
(-)a/members/memberentry.pl (-6 / +42 lines)
Lines 111-122 my $guarantor = undef; Link Here
111
$guarantor = Koha::Patrons->find( $guarantor_id ) if $guarantor_id;
111
$guarantor = Koha::Patrons->find( $guarantor_id ) if $guarantor_id;
112
$template->param( guarantor => $guarantor );
112
$template->param( guarantor => $guarantor );
113
113
114
my @delete_guarantor = $input->multi_param('delete_guarantor');
114
#Search existing guarantor id(s) and new ones from params
115
foreach my $id ( @delete_guarantor ) {
115
my @guarantors;
116
    my $r = Koha::Patron::Relationships->find( $id );
116
my @new_guarantor_ids = grep { $_ ne '' } $input->multi_param('new_guarantor_id');
117
    $r->delete() if $r;
117
118
foreach my $new_guarantor_id (@new_guarantor_ids) {
119
    my $new_guarantor = Koha::Patrons->find( { borrowernumber => $new_guarantor_id } );
120
    push @guarantors, $new_guarantor;
118
}
121
}
119
122
123
my @existing_guarantors = $patron->guarantor_relationships()->guarantors->as_list unless !$patron;
124
push @guarantors, @existing_guarantors;
125
120
## Deal with debarments
126
## Deal with debarments
121
$template->param(
127
$template->param(
122
    restriction_types => scalar Koha::Patron::Restriction::Types->search()
128
    restriction_types => scalar Koha::Patron::Restriction::Types->search()
Lines 266-271 if ( ( $op eq 'insert' ) and !$nodouble ) { Link Here
266
    }
272
    }
267
}
273
}
268
274
275
#Attempt to delete guarantors
276
my @delete_guarantor = $input->multi_param('delete_guarantor');
277
if(@delete_guarantor){
278
    if ( C4::Context->preference('ChildNeedsGuarantor')
279
        && scalar @guarantors - scalar @delete_guarantor == 0 ) {
280
        push @errors, 'ERROR_cannot_delete_guarantor';
281
    } else {
282
        foreach my $id ( @delete_guarantor ) {
283
            my $r = Koha::Patron::Relationships->find( $id );
284
            $r->delete() if $r;
285
        }
286
    }
287
}
288
289
#Check if guarantor requirements are met
290
my $valid_guarantor = @guarantors ? @guarantors : $newdata{'contactname'};
291
if ( ( $op eq 'save' || $op eq 'insert' )
292
    && C4::Context->preference('ChildNeedsGuarantor')
293
    && ( $category->category_type eq 'C' || $category->can_be_guarantee )
294
    && !$valid_guarantor )
295
{
296
    push @errors, 'ERROR_child_no_guarantor';
297
}
298
299
foreach my $guarantor (@guarantors) {
300
    if ( ( $op eq 'save' || $op eq 'insert' ) && $guarantor->is_child || $guarantor->category->can_be_guarantee ) {
301
        push @errors, 'ERROR_guarantor_is_guarantee';
302
    }
303
}
304
269
###############test to take the right zipcode, country and city name ##############
305
###############test to take the right zipcode, country and city name ##############
270
# set only if parameter was passed from the form
306
# set only if parameter was passed from the form
271
$newdata{'city'}    = $input->param('city')    if defined($input->param('city'));
307
$newdata{'city'}    = $input->param('city')    if defined($input->param('city'));
Lines 400-406 if ((!$nok) and $nodouble and ($op eq 'insert' or $op eq 'save')){ Link Here
400
        delete $newdata{password2};
436
        delete $newdata{password2};
401
        $success = 1;
437
        $success = 1;
402
        $patron = try {
438
        $patron = try {
403
            Koha::Patron->new(\%newdata)->store;
439
            Koha::Patron->new(\%newdata)->store({ guarantors => \@guarantors });
404
        } catch {
440
        } catch {
405
            $success = 0;
441
            $success = 0;
406
            $nok = 1;
442
            $nok = 1;
Lines 494-500 if ((!$nok) and $nodouble and ($op eq 'insert' or $op eq 'save')){ Link Here
494
        delete $newdata{password2};
530
        delete $newdata{password2};
495
531
496
        try {
532
        try {
497
            $patron->set(\%newdata)->store if scalar(keys %newdata) > 1;
533
            $patron->set(\%newdata)->store({ guarantors => \@guarantors }) if scalar(keys %newdata) > 1;
498
                # bug 4508 - avoid crash if we're not updating any columns in the borrowers table (editing patron attrs or msg prefs)
534
                # bug 4508 - avoid crash if we're not updating any columns in the borrowers table (editing patron attrs or msg prefs)
499
            $success = 1;
535
            $success = 1;
500
        } catch {
536
        } catch {
(-)a/t/db_dependent/Koha/Patron.t (-3 / +91 lines)
Lines 19-25 Link Here
19
19
20
use Modern::Perl;
20
use Modern::Perl;
21
21
22
use Test::More tests => 24;
22
use Test::More tests => 25;
23
use Test::Exception;
23
use Test::Exception;
24
use Test::Warn;
24
use Test::Warn;
25
25
Lines 1115-1121 subtest 'safe_to_delete() tests' => sub { Link Here
1115
    is( $message->type, 'error', 'Type is error' );
1115
    is( $message->type, 'error', 'Type is error' );
1116
    is( $message->message, 'has_debt', 'Cannot delete, has debt' );
1116
    is( $message->message, 'has_debt', 'Cannot delete, has debt' );
1117
    # cleanup
1117
    # cleanup
1118
    $patron->account->pay({ amount => 10, debits => [ $debit ] });
1118
    #$patron->account->pay({ amount => 10, debits => [ $debit ] });
1119
1119
1120
    ## Happy case :-D
1120
    ## Happy case :-D
1121
    ok( $patron->safe_to_delete, 'Can delete, all conditions met' );
1121
    ok( $patron->safe_to_delete, 'Can delete, all conditions met' );
Lines 1498-1500 subtest 'update privacy tests' => sub { Link Here
1498
    is( $old_checkout->borrowernumber, $anon_patron->id, "Checkout is successfully anonymized");
1498
    is( $old_checkout->borrowernumber, $anon_patron->id, "Checkout is successfully anonymized");
1499
    is( $patron->privacy(), 2, "Patron privacy is successfully updated");
1499
    is( $patron->privacy(), 2, "Patron privacy is successfully updated");
1500
};
1500
};
1501
- 
1501
1502
subtest 'guarantor requirements tests' => sub {
1503
1504
    plan tests => 6;
1505
1506
    $schema->storage->txn_begin;
1507
1508
    my $branchcode = $builder->build( { source => 'Branch' } )->{branchcode};
1509
    my $child_category = $builder->build(
1510
        { source => 'Category', value => { category_type => 'C' } } )
1511
      ->{categorycode};
1512
    my $patron_category = $builder->build(
1513
        { source => 'Category', value => { category_type => 'A' } } )
1514
      ->{categorycode};
1515
1516
    t::lib::Mocks::mock_preference( 'ChildNeedsGuarantor', 0 );
1517
1518
    my $child = Koha::Patron->new(
1519
        {
1520
            branchcode   => $branchcode,
1521
            categorycode => $child_category,
1522
            contactname  => ''
1523
        }
1524
    );
1525
    $child->store();
1526
1527
    ok(
1528
        Koha::Patrons->find( $child->id ),
1529
        'Child patron can be stored without guarantor when ChildNeedsGuarantor is off.'
1530
    );
1531
1532
    t::lib::Mocks::mock_preference( 'ChildNeedsGuarantor', 1 );
1533
1534
    my $child2 = Koha::Patron->new(
1535
        {
1536
            branchcode   => $branchcode,
1537
            categorycode => $child_category,
1538
            contactname  => ''
1539
        }
1540
    );
1541
    my $child3 = $builder->build_object(
1542
        {
1543
            class => 'Koha::Patrons',
1544
            value => { categorycode => $child_category }
1545
        }
1546
    );
1547
    my $patron = $builder->build_object(
1548
        {
1549
            class => 'Koha::Patrons',
1550
            value => { categorycode => $patron_category }
1551
        }
1552
    );
1553
1554
    throws_ok { $child2->store(); }
1555
    'Koha::Exceptions::Patron::Relationship::NoGuarantor',
1556
      'Exception thrown when guarantor is required but not provided.';
1557
1558
    my @guarantors = ( $patron, $child3 );
1559
    throws_ok { $child2->store( { guarantors => \@guarantors } ); }
1560
    'Koha::Exceptions::Patron::Relationship::InvalidRelationship',
1561
      'Exception thrown when child patron is added as guarantor.';
1562
    $child2->discard_changes;
1563
1564
    #test ModMember
1565
    @guarantors = ( $patron );
1566
    $child2->store( { guarantors => \@guarantors } );
1567
1568
    t::lib::Mocks::mock_preference( 'borrowerRelationship', '' );
1569
1570
    my $relationship = Koha::Patron::Relationship->new(
1571
        {   guarantor_id => $patron->borrowernumber,
1572
            guarantee_id => $child2->borrowernumber,
1573
            relationship => ''
1574
        }
1575
    );
1576
    $relationship->store();
1577
1578
    ok( $child2->store(), 'Child patron can be modified and stored when guarantor is stored');
1579
1580
    @guarantors = ( $child3 );
1581
    throws_ok { $child2->store( { guarantors => \@guarantors } ); }
1582
    'Koha::Exceptions::Patron::Relationship::InvalidRelationship',
1583
      'Exception thrown when child patron is modified and child patron is added as guarantor.';
1584
1585
    $relationship->delete;
1586
    throws_ok { $child2->store(); }
1587
    'Koha::Exceptions::Patron::Relationship::NoGuarantor',
1588
      'Exception thrown when guarantor is deleted.';
1589
};

Return to bug 12133