Skip to content

Commit

Permalink
add Judge model and DTO, update CompetitiveEvent model, modify servic…
Browse files Browse the repository at this point in the history
…e and controller to support updated model
  • Loading branch information
Tetyana-K committed Dec 6, 2024
1 parent d89e310 commit cbfc3dc
Show file tree
Hide file tree
Showing 13 changed files with 447 additions and 93 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
//using OutOfSchool.Common.Enums;
using OutOfSchool.Common.Enums;
using OutOfSchool.Services.Enums;
using System.ComponentModel.DataAnnotations;

namespace OutOfSchool.BusinessLogic.Models.CompetitiveEvent;
public class CompetitiveEventCreateDto
{
public Guid Id { get; set; }

public bool IsDeleted { get; set; }

[DataType(DataType.Text)]
[MaxLength(250)]
[MinLength(1)]
public string Title { get; set; }

[Required(ErrorMessage = "ShortTitle is required")]
[DataType(DataType.Text)]
[MaxLength(100)]
[MinLength(1)]
public string ShortTitle { get; set; }

[Required]
[EnumDataType(typeof(CompetitiveEventStates), ErrorMessage = Constants.EnumErrorMessage)]
public CompetitiveEventStates State { get; set; } = CompetitiveEventStates.Draft;

public DateTimeOffset RegistrationStartTime { get; set; }

public DateTimeOffset RegistrationEndTime { get; set; }

public Guid? ParentId { get; set; } = null;

public Guid BuildingHoldingId { get; set; }

public Guid ChildParticipantId { get; set; }

public List<CompetitiveEventDescriptionItemDto> CompetitiveEventDescriptionItems { get; set; }

[MaxLength(2000)]
public string AdditionalDescription { get; set; }

[Required]
public DateTimeOffset ScheduledStartTime { get; set; }

[Required]
public DateTimeOffset ScheduledEndTime { get; set; }

[Required]
public uint NumberOfSeats { get; set; } = uint.MaxValue;

[Required]
//public List<Guid> AccountingTypeOfEvent { get; set; }
public int AccountingTypeOfEventId { get; set; }

[MaxLength(2000)]
public string Description { get; set; }

[MaxLength(2000)]
public string DescriptionOfTheEnrollmentProcedure { get; set; }

[Required]
public Guid OrganizerOfTheEventId { get; set; }

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

public Guid VenueId { get; set; }

public string VenueName { get; set; }

[MaxLength(2000)]
public string PreferentialTermsOfParticipation { get; set; }

public List<JudgeDto> Judges { get; set; }

public List<Guid> ParticipantsOfTheEvent { get; set; } // guid ?

public bool AreThereBenefits { get; set; }

[MaxLength(2000)]
public string Benefits { get; set; }

public uint Rating { get; set; }

public uint NumberOfRatings { get; set; }

public bool OptionsForPeopleWithDisabilities { get; set; }

[MaxLength(2000)]
public string DescriptionOfOptionsForPeopleWithDisabilities { get; set; }

public long CategoryId { get; set; }

[MaxLength(250)]
public string Subcategory { get; set; }

[Range(0, 120, ErrorMessage = "Min age should be a number from 0 to 120")]
public int MinimumAge { get; set; }

[Range(0, 120, ErrorMessage = "Max age should be a number from 0 to 120")]
public int MaximumAge { get; set; }

public List<Guid> Coverage { get; set; }

[Range(0, 100000, ErrorMessage = "Field value should be in a range from 1 to 100 000")]
public int Price { get; set; } = default;

public bool CompetitiveSelection { get; set; }
public uint NumberOfOccupiedSeats { get; set; }
}
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ public class CompetitiveEventDto

public Guid ChildParticipantId { get; set; }

public Guid ChiefJudgeId { get; set; }
//public Guid ChiefJudgeId { get; set; }

public List<CompetitiveEventDescriptionItemDto> CompetitiveEventDescriptionItems { get; set; }

Expand All @@ -53,8 +53,9 @@ public class CompetitiveEventDto
public uint NumberOfSeats { get; set; } = uint.MaxValue;

[Required]
public List<CompetitiveEventAccountingTypeDto> AccountingTypeOfEvent { get; set; }

public int AccountingTypeOfEventId { get; set; }
//public List<CompetitiveEventAccountingTypeDto> AccountingTypeOfEvent { get; set; }

[MaxLength(2000)]
public string Description { get; set; }

Expand All @@ -68,16 +69,23 @@ public class CompetitiveEventDto
public FormOfLearning PlannedFormatOfClasses { get; set; }

public Guid VenueId { get; set; }

[MaxLength(2000)]
public string VenueName { get; set; }

[MaxLength(2000)]
public string PreferentialTermsOfParticipation { get; set; }

public virtual List<JudgeDto> Judges { get; set; }
//public virtual List<Individual> Judges { get; set; }

public List<ProviderDto> ParticipantsOfTheEvent { get; set; }

public bool AreThereBenefits { get; set; }

[MaxLength(2000)]
public string Benefits { get; set; }

public uint Rating { get; set; }

public uint NumberOfRatings { get; set; }
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
using System.ComponentModel.DataAnnotations;
using OutOfSchool.Common.Validators;
using OutOfSchool.Services.Enums;
namespace OutOfSchool.BusinessLogic.Models.CompetitiveEvent;

public class JudgeDto
{
public Guid Id { get; set; }

[Required(ErrorMessage = Constants.RequiredFirstNameErrorMessage)]
[DataType(DataType.Text)]
[MaxLength(Constants.NameMaxLength)]
[CustomUkrainianName(ErrorMessage = Constants.InvalidFirstNameErrorMessage)]
public string FirstName { get; set; } = string.Empty;

[Required(ErrorMessage = Constants.RequiredFirstNameErrorMessage)]
[DataType(DataType.Text)]
[MaxLength(Constants.NameMaxLength)]
[CustomUkrainianName(ErrorMessage = Constants.InvalidLastNameErrorMessage)]
public string LastName { get; set; } = string.Empty;

[DataType(DataType.Text)]
[MaxLength(Constants.NameMaxLength)]
[CustomUkrainianName(ErrorMessage = Constants.InvalidMiddleNameErrorMessage)]
public string MiddleName { get; set; } = string.Empty;

[Required(ErrorMessage = "Gender is required")]
[EnumDataType(typeof(Gender), ErrorMessage = Constants.EnumErrorMessage)]
public Gender Gender { get; set; }

[Required(ErrorMessage = "Date of birth is required")]
[DataType(DataType.Date)]
public DateTime DateOfBirth { get; set; }

public bool IsChiefJudge { get; set; }

[MaxLength(300)]
public string Description { get; set; } = string.Empty;

public string CoverImageId { get; set; } = string.Empty;

public Guid CompetetiveEventId { get; set; }
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,44 +12,57 @@ namespace OutOfSchool.BusinessLogic.Services;
public class CompetitiveEventService : ICompetitiveEventService
{
private readonly IEntityRepositorySoftDeleted<Guid, CompetitiveEvent> competitiveEventRepository;
private readonly IEntityRepositorySoftDeleted<int, CompetitiveEventAccountingType> accountingTypeOfEventRepository;
private readonly IEntityRepository<Guid, Judge> judgeRepository;
private readonly ILogger<CompetitiveEventService> logger;
private readonly IStringLocalizer<SharedResource> localizer;
private readonly IMapper mapper;

public CompetitiveEventService(
IEntityRepositorySoftDeleted<Guid, CompetitiveEvent> competitiveEventRepository,
IEntityRepository<Guid, Judge> judgeRepository,
IEntityRepositorySoftDeleted<int, CompetitiveEventAccountingType> accountingTypeOfEventRepository,
ILogger<CompetitiveEventService> logger,
IStringLocalizer<SharedResource> localizer,
IMapper mapper)
{
this.competitiveEventRepository = competitiveEventRepository ?? throw new ArgumentNullException(nameof(competitiveEventRepository));
this.judgeRepository = judgeRepository ?? throw new ArgumentNullException(nameof(judgeRepository));
this.accountingTypeOfEventRepository = accountingTypeOfEventRepository ?? throw new ArgumentException(nameof(accountingTypeOfEventRepository));
this.logger = logger ?? throw new ArgumentNullException(nameof(logger));
this.localizer = localizer ?? throw new ArgumentNullException(nameof(localizer));
this.mapper = mapper ?? throw new ArgumentNullException(nameof(mapper));
}

/// <inheritdoc/>
public async Task<CompetitiveEventDto> GetById(Guid id)
public async Task<CompetitiveEventDto?> GetById(Guid id)
{
logger.LogTrace($"Getting CompetitiveEvent by Id started. Looking Id = {id}.");

var competitiveEvent = (await competitiveEventRepository.GetById(id).ConfigureAwait(false))
?? throw new ArgumentOutOfRangeException(
nameof(id),
localizer[$"CompetitiveEvent with Id = {id} doesn't exist in the system."]);

logger.LogTrace($"Successfully got a CompetitiveEvent with Id = {id}.");
var competitiveEvent = (await competitiveEventRepository.GetById(id).ConfigureAwait(false));

if (competitiveEvent is null)
{
logger.LogTrace($"CompetitiveEvent with Id = {id} doesn't exist in the system.");
}
else
{
logger.LogTrace($"Successfully got a CompetitiveEvent with Id = {id}.");
}
return mapper.Map<CompetitiveEventDto>(competitiveEvent);
}

/// <inheritdoc/>
public async Task<CompetitiveEventDto> Create(CompetitiveEventDto dto)
public async Task<CompetitiveEventDto> Create(CompetitiveEventCreateDto dto)
{
logger.LogTrace("CompetitiveEvent creating was started.");

ArgumentNullException.ThrowIfNull(dto);

var competitiveEvent = mapper.Map<CompetitiveEvent>(dto);

competitiveEvent.Judges = dto.Judges?.Select(dtoJudges => mapper.Map<Judge>(dtoJudges)).ToList();

var newCompetitiveEvent = await competitiveEventRepository.Create(competitiveEvent).ConfigureAwait(false);

logger.LogTrace($"CompetitiveEvent with Id = {newCompetitiveEvent?.Id} created successfully.");
Expand All @@ -73,6 +86,11 @@ public async Task<CompetitiveEventDto> Update(CompetitiveEventDto dto)
throw new DbUpdateConcurrencyException(message);
}

await ChangeJudges(competitiveEvent, dto.Judges ?? new List<JudgeDto>()).ConfigureAwait(false);

// await ChangeAccountingTypesOfEvent(competitiveEvent,
// dto.AccountingTypeOfEvent ?? new List<CompetitiveEventAccountingTypeDto>()).ConfigureAwait(false);

mapper.Map(dto, competitiveEvent);
competitiveEvent = await competitiveEventRepository.Update(competitiveEvent).ConfigureAwait(false);

Expand Down Expand Up @@ -102,4 +120,41 @@ public async Task Delete(Guid id)
localizer[$"CompetitiveEvent with Id = {id} doesn't exist in the system"]);
}
}

private async Task ChangeJudges(CompetitiveEvent currentCompetitiveEvent, List<JudgeDto> judgeDtoList)
{
var deletedIds = currentCompetitiveEvent.Judges
.Select(x => x.Id)
.Except(judgeDtoList.Select(x => x.Id))
.ToList();

if (deletedIds.Count > 0)
{
var judgeToDelete = currentCompetitiveEvent.Judges
.Where(judge => deletedIds.Contains(judge.Id))
.ToList();

var deleteTasks = judgeToDelete
.Select(deletedJudge => judgeRepository.Delete(deletedJudge));

await Task.WhenAll(deleteTasks).ConfigureAwait(false);
}

foreach (var judgeDto in judgeDtoList)
{
var foundJudge = currentCompetitiveEvent.Judges.FirstOrDefault(j => j.Id == judgeDto.Id);
if (foundJudge != null)
{
mapper.Map(judgeDto, foundJudge);
await judgeRepository.Update(foundJudge).ConfigureAwait(false);
}
else
{
var newJudge = mapper.Map<Judge>(judgeDto);
newJudge.CompetitiveEventId = currentCompetitiveEvent.Id;
await judgeRepository.Create(newJudge).ConfigureAwait(false);
}
}
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,15 @@ public interface ICompetitiveEventService
/// Get entity by it's key.
/// </summary>
/// <param name="id">Key in the table.</param>
/// <returns>CompetitiveEvent.</returns>
Task<CompetitiveEventDto> GetById(Guid id);
/// <returns>CompetitiveEvent or null if event not found.</returns>
Task<CompetitiveEventDto?> GetById(Guid id);

/// <summary>
/// Add entity.
/// </summary>
/// <param name="dto">CompetitiveEvent entity to add.</param>
/// <returns>A <see cref="Task{TResult}"/> representing the result of the asynchronous operation.</returns>
Task<CompetitiveEventDto> Create(CompetitiveEventDto dto);
Task<CompetitiveEventDto> Create(CompetitiveEventCreateDto dto);

/// <summary>
/// Update entity.
Expand Down
31 changes: 31 additions & 0 deletions OutOfSchool/OutOfSchool.BusinessLogic/Util/MappingProfile.cs
Original file line number Diff line number Diff line change
Expand Up @@ -792,7 +792,38 @@ public MappingProfile()
CreateMap<WorkshopFilter, WorkshopFilterWithSettlements>()
.ForMember(dest => dest.SettlementsIds, opt => opt.Ignore());

CreateMap<Judge, JudgeDto>()
.ForMember(dest => dest.MiddleName, opt => opt.MapFrom(src => src.MiddleName ?? string.Empty))
.ForMember(dest => dest.CompetetiveEventId, opt => opt.MapFrom(src => src.CompetitiveEventId));// ??

CreateMap<JudgeDto, Judge>()
.ForMember(dest => dest.CompetitiveEventId, opt => opt.Ignore()) // ??
.ForMember(dest => dest.CompetitiveEvent, opt => opt.Ignore()) // ??
.ForMember(dest => dest.MiddleName, opt => opt.MapFrom(src => src.MiddleName ?? string.Empty));

/* for me as ex
* CreateSoftDeletedMap<TeacherDTO, Teacher>()
.ForMember(dest => dest.CoverImageId, opt => opt.Ignore())
.ForMember(dest => dest.WorkshopId, opt => opt.Ignore())
.ForMember(dest => dest.Images, opt => opt.Ignore())
.ForMember(dest => dest.Workshop, opt => opt.Ignore())
.ForMember(dest => dest.MiddleName, opt => opt.MapFrom(src => src.MiddleName ?? string.Empty));
CreateMap<Teacher, TeacherDTO>()
.ForMember(dest => dest.CoverImage, opt => opt.Ignore())
.ForMember(dest => dest.MiddleName, opt => opt.MapFrom(src => src.MiddleName ?? string.Empty));
*/

CreateMap<CompetitiveEvent, CompetitiveEventDto>().ReverseMap();
//CreateMap<CompetitiveEvent, CompetitiveEventDto>()
// .ForMember(dest => dest.Judges, opt => opt.MapFrom(src => src.Judges));
//CreateSoftDeletedMap<CompetitiveEventDto, CompetitiveEvent>()
// .ForMember(dest => dest.AccountingTypeOfEvent, opt => opt.Ignore());

//CreateSoftDeletedMap<CompetitiveEventCreateDto, CompetitiveEvent>()
// .ForMember(dest => dest.Id, opt => opt.Ignore())
// .ForMember(dest => dest.AccountingTypeOfEvent, opt => opt.Ignore())
// .ForMember(dest => dest.ParticipantsOfTheEvent, opt => opt.Ignore());

CreateMap<CompetitiveEventAccountingType, CompetitiveEventAccountingTypeDto>().ReverseMap();

Expand Down
Loading

0 comments on commit cbfc3dc

Please sign in to comment.