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 (+221 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::Biblioitem;
30
use Koha::Availability::Checks::Checkout;
31
use Koha::Availability::Checks::Item;
32
use Koha::Availability::Checks::IssuingRule;
33
use Koha::Availability::Checks::Patron;
34
35
use Koha::Exceptions::Hold;
36
use Koha::Exceptions::Checkout;
37
use Koha::Exceptions::Item;
38
use Koha::Exceptions::ItemType;
39
use Koha::Exceptions::Patron;
40
41
use DateTime;
42
use Scalar::Util qw( looks_like_number );
43
44
sub new {
45
    my ($class, $params) = @_;
46
47
    my $self = $class->SUPER::new($params);
48
49
    $self->{'duedate'} ||= undef;
50
51
    return $self;
52
}
53
54
sub in_intranet {
55
    my ($self, $params) = @_;
56
    my $reason;
57
58
    $self->reset;
59
60
    my $item = $self->item;
61
    my $biblio = Koha::Biblios->find($item->biblionumber);
62
    my $patron;
63
    unless ($patron = $self->patron) {
64
        Koha::Exceptions::MissingParameter->throw(
65
            error => 'Missing parameter patron. This level of availability query '
66
            .'requires Koha::Item::Availability::Checkout to have a patron '
67
            .'parameter.'
68
        );
69
    }
70
71
    my $branchcode = C4::Circulation::_GetCircControlBranch
72
    (
73
        $item->unblessed,$patron->unblessed
74
    );
75
    my $checkoutcalc = Koha::Availability::Checks::Checkout->new;
76
    my $duedate = $self->duedate;
77
    if ($duedate &&
78
       ($reason = $checkoutcalc->invalid_due_date($item, $patron, $duedate))) {
79
        if (ref($reason) eq 'Koha::Exceptions::Checkout::DueDateBeforeNow') {
80
            $self->confirm($reason);        # due date before now
81
        } else {
82
            $self->unavailable($reason);    # invalid due date
83
        }
84
    }
85
86
    my $bibitem = Koha::Biblioitems->find($item->biblioitemnumber);
87
    my $bibitemcalc = Koha::Availability::Checks::Biblioitem->new($bibitem);
88
    if ($reason = $bibitemcalc->age_restricted($patron)) {
89
        if (C4::Context->preference('AgeRestrictionOverride')) {
90
            $self->confirm($reason);        # age restricted override
91
        } else {
92
            $self->unavailable($reason);    # age restricted
93
        }
94
    }
95
96
    my $patroncalc = Koha::Availability::Checks::Patron->new($patron);
97
    my $allowfineoverride = C4::Context->preference('AllowFineOverride');
98
    if ($reason = $patroncalc->debt_checkout) {
99
        if ($allowfineoverride) {
100
            $self->confirm($reason);        # patron fines override
101
        } else {
102
            $self->unavailable($reason);    # patron fines
103
        }
104
    }
105
    if ($reason = $patroncalc->debt_checkout_guarantees) {
106
        if ($allowfineoverride) {
107
            $self->confirm($reason);        # guarantees' fines override
108
        } else {
109
            $self->unavailable($reason);    # guarantees' fines
110
        }
111
    }
112
    $self->unavailable($reason) if $reason = $patroncalc->debarred;
113
    $self->confirm($reason) if $reason = $patroncalc->from_another_library;
114
    $self->unavailable($reason) if $reason = $patroncalc->gonenoaddress;
115
    $self->unavailable($reason) if $reason = $patroncalc->lost;
116
    $self->unavailable($reason) if $reason = $patroncalc->expired;
117
    if ($reason = $patroncalc->overdue_checkouts) {
118
        my $overduesblockcirc = C4::Context->preference("OverduesBlockCirc");
119
        if ($overduesblockcirc eq 'block') {
120
            $self->unavailable($reason);    # overdue checkouts
121
        }
122
        elsif ($overduesblockcirc eq 'confirmation'){
123
            $self->confirm($reason);        # overdue checkouts override
124
        }
125
    }
126
127
    my $checkoutrulecalc = Koha::Availability::Checks::IssuingRule->new({
128
        item => $item,
129
        patron => $patron,
130
        branchcode => $branchcode,
131
    });
132
    if ($reason = $checkoutrulecalc->zero_checkouts_allowed) {
133
        $self->confirm($reason);             # maxissueqty == 0
134
    }
135
    else {
136
        if ($reason = $checkoutrulecalc->maximum_checkouts_reached) {
137
            if (C4::Context->preference("AllowTooManyOverride")) {
138
                $self->confirm($reason);     # too many override
139
            } else {
140
                $self->unavailable($reason); # too many
141
            }
142
        }
143
    }
144
145
    my $itemcalc = Koha::Availability::Checks::Item->new($item);
146
    $self->unavailable($reason) if $reason = $itemcalc->damaged;
147
    if ($reason = $itemcalc->lost) {
148
        my $issuelostitem = C4::Context->preference("IssueLostItem");
149
        unless ($issuelostitem eq 'nothing') {
150
            if ($issuelostitem eq 'confirm') {
151
                $self->confirm($reason);     # lost item, require confirmation
152
            } elsif ($issuelostitem eq 'alert') {
153
                $self->note($reason);        # lost item, additional note
154
            }
155
        }
156
    }
157
    $self->unavailable($reason) if $reason = $itemcalc->from_another_library;
158
    $self->unavailable($reason) if $reason = $itemcalc->restricted;
159
    $self->unavailable($reason) if $reason = $itemcalc->unknown_barcode;
160
    $self->unavailable($reason) if $reason = $itemcalc->withdrawn;
161
    if ($reason = $itemcalc->notforloan) {
162
        if (C4::Context->preference("AllowNotForLoanOverride")) {
163
            $self->confirm($reason);        # notforloan override
164
        } else {
165
            $self->unavailable($reason);    # notforloan
166
        }
167
    }
168
169
    if (C4::Context->preference("RentalFeesCheckoutConfirmation")
170
        && ($reason = $itemcalc->checkout_fee)) {
171
        $self->confirm($reason);            # checkout fees
172
    }
173
174
    # is item already checked out?
175
    my $issue = Koha::Checkouts->find({ itemnumber => $item->itemnumber });
176
    if ($reason = $itemcalc->checked_out($issue)) {
177
        if ($reason->borrowernumber == $patron->borrowernumber) {
178
            if ($reason = $checkoutcalc->no_more_renewals($issue)) {
179
                if (C4::Context->preference('AllowRenewalLimitOverride')) {
180
                    $self->confirm($reason);     # no more renewals override
181
                } else {
182
                    $self->unavailable($reason); # no more renewals
183
                }
184
            } else {
185
                $self->confirm(Koha::Exceptions::Checkout::Renew->new);
186
            }
187
        } else {
188
            $self->confirm($reason);        # checked out (to someone else)
189
        }
190
    }
191
192
    unless ($params->{'ignore_holds'}) {
193
        if ($reason = $itemcalc->held) {
194
            if ($reason->borrowernumber != $patron->borrowernumber) {
195
                $self->confirm($reason);    # held (to someone else)
196
            }
197
        }
198
    }
199
    if ($reason = $itemcalc->high_hold($patron)) {
200
        if ($params->{'override_high_holds'}) {
201
            $self->note($reason);           # high holds, additional note
202
        } else {
203
            $self->confirm($reason);        # high holds, confirmation
204
        }
205
    }
206
207
    my $nomorerenewals = exists
208
       $self->unavailabilities->{'Koha::Exceptions::Checkout::NoMoreRenewals'}
209
       ? 1 : 0;
210
    my $renew = exists
211
       $self->confirmations->{'Koha::Exceptions::Checkout::Renew'}
212
       ? 1 : 0;
213
    if (!$nomorerenewals && !$renew &&
214
        ($reason = $checkoutcalc->biblio_already_checked_out($biblio, $patron))) {
215
        $self->confirm($reason);
216
    }
217
218
    return $self;
219
}
220
221
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