Skip to content

Commit

Permalink
Nazar yavor26/service provider statuses #955 and #969 (#1000)
Browse files Browse the repository at this point in the history
* Added property ProviderStatus in WorkshopDTO and mapping for it from Workshop model

* Added propperty ProviderStatus to WorkshopES model

* Added term query for ProviderStatus in ESWorkshopProvider

* Added Recheck to ProviderStatus enum

* Added check if the ProbiderStatus is Recheck in PredicateBuild method in WorkshopService

* Added check if the ProviderStatus is Recheck in CreateQueryFromFilter method in ESWorkshopProvider

* Replaced Panding provider status into Recheck in GetNotificationsRecipientIds method in ProviderService. Created and added method GetRegionAdminsIds

* Added mocks of IRegionAdminRepository in integration and unit tests for ProviderService

* Fixed ProviderServiceTests for new enum item Recheck

* Deleted unnecessary comments from method GetNotificationsRecipientIds in ProviderService

* Fixed additional enter before test name

* Fixed WorkshopService after rebase develop

* Moved enum ProviderStatus to Common project

* Changed namespace of ProviderStutus

* Added EnumDataType attribute for ProviderStatus property in WorkshopDTO

* Fixed method GetRegionAdminsIds in ProviderService

* Added synchronization with Elasticsearch for UpdateStatus method in ProviderService

* Added synchronization with Elasticsearch for UpdateProviderWithActionBeforeSavingChanges method in ProviderService if ProviderStatus was changed
  • Loading branch information
NazarYavor26 authored Feb 21, 2023
1 parent dac6ec7 commit f511bf2
Show file tree
Hide file tree
Showing 14 changed files with 96 additions and 23 deletions.
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;

namespace OutOfSchool.Services.Enums;
namespace OutOfSchool.Common.Enums;

[JsonConverter(typeof(StringEnumConverter))]
public enum ProviderStatus
{
Pending,
Editing,
Approved,
Recheck,
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System.ComponentModel.DataAnnotations;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
using OutOfSchool.Common.Enums;
using OutOfSchool.Services.Enums;

namespace OutOfSchool.Services.Models.Configurations;
Expand Down
11 changes: 11 additions & 0 deletions OutOfSchool/OutOfSchool.ElasticsearchData/ESWorkshopProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,17 @@ private QueryContainer CreateQueryFromFilter(WorkshopFilterES filter)
{
var queryContainer = new QueryContainer();

queryContainer &= new TermsQuery()
{
Field = Infer.Field<WorkshopES>(w => w.ProviderStatus),
Terms = new List<ProviderStatus>()
{
ProviderStatus.Approved,
ProviderStatus.Recheck,
}
.Cast<object>(),
};

if (filter.Ids.Any())
{
queryContainer &= new TermsQuery()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ public class WorkshopES

public string ProviderTitle { get; set; }

public ProviderStatus ProviderStatus { get; set; }

public OwnershipType ProviderOwnership { get; set; }

public string Description { get; set; } // Sum of all WorkshopDescriptionItems (SectionName + Description)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
using Moq;
using NUnit.Framework;
using OutOfSchool.Common;
using OutOfSchool.Common.Enums;
using OutOfSchool.Services.Enums;
using OutOfSchool.Services.Models;
using OutOfSchool.Tests.Common;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
using MockQueryable.Moq;
using Moq;
using NUnit.Framework;
using OutOfSchool.Common.Enums;
using OutOfSchool.Services.Enums;
using OutOfSchool.Services.Models;
using OutOfSchool.Services.Repository;
Expand Down Expand Up @@ -40,6 +41,7 @@ public class ProviderServiceTests
private Mock<IMinistryAdminService> ministryAdminServiceMock;
private Mock<IRegionAdminService> regionAdminServiceMock;
private Mock<ICodeficatorService> codeficatorServiceMock;
private Mock<IRegionAdminRepository> regionAdminRepositoryMock;

private List<Provider> fakeProviders;
private User fakeUser;
Expand Down Expand Up @@ -69,6 +71,7 @@ public void SetUp()
ministryAdminServiceMock = new Mock<IMinistryAdminService>();
regionAdminServiceMock = new Mock<IRegionAdminService>();
codeficatorServiceMock = new Mock<ICodeficatorService>();
regionAdminRepositoryMock = new Mock<IRegionAdminRepository>();


mapper = TestHelper.CreateMapperInstanceOfProfileType<MappingProfile>();
Expand All @@ -91,7 +94,8 @@ public void SetUp()
currentUserServiceMock.Object,
ministryAdminServiceMock.Object,
regionAdminServiceMock.Object,
codeficatorServiceMock.Object);
codeficatorServiceMock.Object,
regionAdminRepositoryMock.Object);
}

#region Create
Expand Down Expand Up @@ -427,7 +431,7 @@ public async Task Update_UserCanUpdateExistingEntityOfRelatedProvider_UpdatesExi
{
// Arrange
var provider = fakeProviders.RandomItem();
provider.Status = ProviderStatus.Pending;
provider.Status = ProviderStatus.Recheck;

var updatedTitle = Guid.NewGuid().ToString();
var providerToUpdateDto = mapper.Map<ProviderDto>(provider);
Expand Down Expand Up @@ -455,7 +459,7 @@ public async Task Update_UserCanUpdateExistingEntityOfRelatedProvider_UpdatesExi
TestHelper.AssertDtosAreEqual(providerToUpdateDto, result);
}

[TestCase(ProviderStatus.Pending)]
[TestCase(ProviderStatus.Recheck)]
[TestCase(ProviderStatus.Editing)]
[TestCase(ProviderStatus.Approved)]
public async Task Update_UserTriesToChangeStatus_StatusIsNotChanged(ProviderStatus initialStatus)
Expand Down Expand Up @@ -485,10 +489,10 @@ public async Task Update_UserTriesToChangeStatus_StatusIsNotChanged(ProviderStat
TestHelper.AssertDtosAreEqual(expected, result);
}

[TestCase(ProviderStatus.Pending)]
[TestCase(ProviderStatus.Recheck)]
[TestCase(ProviderStatus.Editing)]
[TestCase(ProviderStatus.Approved)]
public async Task Update_UserChangesFullTitle_StatusIsChangedToPending(ProviderStatus initialStatus)
public async Task Update_UserChangesFullTitle_StatusIsChangedToRecheck(ProviderStatus initialStatus)
{
// Arrange
var provider = fakeProviders.RandomItem();
Expand All @@ -499,7 +503,7 @@ public async Task Update_UserChangesFullTitle_StatusIsChangedToPending(ProviderS
providerToUpdateDto.FullTitle = updatedTitle;

var expected = mapper.Map<ProviderDto>(provider);
expected.Status = ProviderStatus.Pending;
expected.Status = ProviderStatus.Recheck;
expected.FullTitle = updatedTitle;

providersRepositoryMock.Setup(r => r.GetById(It.IsAny<Guid>()))
Expand All @@ -524,10 +528,10 @@ public async Task Update_UserChangesFullTitle_StatusIsChangedToPending(ProviderS
TestHelper.AssertDtosAreEqual(expected, result);
}

[TestCase(ProviderStatus.Pending)]
[TestCase(ProviderStatus.Recheck)]
[TestCase(ProviderStatus.Editing)]
[TestCase(ProviderStatus.Approved)]
public async Task Update_UserChangesEdrpouIpn_StatusIsChangedToPending(ProviderStatus initialStatus)
public async Task Update_UserChangesEdrpouIpn_StatusIsChangedToRecheck(ProviderStatus initialStatus)
{
// Arrange
var provider = fakeProviders.RandomItem();
Expand All @@ -539,7 +543,7 @@ public async Task Update_UserChangesEdrpouIpn_StatusIsChangedToPending(ProviderS
providerToUpdateDto.EdrpouIpn = updatedEdrpouIpn;

var expected = mapper.Map<ProviderDto>(provider);
expected.Status = ProviderStatus.Pending;
expected.Status = ProviderStatus.Recheck;
expected.EdrpouIpn = updatedEdrpouIpn;

providersRepositoryMock.Setup(r => r.GetById(It.IsAny<Guid>()))
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Collections.Generic;
using OutOfSchool.Common.Enums;
using OutOfSchool.Services.Enums;

namespace OutOfSchool.WebApi.Models.Providers;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
using System;
using System.ComponentModel.DataAnnotations;
using OutOfSchool.Services.Enums;
using OutOfSchool.Common.Enums;

namespace OutOfSchool.WebApi.Models.Providers;

Expand Down
3 changes: 3 additions & 0 deletions OutOfSchool/OutOfSchool.WebApi/Models/Workshop/WorkshopDTO.cs
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,9 @@ public class WorkshopDTO : IValidatableObject
[Required]
public Guid ProviderId { get; set; }

[EnumDataType(typeof(ProviderStatus), ErrorMessage = Constants.EnumErrorMessage)]
public ProviderStatus ProviderStatus { get; set; }

[Required]
public long AddressId { get; set; }

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -604,7 +604,9 @@ private Expression<Func<Workshop, bool>> PredicateBuild(WorkshopFilter filter)
}
else
{
predicate = predicate.And(x => x.Provider.Status == ProviderStatus.Approved);
predicate = predicate.And(x => x.Provider.Status == ProviderStatus.Approved)
.Or(x => x.Provider.Status == ProviderStatus.Recheck);

predicate = predicate.And(x => !x.IsBlocked);
}

Expand Down
52 changes: 47 additions & 5 deletions OutOfSchool/OutOfSchool.WebApi/Services/ProviderService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Localization;
using Microsoft.Extensions.Logging;
using OutOfSchool.Common.Enums;
using OutOfSchool.Common.Extensions;
using OutOfSchool.Services.Enums;
using OutOfSchool.Services.Models;
Expand Down Expand Up @@ -40,6 +41,7 @@ public class ProviderService : IProviderService, INotificationReciever
private readonly IMinistryAdminService ministryAdminService;
private readonly IRegionAdminService regionAdminService;
private readonly ICodeficatorService codeficatorService;
private readonly IRegionAdminRepository regionAdminRepository;

// TODO: It should be removed after models revision.
// Temporary instance to fill 'Provider' model 'User' property
Expand Down Expand Up @@ -84,7 +86,8 @@ public ProviderService(
ICurrentUserService currentUserService,
IMinistryAdminService ministryAdminService,
IRegionAdminService regionAdminService,
ICodeficatorService codeficatorService)
ICodeficatorService codeficatorService,
IRegionAdminRepository regionAdminRepository)
{
this.localizer = localizer ?? throw new ArgumentNullException(nameof(localizer));
this.mapper = mapper ?? throw new ArgumentNullException(nameof(mapper));
Expand All @@ -104,6 +107,7 @@ public ProviderService(
this.ministryAdminService = ministryAdminService ?? throw new ArgumentNullException(nameof(ministryAdminService));
this.regionAdminService = regionAdminService ?? throw new ArgumentNullException(nameof(regionAdminService));
this.codeficatorService = codeficatorService ?? throw new ArgumentNullException(nameof(codeficatorService));
this.regionAdminRepository = regionAdminRepository;
}

private protected IImageDependentEntityImagesInteractionService<Provider> ProviderImagesService { get; }
Expand Down Expand Up @@ -277,6 +281,16 @@ public async Task<ProviderStatusDto> UpdateStatus(ProviderStatusDto dto, string
provider.StatusReason = dto.StatusReason;
await providerRepository.UnitOfWork.CompleteAsync().ConfigureAwait(false);

var workshops = await workshopServiceCombiner
.PartialUpdateByProvider(provider)
.ConfigureAwait(false);

foreach (var workshop in workshops)
{
logger.LogInformation($"Provider's properties with Id = {provider?.Id} " +
$"in workshops with Id = {workshop?.Id} updated successfully.");
}

logger.LogInformation($"Provider(id) {dto.ProviderId} Status was changed to {dto.Status}");

await SendNotification(provider, NotificationAction.Update, true, false).ConfigureAwait(false);
Expand Down Expand Up @@ -371,21 +385,21 @@ async Task<IEnumerable<string>> INotificationReciever.GetNotificationsRecipientI

if (action == NotificationAction.Create)
{
// there should be District admin
recipientIds.AddRange(await GetTechAdminsIds().ConfigureAwait(false));
recipientIds.AddRange(await GetMinistryAdminsIds(provider.InstitutionId).ConfigureAwait(false));
recipientIds.AddRange(await GetRegionAdminsIds(provider.LegalAddress).ConfigureAwait(false));
}
else if (action == NotificationAction.Update)
{
if (additionalData != null
&& additionalData.TryGetValue("Status", out var statusValue)
&& Enum.TryParse(statusValue, out ProviderStatus status))
{
if (status == ProviderStatus.Pending)
if (status == ProviderStatus.Recheck)
{
// there should be District admin
recipientIds.AddRange(await GetTechAdminsIds().ConfigureAwait(false));
recipientIds.AddRange(await GetMinistryAdminsIds(provider.InstitutionId).ConfigureAwait(false));
recipientIds.AddRange(await GetRegionAdminsIds(provider.LegalAddress).ConfigureAwait(false));
}
else if (status == ProviderStatus.Editing
|| status == ProviderStatus.Approved)
Expand Down Expand Up @@ -478,6 +492,7 @@ private protected async Task<ProviderDto> UpdateProviderWithActionBeforeSavingCh
try
{
var checkProvider = await providerRepository.GetById(providerDto.Id).ConfigureAwait(false);
var dataSynchronized = false;

if (checkProvider?.UserId != userId)
{
Expand Down Expand Up @@ -526,6 +541,8 @@ private protected async Task<ProviderDto> UpdateProviderWithActionBeforeSavingCh
$"in workshops with Id = {workshop?.Id} updated successfully.");
}

dataSynchronized = true;

return checkProvider;
}).ConfigureAwait(false);
}
Expand All @@ -547,6 +564,20 @@ private protected async Task<ProviderDto> UpdateProviderWithActionBeforeSavingCh

if (statusChanged || licenseChanged)
{
// TODO: Improve logic with duplicating the code below
if (!dataSynchronized)
{
var workshops = await workshopServiceCombiner
.PartialUpdateByProvider(mapper.Map<Provider>(providerDto))
.ConfigureAwait(false);

foreach (var workshop in workshops)
{
logger.LogInformation($"Provider's properties with Id = {checkProvider?.Id} " +
$"in workshops with Id = {workshop?.Id} updated successfully.");
}
}

await SendNotification(checkProvider, NotificationAction.Update, statusChanged, licenseChanged)
.ConfigureAwait(false);
}
Expand All @@ -571,7 +602,7 @@ private void ChangeProviderStatusIfNeeded(
if (!(checkProvider.FullTitle == providerDto.FullTitle
&& checkProvider.EdrpouIpn == providerDto.EdrpouIpn))
{
checkProvider.Status = ProviderStatus.Pending;
checkProvider.Status = ProviderStatus.Recheck;
statusChanged = true;
}

Expand Down Expand Up @@ -742,4 +773,15 @@ private async Task<IEnumerable<string>> GetMinistryAdminsIds(Guid? ministryId)
.ConfigureAwait(false);
return ministryAdminsIds;
}

private async Task<IEnumerable<string>> GetRegionAdminsIds(Address address)
{
var regionAdminsIds = await regionAdminRepository
.GetByFilterNoTracking(a => a.CATOTTGId == address.CATOTTGId)
.Select(a => a.UserId)
.ToListAsync()
.ConfigureAwait(false);

return regionAdminsIds;
}
}
6 changes: 4 additions & 2 deletions OutOfSchool/OutOfSchool.WebApi/Services/ProviderServiceV2.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@ public ProviderServiceV2(
ICurrentUserService currentUserService,
IMinistryAdminService ministryAdminService,
IRegionAdminService regionAdminService,
ICodeficatorService codeficatorService)
ICodeficatorService codeficatorService,
IRegionAdminRepository regionAdminRepository)
: base(
providerRepository,
usersRepository,
Expand All @@ -54,7 +55,8 @@ public ProviderServiceV2(
currentUserService,
ministryAdminService,
regionAdminService,
codeficatorService)
codeficatorService,
regionAdminRepository)
{
}

Expand Down
4 changes: 3 additions & 1 deletion OutOfSchool/OutOfSchool.WebApi/Util/MappingProfile.cs
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,9 @@ public MappingProfile()
x.Status == ApplicationStatus.Approved
|| x.Status == ApplicationStatus.StudyingForYears)))
.ForMember(dest => dest.ProviderLicenseStatus, opt =>
opt.MapFrom(src => src.Provider.LicenseStatus));
opt.MapFrom(src => src.Provider.LicenseStatus))
.ForMember(dest => dest.ProviderStatus, opt =>
opt.MapFrom(src => src.Provider.Status));

CreateMap<WorkshopDescriptionItem, WorkshopDescriptionItemDto>().ReverseMap();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ public async Task SetUp()
var ministryAdminServiceMock = new Mock<IMinistryAdminService>();
var regionAdminService = new Mock<IRegionAdminService>();
var codeficatorService = new Mock<ICodeficatorService>();
var regionAdminRepository = new Mock<IRegionAdminRepository>();

this.providerService = new ProviderService(
providerRepository,
Expand All @@ -79,7 +80,8 @@ public async Task SetUp()
currentUserServiceMock.Object,
ministryAdminServiceMock.Object,
regionAdminService.Object,
codeficatorService.Object);
codeficatorService.Object,
regionAdminRepository.Object);
}

[Test]
Expand Down Expand Up @@ -128,8 +130,7 @@ public async Task UpdateWhenProviderHasSameAdresses_WithActualAddressNull_Update
}

[Test]
public async Task
UpdateWhenProviderHasSameAdresses_WithNewLegalAddressAndActualIsPreviousLegal_UpdatesOneAddress()
public async Task UpdateWhenProviderHasSameAdresses_WithNewLegalAddressAndActualIsPreviousLegal_UpdatesOneAddress()
{
// Arrange
await using var context = this.GetContext();
Expand Down

0 comments on commit f511bf2

Please sign in to comment.