diff --git a/src/Application/Application.csproj b/src/Application/Application.csproj index d2b5ed04..c6c4b8de 100644 --- a/src/Application/Application.csproj +++ b/src/Application/Application.csproj @@ -27,8 +27,4 @@ - - - - \ No newline at end of file diff --git a/src/Application/Common/Interfaces/IApplicationDbContext.cs b/src/Application/Common/Interfaces/IApplicationDbContext.cs index 51e83d7b..23b2ea2e 100644 --- a/src/Application/Common/Interfaces/IApplicationDbContext.cs +++ b/src/Application/Common/Interfaces/IApplicationDbContext.cs @@ -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; @@ -30,7 +31,7 @@ public interface IApplicationDbContext DbSet KeyValues { get; } DbSet ParticipantAssessments { get; } - + DbSet ParticipantBios { get; } DbSet ParticipantEnrolmentHistories { get; } DbSet Timelines { get; } diff --git a/src/Application/Features/Bios/Commands/BeginBio.cs b/src/Application/Features/Bios/Commands/BeginBio.cs new file mode 100644 index 00000000..eccbb519 --- /dev/null +++ b/src/Application/Features/Bios/Commands/BeginBio.cs @@ -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> + { + public required string ParticipantId { get; set; } + } + + public class Handler : IRequestHandler> + { + private readonly IUnitOfWork _unitOfWork; + private readonly ICurrentUserService _currentUserService; + public Handler(IUnitOfWork unitOfWork, ICurrentUserService currentUserService) + { + _unitOfWork = unitOfWork; + _currentUserService = currentUserService; + } + + public async Task> 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.Success(bio.Id); + } + } + + public class Validator : AbstractValidator + { + public Validator() + { + RuleFor(c => c.ParticipantId) + .MinimumLength(9) + .MaximumLength(9) + .Matches(ValidationConstants.AlphaNumeric) + .WithMessage(string.Format(ValidationConstants.AlphaNumericMessage, nameof(Command.ParticipantId))); + } + } + +} diff --git a/src/Application/Features/Bios/Commands/SaveBio.cs b/src/Application/Features/Bios/Commands/SaveBio.cs new file mode 100644 index 00000000..98007d99 --- /dev/null +++ b/src/Application/Features/Bios/Commands/SaveBio.cs @@ -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 + { + public bool Submit { get; set; } = false; + + public required Bio Bio { get; set; } + } + + public class Handler : IRequestHandler + { + private readonly IUnitOfWork _unitOfWork; + + public Handler(IUnitOfWork unitOfWork) + { + _unitOfWork = unitOfWork; + + } + + public async Task 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 + { + 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(); + + } + } + +} diff --git a/src/Application/Features/Bios/Commands/SkipBioForNow.cs b/src/Application/Features/Bios/Commands/SkipBioForNow.cs new file mode 100644 index 00000000..8a0d3084 --- /dev/null +++ b/src/Application/Features/Bios/Commands/SkipBioForNow.cs @@ -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 + { + public string? ParticipantId { get; set;} + } + + public class Handler(IUnitOfWork unitOfWork) : IRequestHandler + { + public async Task 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 + { + 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))); + } + } + +} diff --git a/src/Application/Features/Bios/DTOs/Bio.cs b/src/Application/Features/Bios/DTOs/Bio.cs new file mode 100644 index 00000000..6fb362f1 --- /dev/null +++ b/src/Application/Features/Bios/DTOs/Bio.cs @@ -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; } +} \ No newline at end of file diff --git a/src/Application/Features/Bios/DTOs/BioPathwayValidator.cs b/src/Application/Features/Bios/DTOs/BioPathwayValidator.cs new file mode 100644 index 00000000..ac7423d2 --- /dev/null +++ b/src/Application/Features/Bios/DTOs/BioPathwayValidator.cs @@ -0,0 +1,12 @@ +namespace Cfo.Cats.Application.Features.Bios.DTOs; + +public class BioPathwayValidator : AbstractValidator +{ + public BioPathwayValidator() + { + RuleForEach(model => model.Questions()) + .Must(q => q.IsValid()) + .WithMessage("You must select a valid option!") + .OverridePropertyName("Questions"); + } +} \ No newline at end of file diff --git a/src/Application/Features/Bios/DTOs/BioValidator.cs b/src/Application/Features/Bios/DTOs/BioValidator.cs new file mode 100644 index 00000000..899b05c0 --- /dev/null +++ b/src/Application/Features/Bios/DTOs/BioValidator.cs @@ -0,0 +1,9 @@ +namespace Cfo.Cats.Application.Features.Bios.DTOs; + +public class BioValidator : AbstractValidator +{ + public BioValidator() + { + RuleForEach(model => model.Pathways).SetValidator(new BioPathwayValidator()); + } +} \ No newline at end of file diff --git a/src/Application/Features/Bios/DTOs/ParticipantBioDto.cs b/src/Application/Features/Bios/DTOs/ParticipantBioDto.cs new file mode 100644 index 00000000..1913500a --- /dev/null +++ b/src/Application/Features/Bios/DTOs/ParticipantBioDto.cs @@ -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() + .ForMember(p => p.CreatedDate, options => options.MapFrom(source => source.Created)); + } + } +} + diff --git a/src/Application/Features/Bios/DTOs/PathwayBase.cs b/src/Application/Features/Bios/DTOs/PathwayBase.cs new file mode 100644 index 00000000..78f8445d --- /dev/null +++ b/src/Application/Features/Bios/DTOs/PathwayBase.cs @@ -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 Questions(); + +} \ No newline at end of file diff --git a/src/Application/Features/Bios/DTOs/QuestionBase.cs b/src/Application/Features/Bios/DTOs/QuestionBase.cs new file mode 100644 index 00000000..5d234e5e --- /dev/null +++ b/src/Application/Features/Bios/DTOs/QuestionBase.cs @@ -0,0 +1,53 @@ +using Newtonsoft.Json; + +namespace Cfo.Cats.Application.Features.Bios.DTOs; + +/// +/// Base class for the all questions +/// +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; + } + + /// + /// The question we are asking + /// + [JsonIgnore] + public string Question { get; } + + /// + /// Any other errata about the question. + /// + [JsonIgnore] + public string? OtherInformation { get; } + + /// + /// A collection of options for the answers + /// + [JsonIgnore] + public string[] Options { get; } + + /// + /// Is the answer valid + /// + /// True if the answer has a valid return value + public abstract bool IsValid(); +} + diff --git a/src/Application/Features/Bios/DTOs/SingleChoiceQuestion.cs b/src/Application/Features/Bios/DTOs/SingleChoiceQuestion.cs new file mode 100644 index 00000000..c0d67c34 --- /dev/null +++ b/src/Application/Features/Bios/DTOs/SingleChoiceQuestion.cs @@ -0,0 +1,41 @@ +namespace Cfo.Cats.Application.Features.Bios.DTOs; + +/// +/// An implementation of QuestionBase that only allows a +/// single answer +/// + +public abstract class SingleChoiceQuestion : QuestionBase +{ + protected SingleChoiceQuestion() + : base() + { + } + + protected SingleChoiceQuestion(string question, string[] options) + : base(question, options) + { + + } + + protected SingleChoiceQuestion(string question, string otherInformation, string[] options) + : base(question, otherInformation, options) + { + } + + + /// + /// The answer the user has provided + /// + public string? Answer { get; set; } + + /// + /// Checks the validity of the answer given. + /// + /// true if the answer has been entered, and is contained in our option list, otherwise false + public override bool IsValid() + { + return string.IsNullOrEmpty(Answer) == false + && Options.Any(a => a == Answer); + } +} \ No newline at end of file diff --git a/src/Application/Features/Bios/DTOs/V1/Pathways/ChildhoodExperiences/B1.cs b/src/Application/Features/Bios/DTOs/V1/Pathways/ChildhoodExperiences/B1.cs new file mode 100644 index 00000000..86afe238 --- /dev/null +++ b/src/Application/Features/Bios/DTOs/V1/Pathways/ChildhoodExperiences/B1.cs @@ -0,0 +1,12 @@ +namespace Cfo.Cats.Application.Features.Bios.DTOs.V1.Pathways.ChildhoodExperiences; +public class B1() : SingleChoiceQuestion("Spent time in care as a child", +[ + Yes, + No, + NA +]) +{ + public const string Yes = "Yes"; + public const string No = "No"; + public const string NA = "N/A"; +}; \ No newline at end of file diff --git a/src/Application/Features/Bios/DTOs/V1/Pathways/ChildhoodExperiences/B10.cs b/src/Application/Features/Bios/DTOs/V1/Pathways/ChildhoodExperiences/B10.cs new file mode 100644 index 00000000..d369f109 --- /dev/null +++ b/src/Application/Features/Bios/DTOs/V1/Pathways/ChildhoodExperiences/B10.cs @@ -0,0 +1,12 @@ +namespace Cfo.Cats.Application.Features.Bios.DTOs.V1.Pathways.ChildhoodExperiences; +public class B10() : SingleChoiceQuestion("Felt safe at home", +[ + Yes, + No, + NA +]) +{ + public const string Yes = "Yes"; + public const string No = "No"; + public const string NA = "N/A"; +}; \ No newline at end of file diff --git a/src/Application/Features/Bios/DTOs/V1/Pathways/ChildhoodExperiences/B11.cs b/src/Application/Features/Bios/DTOs/V1/Pathways/ChildhoodExperiences/B11.cs new file mode 100644 index 00000000..9f89aae8 --- /dev/null +++ b/src/Application/Features/Bios/DTOs/V1/Pathways/ChildhoodExperiences/B11.cs @@ -0,0 +1,12 @@ +namespace Cfo.Cats.Application.Features.Bios.DTOs.V1.Pathways.ChildhoodExperiences; +public class B11() : SingleChoiceQuestion("Enjoyed going to school", +[ + Yes, + No, + NA +]) +{ + public const string Yes = "Yes"; + public const string No = "No"; + public const string NA = "N/A"; +}; \ No newline at end of file diff --git a/src/Application/Features/Bios/DTOs/V1/Pathways/ChildhoodExperiences/B12.cs b/src/Application/Features/Bios/DTOs/V1/Pathways/ChildhoodExperiences/B12.cs new file mode 100644 index 00000000..5e46bcf2 --- /dev/null +++ b/src/Application/Features/Bios/DTOs/V1/Pathways/ChildhoodExperiences/B12.cs @@ -0,0 +1,12 @@ +namespace Cfo.Cats.Application.Features.Bios.DTOs.V1.Pathways.ChildhoodExperiences; +public class B12() : SingleChoiceQuestion("Parent or guardian had a drug / alcohol problem", +[ + Yes, + No, + NA +]) +{ + public const string Yes = "Yes"; + public const string No = "No"; + public const string NA = "N/A"; +}; \ No newline at end of file diff --git a/src/Application/Features/Bios/DTOs/V1/Pathways/ChildhoodExperiences/B13.cs b/src/Application/Features/Bios/DTOs/V1/Pathways/ChildhoodExperiences/B13.cs new file mode 100644 index 00000000..da7dd2c0 --- /dev/null +++ b/src/Application/Features/Bios/DTOs/V1/Pathways/ChildhoodExperiences/B13.cs @@ -0,0 +1,12 @@ +namespace Cfo.Cats.Application.Features.Bios.DTOs.V1.Pathways.ChildhoodExperiences; +public class B13() : SingleChoiceQuestion("Parent or guardian was seriously ill / passed away", +[ + Yes, + No, + NA +]) +{ + public const string Yes = "Yes"; + public const string No = "No"; + public const string NA = "N/A"; +}; \ No newline at end of file diff --git a/src/Application/Features/Bios/DTOs/V1/Pathways/ChildhoodExperiences/B14.cs b/src/Application/Features/Bios/DTOs/V1/Pathways/ChildhoodExperiences/B14.cs new file mode 100644 index 00000000..c711e5aa --- /dev/null +++ b/src/Application/Features/Bios/DTOs/V1/Pathways/ChildhoodExperiences/B14.cs @@ -0,0 +1,12 @@ +namespace Cfo.Cats.Application.Features.Bios.DTOs.V1.Pathways.ChildhoodExperiences; +public class B14() : SingleChoiceQuestion("Had a close friend you could confide in", +[ + Yes, + No, + NA +]) +{ + public const string Yes = "Yes"; + public const string No = "No"; + public const string NA = "N/A"; +}; \ No newline at end of file diff --git a/src/Application/Features/Bios/DTOs/V1/Pathways/ChildhoodExperiences/B15.cs b/src/Application/Features/Bios/DTOs/V1/Pathways/ChildhoodExperiences/B15.cs new file mode 100644 index 00000000..1e76f819 --- /dev/null +++ b/src/Application/Features/Bios/DTOs/V1/Pathways/ChildhoodExperiences/B15.cs @@ -0,0 +1,12 @@ +namespace Cfo.Cats.Application.Features.Bios.DTOs.V1.Pathways.ChildhoodExperiences; +public class B15() : SingleChoiceQuestion("Had someone you looked up to", +[ + Yes, + No, + NA +]) +{ + public const string Yes = "Yes"; + public const string No = "No"; + public const string NA = "N/A"; +}; \ No newline at end of file diff --git a/src/Application/Features/Bios/DTOs/V1/Pathways/ChildhoodExperiences/B2.cs b/src/Application/Features/Bios/DTOs/V1/Pathways/ChildhoodExperiences/B2.cs new file mode 100644 index 00000000..333c8626 --- /dev/null +++ b/src/Application/Features/Bios/DTOs/V1/Pathways/ChildhoodExperiences/B2.cs @@ -0,0 +1,12 @@ +namespace Cfo.Cats.Application.Features.Bios.DTOs.V1.Pathways.ChildhoodExperiences; +public class B2() : SingleChoiceQuestion("Spent most of childhood in the same family home", +[ + Yes, + No, + NA +]) +{ + public const string Yes = "Yes"; + public const string No = "No"; + public const string NA = "N/A"; +}; \ No newline at end of file diff --git a/src/Application/Features/Bios/DTOs/V1/Pathways/ChildhoodExperiences/B3.cs b/src/Application/Features/Bios/DTOs/V1/Pathways/ChildhoodExperiences/B3.cs new file mode 100644 index 00000000..2e8b0bdd --- /dev/null +++ b/src/Application/Features/Bios/DTOs/V1/Pathways/ChildhoodExperiences/B3.cs @@ -0,0 +1,12 @@ +namespace Cfo.Cats.Application.Features.Bios.DTOs.V1.Pathways.ChildhoodExperiences; +public class B3() : SingleChoiceQuestion("Suffered abuse or neglect as a child", +[ + Yes, + No, + NA +]) +{ + public const string Yes = "Yes"; + public const string No = "No"; + public const string NA = "N/A"; +}; \ No newline at end of file diff --git a/src/Application/Features/Bios/DTOs/V1/Pathways/ChildhoodExperiences/B4.cs b/src/Application/Features/Bios/DTOs/V1/Pathways/ChildhoodExperiences/B4.cs new file mode 100644 index 00000000..ca2e6137 --- /dev/null +++ b/src/Application/Features/Bios/DTOs/V1/Pathways/ChildhoodExperiences/B4.cs @@ -0,0 +1,12 @@ +namespace Cfo.Cats.Application.Features.Bios.DTOs.V1.Pathways.ChildhoodExperiences; +public class B4() : SingleChoiceQuestion("Had a difficult childhood", +[ + Yes, + No, + NA +]) +{ + public const string Yes = "Yes"; + public const string No = "No"; + public const string NA = "N/A"; +}; \ No newline at end of file diff --git a/src/Application/Features/Bios/DTOs/V1/Pathways/ChildhoodExperiences/B5.cs b/src/Application/Features/Bios/DTOs/V1/Pathways/ChildhoodExperiences/B5.cs new file mode 100644 index 00000000..7c88d529 --- /dev/null +++ b/src/Application/Features/Bios/DTOs/V1/Pathways/ChildhoodExperiences/B5.cs @@ -0,0 +1,12 @@ +namespace Cfo.Cats.Application.Features.Bios.DTOs.V1.Pathways.ChildhoodExperiences; +public class B5() : SingleChoiceQuestion("Both parents/guardians were mostly present", +[ + Yes, + No, + NA +]) +{ + public const string Yes = "Yes"; + public const string No = "No"; + public const string NA = "N/A"; +}; \ No newline at end of file diff --git a/src/Application/Features/Bios/DTOs/V1/Pathways/ChildhoodExperiences/B6.cs b/src/Application/Features/Bios/DTOs/V1/Pathways/ChildhoodExperiences/B6.cs new file mode 100644 index 00000000..dd8128b8 --- /dev/null +++ b/src/Application/Features/Bios/DTOs/V1/Pathways/ChildhoodExperiences/B6.cs @@ -0,0 +1,12 @@ +namespace Cfo.Cats.Application.Features.Bios.DTOs.V1.Pathways.ChildhoodExperiences; +public class B6() : SingleChoiceQuestion("At least one parent or guardian was mostly in work", +[ + Yes, + No, + NA +]) +{ + public const string Yes = "Yes"; + public const string No = "No"; + public const string NA = "N/A"; +}; \ No newline at end of file diff --git a/src/Application/Features/Bios/DTOs/V1/Pathways/ChildhoodExperiences/B7.cs b/src/Application/Features/Bios/DTOs/V1/Pathways/ChildhoodExperiences/B7.cs new file mode 100644 index 00000000..5d33d923 --- /dev/null +++ b/src/Application/Features/Bios/DTOs/V1/Pathways/ChildhoodExperiences/B7.cs @@ -0,0 +1,12 @@ +namespace Cfo.Cats.Application.Features.Bios.DTOs.V1.Pathways.ChildhoodExperiences; +public class B7() : SingleChoiceQuestion("A parent or guardian was in trouble with the police", +[ + Yes, + No, + NA +]) +{ + public const string Yes = "Yes"; + public const string No = "No"; + public const string NA = "N/A"; +}; \ No newline at end of file diff --git a/src/Application/Features/Bios/DTOs/V1/Pathways/ChildhoodExperiences/B8.cs b/src/Application/Features/Bios/DTOs/V1/Pathways/ChildhoodExperiences/B8.cs new file mode 100644 index 00000000..2a19e242 --- /dev/null +++ b/src/Application/Features/Bios/DTOs/V1/Pathways/ChildhoodExperiences/B8.cs @@ -0,0 +1,12 @@ +namespace Cfo.Cats.Application.Features.Bios.DTOs.V1.Pathways.ChildhoodExperiences; +public class B8() : SingleChoiceQuestion("A parent or guardian spent time in prison", +[ + Yes, + No, + NA +]) +{ + public const string Yes = "Yes"; + public const string No = "No"; + public const string NA = "N/A"; +}; \ No newline at end of file diff --git a/src/Application/Features/Bios/DTOs/V1/Pathways/ChildhoodExperiences/B9.cs b/src/Application/Features/Bios/DTOs/V1/Pathways/ChildhoodExperiences/B9.cs new file mode 100644 index 00000000..73510665 --- /dev/null +++ b/src/Application/Features/Bios/DTOs/V1/Pathways/ChildhoodExperiences/B9.cs @@ -0,0 +1,12 @@ +namespace Cfo.Cats.Application.Features.Bios.DTOs.V1.Pathways.ChildhoodExperiences; +public class B9() : SingleChoiceQuestion("Felt loved and cared for at home", +[ + Yes, + No, + NA +]) +{ + public const string Yes = "Yes"; + public const string No = "No"; + public const string NA = "N/A"; +}; \ No newline at end of file diff --git a/src/Application/Features/Bios/DTOs/V1/Pathways/ChildhoodExperiences/ChildhoodExperiencesPathway.cs b/src/Application/Features/Bios/DTOs/V1/Pathways/ChildhoodExperiences/ChildhoodExperiencesPathway.cs new file mode 100644 index 00000000..47b54180 --- /dev/null +++ b/src/Application/Features/Bios/DTOs/V1/Pathways/ChildhoodExperiences/ChildhoodExperiencesPathway.cs @@ -0,0 +1,51 @@ +using System.Text.Json.Serialization; + +namespace Cfo.Cats.Application.Features.Bios.DTOs.V1.Pathways.ChildhoodExperiences; + +public sealed partial class ChildhoodExperiencesPathway + : PathwayBase +{ + + [JsonIgnore] + public override string Title => "ChildhoodExperiences"; + + + + [JsonIgnore] + public override string Icon => CatsIcons.ChildhoodExperiences; + public override IEnumerable Questions() + { + yield return B1; + yield return B2; + yield return B3; + yield return B4; + yield return B5; + yield return B6; + yield return B7; + yield return B8; + yield return B9; + yield return B10; + yield return B11; + yield return B12; + yield return B13; + yield return B14; + yield return B15; + + } + + public B1 B1 { get; private set; } = new(); + public B2 B2 { get; private set; } = new(); + public B3 B3 { get; private set; } = new(); + public B4 B4 { get; private set; } = new(); + public B5 B5 { get;private set; } = new(); + public B6 B6 { get;private set; } = new(); + public B7 B7 { get;private set; } = new(); + public B8 B8 { get;private set; } = new(); + public B9 B9 { get; private set; } = new(); + public B10 B10 { get; private set; } = new(); + public B11 B11 { get; private set; } = new(); + public B12 B12 { get; private set; } = new(); + public B13 B13 { get; private set; } = new(); + public B14 B14 { get; private set; } = new(); + public B15 B15 { get; private set; } = new(); +} diff --git a/src/Application/Features/Bios/DTOs/V1/Pathways/Diversity/A1.cs b/src/Application/Features/Bios/DTOs/V1/Pathways/Diversity/A1.cs new file mode 100644 index 00000000..5ee0324c --- /dev/null +++ b/src/Application/Features/Bios/DTOs/V1/Pathways/Diversity/A1.cs @@ -0,0 +1,13 @@ +namespace Cfo.Cats.Application.Features.Bios.DTOs.V1.Pathways.Diversity; + +public class A1() : SingleChoiceQuestion("Consider yourself a religious person", +[ + Yes, + No, + NA +]) +{ + public const string Yes = "Yes"; + public const string No = "No"; + public const string NA = "N/A"; +}; \ No newline at end of file diff --git a/src/Application/Features/Bios/DTOs/V1/Pathways/Diversity/A10.cs b/src/Application/Features/Bios/DTOs/V1/Pathways/Diversity/A10.cs new file mode 100644 index 00000000..9ea30f29 --- /dev/null +++ b/src/Application/Features/Bios/DTOs/V1/Pathways/Diversity/A10.cs @@ -0,0 +1,13 @@ +namespace Cfo.Cats.Application.Features.Bios.DTOs.V1.Pathways.Diversity; + +public class A10() : SingleChoiceQuestion("Are/have been a member of a gang", +[ + Yes, + No, + NA +]) +{ + public const string Yes = "Yes"; + public const string No = "No"; + public const string NA = "N/A"; +}; \ No newline at end of file diff --git a/src/Application/Features/Bios/DTOs/V1/Pathways/Diversity/A11.cs b/src/Application/Features/Bios/DTOs/V1/Pathways/Diversity/A11.cs new file mode 100644 index 00000000..7e5c4d47 --- /dev/null +++ b/src/Application/Features/Bios/DTOs/V1/Pathways/Diversity/A11.cs @@ -0,0 +1,13 @@ +namespace Cfo.Cats.Application.Features.Bios.DTOs.V1.Pathways.Diversity; + +public class A11() : SingleChoiceQuestion("Have carried an illegal weapon at some point in the past", +[ + Yes, + No, + NA +]) +{ + public const string Yes = "Yes"; + public const string No = "No"; + public const string NA = "N/A"; +}; \ No newline at end of file diff --git a/src/Application/Features/Bios/DTOs/V1/Pathways/Diversity/A12.cs b/src/Application/Features/Bios/DTOs/V1/Pathways/Diversity/A12.cs new file mode 100644 index 00000000..f42c1cef --- /dev/null +++ b/src/Application/Features/Bios/DTOs/V1/Pathways/Diversity/A12.cs @@ -0,0 +1,13 @@ +namespace Cfo.Cats.Application.Features.Bios.DTOs.V1.Pathways.Diversity; + +public class A12() : SingleChoiceQuestion("Have undertaken prostitution or sex work", +[ + Yes, + No, + NA +]) +{ + public const string Yes = "Yes"; + public const string No = "No"; + public const string NA = "N/A"; +}; \ No newline at end of file diff --git a/src/Application/Features/Bios/DTOs/V1/Pathways/Diversity/A13.cs b/src/Application/Features/Bios/DTOs/V1/Pathways/Diversity/A13.cs new file mode 100644 index 00000000..5052a9b6 --- /dev/null +++ b/src/Application/Features/Bios/DTOs/V1/Pathways/Diversity/A13.cs @@ -0,0 +1,13 @@ +namespace Cfo.Cats.Application.Features.Bios.DTOs.V1.Pathways.Diversity; + +public class A13() : SingleChoiceQuestion("Feel you are being taken advantage of by others", +[ + Yes, + No, + NA +]) +{ + public const string Yes = "Yes"; + public const string No = "No"; + public const string NA = "N/A"; +}; \ No newline at end of file diff --git a/src/Application/Features/Bios/DTOs/V1/Pathways/Diversity/A14.cs b/src/Application/Features/Bios/DTOs/V1/Pathways/Diversity/A14.cs new file mode 100644 index 00000000..5a64def2 --- /dev/null +++ b/src/Application/Features/Bios/DTOs/V1/Pathways/Diversity/A14.cs @@ -0,0 +1,13 @@ +namespace Cfo.Cats.Application.Features.Bios.DTOs.V1.Pathways.Diversity; + +public class A14() : SingleChoiceQuestion("Feel you are part of a community ", +[ + Yes, + No, + NA +]) +{ + public const string Yes = "Yes"; + public const string No = "No"; + public const string NA = "N/A"; +}; \ No newline at end of file diff --git a/src/Application/Features/Bios/DTOs/V1/Pathways/Diversity/A15.cs b/src/Application/Features/Bios/DTOs/V1/Pathways/Diversity/A15.cs new file mode 100644 index 00000000..49052816 --- /dev/null +++ b/src/Application/Features/Bios/DTOs/V1/Pathways/Diversity/A15.cs @@ -0,0 +1,13 @@ +namespace Cfo.Cats.Application.Features.Bios.DTOs.V1.Pathways.Diversity; + +public class A15() : SingleChoiceQuestion("Feel you have been discriminated against because of who you are", +[ + Yes, + No, + NA +]) +{ + public const string Yes = "Yes"; + public const string No = "No"; + public const string NA = "N/A"; +}; \ No newline at end of file diff --git a/src/Application/Features/Bios/DTOs/V1/Pathways/Diversity/A16.cs b/src/Application/Features/Bios/DTOs/V1/Pathways/Diversity/A16.cs new file mode 100644 index 00000000..31640637 --- /dev/null +++ b/src/Application/Features/Bios/DTOs/V1/Pathways/Diversity/A16.cs @@ -0,0 +1,12 @@ +namespace Cfo.Cats.Application.Features.Bios.DTOs.V1.Pathways.Diversity; +public class A16() : SingleChoiceQuestion("Feel you generally share the same views of those around you", +[ + Yes, + No, + NA +]) +{ + public const string Yes = "Yes"; + public const string No = "No"; + public const string NA = "N/A"; +}; \ No newline at end of file diff --git a/src/Application/Features/Bios/DTOs/V1/Pathways/Diversity/A17.cs b/src/Application/Features/Bios/DTOs/V1/Pathways/Diversity/A17.cs new file mode 100644 index 00000000..56c7f1bd --- /dev/null +++ b/src/Application/Features/Bios/DTOs/V1/Pathways/Diversity/A17.cs @@ -0,0 +1,13 @@ +namespace Cfo.Cats.Application.Features.Bios.DTOs.V1.Pathways.Diversity; + +public class A17() : SingleChoiceQuestion("Feel you are always getting into trouble, since you were a child", +[ + Yes, + No, + NA +]) +{ + public const string Yes = "Yes"; + public const string No = "No"; + public const string NA = "N/A"; +}; \ No newline at end of file diff --git a/src/Application/Features/Bios/DTOs/V1/Pathways/Diversity/A18.cs b/src/Application/Features/Bios/DTOs/V1/Pathways/Diversity/A18.cs new file mode 100644 index 00000000..36ec327f --- /dev/null +++ b/src/Application/Features/Bios/DTOs/V1/Pathways/Diversity/A18.cs @@ -0,0 +1,13 @@ +namespace Cfo.Cats.Application.Features.Bios.DTOs.V1.Pathways.Diversity; + +public class A18() : SingleChoiceQuestion("Regret the offence(s) you committed", +[ + Yes, + No, + NA +]) +{ + public const string Yes = "Yes"; + public const string No = "No"; + public const string NA = "N/A"; +}; \ No newline at end of file diff --git a/src/Application/Features/Bios/DTOs/V1/Pathways/Diversity/A19.cs b/src/Application/Features/Bios/DTOs/V1/Pathways/Diversity/A19.cs new file mode 100644 index 00000000..9ddbc953 --- /dev/null +++ b/src/Application/Features/Bios/DTOs/V1/Pathways/Diversity/A19.cs @@ -0,0 +1,13 @@ +namespace Cfo.Cats.Application.Features.Bios.DTOs.V1.Pathways.Diversity; + +public class A19() : SingleChoiceQuestion("Feel your current situation is not your fault", +[ + Yes, + No, + NA +]) +{ + public const string Yes = "Yes"; + public const string No = "No"; + public const string NA = "N/A"; +}; \ No newline at end of file diff --git a/src/Application/Features/Bios/DTOs/V1/Pathways/Diversity/A2.cs b/src/Application/Features/Bios/DTOs/V1/Pathways/Diversity/A2.cs new file mode 100644 index 00000000..efaf52a3 --- /dev/null +++ b/src/Application/Features/Bios/DTOs/V1/Pathways/Diversity/A2.cs @@ -0,0 +1,13 @@ +namespace Cfo.Cats.Application.Features.Bios.DTOs.V1.Pathways.Diversity; + +public class A2() : SingleChoiceQuestion("Practise your faith regularly", +[ + Yes, + No, + NA +]) +{ + public const string Yes = "Yes"; + public const string No = "No"; + public const string NA = "N/A"; +}; \ No newline at end of file diff --git a/src/Application/Features/Bios/DTOs/V1/Pathways/Diversity/A20.cs b/src/Application/Features/Bios/DTOs/V1/Pathways/Diversity/A20.cs new file mode 100644 index 00000000..b134256f --- /dev/null +++ b/src/Application/Features/Bios/DTOs/V1/Pathways/Diversity/A20.cs @@ -0,0 +1,13 @@ +namespace Cfo.Cats.Application.Features.Bios.DTOs.V1.Pathways.Diversity; + +public class A20() : SingleChoiceQuestion("Feel you are a better person than you used to be", +[ + Yes, + No, + NA +]) +{ + public const string Yes = "Yes"; + public const string No = "No"; + public const string NA = "N/A"; +}; \ No newline at end of file diff --git a/src/Application/Features/Bios/DTOs/V1/Pathways/Diversity/A3.cs b/src/Application/Features/Bios/DTOs/V1/Pathways/Diversity/A3.cs new file mode 100644 index 00000000..4e2d52b0 --- /dev/null +++ b/src/Application/Features/Bios/DTOs/V1/Pathways/Diversity/A3.cs @@ -0,0 +1,13 @@ +namespace Cfo.Cats.Application.Features.Bios.DTOs.V1.Pathways.Diversity; + +public class A3() : SingleChoiceQuestion("Gay, lesbian, bisexual, or other non-hetero orientation", +[ + Yes, + No, + NA +]) +{ + public const string Yes = "Yes"; + public const string No = "No"; + public const string NA = "N/A"; +}; \ No newline at end of file diff --git a/src/Application/Features/Bios/DTOs/V1/Pathways/Diversity/A4.cs b/src/Application/Features/Bios/DTOs/V1/Pathways/Diversity/A4.cs new file mode 100644 index 00000000..cc1f6a77 --- /dev/null +++ b/src/Application/Features/Bios/DTOs/V1/Pathways/Diversity/A4.cs @@ -0,0 +1,13 @@ +namespace Cfo.Cats.Application.Features.Bios.DTOs.V1.Pathways.Diversity; + +public class A4() : SingleChoiceQuestion("Gender you identify with is different to your registered sex at birth", +[ + Yes, + No, + NA +]) +{ + public const string Yes = "Yes"; + public const string No = "No"; + public const string NA = "N/A"; +}; \ No newline at end of file diff --git a/src/Application/Features/Bios/DTOs/V1/Pathways/Diversity/A5.cs b/src/Application/Features/Bios/DTOs/V1/Pathways/Diversity/A5.cs new file mode 100644 index 00000000..fdab4654 --- /dev/null +++ b/src/Application/Features/Bios/DTOs/V1/Pathways/Diversity/A5.cs @@ -0,0 +1,13 @@ +namespace Cfo.Cats.Application.Features.Bios.DTOs.V1.Pathways.Diversity; + +public class A5() : SingleChoiceQuestion("A member of a Gypsy or Irish traveller community", +[ + Yes, + No, + NA +]) +{ + public const string Yes = "Yes"; + public const string No = "No"; + public const string NA = "N/A"; +}; \ No newline at end of file diff --git a/src/Application/Features/Bios/DTOs/V1/Pathways/Diversity/A6.cs b/src/Application/Features/Bios/DTOs/V1/Pathways/Diversity/A6.cs new file mode 100644 index 00000000..ed156c05 --- /dev/null +++ b/src/Application/Features/Bios/DTOs/V1/Pathways/Diversity/A6.cs @@ -0,0 +1,13 @@ +namespace Cfo.Cats.Application.Features.Bios.DTOs.V1.Pathways.Diversity; + +public class A6() : SingleChoiceQuestion("A member of the Roma community", +[ + Yes, + No, + NA +]) +{ + public const string Yes = "Yes"; + public const string No = "No"; + public const string NA = "N/A"; +}; \ No newline at end of file diff --git a/src/Application/Features/Bios/DTOs/V1/Pathways/Diversity/A7.cs b/src/Application/Features/Bios/DTOs/V1/Pathways/Diversity/A7.cs new file mode 100644 index 00000000..555c4ad7 --- /dev/null +++ b/src/Application/Features/Bios/DTOs/V1/Pathways/Diversity/A7.cs @@ -0,0 +1,13 @@ +namespace Cfo.Cats.Application.Features.Bios.DTOs.V1.Pathways.Diversity; + +public class A7() : SingleChoiceQuestion("Served in the British Armed Forces, inc. Reserves", +[ + Yes, + No, + NA +]) +{ + public const string Yes = "Yes"; + public const string No = "No"; + public const string NA = "N/A"; +}; \ No newline at end of file diff --git a/src/Application/Features/Bios/DTOs/V1/Pathways/Diversity/A8.cs b/src/Application/Features/Bios/DTOs/V1/Pathways/Diversity/A8.cs new file mode 100644 index 00000000..0ddd3824 --- /dev/null +++ b/src/Application/Features/Bios/DTOs/V1/Pathways/Diversity/A8.cs @@ -0,0 +1,13 @@ +namespace Cfo.Cats.Application.Features.Bios.DTOs.V1.Pathways.Diversity; + +public class A8() : SingleChoiceQuestion("Undertook an operational tour with the British Armed Forces", +[ + Yes, + No, + NA +]) +{ + public const string Yes = "Yes"; + public const string No = "No"; + public const string NA = "N/A"; +}; \ No newline at end of file diff --git a/src/Application/Features/Bios/DTOs/V1/Pathways/Diversity/A9.cs b/src/Application/Features/Bios/DTOs/V1/Pathways/Diversity/A9.cs new file mode 100644 index 00000000..680e00f6 --- /dev/null +++ b/src/Application/Features/Bios/DTOs/V1/Pathways/Diversity/A9.cs @@ -0,0 +1,13 @@ +namespace Cfo.Cats.Application.Features.Bios.DTOs.V1.Pathways.Diversity; + +public class A9() : SingleChoiceQuestion("Have seen combat while a member of the British Armed Forces", +[ + Yes, + No, + NA +]) +{ + public const string Yes = "Yes"; + public const string No = "No"; + public const string NA = "N/A"; +}; \ No newline at end of file diff --git a/src/Application/Features/Bios/DTOs/V1/Pathways/Diversity/DiversityPathway.cs b/src/Application/Features/Bios/DTOs/V1/Pathways/Diversity/DiversityPathway.cs new file mode 100644 index 00000000..3831bbe7 --- /dev/null +++ b/src/Application/Features/Bios/DTOs/V1/Pathways/Diversity/DiversityPathway.cs @@ -0,0 +1,61 @@ +using System.Text.Json.Serialization; + +namespace Cfo.Cats.Application.Features.Bios.DTOs.V1.Pathways.Diversity; + +public sealed partial class DiversityPathway + : PathwayBase +{ + + [JsonIgnore] + public override string Title => "Diversity"; + + + + [JsonIgnore] + public override string Icon => CatsIcons.Diversity; + public override IEnumerable Questions() + { + yield return A1; + yield return A2; + yield return A3; + yield return A4; + yield return A5; + yield return A6; + yield return A7; + yield return A8; + yield return A9; + yield return A10; + yield return A11; + yield return A12; + yield return A13; + yield return A14; + yield return A15; + yield return A16; + yield return A17; + yield return A18; + yield return A19; + yield return A20; + } + + public A1 A1 { get; private set; } = new(); + public A2 A2 { get; private set; } = new(); + public A3 A3 { get; private set; } = new(); + public A4 A4 { get; private set; } = new(); + public A5 A5 { get;private set; } = new(); + public A6 A6 { get;private set; } = new(); + public A7 A7 { get;private set; } = new(); + public A8 A8 { get;private set; } = new(); + public A9 A9 { get; private set; } = new(); + public A10 A10 { get; private set; } = new(); + public A11 A11 { get; private set; } = new(); + public A12 A12 { get; private set; } = new(); + public A13 A13 { get; private set; } = new(); + public A14 A14 { get; private set; } = new(); + public A15 A15 { get; private set; } = new(); + public A16 A16 { get; private set; } = new(); + public A17 A17 { get; private set; } = new(); + public A18 A18 { get; private set; } = new(); + public A19 A19 { get; private set; } = new(); + public A20 A20 { get; private set; } = new(); + +} diff --git a/src/Application/Features/Bios/DTOs/V1/Pathways/RecentExperiences/C1.cs b/src/Application/Features/Bios/DTOs/V1/Pathways/RecentExperiences/C1.cs new file mode 100644 index 00000000..16ddeffc --- /dev/null +++ b/src/Application/Features/Bios/DTOs/V1/Pathways/RecentExperiences/C1.cs @@ -0,0 +1,12 @@ +namespace Cfo.Cats.Application.Features.Bios.DTOs.V1.Pathways.RecentExperiences; +public class C1() : SingleChoiceQuestion("Had a loved one become seriously ill or pass away", +[ + Yes, + No, + NA +]) +{ + public const string Yes = "Yes"; + public const string No = "No"; + public const string NA = "N/A"; +}; \ No newline at end of file diff --git a/src/Application/Features/Bios/DTOs/V1/Pathways/RecentExperiences/C10.cs b/src/Application/Features/Bios/DTOs/V1/Pathways/RecentExperiences/C10.cs new file mode 100644 index 00000000..e3ff853b --- /dev/null +++ b/src/Application/Features/Bios/DTOs/V1/Pathways/RecentExperiences/C10.cs @@ -0,0 +1,12 @@ +namespace Cfo.Cats.Application.Features.Bios.DTOs.V1.Pathways.RecentExperiences; +public class C10() : SingleChoiceQuestion("Found a new hobby or interest", +[ + Yes, + No, + NA +]) +{ + public const string Yes = "Yes"; + public const string No = "No"; + public const string NA = "N/A"; +}; \ No newline at end of file diff --git a/src/Application/Features/Bios/DTOs/V1/Pathways/RecentExperiences/C2.cs b/src/Application/Features/Bios/DTOs/V1/Pathways/RecentExperiences/C2.cs new file mode 100644 index 00000000..00d76888 --- /dev/null +++ b/src/Application/Features/Bios/DTOs/V1/Pathways/RecentExperiences/C2.cs @@ -0,0 +1,12 @@ +namespace Cfo.Cats.Application.Features.Bios.DTOs.V1.Pathways.RecentExperiences; +public class C2() : SingleChoiceQuestion("Got engaged, married, entered a civil partnership", +[ + Yes, + No, + NA +]) +{ + public const string Yes = "Yes"; + public const string No = "No"; + public const string NA = "N/A"; +}; \ No newline at end of file diff --git a/src/Application/Features/Bios/DTOs/V1/Pathways/RecentExperiences/C3.cs b/src/Application/Features/Bios/DTOs/V1/Pathways/RecentExperiences/C3.cs new file mode 100644 index 00000000..7281fdca --- /dev/null +++ b/src/Application/Features/Bios/DTOs/V1/Pathways/RecentExperiences/C3.cs @@ -0,0 +1,12 @@ +namespace Cfo.Cats.Application.Features.Bios.DTOs.V1.Pathways.RecentExperiences; +public class C3() : SingleChoiceQuestion("Became a parent", +[ + Yes, + No, + NA +]) +{ + public const string Yes = "Yes"; + public const string No = "No"; + public const string NA = "N/A"; +}; \ No newline at end of file diff --git a/src/Application/Features/Bios/DTOs/V1/Pathways/RecentExperiences/C4.cs b/src/Application/Features/Bios/DTOs/V1/Pathways/RecentExperiences/C4.cs new file mode 100644 index 00000000..ea68f919 --- /dev/null +++ b/src/Application/Features/Bios/DTOs/V1/Pathways/RecentExperiences/C4.cs @@ -0,0 +1,12 @@ +namespace Cfo.Cats.Application.Features.Bios.DTOs.V1.Pathways.RecentExperiences; +public class C4() : SingleChoiceQuestion("Started a new personal relationship", +[ + Yes, + No, + NA +]) +{ + public const string Yes = "Yes"; + public const string No = "No"; + public const string NA = "N/A"; +}; \ No newline at end of file diff --git a/src/Application/Features/Bios/DTOs/V1/Pathways/RecentExperiences/C5.cs b/src/Application/Features/Bios/DTOs/V1/Pathways/RecentExperiences/C5.cs new file mode 100644 index 00000000..cceddcae --- /dev/null +++ b/src/Application/Features/Bios/DTOs/V1/Pathways/RecentExperiences/C5.cs @@ -0,0 +1,12 @@ +namespace Cfo.Cats.Application.Features.Bios.DTOs.V1.Pathways.RecentExperiences; +public class C5() : SingleChoiceQuestion("Left a significant long-term relationship / divorce", +[ + Yes, + No, + NA +]) +{ + public const string Yes = "Yes"; + public const string No = "No"; + public const string NA = "N/A"; +}; \ No newline at end of file diff --git a/src/Application/Features/Bios/DTOs/V1/Pathways/RecentExperiences/C6.cs b/src/Application/Features/Bios/DTOs/V1/Pathways/RecentExperiences/C6.cs new file mode 100644 index 00000000..85284b8b --- /dev/null +++ b/src/Application/Features/Bios/DTOs/V1/Pathways/RecentExperiences/C6.cs @@ -0,0 +1,12 @@ +namespace Cfo.Cats.Application.Features.Bios.DTOs.V1.Pathways.RecentExperiences; +public class C6() : SingleChoiceQuestion("Subject to verbal abuse or harassment", +[ + Yes, + No, + NA +]) +{ + public const string Yes = "Yes"; + public const string No = "No"; + public const string NA = "N/A"; +}; \ No newline at end of file diff --git a/src/Application/Features/Bios/DTOs/V1/Pathways/RecentExperiences/C7.cs b/src/Application/Features/Bios/DTOs/V1/Pathways/RecentExperiences/C7.cs new file mode 100644 index 00000000..af37baa0 --- /dev/null +++ b/src/Application/Features/Bios/DTOs/V1/Pathways/RecentExperiences/C7.cs @@ -0,0 +1,12 @@ +namespace Cfo.Cats.Application.Features.Bios.DTOs.V1.Pathways.RecentExperiences; +public class C7() : SingleChoiceQuestion("Subject to violence or harm by another person", +[ + Yes, + No, + NA +]) +{ + public const string Yes = "Yes"; + public const string No = "No"; + public const string NA = "N/A"; +}; \ No newline at end of file diff --git a/src/Application/Features/Bios/DTOs/V1/Pathways/RecentExperiences/C8.cs b/src/Application/Features/Bios/DTOs/V1/Pathways/RecentExperiences/C8.cs new file mode 100644 index 00000000..c51f4d38 --- /dev/null +++ b/src/Application/Features/Bios/DTOs/V1/Pathways/RecentExperiences/C8.cs @@ -0,0 +1,12 @@ +namespace Cfo.Cats.Application.Features.Bios.DTOs.V1.Pathways.RecentExperiences; +public class C8() : SingleChoiceQuestion("Lost your job", +[ + Yes, + No, + NA +]) +{ + public const string Yes = "Yes"; + public const string No = "No"; + public const string NA = "N/A"; +}; \ No newline at end of file diff --git a/src/Application/Features/Bios/DTOs/V1/Pathways/RecentExperiences/C9.cs b/src/Application/Features/Bios/DTOs/V1/Pathways/RecentExperiences/C9.cs new file mode 100644 index 00000000..2ef1f1da --- /dev/null +++ b/src/Application/Features/Bios/DTOs/V1/Pathways/RecentExperiences/C9.cs @@ -0,0 +1,12 @@ +namespace Cfo.Cats.Application.Features.Bios.DTOs.V1.Pathways.RecentExperiences; +public class C9() : SingleChoiceQuestion("Started a new job", +[ + Yes, + No, + NA +]) +{ + public const string Yes = "Yes"; + public const string No = "No"; + public const string NA = "N/A"; +}; \ No newline at end of file diff --git a/src/Application/Features/Bios/DTOs/V1/Pathways/RecentExperiences/RecentExperiencesPathway.cs b/src/Application/Features/Bios/DTOs/V1/Pathways/RecentExperiences/RecentExperiencesPathway.cs new file mode 100644 index 00000000..57114594 --- /dev/null +++ b/src/Application/Features/Bios/DTOs/V1/Pathways/RecentExperiences/RecentExperiencesPathway.cs @@ -0,0 +1,42 @@ +using System.Text.Json.Serialization; + +namespace Cfo.Cats.Application.Features.Bios.DTOs.V1.Pathways.RecentExperiences; + +public sealed partial class RecentExperiencesPathway + : PathwayBase +{ + + [JsonIgnore] + public override string Title => "RecentExperiences"; + + + + [JsonIgnore] + public override string Icon => CatsIcons.RecentExperiences; + public override IEnumerable Questions() + { + yield return C1; + yield return C2; + yield return C3; + yield return C4; + yield return C5; + yield return C6; + yield return C7; + yield return C8; + yield return C9; + yield return C10; + + } + + public C1 C1 { get; private set; } = new(); + public C2 C2 { get; private set; } = new(); + public C3 C3 { get; private set; } = new(); + public C4 C4 { get; private set; } = new(); + public C5 C5 { get; private set; } = new(); + public C6 C6 { get; private set; } = new(); + public C7 C7 { get; private set; } = new(); + public C8 C8 { get; private set; } = new(); + public C9 C9 { get; private set; } = new(); + public C10 C10 { get; private set; } = new(); + +} diff --git a/src/Application/Features/Bios/Exceptions/InvalidAnswerException.cs b/src/Application/Features/Bios/Exceptions/InvalidAnswerException.cs new file mode 100644 index 00000000..e9d9f2a1 --- /dev/null +++ b/src/Application/Features/Bios/Exceptions/InvalidAnswerException.cs @@ -0,0 +1,11 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Cfo.Cats.Application.Features.Bios.Exceptions; +public class InvalidAnswerException(string question, string answer) + : Exception($"The answer {answer} is not valid for the question {question}"); + + diff --git a/src/Application/Features/Bios/Queries/GetBio.cs b/src/Application/Features/Bios/Queries/GetBio.cs new file mode 100644 index 00000000..6047be77 --- /dev/null +++ b/src/Application/Features/Bios/Queries/GetBio.cs @@ -0,0 +1,74 @@ +using Cfo.Cats.Application.Common.Security; +using Cfo.Cats.Application.Common.Validators; +using Cfo.Cats.Application.SecurityConstants; +using Cfo.Cats.Application.Features.Bios.DTOs; +using Newtonsoft.Json; + + +namespace Cfo.Cats.Application.Features.Bios.Queries; + +public static class GetBio +{ + + /// + /// Returns a Bio for a Participant + /// + [RequestAuthorize(Policy = SecurityPolicies.Enrol)] + public class Query : IRequest> + { + public required string ParticipantId { get; set; } + public Guid? BioId { get; set; } + + } + + internal class Handler : IRequestHandler> + { + private readonly IUnitOfWork _unitOfWork; + public Handler(IUnitOfWork unitOfWork) + { + this._unitOfWork = unitOfWork; + } + + public async Task> Handle(Query request, CancellationToken cancellationToken) + { + var query = _unitOfWork.DbContext.ParticipantBios + .Where(p => p.ParticipantId == request.ParticipantId); + + if (request.BioId is not null) + { + query = query.Where(p => p.Id == request.BioId); + } + + var bioSurvey = await query.OrderByDescending(bioSurvey => bioSurvey.Created) + .FirstOrDefaultAsync(cancellationToken); + + if (bioSurvey is null) + { + return Result.Failure(["Participant not found"]); + } + + Bio bio = JsonConvert.DeserializeObject(bioSurvey.BioJson, + new JsonSerializerSettings + { + TypeNameHandling = TypeNameHandling.Auto + })!; + return Result.Success(bio); + } + } + + public class Validator : AbstractValidator + { + public Validator() + { + + RuleFor(x => x.ParticipantId) + .NotNull(); + + RuleFor(x => x.ParticipantId) + .MinimumLength(9) + .MaximumLength(9) + .Matches(ValidationConstants.AlphaNumeric) + .WithMessage(string.Format(ValidationConstants.AlphaNumericMessage, "Participant Id")); + } + } +} \ No newline at end of file diff --git a/src/Application/Features/Participants/DTOs/ParticipantSummaryDto.cs b/src/Application/Features/Participants/DTOs/ParticipantSummaryDto.cs index 27da8efb..b218833e 100644 --- a/src/Application/Features/Participants/DTOs/ParticipantSummaryDto.cs +++ b/src/Application/Features/Participants/DTOs/ParticipantSummaryDto.cs @@ -1,3 +1,4 @@ +using Cfo.Cats.Application.Features.Bios.DTOs; using Cfo.Cats.Domain.Entities.Assessments; using Cfo.Cats.Domain.Entities.Participants; @@ -42,6 +43,7 @@ public class ParticipantSummaryDto public RiskSummaryDto? LatestRisk { get; set; } + public BioSummaryDto? BioSummary { get; set; } private class Mapping : Profile { @@ -61,6 +63,12 @@ public Mapping() .ForMember(target => target.AssessmentDate, options => options.MapFrom(source => source.Created)) .ForMember(target => target.AssessmentCreator, options => options.MapFrom(source => source.CreatedBy)) .ForMember(target => target.AssessmentScored, options => options.MapFrom(source => source.Scores.All(s => s.Score >= 0))); + + CreateMap() + .ForMember(target => target.BioId, options => options.MapFrom(source => source.Id)) + .ForMember(target => target.BioDate, options => options.MapFrom(source => source.Created)) + .ForMember(target => target.BioStatus, options => options.MapFrom(source => source.Status)) + .ForMember(target => target.BioCreator, options => options.MapFrom(source => source.CreatedBy)); } } @@ -91,3 +99,28 @@ public class AssessmentSummaryDto /// public bool? AssessmentScored { get; set; } } + +public class BioSummaryDto +{ + /// + /// The id of the one and only Bio, atleast for now + /// + public Guid? BioId { get; set; } + + + /// + /// The date when Bio was created. + /// + public DateTime? BioDate { get; set; } + + /// + /// Who created the Bio (if available) + /// + public string? BioCreator { get; set; } + + /// + /// Status of the Bio + /// + public BioStatus BioStatus { get; set; } = BioStatus.NotStarted; + +} diff --git a/src/Application/Features/Participants/Queries/GetParticipantSummary.cs b/src/Application/Features/Participants/Queries/GetParticipantSummary.cs index 6cc84c26..20bfe64d 100644 --- a/src/Application/Features/Participants/Queries/GetParticipantSummary.cs +++ b/src/Application/Features/Participants/Queries/GetParticipantSummary.cs @@ -46,7 +46,13 @@ public async Task> Handle(Query request, Cancellat .FirstOrDefaultAsync(x => x.ParticipantId == request.ParticipantId, cancellationToken); summary.LatestRisk = mapper.Map(risk); - + + var bio = await unitOfWork.DbContext.ParticipantBios + .OrderByDescending(x => x.Created) + .FirstOrDefaultAsync(x => x.ParticipantId == request.ParticipantId, cancellationToken); + + summary.BioSummary = mapper.Map(bio); + return Result.Success(summary); } diff --git a/src/Domain/Common/Enums/BioStatus.cs b/src/Domain/Common/Enums/BioStatus.cs new file mode 100644 index 00000000..8ba0a2d1 --- /dev/null +++ b/src/Domain/Common/Enums/BioStatus.cs @@ -0,0 +1,14 @@ +using Ardalis.SmartEnum; + +namespace Cfo.Cats.Domain.Common.Enums; + +public class BioStatus : SmartEnum +{ + public static readonly BioStatus NotStarted = new(nameof(NotStarted), 0); + public static readonly BioStatus SkippedForNow = new(nameof(SkippedForNow), 1); + public static readonly BioStatus InProgress = new(nameof(InProgress), 2); + public static readonly BioStatus Complete = new(nameof(Complete), 3); + + private BioStatus(string name, int value) + : base(name, value) { } +} diff --git a/src/Domain/Common/Enums/Pathway.cs b/src/Domain/Common/Enums/Pathway.cs index cffd9c41..937ece1c 100644 --- a/src/Domain/Common/Enums/Pathway.cs +++ b/src/Domain/Common/Enums/Pathway.cs @@ -33,5 +33,11 @@ public static class CatsIcons public const string Money = ""; public const string Thoughts = ""; public const string AboutYou = ""; + + public const string Diversity = ""; + public const string Exemption = ""; + public const string ChildhoodExperiences = ""; + public const string RecentExperiences = ""; + } diff --git a/src/Domain/Domain.csproj b/src/Domain/Domain.csproj index 40f57329..dfa01cf8 100644 --- a/src/Domain/Domain.csproj +++ b/src/Domain/Domain.csproj @@ -11,10 +11,10 @@ - - - - + + + + diff --git a/src/Domain/Entities/Bios/ParticipantBio.cs b/src/Domain/Entities/Bios/ParticipantBio.cs new file mode 100644 index 00000000..da832898 --- /dev/null +++ b/src/Domain/Entities/Bios/ParticipantBio.cs @@ -0,0 +1,58 @@ +using Cfo.Cats.Domain.Common.Contracts; +using Cfo.Cats.Domain.Common.Entities; +using Cfo.Cats.Domain.Common.Enums; +using Cfo.Cats.Domain.Events; +using System.Security.Cryptography; + +namespace Cfo.Cats.Domain.Entities.Bios +{ + + public class ParticipantBio : BaseAuditableEntity, IAuditTrial + { + +#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. + private ParticipantBio() + { + } +#pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. + + public string ParticipantId { get; private set; } + public string BioJson { get; private set; } + public BioStatus Status { get; private set; } = BioStatus.NotStarted; + private ParticipantBio(Guid id, string participantId, string bioJson, BioStatus status) + { + Id = id; + ParticipantId = participantId; + BioJson = bioJson; + Status = status; + AddDomainEvent(new BioCreatedDomainEvent(this)); + } + + public ParticipantBio UpdateJson(string json) + { + BioJson = json; + return this; + } + + public ParticipantBio Submit() + { + // this does nothing except raise the event. + AddDomainEvent(new BioCreatedDomainEvent(this)); + return this; + } + + public static ParticipantBio Create(Guid id, string participantId, string bioJson, BioStatus status) + { + return new ParticipantBio(id, participantId, bioJson, status); + } + + public ParticipantBio UpdateStatus(BioStatus status) + { + if(Status != BioStatus.Complete) + { + Status = status; + } + return this; + } + } +} \ No newline at end of file diff --git a/src/Domain/Events/BioEvents.cs b/src/Domain/Events/BioEvents.cs new file mode 100644 index 00000000..2a97b2c5 --- /dev/null +++ b/src/Domain/Events/BioEvents.cs @@ -0,0 +1,8 @@ +using Cfo.Cats.Domain.Common.Events; +using Cfo.Cats.Domain.Entities.Bios; + +namespace Cfo.Cats.Domain.Events; + +public sealed class BioCreatedDomainEvent(ParticipantBio entity) + : CreatedDomainEvent(entity); + diff --git a/src/Infrastructure/Constants/Database/DatabaseConstants.cs b/src/Infrastructure/Constants/Database/DatabaseConstants.cs index b5bd1460..35f5fdba 100644 --- a/src/Infrastructure/Constants/Database/DatabaseConstants.cs +++ b/src/Infrastructure/Constants/Database/DatabaseConstants.cs @@ -22,6 +22,7 @@ public static class Tables public const string LocationMapping = nameof(LocationMapping); public const string Participant = nameof(Participant); public const string Assessment = nameof(Assessment); + public const string Bio = nameof(Bio); public const string Note = nameof(Note); public const string Tenant = nameof(Tenant); public const string TenantDomain = nameof(TenantDomain); diff --git a/src/Infrastructure/Persistence/ApplicationDbContext.cs b/src/Infrastructure/Persistence/ApplicationDbContext.cs index 80614cb8..dc980f73 100644 --- a/src/Infrastructure/Persistence/ApplicationDbContext.cs +++ b/src/Infrastructure/Persistence/ApplicationDbContext.cs @@ -4,6 +4,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.Infrastructure.Persistence.Configurations.Enrolments; using Microsoft.AspNetCore.DataProtection.EntityFrameworkCore; @@ -40,7 +41,8 @@ public ApplicationDbContext(DbContextOptions options) public DbSet Risks => Set(); public DbSet ParticipantAssessments => Set(); - + + public DbSet ParticipantBios => Set(); public DbSet KeyValues => Set(); diff --git a/src/Infrastructure/Persistence/Configurations/Participants/BioEntityTypeConfiguration.cs b/src/Infrastructure/Persistence/Configurations/Participants/BioEntityTypeConfiguration.cs new file mode 100644 index 00000000..bf41a465 --- /dev/null +++ b/src/Infrastructure/Persistence/Configurations/Participants/BioEntityTypeConfiguration.cs @@ -0,0 +1,35 @@ +using Cfo.Cats.Domain.Common.Enums; +using Cfo.Cats.Domain.Entities.Bios; +using Cfo.Cats.Infrastructure.Constants.Database; +using Microsoft.EntityFrameworkCore.Metadata.Builders; + +namespace Cfo.Cats.Infrastructure.Persistence.Configurations.Bios +{ + public class BioEntityTypeConfiguration : IEntityTypeConfiguration + { + public void Configure(EntityTypeBuilder builder) + { + builder.ToTable( + DatabaseConstants.Tables.Bio, + DatabaseConstants.Schemas.Participant); + + builder.HasKey(t => t.Id); + + builder.HasOne() + .WithMany() + .HasForeignKey(pa => pa.ParticipantId) + .OnDelete(DeleteBehavior.Cascade); + + builder.Property(x => x.ParticipantId) + .HasMaxLength(DatabaseConstants.FieldLengths.ParticipantId); + builder.Property(x => x.Status) + .HasConversion( + x => x!.Value, + x => BioStatus.FromValue(x) + ); + + builder.Property(x => x.CreatedBy).HasMaxLength(DatabaseConstants.FieldLengths.GuidId); + builder.Property(x => x.LastModifiedBy).HasMaxLength(DatabaseConstants.FieldLengths.GuidId); + } + } +} \ No newline at end of file diff --git a/src/Migrators/Migrators.MSSQL/Migrations/20240813132251_bio.Designer.cs b/src/Migrators/Migrators.MSSQL/Migrations/20240813132251_bio.Designer.cs new file mode 100644 index 00000000..cb178e4e --- /dev/null +++ b/src/Migrators/Migrators.MSSQL/Migrations/20240813132251_bio.Designer.cs @@ -0,0 +1,2347 @@ +// +using System; +using Cfo.Cats.Infrastructure.Persistence; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace Cfo.Cats.Migrators.MSSQL.Migrations +{ + [DbContext(typeof(ApplicationDbContext))] + [Migration("20240813132251_bio")] + partial class bio + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "8.0.7") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); + + modelBuilder.Entity("Cfo.Cats.Domain.Entities.Administration.Contract", b => + { + b.Property("Id") + .HasMaxLength(12) + .HasColumnType("nvarchar(12)"); + + b.Property("Created") + .HasColumnType("datetime2"); + + b.Property("CreatedBy") + .HasMaxLength(36) + .HasColumnType("nvarchar(36)"); + + b.Property("Description") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("LastModified") + .HasColumnType("datetime2"); + + b.Property("LastModifiedBy") + .HasMaxLength(36) + .HasColumnType("nvarchar(36)"); + + b.Property("LotNumber") + .HasColumnType("int"); + + b.Property("_tenantId") + .HasMaxLength(50) + .HasColumnType("nvarchar(50)") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("LotNumber") + .IsUnique(); + + b.HasIndex("_tenantId"); + + b.ToTable("Contract", "Configuration"); + }); + + modelBuilder.Entity("Cfo.Cats.Domain.Entities.Administration.Location", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("Created") + .HasColumnType("datetime2"); + + b.Property("CreatedBy") + .HasMaxLength(36) + .HasColumnType("nvarchar(36)"); + + b.Property("LastModified") + .HasColumnType("datetime2"); + + b.Property("LastModifiedBy") + .HasMaxLength(36) + .HasColumnType("nvarchar(36)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("_contractId") + .HasMaxLength(12) + .HasColumnType("nvarchar(12)") + .HasColumnName("ContractId"); + + b.Property("_genderProvisionId") + .HasColumnType("int") + .HasColumnName("GenderProvisionId"); + + b.Property("_locationTypeId") + .HasColumnType("int") + .HasColumnName("LocationTypeId"); + + b.Property("_parentLocationId") + .HasColumnType("int") + .HasColumnName("ParentLocationId"); + + b.HasKey("Id"); + + b.HasIndex("_contractId"); + + b.HasIndex("_parentLocationId"); + + b.ToTable("Location", "Configuration"); + }); + + modelBuilder.Entity("Cfo.Cats.Domain.Entities.Administration.LocationMapping", b => + { + b.Property("Code") + .HasMaxLength(3) + .HasColumnType("nvarchar(3)"); + + b.Property("CodeType") + .HasMaxLength(9) + .HasColumnType("nvarchar(9)"); + + b.Property("DeliveryRegion") + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("Description") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("_locationId") + .HasColumnType("int") + .HasColumnName("LocationId"); + + b.HasKey("Code", "CodeType"); + + b.HasIndex("_locationId"); + + b.ToTable("LocationMapping", "Dms"); + }); + + modelBuilder.Entity("Cfo.Cats.Domain.Entities.Administration.Tenant", b => + { + b.Property("Id") + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("Created") + .HasColumnType("datetime2"); + + b.Property("CreatedBy") + .HasMaxLength(36) + .HasColumnType("nvarchar(36)"); + + b.Property("Description") + .IsRequired() + .HasMaxLength(150) + .HasColumnType("nvarchar(150)"); + + b.Property("LastModified") + .HasColumnType("datetime2"); + + b.Property("LastModifiedBy") + .HasMaxLength(36) + .HasColumnType("nvarchar(36)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.HasKey("Id"); + + b.ToTable("Tenant", "Configuration"); + }); + + modelBuilder.Entity("Cfo.Cats.Domain.Entities.Assessments.ParticipantAssessment", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("AssessmentJson") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("Created") + .HasColumnType("datetime2"); + + b.Property("CreatedBy") + .HasMaxLength(36) + .HasColumnType("nvarchar(36)"); + + b.Property("EditorId") + .HasColumnType("nvarchar(36)"); + + b.Property("LastModified") + .HasColumnType("datetime2"); + + b.Property("LastModifiedBy") + .HasMaxLength(36) + .HasColumnType("nvarchar(36)"); + + b.Property("OwnerId") + .HasColumnType("nvarchar(36)"); + + b.Property("ParticipantId") + .IsRequired() + .HasMaxLength(9) + .HasColumnType("nvarchar(9)"); + + b.Property("TenantId") + .HasColumnType("nvarchar(50)"); + + b.HasKey("Id"); + + b.HasIndex("EditorId"); + + b.HasIndex("OwnerId"); + + b.HasIndex("ParticipantId"); + + b.HasIndex("TenantId"); + + b.ToTable("Assessment", "Participant"); + }); + + modelBuilder.Entity("Cfo.Cats.Domain.Entities.AuditTrail", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("AffectedColumns") + .HasColumnType("nvarchar(max)"); + + b.Property("AuditType") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("DateTime") + .HasColumnType("datetime2"); + + b.Property("NewValues") + .HasColumnType("nvarchar(max)"); + + b.Property("OldValues") + .HasColumnType("nvarchar(max)"); + + b.Property("PrimaryKey") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("TableName") + .HasColumnType("nvarchar(max)"); + + b.Property("UserId") + .HasColumnType("nvarchar(36)"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AuditTrail", "Audit"); + }); + + modelBuilder.Entity("Cfo.Cats.Domain.Entities.Bios.ParticipantBio", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("BioJson") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("Created") + .HasColumnType("datetime2"); + + b.Property("CreatedBy") + .HasMaxLength(36) + .HasColumnType("nvarchar(36)"); + + b.Property("LastModified") + .HasColumnType("datetime2"); + + b.Property("LastModifiedBy") + .HasMaxLength(36) + .HasColumnType("nvarchar(36)"); + + b.Property("ParticipantId") + .IsRequired() + .HasMaxLength(9) + .HasColumnType("nvarchar(9)"); + + b.Property("Status") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("ParticipantId"); + + b.ToTable("Bio", "Participant"); + }); + + modelBuilder.Entity("Cfo.Cats.Domain.Entities.Documents.Document", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("Content") + .HasMaxLength(4000) + .HasColumnType("nvarchar(4000)"); + + b.Property("Created") + .HasColumnType("datetime2"); + + b.Property("CreatedBy") + .HasMaxLength(36) + .HasColumnType("nvarchar(36)"); + + b.Property("Description") + .HasColumnType("nvarchar(max)"); + + b.Property("DocumentType") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("EditorId") + .HasMaxLength(36) + .HasColumnType("nvarchar(36)"); + + b.Property("IsPublic") + .HasColumnType("bit"); + + b.Property("LastModified") + .HasColumnType("datetime2"); + + b.Property("LastModifiedBy") + .HasMaxLength(36) + .HasColumnType("nvarchar(36)"); + + b.Property("OwnerId") + .HasMaxLength(36) + .HasColumnType("nvarchar(36)"); + + b.Property("TenantId") + .HasColumnType("nvarchar(50)"); + + b.Property("Title") + .HasColumnType("nvarchar(max)"); + + b.Property("URL") + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.HasIndex("CreatedBy"); + + b.HasIndex("LastModifiedBy"); + + b.HasIndex("TenantId"); + + b.ToTable("Document", "Document"); + }); + + modelBuilder.Entity("Cfo.Cats.Domain.Entities.KeyValue", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("Created") + .HasColumnType("datetime2"); + + b.Property("CreatedBy") + .HasMaxLength(36) + .HasColumnType("nvarchar(36)"); + + b.Property("Description") + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("LastModified") + .HasColumnType("datetime2"); + + b.Property("LastModifiedBy") + .HasMaxLength(36) + .HasColumnType("nvarchar(36)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("Text") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("Value") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.HasKey("Id"); + + b.ToTable("KeyValue", "Configuration"); + }); + + modelBuilder.Entity("Cfo.Cats.Domain.Entities.Participants.EnrolmentEscalationQueueEntry", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("Created") + .HasColumnType("datetime2"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("EditorId") + .HasColumnType("nvarchar(36)"); + + b.Property("IsAccepted") + .HasColumnType("bit"); + + b.Property("IsCompleted") + .HasColumnType("bit"); + + b.Property("LastModified") + .HasColumnType("datetime2"); + + b.Property("LastModifiedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("OwnerId") + .HasColumnType("nvarchar(36)"); + + b.Property("ParticipantId") + .IsRequired() + .HasMaxLength(9) + .HasColumnType("nvarchar(9)"); + + b.Property("TenantId") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.HasKey("Id"); + + b.HasIndex("EditorId"); + + b.HasIndex("OwnerId"); + + b.HasIndex("ParticipantId"); + + b.HasIndex("TenantId"); + + b.ToTable("EscalationQueue", "Enrolment"); + }); + + modelBuilder.Entity("Cfo.Cats.Domain.Entities.Participants.EnrolmentPqaQueueEntry", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("Created") + .HasColumnType("datetime2"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("EditorId") + .HasColumnType("nvarchar(36)"); + + b.Property("IsAccepted") + .HasColumnType("bit"); + + b.Property("IsCompleted") + .HasColumnType("bit"); + + b.Property("LastModified") + .HasColumnType("datetime2"); + + b.Property("LastModifiedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("OwnerId") + .HasColumnType("nvarchar(36)"); + + b.Property("ParticipantId") + .IsRequired() + .HasMaxLength(9) + .HasColumnType("nvarchar(9)"); + + b.Property("TenantId") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.HasKey("Id"); + + b.HasIndex("EditorId"); + + b.HasIndex("OwnerId"); + + b.HasIndex("ParticipantId"); + + b.HasIndex("TenantId"); + + b.ToTable("PqaQueue", "Enrolment"); + }); + + modelBuilder.Entity("Cfo.Cats.Domain.Entities.Participants.EnrolmentQa1QueueEntry", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("Created") + .HasColumnType("datetime2"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("EditorId") + .HasColumnType("nvarchar(36)"); + + b.Property("IsAccepted") + .HasColumnType("bit"); + + b.Property("IsCompleted") + .HasColumnType("bit"); + + b.Property("LastModified") + .HasColumnType("datetime2"); + + b.Property("LastModifiedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("OwnerId") + .HasColumnType("nvarchar(36)"); + + b.Property("ParticipantId") + .IsRequired() + .HasMaxLength(9) + .HasColumnType("nvarchar(9)"); + + b.Property("TenantId") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.HasKey("Id"); + + b.HasIndex("EditorId"); + + b.HasIndex("OwnerId"); + + b.HasIndex("ParticipantId"); + + b.HasIndex("TenantId"); + + b.ToTable("Qa1Queue", "Enrolment"); + }); + + modelBuilder.Entity("Cfo.Cats.Domain.Entities.Participants.EnrolmentQa2QueueEntry", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("Created") + .HasColumnType("datetime2"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("EditorId") + .HasColumnType("nvarchar(36)"); + + b.Property("IsAccepted") + .HasColumnType("bit"); + + b.Property("IsCompleted") + .HasColumnType("bit"); + + b.Property("LastModified") + .HasColumnType("datetime2"); + + b.Property("LastModifiedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("OwnerId") + .HasColumnType("nvarchar(36)"); + + b.Property("ParticipantId") + .IsRequired() + .HasMaxLength(9) + .HasColumnType("nvarchar(9)"); + + b.Property("TenantId") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.HasKey("Id"); + + b.HasIndex("EditorId"); + + b.HasIndex("OwnerId"); + + b.HasIndex("ParticipantId"); + + b.HasIndex("TenantId"); + + b.ToTable("Qa2Queue", "Enrolment"); + }); + + modelBuilder.Entity("Cfo.Cats.Domain.Entities.Participants.Participant", b => + { + b.Property("Id") + .HasMaxLength(9) + .HasColumnType("nvarchar(9)"); + + b.Property("ConsentStatus") + .HasColumnType("int"); + + b.Property("Created") + .HasColumnType("datetime2"); + + b.Property("CreatedBy") + .HasMaxLength(36) + .HasColumnType("nvarchar(36)"); + + b.Property("DateOfBirth") + .IsRequired() + .HasColumnType("date"); + + b.Property("EditorId") + .HasMaxLength(36) + .HasColumnType("nvarchar(36)"); + + b.Property("EnrolmentLocationJustification") + .HasColumnType("nvarchar(max)"); + + b.Property("EnrolmentStatus") + .HasColumnType("int"); + + b.Property("FirstName") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("LastModified") + .HasColumnType("datetime2"); + + b.Property("LastModifiedBy") + .HasMaxLength(36) + .HasColumnType("nvarchar(36)"); + + b.Property("LastName") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("MiddleName") + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("OwnerId") + .HasMaxLength(36) + .HasColumnType("nvarchar(36)"); + + b.Property("ReferralComments") + .HasColumnType("nvarchar(max)"); + + b.Property("ReferralSource") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("_currentLocationId") + .HasColumnType("int") + .HasColumnName("CurrentLocationId"); + + b.Property("_enrolmentLocationId") + .HasColumnType("int") + .HasColumnName("EnrolmentLocationId"); + + b.HasKey("Id"); + + b.HasIndex("EditorId"); + + b.HasIndex("OwnerId"); + + b.HasIndex("_currentLocationId"); + + b.HasIndex("_enrolmentLocationId"); + + b.ToTable("Participant", "Participant"); + }); + + modelBuilder.Entity("Cfo.Cats.Domain.Entities.Participants.ParticipantEnrolmentHistory", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("Created") + .HasColumnType("datetime2"); + + b.Property("CreatedBy") + .HasMaxLength(36) + .HasColumnType("nvarchar(36)"); + + b.Property("EnrolmentStatus") + .HasColumnType("int"); + + b.Property("LastModified") + .HasColumnType("datetime2"); + + b.Property("LastModifiedBy") + .HasMaxLength(36) + .HasColumnType("nvarchar(36)"); + + b.Property("ParticipantId") + .IsRequired() + .HasMaxLength(9) + .HasColumnType("nvarchar(9)"); + + b.HasKey("Id"); + + b.HasIndex("ParticipantId"); + + b.ToTable("EnrolmentHistory", "Participant"); + }); + + modelBuilder.Entity("Cfo.Cats.Domain.Entities.Participants.Risk", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("ActivityRecommendations") + .HasColumnType("nvarchar(max)"); + + b.Property("ActivityRecommendationsReceived") + .HasColumnType("datetime2"); + + b.Property("ActivityRestrictions") + .HasColumnType("nvarchar(max)"); + + b.Property("ActivityRestrictionsReceived") + .HasColumnType("datetime2"); + + b.Property("AdditionalInformation") + .HasColumnType("nvarchar(max)"); + + b.Property("Created") + .HasColumnType("datetime2"); + + b.Property("CreatedBy") + .HasMaxLength(36) + .HasColumnType("nvarchar(36)"); + + b.Property("DeclarationSigned") + .HasColumnType("bit"); + + b.Property("IsRelevantToCommunity") + .HasColumnType("bit"); + + b.Property("IsRelevantToCustody") + .HasColumnType("bit"); + + b.Property("IsSubjectToSHPO") + .HasColumnType("int"); + + b.Property("LastModified") + .HasColumnType("datetime2"); + + b.Property("LastModifiedBy") + .HasMaxLength(36) + .HasColumnType("nvarchar(36)"); + + b.Property("LicenseConditions") + .HasColumnType("nvarchar(max)"); + + b.Property("LicenseEnd") + .HasColumnType("datetime2"); + + b.Property("MappaCategory") + .HasColumnType("int"); + + b.Property("MappaLevel") + .HasColumnType("int"); + + b.Property("NSDCase") + .HasColumnType("int"); + + b.Property("PSFRestrictions") + .HasColumnType("nvarchar(max)"); + + b.Property("PSFRestrictionsReceived") + .HasColumnType("datetime2"); + + b.Property("ParticipantId") + .IsRequired() + .HasColumnType("nvarchar(9)"); + + b.Property("ReferredOn") + .HasColumnType("datetime2"); + + b.Property("ReferrerEmail") + .HasColumnType("nvarchar(max)"); + + b.Property("ReferrerName") + .HasColumnType("nvarchar(max)"); + + b.Property("ReviewJustification") + .HasColumnType("nvarchar(max)"); + + b.Property("ReviewReason") + .HasColumnType("int"); + + b.Property("RiskToChildrenInCommunity") + .HasColumnType("int"); + + b.Property("RiskToChildrenInCustody") + .HasColumnType("int"); + + b.Property("RiskToKnownAdultInCommunity") + .HasColumnType("int"); + + b.Property("RiskToKnownAdultInCustody") + .HasColumnType("int"); + + b.Property("RiskToOtherPrisonersInCommunity") + .HasColumnType("int"); + + b.Property("RiskToOtherPrisonersInCustody") + .HasColumnType("int"); + + b.Property("RiskToPublicInCommunity") + .HasColumnType("int"); + + b.Property("RiskToPublicInCustody") + .HasColumnType("int"); + + b.Property("RiskToSelfInCommunity") + .HasColumnType("int"); + + b.Property("RiskToSelfInCustody") + .HasColumnType("int"); + + b.Property("RiskToStaffInCommunity") + .HasColumnType("int"); + + b.Property("RiskToStaffInCustody") + .HasColumnType("int"); + + b.Property("SpecificRisk") + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.HasIndex("ParticipantId"); + + b.ToTable("Risk", "Participant"); + }); + + modelBuilder.Entity("Cfo.Cats.Domain.Entities.Participants.Timeline", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("Created") + .HasColumnType("datetime2"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(36)"); + + b.Property("EventType") + .HasColumnType("int"); + + b.Property("LastModified") + .HasColumnType("datetime2"); + + b.Property("LastModifiedBy") + .HasMaxLength(36) + .HasColumnType("nvarchar(36)"); + + b.Property("Line1") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("Line2") + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("Line3") + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("ParticipantId") + .IsRequired() + .HasColumnType("nvarchar(9)"); + + b.HasKey("Id"); + + b.HasIndex("CreatedBy"); + + b.HasIndex("ParticipantId"); + + b.ToTable("Timeline", "Participant"); + }); + + modelBuilder.Entity("Cfo.Cats.Domain.Identity.ApplicationRole", b => + { + b.Property("Id") + .HasMaxLength(36) + .HasColumnType("nvarchar(36)"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(36) + .HasColumnType("nvarchar(36)"); + + b.Property("Description") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("NormalizedName") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("RoleRank") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName") + .IsUnique() + .HasDatabaseName("RoleNameIndex"); + + b.ToTable("Role", "Identity"); + }); + + modelBuilder.Entity("Cfo.Cats.Domain.Identity.ApplicationRoleClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("ClaimType") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("ClaimValue") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("Description") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("Group") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("RoleId") + .IsRequired() + .HasMaxLength(36) + .HasColumnType("nvarchar(36)"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("RoleClaim", "Identity"); + }); + + modelBuilder.Entity("Cfo.Cats.Domain.Identity.ApplicationUser", b => + { + b.Property("Id") + .HasMaxLength(36) + .HasColumnType("nvarchar(36)"); + + b.Property("AccessFailedCount") + .HasColumnType("int"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("nvarchar(max)"); + + b.Property("Created") + .HasColumnType("datetime2"); + + b.Property("CreatedBy") + .IsRequired() + .HasMaxLength(36) + .HasColumnType("nvarchar(36)"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("Email") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("EmailConfirmed") + .HasColumnType("bit"); + + b.Property("IsActive") + .HasColumnType("bit"); + + b.Property("IsLive") + .HasColumnType("bit"); + + b.Property("LastModified") + .HasColumnType("datetime2"); + + b.Property("LastModifiedBy") + .HasMaxLength(36) + .HasColumnType("nvarchar(36)"); + + b.Property("LockoutEnabled") + .HasColumnType("bit"); + + b.Property("LockoutEnd") + .HasColumnType("datetimeoffset"); + + b.Property("MemorableDate") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("MemorablePlace") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("NormalizedEmail") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("NormalizedUserName") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("PasswordHash") + .HasColumnType("nvarchar(max)"); + + b.Property("PhoneNumber") + .HasMaxLength(20) + .HasColumnType("nvarchar(20)"); + + b.Property("PhoneNumberConfirmed") + .HasColumnType("bit"); + + b.Property("ProfilePictureDataUrl") + .HasColumnType("text"); + + b.Property("ProviderId") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("RefreshToken") + .HasColumnType("nvarchar(max)"); + + b.Property("RefreshTokenExpiryTime") + .HasColumnType("datetime2"); + + b.Property("RequiresPasswordReset") + .HasColumnType("bit"); + + b.Property("SecurityStamp") + .HasColumnType("nvarchar(max)"); + + b.Property("SuperiorId") + .HasColumnType("nvarchar(36)"); + + b.Property("TenantId") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("TenantName") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("TwoFactorEnabled") + .HasColumnType("bit"); + + b.Property("UserName") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedEmail") + .HasDatabaseName("EmailIndex"); + + b.HasIndex("NormalizedUserName") + .IsUnique() + .HasDatabaseName("UserNameIndex") + .HasFilter("[NormalizedUserName] IS NOT NULL"); + + b.HasIndex("SuperiorId"); + + b.HasIndex("TenantId"); + + b.ToTable("User", "Identity"); + }); + + modelBuilder.Entity("Cfo.Cats.Domain.Identity.ApplicationUserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("ClaimType") + .HasColumnType("nvarchar(max)"); + + b.Property("ClaimValue") + .HasColumnType("nvarchar(max)"); + + b.Property("Description") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("UserId") + .IsRequired() + .HasMaxLength(36) + .HasColumnType("nvarchar(36)"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("UserClaim", "Identity"); + }); + + modelBuilder.Entity("Cfo.Cats.Domain.Identity.ApplicationUserRole", b => + { + b.Property("UserId") + .HasMaxLength(36) + .HasColumnType("nvarchar(36)"); + + b.Property("RoleId") + .HasMaxLength(36) + .HasColumnType("nvarchar(36)"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("UserRole", "Identity"); + }); + + modelBuilder.Entity("Cfo.Cats.Domain.Identity.ApplicationUserToken", b => + { + b.Property("UserId") + .HasMaxLength(36) + .HasColumnType("nvarchar(36)"); + + b.Property("LoginProvider") + .HasColumnType("nvarchar(450)"); + + b.Property("Name") + .HasColumnType("nvarchar(450)"); + + b.Property("Value") + .HasColumnType("nvarchar(max)"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("UserToken", "Identity"); + }); + + modelBuilder.Entity("Cfo.Cats.Domain.Identity.UserLogin", b => + { + b.Property("LoginProvider") + .HasColumnType("nvarchar(450)"); + + b.Property("ProviderKey") + .HasColumnType("nvarchar(450)"); + + b.Property("ProviderDisplayName") + .HasColumnType("nvarchar(max)"); + + b.Property("UserId") + .IsRequired() + .HasMaxLength(36) + .HasColumnType("nvarchar(36)"); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("UserLogin", "Identity"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.DataProtection.EntityFrameworkCore.DataProtectionKey", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("FriendlyName") + .HasColumnType("nvarchar(max)"); + + b.Property("Xml") + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.ToTable("DataProtectionKeys"); + }); + + modelBuilder.Entity("TenantLocation", b => + { + b.Property("LocationId") + .HasColumnType("int"); + + b.Property("TenantId") + .HasColumnType("nvarchar(50)"); + + b.HasKey("LocationId", "TenantId"); + + b.HasIndex("TenantId"); + + b.ToTable("TenantLocation", "Configuration"); + }); + + modelBuilder.Entity("Cfo.Cats.Domain.Entities.Administration.Contract", b => + { + b.HasOne("Cfo.Cats.Domain.Entities.Administration.Tenant", "Tenant") + .WithMany() + .HasForeignKey("_tenantId"); + + b.OwnsOne("Cfo.Cats.Domain.ValueObjects.Lifetime", "Lifetime", b1 => + { + b1.Property("ContractId") + .HasColumnType("nvarchar(12)"); + + b1.Property("EndDate") + .HasColumnType("datetime2") + .HasColumnName("LifetimeEnd"); + + b1.Property("StartDate") + .HasColumnType("datetime2") + .HasColumnName("LifetimeStart"); + + b1.HasKey("ContractId"); + + b1.ToTable("Contract", "Configuration"); + + b1.WithOwner() + .HasForeignKey("ContractId"); + }); + + b.Navigation("Lifetime") + .IsRequired(); + + b.Navigation("Tenant"); + }); + + modelBuilder.Entity("Cfo.Cats.Domain.Entities.Administration.Location", b => + { + b.HasOne("Cfo.Cats.Domain.Entities.Administration.Contract", "Contract") + .WithMany("Locations") + .HasForeignKey("_contractId"); + + b.HasOne("Cfo.Cats.Domain.Entities.Administration.Location", "ParentLocation") + .WithMany("ChildLocations") + .HasForeignKey("_parentLocationId") + .OnDelete(DeleteBehavior.Restrict); + + b.OwnsOne("Cfo.Cats.Domain.ValueObjects.Lifetime", "Lifetime", b1 => + { + b1.Property("LocationId") + .HasColumnType("int"); + + b1.Property("EndDate") + .HasColumnType("datetime2") + .HasColumnName("LifetimeEnd"); + + b1.Property("StartDate") + .HasColumnType("datetime2") + .HasColumnName("LifetimeStart"); + + b1.HasKey("LocationId"); + + b1.ToTable("Location", "Configuration"); + + b1.WithOwner() + .HasForeignKey("LocationId"); + }); + + b.Navigation("Contract"); + + b.Navigation("Lifetime") + .IsRequired(); + + b.Navigation("ParentLocation"); + }); + + modelBuilder.Entity("Cfo.Cats.Domain.Entities.Administration.LocationMapping", b => + { + b.HasOne("Cfo.Cats.Domain.Entities.Administration.Location", "Location") + .WithMany("LocationMappings") + .HasForeignKey("_locationId"); + + b.Navigation("Location"); + }); + + modelBuilder.Entity("Cfo.Cats.Domain.Entities.Administration.Tenant", b => + { + b.OwnsMany("Cfo.Cats.Domain.ValueObjects.TenantDomain", "Domains", b1 => + { + b1.Property("TenantId") + .HasColumnType("nvarchar(50)"); + + b1.Property("Domain") + .HasMaxLength(255) + .HasColumnType("nvarchar(255)"); + + b1.Property("Created") + .HasColumnType("datetime2"); + + b1.Property("CreatedBy") + .HasMaxLength(36) + .HasColumnType("nvarchar(36)"); + + b1.Property("LastModified") + .HasColumnType("datetime2"); + + b1.Property("LastModifiedBy") + .HasMaxLength(36) + .HasColumnType("nvarchar(36)"); + + b1.HasKey("TenantId", "Domain"); + + b1.ToTable("TenantDomain", "Configuration"); + + b1.WithOwner() + .HasForeignKey("TenantId"); + }); + + b.Navigation("Domains"); + }); + + modelBuilder.Entity("Cfo.Cats.Domain.Entities.Assessments.ParticipantAssessment", b => + { + b.HasOne("Cfo.Cats.Domain.Identity.ApplicationUser", "Editor") + .WithMany() + .HasForeignKey("EditorId"); + + b.HasOne("Cfo.Cats.Domain.Identity.ApplicationUser", "Owner") + .WithMany() + .HasForeignKey("OwnerId"); + + b.HasOne("Cfo.Cats.Domain.Entities.Participants.Participant", null) + .WithMany() + .HasForeignKey("ParticipantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Cfo.Cats.Domain.Entities.Administration.Tenant", null) + .WithMany() + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade); + + b.OwnsMany("Cfo.Cats.Domain.ValueObjects.PathwayScore", "Scores", b1 => + { + b1.Property("AssessmentId") + .HasColumnType("uniqueidentifier"); + + b1.Property("Pathway") + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b1.Property("Score") + .HasColumnType("float"); + + b1.HasKey("AssessmentId", "Pathway"); + + b1.ToTable("AssessmentPathwayScore", "Participant"); + + b1.WithOwner() + .HasForeignKey("AssessmentId"); + }); + + b.Navigation("Editor"); + + b.Navigation("Owner"); + + b.Navigation("Scores"); + }); + + modelBuilder.Entity("Cfo.Cats.Domain.Entities.AuditTrail", b => + { + b.HasOne("Cfo.Cats.Domain.Identity.ApplicationUser", "Owner") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("Owner"); + }); + + modelBuilder.Entity("Cfo.Cats.Domain.Entities.Bios.ParticipantBio", b => + { + b.HasOne("Cfo.Cats.Domain.Entities.Participants.Participant", null) + .WithMany() + .HasForeignKey("ParticipantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Cfo.Cats.Domain.Entities.Documents.Document", b => + { + b.HasOne("Cfo.Cats.Domain.Identity.ApplicationUser", "Owner") + .WithMany() + .HasForeignKey("CreatedBy") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("Cfo.Cats.Domain.Identity.ApplicationUser", "Editor") + .WithMany() + .HasForeignKey("LastModifiedBy") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("Cfo.Cats.Domain.Entities.Administration.Tenant", "Tenant") + .WithMany() + .HasForeignKey("TenantId"); + + b.Navigation("Editor"); + + b.Navigation("Owner"); + + b.Navigation("Tenant"); + }); + + modelBuilder.Entity("Cfo.Cats.Domain.Entities.Participants.EnrolmentEscalationQueueEntry", b => + { + b.HasOne("Cfo.Cats.Domain.Identity.ApplicationUser", "Editor") + .WithMany() + .HasForeignKey("EditorId"); + + b.HasOne("Cfo.Cats.Domain.Identity.ApplicationUser", "Owner") + .WithMany() + .HasForeignKey("OwnerId"); + + b.HasOne("Cfo.Cats.Domain.Entities.Participants.Participant", "Participant") + .WithMany() + .HasForeignKey("ParticipantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Cfo.Cats.Domain.Entities.Administration.Tenant", "Tenant") + .WithMany() + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.OwnsMany("Cfo.Cats.Domain.ValueObjects.Note", "Notes", b1 => + { + b1.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b1.Property("Id")); + + b1.Property("CallReference") + .HasMaxLength(20) + .HasColumnType("nvarchar(20)"); + + b1.Property("Created") + .HasColumnType("datetime2"); + + b1.Property("CreatedBy") + .HasMaxLength(36) + .HasColumnType("nvarchar(36)"); + + b1.Property("EnrolmentEscalationQueueEntryId") + .HasColumnType("uniqueidentifier"); + + b1.Property("LastModified") + .HasColumnType("datetime2"); + + b1.Property("LastModifiedBy") + .HasMaxLength(36) + .HasColumnType("nvarchar(36)"); + + b1.Property("Message") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b1.Property("TenantId") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b1.HasKey("Id"); + + b1.HasIndex("CreatedBy"); + + b1.HasIndex("EnrolmentEscalationQueueEntryId"); + + b1.HasIndex("LastModifiedBy"); + + b1.ToTable("EscalationNote", "Enrolment"); + + b1.HasOne("Cfo.Cats.Domain.Identity.ApplicationUser", "CreatedByUser") + .WithMany() + .HasForeignKey("CreatedBy"); + + b1.WithOwner() + .HasForeignKey("EnrolmentEscalationQueueEntryId"); + + b1.HasOne("Cfo.Cats.Domain.Identity.ApplicationUser", "LastModifiedByUser") + .WithMany() + .HasForeignKey("LastModifiedBy"); + + b1.Navigation("CreatedByUser"); + + b1.Navigation("LastModifiedByUser"); + }); + + b.Navigation("Editor"); + + b.Navigation("Notes"); + + b.Navigation("Owner"); + + b.Navigation("Participant"); + + b.Navigation("Tenant"); + }); + + modelBuilder.Entity("Cfo.Cats.Domain.Entities.Participants.EnrolmentPqaQueueEntry", b => + { + b.HasOne("Cfo.Cats.Domain.Identity.ApplicationUser", "Editor") + .WithMany() + .HasForeignKey("EditorId"); + + b.HasOne("Cfo.Cats.Domain.Identity.ApplicationUser", "Owner") + .WithMany() + .HasForeignKey("OwnerId"); + + b.HasOne("Cfo.Cats.Domain.Entities.Participants.Participant", "Participant") + .WithMany() + .HasForeignKey("ParticipantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Cfo.Cats.Domain.Entities.Administration.Tenant", "Tenant") + .WithMany() + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.OwnsMany("Cfo.Cats.Domain.ValueObjects.Note", "Notes", b1 => + { + b1.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b1.Property("Id")); + + b1.Property("CallReference") + .HasMaxLength(20) + .HasColumnType("nvarchar(20)"); + + b1.Property("Created") + .HasColumnType("datetime2"); + + b1.Property("CreatedBy") + .HasMaxLength(36) + .HasColumnType("nvarchar(36)"); + + b1.Property("EnrolmentPqaQueueEntryId") + .HasColumnType("uniqueidentifier"); + + b1.Property("LastModified") + .HasColumnType("datetime2"); + + b1.Property("LastModifiedBy") + .HasMaxLength(36) + .HasColumnType("nvarchar(36)"); + + b1.Property("Message") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b1.Property("TenantId") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b1.HasKey("Id"); + + b1.HasIndex("CreatedBy"); + + b1.HasIndex("EnrolmentPqaQueueEntryId"); + + b1.HasIndex("LastModifiedBy"); + + b1.ToTable("PqaQueueNote", "Enrolment"); + + b1.HasOne("Cfo.Cats.Domain.Identity.ApplicationUser", "CreatedByUser") + .WithMany() + .HasForeignKey("CreatedBy"); + + b1.WithOwner() + .HasForeignKey("EnrolmentPqaQueueEntryId"); + + b1.HasOne("Cfo.Cats.Domain.Identity.ApplicationUser", "LastModifiedByUser") + .WithMany() + .HasForeignKey("LastModifiedBy"); + + b1.Navigation("CreatedByUser"); + + b1.Navigation("LastModifiedByUser"); + }); + + b.Navigation("Editor"); + + b.Navigation("Notes"); + + b.Navigation("Owner"); + + b.Navigation("Participant"); + + b.Navigation("Tenant"); + }); + + modelBuilder.Entity("Cfo.Cats.Domain.Entities.Participants.EnrolmentQa1QueueEntry", b => + { + b.HasOne("Cfo.Cats.Domain.Identity.ApplicationUser", "Editor") + .WithMany() + .HasForeignKey("EditorId"); + + b.HasOne("Cfo.Cats.Domain.Identity.ApplicationUser", "Owner") + .WithMany() + .HasForeignKey("OwnerId"); + + b.HasOne("Cfo.Cats.Domain.Entities.Participants.Participant", "Participant") + .WithMany() + .HasForeignKey("ParticipantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Cfo.Cats.Domain.Entities.Administration.Tenant", "Tenant") + .WithMany() + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.OwnsMany("Cfo.Cats.Domain.ValueObjects.Note", "Notes", b1 => + { + b1.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b1.Property("Id")); + + b1.Property("CallReference") + .HasMaxLength(20) + .HasColumnType("nvarchar(20)"); + + b1.Property("Created") + .HasColumnType("datetime2"); + + b1.Property("CreatedBy") + .HasMaxLength(36) + .HasColumnType("nvarchar(36)"); + + b1.Property("EnrolmentQa1QueueEntryId") + .HasColumnType("uniqueidentifier"); + + b1.Property("LastModified") + .HasColumnType("datetime2"); + + b1.Property("LastModifiedBy") + .HasMaxLength(36) + .HasColumnType("nvarchar(36)"); + + b1.Property("Message") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b1.Property("TenantId") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b1.HasKey("Id"); + + b1.HasIndex("CreatedBy"); + + b1.HasIndex("EnrolmentQa1QueueEntryId"); + + b1.HasIndex("LastModifiedBy"); + + b1.ToTable("Qa1QueueNote", "Enrolment"); + + b1.HasOne("Cfo.Cats.Domain.Identity.ApplicationUser", "CreatedByUser") + .WithMany() + .HasForeignKey("CreatedBy"); + + b1.WithOwner() + .HasForeignKey("EnrolmentQa1QueueEntryId"); + + b1.HasOne("Cfo.Cats.Domain.Identity.ApplicationUser", "LastModifiedByUser") + .WithMany() + .HasForeignKey("LastModifiedBy"); + + b1.Navigation("CreatedByUser"); + + b1.Navigation("LastModifiedByUser"); + }); + + b.Navigation("Editor"); + + b.Navigation("Notes"); + + b.Navigation("Owner"); + + b.Navigation("Participant"); + + b.Navigation("Tenant"); + }); + + modelBuilder.Entity("Cfo.Cats.Domain.Entities.Participants.EnrolmentQa2QueueEntry", b => + { + b.HasOne("Cfo.Cats.Domain.Identity.ApplicationUser", "Editor") + .WithMany() + .HasForeignKey("EditorId"); + + b.HasOne("Cfo.Cats.Domain.Identity.ApplicationUser", "Owner") + .WithMany() + .HasForeignKey("OwnerId"); + + b.HasOne("Cfo.Cats.Domain.Entities.Participants.Participant", "Participant") + .WithMany() + .HasForeignKey("ParticipantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Cfo.Cats.Domain.Entities.Administration.Tenant", "Tenant") + .WithMany() + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.OwnsMany("Cfo.Cats.Domain.ValueObjects.Note", "Notes", b1 => + { + b1.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b1.Property("Id")); + + b1.Property("CallReference") + .HasMaxLength(20) + .HasColumnType("nvarchar(20)"); + + b1.Property("Created") + .HasColumnType("datetime2"); + + b1.Property("CreatedBy") + .HasMaxLength(36) + .HasColumnType("nvarchar(36)"); + + b1.Property("EnrolmentQa2QueueEntryId") + .HasColumnType("uniqueidentifier"); + + b1.Property("LastModified") + .HasColumnType("datetime2"); + + b1.Property("LastModifiedBy") + .HasMaxLength(36) + .HasColumnType("nvarchar(36)"); + + b1.Property("Message") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b1.Property("TenantId") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b1.HasKey("Id"); + + b1.HasIndex("CreatedBy"); + + b1.HasIndex("EnrolmentQa2QueueEntryId"); + + b1.HasIndex("LastModifiedBy"); + + b1.ToTable("Qa2QueueNote", "Enrolment"); + + b1.HasOne("Cfo.Cats.Domain.Identity.ApplicationUser", "CreatedByUser") + .WithMany() + .HasForeignKey("CreatedBy"); + + b1.WithOwner() + .HasForeignKey("EnrolmentQa2QueueEntryId"); + + b1.HasOne("Cfo.Cats.Domain.Identity.ApplicationUser", "LastModifiedByUser") + .WithMany() + .HasForeignKey("LastModifiedBy"); + + b1.Navigation("CreatedByUser"); + + b1.Navigation("LastModifiedByUser"); + }); + + b.Navigation("Editor"); + + b.Navigation("Notes"); + + b.Navigation("Owner"); + + b.Navigation("Participant"); + + b.Navigation("Tenant"); + }); + + modelBuilder.Entity("Cfo.Cats.Domain.Entities.Participants.Participant", b => + { + b.HasOne("Cfo.Cats.Domain.Identity.ApplicationUser", "Editor") + .WithMany() + .HasForeignKey("EditorId"); + + b.HasOne("Cfo.Cats.Domain.Identity.ApplicationUser", "Owner") + .WithMany() + .HasForeignKey("OwnerId"); + + b.HasOne("Cfo.Cats.Domain.Entities.Administration.Location", "CurrentLocation") + .WithMany() + .HasForeignKey("_currentLocationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_Participant_Location"); + + b.HasOne("Cfo.Cats.Domain.Entities.Administration.Location", "EnrolmentLocation") + .WithMany() + .HasForeignKey("_enrolmentLocationId") + .HasConstraintName("FK_Participant_EnrolmentLocation"); + + b.OwnsMany("Cfo.Cats.Domain.Entities.Participants.Consent", "Consents", b1 => + { + b1.Property("ParticipantId") + .HasColumnType("nvarchar(9)"); + + b1.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b1.Property("Id")); + + b1.Property("Created") + .HasColumnType("datetime2"); + + b1.Property("CreatedBy") + .HasMaxLength(36) + .HasColumnType("nvarchar(36)"); + + b1.Property("LastModified") + .HasColumnType("datetime2"); + + b1.Property("LastModifiedBy") + .HasMaxLength(36) + .HasColumnType("nvarchar(36)"); + + b1.Property("_documentId") + .HasColumnType("uniqueidentifier") + .HasColumnName("DocumentId"); + + b1.HasKey("ParticipantId", "Id"); + + b1.HasIndex("_documentId"); + + b1.ToTable("Consent", "Participant"); + + b1.WithOwner() + .HasForeignKey("ParticipantId"); + + b1.HasOne("Cfo.Cats.Domain.Entities.Documents.Document", "Document") + .WithMany() + .HasForeignKey("_documentId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b1.OwnsOne("Cfo.Cats.Domain.ValueObjects.Lifetime", "Lifetime", b2 => + { + b2.Property("ConsentParticipantId") + .HasColumnType("nvarchar(9)"); + + b2.Property("ConsentId") + .HasColumnType("int"); + + b2.Property("EndDate") + .HasColumnType("datetime2") + .HasColumnName("ValidTo"); + + b2.Property("StartDate") + .HasColumnType("datetime2") + .HasColumnName("ValidFrom"); + + b2.HasKey("ConsentParticipantId", "ConsentId"); + + b2.ToTable("Consent", "Participant"); + + b2.WithOwner() + .HasForeignKey("ConsentParticipantId", "ConsentId"); + }); + + b1.Navigation("Document"); + + b1.Navigation("Lifetime") + .IsRequired(); + }); + + b.OwnsMany("Cfo.Cats.Domain.ValueObjects.Note", "Notes", b1 => + { + b1.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b1.Property("Id")); + + b1.Property("CallReference") + .HasMaxLength(20) + .HasColumnType("nvarchar(20)"); + + b1.Property("Created") + .HasColumnType("datetime2"); + + b1.Property("CreatedBy") + .HasMaxLength(36) + .HasColumnType("nvarchar(36)"); + + b1.Property("LastModified") + .HasColumnType("datetime2"); + + b1.Property("LastModifiedBy") + .HasMaxLength(36) + .HasColumnType("nvarchar(36)"); + + b1.Property("Message") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b1.Property("ParticipantId") + .IsRequired() + .HasColumnType("nvarchar(9)"); + + b1.Property("TenantId") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b1.HasKey("Id"); + + b1.HasIndex("CreatedBy"); + + b1.HasIndex("LastModifiedBy"); + + b1.HasIndex("ParticipantId"); + + b1.ToTable("Note", "Participant"); + + b1.HasOne("Cfo.Cats.Domain.Identity.ApplicationUser", "CreatedByUser") + .WithMany() + .HasForeignKey("CreatedBy"); + + b1.HasOne("Cfo.Cats.Domain.Identity.ApplicationUser", "LastModifiedByUser") + .WithMany() + .HasForeignKey("LastModifiedBy"); + + b1.WithOwner() + .HasForeignKey("ParticipantId"); + + b1.Navigation("CreatedByUser"); + + b1.Navigation("LastModifiedByUser"); + }); + + b.OwnsMany("Cfo.Cats.Domain.Entities.Participants.RightToWork", "RightToWorks", b1 => + { + b1.Property("ParticipantId") + .HasColumnType("nvarchar(9)"); + + b1.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b1.Property("Id")); + + b1.Property("Created") + .HasColumnType("datetime2"); + + b1.Property("CreatedBy") + .HasMaxLength(36) + .HasColumnType("nvarchar(36)"); + + b1.Property("LastModified") + .HasColumnType("datetime2"); + + b1.Property("LastModifiedBy") + .HasMaxLength(36) + .HasColumnType("nvarchar(36)"); + + b1.Property("_documentId") + .HasColumnType("uniqueidentifier") + .HasColumnName("DocumentId"); + + b1.HasKey("ParticipantId", "Id"); + + b1.HasIndex("_documentId"); + + b1.ToTable("RightToWork", "Participant"); + + b1.WithOwner() + .HasForeignKey("ParticipantId"); + + b1.HasOne("Cfo.Cats.Domain.Entities.Documents.Document", "Document") + .WithMany() + .HasForeignKey("_documentId"); + + b1.OwnsOne("Cfo.Cats.Domain.ValueObjects.Lifetime", "Lifetime", b2 => + { + b2.Property("RightToWorkParticipantId") + .HasColumnType("nvarchar(9)"); + + b2.Property("RightToWorkId") + .HasColumnType("int"); + + b2.Property("EndDate") + .HasColumnType("datetime2") + .HasColumnName("ValidTo"); + + b2.Property("StartDate") + .HasColumnType("datetime2") + .HasColumnName("ValidFrom"); + + b2.HasKey("RightToWorkParticipantId", "RightToWorkId"); + + b2.ToTable("RightToWork", "Participant"); + + b2.WithOwner() + .HasForeignKey("RightToWorkParticipantId", "RightToWorkId"); + }); + + b1.Navigation("Document"); + + b1.Navigation("Lifetime") + .IsRequired(); + }); + + b.Navigation("Consents"); + + b.Navigation("CurrentLocation"); + + b.Navigation("Editor"); + + b.Navigation("EnrolmentLocation"); + + b.Navigation("Notes"); + + b.Navigation("Owner"); + + b.Navigation("RightToWorks"); + }); + + modelBuilder.Entity("Cfo.Cats.Domain.Entities.Participants.Risk", b => + { + b.HasOne("Cfo.Cats.Domain.Entities.Participants.Participant", null) + .WithMany() + .HasForeignKey("ParticipantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Cfo.Cats.Domain.Entities.Participants.Timeline", b => + { + b.HasOne("Cfo.Cats.Domain.Identity.ApplicationUser", "CreatedByUser") + .WithMany() + .HasForeignKey("CreatedBy") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("Cfo.Cats.Domain.Entities.Participants.Participant", null) + .WithMany() + .HasForeignKey("ParticipantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("CreatedByUser"); + }); + + modelBuilder.Entity("Cfo.Cats.Domain.Identity.ApplicationRoleClaim", b => + { + b.HasOne("Cfo.Cats.Domain.Identity.ApplicationRole", "Role") + .WithMany("RoleClaims") + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Role"); + }); + + modelBuilder.Entity("Cfo.Cats.Domain.Identity.ApplicationUser", b => + { + b.HasOne("Cfo.Cats.Domain.Identity.ApplicationUser", "Superior") + .WithMany() + .HasForeignKey("SuperiorId"); + + b.HasOne("Cfo.Cats.Domain.Entities.Administration.Tenant", "Tenant") + .WithMany() + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.OwnsMany("Cfo.Cats.Domain.ValueObjects.Note", "Notes", b1 => + { + b1.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b1.Property("Id")); + + b1.Property("CallReference") + .HasMaxLength(20) + .HasColumnType("nvarchar(20)"); + + b1.Property("Created") + .HasColumnType("datetime2"); + + b1.Property("CreatedBy") + .HasMaxLength(36) + .HasColumnType("nvarchar(36)"); + + b1.Property("LastModified") + .HasColumnType("datetime2"); + + b1.Property("LastModifiedBy") + .HasMaxLength(36) + .HasColumnType("nvarchar(36)"); + + b1.Property("Message") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("nvarchar(255)"); + + b1.Property("TenantId") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b1.Property("UserId") + .IsRequired() + .HasMaxLength(36) + .HasColumnType("nvarchar(36)"); + + b1.HasKey("Id"); + + b1.HasIndex("CreatedBy"); + + b1.HasIndex("LastModifiedBy"); + + b1.HasIndex("UserId"); + + b1.ToTable("Note", "Identity"); + + b1.HasOne("Cfo.Cats.Domain.Identity.ApplicationUser", "CreatedByUser") + .WithMany() + .HasForeignKey("CreatedBy"); + + b1.HasOne("Cfo.Cats.Domain.Identity.ApplicationUser", "LastModifiedByUser") + .WithMany() + .HasForeignKey("LastModifiedBy"); + + b1.WithOwner() + .HasForeignKey("UserId"); + + b1.Navigation("CreatedByUser"); + + b1.Navigation("LastModifiedByUser"); + }); + + b.Navigation("Notes"); + + b.Navigation("Superior"); + + b.Navigation("Tenant"); + }); + + modelBuilder.Entity("Cfo.Cats.Domain.Identity.ApplicationUserClaim", b => + { + b.HasOne("Cfo.Cats.Domain.Identity.ApplicationUser", "User") + .WithMany("UserClaims") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Cfo.Cats.Domain.Identity.ApplicationUserRole", b => + { + b.HasOne("Cfo.Cats.Domain.Identity.ApplicationRole", "Role") + .WithMany("UserRoles") + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Cfo.Cats.Domain.Identity.ApplicationUser", "User") + .WithMany("UserRoles") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Role"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Cfo.Cats.Domain.Identity.ApplicationUserToken", b => + { + b.HasOne("Cfo.Cats.Domain.Identity.ApplicationUser", "User") + .WithMany("Tokens") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Cfo.Cats.Domain.Identity.UserLogin", b => + { + b.HasOne("Cfo.Cats.Domain.Identity.ApplicationUser", "User") + .WithMany("Logins") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + }); + + modelBuilder.Entity("TenantLocation", b => + { + b.HasOne("Cfo.Cats.Domain.Entities.Administration.Location", null) + .WithMany() + .HasForeignKey("LocationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Cfo.Cats.Domain.Entities.Administration.Tenant", null) + .WithMany() + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Cfo.Cats.Domain.Entities.Administration.Contract", b => + { + b.Navigation("Locations"); + }); + + modelBuilder.Entity("Cfo.Cats.Domain.Entities.Administration.Location", b => + { + b.Navigation("ChildLocations"); + + b.Navigation("LocationMappings"); + }); + + modelBuilder.Entity("Cfo.Cats.Domain.Identity.ApplicationRole", b => + { + b.Navigation("RoleClaims"); + + b.Navigation("UserRoles"); + }); + + modelBuilder.Entity("Cfo.Cats.Domain.Identity.ApplicationUser", b => + { + b.Navigation("Logins"); + + b.Navigation("Tokens"); + + b.Navigation("UserClaims"); + + b.Navigation("UserRoles"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Migrators/Migrators.MSSQL/Migrations/20240813132251_bio.cs b/src/Migrators/Migrators.MSSQL/Migrations/20240813132251_bio.cs new file mode 100644 index 00000000..76e0cb74 --- /dev/null +++ b/src/Migrators/Migrators.MSSQL/Migrations/20240813132251_bio.cs @@ -0,0 +1,55 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Cfo.Cats.Migrators.MSSQL.Migrations +{ + /// + public partial class bio : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "Bio", + schema: "Participant", + columns: table => new + { + Id = table.Column(type: "uniqueidentifier", nullable: false), + ParticipantId = table.Column(type: "nvarchar(9)", maxLength: 9, nullable: false), + BioJson = table.Column(type: "nvarchar(max)", nullable: false), + Status = table.Column(type: "int", nullable: false), + Created = table.Column(type: "datetime2", nullable: true), + CreatedBy = table.Column(type: "nvarchar(36)", maxLength: 36, nullable: true), + LastModified = table.Column(type: "datetime2", nullable: true), + LastModifiedBy = table.Column(type: "nvarchar(36)", maxLength: 36, nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_Bio", x => x.Id); + table.ForeignKey( + name: "FK_Bio_Participant_ParticipantId", + column: x => x.ParticipantId, + principalSchema: "Participant", + principalTable: "Participant", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateIndex( + name: "IX_Bio_ParticipantId", + schema: "Participant", + table: "Bio", + column: "ParticipantId"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "Bio", + schema: "Participant"); + } + } +} diff --git a/src/Migrators/Migrators.MSSQL/Migrations/ApplicationDbContextModelSnapshot.cs b/src/Migrators/Migrators.MSSQL/Migrations/ApplicationDbContextModelSnapshot.cs index 29c936b9..7c245783 100644 --- a/src/Migrators/Migrators.MSSQL/Migrations/ApplicationDbContextModelSnapshot.cs +++ b/src/Migrators/Migrators.MSSQL/Migrations/ApplicationDbContextModelSnapshot.cs @@ -275,6 +275,45 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.ToTable("AuditTrail", "Audit"); }); + modelBuilder.Entity("Cfo.Cats.Domain.Entities.Bios.ParticipantBio", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("BioJson") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("Created") + .HasColumnType("datetime2"); + + b.Property("CreatedBy") + .HasMaxLength(36) + .HasColumnType("nvarchar(36)"); + + b.Property("LastModified") + .HasColumnType("datetime2"); + + b.Property("LastModifiedBy") + .HasMaxLength(36) + .HasColumnType("nvarchar(36)"); + + b.Property("ParticipantId") + .IsRequired() + .HasMaxLength(9) + .HasColumnType("nvarchar(9)"); + + b.Property("Status") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("ParticipantId"); + + b.ToTable("Bio", "Participant"); + }); + modelBuilder.Entity("Cfo.Cats.Domain.Entities.Documents.Document", b => { b.Property("Id") @@ -1439,6 +1478,15 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Navigation("Owner"); }); + modelBuilder.Entity("Cfo.Cats.Domain.Entities.Bios.ParticipantBio", b => + { + b.HasOne("Cfo.Cats.Domain.Entities.Participants.Participant", null) + .WithMany() + .HasForeignKey("ParticipantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + modelBuilder.Entity("Cfo.Cats.Domain.Entities.Documents.Document", b => { b.HasOne("Cfo.Cats.Domain.Identity.ApplicationUser", "Owner") diff --git a/src/Server.UI/Pages/Bio/Bio.razor b/src/Server.UI/Pages/Bio/Bio.razor new file mode 100644 index 00000000..5f4ed0d1 --- /dev/null +++ b/src/Server.UI/Pages/Bio/Bio.razor @@ -0,0 +1,115 @@ +@using Cfo.Cats.Application.Features.Bios.Commands +@using Cfo.Cats.Application.Features.Bios.DTOs +@using Cfo.Cats.Application.Features.Bios.Queries +@using Cfo.Cats.Server.UI.Components.Stepper + +@inherits CatsComponentBase + +@page "/pages/participants/{Upci}/bio/{BioId:guid}" + +@if (_model != null) +{ +
+ + + + @*This top-level form is responsible for submission *@ + + @foreach (var pathway in _model.Pathways) + { + + } + + + + +} + +@code { + + private bool _showPrevious = false; + private ElementReference topOfPageElement; + + [Parameter] + public string Upci { get; set; } = string.Empty; + + [Parameter] + public Guid BioId { get; set; } = Guid.Empty; + + [Parameter] + public Cfo.Cats.Application.Features.Bios.DTOs.Bio? Model { get; set; } + + private Cfo.Cats.Application.Features.Bios.DTOs.Bio? _model; + + private CatsMudStepper Stepper { get; set; } = new(); + + private int TabsLength => Stepper.Steps.Count(); + + //These should be local to result step component in future. + private bool Processing { get; set; } + private bool SubmissionSuccess { get; set; } = false; + + protected override async Task OnInitializedAsync() + { + _model ??= Model; + + if (_model is null) + { + var response = await GetNewMediator().Send(new GetBio.Query() + { + BioId = BioId, + ParticipantId = Upci + }); + + if (response.Succeeded) + { + _model = response.Data!; + } + } + } + + private async Task OnStepChange(int step) + { + Processing = true; + await GetNewMediator().Send(new SaveBio.Command() + { + Bio = _model! + }); + + // Do not show the previous step on the first or last steps. + _showPrevious = Stepper.GetActiveIndex() > 0 && Stepper.IsResultStep == false; + await topOfPageElement.FocusAsync(); + if (step == Stepper.Steps.Count()) + { + await SubmitBio(); + } + + Processing = false; + + + } + + private async Task SubmitBio() + { + if (Stepper.IsAllStepsCompleted()) + { + var validator = new BioValidator(); + var result = await validator.ValidateAsync(_model!); + + if (result.IsValid) + { + Processing = true; + var response = await GetNewMediator().Send(new SaveBio.Command() + { + Bio = _model!, + Submit = true + }); + Processing = false; + SubmissionSuccess = response.Succeeded; + } + + } + } +} diff --git a/src/Server.UI/Pages/Bio/BioComponents/BioCheckbox.razor b/src/Server.UI/Pages/Bio/BioComponents/BioCheckbox.razor new file mode 100644 index 00000000..2f3dbbea --- /dev/null +++ b/src/Server.UI/Pages/Bio/BioComponents/BioCheckbox.razor @@ -0,0 +1,21 @@ + + + +@code { + + public string Statement = string.Empty; + public bool Toggle; + + public BioCheckbox() + { } + + public BioCheckbox(string statement) : this() + { + Statement = statement; + } + + public BioCheckbox(string statement, bool toggle) : this(statement) + { + Toggle = toggle; + } +} diff --git a/src/Server.UI/Pages/Bio/BioComponents/BioQuestion.razor b/src/Server.UI/Pages/Bio/BioComponents/BioQuestion.razor new file mode 100644 index 00000000..a2e3bc45 --- /dev/null +++ b/src/Server.UI/Pages/Bio/BioComponents/BioQuestion.razor @@ -0,0 +1,21 @@ + + + + @Question + + @if (HelperText is not null) + { + + @HelperText + + } + + +@code { + + [Parameter, EditorRequired] + public required string Question { get; init; } = string.Empty; + + [Parameter] + public string? HelperText { get; init; } +} diff --git a/src/Server.UI/Pages/Bio/BioPathway.razor b/src/Server.UI/Pages/Bio/BioPathway.razor new file mode 100644 index 00000000..c7dd9ba3 --- /dev/null +++ b/src/Server.UI/Pages/Bio/BioPathway.razor @@ -0,0 +1,87 @@ +@using Cfo.Cats.Application.Features.Bios.DTOs +@using Cfo.Cats.Server.UI.Components.Stepper + + + + +@if (Model != null) +{ + + + + + + + + @foreach (var question in Model.Questions()) + { + + + + @if (validateCalled && question.IsValid() == false) + { + + You must select an option! + + } + + + + @if (question is SingleChoiceQuestion atq) + { + + @foreach (var item in atq.Options) + { + + } + + + } + + + } + + + + + +} + +@code { + + private MudForm form = new(); + + private bool validateCalled = false; + + + [Parameter] + public PathwayBase? Model { get; set; } + + private async Task Validate() + { + validateCalled = true; + BioPathwayValidator validator = new BioPathwayValidator(); + var result = await validator.ValidateAsync(Model!); + return result.IsValid; + } + + protected override async Task OnAfterRenderAsync(bool firstRender) + { + if (firstRender) + { + await JS.InvokeVoidAsync("removeInlineStyle", ".two-columns"); + } + } +} diff --git a/src/Server.UI/Pages/Participants/Components/CaseBio.razor b/src/Server.UI/Pages/Participants/Components/CaseBio.razor new file mode 100644 index 00000000..dd523aa9 --- /dev/null +++ b/src/Server.UI/Pages/Participants/Components/CaseBio.razor @@ -0,0 +1,121 @@ +@using Cfo.Cats.Application.Features.Bios.DTOs +@using Cfo.Cats.Application.Features.Bios.Queries +@using Cfo.Cats.Domain.Common.Enums + +@inherits CatsComponentBase + + + +@if (_notFound) +{ + + No assessment found. + +} + + +@if (_model is not null) +{ + + + @foreach (var pathway in _model.Pathways) + { + + +
+ + @pathway.Title +
+
+ + + + @foreach (var question in pathway.Questions()) + { + + + + + + + @if (question is SingleChoiceQuestion atq) + { + + @foreach (var item in atq.Options) + { + + } + + + } + + + } + + +
+ } + +
+} + + + +@code { + + private Bio? _model; + private bool _notFound = false; + + [Parameter] + [EditorRequired] + public string ParticipantId { get; set; } = default!; + + protected override async Task OnInitializedAsync() + { + if (_model is not null) + { + return; + } + + try + { + var result = await GetNewMediator().Send(new GetBio.Query() + { + ParticipantId = ParticipantId + }); + + if (result.Succeeded) + { + _model = result.Data; + } + + } + finally + { + _notFound = _model is null; + } + + } + + protected override async Task OnAfterRenderAsync(bool firstRender) + { + await JS.InvokeVoidAsync("removeInlineStyle", ".two-columns"); + } + +} \ No newline at end of file diff --git a/src/Server.UI/Pages/Participants/Components/CaseSummary.razor b/src/Server.UI/Pages/Participants/Components/CaseSummary.razor index aa0717cd..6a48efa7 100644 --- a/src/Server.UI/Pages/Participants/Components/CaseSummary.razor +++ b/src/Server.UI/Pages/Participants/Components/CaseSummary.razor @@ -129,4 +129,76 @@ + + + + + Bio Information + + + + + @if (_bio is null) + { + No Bio has been created. + } + else + { +
+
+
+
+ Date Created +
+
+ @_bio.BioDate!.Value.ToString("dd/MM/yyyy") +
+
+
+
+ Created By +
+
+ @UserService.DataSource.First(u => u.Id == _bio.BioCreator).DisplayName +
+
+
+
+ Status +
+
+ @_bio.BioStatus!.Name.Humanize() +
+
+
+ + +
+ + } +
+ + + @if (CanBeginBio()) + { + + + + + } + @if (CanContinueBio()) + { + + + + } + @if (CanSkipBio()) + { + + + + } + +
+
\ No newline at end of file diff --git a/src/Server.UI/Pages/Participants/Components/CaseSummary.razor.cs b/src/Server.UI/Pages/Participants/Components/CaseSummary.razor.cs index 08f17ea0..2214a7a0 100644 --- a/src/Server.UI/Pages/Participants/Components/CaseSummary.razor.cs +++ b/src/Server.UI/Pages/Participants/Components/CaseSummary.razor.cs @@ -1,16 +1,18 @@ using Cfo.Cats.Application.Common.Interfaces.Identity; using Cfo.Cats.Application.Features.Assessments.Commands; +using Cfo.Cats.Application.Features.Bios.Commands; using Cfo.Cats.Application.Features.Participants.Commands; using Cfo.Cats.Application.Features.Participants.DTOs; using Cfo.Cats.Domain.Common.Enums; using Cfo.Cats.Server.UI.Pages.Risk; + namespace Cfo.Cats.Server.UI.Pages.Participants.Components; public partial class CaseSummary { private AssessmentSummaryDto? _latestAssessment; - + private BioSummaryDto? _bio; [Inject] private IUserService UserService { get; set; } = default!; @@ -24,6 +26,7 @@ protected override void OnParametersSet() ? null : ParticipantSummaryDto.Assessments.OrderByDescending(a => a.AssessmentDate) .First(); + _bio = ParticipantSummaryDto.BioSummary; } public async Task BeginAssessment() @@ -150,4 +153,69 @@ public async Task ExpandRiskInformation() var result = await dialog.Result; } + public async Task BeginBio() + { + var command = new BeginBio.Command + { + ParticipantId = ParticipantSummaryDto.Id + }; + var result = await GetNewMediator().Send(command); + + if (result.Succeeded) + { + Navigation.NavigateTo($"/pages/participants/{ParticipantSummaryDto.Id}/bio/{result.Data}"); + } + else + { + Snackbar.Add($"{result.ErrorMessage}", Severity.Error); + } + } + public async Task SkipBioForNow() + { + var command = new SkipBioForNow.Command() + { + ParticipantId = ParticipantSummaryDto.Id + }; + + var result = await GetNewMediator().Send(command); + if (result.Succeeded) + { + Snackbar.Add($"Bio skipped for now, you can add bio information at any time by clicking Continue Bio button", Severity.Info, + config => { + config.ShowTransitionDuration = 500; + config.HideTransitionDuration = 500; + config.ShowCloseIcon = false; + }); + Navigation.Refresh(true); + } + else + { + Snackbar.Add($"Skipping bio failed", Severity.Error); + } + } + public void ContinueBio() + { + Navigation.NavigateTo($"/pages/participants/{ParticipantSummaryDto.Id}/bio/{_bio!.BioId}"); + } + + /// + /// If true, indicates we are creating Bio. + /// + private bool CanBeginBio() => _bio == null; + + /// + /// If true indicates we have a Bio that is continuable + /// (i.e. Id is not null or do we need a status (Complete or Incomplete etc.)) + /// + /// + private bool CanContinueBio() => _bio != null; + + /// + /// If true, indicates that either the bio doesn't exist OR No step is completed yet + /// + private bool CanSkipBio() + { + return _bio is null || _bio!.BioStatus == BioStatus.NotStarted; + } + } diff --git a/src/Server.UI/Pages/Participants/Participant.razor b/src/Server.UI/Pages/Participants/Participant.razor index 63612bf5..bb229c4b 100644 --- a/src/Server.UI/Pages/Participants/Participant.razor +++ b/src/Server.UI/Pages/Participants/Participant.razor @@ -102,6 +102,9 @@ + + +