Merge pull request #2214 from hongwei1/develop

feature/OBPv510 added new atms endpoints
This commit is contained in:
Simon Redfern 2023-04-05 14:28:10 +02:00 committed by GitHub
commit 9ed2eac430
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 652 additions and 32 deletions

View File

@ -36,7 +36,7 @@ import com.openbankproject.commons.util.{ApiVersion, FieldNameApiVersions, Refle
import net.liftweb.json
import java.net.URLEncoder
import code.api.v5_1_0.{AtmAttributeJsonV510, AtmAttributeResponseJsonV510, CertificateInfoJsonV510, CurrenciesJsonV510, CurrencyJsonV510}
import code.api.v5_1_0.{AtmsJsonV510, _}
import code.endpointMapping.EndpointMappingCommons
import scala.collection.immutable.List
@ -4018,13 +4018,16 @@ object SwaggerDefinitionsJSON {
val atmAttributeResponseJsonV510 = AtmAttributeResponseJsonV510(
bank_id = bankIdExample.value,
atm_id = atmIdExample.value,
atm_attribute_id = "613c83ea-80f9-4560-8404-b9cd4ec42a7f",
name = "OVERDRAFT_START_DATE",
`type` = "DATE_WITH_DAY",
value = "2012-04-23",
is_active = Some(true)
atm_attribute_id = atmAttributeIdExample.value,
name = nameExample.value,
`type` = typeExample.value,
value = valueExample.value,
is_active = Some(activeExample.value.toBoolean)
)
val atmAttributesResponseJsonV510 = AtmAttributesResponseJsonV510(
List(atmAttributeResponseJsonV510)
)
val accountAttributeJson = AccountAttributeJson(
name = "OVERDRAFT_START_DATE",
@ -5284,7 +5287,48 @@ object SwaggerDefinitionsJSON {
total_duration = BigDecimal(durationExample.value),
backend_messages= List(inboundStatusMessage),
)
val atmJsonV510 = AtmJsonV510(
id = Some(atmIdExample.value),
bank_id = bankIdExample.value,
name = atmNameExample.value,
address = addressJsonV300,
location = locationJson,
meta = metaJson,
monday = openingTimesV300,
tuesday = openingTimesV300,
wednesday = openingTimesV300,
thursday = openingTimesV300,
friday = openingTimesV300,
saturday = openingTimesV300,
sunday = openingTimesV300,
is_accessible = isAccessibleExample.value,
located_at = locatedAtExample.value,
more_info = moreInfoExample.value,
has_deposit_capability = hasDepositCapabilityExample.value,
supported_languages = supportedLanguagesJson.supported_languages,
services = atmServicesJson.services,
accessibility_features = accessibilityFeaturesJson.accessibility_features,
supported_currencies = supportedCurrenciesJson.supported_currencies,
notes = atmNotesJson.notes,
location_categories = atmLocationCategoriesJsonV400.location_categories,
minimum_withdrawal = atmMinimumWithdrawalExample.value,
branch_identification = atmBranchIdentificationExample.value,
site_identification = siteIdentification.value,
site_name = atmSiteNameExample.value,
cash_withdrawal_national_fee = cashWithdrawalNationalFeeExample.value,
cash_withdrawal_international_fee = cashWithdrawalInternationalFeeExample.value,
balance_inquiry_fee = balanceInquiryFeeExample.value,
atm_type = atmTypeExample.value,
phone = phoneExample.value,
attributes = Some(List(atmAttributeResponseJsonV510))
)
val atmsJsonV510 = AtmsJsonV510(
atms = List(atmJsonV510)
)
//The common error or success format.
//Just some helper format to use in Json
case class NotSupportedYet()

View File

@ -858,6 +858,9 @@ object ExampleValue {
lazy val atmIdExample = ConnectorField("atme0352a-9a0f-4bfa-b30b-9003aa467f51","A string that MUST uniquely identify the ATM on this OBP instance.")
glossaryItems += makeGlossaryItem("atm_id", atmIdExample)
lazy val atmAttributeIdExample = ConnectorField("xxaf2a-9a0f-4bfa-b30b-9003aa467f51","A string that MUST uniquely identify the ATM Attribute on this OBP instance.")
glossaryItems += makeGlossaryItem("ATM.attribute_id", atmIdExample)
lazy val atmNameExample = ConnectorField("Atm by the Lake","The name of the ATM")
glossaryItems += makeGlossaryItem("ATM.name", atmNameExample)
@ -897,6 +900,9 @@ object ExampleValue {
lazy val balanceInquiryFeeExample = ConnectorField(NoExampleProvided, NoDescriptionProvided)
glossaryItems += makeGlossaryItem("ATM.balance_inquiry_fee", balanceInquiryFeeExample)
lazy val atmTypeExample = ConnectorField(NoExampleProvided, NoDescriptionProvided)
glossaryItems += makeGlossaryItem("ATM.atm_type", atmTypeExample)
lazy val accessibilityFeaturesExample = ConnectorField("""["ATAC","ATAD"]""", NoDescriptionProvided)
glossaryItems += makeGlossaryItem("accessibility_features", accessibilityFeaturesExample)

View File

@ -3904,6 +3904,26 @@ object NewStyle extends MdcLoggable{
Connector.connector.vend.updateCustomerAccountLinkById(customerAccountLinkId: String, relationshipType: String, callContext: Option[CallContext]) map {
i => (unboxFullOrFail(i._1, callContext, UpdateCustomerAccountLinkError), i._2)
}
def getAtmsByBankId(bankId: BankId, offset: Box[String], limit: Box[String], callContext: Option[CallContext]): OBPReturnType[List[AtmT]] =
Connector.connector.vend.getAtms(bankId, callContext) map {
case Empty =>
fullBoxOrException(Empty ?~! atmsNotFound)
case Full((List(), callContext)) =>
Full(List())
case Full((list, _)) => Full(list)
case Failure(msg, _, _) => fullBoxOrException(Empty ?~! msg)
case ParamFailure(msg, _, _, _) => fullBoxOrException(Empty ?~! msg)
} map {
unboxFull(_)
} map {
atm =>
// Before we slice we need to sort in order to keep consistent results
(atm.sortWith(_.atmId.value < _.atmId.value)
// Slice the result in next way: from=offset and until=offset + limit
.slice(offset.getOrElse("0").toInt, offset.getOrElse("0").toInt + limit.getOrElse("100").toInt)
, callContext)
}
}
}

View File

@ -11686,22 +11686,7 @@ trait APIMethods400 {
case _ => true
}
}
(atms, callContext) <- Connector.connector.vend.getAtms(bankId, callContext) map {
case Empty =>
fullBoxOrException(Empty ?~! atmsNotFound)
case Full((List(), callContext)) =>
Full(List())
case Full((list, _)) =>Full(list)
case Failure(msg, _, _) => fullBoxOrException(Empty ?~! msg)
case ParamFailure(msg,_,_,_) => fullBoxOrException(Empty ?~! msg)
} map { unboxFull(_) } map {
branch =>
// Before we slice we need to sort in order to keep consistent results
(branch.sortWith(_.atmId.value < _.atmId.value)
// Slice the result in next way: from=offset and until=offset + limit
.slice(offset.getOrElse("0").toInt, offset.getOrElse("0").toInt + limit.getOrElse("100").toInt)
,callContext)
}
(atms, callContext) <- NewStyle.function.getAtmsByBankId(bankId, offset, limit, cc.callContext)
} yield {
(JSONFactory400.createAtmsJsonV400(atms), HttpCode.`200`(callContext))
}

View File

@ -9,10 +9,12 @@ import code.api.util.ApiTag._
import code.api.util.ErrorMessages.{$UserNotLoggedIn, BankNotFound, ConsentNotFound, InvalidJsonFormat, UnknownError, UserNotFoundByUserId, UserNotLoggedIn, _}
import code.api.util.{APIUtil, ApiRole, CallContext, CurrencyUtil, NewStyle, X509}
import code.api.util.NewStyle.HttpCode
import code.api.v3_0_0.JSONFactory300
import code.api.v3_0_0.JSONFactory300.createAggregateMetricJson
import code.api.v3_1_0.ConsentJsonV310
import code.api.v3_1_0.JSONFactory310.createBadLoginStatusJson
import code.api.v4_0_0.{JSONFactory400, PostApiCollectionJson400}
import code.atmattribute.AtmAttribute
import code.consent.Consents
import code.loginattempts.LoginAttempt
import code.metrics.APIMetrics
@ -24,10 +26,11 @@ import code.util.Helper
import code.views.system.{AccountAccess, ViewDefinition}
import com.github.dwickern.macros.NameOf.nameOf
import com.openbankproject.commons.ExecutionContext.Implicits.global
import com.openbankproject.commons.model.{AtmId, BankId}
import com.openbankproject.commons.model.{AtmId, AtmT, BankId}
import com.openbankproject.commons.model.enums.AtmAttributeType
import com.openbankproject.commons.util.{ApiVersion, ScannedApiVersion}
import net.liftweb.common.Full
import net.liftweb.http.S
import net.liftweb.http.rest.RestHelper
import scala.collection.immutable.{List, Nil}
@ -373,7 +376,7 @@ trait APIMethods510 {
|
|""",
EmptyBody,
transactionAttributesResponseJson,
atmAttributesResponseJsonV510,
List(
$UserNotLoggedIn,
$BankNotFound,
@ -947,6 +950,182 @@ trait APIMethods510 {
}
}
staticResourceDocs += ResourceDoc(
createAtm,
implementedInApiVersion,
nameOf(createAtm),
"POST",
"/banks/BANK_ID/atms",
"Create ATM",
s"""Create ATM.""",
atmJsonV510,
atmJsonV510,
List(
$UserNotLoggedIn,
InvalidJsonFormat,
UnknownError
),
List(apiTagATM, apiTagNewStyle),
Some(List(canCreateAtm, canCreateAtmAtAnyBank))
)
lazy val createAtm: OBPEndpoint = {
case "banks" :: BankId(bankId) :: "atms" :: Nil JsonPost json -> _ => {
cc =>
for {
atmJsonV510 <- NewStyle.function.tryons(s"$InvalidJsonFormat The Json body should be the ${classOf[AtmJsonV510]}", 400, cc.callContext) {
val atm = json.extract[AtmJsonV510]
//Make sure the Create contains proper ATM ID
atm.id.get
atm
}
_ <- Helper.booleanToFuture(s"$InvalidJsonValue BANK_ID has to be the same in the URL and Body", 400, cc.callContext) {
atmJsonV510.bank_id == bankId.value
}
atm <- NewStyle.function.tryons(CouldNotTransformJsonToInternalModel + " Atm", 400, cc.callContext) {
JSONFactory510.transformToAtmFromV510(atmJsonV510)
}
(atm, callContext) <- NewStyle.function.createOrUpdateAtm(atm, cc.callContext)
(atmAttributes, callContext) <- NewStyle.function.getAtmAttributesByAtm(bankId, atm.atmId, callContext)
} yield {
(JSONFactory510.createAtmJsonV510(atm, atmAttributes), HttpCode.`201`(callContext))
}
}
}
staticResourceDocs += ResourceDoc(
updateAtm,
implementedInApiVersion,
nameOf(updateAtm),
"PUT",
"/banks/BANK_ID/atms/ATM_ID",
"UPDATE ATM",
s"""Update ATM.""",
atmJsonV510.copy(id = None, attributes = None),
atmJsonV510,
List(
$UserNotLoggedIn,
InvalidJsonFormat,
UnknownError
),
List(apiTagATM, apiTagNewStyle),
Some(List(canUpdateAtm, canUpdateAtmAtAnyBank))
)
lazy val updateAtm: OBPEndpoint = {
case "banks" :: BankId(bankId) :: "atms" :: AtmId(atmId) :: Nil JsonPut json -> _ => {
cc =>
for {
(atm, callContext) <- NewStyle.function.getAtm(bankId, atmId, cc.callContext)
atmJsonV510 <- NewStyle.function.tryons(s"$InvalidJsonFormat The Json body should be the ${classOf[AtmJsonV510]}", 400, callContext) {
json.extract[AtmJsonV510]
}
_ <- Helper.booleanToFuture(s"$InvalidJsonValue BANK_ID has to be the same in the URL and Body", 400, callContext) {
atmJsonV510.bank_id == bankId.value
}
atm <- NewStyle.function.tryons(CouldNotTransformJsonToInternalModel + " Atm", 400, callContext) {
JSONFactory510.transformToAtmFromV510(atmJsonV510.copy(id = Some(atmId.value)))
}
(atm, callContext) <- NewStyle.function.createOrUpdateAtm(atm, callContext)
(atmAttributes, callContext) <- NewStyle.function.getAtmAttributesByAtm(bankId, atm.atmId, callContext)
} yield {
(JSONFactory510.createAtmJsonV510(atm, atmAttributes), HttpCode.`201`(callContext))
}
}
}
staticResourceDocs += ResourceDoc(
getAtms,
implementedInApiVersion,
nameOf(getAtms),
"GET",
"/banks/BANK_ID/atms",
"Get Bank ATMS",
s"""Get Bank ATMS.""",
EmptyBody,
atmsJsonV510,
List(
$BankNotFound,
UnknownError
),
List(apiTagATM, apiTagNewStyle)
)
lazy val getAtms: OBPEndpoint = {
case "banks" :: BankId(bankId) :: "atms" :: Nil JsonGet _ => {
cc =>
val limit = S.param("limit")
val offset = S.param("offset")
for {
(_, callContext) <- getAtmsIsPublic match {
case false => authenticatedAccess(cc)
case true => anonymousAccess(cc)
}
_ <- Helper.booleanToFuture(failMsg = s"${InvalidNumber} limit:${limit.getOrElse("")}", cc = callContext) {
limit match {
case Full(i) => i.toList.forall(c => Character.isDigit(c) == true)
case _ => true
}
}
_ <- Helper.booleanToFuture(failMsg = maximumLimitExceeded, cc = callContext) {
limit match {
case Full(i) if i.toInt > 10000 => false
case _ => true
}
}
(atms, callContext) <- NewStyle.function.getAtmsByBankId(bankId, offset, limit, callContext)
atmAndAttributesTupleList: List[(AtmT, List[AtmAttribute])] <- Future.sequence(atms.map(
atm => NewStyle.function.getAtmAttributesByAtm(bankId, atm.atmId, callContext).map(_._1).map(
attributes =>{
(atm-> attributes)
}
)))
} yield {
(JSONFactory510.createAtmsJsonV510(atmAndAttributesTupleList), HttpCode.`200`(callContext))
}
}
}
resourceDocs += ResourceDoc(
getAtm,
implementedInApiVersion,
nameOf(getAtm),
"GET",
"/banks/BANK_ID/atms/ATM_ID",
"Get Bank ATM",
s"""Returns information about ATM for a single bank specified by BANK_ID and ATM_ID including:
|
|* Address
|* Geo Location
|* License the data under this endpoint is released under
|* ATM Attributes
|
|
|
|${authenticationRequiredMessage(!getAtmsIsPublic)}""".stripMargin,
EmptyBody,
atmJsonV510,
List(UserNotLoggedIn, BankNotFound, AtmNotFoundByAtmId, UnknownError),
List(apiTagATM, apiTagNewStyle)
)
lazy val getAtm: OBPEndpoint = {
case "banks" :: BankId(bankId) :: "atms" :: AtmId(atmId) :: Nil JsonGet req => {
cc =>
for {
(_, callContext) <- getAtmsIsPublic match {
case false => authenticatedAccess(cc)
case true => anonymousAccess(cc)
}
(_, callContext) <- NewStyle.function.getBank(bankId, callContext)
(atm, callContext) <- NewStyle.function.getAtm(bankId, atmId, callContext)
(atmAttributes, callContext) <- NewStyle.function.getAtmAttributesByAtm(bankId, atmId, callContext)
} yield {
(JSONFactory510.createAtmJsonV510(atm, atmAttributes), HttpCode.`200`(callContext))
}
}
}
}
}

View File

@ -29,12 +29,18 @@ package code.api.v5_1_0
import code.api.Constant
import code.api.util.APIUtil
import code.api.util.APIUtil.gitCommit
import code.api.v1_4_0.JSONFactory1_4_0.{LocationJsonV140, MetaJsonV140, transformToLocationFromV140, transformToMetaFromV140}
import code.api.v3_0_0.JSONFactory300.{createLocationJson, createMetaJson, transformToAddressFromV300}
import code.api.v3_0_0.{AddressJsonV300, OpeningTimesV300}
import code.api.v4_0_0.{EnergySource400, HostedAt400, HostedBy400}
import code.atmattribute.AtmAttribute
import code.atms.Atms.Atm
import code.views.system.{AccountAccess, ViewDefinition}
import com.openbankproject.commons.model.{Address, AtmId, AtmT, BankId, Location, Meta}
import com.openbankproject.commons.util.{ApiVersion, ScannedApiVersion}
import scala.collection.immutable.List
import scala.util.Try
case class APIInfoJsonV510(
@ -67,7 +73,46 @@ case class CheckSystemIntegrityJsonV510(
case class CurrencyJsonV510(alphanumeric_code: String)
case class CurrenciesJsonV510(currencies: List[CurrencyJsonV510])
case class AtmJsonV510 (
id : Option[String],
bank_id : String,
name : String,
address: AddressJsonV300,
location: LocationJsonV140,
meta: MetaJsonV140,
monday: OpeningTimesV300,
tuesday: OpeningTimesV300,
wednesday: OpeningTimesV300,
thursday: OpeningTimesV300,
friday: OpeningTimesV300,
saturday: OpeningTimesV300,
sunday: OpeningTimesV300,
is_accessible : String,
located_at : String,
more_info : String,
has_deposit_capability : String,
supported_languages: List[String],
services: List[String],
accessibility_features: List[String],
supported_currencies: List[String],
notes: List[String],
location_categories: List[String],
minimum_withdrawal: String,
branch_identification: String,
site_identification: String,
site_name: String,
cash_withdrawal_national_fee: String,
cash_withdrawal_international_fee: String,
balance_inquiry_fee: String,
atm_type: String,
phone: String,
attributes: Option[List[AtmAttributeResponseJsonV510]]
)
case class AtmsJsonV510(atms : List[AtmJsonV510])
case class ProductAttributeJsonV510(
name: String,
@ -109,13 +154,134 @@ case class AtmAttributeResponseJsonV510(
is_active: Option[Boolean]
)
case class AtmAttributesResponseJsonV510(atm_attributes: List[AtmAttributeResponseJsonV510])
case class AtmAttributeBankResponseJsonV510(name: String,
value: String)
case class AtmAttributesResponseJson(list: List[AtmAttributeBankResponseJsonV510])
object JSONFactory510 {
def createAtmsJsonV510(atmAndAttributesTupleList: List[(AtmT, List[AtmAttribute])] ): AtmsJsonV510 = {
AtmsJsonV510(atmAndAttributesTupleList.map(
atmAndAttributesTuple =>
createAtmJsonV510(atmAndAttributesTuple._1,atmAndAttributesTuple._2)
))
}
def createAtmJsonV510(atm: AtmT, atmAttributes:List[AtmAttribute]): AtmJsonV510 = {
AtmJsonV510(
id = Some(atm.atmId.value),
bank_id = atm.bankId.value,
name = atm.name,
AddressJsonV300(atm.address.line1,
atm.address.line2,
atm.address.line3,
atm.address.city,
atm.address.county.getOrElse(""),
atm.address.state,
atm.address.postCode,
atm.address.countryCode),
createLocationJson(atm.location),
createMetaJson(atm.meta),
monday = OpeningTimesV300(
opening_time = atm.OpeningTimeOnMonday.getOrElse(""),
closing_time = atm.ClosingTimeOnMonday.getOrElse("")),
tuesday = OpeningTimesV300(
opening_time = atm.OpeningTimeOnTuesday.getOrElse(""),
closing_time = atm.ClosingTimeOnTuesday.getOrElse("")),
wednesday = OpeningTimesV300(
opening_time = atm.OpeningTimeOnWednesday.getOrElse(""),
closing_time = atm.ClosingTimeOnWednesday.getOrElse("")),
thursday = OpeningTimesV300(
opening_time = atm.OpeningTimeOnThursday.getOrElse(""),
closing_time = atm.ClosingTimeOnThursday.getOrElse("")),
friday = OpeningTimesV300(
opening_time = atm.OpeningTimeOnFriday.getOrElse(""),
closing_time = atm.ClosingTimeOnFriday.getOrElse("")),
saturday = OpeningTimesV300(
opening_time = atm.OpeningTimeOnSaturday.getOrElse(""),
closing_time = atm.ClosingTimeOnSaturday.getOrElse("")),
sunday = OpeningTimesV300(
opening_time = atm.OpeningTimeOnSunday.getOrElse(""),
closing_time = atm.ClosingTimeOnSunday.getOrElse("")),
is_accessible = atm.isAccessible.map(_.toString).getOrElse(""),
located_at = atm.locatedAt.getOrElse(""),
more_info = atm.moreInfo.getOrElse(""),
has_deposit_capability = atm.hasDepositCapability.map(_.toString).getOrElse(""),
supported_languages = atm.supportedLanguages.getOrElse(Nil),
services = atm.services.getOrElse(Nil),
accessibility_features = atm.accessibilityFeatures.getOrElse(Nil),
supported_currencies = atm.supportedCurrencies.getOrElse(Nil),
notes = atm.notes.getOrElse(Nil),
location_categories = atm.locationCategories.getOrElse(Nil),
minimum_withdrawal = atm.minimumWithdrawal.getOrElse(""),
branch_identification = atm.branchIdentification.getOrElse(""),
site_identification = atm.siteIdentification.getOrElse(""),
site_name = atm.siteName.getOrElse(""),
cash_withdrawal_national_fee = atm.cashWithdrawalNationalFee.getOrElse(""),
cash_withdrawal_international_fee = atm.cashWithdrawalInternationalFee.getOrElse(""),
balance_inquiry_fee = atm.balanceInquiryFee.getOrElse(""),
atm_type = atm.atmType.getOrElse(""),
phone = atm.phone.getOrElse(""),
attributes = Some(atmAttributes.map(createAtmAttributeJson))
)
}
def transformToAtmFromV510(atmJsonV510: AtmJsonV510): Atm = {
val address: Address = transformToAddressFromV300(atmJsonV510.address) // Note the address in V220 is V140
val location: Location = transformToLocationFromV140(atmJsonV510.location) // Note the location is V140
val meta: Meta = transformToMetaFromV140(atmJsonV510.meta) // Note the meta is V140
val isAccessible: Boolean = Try(atmJsonV510.is_accessible.toBoolean).getOrElse(false)
val hdc: Boolean = Try(atmJsonV510.has_deposit_capability.toBoolean).getOrElse(false)
Atm(
atmId = AtmId(atmJsonV510.id.getOrElse("")),
bankId = BankId(atmJsonV510.bank_id),
name = atmJsonV510.name,
address = address,
location = location,
meta = meta,
OpeningTimeOnMonday = Some(atmJsonV510.monday.opening_time),
ClosingTimeOnMonday = Some(atmJsonV510.monday.closing_time),
OpeningTimeOnTuesday = Some(atmJsonV510.tuesday.opening_time),
ClosingTimeOnTuesday = Some(atmJsonV510.tuesday.closing_time),
OpeningTimeOnWednesday = Some(atmJsonV510.wednesday.opening_time),
ClosingTimeOnWednesday = Some(atmJsonV510.wednesday.closing_time),
OpeningTimeOnThursday = Some(atmJsonV510.thursday.opening_time),
ClosingTimeOnThursday = Some(atmJsonV510.thursday.closing_time),
OpeningTimeOnFriday = Some(atmJsonV510.friday.opening_time),
ClosingTimeOnFriday = Some(atmJsonV510.friday.closing_time),
OpeningTimeOnSaturday = Some(atmJsonV510.saturday.opening_time),
ClosingTimeOnSaturday = Some(atmJsonV510.saturday.closing_time),
OpeningTimeOnSunday = Some(atmJsonV510.sunday.opening_time),
ClosingTimeOnSunday = Some(atmJsonV510.sunday.closing_time),
// Easy access for people who use wheelchairs etc. true or false ""=Unknown
isAccessible = Some(isAccessible),
locatedAt = Some(atmJsonV510.located_at),
moreInfo = Some(atmJsonV510.more_info),
hasDepositCapability = Some(hdc),
supportedLanguages = Some(atmJsonV510.supported_languages),
services = Some(atmJsonV510.services),
accessibilityFeatures = Some(atmJsonV510.accessibility_features),
supportedCurrencies = Some(atmJsonV510.supported_currencies),
notes = Some(atmJsonV510.notes),
minimumWithdrawal = Some(atmJsonV510.minimum_withdrawal),
branchIdentification = Some(atmJsonV510.branch_identification),
locationCategories = Some(atmJsonV510.location_categories),
siteIdentification = Some(atmJsonV510.site_identification),
siteName = Some(atmJsonV510.site_name),
cashWithdrawalNationalFee = Some(atmJsonV510.cash_withdrawal_national_fee),
cashWithdrawalInternationalFee = Some(atmJsonV510.cash_withdrawal_international_fee),
balanceInquiryFee = Some(atmJsonV510.balance_inquiry_fee),
atmType = Some(atmJsonV510.atm_type),
phone = Some(atmJsonV510.phone)
)
}
def getCustomViewNamesCheck(views: List[ViewDefinition]): CheckSystemIntegrityJsonV510 = {
val success = views.size == 0
@ -195,8 +361,8 @@ object JSONFactory510 {
is_active = atmAttribute.isActive
)
def createAtmAttributesJson(bankAttributes: List[AtmAttribute]): AtmAttributesResponseJsonV510 =
AtmAttributesResponseJsonV510(bankAttributes.map(createAtmAttributeJson))
def createAtmAttributesJson(atmAttributes: List[AtmAttribute]): AtmAttributesResponseJsonV510 =
AtmAttributesResponseJsonV510(atmAttributes.map(createAtmAttributeJson))
}

View File

@ -60,7 +60,9 @@ object Atms extends SimpleInjector {
cashWithdrawalNationalFee: Option[String] = None,
cashWithdrawalInternationalFee: Option[String] = None,
balanceInquiryFee: Option[String] = None,
atmType: Option[String] = None,
phone: Option[String] = None,
) extends AtmT
val atmsProvider = new Inject(buildOne _) {}

View File

@ -92,6 +92,8 @@ object MappedAtmsProvider extends AtmsProvider {
.mCashWithdrawalNationalFee(atm.cashWithdrawalNationalFee.orNull)
.mCashWithdrawalInternationalFee(atm.cashWithdrawalInternationalFee.orNull)
.mBalanceInquiryFee(atm.balanceInquiryFee.orNull)
.mAtmType(atm.atmType.orNull)
.mPhone(atm.phone.orNull)
.saveMe()
}
case _ =>
@ -149,6 +151,9 @@ object MappedAtmsProvider extends AtmsProvider {
.mCashWithdrawalNationalFee(atm.cashWithdrawalNationalFee.orNull)
.mCashWithdrawalInternationalFee(atm.cashWithdrawalInternationalFee.orNull)
.mBalanceInquiryFee(atm.balanceInquiryFee.orNull)
.mAtmType(atm.atmType.orNull)
.mPhone(atm.phone.orNull)
.saveMe()
}
}
@ -231,6 +236,8 @@ class MappedAtm extends AtmT with LongKeyedMapper[MappedAtm] with IdPK {
object mCashWithdrawalNationalFee extends MappedString(this, 255)
object mCashWithdrawalInternationalFee extends MappedString(this, 255)
object mBalanceInquiryFee extends MappedString(this, 255)
object mAtmType extends MappedString(this, 255)
object mPhone extends MappedString(this, 255)
override def atmId: AtmId = AtmId(mAtmId.get)
@ -360,6 +367,16 @@ class MappedAtm extends AtmT with LongKeyedMapper[MappedAtm] with IdPK {
case _ => None
}
override def atmType: Option[String] = mAtmType.get match {
case value: String => Some(value)
case _ => None
}
override def phone: Option[String] = mPhone.get match {
case value: String => Some(value)
case _ => None
}
}
//

View File

@ -366,6 +366,8 @@ case class InboundAtmSept2018(
cashWithdrawalNationalFee: Option[String] = None,
cashWithdrawalInternationalFee: Option[String] = None,
balanceInquiryFee: Option[String] = None,
atmType: Option[String] = None,
phone: Option[String] = None,
) extends AtmT
case class InternalTransaction_vSept2018(

View File

@ -62,6 +62,8 @@ class AtmsTest extends V140ServerSetup with DefaultUsers {
cashWithdrawalNationalFee: Option[String] = None,
cashWithdrawalInternationalFee: Option[String] = None,
balanceInquiryFee: Option[String] = None,
atmType: Option[String] = None,
phone: Option[String] = None,
) extends AtmT
case class AddressImpl(line1 : String, line2 : String, line3 : String, city : String, county : Option[String],

View File

@ -0,0 +1,193 @@
package code.api.v5_1_0
import code.api.ResourceDocs1_4_0.SwaggerDefinitionsJSON._
import code.api.util.APIUtil.OAuth._
import code.api.util.ApiRole._
import code.api.util.ErrorMessages.{AtmNotFoundByAtmId, UserHasMissingRoles}
import code.api.util.ExampleValue.atmTypeExample
import code.api.util.{ApiRole, ErrorMessages}
import code.api.v5_1_0.APIMethods510.Implementations5_1_0
import code.entitlement.Entitlement
import code.setup.DefaultUsers
import com.github.dwickern.macros.NameOf.nameOf
import com.openbankproject.commons.model.ErrorMessage
import com.openbankproject.commons.util.ApiVersion
import net.liftweb.json.Serialization.write
import org.scalatest.Tag
class AtmTest extends V510ServerSetup with DefaultUsers {
override def beforeAll() {
super.beforeAll()
}
override def afterAll() {
super.afterAll()
}
/**
* Test tags
* Example: To run tests with tag "getPermissions":
* mvn test -D tagsToInclude
*
* This is made possible by the scalatest maven plugin
*/
object VersionOfApi extends Tag(ApiVersion.v5_1_0.toString)
object ApiEndpoint1 extends Tag(nameOf(Implementations5_1_0.createAtm))
object ApiEndpoint2 extends Tag(nameOf(Implementations5_1_0.updateAtm))
object ApiEndpoint3 extends Tag(nameOf(Implementations5_1_0.getAtms))
object ApiEndpoint4 extends Tag(nameOf(Implementations5_1_0.getAtm))
lazy val bankId = randomBankId
feature(s"Test$ApiEndpoint1 test the error cases - $VersionOfApi") {
scenario(s"We try to consume endpoint $ApiEndpoint1 - Anonymous access", ApiEndpoint1, VersionOfApi) {
When("We make the request")
val requestGet = (v5_1_0_Request / "banks" / bankId / "atms").POST
val responseGet = makePostRequest(requestGet, write(atmJsonV510))
Then("We should get a 401")
And("We should get a message: " + ErrorMessages.UserNotLoggedIn)
responseGet.code should equal(401)
responseGet.body.extract[ErrorMessage].message should equal(ErrorMessages.UserNotLoggedIn)
}
scenario(s"We try to consume endpoint $ApiEndpoint1 without proper role - Authorized access", ApiEndpoint1, VersionOfApi) {
When("We make the request")
val requestGet = (v5_1_0_Request / "banks" / bankId / "atms").POST <@ (user1)
val responseGet = makePostRequest(requestGet, write(atmJsonV510))
Then("We should get a 403")
And("We should get a message: " + s"$canCreateAtmAtAnyBank or $canCreateAtm entitlement required")
responseGet.code should equal(403)
responseGet.body.extract[ErrorMessage].message should startWith(UserHasMissingRoles)
responseGet.body.extract[ErrorMessage].message contains (canCreateAtmAtAnyBank.toString()) shouldBe (true)
responseGet.body.extract[ErrorMessage].message contains (canCreateAtm.toString()) shouldBe (true)
}
}
feature(s"Test$ApiEndpoint2 test the error cases - $VersionOfApi") {
scenario(s"We try to consume endpoint $ApiEndpoint2 - Anonymous access", ApiEndpoint2, VersionOfApi) {
When("We make the request")
val requestGet = (v5_1_0_Request / "banks" / bankId / "atms" / "atmId" ).PUT
val responseGet = makePutRequest(requestGet, write(atmJsonV510))
Then("We should get a 401")
And("We should get a message: " + ErrorMessages.UserNotLoggedIn)
responseGet.code should equal(401)
responseGet.body.extract[ErrorMessage].message should equal(ErrorMessages.UserNotLoggedIn)
}
scenario(s"We try to consume endpoint $ApiEndpoint2 without proper role - Authorized access", ApiEndpoint2, VersionOfApi) {
When("We make the request")
val requestGet = (v5_1_0_Request / "banks" / bankId / "atms" / "atmId" ).PUT <@ (user1)
val responseGet = makePutRequest(requestGet, write(atmJsonV510))
Then("We should get a 403")
And("We should get a message: " + s"$canCreateAtmAtAnyBank or $canCreateAtm entitlement required")
responseGet.code should equal(403)
responseGet.body.extract[ErrorMessage].message should startWith(UserHasMissingRoles)
responseGet.body.extract[ErrorMessage].message contains (canUpdateAtmAtAnyBank.toString()) shouldBe (true)
responseGet.body.extract[ErrorMessage].message contains (canUpdateAtm.toString()) shouldBe (true)
}
scenario(s"We try to consume endpoint $ApiEndpoint2 with proper role but invalid ATM - Authorized access", ApiEndpoint2, VersionOfApi) {
When("We make the request")
val entitlement = Entitlement.entitlement.vend.addEntitlement("", resourceUser1.userId, ApiRole.CanUpdateAtmAtAnyBank.toString)
val requestGet = (v5_1_0_Request / "banks" / bankId / "atms" / "atmId-invalid" ).PUT <@ (user1)
val responseGet = makePutRequest(requestGet, write(atmJsonV510))
Then("We should get a 404")
And("We should get a message: " + s"$AtmNotFoundByAtmId")
responseGet.code should equal(404)
responseGet.body.extract[ErrorMessage].message should startWith(AtmNotFoundByAtmId)
responseGet.body.extract[ErrorMessage].message contains (AtmNotFoundByAtmId) shouldBe (true)
Entitlement.entitlement.vend.deleteEntitlement(entitlement)
}
}
feature(s"Test$ApiEndpoint3 test the error cases - $VersionOfApi") {
scenario(s"We try to consume endpoint $ApiEndpoint3 - Anonymous access", ApiEndpoint3, VersionOfApi) {
When("We make the request")
val request = (v5_1_0_Request / "banks" / bankId / "atms").GET
val response = makeGetRequest(request)
Then("We should get a 200")
response.code should equal(200)
}
}
feature(s"Test$ApiEndpoint1 $ApiEndpoint2 $ApiEndpoint3 $ApiEndpoint4 - $VersionOfApi") {
scenario(s"Test the CUR methods", ApiEndpoint1, VersionOfApi) {
When("We make the CREATE ATMs")
Entitlement.entitlement.vend.addEntitlement("", resourceUser1.userId, ApiRole.CanCreateAtmAtAnyBank.toString)
val requestCreate = (v5_1_0_Request / "banks" / bankId / "atms").POST <@ (user1)
val responseCreate = makePostRequest(requestCreate, write(atmJsonV510.copy(
bank_id = bankId,
atm_type = "atm_type1",
phone = "12345")))
Then("We should get a 201")
responseCreate.code should equal(201)
responseCreate.body.extract[AtmJsonV510].atm_type shouldBe("atm_type1")
responseCreate.body.extract[AtmJsonV510].phone shouldBe("12345")
val atmId = responseCreate.body.extract[AtmJsonV510].id.getOrElse("")
Then("We create three ATM attributes")
Entitlement.entitlement.vend.addEntitlement(bankId, resourceUser1.userId, ApiRole.CanCreateAtmAttribute.toString)
val requestGet = (v5_1_0_Request / "banks" / bankId / "atms" / atmId / "attributes").POST <@ (user1)
makePostRequest(requestGet, write(atmAttributeJsonV510.copy(name = "1")))
makePostRequest(requestGet, write(atmAttributeJsonV510.copy(name = "2")))
makePostRequest(requestGet, write(atmAttributeJsonV510.copy(name = "3")))
Then("We Update the ATMs")
Entitlement.entitlement.vend.addEntitlement("", resourceUser1.userId, ApiRole.CanUpdateAtmAtAnyBank.toString)
val requestUpdate = (v5_1_0_Request / "banks" / bankId / "atms" / atmId).PUT <@ (user1)
val responseUpdate = makePutRequest(requestUpdate, write(atmJsonV510.copy(
bank_id = bankId,
atm_type = "atm_type_111",
phone = "123456")))
Then("We should get a 201")
responseUpdate.code should equal(201)
responseUpdate.body.extract[AtmJsonV510].atm_type shouldBe ("atm_type_111")
responseUpdate.body.extract[AtmJsonV510].phone shouldBe ("123456")
Then("We create 2 more ATMs")
makePostRequest(requestCreate, write(atmJsonV510.copy(
bank_id = bankId,
id = Some("id2"),
atm_type = "atm_type2",
phone = "12345-2")))
makePostRequest(requestCreate, write(atmJsonV510.copy(
bank_id = bankId,
id = Some("id3"),
atm_type = "atm_type3",
phone = "12345-3")))
Then("We Get the ATMs")
val request = (v5_1_0_Request / "banks" / bankId / "atms").GET
Then("We should get a 200")
val responseGet = makeGetRequest(request)
responseGet.code should equal(200)
val atms = responseGet.body.extract[AtmsJsonV510].atms
atms.length should be (3)
atms(0).atm_type equals ("atm_type_111")
atms(1).atm_type equals ("atm_type2")
atms(2).atm_type equals ("atm_type3")
val attibutes = atms.find(_.id == Some(atmId)).get.attributes.get
attibutes.length shouldBe(3)
attibutes(0).name equals ("1")
attibutes(1).name equals ("2")
attibutes(2).name equals ("3")
Then("We Get the ATM")
val requestOne = (v5_1_0_Request / "banks" / bankId / "atms" /atmId ).GET
Then("We should get a 200")
val responseOne = makeGetRequest(requestOne)
responseOne.code should equal(200)
val atm = responseOne.body.extract[AtmJsonV510]
atm.atm_type equals ("atm_type_111")
val atmAttributes = atm.attributes.get
atmAttributes.length shouldBe(3)
atmAttributes(0).name equals ("1")
atmAttributes(1).name equals ("2")
atmAttributes(2).name equals ("3")
}
}
}

View File

@ -269,6 +269,8 @@ case class AtmTCommons(
cashWithdrawalNationalFee: Option[String] = None,
cashWithdrawalInternationalFee: Option[String] = None,
balanceInquiryFee: Option[String] = None,
atmType: Option[String] = None,
phone: Option[String] = None,
) extends AtmT
object AtmTCommons extends Converter[AtmT, AtmTCommons]

View File

@ -182,6 +182,8 @@ trait AtmT {
def cashWithdrawalNationalFee: Option[String]
def cashWithdrawalInternationalFee: Option[String]
def balanceInquiryFee: Option[String]
def atmType: Option[String]
def phone: Option[String]
}
// MappedBranch will implement this.