Bugzilla – Attachment 57369 Details for
Bug 16826
REST API: Add API routes for getting item availability and holdability
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
Bug 16826: Add Koha::Item::Availabilit(y/ies) for item availability
Bug-16826-Add-KohaItemAvailabilityies-for-item-ava.patch (text/plain), 26.81 KB, created by
Lari Taskula
on 2016-11-09 10:45:29 UTC
(
hide
)
Description:
Bug 16826: Add Koha::Item::Availabilit(y/ies) for item availability
Filename:
MIME Type:
Creator:
Lari Taskula
Created:
2016-11-09 10:45:29 UTC
Size:
26.81 KB
patch
obsolete
>From 072745fb7f23e3db7889bcc81de7183f9c9a2764 Mon Sep 17 00:00:00 2001 >From: Lari Taskula <lari.taskula@jns.fi> >Date: Tue, 8 Nov 2016 15:45:38 +0200 >Subject: [PATCH] Bug 16826: Add Koha::Item::Availabilit(y/ies) for item > availability > >This patch adds classes for calculating and storing item availability information. > >Usage is simple, e.g. holdability; >my $item = Koha::Items->find(123); >my $holdability = $item->availabilities->hold; >if ($holdability->available) { > # available for hold! >} else { > # $holdability->description holds the reason for unavailability >} > >To test: >1. Run t/db_dependent/Koha/Item/Availability.t >--- > Koha/Item.pm | 31 ++++ > Koha/Item/Availabilities.pm | 253 ++++++++++++++++++++++++++++ > Koha/Item/Availability.pm | 282 ++++++++++++++++++++++++++++++++ > t/db_dependent/Koha/Item/Availability.t | 250 ++++++++++++++++++++++++++++ > 4 files changed, 816 insertions(+) > create mode 100644 Koha/Item/Availabilities.pm > create mode 100644 Koha/Item/Availability.pm > create mode 100644 t/db_dependent/Koha/Item/Availability.t > >diff --git a/Koha/Item.pm b/Koha/Item.pm >index 51a5ac0..ecf9d42 100644 >--- a/Koha/Item.pm >+++ b/Koha/Item.pm >@@ -25,6 +25,7 @@ use Koha::Database; > > use C4::Context; > use C4::Circulation qw(GetIssuingRule); >+use Koha::Item::Availabilities; > use Koha::Item::Transfer; > use Koha::Patrons; > use Koha::Libraries; >@@ -41,6 +42,24 @@ Koha::Item - Koha Item object class > > =cut > >+=head3 availabilities >+ >+my $availabilities = $item->availabilities; >+ >+# Available for checkout? >+$availabilities->issue->available >+ >+Returns Koha::Item::Availabilities object which holds different types of >+availabilities for this item. >+ >+=cut >+ >+sub availabilities { >+ my ($self) = @_; >+ >+ return Koha::Item::Availabilities->new($self); >+} >+ > =head3 effective_itemtype > > Returns the itemtype for the item based on whether item level itemtypes are set or not. >@@ -53,6 +72,18 @@ sub effective_itemtype { > return $self->_result()->effective_itemtype(); > } > >+=head3 hold_queue_length >+ >+=cut >+ >+sub hold_queue_length { >+ my ( $self ) = @_; >+ >+ my $reserves = Koha::Holds->search({ itemnumber => $self->itemnumber }); >+ return $reserves->count() if $reserves; >+ return 0; >+} >+ > =head3 home_branch > > =cut >diff --git a/Koha/Item/Availabilities.pm b/Koha/Item/Availabilities.pm >new file mode 100644 >index 0000000..091cab4 >--- /dev/null >+++ b/Koha/Item/Availabilities.pm >@@ -0,0 +1,253 @@ >+package Koha::Item::Availabilities; >+ >+# Copyright Koha-Suomi Oy 2016 >+# >+# This file is part of Koha. >+# >+# Koha is free software; you can redistribute it and/or modify it under the >+# terms of the GNU General Public License as published by the Free Software >+# Foundation; either version 3 of the License, or (at your option) any later >+# version. >+# >+# Koha is distributed in the hope that it will be useful, but WITHOUT ANY >+# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR >+# A PARTICULAR PURPOSE. See the GNU General Public License for more details. >+# >+# You should have received a copy of the GNU General Public License along >+# with Koha; if not, write to the Free Software Foundation, Inc., >+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. >+ >+use Modern::Perl; >+ >+use C4::Context; >+use C4::Reserves; >+ >+use Koha::Exceptions; >+use Koha::Issues; >+use Koha::Item::Availability; >+use Koha::Items; >+use Koha::ItemTypes; >+ >+=head1 NAME >+ >+Koha::Item::Availabilities - Koha Item Availabilities object class >+ >+=head1 SYNOPSIS >+ >+ my $availabilities = Koha::Items->find(1337)->availabilities; >+ >+ print "Available for checkout!" if $availabilities->checkout->available; >+ >+=head1 DESCRIPTION >+ >+This class holds logic for calculating different types of availabilities. >+ >+=head2 Class Methods >+ >+=cut >+ >+=head3 new >+ >+=cut >+ >+sub new { >+ my ($class, $params) = @_; >+ >+ my $self = {}; >+ my $item; >+ >+ unless(ref($params) eq 'Koha::Item') { >+ Koha::Exceptions::MissingParameter->throw({ >+ error => "Missing parameter itemnumber", >+ parameter => "itemnumber", >+ }) unless $params->{'itemnumber'}; >+ >+ $item = Koha::Items->find($params->{'itemnumber'}); >+ } else { >+ $item = $params; >+ } >+ >+ $self->{'item'} = $item; >+ $self->{'_use_stored_values'} = 0; >+ >+ bless($self, $class); >+} >+ >+=head3 hold >+ >+Availability for holds. Does not consider patron status. >+ >+=cut >+ >+sub hold { >+ my ($self) = @_; >+ >+ my $item = $self->item; >+ my $availability = Koha::Item::Availability->new->set_available; >+ >+ $availability->set_unavailable("withdrawn") if $item->withdrawn; >+ $availability->set_unavailable("itemlost") if $item->itemlost; >+ $availability->set_unavailable("restricted") if $item->restricted; >+ >+ if ($item->damaged) { >+ if (C4::Context->preference('AllowHoldsOnDamagedItems')) { >+ $availability->add_description("damaged"); >+ } else { >+ $availability->set_unavailable("damaged"); >+ } >+ } >+ >+ my $itemtype; >+ if (C4::Context->preference('item-level_itypes')) { >+ $itemtype = Koha::ItemTypes->find($item->itype); >+ } else { >+ my $biblioitem = Koha::Biblioitems->find($item->biblioitemnumber ); >+ $itemtype = Koha::ItemTypes->find($biblioitem->itemtype); >+ } >+ >+ if ($item->notforloan > 0 || $itemtype && $itemtype->notforloan) { >+ $availability->set_unavailable("notforloan"); >+ } elsif ($item->notforloan < 0) { >+ $availability->set_unavailable("ordered"); >+ } >+ >+ $self->{'_hold'} = $availability; >+ return $availability; >+} >+ >+=head3 issue >+ >+Availability for checkouts. Does not consider patron status. >+ >+=cut >+ >+sub issue { >+ my ($self, $params) = @_; >+ >+ my $item = $self->item; >+ my $availability; >+ unless ($self->use_stored_values) { >+ $availability = $self->hold->clone; >+ } >+ else { >+ if ($self->{'_hold'}) { >+ $availability = $self->{'_hold'}->clone; >+ } else { >+ $availability = $self->hold->clone; >+ } >+ } >+ >+ if (my $issue = Koha::Issues->find({ itemnumber => $item->itemnumber })) { >+ $availability->set_unavailable("onloan", $issue->date_due); >+ } >+ >+ if (C4::Reserves::CheckReserves($item->itemnumber)) { >+ $availability->set_unavailable("reserved"); >+ } >+ >+ $self->{'_issue'} = $availability; >+ return $availability; >+} >+ >+=head3 item >+ >+=cut >+ >+sub item { >+ my ($self) = @_; >+ >+ return $self->{'item'}; >+} >+ >+=head3 local_use >+ >+Same as checkout availability, but exclude notforloan. >+ >+=cut >+ >+sub local_use { >+ my ($self) = @_; >+ >+ my $availability; >+ unless ($self->use_stored_values) { >+ $availability = $self->issue->clone; >+ } >+ else { >+ if ($self->{'_issue'}) { >+ $availability = $self->{'_issue'}->clone; >+ } else { >+ $availability = $self->issue->clone; >+ } >+ } >+ >+ if (grep(/^notforloan$/, @{$availability->description}) >+ && @{$availability->description} == 1) { >+ $availability = $availability->set_available; >+ } >+ $availability->del_description("notforloan"); >+ >+ $self->{'_local_use'} = $availability; >+ return $availability; >+} >+ >+=head3 onsite_checkout >+ >+Same as local_use availability, but consider OnSiteCheckouts system preference. >+ >+=cut >+ >+sub onsite_checkout { >+ my ($self) = @_; >+ >+ my $availability; >+ unless ($self->use_stored_values) { >+ $availability = $self->local_use->clone; >+ } >+ else { >+ if ($self->{'_local_use'}) { >+ $availability = $self->{'_local_use'}->clone; >+ } else { >+ $availability = $self->local_use->clone; >+ } >+ } >+ >+ if (!C4::Context->preference('OnSiteCheckouts')) { >+ $availability = Koha::Item::Availability->new >+ ->set_unavailable("onsite_checkouts_disabled"); >+ } >+ >+ $self->{'_onsite_checkout'} = $availability; >+ return $availability; >+} >+ >+=head3 use_stored_values >+ >+ON: $availabilities->use_stored_values(1); >+OFF: $availabilities->use_stored_values(0); >+ >+Performance enhancement. >+ >+Different availability types are dependent on some others. For example issues >+are dependent on holds; if holds are unavailable, so are issues. If we want to >+gather all types of availabilities in one go, we can store the previous >+availability in the object and use it for the next one without re-calculating >+the previous availabilities. >+ >+This is the purpose of this switch; when enabled, use stored availability in >+the object for availability dependencies. When disabled, always re-calculate >+dependencies as well. >+ >+=cut >+ >+sub use_stored_values { >+ my ($self, $use_stored_values) = @_; >+ >+ if (defined $use_stored_values) { >+ $self->{'_use_stored_values'} = >+ $use_stored_values ? 1 : 0; >+ } >+ >+ return $self->{'_use_stored_values'}; >+} >+ >+1; >diff --git a/Koha/Item/Availability.pm b/Koha/Item/Availability.pm >new file mode 100644 >index 0000000..9464948 >--- /dev/null >+++ b/Koha/Item/Availability.pm >@@ -0,0 +1,282 @@ >+package Koha::Item::Availability; >+ >+# Copyright Koha-Suomi Oy 2016 >+# >+# This file is part of Koha. >+# >+# Koha is free software; you can redistribute it and/or modify it under the >+# terms of the GNU General Public License as published by the Free Software >+# Foundation; either version 3 of the License, or (at your option) any later >+# version. >+# >+# Koha is distributed in the hope that it will be useful, but WITHOUT ANY >+# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR >+# A PARTICULAR PURPOSE. See the GNU General Public License for more details. >+# >+# You should have received a copy of the GNU General Public License along >+# with Koha; if not, write to the Free Software Foundation, Inc., >+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. >+ >+use Modern::Perl; >+ >+use Storable qw(dclone); >+ >+=head1 NAME >+ >+Koha::Item::Availability - Koha Item Availability object class >+ >+=head1 SYNOPSIS >+ >+ my $item = Koha::Items->find(1337); >+ my $availabilities = $item->availabilities; >+ # ref($availabilities) eq 'Koha::Item::Availabilities' >+ # ref($availabilities->issue) eq 'Koha::Item::Availability' >+ >+ print "Available for checkout!" if $availabilities->issue->available; >+ >+=head1 DESCRIPTION >+ >+This class holds item availability information. >+ >+See Koha::Item for availability subroutines. >+ >+=head2 Class Methods >+ >+=cut >+ >+=head3 new >+ >+Returns a new Koha::Item::Availability object. >+ >+=cut >+ >+sub new { >+ my ($class) = @_; >+ >+ my $self = { >+ description => [], >+ availability_needs_confirmation => undef, >+ available => undef, >+ expected_available => undef, >+ }; >+ >+ bless $self, $class; >+} >+ >+=head3 add_description >+ >+$availability->add_description("notforloan"); >+$availability->add_description("withdrawn); >+ >+# $availability->description == ["notforloan", "withdrawn"] >+ >+Pushes a new description to $availability object. Does not duplicate existing >+descriptions. >+ >+Returns updated Koha::Item::Availability object. >+ >+=cut >+ >+sub add_description { >+ my ($self, $description) = @_; >+ >+ return $self unless $description; >+ >+ if (ref($description) eq 'ARRAY') { >+ foreach my $desc (@$description) { >+ if (grep(/^$desc$/, @{$self->{description}})){ >+ next; >+ } >+ push $self->{description}, $desc; >+ } >+ } else { >+ if (!grep(/^$description$/, @{$self->{description}})){ >+ push $self->{description}, $description; >+ } >+ } >+ >+ return $self; >+} >+ >+=head3 clone >+ >+$availability_cloned = $availability->clone; >+$availability->set_unavailable; >+ >+# $availability_cloned->available != $availability->available >+ >+Clones the Koha::Item::Availability object. >+ >+Returns cloned object. >+ >+=cut >+ >+sub clone { >+ my ( $self ) = @_; >+ >+ return dclone($self); >+} >+ >+=head3 del_description >+ >+$availability->add_description(["notforloan", "withdrawn", "itemlost", "restricted"]); >+$availability->del_description("withdrawn"); >+ >+# $availability->description == ["notforloan", "itemlost", "restricted"] >+$availability->del_description(["withdrawn", "restricted"]); >+# $availability->description == ["itemlost"] >+ >+Deletes an availability description(s) if it exists. >+ >+Returns Koha::Item::Availability object. >+ >+=cut >+ >+sub del_description { >+ my ($self, $description) = @_; >+ >+ return $self unless $description; >+ >+ my @updated; >+ if (ref($description) eq 'ARRAY') { >+ foreach my $desc (@$description) { >+ @updated = grep(!/^$desc$/, @{$self->description}); >+ } >+ } else { >+ @updated = grep(!/^$description$/, @{$self->description}); >+ } >+ $self->description(\@updated); >+ >+ return $self; >+} >+ >+=head3 has_description >+ >+$availability->add_description(["notforloan", "withdrawn"]); >+$availability->has_description("withdrawn"); # 1 >+$availability->has_description(["notforloan", "withdrawn"]); # 1 >+$availability->has_description("itemlost"); # 0 >+ >+Finds description(s) in availability descriptions. >+ >+Returns 1 if found, 0 otherwise. >+ >+=cut >+ >+sub has_description { >+ my ($self, $description) = @_; >+ >+ return 0 unless $description; >+ >+ my @found; >+ if (ref($description) eq 'ARRAY') { >+ foreach my $desc (@$description) { >+ if (!grep(/^$desc$/, @{$self->description})){ >+ return 0; >+ } >+ } >+ } else { >+ if (!grep(/^$description$/, @{$self->description})){ >+ return 0; >+ } >+ } >+ >+ return 1; >+} >+ >+=head3 set_available >+ >+$availability->set_available; >+ >+Sets the Koha::Item::Availability object status to available. >+ $availability->available == 1 >+ >+Overrides old availability status, but does not override other stored data in >+the object. Create a new Koha::Item::Availability object to get a fresh start. >+Appends any previously defined availability descriptions with add_description(). >+ >+Returns updated Koha::Item::Availability object. >+ >+=cut >+ >+sub set_available { >+ my ($self, $description) = @_; >+ >+ return $self->_update_availability_status(1, 0, $description); >+} >+ >+=head3 set_needs_confirmation >+ >+$availability->set_needs_confirmation("unbelieveable_reason", "2016-07-07"); >+ >+Sets the Koha::Item::Availability object status to unavailable, >+but needs confirmation. >+ $availability->available == 0 >+ $availability->availability_needs_confirmation == 1 >+ >+Overrides old availability statuses, but does not override other stored data in >+the object. Create a new Koha::Item::Availability object to get a fresh start. >+Appends any previously defined availability descriptions with add_description(). >+Allows you to define expected availability date in C<$expected>. >+ >+Returns updated Koha::Item::Availability object. >+ >+=cut >+ >+sub set_needs_confirmation { >+ my ($self, $description, $expected) = @_; >+ >+ return $self->_update_availability_status(0, 1, $description, $expected); >+} >+ >+=head3 set_unavailable >+ >+$availability->set_unavailable("onloan", "2016-07-07"); >+ >+Sets the Koha::Item::Availability object status to unavailable. >+ $availability->available == 0 >+ >+Overrides old availability status, but does not override other stored data in >+the object. Create a new Koha::Item::Availability object to get a fresh start. >+Appends any previously defined availability descriptions with add_description(). >+Allows you to define expected availability date in C<$expected>. >+ >+Returns updated Koha::Item::Availability object. >+ >+=cut >+ >+sub set_unavailable { >+ my ($self, $description, $expected) = @_; >+ >+ return $self->_update_availability_status(0, 0, $description, $expected); >+} >+ >+sub AUTOLOAD { >+ my ($self, $params) = @_; >+ >+ my $method = our $AUTOLOAD; >+ $method =~ s/.*://; >+ >+ # get & set >+ if (exists $self->{$method}) { >+ unless (defined $params) { >+ return $self->{$method}; >+ } else { >+ $self->{$method} = $params; >+ return $self; >+ } >+ } >+} >+ >+sub _update_availability_status { >+ my ($self, $available, $needs, $desc, $expected) = @_; >+ >+ $self->available($available); >+ $self->availability_needs_confirmation($needs); >+ $self->expected_available($expected) if $expected; >+ $self->add_description($desc); >+ >+ return $self; >+} >+ >+1; >diff --git a/t/db_dependent/Koha/Item/Availability.t b/t/db_dependent/Koha/Item/Availability.t >new file mode 100644 >index 0000000..992e9d3 >--- /dev/null >+++ b/t/db_dependent/Koha/Item/Availability.t >@@ -0,0 +1,250 @@ >+#!/usr/bin/perl >+ >+# Copyright Koha-Suomi Oy 2016 >+# >+# This file is part of Koha >+# >+# Koha is free software; you can redistribute it and/or modify it >+# under the terms of the GNU General Public License as published by >+# the Free Software Foundation; either version 3 of the License, or >+# (at your option) any later version. >+# >+# Koha is distributed in the hope that it will be useful, but >+# WITHOUT ANY WARRANTY; without even the implied warranty of >+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the >+# GNU General Public License for more details. >+# >+# You should have received a copy of the GNU General Public License >+# along with Koha; if not, see <http://www.gnu.org/licenses>. >+ >+use Modern::Perl; >+use Test::More tests => 4; >+use t::lib::Mocks; >+use t::lib::TestBuilder; >+ >+use C4::Biblio; >+use C4::Circulation; >+use C4::Reserves; >+ >+use Koha::Database; >+use Koha::Items; >+use Koha::ItemTypes; >+ >+use_ok('Koha::Item::Availabilities'); >+use_ok('Koha::Item::Availability'); >+ >+my $schema = Koha::Database->new->schema; >+$schema->storage->txn_begin; >+ >+subtest 'Koha::Item::Availability tests' => sub { >+ plan tests => 14; >+ >+ my $availability = Koha::Item::Availability->new->set_available; >+ >+ is($availability->available, 1, "Available"); >+ $availability->set_needs_confirmation; >+ is($availability->availability_needs_confirmation, 1, "Needs confirmation"); >+ $availability->set_unavailable; >+ is($availability->available, 0, "Not available"); >+ >+ $availability->add_description("such available"); >+ $availability->add_description("wow"); >+ $availability->add_description("wow"); >+ >+ ok($availability->has_description("wow"), "Found description 'wow'"); >+ ok($availability->has_description(["wow", "such available"]), >+ "Found description 'wow' and 'such available'"); >+ is($availability->has_description(["wow", "much not found"]), 0, >+ "Didn't find 'wow' and 'much not found'"); >+ is($availability->description->[0], "such available", >+ "Found correct description in correct index 1/4"); >+ is($availability->description->[1], "wow", >+ "Found correct description in correct index 2/2"); >+ >+ $availability->add_description(["much description", "very doge"]); >+ is($availability->description->[2], "much description", >+ "Found correct description in correct index 3/4"); >+ is($availability->description->[3], "very doge", >+ "Found correct description in correct index 4/4"); >+ >+ $availability->del_description("wow"); >+ is($availability->description->[1], "much description", >+ "Found description from correct index after del"); >+ $availability->del_description(["very doge", "such available"]); >+ is($availability->description->[0], "much description", >+ "Found description from correct index after del"); >+ >+ my $availability_clone = $availability; >+ $availability->set_unavailable; >+ is($availability_clone->available, $availability->{available}, >+ "Availability_clone points to availability"); >+ $availability_clone = $availability->clone; >+ $availability->set_available; >+ isnt($availability_clone->available, $availability->{available}, >+ "Availability_clone was cloned and no longer has same availability status"); >+}; >+ >+subtest 'Item availability tests' => sub { >+ plan tests => 14; >+ >+ my $builder = t::lib::TestBuilder->new; >+ my $library = $builder->build({ source => 'Branch' }); >+ my $itemtype_built = $builder->build({ >+ source => 'Itemtype', >+ value => { >+ notforloan => 0, >+ } >+ }); >+ my $biblioitem_built = $builder->build({ >+ source => 'Biblioitem', >+ value => { >+ itemtype => $itemtype_built->{'itemtype'}, >+ } >+ }); >+ my $item_built = $builder->build({ >+ source => 'Item', >+ value => { >+ holding_branch => $library->{branchcode}, >+ homebranch => $library->{branchcode}, >+ biblioitemnumber => $biblioitem_built->{biblioitemnumber}, >+ itype => $itemtype_built->{itemtype}, >+ } >+ }); >+ >+ t::lib::Mocks::mock_preference('item-level_itypes', 0); >+ t::lib::Mocks::mock_preference('OnSiteCheckouts', 1); >+ t::lib::Mocks::mock_preference('AllowHoldsOnDamagedItems', 0); >+ >+ my $itemtype = Koha::ItemTypes->find($itemtype_built->{itemtype}); >+ my $item = Koha::Items->find($item_built->{itemnumber}); >+ $item->set({ >+ notforloan => 0, >+ damaged => 0, >+ itemlost => 0, >+ withdrawn => 0, >+ onloan => undef, >+ restricted => 0, >+ })->store; # set available >+ >+ ok($item->can('availabilities'), "Koha::Item->availabilities exists."); >+ my $availabilities = $item->availabilities; >+ is(ref($availabilities), 'Koha::Item::Availabilities', '$availabilities is blessed as Koha::Item::Availabilities'); >+ >+ my $holdability = $availabilities->hold; >+ my $issuability = $availabilities->issue; >+ my $for_local_use = $availabilities->local_use; >+ my $onsite_issuability = $availabilities->onsite_checkout; >+ is(ref($holdability), 'Koha::Item::Availability', '1/4 Correct class'); >+ is(ref($issuability), 'Koha::Item::Availability', '2/4 Correct class'); >+ is(ref($for_local_use), 'Koha::Item::Availability', '3/4 Correct class'); >+ is(ref($onsite_issuability), 'Koha::Item::Availability', '4/4 Correct class'); >+ >+ ok($holdability->available, 'Available for holds'); >+ ok($issuability->available, 'Available for checkouts'); >+ ok($for_local_use->available, 'Available for local use'); >+ ok($onsite_issuability->available, 'Available for onsite checkout'); >+ >+ # Test plan: >+ # Subtest for each availability type in predefined order; >+ # hold -> checkout -> local_use -> onsite_checkout >+ # Each is dependant on the previous one, no need to run same tests as moving >+ # from left to right. >+ subtest 'Availability: hold' => sub { >+ plan tests => 14; >+ >+ $item->withdrawn(1)->store; >+ ok(!$availabilities->hold->available, "Item withdrawn => not available"); >+ is($availabilities->hold->description->[0], 'withdrawn', 'Description: withdrawn'); >+ $item->withdrawn(0)->itemlost(1)->store; >+ ok(!$availabilities->hold->available, "Item lost => not available"); >+ is($availabilities->hold->description->[0], 'itemlost', 'Description: itemlost'); >+ $item->itemlost(0)->restricted(1)->store; >+ ok(!$availabilities->hold->available, "Item restricted => not available"); >+ is($availabilities->hold->description->[0], 'restricted', 'Description: restricted'); >+ $item->restricted(0)->store; >+ >+ subtest 'Hold on damaged item' => sub { >+ plan tests => 3; >+ >+ t::lib::Mocks::mock_preference('AllowHoldsOnDamagedItems', 0); >+ $item->damaged(1)->store; >+ ok($item->damaged, "Item is damaged"); >+ ok(!$availabilities->hold->available, 'Not available for holds (AllowHoldsOnDamagedItems => 0)'); >+ t::lib::Mocks::mock_preference('AllowHoldsOnDamagedItems', 1); >+ ok($availabilities->hold->available, 'Available for holds (AllowHoldsOnDamagedItems => 1)'); >+ $item->damaged(0)->store; >+ }; >+ >+ t::lib::Mocks::mock_preference('item-level_itypes', 1); >+ $item->notforloan(1)->store; >+ ok(!$availabilities->hold->available, "Item notforloan => not available"); >+ is($availabilities->hold->description->[0], 'notforloan', 'Description: notforloan'); >+ t::lib::Mocks::mock_preference('item-level_itypes', 0); >+ $item->notforloan(0)->store; >+ $itemtype->notforloan(1)->store; >+ ok(!$availabilities->hold->available, "Itemtype notforloan => not available"); >+ is($availabilities->hold->description->[0], 'notforloan', 'Description: notforloan'); >+ $itemtype->notforloan(0)->store; >+ ok($availabilities->hold->available, "Available"); >+ $item->notforloan(-1)->store; >+ ok(!$availabilities->hold->available, "Itemtype notforloan -1 => not available"); >+ is($availabilities->hold->description->[0], 'ordered', 'Description: ordered'); >+ $item->notforloan(0)->store; >+ }; >+ >+ subtest 'Availability: Checkout' => sub { >+ plan tests => 7; >+ >+ my $patron = $builder->build({ source => 'Borrower' }); >+ my $biblio = C4::Biblio::GetBiblio($item->biblionumber); >+ my $priority= C4::Reserves::CalculatePriority( $item->biblionumber ); >+ my $reserve_id = C4::Reserves::AddReserve( >+ $item->holdingbranch, >+ $patron->{borrowernumber}, >+ $item->biblionumber, >+ undef, >+ $priority, >+ undef, undef, undef, >+ $$biblio{title}, >+ $item->itemnumber, >+ undef >+ ); >+ >+ ok(!$availabilities->issue->available, "Item reserved => not available"); >+ is($availabilities->issue->description->[0], 'reserved', 'Description: reserved'); >+ C4::Reserves::CancelReserve({ reserve_id => $reserve_id }); >+ ok($availabilities->issue->available, "Reserve cancelled => available"); >+ >+ my $module = new Test::MockModule('C4::Context'); >+ $module->mock( 'userenv', sub { { branch => $patron->{branchcode} } } ); >+ my $issue = C4::Circulation::AddIssue($patron, $item->barcode, undef, 1); >+ ok(!$availabilities->issue->available, "Item issued => not available"); >+ is($availabilities->issue->description->[0], 'onloan', 'Description: onloan'); >+ is($availabilities->issue->expected_available, >+ $issue->date_due, "Expected to be available '".$issue->date_due."'"); >+ C4::Circulation::AddReturn($item->barcode, $item->homebranch); >+ ok($availabilities->issue->available, "Checkin => available"); >+ }; >+ >+ subtest 'Availability: Local use' => sub { >+ plan tests => 1; >+ >+ $item->notforloan(1)->store; >+ ok($availabilities->local_use->available, "Item notforloan => available"); >+ }; >+ >+ subtest 'Availability: On-site checkout' => sub { >+ plan tests => 2; >+ >+ t::lib::Mocks::mock_preference('OnSiteCheckouts', 0); >+ ok(!$availabilities->onsite_checkout->available, 'Not available for onsite checkout ' >+ .'(OnSiteCheckouts => 0)'); >+ t::lib::Mocks::mock_preference('OnSiteCheckouts', 1); >+ ok($availabilities->onsite_checkout->available, 'Available for onsite checkout ' >+ .'(OnSiteCheckouts => 1)'); >+ }; >+}; >+ >+$schema->storage->txn_rollback; >+ >+1; >-- >1.9.1
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
|
Splinter Review
Attachments on
bug 16826
:
53271
|
53276
|
53371
|
53672
|
53675
|
53813
|
53826
|
53827
|
53922
|
54053
|
56128
|
56129
|
56130
|
56295
|
57271
|
57321
|
57369
|
57370
|
57371
|
57373
|
57382
|
58456
|
58457
|
58458
|
60155
|
60156
|
60157
|
60218
|
60219
|
60267
|
60268
|
60269
|
62727