Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Tsylia/ Added the feature that allows the creation of a group of children by … #1006

Merged
merged 2 commits into from
Mar 6, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,20 @@ public async Task CreateChild_WhenModelIsValid_ShouldReturnCreatedAtActionResult
Assert.IsInstanceOf<CreatedAtActionResult>(result);
}

[Test]
public async Task CreateChildren_WhenModelIsValid_ShouldReturnOkObjectResult()
{
// Arrange
service.Setup(x => x.CreateChildrenForUser(children, currentUserId))
.ReturnsAsync(new ChildrenCreationResultDto());

// Act
var result = await controller.CreateChildren(children).ConfigureAwait(false);

// Assert
Assert.IsInstanceOf<OkObjectResult>(result);
}

[Test]
public async Task UpdateChild_WhenModelIsValid_ShouldReturnOkObjectResult()
{
Expand Down
8 changes: 8 additions & 0 deletions OutOfSchool/OutOfSchool.WebApi/Config/ParentConfig.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
namespace OutOfSchool.WebApi.Config;

public class ParentConfig
{
public const string Name = "Parent";

public int ChildrenMaxNumber { get; set; }
}
25 changes: 25 additions & 0 deletions OutOfSchool/OutOfSchool.WebApi/Controllers/V1/ChildController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,31 @@ public async Task<IActionResult> Create(ChildDto childDto)
child);
}

/// <summary>
/// Method for creating the list of the new user's children.
/// </summary>
/// <param name="childrenDtos">The list of the children entities to add.</param>
/// <returns>The list of the children that were created.</returns>
[HasPermission(Permissions.ChildAddNew)]
[ProducesResponseType(StatusCodes.Status201Created, Type = typeof(ChildDto))]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
[ProducesResponseType(StatusCodes.Status401Unauthorized)]
[ProducesResponseType(StatusCodes.Status403Forbidden)]
[ProducesResponseType(StatusCodes.Status500InternalServerError)]
[HttpPost]
public async Task<IActionResult> CreateChildren(List<ChildDto> childrenDtos)
{
string userId = GettingUserProperties.GetUserId(User);

var children = await service.CreateChildrenForUser(childrenDtos, userId).ConfigureAwait(false);

return Ok(new ChildrenCreationResponse()
{
Parent = children.Parent,
ChildrenCreationResults = children.ChildrenCreationResults,
});
}

/// <summary>
/// Update info about the user's child in the database.
/// </summary>
Expand Down
12 changes: 12 additions & 0 deletions OutOfSchool/OutOfSchool.WebApi/Models/ChildCreationResult.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
using OutOfSchool.WebApi.Common;

namespace OutOfSchool.WebApi.Models;

public class ChildCreationResult
{
public ChildDto Child { get; set; }

public bool IsSuccess { get; set; }

public string Message { get; set; }
}
10 changes: 10 additions & 0 deletions OutOfSchool/OutOfSchool.WebApi/Models/ChildrenCreationResponse.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
using OutOfSchool.WebApi.Common;

namespace OutOfSchool.WebApi.Models;

public class ChildrenCreationResponse
{
public ParentDTO Parent { get; set; }

public List<ChildCreationResult> ChildrenCreationResults { get; set; }
}
10 changes: 10 additions & 0 deletions OutOfSchool/OutOfSchool.WebApi/Models/ChildrenCreationResultDto.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
using OutOfSchool.WebApi.Common;

namespace OutOfSchool.WebApi.Models;

public class ChildrenCreationResultDto
{
public ParentDTO Parent { get; set; }

public List<ChildCreationResult> ChildrenCreationResults { get; set; } = new List<ChildCreationResult>();
}
74 changes: 73 additions & 1 deletion OutOfSchool/OutOfSchool.WebApi/Services/ChildService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,12 @@
using Google.Type;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Nest;
using OutOfSchool.Services.Enums;
using OutOfSchool.Services.Models;
using OutOfSchool.Services.Repository;
using OutOfSchool.WebApi.Common;
using OutOfSchool.WebApi.Extensions;
using OutOfSchool.WebApi.Models;
using OutOfSchool.WebApi.Models.SocialGroup;
Expand All @@ -30,6 +32,7 @@ public class ChildService : IChildService
private readonly IEntityRepository<long, SocialGroup> socialGroupRepository;
private readonly ILogger<ChildService> logger;
private readonly IMapper mapper;
private readonly IOptions<ParentConfig> parentConfig;

/// <summary>
/// Initializes a new instance of the <see cref="ChildService"/> class.
Expand All @@ -39,13 +42,15 @@ public class ChildService : IChildService
/// <param name="socialGroupRepository">Repository for the social groups.</param>
/// <param name="logger">Logger.</param>
/// <param name="mapper">Automapper DI service.</param>
/// <param name="parentConfig">Parent configuration.</param>
public ChildService(
IEntityRepository<Guid, Child> childRepository,
IParentRepository parentRepository,
IEntityRepository<long, SocialGroup> socialGroupRepository,
ILogger<ChildService> logger,
IMapper mapper,
IApplicationRepository applicationRepository)
IApplicationRepository applicationRepository,
IOptions<ParentConfig> parentConfig)
{
this.childRepository = childRepository ?? throw new ArgumentNullException(nameof(childRepository));
this.parentRepository = parentRepository ?? throw new ArgumentNullException(nameof(parentRepository));
Expand All @@ -55,6 +60,7 @@ public ChildService(
this.mapper = mapper ?? throw new ArgumentNullException(nameof(mapper));
this.applicationRepository =
applicationRepository ?? throw new ArgumentNullException(nameof(applicationRepository));
this.parentConfig = parentConfig ?? throw new ArgumentNullException(nameof(parentConfig));
}

/// <inheritdoc/>
Expand Down Expand Up @@ -107,6 +113,72 @@ async Task<Child> CreateChild()
return mapper.Map<ChildDto>(newChild);
}

/// <inheritdoc/>
public async Task<ChildrenCreationResultDto> CreateChildrenForUser(List<ChildDto> childrenDtos, string userId)
{
var parent = (await parentRepository
.GetByFilter(p => p.UserId == userId)
.ConfigureAwait(false))
.SingleOrDefault()
?? throw new UnauthorizedAccessException($"Trying to create a new children the Parent with {nameof(userId)}:{userId} was not found.");

var parentChildrenCount = (await GetChildrenListByParentId(parent.Id, false).ConfigureAwait(false))?.Count;

var children = new ChildrenCreationResultDto()
{
Parent = mapper.Map<ParentDTO>(parent),
};

foreach (var childDto in childrenDtos)
{
try
{
if (parentChildrenCount < parentConfig.Value.ChildrenMaxNumber)
{
var child = await CreateChildForUser(childDto, userId).ConfigureAwait(false);
children.ChildrenCreationResults.Add(CreateChildResult(child));
parentChildrenCount++;
}
else
{
children.ChildrenCreationResults
.Add(CreateChildResult(
childDto,
false,
$"Refused to create a new child with {nameof(Child.ParentId)}:{childDto.ParentId}, {nameof(userId)}:{userId}: " +
$"the limit ({parentConfig.Value.ChildrenMaxNumber}) of the children for parents was reached."));
}
}
catch (Exception ex) when (ex is ArgumentNullException
|| ex is ArgumentException
|| ex is UnauthorizedAccessException
|| ex is DbUpdateException)
{
children.ChildrenCreationResults.Add(CreateChildResult(childDto, false, ex.Message));
logger.LogDebug(
$"There is an error while creating a new child with {nameof(Child.ParentId)}:{childDto.ParentId}, {nameof(userId)}:{userId}: {ex.Message}.");
}
catch (Exception ex)
{
children.ChildrenCreationResults.Add(CreateChildResult(childDto, false));
logger.LogDebug(
$"There is an error while creating a new child with {nameof(Child.ParentId)}:{childDto.ParentId}, {nameof(userId)}:{userId}: {ex.Message}.");
}
}

ChildCreationResult CreateChildResult(ChildDto childDto, bool isSuccess = true, string message = null)
{
return new ChildCreationResult()
{
Child = childDto,
IsSuccess = isSuccess,
Message = message,
};
}

return children;
}

/// <inheritdoc/>
public async Task<SearchResult<ChildDto>> GetByFilter(ChildSearchFilter filter)
{
Expand Down
11 changes: 11 additions & 0 deletions OutOfSchool/OutOfSchool.WebApi/Services/IChildService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,17 @@ public interface IChildService
/// <exception cref="DbUpdateException">If something wrong occurred while saving to the database.</exception>
Task<ChildDto> CreateChildForUser(ChildDto childDto, string userId);

/// <summary>
/// Create the list of the children for specified user.
/// If child's property ParentId is not equal to the parent's Id that was found by specified userId,
/// the child's property will be changed to the proper value: parent's Id that was found.
/// </summary>
/// <param name="childrenDtos">The list of the children to add.</param>
/// <param name="userId">The key in the User table.</param>
/// <returns>A <see cref="Task{TResult}"/> representing the result of the asynchronous operation.
/// The result contains a <see cref="ChildrenCreationResponse"/> that was created.</returns>
Task<ChildrenCreationResultDto> CreateChildrenForUser(List<ChildDto> childrenDtos, string userId);

/// <summary>
/// Get all children from the database.
/// </summary>
Expand Down
1 change: 1 addition & 0 deletions OutOfSchool/OutOfSchool.WebApi/Startup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ public static void AddApplicationServices(this WebApplicationBuilder builder)
services.Configure<ProviderAdminConfig>(configuration.GetSection(ProviderAdminConfig.Name));
services.Configure<CommunicationConfig>(configuration.GetSection(CommunicationConfig.Name));
services.Configure<GeocodingConfig>(configuration.GetSection(GeocodingConfig.Name));
services.Configure<ParentConfig>(configuration.GetSection(ParentConfig.Name));

services.AddLocalization(options => options.ResourcesPath = "Resources");
services.AddAuthentication("Bearer")
Expand Down
Loading