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

(-)a/Koha/CirculationRules.pm (+3 lines)
Lines 79-84 our $RULE_KINDS = { Link Here
79
    cap_fine_to_replacement_price => {
79
    cap_fine_to_replacement_price => {
80
        scope => [ 'branchcode', 'categorycode', 'itemtype' ],
80
        scope => [ 'branchcode', 'categorycode', 'itemtype' ],
81
    },
81
    },
82
    expire_reserves_charge => {
83
        scope => [ 'branchcode', 'categorycode', 'itemtype' ],
84
    },
82
    chargeperiod => {
85
    chargeperiod => {
83
        scope => [ 'branchcode', 'categorycode', 'itemtype' ],
86
        scope => [ 'branchcode', 'categorycode', 'itemtype' ],
84
    },
87
    },
(-)a/Koha/Hold.pm (-1 / +19 lines)
Lines 372-378 sub cancel { Link Here
372
            C4::Reserves::_FixPriority({ biblionumber => $self->biblionumber });
372
            C4::Reserves::_FixPriority({ biblionumber => $self->biblionumber });
373
373
374
            # and, if desired, charge a cancel fee
374
            # and, if desired, charge a cancel fee
375
            my $charge = C4::Context->preference("ExpireReservesMaxPickUpDelayCharge");
375
            my $charge;
376
            if (my $item = $self->item) {
377
                my $branchcode = C4::Reserves::GetReservesControlBranch($item, $self->borrower);
378
                # C4::Reserves::GetReservesControlBranch($item->unblessed, $self->borrower->unblessed);
379
380
                my $rule = Koha::CirculationRules->get_effective_rule(
381
                    {
382
                        categorycode => $self->borrower->categorycode,
383
                        itemtype     => $item->effective_itemtype,
384
                        branchcode   => $branchcode,
385
                        rule_name    => 'expire_reserves_charge',
386
                    }
387
                );
388
                my $rule_value = $rule && $rule->rule_value // '';
389
                $charge = $rule_value ne '' ? $rule_value : C4::Context->preference("ExpireReservesMaxPickUpDelayCharge");
390
            } else {
391
                $charge = C4::Context->preference("ExpireReservesMaxPickUpDelayCharge");
392
            }
393
376
            if ( $charge && $params->{'charge_cancel_fee'} ) {
394
            if ( $charge && $params->{'charge_cancel_fee'} ) {
377
                my $account =
395
                my $account =
378
                  Koha::Account->new( { patron_id => $self->borrowernumber } );
396
                  Koha::Account->new( { patron_id => $self->borrowernumber } );
(-)a/admin/smart-rules.pl (+3 lines)
Lines 110-115 if ($op eq 'delete') { Link Here
110
                opacitemholds                    => undef,
110
                opacitemholds                    => undef,
111
                overduefinescap                  => undef,
111
                overduefinescap                  => undef,
112
                cap_fine_to_replacement_price    => undef,
112
                cap_fine_to_replacement_price    => undef,
113
                expire_reserves_charge           => undef,
113
                article_requests                 => undef,
114
                article_requests                 => undef,
114
                note                             => undef,
115
                note                             => undef,
115
            }
116
            }
Lines 287-292 elsif ($op eq 'add') { Link Here
287
    my $article_requests = $input->param('article_requests') || 'no';
288
    my $article_requests = $input->param('article_requests') || 'no';
288
    my $overduefinescap = $input->param('overduefinescap') || '';
289
    my $overduefinescap = $input->param('overduefinescap') || '';
289
    my $cap_fine_to_replacement_price = ($input->param('cap_fine_to_replacement_price') || '') eq 'on';
290
    my $cap_fine_to_replacement_price = ($input->param('cap_fine_to_replacement_price') || '') eq 'on';
291
    my $expire_reserves_charge = $input->param('expire_reserves_charge') // '';
290
    my $note = $input->param('note');
292
    my $note = $input->param('note');
291
    $debug and warn "Adding $br, $bor, $itemtype, $fine, $maxissueqty, $maxonsiteissueqty, $cap_fine_to_replacement_price";
293
    $debug and warn "Adding $br, $bor, $itemtype, $fine, $maxissueqty, $maxonsiteissueqty, $cap_fine_to_replacement_price";
292
294
Lines 319-324 elsif ($op eq 'add') { Link Here
319
        opacitemholds                 => $opacitemholds,
321
        opacitemholds                 => $opacitemholds,
320
        overduefinescap               => $overduefinescap,
322
        overduefinescap               => $overduefinescap,
321
        cap_fine_to_replacement_price => $cap_fine_to_replacement_price,
323
        cap_fine_to_replacement_price => $cap_fine_to_replacement_price,
324
        expire_reserves_charge        => $expire_reserves_charge,
322
        article_requests              => $article_requests,
325
        article_requests              => $article_requests,
323
        note                          => $note,
326
        note                          => $note,
324
    };
327
    };
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/smart-rules.tt (-2 / +14 lines)
Lines 108-113 Link Here
108
                <th>Fine grace period</th>
108
                <th>Fine grace period</th>
109
                <th>Overdue fines cap (amount)</th>
109
                <th>Overdue fines cap (amount)</th>
110
                <th>Cap fine at replacement price</th>
110
                <th>Cap fine at replacement price</th>
111
                <th>Expire reserve charge</th>
111
                <th>Suspension in days (day)</th>
112
                <th>Suspension in days (day)</th>
112
                <th>Max. suspension duration (day)</th>
113
                <th>Max. suspension duration (day)</th>
113
                <th>Suspension charging interval</th>
114
                <th>Suspension charging interval</th>
Lines 147-152 Link Here
147
                        [% SET firstremind = all_rules.$c.$i.firstremind %]
148
                        [% SET firstremind = all_rules.$c.$i.firstremind %]
148
                        [% SET overduefinescap = all_rules.$c.$i.overduefinescap %]
149
                        [% SET overduefinescap = all_rules.$c.$i.overduefinescap %]
149
                        [% SET cap_fine_to_replacement_price = all_rules.$c.$i.cap_fine_to_replacement_price %]
150
                        [% SET cap_fine_to_replacement_price = all_rules.$c.$i.cap_fine_to_replacement_price %]
151
                        [% SET expire_reserves_charge = all_rules.$c.$i.expire_reserves_charge %]
150
                        [% SET finedays = all_rules.$c.$i.finedays %]
152
                        [% SET finedays = all_rules.$c.$i.finedays %]
151
                        [% SET maxsuspensiondays = all_rules.$c.$i.maxsuspensiondays %]
153
                        [% SET maxsuspensiondays = all_rules.$c.$i.maxsuspensiondays %]
152
                        [% SET suspension_chargeperiod = all_rules.$c.$i.suspension_chargeperiod %]
154
                        [% SET suspension_chargeperiod = all_rules.$c.$i.suspension_chargeperiod %]
Lines 164-170 Link Here
164
                        [% SET article_requests = all_rules.$c.$i.article_requests %]
166
                        [% SET article_requests = all_rules.$c.$i.article_requests %]
165
                        [% SET rentaldiscount = all_rules.$c.$i.rentaldiscount %]
167
                        [% SET rentaldiscount = all_rules.$c.$i.rentaldiscount %]
166
168
167
                        [% SET show_rule = note || maxissueqty || maxonsiteissueqty || issuelength || daysmode || lengthunit || hardduedate || hardduedatecompare || fine || chargeperiod || chargeperiod_charge_at || firstremind || overduefinescap || cap_fine_to_replacement_price || finedays || maxsuspensiondays || suspension_chargeperiod || renewalsallowed || renewalperiod || norenewalbefore || auto_renew || no_auto_renewal_after || no_auto_renewal_after_hard_limit || reservesallowed || holds_per_day || holds_per_record || onshelfholds || opacitemholds || article_requests || rentaldiscount %]
169
                        [% SET show_rule = note || maxissueqty || maxonsiteissueqty || issuelength || daysmode || lengthunit || hardduedate || hardduedatecompare || fine || chargeperiod || chargeperiod_charge_at || firstremind || overduefinescap || cap_fine_to_replacement_price || expire_reserves_charge || finedays || maxsuspensiondays || suspension_chargeperiod || renewalsallowed || renewalperiod || norenewalbefore || auto_renew || no_auto_renewal_after || no_auto_renewal_after_hard_limit || reservesallowed || holds_per_day || holds_per_record || onshelfholds || opacitemholds || article_requests || rentaldiscount %]
168
                        [% IF show_rule %]
170
                        [% IF show_rule %]
169
                            [% SET row_count = row_count + 1 %]
171
                            [% SET row_count = row_count + 1 %]
170
                            <tr row_countd="row_[% row_count | html %]">
172
                            <tr row_countd="row_[% row_count | html %]">
Lines 254-259 Link Here
254
                                            <input type="checkbox" disabled="disabled" />
256
                                            <input type="checkbox" disabled="disabled" />
255
                                        [% END %]
257
                                        [% END %]
256
                                    </td>
258
                                    </td>
259
                                    <td>
260
                                        [% IF expire_reserves_charge.defined && expire_reserves_charge != '' %]
261
                                            [% expire_reserves_charge | html %]
262
                                        [% ELSE %]
263
                                            <a href="/cgi-bin/koha/admin/preferences.pl?op=search&amp;searchfield=ExpireReservesMaxPickUpDelayCharge">Use global</a>
264
                                        [% END %]
265
                                    </td>
257
                                    <td>[% finedays | html %]</td>
266
                                    <td>[% finedays | html %]</td>
258
                                    <td>[% maxsuspensiondays | html %]</td>
267
                                    <td>[% maxsuspensiondays | html %]</td>
259
                                    <td>[% suspension_chargeperiod | html %]</td>
268
                                    <td>[% suspension_chargeperiod | html %]</td>
Lines 402-407 Link Here
402
                    <td><input type="text" name="firstremind" id="firstremind" size="2" /> </td>
411
                    <td><input type="text" name="firstremind" id="firstremind" size="2" /> </td>
403
                    <td><input type="text" name="overduefinescap" id="overduefinescap" size="6" /> </td>
412
                    <td><input type="text" name="overduefinescap" id="overduefinescap" size="6" /> </td>
404
                    <td><input type="checkbox" name="cap_fine_to_replacement_price" id="cap_fine_to_replacement_price" /></td>
413
                    <td><input type="checkbox" name="cap_fine_to_replacement_price" id="cap_fine_to_replacement_price" /></td>
414
                    <td><input type="text" name="expire_reserves_charge" id="expire_reserves_charge" size="6"/></td>
405
                    <td><input type="text" name="finedays" id="fined" size="3" /> </td>
415
                    <td><input type="text" name="finedays" id="fined" size="3" /> </td>
406
                    <td><input type="text" name="maxsuspensiondays" id="maxsuspensiondays" size="3" /> </td>
416
                    <td><input type="text" name="maxsuspensiondays" id="maxsuspensiondays" size="3" /> </td>
407
                    <td><input type="text" name="suspension_chargeperiod" id="suspension_chargeperiod" size="3" /> </td>
417
                    <td><input type="text" name="suspension_chargeperiod" id="suspension_chargeperiod" size="3" /> </td>
Lines 471-476 Link Here
471
                      <th>Fine grace period</th>
481
                      <th>Fine grace period</th>
472
                      <th>Overdue fines cap (amount)</th>
482
                      <th>Overdue fines cap (amount)</th>
473
                      <th>Cap fine at replacement price</th>
483
                      <th>Cap fine at replacement price</th>
484
                      <th>Expire reserve charge</th>
474
                      <th>Suspension in days (day)</th>
485
                      <th>Suspension in days (day)</th>
475
                      <th>Max. suspension duration (day)</th>
486
                      <th>Max. suspension duration (day)</th>
476
                      <th>Suspension charging interval</th>
487
                      <th>Suspension charging interval</th>
Lines 1081-1090 Link Here
1081
                            // Remove potential previous input added
1092
                            // Remove potential previous input added
1082
                            $(current_column).find("input").remove();
1093
                            $(current_column).find("input").remove();
1083
                            $(current_column).append("<input type='hidden' name='"+name+"' value='"+val+"' />");
1094
                            $(current_column).append("<input type='hidden' name='"+name+"' value='"+val+"' />");
1084
                        } else if ( i == 5 || i == 6 || i == 25 || i == 26 || i == 27 ) {
1095
                        } else if ( i == 5 || i == 6 || i == 16 || i == 26 || i == 27 || i == 28 ) {
1085
                            // If the value is not an integer for
1096
                            // If the value is not an integer for
1086
                            //     - "Current checkouts allowed"
1097
                            //     - "Current checkouts allowed"
1087
                            //     - "Current on-site checkouts allowed"
1098
                            //     - "Current on-site checkouts allowed"
1099
                            //     - "Expire reserve charge"
1088
                            //     - "Holds allowed (total)"
1100
                            //     - "Holds allowed (total)"
1089
                            //     - "Holds allowed (daily)"
1101
                            //     - "Holds allowed (daily)"
1090
                            //     - "Holds per record (count)"
1102
                            //     - "Holds per record (count)"
(-)a/t/db_dependent/Holds/Holdfine.t (-1 / +187 lines)
Line 0 Link Here
0
- 
1
#!/usr/bin/perl
2
3
# Copyright The National Library of Finland, University of Helsinki 2020
4
# Copyright Petro Vashchuk <stalkernoid@gmail.com> 2020
5
#
6
# This file is part of Koha.
7
#
8
# Koha is free software; you can redistribute it and/or modify it under the
9
# terms of the GNU General Public License as published by the Free Software
10
# Foundation; either version 3 of the License, or (at your option) any later
11
# version.
12
#
13
# Koha is distributed in the hope that it will be useful, but WITHOUT ANY
14
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
15
# A PARTICULAR PURPOSE. See the GNU General Public License for more details.
16
#
17
# You should have received a copy of the GNU General Public License along
18
# with Koha; if not, see <http://www.gnu.org/licenses>.
19
20
use Modern::Perl;
21
22
use C4::Context;
23
use Koha::CirculationRules;
24
25
use Test::More tests => 10;
26
27
use t::lib::TestBuilder;
28
use t::lib::Mocks;
29
use Koha::Holds;
30
31
use Koha::Account;
32
use Koha::Account::DebitTypes;
33
34
BEGIN {
35
    use_ok('C4::Reserves');
36
}
37
38
my $schema = Koha::Database->schema;
39
$schema->storage->txn_begin;
40
my $dbh = C4::Context->dbh;
41
42
my $builder = t::lib::TestBuilder->new;
43
44
my $library1 = $builder->build({
45
    source => 'Branch',
46
});
47
48
my $bib_title = "Test Title";
49
50
my $borrower = $builder->build({
51
    source => 'Borrower',
52
    value => {
53
        branchcode => $library1->{branchcode},
54
    }
55
});
56
57
my $borrowernumber = $borrower->{borrowernumber};
58
my $library_A_code = $library1->{branchcode};
59
60
my $biblio = $builder->build_sample_biblio({itemtype=>'BK'});
61
my $biblionumber = $biblio->biblionumber;
62
my $item1 = $builder->build_sample_item({
63
    biblionumber => $biblionumber,
64
    itype => 'CF',
65
    homebranch => $library_A_code,
66
    holdingbranch => $library_A_code
67
});
68
my $item2 = $builder->build_sample_item({
69
    biblionumber => $biblionumber,
70
    itype => 'MU',
71
    homebranch => $library_A_code,
72
    holdingbranch => $library_A_code
73
});
74
my $item3 = $builder->build_sample_item({
75
    biblionumber => $biblionumber,
76
    itype => 'MX',
77
    homebranch => $library_A_code,
78
    holdingbranch => $library_A_code
79
});
80
81
$dbh->do("DELETE FROM circulation_rules");
82
Koha::CirculationRules->set_rules(
83
    {
84
        itemtype     => 'CF',
85
        categorycode => undef,
86
        branchcode   => undef,
87
        rules        => {
88
            expire_reserves_charge => '111'
89
        }
90
    }
91
);
92
Koha::CirculationRules->set_rules(
93
    {
94
        itemtype     => 'MU',
95
        categorycode => undef,
96
        branchcode   => undef,
97
        rules        => {
98
            expire_reserves_charge => undef
99
        }
100
    }
101
);
102
103
my $reserve_id;
104
my $account;
105
my $status;
106
my $start_balance;
107
108
# TEST: Hold Computer File item
109
$reserve_id = AddReserve(
110
    {
111
        branchcode       => $library_A_code,
112
        borrowernumber   => $borrowernumber,
113
        biblionumber     => $biblionumber,
114
        priority         => 1,
115
        itemnumber       => $item1->itemnumber,
116
    }
117
);
118
119
$account = Koha::Account->new({ patron_id => $borrowernumber });
120
121
( $status ) = CheckReserves($item1->id);
122
is( $status, 'Reserved', "Hold for the CF created" );
123
124
$start_balance = $account->balance();
125
126
Koha::Holds->find( $reserve_id )->cancel({ charge_cancel_fee => 1 });
127
128
( $status ) = CheckReserves($item1->id);
129
is( $status, '', "Hold for the CF cancelled" );
130
131
is( $account->balance() - $start_balance, 111, "Account debt is 111" );
132
133
# TEST: Hold Music item that has 'expire_reserves_charge' set undef
134
t::lib::Mocks::mock_preference('ExpireReservesMaxPickUpDelayCharge', 222);
135
136
$reserve_id = AddReserve(
137
    {
138
        branchcode       => $library_A_code,
139
        borrowernumber   => $borrowernumber,
140
        biblionumber     => $biblionumber,
141
        priority         => 1,
142
        itemnumber       => $item2->itemnumber,
143
    }
144
);
145
146
$account = Koha::Account->new({ patron_id => $borrowernumber });
147
148
( $status ) = CheckReserves($item2->id);
149
is( $status, 'Reserved', "Hold for the MU created" );
150
151
$start_balance = $account->balance();
152
153
Koha::Holds->find( $reserve_id )->cancel({ charge_cancel_fee => 1 });
154
155
( $status ) = CheckReserves($item2->id);
156
is( $status, '', "Hold for the MU cancelled" );
157
158
is( $account->balance() - $start_balance, 222, "Account debt is 222" );
159
160
# TEST: Hold MX item that has no circulation rules
161
t::lib::Mocks::mock_preference('ExpireReservesMaxPickUpDelayCharge', 333);
162
163
$reserve_id = AddReserve(
164
    {
165
        branchcode       => $library_A_code,
166
        borrowernumber   => $borrowernumber,
167
        biblionumber     => $biblionumber,
168
        priority         => 1,
169
        itemnumber       => $item3->itemnumber,
170
    }
171
);
172
173
$account = Koha::Account->new({ patron_id => $borrowernumber });
174
175
( $status ) = CheckReserves($item3->id);
176
is( $status, 'Reserved', "Hold for the MX created" );
177
178
$start_balance = $account->balance();
179
180
Koha::Holds->find( $reserve_id )->cancel({ charge_cancel_fee => 1 });
181
182
( $status ) = CheckReserves($item3->id);
183
is( $status, '', "Hold for the MX cancelled" );
184
185
is( $account->balance() - $start_balance, 333, "Account debt is 333" );
186
187
$schema->storage->txn_rollback;

Return to bug 25711