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

(-)a/Koha/Item.pm (+171 lines)
Lines 23-28 use Carp; Link Here
23
23
24
use Koha::Database;
24
use Koha::Database;
25
25
26
use C4::Context;
27
use Koha::Holds;
28
use Koha::Issues;
29
use Koha::Item::Availability;
30
use Koha::ItemTypes;
26
use Koha::Patrons;
31
use Koha::Patrons;
27
use Koha::Libraries;
32
use Koha::Libraries;
28
33
Lines 38-43 Koha::Item - Koha Item object class Link Here
38
43
39
=cut
44
=cut
40
45
46
=head3 availabilities
47
48
my $available = $item->availabilities();
49
50
Gets different availability types, generally, without considering patron status.
51
52
Returns HASH containing Koha::Item::Availability objects for each availability
53
type. Currently implemented availabilities are:
54
    * hold
55
    * checkout
56
    * local_use
57
    * onsite_checkout
58
59
=cut
60
61
sub availabilities {
62
    my ( $self, $params ) = @_;
63
64
    my $availabilities; # HASH containing different types of availabilities
65
    my $availability = Koha::Item::Availability->new->set_available;
66
67
    $availability->set_unavailable("withdrawn") if $self->withdrawn;
68
    $availability->set_unavailable("itemlost") if $self->itemlost;
69
    $availability->set_unavailable("restricted") if $self->restricted;
70
71
    if ($self->damaged) {
72
        if (C4::Context->preference('AllowHoldsOnDamagedItems')) {
73
            $availability->add_description("damaged");
74
        } else {
75
            $availability->set_unavailable("damaged");
76
        }
77
    }
78
79
    my $itemtype;
80
    if (C4::Context->preference('item-level_itypes')) {
81
        $itemtype = Koha::ItemTypes->find( $self->itype );
82
    } else {
83
        my $biblioitem = Koha::Biblioitems->find( $self->biblioitemnumber );
84
        $itemtype = Koha::ItemTypes->find( $biblioitem->itemype );
85
    }
86
87
    if ($self->notforloan > 0 || $itemtype && $itemtype->notforloan) {
88
        $availability->set_unavailable("notforloan");
89
    } elsif ($self->notforloan < 0) {
90
        $availability->set_unavailable("ordered");
91
    }
92
93
    # Hold
94
    $availabilities->{'hold'} = $availability->clone;
95
96
    # Checkout
97
     if ($self->onloan) {
98
        my $issue = Koha::Issues->search({ itemnumber => $self->itemnumber })->next;
99
        $availability->set_unavailable("onloan", $issue->date_due) if $issue;
100
    }
101
102
    if (Koha::Holds->search( [
103
            { itemnumber => $self->itemnumber },
104
            { found => [ '=', 'W', 'T' ] }
105
            ])->count()) {
106
       $availability->set_unavailable("reserved");
107
    }
108
109
    $availabilities->{'checkout'} = $availability->clone;
110
111
    # Local Use, 
112
    if (grep(/^notforloan$/, @{$availability->{description}})
113
        && @{$availability->{description}} == 1) {
114
        $availabilities->{'local_use'} = $availability->clone->set_available
115
                                            ->del_description("notforloan");
116
    } else {
117
        $availabilities->{'local_use'} = $availability->clone
118
                                            ->del_description("notforloan");
119
    }
120
121
    # On-site checkout
122
    if (!C4::Context->preference('OnSiteCheckouts')) {
123
        $availabilities->{'onsite_checkout'}
124
        = Koha::Item::Availability->new
125
        ->set_unavailable("onsite_checkouts_disabled");
126
    } else {
127
        $availabilities->{'onsite_checkout'}
128
        = $availabilities->{'local_use'}->clone;
129
    }
130
131
    return $availabilities;
132
}
133
134
=head3 availability_for_checkout
135
136
my $available = $item->availability_for_checkout();
137
138
Gets checkout availability of the item. This subroutine does not check patron
139
status, instead the purpose is to check general availability for this item.
140
141
Returns Koha::Item::Availability object.
142
143
=cut
144
145
sub availability_for_checkout {
146
    my ( $self ) = @_;
147
148
    return $self->availabilities->{'checkout'};
149
}
150
151
=head3 availability_for_local_use
152
153
my $available = $item->availability_for_local_use();
154
155
Gets local use availability of the item.
156
157
Returns Koha::Item::Availability object.
158
159
=cut
160
161
sub availability_for_local_use {
162
    my ( $self ) = @_;
163
164
    return $self->availabilities->{'local_use'};
165
}
166
167
=head3 availability_for_onsite_checkout
168
169
my $available = $item->availability_for_onsite_checkout();
170
171
Gets on-site checkout availability of the item.
172
173
Returns Koha::Item::Availability object.
174
175
=cut
176
177
sub availability_for_onsite_checkout {
178
    my ( $self ) = @_;
179
180
    return $self->availabilities->{'onsite_checkout'};
181
}
182
183
=head3 availability_for_reserve
184
185
my $available = $item->availability_for_reserve();
186
187
Gets reserve availability of the item. This subroutine does not check patron
188
status, instead the purpose is to check general availability for this item.
189
190
Returns Koha::Item::Availability object.
191
192
=cut
193
194
sub availability_for_reserve {
195
    my ( $self ) = @_;
196
197
    return $self->availabilities->{'hold'};
198
}
199
41
=head3 effective_itemtype
200
=head3 effective_itemtype
42
201
43
Returns the itemtype for the item based on whether item level itemtypes are set or not.
202
Returns the itemtype for the item based on whether item level itemtypes are set or not.
Lines 50-55 sub effective_itemtype { Link Here
50
    return $self->_result()->effective_itemtype();
209
    return $self->_result()->effective_itemtype();
51
}
210
}
52
211
212
=head3 hold_queue_length
213
214
=cut
215
216
sub hold_queue_length {
217
    my ( $self ) = @_;
218
219
    my $reserves = Koha::Holds->search({ itemnumber => $self->itemnumber });
220
    return $reserves->count() if $reserves;
221
    return 0;
222
}
223
53
=head3 home_branch
224
=head3 home_branch
54
225
55
=cut
226
=cut
(-)a/Koha/Item/Availability.pm (+284 lines)
Line 0 Link Here
1
package Koha::Item::Availability;
2
3
# Copyright KohaSuomi 2016
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, write to the Free Software Foundation, Inc.,
18
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19
20
use Modern::Perl;
21
22
use Storable qw(dclone);
23
24
=head1 NAME
25
26
Koha::Item::Availability - Koha Item Availability object class
27
28
=head1 SYNOPSIS
29
30
  my $item = Koha::Items->find(1337);
31
  my $availability = $item->get_availability();
32
  # ref($availability) eq 'Koha::Item::Availability'
33
34
  print $availability->get_description() unless $availability->{available}
35
36
=head1 DESCRIPTION
37
38
This class stores item availability information aiming to having one consistent
39
item availability object instead of many different types of HASHES and Boolean
40
values.
41
42
See Koha::Item for availability subroutines.
43
44
=head2 Class Methods
45
46
=cut
47
48
=head3 new
49
50
Returns a new Koha::Item::Availability object.
51
52
=cut
53
54
sub new {
55
    my ( $class ) = @_;
56
57
    my $self = {
58
        description        => [],
59
        availability_needs_confirmation => undef,
60
        available                       => undef,
61
        expected_available              => undef,
62
    };
63
64
    bless( $self, $class );
65
}
66
67
=head3 add_description
68
69
$availability->add_description("notforloan");
70
$availability->add_description("withdrawn);
71
72
# $availability->{description} = ["notforloan", "withdrawn"]
73
74
Pushes a new description to $availability object. Does not duplicate existing
75
descriptions.
76
77
Returns updated Koha::Item::Availability object.
78
79
=cut
80
81
sub add_description {
82
    my ($self, $description) = @_;
83
84
    return $self unless $description;
85
86
    if (ref($description) eq 'ARRAY') {
87
        foreach my $desc (@$description) {
88
            if (grep(/^$desc$/, @{$self->{description}})){
89
                next;
90
            }
91
            push $self->{description}, $desc;
92
        }
93
    } else {
94
        if (!grep(/^$description$/, @{$self->{description}})){
95
            push $self->{description}, $description;
96
        }
97
    }
98
99
    return $self;
100
}
101
102
=head3 clone
103
104
$availability_cloned = $availability->clone;
105
$availability->set_unavailable;
106
107
# $availability_cloned->{available} != $availability->{available}
108
109
Clones the Koha::Item::Availability object.
110
111
Returns cloned object.
112
113
=cut
114
115
sub clone {
116
    my ( $self ) = @_;
117
118
    return dclone($self);
119
}
120
121
=head3 del_description
122
123
$availability->add_description(["notforloan", "withdrawn", "itemlost", "restricted"]);
124
$availability->del_description("withdrawn");
125
126
# $availability->{description} == ["notforloan", "itemlost", "restricted"]
127
$availability->del_description(["withdrawn", "restricted"]);
128
# $availability->{description} == ["itemlost"]
129
130
Deletes an availability description(s) if it exists.
131
132
Returns (possibly updated) Koha::Item::Availability object.
133
134
=cut
135
136
sub del_description {
137
    my ($self, $description) = @_;
138
139
    return $self unless $description;
140
141
    my @updated;
142
    if (ref($description) eq 'ARRAY') {
143
        foreach my $desc (@$description) {
144
            @updated = grep(!/^$desc$/, @{$self->{description}});
145
        }
146
    } else {
147
        @updated = grep(!/^$description$/, @{$self->{description}});
148
    }
149
    $self->{description} = \@updated;
150
151
    return $self;
152
}
153
154
=head3 hash_description
155
156
$availability->add_description(["notforloan", "withdrawn"]);
157
$availability->has_description("withdrawn"); # 1
158
$availability->has_description(["notforloan", "withdrawn"]); # 1
159
$availability->has_description("itemlost"); # 0
160
161
Finds description(s) in availability descriptions.
162
163
Returns 1 if found, 0 otherwise.
164
165
=cut
166
167
sub has_description {
168
    my ($self, $description) = @_;
169
170
    return 0 unless $description;
171
172
    my @found;
173
    if (ref($description) eq 'ARRAY') {
174
        foreach my $desc (@$description) {
175
            if (!grep(/^$desc$/, @{$self->{description}})){
176
                return 0;
177
            }
178
        }
179
    } else {
180
        if (!grep(/^$description$/, @{$self->{description}})){
181
            return 0;
182
        }
183
    }
184
185
    return 1;
186
}
187
188
=head3 reset
189
190
$availability->reset;
191
192
Resets the object.
193
194
=cut
195
196
sub reset {
197
    my ( $self ) = @_;
198
199
    $self->{available} = undef;
200
    $self->{availability_needs_confirmation} = undef;
201
    $self->{expected_available} = undef;
202
    $self->{description} = [];
203
    return $self;
204
}
205
206
=head3 set_available
207
208
$availability->set_available;
209
210
Sets the Koha::Item::Availability object status to available.
211
   $availability->{available} == 1
212
213
Overrides old availability status, but does not override other stored data in
214
the object. Create a new Koha::Item::Availability object to get a fresh start.
215
Appends any previously defined availability descriptions with add_description().
216
217
Returns updated Koha::Item::Availability object.
218
219
=cut
220
221
sub set_available {
222
    my ($self, $description) = @_;
223
224
    return $self->_update_availability_status(1, 0, $description);
225
}
226
227
=head3 set_needs_confirmation
228
229
$availability->set_needs_confirmation("unbelieveable_reason", "2016-07-07");
230
231
Sets the Koha::Item::Availability object status to unavailable,
232
but needs confirmation.
233
   $availability->{available} == 0
234
   $availability->{availability_needs_confirmation} == 1
235
236
Overrides old availability statuses, but does not override other stored data in
237
the object. Create a new Koha::Item::Availability object to get a fresh start.
238
Appends any previously defined availability descriptions with add_description().
239
Allows you to define expected availability date in C<$expected>.
240
241
Returns updated Koha::Item::Availability object.
242
243
=cut
244
245
sub set_needs_confirmation {
246
    my ($self, $description, $expected) = @_;
247
248
    return $self->_update_availability_status(0, 1, $description, $expected);
249
}
250
251
=head3 set_unavailable
252
253
$availability->set_unavailable("onloan", "2016-07-07");
254
255
Sets the Koha::Item::Availability object status to unavailable.
256
   $availability->{available} == 0
257
258
Overrides old availability status, but does not override other stored data in
259
the object. Create a new Koha::Item::Availability object to get a fresh start.
260
Appends any previously defined availability descriptions with add_description().
261
Allows you to define expected availability date in C<$expected>.
262
263
Returns updated Koha::Item::Availability object.
264
265
=cut
266
267
sub set_unavailable {
268
    my ($self, $description, $expected) = @_;
269
270
    return $self->_update_availability_status(0, 0, $description, $expected);
271
}
272
273
sub _update_availability_status {
274
    my ( $self, $available, $needs, $desc, $expected ) = @_;
275
276
    $self->{available} = $available;
277
    $self->{availability_needs_confirmation} = $needs;
278
    $self->{expected_available} = $expected;
279
    $self->add_description($desc);
280
281
    return $self;
282
}
283
284
1;
(-)a/Koha/REST/V1/Availability.pm (+99 lines)
Line 0 Link Here
1
package Koha::REST::V1::Availability;
2
3
# This file is part of Koha.
4
#
5
# Koha is free software; you can redistribute it and/or modify it under the
6
# terms of the GNU General Public License as published by the Free Software
7
# Foundation; either version 3 of the License, or (at your option) any later
8
# version.
9
#
10
# Koha is distributed in the hope that it will be useful, but WITHOUT ANY
11
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
12
# A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
13
#
14
# You should have received a copy of the GNU General Public License along
15
# with Koha; if not, write to the Free Software Foundation, Inc.,
16
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17
18
use Modern::Perl;
19
20
use Mojo::Base 'Mojolicious::Controller';
21
use Mojo::JSON;
22
23
use Koha::Holds;
24
use Koha::Items;
25
26
sub items {
27
    my ($c, $args, $cb) = @_;
28
29
    my @items;
30
    if ($args->{'itemnumber'}) {
31
        push @items, _item_availability(@{$args->{'itemnumber'}});
32
    }
33
    if ($args->{'biblionumber'}) {
34
        my $found_items = Koha::Items->search({ biblionumber => {
35
                            '=', \@{$args->{'biblionumber'}}
36
                            } })->as_list();
37
        my @itemnumbers;
38
        foreach my $item (@$found_items) {
39
            push @itemnumbers, $item->itemnumber;
40
        }
41
42
        push @items, _item_availability(@itemnumbers);
43
    }
44
45
    return $c->$cb({ error => "Item(s) not found"}, 404) unless scalar @items;
46
    return $c->$cb([ @items ], 200);
47
}
48
49
sub _item_availability {
50
    my (@itemnumbers) = @_;
51
52
    my @items;
53
54
    foreach my $itemnumber (@itemnumbers) {
55
        my $item = Koha::Items->find($itemnumber);
56
57
        unless ($item) {
58
            next;
59
        }
60
61
        my $availabilities = _swaggerize_availabilities($item->availabilities());
62
63
        my $holds;
64
        $holds->{'hold_queue_length'} = $item->hold_queue_length();
65
66
        my $iteminfo = {
67
            itemnumber => $item->itemnumber,
68
            barcode => $item->barcode,
69
            biblionumber => $item->biblionumber,
70
            biblioitemnumber => $item->biblioitemnumber,
71
            holdingbranch => $item->holdingbranch,
72
            homebranch => $item->homebranch,
73
            location => $item->location,
74
            itemcallnumber => $item->itemcallnumber,
75
        };
76
77
        # merge availability, hold information and item information
78
        push @items, { %{$availabilities}, %{$holds}, %{$iteminfo} };
79
    }
80
81
    return @items;
82
}
83
84
sub _swaggerize_availabilities {
85
    my ($availabilities) = @_;
86
87
    foreach my $availability (keys $availabilities) {
88
        delete $availabilities->{$availability}->{availability_needs_confirmation};
89
        $availabilities->{$availability}->{available} =
90
        $availabilities->{$availability}->{available}
91
                             ? Mojo::JSON->true
92
                             : Mojo::JSON->false;
93
        $availabilities->{$availability} = { %{$availabilities->{$availability}} };
94
    }
95
96
    return $availabilities;
97
}
98
99
1;
(-)a/api/v1/definitions/availabilities.json (+4 lines)
Line 0 Link Here
1
{
2
  "type": "array",
3
  "items": { "$ref": "availability.json" }
4
}
(-)a/api/v1/definitions/availability.json (+57 lines)
Line 0 Link Here
1
{
2
  "type": "object",
3
  "properties": {
4
    "barcode": {
5
      "type": ["string", "null"],
6
      "description": "item barcode"
7
    },
8
    "biblioitemnumber": {
9
      "type": "string",
10
      "description": "internally assigned biblio item identifier"
11
    },
12
    "biblionumber": {
13
      "type": "string",
14
      "description": "internally assigned biblio identifier"
15
    },
16
    "checkout": {
17
      "$ref": "availabilitystatus.json"
18
    },
19
    "expected_available": {
20
      "type": ["string", "null"],
21
      "description": "date this item is expected to be available"
22
    },
23
    "hold": {
24
      "$ref": "availabilitystatus.json"
25
    },
26
    "holdQueueLength": {
27
      "type": ["integer", "null"],
28
      "description": "number of holdings placed on title/item"
29
    },
30
    "holdingbranch": {
31
      "type": ["string", "null"],
32
      "description": "library that is currently in possession item"
33
    },
34
    "homebranch": {
35
      "type": ["string", "null"],
36
      "description": "library that owns this item"
37
    },
38
    "itemcallnumber": {
39
      "type": ["string", "null"],
40
      "description": "call number for this item"
41
    },
42
    "itemnumber": {
43
      "type": "string",
44
      "description": "internally assigned item identifier"
45
    },
46
    "local_use": {
47
      "$ref": "availabilitystatus.json"
48
    },
49
    "location": {
50
      "type": ["string", "null"],
51
      "description": "authorized value for the shelving location for this item"
52
    },
53
    "onsite_checkout": {
54
      "$ref": "availabilitystatus.json"
55
    }
56
  }
57
}
(-)a/api/v1/definitions/availabilitystatus.json (+16 lines)
Line 0 Link Here
1
{
2
  "type": "object",
3
  "properties": {
4
    "available": {
5
      "type": "boolean",
6
      "description": "availability status"
7
    },
8
    "description": {
9
      "type": "array",
10
      "items": {
11
        "type": ["string", "null"],
12
        "description": "more information on availability"
13
      }
14
    }
15
  }
16
}
(-)a/api/v1/definitions/index.json (+2 lines)
Lines 1-4 Link Here
1
{
1
{
2
    "availability": { "$ref": "availability.json" },
3
    "availabilities": { "$ref": "availabilities.json" },
2
    "patron": { "$ref": "patron.json" },
4
    "patron": { "$ref": "patron.json" },
3
    "holds": { "$ref": "holds.json" },
5
    "holds": { "$ref": "holds.json" },
4
    "hold": { "$ref": "hold.json" },
6
    "hold": { "$ref": "hold.json" },
(-)a/api/v1/swagger.json (-1 / +49 lines)
Lines 14-19 Link Here
14
  },
14
  },
15
  "basePath": "/api/v1",
15
  "basePath": "/api/v1",
16
  "paths": {
16
  "paths": {
17
    "/availability/items": {
18
      "get": {
19
        "operationId": "itemsAvailability",
20
        "tags": ["items", "availability"],
21
        "parameters": [
22
          { "$ref": "#/parameters/itemnumbersQueryParam" },
23
          { "$ref": "#/parameters/biblionumbersQueryParam" }
24
        ],
25
        "consumes": ["application/json"],
26
        "produces": ["application/json"],
27
        "responses": {
28
          "200": {
29
            "description": "Availability information on item(s)",
30
            "schema": {
31
              "$ref": "#/definitions/availabilities"
32
            }
33
          },
34
          "400": {
35
            "description": "Missing or wrong parameters",
36
            "schema": { "$ref": "#/definitions/error" }
37
          },
38
          "404": {
39
            "description": "No item(s) found",
40
            "schema": { "$ref": "#/definitions/error" }
41
          }
42
        }
43
      }
44
    },
17
    "/patrons": {
45
    "/patrons": {
18
      "get": {
46
      "get": {
19
        "operationId": "listPatrons",
47
        "operationId": "listPatrons",
Lines 360-368 Link Here
360
    }
388
    }
361
  },
389
  },
362
  "definitions": {
390
  "definitions": {
363
    "$ref": "./definitions/index.json"
391
    "$ref": "definitions/index.json"
364
  },
392
  },
365
  "parameters": {
393
  "parameters": {
394
    "biblionumbersQueryParam": {
395
      "name": "biblionumber",
396
      "in": "query",
397
      "description": "Internal biblios identifier",
398
      "type": "array",
399
      "items": {
400
        "type": "integer"
401
      },
402
      "collectionFormat": "ssv"
403
    },
366
    "borrowernumberPathParam": {
404
    "borrowernumberPathParam": {
367
      "name": "borrowernumber",
405
      "name": "borrowernumber",
368
      "in": "path",
406
      "in": "path",
Lines 383-388 Link Here
383
      "description": "Internal item identifier",
421
      "description": "Internal item identifier",
384
      "required": true,
422
      "required": true,
385
      "type": "integer"
423
      "type": "integer"
424
    },
425
    "itemnumbersQueryParam": {
426
      "name": "itemnumber",
427
      "in": "query",
428
      "description": "Internal items identifier",
429
      "type": "array",
430
      "items": {
431
        "type": "integer"
432
      },
433
      "collectionFormat": "ssv"
386
    }
434
    }
387
  }
435
  }
388
}
436
}
(-)a/t/Koha/Item/Availability.t (+71 lines)
Line 0 Link Here
1
#!/usr/bin/perl
2
3
# Copyright KohaSuomi 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 => 16;
22
23
use_ok('Koha::Item::Availability');
24
25
my $availability = Koha::Item::Availability->new->set_available;
26
27
is($availability->{available}, 1, "Available");
28
$availability->set_needs_confirmation;
29
is($availability->{availability_needs_confirmation}, 1, "Needs confirmation");
30
$availability->set_unavailable;
31
is($availability->{available}, 0, "Not available");
32
33
$availability->add_description("such available");
34
$availability->add_description("wow");
35
$availability->add_description("wow");
36
37
ok($availability->has_description("wow"), "Found description 'wow'");
38
ok($availability->has_description(["wow", "such available"]),
39
   "Found description 'wow' and 'such available'");
40
is($availability->has_description(["wow", "much not found"]), 0,
41
   "Didn't find 'wow' and 'much not found'");
42
is($availability->{description}[0], "such available",
43
   "Found correct description in correct index 1/4");
44
is($availability->{description}[1], "wow",
45
   "Found correct description in correct index 2/2");
46
47
$availability->add_description(["much description", "very doge"]);
48
is($availability->{description}[2], "much description",
49
   "Found correct description in correct index 3/4");
50
is($availability->{description}[3], "very doge",
51
   "Found correct description in correct index 4/4");
52
53
$availability->del_description("wow");
54
is($availability->{description}[1], "much description",
55
   "Found description from correct index after del");
56
$availability->del_description(["very doge", "such available"]);
57
is($availability->{description}[0], "much description",
58
   "Found description from correct index after del");
59
60
61
my $availability_clone = $availability;
62
$availability->set_unavailable;
63
is($availability_clone->{available}, $availability->{available},
64
   "Availability_clone points to availability");
65
$availability_clone = $availability->clone;
66
$availability->set_available;
67
isnt($availability_clone->{available}, $availability->{available},
68
     "Availability_clone was cloned and no longer has same availability status");
69
70
$availability->reset;
71
is($availability->{available}, undef, "Availability reset");
(-)a/t/db_dependent/Items.t (-2 / +116 lines)
Lines 20-26 use Modern::Perl; Link Here
20
20
21
use MARC::Record;
21
use MARC::Record;
22
use C4::Biblio;
22
use C4::Biblio;
23
use C4::Circulation;
24
use C4::Reserves;
23
use Koha::Database;
25
use Koha::Database;
26
use Koha::Hold;
27
use Koha::Issue;
28
use Koha::Item::Availability;
24
use Koha::Library;
29
use Koha::Library;
25
30
26
use t::lib::Mocks;
31
use t::lib::Mocks;
Lines 30-35 use Test::More tests => 10; Link Here
30
35
31
use Test::Warn;
36
use Test::Warn;
32
37
38
my @USERENV = (1,'test','MASTERTEST','Test','Test','t','Test',0,);
39
my $BRANCH_IDX = 5;
40
C4::Context->_new_userenv ('DUMMY_SESSION_ID');
41
C4::Context->set_userenv ( @USERENV );
42
33
BEGIN {
43
BEGIN {
34
    use_ok('C4::Items');
44
    use_ok('C4::Items');
35
    use_ok('Koha::Items');
45
    use_ok('Koha::Items');
Lines 432-438 subtest 'SearchItems test' => sub { Link Here
432
442
433
subtest 'Koha::Item(s) tests' => sub {
443
subtest 'Koha::Item(s) tests' => sub {
434
444
435
    plan tests => 5;
445
    plan tests => 40;
436
446
437
    $schema->storage->txn_begin();
447
    $schema->storage->txn_begin();
438
448
Lines 443-448 subtest 'Koha::Item(s) tests' => sub { Link Here
443
    my $library2 = $builder->build({
453
    my $library2 = $builder->build({
444
        source => 'Branch',
454
        source => 'Branch',
445
    });
455
    });
456
    my $borrower = $builder->build({
457
        source => 'Borrower',
458
    });
459
    my $itemtype = $builder->build({
460
        source => 'Itemtype',
461
        value => {
462
            notforloan => 1
463
        }
464
    });
446
465
447
    # Create a biblio and item for testing
466
    # Create a biblio and item for testing
448
    t::lib::Mocks::mock_preference('marcflavour', 'MARC21');
467
    t::lib::Mocks::mock_preference('marcflavour', 'MARC21');
Lines 461-466 subtest 'Koha::Item(s) tests' => sub { Link Here
461
    is( ref($holdingbranch), 'Koha::Library', "Got Koha::Library from holding_branch method" );
480
    is( ref($holdingbranch), 'Koha::Library', "Got Koha::Library from holding_branch method" );
462
    is( $holdingbranch->branchcode(), $library2->{branchcode}, "Home branch code matches holdingbranch" );
481
    is( $holdingbranch->branchcode(), $library2->{branchcode}, "Home branch code matches holdingbranch" );
463
482
483
    # Availability tests
484
    my $availability = $item->availability_for_checkout();
485
    is (ref($availability), 'Koha::Item::Availability', 'Got Koha::Item::Availability');
486
    is( $availability->{available}, 1, "Item is available" );
487
    $availability = $item->availability_for_local_use();
488
    is( $availability->{available}, 1, "Item is available for local use" );
489
    my $OnSiteCheckouts = C4::Context->preference('OnSiteCheckouts');
490
    C4::Context->set_preference('OnSiteCheckouts', 0);
491
    $availability = $item->availability_for_onsite_checkout();
492
    is( $availability->{available}, 0, "Not available for on-site checkouts" );
493
    is( $availability->{description}[0], "onsite_checkouts_disabled", "Availability description is 'onsite_checkouts_disabled'" );
494
    C4::Context->set_preference('OnSiteCheckouts', 1);
495
    $availability = $item->availability_for_onsite_checkout();
496
    is( $availability->{available}, 1, "Available for on-site checkouts" );
497
    C4::Context->set_preference('OnSiteCheckouts', $OnSiteCheckouts);
498
499
    $item->set({ onloan => "", damaged => 1 })->store();
500
    my $AllowHoldsOnDamagedItems = C4::Context->preference('AllowHoldsOnDamagedItems');
501
    C4::Context->set_preference('AllowHoldsOnDamagedItems', 0);
502
    $availability = $item->availability_for_checkout();
503
    is( $availability->{available}, 0, "Damaged item unavailable" );
504
    is( $availability->{description}[0], "damaged", "Availability description is 'damaged'" );
505
    $availability = $item->availability_for_local_use();
506
    is( $availability->{available}, 0, "Item is not available for local use" );
507
    $availability = $item->availability_for_onsite_checkout();
508
    is( $availability->{available}, 0, "Item is not available for on-site checkouts" );
509
    C4::Context->set_preference('AllowHoldsOnDamagedItems', 1);
510
    $availability = $item->availability_for_checkout();
511
    is( $availability->{available}, 1, "Damaged item available" );
512
    is( $availability->{description}[0], "damaged", "Availability description is 'damaged'" );
513
    $availability = $item->availability_for_local_use();
514
    is( $availability->{available}, 1, "Item is available for local use" );
515
    $availability = $item->availability_for_onsite_checkout();
516
    is( $availability->{available}, $OnSiteCheckouts, "Item is available for on-site checkouts" );
517
518
    $item->set({ damaged => 0, withdrawn => 1 })->store();
519
    $availability = $item->availability_for_checkout();
520
    is( $availability->{available}, 0, "Item is not available" );
521
    is( $availability->{description}[0], "withdrawn", "Availability description is 'withdrawn'" );
522
523
    $item->set({ withdrawn => 0, itemlost => 1 })->store();
524
    $availability = $item->availability_for_checkout();
525
    is( $availability->{available}, 0, "Item is not available" );
526
    is( $availability->{description}[0], "itemlost", "Availability description is 'itemlost'" );
527
528
    $item->set({ itemlost => 0, restricted => 1 })->store();
529
    $availability = $item->availability_for_checkout();
530
    is( $availability->{available}, 0, "Item is not available" );
531
    is( $availability->{description}[0], "restricted", "Availability description is 'restricted'" );
532
533
    $item->set({ restricted => 0, notforloan => 1 })->store();
534
    $availability = $item->availability_for_checkout();
535
    is( $availability->{available}, 0, "Item is not available" );
536
    is( $availability->{description}[0], "notforloan", "Availability description is 'notforloan'" );
537
    $availability = $item->availability_for_local_use();
538
    is( $availability->{available}, 1, "Item is available for local use" );
539
    $availability = $item->availability_for_onsite_checkout();
540
    is( $availability->{available}, C4::Context->preference('OnSiteCheckouts'), "Good availability for on-site checkouts" );
541
542
    $item->set({ notforloan => 0, itype => $itemtype->{itemtype} })->store();
543
    $availability = $item->availability_for_checkout();
544
    is( $availability->{available}, 0, "Item is not available" );
545
    is( $availability->{description}[0], "notforloan", "Availability description is 'notforloan' (itemtype)" );
546
    $availability = $item->availability_for_local_use();
547
    is( $availability->{available}, 1, "Item is available for local use" );
548
    $availability = $item->availability_for_onsite_checkout();
549
    is( $availability->{available}, C4::Context->preference('OnSiteCheckouts'), "Good availability for on-site checkouts" );
550
551
    $item->set({ itype => undef, barcode => "test" })->store();
552
    my $reserve = Koha::Hold->new(
553
        {
554
            biblionumber   => $item->biblionumber,
555
            itemnumber     => $item->itemnumber,
556
            waitingdate    => '2000-01-01',
557
            borrowernumber => $borrower->{borrowernumber},
558
            branchcode     => $item->homebranch,
559
            suspend        => 0,
560
        }
561
    )->store();
562
    $availability = $item->availability_for_checkout();
563
    is( $availability->{available}, 0, "Item is not available" );
564
    is( $availability->{description}[0], "reserved", "Availability description is 'reserved'" );
565
    $availability = $item->availability_for_reserve();
566
    is( $availability->{available}, 1, "Item is available for reserve" );
567
    CancelReserve({ reserve_id => $reserve->reserve_id });
568
569
    $availability = $item->availability_for_checkout();
570
    is( $availability->{available}, 1, "Item is available" );
571
572
    my $issue = AddIssue($borrower, $item->barcode, undef, 1);
573
    $item = Koha::Items->find($item->itemnumber); # refresh item
574
    $availability = $item->availability_for_checkout();
575
    is( $availability->{available}, 0, "Item is not available" );
576
    is( $availability->{description}[0], "onloan", "Availability description is 'onloan'" );
577
    is( $availability->{expected_available}, $issue->date_due, "Expected to be available '".$issue->date_due."'");
578
464
    $schema->storage->txn_rollback;
579
    $schema->storage->txn_rollback;
465
};
580
};
466
581
Lines 468-474 subtest 'C4::Biblio::EmbedItemsInMarcBiblio' => sub { Link Here
468
    plan tests => 7;
583
    plan tests => 7;
469
584
470
    $schema->storage->txn_begin();
585
    $schema->storage->txn_begin();
471
472
    my $builder = t::lib::TestBuilder->new;
586
    my $builder = t::lib::TestBuilder->new;
473
    my $library1 = $builder->build({
587
    my $library1 = $builder->build({
474
        source => 'Branch',
588
        source => 'Branch',
(-)a/t/db_dependent/api/v1/availability.t (-1 / +290 lines)
Line 0 Link Here
0
- 
1
#!/usr/bin/env perl
2
3
# Copyright KohaSuomi 2016
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, write to the Free Software Foundation, Inc.,
18
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19
20
use Modern::Perl;
21
22
use Test::More tests => 165;
23
use Test::Mojo;
24
use t::lib::TestBuilder;
25
26
use Mojo::JSON;
27
28
use C4::Auth;
29
use C4::Circulation;
30
use C4::Context;
31
32
use Koha::Database;
33
use Koha::Items;
34
use Koha::Patron;
35
36
my $builder = t::lib::TestBuilder->new();
37
38
my $dbh = C4::Context->dbh;
39
$dbh->{AutoCommit} = 0;
40
$dbh->{RaiseError} = 1;
41
42
$ENV{REMOTE_ADDR} = '127.0.0.1';
43
my $t = Test::Mojo->new('Koha::REST::V1');
44
45
my @USERENV = (1,'test','MASTERTEST','Test','Test','t','Test',0,);
46
my $BRANCH_IDX = 5;
47
C4::Context->_new_userenv ('DUMMY_SESSION_ID');
48
C4::Context->set_userenv ( @USERENV );
49
50
my $categorycode = $builder->build({ source => 'Category' })->{ categorycode };
51
my $branchcode = $builder->build({ source => 'Branch' })->{ branchcode };
52
53
my $borrower = $builder->build({ source => 'Borrower' });
54
my $biblio = $builder->build({ source => 'Biblio' });
55
my $biblio2 = $builder->build({ source => 'Biblio' });
56
my $biblionumber = $biblio->{biblionumber};
57
my $biblionumber2 = $biblio2->{biblionumber};
58
59
# $item = available, $item2 = unavailable
60
my $items;
61
$items->{available} = build_item($biblionumber);
62
$items->{notforloan} = build_item($biblionumber2, { notforloan => 1 });
63
$items->{damaged} = build_item($biblionumber2, { damaged => 1 });
64
$items->{withdrawn} = build_item($biblionumber2, { withdrawn => 1 });
65
$items->{onloan}  = build_item($biblionumber2, { onloan => undef });
66
$items->{itemlost} = build_item($biblionumber2, { itemlost => 1 });
67
$items->{reserved} = build_item($biblionumber2);
68
my $reserve = Koha::Hold->new(
69
        {
70
            biblionumber   => $items->{reserved}->{biblionumber},
71
            itemnumber     => $items->{reserved}->{itemnumber},
72
            waitingdate    => '2000-01-01',
73
            borrowernumber => $borrower->{borrowernumber},
74
            branchcode     => $items->{reserved}->{homebranch},
75
            suspend        => 0,
76
        }
77
    )->store();
78
79
my $itemnumber = $items->{available}->{itemnumber};
80
81
$t->get_ok("/api/v1/availability/items?itemnumber=-500382")
82
  ->status_is(404);
83
84
$t->get_ok("/api/v1/availability/items?itemnumber=-500382+-500383")
85
  ->status_is(404);
86
87
$t->get_ok("/api/v1/availability/items?biblionumber=-500382")
88
  ->status_is(404);
89
90
$t->get_ok("/api/v1/availability/items?biblionumber=-500382+-500383")
91
  ->status_is(404);
92
93
C4::Context->set_preference("OnSiteCheckouts", 0);
94
C4::Context->set_preference("AllowHoldsOnDamagedItems", 0);
95
# available item
96
$t->get_ok("/api/v1/availability/items?itemnumber=$itemnumber")
97
  ->status_is(200)
98
  ->json_is('/0/itemnumber', $itemnumber)
99
  ->json_is('/0/biblionumber', $biblionumber)
100
  ->json_is('/0/checkout/available', Mojo::JSON->true)
101
  ->json_is('/0/checkout/description', [])
102
  ->json_is('/0/hold/available', Mojo::JSON->true)
103
  ->json_is('/0/hold/description', [])
104
  ->json_is('/0/local_use/available', Mojo::JSON->true)
105
  ->json_is('/0/local_use/description', [])
106
  ->json_is('/0/onsite_checkout/available', Mojo::JSON->false)
107
  ->json_is('/0/onsite_checkout/description', ["onsite_checkouts_disabled"])
108
  ->json_is('/0/hold_queue_length', 0);
109
C4::Context->set_preference("OnSiteCheckouts", 1);
110
$t->get_ok("/api/v1/availability/items?biblionumber=$biblionumber")
111
  ->status_is(200)
112
  ->json_is('/0/itemnumber', $itemnumber)
113
  ->json_is('/0/biblionumber', $biblionumber)
114
  ->json_is('/0/checkout/available', Mojo::JSON->true)
115
  ->json_is('/0/checkout/description', [])
116
  ->json_is('/0/hold/available', Mojo::JSON->true)
117
  ->json_is('/0/hold/description', [])
118
  ->json_is('/0/local_use/available', Mojo::JSON->true)
119
  ->json_is('/0/local_use/description', [])
120
  ->json_is('/0/onsite_checkout/available', Mojo::JSON->true)
121
  ->json_is('/0/onsite_checkout/description', [])
122
  ->json_is('/0/hold_queue_length', 0);
123
124
# notforloan item
125
$t->get_ok("/api/v1/availability/items?itemnumber=".$items->{notforloan}->{itemnumber})
126
  ->status_is(200)
127
  ->json_is('/0/itemnumber', $items->{notforloan}->{itemnumber})
128
  ->json_is('/0/biblionumber', $biblionumber2)
129
  ->json_is('/0/checkout/available', Mojo::JSON->false)
130
  ->json_is('/0/checkout/description/0', "notforloan")
131
  ->json_is('/0/hold/available', Mojo::JSON->false)
132
  ->json_is('/0/hold/description', ["notforloan"])
133
  ->json_is('/0/local_use/available', Mojo::JSON->true)
134
  ->json_is('/0/local_use/description', [])
135
  ->json_is('/0/onsite_checkout/available', Mojo::JSON->true)
136
  ->json_is('/0/onsite_checkout/description', [])
137
  ->json_is('/0/hold_queue_length', 0);
138
C4::Context->set_preference("OnSiteCheckouts", 0);
139
$t->get_ok("/api/v1/availability/items?itemnumber=$items->{notforloan}->{itemnumber}")
140
  ->status_is(200)
141
  ->json_is('/0/itemnumber', $items->{notforloan}->{itemnumber})
142
  ->json_is('/0/biblionumber', $biblionumber2)
143
  ->json_is('/0/checkout/available', Mojo::JSON->false)
144
  ->json_is('/0/checkout/description', ["notforloan"])
145
  ->json_is('/0/hold/available', Mojo::JSON->false)
146
  ->json_is('/0/hold/description', ["notforloan"])
147
  ->json_is('/0/local_use/available', Mojo::JSON->true)
148
  ->json_is('/0/local_use/description', [])
149
  ->json_is('/0/onsite_checkout/available', Mojo::JSON->false)
150
  ->json_is('/0/onsite_checkout/description', ["onsite_checkouts_disabled"])
151
  ->json_is('/0/hold_queue_length', 0);
152
C4::Context->set_preference("OnSiteCheckouts", 1);
153
154
# damaged item
155
$t->get_ok("/api/v1/availability/items?itemnumber=".$items->{damaged}->{itemnumber})
156
  ->status_is(200)
157
  ->json_is('/0/itemnumber', $items->{damaged}->{itemnumber})
158
  ->json_is('/0/biblionumber', $biblionumber2)
159
  ->json_is('/0/checkout/available', Mojo::JSON->false)
160
  ->json_is('/0/checkout/description', ["damaged"])
161
  ->json_is('/0/hold/available', Mojo::JSON->false)
162
  ->json_is('/0/hold/description', ["damaged"])
163
  ->json_is('/0/local_use/available', Mojo::JSON->false)
164
  ->json_is('/0/local_use/description', ["damaged"])
165
  ->json_is('/0/onsite_checkout/available', Mojo::JSON->false)
166
  ->json_is('/0/onsite_checkout/description', ["damaged"])
167
  ->json_is('/0/hold_queue_length', 0);
168
C4::Context->set_preference("AllowHoldsOnDamagedItems", 1);
169
$t->get_ok("/api/v1/availability/items?itemnumber=".$items->{damaged}->{itemnumber})
170
  ->status_is(200)
171
  ->json_is('/0/itemnumber', $items->{damaged}->{itemnumber})
172
  ->json_is('/0/biblionumber', $biblionumber2)
173
  ->json_is('/0/checkout/available', Mojo::JSON->true)
174
  ->json_is('/0/checkout/description', ["damaged"])
175
  ->json_is('/0/hold/available', Mojo::JSON->true)
176
  ->json_is('/0/hold/description', ["damaged"])
177
  ->json_is('/0/local_use/available', Mojo::JSON->true)
178
  ->json_is('/0/local_use/description', ["damaged"])
179
  ->json_is('/0/onsite_checkout/available', Mojo::JSON->true)
180
  ->json_is('/0/onsite_checkout/description', ["damaged"])
181
  ->json_is('/0/hold_queue_length', 0);
182
183
# withdrawn item
184
$t->get_ok("/api/v1/availability/items?itemnumber=".$items->{withdrawn}->{itemnumber})
185
  ->status_is(200)
186
  ->json_is('/0/itemnumber', $items->{withdrawn}->{itemnumber})
187
  ->json_is('/0/biblionumber', $biblionumber2)
188
  ->json_is('/0/checkout/available', Mojo::JSON->false)
189
  ->json_is('/0/checkout/description', ["withdrawn"])
190
  ->json_is('/0/hold/available', Mojo::JSON->false)
191
  ->json_is('/0/hold/description', ["withdrawn"])
192
  ->json_is('/0/local_use/available', Mojo::JSON->false)
193
  ->json_is('/0/local_use/description', ["withdrawn"])
194
  ->json_is('/0/onsite_checkout/available', Mojo::JSON->false)
195
  ->json_is('/0/onsite_checkout/description', ["withdrawn"])
196
  ->json_is('/0/hold_queue_length', 0);
197
198
# lost item
199
$t->get_ok("/api/v1/availability/items?itemnumber=".$items->{itemlost}->{itemnumber})
200
  ->status_is(200)
201
  ->json_is('/0/itemnumber', $items->{itemlost}->{itemnumber})
202
  ->json_is('/0/biblionumber', $biblionumber2)
203
  ->json_is('/0/checkout/available', Mojo::JSON->false)
204
  ->json_is('/0/checkout/description', ["itemlost"])
205
  ->json_is('/0/hold/available', Mojo::JSON->false)
206
  ->json_is('/0/hold/description', ["itemlost"])
207
  ->json_is('/0/local_use/available', Mojo::JSON->false)
208
  ->json_is('/0/local_use/description', ["itemlost"])
209
  ->json_is('/0/onsite_checkout/available', Mojo::JSON->false)
210
  ->json_is('/0/onsite_checkout/description', ["itemlost"])
211
  ->json_is('/0/hold_queue_length', 0);
212
213
my $issue = AddIssue($borrower, $items->{onloan}->{barcode}, undef, 1);
214
215
# issued item
216
$t->get_ok("/api/v1/availability/items?itemnumber=".$items->{onloan}->{itemnumber})
217
  ->status_is(200)
218
  ->json_is('/0/itemnumber', $items->{onloan}->{itemnumber})
219
  ->json_is('/0/biblionumber', $biblionumber2)
220
  ->json_is('/0/checkout/available', Mojo::JSON->false)
221
  ->json_is('/0/checkout/description', ["onloan"])
222
  ->json_is('/0/hold/available', Mojo::JSON->true)
223
  ->json_is('/0/hold/description', [])
224
  ->json_is('/0/local_use/available', Mojo::JSON->false)
225
  ->json_is('/0/local_use/description', ["onloan"])
226
  ->json_is('/0/onsite_checkout/available', Mojo::JSON->false)
227
  ->json_is('/0/onsite_checkout/description', ["onloan"])
228
  ->json_is('/0/checkout/expected_available', $issue->date_due)
229
  ->json_is('/0/local_use/expected_available', $issue->date_due)
230
  ->json_is('/0/onsite_checkout/expected_available', $issue->date_due)
231
  ->json_is('/0/hold_queue_length', 0);
232
233
# reserved item
234
$t->get_ok("/api/v1/availability/items?itemnumber=".$items->{reserved}->{itemnumber})
235
  ->status_is(200)
236
  ->json_is('/0/itemnumber', $items->{reserved}->{itemnumber})
237
  ->json_is('/0/biblionumber', $biblionumber2)
238
  ->json_is('/0/checkout/available', Mojo::JSON->false)
239
  ->json_is('/0/checkout/description', ["reserved"])
240
  ->json_is('/0/hold/available', Mojo::JSON->true)
241
  ->json_is('/0/hold/description', [])
242
  ->json_is('/0/local_use/available', Mojo::JSON->false)
243
  ->json_is('/0/local_use/description', ["reserved"])
244
  ->json_is('/0/onsite_checkout/available', Mojo::JSON->false)
245
  ->json_is('/0/onsite_checkout/description', ["reserved"])
246
  ->json_is('/0/hold_queue_length', 1);
247
248
# multiple in one request
249
$t->get_ok("/api/v1/availability/items?itemnumber=".$items->{notforloan}->{itemnumber}."+$itemnumber+-500382")
250
  ->status_is(200)
251
  ->json_is('/0/itemnumber', $items->{notforloan}->{itemnumber})
252
  ->json_is('/0/biblionumber', $biblionumber2)
253
  ->json_is('/0/checkout/available', Mojo::JSON->false)
254
  ->json_is('/0/checkout/description/0', "notforloan")
255
  ->json_is('/0/hold/available', Mojo::JSON->false)
256
  ->json_is('/0/hold/description', ["notforloan"])
257
  ->json_is('/0/local_use/available', Mojo::JSON->true)
258
  ->json_is('/0/local_use/description', [])
259
  ->json_is('/0/onsite_checkout/available', Mojo::JSON->true)
260
  ->json_is('/0/onsite_checkout/description', [])
261
  ->json_is('/0/hold_queue_length', 0)
262
  ->json_is('/1/itemnumber', $itemnumber)
263
  ->json_is('/1/biblionumber', $biblionumber)
264
  ->json_is('/1/checkout/available', Mojo::JSON->true)
265
  ->json_is('/1/checkout/description', [])
266
  ->json_is('/1/hold/available', Mojo::JSON->true)
267
  ->json_is('/1/hold/description', [])
268
  ->json_is('/1/local_use/available', Mojo::JSON->true)
269
  ->json_is('/1/local_use/description', [])
270
  ->json_is('/1/onsite_checkout/available', Mojo::JSON->true)
271
  ->json_is('/1/onsite_checkout/description', [])
272
  ->json_is('/1/hold_queue_length', 0);
273
274
sub build_item {
275
    my ($biblionumber, $field) = @_;
276
277
    return $builder->build({
278
        source => 'Item',
279
        value => {
280
            biblionumber => $biblionumber,
281
            notforloan => $field->{notforloan} || 0,
282
            damaged => $field->{damaged} || 0,
283
            withdrawn => $field->{withdrawn} || 0,
284
            itemlost => $field->{itemlost} || 0,
285
            restricted => $field->{restricted} || undef,
286
            onloan => $field->{onloan} || undef,
287
            itype => $field->{itype} || undef,
288
        }
289
    });
290
}

Return to bug 16826