diff --git a/src/main/scala/code/api/STET/v1_4/AISPApi.scala b/src/main/scala/code/api/STET/v1_4/AISPApi.scala index 52eb7ddbb..669a106c7 100644 --- a/src/main/scala/code/api/STET/v1_4/AISPApi.scala +++ b/src/main/scala/code/api/STET/v1_4/AISPApi.scala @@ -22,6 +22,7 @@ import scala.concurrent.ExecutionContext.Implicits.global import scala.concurrent.Future import code.api.STET.v1_4.OBP_STET_1_4 import code.api.util.ApiTag +import code.api.STET.v1_4.JSONFactory_STET_1_4._ object APIMethods_AISPApi extends RestHelper { val apiVersion = OBP_STET_1_4.apiVersion @@ -74,7 +75,31 @@ The ASPSP answers by providing a list of balances on this account. """, json.parse(""""""), - json.parse(""""""), + json.parse("""{ + | "balances": [ + | { + | "name": "Solde comptable au 12/01/2017", + | "balanceAmount": { + | "currency": "EUR", + | "amount": "123.45" + | }, + | "balanceType": "CLBD", + | "lastCommittedTransaction": "A452CH" + | } + | ], + | "_links": { + | "self": { + | "href": "v1/accounts/Alias1/balances-report" + | }, + | "parent-list": { + | "href": "v1/accounts" + | }, + | "transactions": { + | "href": "v1/accounts/Alias1/transactions" + | } + | } + |} + |""".stripMargin), List(UserNotLoggedIn, UnknownError), Catalogs(notCore, notPSD2, notOBWG), ApiTag("AISP") :: apiTagMockedData :: Nil @@ -82,14 +107,22 @@ The ASPSP answers by providing a list of balances on this account. lazy val accountsBalancesGet : OBPEndpoint = { case "accounts" :: accountresourceid:: "balances" :: Nil JsonGet _ => { - cc => + cc => for { (Full(u), callContext) <- authorizedAccess(UserNotLoggedIn, cc) - } yield { - (NotImplemented, callContext) - } - } + _ <- Helper.booleanToFuture(failMsg= DefaultBankIdNotSet ) { defaultBankId != "DEFAULT_BANK_ID_NOT_SET" } + (_, callContext) <- NewStyle.function.getBank(BankId(defaultBankId), callContext) + (bankAccount, callContext) <- NewStyle.function.checkBankAccountExists(BankId(defaultBankId), AccountId(accountresourceid), callContext) + view <- NewStyle.function.view(ViewId("owner"), BankIdAccountId(bankAccount.bankId, bankAccount.accountId), callContext) + _ <- Helper.booleanToFuture(failMsg = s"${UserNoPermissionAccessView} Current VIEW_ID (${view.viewId.value})") {(u.hasViewAccess(view))} + moderatedAccount <- Future {bankAccount.moderatedBankAccount(view, Full(u))} map { + x => fullBoxOrException(x ~> APIFailureNewStyle(UnknownError, 400, callContext.map(_.toLight))) + } map { unboxFull(_) } + } yield { + (createAccountBalanceJSON(moderatedAccount), HttpCode.`200`(callContext)) + } } + } resourceDocs += ResourceDoc( accountsGet, @@ -117,7 +150,47 @@ The TPP sends a request to the ASPSP for retrieving the list of the PSU payment """, json.parse(""""""), - json.parse(""""""), + json.parse("""{ + | "accounts": [ + | { + | "resourceId": "Alias1", + | "bicFi": "BNKAFRPPXXX", + | "name": "Compte de Mr et Mme Dupont", + | "usage": "PRIV", + | "cashAccountType": "CACC", + | "currency": "EUR", + | "psuStatus": "Co-account Holder", + | "_links": { + | "balances": { + | "href": "v1/accounts/Alias1/balances" + | }, + | "transactions": { + | "href": "v1/accounts/Alias1/transactions" + | } + | } + | } + | ], + | "_links": { + | "self": { + | "href": "v1/accounts?page=2" + | }, + | "first": { + | "href": "v1/accounts" + | }, + | "last": { + | "href": "v1/accounts?page=last", + | "templated": true + | }, + | "next": { + | "href": "v1/accounts?page=3", + | "templated": true + | }, + | "prev": { + | "href": "v1/accounts", + | "templated": true + | } + | } + |}""".stripMargin), List(UserNotLoggedIn, UnknownError), Catalogs(notCore, notPSD2, notOBWG), ApiTag("AISP") :: apiTagMockedData :: Nil @@ -125,12 +198,23 @@ The TPP sends a request to the ASPSP for retrieving the list of the PSU payment lazy val accountsGet : OBPEndpoint = { case "accounts" :: Nil JsonGet _ => { - cc => + cc => for { (Full(u), callContext) <- authorizedAccess(UserNotLoggedIn, cc) - } yield { - (NotImplemented, callContext) - } + + _ <- Helper.booleanToFuture(failMsg= DefaultBankIdNotSet ) {defaultBankId != "DEFAULT_BANK_ID_NOT_SET"} + + bankId = BankId(defaultBankId) + + (_, callContext) <- NewStyle.function.getBank(bankId, callContext) + + availablePrivateAccounts <- Views.views.vend.getPrivateBankAccountsFuture(u, bankId) + + Full(accounts) <- {Connector.connector.vend.getBankAccountsFuture(availablePrivateAccounts,callContext)} + + } yield { + (createTransactionListJSON(accounts), callContext) + } } } @@ -166,7 +250,40 @@ The AISP requests the ASPSP on one of the PSU's accounts. It may specify some se """, json.parse(""""""), - json.parse(""""""), + json.parse("""{ + | "transactions": [ + | { + | "entryReference": "AF5T2", + | "transactionAmount": { + | "currency": "EUR", + | "amount": "12.25" + | }, + | "creditDebitIndicator": "CRDT", + | "status": "BOOK", + | "bookingDate": "2018-02-12", + | "remittanceInformation": [ + | "SEPA CREDIT TRANSFER from PSD2Company" + | ] + | } + | ], + | "_links": { + | "self": { + | "href": "v1/accounts/Alias1/transactions" + | }, + | "parent-list": { + | "href": "v1/accounts" + | }, + | "balances": { + | "href": "v1/accounts/Alias1/balances" + | }, + | "last": { + | "href": "v1/accounts/sAlias1/transactions?page=last" + | }, + | "next": { + | "href": "v1/accounts/Alias1/transactions?page=3" + | } + | } + |}""".stripMargin), List(UserNotLoggedIn, UnknownError), Catalogs(notCore, notPSD2, notOBWG), ApiTag("AISP") :: apiTagMockedData :: Nil @@ -177,9 +294,32 @@ The AISP requests the ASPSP on one of the PSU's accounts. It may specify some se cc => for { (Full(u), callContext) <- authorizedAccess(UserNotLoggedIn, cc) - } yield { - (NotImplemented, callContext) - } + + _ <- Helper.booleanToFuture(failMsg= DefaultBankIdNotSet ) {defaultBankId != "DEFAULT_BANK_ID_NOT_SET"} + + bankId = BankId(defaultBankId) + + (_, callContext) <- NewStyle.function.getBank(bankId, callContext) + + (bankAccount, callContext) <- NewStyle.function.checkBankAccountExists(bankId, AccountId(accountresourceid), callContext) + + view <- NewStyle.function.view(ViewId("owner"), BankIdAccountId(bankAccount.bankId, bankAccount.accountId), callContext) + + params <- Future { createQueriesByHttpParams(callContext.get.requestHeaders)} map { + x => fullBoxOrException(x ~> APIFailureNewStyle(UnknownError, 400, callContext.map(_.toLight))) + } map { unboxFull(_) } + + (transactionRequests, callContext) <- Future { Connector.connector.vend.getTransactionRequests210(u, bankAccount)} map { + x => fullBoxOrException(x ~> APIFailureNewStyle(InvalidConnectorResponseForGetTransactionRequests210, 400, callContext.map(_.toLight))) + } map { unboxFull(_) } + + (transactions, callContext) <- Future { bankAccount.getModeratedTransactions(Full(u), view, callContext, params: _*)} map { + x => fullBoxOrException(x ~> APIFailureNewStyle(UnknownError, 400, callContext.map(_.toLight))) + } map { unboxFull(_) } + + } yield { + (createTransactionsJson(transactions, transactionRequests), callContext) + } } } diff --git a/src/main/scala/code/api/STET/v1_4/JSONFactory_SETE_1_4.scala b/src/main/scala/code/api/STET/v1_4/JSONFactory_SETE_1_4.scala new file mode 100644 index 000000000..e970ead95 --- /dev/null +++ b/src/main/scala/code/api/STET/v1_4/JSONFactory_SETE_1_4.scala @@ -0,0 +1,182 @@ +package code.api.STET.v1_4 + +import java.util.Date + +import code.api.STET.v1_4.JSONFactory_STET_1_4.{TransactionLastLink, TransactionNextLink} +import code.api.util.APIUtil +import code.api.v2_1_0.IbanJson +import code.model.{BankAccount, CoreAccount, ModeratedBankAccount, ModeratedTransaction} +import code.transactionrequests.TransactionRequests.TransactionRequest + +import scala.collection.immutable.List + +object JSONFactory_STET_1_4 { + + implicit val formats = net.liftweb.json.DefaultFormats + + trait Links + case class Balances(balances: String) extends Links + case class Transactions(trasactions: String) extends Links + case class ViewAccount(viewAccount: String) extends Links + case class CoreAccountJsonV1( + resourceId: String, + bicFi: String, + currency: String, + accountType: String, + cashAccountType: String, + name: String, + usage: String="PRIV", + psuStatus: String="Co-account Holder", + ) + case class Href(href: String) extends Links + + case class Self(self: Href= Href("v1/accounts?page=2")) extends Links + + case class First(self: Href= Href("v1/accounts")) extends Links + + case class Last( + href: Href= Href("v1/accounts?page=last"), + templated: Boolean = true + ) extends Links + + case class Next( + href: Href= Href("v1/accounts?page=3"), + templated: Boolean = true + ) extends Links + + case class Prev( + href: Href= Href("v1/accounts"), + templated: Boolean = true + ) extends Links + + case class ParentList( + `parent-list`: Href= Href("v1/accounts"), + ) extends Links + + case class TransactionBalanceLink( + href: Href= Href("v1/accounts"), + ) extends Links + + case class TransactionLastLink( + href: Href= Href("v1/accounts"), + ) extends Links + + case class TransactionNextLink( + href: Href= Href("v1/accounts"), + ) extends Links + + + case class TransactionsLinks( + transactions: Href= Href("v1/accounts/Alias1/transactions"), + ) extends Links + + case class AccountsJsonV1( + accounts: List[CoreAccountJsonV1], + _links: List[Links] + ) + + case class AmountOfMoneyV1( + currency : String, + content : String + ) + case class ClosingBookedBody( + amount : AmountOfMoneyV1, + date: String //eg: “2017-10-25”, this is not a valid datetime (not java.util.Date) + ) + case class ExpectedBody( + amount : AmountOfMoneyV1, + lastActionDateTime: Date + ) + case class AccountBalance( + name:String, + balanceAmount: AmountOfMoneyV1, + balanceType:String, + lastCommittedTransaction: String + ) + case class AccountBalances( + `balances`: List[AccountBalance], + _links: List[Links] = List( + Self(Href("v1/accounts/Alias1/balances-report")), + ParentList(Href("v1/accounts")), + TransactionsLinks(Href("v1/accounts/Alias1/transactions")) + ) + ) + + case class TransactionsJsonV1( + transactions: List[TransactionJsonV1], + _links: List[Links]= List( + Self(Href("v1/accounts/Alias1/transactions")), + ParentList(Href("v1/accounts")), + TransactionBalanceLink(Href("v1/accounts/Alias1/balances")), + TransactionLastLink(Href("v1/accounts/sAlias1/transactions?page=last")), + TransactionNextLink(Href("v1/accounts/Alias1/transactions?page=3")) + ) + ) + + case class TransactionJsonV1( + entryReference: String, + creditDebitIndicator: String, + transactionAmount: AmountOfMoneyV1, + bookingDate: Date, + status: String, + remittanceInformation: List[String] + ) + + def createTransactionListJSON(accounts: List[BankAccount]): AccountsJsonV1 = + AccountsJsonV1( + accounts =accounts.map( + account => CoreAccountJsonV1( + resourceId = account.accountId.value, + bicFi = account.swift_bic.getOrElse(account.iban.getOrElse("")), + currency = account.currency, + accountType = account.accountType, + cashAccountType = "CACC", + name = account.accountHolder) + ), + _links=List(Self(), First(), Last(), Next(), Prev()) + ) + + def createAccountBalanceJSON(moderatedAccount: ModeratedBankAccount) = { + AccountBalances( + `balances`= List( + AccountBalance( + name = "Solde comptable au 12/01/2017", + balanceAmount = AmountOfMoneyV1(moderatedAccount.currency.getOrElse(""),moderatedAccount.balance), + balanceType= moderatedAccount.accountType.getOrElse(""), + lastCommittedTransaction="A452CH" + ) + ) + ) + } + + def createTransactionJSON(transaction : ModeratedTransaction) : TransactionJsonV1 = { + TransactionJsonV1( + entryReference = transaction.id.value, + creditDebitIndicator = "", + transactionAmount = AmountOfMoneyV1(APIUtil.stringOptionOrNull(transaction.currency),transaction.amount.get.toString()), + bookingDate = transaction.startDate.get, + status = "COMPLETED", + remittanceInformation = List(APIUtil.stringOptionOrNull(transaction.description)) + ) + } + + def createTransactionFromRequestJSON(transactionRequest : TransactionRequest) : TransactionJsonV1 = { + TransactionJsonV1( + entryReference = transactionRequest.id.value, + creditDebitIndicator = transactionRequest.name, + transactionAmount = AmountOfMoneyV1(transactionRequest.charge.value.currency,transactionRequest.charge.value.amount), + bookingDate = transactionRequest.start_date, + status = "BOOK", + remittanceInformation = List(transactionRequest.body.description) + ) + } + + def createTransactionsJson(transactions: List[ModeratedTransaction], transactionRequests: List[TransactionRequest]) : TransactionsJsonV1 = { + val transactions_booked: List[TransactionJsonV1] = transactions.map(createTransactionJSON) + val transactions_pending: List[TransactionJsonV1] =transactionRequests.filter(_.status!="COMPLETED").map(createTransactionFromRequestJSON) + TransactionsJsonV1( + transactions = transactions_booked:::transactions_pending:::Nil + ) + } + +} diff --git a/src/main/scala/code/api/util/APIUtil.scala b/src/main/scala/code/api/util/APIUtil.scala index b7c029c9a..71ff8aff0 100644 --- a/src/main/scala/code/api/util/APIUtil.scala +++ b/src/main/scala/code/api/util/APIUtil.scala @@ -2285,7 +2285,7 @@ Returns a string showed to the developer val brandSpecificPropertyName = getBrandSpecificPropertyName(nameOfProperty) - logger.debug(s"Standard property $nameOfProperty has bankSpecificPropertyName: $brandSpecificPropertyName") +// logger.debug(s"Standard property $nameOfProperty has bankSpecificPropertyName: $brandSpecificPropertyName") //All the property will first check from system environment, if not find then from the liftweb props file //Replace "." with "_" (environment vars cannot include ".") and convert to upper case diff --git a/src/main/scala/code/fx/fx.scala b/src/main/scala/code/fx/fx.scala index fda847d90..a3849a718 100644 --- a/src/main/scala/code/fx/fx.scala +++ b/src/main/scala/code/fx/fx.scala @@ -15,17 +15,18 @@ object fx extends MdcLoggable { //get data from : http://www.xe.com/de/currencyconverter/convert/?Amount=1&From=AUD&To=EUR val exchangeRates = { Map( - "GBP" -> Map("EUR" -> 1.16278, "USD" -> 1.24930, "JPY" -> 141.373, "AED" -> 4.58882, "INR" -> 84.0950, "KRW" -> 1433.92, "XAF" -> 762.826, "JOD" -> 0.936707, "ILS" -> 4.70020, "AUD" -> 1.63992 ), - "EUR" -> Map("GBP" -> 0.860011, "USD" -> 1.07428, "JPY" -> 121.567, "AED" -> 3.94594, "INR" -> 72.3136, "KRW" -> 1233.03, "XAF" -> 655.957, "JOD" -> 0.838098, "ILS" -> 4.20494, "AUD" -> 1.49707 ), - "USD" -> Map("GBP" -> 0.800446, "EUR" -> 0.930886, "JPY" -> 113.161, "AED" -> 3.67310, "INR" -> 67.3135, "KRW" -> 1147.78, "XAF" -> 610.601, "JOD" -> 0.708659, "ILS" -> 3.55495, "AUD" -> 1.27347 ), - "JPY" -> Map("GBP" -> 0.00707350, "EUR" -> 0.00822592, "USD" -> 0.00883695, "AED" -> 0.0324590, "INR" -> 0.594846, "KRW" -> 10.1428, "XAF" -> 5.39585, "JOD" -> 0.00639777, "ILS" -> 0.0320926, "AUD" -> 0.0114819 ), - "AED" -> Map("GBP" -> 0.217921, "EUR" -> 0.253425, "USD" -> 0.272250, "JPY" -> 30.8081, "INR" -> 18.3255, "KRW" -> 312.482, "XAF" -> 166.236, "AED" -> 0.192964, "ILS" -> 0.968033, "AUD" -> 0.346779 ), - "INR" -> Map("GBP" -> 0.0118913, "EUR" -> 0.0138287, "USD" -> 0.0148559, "JPY" -> 1.68111, "AED" -> 0.0545671, "KRW" -> 17.0512, "XAF" -> 9.07101, "JOD" -> 0.0110959 , "ILS" -> 0.0556764, "AUD" -> 0.0198319 ), - "KRW" -> Map("GBP" -> 0.000697389, "EUR" -> 0.000811008, "USD" -> 0.000871250, "JPY" -> 0.0985917, "AED" -> 0.00320019, "INR" -> 0.0586469, "XAF" -> 0.531986, "JOD" -> 0.000630634, "ILS" -> 0.00316552,"AUD" -> 0.00111694), - "XAF" -> Map("GBP" -> 0.00131092, "EUR" -> 0.00152449, "USD" -> 0.00163773, "JPY" -> 0.185328, "AED" -> 0.00601555, "INR" -> 0.110241, "KRW" -> 1.87975, "JOD" -> 0.00127784, "ILS" -> 0.00641333,"AUD" -> 0.00228226), - "JOD" -> Map("GBP" -> 1.06757, "EUR" -> 0.237707, "USD" -> 1.41112, "JPY" -> 156.304, "AED" -> 5.18231, "INR" -> 90.1236, "KRW" -> 1585.68, "XAF" -> 782.572, "ILS" -> 5.02018, "AUD" -> 1.63992 ), - "ILS" -> Map("GBP" -> 0.212763, "EUR" -> 1.19318, "USD" -> 0.281298, "JPY" -> 31.1599, "AED" -> 1.03302, "INR" -> 17.9609, "KRW" -> 315.903, "XAF" -> 155.925, "JOD" -> 0.199196, "AUD" -> 0.352661 ), - "AUD" -> Map("GBP" -> 0.609788, "EUR" -> 0.667969, "USD" -> 0.785256, "JPY" -> 87.0936, "AED" -> 2.88368, "INR" -> 50.4238, "KRW" -> 895.304, "XAF" -> 438.162, "JOD" -> 0.556152, "ILS" -> 2.83558 ) + "GBP" -> Map("EUR" -> 1.16278, "USD" -> 1.24930, "JPY" -> 141.373, "AED" -> 4.58882, "INR" -> 84.0950, "KRW" -> 1433.92, "XAF" -> 762.826, "JOD" -> 0.936707, "ILS" -> 4.70020, "AUD" -> 1.63992 ,"HKD" -> 10.1468 ), + "EUR" -> Map("GBP" -> 0.860011, "USD" -> 1.07428, "JPY" -> 121.567, "AED" -> 3.94594, "INR" -> 72.3136, "KRW" -> 1233.03, "XAF" -> 655.957, "JOD" -> 0.838098, "ILS" -> 4.20494, "AUD" -> 1.49707 ,"HKD" -> 8.88926 ), + "USD" -> Map("GBP" -> 0.800446, "EUR" -> 0.930886, "JPY" -> 113.161, "AED" -> 3.67310, "INR" -> 67.3135, "KRW" -> 1147.78, "XAF" -> 610.601, "JOD" -> 0.708659, "ILS" -> 3.55495, "AUD" -> 1.27347 ,"HKD" -> 7.84766 ), + "JPY" -> Map("GBP" -> 0.00707350, "EUR" -> 0.00822592, "USD" -> 0.00883695, "AED" -> 0.0324590, "INR" -> 0.594846, "KRW" -> 10.1428, "XAF" -> 5.39585, "JOD" -> 0.00639777, "ILS" -> 0.0320926, "AUD" -> 0.0114819 ,"HKD" -> 0.0709891), + "AED" -> Map("GBP" -> 0.217921, "EUR" -> 0.253425, "USD" -> 0.272250, "JPY" -> 30.8081, "INR" -> 18.3255, "KRW" -> 312.482, "XAF" -> 166.236, "AED" -> 0.192964, "ILS" -> 0.968033, "AUD" -> 0.346779 ,"HKD" -> 2.13685 ), + "INR" -> Map("GBP" -> 0.0118913, "EUR" -> 0.0138287, "USD" -> 0.0148559, "JPY" -> 1.68111, "AED" -> 0.0545671, "KRW" -> 17.0512, "XAF" -> 9.07101, "JOD" -> 0.0110959 , "ILS" -> 0.0556764, "AUD" -> 0.0198319 ,"HKD" -> 0.109972 ), + "KRW" -> Map("GBP" -> 0.000697389, "EUR" -> 0.000811008, "USD" -> 0.000871250, "JPY" -> 0.0985917, "AED" -> 0.00320019, "INR" -> 0.0586469, "XAF" -> 0.531986, "JOD" -> 0.000630634, "ILS" -> 0.00316552,"AUD" -> 0.00111694,"HKD" -> 0.00697233 ), + "XAF" -> Map("GBP" -> 0.00131092, "EUR" -> 0.00152449, "USD" -> 0.00163773, "JPY" -> 0.185328, "AED" -> 0.00601555, "INR" -> 0.110241, "KRW" -> 1.87975, "JOD" -> 0.00127784, "ILS" -> 0.00641333,"AUD" -> 0.00228226,"HKD" -> 0.0135503 ), + "JOD" -> Map("GBP" -> 1.06757, "EUR" -> 0.237707, "USD" -> 1.41112, "JPY" -> 156.304, "AED" -> 5.18231, "INR" -> 90.1236, "KRW" -> 1585.68, "XAF" -> 782.572, "ILS" -> 5.02018, "AUD" -> 1.63992 ,"HKD" -> 11.0687 ), + "ILS" -> Map("GBP" -> 0.212763, "EUR" -> 1.19318, "USD" -> 0.281298, "JPY" -> 31.1599, "AED" -> 1.03302, "INR" -> 17.9609, "KRW" -> 315.903, "XAF" -> 155.925, "JOD" -> 0.199196, "AUD" -> 0.352661 ,"HKD" -> 2.16985 ), + "AUD" -> Map("GBP" -> 0.609788, "EUR" -> 0.667969, "USD" -> 0.785256, "JPY" -> 87.0936, "AED" -> 2.88368, "INR" -> 50.4238, "KRW" -> 895.304, "XAF" -> 438.162, "JOD" -> 0.556152, "ILS" -> 2.83558 ,"HKD" -> 5.61346 ), + "HKD" -> Map("GBP" -> 0.0985443, "EUR" -> 0.112495, "USD" -> 0.127427, "JPY" -> 14.0867, "AED" -> 0.467977, "INR" -> 9.09325, "KRW" -> 143.424, "XAF" -> 73.8049, "JOD" -> 0.0903452, "ILS" -> 0.460862 ,"AUD" -> 0.178137 ) ) }