feature/Add endpoint createCustomer v5.0.0

This commit is contained in:
Marko Milić 2022-09-21 12:49:27 +02:00
parent c325fac91e
commit 264debb837
4 changed files with 185 additions and 2 deletions

View File

@ -2231,6 +2231,26 @@ object SwaggerDefinitionsJSON {
title = ExampleValue.titleExample.value,
branch_id = ExampleValue.branchIdExample.value,
name_suffix = ExampleValue.nameSuffixExample.value
)
val postCustomerJsonV500 =
PostCustomerJsonV500(
legal_name = ExampleValue.legalNameExample.value,
mobile_phone_number = ExampleValue.mobileNumberExample.value,
email = Some(ExampleValue.emailExample.value),
face_image = Some(customerFaceImageJson),
date_of_birth = Some(DateWithDayExampleObject),
relationship_status = Some(ExampleValue.relationshipStatusExample.value),
dependants = Some(ExampleValue.dependentsExample.value.toInt),
dob_of_dependants = Some(List(DateWithDayExampleObject)),
credit_rating = Some(customerCreditRatingJSON),
credit_limit = Some(amountOfMoneyJsonV121),
highest_education_attained = Some(ExampleValue.highestEducationAttainedExample.value),
employment_status = Some(ExampleValue.employmentStatusExample.value),
kyc_status = Some(ExampleValue.kycStatusExample.value.toBoolean),
last_ok_date = Some(DateWithDayExampleObject),
title = Some(ExampleValue.titleExample.value),
branch_id = Some(ExampleValue.branchIdExample.value),
name_suffix = Some(ExampleValue.nameSuffixExample.value)
)
val customerJsonV310 = CustomerJsonV310(

View File

@ -21,7 +21,7 @@ import code.views.Views
import com.github.dwickern.macros.NameOf.nameOf
import com.openbankproject.commons.ExecutionContext.Implicits.global
import com.openbankproject.commons.model.enums.StrongCustomerAuthentication
import com.openbankproject.commons.model.{BankId, UserAuthContextUpdateStatus}
import com.openbankproject.commons.model.{BankId, CreditLimit, CreditRating, CustomerFaceImage, UserAuthContextUpdateStatus}
import com.openbankproject.commons.util.ApiVersion
import net.liftweb.common.Full
import net.liftweb.http.Req
@ -799,6 +799,79 @@ trait APIMethods500 {
}
}
staticResourceDocs += ResourceDoc(
createCustomer,
implementedInApiVersion,
nameOf(createCustomer),
"POST",
"/banks/BANK_ID/customers",
"Create Customer",
s"""
|The Customer resource stores the customer number (which is set by the backend), legal name, email, phone number, their date of birth, relationship status, education attained, a url for a profile image, KYC status etc.
|Dates need to be in the format 2013-01-21T23:08:00Z
|
|Note: If you need to set a specific customer number, use the Update Customer Number endpoint after this call.
|
|${authenticationRequiredMessage(true)}
|""",
postCustomerJsonV500,
customerJsonV310,
List(
$UserNotLoggedIn,
$BankNotFound,
InvalidJsonFormat,
CustomerNumberAlreadyExists,
UserNotFoundById,
CustomerAlreadyExistsForUser,
CreateConsumerError,
UnknownError
),
List(apiTagCustomer, apiTagPerson, apiTagNewStyle),
Some(List(canCreateCustomer,canCreateCustomerAtAnyBank))
)
lazy val createCustomer : OBPEndpoint = {
case "banks" :: BankId(bankId) :: "customers" :: Nil JsonPost json -> _ => {
cc =>
for {
postedData <- NewStyle.function.tryons(s"$InvalidJsonFormat The Json body should be the $PostCustomerJsonV310 ", 400, cc.callContext) {
json.extract[PostCustomerJsonV500]
}
_ <- Helper.booleanToFuture(failMsg = InvalidJsonContent + s" The field dependants(${postedData.dependants.getOrElse(0)}) not equal the length(${postedData.dob_of_dependants.getOrElse(Nil).length }) of dob_of_dependants array", 400, cc.callContext) {
postedData.dependants.getOrElse(0) == postedData.dob_of_dependants.getOrElse(Nil).length
}
(customer, callContext) <- NewStyle.function.createCustomer(
bankId,
postedData.legal_name,
postedData.mobile_phone_number,
postedData.email.getOrElse(""),
CustomerFaceImage(
postedData.face_image.map(_.date).getOrElse(null),
postedData.face_image.map(_.url).getOrElse("")
),
postedData.date_of_birth.getOrElse(null),
postedData.relationship_status.getOrElse(""),
postedData.dependants.getOrElse(0),
postedData.dob_of_dependants.getOrElse(Nil),
postedData.highest_education_attained.getOrElse(""),
postedData.employment_status.getOrElse(""),
postedData.kyc_status.getOrElse(false),
postedData.last_ok_date.getOrElse(null),
postedData.credit_rating.map(i => CreditRating(i.rating, i.source)),
postedData.credit_limit.map(i => CreditLimit(i.currency, i.amount)),
postedData.title.getOrElse(""),
postedData.branch_id.getOrElse(""),
postedData.name_suffix.getOrElse(""),
cc.callContext,
)
} yield {
(JSONFactory310.createCustomerJson(customer), HttpCode.`201`(callContext))
}
}
}
staticResourceDocs += ResourceDoc(
getMyCustomersAtAnyBank,
implementedInApiVersion,

View File

@ -30,10 +30,12 @@ import java.util.Date
import code.api.util.APIUtil.stringOrNull
import code.api.v1_2_1.BankRoutingJsonV121
import code.api.v1_4_0.JSONFactory1_4_0.CustomerFaceImageJson
import code.api.v2_1_0.CustomerCreditRatingJSON
import code.api.v3_1_0.PostConsentEntitlementJsonV310
import code.api.v4_0_0.BankAttributeBankResponseJsonV400
import code.bankattribute.BankAttribute
import com.openbankproject.commons.model.{AccountRoutingJsonV121, Bank, UserAuthContext, UserAuthContextUpdate}
import com.openbankproject.commons.model.{AccountRoutingJsonV121, AmountOfMoneyJsonV121, Bank, UserAuthContext, UserAuthContextUpdate}
import net.liftweb.json.JsonAST.JValue
import scala.collection.immutable.List
@ -58,6 +60,26 @@ case class BankJson500(
attributes: Option[List[BankAttributeBankResponseJsonV400]]
)
case class PostCustomerJsonV500(
legal_name: String,
mobile_phone_number: String,
email: Option[String] = None,
face_image: Option[CustomerFaceImageJson] = None,
date_of_birth: Option[Date] = None,
relationship_status: Option[String] = None,
dependants: Option[Int] = None,
dob_of_dependants: Option[List[Date]] = None,
credit_rating: Option[CustomerCreditRatingJSON] = None,
credit_limit: Option[AmountOfMoneyJsonV121] = None,
highest_education_attained: Option[String] = None,
employment_status: Option[String] = None,
kyc_status: Option[Boolean] = None,
last_ok_date: Option[Date] = None,
title: Option[String] = None,
branch_id: Option[String] = None,
name_suffix: Option[String] = None
)
case class UserAuthContextJsonV500(
user_auth_context_id: String,
user_id: String,

View File

@ -71,6 +71,7 @@ class CustomerTest extends V500ServerSetupAsync {
object ApiEndpoint2 extends Tag(nameOf(Implementations5_0_0.getMyCustomersAtBank))
object ApiEndpoint3 extends Tag(nameOf(Implementations5_0_0.getCustomersAtOneBank))
object ApiEndpoint4 extends Tag(nameOf(Implementations5_0_0.getCustomersMinimalAtOneBank))
object ApiEndpoint5 extends Tag(nameOf(Implementations5_0_0.createCustomer))
lazy val bankId = testBankId1.value
val postCustomerJson = SwaggerDefinitionsJSON.postCustomerJsonV310.copy(last_ok_date= new Date())
@ -209,7 +210,74 @@ class CustomerTest extends V500ServerSetupAsync {
responseApiEndpoint4.body.extract[ErrorMessage].message contains (UserHasMissingRoles ) should be (true)
responseApiEndpoint4.body.extract[ErrorMessage].message contains (CanGetCustomersMinimal.toString()) should be (true)
}
}
feature(s"Create Customer $VersionOfApi - Unauthorized access") {
scenario("We will call the endpoint without user credentials", ApiEndpoint5, VersionOfApi) {
When(s"We make a request $VersionOfApi")
val request = (v5_0_0_Request / "banks" / bankId / "customers").POST
val response = makePostRequest(request, write(postCustomerJson))
Then("We should get a 401")
response.code should equal(401)
And("error should be " + UserNotLoggedIn)
response.body.extract[ErrorMessage].message should equal (UserNotLoggedIn)
}
}
feature(s"Create Customer $VersionOfApi - Authorized access") {
scenario("We will call the endpoint with user credentials", ApiEndpoint5, VersionOfApi) {
When(s"We make a request $VersionOfApi")
val request = (v5_0_0_Request / "banks" / bankId / "customers").POST <@(user1)
val response = makePostRequest(request, write(postCustomerJson))
Then("We should get a 403")
response.code should equal(403)
val errorMsg = UserHasMissingRoles + canCreateCustomer + " or " + canCreateCustomerAtAnyBank
And("error should be " + errorMsg)
val errorMessage = response.body.extract[ErrorMessage].message
errorMessage contains (UserHasMissingRoles) should be (true)
errorMessage contains (canCreateCustomerAtAnyBank.toString()) should be (true)
}
scenario("We will call the endpoint with a user credentials and a proper role", ApiEndpoint5, VersionOfApi) {
Entitlement.entitlement.vend.addEntitlement(bankId, resourceUser1.userId, CanCreateCustomer.toString)
When(s"We make a request $VersionOfApi")
val request = (v5_0_0_Request / "banks" / bankId / "customers").POST <@(user1)
val response = makePostRequest(request, write(postCustomerJson))
Then("We should get a 201")
response.code should equal(201)
val infoPost = response.body.extract[CustomerJsonV310]
When("We make the request: Get Customer specified by CUSTOMER_ID")
Entitlement.entitlement.vend.addEntitlement(bankId, resourceUser1.userId, CanGetCustomer.toString)
val requestGet = (v5_0_0_Request / "banks" / bankId / "customers" / infoPost.customer_id).GET <@ (user1)
val responseGet = makeGetRequest(requestGet)
Then("We should get a 200")
responseGet.code should equal(200)
And("We should get the right information back")
val infoGet = responseGet.body.extract[CustomerJsonV310]
And("POST feedback and GET feedback must be the same")
infoGet should equal(infoPost)
}
scenario("We will call the endpoint with a user credentials and a proper role and minimal POST JSON", ApiEndpoint5, VersionOfApi) {
Entitlement.entitlement.vend.addEntitlement(bankId, resourceUser1.userId, CanCreateCustomer.toString)
When(s"We make a request $VersionOfApi")
val request = (v5_0_0_Request / "banks" / bankId / "customers").POST <@(user1)
val response = makePostRequest(request, write(PostCustomerJsonV500(legal_name = "Legal Name",mobile_phone_number = "+44 07972 444 876")))
Then("We should get a 201")
response.code should equal(201)
val infoPost = response.body.extract[CustomerJsonV310]
When("We make the request: Get Customer specified by CUSTOMER_ID")
Entitlement.entitlement.vend.addEntitlement(bankId, resourceUser1.userId, CanGetCustomer.toString)
val requestGet = (v5_0_0_Request / "banks" / bankId / "customers" / infoPost.customer_id).GET <@ (user1)
val responseGet = makeGetRequest(requestGet)
Then("We should get a 200")
responseGet.code should equal(200)
And("We should get the right information back")
val infoGet = responseGet.body.extract[CustomerJsonV310]
And("POST feedback and GET feedback must be the same")
infoGet should equal(infoPost)
}
}