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

unauth swl update - part1 #710

Merged
merged 7 commits into from
Jan 29, 2024
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
8 changes: 5 additions & 3 deletions src/Spd.Manager.Licence/Constants.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
namespace Spd.Manager.Licence;
internal class Constants
internal static class Constants
{
public static readonly int LICENCE_REPLACE_VALID_BEFORE_EXPIRATION_IN_DAYS = 14;
public static readonly int LICENCE_RENEW_VALID_BEFORE_EXPIRATION_IN_DAYS = 90;
internal const int LicenceReplaceValidBeforeExpirationInDays = 14;
internal const int LicenceWith123YearsRenewValidBeforeExpirationInDays = 90;
internal const int LicenceWith90DaysRenewValidBeforeExpirationInDays = 60;
internal const int LicenceUpdateValidBeforeExpirationInDays = 14;//Licence holder can't request an update within 14 days of expiry date
}
7 changes: 7 additions & 0 deletions src/Spd.Manager.Licence/PersonalLicenceAppContract.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ public interface IPersonalLicenceAppManager
public Task<WorkerLicenceAppUpsertResponse> Handle(AnonymousWorkerLicenceAppNewCommand command, CancellationToken ct);
public Task<WorkerLicenceAppUpsertResponse> Handle(AnonymousWorkerLicenceAppReplaceCommand command, CancellationToken ct);
public Task<WorkerLicenceAppUpsertResponse> Handle(AnonymousWorkerLicenceAppRenewCommand command, CancellationToken ct);
public Task<WorkerLicenceAppUpsertResponse> Handle(AnonymousWorkerLicenceAppUpdateCommand command, CancellationToken ct);
public Task<IEnumerable<LicAppFileInfo>> Handle(CreateDocumentInCacheCommand command, CancellationToken ct);
}

Expand Down Expand Up @@ -42,6 +43,11 @@ public record AnonymousWorkerLicenceAppRenewCommand(
Guid KeyCode)
: IRequest<WorkerLicenceAppUpsertResponse>;

public record AnonymousWorkerLicenceAppUpdateCommand(
WorkerLicenceAppAnonymousSubmitRequestJson LicenceAnonymousRequest,
Guid KeyCode)
: IRequest<WorkerLicenceAppUpsertResponse>;

public record GetWorkerLicenceQuery(Guid LicenceApplicationId) : IRequest<WorkerLicenceResponse>;
public record GetWorkerLicenceAppListQuery(Guid ApplicantId) : IRequest<IEnumerable<WorkerLicenceAppListResponse>>;

Expand Down Expand Up @@ -184,6 +190,7 @@ public record WorkerLicenceAppAnonymousSubmitRequestJson : WorkerLicenceAppBase
public Guid[]? PreviousDocumentIds { get; set; } //documentUrlId, used for renew
public Guid? OriginalApplicationId { get; set; } //for new, it should be null. for renew, replace, update, it should be original application id.
public Guid? OriginalLicenceId { get; set; } //for new, it should be null. for renew, replace, update, it should be original licence id.
public bool? Reprint { get; set; }
}

public record WorkerLicenceCreateResponse
Expand Down
143 changes: 137 additions & 6 deletions src/Spd.Manager.Licence/PersonalLicenceAppManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,10 @@
using Spd.Resource.Applicants.Licence;
using Spd.Resource.Applicants.LicenceApplication;
using Spd.Resource.Applicants.LicenceFee;
using Spd.Resource.Applicants.Tasks;
using Spd.Resource.Organizations.Identity;
using Spd.Utilities.Cache;
using Spd.Utilities.Dynamics;
using Spd.Utilities.Shared.Exceptions;
using Spd.Utilities.TempFileStorage;

Expand All @@ -23,6 +25,7 @@ internal partial class PersonalLicenceAppManager :
IRequestHandler<AnonymousWorkerLicenceAppNewCommand, WorkerLicenceAppUpsertResponse>,
IRequestHandler<AnonymousWorkerLicenceAppReplaceCommand, WorkerLicenceAppUpsertResponse>,
IRequestHandler<AnonymousWorkerLicenceAppRenewCommand, WorkerLicenceAppUpsertResponse>,
IRequestHandler<AnonymousWorkerLicenceAppUpdateCommand, WorkerLicenceAppUpsertResponse>,
IRequestHandler<CreateDocumentInCacheCommand, IEnumerable<LicAppFileInfo>>,
IPersonalLicenceAppManager
{
Expand All @@ -34,6 +37,7 @@ internal partial class PersonalLicenceAppManager :
private readonly IDocumentRepository _documentRepository;
private readonly ILogger<IPersonalLicenceAppManager> _logger;
private readonly ILicenceFeeRepository _feeRepository;
private readonly ITaskRepository _taskRepository;
private readonly IDistributedCache _cache;

public PersonalLicenceAppManager(
Expand All @@ -45,7 +49,8 @@ public PersonalLicenceAppManager(
IDocumentRepository documentUrlRepository,
ILogger<IPersonalLicenceAppManager> logger,
ILicenceFeeRepository feeRepository,
IDistributedCache cache)
IDistributedCache cache,
ITaskRepository taskRepository)
{
_licenceRepository = licenceRepository;
_licenceAppRepository = licenceAppRepository;
Expand All @@ -56,6 +61,7 @@ public PersonalLicenceAppManager(
_logger = logger;
_feeRepository = feeRepository;
_cache = cache;
_taskRepository = taskRepository;
}

#region for portal
Expand Down Expand Up @@ -87,7 +93,7 @@ public async Task<WorkerLicenceAppUpsertResponse> Handle(WorkerLicenceUpsertComm
return _mapper.Map<WorkerLicenceAppUpsertResponse>(response);
}

//authenticated submit
// authenticated submit
public async Task<WorkerLicenceAppUpsertResponse> Handle(WorkerLicenceSubmitCommand cmd, CancellationToken ct)
{
var response = await this.Handle((WorkerLicenceUpsertCommand)cmd, ct);
Expand Down Expand Up @@ -219,7 +225,7 @@ public async Task<WorkerLicenceAppUpsertResponse> Handle(AnonymousWorkerLicenceA
LicenceListResp licences = await _licenceRepository.QueryAsync(new LicenceQry() { LicenceId = request.OriginalLicenceId }, ct);
if (licences == null || !licences.Items.Any())
throw new ArgumentException("cannot find the licence that needs to be replaced.");
if (DateTime.UtcNow.AddDays(Constants.LICENCE_REPLACE_VALID_BEFORE_EXPIRATION_IN_DAYS) > licences.Items.First().ExpiryDate.ToDateTime(new TimeOnly(0, 0)))
if (DateTime.UtcNow.AddDays(Constants.LicenceReplaceValidBeforeExpirationInDays) > licences.Items.First().ExpiryDate.ToDateTime(new TimeOnly(0, 0)))
throw new ArgumentException("the licence cannot be replaced because it will expired soon or already expired");

CreateLicenceApplicationCmd createApp = _mapper.Map<CreateLicenceApplicationCmd>(request);
Expand Down Expand Up @@ -258,9 +264,18 @@ public async Task<WorkerLicenceAppUpsertResponse> Handle(AnonymousWorkerLicenceA
if (originalLicences == null || !originalLicences.Items.Any())
throw new ArgumentException("cannot find the licence that needs to be renewed.");
LicenceResp originalLic = originalLicences.Items.First();
if (DateTime.UtcNow > originalLic.ExpiryDate.AddDays(Constants.LICENCE_RENEW_VALID_BEFORE_EXPIRATION_IN_DAYS).ToDateTime(new TimeOnly(0, 0))
&& DateTime.UtcNow < originalLic.ExpiryDate.ToDateTime(new TimeOnly(0, 0)))
throw new ArgumentException("the licence can only be renewed within 90 days of the expiry date.");
if (originalLic.LicenceTermCode == LicenceTermEnum.NinetyDays)
{
if (DateTime.UtcNow > originalLic.ExpiryDate.AddDays(-Constants.LicenceWith90DaysRenewValidBeforeExpirationInDays).ToDateTime(new TimeOnly(0, 0))
&& DateTime.UtcNow < originalLic.ExpiryDate.ToDateTime(new TimeOnly(0, 0)))
throw new ArgumentException($"the licence can only be renewed within {Constants.LicenceWith90DaysRenewValidBeforeExpirationInDays} days of the expiry date.");
}
else
{
if (DateTime.UtcNow > originalLic.ExpiryDate.AddDays(-Constants.LicenceWith123YearsRenewValidBeforeExpirationInDays).ToDateTime(new TimeOnly(0, 0))
&& DateTime.UtcNow < originalLic.ExpiryDate.ToDateTime(new TimeOnly(0, 0)))
throw new ArgumentException($"the licence can only be renewed within {Constants.LicenceWith123YearsRenewValidBeforeExpirationInDays} days of the expiry date.");
}

CreateLicenceApplicationCmd createApp = _mapper.Map<CreateLicenceApplicationCmd>(request);
var response = await _licenceAppRepository.CreateLicenceApplicationAsync(createApp, ct);
Expand Down Expand Up @@ -312,6 +327,103 @@ await _documentRepository.ManageAsync(

return new WorkerLicenceAppUpsertResponse { LicenceAppId = response.LicenceAppId };
}

public async Task<WorkerLicenceAppUpsertResponse> Handle(AnonymousWorkerLicenceAppUpdateCommand cmd, CancellationToken ct)
{
WorkerLicenceAppAnonymousSubmitRequestJson request = cmd.LicenceAnonymousRequest;
if (cmd.LicenceAnonymousRequest.ApplicationTypeCode != ApplicationTypeCode.Update)
throw new ArgumentException("should be a update request");

//validation: check if original licence meet update condition.
LicenceListResp originalLicences = await _licenceRepository.QueryAsync(new LicenceQry() { LicenceId = request.OriginalLicenceId }, ct);
if (originalLicences == null || !originalLicences.Items.Any())
throw new ArgumentException("cannot find the licence that needs to be updated.");
LicenceResp originalLic = originalLicences.Items.First();
if (DateTime.UtcNow.AddDays(Constants.LicenceUpdateValidBeforeExpirationInDays) > originalLic.ExpiryDate.ToDateTime(new TimeOnly(0, 0)))
throw new ArgumentException($"can't request an update within {Constants.LicenceUpdateValidBeforeExpirationInDays} days of expiry date.");

LicenceApplicationResp originalApp = await _licenceAppRepository.GetLicenceApplicationAsync((Guid)cmd.LicenceAnonymousRequest.OriginalApplicationId, ct);
ChangeSpec changes = GetChanges(originalApp, request);

if ((request.Reprint != null && request.Reprint.Value) || (changes.CategoriesChanged || changes.DogRestraintsChanged))
{
CreateLicenceApplicationCmd createApp = _mapper.Map<CreateLicenceApplicationCmd>(request);
var response = await _licenceAppRepository.CreateLicenceApplicationAsync(createApp, ct);

//add all new files user uploaded
if (cmd.LicenceAnonymousRequest.DocumentKeyCodes != null && cmd.LicenceAnonymousRequest.DocumentKeyCodes.Any())
{
foreach (Guid fileKeyCode in cmd.LicenceAnonymousRequest.DocumentKeyCodes)
{
IEnumerable<LicAppFileInfo> items = await _cache.Get<IEnumerable<LicAppFileInfo>>(fileKeyCode.ToString());
foreach (LicAppFileInfo licAppFile in items)
{
DocumentTypeEnum? docType1 = GetDocumentType1Enum(licAppFile.LicenceDocumentTypeCode);
DocumentTypeEnum? docType2 = GetDocumentType2Enum(licAppFile.LicenceDocumentTypeCode);
DateOnly? expiredDate = cmd.LicenceAnonymousRequest?
.DocumentInfos?
.FirstOrDefault(d => d.LicenceDocumentTypeCode == licAppFile.LicenceDocumentTypeCode)?
.ExpiryDate;
//create bcgov_documenturl and file
await _documentRepository.ManageAsync(new CreateDocumentCmd
{
TempFile = _mapper.Map<SpdTempFile>(licAppFile),
ApplicationId = response.LicenceAppId,
DocumentType = docType1,
DocumentType2 = docType2,
SubmittedByApplicantId = response.ContactId,
ExpiryDate = expiredDate,
}, ct);
}
}
}
//todo : need to pay $20
await CommitApplicationAsync(request, response.LicenceAppId, ct);
}
else
{
//todo: update contact directly
}

//check if criminal charges changes or New Offence Conviction, create task, assign to Licensing RA Coordinator team
if (changes.CriminalHistoryChanged)
await _taskRepository.ManageAsync(new CreateTaskCmd()
{
Description = "Criminal History has Changed",
DueDateTime = new DateTimeOffset(2024, 2, 20, 0, 0, 0, new TimeSpan(0, 0, 0)),
Subject = "Criminal History Changed",
TaskPriorityEnum = TaskPriorityEnum.Normal,
RegardingContactId = originalApp.ContactId,
AssignedTeamId = Guid.Parse(DynamicsConstants.Licencing_Risk_Assessment_Coordinator_Team_Guid),
}, ct);

// check if Hold a Position with Peace Officer Status changed, create task with high priority, assign to Licensing CS team
if (changes.PeaceOfficerStatusChanged)
await _taskRepository.ManageAsync(new CreateTaskCmd()
{
Description = "Peace Officer Status has Changed",
DueDateTime = new DateTimeOffset(2024, 2, 20, 0, 0, 0, new TimeSpan(0, 0, 0)),
Subject = "Peace Officer Status Changed",
TaskPriorityEnum = TaskPriorityEnum.High,
RegardingContactId = originalApp.ContactId,
AssignedTeamId = Guid.Parse(DynamicsConstants.Licensing_Client_Service_Team_Guid),
}, ct);

////Treated for Mental Health Condition, create task, assign to Licensing RA Coordinator team
if (changes.MentalHealthStatusChanged)
await _taskRepository.ManageAsync(new CreateTaskCmd()
{
Description = "Mental Health Status has Changed",
DueDateTime = new DateTimeOffset(2024, 2, 20, 0, 0, 0, new TimeSpan(0, 0, 0)),
Subject = "Mental Health Status Changed",
TaskPriorityEnum = TaskPriorityEnum.Normal,
RegardingContactId = originalApp.ContactId,
AssignedTeamId = Guid.Parse(DynamicsConstants.Licencing_Risk_Assessment_Coordinator_Team_Guid),
}, ct);

return new WorkerLicenceAppUpsertResponse();
}

#endregion

private async Task CommitApplicationAsync(WorkerLicenceAppAnonymousSubmitRequestJson request, Guid licenceAppId, CancellationToken ct, bool HasSwl90DayLicence = false)
Expand Down Expand Up @@ -379,4 +491,23 @@ private async Task<bool> HasDuplicates(Guid applicantId, WorkerLicenceTypeEnum w
}
return false;
}
private ChangeSpec GetChanges(LicenceApplicationResp originalApp, WorkerLicenceAppAnonymousSubmitRequestJson newApp)
{
ChangeSpec changes = new ChangeSpec();
//todo
//if(newApp.CategoryCodes != originalApp.CategoryData)
changes.CategoriesChanged = true;
return changes;
}

private record ChangeSpec
{
public bool NameChanged { get; set; }
public bool CategoriesChanged { get; set; }
public bool DogRestraintsChanged { get; set; }
public bool ContactInfoChanged { get; set; }
public bool PeaceOfficerStatusChanged { get; set; }
public bool MentalHealthStatusChanged { get; set; }
public bool CriminalHistoryChanged { get; set; }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,6 @@ public async Task<IEnumerable<WorkerLicenceAppListResponse>> GetLicenceApplicati
/// Submit Security Worker Licence Application Anonymously
/// deprecated as the request body is too big. the proxy won't let it through.
/// </summary>
/// <param name="WorkerLicenceAppAnonymousSubmitRequest"></param>
/// <returns></returns>
[Route("api/worker-licence-applications/submit/anonymous")]
[HttpPost]
Expand Down Expand Up @@ -283,7 +282,7 @@ public async Task<Guid> UploadLicenceAppFilesAnonymous([FromForm][Required] Lice
}

CreateDocumentInCacheCommand command = new CreateDocumentInCacheCommand(fileUploadRequest);
var newFileInfos = await _mediator.Send(command);
var newFileInfos = await _mediator.Send(command, ct);
Guid fileKeyCode = Guid.NewGuid();
await _cache.Set<IEnumerable<LicAppFileInfo>>(fileKeyCode.ToString(), newFileInfos, TimeSpan.FromMinutes(30));
return fileKeyCode;
Expand All @@ -293,7 +292,7 @@ public async Task<Guid> UploadLicenceAppFilesAnonymous([FromForm][Required] Lice
/// Submit Security Worker Licence Application Json part Anonymously
/// After fe done with the uploading files, then fe do post with json payload, inside payload, it needs to contain an array of keycode for the files.
/// </summary>
/// <param name="WorkerLicenceAppAnonymousSubmitRequest"></param>
/// <param name="jsonRequest">WorkerLicenceAppAnonymousSubmitRequestJson data</param>
/// <returns></returns>
[Route("api/worker-licence-applications/anonymous/{keyCode}/submit")]
[HttpPost]
Expand All @@ -313,19 +312,25 @@ public async Task<WorkerLicenceAppUpsertResponse> SubmitSecurityWorkerLicenceApp
if (jsonRequest.ApplicationTypeCode == ApplicationTypeCode.New)
{
AnonymousWorkerLicenceAppNewCommand command = new(jsonRequest, keyCode);
return await _mediator.Send(command);
return await _mediator.Send(command, ct);
}

if (jsonRequest.ApplicationTypeCode == ApplicationTypeCode.Replacement)
{
AnonymousWorkerLicenceAppReplaceCommand command = new(jsonRequest, keyCode);
return await _mediator.Send(command);
return await _mediator.Send(command, ct);
}

if (jsonRequest.ApplicationTypeCode == ApplicationTypeCode.Renewal)
{
AnonymousWorkerLicenceAppRenewCommand command = new(jsonRequest, keyCode);
return await _mediator.Send(command);
return await _mediator.Send(command, ct);
}

if (jsonRequest.ApplicationTypeCode == ApplicationTypeCode.Update)
{
AnonymousWorkerLicenceAppUpdateCommand command = new(jsonRequest, keyCode);
return await _mediator.Send(command, ct);
}
return null;
}
Expand All @@ -334,6 +339,6 @@ public async Task<WorkerLicenceAppUpsertResponse> SubmitSecurityWorkerLicenceApp

public class GoogleRecaptcha
{
public string RecaptchaCode { get; set; }
public string RecaptchaCode { get; set; } = null!;
}
}
Loading
Loading