Bug 7317: Interlibrary loans framework for Koha.
This Commit is at the heart of adding an interlibrary loans framework for Koha. The framework does not prescribe a particular workflow. Instead it provides a general framework that can be extended & implemented by individual backends whose responsibility it is to implement a specific workflow. The module is largely self-sufficient: it adds new tables to the Koha database and touches only a few files in the Koha source tree. Primarily, we add our files to the Makefile and the koha-conf.xml, define ill paths for the REST API, and introduce links from the main intranet, opac pages & user permissions. Outside of this we simply add new files & functionality. Signed-off-by: Magnus Enger <magnus@libriotech.no> Signed-off-by: Tomas Cohen Arazi <tomascohen@theke.io> Signed-off-by: Benjamin Rokseth <benjamin.rokseth@kul.oslo.kommune.no> Signed-off-by: Jonathan Druart <jonathan.druart@bugs.koha-community.org>
This commit is contained in:
parent
4a1ff8534a
commit
8e86b5e093
|
|
@ -0,0 +1,935 @@
|
|||
package Koha::Illrequest;
|
||||
|
||||
# Copyright PTFS Europe 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 Clone 'clone';
|
||||
use File::Basename qw/basename/;
|
||||
use Koha::Database;
|
||||
use Koha::Email;
|
||||
use Koha::Illrequest;
|
||||
use Koha::Illrequestattributes;
|
||||
use Koha::Patron;
|
||||
use Mail::Sendmail;
|
||||
use Try::Tiny;
|
||||
|
||||
use base qw(Koha::Object);
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Koha::Illrequest - Koha Illrequest Object class
|
||||
|
||||
=head1 (Re)Design
|
||||
|
||||
An ILLRequest consists of two parts; the Illrequest Koha::Object, and a series
|
||||
of related Illrequestattributes.
|
||||
|
||||
The former encapsulates the basic necessary information that any ILL requires
|
||||
to be usable in Koha. The latter is a set of additional properties used by
|
||||
one of the backends.
|
||||
|
||||
The former subsumes the legacy "Status" object. The latter remains
|
||||
encapsulated in the "Record" object.
|
||||
|
||||
TODO:
|
||||
|
||||
- Anything invoking the ->status method; annotated with:
|
||||
+ # Old use of ->status !
|
||||
|
||||
=head1 API
|
||||
|
||||
=head2 Backend API Response Principles
|
||||
|
||||
All methods should return a hashref in the following format:
|
||||
|
||||
=item * error
|
||||
|
||||
This should be set to 1 if an error was encountered.
|
||||
|
||||
=item * status
|
||||
|
||||
The status should be a string from the list of statuses detailed below.
|
||||
|
||||
=item * message
|
||||
|
||||
The message is a free text field that can be passed on to the end user.
|
||||
|
||||
=item * value
|
||||
|
||||
The value returned by the method.
|
||||
|
||||
=over
|
||||
|
||||
=head2 Interface Status Messages
|
||||
|
||||
=over
|
||||
|
||||
=item * branch_address_incomplete
|
||||
|
||||
An interface request has determined branch address details are incomplete.
|
||||
|
||||
=item * cancel_success
|
||||
|
||||
The interface's cancel_request method was successful in cancelling the
|
||||
Illrequest using the API.
|
||||
|
||||
=item * cancel_fail
|
||||
|
||||
The interface's cancel_request method failed to cancel the Illrequest using
|
||||
the API.
|
||||
|
||||
=item * unavailable
|
||||
|
||||
The interface's request method returned saying that the desired item is not
|
||||
available for request.
|
||||
|
||||
=head2 Class Methods
|
||||
|
||||
=cut
|
||||
|
||||
=head3 type
|
||||
|
||||
=cut
|
||||
|
||||
sub _type {
|
||||
return 'Illrequest';
|
||||
}
|
||||
|
||||
sub illrequestattributes {
|
||||
my ( $self ) = @_;
|
||||
return Koha::Illrequestattributes->_new_from_dbic(
|
||||
scalar $self->_result->illrequestattributes
|
||||
);
|
||||
}
|
||||
|
||||
sub patron {
|
||||
my ( $self ) = @_;
|
||||
return Koha::Patron->_new_from_dbic(
|
||||
scalar $self->_result->borrowernumber
|
||||
);
|
||||
}
|
||||
|
||||
sub load_backend {
|
||||
my ( $self, $backend_id ) = @_;
|
||||
|
||||
my @raw = qw/Koha Illbackends/; # Base Path
|
||||
|
||||
my $backend_name = $backend_id || $self->backend;
|
||||
$location = join "/", @raw, $backend_name, "Base.pm"; # File to load
|
||||
$backend_class = join "::", @raw, $backend_name, "Base"; # Package name
|
||||
require $location;
|
||||
$self->{_my_backend} = $backend_class->new({ config => $self->_config });
|
||||
return $self;
|
||||
}
|
||||
|
||||
=head3 _backend
|
||||
|
||||
my $backend = $abstract->_backend($new_backend);
|
||||
my $backend = $abstract->_backend;
|
||||
|
||||
Getter/Setter for our API object.
|
||||
|
||||
=cut
|
||||
|
||||
sub _backend {
|
||||
my ( $self, $backend ) = @_;
|
||||
$self->{_my_backend} = $backend if ( $backend );
|
||||
# Dynamically load our backend object, as late as possible.
|
||||
$self->load_backend unless ( $self->{_my_backend} );
|
||||
return $self->{_my_backend};
|
||||
}
|
||||
|
||||
=head3 _backend_capability
|
||||
|
||||
my $backend_capability_result = $self->_backend_capability($name, $args);
|
||||
|
||||
This is a helper method to invoke optional capabilities in the backend. If
|
||||
the capability named by $name is not supported, return 0, else invoke it,
|
||||
passing $args along with the invocation, and return its return value.
|
||||
|
||||
NOTE: this module suffers from a confusion in termninology:
|
||||
|
||||
in _backend_capability, the notion of capability refers to an optional feature
|
||||
that is implemented in core, but might not be supported by a given backend.
|
||||
|
||||
in capabilities & custom_capability, capability refers to entries in the
|
||||
status_graph (after union between backend and core).
|
||||
|
||||
The easiest way to fix this would be to fix the terminology in
|
||||
capabilities & custom_capability and their callers.
|
||||
|
||||
=cut
|
||||
|
||||
sub _backend_capability {
|
||||
my ( $self, $name, $args ) = @_;
|
||||
my $capability = 0;
|
||||
try {
|
||||
$capability = $self->_backend->capabilities($name);
|
||||
} catch {
|
||||
return 0;
|
||||
};
|
||||
if ( $capability ) {
|
||||
return &{$capability}($args);
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
=head3 _config
|
||||
|
||||
my $config = $abstract->_config($config);
|
||||
my $config = $abstract->_config;
|
||||
|
||||
Getter/Setter for our config object.
|
||||
|
||||
=cut
|
||||
|
||||
sub _config {
|
||||
my ( $self, $config ) = @_;
|
||||
$self->{_my_config} = $config if ( $config );
|
||||
# Load our config object, as late as possible.
|
||||
unless ( $self->{_my_config} ) {
|
||||
$self->{_my_config} = Koha::Illrequest::Config->new;
|
||||
}
|
||||
return $self->{_my_config};
|
||||
}
|
||||
|
||||
=head3 metadata
|
||||
|
||||
=cut
|
||||
|
||||
sub metadata {
|
||||
my ( $self ) = @_;
|
||||
return $self->_backend->metadata($self);
|
||||
}
|
||||
|
||||
=head3 _core_status_graph
|
||||
|
||||
my $core_status_graph = $illrequest->_core_status_graph;
|
||||
|
||||
Returns ILL module's default status graph. A status graph defines the list of
|
||||
available actions at any stage in the ILL workflow. This is for instance used
|
||||
by the perl script & template to generate the correct buttons to display to
|
||||
the end user at any given point.
|
||||
|
||||
=cut
|
||||
|
||||
sub _core_status_graph {
|
||||
my ( $self ) = @_;
|
||||
return {
|
||||
NEW => {
|
||||
prev_actions => [ ], # Actions containing buttons
|
||||
# leading to this status
|
||||
id => 'NEW', # ID of this status
|
||||
name => 'New request', # UI name of this status
|
||||
ui_method_name => 'New request', # UI name of method leading
|
||||
# to this status
|
||||
method => 'create', # method to this status
|
||||
next_actions => [ 'REQ', 'GENREQ', 'KILL' ], # buttons to add to all
|
||||
# requests with this status
|
||||
ui_method_icon => 'fa-plus', # UI Style class
|
||||
},
|
||||
REQ => {
|
||||
prev_actions => [ 'NEW', 'REQREV', 'QUEUED', 'CANCREQ' ],
|
||||
id => 'REQ',
|
||||
name => 'Requested',
|
||||
ui_method_name => 'Confirm request',
|
||||
method => 'confirm',
|
||||
next_actions => [ 'REQREV', 'COMP' ],
|
||||
ui_method_icon => 'fa-check',
|
||||
},
|
||||
GENREQ => {
|
||||
prev_actions => [ 'NEW', 'REQREV' ],
|
||||
id => 'GENREQ',
|
||||
name => 'Requested from partners',
|
||||
ui_method_name => 'Place request with partners',
|
||||
method => 'generic_confirm',
|
||||
next_actions => [ 'COMP' ],
|
||||
ui_method_icon => 'fa-send-o',
|
||||
},
|
||||
REQREV => {
|
||||
prev_actions => [ 'REQ' ],
|
||||
id => 'REQREV',
|
||||
name => 'Request reverted',
|
||||
ui_method_name => 'Revert Request',
|
||||
method => 'cancel',
|
||||
next_actions => [ 'REQ', 'GENREQ', 'KILL' ],
|
||||
ui_method_icon => 'fa-times',
|
||||
},
|
||||
QUEUED => {
|
||||
prev_actions => [ ],
|
||||
id => 'QUEUED',
|
||||
name => 'Queued request',
|
||||
ui_method_name => 0,
|
||||
method => 0,
|
||||
next_actions => [ 'REQ', 'KILL' ],
|
||||
ui_method_icon => 0,
|
||||
},
|
||||
CANCREQ => {
|
||||
prev_actions => [ 'NEW' ],
|
||||
id => 'CANCREQ',
|
||||
name => 'Cancellation requested',
|
||||
ui_method_name => 0,
|
||||
method => 0,
|
||||
next_actions => [ 'KILL', 'REQ' ],
|
||||
ui_method_icon => 0,
|
||||
},
|
||||
COMP => {
|
||||
prev_actions => [ 'REQ' ],
|
||||
id => 'COMP',
|
||||
name => 'Completed',
|
||||
ui_method_name => 'Mark completed',
|
||||
method => 'mark_completed',
|
||||
next_actions => [ ],
|
||||
ui_method_icon => 'fa-check',
|
||||
},
|
||||
KILL => {
|
||||
prev_actions => [ 'QUEUED', 'REQREV', 'NEW', 'CANCREQ' ],
|
||||
id => 'KILL',
|
||||
name => 0,
|
||||
ui_method_name => 'Delete request',
|
||||
method => 'delete',
|
||||
next_actions => [ ],
|
||||
ui_method_icon => 'fa-trash',
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
=head3 _core_status_graph
|
||||
|
||||
my $status_graph = $illrequest->_core_status_graph($origin, $new_graph);
|
||||
|
||||
Return a new status_graph, the result of merging $origin & new_graph. This is
|
||||
operation is a union over the sets defied by the two graphs.
|
||||
|
||||
Each entry in $new_graph is added to $origin. We do not provide a syntax for
|
||||
'subtraction' of entries from $origin.
|
||||
|
||||
Whilst it is not intended that this works, you can override entries in $origin
|
||||
with entries with the same key in $new_graph. This can lead to problematic
|
||||
behaviour when $new_graph adds an entry, which modifies a dependent entry in
|
||||
$origin, only for the entry in $origin to be replaced later with a new entry
|
||||
from $new_graph.
|
||||
|
||||
NOTE: this procedure does not "re-link" entries in $origin or $new_graph,
|
||||
i.e. each of the graphs need to be correct at the outset of the operation.
|
||||
|
||||
=cut
|
||||
|
||||
sub _status_graph_union {
|
||||
my ( $self, $core_status_graph, $backend_status_graph ) = @_;
|
||||
# Create new status graph with:
|
||||
# - all core_status_graph
|
||||
# - for-each each backend_status_graph
|
||||
# + add to new status graph
|
||||
# + for each core prev_action:
|
||||
# * locate core_status
|
||||
# * update next_actions with additional next action.
|
||||
# + for each core next_action:
|
||||
# * locate core_status
|
||||
# * update prev_actions with additional prev action
|
||||
|
||||
my @core_status_ids = keys %{$core_status_graph};
|
||||
my $status_graph = clone($core_status_graph);
|
||||
|
||||
foreach my $backend_status_key ( keys %{$backend_status_graph} ) {
|
||||
$backend_status = $backend_status_graph->{$backend_status_key};
|
||||
# Add to new status graph
|
||||
$status_graph->{$backend_status_key} = $backend_status;
|
||||
# Update all core methods' next_actions.
|
||||
foreach my $prev_action ( @{$backend_status->{prev_actions}} ) {
|
||||
if ( grep $prev_action, @core_status_ids ) {
|
||||
my @next_actions =
|
||||
@{$status_graph->{$prev_action}->{next_actions}};
|
||||
push @next_actions, $backend_status_key;
|
||||
$status_graph->{$prev_action}->{next_actions}
|
||||
= \@next_actions;
|
||||
}
|
||||
}
|
||||
# Update all core methods' prev_actions
|
||||
foreach my $next_action ( @{$backend_status->{next_actions}} ) {
|
||||
if ( grep $next_action, @core_status_ids ) {
|
||||
my @prev_actions =
|
||||
@{$status_graph->{$next_action}->{prev_actions}};
|
||||
push @prev_actions, $backend_status_key;
|
||||
$status_graph->{$next_action}->{prev_actions}
|
||||
= \@prev_actions;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $status_graph;
|
||||
}
|
||||
|
||||
### Core API methods
|
||||
|
||||
=head3 capabilities
|
||||
|
||||
my $capabilities = $illrequest->capabilities;
|
||||
|
||||
Return a hashref mapping methods to operation names supported by the queried
|
||||
backend.
|
||||
|
||||
Example return value:
|
||||
|
||||
{ create => "Create Request", confirm => "Progress Request" }
|
||||
|
||||
NOTE: this module suffers from a confusion in termninology:
|
||||
|
||||
in _backend_capability, the notion of capability refers to an optional feature
|
||||
that is implemented in core, but might not be supported by a given backend.
|
||||
|
||||
in capabilities & custom_capability, capability refers to entries in the
|
||||
status_graph (after union between backend and core).
|
||||
|
||||
The easiest way to fix this would be to fix the terminology in
|
||||
capabilities & custom_capability and their callers.
|
||||
|
||||
=cut
|
||||
|
||||
sub capabilities {
|
||||
my ( $self, $status ) = @_;
|
||||
# Generate up to date status_graph
|
||||
my $status_graph = $self->_status_graph_union(
|
||||
$self->_core_status_graph,
|
||||
$self->_backend->status_graph({
|
||||
request => $self,
|
||||
other => {}
|
||||
})
|
||||
);
|
||||
# Extract available actions from graph.
|
||||
return $status_graph->{$status} if $status;
|
||||
# Or return entire graph.
|
||||
return $status_graph;
|
||||
}
|
||||
|
||||
=head3 custom_capability
|
||||
|
||||
Return the result of invoking $CANDIDATE on this request's backend with
|
||||
$PARAMS, or 0 if $CANDIDATE is an unknown method on backend.
|
||||
|
||||
NOTE: this module suffers from a confusion in termninology:
|
||||
|
||||
in _backend_capability, the notion of capability refers to an optional feature
|
||||
that is implemented in core, but might not be supported by a given backend.
|
||||
|
||||
in capabilities & custom_capability, capability refers to entries in the
|
||||
status_graph (after union between backend and core).
|
||||
|
||||
The easiest way to fix this would be to fix the terminology in
|
||||
capabilities & custom_capability and their callers.
|
||||
|
||||
=cut
|
||||
|
||||
sub custom_capability {
|
||||
my ( $self, $candidate, $params ) = @_;
|
||||
foreach my $capability ( values %{$self->capabilities} ) {
|
||||
if ( $candidate eq $capability->{method} ) {
|
||||
my $response =
|
||||
$self->_backend->$candidate({
|
||||
request => $self,
|
||||
other => $params,
|
||||
});
|
||||
return $self->expandTemplate($response);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
sub available_backends {
|
||||
my ( $self ) = @_;
|
||||
my $backend_dir = $self->_config->backend_dir;
|
||||
my @backends = ();
|
||||
@backends = <$backend_dir/*> if ( $backend_dir );
|
||||
@backends = map { basename($_) } @backends;
|
||||
return \@backends;
|
||||
}
|
||||
|
||||
sub available_actions {
|
||||
my ( $self ) = @_;
|
||||
my $current_action = $self->capabilities($self->status);
|
||||
my @available_actions = map { $self->capabilities($_) }
|
||||
@{$current_action->{next_actions}};
|
||||
return \@available_actions;
|
||||
}
|
||||
|
||||
sub mark_completed {
|
||||
my ( $self ) = @_;
|
||||
$self->status('COMP')->store;
|
||||
return {
|
||||
error => 0,
|
||||
status => '',
|
||||
message => '',
|
||||
method => 'mark_completed',
|
||||
stage => 'commit',
|
||||
next => 'illview',
|
||||
};
|
||||
}
|
||||
|
||||
sub backend_confirm {
|
||||
my ( $self, $params ) = @_;
|
||||
|
||||
# The backend handles setting of mandatory fields in the commit stage:
|
||||
# - orderid
|
||||
# - accessurl, cost (if available).
|
||||
my $response = $self->_backend->confirm({
|
||||
request => $self,
|
||||
other => $params,
|
||||
});
|
||||
return $self->expandTemplate($response);
|
||||
}
|
||||
|
||||
sub backend_update_status {
|
||||
my ( $self, $params ) = @_;
|
||||
return $self->expandTemplate($self->_backend->update_status($params));
|
||||
}
|
||||
|
||||
=head3 backend_cancel
|
||||
|
||||
my $ILLResponse = $illRequest->backend_cancel;
|
||||
|
||||
The standard interface method allowing for request cancellation.
|
||||
|
||||
=cut
|
||||
|
||||
sub backend_cancel {
|
||||
my ( $self, $params ) = @_;
|
||||
|
||||
my $result = $self->_backend->cancel({
|
||||
request => $self,
|
||||
other => $params
|
||||
});
|
||||
|
||||
return $self->expandTemplate($result);
|
||||
}
|
||||
|
||||
=head3 backend_renew
|
||||
|
||||
my $renew_response = $illRequest->backend_renew;
|
||||
|
||||
The standard interface method allowing for request renewal queries.
|
||||
|
||||
=cut
|
||||
|
||||
sub backend_renew {
|
||||
my ( $self ) = @_;
|
||||
return $self->expandTemplate(
|
||||
$self->_backend->renew({
|
||||
request => $self,
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
=head3 backend_create
|
||||
|
||||
my $create_response = $abstractILL->backend_create($params);
|
||||
|
||||
Return an array of Record objects created by querying our backend with
|
||||
a Search query.
|
||||
|
||||
In the context of the other ILL methods, this is a special method: we only
|
||||
pass it $params, as it does not yet have any other data associated with it.
|
||||
|
||||
=cut
|
||||
|
||||
sub backend_create {
|
||||
my ( $self, $params ) = @_;
|
||||
|
||||
# Establish whether we need to do a generic copyright clearance.
|
||||
if ( ( !$params->{stage} || $params->{stage} eq 'init' )
|
||||
&& C4::Context->preference("ILLModuleCopyrightClearance") ) {
|
||||
return {
|
||||
error => 0,
|
||||
status => '',
|
||||
message => '',
|
||||
method => 'create',
|
||||
stage => 'copyrightclearance',
|
||||
value => {
|
||||
backend => $self->_backend->name
|
||||
}
|
||||
};
|
||||
} elsif ( $params->{stage} eq 'copyrightclearance' ) {
|
||||
$params->{stage} = 'init';
|
||||
}
|
||||
|
||||
# First perform API action, then...
|
||||
my $args = {
|
||||
request => $self,
|
||||
other => $params,
|
||||
};
|
||||
my $result = $self->_backend->create($args);
|
||||
|
||||
# ... simple case: we're not at 'commit' stage.
|
||||
my $stage = $result->{stage};
|
||||
return $self->expandTemplate($result)
|
||||
unless ( 'commit' eq $stage );
|
||||
|
||||
# ... complex case: commit!
|
||||
|
||||
# Do we still have space for an ILL or should we queue?
|
||||
my $permitted = $self->check_limits(
|
||||
{ patron => $self->patron }, { librarycode => $self->branchcode }
|
||||
);
|
||||
|
||||
# Now augment our committed request.
|
||||
|
||||
$result->{permitted} = $permitted; # Queue request?
|
||||
|
||||
# This involves...
|
||||
|
||||
# ...Updating status!
|
||||
$self->status('QUEUED')->store unless ( $permitted );
|
||||
|
||||
return $self->expandTemplate($result);
|
||||
}
|
||||
|
||||
=head3 expandTemplate
|
||||
|
||||
my $params = $abstract->expandTemplate($params);
|
||||
|
||||
Return a version of $PARAMS augmented with our required template path.
|
||||
|
||||
=cut
|
||||
|
||||
sub expandTemplate {
|
||||
my ( $self, $params ) = @_;
|
||||
my $backend = $self->_backend->name;
|
||||
# Generate path to file to load
|
||||
my $backend_dir = $self->_config->backend_dir;
|
||||
my $backend_tmpl = join "/", $backend_dir, $backend;
|
||||
my $intra_tmpl = join "/", $backend_tmpl, "intra-includes",
|
||||
$params->{method} . ".inc";
|
||||
my $opac_tmpl = join "/", $backend_tmpl, "opac-includes",
|
||||
$params->{method} . ".inc";
|
||||
# Set files to load
|
||||
$params->{template} = $intra_tmpl;
|
||||
$params->{opac_template} = $opac_tmpl;
|
||||
return $params;
|
||||
}
|
||||
|
||||
#### Abstract Imports
|
||||
|
||||
=head3 getLimits
|
||||
|
||||
my $limit_rules = $abstract->getLimits( {
|
||||
type => 'brw_cat' | 'branch',
|
||||
value => $value
|
||||
} );
|
||||
|
||||
Return the ILL limit rules for the supplied combination of type / value.
|
||||
|
||||
As the config may have no rules for this particular type / value combination,
|
||||
or for the default, we must define fall-back values here.
|
||||
|
||||
=cut
|
||||
|
||||
sub getLimits {
|
||||
my ( $self, $params ) = @_;
|
||||
my $limits = $self->_config->getLimitRules($params->{type});
|
||||
|
||||
return $limits->{$params->{value}}
|
||||
|| $limits->{default}
|
||||
|| { count => -1, method => 'active' };
|
||||
}
|
||||
|
||||
=head3 getPrefix
|
||||
|
||||
my $prefix = $abstract->getPrefix( {
|
||||
brw_cat => $brw_cat,
|
||||
branch => $branch_code,
|
||||
} );
|
||||
|
||||
Return the ILL prefix as defined by our $params: either per borrower category,
|
||||
per branch or the default.
|
||||
|
||||
=cut
|
||||
|
||||
sub getPrefix {
|
||||
my ( $self, $params ) = @_;
|
||||
my $brn_prefixes = $self->_config->getPrefixes('branch');
|
||||
my $brw_prefixes = $self->_config->getPrefixes('brw_cat');
|
||||
|
||||
return $brw_prefixes->{$params->{brw_cat}}
|
||||
|| $brn_prefixes->{$params->{branch}}
|
||||
|| $brw_prefixes->{default}
|
||||
|| ""; # "the empty prefix"
|
||||
}
|
||||
|
||||
#### Illrequests Imports
|
||||
|
||||
=head3 check_limits
|
||||
|
||||
my $ok = $illRequests->check_limits( {
|
||||
borrower => $borrower,
|
||||
branchcode => 'branchcode' | undef,
|
||||
} );
|
||||
|
||||
Given $PARAMS, a hashref containing a $borrower object and a $branchcode,
|
||||
see whether we are still able to place ILLs.
|
||||
|
||||
LimitRules are derived from koha-conf.xml:
|
||||
+ default limit counts, and counting method
|
||||
+ branch specific limit counts & counting method
|
||||
+ borrower category specific limit counts & counting method
|
||||
+ err on the side of caution: a counting fail will cause fail, even if
|
||||
the other counts passes.
|
||||
|
||||
=cut
|
||||
|
||||
sub check_limits {
|
||||
my ( $self, $params ) = @_;
|
||||
my $patron = $params->{patron};
|
||||
my $branchcode = $params->{librarycode} || $patron->branchcode;
|
||||
|
||||
# Establish maximum number of allowed requests
|
||||
my ( $branch_rules, $brw_rules ) = (
|
||||
$self->getLimits( {
|
||||
type => 'branch',
|
||||
value => $branchcode
|
||||
} ),
|
||||
$self->getLimits( {
|
||||
type => 'brw_cat',
|
||||
value => $patron->categorycode,
|
||||
} ),
|
||||
);
|
||||
my ( $branch_limit, $brw_limit )
|
||||
= ( $branch_rules->{count}, $brw_rules->{count} );
|
||||
# Establish currently existing requests
|
||||
my ( $branch_count, $brw_count ) = (
|
||||
$self->_limit_counter(
|
||||
$branch_rules->{method}, { branchcode => $branchcode }
|
||||
),
|
||||
$self->_limit_counter(
|
||||
$brw_rules->{method}, { borrowernumber => $patron->borrowernumber }
|
||||
),
|
||||
);
|
||||
|
||||
# Compare and return
|
||||
# A limit of -1 means no limit exists.
|
||||
# We return blocked if either branch limit or brw limit is reached.
|
||||
if ( ( $branch_limit != -1 && $branch_limit <= $branch_count )
|
||||
|| ( $brw_limit != -1 && $brw_limit <= $brw_count ) ) {
|
||||
return 0;
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
sub _limit_counter {
|
||||
my ( $self, $method, $target ) = @_;
|
||||
|
||||
# Establish parameters of counts
|
||||
my $resultset;
|
||||
if ($method && $method eq 'annual') {
|
||||
$resultset = Koha::Illrequests->search({
|
||||
-and => [
|
||||
%{$target},
|
||||
\"YEAR(placed) = YEAR(NOW())"
|
||||
]
|
||||
});
|
||||
} else { # assume 'active'
|
||||
# XXX: This status list is ugly. There should be a method in config
|
||||
# to return these.
|
||||
$where = { status => { -not_in => [ 'QUEUED', 'COMP' ] } };
|
||||
$resultset = Koha::Illrequests->search({ %{$target}, %{$where} });
|
||||
}
|
||||
|
||||
# Fetch counts
|
||||
return $resultset->count;
|
||||
}
|
||||
|
||||
=head3 requires_moderation
|
||||
|
||||
my $status = $illRequest->requires_moderation;
|
||||
|
||||
Return the name of the status if moderation by staff is required; or 0
|
||||
otherwise.
|
||||
|
||||
=cut
|
||||
|
||||
sub requires_moderation {
|
||||
my ( $self ) = @_;
|
||||
my $require_moderation = {
|
||||
'CANCREQ' => 'CANCREQ',
|
||||
};
|
||||
return $require_moderation->{$self->status};
|
||||
}
|
||||
|
||||
=head3 generic_confirm
|
||||
|
||||
my $stage_summary = $illRequest->generic_confirm;
|
||||
|
||||
Handle the generic_confirm extended method. The first stage involves creating
|
||||
a template email for the end user to edit in the browser. The second stage
|
||||
attempts to submit the email.
|
||||
|
||||
=cut
|
||||
|
||||
sub generic_confirm {
|
||||
my ( $self, $params ) = @_;
|
||||
my $branch = Koha::Libraries->find($params->{current_branchcode})
|
||||
|| die "Invalid current branchcode. Are you logged in as the database user?";
|
||||
if ( !$params->{stage}|| $params->{stage} eq 'init' ) {
|
||||
my $draft->{subject} = "ILL Request";
|
||||
$draft->{body} = <<EOF;
|
||||
Dear Sir/Madam,
|
||||
|
||||
We would like to request an interlibrary loan for a title matching the
|
||||
following description:
|
||||
|
||||
EOF
|
||||
|
||||
my $details = $self->metadata;
|
||||
while (my ($title, $value) = each %{$details}) {
|
||||
$draft->{body} .= " - " . $title . ": " . $value . "\n"
|
||||
if $value;
|
||||
}
|
||||
$draft->{body} .= <<EOF;
|
||||
|
||||
Please let us know if you are able to supply this to us.
|
||||
|
||||
Kind Regards
|
||||
|
||||
EOF
|
||||
|
||||
my @address = map { $branch->$_ }
|
||||
qw/ branchname branchaddress1 branchaddress2 branchaddress3
|
||||
branchzip branchcity branchstate branchcountry branchphone
|
||||
branchemail /;
|
||||
my $address = "";
|
||||
foreach my $line ( @address ) {
|
||||
$address .= $line . "\n" if $line;
|
||||
}
|
||||
|
||||
$draft->{body} .= $address;
|
||||
|
||||
my $partners = Koha::Patrons->search({
|
||||
categorycode => $self->_config->partner_code
|
||||
});
|
||||
return {
|
||||
error => 0,
|
||||
status => '',
|
||||
message => '',
|
||||
method => 'generic_confirm',
|
||||
stage => 'draft',
|
||||
value => {
|
||||
draft => $draft,
|
||||
partners => $partners,
|
||||
}
|
||||
};
|
||||
|
||||
} elsif ( 'draft' eq $params->{stage} ) {
|
||||
# Create the to header
|
||||
my $to = $params->{partners};
|
||||
$to =~ s/^\x00//; # Strip leading NULLs
|
||||
$to =~ s/\x00/; /; # Replace others with '; '
|
||||
die "No target email addresses found. Either select at least one partner or check your ILL partner library records." if ( !$to );
|
||||
# Create the from, replyto and sender headers
|
||||
my $from = $branch->branchemail;
|
||||
my $replyto = $branch->branchreplyto || $from;
|
||||
die "Your branch has no email address. Please set it."
|
||||
if ( !$from );
|
||||
# Create the email
|
||||
my $message = Koha::Email->new;
|
||||
my %mail = $message->create_message_headers(
|
||||
{
|
||||
to => $to,
|
||||
from => $from,
|
||||
replyto => $replyto,
|
||||
subject => Encode::encode( "utf8", $params->{subject} ),
|
||||
message => Encode::encode( "utf8", $params->{body} ),
|
||||
contenttype => 'text/plain',
|
||||
}
|
||||
);
|
||||
# Send it
|
||||
my $result = sendmail(%mail);
|
||||
if ( $result ) {
|
||||
$self->status("GENREQ")->store;
|
||||
return {
|
||||
error => 0,
|
||||
status => '',
|
||||
message => '',
|
||||
method => 'generic_confirm',
|
||||
stage => 'commit',
|
||||
next => 'illview',
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
error => 1,
|
||||
status => 'email_failed',
|
||||
message => $Mail::Sendmail::error,
|
||||
method => 'generic_confirm',
|
||||
stage => 'draft',
|
||||
};
|
||||
}
|
||||
} else {
|
||||
die "Unknown stage, should not have happened."
|
||||
}
|
||||
}
|
||||
|
||||
=head3 id_prefix
|
||||
|
||||
my $prefix = $record->id_prefix;
|
||||
|
||||
Return the prefix appropriate for the current Illrequest as derived from the
|
||||
borrower and branch associated with this request's Status, and the config
|
||||
file.
|
||||
|
||||
=cut
|
||||
|
||||
sub id_prefix {
|
||||
my ( $self ) = @_;
|
||||
my $brw = $self->patron;
|
||||
my $brw_cat = "dummy";
|
||||
$brw_cat = $brw->categorycode
|
||||
unless ( 'HASH' eq ref($brw) && $brw->{deleted} );
|
||||
my $prefix = $self->getPrefix( {
|
||||
brw_cat => $brw_cat,
|
||||
branch => $self->branchcode,
|
||||
} );
|
||||
$prefix .= "-" if ( $prefix );
|
||||
return $prefix;
|
||||
}
|
||||
|
||||
=head3 _censor
|
||||
|
||||
my $params = $illRequest->_censor($params);
|
||||
|
||||
Return $params, modified to reflect our censorship requirements.
|
||||
|
||||
=cut
|
||||
|
||||
sub _censor {
|
||||
my ( $self, $params ) = @_;
|
||||
my $censorship = $self->_config->censorship;
|
||||
$params->{censor_notes_staff} = $censorship->{censor_notes_staff}
|
||||
if ( $params->{opac} );
|
||||
$params->{display_reply_date} = ( $censorship->{censor_reply_date} ) ? 0 : 1;
|
||||
|
||||
return $params;
|
||||
}
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Alex Sassmannshausen <alex.sassmannshausen@ptfs-europe.com>
|
||||
|
||||
=cut
|
||||
|
||||
1;
|
||||
|
|
@ -0,0 +1,384 @@
|
|||
package Koha::Illrequest::Config;
|
||||
|
||||
# Copyright 2013,2014 PTFS Europe Ltd
|
||||
#
|
||||
# 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;
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Koha::Illrequest::Config - Koha ILL Configuration Object
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
Object-oriented class that giving access to the illconfig data derived
|
||||
from ill/config.yaml.
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
Config object providing abstract representation of the expected XML
|
||||
returned by ILL API.
|
||||
|
||||
In particular the config object uses a YAML file, whose path is
|
||||
defined by <illconfig> in koha-conf.xml. That YAML file provides the
|
||||
data structure exposed in this object.
|
||||
|
||||
By default the configured data structure complies with fields used by
|
||||
the British Library Interlibrary Loan DSS API.
|
||||
|
||||
The config file also provides mappings for Record Object accessors.
|
||||
|
||||
=head1 API
|
||||
|
||||
=head2 Class Methods
|
||||
|
||||
=head3 new
|
||||
|
||||
my $config = Koha::Illrequest::Config->new();
|
||||
|
||||
Create a new Koha::Illrequest::Config object, with mapping data loaded from the
|
||||
ILL configuration file.
|
||||
|
||||
=cut
|
||||
|
||||
sub new {
|
||||
my ( $class ) = @_;
|
||||
my $self = {};
|
||||
|
||||
$self->{configuration} = _load_configuration(
|
||||
C4::Context->config("interlibrary_loans"),
|
||||
C4::Context->preference("UnmediatedILL")
|
||||
);
|
||||
|
||||
bless $self, $class;
|
||||
|
||||
return $self;
|
||||
}
|
||||
|
||||
=head3 backend
|
||||
|
||||
$backend = $config->backend($name);
|
||||
$backend = $config->backend;
|
||||
|
||||
Standard setter/accessor for our backend.
|
||||
|
||||
=cut
|
||||
|
||||
sub backend {
|
||||
my ( $self, $new ) = @_;
|
||||
$self->{configuration}->{backend} = $new if $new;
|
||||
return $self->{configuration}->{backend};
|
||||
}
|
||||
|
||||
=head3 backend_dir
|
||||
|
||||
$backend_dir = $config->backend_dir($new_path);
|
||||
$backend_dir = $config->backend_dir;
|
||||
|
||||
Standard setter/accessor for our backend_directory.
|
||||
|
||||
=cut
|
||||
|
||||
sub backend_dir {
|
||||
my ( $self, $new ) = @_;
|
||||
$self->{configuration}->{backend_directory} = $new if $new;
|
||||
return $self->{configuration}->{backend_directory};
|
||||
}
|
||||
|
||||
=head3 partner_code
|
||||
|
||||
$partner_code = $config->partner_code($new_code);
|
||||
$partner_code = $config->partner_code;
|
||||
|
||||
Standard setter/accessor for our partner_code.
|
||||
|
||||
=cut
|
||||
|
||||
sub partner_code {
|
||||
my ( $self, $new ) = @_;
|
||||
$self->{configuration}->{partner_code} = $new if $new;
|
||||
return $self->{configuration}->{partner_code};
|
||||
}
|
||||
|
||||
=head3 limits
|
||||
|
||||
$limits = $config->limits($limitshash);
|
||||
$limits = $config->limits;
|
||||
|
||||
Standard setter/accessor for our limits. No parsing is performed on
|
||||
$LIMITSHASH, so caution should be exercised when using this setter.
|
||||
|
||||
=cut
|
||||
|
||||
sub limits {
|
||||
my ( $self, $new ) = @_;
|
||||
$self->{configuration}->{limits} = $new if $new;
|
||||
return $self->{configuration}->{limits};
|
||||
}
|
||||
|
||||
=head3 getPrefixes
|
||||
|
||||
my $prefixes = $config->getPrefixes('brw_cat' | 'branch');
|
||||
|
||||
Return the prefix for ILLs defined by our config.
|
||||
|
||||
=cut
|
||||
|
||||
sub getPrefixes {
|
||||
my ( $self, $type ) = @_;
|
||||
die "Unexpected type." unless ( $type eq 'brw_cat' || $type eq 'branch' );
|
||||
my $values = $self->{configuration}->{prefixes}->{$type};
|
||||
$values->{default} = $self->{configuration}->{prefixes}->{default};
|
||||
return $values;
|
||||
}
|
||||
|
||||
=head3 getLimitRules
|
||||
|
||||
my $rules = $config->getLimitRules('brw_cat' | 'branch')
|
||||
|
||||
Return the hash of ILL limit rules defined by our config.
|
||||
|
||||
=cut
|
||||
|
||||
sub getLimitRules {
|
||||
my ( $self, $type ) = @_;
|
||||
die "Unexpected type." unless ( $type eq 'brw_cat' || $type eq 'branch' );
|
||||
my $values = $self->{configuration}->{limits}->{$type};
|
||||
$values->{default} = $self->{configuration}->{limits}->{default};
|
||||
return $values;
|
||||
}
|
||||
|
||||
=head3 getDigitalRecipients
|
||||
|
||||
my $recipient_rules= $config->getDigitalRecipients('brw_cat' | 'branch');
|
||||
|
||||
Return the hash of digital_recipient settings defined by our config.
|
||||
|
||||
=cut
|
||||
|
||||
sub getDigitalRecipients {
|
||||
my ( $self, $type ) = @_;
|
||||
die "Unexpected type." unless ( $type eq 'brw_cat' || $type eq 'branch' );
|
||||
my $values = $self->{configuration}->{digital_recipients}->{$type};
|
||||
$values->{default} =
|
||||
$self->{configuration}->{digital_recipients}->{default};
|
||||
return $values;
|
||||
}
|
||||
|
||||
=head3 censorship
|
||||
|
||||
my $censoredValues = $config->censorship($hash);
|
||||
my $censoredValues = $config->censorship;
|
||||
|
||||
Standard setter/accessor for our limits. No parsing is performed on $HASH, so
|
||||
caution should be exercised when using this setter.
|
||||
|
||||
Return our censorship values for the OPAC as loaded from the koha-conf.xml, or
|
||||
the fallback value (no censorship).
|
||||
|
||||
=cut
|
||||
|
||||
sub censorship {
|
||||
my ( $self, $new ) = @_;
|
||||
$self->{configuration}->{censorship} = $new if $new;
|
||||
return $self->{configuration}->{censorship};
|
||||
}
|
||||
|
||||
=head3 _load_configuration
|
||||
|
||||
my $configuration = $config->_load_configuration($config_from_xml);
|
||||
|
||||
Read the configuration values passed as the parameter, and populate a hashref
|
||||
suitable for use with these.
|
||||
|
||||
A key task performed here is the parsing of the input in the configuration
|
||||
file to ensure we have only valid input there.
|
||||
|
||||
=cut
|
||||
|
||||
sub _load_configuration {
|
||||
my ( $xml_config, $unmediated ) = @_;
|
||||
my $xml_backend_dir = $xml_config->{backend_directory};
|
||||
|
||||
# Default data structure to be returned
|
||||
my $configuration = {
|
||||
backend_directory => $xml_backend_dir,
|
||||
censorship => {
|
||||
censor_notes_staff => 0,
|
||||
censor_reply_date => 0,
|
||||
},
|
||||
limits => {},
|
||||
digital_recipients => {},
|
||||
prefixes => {},
|
||||
partner_code => 'ILLLIBS',
|
||||
raw_config => $xml_config,
|
||||
};
|
||||
|
||||
# Per Branch Configuration
|
||||
my $branches = $xml_config->{branch};
|
||||
if ( ref($branches) eq "ARRAY" ) {
|
||||
# Multiple branch overrides defined
|
||||
map {
|
||||
_load_unit_config({
|
||||
unit => $_,
|
||||
id => $_->{code},
|
||||
config => $configuration,
|
||||
type => 'branch'
|
||||
})
|
||||
} @{$branches};
|
||||
} elsif ( ref($branches) eq "HASH" ) {
|
||||
# Single branch override defined
|
||||
_load_unit_config({
|
||||
unit => $branches,
|
||||
id => $branches->{code},
|
||||
config => $configuration,
|
||||
type => 'branch'
|
||||
});
|
||||
}
|
||||
|
||||
# Per Borrower Category Configuration
|
||||
my $brw_cats = $xml_config->{borrower_category};
|
||||
if ( ref($brw_cats) eq "ARRAY" ) {
|
||||
# Multiple borrower category overrides defined
|
||||
map {
|
||||
_load_unit_config({
|
||||
unit => $_,
|
||||
id => $_->{code},
|
||||
config => $configuration,
|
||||
type => 'brw_cat'
|
||||
})
|
||||
} @{$brw_cats};
|
||||
} elsif ( ref($brw_cats) eq "HASH" ) {
|
||||
# Single branch override defined
|
||||
_load_unit_config({
|
||||
unit => $brw_cats,
|
||||
id => $brw_cats->{code},
|
||||
config => $configuration,
|
||||
type => 'brw_cat'
|
||||
});
|
||||
}
|
||||
|
||||
# Default Configuration
|
||||
_load_unit_config({
|
||||
unit => $xml_config,
|
||||
id => 'default',
|
||||
config => $configuration
|
||||
});
|
||||
|
||||
# Censorship
|
||||
my $staff_comments = $xml_config->{staff_request_comments} || 0;
|
||||
$configuration->{censorship}->{censor_notes_staff} = 1
|
||||
if ( $staff_comments && 'hide' eq $staff_comments );
|
||||
my $reply_date = $xml_config->{reply_date} || 0;
|
||||
$configuration->{censorship}->{censor_reply_date} = 1
|
||||
if ( $reply_date && 'hide' eq $reply_date );
|
||||
|
||||
# ILL Partners
|
||||
$configuration->{partner_code} = $xml_config->{partner_code} || 'ILLLIBS';
|
||||
|
||||
die "No DEFAULT_FORMATS has been defined in koha-conf.xml, but UNMEDIATEDILL is active."
|
||||
if ( $unmediated && !$configuration->{default_formats}->{default} );
|
||||
|
||||
return $configuration;
|
||||
}
|
||||
|
||||
=head3 _load_unit_config
|
||||
|
||||
my $configuration->{part} = _load_unit_config($params);
|
||||
|
||||
$PARAMS is a hashref with the following elements:
|
||||
- unit: the part of the configuration we are parsing.
|
||||
- id: the name within which we will store the parsed unit in config.
|
||||
- config: the configuration we are augmenting.
|
||||
- type: the type of config unit we are parsing. Assumed to be 'default'.
|
||||
|
||||
Read `unit', and augment `config' with these under `id'.
|
||||
|
||||
This is a helper for _load_configuration.
|
||||
|
||||
A key task performed here is the parsing of the input in the configuration
|
||||
file to ensure we have only valid input there.
|
||||
|
||||
=cut
|
||||
|
||||
sub _load_unit_config {
|
||||
my ( $params ) = @_;
|
||||
my $unit = $params->{unit};
|
||||
my $id = $params->{id};
|
||||
my $config = $params->{config};
|
||||
my $type = $params->{type};
|
||||
die "TYPE should be either 'branch' or 'brw_cat' if ID is not 'default'."
|
||||
if ( $id ne 'default' && ( $type ne 'branch' && $type ne 'brw_cat') );
|
||||
return $config unless $id;
|
||||
|
||||
if ( $unit->{api_key} && $unit->{api_auth} ) {
|
||||
$config->{credentials}->{api_keys}->{$id} = {
|
||||
api_key => $unit->{api_key},
|
||||
api_auth => $unit->{api_auth},
|
||||
};
|
||||
}
|
||||
# Add request_limit rules.
|
||||
# METHOD := 'annual' || 'active'
|
||||
# COUNT := x >= -1
|
||||
if ( ref $unit->{request_limit} eq 'HASH' ) {
|
||||
my $method = $unit->{request_limit}->{method};
|
||||
my $count = $unit->{request_limit}->{count};
|
||||
if ( 'default' eq $id ) {
|
||||
$config->{limits}->{$id}->{method} = $method
|
||||
if ( $method && ( 'annual' eq $method || 'active' eq $method ) );
|
||||
$config->{limits}->{$id}->{count} = $count
|
||||
if ( $count && ( -1 <= $count ) );
|
||||
} else {
|
||||
$config->{limits}->{$type}->{$id}->{method} = $method
|
||||
if ( $method && ( 'annual' eq $method || 'active' eq $method ) );
|
||||
$config->{limits}->{$type}->{$id}->{count} = $count
|
||||
if ( $count && ( -1 <= $count ) );
|
||||
}
|
||||
}
|
||||
|
||||
# Add prefix rules.
|
||||
# PREFIX := string
|
||||
if ( $unit->{prefix} ) {
|
||||
if ( 'default' eq $id ) {
|
||||
$config->{prefixes}->{$id} = $unit->{prefix};
|
||||
} else {
|
||||
$config->{prefixes}->{$type}->{$id} = $unit->{prefix};
|
||||
}
|
||||
}
|
||||
|
||||
# Add digital_recipient rules.
|
||||
# DIGITAL_RECIPIENT := borrower || branch (defaults to borrower)
|
||||
if ( $unit->{digital_recipient} ) {
|
||||
if ( 'default' eq $id ) {
|
||||
$config->{digital_recipients}->{$id} = $unit->{digital_recipient};
|
||||
} else {
|
||||
$config->{digital_recipients}->{$type}->{$id} =
|
||||
$unit->{digital_recipient};
|
||||
}
|
||||
}
|
||||
|
||||
return $config;
|
||||
}
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Alex Sassmannshausen <alex.sassmannshausen@ptfs-europe.com>
|
||||
|
||||
=cut
|
||||
|
||||
1;
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
package Koha::Illrequestattribute;
|
||||
|
||||
# Copyright PTFS Europe 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 Koha::Database;
|
||||
|
||||
use base qw(Koha::Object);
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Koha::Illrequestattribute - Koha Illrequestattribute Object class
|
||||
|
||||
=head1 API
|
||||
|
||||
=head2 Class Methods
|
||||
|
||||
=cut
|
||||
|
||||
=head3 type
|
||||
|
||||
=cut
|
||||
|
||||
sub _type {
|
||||
return 'Illrequestattribute';
|
||||
}
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Alex Sassmannshausen <alex.sassmannshausen@ptfs-europe.com>
|
||||
|
||||
=cut
|
||||
|
||||
1;
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
package Koha::Illrequestattributes;
|
||||
|
||||
# Copyright PTFS Europe 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 Koha::Database;
|
||||
use Koha::Illrequestattribute;
|
||||
|
||||
use base qw(Koha::Objects);
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Koha::Illrequestattributes - Koha Illrequestattributes Object class
|
||||
|
||||
=head1 API
|
||||
|
||||
=head2 Class Methods
|
||||
|
||||
=cut
|
||||
|
||||
=head3 type
|
||||
|
||||
=cut
|
||||
|
||||
sub _type {
|
||||
return 'Illrequestattribute';
|
||||
}
|
||||
|
||||
sub object_class {
|
||||
return 'Koha::Illrequestattribute';
|
||||
}
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Alex Sassmannshausen <alex.sassmannshausen@ptfs-europe.com>
|
||||
|
||||
=cut
|
||||
|
||||
1;
|
||||
|
|
@ -0,0 +1,97 @@
|
|||
package Koha::Illrequests;
|
||||
|
||||
# Copyright PTFS Europe 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 Koha::Database;
|
||||
use Koha::Illrequest;
|
||||
use Koha::Illrequest::Config;
|
||||
|
||||
use base qw(Koha::Objects);
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Koha::Illrequests - Koha Illrequests Object class
|
||||
|
||||
=head1 API
|
||||
|
||||
=head2 Class Methods
|
||||
|
||||
=cut
|
||||
|
||||
=head3 type
|
||||
|
||||
=cut
|
||||
|
||||
sub _type {
|
||||
return 'Illrequest';
|
||||
}
|
||||
|
||||
sub object_class {
|
||||
return 'Koha::Illrequest';
|
||||
}
|
||||
|
||||
##### To be implemented Facade
|
||||
|
||||
=head3 new
|
||||
|
||||
my $illRequests = Koha::Illrequests->new();
|
||||
|
||||
Create an ILLREQUESTS object, a singleton through which we can interact with
|
||||
ILLREQUEST objects stored in the database or search for ILL candidates at API
|
||||
backends.
|
||||
|
||||
=cut
|
||||
|
||||
sub new {
|
||||
my ( $class, $attributes ) = @_;
|
||||
|
||||
my $self = $class->SUPER::new($class, $attributes);
|
||||
|
||||
my $config = Koha::Illrequest::Config->new; # <- Necessary
|
||||
$self->{_config} = $config; # <- Necessary
|
||||
|
||||
return $self;
|
||||
}
|
||||
|
||||
=head3 search_incomplete
|
||||
|
||||
my $requests = $illRequests->search_incomplete;
|
||||
|
||||
A specialised version of `search`, returning all requests currently
|
||||
not considered completed.
|
||||
|
||||
=cut
|
||||
|
||||
sub search_incomplete {
|
||||
my ( $self ) = @_;
|
||||
$self->search( {
|
||||
status => [
|
||||
-and => { '!=', 'COMP' }, { '!=', 'GENCOMP' }
|
||||
]
|
||||
} );
|
||||
}
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Alex Sassmannshausen <alex.sassmannshausen@ptfs-europe.com>
|
||||
|
||||
=cut
|
||||
|
||||
1;
|
||||
|
|
@ -0,0 +1,85 @@
|
|||
package Koha::REST::V1::Illrequests;
|
||||
|
||||
# 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 Mojo::Base 'Mojolicious::Controller';
|
||||
|
||||
use Koha::Illrequests;
|
||||
use Koha::Library;
|
||||
|
||||
sub list {
|
||||
my ($c, $args, $cb) = @_;
|
||||
|
||||
my $filter;
|
||||
$args //= {};
|
||||
my $output = [];
|
||||
|
||||
# Create a hash where all keys are embedded values
|
||||
# Enables easy checking
|
||||
my %embed;
|
||||
if (defined $args->{embed}) {
|
||||
%embed = map { $_ => 1 } @{$args->{embed}};
|
||||
delete $args->{embed};
|
||||
}
|
||||
|
||||
for my $filter_param ( keys %$args ) {
|
||||
my @values = split(/,/, $args->{$filter_param});
|
||||
$filter->{$filter_param} = \@values;
|
||||
}
|
||||
|
||||
my $requests = Koha::Illrequests->search($filter);
|
||||
|
||||
while (my $request = $requests->next) {
|
||||
my $unblessed = $request->unblessed;
|
||||
# Add the request's id_prefix
|
||||
$unblessed->{id_prefix} = $request->id_prefix;
|
||||
# Augment the request response with patron details
|
||||
# if appropriate
|
||||
if (defined $embed{patron}) {
|
||||
my $patron = $request->patron;
|
||||
$unblessed->{patron} = {
|
||||
firstname => $patron->firstname,
|
||||
surname => $patron->surname,
|
||||
cardnumber => $patron->cardnumber
|
||||
};
|
||||
}
|
||||
# Augment the request response with metadata details
|
||||
# if appropriate
|
||||
if (defined $embed{metadata}) {
|
||||
$unblessed->{metadata} = $request->metadata;
|
||||
}
|
||||
# Augment the request response with status details
|
||||
# if appropriate
|
||||
if (defined $embed{capabilities}) {
|
||||
$unblessed->{capabilities} = $request->capabilities;
|
||||
}
|
||||
# Augment the request response with branch details
|
||||
# if appropriate
|
||||
if (defined $embed{branch}) {
|
||||
$unblessed->{branch} = Koha::Libraries->find(
|
||||
$request->branchcode
|
||||
)->unblessed;
|
||||
}
|
||||
push @{$output}, $unblessed
|
||||
}
|
||||
|
||||
return $c->$cb( $output, 200 );
|
||||
|
||||
}
|
||||
|
||||
1;
|
||||
|
|
@ -312,6 +312,7 @@ my $target_map = {
|
|||
'./etc/zebradb' => { target => 'ZEBRA_CONF_DIR', trimdir => -1 },
|
||||
'./etc/pazpar2' => { target => 'PAZPAR2_CONF_DIR', trimdir => -1 },
|
||||
'./help.pl' => 'INTRANET_CGI_DIR',
|
||||
'./ill' => 'INTRANET_CGI_DIR',
|
||||
'./installer-CPAN.pl' => 'NONE',
|
||||
'./installer' => 'INTRANET_CGI_DIR',
|
||||
'./errors' => {target => 'INTRANET_CGI_DIR'},
|
||||
|
|
|
|||
|
|
@ -22,5 +22,8 @@
|
|||
},
|
||||
"/patrons/{borrowernumber}": {
|
||||
"$ref": "paths/patrons.json#/~1patrons~1{borrowernumber}"
|
||||
},
|
||||
"/illrequests": {
|
||||
"$ref": "paths/illrequests.json#/~1illrequests"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,98 @@
|
|||
{
|
||||
"/illrequests": {
|
||||
"get": {
|
||||
"x-mojo-controller": "Koha::REST::V1::Illrequests",
|
||||
"operationId": "list",
|
||||
"tags": ["illrequests"],
|
||||
"parameters": [{
|
||||
"name": "embed",
|
||||
"in": "query",
|
||||
"description": "Additional objects that should be embedded in the response",
|
||||
"required": false,
|
||||
"type": "array",
|
||||
"collectionFormat": "csv",
|
||||
"items": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"patron",
|
||||
"branch",
|
||||
"capabilities"
|
||||
]
|
||||
}
|
||||
}, {
|
||||
"name": "backend",
|
||||
"in": "query",
|
||||
"description": "The name of a ILL backend",
|
||||
"required": false,
|
||||
"type": "string"
|
||||
}, {
|
||||
"name": "orderid",
|
||||
"in": "query",
|
||||
"description": "The order ID of a request",
|
||||
"required": false,
|
||||
"type": "string"
|
||||
}, {
|
||||
"name": "biblio_id",
|
||||
"in": "query",
|
||||
"description": "The biblio ID associated with a request",
|
||||
"required": false,
|
||||
"type": "integer"
|
||||
}, {
|
||||
"name": "borrower_id",
|
||||
"in": "query",
|
||||
"description": "The borrower ID associated with a request",
|
||||
"required": false,
|
||||
"type": "integer"
|
||||
}, {
|
||||
"name": "completed",
|
||||
"in": "query",
|
||||
"description": "The date the request was considered completed",
|
||||
"required": false,
|
||||
"type": "string"
|
||||
}, {
|
||||
"name": "status",
|
||||
"in": "query",
|
||||
"description": "A full status string e.g. REQREV",
|
||||
"required": false,
|
||||
"type": "string"
|
||||
}, {
|
||||
"name": "medium",
|
||||
"in": "query",
|
||||
"description": "The medium of the requested item",
|
||||
"required": false,
|
||||
"type": "string"
|
||||
}, {
|
||||
"name": "updated",
|
||||
"in": "query",
|
||||
"description": "The last updated date of the request",
|
||||
"required": false,
|
||||
"type": "string"
|
||||
}, {
|
||||
"name": "placed",
|
||||
"in": "query",
|
||||
"description": "The date the request was placed",
|
||||
"required": false,
|
||||
"type": "string"
|
||||
}, {
|
||||
"name": "branch_id",
|
||||
"in": "query",
|
||||
"description": "The ID of the pickup branch",
|
||||
"required": false,
|
||||
"type": "string"
|
||||
}],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK"
|
||||
}
|
||||
},
|
||||
"x-koha-authorization": {
|
||||
"permissions": {
|
||||
"borrowers": "1"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -153,5 +153,26 @@ __PAZPAR2_TOGGLE_XML_POST__
|
|||
<plack_max_requests>50</plack_max_requests>
|
||||
<plack_workers>2</plack_workers>
|
||||
|
||||
<interlibrary_loans>
|
||||
<!-- Path to where Illbackends are located on the system
|
||||
- This setting should normally not be touched -->
|
||||
<backend_directory>__PERL_MODULE_DIR__/Koha/Illbackends</backend_directory>
|
||||
<!-- How should we treat staff comments?
|
||||
- hide: don't show in OPAC
|
||||
- show: show in OPAC -->
|
||||
<staff_request_comments>hide</staff_request_comments>
|
||||
<!-- How should we treat the reply_date field?
|
||||
- hide: don't show this field in the UI
|
||||
- any other string: show, with this label -->
|
||||
<reply_date>hide</reply_date>
|
||||
<!-- Where should digital ILLs be sent?
|
||||
- borrower: send it straight to the borrower email
|
||||
- branch: send the ILL to the branch email -->
|
||||
<digital_recipient>branch</digital_recipient>
|
||||
<!-- What patron category should we use for p2p ILL requests?
|
||||
- By default this is set to 'ILLLIBS' -->
|
||||
<partner_code>ILLLIBS</partner_code>
|
||||
</interlibrary_loans>
|
||||
|
||||
</config>
|
||||
</yazgfs>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,252 @@
|
|||
#!/usr/bin/perl
|
||||
|
||||
# Copyright 2013 PTFS-Europe Ltd and Mark Gavillet
|
||||
# Copyright 2014 PTFS-Europe Ltd
|
||||
#
|
||||
# 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 CGI;
|
||||
|
||||
use C4::Auth;
|
||||
use C4::Output;
|
||||
use Koha::AuthorisedValues;
|
||||
use Koha::Illrequests;
|
||||
use Koha::Libraries;
|
||||
|
||||
my $cgi = CGI->new;
|
||||
my $illRequests = Koha::Illrequests->new;
|
||||
|
||||
# Grab all passed data
|
||||
# 'our' since Plack changes the scoping
|
||||
# of 'my'
|
||||
our $params = $cgi->Vars();
|
||||
|
||||
my $op = $params->{method} || 'illlist';
|
||||
|
||||
my ( $template, $patronnumber, $cookie ) = get_template_and_user( {
|
||||
template_name => 'ill/ill-requests.tt',
|
||||
query => $cgi,
|
||||
type => 'intranet',
|
||||
flagsrequired => { ill => '*' },
|
||||
} );
|
||||
|
||||
if ( $op eq 'illview' ) {
|
||||
# View the details of an ILL
|
||||
my $request = Koha::Illrequests->find($params->{illrequest_id});
|
||||
|
||||
$template->param(
|
||||
request => $request
|
||||
);
|
||||
|
||||
} elsif ( $op eq 'create' ) {
|
||||
# We're in the process of creating a request
|
||||
my $request = Koha::Illrequest->new
|
||||
->load_backend($params->{backend});
|
||||
my $backend_result = $request->backend_create($params);
|
||||
$template->param(
|
||||
whole => $backend_result,
|
||||
request => $request
|
||||
);
|
||||
handle_commit_maybe($backend_result, $request);
|
||||
|
||||
} elsif ( $op eq 'confirm' ) {
|
||||
# Backend 'confirm' method
|
||||
# confirm requires a specific request, so first, find it.
|
||||
my $request = Koha::Illrequests->find($params->{illrequest_id});
|
||||
my $backend_result = $request->backend_confirm($params);
|
||||
$template->param(
|
||||
whole => $backend_result,
|
||||
request => $request,
|
||||
);
|
||||
|
||||
# handle special commit rules & update type
|
||||
handle_commit_maybe($backend_result, $request);
|
||||
|
||||
} elsif ( $op eq 'cancel' ) {
|
||||
# Backend 'cancel' method
|
||||
# cancel requires a specific request, so first, find it.
|
||||
my $request = Koha::Illrequests->find($params->{illrequest_id});
|
||||
my $backend_result = $request->backend_cancel($params);
|
||||
$template->param(
|
||||
whole => $backend_result,
|
||||
request => $request,
|
||||
);
|
||||
|
||||
# handle special commit rules & update type
|
||||
handle_commit_maybe($backend_result, $request);
|
||||
|
||||
} elsif ( $op eq 'edit_action' ) {
|
||||
# Handle edits to the Illrequest object.
|
||||
# (not the Illrequestattributes)
|
||||
# We simulate the API for backend requests for uniformity.
|
||||
# So, init:
|
||||
my $request = Koha::Illrequests->find($params->{illrequest_id});
|
||||
if ( !$params->{stage} ) {
|
||||
my $backend_result = {
|
||||
error => 0,
|
||||
status => '',
|
||||
message => '',
|
||||
method => 'edit_action',
|
||||
stage => 'init',
|
||||
next => '',
|
||||
value => {}
|
||||
};
|
||||
$template->param(
|
||||
whole => $backend_result,
|
||||
request => $request
|
||||
);
|
||||
} else {
|
||||
# Commit:
|
||||
# Save the changes
|
||||
$request->borrowernumber($params->{borrowernumber});
|
||||
$request->biblio_id($params->{biblio_id});
|
||||
$request->branchcode($params->{branchcode});
|
||||
$request->notesopac($params->{notesopac});
|
||||
$request->notesstaff($params->{notesstaff});
|
||||
$request->store;
|
||||
my $backend_result = {
|
||||
error => 0,
|
||||
status => '',
|
||||
message => '',
|
||||
method => 'edit_action',
|
||||
stage => 'commit',
|
||||
next => 'illlist',
|
||||
value => {}
|
||||
};
|
||||
handle_commit_maybe($backend_result, $request);
|
||||
}
|
||||
|
||||
} elsif ( $op eq 'moderate_action' ) {
|
||||
# Moderate action is required for an ILL submodule / syspref.
|
||||
# Currently still needs to be implemented.
|
||||
redirect_to_list();
|
||||
|
||||
} elsif ( $op eq 'delete_confirm') {
|
||||
my $request = Koha::Illrequests->find($params->{illrequest_id});
|
||||
|
||||
$template->param(
|
||||
request => $request
|
||||
);
|
||||
|
||||
} elsif ( $op eq 'delete' ) {
|
||||
|
||||
# Check if the request is confirmed, if not, redirect
|
||||
# to the confirmation view
|
||||
if ($params->{confirmed} == 1) {
|
||||
# We simply delete the request...
|
||||
my $request = Koha::Illrequests->find(
|
||||
$params->{illrequest_id}
|
||||
)->delete;
|
||||
# ... then return to list view.
|
||||
redirect_to_list();
|
||||
} else {
|
||||
print $cgi->redirect(
|
||||
"/cgi-bin/koha/ill/ill-requests.pl?" .
|
||||
"method=delete_confirm&illrequest_id=" .
|
||||
$params->{illrequest_id});
|
||||
}
|
||||
|
||||
} elsif ( $op eq 'mark_completed' ) {
|
||||
my $request = Koha::Illrequests->find($params->{illrequest_id});
|
||||
my $backend_result = $request->mark_completed($params);
|
||||
$template->param(
|
||||
whole => $backend_result,
|
||||
request => $request,
|
||||
);
|
||||
|
||||
# handle special commit rules & update type
|
||||
handle_commit_maybe($backend_result, $request);
|
||||
|
||||
} elsif ( $op eq 'generic_confirm' ) {
|
||||
my $request = Koha::Illrequests->find($params->{illrequest_id});
|
||||
$params->{current_branchcode} = C4::Context->mybranch;
|
||||
my $backend_result = $request->generic_confirm($params);
|
||||
$template->param(
|
||||
whole => $backend_result,
|
||||
request => $request,
|
||||
);
|
||||
|
||||
# handle special commit rules & update type
|
||||
handle_commit_maybe($backend_result, $request);
|
||||
|
||||
} elsif ( $op eq 'illlist') {
|
||||
# Display all current ILLs
|
||||
my $requests = $illRequests->search();
|
||||
|
||||
$template->param(
|
||||
requests => $requests
|
||||
);
|
||||
|
||||
# If we receive a pre-filter, make it available to the template
|
||||
my $possible_filters = ['borrowernumber'];
|
||||
my $active_filters = [];
|
||||
foreach my $filter(@{$possible_filters}) {
|
||||
if ($params->{$filter}) {
|
||||
push @{$active_filters},
|
||||
{ name => $filter, value => $params->{$filter}};
|
||||
}
|
||||
}
|
||||
if (scalar @{$active_filters} > 0) {
|
||||
$template->param(
|
||||
prefilters => $active_filters
|
||||
);
|
||||
}
|
||||
} else {
|
||||
my $request = Koha::Illrequests->find($params->{illrequest_id});
|
||||
my $backend_result = $request->custom_capability($op, $params);
|
||||
$template->param(
|
||||
whole => $backend_result,
|
||||
request => $request,
|
||||
);
|
||||
|
||||
# handle special commit rules & update type
|
||||
handle_commit_maybe($backend_result, $request);
|
||||
}
|
||||
|
||||
# Get a list of backends
|
||||
my $ir = Koha::Illrequest->new;
|
||||
|
||||
$template->param(
|
||||
backends => $ir->available_backends,
|
||||
media => [ "Book", "Article", "Journal" ],
|
||||
query_type => $op,
|
||||
branches => Koha::Libraries->search->unblessed,
|
||||
here_link => "/cgi-bin/koha/ill/ill-requests.pl"
|
||||
);
|
||||
|
||||
output_html_with_http_headers( $cgi, $cookie, $template->output );
|
||||
|
||||
sub handle_commit_maybe {
|
||||
my ( $backend_result, $request ) = @_;
|
||||
# We need to special case 'commit'
|
||||
if ( $backend_result->{stage} eq 'commit' ) {
|
||||
if ( $backend_result->{next} eq 'illview' ) {
|
||||
# Redirect to a view of the newly created request
|
||||
print $cgi->redirect(
|
||||
'/cgi-bin/koha/ill/ill-requests.pl?method=illview&illrequest_id='.
|
||||
$request->id
|
||||
);
|
||||
} else {
|
||||
# Redirect to a requests list view
|
||||
redirect_to_list();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub redirect_to_list {
|
||||
print $cgi->redirect('/cgi-bin/koha/ill/ill-requests.pl');
|
||||
}
|
||||
|
|
@ -3049,3 +3049,95 @@ fieldset.rows + fieldset.action {
|
|||
#patron_search #filters {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#interlibraryloans h1 {
|
||||
margin: 1em 0;
|
||||
}
|
||||
|
||||
#interlibraryloans h2 {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
#interlibraryloans h3 {
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
#interlibraryloans .bg-info {
|
||||
overflow: auto;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
#interlibraryloans #search-summary {
|
||||
-webkit-transform: translateY(-50%);
|
||||
-ms-transform: translateY(-50%);
|
||||
-o-transform: translateY(-50%);
|
||||
transform: translateY(-50%);
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
}
|
||||
|
||||
#interlibraryloans .format h5 {
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
#interlibraryloans .format li {
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
#interlibraryloans .format h4 {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
#interlibraryloans .format input {
|
||||
margin: 10px 0;
|
||||
}
|
||||
|
||||
#interlibraryloans #freeform-fields .custom-name {
|
||||
width: 9em;
|
||||
margin-right: 1em;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
#interlibraryloans #freeform-fields .delete-new-field {
|
||||
margin-left: 1em;
|
||||
}
|
||||
|
||||
#interlibraryloans #add-new-fields {
|
||||
margin: 1em;
|
||||
}
|
||||
|
||||
#interlibraryloans #column-toggle,
|
||||
#interlibraryloans #reset-toggle {
|
||||
margin: 15px 0;
|
||||
line-height: 1.5em;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
#ill-view-panel {
|
||||
margin-top: 15px;
|
||||
}
|
||||
|
||||
#ill-view-panel h3 {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
#ill-view-panel h4 {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
#ill-view-panel .rows div {
|
||||
height: 1em;
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
|
||||
#ill-view-panel #requestattributes .label {
|
||||
width: auto;
|
||||
}
|
||||
|
||||
table#ill-requests {
|
||||
width: 100% !important;
|
||||
}
|
||||
|
||||
table#ill-requests th {
|
||||
text-transform: capitalize;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -117,5 +117,8 @@
|
|||
[% IF Koha.Preference('HouseboundModule') %]
|
||||
[% IF houseboundview %]<li class="active">[% ELSE %]<li>[% END %]<a href="/cgi-bin/koha/members/housebound.pl?borrowernumber=[% borrowernumber %]">Housebound</a></li>
|
||||
[% END %]
|
||||
[% IF Koha.Preference('ILLModule') %]
|
||||
<li><a href="/cgi-bin/koha/ill/ill-requests.pl?borrowernumber=[% borrowernumber %]">Interlibrary loans</a></li>
|
||||
[% END %]
|
||||
</ul></div>
|
||||
[% END %]
|
||||
|
|
|
|||
|
|
@ -0,0 +1,24 @@
|
|||
[% USE Koha %]
|
||||
[% IF Koha.Preference('ILLModule ') %]
|
||||
<div id="toolbar" class="btn-toolbar">
|
||||
[% IF backends.size > 1 %]
|
||||
<div class="dropdown btn-group">
|
||||
<button class="btn btn-sm btn-default dropdown-toggle" type="button" id="ill-backend-dropdown" data-toggle="dropdown" aria-haspopup="true" aria-expanded="true">
|
||||
<i class="fa fa-plus"></i> New ILL request <span class="caret"></span>
|
||||
</button>
|
||||
<ul class="dropdown-menu" aria-labelledby="ill-backend-dropdown">
|
||||
[% FOREACH backend IN backends %]
|
||||
<li><a href="/cgi-bin/koha/ill/ill-requests.pl?method=create&backend=[% backend %]">[% backend %]</a></li>
|
||||
[% END %]
|
||||
</ul>
|
||||
</div>
|
||||
[% ELSE %]
|
||||
<a id="ill-new" class="btn btn-sm btn-default" href="/cgi-bin/koha/ill/ill-requests.pl?method=create&backend=[% backends.0 %]">
|
||||
<i class="fa fa-plus"></i> New ILL request
|
||||
</a>
|
||||
[% END %]
|
||||
<a id="ill-list" class="btn btn-sm btn-default btn-group" href="/cgi-bin/koha/ill/ill-requests.pl">
|
||||
<i class="fa fa-list"></i> List requests
|
||||
</a>
|
||||
</div>
|
||||
[% END %]
|
||||
|
|
@ -20,6 +20,7 @@
|
|||
[%- CASE 'plugins' -%]<span>Koha plugins</span>
|
||||
[%- CASE 'lists' -%]<span>Lists</span>
|
||||
[%- CASE 'clubs' -%]<span>Patron clubs</span>
|
||||
[%- CASE 'ill' -%]<span>Create and modify Interlibrary loan requests</span>
|
||||
[%- END -%]
|
||||
[%- END -%]
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,698 @@
|
|||
[% USE Branches %]
|
||||
[% USE Koha %]
|
||||
|
||||
[% INCLUDE 'doc-head-open.inc' %]
|
||||
<title>Koha › ILL requests ›</title>
|
||||
[% INCLUDE 'doc-head-close.inc' %]
|
||||
<script type="text/javascript" src="[% themelang %]/lib/jquery/plugins/jquery.tablesorter.min.js"></script>
|
||||
<script type="text/javascript" src="[% themelang %]/lib/jquery/plugins/jquery.checkboxes.min.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="[% interface %]/[% theme %]/css/datatables.css">
|
||||
[% INCLUDE 'datatables.inc' %]
|
||||
<script type="text/javascript">
|
||||
//<![CDATA[
|
||||
$(document).ready(function() {
|
||||
|
||||
// Illview Datatable setup
|
||||
|
||||
// Fields we don't want to display
|
||||
var ignore = [
|
||||
'accessurl',
|
||||
'backend',
|
||||
'completed',
|
||||
'branch',
|
||||
'capabilities',
|
||||
'cost',
|
||||
'medium',
|
||||
'notesopac',
|
||||
'notesstaff',
|
||||
'placed',
|
||||
'replied'
|
||||
];
|
||||
|
||||
// Fields we need to expand (flatten)
|
||||
var expand = [
|
||||
'metadata',
|
||||
'patron'
|
||||
];
|
||||
|
||||
// Expanded fields
|
||||
// This is auto populated
|
||||
var expanded = {};
|
||||
|
||||
// The core fields that should be displayed first
|
||||
var core = [
|
||||
'metadata_Author',
|
||||
'metadata_Title',
|
||||
'borrowername',
|
||||
'biblio_id',
|
||||
'branchcode',
|
||||
'status',
|
||||
'updated',
|
||||
'illrequest_id',
|
||||
'action'
|
||||
];
|
||||
|
||||
// Extra fields that we need to tack on to the end
|
||||
var extra = [ 'action' ];
|
||||
|
||||
// Remove any fields we're ignoring
|
||||
var removeIgnore = function(dataObj) {
|
||||
dataObj.forEach(function(thisRow) {
|
||||
ignore.forEach(function(thisIgnore) {
|
||||
if (thisRow.hasOwnProperty(thisIgnore)) {
|
||||
delete thisRow[thisIgnore];
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
// Expand any fields we're expanding
|
||||
var expandExpand = function(row) {
|
||||
expand.forEach(function(thisExpand) {
|
||||
if (row.hasOwnProperty(thisExpand)) {
|
||||
if (!expanded.hasOwnProperty(thisExpand)) {
|
||||
expanded[thisExpand] = [];
|
||||
}
|
||||
var expandObj = row[thisExpand];
|
||||
Object.keys(expandObj).forEach(
|
||||
function(thisExpandCol) {
|
||||
var expColName = thisExpand + '_' + thisExpandCol;
|
||||
// Keep a list of fields that have been expanded
|
||||
// so we can create toggle links for them
|
||||
if (expanded[thisExpand].indexOf(expColName) == -1) {
|
||||
expanded[thisExpand].push(expColName);
|
||||
}
|
||||
expandObj[expColName] =
|
||||
expandObj[thisExpandCol];
|
||||
delete expandObj[thisExpandCol];
|
||||
}
|
||||
);
|
||||
$.extend(true, row, expandObj);
|
||||
delete row[thisExpand];
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// Build a de-duped list of all column names
|
||||
var allCols = {};
|
||||
core.map(function(thisCore) {
|
||||
allCols[thisCore] = 1;
|
||||
});
|
||||
var unionColumns = function(row) {
|
||||
Object.keys(row).forEach(function(col) {
|
||||
if (ignore.indexOf(col) == -1) {
|
||||
allCols[col] = 1;
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// Some rows may not have fields that other rows have,
|
||||
// so make sure all rows have the same fields
|
||||
var fillMissing = function(row) {
|
||||
Object.keys(allCols).forEach(function(thisCol) {
|
||||
row[thisCol] = (!row.hasOwnProperty(thisCol)) ?
|
||||
null :
|
||||
row[thisCol];
|
||||
});
|
||||
}
|
||||
|
||||
// Strip the expand prefix if it exists, we do this for display
|
||||
var stripPrefix = function(value) {
|
||||
expand.forEach(function(thisExpand) {
|
||||
var regex = new RegExp(thisExpand + '_', 'g');
|
||||
value = value.replace(regex, '');
|
||||
});
|
||||
return value;
|
||||
};
|
||||
|
||||
// Our 'render' function for borrowerlink
|
||||
var createBorrowerLink = function(data, type, row) {
|
||||
return '<a title="View borrower details" ' +
|
||||
'href="/cgi-bin/koha/members/moremember.pl?' +
|
||||
'borrowernumber='+row.borrowernumber+'">' +
|
||||
row.patron_firstname + ' ' + row.patron_surname +
|
||||
'</a>';
|
||||
};
|
||||
|
||||
// Render function for request ID
|
||||
var createRequestId = function(data, type, row) {
|
||||
return row.id_prefix + row.illrequest_id;
|
||||
};
|
||||
|
||||
// Render function for request status
|
||||
var createStatus = function(data, type, row, meta) {
|
||||
var origData = meta.settings.oInit.originalData;
|
||||
if (origData.length > 0) {
|
||||
return meta.settings.oInit.originalData[0].capabilities[
|
||||
row.status
|
||||
].name;
|
||||
} else {
|
||||
return '';
|
||||
}
|
||||
};
|
||||
|
||||
// Render function for creating a row's action link
|
||||
var createActionLink = function(data, type, row) {
|
||||
return '<a class="btn btn-default btn-sm" ' +
|
||||
'href="/cgi-bin/koha/ill/ill-requests.pl?' +
|
||||
'method=illview&illrequest_id=' +
|
||||
row.illrequest_id +
|
||||
'">Manage request</a>' +
|
||||
'</div>'
|
||||
};
|
||||
|
||||
// Columns that require special treatment
|
||||
var specialCols = {
|
||||
action: {
|
||||
name: '',
|
||||
func: createActionLink
|
||||
},
|
||||
borrowername: {
|
||||
name: 'Borrower',
|
||||
func: createBorrowerLink
|
||||
},
|
||||
illrequest_id: {
|
||||
name: 'Request number',
|
||||
func: createRequestId
|
||||
},
|
||||
status: {
|
||||
name: 'Status',
|
||||
func: createStatus
|
||||
},
|
||||
biblio_id: {
|
||||
name: 'Biblio number'
|
||||
},
|
||||
branchcode: {
|
||||
name: 'Branch code'
|
||||
}
|
||||
};
|
||||
|
||||
// Helper for handling prefilter column names
|
||||
function toColumnName(myVal) {
|
||||
return myVal
|
||||
.replace(/^filter/, '')
|
||||
.replace(/([A-Z])/g, "_$1")
|
||||
.replace(/^_/,'').toLowerCase();
|
||||
};
|
||||
|
||||
// Toggle request attributes in Illview
|
||||
$('#toggle_requestattributes').click(function() {
|
||||
$('#requestattributes').toggleClass('content_hidden');
|
||||
});
|
||||
|
||||
// Filter partner list
|
||||
$('#partner_filter').keyup(function() {
|
||||
var needle = $('#partner_filter').val();
|
||||
$('#partners > option').each(function() {
|
||||
var regex = new RegExp(needle, 'i');
|
||||
if (
|
||||
needle.length == 0 ||
|
||||
$(this).is(':selected') ||
|
||||
$(this).text().match(regex)
|
||||
) {
|
||||
$(this).show();
|
||||
} else {
|
||||
$(this).hide();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Get our data from the API and process it prior to passing
|
||||
// it to datatables
|
||||
var ajax = $.ajax(
|
||||
'/api/v1/illrequests?embed=metadata,patron,capabilities,branch'
|
||||
).done(function() {
|
||||
var data = JSON.parse(ajax.responseText);
|
||||
// Make a copy, we'll be removing columns next and need
|
||||
// to be able to refer to data that has been removed
|
||||
var dataCopy = $.extend(true, [], data);
|
||||
// Remove all columns we're not interested in
|
||||
removeIgnore(dataCopy);
|
||||
// Expand columns that need it and create an array
|
||||
// of all column names
|
||||
$.each(dataCopy, function(k, row) {
|
||||
expandExpand(row);
|
||||
unionColumns(row);
|
||||
});
|
||||
// Append any extra columns we need to tag on
|
||||
if (extra.length > 0) {
|
||||
extra.forEach(function(thisExtra) {
|
||||
allCols[thisExtra] = 1;
|
||||
});
|
||||
};
|
||||
// Different requests will have different columns,
|
||||
// make sure they all have the same
|
||||
$.each(dataCopy, function(k, row) {
|
||||
fillMissing(row);
|
||||
});
|
||||
|
||||
// Assemble an array of column definitions for passing
|
||||
// to datatables
|
||||
var colData = [];
|
||||
Object.keys(allCols).forEach(function(thisCol) {
|
||||
// We may have defined a pretty name for this column
|
||||
var colName = (
|
||||
specialCols.hasOwnProperty(thisCol) &&
|
||||
specialCols[thisCol].hasOwnProperty('name')
|
||||
) ?
|
||||
specialCols[thisCol].name :
|
||||
thisCol;
|
||||
// Create the table header for this column
|
||||
var str = '<th>' + stripPrefix(colName) + '</th>';
|
||||
$(str).appendTo('#illview-header');
|
||||
// Create the base column object
|
||||
var colObj = {
|
||||
name: thisCol,
|
||||
className: thisCol
|
||||
};
|
||||
// We may need to process the data going in this
|
||||
// column, so do it if necessary
|
||||
if (
|
||||
specialCols.hasOwnProperty(thisCol) &&
|
||||
specialCols[thisCol].hasOwnProperty('func')
|
||||
) {
|
||||
colObj.render = specialCols[thisCol].func;
|
||||
} else {
|
||||
colObj.data = thisCol
|
||||
}
|
||||
colData.push(colObj);
|
||||
});
|
||||
|
||||
// Create the toggle links for all metadata fields
|
||||
var links = [];
|
||||
expanded.metadata.forEach(function(thisExpanded) {
|
||||
if (core.indexOf(thisExpanded) == -1) {
|
||||
links.push(
|
||||
'<a href="#" class="toggle-vis" data-column="' +
|
||||
thisExpanded + '">' + stripPrefix(thisExpanded) +
|
||||
'</a>'
|
||||
);
|
||||
}
|
||||
});
|
||||
$('#column-toggle').append(links.join(' | '));
|
||||
|
||||
// Initialise the datatable
|
||||
var myTable = $('#ill-requests').DataTable($.extend(true, {}, dataTablesDefaults, {
|
||||
aoColumnDefs: [ // Last column shouldn't be sortable or searchable
|
||||
{
|
||||
aTargets: [ 'action' ],
|
||||
bSortable: false,
|
||||
bSearchable: false
|
||||
},
|
||||
],
|
||||
aaSorting: [[ 6, 'desc' ]], // Default sort, updated descending
|
||||
processing: true, // Display a message when manipulating
|
||||
language: {
|
||||
loadingRecords: "Please wait - loading requests...",
|
||||
zeroRecords: "No requests were found"
|
||||
},
|
||||
iDisplayLength: 10, // 10 results per page
|
||||
sPaginationType: "full_numbers", // Pagination display
|
||||
deferRender: true, // Improve performance on big datasets
|
||||
data: dataCopy,
|
||||
columns: colData,
|
||||
originalData: data // Enable render functions to access
|
||||
// our original data
|
||||
}));
|
||||
|
||||
// Reset columns to default
|
||||
var resetColumns = function() {
|
||||
Object.keys(allCols).forEach(function(thisCol) {
|
||||
myTable.column(thisCol + ':name').visible(core.indexOf(thisCol) != -1);
|
||||
});
|
||||
myTable.columns.adjust().draw(false);
|
||||
};
|
||||
|
||||
// Handle the click event on a toggle link
|
||||
$('a.toggle-vis').on('click', function(e) {
|
||||
e.preventDefault();
|
||||
var column = myTable.column(
|
||||
$(this).data('column') + ':name'
|
||||
);
|
||||
column.visible(!column.visible());
|
||||
});
|
||||
|
||||
// Reset column toggling
|
||||
$('#reset-toggle').click(function() {
|
||||
resetColumns();
|
||||
});
|
||||
|
||||
// Handle a prefilter request and do the prefiltering
|
||||
var filters = $('#ill-requests').data();
|
||||
if (typeof filters !== 'undefined') {
|
||||
var filterNames = Object.keys(filters).filter(
|
||||
function(thisData) {
|
||||
return thisData.match(/^filter/);
|
||||
}
|
||||
);
|
||||
filterNames.forEach(function(thisFilter) {
|
||||
var filterName = toColumnName(thisFilter) + ':name';
|
||||
var regex = '^'+filters[thisFilter]+'$';
|
||||
console.log(regex);
|
||||
myTable.columns(filterName).search(regex, true, false);
|
||||
});
|
||||
myTable.draw();
|
||||
}
|
||||
|
||||
// Initialise column hiding
|
||||
resetColumns();
|
||||
|
||||
}
|
||||
);
|
||||
|
||||
});
|
||||
//]]>
|
||||
</script>
|
||||
</head>
|
||||
|
||||
<body id="acq_suggestion" class="acq">
|
||||
[% INCLUDE 'header.inc' %]
|
||||
[% INCLUDE 'cat-search.inc' %]
|
||||
|
||||
<div id="breadcrumbs">
|
||||
<a href="/cgi-bin/koha/mainpage.pl">Home</a> ›
|
||||
[% IF query_type == 'create' %]
|
||||
<a href=[% parent %]>ILL requests</a> › New request
|
||||
[% ELSIF query_type == 'status' %]
|
||||
<a href=[% parent %]>ILL requests</a> › Status
|
||||
[% ELSE %]
|
||||
ILL requests
|
||||
[% END %]
|
||||
</div>
|
||||
|
||||
<div id="doc3" class="yui-t2">
|
||||
<div id="bd">
|
||||
<div id="yui-main">
|
||||
<div id="interlibraryloans" class="yui-b">
|
||||
[% INCLUDE 'ill-toolbar.inc' %]
|
||||
|
||||
[% IF whole.error %]
|
||||
<h1>Error performing operation</h1>
|
||||
<!-- Dispatch on Status -->
|
||||
<p>We encountered an error:</p>
|
||||
<p>
|
||||
<pre>[% whole.message %] ([% whole.status %])</pre>
|
||||
</p>
|
||||
[% END %]
|
||||
|
||||
[% IF query_type == 'create' %]
|
||||
<h1>New ILL request</h1>
|
||||
[% IF whole.stage == 'copyrightclearance' %]
|
||||
<div>
|
||||
<p>
|
||||
[% Koha.Preference('ILLModuleCopyrightClearance') %]
|
||||
</p>
|
||||
<a href="?method=create&stage=copyrightclearance&backend=[% whole.value.backend %]"
|
||||
class="btn btn-sm btn-default btn-group"><i class="fa fa-check">Yes</i></a>
|
||||
<a href="/cgi-bin/koha/ill/ill-requests.pl"
|
||||
class="btn btn-sm btn-default btn-group"><i class="fa fa-times">No</i></a>
|
||||
</div>
|
||||
[% ELSE %]
|
||||
[% PROCESS $whole.template %]
|
||||
[% END %]
|
||||
|
||||
[% ELSIF query_type == 'confirm' %]
|
||||
<h1>Confirm ILL request</h1>
|
||||
[% PROCESS $whole.template %]
|
||||
|
||||
[% ELSIF query_type == 'cancel' and !whole.error %]
|
||||
<h1>Cancel a confirmed request</h1>
|
||||
[% PROCESS $whole.template %]
|
||||
|
||||
[% ELSIF query_type == 'generic_confirm' %]
|
||||
<h1>Place request with partner libraries</h1>
|
||||
<!-- Start of GENERIC_EMAIL case -->
|
||||
[% IF whole.value.partners %]
|
||||
[% ill_url = here_link _ "?method=illview&illrequest_id=" _ request.illrequest_id %]
|
||||
<form method="POST" action=[% here_link %]>
|
||||
<fieldset class="rows">
|
||||
<legend>Interlibrary loan request details</legend>
|
||||
<ol>
|
||||
<li>
|
||||
<label for="partner_filter">Filter partner libraries:</label>
|
||||
<input type="text" id="partner_filter">
|
||||
</li>
|
||||
<li>
|
||||
<label for="partners">Select partner libraries:</label>
|
||||
<select size="5" multiple="true" id="partners"
|
||||
name="partners">
|
||||
[% FOREACH partner IN whole.value.partners %]
|
||||
<option value=[% partner.email %]>
|
||||
[% partner.branchcode _ " - " _ partner.surname %]
|
||||
</option>
|
||||
[% END %]
|
||||
</select>
|
||||
|
||||
</li>
|
||||
<li>
|
||||
<label for="subject">Subject Line</label>
|
||||
<input type="text" name="subject"
|
||||
id="subject" type="text"
|
||||
value="[% whole.value.draft.subject %]"/>
|
||||
</li>
|
||||
<li>
|
||||
<label for="body">Email text:</label>
|
||||
<textarea name="body" id="body" rows="20" cols="80">[% whole.value.draft.body %]</textarea>
|
||||
</li>
|
||||
</ol>
|
||||
<input type="hidden" value="generic_confirm" name="method">
|
||||
<input type="hidden" value="draft" name="stage">
|
||||
<input type="hidden" value="[% request.illrequest_id %]" name="illrequest_id">
|
||||
</fieldset>
|
||||
<fieldset class="action">
|
||||
<input type="submit" class="btn btn-default" value="Send email"/>
|
||||
<span><a href="[% ill_url %]" title="Return to request details">Cancel</a></span>
|
||||
</fieldset>
|
||||
</form>
|
||||
[% ELSE %]
|
||||
<fieldset class="rows">
|
||||
<legend>Interlibrary loan request details</legend>
|
||||
<p>No partners have been defined yet. Please create appropriate patron records (by default ILLLIBS category).</p>
|
||||
<p>Be sure to provide email addresses for these patrons.</p>
|
||||
<p><span><a href="[% ill_url %]" title="Return to request details">Cancel</a></span></p>
|
||||
</fieldset>
|
||||
[% END %]
|
||||
<!-- generic_confirm ends here -->
|
||||
|
||||
[% ELSIF query_type == 'edit_action' %]
|
||||
<form method="POST" action=[% here_link %]>
|
||||
<fieldset class="rows">
|
||||
<legend>Request details</legend>
|
||||
<ol>
|
||||
<li class="borrowernumber">
|
||||
<label for="borrowernumber">Borrower number:</label>
|
||||
<input name="borrowernumber" id="borrowernumber" type="text" value="[% request.borrowernumber %]">
|
||||
</li>
|
||||
<li class="biblio_id">
|
||||
<label for="biblio_id" class="biblio_id">Biblio number:</label>
|
||||
<input name="biblio_id" id="biblio_id" type="text" value="[% request.biblio_id %]">
|
||||
</li>
|
||||
<li class="branchcode">
|
||||
<label for="branchcode" class="branchcode">Branch:</label>
|
||||
<select name="branchcode" id="branch">
|
||||
[% FOREACH branch IN branches %]
|
||||
[% IF ( branch.branchcode == request.branchcode ) %]
|
||||
<option value="[% branch.branchcode %]" selected="selected">
|
||||
[% branch.branchname %]
|
||||
</option>
|
||||
[% ELSE %]
|
||||
<option value="[% branch.branchcode %]">
|
||||
[% branch.branchname %]
|
||||
</option>
|
||||
[% END %]
|
||||
[% END %]
|
||||
</select>
|
||||
</li>
|
||||
<li class="status">
|
||||
<label class="status">Status:</label>
|
||||
[% stat = request.status %]
|
||||
[% request.capabilities.$stat.name %]
|
||||
</li>
|
||||
<li class="updated">
|
||||
<label class="updated">Last updated:</label>
|
||||
[% request.updated %]
|
||||
</li>
|
||||
<li class="medium">
|
||||
<label class="medium">Request type:</label>
|
||||
[% request.medium %]
|
||||
</li>
|
||||
<li class="cost">
|
||||
<label class="cost">Cost:</label>
|
||||
[% request.cost %]
|
||||
</li>
|
||||
<li class="req_id">
|
||||
<label class="req_id">Request number:</label>
|
||||
[% request.id_prefix _ request.illrequest_id %]
|
||||
</li>
|
||||
<li class="notesstaff">
|
||||
<label for="notesstaff" class="notesstaff">Staff notes:</label>
|
||||
<textarea name="notesstaff" id="notesstaff" rows="5">[% request.notesstaff %]</textarea>
|
||||
</li>
|
||||
<li class="notesopac">
|
||||
<label for="notesopac" class="notesopac">Opac notes:</label>
|
||||
<textarea name="notesopac" id="notesopac" rows="5">[% request.notesopac %]</textarea>
|
||||
</li>
|
||||
</ol>
|
||||
</fieldset>
|
||||
<fieldset class="action">
|
||||
<input type="hidden" value="edit_action" name="method">
|
||||
<input type="hidden" value="form" name="stage">
|
||||
<input type="hidden" value="[% request.illrequest_id %]" name="illrequest_id">
|
||||
<input type="submit" value="Submit">
|
||||
<a class="cancel" href="/cgi-bin/koha/ill/ill-requests.pl?method=illview&illrequest_id=[% request.id %]">Cancel</a>
|
||||
</fieldset>
|
||||
</form>
|
||||
|
||||
[% ELSIF query_type == 'delete_confirm' %]
|
||||
|
||||
<div class="dialog alert">
|
||||
<h3>Are you sure you wish to delete this request?</h3>
|
||||
<p>
|
||||
<a class="btn btn-default btn-sm approve" href="?method=delete&illrequest_id=[% request.id %]&confirmed=1"><i class="fa fa-fw fa-check"></i>Yes</a>
|
||||
<a class="btn btn-default btn-sm deny" href="?method=illview&illrequest_id=[% request.id %]"><i class="fa fa-fw fa-remove"></i>No</a>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
|
||||
[% ELSIF query_type == 'illview' %]
|
||||
[% actions = request.available_actions %]
|
||||
[% capabilities = request.capabilities %]
|
||||
[% req_status = request.status %]
|
||||
<h1>Manage ILL request</h1>
|
||||
<div id="toolbar" class="btn-toolbar">
|
||||
<a title="Edit request" id="ill-toolbar-btn-edit-action" class="btn btn-sm btn-default" href="/cgi-bin/koha/ill/ill-requests.pl?method=edit_action&illrequest_id=[% request.illrequest_id %]">
|
||||
<span class="fa fa-pencil"></span>
|
||||
Edit request
|
||||
</a>
|
||||
[% FOREACH action IN actions %]
|
||||
[% IF action.method != 0 %]
|
||||
<a title="[% action.ui_method_name %]" id="ill-toolbar-btn-[% action.id | lower %]" class="btn btn-sm btn-default" href="/cgi-bin/koha/ill/ill-requests.pl?method=[% action.method %]&illrequest_id=[% request.illrequest_id %]">
|
||||
<span class="fa [% action.ui_method_icon %]"></span>
|
||||
[% action.ui_method_name %]
|
||||
</a>
|
||||
[% END %]
|
||||
[% END %]
|
||||
</div>
|
||||
<div id="ill-view-panel" class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<h3>Request details</h3>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<h4>Details from library</h4>
|
||||
<div class="rows">
|
||||
<div class="orderid">
|
||||
<span class="label orderid">Order ID:</span>
|
||||
[% request.orderid || "N/A" %]
|
||||
</div>
|
||||
<div class="borrowernumber">
|
||||
<span class="label borrowernumber">Borrower:</span>
|
||||
[% borrowerlink = "/cgi-bin/koha/members/moremember.pl"
|
||||
_ "?borrowernumber=" _ request.patron.borrowernumber %]
|
||||
<a href="[% borrowerlink %]" title="View borrower details">
|
||||
[% request.patron.firstname _ " "
|
||||
_ request.patron.surname _ " ["
|
||||
_ request.patron.cardnumber
|
||||
_ "]" %]
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="biblio_id">
|
||||
<span class="label biblio_id">Biblio number:</span>
|
||||
[% request.biblio_id || "N/A" %]
|
||||
</div>
|
||||
<div class="branchcode">
|
||||
<span class="label branchcode">Branch:</span>
|
||||
[% Branches.GetName(request.branchcode) %]
|
||||
</div>
|
||||
<div class="status">
|
||||
<span class="label status">Status:</span>
|
||||
[% capabilities.$req_status.name %]
|
||||
</div>
|
||||
<div class="updated">
|
||||
<span class="label updated">Last updated:</span>
|
||||
[% request.updated %]
|
||||
</div>
|
||||
<div class="medium">
|
||||
<span class="label medium">Request type:</span>
|
||||
[% request.medium %]
|
||||
</div>
|
||||
<div class="cost">
|
||||
<span class="label cost">Cost:</span>
|
||||
[% request.cost || "N/A" %]
|
||||
</div>
|
||||
<div class="req_id">
|
||||
<span class="label req_id">Request number:</span>
|
||||
[% request.id_prefix _ request.illrequest_id %]
|
||||
</div>
|
||||
<div class="notesstaff">
|
||||
<span class="label notes_staff">Staff notes:</span>
|
||||
<pre>[% request.notesstaff %]</pre>
|
||||
</div>
|
||||
<div class="notesopac">
|
||||
<span class="label notes_opac">Notes:</span>
|
||||
<pre>[% request.notesopac %]</pre>
|
||||
</div>
|
||||
</div>
|
||||
<div class="rows">
|
||||
<h4>Details from supplier ([% request.backend %])</h4>
|
||||
[% FOREACH meta IN request.metadata %]
|
||||
<div class="requestmeta-[% meta.key %]">
|
||||
<span class="label">[% meta.key %]:</span>
|
||||
[% meta.value %]
|
||||
</div>
|
||||
[% END %]
|
||||
</div>
|
||||
<div class="rows">
|
||||
<h3><a id="toggle_requestattributes" href="#">Toggle full supplier metadata</a></h3>
|
||||
<div id="requestattributes" class="content_hidden">
|
||||
[% FOREACH attr IN request.illrequestattributes %]
|
||||
<div class="requestattr-[% attr.type %]">
|
||||
<span class="label">[% attr.type %]:</span>
|
||||
[% attr.value %]
|
||||
</div>
|
||||
[% END %]
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
[% ELSIF query_type == 'illlist' %]
|
||||
<!-- illlist -->
|
||||
<h1>View ILL requests</h1>
|
||||
<div id="results">
|
||||
<h3>Details for all requests</h3>
|
||||
|
||||
<div id="column-toggle">
|
||||
Toggle additional columns:
|
||||
</div>
|
||||
<div id="reset-toggle"><a href="#">Reset toggled columns</a></div>
|
||||
|
||||
<table
|
||||
[% FOREACH filter IN prefilters %]
|
||||
data-filter-[% filter.name %]="[% filter.value %]"
|
||||
[% END %]
|
||||
id="ill-requests">
|
||||
<thead>
|
||||
<tr id="illview-header"></tr>
|
||||
</thead>
|
||||
<tbody id="illview-body">
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
[% ELSE %]
|
||||
<!-- Custom Backend Action -->
|
||||
[% INCLUDE $whole.template %]
|
||||
|
||||
[% END %]
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
[% TRY %]
|
||||
[% PROCESS backend_jsinclude %]
|
||||
[% CATCH %]
|
||||
[% END %]
|
||||
|
||||
[% INCLUDE 'intranet-bottom.inc' %]
|
||||
|
|
@ -63,6 +63,11 @@
|
|||
<li>
|
||||
<a class="icon_general icon_authorities" href="/cgi-bin/koha/authorities/authorities-home.pl">Authorities</a>
|
||||
</li>
|
||||
[% IF Koha.Preference('ILLModule') %]
|
||||
<li>
|
||||
<a class="icon_general icon_ill" href="/cgi-bin/koha/ill/ill-requests.pl">ILL requests</a>
|
||||
</li>
|
||||
[% END %]
|
||||
</ul>
|
||||
</div><!-- /area-list-left -->
|
||||
</div><!-- /yui-u first -->
|
||||
|
|
|
|||
|
|
@ -104,6 +104,15 @@
|
|||
[% END %]
|
||||
<a href="/cgi-bin/koha/opac-discharge.pl">ask for a discharge</a></li>
|
||||
[% END %]
|
||||
|
||||
[% IF Koha.Preference( 'ILLModule' ) == 1 %]
|
||||
[% IF ( illrequestsview ) %]
|
||||
<li class="active">
|
||||
[% ELSE %]
|
||||
<li>
|
||||
[% END %]
|
||||
<a href="/cgi-bin/koha/opac-illrequests.pl">your interlibrary loan requests</a></li>
|
||||
[% END %]
|
||||
</ul>
|
||||
</div>
|
||||
[% END %]
|
||||
|
|
|
|||
|
|
@ -0,0 +1,221 @@
|
|||
[% USE Koha %]
|
||||
[% USE Branches %]
|
||||
[% INCLUDE 'doc-head-open.inc' %]
|
||||
<title>[% IF ( LibraryNameTitle ) %][% LibraryNameTitle %][% ELSE %]Koha online[% END %] catalog › Your Interlibrary loan requests</title>[% INCLUDE 'doc-head-close.inc' %]
|
||||
[% BLOCK cssinclude %][% END %]
|
||||
</head>
|
||||
[% INCLUDE 'bodytag.inc' bodyid='opac-illrequests' bodyclass='scrollto' %]
|
||||
[% BLOCK messages %]
|
||||
[% IF message == "1" %]
|
||||
<div class="alert alert-success" role="alert">Request updated</div>
|
||||
[% ELSIF message == "2" %]
|
||||
<div class="alert alert-success" role="alert">Request placed</div>
|
||||
[% END %]
|
||||
[% END %]
|
||||
[% INCLUDE 'masthead.inc' %]
|
||||
<div class="main">
|
||||
<ul class="breadcrumb noprint">
|
||||
<li><a href="/cgi-bin/koha/opac-main.pl">Home</a> <span class="divider">›</span></li>
|
||||
[% IF ( loggedinusername ) %]
|
||||
<li><a href="/cgi-bin/koha/opac-user.pl">[% USER_INFO.title %] [% USER_INFO.firstname %] [% USER_INFO.surname %]</a> <span class="divider">›</span></li>
|
||||
[% END %]
|
||||
|
||||
[% IF method != 'list' %]
|
||||
<li><a href="/cgi-bin/koha/opac-illrequests.pl">Interlibrary loan requests</a> <span class="divider">›</span></li>
|
||||
[% IF method == 'create' %]
|
||||
<li>New Interlibrary loan request</li>
|
||||
[% ELSIF method == 'view' %]
|
||||
<li>View Interlibrary loan request</li>
|
||||
[% END %]
|
||||
[% ELSE %]
|
||||
<li>Interlibrary loan requests</li>
|
||||
[% END %]
|
||||
|
||||
</ul> <!-- / .breadcrumb -->
|
||||
|
||||
<div class="container-fluid">
|
||||
<div class="row-fluid">
|
||||
[% IF ( OpacNav||loggedinusername ) && !print %]
|
||||
<div class="span2">
|
||||
<div id="navigation">
|
||||
[% INCLUDE 'navigation.inc' IsPatronPage=1 %]
|
||||
</div>
|
||||
</div>
|
||||
[% END %]
|
||||
|
||||
[% IF ( OpacNav||loggedinusername ) %]
|
||||
<div class="span10">
|
||||
[% ELSE %]
|
||||
<div class="span12">
|
||||
[% END %]
|
||||
<div id="illrequests" class="maincontent">
|
||||
[% IF method == 'create' %]
|
||||
<h2>New Interlibrary loan request</h2>
|
||||
[% INCLUDE messages %]
|
||||
[% IF backends %]
|
||||
<form method="post" id="illrequestcreate-form" novalidate="novalidate">
|
||||
<fieldset class="rows">
|
||||
<label for="backend">Provider:</label>
|
||||
<select name="backend">
|
||||
[% FOREACH backend IN backends %]
|
||||
<option value="[% backend %]">[% backend %]</option>
|
||||
[% END %]
|
||||
</select>
|
||||
</fieldset>
|
||||
<fieldset class="action">
|
||||
<input type="hidden" name="method" value="create">
|
||||
<input type="submit" name="create_select_backend" value="Next »">
|
||||
</fieldset>
|
||||
</form>
|
||||
[% ELSE %]
|
||||
[% PROCESS $whole.opac_template %]
|
||||
[% END %]
|
||||
[% ELSIF method == 'list' %]
|
||||
<h2>Interlibrary loan requests</h2>
|
||||
[% INCLUDE messages %]
|
||||
|
||||
<div id="illrequests-create-button" class="dropdown btn-group">
|
||||
[% IF backends.size > 1 %]
|
||||
<button class="btn btn-default dropdown-toggle" type="button" id="ill-backend-dropdown" data-toggle="dropdown" aria-haspopup="true" aria-expanded="true">
|
||||
<i class="fa fa-plus"></i> Create a new request <span class="caret"></span>
|
||||
</button>
|
||||
<ul id="backend-dropdown-options" class="dropdown-menu nojs" aria-labelledby="ill-backend-dropdown">
|
||||
[% FOREACH backend IN backends %]
|
||||
<li><a href="/cgi-bin/koha/opac-illrequests.pl?method=create&backend=[% backend %]">[% backend %]</a></li>
|
||||
[% END %]
|
||||
</ul>
|
||||
[% ELSE %]
|
||||
<a id="ill-new" class="btn btn-default" href="/cgi-bin/koha/opac-illrequests.pl?method=create&backend=[% backends.0 %]">
|
||||
<i class="fa fa-plus"></i> Create a new request
|
||||
</a>
|
||||
[% END %]
|
||||
</div>
|
||||
|
||||
<table id="illrequestlist" class="table table-bordered table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Author</th>
|
||||
<th>Title</th>
|
||||
<th>Requested from</th>
|
||||
<th>Request type</th>
|
||||
<th>Status</th>
|
||||
<th>Request placed</th>
|
||||
<th>Last updated</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
[% FOREACH request IN requests %]
|
||||
[% status = request.status %]
|
||||
<tr>
|
||||
<td>[% request.metadata.Author || 'N/A' %]</td>
|
||||
<td>[% request.metadata.Title || 'N/A' %]</td>
|
||||
<td>[% request.backend %]</td>
|
||||
<td>[% request.medium %]</td>
|
||||
<td>[% request.capabilities.$status.name %]</td>
|
||||
<td>[% request.placed %]</td>
|
||||
<td>[% request.updated %]</td>
|
||||
<td>
|
||||
<a href="/cgi-bin/koha/opac-illrequests.pl?method=view&illrequest_id=[% request.id %]" class="btn btn-default btn-small pull-right">View</a>
|
||||
</td>
|
||||
</tr>
|
||||
[% END %]
|
||||
</tbody>
|
||||
</table>
|
||||
[% ELSIF method == 'view' %]
|
||||
<h2>View Interlibrary loan request</h2>
|
||||
[% INCLUDE messages %]
|
||||
[% status = request.status %]
|
||||
<form method="post" action="?method=update" id="illrequestupdate-form" novalidate="novalidate">
|
||||
<fieldset class="rows">
|
||||
<legend id="library_legend">Details from library</legend>
|
||||
<ol>
|
||||
<li>
|
||||
<label for="backend">Requested from:</label>
|
||||
[% request.backend %]
|
||||
</li>
|
||||
[% IF request.biblio_id %]
|
||||
<li>
|
||||
<label for="biblio">Requested item:</label>
|
||||
<a href="/cgi-bin/koha/opac-detail.pl?biblionumber=[% request.biblio_id %]">Click here to view</a>
|
||||
</li>
|
||||
[% END %]
|
||||
<li>
|
||||
<label for="branchcode">Collection library:</label>
|
||||
[% Branches.GetName(request.branchcode) %]
|
||||
</li>
|
||||
<li>
|
||||
<label for="status">Status:</label>
|
||||
[% request.capabilities.$status.name %]
|
||||
</li>
|
||||
<li>
|
||||
<label for="medium">Request type:</label>
|
||||
[% request.medium %]
|
||||
</li>
|
||||
<li>
|
||||
<label for="placed">Request placed:</label>
|
||||
[% request.placed %]
|
||||
</li>
|
||||
<li>
|
||||
<label for="updated">Last updated:</label>
|
||||
[% request.updated %]
|
||||
</li>
|
||||
<li>
|
||||
<label for="notesopac">Notes:</label>
|
||||
[% IF !request.completed %]
|
||||
<textarea name="notesopac" rows="5" cols="50">[% request.notesopac %]</textarea>
|
||||
[% ELSE %]
|
||||
[% request.notesopac %]
|
||||
[% END %]
|
||||
</li>
|
||||
</ol>
|
||||
</fieldset>
|
||||
<div class="rows">
|
||||
<legend id="backend_legend">Details from [% request.backend %]</legend>
|
||||
[% FOREACH meta IN request.metadata %]
|
||||
<div class="requestattr-[% meta.key %]">
|
||||
<span class="label">[% meta.key %]:</span>
|
||||
[% meta.value || 'N/A' %]
|
||||
</div>
|
||||
[% END %]
|
||||
</div>
|
||||
<fieldset class="action illrequest-actions">
|
||||
<input type="hidden" name="illrequest_id" value="[% request.illrequest_id %]">
|
||||
<input type="hidden" name="method" value="update">
|
||||
[% IF !request.completed %]
|
||||
[% IF request.status == "NEW" %]
|
||||
<a class="cancel-illrequest btn btn-danger" href="/cgi-bin/koha/opac-illrequests.pl?method=cancreq&illrequest_id=[% request.illrequest_id %]">Request cancellation</a>
|
||||
[% END %]
|
||||
<input type="submit" class="update-illrequest btn btn-default" value="Submit modifications">
|
||||
[% END %]
|
||||
<span class="cancel"><a href="/cgi-bin/koha/opac-illrequests.pl">Cancel</a></span>
|
||||
</fieldset>
|
||||
</form>
|
||||
[% END %]
|
||||
</div> <!-- / .maincontent -->
|
||||
</div> <!-- / .span10/12 -->
|
||||
</div> <!-- / .row-fluid -->
|
||||
</div> <!-- / .container-fluid -->
|
||||
</div> <!-- / .main -->
|
||||
|
||||
[% INCLUDE 'opac-bottom.inc' %]
|
||||
|
||||
[% BLOCK jsinclude %]
|
||||
[% INCLUDE 'datatables.inc' %]
|
||||
<script type="text/javascript">
|
||||
//<![CDATA[
|
||||
$("#illrequestlist").dataTable($.extend(true, {}, dataTablesDefaults, {
|
||||
"aoColumnDefs": [
|
||||
{ "aTargets": [ -1 ], "bSortable": false, "bSearchable": false }
|
||||
],
|
||||
"aaSorting": [[ 3, "desc" ]],
|
||||
"deferRender": true
|
||||
}));
|
||||
$("#backend-dropdown-options").removeClass("nojs");
|
||||
//]]>
|
||||
</script>
|
||||
[% TRY %]
|
||||
[% PROCESS backend_jsinclude %]
|
||||
[% CATCH %]
|
||||
[% END %]
|
||||
[% END %]
|
||||
|
|
@ -253,14 +253,30 @@ href="/cgi-bin/koha/opac-rss.pl?[% query_cgi %][% limit_cgi |html %]" />
|
|||
[% INCLUDE 'page-numbers.inc' %]
|
||||
[% END # / IF total %]
|
||||
|
||||
[% IF Koha.Preference( 'suggestion' ) == 1 %]
|
||||
[% IF Koha.Preference( 'AnonSuggestions' ) == 1 %]
|
||||
<div class="suggestion">Not finding what you're looking for?<br /> Make a <a href="/cgi-bin/koha/opac-suggestions.pl?op=add">purchase suggestion</a></div>
|
||||
[% ELSE %]
|
||||
[% IF ( loggedinusername ) %]<div class="suggestion">Not finding what you're looking for?<br /> Make a <a href="/cgi-bin/koha/opac-suggestions.pl?op=add">purchase suggestion</a></div>[% END %]
|
||||
[% END %]
|
||||
[% IF
|
||||
Koha.Preference( 'suggestion' ) == 1 &&
|
||||
(
|
||||
Koha.Preference( 'AnonSuggestions' ) == 1 ||
|
||||
loggedinusername ||
|
||||
Koha.Preference( 'ILLModule' ) == 1
|
||||
)
|
||||
%]
|
||||
<div class="suggestion">
|
||||
Not finding what you're looking for?
|
||||
<ul>
|
||||
[% IF Koha.Preference( 'AnonSuggestions' ) == 1 %]
|
||||
<li>Make a <a href="/cgi-bin/koha/opac-suggestions.pl?op=add">purchase suggestion</a></li>
|
||||
[% ELSE %]
|
||||
[% IF ( loggedinusername ) %]
|
||||
<li>Make a <a href="/cgi-bin/koha/opac-suggestions.pl?op=add">purchase suggestion</a></li>
|
||||
[% END %]
|
||||
[% END %]
|
||||
[% IF Koha.Preference( 'ILLModule' ) == 1 && loggedinusername %]
|
||||
<li>Make an <a href="/cgi-bin/koha/opac-illrequests.pl?op=create">Interlibrary loan request</a></li>
|
||||
[% END %]
|
||||
</ul>
|
||||
</div>
|
||||
[% END %]
|
||||
|
||||
</div> <!-- / #grouped-results -->
|
||||
</div> <!-- /.span10/12 -->
|
||||
</div> <!-- / .row-fluid -->
|
||||
|
|
|
|||
|
|
@ -562,16 +562,29 @@
|
|||
|
||||
[% END # / IF total %]
|
||||
|
||||
[% IF Koha.Preference( 'suggestion' ) == 1 %]
|
||||
[% IF Koha.Preference( 'AnonSuggestions' ) == 1 %]
|
||||
<div class="suggestion">Not finding what you're looking for?<br /> Make a <a href="/cgi-bin/koha/opac-suggestions.pl?op=add">purchase suggestion</a></div>
|
||||
[% ELSE %]
|
||||
[% IF ( loggedinusername ) %]
|
||||
<div class="suggestion">
|
||||
Not finding what you're looking for?<br /> Make a <a href="/cgi-bin/koha/opac-suggestions.pl?op=add">purchase suggestion</a>
|
||||
</div>
|
||||
[% END %]
|
||||
[% END %]
|
||||
[% IF
|
||||
Koha.Preference( 'suggestion' ) == 1 &&
|
||||
(
|
||||
Koha.Preference( 'AnonSuggestions' ) == 1 ||
|
||||
loggedinusername ||
|
||||
Koha.Preference( 'ILLModule' ) == 1
|
||||
)
|
||||
%]
|
||||
<div class="suggestion">
|
||||
Not finding what you're looking for?
|
||||
<ul>
|
||||
[% IF Koha.Preference( 'AnonSuggestions' ) == 1 %]
|
||||
<li>Make a <a href="/cgi-bin/koha/opac-suggestions.pl?op=add">purchase suggestion</a></li>
|
||||
[% ELSE %]
|
||||
[% IF ( loggedinusername ) %]
|
||||
<li>Make a <a href="/cgi-bin/koha/opac-suggestions.pl?op=add">purchase suggestion</a></li>
|
||||
[% END %]
|
||||
[% END %]
|
||||
[% IF Koha.Preference( 'ILLModule' ) == 1 && loggedinusername %]
|
||||
<li>Make an <a href="/cgi-bin/koha/opac-illrequests.pl?op=create">Interlibrary loan request</a></li>
|
||||
[% END %]
|
||||
</ul>
|
||||
</div>
|
||||
[% END %]
|
||||
</div> <!-- / #userresults -->
|
||||
</div> <!-- /.span10/12 -->
|
||||
|
|
|
|||
|
|
@ -2508,6 +2508,44 @@ a.reviewlink:visited {
|
|||
font-size: 90%;
|
||||
}
|
||||
|
||||
#illrequests {
|
||||
.illrequest-actions {
|
||||
.btn,
|
||||
.cancel {
|
||||
margin-right: 5px;
|
||||
}
|
||||
padding-top: 20px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
#illrequests-create-button {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
.bg-info {
|
||||
overflow: auto;
|
||||
position: relative;
|
||||
}
|
||||
.bg-info {
|
||||
#search-summary {
|
||||
-webkit-transform: translateY(-50%);
|
||||
-ms-transform: translateY(-50%);
|
||||
-o-transform: translateY(-50%);
|
||||
transform: translateY(-50%);
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
}
|
||||
|
||||
}
|
||||
#freeform-fields .custom-name {
|
||||
float: left;
|
||||
width: 8em;
|
||||
margin-right: 1em;
|
||||
text-align: right;
|
||||
}
|
||||
.dropdown:hover .dropdown-menu.nojs {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
#dc_fieldset {
|
||||
border: 1px solid #dddddd;
|
||||
border-width: 1px;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,129 @@
|
|||
#!/usr/bin/perl
|
||||
|
||||
# Copyright 2017 PTFS-Europe Ltd
|
||||
#
|
||||
# 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 CGI qw ( -utf8 );
|
||||
use C4::Auth;
|
||||
use C4::Koha;
|
||||
use C4::Output;
|
||||
|
||||
use Koha::Illrequests;
|
||||
use Koha::Libraries;
|
||||
use Koha::Patrons;
|
||||
|
||||
my $query = new CGI;
|
||||
|
||||
# Grab all passed data
|
||||
# 'our' since Plack changes the scoping
|
||||
# of 'my'
|
||||
our $params = $query->Vars();
|
||||
|
||||
# if illrequests is disabled, leave immediately
|
||||
if ( ! C4::Context->preference('ILLModule') ) {
|
||||
print $query->redirect("/cgi-bin/koha/errors/404.pl");
|
||||
exit;
|
||||
}
|
||||
|
||||
my ( $template, $loggedinuser, $cookie ) = get_template_and_user({
|
||||
template_name => "opac-illrequests.tt",
|
||||
query => $query,
|
||||
type => "opac",
|
||||
authnotrequired => ( C4::Context->preference("OpacPublic") ? 1 : 0 ),
|
||||
});
|
||||
|
||||
my $op = $params->{'method'} || 'list';
|
||||
|
||||
if ( $op eq 'list' ) {
|
||||
|
||||
my $requests = Koha::Illrequests->search(
|
||||
{ borrowernumber => $loggedinuser }
|
||||
);
|
||||
my $req = Koha::Illrequest->new;
|
||||
$template->param(
|
||||
requests => $requests,
|
||||
backends => $req->available_backends
|
||||
);
|
||||
|
||||
} elsif ( $op eq 'view') {
|
||||
my $request = Koha::Illrequests->find({
|
||||
borrowernumber => $loggedinuser,
|
||||
illrequest_id => $params->{illrequest_id}
|
||||
});
|
||||
$template->param(
|
||||
request => $request
|
||||
);
|
||||
|
||||
} elsif ( $op eq 'update') {
|
||||
my $request = Koha::Illrequests->find({
|
||||
borrowernumber => $loggedinuser,
|
||||
illrequest_id => $params->{illrequest_id}
|
||||
});
|
||||
$request->notesopac($params->{notesopac})->store;
|
||||
print $query->redirect(
|
||||
'/cgi-bin/koha/opac-illrequests.pl?method=view&illrequest_id=' .
|
||||
$params->{illrequest_id} .
|
||||
'&message=1'
|
||||
);
|
||||
} elsif ( $op eq 'cancreq') {
|
||||
my $request = Koha::Illrequests->find({
|
||||
borrowernumber => $loggedinuser,
|
||||
illrequest_id => $params->{illrequest_id}
|
||||
});
|
||||
$request->status('CANCREQ')->store;
|
||||
print $query->redirect(
|
||||
'/cgi-bin/koha/opac-illrequests.pl?method=view&illrequest_id=' .
|
||||
$params->{illrequest_id} .
|
||||
'&message=1'
|
||||
);
|
||||
|
||||
} elsif ( $op eq 'create' ) {
|
||||
if (!$params->{backend}) {
|
||||
my $req = Koha::Illrequest->new;
|
||||
$template->param(
|
||||
backends => $req->available_backends
|
||||
);
|
||||
} else {
|
||||
my $request = Koha::Illrequest->new
|
||||
->load_backend($params->{backend});
|
||||
$params->{cardnumber} = Koha::Patrons->find({
|
||||
borrowernumber => $loggedinuser
|
||||
})->cardnumber;
|
||||
my $backend_result = $request->backend_create($params);
|
||||
$template->param(
|
||||
media => [ "Book", "Article", "Journal" ],
|
||||
branches => Koha::Libraries->search->unblessed,
|
||||
whole => $backend_result,
|
||||
request => $request
|
||||
);
|
||||
if ($backend_result->{stage} eq 'commit') {
|
||||
print $query->redirect('/cgi-bin/koha/opac-illrequests.pl?message=2');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
$template->param(
|
||||
message => $params->{message},
|
||||
illrequestsview => 1,
|
||||
method => $op
|
||||
);
|
||||
|
||||
output_html_with_http_headers $query, $cookie, $template->output;
|
||||
|
|
@ -0,0 +1,473 @@
|
|||
#!/usr/bin/perl
|
||||
|
||||
# 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 Koha::Database;
|
||||
use t::lib::Mocks;
|
||||
use t::lib::TestBuilder;
|
||||
use Test::MockObject;
|
||||
use Test::Exception;
|
||||
|
||||
use Test::More tests => 5;
|
||||
|
||||
my $schema = Koha::Database->new->schema;
|
||||
my $builder = t::lib::TestBuilder->new;
|
||||
use_ok('Koha::Illrequest::Config');
|
||||
|
||||
my $base_limits = {
|
||||
branch => { CPL => { count => 1, method => 'annual' } },
|
||||
brw_cat => { A => { count => -1, method => 'active' } },
|
||||
default => { count => 10, method => 'annual' },
|
||||
};
|
||||
|
||||
my $base_censorship = { censor_notes_staff => 1, censor_reply_date => 1 };
|
||||
|
||||
subtest 'Basics' => sub {
|
||||
|
||||
plan tests => 19;
|
||||
|
||||
$schema->storage->txn_begin;
|
||||
|
||||
t::lib::Mocks::mock_preference("UnmediatedILL", 0);
|
||||
t::lib::Mocks::mock_config("interlibrary_loans", {});
|
||||
|
||||
my $config = Koha::Illrequest::Config->new;
|
||||
isa_ok($config, "Koha::Illrequest::Config",
|
||||
"Correctly create and load a config object.");
|
||||
|
||||
# backend:
|
||||
is($config->backend, undef, "backend: Undefined backend is undefined.");
|
||||
is($config->backend("Mock"), "Mock", "backend: setter works.");
|
||||
is($config->backend, "Mock", "backend: setter is persistent.");
|
||||
|
||||
# backend_dir:
|
||||
is($config->backend_dir, undef, "backend_dir: Undefined backend_dir is undefined.");
|
||||
is($config->backend_dir("/tmp/"), "/tmp/", "backend_dir: setter works.");
|
||||
is($config->backend_dir, "/tmp/", "backend_dir: setter is persistent.");
|
||||
|
||||
# partner_code:
|
||||
is($config->partner_code, "ILLLIBS", "partner_code: Undefined partner_code is undefined.");
|
||||
is($config->partner_code("ILLLIBSTST"), "ILLLIBSTST", "partner_code: setter works.");
|
||||
is($config->partner_code, "ILLLIBSTST", "partner_code: setter is persistent.");
|
||||
|
||||
# limits:
|
||||
is_deeply($config->limits, {}, "limits: Undefined limits is empty hash.");
|
||||
is_deeply($config->limits($base_limits), $base_limits, "limits: setter works.");
|
||||
is_deeply($config->limits, $base_limits, "limits: setter is persistent.");
|
||||
|
||||
# censorship:
|
||||
is_deeply($config->censorship, { censor_notes_staff => 0, censor_reply_date => 0 },
|
||||
"censorship: Undefined censorship is default values.");
|
||||
is_deeply($config->censorship($base_censorship), $base_censorship, "censorship: setter works.");
|
||||
is_deeply($config->censorship, $base_censorship, "censorship: setter is persistent.");
|
||||
|
||||
# getLimitRules
|
||||
dies_ok( sub { $config->getLimitRules("FOO") }, "getLimitRules: die if not correct type.");
|
||||
is_deeply($config->getLimitRules("brw_cat"), {
|
||||
A => { count => -1, method => 'active' },
|
||||
default => { count => 10, method => 'annual' },
|
||||
}, "getLimitRules: fetch brw_cat limits.");
|
||||
is_deeply($config->getLimitRules("branch"), {
|
||||
CPL => { count => 1, method => 'annual' },
|
||||
default => { count => 10, method => 'annual' },
|
||||
}, "getLimitRules: fetch brw_cat limits.");
|
||||
|
||||
$schema->storage->txn_rollback;
|
||||
};
|
||||
|
||||
# _load_unit_config:
|
||||
|
||||
subtest '_load_unit_config' => sub {
|
||||
|
||||
plan tests => 10;
|
||||
|
||||
$schema->storage->txn_begin;
|
||||
|
||||
my $config = Koha::Illrequest::Config->new;
|
||||
|
||||
dies_ok(
|
||||
sub { Koha::Illrequest::Config::_load_unit_config({
|
||||
id => 'durineadu', type => 'baz'
|
||||
}) },
|
||||
"_load_unit_config: die if ID is not default, and type is not branch or brw_cat."
|
||||
);
|
||||
is_deeply(
|
||||
Koha::Illrequest::Config::_load_unit_config({
|
||||
unit => {}, id => 'default', config => {}, test => 1
|
||||
}), {}, "_load_unit_config: invocation without id returns unmodified config."
|
||||
);
|
||||
|
||||
is_deeply(
|
||||
Koha::Illrequest::Config::_load_unit_config({
|
||||
unit => { api_key => 'foo', api_auth => 'bar' },
|
||||
id => "CPL", type => 'branch', config => {}
|
||||
}),
|
||||
{ credentials => { api_keys => { CPL => { api_key => 'foo', api_auth => 'bar' } } } },
|
||||
"_load_unit_config: add auth values."
|
||||
);
|
||||
|
||||
# Populate request_limits
|
||||
is_deeply(
|
||||
Koha::Illrequest::Config::_load_unit_config({
|
||||
unit => { request_limit => [ 'heelo', 1234 ] },
|
||||
id => "CPL", type => 'branch', config => {}
|
||||
}), {}, "_load_unit_config: invalid request_limit structure."
|
||||
);
|
||||
is_deeply(
|
||||
Koha::Illrequest::Config::_load_unit_config({
|
||||
unit => { request_limit => { method => 'eudiren', count => '-5465' } },
|
||||
id => "CPL", type => 'branch', config => {}
|
||||
}), {}, "_load_unit_config: invalid method & count."
|
||||
);
|
||||
is_deeply(
|
||||
Koha::Illrequest::Config::_load_unit_config({
|
||||
unit => { request_limit => { method => 'annual', count => 6 } },
|
||||
id => "default", config => {}
|
||||
}),
|
||||
{ limits => { default => { method => 'annual', count => 6 } } },
|
||||
"_load_unit_config: correct default request_limits."
|
||||
);
|
||||
|
||||
# Populate prefix
|
||||
is_deeply(
|
||||
Koha::Illrequest::Config::_load_unit_config({
|
||||
unit => { prefix => 'Foo-ill' },
|
||||
id => "default", config => {}
|
||||
}),
|
||||
{ prefixes => { default => 'Foo-ill' } },
|
||||
"_load_unit_config: correct default prefix."
|
||||
);
|
||||
is_deeply(
|
||||
Koha::Illrequest::Config::_load_unit_config({
|
||||
unit => { prefix => 'Foo-ill' },
|
||||
id => "A", config => {}, type => 'brw_cat'
|
||||
}),
|
||||
{ prefixes => { brw_cat => { A => 'Foo-ill' } } },
|
||||
"_load_unit_config: correct brw_cat prefix."
|
||||
);
|
||||
|
||||
# Populate digital_recipient
|
||||
is_deeply(
|
||||
Koha::Illrequest::Config::_load_unit_config({
|
||||
unit => { digital_recipient => 'borrower' },
|
||||
id => "default", config => {}
|
||||
}),
|
||||
{ digital_recipients => { default => 'borrower' } },
|
||||
"_load_unit_config: correct default digital_recipient."
|
||||
);
|
||||
is_deeply(
|
||||
Koha::Illrequest::Config::_load_unit_config({
|
||||
unit => { digital_recipient => 'branch' },
|
||||
id => "A", config => {}, type => 'brw_cat'
|
||||
}),
|
||||
{ digital_recipients => { brw_cat => { A => 'branch' } } },
|
||||
"_load_unit_config: correct brw_cat digital_recipient."
|
||||
);
|
||||
|
||||
$schema->storage->txn_rollback;
|
||||
};
|
||||
|
||||
# _load_configuration:
|
||||
|
||||
# We have already tested _load_unit_config, so we are reasonably confident
|
||||
# that the per-branch, per-borrower_category & default sections parsing is
|
||||
# good.
|
||||
#
|
||||
# Now we need to ensure that Arrays & Hashes are handled correctly, that
|
||||
# censorship & ill partners are loaded correctly and that the backend
|
||||
# directory is set correctly.
|
||||
|
||||
subtest '_load_configuration' => sub {
|
||||
|
||||
plan tests => 9;
|
||||
|
||||
$schema->storage->txn_begin;
|
||||
|
||||
my $config = Koha::Illrequest::Config->new;
|
||||
|
||||
# Return basic configuration
|
||||
is_deeply(
|
||||
Koha::Illrequest::Config::_load_configuration({}, 0),
|
||||
{
|
||||
backend_directory => undef,
|
||||
censorship => {
|
||||
censor_notes_staff => 0,
|
||||
censor_reply_date => 0,
|
||||
},
|
||||
limits => {},
|
||||
digital_recipients => {},
|
||||
prefixes => {},
|
||||
partner_code => 'ILLLIBS',
|
||||
raw_config => {},
|
||||
},
|
||||
"load_configuration: return the base configuration."
|
||||
);
|
||||
|
||||
# Return correct backend_dir
|
||||
is_deeply(
|
||||
Koha::Illrequest::Config::_load_configuration({ backend_directory => '/tmp/' }, 0),
|
||||
{
|
||||
backend_directory => '/tmp/',
|
||||
censorship => {
|
||||
censor_notes_staff => 0,
|
||||
censor_reply_date => 0,
|
||||
},
|
||||
limits => {},
|
||||
digital_recipients => {},
|
||||
prefixes => {},
|
||||
partner_code => 'ILLLIBS',
|
||||
raw_config => { backend_directory => '/tmp/' },
|
||||
},
|
||||
"load_configuration: return the correct backend_dir."
|
||||
);
|
||||
|
||||
# Map over branch configs
|
||||
my $xml_config = {
|
||||
backend_directory => '/tmp/',
|
||||
branch => [
|
||||
{ code => '1', request_limit => { method => 'annual', count => 1 } },
|
||||
{ code => '2', prefix => '2-prefix' },
|
||||
{ code => '3', digital_recipient => 'branch' }
|
||||
]
|
||||
};
|
||||
is_deeply(
|
||||
Koha::Illrequest::Config::_load_configuration($xml_config, 0),
|
||||
{
|
||||
backend_directory => '/tmp/',
|
||||
censorship => {
|
||||
censor_notes_staff => 0,
|
||||
censor_reply_date => 0,
|
||||
},
|
||||
limits => { branch => { 1 => { method => 'annual', count => 1 } } },
|
||||
digital_recipients => { branch => { 3 => 'branch' } },
|
||||
prefixes => { branch => { 2 => '2-prefix' } },
|
||||
partner_code => 'ILLLIBS',
|
||||
raw_config => $xml_config,
|
||||
},
|
||||
"load_configuration: multi branch config parsed correctly."
|
||||
);
|
||||
# Single branch config
|
||||
$xml_config = {
|
||||
backend_directory => '/tmp/',
|
||||
branch => {
|
||||
code => '1',
|
||||
request_limit => { method => 'annual', count => 1 },
|
||||
prefix => '2-prefix',
|
||||
digital_recipient => 'branch',
|
||||
}
|
||||
};
|
||||
is_deeply(
|
||||
Koha::Illrequest::Config::_load_configuration($xml_config, 0),
|
||||
{
|
||||
backend_directory => '/tmp/',
|
||||
censorship => {
|
||||
censor_notes_staff => 0,
|
||||
censor_reply_date => 0,
|
||||
},
|
||||
limits => { branch => { 1 => { method => 'annual', count => 1 } } },
|
||||
digital_recipients => { branch => { 1 => 'branch' } },
|
||||
prefixes => { branch => { 1 => '2-prefix' } },
|
||||
partner_code => 'ILLLIBS',
|
||||
raw_config => $xml_config,
|
||||
},
|
||||
"load_configuration: single branch config parsed correctly."
|
||||
);
|
||||
|
||||
# Map over borrower_category settings
|
||||
$xml_config = {
|
||||
backend_directory => '/tmp/',
|
||||
borrower_category => [
|
||||
{ code => 'A', request_limit => { method => 'annual', count => 1 } },
|
||||
{ code => 'B', prefix => '2-prefix' },
|
||||
{ code => 'C', digital_recipient => 'branch' }
|
||||
]
|
||||
};
|
||||
is_deeply(
|
||||
Koha::Illrequest::Config::_load_configuration($xml_config, 0),
|
||||
{
|
||||
backend_directory => '/tmp/',
|
||||
censorship => {
|
||||
censor_notes_staff => 0,
|
||||
censor_reply_date => 0,
|
||||
},
|
||||
limits => { brw_cat => { A => { method => 'annual', count => 1 } } },
|
||||
digital_recipients => { brw_cat => { C => 'branch' } },
|
||||
prefixes => { brw_cat => { B => '2-prefix' } },
|
||||
partner_code => 'ILLLIBS',
|
||||
raw_config => $xml_config,
|
||||
},
|
||||
"load_configuration: multi borrower_category config parsed correctly."
|
||||
);
|
||||
# Single borrower_category config
|
||||
$xml_config = {
|
||||
backend_directory => '/tmp/',
|
||||
borrower_category => {
|
||||
code => '1',
|
||||
request_limit => { method => 'annual', count => 1 },
|
||||
prefix => '2-prefix',
|
||||
digital_recipient => 'branch',
|
||||
}
|
||||
};
|
||||
is_deeply(
|
||||
Koha::Illrequest::Config::_load_configuration($xml_config, 0),
|
||||
{
|
||||
backend_directory => '/tmp/',
|
||||
censorship => {
|
||||
censor_notes_staff => 0,
|
||||
censor_reply_date => 0,
|
||||
},
|
||||
limits => { brw_cat => { 1 => { method => 'annual', count => 1 } } },
|
||||
digital_recipients => { brw_cat => { 1 => 'branch' } },
|
||||
prefixes => { brw_cat => { 1 => '2-prefix' } },
|
||||
partner_code => 'ILLLIBS',
|
||||
raw_config => $xml_config,
|
||||
},
|
||||
"load_configuration: single borrower_category config parsed correctly."
|
||||
);
|
||||
|
||||
# Default Configuration
|
||||
$xml_config = {
|
||||
backend_directory => '/tmp/',
|
||||
request_limit => { method => 'annual', count => 1 },
|
||||
prefix => '2-prefix',
|
||||
digital_recipient => 'branch',
|
||||
};
|
||||
is_deeply(
|
||||
Koha::Illrequest::Config::_load_configuration($xml_config, 0),
|
||||
{
|
||||
backend_directory => '/tmp/',
|
||||
censorship => {
|
||||
censor_notes_staff => 0,
|
||||
censor_reply_date => 0,
|
||||
},
|
||||
limits => { default => { method => 'annual', count => 1 } },
|
||||
digital_recipients => { default => 'branch' },
|
||||
prefixes => { default => '2-prefix' },
|
||||
partner_code => 'ILLLIBS',
|
||||
raw_config => $xml_config,
|
||||
},
|
||||
"load_configuration: parse the default configuration."
|
||||
);
|
||||
|
||||
# Censorship
|
||||
$xml_config = {
|
||||
backend_directory => '/tmp/',
|
||||
staff_request_comments => 'hide',
|
||||
reply_date => 'hide'
|
||||
};
|
||||
is_deeply(
|
||||
Koha::Illrequest::Config::_load_configuration($xml_config, 0),
|
||||
{
|
||||
backend_directory => '/tmp/',
|
||||
censorship => {
|
||||
censor_notes_staff => 1,
|
||||
censor_reply_date => 1,
|
||||
},
|
||||
limits => {},
|
||||
digital_recipients => {},
|
||||
prefixes => {},
|
||||
partner_code => 'ILLLIBS',
|
||||
raw_config => $xml_config,
|
||||
},
|
||||
"load_configuration: parse censorship settings configuration."
|
||||
);
|
||||
|
||||
# Partner library category
|
||||
is_deeply(
|
||||
Koha::Illrequest::Config::_load_configuration({ partner_code => 'FOOBAR' }),
|
||||
{
|
||||
backend_directory => undef,
|
||||
censorship => {
|
||||
censor_notes_staff => 0,
|
||||
censor_reply_date => 0,
|
||||
},
|
||||
limits => {},
|
||||
digital_recipients => {},
|
||||
prefixes => {},
|
||||
partner_code => 'FOOBAR',
|
||||
raw_config => { partner_code => 'FOOBAR' },
|
||||
},
|
||||
"load_configuration: Set partner code."
|
||||
);
|
||||
|
||||
$schema->storage->txn_rollback;
|
||||
};
|
||||
|
||||
|
||||
subtest 'Final tests' => sub {
|
||||
|
||||
plan tests => 10;
|
||||
|
||||
$schema->storage->txn_begin;
|
||||
|
||||
t::lib::Mocks::mock_preference("UnmediatedILL", 0);
|
||||
t::lib::Mocks::mock_config("interlibrary_loans", {});
|
||||
|
||||
my $config = Koha::Illrequest::Config->new;
|
||||
|
||||
# getPrefixes (error & undef):
|
||||
dies_ok( sub { $config->getPrefixes("FOO") }, "getPrefixes: die if not correct type.");
|
||||
is_deeply($config->getPrefixes("brw_cat"), { default => undef},
|
||||
"getPrefixes: Undefined brw_cat prefix is undefined.");
|
||||
is_deeply($config->getPrefixes("branch"), { default => undef},
|
||||
"getPrefixes: Undefined branch prefix is undefined.");
|
||||
|
||||
# getDigitalRecipients (error & undef):
|
||||
dies_ok( sub { $config->getDigitalRecipients("FOO") },
|
||||
"getDigitalRecipients: die if not correct type.");
|
||||
is_deeply($config->getDigitalRecipients("brw_cat"), { default => undef},
|
||||
"getDigitalRecipients: Undefined brw_cat dig rec is undefined.");
|
||||
is_deeply($config->getDigitalRecipients("branch"), { default => undef},
|
||||
"getDigitalRecipients: Undefined branch dig rec is undefined.");
|
||||
|
||||
$config->{configuration} = Koha::Illrequest::Config::_load_configuration({
|
||||
backend_directory => '/tmp/',
|
||||
prefix => 'DEFAULT-prefix',
|
||||
digital_recipient => 'branch',
|
||||
borrower_category => [
|
||||
{ code => 'B', prefix => '2-prefix' },
|
||||
{ code => 'C', digital_recipient => 'branch' }
|
||||
],
|
||||
branch => [
|
||||
{ code => '1', prefix => 'T-prefix' },
|
||||
{ code => '2', digital_recipient => 'borrower' }
|
||||
]
|
||||
}, 0
|
||||
);
|
||||
|
||||
# getPrefixes (values):
|
||||
is_deeply($config->getPrefixes("brw_cat"),
|
||||
{ B => '2-prefix', default => 'DEFAULT-prefix' },
|
||||
"getPrefixes: return configuration brw_cat prefixes.");
|
||||
is_deeply($config->getPrefixes("branch"),
|
||||
{ 1 => 'T-prefix', default => 'DEFAULT-prefix' },
|
||||
"getPrefixes: return configuration branch prefixes.");
|
||||
|
||||
# getDigitalRecipients (values):
|
||||
is_deeply($config->getDigitalRecipients("brw_cat"),
|
||||
{ C => 'branch', default => 'branch' },
|
||||
"getDigitalRecipients: return brw_cat digital_recipients.");
|
||||
is_deeply($config->getDigitalRecipients("branch"),
|
||||
{ 2 => 'borrower', default => 'branch' },
|
||||
"getDigitalRecipients: return branch digital_recipients.");
|
||||
|
||||
$schema->storage->txn_rollback;
|
||||
};
|
||||
|
||||
|
||||
1;
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
#!/usr/bin/perl
|
||||
#
|
||||
# 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 2 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 File::Basename qw/basename/;
|
||||
use Koha::Database;
|
||||
use Koha::Patrons;
|
||||
use t::lib::TestBuilder;
|
||||
|
||||
use Test::More tests => 3;
|
||||
|
||||
my $schema = Koha::Database->new->schema;
|
||||
use_ok('Koha::Illrequestattribute');
|
||||
use_ok('Koha::Illrequestattributes');
|
||||
|
||||
subtest 'Basic object tests' => sub {
|
||||
|
||||
plan tests => 5;
|
||||
|
||||
$schema->storage->txn_begin;
|
||||
|
||||
my $builder = t::lib::TestBuilder->new;
|
||||
|
||||
my $illrqattr = $builder->build({ source => 'Illrequestattribute' });
|
||||
|
||||
my $illrqattr_obj = Koha::Illrequestattributes->find(
|
||||
$illrqattr->{illrequest_id},
|
||||
$illrqattr->{type}
|
||||
);
|
||||
isa_ok($illrqattr_obj, 'Koha::Illrequestattribute',
|
||||
"Correctly create and load an illrequestattribute object.");
|
||||
is($illrqattr_obj->illrequest_id, $illrqattr->{illrequest_id},
|
||||
"Illrequest_id getter works.");
|
||||
is($illrqattr_obj->type, $illrqattr->{type},
|
||||
"Type getter works.");
|
||||
is($illrqattr_obj->value, $illrqattr->{value},
|
||||
"Value getter works.");
|
||||
|
||||
$illrqattr_obj->delete;
|
||||
|
||||
is(Koha::Illrequestattributes->search->count, 0,
|
||||
"No attributes found after delete.");
|
||||
|
||||
$schema->storage->txn_rollback;
|
||||
};
|
||||
|
||||
1;
|
||||
|
|
@ -0,0 +1,792 @@
|
|||
#!/usr/bin/perl
|
||||
#
|
||||
# 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 2 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 File::Basename qw/basename/;
|
||||
use Koha::Database;
|
||||
use Koha::Illrequestattributes;
|
||||
use Koha::Illrequest::Config;
|
||||
use Koha::Patrons;
|
||||
use t::lib::Mocks;
|
||||
use t::lib::TestBuilder;
|
||||
use Test::MockObject;
|
||||
use Test::Exception;
|
||||
|
||||
use Test::More tests => 10;
|
||||
|
||||
my $schema = Koha::Database->new->schema;
|
||||
my $builder = t::lib::TestBuilder->new;
|
||||
use_ok('Koha::Illrequest');
|
||||
use_ok('Koha::Illrequests');
|
||||
|
||||
subtest 'Basic object tests' => sub {
|
||||
|
||||
plan tests => 21;
|
||||
|
||||
$schema->storage->txn_begin;
|
||||
|
||||
my $illrq = $builder->build({ source => 'Illrequest' });
|
||||
my $illrq_obj = Koha::Illrequests->find($illrq->{illrequest_id});
|
||||
|
||||
isa_ok($illrq_obj, 'Koha::Illrequest',
|
||||
"Correctly create and load an illrequest object.");
|
||||
isa_ok($illrq_obj->_config, 'Koha::Illrequest::Config',
|
||||
"Created a config object as part of Illrequest creation.");
|
||||
|
||||
is($illrq_obj->illrequest_id, $illrq->{illrequest_id},
|
||||
"Illrequest_id getter works.");
|
||||
is($illrq_obj->borrowernumber, $illrq->{borrowernumber},
|
||||
"Borrowernumber getter works.");
|
||||
is($illrq_obj->biblio_id, $illrq->{biblio_id},
|
||||
"Biblio_Id getter works.");
|
||||
is($illrq_obj->branchcode, $illrq->{branchcode},
|
||||
"Branchcode getter works.");
|
||||
is($illrq_obj->status, $illrq->{status},
|
||||
"Status getter works.");
|
||||
is($illrq_obj->placed, $illrq->{placed},
|
||||
"Placed getter works.");
|
||||
is($illrq_obj->replied, $illrq->{replied},
|
||||
"Replied getter works.");
|
||||
is($illrq_obj->updated, $illrq->{updated},
|
||||
"Updated getter works.");
|
||||
is($illrq_obj->completed, $illrq->{completed},
|
||||
"Completed getter works.");
|
||||
is($illrq_obj->medium, $illrq->{medium},
|
||||
"Medium getter works.");
|
||||
is($illrq_obj->accessurl, $illrq->{accessurl},
|
||||
"Accessurl getter works.");
|
||||
is($illrq_obj->cost, $illrq->{cost},
|
||||
"Cost getter works.");
|
||||
is($illrq_obj->notesopac, $illrq->{notesopac},
|
||||
"Notesopac getter works.");
|
||||
is($illrq_obj->notesstaff, $illrq->{notesstaff},
|
||||
"Notesstaff getter works.");
|
||||
is($illrq_obj->orderid, $illrq->{orderid},
|
||||
"Orderid getter works.");
|
||||
is($illrq_obj->backend, $illrq->{backend},
|
||||
"Backend getter works.");
|
||||
|
||||
isnt($illrq_obj->status, 'COMP',
|
||||
"ILL is not currently marked complete.");
|
||||
$illrq_obj->mark_completed;
|
||||
is($illrq_obj->status, 'COMP',
|
||||
"ILL is now marked complete.");
|
||||
|
||||
$illrq_obj->delete;
|
||||
|
||||
is(Koha::Illrequests->search->count, 0,
|
||||
"No illrequest found after delete.");
|
||||
|
||||
$schema->storage->txn_rollback;
|
||||
};
|
||||
|
||||
subtest 'Working with related objects' => sub {
|
||||
|
||||
plan tests => 5;
|
||||
|
||||
$schema->storage->txn_begin;
|
||||
|
||||
my $patron = $builder->build({ source => 'Borrower' });
|
||||
my $illrq = $builder->build({
|
||||
source => 'Illrequest',
|
||||
value => { borrowernumber => $patron->{borrowernumber} }
|
||||
});
|
||||
my $illrq_obj = Koha::Illrequests->find($illrq->{illrequest_id});
|
||||
|
||||
isa_ok($illrq_obj->patron, 'Koha::Patron',
|
||||
"OK accessing related patron.");
|
||||
|
||||
$builder->build({
|
||||
source => 'Illrequestattribute',
|
||||
value => { illrequest_id => $illrq_obj->illrequest_id, type => 'X' }
|
||||
});
|
||||
$builder->build({
|
||||
source => 'Illrequestattribute',
|
||||
value => { illrequest_id => $illrq_obj->illrequest_id, type => 'Y' }
|
||||
});
|
||||
$builder->build({
|
||||
source => 'Illrequestattribute',
|
||||
value => { illrequest_id => $illrq_obj->illrequest_id, type => 'Z' }
|
||||
});
|
||||
|
||||
is($illrq_obj->illrequestattributes->count, Koha::Illrequestattributes->search->count,
|
||||
"Fetching expected number of Illrequestattributes for our request.");
|
||||
|
||||
my $illrq1 = $builder->build({ source => 'Illrequest' });
|
||||
$builder->build({
|
||||
source => 'Illrequestattribute',
|
||||
value => { illrequest_id => $illrq1->{illrequest_id}, type => 'X' }
|
||||
});
|
||||
|
||||
is($illrq_obj->illrequestattributes->count + 1, Koha::Illrequestattributes->search->count,
|
||||
"Fetching expected number of Illrequestattributes for our request.");
|
||||
|
||||
$illrq_obj->delete;
|
||||
is(Koha::Illrequestattributes->search->count, 1,
|
||||
"Correct number of illrequestattributes after delete.");
|
||||
|
||||
isa_ok(Koha::Patrons->find($patron->{borrowernumber}), 'Koha::Patron',
|
||||
"Borrower was not deleted after illrq delete.");
|
||||
|
||||
$schema->storage->txn_rollback;
|
||||
};
|
||||
|
||||
subtest 'Status Graph tests' => sub {
|
||||
|
||||
plan tests => 4;
|
||||
|
||||
$schema->storage->txn_begin;
|
||||
|
||||
my $illrq = $builder->build({source => 'Illrequest'});
|
||||
my $illrq_obj = Koha::Illrequests->find($illrq->{illrequest_id});
|
||||
|
||||
# _core_status_graph tests: it's just a constant, so here we just make
|
||||
# sure it returns a hashref.
|
||||
is(ref $illrq_obj->_core_status_graph, "HASH",
|
||||
"_core_status_graph returns a hash.");
|
||||
|
||||
# _status_graph_union: let's try different merge operations.
|
||||
# Identity operation
|
||||
is_deeply(
|
||||
$illrq_obj->_status_graph_union($illrq_obj->_core_status_graph, {}),
|
||||
$illrq_obj->_core_status_graph,
|
||||
"core_status_graph + null = core_status_graph"
|
||||
);
|
||||
|
||||
# Simple addition
|
||||
is_deeply(
|
||||
$illrq_obj->_status_graph_union({}, $illrq_obj->_core_status_graph),
|
||||
$illrq_obj->_core_status_graph,
|
||||
"null + core_status_graph = core_status_graph"
|
||||
);
|
||||
|
||||
# Correct merge behaviour
|
||||
is_deeply(
|
||||
$illrq_obj->_status_graph_union({
|
||||
REQ => {
|
||||
prev_actions => [ ],
|
||||
id => 'REQ',
|
||||
next_actions => [ ],
|
||||
},
|
||||
}, {
|
||||
QER => {
|
||||
prev_actions => [ 'REQ' ],
|
||||
id => 'QER',
|
||||
next_actions => [ 'REQ' ],
|
||||
},
|
||||
}),
|
||||
{
|
||||
REQ => {
|
||||
prev_actions => [ 'QER' ],
|
||||
id => 'REQ',
|
||||
next_actions => [ 'QER' ],
|
||||
},
|
||||
QER => {
|
||||
prev_actions => [ 'REQ' ],
|
||||
id => 'QER',
|
||||
next_actions => [ 'REQ' ],
|
||||
},
|
||||
},
|
||||
"REQ atom + linking QER = cyclical status graph"
|
||||
);
|
||||
|
||||
$schema->storage->txn_rollback;
|
||||
};
|
||||
|
||||
subtest 'Backend testing (mocks)' => sub {
|
||||
|
||||
plan tests => 13;
|
||||
|
||||
$schema->storage->txn_begin;
|
||||
|
||||
# testing load_backend & available_backends requires that we have at least
|
||||
# the Dummy plugin installed. load_backend & available_backends don't
|
||||
# currently have tests as a result.
|
||||
|
||||
my $backend = Test::MockObject->new;
|
||||
$backend->set_isa('Koha::Illbackends::Mock');
|
||||
$backend->set_always('name', 'Mock');
|
||||
|
||||
my $patron = $builder->build({ source => 'Borrower' });
|
||||
my $illrq = $builder->build({
|
||||
source => 'Illrequest',
|
||||
value => { borrowernumber => $patron->{borrowernumber} }
|
||||
});
|
||||
my $illrq_obj = Koha::Illrequests->find($illrq->{illrequest_id});
|
||||
|
||||
$illrq_obj->_backend($backend);
|
||||
|
||||
isa_ok($illrq_obj->_backend, 'Koha::Illbackends::Mock',
|
||||
"OK accessing mocked backend.");
|
||||
|
||||
# _backend_capability tests:
|
||||
# We need to test whether this optional feature of a mocked backend
|
||||
# behaves as expected.
|
||||
# 3 scenarios: feature not implemented, feature implemented, but requested
|
||||
# capability is not provided by backend, & feature is implemented &
|
||||
# capability exists. This method can be used to implement custom backend
|
||||
# functionality, such as unmediated in the BLDSS backend (also see
|
||||
# bugzilla 18837).
|
||||
$backend->set_always('capabilities', undef);
|
||||
is($illrq_obj->_backend_capability('Test'), 0,
|
||||
"0 returned on Mock not implementing capabilities.");
|
||||
|
||||
$backend->set_always('capabilities', 0);
|
||||
is($illrq_obj->_backend_capability('Test'), 0,
|
||||
"0 returned on Mock not implementing Test capability.");
|
||||
|
||||
$backend->set_always('capabilities', sub { return 'bar'; } );
|
||||
is($illrq_obj->_backend_capability('Test'), 'bar',
|
||||
"'bar' returned on Mock implementing Test capability.");
|
||||
|
||||
# metadata test: we need to be sure that we return the arbitrary values
|
||||
# from the backend.
|
||||
$backend->mock(
|
||||
'metadata',
|
||||
sub {
|
||||
my ( $self, $rq ) = @_;
|
||||
return {
|
||||
ID => $rq->illrequest_id,
|
||||
Title => $rq->patron->borrowernumber
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
is_deeply(
|
||||
$illrq_obj->metadata,
|
||||
{
|
||||
ID => $illrq_obj->illrequest_id,
|
||||
Title => $illrq_obj->patron->borrowernumber
|
||||
},
|
||||
"Test metadata."
|
||||
);
|
||||
|
||||
# capabilities:
|
||||
|
||||
# No backend graph extension
|
||||
$backend->set_always('status_graph', {});
|
||||
is_deeply($illrq_obj->capabilities('COMP'),
|
||||
{
|
||||
prev_actions => [ 'REQ' ],
|
||||
id => 'COMP',
|
||||
name => 'Completed',
|
||||
ui_method_name => 'Mark completed',
|
||||
method => 'mark_completed',
|
||||
next_actions => [ ],
|
||||
ui_method_icon => 'fa-check',
|
||||
},
|
||||
"Dummy status graph for COMP.");
|
||||
is($illrq_obj->capabilities('UNKNOWN'), undef,
|
||||
"Dummy status graph for UNKNOWN.");
|
||||
is_deeply($illrq_obj->capabilities(),
|
||||
$illrq_obj->_core_status_graph,
|
||||
"Dummy full status graph.");
|
||||
# Simple backend graph extension
|
||||
$backend->set_always('status_graph',
|
||||
{
|
||||
QER => {
|
||||
prev_actions => [ 'REQ' ],
|
||||
id => 'QER',
|
||||
next_actions => [ 'REQ' ],
|
||||
},
|
||||
});
|
||||
is_deeply($illrq_obj->capabilities('QER'),
|
||||
{
|
||||
prev_actions => [ 'REQ' ],
|
||||
id => 'QER',
|
||||
next_actions => [ 'REQ' ],
|
||||
},
|
||||
"Simple status graph for QER.");
|
||||
is($illrq_obj->capabilities('UNKNOWN'), undef,
|
||||
"Simple status graph for UNKNOWN.");
|
||||
is_deeply($illrq_obj->capabilities(),
|
||||
$illrq_obj->_status_graph_union(
|
||||
$illrq_obj->_core_status_graph,
|
||||
{
|
||||
QER => {
|
||||
prev_actions => [ 'REQ' ],
|
||||
id => 'QER',
|
||||
next_actions => [ 'REQ' ],
|
||||
},
|
||||
}
|
||||
),
|
||||
"Simple full status graph.");
|
||||
|
||||
# custom_capability:
|
||||
|
||||
# No backend graph extension
|
||||
$backend->set_always('status_graph', {});
|
||||
is($illrq_obj->custom_capability('unknown', {}), 0,
|
||||
"Unknown candidate.");
|
||||
|
||||
# Simple backend graph extension
|
||||
$backend->set_always('status_graph',
|
||||
{
|
||||
ID => {
|
||||
prev_actions => [ 'REQ' ],
|
||||
id => 'ID',
|
||||
method => 'identity',
|
||||
next_actions => [ 'REQ' ],
|
||||
},
|
||||
});
|
||||
$backend->mock('identity',
|
||||
sub { my ( $self, $params ) = @_; return $params->{other}; });
|
||||
is($illrq_obj->custom_capability('identity', { test => 1 })->{test}, 1,
|
||||
"Resolve identity custom_capability");
|
||||
|
||||
$schema->storage->txn_rollback;
|
||||
};
|
||||
|
||||
|
||||
subtest 'Backend core methods' => sub {
|
||||
|
||||
plan tests => 16;
|
||||
|
||||
$schema->storage->txn_begin;
|
||||
|
||||
# Build infrastructure
|
||||
my $backend = Test::MockObject->new;
|
||||
$backend->set_isa('Koha::Illbackends::Mock');
|
||||
$backend->set_always('name', 'Mock');
|
||||
|
||||
my $config = Test::MockObject->new;
|
||||
$config->set_always('backend_dir', "/tmp");
|
||||
$config->set_always('getLimitRules',
|
||||
{ default => { count => 0, method => 'active' } });
|
||||
|
||||
my $illrq = $builder->build({source => 'Illrequest'});
|
||||
my $illrq_obj = Koha::Illrequests->find($illrq->{illrequest_id});
|
||||
$illrq_obj->_config($config);
|
||||
$illrq_obj->_backend($backend);
|
||||
|
||||
# expandTemplate:
|
||||
is_deeply($illrq_obj->expandTemplate({ test => 1, method => "bar" }),
|
||||
{
|
||||
test => 1,
|
||||
method => "bar",
|
||||
template => "/tmp/Mock/intra-includes/bar.inc",
|
||||
opac_template => "/tmp/Mock/opac-includes/bar.inc",
|
||||
},
|
||||
"ExpandTemplate");
|
||||
|
||||
# backend_create
|
||||
# we are testing simple cases.
|
||||
$backend->set_series('create',
|
||||
{ stage => 'bar', method => 'create' },
|
||||
{ stage => 'commit', method => 'create' },
|
||||
{ stage => 'commit', method => 'create' });
|
||||
# Test Copyright Clearance
|
||||
t::lib::Mocks::mock_preference("ILLModuleCopyrightClearance", "Test Copyright Clearance.");
|
||||
is_deeply($illrq_obj->backend_create({test => 1}),
|
||||
{
|
||||
error => 0,
|
||||
status => '',
|
||||
message => '',
|
||||
method => 'create',
|
||||
stage => 'copyrightclearance',
|
||||
value => {
|
||||
backend => "Mock"
|
||||
}
|
||||
},
|
||||
"Backend create: copyright clearance.");
|
||||
t::lib::Mocks::mock_preference("ILLModuleCopyrightClearance", "");
|
||||
# Test non-commit
|
||||
is_deeply($illrq_obj->backend_create({test => 1}),
|
||||
{
|
||||
stage => 'bar', method => 'create',
|
||||
template => "/tmp/Mock/intra-includes/create.inc",
|
||||
opac_template => "/tmp/Mock/opac-includes/create.inc",
|
||||
},
|
||||
"Backend create: arbitrary stage.");
|
||||
# Test commit
|
||||
is_deeply($illrq_obj->backend_create({test => 1}),
|
||||
{
|
||||
stage => 'commit', method => 'create', permitted => 0,
|
||||
template => "/tmp/Mock/intra-includes/create.inc",
|
||||
opac_template => "/tmp/Mock/opac-includes/create.inc",
|
||||
},
|
||||
"Backend create: arbitrary stage, not permitted.");
|
||||
is($illrq_obj->status, "QUEUED", "Backend create: queued if restricted.");
|
||||
$config->set_always('getLimitRules', {});
|
||||
$illrq_obj->status('NEW');
|
||||
is_deeply($illrq_obj->backend_create({test => 1}),
|
||||
{
|
||||
stage => 'commit', method => 'create', permitted => 1,
|
||||
template => "/tmp/Mock/intra-includes/create.inc",
|
||||
opac_template => "/tmp/Mock/opac-includes/create.inc",
|
||||
},
|
||||
"Backend create: arbitrary stage, permitted.");
|
||||
is($illrq_obj->status, "NEW", "Backend create: not-queued.");
|
||||
|
||||
# backend_renew
|
||||
$backend->set_series('renew', { stage => 'bar', method => 'renew' });
|
||||
is_deeply($illrq_obj->backend_renew({test => 1}),
|
||||
{
|
||||
stage => 'bar', method => 'renew',
|
||||
template => "/tmp/Mock/intra-includes/renew.inc",
|
||||
opac_template => "/tmp/Mock/opac-includes/renew.inc",
|
||||
},
|
||||
"Backend renew: arbitrary stage.");
|
||||
|
||||
# backend_cancel
|
||||
$backend->set_series('cancel', { stage => 'bar', method => 'cancel' });
|
||||
is_deeply($illrq_obj->backend_cancel({test => 1}),
|
||||
{
|
||||
stage => 'bar', method => 'cancel',
|
||||
template => "/tmp/Mock/intra-includes/cancel.inc",
|
||||
opac_template => "/tmp/Mock/opac-includes/cancel.inc",
|
||||
},
|
||||
"Backend cancel: arbitrary stage.");
|
||||
|
||||
# backend_update_status
|
||||
$backend->set_series('update_status', { stage => 'bar', method => 'update_status' });
|
||||
is_deeply($illrq_obj->backend_update_status({test => 1}),
|
||||
{
|
||||
stage => 'bar', method => 'update_status',
|
||||
template => "/tmp/Mock/intra-includes/update_status.inc",
|
||||
opac_template => "/tmp/Mock/opac-includes/update_status.inc",
|
||||
},
|
||||
"Backend update_status: arbitrary stage.");
|
||||
|
||||
# backend_confirm
|
||||
$backend->set_series('confirm', { stage => 'bar', method => 'confirm' });
|
||||
is_deeply($illrq_obj->backend_confirm({test => 1}),
|
||||
{
|
||||
stage => 'bar', method => 'confirm',
|
||||
template => "/tmp/Mock/intra-includes/confirm.inc",
|
||||
opac_template => "/tmp/Mock/opac-includes/confirm.inc",
|
||||
},
|
||||
"Backend confirm: arbitrary stage.");
|
||||
|
||||
$config->set_always('partner_code', "ILLTSTLIB");
|
||||
$backend->set_always('metadata', { Test => "Foobar" });
|
||||
my $illbrn = $builder->build({
|
||||
source => 'Branch',
|
||||
value => { branchemail => "", branchreplyto => "" }
|
||||
});
|
||||
my $partner1 = $builder->build({
|
||||
source => 'Borrower',
|
||||
value => { categorycode => "ILLTSTLIB" },
|
||||
});
|
||||
my $partner2 = $builder->build({
|
||||
source => 'Borrower',
|
||||
value => { categorycode => "ILLTSTLIB" },
|
||||
});
|
||||
my $gen_conf = $illrq_obj->generic_confirm({
|
||||
current_branchcode => $illbrn->{branchcode}
|
||||
});
|
||||
isnt(index($gen_conf->{value}->{draft}->{body}, $backend->metadata->{Test}), -1,
|
||||
"Generic confirm: draft contains metadata."
|
||||
);
|
||||
is($gen_conf->{value}->{partners}->next->borrowernumber, $partner1->{borrowernumber},
|
||||
"Generic cofnirm: partner 1 is correct."
|
||||
);
|
||||
is($gen_conf->{value}->{partners}->next->borrowernumber, $partner2->{borrowernumber},
|
||||
"Generic confirm: partner 2 is correct."
|
||||
);
|
||||
|
||||
dies_ok { $illrq_obj->generic_confirm({
|
||||
current_branchcode => $illbrn->{branchcode},
|
||||
stage => 'draft'
|
||||
}) }
|
||||
"Generic confirm: missing to dies OK.";
|
||||
|
||||
dies_ok { $illrq_obj->generic_confirm({
|
||||
current_branchcode => $illbrn->{branchcode},
|
||||
partners => $partner1->{email},
|
||||
stage => 'draft'
|
||||
}) }
|
||||
"Generic confirm: missing from dies OK.";
|
||||
|
||||
$schema->storage->txn_rollback;
|
||||
};
|
||||
|
||||
|
||||
subtest 'Helpers' => sub {
|
||||
|
||||
plan tests => 9;
|
||||
|
||||
$schema->storage->txn_begin;
|
||||
|
||||
# Build infrastructure
|
||||
my $backend = Test::MockObject->new;
|
||||
$backend->set_isa('Koha::Illbackends::Mock');
|
||||
$backend->set_always('name', 'Mock');
|
||||
|
||||
my $config = Test::MockObject->new;
|
||||
$config->set_always('backend_dir', "/tmp");
|
||||
|
||||
my $patron = $builder->build({
|
||||
source => 'Borrower',
|
||||
value => { categorycode => "A" }
|
||||
});
|
||||
my $illrq = $builder->build({
|
||||
source => 'Illrequest',
|
||||
value => { branchcode => "CPL", borrowernumber => $patron->{borrowernumber} }
|
||||
});
|
||||
my $illrq_obj = Koha::Illrequests->find($illrq->{illrequest_id});
|
||||
$illrq_obj->_config($config);
|
||||
$illrq_obj->_backend($backend);
|
||||
|
||||
# getPrefix
|
||||
$config->set_series('getPrefixes',
|
||||
{ CPL => "TEST", TSL => "BAR", default => "DEFAULT" },
|
||||
{ A => "ATEST", C => "CBAR", default => "DEFAULT" });
|
||||
is($illrq_obj->getPrefix({ brw_cat => "C", branch => "CPL" }), "CBAR",
|
||||
"getPrefix: brw_cat");
|
||||
$config->set_series('getPrefixes',
|
||||
{ CPL => "TEST", TSL => "BAR", default => "DEFAULT" },
|
||||
{ A => "ATEST", C => "CBAR", default => "DEFAULT" });
|
||||
is($illrq_obj->getPrefix({ brw_cat => "UNKNOWN", branch => "CPL" }), "TEST",
|
||||
"getPrefix: branch");
|
||||
$config->set_series('getPrefixes',
|
||||
{ CPL => "TEST", TSL => "BAR", default => "DEFAULT" },
|
||||
{ A => "ATEST", C => "CBAR", default => "DEFAULT" });
|
||||
is($illrq_obj->getPrefix({ brw_cat => "UNKNOWN", branch => "UNKNOWN" }), "DEFAULT",
|
||||
"getPrefix: default");
|
||||
$config->set_always('getPrefixes', {});
|
||||
is($illrq_obj->getPrefix({ brw_cat => "UNKNOWN", branch => "UNKNOWN" }), "",
|
||||
"getPrefix: the empty prefix");
|
||||
|
||||
# id_prefix
|
||||
$config->set_series('getPrefixes',
|
||||
{ CPL => "TEST", TSL => "BAR", default => "DEFAULT" },
|
||||
{ A => "ATEST", C => "CBAR", default => "DEFAULT" });
|
||||
is($illrq_obj->id_prefix, "ATEST-", "id_prefix: brw_cat");
|
||||
$config->set_series('getPrefixes',
|
||||
{ CPL => "TEST", TSL => "BAR", default => "DEFAULT" },
|
||||
{ AB => "ATEST", CD => "CBAR", default => "DEFAULT" });
|
||||
is($illrq_obj->id_prefix, "TEST-", "id_prefix: branch");
|
||||
$config->set_series('getPrefixes',
|
||||
{ CPLT => "TEST", TSLT => "BAR", default => "DEFAULT" },
|
||||
{ AB => "ATEST", CD => "CBAR", default => "DEFAULT" });
|
||||
is($illrq_obj->id_prefix, "DEFAULT-", "id_prefix: default");
|
||||
|
||||
# requires_moderation
|
||||
$illrq_obj->status('NEW')->store;
|
||||
is($illrq_obj->requires_moderation, undef, "requires_moderation: No.");
|
||||
$illrq_obj->status('CANCREQ')->store;
|
||||
is($illrq_obj->requires_moderation, 'CANCREQ', "requires_moderation: Yes.");
|
||||
|
||||
$schema->storage->txn_rollback;
|
||||
};
|
||||
|
||||
|
||||
subtest 'Censorship' => sub {
|
||||
|
||||
plan tests => 2;
|
||||
|
||||
$schema->storage->txn_begin;
|
||||
|
||||
# Build infrastructure
|
||||
my $backend = Test::MockObject->new;
|
||||
$backend->set_isa('Koha::Illbackends::Mock');
|
||||
$backend->set_always('name', 'Mock');
|
||||
|
||||
my $config = Test::MockObject->new;
|
||||
$config->set_always('backend_dir', "/tmp");
|
||||
|
||||
my $illrq = $builder->build({source => 'Illrequest'});
|
||||
my $illrq_obj = Koha::Illrequests->find($illrq->{illrequest_id});
|
||||
$illrq_obj->_config($config);
|
||||
$illrq_obj->_backend($backend);
|
||||
|
||||
$config->set_always('censorship', { censor_notes_staff => 1, censor_reply_date => 0 });
|
||||
|
||||
my $censor_out = $illrq_obj->_censor({ foo => 'bar', baz => 564 });
|
||||
is_deeply($censor_out, { foo => 'bar', baz => 564, display_reply_date => 1 },
|
||||
"_censor: not OPAC, reply_date = 1");
|
||||
|
||||
$censor_out = $illrq_obj->_censor({ foo => 'bar', baz => 564, opac => 1 });
|
||||
is_deeply($censor_out, {
|
||||
foo => 'bar', baz => 564, censor_notes_staff => 1,
|
||||
display_reply_date => 1, opac => 1
|
||||
}, "_censor: notes_staff = 0, reply_date = 0");
|
||||
|
||||
$schema->storage->txn_rollback;
|
||||
};
|
||||
|
||||
subtest 'Checking Limits' => sub {
|
||||
|
||||
plan tests => 30;
|
||||
|
||||
$schema->storage->txn_begin;
|
||||
|
||||
# Build infrastructure
|
||||
my $backend = Test::MockObject->new;
|
||||
$backend->set_isa('Koha::Illbackends::Mock');
|
||||
$backend->set_always('name', 'Mock');
|
||||
|
||||
my $config = Test::MockObject->new;
|
||||
$config->set_always('backend_dir', "/tmp");
|
||||
|
||||
my $illrq = $builder->build({source => 'Illrequest'});
|
||||
my $illrq_obj = Koha::Illrequests->find($illrq->{illrequest_id});
|
||||
$illrq_obj->_config($config);
|
||||
$illrq_obj->_backend($backend);
|
||||
|
||||
# getLimits
|
||||
$config->set_series('getLimitRules',
|
||||
{ CPL => { count => 1, method => 'test' } },
|
||||
{ default => { count => 0, method => 'active' } });
|
||||
is_deeply($illrq_obj->getLimits({ type => 'branch', value => "CPL" }),
|
||||
{ count => 1, method => 'test' },
|
||||
"getLimits: by value.");
|
||||
is_deeply($illrq_obj->getLimits({ type => 'branch' }),
|
||||
{ count => 0, method => 'active' },
|
||||
"getLimits: by default.");
|
||||
is_deeply($illrq_obj->getLimits({ type => 'branch', value => "CPL" }),
|
||||
{ count => -1, method => 'active' },
|
||||
"getLimits: by hard-coded.");
|
||||
|
||||
#_limit_counter
|
||||
is($illrq_obj->_limit_counter('annual', { branchcode => $illrq_obj->branchcode }),
|
||||
1, "_limit_counter: Initial branch annual count.");
|
||||
is($illrq_obj->_limit_counter('active', { branchcode => $illrq_obj->branchcode }),
|
||||
1, "_limit_counter: Initial branch active count.");
|
||||
is($illrq_obj->_limit_counter('annual', { borrowernumber => $illrq_obj->borrowernumber }),
|
||||
1, "_limit_counter: Initial patron annual count.");
|
||||
is($illrq_obj->_limit_counter('active', { borrowernumber => $illrq_obj->borrowernumber }),
|
||||
1, "_limit_counter: Initial patron active count.");
|
||||
$builder->build({
|
||||
source => 'Illrequest',
|
||||
value => {
|
||||
branchcode => $illrq_obj->branchcode,
|
||||
borrowernumber => $illrq_obj->borrowernumber,
|
||||
}
|
||||
});
|
||||
is($illrq_obj->_limit_counter('annual', { branchcode => $illrq_obj->branchcode }),
|
||||
2, "_limit_counter: Add a qualifying request for branch annual count.");
|
||||
is($illrq_obj->_limit_counter('active', { branchcode => $illrq_obj->branchcode }),
|
||||
2, "_limit_counter: Add a qualifying request for branch active count.");
|
||||
is($illrq_obj->_limit_counter('annual', { borrowernumber => $illrq_obj->borrowernumber }),
|
||||
2, "_limit_counter: Add a qualifying request for patron annual count.");
|
||||
is($illrq_obj->_limit_counter('active', { borrowernumber => $illrq_obj->borrowernumber }),
|
||||
2, "_limit_counter: Add a qualifying request for patron active count.");
|
||||
$builder->build({
|
||||
source => 'Illrequest',
|
||||
value => {
|
||||
branchcode => $illrq_obj->branchcode,
|
||||
borrowernumber => $illrq_obj->borrowernumber,
|
||||
placed => "2005-05-31",
|
||||
}
|
||||
});
|
||||
is($illrq_obj->_limit_counter('annual', { branchcode => $illrq_obj->branchcode }),
|
||||
2, "_limit_counter: Add an out-of-date branch request.");
|
||||
is($illrq_obj->_limit_counter('active', { branchcode => $illrq_obj->branchcode }),
|
||||
3, "_limit_counter: Add a qualifying request for branch active count.");
|
||||
is($illrq_obj->_limit_counter('annual', { borrowernumber => $illrq_obj->borrowernumber }),
|
||||
2, "_limit_counter: Add an out-of-date patron request.");
|
||||
is($illrq_obj->_limit_counter('active', { borrowernumber => $illrq_obj->borrowernumber }),
|
||||
3, "_limit_counter: Add a qualifying request for patron active count.");
|
||||
$builder->build({
|
||||
source => 'Illrequest',
|
||||
value => {
|
||||
branchcode => $illrq_obj->branchcode,
|
||||
borrowernumber => $illrq_obj->borrowernumber,
|
||||
status => "COMP",
|
||||
}
|
||||
});
|
||||
is($illrq_obj->_limit_counter('annual', { branchcode => $illrq_obj->branchcode }),
|
||||
3, "_limit_counter: Add a qualifying request for branch annual count.");
|
||||
is($illrq_obj->_limit_counter('active', { branchcode => $illrq_obj->branchcode }),
|
||||
3, "_limit_counter: Add a completed request for branch active count.");
|
||||
is($illrq_obj->_limit_counter('annual', { borrowernumber => $illrq_obj->borrowernumber }),
|
||||
3, "_limit_counter: Add a qualifying request for patron annual count.");
|
||||
is($illrq_obj->_limit_counter('active', { borrowernumber => $illrq_obj->borrowernumber }),
|
||||
3, "_limit_counter: Add a completed request for patron active count.");
|
||||
|
||||
# check_limits:
|
||||
|
||||
# We've tested _limit_counter, so all we need to test here is whether the
|
||||
# current counts of 3 for each work as they should against different
|
||||
# configuration declarations.
|
||||
|
||||
# No limits
|
||||
$config->set_always('getLimitRules', undef);
|
||||
is($illrq_obj->check_limits({patron => $illrq_obj->patron,
|
||||
librarycode => $illrq_obj->branchcode}),
|
||||
1, "check_limits: no configuration => no limits.");
|
||||
|
||||
# Branch tests
|
||||
$config->set_always('getLimitRules',
|
||||
{ $illrq_obj->branchcode => { count => 1, method => 'active' } });
|
||||
is($illrq_obj->check_limits({patron => $illrq_obj->patron,
|
||||
librarycode => $illrq_obj->branchcode}),
|
||||
0, "check_limits: branch active limit exceeded.");
|
||||
$config->set_always('getLimitRules',
|
||||
{ $illrq_obj->branchcode => { count => 1, method => 'annual' } });
|
||||
is($illrq_obj->check_limits({patron => $illrq_obj->patron,
|
||||
librarycode => $illrq_obj->branchcode}),
|
||||
0, "check_limits: branch annual limit exceeded.");
|
||||
$config->set_always('getLimitRules',
|
||||
{ $illrq_obj->branchcode => { count => 4, method => 'active' } });
|
||||
is($illrq_obj->check_limits({patron => $illrq_obj->patron,
|
||||
librarycode => $illrq_obj->branchcode}),
|
||||
1, "check_limits: branch active limit OK.");
|
||||
$config->set_always('getLimitRules',
|
||||
{ $illrq_obj->branchcode => { count => 4, method => 'annual' } });
|
||||
is($illrq_obj->check_limits({patron => $illrq_obj->patron,
|
||||
librarycode => $illrq_obj->branchcode}),
|
||||
1, "check_limits: branch annual limit OK.");
|
||||
|
||||
# Patron tests
|
||||
$config->set_always('getLimitRules',
|
||||
{ $illrq_obj->patron->categorycode => { count => 1, method => 'active' } });
|
||||
is($illrq_obj->check_limits({patron => $illrq_obj->patron,
|
||||
librarycode => $illrq_obj->branchcode}),
|
||||
0, "check_limits: patron category active limit exceeded.");
|
||||
$config->set_always('getLimitRules',
|
||||
{ $illrq_obj->patron->categorycode => { count => 1, method => 'annual' } });
|
||||
is($illrq_obj->check_limits({patron => $illrq_obj->patron,
|
||||
librarycode => $illrq_obj->branchcode}),
|
||||
0, "check_limits: patron category annual limit exceeded.");
|
||||
$config->set_always('getLimitRules',
|
||||
{ $illrq_obj->patron->categorycode => { count => 4, method => 'active' } });
|
||||
is($illrq_obj->check_limits({patron => $illrq_obj->patron,
|
||||
librarycode => $illrq_obj->branchcode}),
|
||||
1, "check_limits: patron category active limit OK.");
|
||||
$config->set_always('getLimitRules',
|
||||
{ $illrq_obj->patron->categorycode => { count => 4, method => 'annual' } });
|
||||
is($illrq_obj->check_limits({patron => $illrq_obj->patron,
|
||||
librarycode => $illrq_obj->branchcode}),
|
||||
1, "check_limits: patron category annual limit OK.");
|
||||
|
||||
# One rule cancels the other
|
||||
$config->set_series('getLimitRules',
|
||||
# Branch rules allow request
|
||||
{ $illrq_obj->branchcode => { count => 4, method => 'active' } },
|
||||
# Patron rule forbids it
|
||||
{ $illrq_obj->patron->categorycode => { count => 1, method => 'annual' } });
|
||||
is($illrq_obj->check_limits({patron => $illrq_obj->patron,
|
||||
librarycode => $illrq_obj->branchcode}),
|
||||
0, "check_limits: patron category veto overrides branch OK.");
|
||||
$config->set_series('getLimitRules',
|
||||
# Branch rules allow request
|
||||
{ $illrq_obj->branchcode => { count => 1, method => 'active' } },
|
||||
# Patron rule forbids it
|
||||
{ $illrq_obj->patron->categorycode => { count => 4, method => 'annual' } });
|
||||
is($illrq_obj->check_limits({patron => $illrq_obj->patron,
|
||||
librarycode => $illrq_obj->branchcode}),
|
||||
0, "check_limits: branch veto overrides patron category OK.");
|
||||
|
||||
$schema->storage->txn_rollback;
|
||||
};
|
||||
|
||||
1;
|
||||
|
|
@ -0,0 +1,136 @@
|
|||
#!/usr/bin/env perl
|
||||
|
||||
# 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 Test::More tests => 1;
|
||||
use Test::Mojo;
|
||||
use Test::Warn;
|
||||
|
||||
use t::lib::TestBuilder;
|
||||
use t::lib::Mocks;
|
||||
|
||||
use C4::Auth;
|
||||
use Koha::Illrequests;
|
||||
|
||||
my $schema = Koha::Database->new->schema;
|
||||
my $builder = t::lib::TestBuilder->new;
|
||||
|
||||
# FIXME: sessionStorage defaults to mysql, but it seems to break transaction handling
|
||||
# this affects the other REST api tests
|
||||
t::lib::Mocks::mock_preference( 'SessionStorage', 'tmp' );
|
||||
|
||||
my $remote_address = '127.0.0.1';
|
||||
my $t = Test::Mojo->new('Koha::REST::V1');
|
||||
|
||||
subtest 'list() tests' => sub {
|
||||
|
||||
plan tests => 6;
|
||||
|
||||
$schema->storage->txn_begin;
|
||||
|
||||
Koha::Illrequests->search->delete;
|
||||
my ( $borrowernumber, $session_id ) =
|
||||
create_user_and_session( { authorized => 1 } );
|
||||
|
||||
## Authorized user tests
|
||||
# No requests, so empty array should be returned
|
||||
my $tx = $t->ua->build_tx( GET => '/api/v1/illrequests' );
|
||||
$tx->req->cookies( { name => 'CGISESSID', value => $session_id } );
|
||||
$tx->req->env( { REMOTE_ADDR => $remote_address } );
|
||||
$t->request_ok($tx)->status_is(200)->json_is( [] );
|
||||
|
||||
# my $city_country = 'France';
|
||||
# my $city = $builder->build(
|
||||
# { source => 'City', value => { city_country => $city_country } } );
|
||||
#
|
||||
# # One city created, should get returned
|
||||
# $tx = $t->ua->build_tx( GET => '/api/v1/cities' );
|
||||
# $tx->req->cookies( { name => 'CGISESSID', value => $session_id } );
|
||||
# $tx->req->env( { REMOTE_ADDR => $remote_address } );
|
||||
# $t->request_ok($tx)->status_is(200)->json_is( [$city] );
|
||||
#
|
||||
# my $another_city = $builder->build(
|
||||
# { source => 'City', value => { city_country => $city_country } } );
|
||||
# my $city_with_another_country = $builder->build( { source => 'City' } );
|
||||
#
|
||||
# # Two cities created, they should both be returned
|
||||
# $tx = $t->ua->build_tx( GET => '/api/v1/cities' );
|
||||
# $tx->req->cookies( { name => 'CGISESSID', value => $session_id } );
|
||||
# $tx->req->env( { REMOTE_ADDR => $remote_address } );
|
||||
# $t->request_ok($tx)->status_is(200)
|
||||
# ->json_is( [ $city, $another_city, $city_with_another_country ] );
|
||||
#
|
||||
# # Filtering works, two cities sharing city_country
|
||||
# $tx =
|
||||
# $t->ua->build_tx( GET => "/api/v1/cities?city_country=" . $city_country );
|
||||
# $tx->req->cookies( { name => 'CGISESSID', value => $session_id } );
|
||||
# $tx->req->env( { REMOTE_ADDR => $remote_address } );
|
||||
# my $result =
|
||||
# $t->request_ok($tx)->status_is(200)->json_is( [ $city, $another_city ] );
|
||||
#
|
||||
# $tx = $t->ua->build_tx(
|
||||
# GET => "/api/v1/cities?city_name=" . $city->{city_name} );
|
||||
# $tx->req->cookies( { name => 'CGISESSID', value => $session_id } );
|
||||
# $tx->req->env( { REMOTE_ADDR => $remote_address } );
|
||||
# $t->request_ok($tx)->status_is(200)->json_is( [$city] );
|
||||
|
||||
# Warn on unsupported query parameter
|
||||
$tx = $t->ua->build_tx( GET => '/api/v1/illrequests?request_blah=blah' );
|
||||
$tx->req->cookies( { name => 'CGISESSID', value => $session_id } );
|
||||
$tx->req->env( { REMOTE_ADDR => $remote_address } );
|
||||
$t->request_ok($tx)->status_is(400)->json_is(
|
||||
[{ path => '/query/request_blah', message => 'Malformed query string'}]
|
||||
);
|
||||
|
||||
$schema->storage->txn_rollback;
|
||||
};
|
||||
|
||||
sub create_user_and_session {
|
||||
|
||||
my $args = shift;
|
||||
my $flags = ( $args->{authorized} ) ? $args->{authorized} : 0;
|
||||
my $dbh = C4::Context->dbh;
|
||||
|
||||
my $user = $builder->build(
|
||||
{
|
||||
source => 'Borrower',
|
||||
value => {
|
||||
flags => $flags
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
# Create a session for the authorized user
|
||||
my $session = C4::Auth::get_session('');
|
||||
$session->param( 'number', $user->{borrowernumber} );
|
||||
$session->param( 'id', $user->{userid} );
|
||||
$session->param( 'ip', '127.0.0.1' );
|
||||
$session->param( 'lasttime', time() );
|
||||
$session->flush;
|
||||
|
||||
if ( $args->{authorized} ) {
|
||||
$dbh->do( "
|
||||
INSERT INTO user_permissions (borrowernumber,module_bit,code)
|
||||
VALUES (?,3,'parameters_remaining_permissions')", undef,
|
||||
$user->{borrowernumber} );
|
||||
}
|
||||
|
||||
return ( $user->{borrowernumber}, $session->id );
|
||||
}
|
||||
|
||||
1;
|
||||
Loading…
Reference in New Issue