diff --git a/app/controllers/api/v1/user/ordergroup_controller.rb b/app/controllers/api/v1/user/ordergroup_controller.rb new file mode 100644 index 00000000..7af268f2 --- /dev/null +++ b/app/controllers/api/v1/user/ordergroup_controller.rb @@ -0,0 +1,23 @@ +class Api::V1::User::OrdergroupController < Api::V1::BaseController + + before_action ->{ doorkeeper_authorize! 'finance:user' }, only: [:financial_overview] + + def financial_overview + ordergroup = Ordergroup.include_transaction_class_sum.find(current_ordergroup.id) + + render json: { + financial_overview: { + account_balance: ordergroup.account_balance.to_f, + available_funds: ordergroup.get_available_funds.to_f, + financial_transaction_class_sums: FinancialTransactionClass.sorted.map { |c| + { + id: c.id, + name: c.display, + amount: ordergroup["sum_of_class_#{c.id}"].to_f + } + } + } + } + end + +end diff --git a/config/routes.rb b/config/routes.rb index 07d32a4f..07b49cb9 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -265,6 +265,7 @@ Rails.application.routes.draw do namespace :user do root to: 'users#show' + get :financial_overview, to: 'ordergroup#financial_overview' resources :financial_transactions, only: [:index, :show, :create] resources :group_order_articles end diff --git a/doc/swagger.v1.yml b/doc/swagger.v1.yml index 719f8fd5..6c34e44c 100644 --- a/doc/swagger.v1.yml +++ b/doc/swagger.v1.yml @@ -58,6 +58,31 @@ paths: security: - foodsoft_auth: ['user:read', 'user:write'] + /user/financial_overview: + get: + summary: financial summary about the currently logged-in user + tags: + - 1. User + - 6. FinancialTransaction + responses: + 200: + description: success + schema: + type: object + properties: + financial_overview: + $ref: '#/definitions/FinanceOverview' + 401: + description: not logged-in + schema: + $ref: '#/definitions/Error401' + 403: + description: missing scope + schema: + $ref: '#/definitions/Error403' + security: + - foodsoft_auth: ['finance:user'] + /user/financial_transactions: get: summary: financial transactions of the member's ordergroup @@ -828,6 +853,32 @@ definitions: description: name of the class of the transaction required: ['id', 'name', 'financial_transaction_class_id', 'financial_transaction_class_name'] + FinanceOverview: + type: object + properties: + account_balance: + type: number + description: booked accout balance of ordergroup + available_funds: + type: number + description: fund available to order articles + financial_transaction_class_sums: + type: array + items: + type: object + properties: + id: + type: integer + description: id of the financial transaction class + name: + type: string + description: name of the financial transaction class + amount: + type: number + description: sum of the amounts belonging to the financial transaction class + required: ['id', 'name', 'amount'] + required: ['account_balance', 'available_funds', 'financial_transaction_class_sums'] + ArticleCategory: type: object properties: diff --git a/spec/api/v1/swagger_spec.rb b/spec/api/v1/swagger_spec.rb index ecafe756..0710b8a7 100644 --- a/spec/api/v1/swagger_spec.rb +++ b/spec/api/v1/swagger_spec.rb @@ -27,6 +27,16 @@ describe 'API v1', type: :apivore, order: :defined do it_handles_invalid_token_and_scope(:get, '/user') end + context 'user/financial_overview' do + let(:api_scopes) { ['finance:user'] } + let!(:user) { create :user, :ordergroup } + + it { is_expected.to validate(:get, '/user/financial_overview', 200, api_auth) } + it { is_expected.to validate(:get, '/user/financial_overview', 401) } + + it_handles_invalid_token_and_scope(:get, '/user/financial_overview') + end + context 'user/financial_transactions' do let(:api_scopes) { ['finance:user'] } let(:other_user) { create :user, :ordergroup } diff --git a/spec/api/v1/user/ordergroup_spec.rb b/spec/api/v1/user/ordergroup_spec.rb new file mode 100644 index 00000000..06cca3e2 --- /dev/null +++ b/spec/api/v1/user/ordergroup_spec.rb @@ -0,0 +1,55 @@ +require 'spec_helper' + +describe Api::V1::User::OrdergroupController, type: :controller do + include ApiOAuth + let(:user) { create :user, :ordergroup } + let(:api_scopes) { ['finance:user'] } + + let(:ftc1) { create :financial_transaction_class } + let(:ftc2) { create :financial_transaction_class } + let(:ftt1) { create :financial_transaction_type, financial_transaction_class: ftc1 } + let(:ftt2) { create :financial_transaction_type, financial_transaction_class: ftc2 } + let(:ftt3) { create :financial_transaction_type, financial_transaction_class: ftc2 } + + describe "GET :financial_overview" do + let(:order) { create(:order, article_count: 1) } + let(:oa_1) { order.order_articles.first } + + let!(:go) { create(:group_order, order: order, ordergroup: user.ordergroup) } + let!(:goa) { create(:group_order_article, group_order: go, order_article: oa_1, quantity: 1, tolerance: 0) } + before { go.update_price!; user.ordergroup.update_stats! } + + let(:json_financial_overview) { json_response['financial_overview'] } + + before do + og = user.ordergroup + og.add_financial_transaction!(-1, '-1', user, ftt1) + og.add_financial_transaction!(2, '2', user, ftt1) + og.add_financial_transaction!(3, '3', user, ftt1) + + og.add_financial_transaction!(-10, '-10', user, ftt2) + og.add_financial_transaction!(20, '20', user, ftt2) + og.add_financial_transaction!(30, '30', user, ftt2) + + og.add_financial_transaction!(-100, '-100', user, ftt3) + og.add_financial_transaction!(200, '200', user, ftt3) + og.add_financial_transaction!(300, '300', user, ftt3) + end + + it "returns correct values" do + get :financial_overview, params: { foodcoop: 'f' } + expect(json_financial_overview['account_balance']).to eq 444 + expect(json_financial_overview['available_funds']).to eq 444 - go.price + + ftcs = Hash[ json_financial_overview['financial_transaction_class_sums'].map { |x| [x['id'], x] } ] + + ftcs1 = ftcs[ftc1.id] + expect(ftcs1['name']).to eq ftc1.name + expect(ftcs1['amount']).to eq 4 + + ftcs2 = ftcs[ftc2.id] + expect(ftcs2['name']).to eq ftc2.name + expect(ftcs2['amount']).to eq 440 + end + end +end