Browse Source

Bug 19661: REST API - Funds Endpoint

This patch adds a new route to the REST api:

/api/v1/acquisitions/funds/

Signed-off-by: David Bourgault <david.bourgault@inlibro.com>

Signed-off-by: Josef Moravec <josef.moravec@gmail.com>
Signed-off-by: Martin Renvoize <martin.renvoize@ptfs-europe.com>

Signed-off-by: Nick Clemens <nick@bywatersolutions.com>
19.05.x
Matthias Meusburger 5 years ago
committed by Nick Clemens
parent
commit
717975abeb
  1. 105
      Koha/REST/V1/Acquisitions/Funds.pm
  2. 3
      api/v1/swagger/definitions.json
  3. 24
      api/v1/swagger/definitions/fund.json
  4. 5
      api/v1/swagger/parameters.json
  5. 9
      api/v1/swagger/parameters/fund.json
  6. 3
      api/v1/swagger/paths.json
  7. 73
      api/v1/swagger/paths/acquisitions_funds.json
  8. 6
      api/v1/swagger/x-primitives.json
  9. 125
      t/db_dependent/api/v1/acquisitions_funds.t

105
Koha/REST/V1/Acquisitions/Funds.pm

@ -0,0 +1,105 @@
package Koha::REST::V1::Acquisitions::Funds;
# 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 C4::Budgets;
use JSON qw(to_json);
use Try::Tiny;
=head1 NAME
Koha::REST::V1::Acquisitions::Funds
=head1 API
=head2 Methods
=head3 list_funds
Controller function that handles listing Funds
=cut
sub list_funds {
my $c = shift->openapi->valid_input or return;
my $args = _to_model($c->req->params->to_hash);
my $filter;
for my $filter_param ( keys %$args ) {
$filter->{$filter_param} = { LIKE => $args->{$filter_param} . "%" }
if $args->{$filter_param};
}
return try {
my $funds = GetBudgets($filter);
my @fundsArray = map { _to_api($_) } @$funds;
return $c->render( status => 200,
openapi => \@fundsArray);
}
catch {
if ( $_->isa('DBIx::Class::Exception') ) {
return $c->render( status => 500,
openapi => { error => $_->{msg} } );
}
else {
return $c->render( status => 500,
openapi => { error => "Something went wrong, check the logs. $_ $filter" } );
}
};
}
=head3 _to_api
Helper function that maps a Fund into
the attribute names the exposed REST api spec.
=cut
sub _to_api {
my $fund = shift;
my $returnfund;
$returnfund->{id} = delete $fund->{budget_id};
$returnfund->{code} = delete $fund->{budget_code};
$returnfund->{name} = delete $fund->{budget_name};
return $returnfund;
}
=head3 _to_model
Helper function that maps REST api objects into Fund
attribute names.
=cut
sub _to_model {
my $fund = shift;
# Rename back
$fund->{budget_id} = delete $fund->{id};
$fund->{budget_code} = delete $fund->{code};
$fund->{budget_name} = delete $fund->{name};
return $fund;
}
1;

3
api/v1/swagger/definitions.json

@ -28,5 +28,8 @@
},
"vendor": {
"$ref": "definitions/vendor.json"
},
"fund": {
"$ref": "definitions/fund.json"
}
}

24
api/v1/swagger/definitions/fund.json

@ -0,0 +1,24 @@
{
"type": "object",
"properties": {
"id": {
"$ref": "../x-primitives.json#/fund_id"
},
"code": {
"type": [
"string",
"null"
],
"description": "Fund code"
},
"name": {
"type": [
"string",
"null"
],
"description": "Fund name"
}
},
"additionalProperties": false,
"required": ["name"]
}

5
api/v1/swagger/parameters.json

@ -54,5 +54,8 @@
"required": false,
"description": "Page size, for paginated object listing",
"type": "integer"
}
},
"fundidPathParam": {
"$ref": "parameters/fund.json#/fundidPathParam"
}
}

9
api/v1/swagger/parameters/fund.json

@ -0,0 +1,9 @@
{
"fundidPathParam": {
"name": "fund_id",
"in": "path",
"description": "Fund id",
"required": true,
"type": "integer"
}
}

3
api/v1/swagger/paths.json

@ -8,6 +8,9 @@
"/acquisitions/vendors/{vendor_id}": {
"$ref": "paths/acquisitions_vendors.json#/~1acquisitions~1vendors~1{vendor_id}"
},
"/acquisitions/funds": {
"$ref": "paths/acquisitions_funds.json#/~1acquisitions~1funds"
},
"/cities": {
"$ref": "paths/cities.json#/~1cities"
},

73
api/v1/swagger/paths/acquisitions_funds.json

@ -0,0 +1,73 @@
{
"/acquisitions/funds": {
"get": {
"x-mojo-to": "Acquisitions::Funds#list_funds",
"operationId": "listFunds",
"tags": ["acquisitions","funds"],
"produces": [
"application/json"
],
"parameters": [{
"name": "name",
"in": "query",
"description": "Case insensitive search on fund name",
"required": false,
"type": "string"
},
{
"name": "budget_owner_id",
"in": "query",
"description": "Display only the funds that belongs to the given borrowernumber",
"required": false,
"type": "integer"
}
],
"responses": {
"200": {
"description": "A list of funds",
"schema": {
"type": "array",
"items": {
"$ref": "../definitions.json#/fund"
}
}
},
"401": {
"description": "Authentication required",
"schema": {
"$ref": "../definitions.json#/error"
}
},
"403": {
"description": "Access forbidden",
"schema": {
"$ref": "../definitions.json#/error"
}
},
"404": {
"description": "Fund not found",
"schema": {
"$ref": "../definitions.json#/error"
}
},
"500": {
"description": "Internal server error",
"schema": {
"$ref": "../definitions.json#/error"
}
},
"503": {
"description": "Under maintenance",
"schema": {
"$ref": "../definitions.json#/error"
}
}
},
"x-koha-authorization": {
"permissions": {
"acquisition": "budget_manage_all"
}
}
}
}
}

6
api/v1/swagger/x-primitives.json

@ -42,5 +42,11 @@
"type": "integer",
"description": "internally assigned vendor identifier",
"readOnly": true
},
"fund_id": {
"type": "integer",
"description": "internally assigned fund identifier",
"readOnly": true
}
}

125
t/db_dependent/api/v1/acquisitions_funds.t

@ -0,0 +1,125 @@
#!/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 => 14;
use Test::Mojo;
use t::lib::TestBuilder;
use t::lib::Mocks;
use C4::Auth;
use C4::Context;
use C4::Budgets;
use Koha::Database;
use Koha::Patron;
my $schema = Koha::Database->new->schema;
my $builder = t::lib::TestBuilder->new();
$schema->storage->txn_begin;
# 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' );
$ENV{REMOTE_ADDR} = '127.0.0.1';
my $t = Test::Mojo->new('Koha::REST::V1');
my $fund1 = {
budget_code => 'ABCD',
budget_amount => '123.132000',
budget_name => 'Periodiques',
budget_notes => 'This is a note',
};
my $budget_id = AddBudget($fund1);
isnt( $budget_id, undef, 'AddBudget does not returns undef' );
$t->get_ok('/api/v1/acquisitions/funds')
->status_is(401);
$t->get_ok('/api/v1/acquisitions/funds/?name=testFund')
->status_is(401);
my ( $borrowernumber, $session_id )
#= create_user_and_session( { authorized => 1 } );
= create_user_and_session( );
my $tx = $t->ua->build_tx(GET => '/api/v1/acquisitions/funds');
$tx->req->cookies({name => 'CGISESSID', value => $session_id});
$tx->req->env({REMOTE_ADDR => '127.0.0.1'});
$t->request_ok($tx)
->status_is(403);
$tx = $t->ua->build_tx(GET => "/api/v1/acquisitions/funds/?name=" . $fund1->{ budget_name });
$tx->req->cookies({name => 'CGISESSID', value => $session_id});
$tx->req->env({REMOTE_ADDR => '127.0.0.1'});
$t->request_ok($tx)
->status_is(403);
( $borrowernumber, $session_id )
= create_user_and_session( { authorized => 1 } );
$tx = $t->ua->build_tx(GET => '/api/v1/acquisitions/funds');
$tx->req->cookies({name => 'CGISESSID', value => $session_id});
$tx->req->env({REMOTE_ADDR => '127.0.0.1'});
$t->request_ok($tx)
->status_is(200);
$tx = $t->ua->build_tx(GET => "/api/v1/acquisitions/funds/?name=" . $fund1->{ budget_name });
$tx->req->cookies({name => 'CGISESSID', value => $session_id});
$tx->req->env({REMOTE_ADDR => '127.0.0.1'});
$t->request_ok($tx)
->status_is(200)
->json_like('/0/name' => qr/$fund1->{ budget_name }/);
$schema->storage->txn_rollback;
sub create_user_and_session {
my $args = shift;
my $flags = ( $args->{authorized} ) ? 2052 : 0;
# 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(
q{
INSERT INTO user_permissions (borrowernumber,module_bit,code)
VALUES (?,11,'budget_manage_all')},
undef, $user->{borrowernumber}
);
}
return ( $user->{borrowernumber}, $session->id );
}
Loading…
Cancel
Save