Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Work on showing the assessment in the participant dashboard. #57

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

public interface ICacheInvalidatorRequest<TResponse> : IRequest<TResponse>
{
string CacheKey { get; }
string[] CacheKeys { get; }

CancellationTokenSource? SharedExpiryTokenSource { get; }
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ public class Command : ICacheInvalidatorRequest<Result<Guid>>
public required string ParticipantId { get; set; }

//TODO: this could be done at a per participant level
public string CacheKey => AssessmentsCacheKey.GetAllCacheKey;
public string[] CacheKeys => [ AssessmentsCacheKey.GetAllCacheKey ];
public CancellationTokenSource? SharedExpiryTokenSource
=> AssessmentsCacheKey.SharedExpiryTokenSource();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ public static class SaveAssessment
public class Command : ICacheInvalidatorRequest<Result>
{
//TODO: cache individually
public string CacheKey => AssessmentsCacheKey.GetAllCacheKey;
public string[] CacheKeys => [ AssessmentsCacheKey.GetAllCacheKey ];
public CancellationTokenSource? SharedExpiryTokenSource => AssessmentsCacheKey.SharedExpiryTokenSource();

public bool Submit { get; set; } = false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ public static CancellationTokenSource SharedExpiryTokenSource()
return tokenSource;
}

public static string GetCacheKey(string parameters)
public static string GetCandidateCacheKey(string parameters)
{
return $"EnrolmentsWithPaginationQuery,{parameters}";
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ public class CandidateSearchQuery : ICacheableRequest<IEnumerable<CandidateDto>>
public required DateTime? DateOfBirth { get; set; }
public required UserProfile CurrentUser { get; set; }

public string CacheKey => CandidatesCacheKey.GetCacheKey($"{this}");
public string CacheKey => CandidatesCacheKey.GetCandidateCacheKey($"{this}");

public MemoryCacheEntryOptions? Options => CandidatesCacheKey.MemoryCacheEntryOptions;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ namespace Cfo.Cats.Application.Features.Documents.Commands.Upload;
[RequestAuthorize(Policy = PolicyNames.AllowDocumentUpload)]
public class UploadDocumentCommand : ICacheInvalidatorRequest<Result<Guid>>
{
public string CacheKey { get; } = string.Empty;
public string[] CacheKeys { get; } = [];

public CancellationTokenSource? SharedExpiryTokenSource
=> DocumentCacheKey.SharedExpiryTokenSource();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ public class AddEditKeyValueCommand : ICacheInvalidatorRequest<Result<int>>
[Description("Description")] public string? Description { get; set; }

public TrackingState TrackingState { get; set; } = TrackingState.Unchanged;
public string CacheKey => KeyValueCacheKey.GetAllCacheKey;
public string[] CacheKeys => [KeyValueCacheKey.GetAllCacheKey];

public CancellationTokenSource? SharedExpiryTokenSource => KeyValueCacheKey.SharedExpiryTokenSource();

private class Mapping : Profile
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,6 @@ public DeleteKeyValueCommand(int[] id)
}

public int[] Id { get; }
public string CacheKey => KeyValueCacheKey.GetAllCacheKey;
public string[] CacheKeys => [ KeyValueCacheKey.GetAllCacheKey ];
public CancellationTokenSource? SharedExpiryTokenSource => KeyValueCacheKey.SharedExpiryTokenSource();
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,6 @@ public class ImportKeyValuesCommand(string fileName, byte[] data) : ICacheInvali
{
public string FileName { get; set; } = fileName;
public byte[] Data { get; set; } = data;
public string CacheKey => KeyValueCacheKey.GetAllCacheKey;
public string[] CacheKeys => [ KeyValueCacheKey.GetAllCacheKey ];
public CancellationTokenSource? SharedExpiryTokenSource => KeyValueCacheKey.SharedExpiryTokenSource();
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ static ParticipantCacheKey()
);

public static string GetCacheKey(string parameters) => $"ParticipantCacheKey,{parameters}";
public static string GetSummaryCacheKey(string id) => $"ParticipantSummary,{id}";

public static CancellationTokenSource SharedExpiryTokenSource()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ public class Command: ICacheInvalidatorRequest<Result<string>>

public UserProfile? CurrentUser { get; set; }

public string CacheKey => ParticipantCacheKey.GetCacheKey($"{this}");
public string[] CacheKeys => [ ParticipantCacheKey.GetCacheKey($"{this}") ];

public CancellationTokenSource? SharedExpiryTokenSource
=> ParticipantCacheKey.SharedExpiryTokenSource();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ public class Command(string identifier, LocationDto currentLocation, LocationDto
[Description("Enrol at an alternative location enrolment")]
public bool EnrolFromOtherLocation { get; set; } = enrolmentLocation.Id != currentLocation.Id;

public string CacheKey => ParticipantCacheKey.GetCacheKey($"Id:{this.Identifier}");
public string[] CacheKeys => [ParticipantCacheKey.GetCacheKey($"Id:{this.Identifier}")];
public CancellationTokenSource? SharedExpiryTokenSource
=> ParticipantCacheKey.SharedExpiryTokenSource();
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
using Cfo.Cats.Application.Common.Security;
using Cfo.Cats.Application.Features.Candidates.Caching;
using Cfo.Cats.Application.Features.Participants.Caching;
using Cfo.Cats.Application.SecurityConstants;

namespace Cfo.Cats.Application.Features.Documents.Commands.Transistion;
namespace Cfo.Cats.Application.Features.Participants.Commands.Transistion;

public static class SubmitToProviderQa
{
Expand All @@ -11,7 +12,10 @@ public class Command : ICacheInvalidatorRequest<Result>
{
public required string ParticipantId { get; set; }

public string CacheKey => CandidatesCacheKey.GetCacheKey(ParticipantId);
public string[] CacheKeys => [
ParticipantCacheKey.GetCacheKey(ParticipantId),
ParticipantCacheKey.GetSummaryCacheKey(ParticipantId)
];

public CancellationTokenSource? SharedExpiryTokenSource => CandidatesCacheKey.SharedExpiryTokenSource();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

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

[Description("Participants")]
public class ParticipantDto
{
[Description("CATS Identifier")]
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
using Cfo.Cats.Domain.Entities.Assessments;
using Cfo.Cats.Domain.Entities.Participants;

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

/// <summary>
/// Represents the initial dashboard
/// </summary>
public class ParticipantSummaryDto
{

public required string Id { get; set; }

/// <summary>
/// The full name of the participant
/// </summary>
public required string ParticipantName { get; set; }

/// <summary>
/// The current location of the participant
/// </summary>
public required string Location { get; set; }

/// <summary>
/// The participant's date of birth
/// </summary>
public required DateOnly DateOfBirth { get; set; }

/// <summary>
/// The current enrolment status of the participant
/// </summary>
public EnrolmentStatus EnrolmentStatus { get; set; } = EnrolmentStatus.PendingStatus;

/// <summary>
/// The person who "owns" this participant's case. Usually the support worker.
/// </summary>
public required string OwnerName { get; set; }

public AssessmentSummaryDto[] Assessments { get; set; } = [];


private class Mapping : Profile
{
public Mapping()
{
CreateMap<Participant, ParticipantSummaryDto>(MemberList.None)
.ForMember(target => target.Id, options => options.MapFrom(source => source.Id))
.ForMember(target => target.Location, options => options.MapFrom(source => source.CurrentLocation.Name))
.ForMember(target => target.OwnerName, options => options.MapFrom(source => source.Owner!.DisplayName));

CreateMap<ParticipantAssessment, AssessmentSummaryDto>()
.ForMember(target => target.AssessmentId, options => options.MapFrom(source => source.Id))
.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)));
}
}


}

public class AssessmentSummaryDto
{
/// <summary>
/// The id of the latest assessment
/// </summary>
public Guid? AssessmentId { get; set; }


/// <summary>
/// If there are any assessments these are the dates they latest one was created.
/// </summary>
public DateTime? AssessmentDate { get; set; }

/// <summary>
/// Who created the most recent assessment (if available)
/// </summary>
public string? AssessmentCreator { get; set; }

/// <summary>
/// Has the latest assessment been scored? This can be a surrogate for
/// submitted and should make the assessment read-only
/// </summary>
public bool? AssessmentScored { get; set; }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
using Cfo.Cats.Application.Common.Security;
using Cfo.Cats.Application.Features.Participants.Caching;
using Cfo.Cats.Application.Features.Participants.DTOs;
using Cfo.Cats.Application.SecurityConstants;

namespace Cfo.Cats.Application.Features.Participants.Queries;

public static class GetParticipantSummary
{
[RequestAuthorize(Policy = PolicyNames.AllowCandidateSearch)]
public class Query : ICacheableRequest<Result<ParticipantSummaryDto>>
{
public required string ParticipantId { get; set; }
public required UserProfile CurrentUser { get; set; }

public string CacheKey => ParticipantCacheKey.GetCacheKey($"ParticipantSummary,{ParticipantId}");
public MemoryCacheEntryOptions? Options => ParticipantCacheKey.MemoryCacheEntryOptions;

}

public class Handler(IApplicationDbContext context, IMapper mapper) : IRequestHandler<Query, Result<ParticipantSummaryDto>>
{

public async Task<Result<ParticipantSummaryDto>> Handle(Query request, CancellationToken cancellationToken)
{
var query = from c in context.Participants
where c.Id == request.ParticipantId
select c;

var summary = await query.ProjectTo<ParticipantSummaryDto>(mapper.ConfigurationProvider)
.FirstOrDefaultAsync(cancellationToken);

if (summary == null)
{
throw new NotFoundException(nameof(ParticipantSummaryDto), request.ParticipantId);
}

summary.Assessments = await context.ParticipantAssessments
.Where(pa => pa.ParticipantId == request.ParticipantId)
.ProjectTo<AssessmentSummaryDto>(mapper.ConfigurationProvider)
.ToArrayAsync(cancellationToken);

return await Result<ParticipantSummaryDto>.SuccessAsync(summary);

}
}

public class Validator : AbstractValidator<Query>
{
public Validator()
{
RuleFor(x => x.ParticipantId)
.MinimumLength(9)
.MaximumLength(9)
.WithMessage("Invalid participant id");
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ public class AddEditTenantCommand : ICacheInvalidatorRequest<Result<string>>
[Description("Description")]
public string? Description { get; set; }

public string CacheKey => TenantCacheKey.GetAllCacheKey;
public string[] CacheKeys => [TenantCacheKey.GetAllCacheKey];
public CancellationTokenSource? SharedExpiryTokenSource =>
TenantCacheKey.SharedExpiryTokenSource();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ public DeleteTenantCommand(string[] id)
}

public string[] Id { get; }
public string CacheKey => TenantCacheKey.GetAllCacheKey;
public string[] CacheKeys => [TenantCacheKey.GetAllCacheKey];
public CancellationTokenSource? SharedExpiryTokenSource =>
TenantCacheKey.SharedExpiryTokenSource();
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ public class Command : ICacheInvalidatorRequest<Result<string>>
{
public required string Id { get; set; }
public required string Name { get; set; }
public string CacheKey => TenantCacheKey.GetAllCacheKey;
public string[] CacheKeys => [TenantCacheKey.GetAllCacheKey];
public CancellationTokenSource? SharedExpiryTokenSource =>
TenantCacheKey.SharedExpiryTokenSource();

Expand Down
5 changes: 3 additions & 2 deletions src/Application/Pipeline/CacheInvalidationBehaviour.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,10 @@ CancellationToken cancellationToken
{
logger.LogTrace("{Name} cache expire with {@Request}", nameof(request), request);
var response = await next().ConfigureAwait(false);
if (!string.IsNullOrEmpty(request.CacheKey))

foreach (var key in request.CacheKeys)
{
cache.Remove(request.CacheKey);
cache.Remove(key);
}

request.SharedExpiryTokenSource?.Cancel();
Expand Down
9 changes: 9 additions & 0 deletions src/Domain/Common/Enums/EnrolmentStatus.cs
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,17 @@ public SubmittedToProvider()

protected override EnrolmentStatus[] GetAllowedTransitions()
=> [AbandonedStatus, PendingStatus];

public override bool StatusSupportsReassessment() => false;

}

private sealed class SubmittedToAuthority : EnrolmentStatus
{
public SubmittedToAuthority(): base(nameof(SubmittedToAuthority), 2) { }

public override bool StatusSupportsReassessment() => false;

protected override EnrolmentStatus[] GetAllowedTransitions() =>
[ SubmittedToProviderStatus, ApprovedStatus ];
}
Expand All @@ -72,4 +77,8 @@ protected override EnrolmentStatus[] GetAllowedTransitions() =>

}

/// <summary>
/// Indicates that a participant at this enrolment stage is allowed to have a new assessment created
/// </summary>
public virtual bool StatusSupportsReassessment() => true;
}
3 changes: 2 additions & 1 deletion src/Infrastructure/Constants/ConstantString.cs
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,8 @@ public static string Localize(string key)
public static string ArchiveConfirmationTitle => Localize("Archive Confirmation");
public static string LogoutConfirmationTitle => Localize("Logout Confirmation");

public static string ResumeEnrolment => Localize("Continue Enrolment");
public static string NewEnrolment => Localize("New Enrolment");
public static string ResumeEnrolment => Localize("Resume Enrolment");

public static string LogoutConfirmation =>
Localize("You are attempting to log out of application. Do you really want to log out?");
Expand Down
2 changes: 1 addition & 1 deletion src/Server.UI/Pages/Assessment/Assessment.razor
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
{
<CatsMudStepper @ref="@Stepper" Color="Color.Primary" Variant="Variant.Filled"
MobileView="false" HeaderBadgeView="HeaderBadgeView.All" HeaderTextView="HeaderTextView.All"
ActiveStepChanged="@OnStepChange" ShowSkipButton="false">
ActiveStepChanged="@OnStepChange" ShowSkipButton="false" >
<ChildContent>
<MudForm Model="@_model">
@*This top-level form is responsible for submission *@
Expand Down
Loading
Loading