diff --git a/OutOfSchool/OutOfSchool.WebApi/Controllers/V1/MinistryAdminController.cs b/OutOfSchool/OutOfSchool.WebApi/Controllers/V1/MinistryAdminController.cs index 33b0bf9857..d590d44d88 100644 --- a/OutOfSchool/OutOfSchool.WebApi/Controllers/V1/MinistryAdminController.cs +++ b/OutOfSchool/OutOfSchool.WebApi/Controllers/V1/MinistryAdminController.cs @@ -60,6 +60,55 @@ public async Task Profile() return Ok(ministryAdmin); } + /// + /// Get MinistryAdmin by it's id. + /// + /// MinistryAdmin id. + /// Authorized MinistryAdmin's profile. + [HasPermission(Permissions.SystemManagement)] + [HttpGet] + [ProducesResponseType(StatusCodes.Status200OK, Type = typeof(MinistryAdminDto))] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(StatusCodes.Status403Forbidden)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + public async Task GetById([FromQuery] long id) + { + var ministryAdmin = await ministryAdminService.GetById(id).ConfigureAwait(false); + if (ministryAdmin == null) + { + return NotFound($"There is no Ministry admin in DB with {nameof(ministryAdmin.Id)} - {id}"); + } + + return Ok(ministryAdmin); + } + + /// + /// Get MinistryAdmins that match filter's parameters. + /// + /// Entity that represents searching parameters. + /// , or no content. + [HasPermission(Permissions.SystemManagement)] + [HttpGet] + [ProducesResponseType(StatusCodes.Status200OK, Type = typeof(SearchResult))] + [ProducesResponseType(StatusCodes.Status204NoContent)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(StatusCodes.Status403Forbidden)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + public async Task GetByFilter([FromQuery] MinistryAdminFilter filter) + { + var ministryAdmins = await ministryAdminService.GetByFilter(filter).ConfigureAwait(false); + + if (ministryAdmins.TotalAmount < 1) + { + return NoContent(); + } + + return Ok(ministryAdmins); + } + /// /// Method for creating new MinistryAdmin. /// diff --git a/OutOfSchool/OutOfSchool.WebApi/Models/MinistryAdminFilter.cs b/OutOfSchool/OutOfSchool.WebApi/Models/MinistryAdminFilter.cs new file mode 100644 index 0000000000..af43ab0e94 --- /dev/null +++ b/OutOfSchool/OutOfSchool.WebApi/Models/MinistryAdminFilter.cs @@ -0,0 +1,6 @@ +namespace OutOfSchool.WebApi.Models; + +public class MinistryAdminFilter : SearchStringFilter +{ + public Guid InstitutionId { get; set; } = Guid.Empty; +} \ No newline at end of file diff --git a/OutOfSchool/OutOfSchool.WebApi/Services/IMinistryAdminService.cs b/OutOfSchool/OutOfSchool.WebApi/Services/IMinistryAdminService.cs index f25e1126d8..643c55b402 100644 --- a/OutOfSchool/OutOfSchool.WebApi/Services/IMinistryAdminService.cs +++ b/OutOfSchool/OutOfSchool.WebApi/Services/IMinistryAdminService.cs @@ -12,6 +12,14 @@ public interface IMinistryAdminService /// A representing the result of the asynchronous operation. Task GetByUserId(string id); + /// + /// Get entity by it's key. + /// + /// Key in the table. + /// A representing the result of the asynchronous operation. + /// The task result contains the entity that was found, or null. + Task GetById(long id); + /// /// Create Ministry Admin. /// @@ -54,4 +62,12 @@ public interface IMinistryAdminService /// The task result contains if provider is subordinate of the ministry admin /// filter; otherwise, . Task IsProviderSubordinateAsync(string ministryAdminUserId, Guid providerId); + + /// + /// Get Ministry Admins from the database that match filter's parameters. + /// + /// Filter with specified searching parameters. + /// A representing the result of the asynchronous operation. + /// The task result contains the that contains found elements. + Task> GetByFilter(MinistryAdminFilter filter); } \ No newline at end of file diff --git a/OutOfSchool/OutOfSchool.WebApi/Services/MinistryAdminService.cs b/OutOfSchool/OutOfSchool.WebApi/Services/MinistryAdminService.cs index 50995e0c7c..9c814ca48f 100644 --- a/OutOfSchool/OutOfSchool.WebApi/Services/MinistryAdminService.cs +++ b/OutOfSchool/OutOfSchool.WebApi/Services/MinistryAdminService.cs @@ -1,9 +1,11 @@ -using AutoMapper; +using System.Linq.Expressions; +using AutoMapper; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Options; using Newtonsoft.Json; using OutOfSchool.Common.Models; +using OutOfSchool.Services.Enums; using OutOfSchool.WebApi.Models; namespace OutOfSchool.WebApi.Services; @@ -36,6 +38,22 @@ public MinistryAdminService( responseDto = new ResponseDto(); } + public async Task GetById(long id) + { + logger.LogInformation($"Getting InstitutionAdmin by Id started. Looking Id = {id}."); + + var institutionAdmin = await institutionAdminRepository.GetById(id).ConfigureAwait(false); + + if (institutionAdmin is null) + { + return null; + } + + logger.LogInformation($"Successfully got a InstitutionAdmin with Id = {id}."); + + return mapper.Map(institutionAdmin); + } + public async Task GetByUserId(string id) { logger.LogInformation($"Getting MinistryAdmin by UserId started. Looking UserId is {id}."); @@ -86,6 +104,48 @@ public async Task CreateMinistryAdminAsync(string userId, CreateMin return response; } + /// + public async Task> GetByFilter(MinistryAdminFilter filter) + { + logger.LogInformation("Getting all Ministry admins started (by filter)."); + + filter ??= new MinistryAdminFilter(); + ModelValidationHelper.ValidateOffsetFilter(filter); + + var filterPredicate = PredicateBuild(filter); + + int count = await institutionAdminRepository.Count(filterPredicate).ConfigureAwait(false); + + var sortExpression = new Dictionary>, SortDirection> + { + { x => x.User.LastName, SortDirection.Ascending }, + }; + var institutionAdmins = await institutionAdminRepository + .Get( + skip: filter.From, + take: filter.Size, + includeProperties: string.Empty, + where: filterPredicate, + orderBy: sortExpression, + asNoTracking: false) + .ToListAsync() + .ConfigureAwait(false); + + logger.LogInformation(!institutionAdmins.Any() + ? "Parents table is empty." + : $"All {institutionAdmins.Count} records were successfully received from the Parent table"); + + var ministryAdminsDto = institutionAdmins.Select(admin => mapper.Map(admin)).ToList(); + + var result = new SearchResult() + { + TotalAmount = count, + Entities = ministryAdminsDto, + }; + + return result; + } + /// public async Task Update(MinistryAdminDto ministryAdminDto) { @@ -215,4 +275,33 @@ public async Task IsProviderSubordinateAsync(string ministryAdminUserId, G .Any(x => x.UserId == ministryAdminUserId && x.Institution.RelatedProviders.Any(rp => rp.Id == providerId)).ConfigureAwait(false); } + + private static Expression> PredicateBuild(MinistryAdminFilter filter) + { + var predicate = PredicateBuilder.True(); + + if (!string.IsNullOrWhiteSpace(filter.SearchString)) + { + var tempPredicate = PredicateBuilder.False(); + + foreach (var word in filter.SearchString.Split(' ', ',', StringSplitOptions.RemoveEmptyEntries)) + { + tempPredicate = tempPredicate.Or( + x => x.User.FirstName.Contains(word, StringComparison.InvariantCultureIgnoreCase) + || x.User.LastName.Contains(word, StringComparison.InvariantCultureIgnoreCase) + || x.User.Email.Contains(word, StringComparison.InvariantCultureIgnoreCase) + || x.Institution.Title.Contains(word, StringComparison.InvariantCultureIgnoreCase) + || x.User.PhoneNumber.Contains(word, StringComparison.InvariantCultureIgnoreCase)); + } + + predicate = predicate.And(tempPredicate); + } + + if (filter.InstitutionId != Guid.Empty) + { + predicate = predicate.And(a => a.Institution.Id == filter.InstitutionId); + } + + return predicate; + } } \ No newline at end of file diff --git a/OutOfSchool/OutOfSchool.WebApi/Util/MappingProfile.cs b/OutOfSchool/OutOfSchool.WebApi/Util/MappingProfile.cs index a649c141ac..006ecf327d 100644 --- a/OutOfSchool/OutOfSchool.WebApi/Util/MappingProfile.cs +++ b/OutOfSchool/OutOfSchool.WebApi/Util/MappingProfile.cs @@ -296,7 +296,7 @@ public MappingProfile() .ForMember(dest => dest.PhoneNumber, opt => opt.MapFrom(src => src.User.PhoneNumber)) .ForMember(dest => dest.Email, opt => opt.MapFrom(src => src.User.Email)) .ForMember(dest => dest.AccountStatus, m => m.Ignore()) - .ForMember(dest => dest.Gender, m => m.Ignore()); + .ForMember(dest => dest.Gender, m => m.MapFrom(src => src.User.Gender)); CreateMap() .ForMember(dest => dest.EntityType, opt => opt.Ignore())