Skip to content
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
4 changes: 2 additions & 2 deletions src/Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@
<PackageVersion Include="Bogus" Version="35.6.3" />
<PackageVersion Include="AWSSDK.S3" Version="3.7.416.16" />
<PackageVersion Include="coverlet.collector" Version="6.0.4" />
<PackageVersion Include="FluentValidation" Version="11.11.0" />
<PackageVersion Include="FluentValidation.AspNetCore" Version="11.3.0" />
<PackageVersion Include="FluentValidation" Version="12.0.0" />
<PackageVersion Include="FluentValidation.AspNetCore" Version="11.3.1" />
<PackageVersion Include="Flurl" Version="4.0.0" />
<PackageVersion Include="IdentityModel" Version="7.0.0" />
<PackageVersion Include="MartinCostello.Logging.XUnit" Version="0.5.1" />
Expand Down
9 changes: 0 additions & 9 deletions src/Spd.Manager.Licence/BizProfileContract.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,15 +41,6 @@ public record BizInfo

}

public record BranchInfo
{
public Guid? BranchId { get; set; }
public Address? BranchAddress { get; set; }
public string? BranchManager { get; set; }
public string? BranchPhoneNumber { get; set; }
public string? BranchEmailAddr { get; set; }
}

public record BizListResponse
{
public Guid BizId { get; set; } //which is accountid in account
Expand Down
1 change: 1 addition & 0 deletions src/Spd.Manager.Licence/DogTrainerAppValidation.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,5 +35,6 @@ public DogTrainerChangeRequestValidator()
{
Include(new DogTrainerRequestValidator());
RuleFor(r => r.OriginalLicenceId).NotEmpty();
RuleFor(r => r.ApplicantId).NotEqual(Guid.Empty).NotEmpty();
}
}
41 changes: 41 additions & 0 deletions src/Spd.Manager.Licence/MDRARegistrationContract.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
using MediatR;
using Spd.Manager.Shared;

namespace Spd.Manager.Licence;
public interface IMDRARegistrationManager
{
//anonymous
public Task<MDRARegistrationCommandResponse> Handle(MDRARegistrationNewCommand command, CancellationToken ct);
public Task<MDRARegistrationCommandResponse> Handle(MDRARegistrationRenewCommand command, CancellationToken ct);
public Task<MDRARegistrationCommandResponse> Handle(MDRARegistrationUpdateCommand command, CancellationToken ct);
}

public record MDRARegistrationNewCommand(MDRARegistrationRequest SubmitRequest, IEnumerable<LicAppFileInfo> LicAppFileInfos) : IRequest<MDRARegistrationCommandResponse>;
public record MDRARegistrationRenewCommand(MDRARegistrationRequest ChangeRequest, IEnumerable<LicAppFileInfo> LicAppFileInfos) : IRequest<MDRARegistrationCommandResponse>;
public record MDRARegistrationUpdateCommand(MDRARegistrationRequest ChangeRequest, IEnumerable<LicAppFileInfo> LicAppFileInfos) : IRequest<MDRARegistrationCommandResponse>;

public record MDRARegistrationRequest
{
public ApplicationTypeCode ApplicationTypeCode { get; set; }
public ApplicationOriginTypeCode ApplicationOriginTypeCode { get; set; } = ApplicationOriginTypeCode.WebForm;
public string BizOwnerLastName { get; set; }
public string BizOwnerFirstName { get; set; }
public string BizOwnerMiddleName { get; set; }
public string? BizLegalName { get; set; }
public string? BizTradeName { get; set; }
public Address? BizMailingAddress { get; set; }
public Address? BizAddress { get; set; }
public string BizManagerLastName { get; set; }
public string BizManagerFirstName { get; set; }
public string BizManagerMiddleName { get; set; }
public string? BizPhoneNumber { get; set; }
public string? BizEmailAddress { get; set; }
public IEnumerable<BranchInfo>? Branches { get; set; }
public IEnumerable<Guid>? DocumentKeyCodes { get; set; }
}

public record MDRARegistrationCommandResponse
{
public Guid? OrgRegistrationId { get; set; }
}

82 changes: 82 additions & 0 deletions src/Spd.Manager.Licence/MDRARegistrationManager.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
using AutoMapper;
using MediatR;
using Spd.Manager.Shared;
using Spd.Resource.Repository.Application;
using Spd.Resource.Repository.Document;
using Spd.Resource.Repository.MDRARegistration;
using Spd.Utilities.Shared.Exceptions;
using System.Net;

namespace Spd.Manager.Licence;
internal class MDRARegistrationManager :
IRequestHandler<MDRARegistrationNewCommand, MDRARegistrationCommandResponse>,
IRequestHandler<MDRARegistrationRenewCommand, MDRARegistrationCommandResponse>,
IRequestHandler<MDRARegistrationUpdateCommand, MDRARegistrationCommandResponse>,
IMDRARegistrationManager
{
private readonly IMapper _mapper;
private readonly IMDRARegistrationRepository _repository;
private readonly IDocumentRepository _documentRepository;

public MDRARegistrationManager(IMapper mapper,
IMDRARegistrationRepository repository,
IDocumentRepository documentRepository)
{
this._mapper = mapper;
this._repository = repository;
this._documentRepository = documentRepository;
}

#region anonymous
public async Task<MDRARegistrationCommandResponse> Handle(MDRARegistrationNewCommand cmd, CancellationToken ct)
{
ValidateFilesForNewApp(cmd);
CreateMDRARegistrationCmd createCmd = _mapper.Map<CreateMDRARegistrationCmd>(cmd.SubmitRequest);
MDRARegistrationResp respone = await _repository.CreateMDRARegistrationAsync(createCmd, ct);
await UploadNewDocsAsync(cmd.LicAppFileInfos, respone.RegistrationId, ct);
return new MDRARegistrationCommandResponse { OrgRegistrationId = respone.RegistrationId };
}

public async Task<MDRARegistrationCommandResponse> Handle(MDRARegistrationRenewCommand cmd, CancellationToken ct)
{
return new MDRARegistrationCommandResponse { OrgRegistrationId = Guid.Empty };
}

public async Task<MDRARegistrationCommandResponse> Handle(MDRARegistrationUpdateCommand cmd, CancellationToken ct)
{
return new MDRARegistrationCommandResponse { OrgRegistrationId = Guid.Empty };
}
#endregion

private static void ValidateFilesForNewApp(MDRARegistrationNewCommand cmd)
{
MDRARegistrationRequest request = cmd.SubmitRequest;
IEnumerable<LicAppFileInfo> fileInfos = cmd.LicAppFileInfos;

if (request.ApplicationTypeCode == ApplicationTypeCode.New) //both new and renew need biz licence Registry Document
{
if (!fileInfos.Any(f => f.LicenceDocumentTypeCode == LicenceDocumentTypeCode.CorporateRegistryDocument))
{
throw new ApiException(HttpStatusCode.BadRequest, "Must provide copies of business licence registration documents.");
}
}
}

//upload file from cache to main bucket
protected async Task UploadNewDocsAsync(
IEnumerable<LicAppFileInfo> newFileInfos,
Guid? orgRegistrationId,
CancellationToken ct)
{
if (newFileInfos != null && newFileInfos.Any())
{
foreach (LicAppFileInfo licAppFile in newFileInfos)
{
SpdTempFile? tempFile = _mapper.Map<SpdTempFile>(licAppFile);
CreateDocumentCmd? fileCmd = _mapper.Map<CreateDocumentCmd>(licAppFile);
fileCmd.OrgRegistrationId = orgRegistrationId;
await _documentRepository.ManageAsync(fileCmd, ct);
}
}
}
}
42 changes: 42 additions & 0 deletions src/Spd.Manager.Licence/MDRARegistrationValidation.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
using FluentValidation;

namespace Spd.Manager.Licence;

public class MDRARegistrationValidator : AbstractValidator<MDRARegistrationRequest>
{
public MDRARegistrationValidator()
{
RuleFor(x => x.BizOwnerLastName).NotEmpty().MaximumLength(40);
RuleFor(r => r.BizLegalName).MaximumLength(200);
RuleFor(r => r.BizEmailAddress).EmailAddress();
RuleFor(x => x.BizManagerLastName).NotEmpty().MaximumLength(40);
RuleFor(r => r.BizAddress).SetValidator(new AddressValidator());
RuleFor(r => r.BizMailingAddress).SetValidator(new AddressValidator());
RuleFor(r => r.Branches)
.ForEach(r => r
.Must(r => !string.IsNullOrEmpty(r.BranchAddress?.AddressLine1))
.Must(r => !string.IsNullOrEmpty(r.BranchAddress?.City))
.Must(r => !string.IsNullOrEmpty(r.BranchAddress?.Country))
.Must(r => !string.IsNullOrEmpty(r.BranchAddress?.Province))
.Must(r => !string.IsNullOrEmpty(r.BranchAddress?.PostalCode))
.Must(r => !string.IsNullOrEmpty(r.BranchManager))
.Must(r => r.BranchPhoneNumber == null || r.BranchPhoneNumber?.Length <= 15))
.WithMessage("Missing branch address information.")
.When(r => r.Branches != null);
}
}

public class AddressValidator : AbstractValidator<Address>
{
public AddressValidator()
{
RuleFor(r => r.Province).NotEmpty().MaximumLength(100);
RuleFor(r => r.City).NotEmpty().MaximumLength(100);
RuleFor(r => r.AddressLine1).NotEmpty().MaximumLength(100);
RuleFor(r => r.Country).NotEmpty().MaximumLength(100);
RuleFor(r => r.PostalCode).NotEmpty().MaximumLength(20);
}
}



3 changes: 3 additions & 0 deletions src/Spd.Manager.Licence/Mappings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
using Spd.Resource.Repository.LicApp;
using Spd.Resource.Repository.Licence;
using Spd.Resource.Repository.LicenceFee;
using Spd.Resource.Repository.MDRARegistration;
using Spd.Resource.Repository.PersonLicApplication;
using Spd.Resource.Repository.PortalUser;
using Spd.Resource.Repository.RetiredDogApp;
Expand Down Expand Up @@ -507,6 +508,8 @@ public Mappings()
CreateMap<RetiredDogLicenceAppChangeRequest, CreateRetiredDogAppCmd>();
CreateMap<RetiredDogAppCmdResp, RetiredDogAppCommandResponse>();
CreateMap<RetiredDogAppResp, RetiredDogLicenceAppResponse>();
CreateMap<MDRARegistrationRequest, CreateMDRARegistrationCmd>()
.ForMember(d => d.Branches, opt => opt.MapFrom(s => GetBranchAddr(s.Branches)));
}

private static WorkerCategoryTypeEnum[] GetCategories(IEnumerable<WorkerCategoryTypeCode> codes)
Expand Down
10 changes: 9 additions & 1 deletion src/Spd.Manager.Licence/SharedContract.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
namespace Spd.Manager.Licence;

public class UploadFileRequest
{
public LicenceDocumentTypeCode FileTypeCode { get; set; }
Expand Down Expand Up @@ -199,4 +198,13 @@ public record ContactInfo
public string? MiddleName1 { get; set; }
public string? MiddleName2 { get; set; }
public string? Surname { get; set; }
}

public record BranchInfo
{
public Guid? BranchId { get; set; }
public Address? BranchAddress { get; set; }
public string? BranchManager { get; set; }
public string? BranchPhoneNumber { get; set; }
public string? BranchEmailAddr { get; set; }
}
80 changes: 80 additions & 0 deletions src/Spd.Presentation.Licensing/Controllers/MDRAController.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
using FluentValidation;
using MediatR;
using Microsoft.AspNetCore.DataProtection;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Caching.Distributed;
using Spd.Manager.Licence;
using Spd.Manager.Shared;
using Spd.Utilities.Recaptcha;
using Spd.Utilities.Shared.Exceptions;
using System.ComponentModel.DataAnnotations;
using System.Net;
using System.Text.Json;

namespace Spd.Presentation.Licensing.Controllers
{
[ApiController]
public class MDRAController : SpdLicenceControllerBase
{
private readonly IMediator _mediator;
private readonly IValidator<MDRARegistrationRequest> _mdraRequestValidator;

public MDRAController(IMediator mediator,
IConfiguration configuration,
IDataProtectionProvider dataProtector,
IRecaptchaVerificationService recaptchaVerificationService,
IDistributedCache cache,
IValidator<MDRARegistrationRequest> mdraRequestValidator) : base(cache, dataProtector, recaptchaVerificationService, configuration)
{
_mediator = mediator;
_mdraRequestValidator = mdraRequestValidator;
}

#region anonymous

/// <summary>
/// Submit MDRA registration 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.
/// The session keycode is stored in the cookies.
/// </summary>
/// <param name="jsonRequest">MDRARegistrationRequest data</param>
/// <param name="ct"></param>
/// <returns></returns>
[Route("api/mdra-registrations")]
[HttpPost]
public async Task<MDRARegistrationCommandResponse?> SubmitMDRARegistrationAnonymous([FromBody][Required] MDRARegistrationRequest jsonRequest, CancellationToken ct)
{
await VerifyKeyCode();

IEnumerable<LicAppFileInfo> newDocInfos = await GetAllNewDocsInfoAsync(jsonRequest.DocumentKeyCodes, ct);
var validateResult = await _mdraRequestValidator.ValidateAsync(jsonRequest, ct);
if (!validateResult.IsValid)
throw new ApiException(HttpStatusCode.BadRequest, JsonSerializer.Serialize(validateResult.Errors));
jsonRequest.ApplicationOriginTypeCode = ApplicationOriginTypeCode.WebForm;

MDRARegistrationCommandResponse? response = null;
if (jsonRequest.ApplicationTypeCode == ApplicationTypeCode.New)
{
MDRARegistrationNewCommand command = new(jsonRequest, newDocInfos);
response = await _mediator.Send(command, ct);
}

//if (jsonRequest.ApplicationTypeCode == ApplicationTypeCode.Renewal)
//{
// MDRARegistrationNewCommand command = new(jsonRequest, newDocInfos);
// response = await _mediator.Send(command, ct);
//}

//if (jsonRequest.ApplicationTypeCode == ApplicationTypeCode.Update)
//{
// MDRARegistrationNewCommand command = new(jsonRequest, newDocInfos);
// response = await _mediator.Send(command, ct);
//}
SetValueToResponseCookie(SessionConstants.AnonymousApplicationSubmitKeyCode, String.Empty);
SetValueToResponseCookie(SessionConstants.AnonymousApplicationContext, String.Empty);
return response;
}

#endregion anonymous
}
}
2 changes: 2 additions & 0 deletions src/Spd.Resource.Repository/Configurer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
using Spd.Resource.Repository.LicApp;
using Spd.Resource.Repository.Licence;
using Spd.Resource.Repository.LicenceFee;
using Spd.Resource.Repository.MDRARegistration;
using Spd.Resource.Repository.OptionSet;
using Spd.Resource.Repository.Org;
using Spd.Resource.Repository.Payment;
Expand Down Expand Up @@ -80,5 +81,6 @@ public void Configure(ConfigurationContext configurationServices)
configurationServices.Services.AddTransient<IDogTeamRepository, DogTeamRepository>();
configurationServices.Services.AddTransient<IDogTrainerAppRepository, DogTrainerAppRepository>();
configurationServices.Services.AddTransient<IRetiredDogAppRepository, RetiredDogAppRepository>();
configurationServices.Services.AddTransient<IMDRARegistrationRepository, MDRARegistrationRepository>();
}
}
1 change: 1 addition & 0 deletions src/Spd.Resource.Repository/Document/Contract.cs
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ public record CreateDocumentCmd : DocumentCmd
public Guid? SubmittedByApplicantId { get; set; }
public Guid? LicenceId { get; set; }
public Guid? AccountId { get; set; }
public Guid? OrgRegistrationId { get; set; }
public DocumentTypeEnum? DocumentType { get; set; } //tag1
public DocumentTypeEnum? DocumentType2 { get; set; } //tag2
public DateOnly? ExpiryDate { get; set; }
Expand Down
7 changes: 7 additions & 0 deletions src/Spd.Resource.Repository/Document/DocumentRepository.cs
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,13 @@ private async Task<DocumentResp> DocumentCreateAsync(CreateDocumentCmd cmd, Canc
throw new ArgumentException("invalid contact id");
_context.SetLink(documenturl, nameof(documenturl.bcgov_Customer_contact), contact);
}
if (cmd.OrgRegistrationId != null)
{
spd_orgregistration? registration = await _context.GetOrgRegistrationById((Guid)cmd.OrgRegistrationId, ct);
if (registration == null)
throw new ArgumentException("invalid org registration id");
_context.SetLink(documenturl, nameof(documenturl.spd_OrgRegistrationId), registration);
}
if (cmd.TaskId != null)
{
task? task = await _context.GetTaskById((Guid)cmd.TaskId, ct);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ public async Task<DogTrainerAppCmdResp> CreateDogTrainerAppAsync(CreateDogTraine
}
else if (cmd.ApplicationTypeCode == ApplicationTypeEnum.Renewal || cmd.ApplicationTypeCode == ApplicationTypeEnum.Replacement)
{
app = PrepareNewAppDataInDbContext(cmd, contact);
contact = UpdateContact(cmd, (Guid)cmd.ApplicantId);
app = PrepareNewAppDataInDbContext(cmd, contact);
if (contact != null)
{
_context.SetLink(app, nameof(spd_application.spd_ApplicantId_contact), contact);
Expand Down
Loading