Skip to content

Commit

Permalink
Tsylia/ Added the feature that allows the creation of a group of chil…
Browse files Browse the repository at this point in the history
…dren by … (#1006)

* Added the feature that allows the creation of a group of children by the list.

* Added the limit of the children that are created.
  • Loading branch information
andriitsylia authored Mar 6, 2023
1 parent 725ee8c commit 0c03025
Show file tree
Hide file tree
Showing 10 changed files with 379 additions and 212 deletions.
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

0 comments on commit 0c03025

Please sign in to comment.