From 786df0b274507fdb4dab5cbeb2c73d18033537b2 Mon Sep 17 00:00:00 2001 From: Matt Blenkinsop Date: Thu, 22 Aug 2024 17:49:53 +0100 Subject: [PATCH] wip --- .../Acquire/Controllers/ControllerUtils.pm | 17 + .../FundManagement/FundAllocations.pm | 13 +- tests/t/api/fund_allocations.t | 329 ++++++++++++++++++ 3 files changed, 348 insertions(+), 11 deletions(-) create mode 100644 tests/t/api/fund_allocations.t diff --git a/Koha/Plugin/Acquire/Controllers/ControllerUtils.pm b/Koha/Plugin/Acquire/Controllers/ControllerUtils.pm index 7d69e6e..69ed9d3 100644 --- a/Koha/Plugin/Acquire/Controllers/ControllerUtils.pm +++ b/Koha/Plugin/Acquire/Controllers/ControllerUtils.pm @@ -148,4 +148,21 @@ sub add_accounting_values_to_ledgers_or_fund_groups_or_funds { return $data; } +sub add_totals_to_fund_allocations { + my ($self, $args) = @_; + + my $allocations = $args->{allocations}; + my @sorted_allocations = sort { $a->{allocation_amount} <=> $b->{allocation_amount} } @$allocations; + + my $total = 0; + foreach my $allocation_index ( 1 .. scalar(@sorted_allocations) ) { + my $allocation = $sorted_allocations[ $allocation_index - 1 ]; + $allocation->{allocation_index} = $allocation_index; + $total += $allocation->{allocation_amount}; + $allocation->{new_fund_value} = $total; + } + + return \@sorted_allocations; +} + 1; diff --git a/Koha/Plugin/Acquire/Controllers/FundManagement/FundAllocations.pm b/Koha/Plugin/Acquire/Controllers/FundManagement/FundAllocations.pm index 59d586b..7a7312e 100644 --- a/Koha/Plugin/Acquire/Controllers/FundManagement/FundAllocations.pm +++ b/Koha/Plugin/Acquire/Controllers/FundManagement/FundAllocations.pm @@ -49,18 +49,9 @@ sub list { my $filtered_fund_allocations = Koha::Plugin::Acquire::Controllers::ControllerUtils->filter_data_by_group( { dataset => $fund_allocations } ); - my @sorted_allocations = - sort { $a->{fund_allocation_id} <=> $b->{fund_allocation_id} } @{$filtered_fund_allocations}; - - my $total = 0; - foreach my $allocation_index ( 1 .. scalar(@sorted_allocations) ) { - my $allocation = $sorted_allocations[ $allocation_index - 1 ]; - $allocation->{allocation_index} = $allocation_index; - $total += $allocation->{allocation_amount}; - $allocation->{new_fund_value} = $total; - } + my $sorted_allocations = Koha::Plugin::Acquire::Controllers::ControllerUtils->add_totals_to_fund_allocations( { allocations => $filtered_fund_allocations } ); - return $c->render( status => 200, openapi => \@sorted_allocations ); + return $c->render( status => 200, openapi => $sorted_allocations ); } catch { $c->unhandled_exception($_); }; diff --git a/tests/t/api/fund_allocations.t b/tests/t/api/fund_allocations.t new file mode 100644 index 0000000..23d1b7b --- /dev/null +++ b/tests/t/api/fund_allocations.t @@ -0,0 +1,329 @@ +#!/usr/bin/env perl + +# Copyright 2024 PTFS Europe + +# This file is part of Koha. +# +# Koha is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# Koha is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Koha; if not, see . + +use Modern::Perl; + +use Test::More tests => 4; +use Test::Mojo; + +use t::lib::TestBuilder; +use t::lib::Mocks; + +use Koha::Acquire::Funds::FundAllocations; +use Koha::Database; + +# This test file contains commented out sections that other tests do not. +# These are examples for what will be used when the API definitions and permissions have been defined + +my $schema = Koha::Database->new->schema; +my $builder = t::lib::TestBuilder->new; + +my $t = Test::Mojo->new('Koha::REST::V1'); +t::lib::Mocks::mock_preference( 'RESTBasicAuth', 1 ); + +subtest 'list() tests' => sub { + + plan tests => 23; + + $schema->storage->txn_begin; + + my $librarian = $builder->build_object( + { + class => 'Koha::Patrons', + value => { flags => 2**28 } + } + ); + my $password = 'thePassword123'; + $librarian->set_password( { password => $password, skip_validation => 1 } ); + my $userid = $librarian->userid; + + my $patron = $builder->build_object( + { + class => 'Koha::Patrons', + value => { flags => 0 } + } + ); + + $patron->set_password( { password => $password, skip_validation => 1 } ); + my $unauth_userid = $patron->userid; + + my $library = $builder->build_object( { class => 'Koha::Libraries' } ); + my $lib_group = Koha::Library::Group->new( { title => "Test root group" } )->store(); + my $group_library = + Koha::Library::Group->new( { parent_id => $lib_group->id, branchcode => $library->branchcode } )->store(); + + my $module = Test::MockModule->new('C4::Context'); + $module->mock( + 'mybranch', + sub { + return $library->branchcode; + } + ); + + ## Authorized user tests + # No titles, so empty array should be returned + $t->get_ok("//$userid:$password@/api/v1/contrib/acquire/fund_allocations")->status_is(200)->json_is( [] ); + + my $fund_allocation = $builder->build_object( + { class => 'Koha::Acquire::Funds::FundAllocations', value => { visible_to => $lib_group->id } } ); + + my $module2 = Test::MockModule->new('Koha::Plugin::Acquire::Controllers::ControllerUtils'); + $module2->mock( + 'add_totals_to_fund_allocations', + sub { + my @allocations = (); + push @allocations, $fund_allocation->unblessed; + return \@allocations; + } + ); + $t->get_ok("//$userid:$password@/api/v1/contrib/acquire/fund_allocations")->status_is(200)->json_is( '/0/currency' => $fund_allocation->currency )->json_is( '/0/reference' => $fund_allocation->reference ); + + my $another_fa = $builder->build_object( + { + class => 'Koha::Acquire::Funds::FundAllocations', + value => { visible_to => $lib_group->id } + + } + ); + + $module2->mock( + 'add_totals_to_fund_allocations', + sub { + my @allocations = (); + push @allocations, $fund_allocation->unblessed; + push @allocations, $another_fa->unblessed; + return \@allocations; + } + ); + # Two fund_allocations created, they should both be returned + $t->get_ok("//$userid:$password@/api/v1/contrib/acquire/fund_allocations")->status_is(200) + ->json_is( '/0/currency' => $fund_allocation->currency ) + ->json_is( '/0/reference' => $fund_allocation->reference ) + ->json_is( '/1/currency' => $another_fa->currency ) + ->json_is( '/1/reference' => $another_fa->reference ); + + # Attempt to search by title like 'ko' + $fund_allocation->delete; + $another_fa->delete; + $module2->mock( + 'add_totals_to_fund_allocations', + sub { + my @allocations = (); + return \@allocations; + } + ); + $t->get_ok(qq~//$userid:$password@/api/v1/contrib/acquire/fund_allocations?q=[{"me.reference":{"like":"%ko%"}}]~)->status_is(200) + ->json_is( [] ); + + my $fund_allocations_search = $builder->build_object( + { + class => 'Koha::Acquire::Funds::FundAllocations', + value => { + reference => 'koha', + visible_to => $lib_group->id + } + } + ); + $module2->mock( + 'add_totals_to_fund_allocations', + sub { + my @allocations = (); + push @allocations, $fund_allocations_search->unblessed; + return \@allocations; + } + ); + + # Search works, searching for title like 'ko' + $t->get_ok(qq~//$userid:$password@/api/v1/contrib/acquire/fund_allocations?q=[{"me.reference":{"like":"%ko%"}}]~)->status_is(200) + ->json_is( '/0/currency' => $fund_allocations_search->currency ) + ->json_is( '/0/reference' => $fund_allocations_search->reference ); + + + # Warn on unsupported query parameter + $t->get_ok("//$userid:$password@/api/v1/contrib/acquire/fund_allocations?blah=blah")->status_is(400) + ->json_is( [ { path => '/query/blah', message => 'Malformed query string' } ] ); + + $schema->storage->txn_rollback; +}; + +subtest 'get() tests' => sub { + + plan tests => 6; + + $schema->storage->txn_begin; + + my $librarian = $builder->build_object( + { + class => 'Koha::Patrons', + value => { flags => 2**28 } + } + ); + my $password = 'thePassword123'; + $librarian->set_password( { password => $password, skip_validation => 1 } ); + my $userid = $librarian->userid; + + my $patron = $builder->build_object( + { + class => 'Koha::Patrons', + value => { flags => 0 } + } + ); + + $patron->set_password( { password => $password, skip_validation => 1 } ); + my $unauth_userid = $patron->userid; + + my $library = $builder->build_object( { class => 'Koha::Libraries' } ); + my $lib_group = Koha::Library::Group->new( { title => "Test root group" } )->store(); + my $group_library = + Koha::Library::Group->new( { parent_id => $lib_group->id, branchcode => $library->branchcode } )->store(); + + my $module = Test::MockModule->new('C4::Context'); + $module->mock( + 'mybranch', + sub { + return $library->branchcode; + } + ); + my $fund_allocation = $builder->build_object( + { class => 'Koha::Acquire::Funds::FundAllocations', value => { visible_to => $lib_group->id } } ); + + my $module2 = Test::MockModule->new('Koha::Plugin::Acquire::Controllers::ControllerUtils'); + $module2->mock( + 'add_lib_group_data', + sub { + return $fund_allocation; + } + ); + + # This fund_allocation exists, should get returned + $t->get_ok( "//$userid:$password@/api/v1/contrib/acquire/fund_allocations/" . $fund_allocation->fund_allocation_id )->status_is(200) + ->json_is( $fund_allocation->to_api ); + + # Attempt to get non-existent fund_allocations + my $non_existent_fund_allocations = $builder->build_object( { class => 'Koha::Acquire::Funds::FundAllocations' } ); + my $non_existent_id = $non_existent_fund_allocations->fund_allocation_id; + $non_existent_fund_allocations->delete; + + $t->get_ok("//$userid:$password@/api/v1/contrib/acquire/fund_allocations/$non_existent_id")->status_is(404) + ->json_is( '/error' => 'Ledger not found' ); + + $schema->storage->txn_rollback; +}; + +subtest 'add() tests' => sub { + + plan tests => 9; + + $schema->storage->txn_begin; + + my $librarian = $builder->build_object( + { + class => 'Koha::Patrons', + value => { flags => 2**28 } + } + ); + my $password = 'thePassword123'; + $librarian->set_password( { password => $password, skip_validation => 1 } ); + my $userid = $librarian->userid; + + my $patron = $builder->build_object( + { + class => 'Koha::Patrons', + value => { flags => 0 } + } + ); + + $patron->set_password( { password => $password, skip_validation => 1 } ); + my $unauth_userid = $patron->userid; + + my $library = $builder->build_object( { class => 'Koha::Libraries' } ); + my $lib_group = Koha::Library::Group->new( { title => "Test root group" } )->store(); + my $group_library = + Koha::Library::Group->new( { parent_id => $lib_group->id, branchcode => $library->branchcode } )->store(); + + my $module = Test::MockModule->new('C4::Context'); + $module->mock( + 'mybranch', + sub { + return $library->branchcode; + } + ); + + my $fund_allocation = { + name => "test", + description => "test", + code => "1", + external_id => "01", + status => "1", + owner_id => "1", + visible_to => "1", + currency => "GBP", + }; + + # Authorized attempt to write + my $fund_allocation_id = + $t->post_ok( "//$userid:$password@/api/v1/contrib/acquire/fund_allocations" => json => $fund_allocation ) + ->status_is( 201, 'SWAGGER3.2.1' )->header_like( + Location => qr|^/api/v1/contrib/acquire/fund_allocations/\d*|, + 'SWAGGER3.4.1' + )->json_is( '/name' => $fund_allocation->{name} )->json_is( '/description' => $fund_allocation->{description} ) + ->json_is( '/code' => $fund_allocation->{code} )->json_is( '/status' => $fund_allocation->{status} ) + ->json_is( '/owner_id' => $fund_allocation->{owner_id} )->json_is( '/visible_to' => $fund_allocation->{visible_to} ) + ->tx->res->json->{fund_allocation_id}; + + $schema->storage->txn_rollback; +}; + +subtest 'delete() tests' => sub { + + plan tests => 5; + + $schema->storage->txn_begin; + + my $librarian = $builder->build_object( + { + class => 'Koha::Patrons', + value => { flags => 2**28 } + } + ); + my $password = 'thePassword123'; + $librarian->set_password( { password => $password, skip_validation => 1 } ); + my $userid = $librarian->userid; + + my $patron = $builder->build_object( + { + class => 'Koha::Patrons', + value => { flags => 0 } + } + ); + + $patron->set_password( { password => $password, skip_validation => 1 } ); + my $unauth_userid = $patron->userid; + + my $fund_allocation_id = $builder->build_object( { class => 'Koha::Acquire::Funds::FundAllocations' } )->fund_allocation_id; + + # Delete existing fund_allocations + $t->delete_ok("//$userid:$password@/api/v1/contrib/acquire/fund_allocations/$fund_allocation_id")->status_is( 204, 'SWAGGER3.2.4' ) + ->content_is( '', 'SWAGGER3.3.4' ); + + # Attempt to delete non-existent fund_allocations + $t->delete_ok("//$userid:$password@/api/v1/contrib/acquire/fund_allocations/$fund_allocation_id")->status_is(404); + + $schema->storage->txn_rollback; +};