Skip to content

Commit

Permalink
Merge pull request #2469 from hongwei1/develop
Browse files Browse the repository at this point in the history
Feature/added support for IBAN and ACCOUNT_NUMBER for counterparty payment
  • Loading branch information
simonredfern authored Dec 23, 2024
2 parents 4ab6f5d + 3ac4989 commit 40e06cd
Show file tree
Hide file tree
Showing 13 changed files with 286 additions and 88 deletions.
3 changes: 3 additions & 0 deletions obp-api/src/main/scala/code/api/util/ErrorMessages.scala
Original file line number Diff line number Diff line change
Expand Up @@ -511,6 +511,9 @@ object ErrorMessages {
val CustomViewAlreadyExistsError = "OBP-30266: The custom view is already exists."
val UserDoesNotHavePermission = "OBP-30267: The user does not have the permission:"
val CounterpartyLimitValidationError = "OBP-30268: Counterparty Limit Validation Error."
val AccountNumberNotUniqueError = "OBP-30269: Finding an account by the accountNumber is ambiguous."
val InvalidAccountNumber = "OBP-30270: Account not found. Please specify a valid value for ACCOUNT_NUMBER."
val BankAccountNotFoundByRoutings = "OBP-30271: Bank Account not found. Please specify valid values for routing schemes and addresses."

val TaxResidenceNotFound = "OBP-30300: Tax Residence not found by TAX_RESIDENCE_ID. "
val CustomerAddressNotFound = "OBP-30310: Customer's Address not found by CUSTOMER_ADDRESS_ID. "
Expand Down
30 changes: 27 additions & 3 deletions obp-api/src/main/scala/code/api/util/NewStyle.scala
Original file line number Diff line number Diff line change
Expand Up @@ -403,6 +403,24 @@ object NewStyle extends MdcLoggable{
}
}

def getBankAccountByRoutings(
bankAccountRoutings: BankAccountRoutings,
callContext: Option[CallContext]
): OBPReturnType[BankAccount] = {
Connector.connector.vend.getBankAccountByRoutings(
bankAccountRoutings: BankAccountRoutings,
callContext: Option[CallContext]
) map { i =>
(
unboxFullOrFail(i._1, callContext,s"$BankAccountNotFoundByRoutings " +
s"Current bank scheme is ${bankAccountRoutings.bank.scheme}, current bank address is ${bankAccountRoutings.bank.address}," +
s"Current account scheme is ${bankAccountRoutings.account.scheme}, current account address is ${bankAccountRoutings.account.scheme}," +
s"Current branch scheme is ${bankAccountRoutings.branch.scheme}, current branch address is ${bankAccountRoutings.branch.scheme}",
404
), i._2)
}
}

def getAccountRoutingsByScheme(bankId: Option[BankId], scheme: String, callContext: Option[CallContext]) : OBPReturnType[List[BankAccountRouting]] = {
Connector.connector.vend.getAccountRoutingsByScheme(bankId: Option[BankId], scheme: String, callContext: Option[CallContext]) map { i =>
(unboxFullOrFail(i._1, callContext,s"$AccountRoutingNotFound Current scheme is $scheme, current bankId is $bankId", 404 ), i._2)
Expand Down Expand Up @@ -447,6 +465,11 @@ object NewStyle extends MdcLoggable{
(unboxFullOrFail(i._1, callContext, s"$BankAccountNotFound Current BankId is $bankId and Current AccountId is $accountId", 404), i._2)
}

def getBankAccountByNumber(bankId : Option[BankId], accountNumber : String, callContext: Option[CallContext]) : OBPReturnType[(BankAccount)] = {
Connector.connector.vend.getBankAccountByNumber(bankId, accountNumber, callContext) } map { i =>
(unboxFullOrFail(i._1, callContext, s"$BankAccountNotFound Current BankId is $bankId and Current AccountNumber is $accountNumber", 404), i._2)
}

def getBankSettlementAccounts(bankId: BankId, callContext: Option[CallContext]): OBPReturnType[List[BankAccount]] = {
Connector.connector.vend.getBankSettlementAccounts(bankId: BankId, callContext: Option[CallContext]) map { i =>
(unboxFullOrFail(i._1, callContext,s"$BankNotFound Current BankId is $bankId", 404 ), i._2)
Expand Down Expand Up @@ -1230,10 +1253,11 @@ object NewStyle extends MdcLoggable{
i._2)
}
}
def getBankAccountFromCounterparty(counterparty: CounterpartyTrait, isOutgoingAccount: Boolean, callContext: Option[CallContext]) : Future[BankAccount] =
def getBankAccountFromCounterparty(counterparty: CounterpartyTrait, isOutgoingAccount: Boolean, callContext: Option[CallContext]) : OBPReturnType[BankAccount] =
{
Future{BankAccountX.getBankAccountFromCounterparty(counterparty, isOutgoingAccount)} map {
unboxFullOrFail(_, callContext, s"$UnknownError ")
Connector.connector.vend.getBankAccountFromCounterparty(counterparty: CounterpartyTrait, isOutgoingAccount: Boolean, callContext: Option[CallContext]) map { i =>
(unboxFullOrFail(i._1, callContext, s"$InvalidConnectorResponse ${nameOf(getBankAccountFromCounterparty _)}", 400),
i._2)
}
}

Expand Down
4 changes: 2 additions & 2 deletions obp-api/src/main/scala/code/api/v2_1_0/APIMethods210.scala
Original file line number Diff line number Diff line change
Expand Up @@ -506,7 +506,7 @@ trait APIMethods210 {
}
toCounterpartyId = transactionRequestBodyCounterparty.to.counterparty_id
(toCounterparty, callContext) <- NewStyle.function.getCounterpartyByCounterpartyId(CounterpartyId(toCounterpartyId), callContext)
toAccount <- NewStyle.function.getBankAccountFromCounterparty(toCounterparty, true, callContext)
(toAccount, callContext) <- NewStyle.function.getBankAccountFromCounterparty(toCounterparty, true, callContext)
// Check we can send money to it.
_ <- Helper.booleanToFuture(s"$CounterpartyBeneficiaryPermit", cc=callContext) {
toCounterparty.isBeneficiary == true
Expand Down Expand Up @@ -538,7 +538,7 @@ trait APIMethods210 {
}
toIban = transDetailsSEPAJson.to.iban
(toCounterparty, callContext) <- NewStyle.function.getCounterpartyByIban(toIban, callContext)
toAccount <- NewStyle.function.getBankAccountFromCounterparty(toCounterparty, true, callContext)
(toAccount, callContext) <- NewStyle.function.getBankAccountFromCounterparty(toCounterparty, true, callContext)
_ <- Helper.booleanToFuture(s"$CounterpartyBeneficiaryPermit", cc=callContext) {
toCounterparty.isBeneficiary == true
}
Expand Down
23 changes: 18 additions & 5 deletions obp-api/src/main/scala/code/api/v2_2_0/APIMethods220.scala
Original file line number Diff line number Diff line change
Expand Up @@ -1193,11 +1193,11 @@ trait APIMethods220 {
json.extract[PostCounterpartyJSON]
}
view <- NewStyle.function.checkViewAccessAndReturnView(viewId, BankIdAccountId(bankId, accountId), Some(u), callContext)

_ <- Helper.booleanToFuture(s"$NoViewPermission can_add_counterparty. Please use a view with that permission or add the permission to this view.", cc=callContext) {view.canAddCounterparty}

(counterparty, callContext) <- Connector.connector.vend.checkCounterpartyExists(postJson.name, bankId.value, accountId.value, viewId.value, callContext)

_ <- Helper.booleanToFuture(CounterpartyAlreadyExists.replace("value for BANK_ID or ACCOUNT_ID or VIEW_ID or NAME.",
s"COUNTERPARTY_NAME(${postJson.name}) for the BANK_ID(${bankId.value}) and ACCOUNT_ID(${accountId.value}) and VIEW_ID($viewId)"), cc=callContext){
counterparty.isEmpty
Expand All @@ -1223,10 +1223,23 @@ trait APIMethods220 {
} yield {
(account, callContext)
}
}
else
}else if (postJson.other_bank_routing_scheme.equalsIgnoreCase("ACCOUNT_NUMBER")|| postJson.other_bank_routing_scheme.equalsIgnoreCase("ACCOUNT_NO")) {
for {
bankIdOption <- Future.successful(if (postJson.other_bank_routing_address.isEmpty) None else Some(postJson.other_bank_routing_address))
(account, callContext) <- NewStyle.function.getBankAccountByNumber(
bankIdOption.map(BankId(_)),
postJson.other_bank_routing_address,
callContext)
} yield {
(account, callContext)
}
}else
Future{(Full(), Some(cc))}


otherAccountRoutingSchemeOBPFormat = if(postJson.other_account_routing_scheme.equalsIgnoreCase("AccountNo")) "ACCOUNT_NUMBER" else StringHelpers.snakify(postJson.other_account_routing_scheme).toUpperCase


(counterparty, callContext) <- NewStyle.function.createCounterparty(
name=postJson.name,
description=postJson.description,
Expand All @@ -1235,7 +1248,7 @@ trait APIMethods220 {
thisBankId=bankId.value,
thisAccountId=accountId.value,
thisViewId = viewId.value,
otherAccountRoutingScheme=postJson.other_account_routing_scheme,
otherAccountRoutingScheme=otherAccountRoutingSchemeOBPFormat,
otherAccountRoutingAddress=postJson.other_account_routing_address,
otherAccountSecondaryRoutingScheme=postJson.other_account_secondary_routing_scheme,
otherAccountSecondaryRoutingAddress=postJson.other_account_secondary_routing_address,
Expand Down
4 changes: 2 additions & 2 deletions obp-api/src/main/scala/code/api/v3_1_0/APIMethods310.scala
Original file line number Diff line number Diff line change
Expand Up @@ -5654,7 +5654,7 @@ trait APIMethods310 {
} else if (fromAccountPost.bank_id.isEmpty && fromAccountPost.account_id.isEmpty && fromAccountPost.counterparty_id.isDefined){
for {
(fromCounterparty, callContext) <- NewStyle.function.getCounterpartyByCounterpartyId(CounterpartyId(fromAccountPost.counterparty_id.get), cc.callContext)
fromAccount <- NewStyle.function.getBankAccountFromCounterparty(fromCounterparty, false, callContext)
(fromAccount, callContext) <- NewStyle.function.getBankAccountFromCounterparty(fromCounterparty, false, callContext)
}yield{
(fromAccount, callContext)
}
Expand All @@ -5674,7 +5674,7 @@ trait APIMethods310 {
} else if (toAccountPost.bank_id.isEmpty && toAccountPost.account_id.isEmpty && toAccountPost.counterparty_id.isDefined){
for {
(toCounterparty, callContext) <- NewStyle.function.getCounterpartyByCounterpartyId(CounterpartyId(toAccountPost.counterparty_id.get), cc.callContext)
toAccount <- NewStyle.function.getBankAccountFromCounterparty(toCounterparty, true, callContext)
(toAccount, callContext) <- NewStyle.function.getBankAccountFromCounterparty(toCounterparty, true, callContext)
}yield{
(toAccount, callContext)
}
Expand Down
Loading

0 comments on commit 40e06cd

Please sign in to comment.