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

Bio functionality #137

Merged
merged 11 commits into from
Aug 15, 2024
4 changes: 0 additions & 4 deletions src/Application/Application.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,4 @@
<ItemGroup>
<ProjectReference Include="..\Domain\Domain.csproj" />
</ItemGroup>
<ItemGroup>
<None Remove="DependencyInjection.cs.bak" />
<None Remove="Application.csproj.bak" />
</ItemGroup>
</Project>
3 changes: 2 additions & 1 deletion src/Application/Common/Interfaces/IApplicationDbContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using Cfo.Cats.Domain.Entities.Assessments;
using Cfo.Cats.Domain.Entities.Documents;
using Cfo.Cats.Domain.Entities.Participants;
using Cfo.Cats.Domain.Entities.Bios;
using Cfo.Cats.Domain.Identity;
using Cfo.Cats.Domain.ValueObjects;
using Microsoft.AspNetCore.DataProtection.EntityFrameworkCore;
Expand Down Expand Up @@ -30,7 +31,7 @@ public interface IApplicationDbContext
DbSet<KeyValue> KeyValues { get; }

DbSet<ParticipantAssessment> ParticipantAssessments { get; }

DbSet<ParticipantBio> ParticipantBios { get; }
DbSet<ParticipantEnrolmentHistory> ParticipantEnrolmentHistories { get; }

DbSet<Timeline> Timelines { get; }
Expand Down
69 changes: 69 additions & 0 deletions src/Application/Features/Bios/Commands/BeginBio.cs
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • Removed the caching references
  • Added additional validation to the command (alpha numeric)

Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
using Cfo.Cats.Application.Common.Security;
using Cfo.Cats.Application.Features.Bios.DTOs;
using Cfo.Cats.Application.Features.Bios.DTOs.V1.Pathways.Diversity;
using Cfo.Cats.Application.Features.Bios.DTOs.V1.Pathways.ChildhoodExperiences;
using Cfo.Cats.Application.Features.Bios.DTOs.V1.Pathways.RecentExperiences;
using Cfo.Cats.Application.SecurityConstants;
using Cfo.Cats.Domain.Entities.Bios;
using Newtonsoft.Json;
using Cfo.Cats.Application.Common.Validators;


namespace Cfo.Cats.Application.Features.Bios.Commands;

public static class BeginBio
{
[RequestAuthorize(Policy = SecurityPolicies.Enrol)]
public class Command : IRequest<Result<Guid>>
{
public required string ParticipantId { get; set; }
}

public class Handler : IRequestHandler<Command, Result<Guid>>
{
private readonly IUnitOfWork _unitOfWork;
private readonly ICurrentUserService _currentUserService;
public Handler(IUnitOfWork unitOfWork, ICurrentUserService currentUserService)
{
_unitOfWork = unitOfWork;
_currentUserService = currentUserService;
}

public async Task<Result<Guid>> Handle(Command request, CancellationToken cancellationToken)
{
Bio bio = new Bio()
{
Id = Guid.NewGuid(),
ParticipantId = request.ParticipantId,
Pathways =
[
new ChildhoodExperiencesPathway(),
new DiversityPathway(),
new RecentExperiencesPathway(),
]
};

string json = JsonConvert.SerializeObject(bio, new JsonSerializerSettings
{
TypeNameHandling = TypeNameHandling.Auto
});

ParticipantBio bioSurvey = ParticipantBio.Create(bio.Id, request.ParticipantId, bioJson: json, BioStatus.NotStarted);
await _unitOfWork.DbContext.ParticipantBios.AddAsync(bioSurvey);
return Result<Guid>.Success(bio.Id);
}
}

public class Validator : AbstractValidator<Command>
{
public Validator()
{
RuleFor(c => c.ParticipantId)
.MinimumLength(9)
.MaximumLength(9)
.Matches(ValidationConstants.AlphaNumeric)
.WithMessage(string.Format(ValidationConstants.AlphaNumericMessage, nameof(Command.ParticipantId)));
}
}

}
75 changes: 75 additions & 0 deletions src/Application/Features/Bios/Commands/SaveBio.cs
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • Removed caching
  • added validation

Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
using Cfo.Cats.Application.Common.Security;
using Cfo.Cats.Application.Common.Validators;
using Cfo.Cats.Application.Features.Bios.DTOs;
using Cfo.Cats.Application.SecurityConstants;
using Cfo.Cats.Domain.Entities.Bios;
using Newtonsoft.Json;

namespace Cfo.Cats.Application.Features.Bios.Commands;

public static class SaveBio
{
[RequestAuthorize(Policy = SecurityPolicies.Enrol)]
public class Command : IRequest<Result>
{
public bool Submit { get; set; } = false;

public required Bio Bio { get; set; }
}

public class Handler : IRequestHandler<Command, Result>
{
private readonly IUnitOfWork _unitOfWork;

public Handler(IUnitOfWork unitOfWork)
{
_unitOfWork = unitOfWork;

}

public async Task<Result> Handle(Command request, CancellationToken cancellationToken)
{

ParticipantBio? bio = await _unitOfWork.DbContext.ParticipantBios
.FirstOrDefaultAsync(r => r.Id == request.Bio.Id && r.ParticipantId == request.Bio.ParticipantId, cancellationToken);

if(bio == null)
{
return Result.Failure("Bio not found");
}

bio.UpdateJson(JsonConvert.SerializeObject(request.Bio, new JsonSerializerSettings
{
TypeNameHandling = TypeNameHandling.Auto
}));
bio.UpdateStatus(BioStatus.InProgress);
if (request.Submit)
{
bio.UpdateStatus(BioStatus.Complete);
bio.Submit();
}

return Result.Success();
}
}

public class Validator : AbstractValidator<Command>
{
public Validator()
{
RuleFor(x => x.Bio)
.NotNull();

RuleFor(x => x.Bio.ParticipantId)
.MinimumLength(9)
.MaximumLength(9)
.Matches(ValidationConstants.AlphaNumeric)
.WithMessage(string.Format(ValidationConstants.AlphaNumericMessage, nameof(Command.Bio.ParticipantId)));

RuleFor(x => x.Bio.Id)
.NotEmpty();

}
}

}
72 changes: 72 additions & 0 deletions src/Application/Features/Bios/Commands/SkipBioForNow.cs
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caching removed. Change signature to simplify UI

Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
using Cfo.Cats.Application.Common.Security;
using Cfo.Cats.Application.Common.Validators;
using Cfo.Cats.Application.Features.Bios.DTOs;
using Cfo.Cats.Application.Features.Bios.DTOs.V1.Pathways.ChildhoodExperiences;
using Cfo.Cats.Application.Features.Bios.DTOs.V1.Pathways.Diversity;
using Cfo.Cats.Application.Features.Bios.DTOs.V1.Pathways.RecentExperiences;
using Cfo.Cats.Application.SecurityConstants;
using Cfo.Cats.Domain.Entities.Bios;
using DocumentFormat.OpenXml.Office.PowerPoint.Y2021.M06.Main;
using Newtonsoft.Json;

namespace Cfo.Cats.Application.Features.Bios.Commands;

public static class SkipBioForNow
{
[RequestAuthorize(Policy = SecurityPolicies.Enrol)]
public class Command : IRequest<Result>
{
public string? ParticipantId { get; set;}
}

public class Handler(IUnitOfWork unitOfWork) : IRequestHandler<Command, Result>
{
public async Task<Result> Handle(Command request, CancellationToken cancellationToken)
{
ParticipantBio? bio = await unitOfWork.DbContext.ParticipantBios.FirstOrDefaultAsync(r => r.ParticipantId == request.ParticipantId);

if (bio == null)
{
Bio newBio = new Bio()
{
Id = Guid.NewGuid(),
ParticipantId = request.ParticipantId!,
Pathways =
[
new ChildhoodExperiencesPathway(),
new DiversityPathway(),
new RecentExperiencesPathway(),
]
};

string json = JsonConvert.SerializeObject(newBio, new JsonSerializerSettings
{
TypeNameHandling = TypeNameHandling.Auto
});

bio = ParticipantBio.Create(newBio.Id, request.ParticipantId!, json, BioStatus.NotStarted);
unitOfWork.DbContext.ParticipantBios.Add(bio);
}

bio.UpdateStatus(BioStatus.SkippedForNow);
return Result.Success();
}
}

public class Validator : AbstractValidator<Command>
{
private IUnitOfWork _unitOfWork;

public Validator(IUnitOfWork unitOfWork)
{
_unitOfWork = unitOfWork;

RuleFor(x => x.ParticipantId)
.MinimumLength(9)
.MaximumLength(9)
.Matches(ValidationConstants.AlphaNumeric)
.WithMessage(string.Format(ValidationConstants.AlphaNumericMessage, nameof(Command.ParticipantId)));
}
}

}
8 changes: 8 additions & 0 deletions src/Application/Features/Bios/DTOs/Bio.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
namespace Cfo.Cats.Application.Features.Bios.DTOs;

public class Bio
{
public required Guid Id { get; set; }
public required string ParticipantId { get; set; }
public required PathwayBase[] Pathways { get; set; }
}
12 changes: 12 additions & 0 deletions src/Application/Features/Bios/DTOs/BioPathwayValidator.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
namespace Cfo.Cats.Application.Features.Bios.DTOs;

public class BioPathwayValidator : AbstractValidator<PathwayBase>
{
public BioPathwayValidator()
{
RuleForEach(model => model.Questions())
.Must(q => q.IsValid())
.WithMessage("You must select a valid option!")
.OverridePropertyName("Questions");
}
}
9 changes: 9 additions & 0 deletions src/Application/Features/Bios/DTOs/BioValidator.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
namespace Cfo.Cats.Application.Features.Bios.DTOs;

public class BioValidator : AbstractValidator<Bio>
{
public BioValidator()
{
RuleForEach(model => model.Pathways).SetValidator(new BioPathwayValidator());
}
}
19 changes: 19 additions & 0 deletions src/Application/Features/Bios/DTOs/ParticipantBioDto.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
using Cfo.Cats.Domain.Entities.Bios;

namespace Cfo.Cats.Application.Features.Bios.DTOs;

public class ParticipantBioDto
{
public required string ParticipantId { get; set; }
public required DateTime CreatedDate { get; set; }

private class Mapping : Profile
{
public Mapping()
{
CreateMap<ParticipantBio, ParticipantBioDto>()
.ForMember(p => p.CreatedDate, options => options.MapFrom(source => source.Created));
}
}
}

15 changes: 15 additions & 0 deletions src/Application/Features/Bios/DTOs/PathwayBase.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
using Newtonsoft.Json;

namespace Cfo.Cats.Application.Features.Bios.DTOs;

public abstract class PathwayBase
{
[JsonIgnore]
public abstract string Title { get; }

[JsonIgnore]
public abstract string Icon { get; }

public abstract IEnumerable<QuestionBase> Questions();

}
53 changes: 53 additions & 0 deletions src/Application/Features/Bios/DTOs/QuestionBase.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
using Newtonsoft.Json;

namespace Cfo.Cats.Application.Features.Bios.DTOs;

/// <summary>
/// Base class for the all questions
/// </summary>
public abstract partial class QuestionBase
{

#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable.
protected QuestionBase()
{
}
#pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable.

protected QuestionBase(string question, string[] options)
{
this.Question = question;
this.Options = options;
}

protected QuestionBase(string question, string otherInformation, string[] options)
: this(question, options)
{
this.OtherInformation = otherInformation;
}

/// <summary>
/// The question we are asking
/// </summary>
[JsonIgnore]
public string Question { get; }

/// <summary>
/// Any other errata about the question.
/// </summary>
[JsonIgnore]
public string? OtherInformation { get; }

/// <summary>
/// A collection of options for the answers
/// </summary>
[JsonIgnore]
public string[] Options { get; }

/// <summary>
/// Is the answer valid
/// </summary>
/// <returns>True if the answer has a valid return value</returns>
public abstract bool IsValid();
}

Loading
Loading