added two more endpoints for Berlin Group and added the basic tests

This commit is contained in:
hongwei1 2018-04-10 15:34:22 +02:00
parent 47fe0fb9db
commit 4207835ce5
13 changed files with 290 additions and 34 deletions

View File

@ -1,6 +1,6 @@
package code.api.ResourceDocs1_4_0
import code.api.berlin.group.v1.JSONFactory_BERLIN_GROUP_1.{Balances, CoreAccountJson_v1, CoreAccountsJson_v1, Transactions}
import code.api.berlin.group.v1.JSONFactory_BERLIN_GROUP_1.{Balances, CoreAccountJsonV1, CoreAccountsJsonV1, Transactions}
import code.api.util.APIUtil
import code.api.util.APIUtil.{defaultJValue, _}
import code.api.util.ApiRole._
@ -2074,7 +2074,7 @@ object SwaggerDefinitionsJSON {
)
val coreAccountsJsonV300 = CoreAccountsJsonV300(accounts = List(coreAccount))
val coreAccountJson_v1 = CoreAccountJson_v1(
val coreAccountJson_v1 = CoreAccountJsonV1(
id = "3dc3d5b3-7023-4848-9853-f5400a64e80f",
iban = "DE2310010010123456789",
currency = "EUR",
@ -2085,7 +2085,7 @@ object SwaggerDefinitionsJSON {
Transactions("/v1/accounts/3dc3d5b3-7023-4848-9853-f5400a64e80f/transactions")),
name = "Main Account"
)
val coreAccountsJson_v1 = CoreAccountsJson_v1(List(coreAccountJson_v1))
val coreAccountsJson_v1 = CoreAccountsJsonV1(List(coreAccountJson_v1))
val accountIdJson = AccountIdJson(
id = "5995d6a2-01b3-423c-a173-5481df49bdaf"

View File

@ -1,16 +1,20 @@
package code.api.berlin.group.v1
import code.api.APIFailureNewStyle
import code.api.ResourceDocs1_4_0.SwaggerDefinitionsJSON
import code.api.util.APIUtil._
import code.api.util.ApiVersion
import code.api.util.ErrorMessages.{UnknownError, UserNotLoggedIn}
import code.api.util.ErrorMessages.{BankAccountNotFound, UnknownError, UserNoPermissionAccessView, UserNotLoggedIn, ViewNotFound}
import code.bankconnectors.Connector
import code.model._
import code.util.Helper
import code.views.Views
import net.liftweb.http.rest.RestHelper
import scala.collection.immutable.Nil
import scala.collection.mutable.ArrayBuffer
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.Future
trait APIMethods_BERLIN_GROUP_1 {
//needs to be a RestHelper to get access to JsonGet, JsonPost, etc.
@ -25,15 +29,15 @@ trait APIMethods_BERLIN_GROUP_1 {
resourceDocs += ResourceDoc(
corePrivateAccountsAllBanks1,
readAccountList,
implementedInApiVersion,
"corePrivateAccountsAllBanks1",
"readAccountList",
"GET",
"/accounts",
"Experimental - BG Get Accounts at all Banks",
s"""Get private accounts at all banks.
|Returns the list of accounts containing private views for the user at all banks.
|
"Experimental - BG Read Account List",
s"""
|Reads a list of bank accounts, with balances where required.
|It is assumed that a consent of the PSU to this access is already given and stored on the ASPSP system.
|
|${authenticationRequiredMessage(true)}
|""",
@ -44,11 +48,11 @@ trait APIMethods_BERLIN_GROUP_1 {
List(apiTagBerlinGroup, apiTagAccount, apiTagPrivateData))
apiRelations += ApiRelation(corePrivateAccountsAllBanks1, corePrivateAccountsAllBanks1, "self")
apiRelations += ApiRelation(readAccountList, readAccountList, "self")
lazy val corePrivateAccountsAllBanks1 : OBPEndpoint = {
lazy val readAccountList : OBPEndpoint = {
//get private accounts for all banks
case "accounts" :: Nil JsonGet _ => {
cc =>
@ -58,13 +62,100 @@ trait APIMethods_BERLIN_GROUP_1 {
availablePrivateAccounts <- Views.views.vend.getPrivateBankAccountsFuture(u)
coreAccounts <- {Connector.connector.vend.getCoreBankAccountsFuture(availablePrivateAccounts, callContext)}
} yield {
(JSONFactory_BERLIN_GROUP_1.createCoreAccountsByCoreAccountsJSON(coreAccounts.getOrElse(Nil)), callContext)
(JSONFactory_BERLIN_GROUP_1.createTransactionListJSON(coreAccounts.getOrElse(Nil)), callContext)
}
}
}
resourceDocs += ResourceDoc(
readBalance,
implementedInApiVersion,
"readBalance",
"GET",
"/accounts/ACCOUNT_ID/balances",
"Experimental - BG Read Balance",
s"""
|Reads account data from a given account addressed by account-id.
|
|${authenticationRequiredMessage(true)}
|""",
emptyObjectJson,
SwaggerDefinitionsJSON.coreAccountsJson_v1,
List(UserNotLoggedIn,UnknownError),
Catalogs(Core, PSD2, OBWG),
List(apiTagBerlinGroup, apiTagAccount, apiTagPrivateData))
lazy val readBalance : OBPEndpoint = {
//get private accounts for all banks
case "accounts" :: AccountId(accountId) :: "balances" :: Nil JsonGet _ => {
cc =>
for {
(user, callContext) <- extractCallContext(UserNotLoggedIn, cc)
u <- unboxFullAndWrapIntoFuture{ user }
account <- Future { BankAccount(BankId(defaultBankId), accountId, callContext) } map {
x => fullBoxOrException(x ~> APIFailureNewStyle(BankAccountNotFound, 400, Some(cc.toLight)))
} map { unboxFull(_) }
view <- Views.views.vend.viewFuture(ViewId("owner"), BankIdAccountId(account.bankId, account.accountId)) map {
x => fullBoxOrException(x ~> APIFailureNewStyle(ViewNotFound, 400, Some(cc.toLight)))
} map { unboxFull(_) }
_ <- Helper.booleanToFuture(failMsg = UserNoPermissionAccessView) {(u.hasViewAccess(view))}
moderatedAccount <- Future {account.moderatedBankAccount(view, user)} map {
x => fullBoxOrException(x ~> APIFailureNewStyle(ViewNotFound, 400, Some(cc.toLight)))
} map { unboxFull(_) }
} yield {
(JSONFactory_BERLIN_GROUP_1.createAccountBalanceJSON(moderatedAccount), callContext)
}
}
}
resourceDocs += ResourceDoc(
readTransactionList,
implementedInApiVersion,
"readTransactionList",
"GET",
"/accounts/ACCOUNT_ID/transactions",
"Experimental - BG Read Account Transactions",
s"""
|Reads account data from a given account addressed by account-id.
|${authenticationRequiredMessage(true)}
|""",
emptyObjectJson,
SwaggerDefinitionsJSON.coreAccountsJson_v1,
List(UserNotLoggedIn,UnknownError),
Catalogs(Core, PSD2, OBWG),
List(apiTagBerlinGroup, apiTagAccount, apiTagPrivateData))
lazy val readTransactionList : OBPEndpoint = {
//get private accounts for all banks
case "accounts" :: AccountId(accountId) :: "transactions" :: Nil JsonGet _ => {
cc =>
for {
(user, callContext) <- extractCallContext(UserNotLoggedIn, cc)
u <- unboxFullAndWrapIntoFuture{ user }
bankAccount <- Future { BankAccount(BankId(defaultBankId), accountId, callContext) } map {
x => fullBoxOrException(x ~> APIFailureNewStyle(BankAccountNotFound, 400, Some(cc.toLight)))
} map { unboxFull(_) }
view <- Views.views.vend.viewFuture(ViewId("owner"), BankIdAccountId(bankAccount.bankId, bankAccount.accountId)) map {
x => fullBoxOrException(x ~> APIFailureNewStyle(ViewNotFound, 400, Some(cc.toLight)))
} map { unboxFull(_) }
params <- Future { getTransactionParams(callContext.get.requestHeaders)} map {
x => fullBoxOrException(x ~> APIFailureNewStyle(BankAccountNotFound, 400, Some(cc.toLight)))
} map { unboxFull(_) }
transactionRequests <- Future { Connector.connector.vend.getTransactionRequests210(u, bankAccount)} map {
x => fullBoxOrException(x ~> APIFailureNewStyle(BankAccountNotFound, 400, Some(cc.toLight)))
} map { unboxFull(_) }
} yield {
//TODO here, we map the `transactionRequests` to the Berlin Group `transactions`.
(JSONFactory_BERLIN_GROUP_1.createTransactionsJson(transactionRequests), callContext)
}
}
}
}
}

View File

@ -1,6 +1,11 @@
package code.api.berlin.group.v1
import code.model.CoreAccount
import java.util.Date
import code.api.util.APIUtil
import code.api.v2_1_0.IbanJson
import code.model.{CoreAccount, ModeratedBankAccount}
import code.transactionrequests.TransactionRequests.TransactionRequest
import scala.collection.immutable.List
@ -11,7 +16,8 @@ object JSONFactory_BERLIN_GROUP_1 {
trait links
case class Balances(balances: String) extends links
case class Transactions(trasactions: String) extends links
case class CoreAccountJson_v1(
case class viewAccount(viewAccount: String) extends links
case class CoreAccountJsonV1(
id: String,
iban: String,
currency: String,
@ -21,21 +27,84 @@ object JSONFactory_BERLIN_GROUP_1 {
name: String
)
case class CoreAccountsJson_v1(`account-list`: List[CoreAccountJson_v1])
case class CoreAccountsJsonV1(`account-list`: List[CoreAccountJsonV1])
case class AmountOfMoneyV1(
currency : String,
content : String
)
case class ClosingBookedBody(
amount : AmountOfMoneyV1,
date: 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 createCoreAccountsByCoreAccountsJSON(coreAccounts: List[CoreAccount]) = {
CoreAccountsJson_v1(coreAccounts.map(
x => CoreAccountJson_v1(
def createTransactionListJSON(coreAccounts: List[CoreAccount]) = {
CoreAccountsJsonV1(coreAccounts.map(
x => CoreAccountJsonV1(
id = x.id,
iban = if (x.account_routing.scheme == "IBAN") x.account_routing.address else "",
currency = "",
accountType = "",
cashAccountType = "",
_links = Nil,
_links = Balances(s"/${OBP_BERLIN_GROUP_1.version}/accounts/${x.id}/balances") :: Transactions(s"/${OBP_BERLIN_GROUP_1.version}/accounts/${x.id}/transactions") :: Nil,
name = x.label)
)
)
}
def createAccountBalanceJSON(moderatedAccount : ModeratedBankAccount) = {
AccountBalances(
AccountBalance(
closingBooked = ClosingBookedBody(amount = AmountOfMoneyV1(currency=moderatedAccount.currency.getOrElse(""), content = moderatedAccount.balance ), date = APIUtil.exampleDate),
//TODO these expected fileds need be fixed.
expected = ExpectedBody (amount = AmountOfMoneyV1(currency=moderatedAccount.currency.getOrElse(""), content = moderatedAccount.balance), lastActionDateTime = APIUtil.exampleDate)
) :: Nil
)
}
def createTransactionJSON(transactionRequest : TransactionRequest) : TransactionJsonV1 = {
TransactionJsonV1(
transactionId = transactionRequest.id.value,
creditorName ="",
creditorAccount = IbanJson(transactionRequest.id.value),
amount = AmountOfMoneyV1(transactionRequest.charge.value.currency, ""),
bookingDate = transactionRequest.start_date,
valueDate = transactionRequest.end_date,
remittanceInformationUnstructured = transactionRequest.body.description
)
}
def createTransactionsJson(transactionRequests: List[TransactionRequest]) : TransactionsJsonV1 = {
TransactionsJsonV1(
transactions_booked =transactionRequests.filter(_.status=="COMPLETED").map(createTransactionJSON),
transactions_pending =transactionRequests.filter(_.status!="COMPLETED").map(createTransactionJSON),
_links = viewAccount(s"/${OBP_BERLIN_GROUP_1.version}/accounts/${transactionRequests.head.from.account_id}/balances")::Nil
)
}
}

View File

@ -50,7 +50,11 @@ object OBP_BERLIN_GROUP_1 extends OBPRestHelper with APIMethods_BERLIN_GROUP_1 w
val version = ApiVersion.berlinGroupV1
val versionStatus = "DRAFT"
val endpointsOf1 = Implementations1.corePrivateAccountsAllBanks1 :: Nil
val endpointsOf1 =
Implementations1.readAccountList ::
Implementations1.readBalance ::
Implementations1.readTransactionList ::
Nil
val allResourceDocs = Implementations1.resourceDocs

View File

@ -2020,4 +2020,6 @@ Returns a string showed to the developer
// All OBP REST end points start with /obp
def getObpApiRoot: String = s"$getServerUrl/obp"
lazy val defaultBankId = APIUtil.getPropsValue("defaultBank.bank_id", "DEFAULT_BANK_ID_NOT_SET")
}

View File

@ -53,11 +53,6 @@ trait APIMethods200 {
// helper methods begin here
val defaultBankId = APIUtil.getPropsValue("defaultBank.bank_id", "DEFAULT_BANK_ID_NOT_SET")
// shows a small representation of View
private def publicBankAccountBasicListToJson(bankAccounts: List[BankAccount], publicViews : List[View]): JValue = {
Extraction.decompose(publicBasicBankAccountList(bankAccounts, publicViews))

View File

@ -0,0 +1,9 @@
package code.api.berlin.group.v1
import code.setup.ServerSetupWithTestData
trait BerlinGroupV1ServerSetup extends ServerSetupWithTestData {
def BerlinGroup_V1Request = baseRequest / "berlin-group" / "v1"
}

View File

@ -0,0 +1,49 @@
package code.api.berlin.group.v1
import code.api.util.APIUtil.OAuth._
import code.setup.{APIResponse, DefaultUsers}
import org.scalatest.Tag
//TODO just a quick tests, when the endpoints are clear, we need more tests here.
class BerlinGroupV1Tests extends BerlinGroupV1ServerSetup with DefaultUsers {
object BerlinGroup extends Tag("berlinGroup")
feature("test the BG Read Account List")
{
scenario("Successful Case", BerlinGroup)
{
val requestGetAll = (BerlinGroup_V1Request / "accounts" ).GET <@(user1)
val response: APIResponse = makeGetRequest(requestGetAll)
Then("We should get a 200 ")
response.code should equal(200)
}
}
feature("test the BG Read Balance")
{
scenario("Successful Case", BerlinGroup)
{
val Account_Id = testAccountId1
val requestGetAll = (BerlinGroup_V1Request / "accounts"/"testAccount1"/"balances" ).GET <@(user1)
val response = makeGetRequest(requestGetAll)
Then("We should get a 200 ")
response.code should equal(200)
}
}
feature("test the BG Read Account Transactions")
{
scenario("Successful Case", BerlinGroup)
{
val requestGetAll = (BerlinGroup_V1Request / "accounts"/"testAccount1"/"transactions" ).GET <@(user1)
val response = makeGetRequest(requestGetAll)
Then("We should get a 200 ")
response.code should equal(200)
}
}
}

View File

@ -33,7 +33,7 @@ class CreateUserTest extends V200ServerSetup with BeforeAndAfter {
val testConsumer = Consumers.consumers.vend.createConsumer(Some(KEY), Some(SECRET), Some(true), Some("test application"), None, None, None, None, None)
}
val consumer = new Consumer(KEY, SECRET)
override lazy val consumer = new Consumer(KEY, SECRET)
def oauthRequest = baseRequest / "oauth"
def directLoginRequest = baseRequest / "my" / "logins" / "direct"

View File

@ -7,11 +7,11 @@ import bootstrap.liftweb.ToSchemify
import code.accountholder.AccountHolders
import code.api.util.APIUtil
import code.entitlement.Entitlement
import code.metadata.counterparties.{Counterparties, CounterpartyTrait}
import code.metadata.counterparties.{Counterparties, CounterpartyTrait, MappedCounterparty}
import code.model._
import code.model.dataAccess._
import code.transaction.MappedTransaction
import code.transactionrequests.TransactionRequests
import code.transactionrequests.{MappedTransactionRequest, TransactionRequests}
import code.views.Views
import net.liftweb.common.Box
import net.liftweb.mapper.{By, MetaMapper}
@ -135,6 +135,24 @@ trait LocalMappedConnectorTestSetup extends TestConnectorSetupWithStandardPermis
.toTransaction.orNull
}
override protected def createTransactionRequest(account: BankAccount) = {
MappedTransactionRequest.create
.mTransactionRequestId(UUID.randomUUID().toString)
.mType("SANDBOX_TAN")
.mFrom_BankId(account.bankId.value)
.mFrom_AccountId(account.accountId.value)
.mTo_BankId(randomString(5))
.mTo_AccountId(randomString(5))
.mBody_Value_Currency(account.currency)
.mBody_Value_Amount("1000")
.mBody_Description("This is a description..")
.mStatus("COMPLETED")
.mStartDate(now)
.mEndDate(now)
.saveMe
}
override protected def wipeTestData() = {
//returns true if the model should not be wiped after each test
def exclusion(m : MetaMapper[_]) = {
@ -149,6 +167,10 @@ trait LocalMappedConnectorTestSetup extends TestConnectorSetupWithStandardPermis
Views.views.vend.bulkDeleteAllPermissionsAndViews()
AccountHolders.accountHolders.vend.bulkDeleteAllAccountHolders()
TransactionRequests.transactionRequestProvider.vend.bulkDeleteTransactionRequests()
MappedTransaction.bulkDelete_!!()
MappedBank.bulkDelete_!!()
MappedBankAccount.bulkDelete_!!()
MappedCounterparty.bulkDelete_!!()
}
}
}

View File

@ -99,5 +99,7 @@ trait LocalRecordConnectorTestSetup extends TestConnectorSetupWithStandardPermis
env.save(true)
}
override protected def createTransactionRequest(account: BankAccount) = Unit
}

View File

@ -89,7 +89,7 @@ trait ServerSetup extends FeatureSpec with SendServerRequests
}
trait ServerSetupWithTestData extends ServerSetup with DefaultConnectorTestSetup {
trait ServerSetupWithTestData extends ServerSetup with DefaultConnectorTestSetup with DefaultUsers{
override def beforeEach() = {
super.beforeEach()
@ -97,9 +97,11 @@ trait ServerSetupWithTestData extends ServerSetup with DefaultConnectorTestSetup
//fake banks
val banks = createBanks()
//fake bank accounts
val accounts = createAccounts(banks)
val accounts = createAccounts(resourceUser1, banks)
//fake transactions
createTransactions(accounts)
//fake transactionRequests
createTransactionRequests(accounts)
}
override def afterEach() = {

View File

@ -14,6 +14,7 @@ trait TestConnectorSetup {
@deprecated("Please use `createAccountAndOwnerView` instead, we need owner view for each account! ","2018-02-23")
protected def createAccount(bankId: BankId, accountId : AccountId, currency : String) : BankAccount
protected def createTransaction(account : BankAccount, startDate : Date, finishDate : Date)
protected def createTransactionRequest(account: BankAccount)
protected def updateAccountCurrency(bankId: BankId, accountId : AccountId, currency : String) : BankAccount
protected def createCounterparty(bankId: String, accountId: String, accountRoutingAddress: String, otherAccountRoutingScheme: String, isBeneficiary: Boolean, createdByUserId:String): CounterpartyTrait
@ -48,11 +49,11 @@ trait TestConnectorSetup {
* This will create the test accounts for testBanks.
* It will also create ownerView, PublicView and RandomView ...
*/
final protected def createAccounts(banks : Traversable[Bank]) : Traversable[BankAccount] = {
final protected def createAccounts(user: User, banks : Traversable[Bank]) : Traversable[BankAccount] = {
val testAccountCurrency = "EUR"
val accounts = banks.flatMap(bank => {
for { i <- 0 until 2 } yield {
createAccountAndOwnerView(None, bank.bankId, AccountId("testAccount"+i), testAccountCurrency)
createAccountAndOwnerView(Some(user), bank.bankId, AccountId("testAccount"+i), testAccountCurrency)
}
})
@ -107,6 +108,16 @@ trait TestConnectorSetup {
Connector.connector.vend.getTransactions(account.bankId, account.accountId, OBPOffset(0), OBPLimit(NUM_TRANSACTIONS))
})
}
final protected def createTransactionRequests(accounts : Traversable[BankAccount]) = {
val NUM_TRANSACTIONS = 10
accounts.foreach(account => {
for(i <- 0 until NUM_TRANSACTIONS)
createTransactionRequest(account)
}
)
}
final protected def createPaymentTestBank() : Bank =
createBank("payment-test-bank")