feature/BGv1.3 added periodic_payments - step2

This commit is contained in:
Hongwei 2024-08-20 08:28:42 +02:00
parent 756ea2e662
commit d4aa006dac
8 changed files with 37 additions and 264 deletions

View File

@ -542,33 +542,33 @@ Check the transaction status of a payment initiation.""",
TransactionRequestTypes.withName(paymentProduct.replaceAll("-", "_").toUpperCase)
}
transDetailsJson <- NewStyle.function.tryons(s"$InvalidJsonFormat The Json body should be the $SepaCreditTransfersBerlinGroupV13 ", 400, callContext) {
sepaCreditTransfersBerlinGroupV13 <- NewStyle.function.tryons(s"$InvalidJsonFormat The Json body should be the $SepaCreditTransfersBerlinGroupV13 ", 400, callContext) {
json.extract[SepaCreditTransfersBerlinGroupV13]
}
//If it is periodic_payments, we need to make sure, we have more fileds.
_ <- Helper.booleanToFuture(s"$InvalidJsonFormat startDate field is missing. ", 400, callContext) {
if(PaymentServiceTypes.withName(paymentService.replaceAll("-", "_")).equals(PaymentServiceTypes.periodic_payments)) {
transDetailsJson.startDate.isDefined
sepaCreditTransfersBerlinGroupV13.startDate.isDefined
} else {
true
}
}
_ <- Helper.booleanToFuture(s"$InvalidJsonFormat frequency field is missing. ", 400, callContext) {
if(PaymentServiceTypes.withName(paymentService.replaceAll("-", "_")).equals(PaymentServiceTypes.periodic_payments)) {
transDetailsJson.frequency.isDefined
sepaCreditTransfersBerlinGroupV13.frequency.isDefined
} else {
true
}
}
transDetailsSerialized <- NewStyle.function.tryons(s"$UnknownError Can not serialize in request Json ", 400, callContext) {
write(transDetailsJson)(Serialization.formats(NoTypeHints))
write(sepaCreditTransfersBerlinGroupV13)(Serialization.formats(NoTypeHints))
}
isValidAmountNumber <- NewStyle.function.tryons(s"$InvalidNumber Current input is ${transDetailsJson.instructedAmount.amount} ", 400, callContext) {
BigDecimal(transDetailsJson.instructedAmount.amount)
isValidAmountNumber <- NewStyle.function.tryons(s"$InvalidNumber Current input is ${sepaCreditTransfersBerlinGroupV13.instructedAmount.amount} ", 400, callContext) {
BigDecimal(sepaCreditTransfersBerlinGroupV13.instructedAmount.amount)
}
_ <- Helper.booleanToFuture(s"${NotPositiveAmount} Current input is: '${isValidAmountNumber}'", cc = callContext) {
@ -576,13 +576,13 @@ Check the transaction status of a payment initiation.""",
}
// Prevent default value for transaction request type (at least).
_ <- Helper.booleanToFuture(s"${InvalidISOCurrencyCode} Current input is: '${transDetailsJson.instructedAmount.currency}'", cc = callContext) {
isValidCurrencyISOCode(transDetailsJson.instructedAmount.currency)
_ <- Helper.booleanToFuture(s"${InvalidISOCurrencyCode} Current input is: '${sepaCreditTransfersBerlinGroupV13.instructedAmount.currency}'", cc = callContext) {
isValidCurrencyISOCode(sepaCreditTransfersBerlinGroupV13.instructedAmount.currency)
}
_ <- NewStyle.function.isEnabledTransactionRequests(callContext)
fromAccountIban = transDetailsJson.debtorAccount.iban
toAccountIban = transDetailsJson.creditorAccount.iban
fromAccountIban = sepaCreditTransfersBerlinGroupV13.debtorAccount.iban
toAccountIban = sepaCreditTransfersBerlinGroupV13.creditorAccount.iban
(fromAccount, callContext) <- NewStyle.function.getBankAccountByIban(fromAccountIban, callContext)
(ibanChecker, callContext) <- NewStyle.function.validateAndCheckIbanNumber(toAccountIban, callContext)
@ -601,11 +601,11 @@ Check the transaction status of a payment initiation.""",
NewStyle.function.hasEntitlement(fromAccount.bankId.value, u.userId, ApiRole.canCreateAnyTransactionRequest, callContext, InsufficientAuthorisationToCreateTransactionRequest)
// Prevent default value for transaction request type (at least).
_ <- Helper.booleanToFuture(s"From Account Currency is ${fromAccount.currency}, but Requested Transaction Currency is: ${transDetailsJson.instructedAmount.currency}", cc = callContext) {
transDetailsJson.instructedAmount.currency == fromAccount.currency
_ <- Helper.booleanToFuture(s"From Account Currency is ${fromAccount.currency}, but Requested Transaction Currency is: ${sepaCreditTransfersBerlinGroupV13.instructedAmount.currency}", cc = callContext) {
sepaCreditTransfersBerlinGroupV13.instructedAmount.currency == fromAccount.currency
}
amountOfMoneyJSON = transDetailsJson.instructedAmount
amountOfMoneyJSON = sepaCreditTransfersBerlinGroupV13.instructedAmount
(createdTransactionRequest, callContext) <- transactionRequestTypes match {
case TransactionRequestTypes.SEPA_CREDIT_TRANSFERS => {
@ -625,7 +625,7 @@ Check the transaction status of a payment initiation.""",
Some(BERLIN_GROUP_PAYMENT_CHALLENGE),
None,
None,
Some(transDetailsJson),
Some(sepaCreditTransfersBerlinGroupV13),
callContext
) //in SANDBOX_TAN, ChargePolicy set default "SHARED"
} yield (createdTransactionRequest, callContext)

View File

@ -1191,7 +1191,8 @@ trait Connector extends MdcLoggable {
details: String,
status: String,
charge: TransactionRequestCharge,
chargePolicy: String): Box[TransactionRequest] = Failure(setUnimplementedError)
chargePolicy: String,
berlinGroupPayments: Option[SepaCreditTransfersBerlinGroupV13]): Box[TransactionRequest] = Failure(setUnimplementedError)
def notifyTransactionRequest(fromAccount: BankAccount, toAccount: BankAccount, transactionRequest: TransactionRequest, callContext: Option[CallContext]): OBPReturnType[Box[TransactionRequestStatusValue]] =
Future{(Failure(setUnimplementedError), callContext)}

View File

@ -2234,7 +2234,8 @@ object LocalMappedConnector extends Connector with MdcLoggable {
details: String,
status: String,
charge: TransactionRequestCharge,
chargePolicy: String): Box[TransactionRequest] = {
chargePolicy: String,
berlinGroupPayments: Option[SepaCreditTransfersBerlinGroupV13]): Box[TransactionRequest] = {
TransactionRequests.transactionRequestProvider.vend.createTransactionRequestImpl210(transactionRequestId,
transactionRequestType,
@ -2244,7 +2245,8 @@ object LocalMappedConnector extends Connector with MdcLoggable {
details,
status,
charge,
chargePolicy)
chargePolicy,
berlinGroupPayments: Option[SepaCreditTransfersBerlinGroupV13])
}
override def saveTransactionRequestTransactionImpl(transactionRequestId: TransactionRequestId, transactionId: TransactionId): Box[Boolean] = {

View File

@ -39,7 +39,6 @@ object RemotedataActors extends MdcLoggable {
ActorProps[RemotedataCustomerDependantsActor] -> RemotedataCustomerDependants.actorName,
ActorProps[RemotedataUserCustomerLinksActor] -> RemotedataUserCustomerLinks.actorName,
ActorProps[RemotedataConsumersActor] -> RemotedataConsumers.actorName,
ActorProps[RemotedataTransactionRequestsActor] -> RemotedataTransactionRequests.actorName,
ActorProps[RemotedataMetricsActor] -> RemotedataMetrics.actorName,
ActorProps[RemotedataTokensActor] -> RemotedataTokens.actorName,
ActorProps[RemotedataNoncesActor] -> RemotedataNonces.actorName,

View File

@ -1,94 +0,0 @@
package code.remotedata
import akka.pattern.ask
import code.actorsystem.ObpActorInit
import com.openbankproject.commons.model.{TransactionRequest, TransactionRequestChallenge, TransactionRequestCharge, _}
import code.transactionrequests.{MappedTransactionRequest, RemotedataTransactionRequestsCaseClasses, TransactionRequestProvider}
import net.liftweb.common.Box
object RemotedataTransactionRequests extends ObpActorInit with TransactionRequestProvider {
val cc = RemotedataTransactionRequestsCaseClasses
def getMappedTransactionRequest(transactionRequestId: TransactionRequestId): Box[MappedTransactionRequest] = getValueFromFuture(
(actor ? cc.getMappedTransactionRequest(transactionRequestId)).mapTo[Box[MappedTransactionRequest]]
)
def getTransactionRequestsFromProvider(bankId: BankId, accountId: AccountId): Box[List[TransactionRequest]] = getValueFromFuture(
(actor ? cc.getTransactionRequestsFromProvider(bankId, accountId)).mapTo[Box[List[TransactionRequest]]]
)
def getTransactionRequestFromProvider(transactionRequestId: TransactionRequestId): Box[TransactionRequest] = getValueFromFuture(
(actor ? cc.getTransactionRequestFromProvider(transactionRequestId)).mapTo[Box[TransactionRequest]]
)
def updateAllPendingTransactionRequests(): Box[Option[Unit]] = getValueFromFuture(
(actor ? cc.updateAllPendingTransactionRequests()).mapTo[ Box[Option[Unit]]]
)
def createTransactionRequestImpl(transactionRequestId: TransactionRequestId,
transactionRequestType: TransactionRequestType,
account: BankAccount,
counterparty: BankAccount,
body: TransactionRequestBody,
status: String,
charge: TransactionRequestCharge): Box[TransactionRequest] = getValueFromFuture(
(actor ? cc.createTransactionRequestImpl(
transactionRequestId,
transactionRequestType,
account,
counterparty,
body,
status,
charge)).mapTo[Box[TransactionRequest]]
)
def createTransactionRequestImpl210(transactionRequestId: TransactionRequestId,
transactionRequestType: TransactionRequestType,
fromAccount: BankAccount,
toAccount: BankAccount,
transactionRequestCommonBody: TransactionRequestCommonBodyJSON,
details: String,
status: String,
charge: TransactionRequestCharge,
chargePolicy: String): Box[TransactionRequest] = getValueFromFuture(
(actor ? cc.createTransactionRequestImpl210(
transactionRequestId,
transactionRequestType,
fromAccount,
toAccount,
transactionRequestCommonBody,
details,
status,
charge,
chargePolicy)).mapTo[Box[TransactionRequest]]
)
def saveTransactionRequestTransactionImpl(transactionRequestId: TransactionRequestId, transactionId: TransactionId): Box[Boolean] = getValueFromFuture(
(actor ? cc.saveTransactionRequestTransactionImpl(transactionRequestId, transactionId)).mapTo[Box[Boolean]]
)
def saveTransactionRequestChallengeImpl(transactionRequestId: TransactionRequestId, challenge: TransactionRequestChallenge): Box[Boolean] = getValueFromFuture(
(actor ? cc.saveTransactionRequestChallengeImpl(transactionRequestId, challenge)).mapTo[Box[Boolean]]
)
def saveTransactionRequestStatusImpl(transactionRequestId: TransactionRequestId, status: String): Box[Boolean] = getValueFromFuture(
(actor ? cc.saveTransactionRequestStatusImpl(transactionRequestId, status)).mapTo[Box[Boolean]]
)
def saveTransactionRequestDescriptionImpl(transactionRequestId: TransactionRequestId, description: String): Box[Boolean] = getValueFromFuture(
(actor ? cc.saveTransactionRequestDescriptionImpl(transactionRequestId, description)).mapTo[Box[Boolean]]
)
def bulkDeleteTransactionRequests(): Boolean = getValueFromFuture(
(actor ? cc.bulkDeleteTransactionRequests()).mapTo[Boolean]
)
override def bulkDeleteTransactionRequestsByTransactionId(transactionId: TransactionId): Boolean = getValueFromFuture(
(actor ? cc.bulkDeleteTransactionRequestsByTransactionId(transactionId)).mapTo[Boolean]
)
}

View File

@ -1,110 +0,0 @@
package code.remotedata
import akka.actor.Actor
import code.actorsystem.ObpActorHelper
import code.transactionrequests.{MappedTransactionRequestProvider, RemotedataTransactionRequestsCaseClasses}
import code.util.Helper.MdcLoggable
import com.openbankproject.commons.model._
class RemotedataTransactionRequestsActor extends Actor with ObpActorHelper with MdcLoggable {
val mapper = MappedTransactionRequestProvider
val cc = RemotedataTransactionRequestsCaseClasses
def receive = {
case cc.getMappedTransactionRequest(transactionRequestId: TransactionRequestId) =>
logger.debug("getMappedTransactionRequest(" + transactionRequestId + ")")
sender ! (mapper.getMappedTransactionRequest(transactionRequestId))
case cc.getTransactionRequestsFromProvider(bankId: BankId, accountId: AccountId) =>
logger.debug("getTransactionRequestsFromProvider(" + bankId + ", " + accountId + ", " + ")")
sender ! (mapper.getTransactionRequestsFromProvider(bankId, accountId))
case cc.getTransactionRequestFromProvider(transactionRequestId: TransactionRequestId) =>
logger.debug("getTransactionRequestFromProvider(" + transactionRequestId + ")")
sender ! (mapper.getTransactionRequestFromProvider(transactionRequestId))
case cc.updateAllPendingTransactionRequests() =>
logger.debug("updateAllPendingTransactionRequests()")
sender ! (mapper.updateAllPendingTransactionRequests)
case cc.createTransactionRequestImpl(transactionRequestId: TransactionRequestId,
transactionRequestType: TransactionRequestType,
account: BankAccount,
counterparty: BankAccount,
body: TransactionRequestBody,
status: String,
charge: TransactionRequestCharge) =>
logger.debug("createTransactionRequestImpl(" + transactionRequestId + ", " +
transactionRequestType + ", " +
account + ", " +
counterparty + ", " +
body + ", " +
status + ", " +
charge + ", " +
")")
sender ! (mapper.createTransactionRequestImpl(transactionRequestId,
transactionRequestType,
account,
counterparty,
body,
status,
charge))
case cc.createTransactionRequestImpl210(transactionRequestId: TransactionRequestId,
transactionRequestType: TransactionRequestType,
fromAccount: BankAccount,
toAccount: BankAccount,
transactionRequestCommonBody: TransactionRequestCommonBodyJSON,
details: String,
status: String,
charge: TransactionRequestCharge,
chargePolicy: String) =>
logger.debug("createTransactionRequestImpl210(" + transactionRequestId + ", " +
transactionRequestType + ", " +
fromAccount + ", " +
toAccount + ", " +
transactionRequestCommonBody + ", " +
details + ", " +
status + ", " +
charge + ", " +
chargePolicy + ", " +
")")
sender ! (mapper.createTransactionRequestImpl210(transactionRequestId,
transactionRequestType,
fromAccount,
toAccount,
transactionRequestCommonBody,
details,
status,
charge,
chargePolicy))
case cc.saveTransactionRequestTransactionImpl(transactionRequestId: TransactionRequestId, transactionId: TransactionId) =>
logger.debug("saveTransactionRequestTransactionImpl(" + transactionRequestId + ", " + transactionId + ")")
sender ! (mapper.saveTransactionRequestTransactionImpl(transactionRequestId, transactionId))
case cc.saveTransactionRequestChallengeImpl(transactionRequestId: TransactionRequestId, challenge: TransactionRequestChallenge) =>
logger.debug("saveTransactionRequestChallengeImpl(" + transactionRequestId + ", " + challenge + ")")
sender ! (mapper.saveTransactionRequestChallengeImpl(transactionRequestId, challenge))
case cc.saveTransactionRequestStatusImpl(transactionRequestId: TransactionRequestId, status: String) =>
logger.debug("saveTransactionRequestStatusImpl(" + transactionRequestId + ", " + status + ")")
sender ! (mapper.saveTransactionRequestStatusImpl(transactionRequestId, status))
case cc.bulkDeleteTransactionRequests() =>
logger.debug("bulkDeleteTransactionRequests()")
sender ! (mapper.bulkDeleteTransactionRequests())
case cc.bulkDeleteTransactionRequestsByTransactionId(transactionId: TransactionId) =>
logger.debug(s"bulkDeleteTransactionRequestsByTransactionId($transactionId)")
sender ! (mapper.bulkDeleteTransactionRequestsByTransactionId(transactionId))
case message => logger.warn("[AKKA ACTOR ERROR - REQUEST NOT RECOGNIZED] " + message)
}
}

View File

@ -1,5 +1,6 @@
package code.transactionrequests
import code.api.util.APIUtil.DateWithMsFormat
import code.api.util.CustomJsonFormats
import code.api.util.ErrorMessages._
import code.bankconnectors.Connector
@ -14,6 +15,8 @@ import net.liftweb.json.JsonAST.{JField, JObject, JString}
import net.liftweb.mapper._
import net.liftweb.util.Helpers._
import java.text.SimpleDateFormat
object MappedTransactionRequestProvider extends TransactionRequestProvider {
private val logger = Logger(classOf[TransactionRequestProvider])
@ -84,7 +87,8 @@ object MappedTransactionRequestProvider extends TransactionRequestProvider {
details: String,
status: String,
charge: TransactionRequestCharge,
chargePolicy: String): Box[TransactionRequest] = {
chargePolicy: String,
berlinGroupPayments: Option[SepaCreditTransfersBerlinGroupV13]): Box[TransactionRequest] = {
val toAccountRouting = transactionRequestType.value match {
case "SEPA" =>
@ -93,6 +97,9 @@ object MappedTransactionRequestProvider extends TransactionRequestProvider {
case _ => toAccount.accountRoutings.headOption
}
val paymentStartDate = berlinGroupPayments.flatMap(_.startDate).map(DateWithMsFormat.parse)
val paymentEndDate = berlinGroupPayments.flatMap(_.endDate).map(DateWithMsFormat.parse)
// Note: We don't save transaction_ids, status and challenge here.
val mappedTransactionRequest = MappedTransactionRequest.create
@ -139,11 +146,11 @@ object MappedTransactionRequestProvider extends TransactionRequestProvider {
.mDetails(details) // This is the details / body of the request (contains all fields in the body)
.mPaymentStartDate(now)
.mPaymentEndDate(now)
.mPaymentExecutionRule("")
.mPaymentFrequency("")
.mPaymentDayOfExecution("")
.mPaymentStartDate(paymentStartDate.orNull)
.mPaymentEndDate(paymentEndDate.orNull)
.mPaymentExecutionRule(berlinGroupPayments.flatMap(_.executionRule).orNull)
.mPaymentFrequency(berlinGroupPayments.flatMap(_.frequency).orNull)
.mPaymentDayOfExecution(berlinGroupPayments.flatMap(_.dayOfExecution).orNull)
.saveMe
Full(mappedTransactionRequest).flatMap(_.toTransactionRequest)

View File

@ -2,7 +2,6 @@ package code.transactionrequests
import code.api.util.APIUtil
import code.remotedata.RemotedataTransactionRequests
import com.openbankproject.commons.model.{TransactionRequest, TransactionRequestChallenge, TransactionRequestCharge, _}
import net.liftweb.common.{Box, Logger}
import net.liftweb.util.SimpleInjector
@ -29,10 +28,7 @@ object TransactionRequests extends SimpleInjector {
def buildOne: TransactionRequestProvider =
APIUtil.getPropsValue("transactionRequests_connector", "mapped") match {
case "mapped" => APIUtil.getPropsAsBoolValue("use_akka", false) match {
case false => MappedTransactionRequestProvider
case true => RemotedataTransactionRequests // We will use Akka as a middleware
}
case "mapped" => MappedTransactionRequestProvider
case tc: String => throw new IllegalArgumentException("No such connector for Transaction Requests: " + tc)
}
@ -78,7 +74,8 @@ trait TransactionRequestProvider {
details: String,
status: String,
charge: TransactionRequestCharge,
chargePolicy: String): Box[TransactionRequest]
chargePolicy: String,
berlinGroupPayments: Option[SepaCreditTransfersBerlinGroupV13]): Box[TransactionRequest]
def saveTransactionRequestTransactionImpl(transactionRequestId: TransactionRequestId, transactionId: TransactionId): Box[Boolean]
def saveTransactionRequestChallengeImpl(transactionRequestId: TransactionRequestId, challenge: TransactionRequestChallenge): Box[Boolean]
def saveTransactionRequestStatusImpl(transactionRequestId: TransactionRequestId, status: String): Box[Boolean]
@ -87,33 +84,4 @@ trait TransactionRequestProvider {
def bulkDeleteTransactionRequests(): Boolean
}
class RemotedataTransactionRequestsCaseClasses {
case class getMappedTransactionRequest(transactionRequestId: TransactionRequestId)
case class getTransactionRequestsFromProvider(bankId : BankId, accountId: AccountId)
case class getTransactionRequestFromProvider(transactionRequestId : TransactionRequestId)
case class updateAllPendingTransactionRequests()
case class createTransactionRequestImpl(transactionRequestId: TransactionRequestId,
transactionRequestType: TransactionRequestType,
account : BankAccount,
counterparty : BankAccount,
body: TransactionRequestBody,
status: String,
charge: TransactionRequestCharge)
case class createTransactionRequestImpl210(transactionRequestId: TransactionRequestId,
transactionRequestType: TransactionRequestType,
fromAccount: BankAccount,
toAccount: BankAccount,
transactionRequestCommonBody: TransactionRequestCommonBodyJSON,
details: String,
status: String,
charge: TransactionRequestCharge,
chargePolicy: String)
case class saveTransactionRequestTransactionImpl(transactionRequestId: TransactionRequestId, transactionId: TransactionId)
case class saveTransactionRequestChallengeImpl(transactionRequestId: TransactionRequestId, challenge: TransactionRequestChallenge)
case class saveTransactionRequestStatusImpl(transactionRequestId: TransactionRequestId, status: String)
case class saveTransactionRequestDescriptionImpl(transactionRequestId: TransactionRequestId, description: String)
case class bulkDeleteTransactionRequestsByTransactionId(transactionId: TransactionId)
case class bulkDeleteTransactionRequests()
}
object RemotedataTransactionRequestsCaseClasses extends RemotedataTransactionRequestsCaseClasses