From e71169ffcedea19440875565a87fba0f146732df Mon Sep 17 00:00:00 2001 From: hongwei Date: Tue, 22 Oct 2024 18:40:40 +0200 Subject: [PATCH] refactor/moved makePaymentImpl to LocalMappedConnectorInternal --- .../scala/code/bankconnectors/Connector.scala | 4 - .../bankconnectors/ConnectorBuilderUtil.scala | 2 - .../bankconnectors/LocalMappedConnector.scala | 92 ++----------------- .../LocalMappedConnectorInternal.scala | 85 +++++++++++++++-- .../commons/dto/JsonsTransfer.scala | 10 -- 5 files changed, 88 insertions(+), 105 deletions(-) diff --git a/obp-api/src/main/scala/code/bankconnectors/Connector.scala b/obp-api/src/main/scala/code/bankconnectors/Connector.scala index 770464b60..b1ad0306f 100644 --- a/obp-api/src/main/scala/code/bankconnectors/Connector.scala +++ b/obp-api/src/main/scala/code/bankconnectors/Connector.scala @@ -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 */ diff --git a/obp-api/src/main/scala/code/bankconnectors/ConnectorBuilderUtil.scala b/obp-api/src/main/scala/code/bankconnectors/ConnectorBuilderUtil.scala index cf0dcf38c..5a9944041 100644 --- a/obp-api/src/main/scala/code/bankconnectors/ConnectorBuilderUtil.scala +++ b/obp-api/src/main/scala/code/bankconnectors/ConnectorBuilderUtil.scala @@ -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( diff --git a/obp-api/src/main/scala/code/bankconnectors/LocalMappedConnector.scala b/obp-api/src/main/scala/code/bankconnectors/LocalMappedConnector.scala index 290ede081..26a2d1a4b 100644 --- a/obp-api/src/main/scala/code/bankconnectors/LocalMappedConnector.scala +++ b/obp-api/src/main/scala/code/bankconnectors/LocalMappedConnector.scala @@ -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.
- * Returns the id of the saved transactionId.
- */ - 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 diff --git a/obp-api/src/main/scala/code/bankconnectors/LocalMappedConnectorInternal.scala b/obp-api/src/main/scala/code/bankconnectors/LocalMappedConnectorInternal.scala index fc5125337..8eb0e111d 100644 --- a/obp-api/src/main/scala/code/bankconnectors/LocalMappedConnectorInternal.scala +++ b/obp-api/src/main/scala/code/bankconnectors/LocalMappedConnectorInternal.scala @@ -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.
+ * Returns the id of the saved transactionId.
+ */ + 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 + } + } + } diff --git a/obp-commons/src/main/scala/com/openbankproject/commons/dto/JsonsTransfer.scala b/obp-commons/src/main/scala/com/openbankproject/commons/dto/JsonsTransfer.scala index 313ec3dd3..b8418f990 100644 --- a/obp-commons/src/main/scala/com/openbankproject/commons/dto/JsonsTransfer.scala +++ b/obp-commons/src/main/scala/com/openbankproject/commons/dto/JsonsTransfer.scala @@ -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()