11package code .api .v6_0_0
22
3- import code .api .{ APIFailureNewStyle , DirectLogin , ObpApiFailure }
4- import code .api .v6_0_0 . JSONFactory600
3+ import code .accountattribute . AccountAttributeX
4+ import code .api .{ DirectLogin , ObpApiFailure }
55import code .api .ResourceDocs1_4_0 .SwaggerDefinitionsJSON ._
66import code .api .util .APIUtil ._
7- import code .api .util .ApiRole .{ CanCreateEntitlementAtOneBank , CanReadDynamicResourceDocsAtOneBank , canCreateBank , canDeleteRateLimiting , canReadCallLimits , canSetCallLimits }
7+ import code .api .util .ApiRole ._
88import code .api .util .ApiTag ._
99import code .api .util .ErrorMessages .{$UserNotLoggedIn , InvalidDateFormat , InvalidJsonFormat , UnknownError , _ }
1010import code .api .util .FutureUtil .EndpointContext
11- import code .api .util .{APIUtil , ErrorMessages , NewStyle , RateLimitingUtil }
1211import code .api .util .NewStyle .HttpCode
13- import code .api .v5_0_0 .{JSONFactory500 , PostBankJson500 }
12+ import code .api .util .{APIUtil , ErrorMessages , NewStyle , RateLimitingUtil }
13+ import code .api .v3_0_0 .JSONFactory300
14+ import code .api .v5_0_0 .JSONFactory500
1415import code .api .v6_0_0 .JSONFactory600 .{createActiveCallLimitsJsonV600 , createCallLimitJsonV600 , createCurrentUsageJson }
1516import code .bankconnectors .LocalMappedConnectorInternal
1617import code .bankconnectors .LocalMappedConnectorInternal ._
1718import code .entitlement .Entitlement
19+ import code .model ._
1820import code .ratelimiting .RateLimitingDI
1921import code .util .Helper
2022import code .util .Helper .SILENCE_IS_GOLDEN
@@ -23,11 +25,10 @@ import com.github.dwickern.macros.NameOf.nameOf
2325import com .openbankproject .commons .ExecutionContext .Implicits .global
2426import com .openbankproject .commons .model ._
2527import com .openbankproject .commons .util .{ApiVersion , ScannedApiVersion }
26- import net .liftweb .common .{Box , Empty , Full }
28+ import net .liftweb .common .{Empty , Full }
2729import net .liftweb .http .rest .RestHelper
2830
2931import java .text .SimpleDateFormat
30- import java .util .Date
3132import scala .collection .immutable .{List , Nil }
3233import scala .collection .mutable .ArrayBuffer
3334import scala .concurrent .Future
@@ -49,6 +50,102 @@ trait APIMethods600 {
4950 val codeContext = CodeContext (staticResourceDocs, apiRelations)
5051
5152
53+ staticResourceDocs += ResourceDoc (
54+ createTransactionRequestHold,
55+ implementedInApiVersion,
56+ nameOf(createTransactionRequestHold),
57+ " POST" ,
58+ " /banks/BANK_ID/accounts/ACCOUNT_ID/owner/transaction-request-types/HOLD/transaction-requests" ,
59+ " Create Transaction Request (HOLD)" ,
60+ s """
61+ |
62+ |Create a transaction request to move funds from the account to its Holding Account.
63+ |If the Holding Account does not exist, it will be created automatically.
64+ |
65+ | ${transactionRequestGeneralText}
66+ |
67+ """ .stripMargin,
68+ transactionRequestBodyHoldJsonV600,
69+ transactionRequestWithChargeJSON400,
70+ List (
71+ $UserNotLoggedIn ,
72+ $BankNotFound ,
73+ $BankAccountNotFound ,
74+ InsufficientAuthorisationToCreateTransactionRequest ,
75+ InvalidTransactionRequestType ,
76+ InvalidJsonFormat ,
77+ NotPositiveAmount ,
78+ InvalidTransactionRequestCurrency ,
79+ TransactionDisabled ,
80+ UnknownError
81+ ),
82+ List (apiTagTransactionRequest, apiTagPSD2PIS, apiTagPsd2)
83+ )
84+
85+ lazy val createTransactionRequestHold : OBPEndpoint = {
86+ case " banks" :: BankId (bankId) :: " accounts" :: AccountId (accountId) :: ViewId (viewId) :: " transaction-request-types" ::
87+ " HOLD" :: " transaction-requests" :: Nil JsonPost json -> _ =>
88+ cc => implicit val ec = EndpointContext (Some (cc))
89+ val transactionRequestType = TransactionRequestType (" HOLD" )
90+ LocalMappedConnectorInternal .createTransactionRequest(bankId, accountId, viewId , transactionRequestType, json)
91+ }
92+
93+ // --- GET Holding Account by Parent ---
94+ staticResourceDocs += ResourceDoc (
95+ getHoldingAccountByReleaser,
96+ implementedInApiVersion,
97+ nameOf(getHoldingAccountByReleaser),
98+ " GET" ,
99+ " /banks/BANK_ID/accounts/ACCOUNT_ID/VIEW_ID/holding-accounts" ,
100+ " Get Holding Accounts By Releaser" ,
101+ s """
102+ |
103+ |Return the first Holding Account linked to the given releaser account via account attribute `RELEASER_ACCOUNT_ID`.
104+ |Response is wrapped in a list and includes account attributes.
105+ |
106+ """ .stripMargin,
107+ EmptyBody ,
108+ moderatedCoreAccountsJsonV300,
109+ List (
110+ $UserNotLoggedIn ,
111+ $BankNotFound ,
112+ $BankAccountNotFound ,
113+ $UserNoPermissionAccessView ,
114+ UnknownError
115+ ),
116+ List (apiTagAccount)
117+ )
118+
119+ lazy val getHoldingAccountByReleaser : OBPEndpoint = {
120+ case " banks" :: BankId (bankId) :: " accounts" :: AccountId (accountId) :: ViewId (viewId) :: " holding-accounts" :: Nil JsonGet _ =>
121+ cc => implicit val ec = EndpointContext (Some (cc))
122+ for {
123+ (user @ Full (u), _, _, view, callContext) <- SS .userBankAccountView
124+ // Find accounts by attribute RELEASER_ACCOUNT_ID
125+ (accountIdsBox, callContext) <- AccountAttributeX .accountAttributeProvider.vend.getAccountIdsByParams(bankId, Map (" RELEASER_ACCOUNT_ID" -> List (accountId.value))) map { ids => (ids, callContext) }
126+ accountIds = accountIdsBox.getOrElse(Nil )
127+ // load the first holding account
128+ holdingOpt <- {
129+ def firstHolding (ids : List [String ]): Future [Option [BankAccount ]] = ids match {
130+ case Nil => Future .successful(None )
131+ case id :: tail =>
132+ NewStyle .function.getBankAccount(bankId, AccountId (id), callContext).flatMap { case (acc, cc) =>
133+ if (acc.accountType == " HOLDING" ) Future .successful(Some (acc)) else firstHolding(tail)
134+ }
135+ }
136+ firstHolding(accountIds)
137+ }
138+ holding <- NewStyle .function.tryons($BankAccountNotFound , 404 , callContext) { holdingOpt.get }
139+ moderatedAccount <- Future { holding.moderatedBankAccount(view, BankIdAccountId (holding.bankId, holding.accountId), user, callContext) } map {
140+ x => unboxFullOrFail(x, callContext, UnknownError )
141+ }
142+ (attributes, callContext) <- NewStyle .function.getAccountAttributesByAccount(bankId, holding.accountId, callContext)
143+ } yield {
144+ val accountsJson = JSONFactory300 .createFirehoseCoreBankAccountJSON(List (moderatedAccount), Some (attributes))
145+ (accountsJson, HttpCode .`200`(callContext))
146+ }
147+ }
148+
52149 staticResourceDocs += ResourceDoc (
53150 getCurrentCallsLimit,
54151 implementedInApiVersion,
0 commit comments