From 2b7327a5c5acdb89365655933505ba7964249b1f Mon Sep 17 00:00:00 2001 From: hongwei Date: Mon, 18 Feb 2019 12:42:39 +0100 Subject: [PATCH 1/5] added HKD for exchangeRates --- src/main/scala/code/fx/fx.scala | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) 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 ) ) } From aee8511321204aadc53d7da84df43b8a97f848f0 Mon Sep 17 00:00:00 2001 From: hongwei Date: Mon, 18 Feb 2019 13:06:44 +0100 Subject: [PATCH 2/5] commented the `getPropValue` debug log --- src/main/scala/code/api/util/APIUtil.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/scala/code/api/util/APIUtil.scala b/src/main/scala/code/api/util/APIUtil.scala index 9646f4596..3cb47f332 100644 --- a/src/main/scala/code/api/util/APIUtil.scala +++ b/src/main/scala/code/api/util/APIUtil.scala @@ -2230,7 +2230,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 From d9136a0e2f0c087726880ad66574d03e335d152a Mon Sep 17 00:00:00 2001 From: hongwei Date: Wed, 20 Feb 2019 09:31:44 +0100 Subject: [PATCH 3/5] implemeted getAccount for STET --- .../scala/code/api/STET/v1_4/AISPApi.scala | 62 ++++++- .../api/STET/v1_4/JSONFactory_SETE_1_4.scala | 162 ++++++++++++++++++ 2 files changed, 219 insertions(+), 5 deletions(-) create mode 100644 src/main/scala/code/api/STET/v1_4/JSONFactory_SETE_1_4.scala 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 7cf0bcbe9..ecdc37944 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 @@ -117,7 +118,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 +166,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) <- authorizeEndpoint(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) + } } } 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..cfc589bd5 --- /dev/null +++ b/src/main/scala/code/api/STET/v1_4/JSONFactory_SETE_1_4.scala @@ -0,0 +1,162 @@ +package code.api.STET.v1_4 + +import java.util.Date + +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 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( + closingBooked: ClosingBookedBody, + expected: ExpectedBody + ) + case class AccountBalances(`balances`: List[AccountBalance]) + + case class TransactionsJsonV1( + transactions_booked: List[TransactionJsonV1], + transactions_pending: List[TransactionJsonV1], + _links: List[ViewAccount] + ) + + case class TransactionJsonV1( + transactionId: String, + creditorName: String, + creditorAccount: IbanJson, + amount: AmountOfMoneyV1, + bookingDate: Date, + valueDate: Date, + remittanceInformationUnstructured: 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, transactionRequests: List[TransactionRequest]) = { + // get the latest end_date of `COMPLETED` transactionRequests + val latestCompletedEndDate = transactionRequests.sortBy(_.end_date).reverse.filter(_.status == "COMPLETED").map(_.end_date).headOption.getOrElse(null) + + //get the latest end_date of !`COMPLETED` transactionRequests + val latestUncompletedEndDate = transactionRequests.sortBy(_.end_date).reverse.filter(_.status != "COMPLETED").map(_.end_date).headOption.getOrElse(null) + + // get the SUM of the amount of all !`COMPLETED` transactionRequests + val sumOfAllUncompletedTransactionrequests = transactionRequests.filter(_.status != "COMPLETED").map(_.body.value.amount).map(BigDecimal(_)).sum + // sum of the unCompletedTransactions and the account.balance is the current expectd amount: + val sumOfAll = (BigDecimal(moderatedAccount.balance) + sumOfAllUncompletedTransactionrequests).toString() + + AccountBalances( + AccountBalance( + closingBooked = ClosingBookedBody( + amount = AmountOfMoneyV1(currency = moderatedAccount.currency.getOrElse(""), content = moderatedAccount.balance), + date = APIUtil.DateWithDayFormat.format(latestCompletedEndDate) + ), + expected = ExpectedBody( + amount = AmountOfMoneyV1(currency = moderatedAccount.currency.getOrElse(""), + content = sumOfAll), + lastActionDateTime = latestUncompletedEndDate) + ) :: Nil + ) + } + + def createTransactionJSON(transaction : ModeratedTransaction) : TransactionJsonV1 = { + TransactionJsonV1( + transactionId = transaction.id.value, + creditorName = "", + creditorAccount = IbanJson(APIUtil.stringOptionOrNull(transaction.bankAccount.get.iban)), + amount = AmountOfMoneyV1(APIUtil.stringOptionOrNull(transaction.currency), transaction.amount.get.toString()), + bookingDate = transaction.startDate.get, + valueDate = transaction.finishDate.get, + remittanceInformationUnstructured = APIUtil.stringOptionOrNull(transaction.description) + ) + } + + def createTransactionFromRequestJSON(transactionRequest : TransactionRequest) : TransactionJsonV1 = { + TransactionJsonV1( + transactionId = transactionRequest.id.value, + creditorName = transactionRequest.name, + creditorAccount = IbanJson(transactionRequest.from.account_id), + amount = AmountOfMoneyV1(transactionRequest.charge.value.currency, transactionRequest.charge.value.amount), + bookingDate = transactionRequest.start_date, + valueDate = transactionRequest.end_date, + remittanceInformationUnstructured = transactionRequest.body.description + ) + } + + def createTransactionsJson(transactions: List[ModeratedTransaction], transactionRequests: List[TransactionRequest]) : TransactionsJsonV1 = { + TransactionsJsonV1( + transactions_booked =transactions.map(createTransactionJSON), + transactions_pending =transactionRequests.filter(_.status!="COMPLETED").map(createTransactionFromRequestJSON), + _links = ViewAccount(s"/${OBP_STET_1_4.version}/accounts/${transactionRequests.head.from.account_id}/balances")::Nil + ) + } + +} From 6454163397dcffe1d73b4a3f66ba9e91285d020c Mon Sep 17 00:00:00 2001 From: hongwei Date: Wed, 20 Feb 2019 10:46:17 +0100 Subject: [PATCH 4/5] implemeted getAccountBalance for STET --- .../scala/code/api/STET/v1_4/AISPApi.scala | 44 +++++++++-- .../api/STET/v1_4/JSONFactory_SETE_1_4.scala | 76 ++++++++++--------- 2 files changed, 78 insertions(+), 42 deletions(-) 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 ecdc37944..d84fb05c5 100644 --- a/src/main/scala/code/api/STET/v1_4/AISPApi.scala +++ b/src/main/scala/code/api/STET/v1_4/AISPApi.scala @@ -75,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 @@ -83,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) <- authorizeEndpoint(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, 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 index cfc589bd5..48611bb18 100644 --- 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 @@ -13,10 +13,10 @@ 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 + 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, @@ -27,30 +27,38 @@ object JSONFactory_STET_1_4 { usage: String="PRIV", psuStatus: String="Co-account Holder", ) - case class Href(href: String) extends links + case class Href(href: String) extends Links - case class Self(self: Href= Href("v1/accounts?page=2")) 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 First(self: Href= Href("v1/accounts")) extends Links case class Last( href: Href= Href("v1/accounts?page=last"), templated: Boolean = true - ) extends links + ) extends Links case class Next( href: Href= Href("v1/accounts?page=3"), templated: Boolean = true - ) extends links + ) extends Links case class Prev( href: Href= Href("v1/accounts"), templated: Boolean = true - ) extends links + ) extends Links + + case class ParentList( + `parent-list`: 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] + _links: List[Links] ) case class AmountOfMoneyV1( @@ -66,10 +74,19 @@ object JSONFactory_STET_1_4 { lastActionDateTime: Date ) case class AccountBalance( - closingBooked: ClosingBookedBody, - expected: ExpectedBody + 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 AccountBalances(`balances`: List[AccountBalance]) case class TransactionsJsonV1( transactions_booked: List[TransactionJsonV1], @@ -101,29 +118,16 @@ object JSONFactory_STET_1_4 { _links=List(Self(), First(), Last(), Next(), Prev()) ) - def createAccountBalanceJSON(moderatedAccount: ModeratedBankAccount, transactionRequests: List[TransactionRequest]) = { - // get the latest end_date of `COMPLETED` transactionRequests - val latestCompletedEndDate = transactionRequests.sortBy(_.end_date).reverse.filter(_.status == "COMPLETED").map(_.end_date).headOption.getOrElse(null) - - //get the latest end_date of !`COMPLETED` transactionRequests - val latestUncompletedEndDate = transactionRequests.sortBy(_.end_date).reverse.filter(_.status != "COMPLETED").map(_.end_date).headOption.getOrElse(null) - - // get the SUM of the amount of all !`COMPLETED` transactionRequests - val sumOfAllUncompletedTransactionrequests = transactionRequests.filter(_.status != "COMPLETED").map(_.body.value.amount).map(BigDecimal(_)).sum - // sum of the unCompletedTransactions and the account.balance is the current expectd amount: - val sumOfAll = (BigDecimal(moderatedAccount.balance) + sumOfAllUncompletedTransactionrequests).toString() - + def createAccountBalanceJSON(moderatedAccount: ModeratedBankAccount) = { AccountBalances( - AccountBalance( - closingBooked = ClosingBookedBody( - amount = AmountOfMoneyV1(currency = moderatedAccount.currency.getOrElse(""), content = moderatedAccount.balance), - date = APIUtil.DateWithDayFormat.format(latestCompletedEndDate) - ), - expected = ExpectedBody( - amount = AmountOfMoneyV1(currency = moderatedAccount.currency.getOrElse(""), - content = sumOfAll), - lastActionDateTime = latestUncompletedEndDate) - ) :: Nil + `balances`= List( + AccountBalance( + name = "Solde comptable au 12/01/2017", + balanceAmount = AmountOfMoneyV1(moderatedAccount.currency.getOrElse(""),moderatedAccount.balance), + balanceType= moderatedAccount.accountType.getOrElse(""), + lastCommittedTransaction="A452CH" + ) + ) ) } From daaac9079b1cfdccdf622562bb050e2adc11d1ee Mon Sep 17 00:00:00 2001 From: hongwei Date: Wed, 20 Feb 2019 11:01:22 +0100 Subject: [PATCH 5/5] implemeted getTransactions for STET --- .../scala/code/api/STET/v1_4/AISPApi.scala | 64 +++++++++++++++++-- .../api/STET/v1_4/JSONFactory_SETE_1_4.scala | 64 ++++++++++++------- 2 files changed, 100 insertions(+), 28 deletions(-) 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 d84fb05c5..361d20450 100644 --- a/src/main/scala/code/api/STET/v1_4/AISPApi.scala +++ b/src/main/scala/code/api/STET/v1_4/AISPApi.scala @@ -250,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 @@ -261,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) <- authorizeEndpoint(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 index 48611bb18..e970ead95 100644 --- 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 @@ -2,6 +2,7 @@ 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} @@ -52,6 +53,19 @@ object JSONFactory_STET_1_4 { `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 @@ -89,19 +103,23 @@ object JSONFactory_STET_1_4 { ) case class TransactionsJsonV1( - transactions_booked: List[TransactionJsonV1], - transactions_pending: List[TransactionJsonV1], - _links: List[ViewAccount] + 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( - transactionId: String, - creditorName: String, - creditorAccount: IbanJson, - amount: AmountOfMoneyV1, + entryReference: String, + creditDebitIndicator: String, + transactionAmount: AmountOfMoneyV1, bookingDate: Date, - valueDate: Date, - remittanceInformationUnstructured: String + status: String, + remittanceInformation: List[String] ) def createTransactionListJSON(accounts: List[BankAccount]): AccountsJsonV1 = @@ -133,33 +151,31 @@ object JSONFactory_STET_1_4 { def createTransactionJSON(transaction : ModeratedTransaction) : TransactionJsonV1 = { TransactionJsonV1( - transactionId = transaction.id.value, - creditorName = "", - creditorAccount = IbanJson(APIUtil.stringOptionOrNull(transaction.bankAccount.get.iban)), - amount = AmountOfMoneyV1(APIUtil.stringOptionOrNull(transaction.currency), transaction.amount.get.toString()), + entryReference = transaction.id.value, + creditDebitIndicator = "", + transactionAmount = AmountOfMoneyV1(APIUtil.stringOptionOrNull(transaction.currency),transaction.amount.get.toString()), bookingDate = transaction.startDate.get, - valueDate = transaction.finishDate.get, - remittanceInformationUnstructured = APIUtil.stringOptionOrNull(transaction.description) + status = "COMPLETED", + remittanceInformation = List(APIUtil.stringOptionOrNull(transaction.description)) ) } def createTransactionFromRequestJSON(transactionRequest : TransactionRequest) : TransactionJsonV1 = { TransactionJsonV1( - transactionId = transactionRequest.id.value, - creditorName = transactionRequest.name, - creditorAccount = IbanJson(transactionRequest.from.account_id), - amount = AmountOfMoneyV1(transactionRequest.charge.value.currency, transactionRequest.charge.value.amount), + entryReference = transactionRequest.id.value, + creditDebitIndicator = transactionRequest.name, + transactionAmount = AmountOfMoneyV1(transactionRequest.charge.value.currency,transactionRequest.charge.value.amount), bookingDate = transactionRequest.start_date, - valueDate = transactionRequest.end_date, - remittanceInformationUnstructured = transactionRequest.body.description + 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_booked =transactions.map(createTransactionJSON), - transactions_pending =transactionRequests.filter(_.status!="COMPLETED").map(createTransactionFromRequestJSON), - _links = ViewAccount(s"/${OBP_STET_1_4.version}/accounts/${transactionRequests.head.from.account_id}/balances")::Nil + transactions = transactions_booked:::transactions_pending:::Nil ) }