mirror of
https://github.com/we-promise/sure.git
synced 2026-06-07 19:59:00 +00:00
Add exchange rate feature with multi-currency transactions and transfers support (#1099)
Co-authored-by: Pedro J. Aramburu <pedro@joakin.dev>
This commit is contained in:
committed by
GitHub
parent
8e81e967fc
commit
f699660479
@@ -25,6 +25,143 @@ class TransfersControllerTest < ActionDispatch::IntegrationTest
|
||||
end
|
||||
end
|
||||
|
||||
test "can create transfer with custom exchange rate" do
|
||||
usd_account = accounts(:depository)
|
||||
eur_account = users(:family_admin).family.accounts.create!(
|
||||
name: "EUR Account",
|
||||
balance: 1000,
|
||||
currency: "EUR",
|
||||
accountable: Depository.new
|
||||
)
|
||||
|
||||
assert_equal "USD", usd_account.currency
|
||||
assert_equal "EUR", eur_account.currency
|
||||
|
||||
assert_difference "Transfer.count", 1 do
|
||||
post transfers_url, params: {
|
||||
transfer: {
|
||||
from_account_id: usd_account.id,
|
||||
to_account_id: eur_account.id,
|
||||
date: Date.current,
|
||||
amount: 100,
|
||||
exchange_rate: 0.92
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
transfer = Transfer.where(
|
||||
"outflow_transaction_id IN (?) AND inflow_transaction_id IN (?)",
|
||||
usd_account.transactions.pluck(:id),
|
||||
eur_account.transactions.pluck(:id)
|
||||
).last
|
||||
assert_not_nil transfer
|
||||
assert_equal "USD", transfer.outflow_transaction.entry.currency
|
||||
assert_equal "EUR", transfer.inflow_transaction.entry.currency
|
||||
assert_equal 100, transfer.outflow_transaction.entry.amount
|
||||
assert_in_delta(-92, transfer.inflow_transaction.entry.amount, 0.01)
|
||||
end
|
||||
|
||||
test "exchange_rate endpoint returns 400 when from currency is missing" do
|
||||
get exchange_rate_url, params: {
|
||||
to: "USD"
|
||||
}
|
||||
|
||||
assert_response :bad_request
|
||||
json_response = JSON.parse(response.body)
|
||||
assert_equal "from and to currencies are required", json_response["error"]
|
||||
end
|
||||
|
||||
test "exchange_rate endpoint returns 400 when to currency is missing" do
|
||||
get exchange_rate_url, params: {
|
||||
from: "EUR"
|
||||
}
|
||||
|
||||
assert_response :bad_request
|
||||
json_response = JSON.parse(response.body)
|
||||
assert_equal "from and to currencies are required", json_response["error"]
|
||||
end
|
||||
|
||||
test "exchange_rate endpoint returns 400 on invalid date format" do
|
||||
get exchange_rate_url, params: {
|
||||
from: "EUR",
|
||||
to: "USD",
|
||||
date: "not-a-date"
|
||||
}
|
||||
|
||||
assert_response :bad_request
|
||||
json_response = JSON.parse(response.body)
|
||||
assert_equal "Invalid date format", json_response["error"]
|
||||
end
|
||||
|
||||
test "exchange_rate endpoint returns rate for different currencies" do
|
||||
ExchangeRate.expects(:find_or_fetch_rate)
|
||||
.with(from: "USD", to: "EUR", date: Date.current)
|
||||
.returns(OpenStruct.new(rate: 0.92))
|
||||
|
||||
get exchange_rate_url, params: {
|
||||
from: "USD",
|
||||
to: "EUR",
|
||||
date: Date.current.to_s
|
||||
}
|
||||
|
||||
assert_response :success
|
||||
json_response = JSON.parse(response.body)
|
||||
assert_equal 0.92, json_response["rate"]
|
||||
end
|
||||
|
||||
test "exchange_rate endpoint returns error when exchange rate unavailable" do
|
||||
ExchangeRate.expects(:find_or_fetch_rate)
|
||||
.with(from: "USD", to: "EUR", date: Date.current)
|
||||
.returns(nil)
|
||||
|
||||
get exchange_rate_url, params: {
|
||||
from: "USD",
|
||||
to: "EUR",
|
||||
date: Date.current.to_s
|
||||
}
|
||||
|
||||
assert_response :not_found
|
||||
json_response = JSON.parse(response.body)
|
||||
assert_equal "Exchange rate not found", json_response["error"]
|
||||
end
|
||||
|
||||
test "cannot create transfer when exchange rate unavailable and no custom rate provided" do
|
||||
usd_account = accounts(:depository)
|
||||
eur_account = users(:family_admin).family.accounts.create!(
|
||||
name: "EUR Account",
|
||||
balance: 1000,
|
||||
currency: "EUR",
|
||||
accountable: Depository.new
|
||||
)
|
||||
|
||||
ExchangeRate.stubs(:find_or_fetch_rate).returns(nil)
|
||||
|
||||
assert_no_difference "Transfer.count" do
|
||||
post transfers_url, params: {
|
||||
transfer: {
|
||||
from_account_id: usd_account.id,
|
||||
to_account_id: eur_account.id,
|
||||
date: Date.current,
|
||||
amount: 100
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
assert_response :unprocessable_entity
|
||||
end
|
||||
|
||||
test "exchange_rate endpoint returns same_currency for matching currencies" do
|
||||
get exchange_rate_url, params: {
|
||||
from: "USD",
|
||||
to: "USD"
|
||||
}
|
||||
|
||||
assert_response :success
|
||||
json_response = JSON.parse(response.body)
|
||||
assert_equal true, json_response["same_currency"]
|
||||
assert_equal 1.0, json_response["rate"]
|
||||
end
|
||||
|
||||
test "soft deletes transfer" do
|
||||
assert_difference -> { Transfer.count }, -1 do
|
||||
delete transfer_url(transfers(:one))
|
||||
|
||||
Reference in New Issue
Block a user