Skip to content

Commit

Permalink
API v1 financial_transactions endpoints
Browse files Browse the repository at this point in the history
  • Loading branch information
wvengen committed Oct 15, 2018
1 parent b3b57ae commit 406ade0
Show file tree
Hide file tree
Showing 8 changed files with 252 additions and 0 deletions.
20 changes: 20 additions & 0 deletions app/controllers/api/v1/financial_transactions_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
class Api::V1::FinancialTransactionsController < Api::V1::BaseController
include Concerns::CollectionScope

before_action :require_ordergroup

def index
render_collection search_scope
end

def show
render json: scope.find(params.require(:id))
end

private

def scope
current_ordergroup.financial_transactions
end

end
49 changes: 49 additions & 0 deletions app/controllers/concerns/collection_scope.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
module Concerns::CollectionScope
extend ActiveSupport::Concern

private

def scope
raise NotImplementedError, 'Please override #scope when you use Concerns::CollectionScope'
end

def default_per_page
20
end

def max_per_page
250
end

def per_page
# allow max_per_page and default_per_page to be nil as well
if params[:per_page]
[params[:per_page].to_i, max_per_page].compact.min
else
default_per_page
end
end

def search_scope
s = scope
s = scope.ransack(params[:q]).result(distinct: true) if params[:q]
s = s.page(params[:page].to_i).per(per_page) if per_page && per_page >= 0
s
end

def render_collection(scope)
render json: scope, meta: collection_meta(scope)
end

def collection_meta(scope, extra = {})
return unless scope.respond_to?(:total_count) && per_page

{
page: params[:page].to_i,
per_page: per_page,
total_pages: (scope.total_count / [1, per_page].max).ceil,
total_count: scope.total_count
}.merge(extra)
end

end
8 changes: 8 additions & 0 deletions app/models/financial_transaction.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,14 @@ class FinancialTransaction < ActiveRecord::Base
initialize_financial_transaction_type
end

def self.ransackable_attributes(auth_object = nil)
%w(id amount note created_on user_id)
end

def self.ransackable_associations(auth_object = nil)
%w() # none, and certainly not user until we've secured that more
end

# Use this save method instead of simple save and after callback
def add_transaction!
ordergroup.add_financial_transaction! amount, note, user, financial_transaction_type
Expand Down
18 changes: 18 additions & 0 deletions app/serializers/financial_transaction_serializer.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
class FinancialTransactionSerializer < ActiveModel::Serializer
include ApplicationHelper

attributes :id, :user_id, :user_name, :amount, :note, :created_at

def user_name
show_user object.user
end

def amount
object.amount.to_f
end

def created_at
# use Rails convention in API, which is less easier to migrate later
object.created_on
end
end
1 change: 1 addition & 0 deletions config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,7 @@
resource :user, only: [:show]
resource :config, only: [:show]
resource :navigation, only: [:show]
resources :financial_transactions, only: [:index, :show]
end
end

Expand Down
119 changes: 119 additions & 0 deletions doc/swagger.v1.yml
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,59 @@ paths:
$ref: '#/definitions/Error401'
security:
- foodsoft_auth: ['all']

/financial_transactions:
get:
summary: financial transactions of the member's ordergroup
tags:
- 6. FinancialTransaction
parameters:
- $ref: '#/parameters/page'
- $ref: '#/parameters/per_page'
responses:
200:
description: success
schema:
type: object
properties:
financial_transactions:
type: array
items:
$ref: '#/definitions/FinancialTransaction'
meta:
$ref: '#/definitions/Meta'
403:
description: user has no ordergroup
schema:
$ref: '#/definitions/Error403'
security:
- foodsoft_auth: ['all']
/financial_transactions/{id}:
parameters:
- $ref: '#/parameters/idInUrl'
get:
summary: find financial transaction by id
tags:
- 6. FinancialTransaction
responses:
200:
description: success
schema:
type: object
properties:
financial_transaction:
$ref: '#/definitions/FinancialTransaction'
403:
description: user has no ordergroup
schema:
$ref: '#/definitions/Error403'
404:
description: not found
schema:
$ref: '#/definitions/Error404'
security:
- foodsoft_auth: ['all']

/config:
get:
summary: configuration variables
Expand Down Expand Up @@ -88,6 +141,31 @@ paths:
security:
- foodsoft_auth: ['all']

parameters:
# url parameters
idInUrl:
name: id
type: integer
in: path
minimum: 1
required: true

# query parameters
page:
name: page
type: integer
in: query
description: page number
minimum: 0
default: 0
per_page:
name: per_page
type: integer
in: query
description: items per page
minimum: 0
default: 20

definitions:
# models
User:
Expand All @@ -106,6 +184,47 @@ definitions:
description: language code
required: ['id', 'name', 'email']

FinancialTransaction:
type: object
properties:
id:
type: integer
user_id:
type: ['integer', 'null']
description: id of user who entered the transaction (may be <tt>null</tt> for deleted users or 0 for a system user)
user_name:
type: ['string', 'null']
description: name of user who entered the transaction (may be <tt>null</tt> or empty string for deleted users or system users)
amount:
type: number
description: amount credited (negative for a debit transaction)
note:
type: string
description: note entered with the transaction
created_on:
type: string
format: date-time
description: when the transaction was entered
required: ['id', 'user_id', 'user_name', 'amount', 'note', 'created_at']

# collection meta object in root of a response
Meta:
type: object
properties:
page:
type: integer
description: page number of the returned collection
per_page:
type: integer
description: number of items per page
total_pages:
type: integer
description: total number of pages
total_count:
type: integer
description: total number of items in the collection
required: ['page', 'per_page', 'total_pages', 'total_count']

Error:
type: object
properties:
Expand Down
22 changes: 22 additions & 0 deletions spec/api/v1/swagger_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,28 @@ def fetch_swagger!
end
end

context 'financial_transactions' do
let(:other_user) { create :user, :ordergroup }
let!(:other_ft_1) { create :financial_transaction, ordergroup: other_user.ordergroup }

context 'without ordergroup' do
it { is_expected.to validate(:get, '/financial_transactions', 403, auth) }
it { is_expected.to validate(:get, '/financial_transactions/{id}', 403, auth({'id' => other_ft_1.id})) }
end

context 'in ordergroup' do
let(:user) { create :user, :ordergroup }
let!(:ft_1) { create :financial_transaction, ordergroup: user.ordergroup }
let!(:ft_2) { create :financial_transaction, ordergroup: user.ordergroup }
let!(:ft_3) { create :financial_transaction, ordergroup: user.ordergroup }

it { is_expected.to validate(:get, '/financial_transactions', 200, auth) }
it { is_expected.to validate(:get, '/financial_transactions/{id}', 200, auth({'id' => ft_2.id})) }
it { is_expected.to validate(:get, '/financial_transactions/{id}', 404, auth({'id' => other_ft_1.id})) }
it { is_expected.to validate(:get, '/financial_transactions/{id}', 404, auth({'id' => FinancialTransaction.last.id + 1})) }
end
end

context 'config' do
it { is_expected.to validate(:get, '/config', 200, auth) }
it { is_expected.to validate(:get, '/config', 401) }
Expand Down
15 changes: 15 additions & 0 deletions spec/factories/financial_transaction.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
require 'factory_bot'

FactoryBot.define do
factory :financial_transaction do
user
ordergroup
amount { rand(-99_999.00..99_999.00) }
note { Faker::Lorem.sentence }

# This builds a new type and class by default, while for normal financial
# transactions we'd use the default. This, however, is the easiest way to
# get the factory going. If you want equal types, specify it explicitly.
financial_transaction_type
end
end

0 comments on commit 406ade0

Please sign in to comment.