From 25cabe25060e0d38ed5c2762ec86ad7496949d1e Mon Sep 17 00:00:00 2001 From: Piotr Wachulec Date: Wed, 15 Jul 2020 14:54:44 +0200 Subject: [PATCH 01/14] Removed unused reference --- .../Payments/Application/Payers/GetPayer/GetPayerQueryHandler.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Modules/Payments/Application/Payers/GetPayer/GetPayerQueryHandler.cs b/src/Modules/Payments/Application/Payers/GetPayer/GetPayerQueryHandler.cs index ab804408..96309930 100644 --- a/src/Modules/Payments/Application/Payers/GetPayer/GetPayerQueryHandler.cs +++ b/src/Modules/Payments/Application/Payers/GetPayer/GetPayerQueryHandler.cs @@ -1,7 +1,6 @@ using System.Threading; using System.Threading.Tasks; using CompanyName.MyMeetings.BuildingBlocks.Application.Data; -using CompanyName.MyMeetings.BuildingBlocks.Infrastructure; using CompanyName.MyMeetings.Modules.Payments.Application.Configuration.Queries; using Dapper; From 9d3624624acba6ca38c030270e621664576a6a7e Mon Sep 17 00:00:00 2001 From: Piotr Wachulec Date: Wed, 15 Jul 2020 15:37:42 +0200 Subject: [PATCH 02/14] Removed unnecessary indentation --- .../Meetings/Infrastructure/Configuration/MeetingsStartup.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Modules/Meetings/Infrastructure/Configuration/MeetingsStartup.cs b/src/Modules/Meetings/Infrastructure/Configuration/MeetingsStartup.cs index 2fd3eb82..abfe7301 100644 --- a/src/Modules/Meetings/Infrastructure/Configuration/MeetingsStartup.cs +++ b/src/Modules/Meetings/Infrastructure/Configuration/MeetingsStartup.cs @@ -57,7 +57,7 @@ private static void ConfigureCompositionRoot( containerBuilder.RegisterModule(new ProcessingModule()); containerBuilder.RegisterModule(new EventsBusModule(eventsBus)); - containerBuilder.RegisterModule(new MediatorModule()); + containerBuilder.RegisterModule(new MediatorModule()); containerBuilder.RegisterModule(new AuthenticationModule()); containerBuilder.RegisterModule(new OutboxModule()); containerBuilder.RegisterModule(new EmailModule(emailsConfiguration)); From 4de558f420be3d23e21ff19b513d02825511626d Mon Sep 17 00:00:00 2001 From: Piotr Wachulec Date: Wed, 15 Jul 2020 15:39:58 +0200 Subject: [PATCH 03/14] Created email configuration for Payments module --- .../Configuration/Email/EmailModule.cs | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 src/Modules/Payments/Infrastructure/Configuration/Email/EmailModule.cs diff --git a/src/Modules/Payments/Infrastructure/Configuration/Email/EmailModule.cs b/src/Modules/Payments/Infrastructure/Configuration/Email/EmailModule.cs new file mode 100644 index 00000000..0bac17d7 --- /dev/null +++ b/src/Modules/Payments/Infrastructure/Configuration/Email/EmailModule.cs @@ -0,0 +1,24 @@ +using Autofac; +using CompanyName.MyMeetings.BuildingBlocks.Application.Emails; +using CompanyName.MyMeetings.BuildingBlocks.Infrastructure.Emails; + +namespace CompanyName.MyMeetings.Modules.Payments.Infrastructure.Configuration.Email +{ + internal class EmailModule : Module + { + private readonly EmailsConfiguration _configuration; + + public EmailModule(EmailsConfiguration configuration) + { + _configuration = configuration; + } + + protected override void Load(ContainerBuilder builder) + { + builder.RegisterType() + .As() + .WithParameter("configuration", _configuration) + .InstancePerLifetimeScope(); + } + } +} \ No newline at end of file From 41d32483e319f99d777766dd4c4b64581aeb95a0 Mon Sep 17 00:00:00 2001 From: Piotr Wachulec Date: Wed, 15 Jul 2020 15:41:01 +0200 Subject: [PATCH 04/14] Marked EmailSender prop as readonly --- .../SendUserRegistrationConfirmationEmailCommandHandler.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Modules/UserAccess/Application/UserRegistrations/SendUserRegistrationConfirmationEmail/SendUserRegistrationConfirmationEmailCommandHandler.cs b/src/Modules/UserAccess/Application/UserRegistrations/SendUserRegistrationConfirmationEmail/SendUserRegistrationConfirmationEmailCommandHandler.cs index 6e248a87..ba2ea844 100644 --- a/src/Modules/UserAccess/Application/UserRegistrations/SendUserRegistrationConfirmationEmail/SendUserRegistrationConfirmationEmailCommandHandler.cs +++ b/src/Modules/UserAccess/Application/UserRegistrations/SendUserRegistrationConfirmationEmail/SendUserRegistrationConfirmationEmailCommandHandler.cs @@ -1,7 +1,6 @@ using System.Threading; using System.Threading.Tasks; using CompanyName.MyMeetings.BuildingBlocks.Application.Emails; -using CompanyName.MyMeetings.BuildingBlocks.Infrastructure.Emails; using CompanyName.MyMeetings.Modules.UserAccess.Application.Configuration.Commands; using MediatR; @@ -9,7 +8,7 @@ namespace CompanyName.MyMeetings.Modules.UserAccess.Application.UserRegistration { internal class SendUserRegistrationConfirmationEmailCommandHandler : ICommandHandler { - private IEmailSender _emailSender; + private readonly IEmailSender _emailSender; public SendUserRegistrationConfirmationEmailCommandHandler(IEmailSender emailSender) { From 2956853cfcfd762a9c72169f03b3e0b9ee4e1cf0 Mon Sep 17 00:00:00 2001 From: Piotr Wachulec Date: Wed, 15 Jul 2020 15:41:56 +0200 Subject: [PATCH 05/14] Added email config in startups --- src/API/CompanyName.MyMeetings.API/Startup.cs | 3 ++- .../Infrastructure/Configuration/PaymentsStartup.cs | 7 ++++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/API/CompanyName.MyMeetings.API/Startup.cs b/src/API/CompanyName.MyMeetings.API/Startup.cs index 444b7b8a..9b535d5b 100644 --- a/src/API/CompanyName.MyMeetings.API/Startup.cs +++ b/src/API/CompanyName.MyMeetings.API/Startup.cs @@ -187,7 +187,8 @@ private IServiceProvider CreateAutofacServiceProvider(IServiceCollection service PaymentsStartup.Initialize( this._configuration[MeetingsConnectionString], executionContextAccessor, - _logger, + _logger, + emailsConfiguration, null); return new AutofacServiceProvider(container); diff --git a/src/Modules/Payments/Infrastructure/Configuration/PaymentsStartup.cs b/src/Modules/Payments/Infrastructure/Configuration/PaymentsStartup.cs index 48b7086a..5e778b80 100644 --- a/src/Modules/Payments/Infrastructure/Configuration/PaymentsStartup.cs +++ b/src/Modules/Payments/Infrastructure/Configuration/PaymentsStartup.cs @@ -1,9 +1,11 @@ using Autofac; using CompanyName.MyMeetings.BuildingBlocks.Application; +using CompanyName.MyMeetings.BuildingBlocks.Infrastructure.Emails; using CompanyName.MyMeetings.BuildingBlocks.Infrastructure.EventBus; using CompanyName.MyMeetings.Modules.Payments.Infrastructure.AggregateStore; using CompanyName.MyMeetings.Modules.Payments.Infrastructure.Configuration.Authentication; using CompanyName.MyMeetings.Modules.Payments.Infrastructure.Configuration.DataAccess; +using CompanyName.MyMeetings.Modules.Payments.Infrastructure.Configuration.Email; using CompanyName.MyMeetings.Modules.Payments.Infrastructure.Configuration.EventsBus; using CompanyName.MyMeetings.Modules.Payments.Infrastructure.Configuration.Logging; using CompanyName.MyMeetings.Modules.Payments.Infrastructure.Configuration.Mediation; @@ -25,12 +27,13 @@ public static void Initialize( string connectionString, IExecutionContextAccessor executionContextAccessor, ILogger logger, + EmailsConfiguration emailsConfiguration, IEventsBus eventsBus, bool runQuartz = true) { var moduleLogger = logger.ForContext("Module", "Payments"); - ConfigureCompositionRoot(connectionString, executionContextAccessor, moduleLogger, eventsBus, runQuartz); + ConfigureCompositionRoot(connectionString, executionContextAccessor, moduleLogger, emailsConfiguration, eventsBus, runQuartz); if (runQuartz) { @@ -44,6 +47,7 @@ private static void ConfigureCompositionRoot( string connectionString, IExecutionContextAccessor executionContextAccessor, ILogger logger, + EmailsConfiguration emailsConfiguration, IEventsBus eventsBus, bool runQuartz = true) { @@ -55,6 +59,7 @@ private static void ConfigureCompositionRoot( containerBuilder.RegisterModule(new DataAccessModule(connectionString, loggerFactory)); containerBuilder.RegisterModule(new ProcessingModule()); + containerBuilder.RegisterModule(new EmailModule(emailsConfiguration)); containerBuilder.RegisterModule(new EventsBusModule(eventsBus)); containerBuilder.RegisterModule(new MediatorModule()); containerBuilder.RegisterModule(new AuthenticationModule()); From f48152c5b98e6cfed8e948ff2101511610d58c5b Mon Sep 17 00:00:00 2001 From: Piotr Wachulec Date: Wed, 15 Jul 2020 15:43:56 +0200 Subject: [PATCH 06/14] Updated TestBase to new module config --- .../Payments/Tests/IntegrationTests/SeedWork/TestBase.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/Modules/Payments/Tests/IntegrationTests/SeedWork/TestBase.cs b/src/Modules/Payments/Tests/IntegrationTests/SeedWork/TestBase.cs index 543bb5ad..f7787630 100644 --- a/src/Modules/Payments/Tests/IntegrationTests/SeedWork/TestBase.cs +++ b/src/Modules/Payments/Tests/IntegrationTests/SeedWork/TestBase.cs @@ -29,6 +29,8 @@ public class TestBase protected IEmailSender EmailSender; + protected EmailsConfiguration EmailsConfiguration; + protected EventsBusMock EventsBus; protected ExecutionContextMock ExecutionContext; @@ -53,6 +55,7 @@ public async Task BeforeEachTest() Logger = Substitute.For(); EmailSender = Substitute.For(); + EmailsConfiguration = new EmailsConfiguration("from@email.com"); EventsBus = new EventsBusMock(); ExecutionContext = new ExecutionContextMock(Guid.NewGuid()); @@ -60,6 +63,7 @@ public async Task BeforeEachTest() ConnectionString, ExecutionContext, Logger, + EmailsConfiguration, EventsBus, true); From 3a11ae614587db3e174f36a3b10583c2cc4ac48e Mon Sep 17 00:00:00 2001 From: Piotr Wachulec Date: Wed, 15 Jul 2020 15:46:38 +0200 Subject: [PATCH 07/14] Removed unused using --- .../SubscriptionCreatedNotificationHandler.cs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/Modules/Payments/Application/Subscriptions/CreateSubscription/SubscriptionCreatedNotificationHandler.cs b/src/Modules/Payments/Application/Subscriptions/CreateSubscription/SubscriptionCreatedNotificationHandler.cs index f2c7763c..a3f8a970 100644 --- a/src/Modules/Payments/Application/Subscriptions/CreateSubscription/SubscriptionCreatedNotificationHandler.cs +++ b/src/Modules/Payments/Application/Subscriptions/CreateSubscription/SubscriptionCreatedNotificationHandler.cs @@ -1,5 +1,4 @@ -using System; -using System.Threading; +using System.Threading; using System.Threading.Tasks; using CompanyName.MyMeetings.BuildingBlocks.Infrastructure.EventBus; using CompanyName.MyMeetings.Modules.Payments.IntegrationEvents; @@ -17,7 +16,7 @@ public SubscriptionCreatedNotificationHandler(IEventsBus eventsBus) } public Task Handle(SubscriptionCreatedNotification notification, CancellationToken cancellationToken) - { + { _eventsBus.Publish(new SubscriptionExpirationDateChangedIntegrationEvent(notification.Id, notification.DomainEvent.OccurredOn, notification.DomainEvent.PayerId, From 3365b4444310655bf28d054a4d7db6b550e3450c Mon Sep 17 00:00:00 2001 From: Piotr Wachulec Date: Wed, 15 Jul 2020 15:47:44 +0200 Subject: [PATCH 08/14] Added enquequing email after SubscriptionCreated notification --- ...nCreatedEnqueueEmailConfirmationHandler.cs | 57 +++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 src/Modules/Payments/Application/Subscriptions/CreateSubscription/SubscriptionCreatedEnqueueEmailConfirmationHandler.cs diff --git a/src/Modules/Payments/Application/Subscriptions/CreateSubscription/SubscriptionCreatedEnqueueEmailConfirmationHandler.cs b/src/Modules/Payments/Application/Subscriptions/CreateSubscription/SubscriptionCreatedEnqueueEmailConfirmationHandler.cs new file mode 100644 index 00000000..f05c2561 --- /dev/null +++ b/src/Modules/Payments/Application/Subscriptions/CreateSubscription/SubscriptionCreatedEnqueueEmailConfirmationHandler.cs @@ -0,0 +1,57 @@ +using System; +using System.Threading; +using System.Threading.Tasks; +using CompanyName.MyMeetings.BuildingBlocks.Application.Data; +using CompanyName.MyMeetings.Modules.Payments.Application.Configuration.Commands; +using CompanyName.MyMeetings.Modules.Payments.Application.Payers.GetPayer; +using CompanyName.MyMeetings.Modules.Payments.Application.Subscriptions.SendSubscriptionCreationConfirmationEmail; +using CompanyName.MyMeetings.Modules.Payments.Domain.Subscriptions; +using Dapper; +using MediatR; + +namespace CompanyName.MyMeetings.Modules.Payments.Application.Subscriptions.CreateSubscription +{ + public class SubscriptionCreatedEnqueueEmailConfirmationHandler : INotificationHandler + { + private readonly ICommandsScheduler _commandsScheduler; + private readonly ISqlConnectionFactory _sqlConnectionFactory; + + public SubscriptionCreatedEnqueueEmailConfirmationHandler( + ICommandsScheduler commandsScheduler, + ISqlConnectionFactory sqlConnectionFactory) + { + _commandsScheduler = commandsScheduler; + _sqlConnectionFactory = sqlConnectionFactory; + } + + public async Task Handle(SubscriptionCreatedNotification notification, CancellationToken cancellationToken) + { + var payer = await GetPayerDetails(notification.DomainEvent.PayerId); + + await _commandsScheduler.EnqueueAsync(new SendSubscriptionCreationConfirmationEmailCommand( + Guid.NewGuid(), + new SubscriptionId(notification.DomainEvent.SubscriptionId), + payer.Email)); + } + + private async Task GetPayerDetails(Guid payerId) + { + var connection = _sqlConnectionFactory.GetOpenConnection(); + + const string sql = "SELECT " + + "[Payer].[Id], " + + "[Payer].[Login], " + + "[Payer].[Email], " + + "[Payer].[FirstName], " + + "[Payer].[LastName], " + + "[Payer].[Name] " + + "FROM [payments].[Payers] AS [Payer] " + + "WHERE [Payer].[Id] = @PayerId"; + + return await connection.QuerySingleAsync(sql, new + { + payerId + }); + } + } +} \ No newline at end of file From fce8d6b1bf1eeccaa1bba12b6d256b801921e00d Mon Sep 17 00:00:00 2001 From: Piotr Wachulec Date: Wed, 15 Jul 2020 15:48:14 +0200 Subject: [PATCH 09/14] Created command and handler for sending subscription creation confirmation email --- ...riptionCreationConfirmationEmailCommand.cs | 25 +++++++++++++++++ ...CreationConfirmationEmailCommandHandler.cs | 27 +++++++++++++++++++ 2 files changed, 52 insertions(+) create mode 100644 src/Modules/Payments/Application/Subscriptions/SendSubscriptionCreationConfirmationEmail/SendSubscriptionCreationConfirmationEmailCommand.cs create mode 100644 src/Modules/Payments/Application/Subscriptions/SendSubscriptionCreationConfirmationEmail/SendSubscriptionCreationConfirmationEmailCommandHandler.cs diff --git a/src/Modules/Payments/Application/Subscriptions/SendSubscriptionCreationConfirmationEmail/SendSubscriptionCreationConfirmationEmailCommand.cs b/src/Modules/Payments/Application/Subscriptions/SendSubscriptionCreationConfirmationEmail/SendSubscriptionCreationConfirmationEmailCommand.cs new file mode 100644 index 00000000..06895adf --- /dev/null +++ b/src/Modules/Payments/Application/Subscriptions/SendSubscriptionCreationConfirmationEmail/SendSubscriptionCreationConfirmationEmailCommand.cs @@ -0,0 +1,25 @@ +using System; +using CompanyName.MyMeetings.Modules.Payments.Application.Configuration.Commands; +using CompanyName.MyMeetings.Modules.Payments.Domain.Subscriptions; +using Newtonsoft.Json; + +namespace CompanyName.MyMeetings.Modules.Payments.Application.Subscriptions.SendSubscriptionCreationConfirmationEmail +{ + public class SendSubscriptionCreationConfirmationEmailCommand : InternalCommandBase + { + internal SubscriptionId SubscriptionId { get; } + + internal string Email { get; } + + [JsonConstructor] + public SendSubscriptionCreationConfirmationEmailCommand( + Guid id, + SubscriptionId subscriptionId, + string email) + : base(id) + { + SubscriptionId = subscriptionId; + Email = email; + } + } +} \ No newline at end of file diff --git a/src/Modules/Payments/Application/Subscriptions/SendSubscriptionCreationConfirmationEmail/SendSubscriptionCreationConfirmationEmailCommandHandler.cs b/src/Modules/Payments/Application/Subscriptions/SendSubscriptionCreationConfirmationEmail/SendSubscriptionCreationConfirmationEmailCommandHandler.cs new file mode 100644 index 00000000..296b73bd --- /dev/null +++ b/src/Modules/Payments/Application/Subscriptions/SendSubscriptionCreationConfirmationEmail/SendSubscriptionCreationConfirmationEmailCommandHandler.cs @@ -0,0 +1,27 @@ +using System.Threading; +using System.Threading.Tasks; +using CompanyName.MyMeetings.BuildingBlocks.Application.Emails; +using CompanyName.MyMeetings.Modules.Payments.Application.Configuration.Commands; +using MediatR; + +namespace CompanyName.MyMeetings.Modules.Payments.Application.Subscriptions.SendSubscriptionCreationConfirmationEmail +{ + public class SendSubscriptionCreationConfirmationEmailCommandHandler : ICommandHandler + { + private readonly IEmailSender _emailSender; + + public SendSubscriptionCreationConfirmationEmailCommandHandler(IEmailSender emailSender) + { + _emailSender = emailSender; + } + + public Task Handle(SendSubscriptionCreationConfirmationEmailCommand request, CancellationToken cancellationToken) + { + var emailMessage = new EmailMessage(request.Email, "MyMeetings - Subscription purchased", + $"Subscription {request.SubscriptionId.Value} was successfully paid and created with ❤ for you!"); + + _emailSender.SendEmail(emailMessage); + return Unit.Task; + } + } +} \ No newline at end of file From 3d9557b3a719b2e244b99109fea8e07bafb0ccf1 Mon Sep 17 00:00:00 2001 From: Piotr Wachulec Date: Wed, 15 Jul 2020 15:57:04 +0200 Subject: [PATCH 10/14] Added enqueuing email with confirmation after subscription renewal --- ...nRenewedEnqueueEmailConfirmationHandler.cs | 57 +++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 src/Modules/Payments/Application/Subscriptions/RenewSubscription/SubscriptionRenewedEnqueueEmailConfirmationHandler.cs diff --git a/src/Modules/Payments/Application/Subscriptions/RenewSubscription/SubscriptionRenewedEnqueueEmailConfirmationHandler.cs b/src/Modules/Payments/Application/Subscriptions/RenewSubscription/SubscriptionRenewedEnqueueEmailConfirmationHandler.cs new file mode 100644 index 00000000..4e3dd952 --- /dev/null +++ b/src/Modules/Payments/Application/Subscriptions/RenewSubscription/SubscriptionRenewedEnqueueEmailConfirmationHandler.cs @@ -0,0 +1,57 @@ +using System; +using System.Threading; +using System.Threading.Tasks; +using CompanyName.MyMeetings.BuildingBlocks.Application.Data; +using CompanyName.MyMeetings.Modules.Payments.Application.Configuration.Commands; +using CompanyName.MyMeetings.Modules.Payments.Application.Payers.GetPayer; +using CompanyName.MyMeetings.Modules.Payments.Application.Subscriptions.SendSubscriptionRenewalConfirmationEmail; +using CompanyName.MyMeetings.Modules.Payments.Domain.Subscriptions; +using Dapper; +using MediatR; + +namespace CompanyName.MyMeetings.Modules.Payments.Application.Subscriptions.RenewSubscription +{ + public class SubscriptionRenewedEnqueueEmailConfirmationHandler : INotificationHandler + { + private readonly ICommandsScheduler _commandsScheduler; + private readonly ISqlConnectionFactory _sqlConnectionFactory; + + public SubscriptionRenewedEnqueueEmailConfirmationHandler( + ICommandsScheduler commandsScheduler, + ISqlConnectionFactory sqlConnectionFactory) + { + _commandsScheduler = commandsScheduler; + _sqlConnectionFactory = sqlConnectionFactory; + } + + public async Task Handle(SubscriptionRenewedNotification notification, CancellationToken cancellationToken) + { + var payer = await GetPayerDetails(notification.DomainEvent.PayerId); + + await _commandsScheduler.EnqueueAsync(new SendSubscriptionRenewalConfirmationEmailCommand( + Guid.NewGuid(), + new SubscriptionId(notification.DomainEvent.SubscriptionId), + payer.Email)); + } + + private async Task GetPayerDetails(Guid payerId) + { + var connection = _sqlConnectionFactory.GetOpenConnection(); + + const string sql = "SELECT " + + "[Payer].[Id], " + + "[Payer].[Login], " + + "[Payer].[Email], " + + "[Payer].[FirstName], " + + "[Payer].[LastName], " + + "[Payer].[Name] " + + "FROM [payments].[Payers] AS [Payer] " + + "WHERE [Payer].[Id] = @PayerId"; + + return await connection.QuerySingleAsync(sql, new + { + payerId + }); + } + } +} \ No newline at end of file From 1f6a44c4c9a417a19634c884710fa6130eaade35 Mon Sep 17 00:00:00 2001 From: Piotr Wachulec Date: Wed, 15 Jul 2020 15:58:03 +0200 Subject: [PATCH 11/14] Added sending enqueued confirmation --- ...criptionRenewalConfirmationEmailCommand.cs | 25 +++++++++++++++++ ...nRenewalConfirmationEmailCommandHandler.cs | 27 +++++++++++++++++++ 2 files changed, 52 insertions(+) create mode 100644 src/Modules/Payments/Application/Subscriptions/SendSubscriptionRenewalConfirmationEmail/SendSubscriptionRenewalConfirmationEmailCommand.cs create mode 100644 src/Modules/Payments/Application/Subscriptions/SendSubscriptionRenewalConfirmationEmail/SendSubscriptionRenewalConfirmationEmailCommandHandler.cs diff --git a/src/Modules/Payments/Application/Subscriptions/SendSubscriptionRenewalConfirmationEmail/SendSubscriptionRenewalConfirmationEmailCommand.cs b/src/Modules/Payments/Application/Subscriptions/SendSubscriptionRenewalConfirmationEmail/SendSubscriptionRenewalConfirmationEmailCommand.cs new file mode 100644 index 00000000..b6d525ea --- /dev/null +++ b/src/Modules/Payments/Application/Subscriptions/SendSubscriptionRenewalConfirmationEmail/SendSubscriptionRenewalConfirmationEmailCommand.cs @@ -0,0 +1,25 @@ +using System; +using CompanyName.MyMeetings.Modules.Payments.Application.Configuration.Commands; +using CompanyName.MyMeetings.Modules.Payments.Domain.Subscriptions; +using Newtonsoft.Json; + +namespace CompanyName.MyMeetings.Modules.Payments.Application.Subscriptions.SendSubscriptionRenewalConfirmationEmail +{ + public class SendSubscriptionRenewalConfirmationEmailCommand : InternalCommandBase + { + internal SubscriptionId SubscriptionId { get; } + + internal string Email { get; } + + [JsonConstructor] + public SendSubscriptionRenewalConfirmationEmailCommand( + Guid id, + SubscriptionId subscriptionId, + string email) + : base(id) + { + SubscriptionId = subscriptionId; + Email = email; + } + } +} \ No newline at end of file diff --git a/src/Modules/Payments/Application/Subscriptions/SendSubscriptionRenewalConfirmationEmail/SendSubscriptionRenewalConfirmationEmailCommandHandler.cs b/src/Modules/Payments/Application/Subscriptions/SendSubscriptionRenewalConfirmationEmail/SendSubscriptionRenewalConfirmationEmailCommandHandler.cs new file mode 100644 index 00000000..ed98c47f --- /dev/null +++ b/src/Modules/Payments/Application/Subscriptions/SendSubscriptionRenewalConfirmationEmail/SendSubscriptionRenewalConfirmationEmailCommandHandler.cs @@ -0,0 +1,27 @@ +using System.Threading; +using System.Threading.Tasks; +using CompanyName.MyMeetings.BuildingBlocks.Application.Emails; +using CompanyName.MyMeetings.Modules.Payments.Application.Configuration.Commands; +using MediatR; + +namespace CompanyName.MyMeetings.Modules.Payments.Application.Subscriptions.SendSubscriptionRenewalConfirmationEmail +{ + public class SendSubscriptionRenewalConfirmationEmailCommandHandler : ICommandHandler + { + private readonly IEmailSender _emailSender; + + public SendSubscriptionRenewalConfirmationEmailCommandHandler(IEmailSender emailSender) + { + _emailSender = emailSender; + } + + public Task Handle(SendSubscriptionRenewalConfirmationEmailCommand request, CancellationToken cancellationToken) + { + var emailMessage = new EmailMessage(request.Email, "MyMeetings - Subscription renewed", + $"Subscription {request.SubscriptionId.Value} was successfully paid and renewed with ❤ for you!"); + + _emailSender.SendEmail(emailMessage); + return Unit.Task; + } + } +} \ No newline at end of file From 7ee71b927064ee6edbd2c6b215c40ac5c7a5f716 Mon Sep 17 00:00:00 2001 From: Piotr Wachulec Date: Fri, 17 Jul 2020 11:39:38 +0200 Subject: [PATCH 12/14] Extrated getting Payer email to provider class --- .../GetPayerEmail/PayerEmailProvider.cs | 38 +++++++++++++++++++ ...nCreatedEnqueueEmailConfirmationHandler.cs | 25 ++---------- ...nRenewedEnqueueEmailConfirmationHandler.cs | 25 ++---------- 3 files changed, 46 insertions(+), 42 deletions(-) create mode 100644 src/Modules/Payments/Application/Payers/GetPayerEmail/PayerEmailProvider.cs diff --git a/src/Modules/Payments/Application/Payers/GetPayerEmail/PayerEmailProvider.cs b/src/Modules/Payments/Application/Payers/GetPayerEmail/PayerEmailProvider.cs new file mode 100644 index 00000000..bd704515 --- /dev/null +++ b/src/Modules/Payments/Application/Payers/GetPayerEmail/PayerEmailProvider.cs @@ -0,0 +1,38 @@ +using System; +using System.Threading.Tasks; +using CompanyName.MyMeetings.BuildingBlocks.Application.Data; +using CompanyName.MyMeetings.Modules.Payments.Application.Payers.GetPayer; +using Dapper; + +namespace CompanyName.MyMeetings.Modules.Payments.Application.Payers.GetPayerEmail +{ + public static class PayerEmailProvider + { + private static ISqlConnectionFactory _sqlConnectionFactory; + + public static void Init(ISqlConnectionFactory sqlConnectionFactory) + { + _sqlConnectionFactory = sqlConnectionFactory; + } + + public static async Task GetPayerDetails(Guid payerId) + { + var connection = _sqlConnectionFactory.GetOpenConnection(); + + const string sql = "SELECT " + + "[Payer].[Id], " + + "[Payer].[Login], " + + "[Payer].[Email], " + + "[Payer].[FirstName], " + + "[Payer].[LastName], " + + "[Payer].[Name] " + + "FROM [payments].[Payers] AS [Payer] " + + "WHERE [Payer].[Id] = @PayerId"; + + return await connection.QuerySingleAsync(sql, new + { + payerId + }); + } + } +} \ No newline at end of file diff --git a/src/Modules/Payments/Application/Subscriptions/CreateSubscription/SubscriptionCreatedEnqueueEmailConfirmationHandler.cs b/src/Modules/Payments/Application/Subscriptions/CreateSubscription/SubscriptionCreatedEnqueueEmailConfirmationHandler.cs index f05c2561..59bea7d3 100644 --- a/src/Modules/Payments/Application/Subscriptions/CreateSubscription/SubscriptionCreatedEnqueueEmailConfirmationHandler.cs +++ b/src/Modules/Payments/Application/Subscriptions/CreateSubscription/SubscriptionCreatedEnqueueEmailConfirmationHandler.cs @@ -4,6 +4,7 @@ using CompanyName.MyMeetings.BuildingBlocks.Application.Data; using CompanyName.MyMeetings.Modules.Payments.Application.Configuration.Commands; using CompanyName.MyMeetings.Modules.Payments.Application.Payers.GetPayer; +using CompanyName.MyMeetings.Modules.Payments.Application.Payers.GetPayerEmail; using CompanyName.MyMeetings.Modules.Payments.Application.Subscriptions.SendSubscriptionCreationConfirmationEmail; using CompanyName.MyMeetings.Modules.Payments.Domain.Subscriptions; using Dapper; @@ -26,32 +27,14 @@ public SubscriptionCreatedEnqueueEmailConfirmationHandler( public async Task Handle(SubscriptionCreatedNotification notification, CancellationToken cancellationToken) { - var payer = await GetPayerDetails(notification.DomainEvent.PayerId); + PayerEmailProvider.Init(_sqlConnectionFactory); + + var payer = await PayerEmailProvider.GetPayerDetails(notification.DomainEvent.PayerId); await _commandsScheduler.EnqueueAsync(new SendSubscriptionCreationConfirmationEmailCommand( Guid.NewGuid(), new SubscriptionId(notification.DomainEvent.SubscriptionId), payer.Email)); } - - private async Task GetPayerDetails(Guid payerId) - { - var connection = _sqlConnectionFactory.GetOpenConnection(); - - const string sql = "SELECT " + - "[Payer].[Id], " + - "[Payer].[Login], " + - "[Payer].[Email], " + - "[Payer].[FirstName], " + - "[Payer].[LastName], " + - "[Payer].[Name] " + - "FROM [payments].[Payers] AS [Payer] " + - "WHERE [Payer].[Id] = @PayerId"; - - return await connection.QuerySingleAsync(sql, new - { - payerId - }); - } } } \ No newline at end of file diff --git a/src/Modules/Payments/Application/Subscriptions/RenewSubscription/SubscriptionRenewedEnqueueEmailConfirmationHandler.cs b/src/Modules/Payments/Application/Subscriptions/RenewSubscription/SubscriptionRenewedEnqueueEmailConfirmationHandler.cs index 4e3dd952..4c2c0058 100644 --- a/src/Modules/Payments/Application/Subscriptions/RenewSubscription/SubscriptionRenewedEnqueueEmailConfirmationHandler.cs +++ b/src/Modules/Payments/Application/Subscriptions/RenewSubscription/SubscriptionRenewedEnqueueEmailConfirmationHandler.cs @@ -4,6 +4,7 @@ using CompanyName.MyMeetings.BuildingBlocks.Application.Data; using CompanyName.MyMeetings.Modules.Payments.Application.Configuration.Commands; using CompanyName.MyMeetings.Modules.Payments.Application.Payers.GetPayer; +using CompanyName.MyMeetings.Modules.Payments.Application.Payers.GetPayerEmail; using CompanyName.MyMeetings.Modules.Payments.Application.Subscriptions.SendSubscriptionRenewalConfirmationEmail; using CompanyName.MyMeetings.Modules.Payments.Domain.Subscriptions; using Dapper; @@ -26,32 +27,14 @@ public SubscriptionRenewedEnqueueEmailConfirmationHandler( public async Task Handle(SubscriptionRenewedNotification notification, CancellationToken cancellationToken) { - var payer = await GetPayerDetails(notification.DomainEvent.PayerId); + PayerEmailProvider.Init(_sqlConnectionFactory); + + var payer = await PayerEmailProvider.GetPayerDetails(notification.DomainEvent.PayerId); await _commandsScheduler.EnqueueAsync(new SendSubscriptionRenewalConfirmationEmailCommand( Guid.NewGuid(), new SubscriptionId(notification.DomainEvent.SubscriptionId), payer.Email)); } - - private async Task GetPayerDetails(Guid payerId) - { - var connection = _sqlConnectionFactory.GetOpenConnection(); - - const string sql = "SELECT " + - "[Payer].[Id], " + - "[Payer].[Login], " + - "[Payer].[Email], " + - "[Payer].[FirstName], " + - "[Payer].[LastName], " + - "[Payer].[Name] " + - "FROM [payments].[Payers] AS [Payer] " + - "WHERE [Payer].[Id] = @PayerId"; - - return await connection.QuerySingleAsync(sql, new - { - payerId - }); - } } } \ No newline at end of file From 417e0a82bffbadcc2d255b966cf9d695ae16b1a9 Mon Sep 17 00:00:00 2001 From: Piotr Wachulec Date: Fri, 17 Jul 2020 17:37:47 +0200 Subject: [PATCH 13/14] Refactored getting payer email method --- .../GetPayerEmail/PayerEmailProvider.cs | 19 +++---------------- ...nCreatedEnqueueEmailConfirmationHandler.cs | 8 ++++---- ...nRenewedEnqueueEmailConfirmationHandler.cs | 8 ++++---- 3 files changed, 11 insertions(+), 24 deletions(-) diff --git a/src/Modules/Payments/Application/Payers/GetPayerEmail/PayerEmailProvider.cs b/src/Modules/Payments/Application/Payers/GetPayerEmail/PayerEmailProvider.cs index bd704515..6765772b 100644 --- a/src/Modules/Payments/Application/Payers/GetPayerEmail/PayerEmailProvider.cs +++ b/src/Modules/Payments/Application/Payers/GetPayerEmail/PayerEmailProvider.cs @@ -1,35 +1,22 @@ using System; using System.Threading.Tasks; using CompanyName.MyMeetings.BuildingBlocks.Application.Data; -using CompanyName.MyMeetings.Modules.Payments.Application.Payers.GetPayer; using Dapper; namespace CompanyName.MyMeetings.Modules.Payments.Application.Payers.GetPayerEmail { public static class PayerEmailProvider { - private static ISqlConnectionFactory _sqlConnectionFactory; - - public static void Init(ISqlConnectionFactory sqlConnectionFactory) + public static async Task GetPayerEmail(Guid payerId, ISqlConnectionFactory sqlConnectionFactory) { - _sqlConnectionFactory = sqlConnectionFactory; - } - - public static async Task GetPayerDetails(Guid payerId) - { - var connection = _sqlConnectionFactory.GetOpenConnection(); + var connection = sqlConnectionFactory.GetOpenConnection(); const string sql = "SELECT " + - "[Payer].[Id], " + - "[Payer].[Login], " + "[Payer].[Email], " + - "[Payer].[FirstName], " + - "[Payer].[LastName], " + - "[Payer].[Name] " + "FROM [payments].[Payers] AS [Payer] " + "WHERE [Payer].[Id] = @PayerId"; - return await connection.QuerySingleAsync(sql, new + return await connection.QuerySingleAsync(sql, new { payerId }); diff --git a/src/Modules/Payments/Application/Subscriptions/CreateSubscription/SubscriptionCreatedEnqueueEmailConfirmationHandler.cs b/src/Modules/Payments/Application/Subscriptions/CreateSubscription/SubscriptionCreatedEnqueueEmailConfirmationHandler.cs index 59bea7d3..f89c4fc1 100644 --- a/src/Modules/Payments/Application/Subscriptions/CreateSubscription/SubscriptionCreatedEnqueueEmailConfirmationHandler.cs +++ b/src/Modules/Payments/Application/Subscriptions/CreateSubscription/SubscriptionCreatedEnqueueEmailConfirmationHandler.cs @@ -27,14 +27,14 @@ public SubscriptionCreatedEnqueueEmailConfirmationHandler( public async Task Handle(SubscriptionCreatedNotification notification, CancellationToken cancellationToken) { - PayerEmailProvider.Init(_sqlConnectionFactory); - - var payer = await PayerEmailProvider.GetPayerDetails(notification.DomainEvent.PayerId); + var payerEmail = await PayerEmailProvider.GetPayerEmail( + notification.DomainEvent.PayerId, + _sqlConnectionFactory); await _commandsScheduler.EnqueueAsync(new SendSubscriptionCreationConfirmationEmailCommand( Guid.NewGuid(), new SubscriptionId(notification.DomainEvent.SubscriptionId), - payer.Email)); + payerEmail)); } } } \ No newline at end of file diff --git a/src/Modules/Payments/Application/Subscriptions/RenewSubscription/SubscriptionRenewedEnqueueEmailConfirmationHandler.cs b/src/Modules/Payments/Application/Subscriptions/RenewSubscription/SubscriptionRenewedEnqueueEmailConfirmationHandler.cs index 4c2c0058..c918febe 100644 --- a/src/Modules/Payments/Application/Subscriptions/RenewSubscription/SubscriptionRenewedEnqueueEmailConfirmationHandler.cs +++ b/src/Modules/Payments/Application/Subscriptions/RenewSubscription/SubscriptionRenewedEnqueueEmailConfirmationHandler.cs @@ -27,14 +27,14 @@ public SubscriptionRenewedEnqueueEmailConfirmationHandler( public async Task Handle(SubscriptionRenewedNotification notification, CancellationToken cancellationToken) { - PayerEmailProvider.Init(_sqlConnectionFactory); - - var payer = await PayerEmailProvider.GetPayerDetails(notification.DomainEvent.PayerId); + var payerEmail = await PayerEmailProvider.GetPayerEmail( + notification.DomainEvent.PayerId, + _sqlConnectionFactory); await _commandsScheduler.EnqueueAsync(new SendSubscriptionRenewalConfirmationEmailCommand( Guid.NewGuid(), new SubscriptionId(notification.DomainEvent.SubscriptionId), - payer.Email)); + payerEmail)); } } } \ No newline at end of file From 2e1d3a0667d22537e85cdd788381fb54bfe66dce Mon Sep 17 00:00:00 2001 From: Piotr Wachulec Date: Fri, 17 Jul 2020 21:46:34 +0200 Subject: [PATCH 14/14] Fixed typo in sql query --- .../Application/Payers/GetPayerEmail/PayerEmailProvider.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Modules/Payments/Application/Payers/GetPayerEmail/PayerEmailProvider.cs b/src/Modules/Payments/Application/Payers/GetPayerEmail/PayerEmailProvider.cs index 6765772b..cb831ae7 100644 --- a/src/Modules/Payments/Application/Payers/GetPayerEmail/PayerEmailProvider.cs +++ b/src/Modules/Payments/Application/Payers/GetPayerEmail/PayerEmailProvider.cs @@ -12,7 +12,7 @@ public static async Task GetPayerEmail(Guid payerId, ISqlConnectionFacto var connection = sqlConnectionFactory.GetOpenConnection(); const string sql = "SELECT " + - "[Payer].[Email], " + + "[Payer].[Email] " + "FROM [payments].[Payers] AS [Payer] " + "WHERE [Payer].[Id] = @PayerId";