diff --git a/obp-api/src/main/scala/bootstrap/liftweb/Boot.scala b/obp-api/src/main/scala/bootstrap/liftweb/Boot.scala index 1de144150..6782f3deb 100644 --- a/obp-api/src/main/scala/bootstrap/liftweb/Boot.scala +++ b/obp-api/src/main/scala/bootstrap/liftweb/Boot.scala @@ -26,9 +26,6 @@ TESOBE (http://www.tesobe.com/) */ package bootstrap.liftweb -import java.io.{File, FileInputStream} -import java.util.stream.Collectors -import java.util.{Locale, TimeZone} import code.CustomerDependants.MappedCustomerDependant import code.DynamicData.DynamicData import code.DynamicEndpoint.DynamicEndpoint @@ -43,8 +40,8 @@ import code.api.ResourceDocs1_4_0._ import code.api._ import code.api.attributedefinition.AttributeDefinition import code.api.cache.Redis +import code.api.util.APIUtil.{enableVersionIfAllowed, errorJsonResponse, getPropsValue} import code.api.util.ApiRole.CanCreateEntitlementAtAnyBank -import code.api.util.APIUtil.{enableVersionIfAllowed, errorJsonResponse, getPropsValue, gitCommit} import code.api.util._ import code.api.util.migration.Migration import code.api.util.migration.Migration.DbFunction @@ -53,11 +50,10 @@ import code.apicollectionendpoint.ApiCollectionEndpoint import code.atmattribute.AtmAttribute import code.atms.MappedAtm import code.authtypevalidation.AuthenticationTypeValidation +import code.bankaccountbalance.BankAccountBalance import code.bankattribute.BankAttribute -import code.bankconnectors.storedprocedure.StoredProceduresMockedData import code.bankconnectors.{Connector, ConnectorEndpoints} import code.branches.MappedBranch -import code.etag.MappedETag import code.cardattribute.MappedCardAttribute import code.cards.{MappedPhysicalCard, PinReset} import code.connectormethod.ConnectorMethod @@ -79,6 +75,7 @@ import code.endpointMapping.EndpointMapping import code.endpointTag.EndpointTag import code.entitlement.{Entitlement, MappedEntitlement} import code.entitlementrequest.MappedEntitlementRequest +import code.etag.MappedETag import code.fx.{MappedCurrency, MappedFXRate} import code.kycchecks.MappedKycCheck import code.kycdocuments.MappedKycDocument @@ -96,9 +93,9 @@ import code.metadata.wheretags.MappedWhereTag import code.methodrouting.MethodRouting import code.metrics.{MappedConnectorMetric, MappedMetric, MetricArchive} import code.migration.MigrationScriptLog +import code.model._ import code.model.dataAccess._ import code.model.dataAccess.internalMapping.AccountIdMapping -import code.model._ import code.obp.grpc.HelloWorldServer import code.productAttributeattribute.MappedProductAttribute import code.productcollection.MappedProductCollection @@ -107,10 +104,11 @@ import code.productfee.ProductFee import code.products.MappedProduct import code.ratelimiting.RateLimiting import code.regulatedentities.MappedRegulatedEntity -import code.scheduler.{ConsentScheduler, DataBaseCleanerScheduler, DatabaseDriverScheduler, JobScheduler, MetricsArchiveScheduler, TransactionScheduler} +import code.regulatedentities.attribute.RegulatedEntityAttribute +import code.scheduler._ import code.scope.{MappedScope, MappedUserScope} import code.signingbaskets.{MappedSigningBasket, MappedSigningBasketConsent, MappedSigningBasketPayment} -import code.snippet.{OAuthAuthorisation, OAuthWorkedThanks} +import code.snippet.OAuthWorkedThanks import code.socialmedia.MappedSocialMedia import code.standingorders.StandingOrder import code.taxresidence.MappedTaxResidence @@ -133,17 +131,13 @@ import code.views.Views import code.views.system.{AccountAccess, ViewDefinition, ViewPermission} import code.webhook.{BankAccountNotificationWebhook, MappedAccountWebhook, SystemAccountNotificationWebhook} import code.webuiprops.WebUiProps -import code.regulatedentities.attribute.RegulatedEntityAttribute import com.openbankproject.commons.model.ErrorMessage import com.openbankproject.commons.util.Functions.Implicits._ import com.openbankproject.commons.util.{ApiVersion, Functions} -import code.bankaccountbalance.BankAccountBalance -import javax.mail.internet.MimeMessage import net.liftweb.common._ import net.liftweb.db.{DB, DBLogEntry} import net.liftweb.http.LiftRules.DispatchPF import net.liftweb.http._ -import net.liftweb.http.provider.HTTPCookie import net.liftweb.json.Extraction import net.liftweb.mapper.{DefaultConnectionIdentifier => _, _} import net.liftweb.sitemap.Loc._ @@ -152,7 +146,11 @@ import net.liftweb.util.Helpers._ import net.liftweb.util._ import org.apache.commons.io.FileUtils -import scala.concurrent.{ExecutionContext, Future} +import java.io.{File, FileInputStream} +import java.util.stream.Collectors +import java.util.{Locale, TimeZone} +import javax.mail.internet.MimeMessage +import scala.concurrent.ExecutionContext /** * A class that's instantiated early and run. It allows the application @@ -1010,6 +1008,8 @@ class Boot extends MdcLoggable { } } + + LiftRules.statelessDispatch.append(aliveCheck) } diff --git a/obp-api/src/main/scala/code/api/aliveCheck.scala b/obp-api/src/main/scala/code/api/aliveCheck.scala new file mode 100644 index 000000000..dadd4e0a5 --- /dev/null +++ b/obp-api/src/main/scala/code/api/aliveCheck.scala @@ -0,0 +1,40 @@ +/** +Open Bank Project - API +Copyright (C) 2011-2019, TESOBE GmbH + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU Affero General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Affero General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program. If not, see . + +Email: contact@tesobe.com +TESOBE GmbH. +Osloer Strasse 16/17 +Berlin 13359, Germany + +This product includes software developed at +TESOBE (http://www.tesobe.com/) + + */ +package code.api + +import code.util.Helper.MdcLoggable +import net.liftweb.http._ +import net.liftweb.http.rest.RestHelper +import net.liftweb.json.Extraction + + +object aliveCheck extends RestHelper with MdcLoggable { + serve { + case Req("alive" :: Nil, _, GetRequest) => + JsonResponse(Extraction.decompose(true), Nil, Nil, 200) + } +} diff --git a/obp-api/src/main/scala/code/api/berlin/group/v1_3/AccountInformationServiceAISApi.scala b/obp-api/src/main/scala/code/api/berlin/group/v1_3/AccountInformationServiceAISApi.scala index 287327ac8..755fd4d28 100644 --- a/obp-api/src/main/scala/code/api/berlin/group/v1_3/AccountInformationServiceAISApi.scala +++ b/obp-api/src/main/scala/code/api/berlin/group/v1_3/AccountInformationServiceAISApi.scala @@ -343,13 +343,19 @@ of the PSU at this ASPSP. attribute.value.equalsIgnoreCase("card") ).isEmpty) + (balances, callContext) <- JSONFactory_BERLIN_GROUP_1_3.flattenOBPReturnType(bankAccountsFiltered.map(bankAccont => code.api.util.newstyle.BankAccountBalanceNewStyle.getBankAccountBalances( + bankAccont.accountId, + callContext + ))) + } yield { (JSONFactory_BERLIN_GROUP_1_3.createAccountListJson( bankAccountsFiltered, canReadBalancesAccounts, canReadTransactionsAccounts, u, - withBalanceParam + withBalanceParam, + balances ), callContext) } } diff --git a/obp-api/src/main/scala/code/api/berlin/group/v1_3/JSONFactory_BERLIN_GROUP_1_3.scala b/obp-api/src/main/scala/code/api/berlin/group/v1_3/JSONFactory_BERLIN_GROUP_1_3.scala index 4204834e1..8924d05ca 100644 --- a/obp-api/src/main/scala/code/api/berlin/group/v1_3/JSONFactory_BERLIN_GROUP_1_3.scala +++ b/obp-api/src/main/scala/code/api/berlin/group/v1_3/JSONFactory_BERLIN_GROUP_1_3.scala @@ -17,7 +17,8 @@ import net.liftweb.json.{JValue, parse} import java.text.SimpleDateFormat import java.util.Date - +import scala.concurrent.Future +import com.openbankproject.commons.ExecutionContext.Implicits.global case class JvalueCaseClass(jvalueToCaseclass: JValue) object JSONFactory_BERLIN_GROUP_1_3 extends CustomJsonFormats with MdcLoggable{ @@ -310,13 +311,24 @@ object JSONFactory_BERLIN_GROUP_1_3 extends CustomJsonFormats with MdcLoggable{ case class UpdatePaymentPsuDataJson( scaAuthenticationData: String ) - + + + def flattenOBPReturnType( + list: List[OBPReturnType[List[BankAccountBalanceTrait]]] + ): OBPReturnType[List[BankAccountBalanceTrait]] = { + Future.sequence(list).map { results => + val combinedBalances = results.flatMap(_._1) // Combine all balances + val callContext = results.headOption.flatMap(_._2) // Use the first CallContext + (combinedBalances, callContext) + } + } def createAccountListJson(bankAccounts: List[BankAccount], canReadBalancesAccounts: List[BankIdAccountId], canReadTransactionsAccounts: List[BankIdAccountId], user: User, - withBalanceParam:Option[Boolean] + withBalanceParam:Option[Boolean], + balances: List[BankAccountBalanceTrait] ): CoreAccountsJsonV13 = { CoreAccountsJsonV13(bankAccounts.map { x => @@ -327,9 +339,9 @@ object JSONFactory_BERLIN_GROUP_1_3 extends CustomJsonFormats with MdcLoggable{ val transactionRef = LinkHrefJson(s"/$commonPath/transactions") val canReadTransactions = canReadTransactionsAccounts.map(_.accountId.value).contains(x.accountId.value) val accountBalances = if(withBalanceParam == Some(true)){ - Some(List(CoreAccountBalanceJson( - balanceAmount = AmountOfMoneyV13(x.currency, x.balance.toString), - balanceType = "openingBooked"))) + Some(balances.filter(_.accountId.equals(x.accountId)).map(balance =>(List(CoreAccountBalanceJson( + balanceAmount = AmountOfMoneyV13(x.currency, balance.balanceAmount.toString()), + balanceType = balance.balanceType)))).flatten) }else{ None } diff --git a/obp-api/src/main/scala/code/bankconnectors/generator/ConnectorBuilderUtil.scala b/obp-api/src/main/scala/code/bankconnectors/generator/ConnectorBuilderUtil.scala index 8c58ecc38..f518a7bb4 100644 --- a/obp-api/src/main/scala/code/bankconnectors/generator/ConnectorBuilderUtil.scala +++ b/obp-api/src/main/scala/code/bankconnectors/generator/ConnectorBuilderUtil.scala @@ -2,7 +2,7 @@ package code.bankconnectors.generator import code.api.util.CodeGenerateUtils.createDocExample import code.api.util.{APIUtil, CallContext} -import code.bankconnectors.{Connector, LocalMappedConnector} +import code.bankconnectors.Connector import com.openbankproject.commons.util.ReflectUtils import org.apache.commons.io.FileUtils import org.apache.commons.lang3.StringUtils.uncapitalize @@ -437,6 +437,10 @@ object ConnectorBuilderUtil { "getAccountsHeldByUser", "getRegulatedEntities", "getRegulatedEntityByEntityId", + "getBankAccountBalancesByAccountId", + "getBankAccountBalanceById", + "createOrUpdateBankAccountBalance", + "deleteBankAccountBalance", ).distinct /** diff --git a/obp-api/src/main/scala/code/bankconnectors/rabbitmq/RabbitMQConnector_vOct2024.scala b/obp-api/src/main/scala/code/bankconnectors/rabbitmq/RabbitMQConnector_vOct2024.scala index ea08ff63c..30472e31a 100644 --- a/obp-api/src/main/scala/code/bankconnectors/rabbitmq/RabbitMQConnector_vOct2024.scala +++ b/obp-api/src/main/scala/code/bankconnectors/rabbitmq/RabbitMQConnector_vOct2024.scala @@ -23,7 +23,6 @@ Osloerstrasse 16/17 Berlin 13359, Germany */ -import java.util.Date import code.api.ResourceDocs1_4_0.MessageDocsSwaggerDefinitions import code.api.util.APIUtil.{AdapterImplementation, MessageDoc, OBPReturnType, _} import code.api.util.ErrorMessages._ @@ -33,15 +32,15 @@ import code.bankconnectors._ import code.util.Helper import code.util.Helper.MdcLoggable import com.openbankproject.commons.ExecutionContext.Implicits.global -import com.openbankproject.commons.dto.{InBoundTrait, _} +import com.openbankproject.commons.dto._ import com.openbankproject.commons.model.enums.StrongCustomerAuthenticationStatus.SCAStatus import com.openbankproject.commons.model.enums._ -import com.openbankproject.commons.model.{TopicTrait, RegulatedEntityAttributeSimple, _} -import com.openbankproject.commons.util.ReflectUtils -import net.liftweb.common.{Box, _} +import com.openbankproject.commons.model.{Meta, _} +import net.liftweb.common._ import net.liftweb.json._ import net.liftweb.util.StringHelpers +import java.util.Date import scala.collection.mutable.ArrayBuffer import scala.concurrent.Future import scala.language.postfixOps @@ -68,7 +67,7 @@ trait RabbitMQConnector_vOct2024 extends Connector with MdcLoggable { val errorCodeExample = "INTERNAL-OBP-ADAPTER-6001: ..." //---------------- dynamic start -------------------please don't modify this line -// ---------- created on 2025-04-04T14:01:22Z +// ---------- created on 2025-05-22T11:32:05Z messageDocs += getAdapterInfoDoc def getAdapterInfoDoc = MessageDoc( @@ -1073,7 +1072,7 @@ trait RabbitMQConnector_vOct2024 extends Connector with MdcLoggable { address=accountRoutingAddressExample.value)), balances=List( BankAccountBalance(balance= AmountOfMoney(currency=balanceCurrencyExample.value, amount=balanceAmountExample.value), - balanceType="string")), + balanceType=balanceTypeExample.value)), overallBalance= AmountOfMoney(currency=currencyExample.value, amount=amountExample.value), overallBalanceDate=toDate(overallBalanceDateExample))) @@ -3701,7 +3700,7 @@ trait RabbitMQConnector_vOct2024 extends Connector with MdcLoggable { moreInfo=Some(moreInfoExample.value), hasDepositCapability=Some(hasDepositCapabilityExample.value.toBoolean), supportedLanguages=Some(supportedLanguagesExample.value.replace("[","").replace("]","").split(",").toList), - services=Some(listExample.value.replace("[","").replace("]","").split(",").toList), + services=Some(servicesExample.value.replace("[","").replace("]","").split(",").toList), accessibilityFeatures=Some(accessibilityFeaturesExample.value.replace("[","").replace("]","").split(",").toList), supportedCurrencies=Some(supportedCurrenciesExample.value.replace("[","").replace("]","").split(",").toList), notes=Some(listExample.value.replace("[","").replace("]","").split(",").toList), @@ -3782,7 +3781,7 @@ trait RabbitMQConnector_vOct2024 extends Connector with MdcLoggable { moreInfo=Some(moreInfoExample.value), hasDepositCapability=Some(hasDepositCapabilityExample.value.toBoolean), supportedLanguages=Some(supportedLanguagesExample.value.replace("[","").replace("]","").split(",").toList), - services=Some(listExample.value.replace("[","").replace("]","").split(",").toList), + services=Some(servicesExample.value.replace("[","").replace("]","").split(",").toList), accessibilityFeatures=Some(accessibilityFeaturesExample.value.replace("[","").replace("]","").split(",").toList), supportedCurrencies=Some(supportedCurrenciesExample.value.replace("[","").replace("]","").split(",").toList), notes=Some(listExample.value.replace("[","").replace("]","").split(",").toList), @@ -7081,32 +7080,21 @@ trait RabbitMQConnector_vOct2024 extends Connector with MdcLoggable { exampleInboundMessage = ( InBoundGetRegulatedEntities(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, status=MessageDocsSwaggerDefinitions.inboundStatus, - data=List(RegulatedEntityTraitCommons(entityId = "0af807d7-3c39-43ef-9712-82bcfde1b9ca", - certificateAuthorityCaOwnerId = "CY_CBC", - entityName = "EXAMPLE COMPANY LTD", - entityCode = "PSD_PICY_CBC!12345", - entityCertificatePublicKey = - """-----BEGIN CERTIFICATE-----MIICsjCCAZqgAwIBAgIGAYwQ62R0MA0GCSqGSIb3DQEBCwUAMBoxGDAWBgNVBAMMD2 - |FwcC5leGFtcGxlLmNvbTAeFw0yMzExMjcxMzE1MTFaFw0yNTExMjYxMzE1MTFaMBoxGDAWBgNVBAMMD2FwcC5leGFtcGxlLmNvbTCCASIwDQ - |YJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAK9WIodZHWzKyCcf9YfWEhPURbfO6zKuMqzHN27GdqHsVVEGxP4F/J4mso+0ENcRr6ur4u81iRE - |aVdCc40rHDHVJNEtniD8Icbz7tcsqAewIVhc/q6WXGqImJpCq7hA0m247dDsaZT0lb/MVBiMoJxDEmAE/GYYnWTEn84R35WhJsMvuQ7QmLvNg6 - |RkChY6POCT/YKe9NKwa1NqI1U+oA5RFzAaFtytvZCE3jtp+aR0brL7qaGfgxm6B7dEpGyhg0NcVCV7xMQNq2JxZTVdAr6lcsRGaAFulakmW3aN - |nmK+L35Wu8uW+OxNxwUuC6f3b4FVBa276FMuUTRfu7gc+k6kCAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAAU5CjEyAoyTn7PgFpQD48ZNPuUsEQ - |19gzYgJvHMzFIoZ7jKBodjO5mCzWBcR7A4mpeAsdyiNBl2sTiZscSnNqxk61jVzP5Ba1D7XtOjjr7+3iqowrThj6BY40QqhYh/6BSY9fDzVZQi - |Hnvlo6ZUM5kUK6OavZOovKlp5DIl5sGqoP0qAJnpQ4nhB2WVVsKfPlOXc+2KSsbJ23g9l8zaTMr+X0umlvfEKqyEl1Fa2L1dO0y/KFQ+ILmxcZ - |LpRdq1hRAjd0quq9qGC8ucXhRWDgM4hslVpau0da68g0aItWNez3mc5lB82b3dcZpFMzO41bgw7gvw10AvvTfQDqEYIuQ==-----END CERTIFICATE----- """.stripMargin, - entityType = "PSD_PI", - entityAddress = "EXAMPLE COMPANY LTD, 5 SOME STREET", - entityTownCity = "SOME CITY", - entityPostCode = "1060", - entityCountry = "CY", - entityWebSite = "www.example.com", - services = """[{"CY":["PS_010","PS_020","PS_03C","PS_04C"]}]""", - attributes = Some(List(RegulatedEntityAttributeSimple( - attributeType=attributeTypeExample.value, - name=attributeNameExample.value, - value=attributeValueExample.value) - ))))) + data=List( RegulatedEntityTraitCommons(entityId=entityIdExample.value, + certificateAuthorityCaOwnerId=certificateAuthorityCaOwnerIdExample.value, + entityName=entityNameExample.value, + entityCode=entityCodeExample.value, + entityCertificatePublicKey=entityCertificatePublicKeyExample.value, + entityType=entityTypeExample.value, + entityAddress=entityAddressExample.value, + entityTownCity=entityTownCityExample.value, + entityPostCode=entityPostCodeExample.value, + entityCountry=entityCountryExample.value, + entityWebSite=entityWebSiteExample.value, + services=servicesExample.value, + attributes=Some(List( RegulatedEntityAttributeSimple(attributeType=attributeTypeExample.value, + name=nameExample.value, + value=valueExample.value)))))) ), adapterImplementation = Some(AdapterImplementation("- Core", 1)) ) @@ -7132,32 +7120,21 @@ trait RabbitMQConnector_vOct2024 extends Connector with MdcLoggable { exampleInboundMessage = ( InBoundGetRegulatedEntityByEntityId(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, status=MessageDocsSwaggerDefinitions.inboundStatus, - data= RegulatedEntityTraitCommons(entityId = "0af807d7-3c39-43ef-9712-82bcfde1b9ca", - certificateAuthorityCaOwnerId = "CY_CBC", - entityName = "EXAMPLE COMPANY LTD", - entityCode = "PSD_PICY_CBC!12345", - entityCertificatePublicKey = - """-----BEGIN CERTIFICATE-----MIICsjCCAZqgAwIBAgIGAYwQ62R0MA0GCSqGSIb3DQEBCwUAMBoxGDAWBgNVBAMMD2 - |FwcC5leGFtcGxlLmNvbTAeFw0yMzExMjcxMzE1MTFaFw0yNTExMjYxMzE1MTFaMBoxGDAWBgNVBAMMD2FwcC5leGFtcGxlLmNvbTCCASIwDQ - |YJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAK9WIodZHWzKyCcf9YfWEhPURbfO6zKuMqzHN27GdqHsVVEGxP4F/J4mso+0ENcRr6ur4u81iRE - |aVdCc40rHDHVJNEtniD8Icbz7tcsqAewIVhc/q6WXGqImJpCq7hA0m247dDsaZT0lb/MVBiMoJxDEmAE/GYYnWTEn84R35WhJsMvuQ7QmLvNg6 - |RkChY6POCT/YKe9NKwa1NqI1U+oA5RFzAaFtytvZCE3jtp+aR0brL7qaGfgxm6B7dEpGyhg0NcVCV7xMQNq2JxZTVdAr6lcsRGaAFulakmW3aN - |nmK+L35Wu8uW+OxNxwUuC6f3b4FVBa276FMuUTRfu7gc+k6kCAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAAU5CjEyAoyTn7PgFpQD48ZNPuUsEQ - |19gzYgJvHMzFIoZ7jKBodjO5mCzWBcR7A4mpeAsdyiNBl2sTiZscSnNqxk61jVzP5Ba1D7XtOjjr7+3iqowrThj6BY40QqhYh/6BSY9fDzVZQi - |Hnvlo6ZUM5kUK6OavZOovKlp5DIl5sGqoP0qAJnpQ4nhB2WVVsKfPlOXc+2KSsbJ23g9l8zaTMr+X0umlvfEKqyEl1Fa2L1dO0y/KFQ+ILmxcZ - |LpRdq1hRAjd0quq9qGC8ucXhRWDgM4hslVpau0da68g0aItWNez3mc5lB82b3dcZpFMzO41bgw7gvw10AvvTfQDqEYIuQ==-----END CERTIFICATE----- """.stripMargin, - entityType = "PSD_PI", - entityAddress = "EXAMPLE COMPANY LTD, 5 SOME STREET", - entityTownCity = "SOME CITY", - entityPostCode = "1060", - entityCountry = "CY", - entityWebSite = "www.example.com", - services = """[{"CY":["PS_010","PS_020","PS_03C","PS_04C"]}]""", - attributes = Some(List(RegulatedEntityAttributeSimple( - attributeType=attributeTypeExample.value, - name=attributeNameExample.value, - value=attributeValueExample.value) - )))) + data= RegulatedEntityTraitCommons(entityId=entityIdExample.value, + certificateAuthorityCaOwnerId=certificateAuthorityCaOwnerIdExample.value, + entityName=entityNameExample.value, + entityCode=entityCodeExample.value, + entityCertificatePublicKey=entityCertificatePublicKeyExample.value, + entityType=entityTypeExample.value, + entityAddress=entityAddressExample.value, + entityTownCity=entityTownCityExample.value, + entityPostCode=entityPostCodeExample.value, + entityCountry=entityCountryExample.value, + entityWebSite=entityWebSiteExample.value, + services=servicesExample.value, + attributes=Some(List( RegulatedEntityAttributeSimple(attributeType=attributeTypeExample.value, + name=nameExample.value, + value=valueExample.value))))) ), adapterImplementation = Some(AdapterImplementation("- Core", 1)) ) @@ -7169,8 +7146,128 @@ trait RabbitMQConnector_vOct2024 extends Connector with MdcLoggable { response.map(convertToTuple[RegulatedEntityTraitCommons](callContext)) } -// ---------- created on 2025-04-04T14:01:22Z -//---------------- dynamic end ---------------------please don't modify this line + messageDocs += getBankAccountBalancesByAccountIdDoc + def getBankAccountBalancesByAccountIdDoc = MessageDoc( + process = "obp.getBankAccountBalancesByAccountId", + messageFormat = messageFormat, + description = "Get Bank Account Balances By Account Id", + outboundTopic = None, + inboundTopic = None, + exampleOutboundMessage = ( + OutBoundGetBankAccountBalancesByAccountId(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, + accountId=AccountId(accountIdExample.value)) + ), + exampleInboundMessage = ( + InBoundGetBankAccountBalancesByAccountId(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, + status=MessageDocsSwaggerDefinitions.inboundStatus, + data=List( BankAccountBalanceTraitCommons(bankId=BankId(bankIdExample.value), + accountId=AccountId(accountIdExample.value), + balanceId=BalanceId(balanceIdExample.value), + balanceType=balanceTypeExample.value, + balanceAmount=BigDecimal(balanceAmountExample.value)))) + ), + adapterImplementation = Some(AdapterImplementation("- Core", 1)) + ) + + override def getBankAccountBalancesByAccountId(accountId: AccountId, callContext: Option[CallContext]): OBPReturnType[Box[List[BankAccountBalanceTrait]]] = { + import com.openbankproject.commons.dto.{InBoundGetBankAccountBalancesByAccountId => InBound, OutBoundGetBankAccountBalancesByAccountId => OutBound} + val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, accountId) + val response: Future[Box[InBound]] = sendRequest[InBound]("obp_get_bank_account_balances_by_account_id", req, callContext) + response.map(convertToTuple[List[BankAccountBalanceTraitCommons]](callContext)) + } + + messageDocs += getBankAccountBalanceByIdDoc + def getBankAccountBalanceByIdDoc = MessageDoc( + process = "obp.getBankAccountBalanceById", + messageFormat = messageFormat, + description = "Get Bank Account Balance By Id", + outboundTopic = None, + inboundTopic = None, + exampleOutboundMessage = ( + OutBoundGetBankAccountBalanceById(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, + balanceId=BalanceId(balanceIdExample.value)) + ), + exampleInboundMessage = ( + InBoundGetBankAccountBalanceById(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, + status=MessageDocsSwaggerDefinitions.inboundStatus, + data= BankAccountBalanceTraitCommons(bankId=BankId(bankIdExample.value), + accountId=AccountId(accountIdExample.value), + balanceId=BalanceId(balanceIdExample.value), + balanceType=balanceTypeExample.value, + balanceAmount=BigDecimal(balanceAmountExample.value))) + ), + adapterImplementation = Some(AdapterImplementation("- Core", 1)) + ) + + override def getBankAccountBalanceById(balanceId: BalanceId, callContext: Option[CallContext]): OBPReturnType[Box[BankAccountBalanceTrait]] = { + import com.openbankproject.commons.dto.{InBoundGetBankAccountBalanceById => InBound, OutBoundGetBankAccountBalanceById => OutBound} + val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, balanceId) + val response: Future[Box[InBound]] = sendRequest[InBound]("obp_get_bank_account_balance_by_id", req, callContext) + response.map(convertToTuple[BankAccountBalanceTraitCommons](callContext)) + } + + messageDocs += createOrUpdateBankAccountBalanceDoc + def createOrUpdateBankAccountBalanceDoc = MessageDoc( + process = "obp.createOrUpdateBankAccountBalance", + messageFormat = messageFormat, + description = "Create Or Update Bank Account Balance", + outboundTopic = None, + inboundTopic = None, + exampleOutboundMessage = ( + OutBoundCreateOrUpdateBankAccountBalance(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, + bankId=BankId(bankIdExample.value), + accountId=AccountId(accountIdExample.value), + balanceId=Some(BalanceId(balanceIdExample.value)), + balanceType=balanceTypeExample.value, + balanceAmount=BigDecimal(balanceAmountExample.value)) + ), + exampleInboundMessage = ( + InBoundCreateOrUpdateBankAccountBalance(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, + status=MessageDocsSwaggerDefinitions.inboundStatus, + data= BankAccountBalanceTraitCommons(bankId=BankId(bankIdExample.value), + accountId=AccountId(accountIdExample.value), + balanceId=BalanceId(balanceIdExample.value), + balanceType=balanceTypeExample.value, + balanceAmount=BigDecimal(balanceAmountExample.value))) + ), + adapterImplementation = Some(AdapterImplementation("- Core", 1)) + ) + + override def createOrUpdateBankAccountBalance(bankId: BankId, accountId: AccountId, balanceId: Option[BalanceId], balanceType: String, balanceAmount: BigDecimal, callContext: Option[CallContext]): OBPReturnType[Box[BankAccountBalanceTrait]] = { + import com.openbankproject.commons.dto.{InBoundCreateOrUpdateBankAccountBalance => InBound, OutBoundCreateOrUpdateBankAccountBalance => OutBound} + val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, bankId, accountId, balanceId, balanceType, balanceAmount) + val response: Future[Box[InBound]] = sendRequest[InBound]("obp_create_or_update_bank_account_balance", req, callContext) + response.map(convertToTuple[BankAccountBalanceTraitCommons](callContext)) + } + + messageDocs += deleteBankAccountBalanceDoc + def deleteBankAccountBalanceDoc = MessageDoc( + process = "obp.deleteBankAccountBalance", + messageFormat = messageFormat, + description = "Delete Bank Account Balance", + outboundTopic = None, + inboundTopic = None, + exampleOutboundMessage = ( + OutBoundDeleteBankAccountBalance(outboundAdapterCallContext=MessageDocsSwaggerDefinitions.outboundAdapterCallContext, + balanceId=BalanceId(balanceIdExample.value)) + ), + exampleInboundMessage = ( + InBoundDeleteBankAccountBalance(inboundAdapterCallContext=MessageDocsSwaggerDefinitions.inboundAdapterCallContext, + status=MessageDocsSwaggerDefinitions.inboundStatus, + data=true) + ), + adapterImplementation = Some(AdapterImplementation("- Core", 1)) + ) + + override def deleteBankAccountBalance(balanceId: BalanceId, callContext: Option[CallContext]): OBPReturnType[Box[Boolean]] = { + import com.openbankproject.commons.dto.{InBoundDeleteBankAccountBalance => InBound, OutBoundDeleteBankAccountBalance => OutBound} + val req = OutBound(callContext.map(_.toOutboundAdapterCallContext).orNull, balanceId) + val response: Future[Box[InBound]] = sendRequest[InBound]("obp_delete_bank_account_balance", req, callContext) + response.map(convertToTuple[Boolean](callContext)) + } + +// ---------- created on 2025-05-22T11:32:05Z +//---------------- dynamic end ---------------------please don't modify this line private val availableOperation = DynamicEntityOperation.values.map(it => s""""$it"""").mkString("[", ", ", "]") diff --git a/obp-api/src/test/scala/code/api/v1_3_0/PhysicalCardsTest.scala b/obp-api/src/test/scala/code/api/v1_3_0/PhysicalCardsTest.scala index af406bbdf..4e54ad7be 100644 --- a/obp-api/src/test/scala/code/api/v1_3_0/PhysicalCardsTest.scala +++ b/obp-api/src/test/scala/code/api/v1_3_0/PhysicalCardsTest.scala @@ -1,10 +1,10 @@ package code.api.v1_3_0 import java.util.Date - import code.api.util.APIUtil.OAuth._ -import code.api.util.{APIUtil, CallContext, OBPQueryParam} +import code.api.util.{APIUtil, ApiRole, CallContext, OBPQueryParam} import code.bankconnectors.Connector +import code.entitlement.Entitlement import code.setup.{DefaultConnectorTestSetup, DefaultUsers, ServerSetup} import code.util.Helper.MdcLoggable import com.openbankproject.commons.model._ @@ -13,7 +13,7 @@ import net.liftweb.common.{Box, Full} import scala.concurrent.Future import com.openbankproject.commons.ExecutionContext.Implicits.global -class PhysicalCardsTest extends ServerSetup with DefaultUsers with DefaultConnectorTestSetup { +class PhysicalCardsTest extends ServerSetup with DefaultUsers with DefaultConnectorTestSetup { def v1_3Request = baseRequest / "obp" / "v1.3.0" @@ -34,10 +34,10 @@ class PhysicalCardsTest extends ServerSetup with DefaultUsers with DefaultConne Connector.connector.default.set(Connector.buildOne) wipeTestData() } - - def createCard(number : String) = PhysicalCard( - cardId ="", - bankId= bank.bankId.value, + + def createCard(number: String) = PhysicalCard( + cardId = "", + bankId = bank.bankId.value, bankCardNumber = number, cardType = "", nameOnCard = "", @@ -74,10 +74,13 @@ class PhysicalCardsTest extends ServerSetup with DefaultUsers with DefaultConne implicit override val nameOfConnector = "MockedCardConnector" - - + override def getBankLegacy(bankId: BankId, callContext: Option[CallContext]) = Full(bank, callContext) + override def getBank(bankId: BankId, callContext: Option[CallContext]) = Future { + getBankLegacy(bankId, callContext) + } + //these methods are required in this test, there is no need to extends connector. override def getPhysicalCardsForUser(user: User, callContext: Option[CallContext]) = { val cardList = if (user == resourceUser1) { @@ -100,13 +103,14 @@ class PhysicalCardsTest extends ServerSetup with DefaultUsers with DefaultConne } Full(cardList) }.map((_, callContext)) - - feature("Getting details of physical cards") { + } + + feature("Getting details of physical cards") { scenario("A user wants to get details of all their cards across all banks") { When("A user requests their cards") - val request = (v1_3Request / "cards").GET <@(user1) + val request = (v1_3Request / "cards").GET <@ (user1) val response = makeGetRequest(request) Then("We should get a 200") @@ -126,9 +130,17 @@ class PhysicalCardsTest extends ServerSetup with DefaultUsers with DefaultConne When("A user requests their cards") //our dummy connector doesn't care about the value of the bank id, so we can just use "somebank" - val request = (v1_3Request / "banks" / bank.bankId.value / "cards").GET <@(user1) - val response = makeGetRequest(request) + val request = (v1_3Request / "banks" / bank.bankId.value / "cards").GET <@ (user1) + val response1 = makeGetRequest(request) + Then("We should get a 403") + response1.code should equal(403) + + When("We add one required entitlement") + Entitlement.entitlement.vend.addEntitlement(bank.bankId.value, resourceUser1.userId, ApiRole.CanGetCardsForBank.toString) + val response = makeGetRequest(request) + + Then("We should get a 200") response.code should equal(200) @@ -144,7 +156,6 @@ class PhysicalCardsTest extends ServerSetup with DefaultUsers with DefaultConne } } - - } - + + } 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 b14ab8e68..aa44348d0 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 @@ -26,14 +26,13 @@ package com.openbankproject.commons.dto -import java.util.Date -import com.openbankproject.commons.model.enums.{AttributeCategory, AttributeType, BankAttributeType, CardAttributeType, ChallengeType, CustomerAttributeType, DynamicEntityOperation, PaymentServiceTypes, StrongCustomerAuthentication, SuppliedAnswerType, TransactionAttributeType, TransactionRequestAttributeType, TransactionRequestStatus, TransactionRequestTypes, UserAttributeType} import com.openbankproject.commons.model.enums.StrongCustomerAuthentication.SCA import com.openbankproject.commons.model.enums.StrongCustomerAuthenticationStatus.SCAStatus -import com.openbankproject.commons.model.{enums, _} +import com.openbankproject.commons.model.enums.{TransactionRequestStatus, _} +import com.openbankproject.commons.model._ import net.liftweb.json.{JObject, JValue} -import scala.collection.immutable.List +import java.util.Date trait InBoundTrait[T] { val inboundAdapterCallContext: InboundAdapterCallContext @@ -43,6 +42,30 @@ trait InBoundTrait[T] { //--------generated + +case class OutBoundGetBankAccountBalancesByAccountId (outboundAdapterCallContext: OutboundAdapterCallContext, + accountId: AccountId) extends TopicTrait +case class InBoundGetBankAccountBalancesByAccountId (inboundAdapterCallContext: InboundAdapterCallContext, status: Status, data: List[BankAccountBalanceTraitCommons]) extends InBoundTrait[List[BankAccountBalanceTraitCommons]] + + +case class OutBoundGetBankAccountBalanceById (outboundAdapterCallContext: OutboundAdapterCallContext, + balanceId: BalanceId) extends TopicTrait +case class InBoundGetBankAccountBalanceById (inboundAdapterCallContext: InboundAdapterCallContext, status: Status, data: BankAccountBalanceTraitCommons) extends InBoundTrait[BankAccountBalanceTraitCommons] + + +case class OutBoundCreateOrUpdateBankAccountBalance (outboundAdapterCallContext: OutboundAdapterCallContext, + bankId: BankId, + accountId: AccountId, + balanceId: Option[BalanceId], + balanceType: String, + balanceAmount: BigDecimal) extends TopicTrait +case class InBoundCreateOrUpdateBankAccountBalance (inboundAdapterCallContext: InboundAdapterCallContext, status: Status, data: BankAccountBalanceTraitCommons) extends InBoundTrait[BankAccountBalanceTraitCommons] + + +case class OutBoundDeleteBankAccountBalance (outboundAdapterCallContext: OutboundAdapterCallContext, + balanceId: BalanceId) extends TopicTrait +case class InBoundDeleteBankAccountBalance (inboundAdapterCallContext: InboundAdapterCallContext, status: Status, data: Boolean) extends InBoundTrait[Boolean] + case class OutBoundGetRegulatedEntities (outboundAdapterCallContext: OutboundAdapterCallContext) extends TopicTrait case class InBoundGetRegulatedEntities (inboundAdapterCallContext: InboundAdapterCallContext, status: Status, data: List[RegulatedEntityTraitCommons]) extends InBoundTrait[List[RegulatedEntityTraitCommons]] diff --git a/obp-commons/src/main/scala/com/openbankproject/commons/model/CommonModel.scala b/obp-commons/src/main/scala/com/openbankproject/commons/model/CommonModel.scala index e921f989d..066f2d3e5 100644 --- a/obp-commons/src/main/scala/com/openbankproject/commons/model/CommonModel.scala +++ b/obp-commons/src/main/scala/com/openbankproject/commons/model/CommonModel.scala @@ -26,16 +26,16 @@ TESOBE (http://www.tesobe.com/) */ package com.openbankproject.commons.model -import java.util.Date import com.openbankproject.commons.model.enums.StrongCustomerAuthentication.SCA import com.openbankproject.commons.model.enums.StrongCustomerAuthenticationStatus.SCAStatus import com.openbankproject.commons.model.enums._ import com.openbankproject.commons.util.{ReflectUtils, optional} import net.liftweb.json.JsonAST.{JObject, JValue} -import net.liftweb.json.{Formats, JInt, JString} import net.liftweb.json.JsonDSL._ +import net.liftweb.json.{Formats, JInt, JString} import java.lang +import java.util.Date import scala.reflect.runtime.universe._ @@ -128,6 +128,14 @@ case class BankAccountCommons( object BankAccountCommons extends Converter[BankAccount, BankAccountCommons] +case class BankAccountBalanceTraitCommons( + bankId :BankId, + accountId :AccountId, + balanceId :BalanceId, + balanceType :String, + balanceAmount :BigDecimal) extends BankAccountBalanceTrait +object BankAccountBalanceTraitCommons extends Converter[BankAccountBalanceTrait, BankAccountBalanceTraitCommons] + case class ProductCollectionItemCommons( collectionCode :String, memberProductCode :String) extends ProductCollectionItem