feature/Add the connector method to save the double-entry transaction

This commit is contained in:
Guillaume Kergreis 2020-08-26 21:36:43 +02:00
parent 07b150c116
commit 8abd5bc514
7 changed files with 110 additions and 47 deletions

View File

@ -453,6 +453,7 @@ object ErrorMessages {
val InvalidConnectorResponseForCreateTransactionAfterChallengev300 = "OBP-50213: The Connector did not return a valid response for payments."
val InvalidConnectorResponseForMissingRequiredValues = "OBP-50214: Connector return the data, but the data has missing required values."
val InvalidConnectorResponseForCreateChallenge = "OBP-50215: Connector did not return the set of challenge we requested."
val InvalidConnectorResponseForSaveDoubleEntryBookTransaction = "OBP-50216: The Connector did not return a valid response for saving double-entry transaction."
// Adapter Exceptions (OBP-6XXXX)

View File

@ -29,7 +29,7 @@ import com.openbankproject.commons.model.FXRate
import code.metadata.counterparties.Counterparties
import code.methodrouting.{MethodRoutingCommons, MethodRoutingProvider, MethodRoutingT}
import code.model._
import code.model.dataAccess.BankAccountRouting
import code.model.dataAccess.{BankAccountRouting, DoubleEntryBookTransaction}
import code.standingorders.StandingOrderTrait
import code.usercustomerlinks.UserCustomerLink
import code.util.Helper
@ -955,7 +955,12 @@ object NewStyle {
) map { i =>
(unboxFullOrFail(i._1, callContext, s"$InvalidConnectorResponseForMakePayment ",400), i._2)
}
def saveDoubleEntryBookTransaction(transactionRequestId: Option[TransactionRequestId], debitTransactionId: TransactionId, creditTransactionId: TransactionId, callContext: Option[CallContext]): OBPReturnType[DoubleEntryTransaction] =
Connector.connector.vend.saveDoubleEntryBookTransaction(transactionRequestId: Option[TransactionRequestId], debitTransactionId: TransactionId, creditTransactionId: TransactionId, callContext: Option[CallContext]) map { i =>
(unboxFullOrFail(i._1, callContext, s"$InvalidConnectorResponseForSaveDoubleEntryBookTransaction ", 400), i._2)
}
def createOrUpdateProductAttribute(
bankId: BankId,
productCode: ProductCode,

View File

@ -704,6 +704,10 @@ trait Connector extends MdcLoggable {
chargePolicy: String,
callContext: Option[CallContext]): OBPReturnType[Box[TransactionId]]= Future{(Failure(setUnimplementedError), callContext)}
def saveDoubleEntryBookTransaction(transactionRequestId: Option[TransactionRequestId],
debitTransactionId: TransactionId,
creditTransactionId: TransactionId,
callContext: Option[CallContext]): OBPReturnType[Box[DoubleEntryTransaction]]= Future{(Failure(setUnimplementedError), callContext)}
protected def makePaymentImpl(fromAccount: BankAccount, toAccount: BankAccount, transactionRequestCommonBody: TransactionRequestCommonBodyJSON, amt: BigDecimal, description: String, transactionRequestType: TransactionRequestType, chargePolicy: String): Box[TransactionId]= Failure(setUnimplementedError)

View File

@ -9,6 +9,7 @@ import code.DynamicEndpoint.{DynamicEndpointProvider, DynamicEndpointT}
import code.accountapplication.AccountApplicationX
import code.accountattribute.AccountAttributeX
import code.accountholders.{AccountHolders, MapperAccountHolders}
import code.api.Constant.{INCOMING_ACCOUNT_ID, OUTGOING_ACCOUNT_ID}
import code.api.ResourceDocs1_4_0.SwaggerDefinitionsJSON
import code.api.attributedefinition.{AttributeDefinition, AttributeDefinitionDI}
import code.api.cache.Caching
@ -1097,17 +1098,49 @@ object LocalMappedConnector extends Connector with MdcLoggable {
}
fromTransAmt = -amount //from fromAccount balance should decrease
toTransAmt = fx.convert(amount, rate)
sentTransactionId <- Future {
debitTransactionId <- Future {
saveTransaction(fromAccount, toAccount, transactionRequestCommonBody, fromTransAmt, description, transactionRequestType, chargePolicy)
.or {
val settlementAccount = BankAccountX(toAccount.bankId, AccountId(transactionRequestType.value), callContext)
.or(BankAccountX(toAccount.bankId, AccountId(INCOMING_ACCOUNT_ID), callContext))
settlementAccount.flatMap(settlementAccount =>
saveTransaction(settlementAccount._1, toAccount, transactionRequestCommonBody, fromTransAmt, description, transactionRequestType, chargePolicy)
)
}
}
_sentTransactionId <- Future {
creditTransactionId <- Future {
saveTransaction(toAccount, fromAccount, transactionRequestCommonBody, toTransAmt, description, transactionRequestType, chargePolicy)
.or {
val settlementAccount = BankAccountX(fromAccount.bankId, AccountId(transactionRequestType.value), callContext)
.or(BankAccountX(fromAccount.bankId, AccountId(OUTGOING_ACCOUNT_ID), callContext))
settlementAccount.flatMap(settlementAccount =>
saveTransaction(settlementAccount._1, fromAccount, transactionRequestCommonBody, toTransAmt, description, transactionRequestType, chargePolicy)
)
}
}
_ <- NewStyle.function.saveDoubleEntryBookTransaction(
Some(transactionRequestId),
debitTransactionId.openOrThrowException("Error while opening debitTransactionId"),
creditTransactionId.openOrThrowException("Error while opening creditTransactionId"),
callContext)
} yield {
(sentTransactionId, callContext)
(debitTransactionId, callContext)
}
}
override def saveDoubleEntryBookTransaction(transactionRequestId: Option[TransactionRequestId],
debitTransactionId: TransactionId,
creditTransactionId: TransactionId,
callContext: Option[CallContext]): OBPReturnType[Box[DoubleEntryTransaction]] = {
Future(
tryo(DoubleEntryBookTransaction.create
.TransactionRequestId(transactionRequestId.map(_.value).getOrElse(""))
.DebitTransactionId(debitTransactionId.value)
.CreditTransactionId(creditTransactionId.value)
.saveMe())
).map(doubleEntryTransaction => (doubleEntryTransaction, callContext))
}
override def makePaymentV400(transactionRequest: TransactionRequest,
reasons: Option[List[TransactionRequestReason]],
callContext: Option[CallContext]): Future[Box[(TransactionId, Option[CallContext])]] = Future {
@ -1162,29 +1195,37 @@ object LocalMappedConnector extends Connector with MdcLoggable {
fromTransAmt = -amount //from fromAccount balance should decrease
toTransAmt = fx.convert(amount, rate)
(sentTransactionId, callContext) <- saveHistoricalTransaction(
fromAccount: BankAccount,
toAccount: BankAccount,
posted: Date,
completed: Date,
amount = fromTransAmt,
description: String,
transactionRequestType: String,
chargePolicy: String,
callContext: Option[CallContext]
_ <- Future(println(fromAccount))
_ <- Future(println(toAccount))
debitTransactionId <- Future(
saveHistoricalTransaction(fromAccount, toAccount, posted, completed, fromTransAmt, description, transactionRequestType, chargePolicy, callContext)
.or {
val settlementAccount = BankAccountX(toAccount.bankId, AccountId(transactionRequestType), callContext)
.or(BankAccountX(toAccount.bankId, AccountId(INCOMING_ACCOUNT_ID), callContext))
.openOrThrowException("Error while opening incoming settlement settlementAccount")
saveHistoricalTransaction(settlementAccount._1, toAccount, posted, completed, fromTransAmt, description, transactionRequestType, chargePolicy, callContext)
}
)
(_sentTransactionId, callContext) <- saveHistoricalTransaction(
toAccount: BankAccount,
fromAccount: BankAccount,
posted: Date,
completed: Date,
amount = toTransAmt,
description: String,
transactionRequestType: String,
chargePolicy: String,
callContext: Option[CallContext])
creditTransactionId <- Future(
saveHistoricalTransaction(toAccount, fromAccount, posted, completed, toTransAmt, description, transactionRequestType, chargePolicy, callContext)
.or {
val settlementAccount = BankAccountX(fromAccount.bankId, AccountId(transactionRequestType), callContext)
.or(BankAccountX(fromAccount.bankId, AccountId(OUTGOING_ACCOUNT_ID), callContext))
.openOrThrowException("Error while opening outgoing settlement settlementAccount")
saveHistoricalTransaction(settlementAccount._1, fromAccount, posted, completed, toTransAmt, description, transactionRequestType, chargePolicy, callContext)
}
)
_ <- NewStyle.function.saveDoubleEntryBookTransaction(
transactionRequestId = None,
debitTransactionId.openOrThrowException("Error while opening debitTransactionId"),
creditTransactionId.openOrThrowException("Error while opening creditTransactionId"),
callContext)
} yield {
(sentTransactionId, callContext)
(debitTransactionId, callContext)
}
}
@ -1199,8 +1240,7 @@ object LocalMappedConnector extends Connector with MdcLoggable {
transactionRequestType: String,
chargePolicy: String,
callContext: Option[CallContext]
): Future[(Box[TransactionId], Option[CallContext])] = Future {
(
): Box[TransactionId] =
for {
currency <- Full(fromAccount.currency)
//update the balance of the fromAccount for which a transaction is being created
@ -1236,8 +1276,7 @@ object LocalMappedConnector extends Connector with MdcLoggable {
.saveMe) ?~! s"$CreateTransactionsException, exception happened when create new mappedTransaction"
} yield {
mappedTransaction.theTransactionId
}, callContext)
}
}
/**
* Saves a transaction with @amount, @toAccount and @transactionRequestType for @fromAccount and @toCounterparty. <br>

View File

@ -26,6 +26,8 @@ TESOBE (http://www.tesobe.com/)
*/
package code.model
import java.util.Date
import code.accountholders.AccountHolders
import code.api.{APIFailureNewStyle, Constant}
import code.api.util.APIUtil.{OBPReturnType, canGrantAccessToViewCommon, canRevokeAccessToViewCommon, fullBoxOrException, unboxFull, unboxFullOrFail}
@ -38,7 +40,7 @@ import code.util.Helper
import code.util.Helper.MdcLoggable
import code.views.Views
import code.views.system.AccountAccess
import com.openbankproject.commons.model.{AccountId, AccountRouting, Bank, BankAccount, BankAccountInMemory, BankId, BankIdAccountId, Counterparty, CounterpartyId, CounterpartyTrait, CreateViewJson, Customer, Permission, TransactionId, UpdateViewJSON, User, UserPrimaryKey, View, ViewId, ViewIdBankIdAccountId}
import com.openbankproject.commons.model.{AccountId, AccountRouting, Attribute, Bank, BankAccount, BankAccountCommons, BankAccountInMemory, BankId, BankIdAccountId, Counterparty, CounterpartyId, CounterpartyTrait, CreateViewJson, Customer, Permission, TransactionId, UpdateViewJSON, User, UserPrimaryKey, View, ViewId, ViewIdBankIdAccountId}
import net.liftweb.common._
import net.liftweb.json.JsonDSL._
import net.liftweb.json.{JArray, JObject}
@ -551,24 +553,28 @@ object BankAccountX {
toAccount
}
else {
//in obp we have the default bank and default accounts for this case:
//in obp we are creating a fake account with the counterparty information in this case:
//These are just the obp mapped mode, if connector to the bank, bank will decide it.
val defaultBankId= BankId(APIUtil.defaultBankId)
val incomingAccountId= AccountId(Constant.INCOMING_ACCOUNT_ID)
val outgoingAccountId= AccountId(Constant.OUTGOING_ACCOUNT_ID)
val bankAccount: Box[BankAccount] = if (isOutgoingAccount){
LocalMappedConnector.getBankAccountOld(defaultBankId,outgoingAccountId)
} else{
LocalMappedConnector.getBankAccountOld(defaultBankId,incomingAccountId)
}
Full(
bankAccount.openOrThrowException("").asInstanceOf[MappedBankAccount]
.holder(counterparty.name) //We mapped the counterpartName to otherAccount. please see @APIUtil.createImplicitCounterpartyId
.accountIban(counterparty.otherAccountRoutingAddress)//now, we only have single pair AccountRouting, will put these to AccountRoutings later.
.mAccountRoutingScheme(counterparty.otherBankRoutingScheme)//This is for the swift bank code..
.mAccountRoutingScheme(counterparty.otherBankRoutingAddress)
)
Full(BankAccountCommons(
AccountId(""), "", 0, "EUR", "", "", "", BankId(""), new Date(), "",
accountRoutings = List(
AccountRouting(counterparty.otherAccountRoutingScheme, counterparty.otherAccountRoutingAddress),
AccountRouting(counterparty.otherAccountSecondaryRoutingScheme, counterparty.otherAccountSecondaryRoutingAddress)
),
List.empty, accountHolder = counterparty.name,
Some(List(Attribute(
name = "BANK_ROUTING_SCHEME",
`type` = "STRING",
value = counterparty.otherBankRoutingScheme
),
Attribute(
name = "BANK_ROUTING_ADDRESS",
`type` = "STRING",
value = counterparty.otherBankRoutingAddress
),
))
))
}
}

View File

@ -358,3 +358,11 @@ trait DoubleEntryBookTransactionTrait {
def debitTransactionId: TransactionId
def creditTransactionId: TransactionId
}
case class DoubleEntryTransaction(
transactionRequestId: Option[TransactionRequestId],
debitTransactionId: TransactionId,
creditTransactionId: TransactionId
) extends DoubleEntryBookTransactionTrait
object DoubleEntryTransaction extends Converter[DoubleEntryBookTransactionTrait, DoubleEntryTransaction]