Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/counterparty limit #2404

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion obp-api/src/main/scala/bootstrap/liftweb/Boot.scala
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ import code.connectormethod.ConnectorMethod
import code.consent.{ConsentRequest, MappedConsent}
import code.consumer.Consumers
import code.context.{MappedConsentAuthContext, MappedUserAuthContext, MappedUserAuthContextUpdate}
import code.counterpartylimit.CounterpartyLimit
import code.crm.MappedCrmEvent
import code.customer.internalMapping.MappedCustomerIdMapping
import code.customer.{MappedCustomer, MappedCustomerMessage}
Expand Down Expand Up @@ -1087,7 +1088,8 @@ object ToSchemify {
EndpointTag,
ProductFee,
ViewPermission,
UserInitAction
UserInitAction,
CounterpartyLimit
)

// start grpc server
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5396,6 +5396,27 @@ object SwaggerDefinitionsJSON {
phone = phoneExample.value,
)

val postCounterpartyLimitV510 = PostCounterpartyLimitV510(
max_single_amount = maxSingleAmountExample.value.toInt,
max_monthly_amount = maxMonthlyAmountExample.value.toInt,
max_number_of_monthly_transactions = maxNumberOfMonthlyTransactionsExample.value.toInt,
max_yearly_amount = maxYearlyAmountExample.value.toInt,
max_number_of_yearly_transactions = maxNumberOfYearlyTransactionsExample.value.toInt
)

val counterpartyLimitV510 = CounterpartyLimitV510(
counterparty_limit_id = counterpartyLimitIdExample.value,
bank_id = bankIdExample.value,
account_id = accountIdExample.value,
view_id = viewIdExample.value,
counterparty_id = counterpartyIdExample.value,
max_single_amount = maxSingleAmountExample.value.toInt,
max_monthly_amount = maxMonthlyAmountExample.value.toInt,
max_number_of_monthly_transactions = maxNumberOfMonthlyTransactionsExample.value.toInt,
max_yearly_amount = maxYearlyAmountExample.value.toInt,
max_number_of_yearly_transactions = maxNumberOfYearlyTransactionsExample.value.toInt
)

val atmsJsonV510 = AtmsJsonV510(
atms = List(atmJsonV510)
)
Expand Down
23 changes: 22 additions & 1 deletion obp-api/src/main/scala/code/api/util/APIUtil.scala
Original file line number Diff line number Diff line change
Expand Up @@ -1696,6 +1696,8 @@ object APIUtil extends MdcLoggable with CustomJsonFormats{
private val isNeedCheckView = errorResponseBodies.contains($UserNoPermissionAccessView) &&
requestUrlPartPath.contains("BANK_ID") && requestUrlPartPath.contains("ACCOUNT_ID") && requestUrlPartPath.contains("VIEW_ID")

private val isNeedCheckCounterparty = errorResponseBodies.contains($CounterpartyNotFoundByCounterpartyId) && requestUrlPartPath.contains("COUNTERPARTY_ID")

private val reversedRequestUrl = requestUrlPartPath.reverse
def getPathParams(url: List[String]): Map[String, String] =
reversedRequestUrl.zip(url.reverse) collect {
Expand Down Expand Up @@ -1775,6 +1777,14 @@ object APIUtil extends MdcLoggable with CustomJsonFormats{
Future.successful(null.asInstanceOf[View])
}
}

def checkCounterparty(counterpartyId: Option[CounterpartyId], callContext: Option[CallContext]): OBPReturnType[CounterpartyTrait] = {
if(isNeedCheckCounterparty && counterpartyId.isDefined) {
checkCounterpartyFun(counterpartyId.get)(callContext)
} else {
Future.successful(null.asInstanceOf[CounterpartyTrait] -> callContext)
}
}
// reset connectorMethods
{
val checkerFunctions = mutable.ListBuffer[PartialFunction[_, _]]()
Expand All @@ -1795,6 +1805,9 @@ object APIUtil extends MdcLoggable with CustomJsonFormats{
if (isNeedCheckView) {
checkerFunctions += checkViewFun
}
if (isNeedCheckCounterparty) {
checkerFunctions += checkCounterpartyFun
}
val addedMethods: List[String] = checkerFunctions.toList.flatMap(getDependentConnectorMethods(_))
.map(value =>("obp." +value).intern())

Expand Down Expand Up @@ -1841,6 +1854,7 @@ object APIUtil extends MdcLoggable with CustomJsonFormats{
val bankId = pathParams.get("BANK_ID").map(BankId(_))
val accountId = pathParams.get("ACCOUNT_ID").map(AccountId(_))
val viewId = pathParams.get("VIEW_ID").map(ViewId(_))
val counterpartyId = pathParams.get("COUNTERPARTY_ID").map(CounterpartyId(_))

val request: Box[Req] = S.request
val session: Box[LiftSession] = S.session
Expand All @@ -1851,7 +1865,8 @@ object APIUtil extends MdcLoggable with CustomJsonFormats{
* 2. check bankId
* 3. roles check
* 4. check accountId
* 5. view
* 5. view access
* 6. check counterpartyId
*
* A Bank MUST be checked before Roles.
* In opposite case we get next paradox:
Expand All @@ -1878,6 +1893,9 @@ object APIUtil extends MdcLoggable with CustomJsonFormats{

// check user access permission of this viewId corresponding view
view <- checkView(viewId, bankId, accountId, boxUser, callContext)

counterparty <- checkCounterparty(counterpartyId, callContext)

} yield {
val newCallContext = if(boxUser.isDefined) callContext.map(_.copy(user=boxUser)) else callContext

Expand Down Expand Up @@ -4232,6 +4250,9 @@ object APIUtil extends MdcLoggable with CustomJsonFormats{
private val checkViewFun: PartialFunction[ViewId, (BankIdAccountId, Option[User], Option[CallContext]) => Future[View]] = {
case x => NewStyle.function.checkViewAccessAndReturnView(x, _, _, _)
}
private val checkCounterpartyFun: PartialFunction[CounterpartyId, Option[CallContext] => OBPReturnType[CounterpartyTrait]] = {
case x => NewStyle.function.getCounterpartyByCounterpartyId(x, _)
}

// cache for method -> called obp methods:
// (className, methodName, signature) -> List[(className, methodName, signature)]
Expand Down
1 change: 1 addition & 0 deletions obp-api/src/main/scala/code/api/util/ApiTag.scala
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ object ApiTag {
val apiTagWebUiProps = ResourceDocTag("WebUi-Props")
val apiTagEndpointMapping = ResourceDocTag("Endpoint-Mapping")
val apiTagRateLimits = ResourceDocTag("Rate-Limits")
val apiTagCounterpartyLimits = ResourceDocTag("Counterparty-Limits")

val apiTagApiCollection = ResourceDocTag("Api-Collection")

Expand Down
10 changes: 10 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 @@ -506,6 +506,11 @@ object ErrorMessages {
val SystemViewCannotBePublicError = "OBP-30258: System view cannot be public"
val CreateCustomViewError = "OBP-30259: Could not create the custom view"
val UpdateCustomViewError = "OBP-30260: Could not update the custom view"
val CreateCounterpartyLimitError = "OBP-30261: Could not create the counterparty limit."
val UpdateCounterpartyLimitError = "OBP-30262: Could not update the counterparty limit."
val GetCounterpartyLimitError = "OBP-30263: Counterparty limit not found. Please specify a valid value for BANK_ID, ACCOUNT_ID, VIEW_ID or COUNTERPARTY_ID."
val CounterpartyLimitAlreadyExists = "OBP-30264: Counterparty limit already exists. Please specify a different value for BANK_ID, ACCOUNT_ID, VIEW_ID or COUNTERPARTY_ID."
val DeleteCounterpartyLimitError = "OBP-30265: Could not delete the counterparty limit."

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 Expand Up @@ -848,6 +853,11 @@ object ErrorMessages {
* validate method: NewStyle.function.checkViewAccessAndReturnView
*/
def $UserNoPermissionAccessView = UserNoPermissionAccessView

/**
* validate method: NewStyle.function.getCounterpartyByCounterpartyId
*/
def $CounterpartyNotFoundByCounterpartyId = CounterpartyNotFoundByCounterpartyId


def getDuplicatedMessageNumbers = {
Expand Down
18 changes: 18 additions & 0 deletions obp-api/src/main/scala/code/api/util/ExampleValue.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2147,6 +2147,24 @@ object ExampleValue {
lazy val transactionRequestTypesExample = ConnectorField(NoExampleProvided,NoDescriptionProvided)
glossaryItems += makeGlossaryItem("transaction_request_types", transactionRequestTypesExample)

lazy val counterpartyLimitIdExample = ConnectorField("abc9a7e4-6d02-40e3-a129-0b2bf89de9b1","A string that MUST uniquely identify the Counterparty Limit on this OBP instance.")
glossaryItems += makeGlossaryItem("counterparty_limit_id", counterpartyLimitIdExample)

lazy val maxSingleAmountExample = ConnectorField("1000",NoDescriptionProvided)
glossaryItems += makeGlossaryItem("max_single_amount", maxSingleAmountExample)

lazy val maxMonthlyAmountExample = ConnectorField("10000",NoDescriptionProvided)
glossaryItems += makeGlossaryItem("max_monthly_amount", maxMonthlyAmountExample)

lazy val maxNumberOfMonthlyTransactionsExample = ConnectorField("10",NoDescriptionProvided)
glossaryItems += makeGlossaryItem("max_number_of_monthly_transactions", maxNumberOfMonthlyTransactionsExample)

lazy val maxYearlyAmountExample = ConnectorField("12000",NoDescriptionProvided)
glossaryItems += makeGlossaryItem("max_yearly_amount", maxYearlyAmountExample)

lazy val maxNumberOfYearlyTransactionsExample = ConnectorField("100",NoDescriptionProvided)
glossaryItems += makeGlossaryItem("max_number_of_yearly_transactions", maxNumberOfYearlyTransactionsExample)

lazy val canAddImageUrlExample = ConnectorField(booleanTrue,NoDescriptionProvided)
glossaryItems += makeGlossaryItem("can_add_image_url", canAddImageUrlExample)

Expand Down
65 changes: 63 additions & 2 deletions obp-api/src/main/scala/code/api/util/NewStyle.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package code.api.util

import java.util.Date
import java.util.UUID.randomUUID

import akka.http.scaladsl.model.HttpMethod
import code.DynamicEndpoint.{DynamicEndpointProvider, DynamicEndpointT}
import code.api.{APIFailureNewStyle, Constant, JsonResponseException}
Expand Down Expand Up @@ -54,8 +53,8 @@ import net.liftweb.json.JsonDSL._
import net.liftweb.json.{JField, JInt, JNothing, JNull, JObject, JString, JValue, _}
import net.liftweb.util.Helpers.tryo
import org.apache.commons.lang3.StringUtils
import java.security.AccessControlException

import java.security.AccessControlException
import scala.collection.immutable.{List, Nil}
import scala.concurrent.Future
import scala.math.BigDecimal
Expand All @@ -71,6 +70,7 @@ import code.api.dynamic.entity.helper.{DynamicEntityHelper, DynamicEntityInfo}
import code.atmattribute.AtmAttribute
import code.bankattribute.BankAttribute
import code.connectormethod.{ConnectorMethodProvider, JsonConnectorMethod}
import code.counterpartylimit.{CounterpartyLimit, CounterpartyLimitTrait}
import code.crm.CrmEvent
import code.crm.CrmEvent.CrmEvent
import code.customeraccountlinks.CustomerAccountLinkTrait
Expand Down Expand Up @@ -4056,6 +4056,67 @@ object NewStyle extends MdcLoggable{
(unboxFullOrFail(i, callContext, s"$DeleteCustomViewError"), callContext)
}

def createOrUpdateCounterpartyLimit(
bankId: String,
accountId: String,
viewId: String,
counterpartyId: String,
maxSingleAmount: Int,
maxMonthlyAmount: Int,
maxNumberOfMonthlyTransactions: Int,
maxYearlyAmount: Int,
maxNumberOfYearlyTransactions: Int,
callContext: Option[CallContext]
): OBPReturnType[CounterpartyLimitTrait] =
Connector.connector.vend.createOrUpdateCounterpartyLimit(
bankId: String,
accountId: String,
viewId: String,
counterpartyId: String,
maxSingleAmount: Int,
maxMonthlyAmount: Int,
maxNumberOfMonthlyTransactions: Int,
maxYearlyAmount: Int,
maxNumberOfYearlyTransactions: Int,
callContext: Option[CallContext]
) map {
i => (unboxFullOrFail(i._1, callContext, CreateCounterpartyLimitError), i._2)
}

def getCounterpartyLimit(
bankId: String,
accountId: String,
viewId: String,
counterpartyId: String,
callContext: Option[CallContext]
): OBPReturnType[CounterpartyLimitTrait] =
Connector.connector.vend.getCounterpartyLimit(
bankId: String,
accountId: String,
viewId: String,
counterpartyId: String,
callContext: Option[CallContext]
) map {
i => (unboxFullOrFail(i._1, callContext, s"$GetCounterpartyLimitError Current BANK_ID($bankId), " +
s"ACCOUNT_ID($accountId), VIEW_ID($viewId),COUNTERPARTY_ID($counterpartyId)"), i._2)
}

def deleteCounterpartyLimit(
bankId: String,
accountId: String,
viewId: String,
counterpartyId: String,
callContext: Option[CallContext]
): OBPReturnType[Boolean] =
Connector.connector.vend.deleteCounterpartyLimit(
bankId: String,
accountId: String,
viewId: String,
counterpartyId: String,
callContext: Option[CallContext]
) map {
i => (unboxFullOrFail(i._1, callContext, s"$DeleteCounterpartyLimitError"), i._2)
}
}

}
3 changes: 2 additions & 1 deletion obp-api/src/main/scala/code/api/v1_2_1/APIMethods121.scala
Original file line number Diff line number Diff line change
Expand Up @@ -645,7 +645,8 @@ trait APIMethods121 {
),
List(apiTagAccount, apiTagView, apiTagOldStyle)
)


//TODO. remove and replace it with V510.
lazy val updateViewForBankAccount: OBPEndpoint = {
//updates a view on a bank account
case "banks" :: BankId(bankId) :: "accounts" :: AccountId(accountId
Expand Down
1 change: 1 addition & 0 deletions obp-api/src/main/scala/code/api/v3_0_0/APIMethods300.scala
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,7 @@ trait APIMethods300 {
),
List(apiTagView, apiTagAccount))

//TODO. remove and replace it with V510.
lazy val createViewForBankAccount : OBPEndpoint = {
//creates a view on an bank account
case "banks" :: BankId(bankId) :: "accounts" :: AccountId(accountId) :: "views" :: Nil JsonPost json -> _ => {
Expand Down
Loading
Loading