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

(-)a/Koha/Account.pm (+3 lines)
Lines 39-44 use Koha::Account::DebitTypes; Link Here
39
use Koha::Exceptions;
39
use Koha::Exceptions;
40
use Koha::Exceptions::Account;
40
use Koha::Exceptions::Account;
41
use Koha::Plugins;
41
use Koha::Plugins;
42
use Koha::Patron::Debarments;
42
43
43
=head1 NAME
44
=head1 NAME
44
45
Lines 117-122 sub pay { Link Here
117
        }
118
        }
118
    );
119
    );
119
120
121
    Koha::Patron::Debarments::del_restrictions_after_payment({ borrowernumber => $self->{patron_id} });
122
120
    # NOTE: Pay historically always applied as much credit as it could to all
123
    # NOTE: Pay historically always applied as much credit as it could to all
121
    # existing outstanding debits, whether passed specific debits or otherwise.
124
    # existing outstanding debits, whether passed specific debits or otherwise.
122
    if ( $payment->amountoutstanding ) {
125
    if ( $payment->amountoutstanding ) {
(-)a/Koha/Patron/Debarments.pm (+38 lines)
Lines 21-26 use Modern::Perl; Link Here
21
21
22
use C4::Context;
22
use C4::Context;
23
23
24
use Koha::Patron::Restriction::Types;
25
24
our ( @ISA, @EXPORT_OK );
26
our ( @ISA, @EXPORT_OK );
25
27
26
BEGIN {
28
BEGIN {
Lines 270-275 sub UpdateBorrowerDebarmentFlags { Link Here
270
    return $dbh->do( "UPDATE borrowers SET debarred = ?, debarredcomment = ? WHERE borrowernumber = ?", {}, ( $expiration, $comment, $borrowernumber ) );
272
    return $dbh->do( "UPDATE borrowers SET debarred = ?, debarredcomment = ? WHERE borrowernumber = ?", {}, ( $expiration, $comment, $borrowernumber ) );
271
}
273
}
272
274
275
=head2 del_restrictions_after_payment
276
277
my $success = del_restrictions_after_payment({
278
    borrowernumber => $borrowernumber,
279
});
280
281
Deletes any restrictions from patron by following the rules
282
defined in "Patron restrictions".
283
284
=cut
285
286
sub del_restrictions_after_payment {
287
    my ($params) = @_;
288
289
    my $borrowernumber = $params->{'borrowernumber'};
290
    return unless ( $borrowernumber );
291
292
    my $patron_restrictions = GetDebarments( { borrowernumber => $borrowernumber } );
293
    return unless ( $patron_restrictions );
294
295
    my $patron = Koha::Patrons->find( $borrowernumber );
296
    return unless ( $patron );
297
298
    my $lines = Koha::Account::Lines->search({ borrowernumber  => $borrowernumber });
299
    my $total_due = $lines->total_outstanding;
300
301
    foreach my $patron_restriction (@{ $patron_restrictions }){
302
        my $restriction = Koha::Patron::Restriction::Types->find({
303
            code => $patron_restriction->{type}
304
        });
305
        if($restriction->lift_after_payment && $total_due <= $restriction->fee_limit){
306
            DelDebarment($patron_restriction->{'borrower_debarment_id'});
307
        }
308
    }
309
}
310
273
=head2 _GetBorrowernumberByDebarmentId
311
=head2 _GetBorrowernumberByDebarmentId
274
312
275
my $borrowernumber = _GetBorrowernumberByDebarmentId( $borrower_debarment_id );
313
my $borrowernumber = _GetBorrowernumberByDebarmentId( $borrower_debarment_id );
(-)a/admin/restrictions.pl (-2 / +8 lines)
Lines 54-59 if ( $op eq 'add_form') { Link Here
54
} elsif ( $op eq 'add_validate' ) {
54
} elsif ( $op eq 'add_validate' ) {
55
55
56
    my $display_text = $input->param('display_text');
56
    my $display_text = $input->param('display_text');
57
    my $lift_after_payment = $input->param('lift_after_payment');
58
    my $fee_limit = $input->param('fee_limit');
57
    my $is_a_modif = $input->param("is_a_modif");
59
    my $is_a_modif = $input->param("is_a_modif");
58
60
59
    if ($is_a_modif) {
61
    if ($is_a_modif) {
Lines 64-76 if ( $op eq 'add_form') { Link Here
64
                display_text => $display_text,
66
                display_text => $display_text,
65
            }
67
            }
66
        );
68
        );
67
        if ($dupe->count) {
69
        if ($dupe->count && $dupe->unblessed->{code} ne $code) {
68
            push @messages, {
70
            push @messages, {
69
                type => 'error', code => 'duplicate_display_text'
71
                type => 'error', code => 'duplicate_display_text'
70
            };
72
            };
71
        } else {
73
        } else {
72
            my $restriction = Koha::Patron::Restriction::Types->find($code);
74
            my $restriction = Koha::Patron::Restriction::Types->find($code);
73
            $restriction->display_text($display_text);
75
            $restriction->display_text($display_text);
76
            $restriction->lift_after_payment($lift_after_payment);
77
            $restriction->fee_limit($fee_limit);
74
            $restriction->store;
78
            $restriction->store;
75
            push @messages, { type => 'message', code => 'update_success' };
79
            push @messages, { type => 'message', code => 'update_success' };
76
        }
80
        }
Lines 84-90 if ( $op eq 'add_form') { Link Here
84
        } else {
88
        } else {
85
            my $restriction = Koha::Patron::Restriction::Type->new({
89
            my $restriction = Koha::Patron::Restriction::Type->new({
86
                code => $code,
90
                code => $code,
87
                display_text => $display_text
91
                display_text => $display_text,
92
                lift_after_payment => $lift_after_payment,
93
                fee_limit => $fee_limit
88
            });
94
            });
89
            $restriction->store;
95
            $restriction->store;
90
            push @messages, { type => 'message', code => 'add_success' };
96
            push @messages, { type => 'message', code => 'add_success' };
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/restrictions.tt (+34 lines)
Lines 113-118 Link Here
113
                        <input type="text" value="[% restriction.display_text | html %]" name="display_text" id="display_text" size="50" maxlength="50" class="required" required="required" />
113
                        <input type="text" value="[% restriction.display_text | html %]" name="display_text" id="display_text" size="50" maxlength="50" class="required" required="required" />
114
                        <span class="required">Required</span>
114
                        <span class="required">Required</span>
115
                    </li>
115
                    </li>
116
                    <li>
117
                        <label for="lift_after_payment" class="required">Lift after payment: </label>
118
                        <select type="text" name="lift_after_payment" id="lift_after_payment" class="required" required="required" />
119
                            <option value="1" selected="selected">Yes</option>
120
                            <option value="0">No</option>
121
                        </select>
122
                        <span class="required">Required</span>
123
                    </li>
124
                    <li>
125
                        <label for="fee_limit" class="required">Fee limit: </label>
126
                        <input type="text" value="[% restriction.fee_limit | html %]" inputmode="decimal" pattern="^\d+(\.\d{2})?$" min="0" name="fee_limit" id="fee_limit" class="required" required="required" />
127
                        <span class="required">Required</span>
128
                    </li>
116
                [% ELSE %]
129
                [% ELSE %]
117
                    <li>
130
                    <li>
118
                        <label for="code" class="required">Code: </label>
131
                        <label for="code" class="required">Code: </label>
Lines 124-129 Link Here
124
                        <input type="text" name="display_text" id="display_text" size="50" maxlength="50" class="required" required="required" />
137
                        <input type="text" name="display_text" id="display_text" size="50" maxlength="50" class="required" required="required" />
125
                        <span class="required">Required</span>
138
                        <span class="required">Required</span>
126
                    </li>
139
                    </li>
140
                    <li>
141
                        <label for="lift_after_payment" class="required">Lift after payment: </label>
142
                        <select type="text" name="lift_after_payment" id="lift_after_payment" class="required" required="required" />
143
                            <option value="1" selected="selected">Yes</option>
144
                            <option value="0">No</option>
145
                        </select>
146
                        <span class="required">Required</span>
147
                    </li>
148
                    <li>
149
                        <label for="fee_limit" class="required">Fee limit: </label>
150
                        <input type="text" inputmode="decimal" pattern="^\d+(\.\d{2})?$" min="0" name="fee_limit" id="fee_limit" class="required" required="required" />
151
                        <span class="required">Required</span>
152
                    </li>
127
                [% END %]
153
                [% END %]
128
            </ol>
154
            </ol>
129
        </fieldset>
155
        </fieldset>
Lines 166-171 Link Here
166
                        <th scope="col">Code</th>
192
                        <th scope="col">Code</th>
167
                        <th scope="col">Label</th>
193
                        <th scope="col">Label</th>
168
                        <th scope="col">Default</th>
194
                        <th scope="col">Default</th>
195
                        <th scope="col">Lift after payment?</th>
196
                        <th scope="col">Fee limit</th>
169
                        <th scope="col">Actions</th>
197
                        <th scope="col">Actions</th>
170
                    </tr>
198
                    </tr>
171
                </thead>
199
                </thead>
Lines 181-186 Link Here
181
                            <td>
209
                            <td>
182
                                [% IF restriction.is_default %]Yes[% END %]
210
                                [% IF restriction.is_default %]Yes[% END %]
183
                            </td>
211
                            </td>
212
                            <td>
213
                                [% IF restriction.lift_after_payment %]Yes[% END %]
214
                            </td>
215
                            <td>
216
                                [% IF restriction.fee_limit %][% restriction.fee_limit %][% END %]
217
                            </td>
184
                            <td class="actions">
218
                            <td class="actions">
185
                                <a class="btn btn-default btn-xs" href="/cgi-bin/koha/admin/restrictions.pl?op=add_form&amp;code=[% restriction.code | uri %]"><i class="fa-solid fa-pencil" aria-hidden="true"></i> Edit</a>
219
                                <a class="btn btn-default btn-xs" href="/cgi-bin/koha/admin/restrictions.pl?op=add_form&amp;code=[% restriction.code | uri %]"><i class="fa-solid fa-pencil" aria-hidden="true"></i> Edit</a>
186
                                [% IF !restriction.is_system && !restriction.is_default %]
220
                                [% IF !restriction.is_system && !restriction.is_default %]
(-)a/koha-tmpl/intranet-tmpl/prog/js/restrictiontypes.js (-1 / +2 lines)
Lines 9-15 jQuery.validator.addMethod( "restrictionDisplayText", function(value){ Link Here
9
    var ex = Object.values(existing).map(function(el) {
9
    var ex = Object.values(existing).map(function(el) {
10
        return el.toLowerCase();
10
        return el.toLowerCase();
11
    });
11
    });
12
    return (value.length > 0 && ex.indexOf(value.toLowerCase()) > -1) ?
12
    var code = $('input[name="code"]').val();
13
    return (value.length > 0 && ex.indexOf(value.toLowerCase()) > -1) && existing[code] != value ?
13
        false :
14
        false :
14
        true;
15
        true;
15
}, MSG_DUPLICATE_DISPLAY_TEXT);
16
}, MSG_DUPLICATE_DISPLAY_TEXT);
(-)a/t/db_dependent/Patron/Borrower_Debarments.t (-2 / +75 lines)
Lines 5-14 use Modern::Perl; Link Here
5
use C4::Context;
5
use C4::Context;
6
use Koha::Database;
6
use Koha::Database;
7
use Koha::Patrons;
7
use Koha::Patrons;
8
use Koha::Account;
8
9
9
use t::lib::TestBuilder;
10
use t::lib::TestBuilder;
10
11
11
use Test::More tests => 34;
12
use Test::More tests => 38;
12
13
13
use_ok('Koha::Patron::Debarments');
14
use_ok('Koha::Patron::Debarments');
14
15
Lines 221-223 is( Koha::Patrons->find($borrowernumber3)->debarred, Link Here
221
    $debarreddate2, 'Koha::Patron->merge_with() transfers well debarred' );
222
    $debarreddate2, 'Koha::Patron->merge_with() transfers well debarred' );
222
is( Koha::Patrons->find($borrowernumber3)->debarredcomment,
223
is( Koha::Patrons->find($borrowernumber3)->debarredcomment,
223
    $debarredcomment2, 'Koha::Patron->merge_with() transfers well debarredcomment' );
224
    $debarredcomment2, 'Koha::Patron->merge_with() transfers well debarredcomment' );
224
- 
225
226
# Test removing debartments after payment
227
$builder->build(
228
    {
229
        source => 'RestrictionType',
230
        value  => {
231
            code               => 'TEST',
232
            display_text       => 'This is a test.',
233
            is_system          => 0,
234
            is_default         => 0,
235
            lift_after_payment => 1,
236
            fee_limit          => 5
237
        }
238
    }
239
);
240
241
$builder->build(
242
    {
243
        source => 'RestrictionType',
244
        value  => {
245
            code               => 'TEST2',
246
            display_text       => 'This too is a test.',
247
            is_system          => 0,
248
            is_default         => 0,
249
            lift_after_payment => 1,
250
            fee_limit          => 0
251
        }
252
    }
253
);
254
255
my $borrowernumber4 = Koha::Patron->new(
256
    {
257
        firstname    => 'First',
258
        surname      => 'Sur',
259
        categorycode => $patron_category->{categorycode},
260
        branchcode   => $library->{branchcode},
261
    }
262
)->store->borrowernumber;
263
264
my $account = Koha::Account->new({ patron_id => $borrowernumber4 });
265
my $line1 = $account->add_debit({ type => 'ACCOUNT', amount => 10, interface => 'commandline' });
266
267
Koha::Patron::Debarments::AddDebarment(
268
    {
269
        borrowernumber => $borrowernumber4,
270
        expiration     => '9999-06-10',
271
        type           => 'TEST',
272
        comment        => 'Test delete'
273
    }
274
);
275
276
Koha::Patron::Debarments::AddDebarment(
277
    {
278
        borrowernumber => $borrowernumber4,
279
        expiration     => '9999-10-10',
280
        type           => 'TEST2',
281
        comment        => 'Test delete again',
282
    }
283
);
284
285
$debarments = Koha::Patron::Debarments::GetDebarments({ borrowernumber => $borrowernumber4 });
286
287
is( @$debarments, 2, "GetDebarments returns 2 debarments before payment" );
288
289
$account->pay({amount => 5});
290
291
$debarments = Koha::Patron::Debarments::GetDebarments({ borrowernumber => $borrowernumber4 });
292
is( @$debarments, 1, "GetDebarments returns 1 debarment after paying half of the fee" );
293
is( @$debarments[0]->{type}, "TEST2", "Debarment left has type value 'TEST2'" );
294
295
$account->pay({amount => 5});
296
$debarments = Koha::Patron::Debarments::GetDebarments({ borrowernumber => $borrowernumber4 });
297
is( @$debarments, 0, "GetDebarments returns 0 debarments after paying all fees" );

Return to bug 16223