Merge pull request #1715 from GuillaumeKergreis/SelectAccountIdPaymentResponse

Payment return the transactionId associated to the bank account
This commit is contained in:
Simon Redfern 2020-09-21 14:46:34 +02:00 committed by GitHub
commit 59daf4d144
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 79 additions and 32 deletions

View File

@ -91,7 +91,7 @@ import scala.concurrent._
import scala.concurrent.duration._
import scala.language.postfixOps
import scala.math.{BigDecimal, BigInt}
import scala.util.Random
import scala.util.{Random, Try}
object LocalMappedConnector extends Connector with MdcLoggable {
@ -1183,16 +1183,16 @@ object LocalMappedConnector extends Connector with MdcLoggable {
.fallbackTo(NewStyle.function.getBank(toAccount.bankId, callContext))
debitRate <- Future (fx.exchangeRate(currency, fromAccount.currency, Some(bankIdExchangeRate.bankId.value)))
_ <- Helper.booleanToFuture(s"$InvalidCurrency The requested currency conversion (${currency} to ${fromAccount.currency}) is not supported."){debitRate.isDefined}
_ <- Helper.booleanToFuture(s"$InvalidCurrency The requested currency conversion ($currency to ${fromAccount.currency}) is not supported."){debitRate.isDefined}
creditRate <- Future (fx.exchangeRate(currency, toAccount.currency, Some(bankIdExchangeRate.bankId.value)))
_ <- Helper.booleanToFuture(s"$InvalidCurrency The requested currency conversion (${currency} to ${toAccount.currency}) is not supported."){creditRate.isDefined}
_ <- Helper.booleanToFuture(s"$InvalidCurrency The requested currency conversion ($currency to ${toAccount.currency}) is not supported."){creditRate.isDefined}
fromTransAmt = -fx.convert(amount, debitRate) //from fromAccount balance should decrease
toTransAmt = fx.convert(amount, creditRate)
debitTransactionBox <- Future(
saveHistoricalTransaction(fromAccount, toAccount, posted, completed, fromTransAmt, description, transactionRequestType, chargePolicy, callContext)
.map(debitTransactionId => (fromAccount.bankId, fromAccount.accountId, debitTransactionId))
.map(debitTransactionId => (fromAccount.bankId, fromAccount.accountId, debitTransactionId, false))
.or {
// If we don't find any corresponding obp account, we debit a bank settlement account
val settlementAccount = {
@ -1203,15 +1203,22 @@ object LocalMappedConnector extends Connector with MdcLoggable {
// If no specific settlement account exist for this currency, we use the default incoming account (EUR)
.or(BankAccountX(toAccount.bankId, AccountId(INCOMING_ACCOUNT_ID), callContext))
}
settlementAccount.flatMap(settlementAccount =>
saveHistoricalTransaction(settlementAccount._1, toAccount, posted, completed, fromTransAmt, description, transactionRequestType, chargePolicy, callContext)
.map(debitTransactionId => (settlementAccount._1.bankId, settlementAccount._1.accountId, debitTransactionId))
)
settlementAccount.flatMap(settlementAccount => {
val fromTransAmtSettlementAccount: BigDecimal = {
// In the case we selected the default settlement account INCOMING_ACCOUNT_ID account and that the counterparty currency is different from EUR, we need to calculate the amount in EUR
if (settlementAccount._1.accountId.value == INCOMING_ACCOUNT_ID && settlementAccount._1.currency != fromAccount.currency) {
val rate = fx.exchangeRate(currency, settlementAccount._1.currency, Some(bankIdExchangeRate.bankId.value))
Try(-fx.convert(amount, rate)).getOrElse(throw new Exception(s"$InvalidCurrency The requested currency conversion ($currency to ${settlementAccount._1.currency}) is not supported."))
} else fromTransAmt
}
saveHistoricalTransaction(settlementAccount._1, toAccount, posted, completed, fromTransAmtSettlementAccount, description, transactionRequestType, chargePolicy, callContext)
.map(debitTransactionId => (settlementAccount._1.bankId, settlementAccount._1.accountId, debitTransactionId, true))
})
}
)
creditTransactionBox <- Future(
saveHistoricalTransaction(toAccount, fromAccount, posted, completed, toTransAmt, description, transactionRequestType, chargePolicy, callContext)
.map(creditTransactionId => (toAccount.bankId, toAccount.accountId, creditTransactionId))
.map(creditTransactionId => (toAccount.bankId, toAccount.accountId, creditTransactionId, false))
.or {
// If we don't find any corresponding obp account, we credit a bank settlement account
val settlementAccount =
@ -1221,15 +1228,22 @@ object LocalMappedConnector extends Connector with MdcLoggable {
.or(BankAccountX(fromAccount.bankId, AccountId("DEFAULT_SETTLEMENT_ACCOUNT_" + toAccount.currency), callContext))
// If no specific settlement account exist for this currency, we use the default outgoing account (EUR)
.or(BankAccountX(fromAccount.bankId, AccountId(OUTGOING_ACCOUNT_ID), callContext))
settlementAccount.flatMap(settlementAccount =>
saveHistoricalTransaction(settlementAccount._1, fromAccount, posted, completed, toTransAmt, description, transactionRequestType, chargePolicy, callContext)
.map(creditTransactionId => (settlementAccount._1.bankId, settlementAccount._1.accountId, creditTransactionId))
)
settlementAccount.flatMap(settlementAccount => {
val toTransAmtSettlementAccount: BigDecimal = {
// In the case we selected the default settlement account OUTGOING_ACCOUNT_ID account and that the counterparty currency is different from EUR, we need to calculate the amount in EUR
if (settlementAccount._1.accountId.value == OUTGOING_ACCOUNT_ID && settlementAccount._1.currency != toAccount.currency) {
val rate = fx.exchangeRate(currency, settlementAccount._1.currency, Some(bankIdExchangeRate.bankId.value))
Try(fx.convert(amount, rate)).getOrElse(throw new Exception(s"$InvalidCurrency The requested currency conversion ($currency to ${settlementAccount._1.currency}) is not supported."))
} else toTransAmt
}
saveHistoricalTransaction(settlementAccount._1, fromAccount, posted, completed, toTransAmtSettlementAccount, description, transactionRequestType, chargePolicy, callContext)
.map(creditTransactionId => (settlementAccount._1.bankId, settlementAccount._1.accountId, creditTransactionId, true))
})
}
)
debitTransaction = debitTransactionBox.openOrThrowException("Error while opening debitTransaction")
creditTransaction = creditTransactionBox.openOrThrowException("Error while opening creditTransaction")
debitTransaction = debitTransactionBox.openOrThrowException(s"Error while opening debitTransaction. This error can happen when no settlement can be found, please check that $INCOMING_ACCOUNT_ID exists at bank ${toAccount.bankId.value}")
creditTransaction = creditTransactionBox.openOrThrowException(s"Error while opening creditTransaction. This error can happen when no settlement can be found, please check that $OUTGOING_ACCOUNT_ID exists at bank ${fromAccount.bankId.value}")
_ <- NewStyle.function.saveDoubleEntryBookTransaction(
DoubleEntryTransaction(
@ -1244,7 +1258,14 @@ object LocalMappedConnector extends Connector with MdcLoggable {
creditTransactionId = creditTransaction._3
), callContext)
} yield {
(debitTransactionBox.map(_._3), callContext)
val transactionId: Box[TransactionId] = (debitTransaction._4, creditTransaction._4) match {
// If the debit transaction is on a settlement account and the credit transaction is on an OBP account, we return the credit transaction id
case (true, false) => creditTransactionBox.map(_._3)
// In all the other cases, we return the debit transaction id
case _ => debitTransactionBox.map(_._3)
}
(transactionId, callContext)
// In the future, we should return the both transactions as the API response
}
}
@ -1319,16 +1340,16 @@ object LocalMappedConnector extends Connector with MdcLoggable {
transactionCurrency = transactionRequestCommonBody.value.currency
debitRate <- Future (fx.exchangeRate(transactionCurrency, fromAccount.currency, Some(bankIdExchangeRate.bankId.value)))
_ <- Helper.booleanToFuture(s"$InvalidCurrency The requested currency conversion (${transactionCurrency} to ${fromAccount.currency}) is not supported."){debitRate.isDefined}
_ <- Helper.booleanToFuture(s"$InvalidCurrency The requested currency conversion ($transactionCurrency to ${fromAccount.currency}) is not supported."){debitRate.isDefined}
creditRate <- Future (fx.exchangeRate(transactionCurrency, toAccount.currency, Some(bankIdExchangeRate.bankId.value)))
_ <- Helper.booleanToFuture(s"$InvalidCurrency The requested currency conversion (${transactionCurrency} to ${toAccount.currency}) is not supported."){creditRate.isDefined}
_ <- Helper.booleanToFuture(s"$InvalidCurrency The requested currency conversion ($transactionCurrency to ${toAccount.currency}) is not supported."){creditRate.isDefined}
fromTransAmt = -fx.convert(amount, debitRate) //from fromAccount balance should decrease
toTransAmt = fx.convert(amount, creditRate)
debitTransactionBox <- Future {
saveTransaction(fromAccount, toAccount, transactionRequestCommonBody, fromTransAmt, description, transactionRequestType, chargePolicy)
.map(debitTransactionId => (fromAccount.bankId, fromAccount.accountId, debitTransactionId))
.map(debitTransactionId => (fromAccount.bankId, fromAccount.accountId, debitTransactionId, false))
.or {
// If we don't find any corresponding obp account, we debit a bank settlement account
val settlementAccount =
@ -1338,15 +1359,22 @@ object LocalMappedConnector extends Connector with MdcLoggable {
.or(BankAccountX(toAccount.bankId, AccountId("DEFAULT_SETTLEMENT_ACCOUNT_" + fromAccount.currency), callContext))
// If no specific settlement account exist for this currency, we use the default incoming account (EUR)
.or(BankAccountX(toAccount.bankId, AccountId(INCOMING_ACCOUNT_ID), callContext))
settlementAccount.flatMap(settlementAccount =>
saveTransaction(settlementAccount._1, toAccount, transactionRequestCommonBody, fromTransAmt, description, transactionRequestType, chargePolicy)
.map(debitTransactionId => (settlementAccount._1.bankId, settlementAccount._1.accountId, debitTransactionId))
)
settlementAccount.flatMap(settlementAccount => {
val fromTransAmtSettlementAccount = {
// In the case we selected the default settlement account INCOMING_ACCOUNT_ID account and that the counterparty currency is different from EUR, we need to calculate the amount in EUR
if (settlementAccount._1.accountId.value == INCOMING_ACCOUNT_ID && settlementAccount._1.currency != fromAccount.currency) {
val rate = fx.exchangeRate(transactionCurrency, settlementAccount._1.currency, Some(bankIdExchangeRate.bankId.value))
Try(-fx.convert(amount, rate)).getOrElse(throw new Exception(s"$InvalidCurrency The requested currency conversion ($transactionCurrency to ${settlementAccount._1.currency}) is not supported."))
} else fromTransAmt
}
saveTransaction(settlementAccount._1, toAccount, transactionRequestCommonBody, fromTransAmtSettlementAccount, description, transactionRequestType, chargePolicy)
.map(debitTransactionId => (settlementAccount._1.bankId, settlementAccount._1.accountId, debitTransactionId, true))
})
}
}
creditTransactionBox <- Future {
saveTransaction(toAccount, fromAccount, transactionRequestCommonBody, toTransAmt, description, transactionRequestType, chargePolicy)
.map(creditTransactionId => (toAccount.bankId, toAccount.accountId, creditTransactionId))
.map(creditTransactionId => (toAccount.bankId, toAccount.accountId, creditTransactionId, false))
.or {
// If we don't find any corresponding obp account, we credit a bank settlement account
val settlementAccount =
@ -1356,15 +1384,22 @@ object LocalMappedConnector extends Connector with MdcLoggable {
.or(BankAccountX(fromAccount.bankId, AccountId("DEFAULT_SETTLEMENT_ACCOUNT_" + toAccount.currency), callContext))
// If no specific settlement account exist for this currency, we use the default outgoing account (EUR)
.or(BankAccountX(fromAccount.bankId, AccountId(OUTGOING_ACCOUNT_ID), callContext))
settlementAccount.flatMap(settlementAccount =>
saveTransaction(settlementAccount._1, fromAccount, transactionRequestCommonBody, toTransAmt, description, transactionRequestType, chargePolicy)
.map(creditTransactionId => (settlementAccount._1.bankId, settlementAccount._1.accountId, creditTransactionId))
)
settlementAccount.flatMap(settlementAccount => {
val toTransAmtSettlementAccount = {
// In the case we selected the default settlement account OUTGOING_ACCOUNT_ID account and that the counterparty currency is different from EUR, we need to calculate the amount in EUR
if (settlementAccount._1.accountId.value == OUTGOING_ACCOUNT_ID && settlementAccount._1.currency != toAccount.currency) {
val rate = fx.exchangeRate(transactionCurrency, settlementAccount._1.currency, Some(bankIdExchangeRate.bankId.value))
Try(fx.convert(amount, rate)).getOrElse(throw new Exception(s"$InvalidCurrency The requested currency conversion ($transactionCurrency to ${settlementAccount._1.currency}) is not supported."))
} else toTransAmt
}
saveTransaction(settlementAccount._1, fromAccount, transactionRequestCommonBody, toTransAmtSettlementAccount, description, transactionRequestType, chargePolicy)
.map(creditTransactionId => (settlementAccount._1.bankId, settlementAccount._1.accountId, creditTransactionId, true))
})
}
}
debitTransaction = debitTransactionBox.openOrThrowException("Error while opening debitTransaction")
creditTransaction = creditTransactionBox.openOrThrowException("Error while opening creditTransaction")
debitTransaction = debitTransactionBox.openOrThrowException(s"Error while opening debitTransaction. This error can happen when no settlement can be found, please check that $INCOMING_ACCOUNT_ID exists at bank ${toAccount.bankId.value}")
creditTransaction = creditTransactionBox.openOrThrowException(s"Error while opening creditTransaction. This error can happen when no settlement can be found, please check that $OUTGOING_ACCOUNT_ID exists at bank ${fromAccount.bankId.value}")
_ <- NewStyle.function.saveDoubleEntryBookTransaction(
DoubleEntryTransaction(
@ -1378,7 +1413,16 @@ object LocalMappedConnector extends Connector with MdcLoggable {
creditTransactionAccountId = creditTransaction._2,
creditTransactionId = creditTransaction._3
), callContext)
} yield (debitTransactionBox.map(_._3), callContext)
} yield {
val transactionId: Box[TransactionId] = (debitTransaction._4, creditTransaction._4) match {
// If the debit transaction is on a settlement account and the credit transaction is on an OBP account, we return the credit transaction id
case (true, false) => creditTransactionBox.map(_._3)
// In all the other cases, we return the debit transaction id
case _ => debitTransactionBox.map(_._3)
}
(transactionId, callContext)
// In the future, we should return the both transactions as the API response
}
/**
* Saves a transaction with @amount, @toAccount and @transactionRequestType for @fromAccount and @toCounterparty. <br>

View File

@ -563,9 +563,12 @@ object BankAccountX {
if (counterparty.otherAccountSecondaryRoutingScheme.isEmpty) Nil
else List(AccountRouting(counterparty.otherAccountSecondaryRoutingScheme, counterparty.otherAccountSecondaryRoutingAddress))
// Due to the new field in the database, old counterparty have void currency, so by default, we set it to EUR
val counterpartyCurrency = if (counterparty.currency.nonEmpty) counterparty.currency else "EUR"
Full(BankAccountCommons(
AccountId(""), "", 0,
currency = counterparty.currency
currency = counterpartyCurrency
, "", "", "", BankId(""), new Date(), "",
accountRoutings = accountRouting1 ++ accountRouting2,
List.empty, accountHolder = counterparty.name,