diff --git a/DVSRegister.BusinessLogic/Services/RemoveProvider2i/IRemoveProvider2iService.cs b/DVSRegister.BusinessLogic/Services/RemoveProvider2i/IRemoveProvider2iService.cs index 5a69964..9c36b0d 100644 --- a/DVSRegister.BusinessLogic/Services/RemoveProvider2i/IRemoveProvider2iService.cs +++ b/DVSRegister.BusinessLogic/Services/RemoveProvider2i/IRemoveProvider2iService.cs @@ -1,5 +1,6 @@ using DVSRegister.BusinessLogic.Models.CAB; using DVSRegister.CommonUtility.Models; +using DVSRegister.CommonUtility.Models.Enums; namespace DVSRegister.BusinessLogic.Services { @@ -7,7 +8,7 @@ public interface IRemoveProvider2iService { //Remove provider public Task GetProviderAndServiceDetailsByRemovalToken(string token, string tokenId); - public Task UpdateRemovalStatus(string token, string tokenId, ProviderProfileDto providerDto, string loggedInUserEmail); + public Task UpdateRemovalStatus(TeamEnum team, string token, string tokenId, ProviderProfileDto providerDto, string loggedInUserEmail); public Task RemoveRemovalToken(string token, string tokenId, string loggedInUserEmail); } } diff --git a/DVSRegister.BusinessLogic/Services/RemoveProvider2i/RemoveProvider2iService.cs b/DVSRegister.BusinessLogic/Services/RemoveProvider2i/RemoveProvider2iService.cs index dd288ae..5cef6ea 100644 --- a/DVSRegister.BusinessLogic/Services/RemoveProvider2i/RemoveProvider2iService.cs +++ b/DVSRegister.BusinessLogic/Services/RemoveProvider2i/RemoveProvider2iService.cs @@ -28,8 +28,20 @@ public RemoveProvider2iService(IRemoveProvider2iRepository removeProvider2iRepos if (removeProviderToken.Provider != null) { var provider = await removeProvider2iRepository.GetProviderDetails(removeProviderToken.ProviderProfileId); - ProviderProfileDto providerProfileDto = mapper.Map(provider); - return providerProfileDto; + if (removeProviderToken.RemoveTokenServiceMapping != null && removeProviderToken.RemoveTokenServiceMapping.Count>0) + { + var mappedServiceIds = removeProviderToken.RemoveTokenServiceMapping.Where(mapping => mapping.RemoveProviderTokenId == removeProviderToken.Id).Select(mapping => mapping.ServiceId).ToList(); + ProviderProfileDto providerProfileDto = mapper.Map(provider); + providerProfileDto.Services = providerProfileDto.Services.Where(service => mappedServiceIds.Contains(service.Id)).ToList(); + return providerProfileDto; + + } + else + { + ProviderProfileDto providerProfileDto = mapper.Map(provider); + return providerProfileDto; + } + } else { @@ -37,26 +49,42 @@ public RemoveProvider2iService(IRemoveProvider2iRepository removeProvider2iRepos } } - public async Task UpdateRemovalStatus(string token, string tokenId, ProviderProfileDto providerDto, string loggedInUserEmail) + public async Task UpdateRemovalStatus(TeamEnum team, string token, string tokenId, ProviderProfileDto providerDto, string loggedInUserEmail) { GenericResponse genericResponse = new(); RemoveProviderToken removeProviderToken = await removeProvider2iRepository.GetRemoveProviderToken(token, tokenId); - TeamEnum teamEnum = TeamEnum.Provider;// To Do : update after correcting Removal Reason to int + + + if (!string.IsNullOrEmpty(removeProviderToken.Token) && !string.IsNullOrEmpty(removeProviderToken.TokenId)) //proceed update status if token exists { if (removeProviderToken.RemoveTokenServiceMapping != null && removeProviderToken.RemoveTokenServiceMapping.Count > 0) // remove selected services in this case { - List serviceIds = removeProviderToken.RemoveTokenServiceMapping.Select(mapping => mapping.ServiceId).ToList(); - genericResponse = await removeProvider2iRepository.UpdateRemovalStatus(providerDto.Id, teamEnum, EventTypeEnum.RemoveServices2i, serviceIds, loggedInUserEmail); + List serviceIds = providerDto.Services.Select(s => s.Id).ToList(); + genericResponse = await removeProvider2iRepository.UpdateRemovalStatus(providerDto.Id, team, EventTypeEnum.RemoveServices2i, serviceIds, loggedInUserEmail); + // get updated service list and decide provider status + ProviderProfile providerProfile = await removeProvider2iRepository.GetProviderWithAllServices(providerDto.Id); + // update provider status + ProviderStatusEnum providerStatus = GetProviderStatus(providerProfile.Services, providerProfile.ProviderStatus); + genericResponse = await removeProvider2iRepository.UpdateProviderStatus(providerDto.Id, providerStatus, loggedInUserEmail, EventTypeEnum.RemoveProvider2i); + } else - { - genericResponse = await removeProvider2iRepository.UpdateRemovalStatus(providerDto.Id, teamEnum, EventTypeEnum.RemoveServices2i, null, loggedInUserEmail); + { + genericResponse = await removeProvider2iRepository.UpdateRemovalStatus(providerDto.Id, team, EventTypeEnum.RemoveServices2i, null, loggedInUserEmail); } - + if (genericResponse.Success) { - // ToDo : send email confirmation + if(team == TeamEnum.Provider) + { + await emailSender.SendRemovalRequestConfirmedToDIP(providerDto.PrimaryContactFullName, providerDto.PrimaryContactEmail); + } + + if (team == TeamEnum.DSIT) + { + //to do + } } } @@ -67,5 +95,49 @@ public async Task RemoveRemovalToken(string token, string tokenId, string { return await removeProvider2iRepository.RemoveRemovalToken(token, tokenId, loggedInUserEmail); } + + #region private methods + private ProviderStatusEnum GetProviderStatus(ICollection services, ProviderStatusEnum currentStatus) + { + ProviderStatusEnum providerStatus = currentStatus; + if (services != null && services.Count > 0) + { + + if (services.All(service => service.ServiceStatus == ServiceStatusEnum.Removed)) + { + providerStatus = ProviderStatusEnum.RemovedFromRegister; + } + + var priorityOrder = new List + { + ServiceStatusEnum.CabAwaitingRemovalConfirmation, + ServiceStatusEnum.ReadyToPublish, + ServiceStatusEnum.AwaitingRemovalConfirmation, + ServiceStatusEnum.Published, + ServiceStatusEnum.Removed + }; + + ServiceStatusEnum highestPriorityStatus = services.Select(service => service.ServiceStatus).OrderBy(status => priorityOrder.IndexOf(status)).FirstOrDefault(); + + + switch (highestPriorityStatus) + { + case ServiceStatusEnum.CabAwaitingRemovalConfirmation: + return ProviderStatusEnum.CabAwaitingRemovalConfirmation; + case ServiceStatusEnum.ReadyToPublish: + bool hasPublishedServices = services.Any(service => service.ServiceStatus == ServiceStatusEnum.Published); + return hasPublishedServices ? ProviderStatusEnum.PublishedActionRequired : ProviderStatusEnum.ActionRequired; + case ServiceStatusEnum.AwaitingRemovalConfirmation: + return ProviderStatusEnum.AwaitingRemovalConfirmation; + case ServiceStatusEnum.Published: + return ProviderStatusEnum.Published; + default: + return ProviderStatusEnum.AwaitingRemovalConfirmation; + } + + } + return providerStatus; + } + #endregion } } diff --git a/DVSRegister.CommonUtility/Email/GovUkNotifyApi.cs b/DVSRegister.CommonUtility/Email/GovUkNotifyApi.cs index 4cfcfe1..4793676 100644 --- a/DVSRegister.CommonUtility/Email/GovUkNotifyApi.cs +++ b/DVSRegister.CommonUtility/Email/GovUkNotifyApi.cs @@ -233,6 +233,27 @@ public async Task SendAgreementToPublishToDSIT(string companyName, string }; return await SendEmail(emailModel); } + + #endregion + + #region Remove + public async Task SendRemovalRequestConfirmedToDIP(string recipientName, string emailAddress) + { + var template = govUkNotifyConfig.ProviderRemovalRequestConfirmed; + + var personalisation = new Dictionary + { + { template.RecipientName, recipientName} + + }; + var emailModel = new GovUkNotifyEmailModel + { + EmailAddress = govUkNotifyConfig.OfDiaEmailId, + TemplateId = template.Id, + Personalisation = personalisation + }; + return await SendEmail(emailModel); + } #endregion } } diff --git a/DVSRegister.CommonUtility/Email/IEmailSender.cs b/DVSRegister.CommonUtility/Email/IEmailSender.cs index 1c81b92..634c80e 100644 --- a/DVSRegister.CommonUtility/Email/IEmailSender.cs +++ b/DVSRegister.CommonUtility/Email/IEmailSender.cs @@ -19,5 +19,10 @@ public interface IEmailSender public Task SendAgreementToPublishToDSIT(string companyName, string serviceName); public Task SendAgreementToPublishToDIP(string companyName, string serviceName, string recipientName, string emailAddress); + //remove emails + + public Task SendRemovalRequestConfirmedToDIP(string recipientName, string emailAddress); + + } } diff --git a/DVSRegister.CommonUtility/JWT/IJwtService.cs b/DVSRegister.CommonUtility/JWT/IJwtService.cs index 4a9aabd..08cd9b6 100644 --- a/DVSRegister.CommonUtility/JWT/IJwtService.cs +++ b/DVSRegister.CommonUtility/JWT/IJwtService.cs @@ -5,6 +5,6 @@ namespace DVSRegister.CommonUtility.JWT public interface IJwtService { public TokenDetails GenerateToken(); - public Task ValidateToken(string token); + public Task ValidateToken(string token, string audience = ""); } } diff --git a/DVSRegister.CommonUtility/JWT/JwtService.cs b/DVSRegister.CommonUtility/JWT/JwtService.cs index c44ae6b..8024338 100644 --- a/DVSRegister.CommonUtility/JWT/JwtService.cs +++ b/DVSRegister.CommonUtility/JWT/JwtService.cs @@ -48,7 +48,7 @@ public TokenDetails GenerateToken() return tokenDetails; } - public async Task ValidateToken(string token) + public async Task ValidateToken(string token, string audience = "") { TokenDetails tokenDetails = new TokenDetails(); @@ -60,7 +60,7 @@ public async Task ValidateToken(string token) ValidateLifetime = false, ValidateIssuerSigningKey = true, ValidIssuer = jwtSettings.Issuer, - ValidAudience = jwtSettings.Audience, + ValidAudience = string.IsNullOrEmpty(audience)? jwtSettings.Audience: "DSIT", RequireExpirationTime = true, IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(jwtSettings.SecretKey)) }; diff --git a/DVSRegister.CommonUtility/Models/Email/GovUkNotifyConfiguration.cs b/DVSRegister.CommonUtility/Models/Email/GovUkNotifyConfiguration.cs index 30206e2..b0197f5 100644 --- a/DVSRegister.CommonUtility/Models/Email/GovUkNotifyConfiguration.cs +++ b/DVSRegister.CommonUtility/Models/Email/GovUkNotifyConfiguration.cs @@ -21,5 +21,6 @@ public class GovUkNotifyConfiguration public AgreementToPublishTemplate AgreementToPublishTemplate { get; set; } public AgreementToPublishToDSITTemplate AgreementToPublishToDSITTemplate { get; set; } public AgreementToProceedApplicationToDSIT AgreementToProceedApplicationToDSIT { get; set; } + public ProviderRemovalRequestConfirmed ProviderRemovalRequestConfirmed { get; set; } } } diff --git a/DVSRegister.CommonUtility/Models/Email/ProviderRemovalRequestConfirmed.cs b/DVSRegister.CommonUtility/Models/Email/ProviderRemovalRequestConfirmed.cs new file mode 100644 index 0000000..09dbcb3 --- /dev/null +++ b/DVSRegister.CommonUtility/Models/Email/ProviderRemovalRequestConfirmed.cs @@ -0,0 +1,8 @@ +namespace DVSRegister.CommonUtility.Models +{ + public class ProviderRemovalRequestConfirmed + { + public string Id { get; set; } + public string RecipientName { get; set; } + } +} diff --git a/DVSRegister.Data/RemoveProvider2i/IRemoveProvider2iRepository.cs b/DVSRegister.Data/RemoveProvider2i/IRemoveProvider2iRepository.cs index 9247471..74dbfd9 100644 --- a/DVSRegister.Data/RemoveProvider2i/IRemoveProvider2iRepository.cs +++ b/DVSRegister.Data/RemoveProvider2i/IRemoveProvider2iRepository.cs @@ -13,6 +13,9 @@ public interface IRemoveProvider2iRepository public Task GetProviderDetails(int providerId); public Task UpdateRemovalStatus(int providerProfileId, TeamEnum teamEnum, EventTypeEnum eventType, List? serviceIds, string loggedInUserEmail); public Task RemoveRemovalToken(string token, string tokenId, string loggedInUserEmail); + + public Task GetProviderWithAllServices(int providerId); + public Task UpdateProviderStatus(int providerProfileId, ProviderStatusEnum providerStatus, string loggedInUserEmail, EventTypeEnum eventType); #endregion } } diff --git a/DVSRegister.Data/RemoveProvider2i/RemoveProvider2iRepository.cs b/DVSRegister.Data/RemoveProvider2i/RemoveProvider2iRepository.cs index ec5997f..d647fec 100644 --- a/DVSRegister.Data/RemoveProvider2i/RemoveProvider2iRepository.cs +++ b/DVSRegister.Data/RemoveProvider2i/RemoveProvider2iRepository.cs @@ -1,7 +1,6 @@ -using DVSRegister.CommonUtility.Models.Enums; -using DVSRegister.CommonUtility.Models; +using DVSRegister.CommonUtility.Models; +using DVSRegister.CommonUtility.Models.Enums; using DVSRegister.Data.Entities; -using DVSRegister.Data.Repositories; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Logging; @@ -20,11 +19,18 @@ public RemoveProvider2iRepository(DVSRegisterDbContext context, ILogger GetRemoveProviderToken(string token, string tokenId) { - return await context.RemoveProviderToken.Include(p => p.Provider).ThenInclude(p => p.Services) + return await context.RemoveProviderToken.Include(p => p.Provider).ThenInclude(p => p.Services).Include(p=>p.RemoveTokenServiceMapping) .FirstOrDefaultAsync(e => e.Token == token && e.TokenId == tokenId) ?? new RemoveProviderToken(); } + public async Task GetProviderWithAllServices(int providerId) + { + ProviderProfile provider = new(); + provider = await context.ProviderProfile.Include(p => p.Services) + .Where(p => p.Id == providerId).FirstOrDefaultAsync() ?? new ProviderProfile(); + return provider; + } public async Task GetProviderDetails(int providerId) { ProviderProfile provider = new(); @@ -81,14 +87,20 @@ public async Task UpdateRemovalStatus(int providerProfileId, Te using var transaction = await context.Database.BeginTransactionAsync(); try { - if (serviceIds != null || serviceIds?.Count > 0)// remove only selected services + if (serviceIds != null && serviceIds.Count > 0)// remove only selected services { - var existingServices = await context.Service.Where(e => e.ProviderProfileId == providerProfileId && serviceIds.Contains(e.Id)).ToListAsync(); - foreach (var existingService in existingServices) + foreach (var item in serviceIds) { - existingService.ServiceStatus = ServiceStatusEnum.Removed; - existingService.ModifiedTime = DateTime.UtcNow; + var service = await context.Service.Where(s => s.Id == item && s.ProviderProfileId == providerProfileId).FirstOrDefaultAsync(); + if (service.ServiceStatus == ServiceStatusEnum.AwaitingRemovalConfirmation) + { + service.ServiceStatus = ServiceStatusEnum.Removed; + service.ModifiedTime = DateTime.UtcNow; + service.RemovedTime = DateTime.UtcNow; + } + } + } else // remove all services and provider { @@ -97,14 +109,18 @@ public async Task UpdateRemovalStatus(int providerProfileId, Te { existingProvider.ModifiedTime = DateTime.UtcNow; existingProvider.ProviderStatus = ProviderStatusEnum.RemovedFromRegister; - + existingProvider.RemovedTime = DateTime.UtcNow; // Update the status of each service if (existingProvider.Services != null) { foreach (var service in existingProvider.Services) { - service.ServiceStatus = ServiceStatusEnum.Removed; - service.ModifiedTime = DateTime.UtcNow; + if (service.ServiceStatus == ServiceStatusEnum.AwaitingRemovalConfirmation ) + { + service.ServiceStatus = ServiceStatusEnum.Removed; + service.ModifiedTime = DateTime.UtcNow; + service.RemovedTime = DateTime.UtcNow; + } } } } @@ -137,7 +153,40 @@ public async Task RemoveRemovalToken(string token, string tokenId, string return false; } + + + public async Task UpdateProviderStatus(int providerProfileId, ProviderStatusEnum providerStatus, string loggedInUserEmail, EventTypeEnum eventType) + { + GenericResponse genericResponse = new(); + using var transaction = await context.Database.BeginTransactionAsync(); + try + { + var existingProvider = await context.ProviderProfile.FirstOrDefaultAsync(p => p.Id == providerProfileId); + if (existingProvider != null) + { + + existingProvider.ModifiedTime = DateTime.UtcNow; + existingProvider.ProviderStatus = providerStatus; + + if (providerStatus == ProviderStatusEnum.RemovedFromRegister) + { + existingProvider.RemovedTime = DateTime.UtcNow; + } + + } + await context.SaveChangesAsync(TeamEnum.DSIT, eventType, loggedInUserEmail); + await transaction.CommitAsync(); + genericResponse.Success = true; + } + catch (Exception ex) + { + genericResponse.Success = false; + await transaction.RollbackAsync(); + logger.LogError(ex.Message); + } + return genericResponse; + } #endregion - } + } } diff --git a/DVSRegister/Controllers/RemoveProvider2iController.cs b/DVSRegister/Controllers/RemoveProvider2iController.cs index 96e071d..06883b7 100644 --- a/DVSRegister/Controllers/RemoveProvider2iController.cs +++ b/DVSRegister/Controllers/RemoveProvider2iController.cs @@ -55,7 +55,7 @@ public async Task RemoveProviderDetails(string token) [HttpPost("provider/provider-details")] public async Task RemoveProviderDetails(RemoveProviderViewModel removeProviderViewModel, string action) { - string user = string.Empty;// To Do : update based on reason in provider + string user = "Provider"; if (!string.IsNullOrEmpty(removeProviderViewModel.token)) { @@ -66,9 +66,10 @@ public async Task RemoveProviderDetails(RemoveProviderViewModel r if (tokenDetails != null && tokenDetails.IsAuthorised) { ProviderProfileDto? provider = await removeProvider2iService.GetProviderAndServiceDetailsByRemovalToken(tokenDetails.Token, tokenDetails.TokenId); + user = provider.PrimaryContactEmail + ";" + provider.SecondaryContactEmail; if (ModelState.IsValid) { - GenericResponse genericResponse = await removeProvider2iService.UpdateRemovalStatus(tokenDetails.Token, tokenDetails.TokenId, provider, user); + GenericResponse genericResponse = await removeProvider2iService.UpdateRemovalStatus(TeamEnum.Provider, tokenDetails.Token, tokenDetails.TokenId, provider, user); if (genericResponse.Success) { await removeProvider2iService.RemoveRemovalToken(tokenDetails.Token, tokenDetails.TokenId, user); @@ -123,7 +124,7 @@ public async Task RemoveProviderDetailsDSIT(string token) if (!string.IsNullOrEmpty(token)) { removeProviderViewModel.token = token; - TokenDetails tokenDetails = await jwtService.ValidateToken(token); + TokenDetails tokenDetails = await jwtService.ValidateToken(token, "DSIT"); if (tokenDetails != null && tokenDetails.IsAuthorised) { ProviderProfileDto? provider = await removeProvider2iService.GetProviderAndServiceDetailsByRemovalToken(tokenDetails.Token, tokenDetails.TokenId); @@ -150,20 +151,20 @@ public async Task RemoveProviderDetailsDSIT(string token) [HttpPost("dsit/provider-details")] public async Task RemoveProviderDetailsDSIT(RemoveProviderViewModel removeProviderViewModel, string action) { - string user = string.Empty;// To Do : update based on reason in provider + string user = "DSIT"; if (!string.IsNullOrEmpty(removeProviderViewModel.token)) { if (action == "remove") { - TokenDetails tokenDetails = await jwtService.ValidateToken(removeProviderViewModel.token); + TokenDetails tokenDetails = await jwtService.ValidateToken(removeProviderViewModel.token, "DSIT"); if (tokenDetails != null && tokenDetails.IsAuthorised) { ProviderProfileDto? provider = await removeProvider2iService.GetProviderAndServiceDetailsByRemovalToken(tokenDetails.Token, tokenDetails.TokenId); if (ModelState.IsValid) { - GenericResponse genericResponse = await removeProvider2iService.UpdateRemovalStatus(tokenDetails.Token, tokenDetails.TokenId, provider, user); + GenericResponse genericResponse = await removeProvider2iService.UpdateRemovalStatus(TeamEnum.DSIT,tokenDetails.Token, tokenDetails.TokenId, provider, user); if (genericResponse.Success) { await removeProvider2iService.RemoveRemovalToken(tokenDetails.Token, tokenDetails.TokenId, user); diff --git a/DVSRegister/appsettings.json b/DVSRegister/appsettings.json index feba6f0..bebe3f4 100644 --- a/DVSRegister/appsettings.json +++ b/DVSRegister/appsettings.json @@ -69,6 +69,10 @@ "Id": "dcdeb9b2-81b3-4601-aa30-da1ebb69bc8c", "CompanyName": "company name", "ServiceName": "service name" + }, + "ProviderRemovalRequestConfirmed": { + "Id": "ccbb93eb-410e-497d-9cea-a778bf2a9162", + "RecipientName": "recipient name" } }, "Cookies": {