refactor/moved makePaymentImpl to LocalMappedConnectorInternal

This commit is contained in:
hongwei 2024-10-22 18:40:40 +02:00
parent cb9d9cc936
commit e71169ffce
5 changed files with 88 additions and 105 deletions

View File

@ -716,7 +716,6 @@ trait Connector extends MdcLoggable {
callContext: Option[CallContext]
): OBPReturnType[Box[PhysicalCardTrait]] = Future{(Failure{setUnimplementedError(nameOf(updatePhysicalCard _))}, callContext)}
//Payments api: just return Failure("not supported") from makePaymentImpl if you don't want to implement it
/**
* \
*
@ -767,10 +766,7 @@ trait Connector extends MdcLoggable {
def getBalancingTransaction(transactionId: TransactionId,
callContext: Option[CallContext]): OBPReturnType[Box[DoubleEntryTransaction]]= Future{(Failure(setUnimplementedError(nameOf(getBalancingTransaction _))), callContext)}
protected def makePaymentImpl(fromAccount: BankAccount, toAccount: BankAccount, transactionRequestCommonBody: TransactionRequestCommonBodyJSON, amt: BigDecimal, description: String, transactionRequestType: TransactionRequestType, chargePolicy: String): Box[TransactionId]= Failure(setUnimplementedError(nameOf(makePaymentImpl _)))
/*
Transaction Requests
*/

View File

@ -415,9 +415,7 @@ object ConnectorBuilderUtil {
* modifier is protected methods, not recommend generate these methods, they should always for special purpose
*/
val protectedMethods = List(
"makePaymentImpl",
"saveTransactionRequestStatusImpl",
"getTransactionRequestStatusesImpl",
).distinct
val omitMethods = List(

View File

@ -1689,31 +1689,6 @@ object LocalMappedConnector extends Connector with MdcLoggable {
transactionRequestAttributeId: String
).map((_, callContext))
}
/**
* Perform a payment (in the sandbox) Store one or more transactions
*/
override def makePaymentImpl(fromAccount: BankAccount,
toAccount: BankAccount,
transactionRequestCommonBody: TransactionRequestCommonBodyJSON,
amount: BigDecimal,
description: String,
transactionRequestType: TransactionRequestType,
chargePolicy: String): Box[TransactionId] = {
for {
//def exchangeRate --> do not return any exception, but it may return NONO there.
rate <- Full (fx.exchangeRate(fromAccount.currency, toAccount.currency, Some(fromAccount.bankId.value)))
_ <- booleanToBox(rate.isDefined) ?~! s"$InvalidCurrency The requested currency conversion (${fromAccount.currency} to ${fromAccount.currency}) is not supported."
fromTransAmt = -amount //from fromAccount balance should decrease
toTransAmt = fx.convert(amount, rate)
sentTransactionId <- saveTransaction(fromAccount, toAccount, transactionRequestCommonBody, fromTransAmt, description, transactionRequestType, chargePolicy)
_sentTransactionId <- saveTransaction(toAccount, fromAccount, transactionRequestCommonBody, toTransAmt, description, transactionRequestType, chargePolicy)
} yield {
sentTransactionId
}
}
override def makePaymentv210(fromAccount: BankAccount,
toAccount: BankAccount,
transactionRequestId: TransactionRequestId,
@ -1990,7 +1965,7 @@ object LocalMappedConnector extends Connector with MdcLoggable {
toTransAmt = fx.convert(amount, creditRate)
debitTransactionBox <- Future {
saveTransaction(fromAccount, toAccount, transactionRequestCommonBody, fromTransAmt, description, transactionRequestType, chargePolicy)
LocalMappedConnectorInternal.saveTransaction(fromAccount, toAccount, transactionRequestCommonBody, fromTransAmt, description, transactionRequestType, chargePolicy)
.map(debitTransactionId => (fromAccount.bankId, fromAccount.accountId, debitTransactionId, false))
.or {
// If we don't find any corresponding obp account, we debit a bank settlement account
@ -2009,13 +1984,13 @@ object LocalMappedConnector extends Connector with MdcLoggable {
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)
LocalMappedConnectorInternal.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)
LocalMappedConnectorInternal.saveTransaction(toAccount, fromAccount, transactionRequestCommonBody, toTransAmt, description, transactionRequestType, chargePolicy)
.map(creditTransactionId => (toAccount.bankId, toAccount.accountId, creditTransactionId, false))
.or {
// If we don't find any corresponding obp account, we credit a bank settlement account
@ -2034,7 +2009,7 @@ object LocalMappedConnector extends Connector with MdcLoggable {
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)
LocalMappedConnectorInternal.saveTransaction(settlementAccount._1, fromAccount, transactionRequestCommonBody, toTransAmtSettlementAccount, description, transactionRequestType, chargePolicy)
.map(creditTransactionId => (settlementAccount._1.bankId, settlementAccount._1.accountId, creditTransactionId, true))
})
}
@ -2066,56 +2041,7 @@ object LocalMappedConnector extends Connector with MdcLoggable {
// 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>
* Returns the id of the saved transactionId.<br>
*/
private def saveTransaction(fromAccount: BankAccount,
toAccount: BankAccount,
transactionRequestCommonBody: TransactionRequestCommonBodyJSON,
amount: BigDecimal,
description: String,
transactionRequestType: TransactionRequestType,
chargePolicy: String): Box[TransactionId] = {
for {
currency <- Full(fromAccount.currency)
//update the balance of the fromAccount for which a transaction is being created
newAccountBalance <- Full(Helper.convertToSmallestCurrencyUnits(fromAccount.balance, currency) + Helper.convertToSmallestCurrencyUnits(amount, currency))
//Here is the `LocalMappedConnector`, once get this point, fromAccount must be a mappedBankAccount. So can use asInstanceOf....
_ <- tryo(fromAccount.asInstanceOf[MappedBankAccount].accountBalance(newAccountBalance).save) ?~! UpdateBankAccountException
mappedTransaction <- tryo(MappedTransaction.create
//No matter which type (SANDBOX_TAN,SEPA,FREE_FORM,COUNTERPARTYE), always filled the following nine fields.
.bank(fromAccount.bankId.value)
.account(fromAccount.accountId.value)
.transactionType(transactionRequestType.value)
.amount(Helper.convertToSmallestCurrencyUnits(amount, currency))
.newAccountBalance(newAccountBalance)
.currency(currency)
.tStartDate(now)
.tFinishDate(now)
.description(description)
//Old data: other BankAccount(toAccount: BankAccount)simulate counterparty
.counterpartyAccountHolder(toAccount.accountHolder)
.counterpartyAccountNumber(toAccount.number)
.counterpartyAccountKind(toAccount.accountType)
.counterpartyBankName(toAccount.bankName)
.counterpartyIban(toAccount.accountRoutings.find(_.scheme == AccountRoutingScheme.IBAN.toString).map(_.address).getOrElse(""))
.counterpartyNationalId(toAccount.nationalIdentifier)
//New data: real counterparty (toCounterparty: CounterpartyTrait)
// .CPCounterPartyId(toAccount.accountId.value)
.CPOtherAccountRoutingScheme(toAccount.accountRoutings.headOption.map(_.scheme).getOrElse(""))
.CPOtherAccountRoutingAddress(toAccount.accountRoutings.headOption.map(_.address).getOrElse(""))
.CPOtherBankRoutingScheme(toAccount.bankRoutingScheme)
.CPOtherBankRoutingAddress(toAccount.bankRoutingAddress)
.chargePolicy(chargePolicy)
.saveMe) ?~! s"$CreateTransactionsException, exception happened when create new mappedTransaction"
} yield {
mappedTransaction.theTransactionId
}
}
override def cancelPaymentV400(transactionId: TransactionId,
callContext: Option[CallContext]): OBPReturnType[Box[CancelPayment]] = Future {
@ -4296,7 +4222,7 @@ object LocalMappedConnector extends Connector with MdcLoggable {
// Note for 'new MappedCounterparty()' in the following :
// We update the makePaymentImpl in V210, added the new parameter 'toCounterparty: CounterpartyTrait' for V210
// But in V200 or before, we do not used the new parameter toCounterparty. So just keep it empty.
transactionId <- makePaymentImpl(fromAccount,
transactionId <- LocalMappedConnectorInternal.makePaymentImpl(fromAccount,
toAccount,
transactionRequestCommonBody = null, //Note transactionRequestCommonBody started to use in V210
amt,
@ -4323,7 +4249,7 @@ object LocalMappedConnector extends Connector with MdcLoggable {
transactionRequestType: TransactionRequestType,
chargePolicy: String): Box[TransactionId] = {
for {
transactionId <- makePaymentImpl(fromAccount, toAccount, transactionRequestCommonBody, amount, description, transactionRequestType, chargePolicy) ?~! InvalidConnectorResponseForMakePayment
transactionId <- LocalMappedConnectorInternal.makePaymentImpl(fromAccount, toAccount, transactionRequestCommonBody, amount, description, transactionRequestType, chargePolicy) ?~! InvalidConnectorResponseForMakePayment
} yield transactionId
}
@ -4484,10 +4410,10 @@ object LocalMappedConnector extends Connector with MdcLoggable {
Future(Full(
if (transactionRequestCommonBodyAmount < challengeThresholdAmount && transactionRequestType.value != REFUND.toString) {
// For any connector != mapped we should probably assume that transaction_request_status_scheduler_delay will be > 0
// so that getTransactionRequestStatusesImpl needs to be implemented for all connectors except mapped.
// so that getTransactionRequestStatuses needs to be implemented for all connectors except mapped.
// i.e. if we are certain that saveTransaction will be honored immediately by the backend, then transaction_request_status_scheduler_delay
// can be empty in the props file. Otherwise, the status will be set to STATUS_PENDING
// and getTransactionRequestStatusesImpl needs to be run periodically to update the transaction request status.
// and getTransactionRequestStatuses needs to be run periodically to update the transaction request status.
if (APIUtil.getPropsAsLongValue("transaction_request_status_scheduler_delay").isEmpty)
TransactionRequestStatus.COMPLETED
else

View File

@ -7,8 +7,10 @@ import code.api.util.APIUtil._
import code.api.util.ErrorMessages._
import code.api.util._
import code.branches.MappedBranch
import code.fx.fx
import code.management.ImporterAPI.ImporterTransaction
import code.model.dataAccess.{BankAccountRouting, MappedBank, MappedBankAccount}
import code.model.toBankAccountExtended
import code.transaction.MappedTransaction
import code.transactionrequests._
import com.tesobe.CacheKeyFromArguments
@ -16,15 +18,12 @@ import code.util.Helper
import code.util.Helper._
import com.openbankproject.commons.ExecutionContext.Implicits.global
import com.openbankproject.commons.model._
import com.openbankproject.commons.model.enums.TransactionRequestStatus
import com.openbankproject.commons.model.enums.TransactionRequestTypes
import com.openbankproject.commons.model.enums.PaymentServiceTypes
import com.openbankproject.commons.model.enums.{AccountRoutingScheme, PaymentServiceTypes, TransactionRequestStatus, TransactionRequestTypes}
import net.liftweb.common._
import net.liftweb.json.Serialization.write
import net.liftweb.json.{NoTypeHints, Serialization}
import net.liftweb.mapper.By
import net.liftweb.util.Helpers
import net.liftweb.util.Helpers.tryo
import net.liftweb.util.Helpers.{now, tryo}
import java.util.Date
import java.util.UUID.randomUUID
@ -386,7 +385,7 @@ object LocalMappedConnectorInternal extends MdcLoggable {
account <- Connector.connector.vend.getBankAccountLegacy(bankId, accountId, None).map(_._1).map(_.asInstanceOf[MappedBankAccount])
} yield {
account.accountBalance(Helper.convertToSmallestCurrencyUnits(newBalance, account.currency)).save
setBankAccountLastUpdated(bank.nationalIdentifier, account.number, Helpers.now).openOrThrowException(attemptedToOpenAnEmptyBox)
setBankAccountLastUpdated(bank.nationalIdentifier, account.number, now).openOrThrowException(attemptedToOpenAnEmptyBox)
}
Full(result.getOrElse(false))
@ -579,4 +578,78 @@ object LocalMappedConnectorInternal extends MdcLoggable {
}
}
}
def makePaymentImpl(fromAccount: BankAccount,
toAccount: BankAccount,
transactionRequestCommonBody: TransactionRequestCommonBodyJSON,
amount: BigDecimal,
description: String,
transactionRequestType: TransactionRequestType,
chargePolicy: String): Box[TransactionId] = {
for {
//def exchangeRate --> do not return any exception, but it may return NONO there.
rate <- Full (fx.exchangeRate(fromAccount.currency, toAccount.currency, Some(fromAccount.bankId.value)))
_ <- booleanToBox(rate.isDefined) ?~! s"$InvalidCurrency The requested currency conversion (${fromAccount.currency} to ${fromAccount.currency}) is not supported."
fromTransAmt = -amount //from fromAccount balance should decrease
toTransAmt = fx.convert(amount, rate)
sentTransactionId <- saveTransaction(fromAccount, toAccount, transactionRequestCommonBody, fromTransAmt, description, transactionRequestType, chargePolicy)
_sentTransactionId <- saveTransaction(toAccount, fromAccount, transactionRequestCommonBody, toTransAmt, description, transactionRequestType, chargePolicy)
} yield {
sentTransactionId
}
}
/**
* Saves a transaction with @amount, @toAccount and @transactionRequestType for @fromAccount and @toCounterparty. <br>
* Returns the id of the saved transactionId.<br>
*/
def saveTransaction(
fromAccount: BankAccount,
toAccount: BankAccount,
transactionRequestCommonBody: TransactionRequestCommonBodyJSON,
amount: BigDecimal,
description: String,
transactionRequestType: TransactionRequestType,
chargePolicy: String): Box[TransactionId] = {
for {
currency <- Full(fromAccount.currency)
//update the balance of the fromAccount for which a transaction is being created
newAccountBalance <- Full(Helper.convertToSmallestCurrencyUnits(fromAccount.balance, currency) + Helper.convertToSmallestCurrencyUnits(amount, currency))
//Here is the `LocalMappedConnector`, once get this point, fromAccount must be a mappedBankAccount. So can use asInstanceOf....
_ <- tryo(fromAccount.asInstanceOf[MappedBankAccount].accountBalance(newAccountBalance).save) ?~! UpdateBankAccountException
mappedTransaction <- tryo(MappedTransaction.create
//No matter which type (SANDBOX_TAN,SEPA,FREE_FORM,COUNTERPARTYE), always filled the following nine fields.
.bank(fromAccount.bankId.value)
.account(fromAccount.accountId.value)
.transactionType(transactionRequestType.value)
.amount(Helper.convertToSmallestCurrencyUnits(amount, currency))
.newAccountBalance(newAccountBalance)
.currency(currency)
.tStartDate(now)
.tFinishDate(now)
.description(description)
//Old data: other BankAccount(toAccount: BankAccount)simulate counterparty
.counterpartyAccountHolder(toAccount.accountHolder)
.counterpartyAccountNumber(toAccount.number)
.counterpartyAccountKind(toAccount.accountType)
.counterpartyBankName(toAccount.bankName)
.counterpartyIban(toAccount.accountRoutings.find(_.scheme == AccountRoutingScheme.IBAN.toString).map(_.address).getOrElse(""))
.counterpartyNationalId(toAccount.nationalIdentifier)
//New data: real counterparty (toCounterparty: CounterpartyTrait)
// .CPCounterPartyId(toAccount.accountId.value)
.CPOtherAccountRoutingScheme(toAccount.accountRoutings.headOption.map(_.scheme).getOrElse(""))
.CPOtherAccountRoutingAddress(toAccount.accountRoutings.headOption.map(_.address).getOrElse(""))
.CPOtherBankRoutingScheme(toAccount.bankRoutingScheme)
.CPOtherBankRoutingAddress(toAccount.bankRoutingAddress)
.chargePolicy(chargePolicy)
.saveMe) ?~! s"$CreateTransactionsException, exception happened when create new mappedTransaction"
} yield {
mappedTransaction.theTransactionId
}
}
}

View File

@ -1064,11 +1064,6 @@ case class InBoundMakePaymentv200(status: Status, data: TransactionId) extends I
override val inboundAdapterCallContext: InboundAdapterCallContext = InboundAdapterCallContext()
}
case class OutBoundMakePaymentImpl(fromAccount: BankAccount, toAccount: BankAccount, transactionRequestCommonBody: TransactionRequestCommonBodyJSON, amt: BigDecimal, description: String, transactionRequestType: TransactionRequestType, chargePolicy: String) extends TopicTrait
case class InBoundMakePaymentImpl(status: Status, data: TransactionId) extends InBoundTrait[TransactionId] {
override val inboundAdapterCallContext: InboundAdapterCallContext = InboundAdapterCallContext()
}
case class OutBoundCreateTransactionRequest(outboundAdapterCallContext: OutboundAdapterCallContext,initiator: User, fromAccount: BankAccount, toAccount: BankAccount, transactionRequestType: TransactionRequestType, body: TransactionRequestBody) extends TopicTrait
case class InBoundCreateTransactionRequest(status: Status, data: TransactionRequest) extends InBoundTrait[TransactionRequest] {
override val inboundAdapterCallContext: InboundAdapterCallContext = InboundAdapterCallContext()
@ -1159,11 +1154,6 @@ case class InBoundGetTransactionRequestStatuses(status: Status, data: Transactio
override val inboundAdapterCallContext: InboundAdapterCallContext = InboundAdapterCallContext()
}
case class OutBoundGetTransactionRequestsImpl(fromAccount: BankAccount) extends TopicTrait
case class InBoundGetTransactionRequestsImpl(status: Status, data: List[TransactionRequest]) extends InBoundTrait[List[TransactionRequest]] {
override val inboundAdapterCallContext: InboundAdapterCallContext = InboundAdapterCallContext()
}
case class OutBoundGetTransactionRequestTypes(outboundAdapterCallContext: OutboundAdapterCallContext, initiator: User, fromAccount: BankAccount) extends TopicTrait
case class InBoundGetTransactionRequestTypes(status: Status, data: List[TransactionRequestType]) extends InBoundTrait[List[TransactionRequestType]] {
override val inboundAdapterCallContext: InboundAdapterCallContext = InboundAdapterCallContext()