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

(-)a/Koha/Item.pm (+167 lines)
Lines 25-31 use Koha::Database; Link Here
25
25
26
use C4::Context;
26
use C4::Context;
27
use C4::Circulation qw(GetIssuingRule);
27
use C4::Circulation qw(GetIssuingRule);
28
use Koha::Holds;
29
use Koha::Issues;
30
use Koha::Item::Availability;
28
use Koha::Item::Transfer;
31
use Koha::Item::Transfer;
32
use Koha::ItemTypes;
29
use Koha::Patrons;
33
use Koha::Patrons;
30
use Koha::Libraries;
34
use Koha::Libraries;
31
35
Lines 41-46 Koha::Item - Koha Item object class Link Here
41
45
42
=cut
46
=cut
43
47
48
=head3 availabilities
49
50
my $available = $item->availabilities();
51
52
Gets different availability types, generally, without considering patron status.
53
54
Returns hash-ref containing Koha::Item::Availability objects for each availability
55
type. Currently implemented availabilities are:
56
    * hold
57
    * checkout
58
    * local_use
59
    * onsite_checkout
60
61
=cut
62
63
sub availabilities {
64
    my ( $self, $params ) = @_;
65
66
    my $availabilities; # contains different types of availabilities
67
    my $availability = Koha::Item::Availability->new->set_available;
68
69
    $availability->set_unavailable("withdrawn") if $self->withdrawn;
70
    $availability->set_unavailable("itemlost") if $self->itemlost;
71
    $availability->set_unavailable("restricted") if $self->restricted;
72
73
    if ($self->damaged) {
74
        if (C4::Context->preference('AllowHoldsOnDamagedItems')) {
75
            $availability->add_description("damaged");
76
        } else {
77
            $availability->set_unavailable("damaged");
78
        }
79
    }
80
81
    my $itemtype;
82
    if (C4::Context->preference('item-level_itypes')) {
83
        $itemtype = Koha::ItemTypes->find( $self->itype );
84
    } else {
85
        my $biblioitem = Koha::Biblioitems->find( $self->biblioitemnumber );
86
        $itemtype = Koha::ItemTypes->find( $biblioitem->itemtype );
87
    }
88
89
    if ($self->notforloan > 0 || $itemtype && $itemtype->notforloan) {
90
        $availability->set_unavailable("notforloan");
91
    } elsif ($self->notforloan < 0) {
92
        $availability->set_unavailable("ordered");
93
    }
94
95
    # Hold
96
    $availabilities->{'hold'} = $availability->clone;
97
98
    # Checkout
99
    if ($self->onloan) {
100
        my $issue = Koha::Issues->search({ itemnumber => $self->itemnumber })->next;
101
        $availability->set_unavailable("onloan", $issue->date_due) if $issue;
102
    }
103
104
    if (C4::Reserves::CheckReserves($self->itemnumber)) {
105
        $availability->set_unavailable("reserved");
106
    }
107
108
    $availabilities->{'checkout'} = $availability->clone;
109
110
    # Local Use,
111
    if (grep(/^notforloan$/, @{$availability->{description}})
112
        && @{$availability->{description}} == 1) {
113
        $availabilities->{'local_use'} = $availability->clone->set_available
114
                                            ->del_description("notforloan");
115
    } else {
116
        $availabilities->{'local_use'} = $availability->clone
117
                                            ->del_description("notforloan");
118
    }
119
120
    # On-site checkout
121
    if (!C4::Context->preference('OnSiteCheckouts')) {
122
        $availabilities->{'onsite_checkout'}
123
        = Koha::Item::Availability->new
124
        ->set_unavailable("onsite_checkouts_disabled");
125
    } else {
126
        $availabilities->{'onsite_checkout'}
127
        = $availabilities->{'local_use'}->clone;
128
    }
129
130
    return $availabilities;
131
}
132
133
=head3 availability_for_checkout
134
135
my $available = $item->availability_for_checkout();
136
137
Gets checkout availability of the item. This subroutine does not check patron
138
status, instead the purpose is to check general availability for this item.
139
140
Returns Koha::Item::Availability object.
141
142
=cut
143
144
sub availability_for_checkout {
145
    my ( $self ) = @_;
146
147
    return $self->availabilities->{'checkout'};
148
}
149
150
=head3 availability_for_local_use
151
152
my $available = $item->availability_for_local_use();
153
154
Gets local use availability of the item.
155
156
Returns Koha::Item::Availability object.
157
158
=cut
159
160
sub availability_for_local_use {
161
    my ( $self ) = @_;
162
163
    return $self->availabilities->{'local_use'};
164
}
165
166
=head3 availability_for_onsite_checkout
167
168
my $available = $item->availability_for_onsite_checkout();
169
170
Gets on-site checkout availability of the item.
171
172
Returns Koha::Item::Availability object.
173
174
=cut
175
176
sub availability_for_onsite_checkout {
177
    my ( $self ) = @_;
178
179
    return $self->availabilities->{'onsite_checkout'};
180
}
181
182
=head3 availability_for_reserve
183
184
my $available = $item->availability_for_reserve();
185
186
Gets reserve availability of the item. This subroutine does not check patron
187
status, instead the purpose is to check general availability for this item.
188
189
Returns Koha::Item::Availability object.
190
191
=cut
192
193
sub availability_for_reserve {
194
    my ( $self ) = @_;
195
196
    return $self->availabilities->{'hold'};
197
}
198
44
=head3 effective_itemtype
199
=head3 effective_itemtype
45
200
46
Returns the itemtype for the item based on whether item level itemtypes are set or not.
201
Returns the itemtype for the item based on whether item level itemtypes are set or not.
Lines 53-58 sub effective_itemtype { Link Here
53
    return $self->_result()->effective_itemtype();
208
    return $self->_result()->effective_itemtype();
54
}
209
}
55
210
211
=head3 hold_queue_length
212
213
=cut
214
215
sub hold_queue_length {
216
    my ( $self ) = @_;
217
218
    my $reserves = Koha::Holds->search({ itemnumber => $self->itemnumber });
219
    return $reserves->count() if $reserves;
220
    return 0;
221
}
222
56
=head3 home_branch
223
=head3 home_branch
57
224
58
=cut
225
=cut
(-)a/Koha/Item/Availability.pm (+283 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 $availabilities = $item->availabilities();
32
  # ref($availabilities) eq 'HASH'
33
  # ref($availabilities->{'checkout'}) eq 'Koha::Item::Availability'
34
35
  print "Available for checkout!" if $availabilities->{'checkout'}->{available};
36
37
=head1 DESCRIPTION
38
39
This class holds item availability information.
40
41
See Koha::Item for availability subroutines.
42
43
=head2 Class Methods
44
45
=cut
46
47
=head3 new
48
49
Returns a new Koha::Item::Availability object.
50
51
=cut
52
53
sub new {
54
    my ( $class ) = @_;
55
56
    my $self = {
57
        description        => [],
58
        availability_needs_confirmation => undef,
59
        available                       => undef,
60
        expected_available              => undef,
61
    };
62
63
    bless( $self, $class );
64
}
65
66
=head3 add_description
67
68
$availability->add_description("notforloan");
69
$availability->add_description("withdrawn);
70
71
# $availability->{description} = ["notforloan", "withdrawn"]
72
73
Pushes a new description to $availability object. Does not duplicate existing
74
descriptions.
75
76
Returns updated Koha::Item::Availability object.
77
78
=cut
79
80
sub add_description {
81
    my ($self, $description) = @_;
82
83
    return $self unless $description;
84
85
    if (ref($description) eq 'ARRAY') {
86
        foreach my $desc (@$description) {
87
            if (grep(/^$desc$/, @{$self->{description}})){
88
                next;
89
            }
90
            push $self->{description}, $desc;
91
        }
92
    } else {
93
        if (!grep(/^$description$/, @{$self->{description}})){
94
            push $self->{description}, $description;
95
        }
96
    }
97
98
    return $self;
99
}
100
101
=head3 clone
102
103
$availability_cloned = $availability->clone;
104
$availability->set_unavailable;
105
106
# $availability_cloned->{available} != $availability->{available}
107
108
Clones the Koha::Item::Availability object.
109
110
Returns cloned object.
111
112
=cut
113
114
sub clone {
115
    my ( $self ) = @_;
116
117
    return dclone($self);
118
}
119
120
=head3 del_description
121
122
$availability->add_description(["notforloan", "withdrawn", "itemlost", "restricted"]);
123
$availability->del_description("withdrawn");
124
125
# $availability->{description} == ["notforloan", "itemlost", "restricted"]
126
$availability->del_description(["withdrawn", "restricted"]);
127
# $availability->{description} == ["itemlost"]
128
129
Deletes an availability description(s) if it exists.
130
131
Returns (possibly updated) Koha::Item::Availability object.
132
133
=cut
134
135
sub del_description {
136
    my ($self, $description) = @_;
137
138
    return $self unless $description;
139
140
    my @updated;
141
    if (ref($description) eq 'ARRAY') {
142
        foreach my $desc (@$description) {
143
            @updated = grep(!/^$desc$/, @{$self->{description}});
144
        }
145
    } else {
146
        @updated = grep(!/^$description$/, @{$self->{description}});
147
    }
148
    $self->{description} = \@updated;
149
150
    return $self;
151
}
152
153
=head3 has_description
154
155
$availability->add_description(["notforloan", "withdrawn"]);
156
$availability->has_description("withdrawn"); # 1
157
$availability->has_description(["notforloan", "withdrawn"]); # 1
158
$availability->has_description("itemlost"); # 0
159
160
Finds description(s) in availability descriptions.
161
162
Returns 1 if found, 0 otherwise.
163
164
=cut
165
166
sub has_description {
167
    my ($self, $description) = @_;
168
169
    return 0 unless $description;
170
171
    my @found;
172
    if (ref($description) eq 'ARRAY') {
173
        foreach my $desc (@$description) {
174
            if (!grep(/^$desc$/, @{$self->{description}})){
175
                return 0;
176
            }
177
        }
178
    } else {
179
        if (!grep(/^$description$/, @{$self->{description}})){
180
            return 0;
181
        }
182
    }
183
184
    return 1;
185
}
186
187
=head3 reset
188
189
$availability->reset;
190
191
Resets the object.
192
193
=cut
194
195
sub reset {
196
    my ( $self ) = @_;
197
198
    $self->{available} = undef;
199
    $self->{availability_needs_confirmation} = undef;
200
    $self->{expected_available} = undef;
201
    $self->{description} = [];
202
    return $self;
203
}
204
205
=head3 set_available
206
207
$availability->set_available;
208
209
Sets the Koha::Item::Availability object status to available.
210
   $availability->{available} == 1
211
212
Overrides old availability status, but does not override other stored data in
213
the object. Create a new Koha::Item::Availability object to get a fresh start.
214
Appends any previously defined availability descriptions with add_description().
215
216
Returns updated Koha::Item::Availability object.
217
218
=cut
219
220
sub set_available {
221
    my ($self, $description) = @_;
222
223
    return $self->_update_availability_status(1, 0, $description);
224
}
225
226
=head3 set_needs_confirmation
227
228
$availability->set_needs_confirmation("unbelieveable_reason", "2016-07-07");
229
230
Sets the Koha::Item::Availability object status to unavailable,
231
but needs confirmation.
232
   $availability->{available} == 0
233
   $availability->{availability_needs_confirmation} == 1
234
235
Overrides old availability statuses, but does not override other stored data in
236
the object. Create a new Koha::Item::Availability object to get a fresh start.
237
Appends any previously defined availability descriptions with add_description().
238
Allows you to define expected availability date in C<$expected>.
239
240
Returns updated Koha::Item::Availability object.
241
242
=cut
243
244
sub set_needs_confirmation {
245
    my ($self, $description, $expected) = @_;
246
247
    return $self->_update_availability_status(0, 1, $description, $expected);
248
}
249
250
=head3 set_unavailable
251
252
$availability->set_unavailable("onloan", "2016-07-07");
253
254
Sets the Koha::Item::Availability object status to unavailable.
255
   $availability->{available} == 0
256
257
Overrides old availability status, but does not override other stored data in
258
the object. Create a new Koha::Item::Availability object to get a fresh start.
259
Appends any previously defined availability descriptions with add_description().
260
Allows you to define expected availability date in C<$expected>.
261
262
Returns updated Koha::Item::Availability object.
263
264
=cut
265
266
sub set_unavailable {
267
    my ($self, $description, $expected) = @_;
268
269
    return $self->_update_availability_status(0, 0, $description, $expected);
270
}
271
272
sub _update_availability_status {
273
    my ( $self, $available, $needs, $desc, $expected ) = @_;
274
275
    $self->{available} = $available;
276
    $self->{availability_needs_confirmation} = $needs;
277
    $self->{expected_available} = $expected if $expected;
278
    $self->add_description($desc);
279
280
    return $self;
281
}
282
283
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/swagger/definitions.json (+6 lines)
Lines 1-4 Link Here
1
{
1
{
2
  "availability": {
3
    "$ref": "definitions/availability.json"
4
  },
5
  "availabilities": {
6
    "$ref": "definitions/availabilities.json"
7
  },
2
  "city": {
8
  "city": {
3
    "$ref": "definitions/city.json"
9
    "$ref": "definitions/city.json"
4
  },
10
  },
(-)a/api/v1/swagger/definitions/availabilities.json (+4 lines)
Line 0 Link Here
1
{
2
  "type": "array",
3
  "items": { "$ref": "availability.json" }
4
}
(-)a/api/v1/swagger/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/swagger/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/swagger/parameters.json (+6 lines)
Lines 1-4 Link Here
1
{
1
{
2
  "biblionumbersQueryParam": {
3
    "$ref": "parameters/biblio.json#/biblionumbersQueryParam"
4
  },
2
  "borrowernumberPathParam": {
5
  "borrowernumberPathParam": {
3
    "$ref": "parameters/patron.json#/borrowernumberPathParam"
6
    "$ref": "parameters/patron.json#/borrowernumberPathParam"
4
  },
7
  },
Lines 13-17 Link Here
13
  },
16
  },
14
  "itemnumberPathParam": {
17
  "itemnumberPathParam": {
15
    "$ref": "parameters/item.json#/itemnumberPathParam"
18
    "$ref": "parameters/item.json#/itemnumberPathParam"
19
  },
20
  "itemnumbersQueryParam": {
21
    "$ref": "parameters/item.json#/itemnumbersQueryParam"
16
  }
22
  }
17
}
23
}
(-)a/api/v1/swagger/parameters/biblio.json (+12 lines)
Line 0 Link Here
1
{
2
  "biblionumbersQueryParam": {
3
    "name": "biblionumber",
4
    "in": "query",
5
    "description": "Internal biblios identifier",
6
    "type": "array",
7
    "items": {
8
      "type": "integer"
9
    },
10
    "collectionFormat": "ssv"
11
  }
12
}
(-)a/api/v1/swagger/parameters/item.json (+10 lines)
Lines 5-9 Link Here
5
    "description": "Internal item identifier",
5
    "description": "Internal item identifier",
6
    "required": true,
6
    "required": true,
7
    "type": "integer"
7
    "type": "integer"
8
  },
9
  "itemnumbersQueryParam": {
10
    "name": "itemnumber",
11
    "in": "query",
12
    "description": "Internal items identifier",
13
    "type": "array",
14
    "items": {
15
      "type": "integer"
16
    },
17
    "collectionFormat": "ssv"
8
  }
18
  }
9
}
19
}
(-)a/api/v1/swagger/paths.json (+3 lines)
Lines 1-4 Link Here
1
{
1
{
2
  "/availability/items": {
3
    "$ref": "paths/availability.json#/~1availability~1items"
4
  },
2
  "/cities": {
5
  "/cities": {
3
    "$ref": "paths/cities.json#/~1cities"
6
    "$ref": "paths/cities.json#/~1cities"
4
  },
7
  },
(-)a/api/v1/swagger/paths/availability.json (+36 lines)
Line 0 Link Here
1
{
2
  "/availability/items": {
3
    "get": {
4
      "operationId": "itemsAvailability",
5
      "tags": ["items", "availability"],
6
      "parameters": [{
7
          "$ref": "../parameters.json#/itemnumbersQueryParam"
8
        }, {
9
          "$ref": "../parameters.json#/biblionumbersQueryParam"
10
        }
11
      ],
12
      "consumes": ["application/json"],
13
      "produces": ["application/json"],
14
      "responses": {
15
        "200": {
16
          "description": "Availability information on item(s)",
17
          "schema": {
18
            "$ref": "../definitions.json#/availabilities"
19
          }
20
        },
21
        "400": {
22
          "description": "Missing or wrong parameters",
23
          "schema": {
24
            "$ref": "../definitions.json#/error"
25
          }
26
        },
27
        "404": {
28
          "description": "No item(s) found",
29
          "schema": {
30
            "$ref": "../definitions.json#/error"
31
          }
32
        }
33
      }
34
    }
35
  }
36
}
(-)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 (-1 / +130 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 462-468 subtest 'SearchItems test' => sub { Link Here
462
467
463
subtest 'Koha::Item(s) tests' => sub {
468
subtest 'Koha::Item(s) tests' => sub {
464
469
465
    plan tests => 5;
470
    plan tests => 41;
466
471
467
    $schema->storage->txn_begin();
472
    $schema->storage->txn_begin();
468
473
Lines 475-480 subtest 'Koha::Item(s) tests' => sub { Link Here
475
    });
480
    });
476
    my $itemtype = $builder->build({
481
    my $itemtype = $builder->build({
477
        source => 'Itemtype',
482
        source => 'Itemtype',
483
        value => {
484
            notforloan => 0,
485
        }
486
    });
487
    my $borrower = $builder->build({
488
        source => 'Borrower',
489
    });
490
    my $itemtype2 = $builder->build({
491
        source => 'Itemtype',
492
        value => {
493
            notforloan => 1,
494
        }
478
    });
495
    });
479
496
480
    # Create a biblio and item for testing
497
    # Create a biblio and item for testing
Lines 501-506 subtest 'Koha::Item(s) tests' => sub { Link Here
501
    is( ref($holdingbranch), 'Koha::Library', "Got Koha::Library from holding_branch method" );
518
    is( ref($holdingbranch), 'Koha::Library', "Got Koha::Library from holding_branch method" );
502
    is( $holdingbranch->branchcode(), $library2->{branchcode}, "Home branch code matches holdingbranch" );
519
    is( $holdingbranch->branchcode(), $library2->{branchcode}, "Home branch code matches holdingbranch" );
503
520
521
    # Availability tests
522
    my $availability = $item->availability_for_checkout();
523
    is (ref($availability), 'Koha::Item::Availability', 'Got Koha::Item::Availability');
524
    is( $availability->{available}, 1, "Item is available" );
525
    $availability = $item->availability_for_local_use();
526
    is( $availability->{available}, 1, "Item is available for local use" );
527
    t::lib::Mocks::mock_preference('OnSiteCheckouts', 0);
528
    $availability = $item->availability_for_onsite_checkout();
529
    is( $availability->{available}, 0, "Not available for on-site checkouts" );
530
    is( $availability->{description}[0], "onsite_checkouts_disabled", "Availability description is 'onsite_checkouts_disabled'" );
531
    t::lib::Mocks::mock_preference('OnSiteCheckouts', 1);
532
    $availability = $item->availability_for_onsite_checkout();
533
    is( $availability->{available}, 1, "Available for on-site checkouts" );
534
535
    $item->set({ onloan => "", damaged => 1 })->store();
536
    t::lib::Mocks::mock_preference('AllowHoldsOnDamagedItems', 0);
537
    $availability = $item->availability_for_checkout();
538
    is( $availability->{available}, 0, "Damaged item unavailable" );
539
    is( $availability->{description}[0], "damaged", "Availability description is 'damaged'" );
540
    $availability = $item->availability_for_local_use();
541
    is( $availability->{available}, 0, "Item is not available for local use" );
542
    $availability = $item->availability_for_onsite_checkout();
543
    is( $availability->{available}, 0, "Item is not available for on-site checkouts" );
544
    t::lib::Mocks::mock_preference('AllowHoldsOnDamagedItems', 1);
545
    $availability = $item->availability_for_checkout();
546
    is( $availability->{available}, 1, "Damaged item available" );
547
    is( $availability->{description}[0], "damaged", "Availability description is 'damaged'" );
548
    $availability = $item->availability_for_local_use();
549
    is( $availability->{available}, 1, "Item is available for local use" );
550
    $availability = $item->availability_for_onsite_checkout();
551
    is( $availability->{available}, 1, "Item is available for on-site checkouts" );
552
553
    $item->set({ damaged => 0, withdrawn => 1 })->store();
554
    $availability = $item->availability_for_checkout();
555
    is( $availability->{available}, 0, "Item is not available" );
556
    is( $availability->{description}[0], "withdrawn", "Availability description is 'withdrawn'" );
557
558
    $item->set({ withdrawn => 0, itemlost => 1 })->store();
559
    $availability = $item->availability_for_checkout();
560
    is( $availability->{available}, 0, "Item is not available" );
561
    is( $availability->{description}[0], "itemlost", "Availability description is 'itemlost'" );
562
563
    $item->set({ itemlost => 0, restricted => 1 })->store();
564
    $availability = $item->availability_for_checkout();
565
    is( $availability->{available}, 0, "Item is not available" );
566
    is( $availability->{description}[0], "restricted", "Availability description is 'restricted'" );
567
568
    $item->set({ restricted => 0, notforloan => 1 })->store();
569
    $availability = $item->availability_for_checkout();
570
    is( $availability->{available}, 0, "Item is not available" );
571
    is( $availability->{description}[0], "notforloan", "Availability description is 'notforloan'" );
572
    $availability = $item->availability_for_local_use();
573
    is( $availability->{available}, 1, "Item is available for local use" );
574
    $availability = $item->availability_for_onsite_checkout();
575
    is( $availability->{available}, C4::Context->preference('OnSiteCheckouts'), "Good availability for on-site checkouts" );
576
577
    $item->set({ notforloan => 0, itype => $itemtype2->{itemtype} })->store();
578
    $availability = $item->availability_for_checkout();
579
    is( $availability->{available}, 0, "Item is not available" );
580
    is( $availability->{description}[0], "notforloan", "Availability description is 'notforloan' (itemtype)" );
581
    $availability = $item->availability_for_local_use();
582
    is( $availability->{available}, 1, "Item is available for local use" );
583
    $availability = $item->availability_for_onsite_checkout();
584
    is( $availability->{available}, C4::Context->preference('OnSiteCheckouts'), "Good availability for on-site checkouts" );
585
586
    $item->set({ itype => undef, barcode => "test" })->store();
587
    my $biblio = C4::Biblio::GetBiblio($item->biblionumber);
588
    my $priority= C4::Reserves::CalculatePriority( $item->biblionumber );
589
    my $reserve_id = C4::Reserves::AddReserve(
590
        $item->holdingbranch,
591
        $borrower->{borrowernumber},
592
        $item->biblionumber,
593
        undef,
594
        $priority,
595
        undef, undef, undef,
596
        $$biblio{title},
597
        $itemnumber,
598
        undef
599
    );
600
    my $reserve = Koha::Holds->find($reserve_id);
601
    $availability = $item->availability_for_checkout();
602
    is( $availability->{available}, 0, "Item is not available" );
603
    is( $availability->{description}[0], "reserved", "Availability description is 'reserved'" );
604
    $availability = $item->availability_for_reserve();
605
    is( $availability->{available}, 1, "Item is available for reserve" );
606
607
    # Make sure other items are still show as available for checkout
608
    my ( $item_bibnum2, $item_bibitemnum2, $itemnumber2 ) = AddItem(
609
        {
610
            homebranch    => $library1->{branchcode},
611
            holdingbranch => $library2->{branchcode},
612
            itype         => $itemtype->{itemtype},
613
        },
614
        $bibnum
615
    );
616
    my $item2 = Koha::Items->find($itemnumber2);
617
    is($item2->availability_for_checkout()->{available}, 1, "Another item is available for check out");
618
619
    CancelReserve({ reserve_id => $reserve->reserve_id });
620
621
    $availability = $item->availability_for_checkout();
622
    is( $availability->{available}, 1, "Item is available" );
623
624
    my $module = new Test::MockModule('C4::Context');
625
    $module->mock( 'userenv', sub { { branch => $borrower->{branchcode} } } );
626
    my $issue = AddIssue($borrower, $item->barcode, undef, 1);
627
    $item = Koha::Items->find($item->itemnumber); # refresh item
628
    $availability = $item->availability_for_checkout();
629
    is( $availability->{available}, 0, "Item is not available" );
630
    is( $availability->{description}[0], "onloan", "Availability description is 'onloan'" );
631
    is( $availability->{expected_available}, $issue->date_due, "Expected to be available '".$issue->date_due."'");
632
504
    $schema->storage->txn_rollback;
633
    $schema->storage->txn_rollback;
505
};
634
};
506
635
(-)a/t/db_dependent/api/v1/availability.t (-1 / +292 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::Mocks;
25
use t::lib::TestBuilder;
26
27
use Mojo::JSON;
28
29
use C4::Auth;
30
use C4::Circulation;
31
use C4::Context;
32
33
use Koha::Database;
34
use Koha::Items;
35
use Koha::Patron;
36
37
my $builder = t::lib::TestBuilder->new();
38
39
my $dbh = C4::Context->dbh;
40
$dbh->{AutoCommit} = 0;
41
$dbh->{RaiseError} = 1;
42
43
$ENV{REMOTE_ADDR} = '127.0.0.1';
44
my $t = Test::Mojo->new('Koha::REST::V1');
45
46
my $categorycode = $builder->build({ source => 'Category' })->{ categorycode };
47
my $branchcode = $builder->build({ source => 'Branch' })->{ branchcode };
48
49
my $borrower = $builder->build({ source => 'Borrower' });
50
my $biblio = $builder->build({ source => 'Biblio' });
51
my $biblio2 = $builder->build({ source => 'Biblio' });
52
my $biblionumber = $biblio->{biblionumber};
53
my $biblionumber2 = $biblio2->{biblionumber};
54
55
my $module = new Test::MockModule('C4::Context');
56
$module->mock( 'userenv', sub { { branch => $borrower->{branchcode} } } );
57
58
# $item = available, $item2 = unavailable
59
my $items;
60
$items->{available} = build_item($biblionumber);
61
$items->{notforloan} = build_item($biblionumber2, { notforloan => 1 });
62
$items->{damaged} = build_item($biblionumber2, { damaged => 1 });
63
$items->{withdrawn} = build_item($biblionumber2, { withdrawn => 1 });
64
$items->{onloan}  = build_item($biblionumber2, { onloan => undef });
65
$items->{itemlost} = build_item($biblionumber2, { itemlost => 1 });
66
$items->{reserved} = build_item($biblionumber2);
67
my $priority= C4::Reserves::CalculatePriority($items->{reserved}->{biblionumber});
68
my $reserve_id = C4::Reserves::AddReserve(
69
    $items->{reserved}->{homebranch},
70
    $borrower->{borrowernumber},
71
    $items->{reserved}->{biblionumber},
72
    undef,
73
    $priority,
74
    undef, undef, undef,
75
    $$biblio{title},
76
    $items->{reserved}->{itemnumber},
77
    undef
78
);
79
my $reserve = Koha::Holds->find($reserve_id);
80
81
my $itemnumber = $items->{available}->{itemnumber};
82
83
$t->get_ok("/api/v1/availability/items?itemnumber=-500382")
84
  ->status_is(404);
85
86
$t->get_ok("/api/v1/availability/items?itemnumber=-500382+-500383")
87
  ->status_is(404);
88
89
$t->get_ok("/api/v1/availability/items?biblionumber=-500382")
90
  ->status_is(404);
91
92
$t->get_ok("/api/v1/availability/items?biblionumber=-500382+-500383")
93
  ->status_is(404);
94
95
t::lib::Mocks::mock_preference('OnSiteCheckouts', 0);
96
t::lib::Mocks::mock_preference('AllowHoldsOnDamagedItems', 0);
97
# available item
98
$t->get_ok("/api/v1/availability/items?itemnumber=$itemnumber")
99
  ->status_is(200)
100
  ->json_is('/0/itemnumber', $itemnumber)
101
  ->json_is('/0/biblionumber', $biblionumber)
102
  ->json_is('/0/checkout/available', Mojo::JSON->true)
103
  ->json_is('/0/checkout/description', [])
104
  ->json_is('/0/hold/available', Mojo::JSON->true)
105
  ->json_is('/0/hold/description', [])
106
  ->json_is('/0/local_use/available', Mojo::JSON->true)
107
  ->json_is('/0/local_use/description', [])
108
  ->json_is('/0/onsite_checkout/available', Mojo::JSON->false)
109
  ->json_is('/0/onsite_checkout/description', ["onsite_checkouts_disabled"])
110
  ->json_is('/0/hold_queue_length', 0);
111
t::lib::Mocks::mock_preference('OnSiteCheckouts', 1);
112
$t->get_ok("/api/v1/availability/items?biblionumber=$biblionumber")
113
  ->status_is(200)
114
  ->json_is('/0/itemnumber', $itemnumber)
115
  ->json_is('/0/biblionumber', $biblionumber)
116
  ->json_is('/0/checkout/available', Mojo::JSON->true)
117
  ->json_is('/0/checkout/description', [])
118
  ->json_is('/0/hold/available', Mojo::JSON->true)
119
  ->json_is('/0/hold/description', [])
120
  ->json_is('/0/local_use/available', Mojo::JSON->true)
121
  ->json_is('/0/local_use/description', [])
122
  ->json_is('/0/onsite_checkout/available', Mojo::JSON->true)
123
  ->json_is('/0/onsite_checkout/description', [])
124
  ->json_is('/0/hold_queue_length', 0);
125
126
# notforloan item
127
$t->get_ok("/api/v1/availability/items?itemnumber=".$items->{notforloan}->{itemnumber})
128
  ->status_is(200)
129
  ->json_is('/0/itemnumber', $items->{notforloan}->{itemnumber})
130
  ->json_is('/0/biblionumber', $biblionumber2)
131
  ->json_is('/0/checkout/available', Mojo::JSON->false)
132
  ->json_is('/0/checkout/description/0', "notforloan")
133
  ->json_is('/0/hold/available', Mojo::JSON->false)
134
  ->json_is('/0/hold/description', ["notforloan"])
135
  ->json_is('/0/local_use/available', Mojo::JSON->true)
136
  ->json_is('/0/local_use/description', [])
137
  ->json_is('/0/onsite_checkout/available', Mojo::JSON->true)
138
  ->json_is('/0/onsite_checkout/description', [])
139
  ->json_is('/0/hold_queue_length', 0);
140
t::lib::Mocks::mock_preference('OnSiteCheckouts', 0);
141
$t->get_ok("/api/v1/availability/items?itemnumber=$items->{notforloan}->{itemnumber}")
142
  ->status_is(200)
143
  ->json_is('/0/itemnumber', $items->{notforloan}->{itemnumber})
144
  ->json_is('/0/biblionumber', $biblionumber2)
145
  ->json_is('/0/checkout/available', Mojo::JSON->false)
146
  ->json_is('/0/checkout/description', ["notforloan"])
147
  ->json_is('/0/hold/available', Mojo::JSON->false)
148
  ->json_is('/0/hold/description', ["notforloan"])
149
  ->json_is('/0/local_use/available', Mojo::JSON->true)
150
  ->json_is('/0/local_use/description', [])
151
  ->json_is('/0/onsite_checkout/available', Mojo::JSON->false)
152
  ->json_is('/0/onsite_checkout/description', ["onsite_checkouts_disabled"])
153
  ->json_is('/0/hold_queue_length', 0);
154
t::lib::Mocks::mock_preference('OnSiteCheckouts', 1);
155
156
# damaged item
157
$t->get_ok("/api/v1/availability/items?itemnumber=".$items->{damaged}->{itemnumber})
158
  ->status_is(200)
159
  ->json_is('/0/itemnumber', $items->{damaged}->{itemnumber})
160
  ->json_is('/0/biblionumber', $biblionumber2)
161
  ->json_is('/0/checkout/available', Mojo::JSON->false)
162
  ->json_is('/0/checkout/description', ["damaged"])
163
  ->json_is('/0/hold/available', Mojo::JSON->false)
164
  ->json_is('/0/hold/description', ["damaged"])
165
  ->json_is('/0/local_use/available', Mojo::JSON->false)
166
  ->json_is('/0/local_use/description', ["damaged"])
167
  ->json_is('/0/onsite_checkout/available', Mojo::JSON->false)
168
  ->json_is('/0/onsite_checkout/description', ["damaged"])
169
  ->json_is('/0/hold_queue_length', 0);
170
t::lib::Mocks::mock_preference('AllowHoldsOnDamagedItems', 1);
171
$t->get_ok("/api/v1/availability/items?itemnumber=".$items->{damaged}->{itemnumber})
172
  ->status_is(200)
173
  ->json_is('/0/itemnumber', $items->{damaged}->{itemnumber})
174
  ->json_is('/0/biblionumber', $biblionumber2)
175
  ->json_is('/0/checkout/available', Mojo::JSON->true)
176
  ->json_is('/0/checkout/description', ["damaged"])
177
  ->json_is('/0/hold/available', Mojo::JSON->true)
178
  ->json_is('/0/hold/description', ["damaged"])
179
  ->json_is('/0/local_use/available', Mojo::JSON->true)
180
  ->json_is('/0/local_use/description', ["damaged"])
181
  ->json_is('/0/onsite_checkout/available', Mojo::JSON->true)
182
  ->json_is('/0/onsite_checkout/description', ["damaged"])
183
  ->json_is('/0/hold_queue_length', 0);
184
185
# withdrawn item
186
$t->get_ok("/api/v1/availability/items?itemnumber=".$items->{withdrawn}->{itemnumber})
187
  ->status_is(200)
188
  ->json_is('/0/itemnumber', $items->{withdrawn}->{itemnumber})
189
  ->json_is('/0/biblionumber', $biblionumber2)
190
  ->json_is('/0/checkout/available', Mojo::JSON->false)
191
  ->json_is('/0/checkout/description', ["withdrawn"])
192
  ->json_is('/0/hold/available', Mojo::JSON->false)
193
  ->json_is('/0/hold/description', ["withdrawn"])
194
  ->json_is('/0/local_use/available', Mojo::JSON->false)
195
  ->json_is('/0/local_use/description', ["withdrawn"])
196
  ->json_is('/0/onsite_checkout/available', Mojo::JSON->false)
197
  ->json_is('/0/onsite_checkout/description', ["withdrawn"])
198
  ->json_is('/0/hold_queue_length', 0);
199
200
# lost item
201
$t->get_ok("/api/v1/availability/items?itemnumber=".$items->{itemlost}->{itemnumber})
202
  ->status_is(200)
203
  ->json_is('/0/itemnumber', $items->{itemlost}->{itemnumber})
204
  ->json_is('/0/biblionumber', $biblionumber2)
205
  ->json_is('/0/checkout/available', Mojo::JSON->false)
206
  ->json_is('/0/checkout/description', ["itemlost"])
207
  ->json_is('/0/hold/available', Mojo::JSON->false)
208
  ->json_is('/0/hold/description', ["itemlost"])
209
  ->json_is('/0/local_use/available', Mojo::JSON->false)
210
  ->json_is('/0/local_use/description', ["itemlost"])
211
  ->json_is('/0/onsite_checkout/available', Mojo::JSON->false)
212
  ->json_is('/0/onsite_checkout/description', ["itemlost"])
213
  ->json_is('/0/hold_queue_length', 0);
214
215
my $issue = AddIssue($borrower, $items->{onloan}->{barcode}, undef, 1);
216
217
# issued item
218
$t->get_ok("/api/v1/availability/items?itemnumber=".$items->{onloan}->{itemnumber})
219
  ->status_is(200)
220
  ->json_is('/0/itemnumber', $items->{onloan}->{itemnumber})
221
  ->json_is('/0/biblionumber', $biblionumber2)
222
  ->json_is('/0/checkout/available', Mojo::JSON->false)
223
  ->json_is('/0/checkout/description', ["onloan"])
224
  ->json_is('/0/hold/available', Mojo::JSON->true)
225
  ->json_is('/0/hold/description', [])
226
  ->json_is('/0/local_use/available', Mojo::JSON->false)
227
  ->json_is('/0/local_use/description', ["onloan"])
228
  ->json_is('/0/onsite_checkout/available', Mojo::JSON->false)
229
  ->json_is('/0/onsite_checkout/description', ["onloan"])
230
  ->json_is('/0/checkout/expected_available', $issue->date_due)
231
  ->json_is('/0/local_use/expected_available', $issue->date_due)
232
  ->json_is('/0/onsite_checkout/expected_available', $issue->date_due)
233
  ->json_is('/0/hold_queue_length', 0);
234
235
# reserved item
236
$t->get_ok("/api/v1/availability/items?itemnumber=".$items->{reserved}->{itemnumber})
237
  ->status_is(200)
238
  ->json_is('/0/itemnumber', $items->{reserved}->{itemnumber})
239
  ->json_is('/0/biblionumber', $biblionumber2)
240
  ->json_is('/0/checkout/available', Mojo::JSON->false)
241
  ->json_is('/0/checkout/description', ["reserved"])
242
  ->json_is('/0/hold/available', Mojo::JSON->true)
243
  ->json_is('/0/hold/description', [])
244
  ->json_is('/0/local_use/available', Mojo::JSON->false)
245
  ->json_is('/0/local_use/description', ["reserved"])
246
  ->json_is('/0/onsite_checkout/available', Mojo::JSON->false)
247
  ->json_is('/0/onsite_checkout/description', ["reserved"])
248
  ->json_is('/0/hold_queue_length', 1);
249
250
# multiple in one request
251
$t->get_ok("/api/v1/availability/items?itemnumber=".$items->{notforloan}->{itemnumber}."+$itemnumber+-500382")
252
  ->status_is(200)
253
  ->json_is('/0/itemnumber', $items->{notforloan}->{itemnumber})
254
  ->json_is('/0/biblionumber', $biblionumber2)
255
  ->json_is('/0/checkout/available', Mojo::JSON->false)
256
  ->json_is('/0/checkout/description/0', "notforloan")
257
  ->json_is('/0/hold/available', Mojo::JSON->false)
258
  ->json_is('/0/hold/description', ["notforloan"])
259
  ->json_is('/0/local_use/available', Mojo::JSON->true)
260
  ->json_is('/0/local_use/description', [])
261
  ->json_is('/0/onsite_checkout/available', Mojo::JSON->true)
262
  ->json_is('/0/onsite_checkout/description', [])
263
  ->json_is('/0/hold_queue_length', 0)
264
  ->json_is('/1/itemnumber', $itemnumber)
265
  ->json_is('/1/biblionumber', $biblionumber)
266
  ->json_is('/1/checkout/available', Mojo::JSON->true)
267
  ->json_is('/1/checkout/description', [])
268
  ->json_is('/1/hold/available', Mojo::JSON->true)
269
  ->json_is('/1/hold/description', [])
270
  ->json_is('/1/local_use/available', Mojo::JSON->true)
271
  ->json_is('/1/local_use/description', [])
272
  ->json_is('/1/onsite_checkout/available', Mojo::JSON->true)
273
  ->json_is('/1/onsite_checkout/description', [])
274
  ->json_is('/1/hold_queue_length', 0);
275
276
sub build_item {
277
    my ($biblionumber, $field) = @_;
278
279
    return $builder->build({
280
        source => 'Item',
281
        value => {
282
            biblionumber => $biblionumber,
283
            notforloan => $field->{notforloan} || 0,
284
            damaged => $field->{damaged} || 0,
285
            withdrawn => $field->{withdrawn} || 0,
286
            itemlost => $field->{itemlost} || 0,
287
            restricted => $field->{restricted} || undef,
288
            onloan => $field->{onloan} || undef,
289
            itype => $field->{itype} || undef,
290
        }
291
    });
292
}

Return to bug 16826