--- /dev/null
+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;
},
"vendor": {
"$ref": "definitions/vendor.json"
+ },
+ "fund": {
+ "$ref": "definitions/fund.json"
}
}
--- /dev/null
+{
+ "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"]
+}
"required": false,
"description": "Page size, for paginated object listing",
"type": "integer"
- }
+ },
+ "fundidPathParam": {
+ "$ref": "parameters/fund.json#/fundidPathParam"
+ }
}
--- /dev/null
+{
+ "fundidPathParam": {
+ "name": "fund_id",
+ "in": "path",
+ "description": "Fund id",
+ "required": true,
+ "type": "integer"
+ }
+}
"/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"
},
--- /dev/null
+{
+ "/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"
+ }
+ }
+ }
+ }
+}
"type": "integer",
"description": "internally assigned vendor identifier",
"readOnly": true
+ },
+ "fund_id": {
+ "type": "integer",
+ "description": "internally assigned fund identifier",
+ "readOnly": true
}
+
}
--- /dev/null
+#!/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 );
+}