99 lines
3.5 KiB
Ruby
99 lines
3.5 KiB
Ruby
# encoding: UTF-8
|
|
# frozen_string_literal: true
|
|
|
|
module API
|
|
module V2
|
|
module Management
|
|
class Transfers < Grape::API
|
|
# TODO: Add endpoints for listing Transfer/Transfers.
|
|
|
|
desc 'Creates new transfer.' do
|
|
@settings[:scope] = :write_transfers
|
|
end
|
|
params do
|
|
requires :key,
|
|
type: String,
|
|
desc: 'Unique Transfer Key.'
|
|
requires :category,
|
|
type: String,
|
|
desc: 'Transfer Category.'
|
|
optional :description,
|
|
type: String,
|
|
desc: 'Transfer Description.'
|
|
|
|
requires(:operations, type: Array, allow_blank: false) do
|
|
requires :currency,
|
|
type: String,
|
|
values: -> { Currency.codes(bothcase: true) },
|
|
desc: 'Operation currency.'
|
|
requires :amount,
|
|
type: BigDecimal,
|
|
values: ->(v) { v.to_d.positive? },
|
|
desc: 'Operation amount.'
|
|
|
|
requires :account_src, type: Hash do
|
|
requires :code,
|
|
type: Integer,
|
|
values: -> { ::Operations::Account.pluck(:code) },
|
|
desc: 'Source Account code.'
|
|
given code: ->(code) { ::Operations::Account.find_by(code: code).try(:scope).try(:member?) } do
|
|
requires :uid,
|
|
type: String,
|
|
desc: 'Source Account User ID (for accounts with member scope).'
|
|
end
|
|
end
|
|
|
|
requires :account_dst, type: Hash do
|
|
requires :code,
|
|
type: Integer,
|
|
values: -> { ::Operations::Account.pluck(:code) },
|
|
desc: 'Destination Account code.'
|
|
given code: ->(code) { ::Operations::Account.find_by(code: code).try(:scope).try(:member?) } do
|
|
requires :uid,
|
|
type: String,
|
|
desc: 'Destination Account User ID (for accounts with member scope).'
|
|
end
|
|
end
|
|
end
|
|
end
|
|
post '/transfers/new' do
|
|
declared_params = declared(params)
|
|
|
|
attrs = declared_params.slice(:key, :category, :description)
|
|
|
|
declared_params[:operations].each do |op_pair|
|
|
currency = Currency.find(op_pair[:currency])
|
|
|
|
debit_op = op_pair[:account_src].merge(debit: op_pair[:amount], credit: 0.0, currency: currency)
|
|
credit_op = op_pair[:account_dst].merge(credit: op_pair[:amount], debit: 0.0, currency: currency)
|
|
|
|
[debit_op, credit_op].each do |op|
|
|
klass = ::Operations.klass_for(code: op['code'])
|
|
|
|
uid = op.delete(:uid)
|
|
op.merge!(member: Member.find_by!(uid: uid)) if uid.present?
|
|
|
|
type = ::Operations::Account.find_by(code: op[:code]).type
|
|
type_plural = type.pluralize
|
|
if attrs[type_plural].present?
|
|
attrs[type_plural].push(klass.new(op))
|
|
else
|
|
attrs[type_plural] = [klass.new(op)]
|
|
end
|
|
end
|
|
end
|
|
|
|
present Transfer.create!(attrs), with: Entities::Transfer
|
|
status 201
|
|
rescue ActiveRecord::RecordInvalid => e
|
|
body errors: e.message
|
|
status 422
|
|
rescue ::Account::AccountError => e
|
|
body errors: "Account balance is insufficient (#{e.message})"
|
|
status 422
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|