feature/VRP Consent acceptance

This commit is contained in:
Marko Milić 2025-01-29 15:37:57 +01:00
parent 45b1557352
commit 39dd665bea
3 changed files with 92 additions and 23 deletions

View File

@ -0,0 +1,36 @@
package code.api.util
import java.time.Duration
object DateTimeUtil {
/*
Examples:
println(formatDuration(90000)) // "1 day, 1 hour"
println(formatDuration(86400)) // "1 day"
println(formatDuration(172800)) // "2 days"
println(formatDuration(7200)) // "2 hours"
println(formatDuration(3661)) // "1 hour, 1 minute, 1 second"
println(formatDuration(120)) // "2 minutes"
println(formatDuration(30)) // "30 seconds"
println(formatDuration(0)) // "less than a second"
*/
def formatDuration(seconds: Long): String = {
val days = seconds / 86400
val hours = (seconds % 86400) / 3600
val minutes = (seconds % 3600) / 60
val secs = seconds % 60
def plural(value: Long, unit: String): Option[String] =
if (value > 0) Some(s"$value ${unit}${if (value > 1) "s" else ""}") else None
val parts = List(
plural(days, "day"),
plural(hours, "hour"),
plural(minutes, "minute"),
plural(secs, "second")
).flatten // Remove None values
if (parts.isEmpty) "less than a second" else parts.mkString(", ")
}
}

View File

@ -28,7 +28,7 @@ package code.snippet
import code.api.util.APIUtil._
import code.api.util.ErrorMessages.InvalidJsonFormat
import code.api.util.{APIUtil, CustomJsonFormats}
import code.api.util.{APIUtil, CustomJsonFormats, DateTimeUtil}
import code.api.v5_1_0.{APIMethods510, ConsentJsonV510}
import code.api.v5_0_0.{APIMethods500, ConsentJsonV500, ConsentRequestResponseJson}
import code.api.v3_1_0.{APIMethods310, ConsentChallengeJsonV310, ConsumerJsonV310}
@ -40,6 +40,7 @@ import net.liftweb.http.rest.RestHelper
import net.liftweb.http.{GetRequest, PostRequest, RequestVar, S, SHtml}
import net.liftweb.json
import net.liftweb.json.Formats
import net.liftweb.util.CssSel
import net.liftweb.util.Helpers._
class VrpConsentCreation extends MdcLoggable with RestHelper with APIMethods510 with APIMethods500 with APIMethods310 {
@ -60,22 +61,23 @@ class VrpConsentCreation extends MdcLoggable with RestHelper with APIMethods510
case Full(consentRequestResponseJson) =>
val jsonAst = consentRequestResponseJson.payload
val currency = (jsonAst \ "to_account" \ "limit" \ "currency").extract[String]
val ttl: Long = (jsonAst \ "time_to_live").extract[Long]
val formText =
s"""
|I, ${AuthUser.currentUser.flatMap(_.user.foreign.map(_.name)).getOrElse("")}
|, grant to transfer of funds from my account at ${(jsonAst \ "from_account" \ "bank_routing" \ "address").extract[String]}
|, ${(jsonAst \ "from_account" \ "account_routing" \ "address").extract[String]}
|, to ${(jsonAst \ "to_account" \ "counterparty_name").extract[String]}
|, address ${(jsonAst \ "to_account" \ "bank_routing" \ "address").extract[String]}
|, of $currency, ${(jsonAst \ "to_account" \ "limit" \ "max_single_amount").extract[String]}
| per transaction, up to $currency, ${(jsonAst \ "to_account" \ "limit" \ "max_monthly_amount").extract[String]}
| per month, up to ${(jsonAst \ "to_account" \ "limit" \ "max_number_of_monthly_transactions").extract[String]} transactions per month
|, up to $currency, ${(jsonAst \ "to_account" \ "limit" \ "max_yearly_amount").extract[String]}
| per year, and up to ${(jsonAst \ "to_account" \ "limit" \ "max_number_of_yearly_transactions").extract[String]} transactions per year
|, up to the total amount of $currency, ${(jsonAst \ "to_account" \ "limit" \ "max_total_amount").extract[String]}
| and up to a total of ${(jsonAst \ "to_account" \ "limit" \ "max_number_of_transactions").extract[String]} in total.
|This consent will be valid from ${(jsonAst \ "valid_from").extract[String]} for ${(jsonAst \ "time_to_live").extract[String]} seconds.
|""".stripMargin
s"""I, ${AuthUser.currentUser.map(_.firstName.get).getOrElse("")} ${AuthUser.currentUser.map(_.lastName.get).getOrElse("")}, consent to the service provider <CONSUMER_NAME> making transfers on my behalf from my bank account number ${(jsonAst \ "from_account" \ "account_routing" \ "address").extract[String]}, to the beneficiary ${(jsonAst \ "to_account" \ "counterparty_name").extract[String]}, account number ${(jsonAst \ "to_account" \ "account_routing" \ "address").extract[String]} at bank code ${(jsonAst \ "to_account" \ "bank_routing" \ "address").extract[String]}.
|
|The transfers governed by this consent must respect the following rules:
|
| 1) The grand total amount will not exceed {limit ($currency), (${(jsonAst \ "to_account" \ "limit" \ "max_total_amount").extract[String]})}
| 2) Any single amount will not exceed {limit ($currency), (${(jsonAst \ "to_account" \ "limit" \ "max_single_amount").extract[String]})}
| 3) The maximum amount per month that can be transferred is {limit ($currency), (${(jsonAst \ "to_account" \ "limit" \ "max_monthly_amount").extract[String]})} over {limit (${(jsonAst \ "to_account" \ "limit" \ "max_number_of_monthly_transactions").extract[String]}) transactions.
| 4) The maximum amount per year that can be transferred is {limit ($currency), (${(jsonAst \ "to_account" \ "limit" \ "max_yearly_amount").extract[String]})} over {limit (${(jsonAst \ "to_account" \ "limit" \ "max_number_of_yearly_transactions").extract[String]}) transactions.
|
|This consent will start on date {${(jsonAst \ "valid_from").extract[String]}} and be valid for ${DateTimeUtil.formatDuration(ttl)}.
|
|I understand that I can revoke this consent at any time.
|""".stripMargin
"#confirm-vrp-consent-request-form-title *" #> s"Please confirm or deny the following consent request:" &
"#confirm-vrp-consent-request-form-text *" #> s"""$formText""" &
"#from_bank_routing_scheme [value]" #> s"${(jsonAst \ "from_account" \ "bank_routing" \ "scheme").extract[String]}" &
@ -103,6 +105,7 @@ class VrpConsentCreation extends MdcLoggable with RestHelper with APIMethods510
"#valid_from [value]" #> s"${(jsonAst \ "valid_from").extract[String]}" &
"#email [value]" #> s"${(jsonAst \ "email").extract[String]}" &
"#phone_number [value]" #> s"${(jsonAst \ "phone_number").extract[String]}" &
showHideElements &
"#confirm-vrp-consent-request-confirm-submit-button" #> SHtml.onSubmitUnit(confirmConsentRequestProcess)
case _ =>
"#confirm-vrp-consent-request-form-title *" #> s"Please confirm or deny the following consent request:" &
@ -116,6 +119,25 @@ class VrpConsentCreation extends MdcLoggable with RestHelper with APIMethods510
}
}
def showHideElements: CssSel = {
if (ObpS.param("format").isEmpty) {
"#confirm-vrp-consent-request-form-text-div [style]" #> "display:block" &
"#confirm-vrp-consent-request-form-fields [style]" #> "display:block"
} else if(ObpS.param("format").contains("1")) {
"#confirm-vrp-consent-request-form-text-div [style]" #> "display:none" &
"#confirm-vrp-consent-request-form-fields [style]" #> "display:block"
} else if(ObpS.param("format").contains("2")) {
"#confirm-vrp-consent-request-form-text-div [style]" #> "display:block" &
"#confirm-vrp-consent-request-form-fields [style]" #> "display:none"
} else if(ObpS.param("format").contains("3")) {
"#confirm-vrp-consent-request-form-text-div [style]" #> "display:block" &
"#confirm-vrp-consent-request-form-fields [style]" #> "display:block"
} else {
"#confirm-vrp-consent-request-form-text-div [style]" #> "display:block" &
"#confirm-vrp-consent-request-form-fields [style]" #> "display:block"
}
}
def confirmVrpConsent = {
"#otp-value" #> SHtml.textElem(otpValue) &

View File

@ -28,13 +28,15 @@ Berlin 13359, Germany
-->
<div data-lift="surround?with=default;at=content">
<div id="confirm-vrp-consent-request-div" style="width: 90%; margin: 0 auto;" data-lift="VrpConsentCreation.confirmVrpConsentRequest">
<form method="post">
<div class="form-group">
<h3 id="confirm-vrp-consent-request-form-title">Please check the VRP Consent Request: </h3>
<p id="confirm-vrp-consent-request-form-text"></p>
<div id="confirm-vrp-consent-request" style="width: 90%; margin: 0 auto;" data-lift="VrpConsentCreation.confirmVrpConsentRequest">
<div class="form-group">
<h3 id="confirm-vrp-consent-request-form-title">Please check the VRP Consent Request: </h3>
<div id="confirm-vrp-consent-request-form-text-div">
<pre id="confirm-vrp-consent-request-form-text"></pre>
</div>
<div class="wrap-text">
</div>
<form method="post">
<div class="wrap-text" id="confirm-vrp-consent-request-form-fields">
<div class="form-group col-md-6">
<h4>From Account</h4>
<div class="form-row">
@ -180,9 +182,18 @@ Berlin 13359, Germany
<br>
<script>
// Apply the `readonly` attribute dynamically
const elements = document.querySelectorAll('#confirm-vrp-consent-request-div input, #confirm-vrp-consent-request-div textarea');
const elements = document.querySelectorAll('#confirm-vrp-consent-request input, #confirm-vrp-consent-request textarea');
elements.forEach(el => el.setAttribute('readonly', 'readonly'));
</script>
<style>
pre {
white-space: pre-wrap; /* Preserve whitespace and wrap at spaces */
word-break: normal; /* Prevent breaking words */
overflow-wrap: normal; /* Prevent breaking words */
overflow-x: auto; /* Allow horizontal scrolling if necessary */
}
</style>
</form>
</div>
</div>