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

CFODEV-506: CATS-DMS Integration (candidate search) #25

Merged
merged 17 commits into from
Jun 27, 2024
Merged
Show file tree
Hide file tree
Changes from 14 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
7 changes: 7 additions & 0 deletions NuGet.config
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<packageSources>
<add key="nuget.org" value="https://api.nuget.org/v3/index.json" />
<add key="co-financing.org" value="https://packages.co-financing.org/nuget" />
</packageSources>
</configuration>
7 changes: 4 additions & 3 deletions cats.sln
Copy link
Contributor

Choose a reason for hiding this comment

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

Well remembered. I always forget this bit!

Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@


Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.0.31903.59
Expand All @@ -21,12 +21,13 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Server.UI", "src\Server.UI\
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "_SolutionItems", "_SolutionItems", "{1B26F38D-22D1-4A00-B3D3-D77C5979281B}"
ProjectSection(SolutionItems) = preProject
.editorconfig = .editorconfig
.gitignore = .gitignore
docker-compose.yml = docker-compose.yml
.config\dotnet-tools.json = .config\dotnet-tools.json
LICENSE = LICENSE
NuGet.config = NuGet.config
README.md = README.md
.gitignore = .gitignore
.editorconfig = .editorconfig
EndProjectSection
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Build", "build\Build.csproj", "{7CC5B8A2-2122-4907-B970-FD7A3EEA1C4C}"
Expand Down
3 changes: 0 additions & 3 deletions src/Application/Common/Interfaces/IApplicationDbContext.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using Cfo.Cats.Domain.Entities.Administration;
using Cfo.Cats.Domain.Entities.Candidates;
using Cfo.Cats.Domain.Entities.Documents;
using Cfo.Cats.Domain.Entities.Participants;
using Cfo.Cats.Domain.Identity;
Expand All @@ -23,8 +22,6 @@ public interface IApplicationDbContext

public DbSet<KeyValue> KeyValues { get; }

public DbSet<Candidate> Candidates { get; }

public DbSet<ParticipantEnrolmentHistory> ParticipantEnrolmentHistories { get; }

public DbSet<ApplicationUser> Users { get; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,10 @@ public CandidateFluentValidator()
return result.Errors.Select(e => e.ErrorMessage);
};

private bool BeValidAge(DateTime? date)
private bool BeValidAge(DateTime date)
{
var minimumAge = DateTime.Now.Date.AddYears(-18);
return date is not null && (minimumAge < date) == false;
return (minimumAge < date) == false;
}

}
67 changes: 40 additions & 27 deletions src/Application/Features/Candidates/DTOs/CandidateDto.cs
Original file line number Diff line number Diff line change
@@ -1,34 +1,66 @@
using Cfo.Cats.Domain.Entities.Candidates;
using Cfo.Cats.Domain.Entities.Participants;

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

public class CandidateDto
{
/// <summary>
/// The CATS identifier
/// </summary>
public string Identifier { get; set; }

Check warning on line 8 in src/Application/Features/Candidates/DTOs/CandidateDto.cs

View workflow job for this annotation

GitHub Actions / build

Non-nullable property 'Identifier' must contain a non-null value when exiting constructor. Consider declaring the property as nullable.

/// <summary>
/// The first name of the candidate
/// </summary>
public string FirstName { get; set; }

Check warning on line 13 in src/Application/Features/Candidates/DTOs/CandidateDto.cs

View workflow job for this annotation

GitHub Actions / build

Non-nullable property 'FirstName' must contain a non-null value when exiting constructor. Consider declaring the property as nullable.

/// <summary>
/// The second (or middle) name of the candidate
/// </summary>
public string SecondName { get; set; }

Check warning on line 18 in src/Application/Features/Candidates/DTOs/CandidateDto.cs

View workflow job for this annotation

GitHub Actions / build

Non-nullable property 'SecondName' must contain a non-null value when exiting constructor. Consider declaring the property as nullable.

/// <summary>
/// The candidates last name
/// </summary>
public string LastName { get; set; }

Check warning on line 23 in src/Application/Features/Candidates/DTOs/CandidateDto.cs

View workflow job for this annotation

GitHub Actions / build

Non-nullable property 'LastName' must contain a non-null value when exiting constructor. Consider declaring the property as nullable.

/// <summary>
/// The candidates date of birth
/// </summary>
public DateTime? DateOfBirth { get; set; }
public DateTime DateOfBirth { get; set; }

/// <summary>
/// A collection of identifiers from external systems.
/// The candidates NOMIS Number (if applicable).
/// </summary>
public string[] ExternalIdentifiers { get; set; }
public string? NomisNumber { get; set; }

/// <summary>
/// The candidates Crn (if applicable).
/// </summary>
public string? Crn { get; set; }

/// <summary>
/// Indicates whether the primary record is marked as active in the data source(s).
/// </summary>
public bool IsActive { get; set; }

/// <summary>
/// The candidates gender (Male/Female).
/// </summary>
public string Gender { get; set; }

/// <summary>
/// The candidates nationality
/// </summary>
public string Nationality { get; set; }

/// <summary>
/// The candidates ethnicity
/// </summary>
public string Ethnicity { get; set; }

/// <summary>
/// The primary source of information (NOMIS/DELIUS).
/// </summary>
public string Origin { get; set; }

/// <summary>
/// The location CATS thinks the user is registered at
Expand All @@ -38,23 +70,4 @@
public EnrolmentStatus? EnrolmentStatus { get; set; }

public string? ReferralSource { get; set; }

private class Mapping : Profile
{
public Mapping()
{
CreateMap<Candidate, CandidateDto>(MemberList.None)
.ForMember(candidateDto => candidateDto.Identifier,
options => options.MapFrom(candidate => candidate.Id))
.ForMember(candidateDto => candidateDto.FirstName,
options => options.MapFrom(candidate => candidate.FirstName))
.ForMember(candidateDto => candidateDto.LastName,
options => options.MapFrom(candidate => candidate.LastName))
.ForMember(candidateDto => candidateDto.CurrentLocation,
options => options.MapFrom(candidate => candidate.CurrentLocation.Name))
.ForMember(candidateDto => candidateDto.ExternalIdentifiers,
options => options.MapFrom(candidate => candidate.Identifiers.Select(p => p.IdentifierValue).ToArray()));

}
}
}

This file was deleted.

Copy link
Contributor

Choose a reason for hiding this comment

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

This can be improved by using automapper to switch between commands and DTOs

Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
using Cfo.Cats.Application.Common.Security;
using Cfo.Cats.Application.Features.Candidates.DTOs;
using Cfo.Cats.Application.Features.Participants.Caching;
using Cfo.Cats.Application.SecurityConstants;
using Cfo.Cats.Domain.Entities.Candidates;
using Cfo.Cats.Domain.Entities.Participants;

namespace Cfo.Cats.Application.Features.Participants.Commands;
Expand All @@ -14,14 +14,16 @@ public class Command: ICacheInvalidatorRequest<Result<string>>
/// <summary>
/// The CATS identifier
/// </summary>
public string? Identifier { get; set; }
public string? Identifier => Candidate.Identifier;

public required CandidateDto Candidate { get; set; }

public string? ReferralSource { get; set; }

public string? ReferralComments { get; set; }

public UserProfile? CurrentUser { get; set; }

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

public CancellationTokenSource? SharedExpiryTokenSource
Expand All @@ -38,8 +40,8 @@ public class Handler(IApplicationDbContext dbContext, ICurrentUserService curren
{
public async Task<Result<string>> Handle(Command request, CancellationToken cancellationToken)
{
Candidate candidate = await dbContext.Candidates.FirstAsync(c => c.Id == request.Identifier, cancellationToken);
Participant participant = Participant.CreateFrom(candidate, request.ReferralSource!, request.ReferralComments);
var candidate = request.Candidate;
Participant participant = Participant.CreateFrom(candidate.Identifier, candidate.FirstName, candidate.LastName, candidate.DateOfBirth, request.ReferralSource!, request.ReferralComments);
participant.AssignTo(currentUserService.UserId);

dbContext.Participants.Add(participant);
Expand Down
34 changes: 34 additions & 0 deletions src/Application/Features/Participants/Queries/ExistsById.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
using Cfo.Cats.Application.Common.Security;
using Cfo.Cats.Application.Features.Participants.Caching;
using Cfo.Cats.Application.SecurityConstants;

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

public static class CheckParticipantExistsById
{
[RequestAuthorize(Policy = PolicyNames.AllowEnrol)]
public class Query : ICacheableRequest<bool>
{
public required string Id { get; set; }
public string CacheKey => ParticipantCacheKey.GetCacheKey($"{Id}");
public MemoryCacheEntryOptions? Options => ParticipantCacheKey.MemoryCacheEntryOptions;
}

public class Handler : IRequestHandler<Query, bool>
{
private readonly IApplicationDbContext _context;

public Handler(IApplicationDbContext context)
{
_context = context;
}

public async Task<bool> Handle(Query request, CancellationToken cancellationToken)
{
return await _context.Participants
.AnyAsync(p => p.Id == request.Id, cancellationToken);
}
}

}

47 changes: 0 additions & 47 deletions src/Domain/Entities/Candidates/Candidate.cs

This file was deleted.

14 changes: 6 additions & 8 deletions src/Domain/Entities/Participants/Participant.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,6 @@
using Cfo.Cats.Domain.Common.Enums;
using Cfo.Cats.Domain.Common.Exceptions;
using Cfo.Cats.Domain.Entities.Administration;
using Cfo.Cats.Domain.Entities.Candidates;
using Cfo.Cats.Domain.Entities.Documents;
using Cfo.Cats.Domain.Events;

namespace Cfo.Cats.Domain.Entities.Participants;
Expand All @@ -29,19 +27,19 @@ private Participant()
}
#pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable.

public static Participant CreateFrom(Candidate candidate, string referralSource, string? referralComments)
public static Participant CreateFrom(string id, string firstName, string lastName, DateTime dateOfBirth, string referralSource, string? referralComments)
{
Participant p = new Participant
{
ConsentStatus = ConsentStatus.PendingStatus,
EnrolmentStatus = EnrolmentStatus.PendingStatus,
Id = candidate.Id,
DateOfBirth = DateOnly.FromDateTime(candidate.DateOfBirth),
FirstName = candidate.FirstName,
LastName = candidate.LastName,
Id = id,
DateOfBirth = DateOnly.FromDateTime(dateOfBirth),
FirstName = firstName,
LastName = lastName,
ReferralSource = referralSource,
ReferralComments = referralComments,
_currentLocationId = candidate.CurrentLocationId
_currentLocationId = 1
};

p.AddDomainEvent(new ParticipantCreatedDomainEvent(p));
Expand Down
36 changes: 0 additions & 36 deletions src/Domain/ValueObjects/CandidateIdentifier.cs

This file was deleted.

2 changes: 0 additions & 2 deletions src/Infrastructure/Constants/Database/DatabaseSchema.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,6 @@ public static class Tables
public const string ApplicationUserToken = nameof(ApplicationUserToken);
public const string ApplicationUserRole = nameof(ApplicationUserRole);
public const string AuditTrail = nameof(AuditTrail);
public const string Candidate = nameof(Candidate);
public const string CandidateIdentifier = nameof(CandidateIdentifier);
public const string Consent = nameof(Consent);
public const string Contract = nameof(Contract);
public const string Document = nameof(Document);
Expand Down
Loading
Loading