From 9676978d780373fc3d995a72f01c66076cf0d09d Mon Sep 17 00:00:00 2001 From: Iliyan Iliev Date: Wed, 17 Jun 2020 18:08:34 +0300 Subject: [PATCH 1/2] Closes #10 --- settings.yaml | 21 ++++- .../Services/INotificationsService.cs | 13 +++ .../KycService.cs | 46 ++++++++++- .../MAVN.Service.Kyc.DomainServices.csproj | 3 + .../NotificationsService.cs | 79 +++++++++++++++++++ .../Modules/RabbitMqModule.cs | 5 ++ src/MAVN.Service.Kyc/Modules/ServiceModule.cs | 15 ++++ src/MAVN.Service.Kyc/Settings/AppSettings.cs | 6 ++ .../EmailSettings/KycApprovedEmail.cs | 9 +++ .../EmailSettings/KycRejectedEmail.cs | 8 ++ src/MAVN.Service.Kyc/Settings/KycSettings.cs | 7 ++ 11 files changed, 210 insertions(+), 2 deletions(-) create mode 100644 src/MAVN.Service.Kyc.Domain/Services/INotificationsService.cs create mode 100644 src/MAVN.Service.Kyc.DomainServices/NotificationsService.cs create mode 100644 src/MAVN.Service.Kyc/Settings/EmailSettings/KycApprovedEmail.cs create mode 100644 src/MAVN.Service.Kyc/Settings/EmailSettings/KycRejectedEmail.cs diff --git a/settings.yaml b/settings.yaml index f7e1a9b..7ae6770 100644 --- a/settings.yaml +++ b/settings.yaml @@ -17,6 +17,20 @@ KycService: settings-key: UserManagementRabbitMQ types: - RabbitMq + BackOfficeLink: + settings-key: AdminManagementService-BackOfficeLink + KycApprovedEmail: + EmailTemplateId: + settings-key: KycService-KycApprovedEmail-EmailTemplateId + SubjectTemplateId: + settings-key: KycService-KycApprovedEmail-SubjectTemplateId + VoucherManagerUrl: + settings-key: KycService-KycApprovedEmail-VoucherManagerUrl + KycRejectedEmail: + EmailTemplateId: + settings-key: KycService-KycRejectedEmail-EmailTemplateId + SubjectTemplateId: + settings-key: KycService-KycRejectedEmail-SubjectTemplateId SlackNotifications: AzureQueue: ConnectionString: @@ -28,4 +42,9 @@ SlackNotifications: MonitoringServiceClient: MonitoringServiceUrl: settings-key: MonitoringServiceUrl - +PartnerManagementService: + ServiceUrl: + settings-key: PartnerManagementServiceUrl +AdminManagementService: + ServiceUrl: + settings-key: AdminManagementServiceUrl \ No newline at end of file diff --git a/src/MAVN.Service.Kyc.Domain/Services/INotificationsService.cs b/src/MAVN.Service.Kyc.Domain/Services/INotificationsService.cs new file mode 100644 index 0000000..39b4c69 --- /dev/null +++ b/src/MAVN.Service.Kyc.Domain/Services/INotificationsService.cs @@ -0,0 +1,13 @@ +using System.Threading.Tasks; + +namespace MAVN.Service.Kyc.Domain.Services +{ + public interface INotificationsService + { + Task NotifyKycApprovedAsync(string adminUserId, string adminUserEmail, string adminUserName, + string partnerName); + + Task NotifyKycRejectedAsync(string adminUserId, string adminUserEmail, string adminUserName, string partnerName, + string rejectionComment); + } +} diff --git a/src/MAVN.Service.Kyc.DomainServices/KycService.cs b/src/MAVN.Service.Kyc.DomainServices/KycService.cs index 22ec58b..b6a7229 100644 --- a/src/MAVN.Service.Kyc.DomainServices/KycService.cs +++ b/src/MAVN.Service.Kyc.DomainServices/KycService.cs @@ -3,10 +3,14 @@ using System.Threading.Tasks; using Common.Log; using Lykke.Common.Log; +using MAVN.Service.AdminManagement.Client; +using MAVN.Service.AdminManagement.Client.Models.Enums; +using MAVN.Service.AdminManagement.Client.Models.Requests; using MAVN.Service.Kyc.Domain.Enums; using MAVN.Service.Kyc.Domain.Models; using MAVN.Service.Kyc.Domain.Repositories; using MAVN.Service.Kyc.Domain.Services; +using MAVN.Service.PartnerManagement.Client; namespace MAVN.Service.Kyc.DomainServices { @@ -14,12 +18,24 @@ public class KycService : IKycService { private readonly IKycInformationRepository _kycInformationRepository; private readonly IKycStatusChangeRepository _kycStatusChangeRepository; + private readonly INotificationsService _notificationsService; + private IPartnerManagementClient _partnerManagementClient; + private readonly IAdminManagementServiceClient _adminManagementClient; private readonly ILog _log; - public KycService(IKycInformationRepository kycInformationRepository, IKycStatusChangeRepository kycStatusChangeRepository, ILogFactory logFactory) + public KycService( + IKycInformationRepository kycInformationRepository, + IKycStatusChangeRepository kycStatusChangeRepository, + INotificationsService notificationsService, + IPartnerManagementClient partnerManagementClient, + IAdminManagementServiceClient adminManagementClient, + ILogFactory logFactory) { _kycInformationRepository = kycInformationRepository; _kycStatusChangeRepository = kycStatusChangeRepository; + _notificationsService = notificationsService; + _partnerManagementClient = partnerManagementClient; + _adminManagementClient = adminManagementClient; _log = logFactory.CreateLog(this); } @@ -71,6 +87,34 @@ public async Task UpdateKycInfoAsync(KycInformation mo await _kycInformationRepository.UpdateAsync(model); + if (model.KycStatus != KycStatus.Accepted && model.KycStatus != KycStatus.Rejected) + return UpdateKycStatusErrorCode.None; + + var admin = await _adminManagementClient.AdminsApi.GetByIdAsync( + new GetAdminByIdRequestModel { AdminUserId = model.AdminUserId.ToString() }); + + if (admin.Error != AdminUserResponseErrorCodes.None || admin.Profile == null) + { + _log.Warning("Missing admin when trying to send KYC notification", context: model.AdminUserId); + return UpdateKycStatusErrorCode.None; + } + + var partner = await _partnerManagementClient.Partners.GetByIdAsync(model.PartnerId); + + if (partner == null) + { + _log.Warning("Missing partner when trying to send KYC notification", context: model.PartnerId); + return UpdateKycStatusErrorCode.None; + } + + if (model.KycStatus == KycStatus.Accepted) + await _notificationsService.NotifyKycApprovedAsync(model.AdminUserId.ToString(), + admin.Profile.Email, + admin.Profile.FirstName, partner.Name); + else + await _notificationsService.NotifyKycRejectedAsync(model.AdminUserId.ToString(), + admin.Profile.Email, admin.Profile.FirstName, partner.Name, model.Comment); + return UpdateKycStatusErrorCode.None; } diff --git a/src/MAVN.Service.Kyc.DomainServices/MAVN.Service.Kyc.DomainServices.csproj b/src/MAVN.Service.Kyc.DomainServices/MAVN.Service.Kyc.DomainServices.csproj index 85caced..6df8b30 100644 --- a/src/MAVN.Service.Kyc.DomainServices/MAVN.Service.Kyc.DomainServices.csproj +++ b/src/MAVN.Service.Kyc.DomainServices/MAVN.Service.Kyc.DomainServices.csproj @@ -6,6 +6,9 @@ + + + diff --git a/src/MAVN.Service.Kyc.DomainServices/NotificationsService.cs b/src/MAVN.Service.Kyc.DomainServices/NotificationsService.cs new file mode 100644 index 0000000..b78d839 --- /dev/null +++ b/src/MAVN.Service.Kyc.DomainServices/NotificationsService.cs @@ -0,0 +1,79 @@ +using System.Collections.Generic; +using System.Threading.Tasks; +using Lykke.Common; +using Lykke.RabbitMqBroker.Publisher; +using MAVN.Service.Kyc.Domain.Services; +using MAVN.Service.NotificationSystem.SubscriberContract; + +namespace MAVN.Service.Kyc.DomainServices +{ + public class NotificationsService : INotificationsService + { + private readonly IRabbitPublisher _emailsPublisher; + private readonly string _backOfficeUrl; + private readonly string _kycApprovedEmailTemplateId; + private readonly string _kycApprovedEmailSubjectTemplateId; + private readonly string _kycRejectedEmailTemplateId; + private readonly string _kycRejectedEmailSubjectTemplateId; + private readonly string _voucherManagerUrl; + + public NotificationsService( + IRabbitPublisher emailsPublisher, + string backOfficeUrl, + string kycApprovedEmailTemplateId, + string kycApprovedEmailSubjectTemplateId, + string kycRejectedEmailTemplateId, + string kycRejectedEmailSubjectTemplateId, + string voucherManagerUrl) + { + _emailsPublisher = emailsPublisher; + _backOfficeUrl = backOfficeUrl; + _kycApprovedEmailTemplateId = kycApprovedEmailTemplateId; + _kycApprovedEmailSubjectTemplateId = kycApprovedEmailSubjectTemplateId; + _kycRejectedEmailTemplateId = kycRejectedEmailTemplateId; + _kycRejectedEmailSubjectTemplateId = kycRejectedEmailSubjectTemplateId; + _voucherManagerUrl = voucherManagerUrl; + } + + public async Task NotifyKycApprovedAsync(string adminUserId, string adminUserEmail, string adminUserName, string partnerName) + { + var values = new Dictionary + { + {"BusinessName", partnerName}, + {"VoucherManagerUrl", _backOfficeUrl + _voucherManagerUrl}, + {"AdminUserName", $" {adminUserName}"}, + }; + + await SendEmailAsync(adminUserId, adminUserEmail, values, _kycApprovedEmailTemplateId, + _kycApprovedEmailSubjectTemplateId); + } + + public async Task NotifyKycRejectedAsync(string adminUserId, string adminUserEmail, string adminUserName, string partnerName, string rejectionComment) + { + var values = new Dictionary + { + {"BusinessName", partnerName}, + {"RejectionComment", rejectionComment}, + {"AdminUserName", $" {adminUserName}"}, + }; + + await SendEmailAsync(adminUserId, adminUserEmail, values, _kycRejectedEmailTemplateId, + _kycRejectedEmailSubjectTemplateId); + } + + private async Task SendEmailAsync(string customerId, string destination, Dictionary values, string emailTemplateId, string subjectTemplateId) + { + if (!string.IsNullOrWhiteSpace(destination)) + values["target_email"] = destination; + + await _emailsPublisher.PublishAsync(new EmailMessageEvent + { + CustomerId = customerId, + MessageTemplateId = emailTemplateId, + SubjectTemplateId = subjectTemplateId, + TemplateParameters = values, + Source = $"{AppEnvironment.Name} - {AppEnvironment.Version}" + }); + } + } +} diff --git a/src/MAVN.Service.Kyc/Modules/RabbitMqModule.cs b/src/MAVN.Service.Kyc/Modules/RabbitMqModule.cs index 02bb93e..18067fb 100644 --- a/src/MAVN.Service.Kyc/Modules/RabbitMqModule.cs +++ b/src/MAVN.Service.Kyc/Modules/RabbitMqModule.cs @@ -1,9 +1,11 @@ using Autofac; using JetBrains.Annotations; +using Lykke.RabbitMqBroker.Publisher; using Lykke.RabbitMqBroker.Subscriber; using Lykke.SettingsReader; using MAVN.Service.Kyc.DomainServices.RabbitMq.Subscribers; using MAVN.Service.Kyc.Settings; +using MAVN.Service.NotificationSystem.SubscriberContract; using MAVN.Service.PartnerManagement.Contract; namespace MAVN.Service.Kyc.Modules @@ -13,6 +15,7 @@ public class RabbitMqModule : Module { private const string DefaultQueueName = "kyc"; private const string PartnerCreatedExchangeName = "lykke.customer.partnercreated"; + private const string NotificationSystemEmailExchangeName = "lykke.notificationsystem.command.emailmessage"; private readonly RabbitMqSettings _settings; @@ -29,6 +32,8 @@ protected override void Load(ContainerBuilder builder) private void RegisterRabbitMqPublishers(ContainerBuilder builder) { + builder.RegisterJsonRabbitPublisher(_settings.Publishers.ConnectionString, + NotificationSystemEmailExchangeName); } private void RegisterRabbitMqSubscribers(ContainerBuilder builder) diff --git a/src/MAVN.Service.Kyc/Modules/ServiceModule.cs b/src/MAVN.Service.Kyc/Modules/ServiceModule.cs index 01c337c..9045381 100644 --- a/src/MAVN.Service.Kyc/Modules/ServiceModule.cs +++ b/src/MAVN.Service.Kyc/Modules/ServiceModule.cs @@ -3,10 +3,12 @@ using Lykke.Sdk; using Lykke.Sdk.Health; using Lykke.SettingsReader; +using MAVN.Service.AdminManagement.Client; using MAVN.Service.Kyc.Domain.Services; using MAVN.Service.Kyc.DomainServices; using MAVN.Service.Kyc.Services; using MAVN.Service.Kyc.Settings; +using MAVN.Service.PartnerManagement.Client; namespace MAVN.Service.Kyc.Modules { @@ -38,6 +40,19 @@ protected override void Load(ContainerBuilder builder) builder.RegisterType() .As() .SingleInstance(); + + builder.RegisterType() + .As() + .WithParameter("backOfficeUrl", _appSettings.CurrentValue.KycService.BackOfficeLink) + .WithParameter("kycApprovedEmailTemplateId", _appSettings.CurrentValue.KycService.KycApprovedEmail.EmailTemplateId) + .WithParameter("kycApprovedEmailSubjectTemplateId", _appSettings.CurrentValue.KycService.KycApprovedEmail.SubjectTemplateId) + .WithParameter("kycRejectedEmailTemplateId", _appSettings.CurrentValue.KycService.KycRejectedEmail.EmailTemplateId) + .WithParameter("kycRejectedEmailSubjectTemplateId", _appSettings.CurrentValue.KycService.KycRejectedEmail.SubjectTemplateId) + .WithParameter("voucherManagerUrl", _appSettings.CurrentValue.KycService.KycApprovedEmail.VoucherManagerUrl) + .SingleInstance(); + + builder.RegisterAdminManagementClient(_appSettings.CurrentValue.AdminManagementService); + builder.RegisterPartnerManagementClient(_appSettings.CurrentValue.PartnerManagementService); } } } diff --git a/src/MAVN.Service.Kyc/Settings/AppSettings.cs b/src/MAVN.Service.Kyc/Settings/AppSettings.cs index 4b3c8c8..839ffdb 100644 --- a/src/MAVN.Service.Kyc/Settings/AppSettings.cs +++ b/src/MAVN.Service.Kyc/Settings/AppSettings.cs @@ -1,5 +1,7 @@ using JetBrains.Annotations; using Lykke.Sdk.Settings; +using MAVN.Service.AdminManagement.Client; +using MAVN.Service.PartnerManagement.Client; namespace MAVN.Service.Kyc.Settings { @@ -7,5 +9,9 @@ namespace MAVN.Service.Kyc.Settings public class AppSettings : BaseAppSettings { public KycSettings KycService { get; set; } + + public AdminManagementServiceClientSettings AdminManagementService { get; set; } + + public PartnerManagementServiceClientSettings PartnerManagementService { get; set; } } } diff --git a/src/MAVN.Service.Kyc/Settings/EmailSettings/KycApprovedEmail.cs b/src/MAVN.Service.Kyc/Settings/EmailSettings/KycApprovedEmail.cs new file mode 100644 index 0000000..cf6bf71 --- /dev/null +++ b/src/MAVN.Service.Kyc/Settings/EmailSettings/KycApprovedEmail.cs @@ -0,0 +1,9 @@ +namespace MAVN.Service.Kyc.Settings.EmailSettings +{ + public class KycApprovedEmail + { + public string EmailTemplateId { set; get; } + public string SubjectTemplateId { set; get; } + public string VoucherManagerUrl { get; set; } + } +} diff --git a/src/MAVN.Service.Kyc/Settings/EmailSettings/KycRejectedEmail.cs b/src/MAVN.Service.Kyc/Settings/EmailSettings/KycRejectedEmail.cs new file mode 100644 index 0000000..910e984 --- /dev/null +++ b/src/MAVN.Service.Kyc/Settings/EmailSettings/KycRejectedEmail.cs @@ -0,0 +1,8 @@ +namespace MAVN.Service.Kyc.Settings.EmailSettings +{ + public class KycRejectedEmail + { + public string EmailTemplateId { set; get; } + public string SubjectTemplateId { set; get; } + } +} diff --git a/src/MAVN.Service.Kyc/Settings/KycSettings.cs b/src/MAVN.Service.Kyc/Settings/KycSettings.cs index e89232d..b1adc8b 100644 --- a/src/MAVN.Service.Kyc/Settings/KycSettings.cs +++ b/src/MAVN.Service.Kyc/Settings/KycSettings.cs @@ -1,5 +1,6 @@ using JetBrains.Annotations; using Lykke.SettingsReader.Attributes; +using MAVN.Service.Kyc.Settings.EmailSettings; namespace MAVN.Service.Kyc.Settings { @@ -9,5 +10,11 @@ public class KycSettings public DbSettings Db { get; set; } public RabbitMqSettings Rabbit { get; set; } + + public KycApprovedEmail KycApprovedEmail { get; set; } + + public KycRejectedEmail KycRejectedEmail { get; set; } + + public string BackOfficeLink { get; set; } } } From 60bda898035fc0c38ea616f39e5e30174c3e2f03 Mon Sep 17 00:00:00 2001 From: Iliyan Iliev Date: Wed, 17 Jun 2020 18:16:36 +0300 Subject: [PATCH 2/2] add whitespace only to non empty names in email notifications --- src/MAVN.Service.Kyc.DomainServices/NotificationsService.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/MAVN.Service.Kyc.DomainServices/NotificationsService.cs b/src/MAVN.Service.Kyc.DomainServices/NotificationsService.cs index b78d839..a412531 100644 --- a/src/MAVN.Service.Kyc.DomainServices/NotificationsService.cs +++ b/src/MAVN.Service.Kyc.DomainServices/NotificationsService.cs @@ -41,7 +41,7 @@ public async Task NotifyKycApprovedAsync(string adminUserId, string adminUserEma { {"BusinessName", partnerName}, {"VoucherManagerUrl", _backOfficeUrl + _voucherManagerUrl}, - {"AdminUserName", $" {adminUserName}"}, + {"AdminUserName", !string.IsNullOrEmpty(adminUserName) ? $" {adminUserName}" : adminUserName}, }; await SendEmailAsync(adminUserId, adminUserEmail, values, _kycApprovedEmailTemplateId, @@ -54,7 +54,7 @@ public async Task NotifyKycRejectedAsync(string adminUserId, string adminUserEma { {"BusinessName", partnerName}, {"RejectionComment", rejectionComment}, - {"AdminUserName", $" {adminUserName}"}, + {"AdminUserName", !string.IsNullOrEmpty(adminUserName) ? $" {adminUserName}" : adminUserName}, }; await SendEmailAsync(adminUserId, adminUserEmail, values, _kycRejectedEmailTemplateId,