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 111-116 if ($op eq 'delete') { Link Here
111
                opacitemholds                    => undef,
111
                opacitemholds                    => undef,
112
                overduefinescap                  => undef,
112
                overduefinescap                  => undef,
113
                cap_fine_to_replacement_price    => undef,
113
                cap_fine_to_replacement_price    => undef,
114
                expire_reserves_charge           => undef,
114
                article_requests                 => undef,
115
                article_requests                 => undef,
115
                note                             => undef,
116
                note                             => undef,
116
            }
117
            }
Lines 288-293 elsif ($op eq 'add') { Link Here
288
    my $article_requests = $input->param('article_requests') || 'no';
289
    my $article_requests = $input->param('article_requests') || 'no';
289
    my $overduefinescap = $input->param('overduefinescap') || '';
290
    my $overduefinescap = $input->param('overduefinescap') || '';
290
    my $cap_fine_to_replacement_price = ($input->param('cap_fine_to_replacement_price') || '') eq 'on';
291
    my $cap_fine_to_replacement_price = ($input->param('cap_fine_to_replacement_price') || '') eq 'on';
292
    my $expire_reserves_charge = $input->param('expire_reserves_charge') // '';
291
    my $note = $input->param('note');
293
    my $note = $input->param('note');
292
    $debug and warn "Adding $br, $bor, $itemtype, $fine, $maxissueqty, $maxonsiteissueqty, $cap_fine_to_replacement_price";
294
    $debug and warn "Adding $br, $bor, $itemtype, $fine, $maxissueqty, $maxonsiteissueqty, $cap_fine_to_replacement_price";
293
295
Lines 320-325 elsif ($op eq 'add') { Link Here
320
        opacitemholds                 => $opacitemholds,
322
        opacitemholds                 => $opacitemholds,
321
        overduefinescap               => $overduefinescap,
323
        overduefinescap               => $overduefinescap,
322
        cap_fine_to_replacement_price => $cap_fine_to_replacement_price,
324
        cap_fine_to_replacement_price => $cap_fine_to_replacement_price,
325
        expire_reserves_charge        => $expire_reserves_charge,
323
        article_requests              => $article_requests,
326
        article_requests              => $article_requests,
324
        note                          => $note,
327
        note                          => $note,
325
    };
328
    };
(-)a/installer/data/mysql/updatedatabase.pl (+1 lines)
Lines 20696-20701 if( CheckVersion( $DBversion ) ) { Link Here
20696
        auto_renew
20696
        auto_renew
20697
        no_auto_renewal_after
20697
        no_auto_renewal_after
20698
        no_auto_renewal_after_hard_limit
20698
        no_auto_renewal_after_hard_limit
20699
        expire_reserves_charge
20699
        reservesallowed
20700
        reservesallowed
20700
        holds_per_record
20701
        holds_per_record
20701
        holds_per_day
20702
        holds_per_day
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/smart-rules.tt (-2 / +14 lines)
Lines 102-107 Link Here
102
                <th>Fine grace period</th>
102
                <th>Fine grace period</th>
103
                <th>Overdue fines cap (amount)</th>
103
                <th>Overdue fines cap (amount)</th>
104
                <th>Cap fine at replacement price</th>
104
                <th>Cap fine at replacement price</th>
105
                <th>Expire reserve charge</th>
105
                <th>Suspension in days (day)</th>
106
                <th>Suspension in days (day)</th>
106
                <th>Max. suspension duration (day)</th>
107
                <th>Max. suspension duration (day)</th>
107
                <th>Suspension charging interval</th>
108
                <th>Suspension charging interval</th>
Lines 141-146 Link Here
141
                        [% SET firstremind = all_rules.$c.$i.firstremind %]
142
                        [% SET firstremind = all_rules.$c.$i.firstremind %]
142
                        [% SET overduefinescap = all_rules.$c.$i.overduefinescap %]
143
                        [% SET overduefinescap = all_rules.$c.$i.overduefinescap %]
143
                        [% SET cap_fine_to_replacement_price = all_rules.$c.$i.cap_fine_to_replacement_price %]
144
                        [% SET cap_fine_to_replacement_price = all_rules.$c.$i.cap_fine_to_replacement_price %]
145
                        [% SET expire_reserves_charge = all_rules.$c.$i.expire_reserves_charge %]
144
                        [% SET finedays = all_rules.$c.$i.finedays %]
146
                        [% SET finedays = all_rules.$c.$i.finedays %]
145
                        [% SET maxsuspensiondays = all_rules.$c.$i.maxsuspensiondays %]
147
                        [% SET maxsuspensiondays = all_rules.$c.$i.maxsuspensiondays %]
146
                        [% SET suspension_chargeperiod = all_rules.$c.$i.suspension_chargeperiod %]
148
                        [% SET suspension_chargeperiod = all_rules.$c.$i.suspension_chargeperiod %]
Lines 158-164 Link Here
158
                        [% SET article_requests = all_rules.$c.$i.article_requests %]
160
                        [% SET article_requests = all_rules.$c.$i.article_requests %]
159
                        [% SET rentaldiscount = all_rules.$c.$i.rentaldiscount %]
161
                        [% SET rentaldiscount = all_rules.$c.$i.rentaldiscount %]
160
162
161
                        [% 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 %]
163
                        [% 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 %]
162
                        [% IF show_rule %]
164
                        [% IF show_rule %]
163
                            [% SET row_count = row_count + 1 %]
165
                            [% SET row_count = row_count + 1 %]
164
                            <tr row_countd="row_[% row_count | html %]">
166
                            <tr row_countd="row_[% row_count | html %]">
Lines 246-251 Link Here
246
                                            <input type="checkbox" disabled="disabled" />
248
                                            <input type="checkbox" disabled="disabled" />
247
                                        [% END %]
249
                                        [% END %]
248
                                    </td>
250
                                    </td>
251
                                    <td>
252
                                        [% IF expire_reserves_charge.defined && expire_reserves_charge != '' %]
253
                                            [% expire_reserves_charge | html %]
254
                                        [% ELSE %]
255
                                            <a href="/cgi-bin/koha/admin/preferences.pl?op=search&amp;searchfield=ExpireReservesMaxPickUpDelayCharge">Use global</a>
256
                                        [% END %]
257
                                    </td>
249
                                    <td>[% finedays | html %]</td>
258
                                    <td>[% finedays | html %]</td>
250
                                    <td>[% maxsuspensiondays | html %]</td>
259
                                    <td>[% maxsuspensiondays | html %]</td>
251
                                    <td>[% suspension_chargeperiod | html %]</td>
260
                                    <td>[% suspension_chargeperiod | html %]</td>
Lines 381-386 Link Here
381
                    <td><input type="text" name="firstremind" id="firstremind" size="2" /> </td>
390
                    <td><input type="text" name="firstremind" id="firstremind" size="2" /> </td>
382
                    <td><input type="text" name="overduefinescap" id="overduefinescap" size="6" /> </td>
391
                    <td><input type="text" name="overduefinescap" id="overduefinescap" size="6" /> </td>
383
                    <td><input type="checkbox" name="cap_fine_to_replacement_price" id="cap_fine_to_replacement_price" /></td>
392
                    <td><input type="checkbox" name="cap_fine_to_replacement_price" id="cap_fine_to_replacement_price" /></td>
393
                    <td><input type="text" name="expire_reserves_charge" id="expire_reserves_charge" size="6"/></td>
384
                    <td><input type="text" name="finedays" id="fined" size="3" /> </td>
394
                    <td><input type="text" name="finedays" id="fined" size="3" /> </td>
385
                    <td><input type="text" name="maxsuspensiondays" id="maxsuspensiondays" size="3" /> </td>
395
                    <td><input type="text" name="maxsuspensiondays" id="maxsuspensiondays" size="3" /> </td>
386
                    <td><input type="text" name="suspension_chargeperiod" id="suspension_chargeperiod" size="3" /> </td>
396
                    <td><input type="text" name="suspension_chargeperiod" id="suspension_chargeperiod" size="3" /> </td>
Lines 448-453 Link Here
448
                      <th>Fine grace period</th>
458
                      <th>Fine grace period</th>
449
                      <th>Overdue fines cap (amount)</th>
459
                      <th>Overdue fines cap (amount)</th>
450
                      <th>Cap fine at replacement price</th>
460
                      <th>Cap fine at replacement price</th>
461
                      <th>Expire reserve charge</th>
451
                      <th>Suspension in days (day)</th>
462
                      <th>Suspension in days (day)</th>
452
                      <th>Max. suspension duration (day)</th>
463
                      <th>Max. suspension duration (day)</th>
453
                      <th>Suspension charging interval</th>
464
                      <th>Suspension charging interval</th>
Lines 1045-1054 Link Here
1045
                            // Remove potential previous input added
1056
                            // Remove potential previous input added
1046
                            $(current_column).find("input").remove();
1057
                            $(current_column).find("input").remove();
1047
                            $(current_column).append("<input type='hidden' name='"+name+"' value='"+val+"' />");
1058
                            $(current_column).append("<input type='hidden' name='"+name+"' value='"+val+"' />");
1048
                        } else if ( i == 5 || i == 6 || i == 25 || i == 26 || i == 27 ) {
1059
                        } else if ( i == 5 || i == 6 || i == 16 || i == 26 || i == 27 || i == 28 ) {
1049
                            // If the value is not an integer for
1060
                            // If the value is not an integer for
1050
                            //     - "Current checkouts allowed"
1061
                            //     - "Current checkouts allowed"
1051
                            //     - "Current on-site checkouts allowed"
1062
                            //     - "Current on-site checkouts allowed"
1063
                            //     - "Expire reserve charge"
1052
                            //     - "Holds allowed (total)"
1064
                            //     - "Holds allowed (total)"
1053
                            //     - "Holds allowed (daily)"
1065
                            //     - "Holds allowed (daily)"
1054
                            //     - "Holds per record (count)"
1066
                            //     - "Holds per record (count)"
(-)a/t/db_dependent/Holds/Holdfine.t (-1 / +186 lines)
Line 0 Link Here
0
- 
1
#!/usr/bin/perl
2
3
# Copyright The National Library of Finland, University of Helsinki 2020
4
#
5
# This file is part of Koha.
6
#
7
# Koha is free software; you can redistribute it and/or modify it under the
8
# terms of the GNU General Public License as published by the Free Software
9
# Foundation; either version 3 of the License, or (at your option) any later
10
# version.
11
#
12
# Koha is distributed in the hope that it will be useful, but WITHOUT ANY
13
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
14
# A PARTICULAR PURPOSE. See the GNU General Public License for more details.
15
#
16
# You should have received a copy of the GNU General Public License along
17
# with Koha; if not, see <http://www.gnu.org/licenses>.
18
19
use Modern::Perl;
20
21
use C4::Context;
22
use Koha::CirculationRules;
23
24
use Test::More tests => 10;
25
26
use t::lib::TestBuilder;
27
use t::lib::Mocks;
28
use Koha::Holds;
29
30
use Koha::Account;
31
use Koha::Account::DebitTypes;
32
33
BEGIN {
34
    use_ok('C4::Reserves');
35
}
36
37
my $schema = Koha::Database->schema;
38
$schema->storage->txn_begin;
39
my $dbh = C4::Context->dbh;
40
41
my $builder = t::lib::TestBuilder->new;
42
43
my $library1 = $builder->build({
44
    source => 'Branch',
45
});
46
47
my $bib_title = "Test Title";
48
49
my $borrower = $builder->build({
50
    source => 'Borrower',
51
    value => {
52
        branchcode => $library1->{branchcode},
53
    }
54
});
55
56
my $borrowernumber = $borrower->{borrowernumber};
57
my $library_A_code = $library1->{branchcode};
58
59
my $biblio = $builder->build_sample_biblio({itemtype=>'BK'});
60
my $biblionumber = $biblio->biblionumber;
61
my $item1 = $builder->build_sample_item({
62
    biblionumber => $biblionumber,
63
    itype => 'CF',
64
    homebranch => $library_A_code,
65
    holdingbranch => $library_A_code
66
});
67
my $item2 = $builder->build_sample_item({
68
    biblionumber => $biblionumber,
69
    itype => 'MU',
70
    homebranch => $library_A_code,
71
    holdingbranch => $library_A_code
72
});
73
my $item3 = $builder->build_sample_item({
74
    biblionumber => $biblionumber,
75
    itype => 'MX',
76
    homebranch => $library_A_code,
77
    holdingbranch => $library_A_code
78
});
79
80
$dbh->do("DELETE FROM circulation_rules");
81
Koha::CirculationRules->set_rules(
82
    {
83
        itemtype     => 'CF',
84
        categorycode => undef,
85
        branchcode   => undef,
86
        rules        => {
87
            expire_reserves_charge => '111'
88
        }
89
    }
90
);
91
Koha::CirculationRules->set_rules(
92
    {
93
        itemtype     => 'MU',
94
        categorycode => undef,
95
        branchcode   => undef,
96
        rules        => {
97
            expire_reserves_charge => undef
98
        }
99
    }
100
);
101
102
my $reserve_id;
103
my $account;
104
my $status;
105
my $start_balance;
106
107
# TEST: Hold Computer File item
108
$reserve_id = AddReserve(
109
    {
110
        branchcode       => $library_A_code,
111
        borrowernumber   => $borrowernumber,
112
        biblionumber     => $biblionumber,
113
        priority         => 1,
114
        itemnumber       => $item1->itemnumber,
115
    }
116
);
117
118
$account = Koha::Account->new({ patron_id => $borrowernumber });
119
120
( $status ) = CheckReserves($item1->id);
121
is( $status, 'Reserved', "Hold for the CF created" );
122
123
$start_balance = $account->balance();
124
125
Koha::Holds->find( $reserve_id )->cancel({ charge_cancel_fee => 1 });
126
127
( $status ) = CheckReserves($item1->id);
128
is( $status, '', "Hold for the CF cancelled" );
129
130
is( $account->balance() - $start_balance, 111, "Account debt is 111" );
131
132
# TEST: Hold Music item that has 'expire_reserves_charge' set undef
133
t::lib::Mocks::mock_preference('ExpireReservesMaxPickUpDelayCharge', 222);
134
135
$reserve_id = AddReserve(
136
    {
137
        branchcode       => $library_A_code,
138
        borrowernumber   => $borrowernumber,
139
        biblionumber     => $biblionumber,
140
        priority         => 1,
141
        itemnumber       => $item2->itemnumber,
142
    }
143
);
144
145
$account = Koha::Account->new({ patron_id => $borrowernumber });
146
147
( $status ) = CheckReserves($item2->id);
148
is( $status, 'Reserved', "Hold for the MU created" );
149
150
$start_balance = $account->balance();
151
152
Koha::Holds->find( $reserve_id )->cancel({ charge_cancel_fee => 1 });
153
154
( $status ) = CheckReserves($item2->id);
155
is( $status, '', "Hold for the MU cancelled" );
156
157
is( $account->balance() - $start_balance, 222, "Account debt is 222" );
158
159
# TEST: Hold MX item that has no circulation rules
160
t::lib::Mocks::mock_preference('ExpireReservesMaxPickUpDelayCharge', 333);
161
162
$reserve_id = AddReserve(
163
    {
164
        branchcode       => $library_A_code,
165
        borrowernumber   => $borrowernumber,
166
        biblionumber     => $biblionumber,
167
        priority         => 1,
168
        itemnumber       => $item3->itemnumber,
169
    }
170
);
171
172
$account = Koha::Account->new({ patron_id => $borrowernumber });
173
174
( $status ) = CheckReserves($item3->id);
175
is( $status, 'Reserved', "Hold for the MX created" );
176
177
$start_balance = $account->balance();
178
179
Koha::Holds->find( $reserve_id )->cancel({ charge_cancel_fee => 1 });
180
181
( $status ) = CheckReserves($item3->id);
182
is( $status, '', "Hold for the MX cancelled" );
183
184
is( $account->balance() - $start_balance, 333, "Account debt is 333" );
185
186
$schema->storage->txn_rollback;

Return to bug 25711