Skip to content

Commit

Permalink
Merge pull request #167 from pagopa/SELC-1661
Browse files Browse the repository at this point in the history
Selc 1661 Onboarding an institute without registry proxy
  • Loading branch information
andrea-putzu authored Nov 15, 2022
2 parents 1fd297a + 32b2c05 commit 950db50
Show file tree
Hide file tree
Showing 14 changed files with 218 additions and 36 deletions.
15 changes: 15 additions & 0 deletions src/main/resources/application-standalone.conf
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,21 @@ party-process {
}
productName = "productName"
}

onboarding-notification-mail-placeholders {
adminEmail = ${ADDRESS_EMAIL_NOTIFICATION_ADMIN}
path = "src/test/resources/mail-template-notification.json"
path = ${?MAIL_TEMPLATE_NOTIFICATION_PATH}
confirm-token {
name = "confirmTokenURL"
placeholder = "https://dev.selfcare.pagopa.it/dashboard/admin/onboarding?token="
placeholder = ${?SELFCARE_ADMIN_NOTIFICATION_URL}
}
productName = "productName"
requesterName = "requesterName"
requesterSurname = "requesterSurname"
institutionName = "institutionName"
}
}

services {
Expand Down
12 changes: 12 additions & 0 deletions src/main/resources/application.conf
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,18 @@ party-process {
productName = "productName"
}
}
onboarding-notification-mail-placeholders {
adminEmail = ${ADDRESS_EMAIL_NOTIFICATION_ADMIN}
path = ${MAIL_TEMPLATE_NOTIFICATION_PATH}
confirm-token {
name = "confirmTokenURL"
placeholder = ${SELFCARE_ADMIN_NOTIFICATION_URL}
}
productName = "productName"
requesterName = "requesterName"
requesterSurname = "requesterSurname"
institutionName = "institutionName"
}

services {
party-management = ${PARTY_MANAGEMENT_URL}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package it.pagopa.interop.partyprocess.api.converters.partymanagement

import it.pagopa.interop.partymanagement.client.model.{DataProtectionOfficer => DependencyDataProtectionOfficer}
import it.pagopa.interop.partyprocess.model.DataProtectionOfficer

object DataProtectionOfficerConverter {
def dependencyToApi(dataProtectionOfficer: DependencyDataProtectionOfficer): DataProtectionOfficer =
DataProtectionOfficer(
address = dataProtectionOfficer.address,
email = dataProtectionOfficer.email,
pec = dataProtectionOfficer.pec
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ object InstitutionConverter {
institutionType = institution.institutionType,
origin = institution.origin,
attributes = institution.attributes.map(AttributeConverter.dependencyToApi),
paymentServiceProvider = None,
dataProtectionOfficer = None
paymentServiceProvider = institution.paymentServiceProvider.map(PaymentServiceProviderConverter.dependencyToApi),
dataProtectionOfficer = institution.dataProtectionOfficer.map(DataProtectionOfficerConverter.dependencyToApi)
)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package it.pagopa.interop.partyprocess.api.converters.partymanagement

import it.pagopa.interop.partymanagement.client.model.{PaymentServiceProvider => DependencyPaymentServiceProvider}
import it.pagopa.interop.partyprocess.model.PaymentServiceProvider

object PaymentServiceProviderConverter {
def dependencyToApi(paymentServiceProvider: DependencyPaymentServiceProvider): PaymentServiceProvider =
PaymentServiceProvider(
abiCode = paymentServiceProvider.abiCode,
businessRegisterNumber = paymentServiceProvider.businessRegisterNumber,
legalRegisterName = paymentServiceProvider.legalRegisterName,
legalRegisterNumber = paymentServiceProvider.legalRegisterNumber,
vatNumberGroup = paymentServiceProvider.vatNumberGroup
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -39,12 +39,14 @@ class ProcessApiServiceImpl(
signatureService: SignatureService,
mailer: MailEngine,
mailTemplate: PersistedTemplate,
mailNotificationTemplate: PersistedTemplate,
relationshipService: RelationshipService,
productService: ProductService
)(implicit ec: ExecutionContext)
extends ProcessApiService {

private val logger = Logger.takingImplicit[ContextFieldsToLog](this.getClass)
private val SELC = "SELC"

private final val validOnboardingStates: Seq[PartyManagementDependency.RelationshipState] =
List(
Expand All @@ -67,6 +69,20 @@ class ProcessApiServiceImpl(
)("onboarding-contract-email")
}

private def sendOnboardingNotificationMail(
addresses: Seq[String],
file: File,
productName: String,
onboardingMailParameters: Map[String, String]
)(implicit contexts: Seq[(String, String)]): Future[Unit] = {
mailer.sendMail(mailNotificationTemplate)(
addresses,
s"${productName}_accordo_adesione.pdf",
file,
onboardingMailParameters
)("onboarding-complete-email-notification")
}

/** Code: 204, Message: successful operation
* Code: 400, Message: Invalid ID supplied, DataType: Problem
* Code: 404, Message: Not found, DataType: Problem
Expand Down Expand Up @@ -394,7 +410,8 @@ class ProcessApiServiceImpl(
productRole,
onboardingRequest.pricingPlan,
onboardingRequest.institutionUpdate,
onboardingRequest.billing
onboardingRequest.billing,
institution.origin
)(bearer)
case _ =>
createOrGetRelationship(
Expand All @@ -405,7 +422,7 @@ class ProcessApiServiceImpl(
productRole,
None,
None,
None
None // , institution.origin
)(bearer)
}
}
Expand All @@ -419,11 +436,23 @@ class ProcessApiServiceImpl(
onboardingRequest.contract.path
)(bearer)
_ = logger.info("Digest {}", digest)
onboardingMailParameters <- getOnboardingMailParameters(token.token, currentUser, onboardingRequest)
destinationMails = ApplicationConfiguration.destinationMails.getOrElse(
Seq(onboardingRequest.institutionUpdate.flatMap(_.digitalAddress).getOrElse(institution.digitalAddress))
)
_ <- sendOnboardingMail(destinationMails, pdf, onboardingRequest.productName, onboardingMailParameters)

onboardingMailParameters <- institution.origin match {
case SELC => getOnboardingMailNotificationParameters(token.token, currentUser, onboardingRequest)
case _ => getOnboardingMailParameters(token.token, currentUser, onboardingRequest)
}
destinationMails = institution.origin match {
case SELC => Seq(ApplicationConfiguration.onboardingMailNotificationInstitutionAdminEmailAddress)
case _ =>
ApplicationConfiguration.destinationMails.getOrElse(
Seq(onboardingRequest.institutionUpdate.flatMap(_.digitalAddress).getOrElse(institution.digitalAddress))
)
}
_ <- institution.origin match {
case SELC =>
sendOnboardingNotificationMail(destinationMails, pdf, onboardingRequest.productName, onboardingMailParameters)
case _ => sendOnboardingMail(destinationMails, pdf, onboardingRequest.productName, onboardingMailParameters)
}
_ = logger.info(s"$token")
} yield ()
}
Expand All @@ -445,6 +474,39 @@ class ProcessApiServiceImpl(
.unlessA(institution.origin != "IPA" || areIpaDataMatching)
}

private def getOnboardingMailNotificationParameters(
token: String,
currentUser: UserRegistryUser,
onboardingRequest: OnboardingSignedRequest
): Future[Map[String, String]] = {
val tokenParameters: Map[String, String] = {
ApplicationConfiguration.onboardingMailNotificationPlaceholdersReplacement.map { case (k, placeholder) =>
(k, s"$placeholder$token")
}
}

val productParameters: Map[String, String] = Map(
ApplicationConfiguration.onboardingMailNotificationProductNamePlaceholder -> onboardingRequest.productName
)

val userParameters: Map[String, String] = Map(
ApplicationConfiguration.onboardingMailNotificationRequesterNamePlaceholder -> currentUser.name.getOrElse(""),
ApplicationConfiguration.onboardingMailNotificationRequesterSurnamePlaceholder -> currentUser.surname.getOrElse(
""
)
)

val institutionInfoParameters: Map[String, String] = {
onboardingRequest.institutionUpdate.fold(Map.empty[String, String]) { iu =>
Seq(
ApplicationConfiguration.onboardingMailNotificationInstitutionNamePlaceholder.some.zip(iu.description)
).flatten.toMap
}
}

Future.successful(tokenParameters ++ productParameters ++ userParameters ++ institutionInfoParameters)
}

private def getOnboardingMailParameters(
token: String,
currentUser: UserRegistryUser,
Expand Down Expand Up @@ -509,7 +571,8 @@ class ProcessApiServiceImpl(
productRole: String,
pricingPlan: Option[String],
institutionUpdate: Option[InstitutionUpdate],
billing: Option[Billing]
billing: Option[Billing],
origin: String = SELC
)(bearer: String)(implicit contexts: Seq[(String, String)]): Future[PartyManagementDependency.Relationship] = {
val relationshipSeed: PartyManagementDependency.RelationshipSeed =
PartyManagementDependency.RelationshipSeed(
Expand All @@ -525,16 +588,29 @@ class ProcessApiServiceImpl(
digitalAddress = i.digitalAddress,
address = i.address,
zipCode = i.zipCode,
taxCode = i.taxCode
taxCode = i.taxCode,
paymentServiceProvider = i.paymentServiceProvider.map(p =>
PartyManagementDependency.PaymentServiceProvider(
abiCode = p.abiCode,
businessRegisterNumber = p.businessRegisterNumber,
legalRegisterName = p.legalRegisterName,
legalRegisterNumber = p.legalRegisterNumber,
vatNumberGroup = p.vatNumberGroup
)
),
dataProtectionOfficer = i.dataProtectionOfficer.map(d =>
PartyManagementDependency.DataProtectionOfficer(address = d.address, email = d.email, pec = d.pec)
)
)
),
billing = billing.map(b =>
PartyManagementDependency.Billing(
vatNumber = b.vatNumber,
recipientCode = b.recipientCode,
publicServices = b.publicServices
)
)
PartyManagementDependency
.Billing(vatNumber = b.vatNumber, recipientCode = b.recipientCode, publicServices = b.publicServices)
),
state = origin match {
case SELC => Option(PartyManagementDependency.RelationshipState.TOBEVALIDATED)
case _ => Option(PartyManagementDependency.RelationshipState.PENDING)
}
)

partyManagementService
Expand Down Expand Up @@ -687,7 +763,8 @@ class ProcessApiServiceImpl(
relationship.product.id == product &&
(
relationship.state != PartyManagementDependency.RelationshipState.PENDING &&
relationship.state != PartyManagementDependency.RelationshipState.REJECTED
relationship.state != PartyManagementDependency.RelationshipState.REJECTED &&
relationship.state != PartyManagementDependency.RelationshipState.TOBEVALIDATED
)

}
Expand Down Expand Up @@ -752,7 +829,7 @@ class ProcessApiServiceImpl(
): Future[PartyManagementDependency.Institution] = {
val seed = PartyManagementDependency.InstitutionSeed(
externalId = externalId,
originId = "SELC",
originId = s"${institutionSeed.institutionType.getOrElse("SELC")}_${externalId}",
description = institutionSeed.description,
digitalAddress = institutionSeed.digitalAddress,
taxCode = institutionSeed.taxCode,
Expand All @@ -761,7 +838,7 @@ class ProcessApiServiceImpl(
address = institutionSeed.address,
zipCode = institutionSeed.zipCode,
institutionType = institutionSeed.institutionType,
origin = s"${institutionSeed.institutionType.getOrElse("SELC")}_${externalId}"
origin = SELC
)

for {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,26 @@ object ApplicationConfiguration {
val onboardingMailBillingRecipientCodePlaceholder: String =
config.getString("party-process.mail-template.onboarding-mail-placeholders.billing.recipientCode")

val onboardingMailNotificationPlaceholdersReplacement: Map[String, String] = {
Map(
config
.getString("party-process.mail-template.onboarding-notification-mail-placeholders.confirm-token.name") -> config
.getString("party-process.mail-template.onboarding-notification-mail-placeholders.confirm-token.placeholder")
)
}
val onboardingMailNotificationProductNamePlaceholder: String =
config.getString("party-process.mail-template.onboarding-notification-mail-placeholders.productName")
val onboardingMailNotificationRequesterNamePlaceholder: String =
config.getString("party-process.mail-template.onboarding-notification-mail-placeholders.requesterName")
val onboardingMailNotificationRequesterSurnamePlaceholder: String =
config.getString("party-process.mail-template.onboarding-notification-mail-placeholders.requesterSurname")
val onboardingMailNotificationInstitutionNamePlaceholder: String =
config.getString("party-process.mail-template.onboarding-notification-mail-placeholders.institutionName")
val onboardingMailNotificationInstitutionAdminEmailAddress: String =
config.getString("party-process.mail-template.onboarding-notification-mail-placeholders.adminEmail")
val onboardingNotificationMailTemplatePath: String =
config.getString("party-process.mail-template.onboarding-notification-mail-placeholders.path")

val storageContainer: String = config.getString("party-process.storage.container")

val jwtAudience: Set[String] = config.getString("party-process.jwt.audience").split(",").toSet.filter(_.nonEmpty)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ trait Dependencies {
userRegistryManagementService: UserRegistryManagementService,
fileManager: FileManager,
mailTemplate: PersistedTemplate,
mailNotificationTemplate: PersistedTemplate,
jwtReader: JWTReader
)(implicit ec: ExecutionContext): ProcessApi = new ProcessApi(
new ProcessApiServiceImpl(
Expand All @@ -128,6 +129,7 @@ trait Dependencies {
signatureService,
onboardingInitMailer,
mailTemplate,
mailNotificationTemplate,
relationshipService,
productService
),
Expand Down Expand Up @@ -188,6 +190,11 @@ trait Dependencies {
): Future[PersistedTemplate] =
MailTemplate.get(ApplicationConfiguration.onboardingCompleteMailTemplatePath, fileManager)

def getOnboardingNotificationMailTemplate(fileManager: FileManager)(implicit
ec: ExecutionContext
): Future[PersistedTemplate] =
MailTemplate.get(ApplicationConfiguration.onboardingNotificationMailTemplatePath, fileManager)

def getJwtValidator()(implicit ec: ExecutionContext): Future[JWTReader] = JWTConfiguration.jwtReader
.loadKeyset()
.toFuture
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,11 @@ object Main extends App with CORSSupport with Dependencies {
logger.info(renderBuildInfo(BuildInfo))

val serverBinding: Future[Http.ServerBinding] = for {
jwtReader <- getJwtValidator()
fileManager <- getFileManager()
onboardingInitMailTemplate <- getOnboardingInitMailTemplate(fileManager)
onboardingCompleteMailTemplate <- getOnboardingCompleteMailTemplate(fileManager)
jwtReader <- getJwtValidator()
fileManager <- getFileManager()
onboardingInitMailTemplate <- getOnboardingInitMailTemplate(fileManager)
onboardingCompleteMailTemplate <- getOnboardingCompleteMailTemplate(fileManager)
onboardingNotificationMailTemplate <- getOnboardingNotificationMailTemplate(fileManager)
partyManService = partyManagementService(blockingEc)
relService = relationshipService(partyManService)
prodService = productService(partyManService)
Expand All @@ -59,6 +60,7 @@ object Main extends App with CORSSupport with Dependencies {
userreg,
fileManager,
onboardingInitMailTemplate,
onboardingNotificationMailTemplate,
jwtReader
)
public = publicApi(
Expand Down
13 changes: 13 additions & 0 deletions src/test/resources/application-test.conf
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,19 @@ party-process {
}
productName = "productName"
}

onboarding-notification-mail-placeholders {
adminEmail = "[email protected]"
path = "src/test/resources/mail-template-notification.json"
confirm-token {
name = "confirmTokenURL"
placeholder = "selfcare-value"
}
productName = "productName"
requesterName = "requesterName"
requesterSurname = "requesterSurname"
institutionName = "institutionName"
}
}

services {
Expand Down
Loading

0 comments on commit 950db50

Please sign in to comment.