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 186-192 to db Link Here
186
=cut
186
=cut
187
187
188
sub store {
188
sub store {
189
    my ($self) = @_;
189
    my $self = shift;
190
    my $params = @_ ? shift : {};
191
192
    my $guarantors = $params->{guarantors} // [];
190
193
191
    $self->_result->result_source->schema->txn_do(
194
    $self->_result->result_source->schema->txn_do(
192
        sub {
195
        sub {
Lines 283-288 sub store { Link Here
283
286
284
                $self->borrowernumber(undef);
287
                $self->borrowernumber(undef);
285
288
289
                if ( C4::Context->preference('ChildNeedsGuarantor')
290
                    and ( $self->is_child or $self->category->can_be_guarantee )
291
                    and $self->contactname eq ""
292
                    and !@$guarantors )
293
                {
294
                    Koha::Exceptions::Patron::Relationship::NoGuarantor->throw();
295
                }
296
297
                foreach my $guarantor (@$guarantors) {
298
                    if ( $guarantor->is_child or $guarantor->category->can_be_guarantee) {
299
                        Koha::Exceptions::Patron::Relationship::InvalidRelationship
300
                        ->throw( invalid_guarantor => 1 );
301
                    }
302
                }
303
286
                $self = $self->SUPER::store;
304
                $self = $self->SUPER::store;
287
305
288
                $self->add_enrolment_fee_if_needed(0);
306
                $self->add_enrolment_fee_if_needed(0);
Lines 328-333 sub store { Link Here
328
346
329
                }
347
                }
330
348
349
                my @existing_guarantors = $self->guarantor_relationships()->guarantors->as_list;
350
                push @$guarantors, @existing_guarantors;
351
352
                if ( C4::Context->preference('ChildNeedsGuarantor')
353
                    and ( $self->is_child or $self->category->can_be_guarantee )
354
                    and $self->contactname eq ""
355
                    and !@$guarantors )
356
                {
357
                    Koha::Exceptions::Patron::Relationship::NoGuarantor->throw();
358
                }
359
360
                foreach my $guarantor (@$guarantors) {
361
                    if ( $guarantor->is_child or $guarantor->category->can_be_guarantee) {
362
                        Koha::Exceptions::Patron::Relationship::InvalidRelationship
363
                        ->throw( invalid_guarantor => 1 );
364
                    }
365
                }
366
331
                # Actionlogs
367
                # Actionlogs
332
                if ( C4::Context->preference("BorrowersLog") ) {
368
                if ( C4::Context->preference("BorrowersLog") ) {
333
                    my $info;
369
                    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 365-370 Patrons: Link Here
365
               1: Allow
365
               1: Allow
366
               0: "Don't allow"
366
               0: "Don't allow"
367
         - staff to set the ability for a patron's charges to be viewed by linked patrons in the OPAC.
367
         - staff to set the ability for a patron's charges to be viewed by linked patrons in the OPAC.
368
     -
369
         - "A child patron"
370
         - pref: "ChildNeedsGuarantor"
371
           choices:
372
               1: "must have"
373
               0: "doesn't need"
374
         - a guarantor when adding the patron.
368
375
369
    Privacy:
376
    Privacy:
370
     -
377
     -
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/members/memberentrygen.tt (+9 lines)
Lines 183-188 legend:hover { Link Here
183
                                    [% IF ERROR_bad_email_alternative %]
183
                                    [% IF ERROR_bad_email_alternative %]
184
                                        <li id="ERROR_bad_email_alternative">The alternative email is invalid.</li>
184
                                        <li id="ERROR_bad_email_alternative">The alternative email is invalid.</li>
185
                                    [% END %]
185
                                    [% END %]
186
                                    [% IF ( ERROR_child_no_guarantor ) %]
187
                                        <li id="ERROR_child_no_guarantor">A child patron needs a guarantor.</li>
188
                                    [% END %]
189
                                    [% IF ( ERROR_guarantor_is_guarantee ) %]
190
                                        <li id="ERROR_guarantor_is_guarantee">A guarantor cannot be a guarantee.</li>
191
                                    [% END %]
192
                                    [% IF ( ERROR_cannot_delete_guarantor ) %]
193
                                        <li id="ERROR_cannot_delete_guarantor">Cannot delete guarantor(s). A child patron needs a guarantor.</li>
194
                                    [% END %]
186
                                </ul>
195
                                </ul>
187
                            </div>
196
                            </div>
188
                        [% END %]
197
                        [% 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 404-410 if ((!$nok) and $nodouble and ($op eq 'insert' or $op eq 'save')){ Link Here
404
        delete $newdata{password2};
440
        delete $newdata{password2};
405
        $success = 1;
441
        $success = 1;
406
        $patron = try {
442
        $patron = try {
407
            Koha::Patron->new(\%newdata)->store;
443
            Koha::Patron->new(\%newdata)->store({ guarantors => \@guarantors });
408
        } catch {
444
        } catch {
409
            $success = 0;
445
            $success = 0;
410
            $nok = 1;
446
            $nok = 1;
Lines 498-504 if ((!$nok) and $nodouble and ($op eq 'insert' or $op eq 'save')){ Link Here
498
        delete $newdata{password2};
534
        delete $newdata{password2};
499
535
500
        try {
536
        try {
501
            $patron->set(\%newdata)->store if scalar(keys %newdata) > 1;
537
            $patron->set(\%newdata)->store({ guarantors => \@guarantors }) if scalar(keys %newdata) > 1;
502
                # bug 4508 - avoid crash if we're not updating any columns in the borrowers table (editing patron attrs or msg prefs)
538
                # bug 4508 - avoid crash if we're not updating any columns in the borrowers table (editing patron attrs or msg prefs)
503
            $success = 1;
539
            $success = 1;
504
        } catch {
540
        } catch {
(-)a/t/db_dependent/Koha/Patron.t (-1 / +88 lines)
Lines 1549-1551 subtest 'update privacy tests' => sub { Link Here
1549
    is( $old_checkout->borrowernumber, $anon_patron->id, "Checkout is successfully anonymized");
1549
    is( $old_checkout->borrowernumber, $anon_patron->id, "Checkout is successfully anonymized");
1550
    is( $patron->privacy(), 2, "Patron privacy is successfully updated");
1550
    is( $patron->privacy(), 2, "Patron privacy is successfully updated");
1551
};
1551
};
1552
- 
1552
1553
subtest 'guarantor requirements tests' => sub {
1554
1555
    plan tests => 6;
1556
1557
    $schema->storage->txn_begin;
1558
1559
    my $branchcode = $builder->build( { source => 'Branch' } )->{branchcode};
1560
    my $child_category = $builder->build(
1561
        { source => 'Category', value => { category_type => 'C', can_be_guarantee => 1 } } )
1562
      ->{categorycode};
1563
    my $patron_category = $builder->build(
1564
        { source => 'Category', value => { category_type => 'A', can_be_guarantee => 0 } } )
1565
      ->{categorycode};
1566
1567
    t::lib::Mocks::mock_preference( 'ChildNeedsGuarantor', 0 );
1568
1569
    my $child = Koha::Patron->new(
1570
        {
1571
            branchcode   => $branchcode,
1572
            categorycode => $child_category,
1573
            contactname  => ''
1574
        }
1575
    );
1576
    $child->store();
1577
1578
    ok(
1579
        Koha::Patrons->find( $child->id ),
1580
        'Child patron can be stored without guarantor when ChildNeedsGuarantor is off.'
1581
    );
1582
1583
    t::lib::Mocks::mock_preference( 'ChildNeedsGuarantor', 1 );
1584
1585
    my $child2 = Koha::Patron->new(
1586
        {
1587
            branchcode   => $branchcode,
1588
            categorycode => $child_category,
1589
            contactname  => ''
1590
        }
1591
    );
1592
    my $child3 = $builder->build_object(
1593
        {
1594
            class => 'Koha::Patrons',
1595
            value => { categorycode => $child_category }
1596
        }
1597
    );
1598
    my $patron = $builder->build_object(
1599
        {
1600
            class => 'Koha::Patrons',
1601
            value => { categorycode => $patron_category }
1602
        }
1603
    );
1604
1605
    throws_ok { $child2->store(); }
1606
    'Koha::Exceptions::Patron::Relationship::NoGuarantor',
1607
      'Exception thrown when guarantor is required but not provided.';
1608
1609
    my @guarantors = ( $patron, $child3 );
1610
    throws_ok { $child2->store( { guarantors => \@guarantors } ); }
1611
    'Koha::Exceptions::Patron::Relationship::InvalidRelationship',
1612
      'Exception thrown when child patron is added as guarantor.';
1613
1614
    #test ModMember
1615
    @guarantors = ( $patron );
1616
    $child2->store( { guarantors => \@guarantors } )->discard_changes();
1617
1618
    t::lib::Mocks::mock_preference( 'borrowerRelationship', '' );
1619
1620
    my $relationship = Koha::Patron::Relationship->new(
1621
        {   guarantor_id => $patron->borrowernumber,
1622
            guarantee_id => $child2->borrowernumber,
1623
            relationship => ''
1624
        }
1625
    );
1626
    $relationship->store();
1627
1628
    ok( $child2->store(), 'Child patron can be modified and stored when guarantor is stored');
1629
1630
    @guarantors = ( $child3 );
1631
    throws_ok { $child2->store( { guarantors => \@guarantors } ); }
1632
    'Koha::Exceptions::Patron::Relationship::InvalidRelationship',
1633
      'Exception thrown when child patron is modified and child patron is added as guarantor.';
1634
1635
    $relationship->delete;
1636
    throws_ok { $child2->store(); }
1637
    'Koha::Exceptions::Patron::Relationship::NoGuarantor',
1638
      'Exception thrown when guarantor is deleted.';
1639
};

Return to bug 12133