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

(-)a/Koha/Availability/Checkout.pm (+38 lines)
Line 0 Link Here
1
package Koha::Availability::Checkout;
2
3
# Copyright Koha-Suomi Oy 2016
4
#
5
# This file is part of Koha
6
#
7
# Koha is free software; you can redistribute it and/or modify it
8
# under the terms of the GNU General Public License as published by
9
# the Free Software Foundation; either version 3 of the License, or
10
# (at your option) any later version.
11
#
12
# Koha is distributed in the hope that it will be useful, but
13
# WITHOUT ANY WARRANTY; without even the implied warranty of
14
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
# GNU General Public License for more details.
16
#
17
# You should have received a copy of the GNU General Public License
18
# along with Koha; if not, see <http://www.gnu.org/licenses>.
19
20
use Modern::Perl;
21
22
use Koha::Item::Availability::Checkout;
23
24
use Koha::Exceptions;
25
26
sub new {
27
    my ($class, $params) = @_;
28
29
    bless $params, $class;
30
}
31
32
sub item {
33
    my ($self, $params) = @_;
34
35
    return Koha::Item::Availability::Checkout->new($params);
36
}
37
38
1;
(-)a/Koha/Item/Availability/Checkout.pm (+223 lines)
Line 0 Link Here
1
package Koha::Item::Availability::Checkout;
2
3
# Copyright Koha-Suomi Oy 2016
4
#
5
# This file is part of Koha
6
#
7
# Koha is free software; you can redistribute it and/or modify it
8
# under the terms of the GNU General Public License as published by
9
# the Free Software Foundation; either version 3 of the License, or
10
# (at your option) any later version.
11
#
12
# Koha is distributed in the hope that it will be useful, but
13
# WITHOUT ANY WARRANTY; without even the implied warranty of
14
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
# GNU General Public License for more details.
16
#
17
# You should have received a copy of the GNU General Public License
18
# along with Koha; if not, see <http://www.gnu.org/licenses>.
19
20
use Modern::Perl;
21
22
use base qw(Koha::Item::Availability);
23
24
use Koha::Biblioitems;
25
use Koha::Checkouts;
26
use Koha::DateUtils;
27
use Koha::Items;
28
29
use Koha::Availability::Checks::Biblio;
30
use Koha::Availability::Checks::Biblioitem;
31
use Koha::Availability::Checks::Checkout;
32
use Koha::Availability::Checks::Item;
33
use Koha::Availability::Checks::IssuingRule;
34
use Koha::Availability::Checks::Patron;
35
36
use Koha::Exceptions::Hold;
37
use Koha::Exceptions::Checkout;
38
use Koha::Exceptions::Item;
39
use Koha::Exceptions::ItemType;
40
use Koha::Exceptions::Patron;
41
42
use DateTime;
43
use Scalar::Util qw( looks_like_number );
44
45
sub new {
46
    my ($class, $params) = @_;
47
48
    my $self = $class->SUPER::new($params);
49
50
    $self->{'duedate'} ||= undef;
51
52
    return $self;
53
}
54
55
sub in_intranet {
56
    my ($self, $params) = @_;
57
    my $reason;
58
59
    $self->reset;
60
61
    my $item = $self->item;
62
    my $biblio = Koha::Biblios->find($item->biblionumber);
63
    my $patron;
64
    unless ($patron = $self->patron) {
65
        Koha::Exceptions::MissingParameter->throw(
66
            error => 'Missing parameter patron. This level of availability query '
67
            .'requires Koha::Item::Availability::Checkout to have a patron '
68
            .'parameter.'
69
        );
70
    }
71
72
    my $branchcode = C4::Circulation::_GetCircControlBranch
73
    (
74
        $item->unblessed,$patron->unblessed
75
    );
76
    my $checkoutcalc = Koha::Availability::Checks::Checkout->new;
77
    my $duedate = $self->duedate;
78
    if ($duedate &&
79
       ($reason = $checkoutcalc->invalid_due_date($item, $patron, $duedate))) {
80
        if (ref($reason) eq 'Koha::Exceptions::Checkout::DueDateBeforeNow') {
81
            $self->confirm($reason);        # due date before now
82
        } else {
83
            $self->unavailable($reason);    # invalid due date
84
        }
85
    }
86
87
    my $bibitem = Koha::Biblioitems->find($item->biblioitemnumber);
88
    my $bibitemcalc = Koha::Availability::Checks::Biblioitem->new($bibitem);
89
    if ($reason = $bibitemcalc->age_restricted($patron)) {
90
        if (C4::Context->preference('AgeRestrictionOverride')) {
91
            $self->confirm($reason);        # age restricted override
92
        } else {
93
            $self->unavailable($reason);    # age restricted
94
        }
95
    }
96
97
    my $patroncalc = Koha::Availability::Checks::Patron->new($patron);
98
    my $allowfineoverride = C4::Context->preference('AllowFineOverride');
99
    if ($reason = $patroncalc->debt_checkout) {
100
        if ($allowfineoverride) {
101
            $self->confirm($reason);        # patron fines override
102
        } else {
103
            $self->unavailable($reason);    # patron fines
104
        }
105
    }
106
    if ($reason = $patroncalc->debt_checkout_guarantees) {
107
        if ($allowfineoverride) {
108
            $self->confirm($reason);        # guarantees' fines override
109
        } else {
110
            $self->unavailable($reason);    # guarantees' fines
111
        }
112
    }
113
    $self->unavailable($reason) if $reason = $patroncalc->debarred;
114
    $self->confirm($reason) if $reason = $patroncalc->from_another_library;
115
    $self->unavailable($reason) if $reason = $patroncalc->gonenoaddress;
116
    $self->unavailable($reason) if $reason = $patroncalc->lost;
117
    $self->unavailable($reason) if $reason = $patroncalc->expired;
118
    if ($reason = $patroncalc->overdue_checkouts) {
119
        my $overduesblockcirc = C4::Context->preference("OverduesBlockCirc");
120
        if ($overduesblockcirc eq 'block') {
121
            $self->unavailable($reason);    # overdue checkouts
122
        }
123
        elsif ($overduesblockcirc eq 'confirmation'){
124
            $self->confirm($reason);        # overdue checkouts override
125
        }
126
    }
127
128
    my $checkoutrulecalc = Koha::Availability::Checks::IssuingRule->new({
129
        item => $item,
130
        patron => $patron,
131
        branchcode => $branchcode,
132
    });
133
    if ($reason = $checkoutrulecalc->zero_checkouts_allowed) {
134
        $self->confirm($reason);             # maxissueqty == 0
135
    }
136
    else {
137
        if ($reason = $checkoutrulecalc->maximum_checkouts_reached) {
138
            if (C4::Context->preference("AllowTooManyOverride")) {
139
                $self->confirm($reason);     # too many override
140
            } else {
141
                $self->unavailable($reason); # too many
142
            }
143
        }
144
    }
145
146
    my $itemcalc = Koha::Availability::Checks::Item->new($item);
147
    $self->unavailable($reason) if $reason = $itemcalc->damaged;
148
    if ($reason = $itemcalc->lost) {
149
        my $issuelostitem = C4::Context->preference("IssueLostItem");
150
        unless ($issuelostitem eq 'nothing') {
151
            if ($issuelostitem eq 'confirm') {
152
                $self->confirm($reason);     # lost item, require confirmation
153
            } elsif ($issuelostitem eq 'alert') {
154
                $self->note($reason);        # lost item, additional note
155
            }
156
        }
157
    }
158
    $self->unavailable($reason) if $reason = $itemcalc->from_another_library;
159
    $self->unavailable($reason) if $reason = $itemcalc->restricted;
160
    $self->unavailable($reason) if $reason = $itemcalc->unknown_barcode;
161
    $self->unavailable($reason) if $reason = $itemcalc->withdrawn;
162
    if ($reason = $itemcalc->notforloan) {
163
        if (C4::Context->preference("AllowNotForLoanOverride")) {
164
            $self->confirm($reason);        # notforloan override
165
        } else {
166
            $self->unavailable($reason);    # notforloan
167
        }
168
    }
169
170
    if (C4::Context->preference("RentalFeesCheckoutConfirmation")
171
        && ($reason = $itemcalc->checkout_fee)) {
172
        $self->confirm($reason);            # checkout fees
173
    }
174
175
    # is item already checked out?
176
    my $issue = Koha::Checkouts->find({ itemnumber => $item->itemnumber });
177
    if ($reason = $itemcalc->checked_out($issue)) {
178
        if ($reason->borrowernumber == $patron->borrowernumber) {
179
            if ($reason = $checkoutcalc->no_more_renewals($issue)) {
180
                if (C4::Context->preference('AllowRenewalLimitOverride')) {
181
                    $self->confirm($reason);     # no more renewals override
182
                } else {
183
                    $self->unavailable($reason); # no more renewals
184
                }
185
            } else {
186
                $self->confirm(Koha::Exceptions::Checkout::Renew->new);
187
            }
188
        } else {
189
            $self->confirm($reason);        # checked out (to someone else)
190
        }
191
    }
192
193
    unless ($params->{'ignore_holds'}) {
194
        if ($reason = $itemcalc->held) {
195
            if ($reason->borrowernumber != $patron->borrowernumber) {
196
                $self->confirm($reason);    # held (to someone else)
197
            }
198
        }
199
    }
200
    if ($reason = $itemcalc->high_hold($patron)) {
201
        if ($params->{'override_high_holds'}) {
202
            $self->note($reason);           # high holds, additional note
203
        } else {
204
            $self->confirm($reason);        # high holds, confirmation
205
        }
206
    }
207
208
    my $bibliocalc = Koha::Availability::Checks::Biblio->new($biblio);
209
    my $nomorerenewals = exists
210
       $self->unavailabilities->{'Koha::Exceptions::Checkout::NoMoreRenewals'}
211
       ? 1 : 0;
212
    my $renew = exists
213
       $self->confirmations->{'Koha::Exceptions::Checkout::Renew'}
214
       ? 1 : 0;
215
    if (!$nomorerenewals && !$renew &&
216
        ($reason = $bibliocalc->checked_out($patron))) {
217
        $self->confirm($reason);
218
    }
219
220
    return $self;
221
}
222
223
1;
(-)a/t/db_dependent/Koha/Item/Availability/Checkout.t (-1 / +349 lines)
Line 0 Link Here
0
- 
1
#!/usr/bin/perl
2
3
# Copyright Koha-Suomi Oy 2016
4
#
5
# This file is part of Koha
6
#
7
# Koha is free software; you can redistribute it and/or modify it
8
# under the terms of the GNU General Public License as published by
9
# the Free Software Foundation; either version 3 of the License, or
10
# (at your option) any later version.
11
#
12
# Koha is distributed in the hope that it will be useful, but
13
# WITHOUT ANY WARRANTY; without even the implied warranty of
14
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
# GNU General Public License for more details.
16
#
17
# You should have received a copy of the GNU General Public License
18
# along with Koha; if not, see <http://www.gnu.org/licenses>.
19
20
use Modern::Perl;
21
use Test::More tests => 10;
22
use t::lib::Mocks;
23
use t::lib::TestBuilder;
24
require t::db_dependent::Koha::Availability::Helpers;
25
26
use C4::Biblio;
27
use C4::Circulation;
28
use C4::Reserves;
29
30
use Koha::Biblioitems;
31
use Koha::Checkouts;
32
use Koha::Database;
33
use Koha::IssuingRules;
34
use Koha::Items;
35
use Koha::ItemTypes;
36
37
use Koha::Exceptions;
38
use Koha::Exceptions::Hold;
39
use Koha::Exceptions::Checkout;
40
use Koha::Exceptions::Item;
41
use Koha::Exceptions::ItemType;
42
use Koha::Exceptions::Patron;
43
44
use_ok('Koha::Item::Availability::Checkout');
45
46
my $schema = Koha::Database->new->schema;
47
$schema->storage->txn_begin;
48
49
my $dbh = C4::Context->dbh;
50
$dbh->{RaiseError} = 1;
51
52
set_default_circulation_rules();
53
set_default_system_preferences();
54
55
my $builder = t::lib::TestBuilder->new;
56
my $library = $builder->build({ source => 'Branch' });
57
58
subtest 'Checkout lost item' => sub {
59
    plan tests => 12;
60
61
    my $patron = build_a_test_patron();
62
    my $item = build_a_test_item();
63
    $item->itemlost(1)->store;
64
    t::lib::Mocks::mock_preference('IssueLostItem', 'confirm');
65
    my $availability = Koha::Item::Availability::Checkout->new({
66
        item => $item,
67
        patron => $patron
68
    })->in_intranet;
69
    ok($item->itemlost, 'When I look at the item, I cannot see it because it'
70
       .' is lost.');
71
    is(C4::Context->preference('IssueLostItem'), 'confirm', 'Lost items can be'
72
       .' issued but require confirmation.');
73
    ok($availability->available, 'When I check item checkout availability,'
74
       .' I can see it is available.');
75
    is($availability->confirm, 1, 'However, there is one thing that needs'
76
       .' a confirmation.');
77
    my $expected = 'Koha::Exceptions::Item::Lost';
78
    is(ref($availability->confirmations->{$expected}), $expected, 'Then I am'
79
       .' told that lost item status needs to be confirmed.');
80
    t::lib::Mocks::mock_preference('IssueLostItem', 'nothing');
81
    is(C4::Context->preference('IssueLostItem'), 'nothing', 'Then I changed'
82
       .' the settings. Lost items can now be issued without confirmation.');
83
    ok($availability->in_intranet->available, 'When I again check item'
84
       .' availability for checkout, it seems to be available.');
85
    ok(!$availability->confirm, 'Then availability does not need confirmation.');
86
    t::lib::Mocks::mock_preference('IssueLostItem', 'alert');
87
    is(C4::Context->preference('IssueLostItem'), 'alert', 'Then I changed'
88
       .' the settings. Lost items can now be issued, but shows an additional note.');
89
    ok($availability->in_intranet->available, 'When I again check item'
90
       .' availability for checkout, it seems to be available.');
91
    is($availability->note, 1, 'Then availability has one additional note.');
92
    is(ref($availability->notes->{$expected}), $expected, 'Then I am told that'
93
       .' in an additional note that the item is lost.');
94
    $item->itemlost(0)->store;
95
};
96
97
subtest 'Checkout held item' => sub {
98
    plan tests => 6;
99
100
    my $patron = build_a_test_patron();
101
    my $patron2 = build_a_test_patron();
102
    my $item = build_a_test_item();
103
    my $biblio = C4::Biblio::GetBiblio($item->biblionumber);
104
    my $priority= C4::Reserves::CalculatePriority($item->biblionumber);
105
    my $reserve_id = add_biblio_level_hold($item, $patron2, $item->homebranch);
106
107
    my $availability = Koha::Item::Availability::Checkout->new({
108
        item => $item,
109
        patron => $patron
110
    })->in_intranet;
111
    my $expected = 'Koha::Exceptions::Item::Held';
112
    ok($reserve_id, 'There seems to be a hold on this item.');
113
    ok($availability->available, 'When I check item availability for checkout,'
114
       .' then it is available.');
115
    is($availability->confirm, 1, 'Then there is one thing to be confirmed.');
116
    ok($availability->confirmations->{$expected}, $expected);
117
    C4::Reserves::CancelReserve({ reserve_id => $reserve_id });
118
    ok($availability->in_intranet->available, 'Given I have cancelled the hold,'
119
       .' then the item is still available.');
120
    ok(!$availability->confirm, 'Then there is no need to make confirmations.');
121
};
122
123
subtest 'Checkout a checked out item (checked out for someone else)' => sub {
124
    plan tests => 4;
125
126
    my $patron = build_a_test_patron();
127
    my $patron2 = build_a_test_patron();
128
    my $item = build_a_test_item();
129
    my $checkout = issue_item($item, $patron2);
130
131
    my $availability = Koha::Item::Availability::Checkout->new({
132
        item => $item,
133
        patron => $patron
134
    })->in_intranet;
135
    my $expected = 'Koha::Exceptions::Item::CheckedOut';
136
    ok($checkout, 'This item seems to be checked out.');
137
    ok($availability->available, 'When I check item availability for checkout,'
138
       .' then it is available.');
139
    is($availability->confirm, 1, 'Then there is one thing to be confirmed.');
140
    ok($availability->confirmations->{$expected}, $expected);
141
};
142
143
subtest 'Checkout a checked out item (checked out for me)' => sub {
144
    plan tests => 10;
145
146
    my $patron = build_a_test_patron();
147
    my $item = build_a_test_item();
148
    my $checkout = issue_item($item, $patron);
149
150
    my $availability = Koha::Item::Availability::Checkout->new({
151
        item => $item,
152
        patron => $patron
153
    })->in_intranet;
154
    my $expected = 'Koha::Exceptions::Checkout::Renew';
155
    ok($checkout, 'This item seems to be checked out.');
156
    ok($availability->available, 'When I check item availability for checkout,'
157
       .' then it is available.');
158
    is($availability->confirm, 1, 'Then there is one thing to be confirmed.');
159
    ok($availability->confirmations->{$expected}, $expected);
160
    C4::Circulation::AddRenewal($patron->borrowernumber, $item->itemnumber);
161
    my ($renewcount, $renewsallowed, $renewsleft) =
162
    C4::Circulation::GetRenewCount($patron->borrowernumber, $item->itemnumber);
163
    is($renewcount, 1, 'Given I have now renewed this item once.');
164
    is($renewsallowed, 1, 'The maximum allowed amount of renewals is 1.');
165
    is($renewsleft, 0, 'This means I have zero renews left.');
166
    $expected = 'Koha::Exceptions::Checkout::NoMoreRenewals';
167
    ok(!$availability->in_intranet->available, 'When I check item availability again'
168
       .' for checkout, then it is not available.');
169
    is($availability->unavailable, 1, 'Then there is one reason for unavailability.');
170
    ok($availability->unavailabilities->{$expected}, $expected);
171
};
172
173
subtest 'Checkout fee' => sub {
174
    plan tests => 8;
175
176
    t::lib::Mocks::mock_preference('RentalFeesCheckoutConfirmation', 1);
177
    my $patron = build_a_test_patron();
178
    my $item = build_a_test_item();
179
    my $itemtype = Koha::ItemTypes->find($item->effective_itemtype);
180
    $itemtype->rentalcharge('5')->store;
181
    my $availability = Koha::Item::Availability::Checkout->new({
182
        item => $item,
183
        patron => $patron
184
    })->in_intranet;
185
    my $expected = 'Koha::Exceptions::Checkout::Fee';
186
    is($itemtype->rentalcharge, 5, 'Item has a rental fee.');
187
    ok(C4::Context->preference('RentalFeesCheckoutConfirmation'),
188
       'Checkouts with rental fees must be confirmed.');
189
    ok($availability->available, 'When I check item availability for checkout,'
190
       .' then it is available.');
191
    is($availability->confirm, 1, 'Then there is one thing to be confirmed.');
192
    my $ret = $availability->confirmations->{$expected};
193
    is(ref($ret), $expected, "The thing to be confirmed is $expected.");
194
    is($ret->amount, '5.00', 'The exception defines a correct amount of 5 for rental charge.');
195
    t::lib::Mocks::mock_preference('RentalFeesCheckoutConfirmation', 0);
196
    ok(!C4::Context->preference('RentalFeesCheckoutConfirmation'),
197
       'Then I changed settings so that rental fees are no longer required to be confirmed.');
198
    ok(!$availability->in_intranet->confirm, 'Then there is nothing to be confirmed.');
199
};
200
201
subtest 'Overdues block' => sub {
202
    plan tests => 3;
203
204
    t::lib::Mocks::mock_preference('OverduesBlockCirc', 'block');
205
    my $patron = build_a_test_patron();
206
    my $item = build_a_test_item();
207
    my $itemtype = Koha::ItemTypes->find($item->effective_itemtype);
208
    issue_item($item, $patron);
209
    my $issue = Koha::Checkouts->find({ borrowernumber => $patron->borrowernumber });
210
    $issue->date_due('2000-01-01 23:59:00')->store;
211
    my $availability = Koha::Item::Availability::Checkout->new({
212
        item => $item,
213
        patron => $patron
214
    })->in_intranet;
215
    my $accountline = Koha::Account::Lines->find({ borrowernumber => $patron->borrowernumber });
216
    my $expected = 'Koha::Exceptions::Patron::DebarredOverdue';
217
    ok(!$availability->available, 'When I check item availability for checkout,'
218
       .' then the item is not available.');
219
    is($availability->unavailable, 1, 'There is one reason for unavailability.');
220
    is(ref($availability->unavailabilities->{$expected}), $expected,
221
       "Then the reason for unavailability is $expected.");
222
};
223
224
subtest 'Maximum checkouts reached' => sub {
225
    plan tests => 8;
226
227
    t::lib::Mocks::mock_preference('AllowTooManyOverride', 0);
228
229
    my $patron = build_a_test_patron();
230
    my $item1 = build_a_test_item();
231
    my $item2 = build_a_test_item();
232
    issue_item($item2, $patron);
233
    Koha::IssuingRules->search->delete;
234
    my $rule = Koha::IssuingRule->new({
235
        branchcode   => '*',
236
        itemtype     => '*',
237
        categorycode => '*',
238
        maxissueqty => 1,
239
    })->store;
240
    my $availability = Koha::Item::Availability::Checkout->new({
241
        item => $item1,
242
        patron => $patron
243
    })->in_intranet;
244
    my $expected = 'Koha::Exceptions::Checkout::MaximumCheckoutsReached';
245
    is(C4::Context->preference("AllowTooManyOverride"), 0,
246
       'AllowTooManyOverride system preference is disabled.');
247
    ok(!$availability->available, 'When I check item availability for checkout,'
248
       .' then the item is not available.');
249
    is($availability->unavailable, 1, 'Then there is one reason for unavailability.');
250
    is(ref($availability->unavailabilities->{$expected}), $expected,
251
        "Then the reason for unavailability is $expected.");
252
253
    t::lib::Mocks::mock_preference('AllowTooManyOverride', 1);
254
    $availability = Koha::Item::Availability::Checkout->new({
255
        item => $item1,
256
        patron => $patron
257
    })->in_intranet;
258
    is(C4::Context->preference("AllowTooManyOverride"), 1,
259
       'AllowTooManyOverride system preference is now enabled.');
260
    ok($availability->available, 'When I check item availability for checkout,'
261
       .' then the item is available.');
262
    is($availability->confirm, 1, 'Then there is one reason to be confirmed.');
263
    is(ref($availability->confirmations->{$expected}), $expected,
264
        "Then the reason for confirmation is $expected.");
265
};
266
267
subtest 'AllowNotForLoanOverride' => sub {
268
    plan tests => 9;
269
270
    t::lib::Mocks::mock_preference('AllowNotForLoanOverride', 0);
271
272
    my $patron = build_a_test_patron();
273
    my $item = build_a_test_item();
274
    $item->notforloan('1')->store;
275
276
    my $availability = Koha::Item::Availability::Checkout->new({
277
        item => $item,
278
        patron => $patron
279
    })->in_intranet;
280
    my $expected = 'Koha::Exceptions::Item::NotForLoan';
281
    is($item->notforloan, 1, 'Item is not for loan.');
282
    is(C4::Context->preference("AllowNotForLoanOverride"), 0,
283
       'AllowNotForLoanOverride system preference is disabled.');
284
    ok(!$availability->available, 'When I check item availability for checkout,'
285
       .' then the item is not available.');
286
    is($availability->unavailable, 1, 'Then there is one reason for unavailability.');
287
    is(ref($availability->unavailabilities->{$expected}), $expected,
288
        "Then the reason for unavailability is $expected.");
289
    t::lib::Mocks::mock_preference('AllowNotForLoanOverride', 1);
290
    $availability = Koha::Item::Availability::Checkout->new({
291
        item => $item,
292
        patron => $patron
293
    })->in_intranet;
294
    is(C4::Context->preference("AllowNotForLoanOverride"), 1,
295
       'AllowNotForLoanOverride system preference is now enabled.');
296
    ok($availability->available, 'When I check item availability for checkout,'
297
       .' then the item is available.');
298
    is($availability->confirm, 1, 'Then there is one reason to be confirmed.');
299
    is(ref($availability->confirmations->{$expected}), $expected,
300
        "Then the reason for confirmation is $expected.");
301
};
302
303
subtest 'High holds' => sub {
304
    plan tests => 8;
305
306
    t::lib::Mocks::mock_preference('decreaseLoanHighHolds', 1);
307
    t::lib::Mocks::mock_preference('decreaseLoanHighHoldsDuration', 3);
308
    t::lib::Mocks::mock_preference('decreaseLoanHighHoldsValue', 1);
309
    t::lib::Mocks::mock_preference('decreaseLoanHighHoldsControl', 'static');
310
311
    my $patron = build_a_test_patron();
312
    my $item = build_a_test_item();
313
    my $rule = Koha::IssuingRules->get_effective_issuing_rule;
314
    my $threedays = output_pref({
315
        dt => dt_from_string()->add_duration(
316
        DateTime::Duration->new(days => 3)),
317
        dateformat => 'iso',
318
        dateonly => 1,
319
    });
320
    $rule->issuelength('14')->store;
321
    add_biblio_level_hold($item, $patron, $patron->branchcode);
322
323
    my $availability = Koha::Item::Availability::Checkout->new({
324
        item => $item,
325
        patron => $patron
326
    })->in_intranet;
327
    my $expected = 'Koha::Exceptions::Item::HighHolds';
328
    ok($availability->available, 'When I check item availability for checkout,'
329
       .' then the item is available.');
330
    my $hh = $availability->confirmations->{$expected};
331
    is(ref($hh), $expected, "Then a reason to be confirmed is $expected.");
332
    is($hh->num_holds, 1, 'The reason tells me there is one hold.');
333
    is($hh->duration, 3, 'The reason tells me the duration.');
334
    is($hh->returndate, $threedays, 'The reason tells me the returndate is in 3 days.');
335
    ok($availability = Koha::Item::Availability::Checkout->new({
336
        item => $item,
337
        patron => $patron
338
    })->in_intranet({ override_high_holds => 1 }),
339
       'Given a parameter override_high_holds, we can get the status as'
340
       .' an additional note instead of requiring a confirmation.');
341
    ok($availability->available, 'When I check item availability for checkout,'
342
       .' then the item is available.');
343
    $hh = $availability->notes->{$expected};
344
    is(ref($hh), $expected, "Then an additional note is $expected.");
345
};
346
347
$schema->storage->txn_rollback;
348
349
1;

Return to bug 17712