From 4a69337fd7d5f692b5c115f5f4f003a863ac4514 Mon Sep 17 00:00:00 2001 From: Lari Taskula Date: Fri, 18 Nov 2016 13:09:12 +0200 Subject: [PATCH] Bug 17712: Add base for item and biblio availability This patch adds two new classes: - Koha::Biblio::Availability - Koha::Item::Availability These classes represent biblio- and item-level availabilities and the purpose of this patch is simply to provide constructors that validate given biblio/item and patron parameters. Hold / checkout / search view availabilities (the actual answers to availability) will be provided in the next patches. To test: 1. Run t/db_dependent/Koha/Item/Availability.t 2. Run t/db_dependent/Koha/Biblio/Availability.t --- Koha/Biblio/Availability.pm | 132 +++++++++++++++++++++++++ Koha/Item/Availability.pm | 126 +++++++++++++++++++++++ t/db_dependent/Koha/Biblio/Availability.t | 159 ++++++++++++++++++++++++++++++ t/db_dependent/Koha/Item/Availability.t | 159 ++++++++++++++++++++++++++++++ 4 files changed, 576 insertions(+) create mode 100644 Koha/Biblio/Availability.pm create mode 100644 Koha/Item/Availability.pm create mode 100644 t/db_dependent/Koha/Biblio/Availability.t create mode 100644 t/db_dependent/Koha/Item/Availability.t diff --git a/Koha/Biblio/Availability.pm b/Koha/Biblio/Availability.pm new file mode 100644 index 0000000..654457b --- /dev/null +++ b/Koha/Biblio/Availability.pm @@ -0,0 +1,132 @@ +package Koha::Biblio::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 Scalar::Util qw(looks_like_number); + +use base qw(Koha::Availability); + +use Koha::Exceptions; +use Koha::Exceptions::Biblio; +use Koha::Exceptions::Patron; + +=head1 NAME + +Koha::Biblio::Availability - Koha Biblio Availability object class + +=head1 SYNOPSIS + +Parent class for different types of biblio availabilities. + +=head1 DESCRIPTION + +=head2 Class Methods + +This class is for storing biblio availability information. It is a subclass of +Koha::Availability. For more documentation on usage, see Koha::Availability. + +=cut + +=head3 new + +my $availability = Koha::Biblio::Availability->new({ + biblionumber => 123 +}); + +REQUIRED PARAMETERS: + biblio (Koha::Biblio) / biblionumber + +OPTIONAL PARAMETERS: + patron (Koha::Patron) / borrowernumber + +Creates a new Koha::Biblio::Availability object. + +=cut + +sub new { + my $class = shift; + my ($params) = @_; + my $self = $class->SUPER::new(@_); + + $self->{'biblio'} = undef; + $self->{'patron'} = undef; + + # ARRAYref of Koha::Item::Availability objects + # ...for available items + $self->{'item_availabilities'} = []; + # ...for unavailabile items + $self->{'item_unavailabilities'} = []; + + if (exists $params->{'biblio'}) { + unless (ref($params->{'biblio'}) eq 'Koha::Biblio') { + Koha::Exceptions::BadParameter->throw( + error => 'Parameter must be a Koha::Biblio object.', + parameter => 'biblio', + ); + } + $self->biblio($params->{'biblio'}); + } elsif (exists $params->{'biblionumber'}) { + unless (looks_like_number($params->{'biblionumber'})) { + Koha::Exceptions::BadParameter->throw( + error => 'Parameter must be a numeric value.', + parameter => 'biblionumber', + ); + } + $self->biblio(Koha::Biblios->find($params->{'biblionumber'})); + unless ($self->biblio) { + Koha::Exceptions::Biblio::NotFound->throw( + error => 'Biblio not found.', + biblionumber => $params->{'biblionumber'}, + ); + } + } else { + Koha::Exceptions::MissingParameter->throw( + error => "Missing one of parameters 'biblionumber, 'biblio'.", + parameter => ["biblionumber", "biblio"], + ); + } + + if (exists $params->{'patron'}) { + unless (ref($params->{'patron'}) eq 'Koha::Patron') { + Koha::Exceptions::BadParameter->throw( + error => 'Parameter must be a Koha::Patron object.', + parameter => 'patron', + ); + } + $self->patron($params->{'patron'}); + } elsif (exists $params->{'borrowernumber'}) { + unless (looks_like_number($params->{'borrowernumber'})) { + Koha::Exceptions::BadParameter->throw( + error => 'Parameter must be a numeric value.', + parameter => 'borrowernumber', + ); + } + $self->patron(Koha::Patrons->find($params->{'borrowernumber'})); + unless ($self->patron) { + Koha::Exceptions::Patron::NotFound->throw( + error => 'Patron not found.', + borrowernumber => $params->{'borrowernumber'}, + ); + } + } + + return $self; +} + +1; diff --git a/Koha/Item/Availability.pm b/Koha/Item/Availability.pm new file mode 100644 index 0000000..c26d79b --- /dev/null +++ b/Koha/Item/Availability.pm @@ -0,0 +1,126 @@ +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 Scalar::Util qw(looks_like_number); + +use base qw(Koha::Availability); + +use Koha::Exceptions; +use Koha::Exceptions::Item; +use Koha::Exceptions::Patron; + +=head1 NAME + +Koha::Item::Availability - Koha Item Availability object class + +=head1 SYNOPSIS + +Parent class for different types of item availabilities. + +=head1 DESCRIPTION + +=head2 Class Methods + +This class is for storing item availability information. It is a subclass of +Koha::Availability. For more documentation on usage, see Koha::Availability. + +=cut + +=head3 new + +my $availability = Koha::Item::Availability->new({ + itemnumber => 123 +}); + +REQUIRED PARAMETERS: + item (Koha::Item) / itemnumber + +OPTIONAL PARAMETERS: + patron (Koha::Patron) / borrowernumber + +Creates a new Koha::Item::Availability object. + +=cut + +sub new { + my $class = shift; + my ($params) = @_; + my $self = $class->SUPER::new(@_); + + $self->{'item'} = undef; + $self->{'patron'} = undef; + + if (exists $params->{'item'}) { + unless (ref($params->{'item'}) eq 'Koha::Item') { + Koha::Exceptions::BadParameter->throw( + error => 'Parameter must be a Koha::Item object.', + parameter => 'item', + ); + } + $self->item($params->{'item'}); + } elsif (exists $params->{'itemnumber'}) { + unless (looks_like_number($params->{'itemnumber'})) { + Koha::Exceptions::BadParameter->throw( + error => 'Parameter must be a numeric value.', + parameter => 'itemnumber', + ); + } + $self->item(Koha::Items->find($params->{'itemnumber'})); + unless ($self->item) { + Koha::Exceptions::Item::NotFound->throw( + error => 'Item not found.', + itemnumber => $params->{'itemnumber'}, + ); + } + } else { + Koha::Exceptions::MissingParameter->throw( + error => "Missing one of parameters 'itemnumber, 'item'.", + parameter => ["itemnumber", "item"], + ); + } + + if (exists $params->{'patron'}) { + unless (ref($params->{'patron'}) eq 'Koha::Patron') { + Koha::Exceptions::BadParameter->throw( + error => 'Parameter must be a Koha::Patron object.', + parameter => 'patron', + ); + } + $self->patron($params->{'patron'}); + } elsif (exists $params->{'borrowernumber'}) { + unless (looks_like_number($params->{'borrowernumber'})) { + Koha::Exceptions::BadParameter->throw( + error => 'Parameter must be a numeric value.', + parameter => 'borrowernumber', + ); + } + $self->patron(Koha::Patrons->find($params->{'borrowernumber'})); + unless ($self->patron) { + Koha::Exceptions::Patron::NotFound->throw( + error => 'Patron not found.', + borrowernumber => $params->{'borrowernumber'}, + ); + } + } + + return $self; +} + +1; diff --git a/t/db_dependent/Koha/Biblio/Availability.t b/t/db_dependent/Koha/Biblio/Availability.t new file mode 100644 index 0000000..9e4c412 --- /dev/null +++ b/t/db_dependent/Koha/Biblio/Availability.t @@ -0,0 +1,159 @@ +#!/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 . + +use Modern::Perl; +use Test::More tests => 14; +use t::lib::TestBuilder; + +use Koha::Database; +use Koha::Biblios; + +use Koha::Exceptions; + +use_ok('Koha::Biblio::Availability'); + +my $schema = Koha::Database->new->schema; +$schema->storage->txn_begin; + +my $builder = t::lib::TestBuilder->new; +my $biblio = Koha::Biblios->find($builder->build({source => 'Biblio'})->{'biblionumber'}); +my $patron = Koha::Patrons->find($builder->build({source => 'Borrower'})->{'borrowernumber'}); + +subtest 'Check Koha::Biblio::Availability -object default values' => \&check_default_values; + +subtest 'Attempt to instantiate holdability class with valid biblio' => sub { + plan tests => 1; + + my $availability = Koha::Biblio::Availability->new({ biblio => $biblio }); + ok($availability->available, 'When I instantiate class with a valid biblio, then it is available.'); +}; + +subtest 'Attempt to instantiate holdability class with valid biblionumber' => sub { + plan tests => 1; + + my $availability = Koha::Biblio::Availability->new({ biblionumber => $biblio->biblionumber }); + ok($availability->available, 'When I instantiate class with a valid biblionumber, then it is available.'); +}; + +subtest 'Attempt to instantiate holdability class without specifying an biblio' => sub { + plan tests => 2; + + my $availability = eval{Koha::Biblio::Availability->new}; + ok($@, 'When I instantiate class without giving an biblio,' + .' an exception is thrown.'); + is(ref($@), 'Koha::Exceptions::MissingParameter', + 'Then I see that Koha::Exceptions::MissingParameter is thrown.'); +}; + +subtest 'Attempt to instantiate holdability class with notfound biblionumber' => sub { + plan tests => 2; + + my $availability = eval{Koha::Biblio::Availability->new({ biblionumber => -9001 })}; + ok($@, 'When I instantiate class with valid biblionumber that does not' + .' refer to any stored biblio, an exception is thrown.'); + is(ref($@), 'Koha::Exceptions::Biblio::NotFound', + 'Then I see that Koha::Exceptions::Biblio::NotFound is thrown.'); +}; + +subtest 'Attempt to instantiate holdability class with invalid biblionumber' => sub { + plan tests => 2; + + my $availability = eval{Koha::Biblio::Availability->new({ biblionumber => 'lol' })}; + ok($@, 'When I instantiate class with invalid biblionumber that is not' + .' a number, an exception is thrown.'); + is(ref($@), 'Koha::Exceptions::BadParameter', + 'Then I see that Koha::Exceptions::BadParameter is thrown.'); +}; + +subtest 'Attempt to instantiate holdability class with invalid biblio' => sub { + plan tests => 2; + + my $availability = eval{Koha::Biblio::Availability->new({ biblio => {'nonsense'=>'yeah'} })}; + ok($@, 'When I instantiate class with invalid biblio,' + .' an exception is thrown.'); + is(ref($@), 'Koha::Exceptions::BadParameter', + 'Then I see that Koha::Exceptions::BadParameter is thrown.'); +}; + +subtest 'Attempt to instantiate holdability class with valid patron' => sub { + plan tests => 1; + + my $availability = Koha::Biblio::Availability->new({ biblio => $biblio, patron => $patron }); + ok($availability->available, 'When I instantiate class with a valid patron, then it is available.'); +}; + +subtest 'Attempt to instantiate holdability class with valid borrowernumber' => sub { + plan tests => 1; + + my $availability = Koha::Biblio::Availability->new({ biblio => $biblio, borrowernumber => $patron->borrowernumber }); + ok($availability->available, 'When I instantiate class with a valid borrowernumber, then it is available.'); +}; + +subtest 'Attempt to instantiate holdability class without specifying a patron' => sub { + plan tests => 2; + + my $availability = eval{Koha::Biblio::Availability->new({ biblio => $biblio })}; + is($availability->available, 1, 'When I request availability without specifying patron,' + .' then the biblio is available.'); + is(ref($@), '', 'Then holdability can be checked without giving a patron.'); +}; + +subtest 'Attempt to instantiate holdability class with notfound borrowernumber' => sub { + plan tests => 2; + + my $availability = eval{Koha::Biblio::Availability->new({ biblio => $biblio, borrowernumber => -9001 })}; + ok($@, 'When I instantiate class with valid borrowernumber that does not' + .' refer to any stored biblio, an exception is thrown.'); + is(ref($@), 'Koha::Exceptions::Patron::NotFound', + 'Then I see that Koha::Exceptions::Patron::NotFound is thrown.'); +}; + +subtest 'Attempt to instantiate holdability class with invalid borrowernumber' => sub { + plan tests => 2; + + my $availability = eval{Koha::Biblio::Availability->new({ biblio => $biblio, borrowernumber => 'lol' })}; + ok($@, 'When I instantiate class with invalid borrowernumber that is not' + .' a number, an exception is thrown.'); + is(ref($@), 'Koha::Exceptions::BadParameter', + 'Then I see that Koha::Exceptions::BadParameter is thrown.'); +}; + +subtest 'Attempt to instantiate holdability class with invalid patron' => sub { + plan tests => 1; + + my $availability = eval{Koha::Biblio::Availability->new({ biblio => $biblio, patron => $biblio })}; + is(ref($@), 'Koha::Exceptions::BadParameter', 'Patron not found'); +}; + +$schema->storage->txn_rollback; + +sub check_default_values { + plan tests => 7; + + my $availability = Koha::Biblio::Availability->new({ biblio => $biblio}); + is($availability->available, 1, 'Koha::Biblio::Availability -object is available.'); + is(keys %{$availability->unavailabilities}, 0, 'There are no unavailabilities.'); + is(keys %{$availability->confirmations}, 0, 'Nothing needs to be confirmed.'); + is(keys %{$availability->notes}, 0, 'There are no additional notes.'); + is(ref($availability->biblio), 'Koha::Biblio', 'This availability is related to an biblio.'); + is($availability->patron, undef, 'This availability is not related to any patron.'); + is($availability->expected_available, undef, 'There is no expectation of future availability'); +} + +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..a07a487 --- /dev/null +++ b/t/db_dependent/Koha/Item/Availability.t @@ -0,0 +1,159 @@ +#!/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 . + +use Modern::Perl; +use Test::More tests => 14; +use t::lib::TestBuilder; + +use Koha::Database; +use Koha::Items; + +use Koha::Exceptions; + +use_ok('Koha::Item::Availability'); + +my $schema = Koha::Database->new->schema; +$schema->storage->txn_begin; + +my $builder = t::lib::TestBuilder->new; +my $item = Koha::Items->find($builder->build({source => 'Item'})->{'itemnumber'}); +my $patron = Koha::Patrons->find($builder->build({source => 'Borrower'})->{'borrowernumber'}); + +subtest 'Check Koha::Item::Availability -object default values' => \&check_default_values; + +subtest 'Attempt to instantiate holdability class with valid item' => sub { + plan tests => 1; + + my $availability = Koha::Item::Availability->new({ item => $item }); + ok($availability->available, 'When I instantiate class with a valid item, then it is available.'); +}; + +subtest 'Attempt to instantiate holdability class with valid itemnumber' => sub { + plan tests => 1; + + my $availability = Koha::Item::Availability->new({ itemnumber => $item->itemnumber }); + ok($availability->available, 'When I instantiate class with a valid itemnumber, then it is available.'); +}; + +subtest 'Attempt to instantiate holdability class without specifying an item' => sub { + plan tests => 2; + + my $availability = eval{Koha::Item::Availability->new}; + ok($@, 'When I instantiate class without giving an item,' + .' an exception is thrown.'); + is(ref($@), 'Koha::Exceptions::MissingParameter', + 'Then I see that Koha::Exceptions::MissingParameter is thrown.'); +}; + +subtest 'Attempt to instantiate holdability class with notfound itemnumber' => sub { + plan tests => 2; + + my $availability = eval{Koha::Item::Availability->new({ itemnumber => -9001 })}; + ok($@, 'When I instantiate class with valid itemnumber that does not' + .' refer to any stored item, an exception is thrown.'); + is(ref($@), 'Koha::Exceptions::Item::NotFound', + 'Then I see that Koha::Exceptions::Item::NotFound is thrown.'); +}; + +subtest 'Attempt to instantiate holdability class with invalid itemnumber' => sub { + plan tests => 2; + + my $availability = eval{Koha::Item::Availability->new({ itemnumber => 'lol' })}; + ok($@, 'When I instantiate class with invalid itemnumber that is not' + .' a number, an exception is thrown.'); + is(ref($@), 'Koha::Exceptions::BadParameter', + 'Then I see that Koha::Exceptions::BadParameter is thrown.'); +}; + +subtest 'Attempt to instantiate holdability class with invalid item' => sub { + plan tests => 2; + + my $availability = eval{Koha::Item::Availability->new({ item => {'nonsense'=>'yeah'} })}; + ok($@, 'When I instantiate class with invalid item,' + .' an exception is thrown.'); + is(ref($@), 'Koha::Exceptions::BadParameter', + 'Then I see that Koha::Exceptions::BadParameter is thrown.'); +}; + +subtest 'Attempt to instantiate holdability class with valid patron' => sub { + plan tests => 1; + + my $availability = Koha::Item::Availability->new({ item => $item, patron => $patron }); + ok($availability->available, 'When I instantiate class with a valid patron, then it is available.'); +}; + +subtest 'Attempt to instantiate holdability class with valid borrowernumber' => sub { + plan tests => 1; + + my $availability = Koha::Item::Availability->new({ item => $item, borrowernumber => $patron->borrowernumber }); + ok($availability->available, 'When I instantiate class with a valid borrowernumber, then it is available.'); +}; + +subtest 'Attempt to instantiate holdability class without specifying a patron' => sub { + plan tests => 2; + + my $availability = eval{Koha::Item::Availability->new({ item => $item })}; + is($availability->available, 1, 'When I request availability without specifying patron,' + .' then the item is available.'); + is(ref($@), '', 'Then holdability can be checked without giving a patron.'); +}; + +subtest 'Attempt to instantiate holdability class with notfound borrowernumber' => sub { + plan tests => 2; + + my $availability = eval{Koha::Item::Availability->new({ item => $item, borrowernumber => -9001 })}; + ok($@, 'When I instantiate class with valid borrowernumber that does not' + .' refer to any stored item, an exception is thrown.'); + is(ref($@), 'Koha::Exceptions::Patron::NotFound', + 'Then I see that Koha::Exceptions::Patron::NotFound is thrown.'); +}; + +subtest 'Attempt to instantiate holdability class with invalid borrowernumber' => sub { + plan tests => 2; + + my $availability = eval{Koha::Item::Availability->new({ item => $item, borrowernumber => 'lol' })}; + ok($@, 'When I instantiate class with invalid borrowernumber that is not' + .' a number, an exception is thrown.'); + is(ref($@), 'Koha::Exceptions::BadParameter', + 'Then I see that Koha::Exceptions::BadParameter is thrown.'); +}; + +subtest 'Attempt to instantiate holdability class with invalid patron' => sub { + plan tests => 1; + + my $availability = eval{Koha::Item::Availability->new({ item => $item, patron => $item })}; + is(ref($@), 'Koha::Exceptions::BadParameter', 'Patron not found'); +}; + +$schema->storage->txn_rollback; + +sub check_default_values { + plan tests => 7; + + my $availability = Koha::Item::Availability->new({ item => $item}); + is($availability->available, 1, 'Koha::Item::Availability -object is available.'); + is(keys %{$availability->unavailabilities}, 0, 'There are no unavailabilities.'); + is(keys %{$availability->confirmations}, 0, 'Nothing needs to be confirmed.'); + is(keys %{$availability->notes}, 0, 'There are no additional notes.'); + is(ref($availability->item), 'Koha::Item', 'This availability is related to an item.'); + is($availability->patron, undef, 'This availability is not related to any patron.'); + is($availability->expected_available, undef, 'There is no expectation of future availability'); +} + +1; -- 1.9.1