From f757e30d4e91e491d3e2ee096862eb46fa6052ea Mon Sep 17 00:00:00 2001 From: Peggy Date: Fri, 6 Dec 2024 06:58:43 -0800 Subject: [PATCH] [SPDBT-3414][SPDBT-3415]Licensing-be: Add an endpoint in licenceController to accept request with licencenumber, fn and ln. (#1973) # Description This PR includes the following proposed change(s): - [SPDBT-3414] Licensing-be: Add an endpoint in licenceController to accept request with licencenumber, fn and ln. - [SPDBT-3415] License-be: provide an endpoint for searching biz licence. --- src/Spd.Manager.Licence/LicenceContract.cs | 2 + src/Spd.Manager.Licence/LicenceManager.cs | 53 ++++++++++++++++++- .../Controllers/LicenceController.cs | 25 +++++++++ .../Licence/Contract.cs | 3 ++ .../Licence/LicenceRepository.cs | 14 ++--- 5 files changed, 90 insertions(+), 7 deletions(-) diff --git a/src/Spd.Manager.Licence/LicenceContract.cs b/src/Spd.Manager.Licence/LicenceContract.cs index 0c7e92b6f..7e692b4c6 100644 --- a/src/Spd.Manager.Licence/LicenceContract.cs +++ b/src/Spd.Manager.Licence/LicenceContract.cs @@ -8,6 +8,7 @@ public interface ILicenceManager public Task Handle(LicenceByIdQuery query, CancellationToken ct); public Task Handle(LicenceQuery query, CancellationToken ct); public Task> Handle(LicenceListQuery query, CancellationToken ct); + public Task> Handle(LicenceListSearch search, CancellationToken ct); public Task Handle(LicencePhotoQuery query, CancellationToken ct); } @@ -65,3 +66,4 @@ public record LicenceQuery(string? LicenceNumber, string? AccessCode) : IRequest public record LicenceByIdQuery(Guid LicenceId) : IRequest; public record LicenceListQuery(Guid? ApplicantId, Guid? BizId) : IRequest>; public record LicencePhotoQuery(Guid LicenceId) : IRequest; +public record LicenceListSearch(string? LicenceNumber, string? FirstName, string? LastName, string? BizName, ServiceTypeCode ServiceTypeCode) : IRequest>; diff --git a/src/Spd.Manager.Licence/LicenceManager.cs b/src/Spd.Manager.Licence/LicenceManager.cs index 177bfa672..dee66f6dd 100644 --- a/src/Spd.Manager.Licence/LicenceManager.cs +++ b/src/Spd.Manager.Licence/LicenceManager.cs @@ -18,6 +18,7 @@ internal class LicenceManager : IRequestHandler, IRequestHandler, IRequestHandler>, + IRequestHandler>, ILicenceManager { private readonly ILicenceRepository _licenceRepository; @@ -100,7 +101,7 @@ public async Task> Handle(LicenceListQuery que if (!response.Items.Any()) { _logger.LogDebug("No licence found."); - return Array.Empty(); + return Array.Empty(); } //only return expired and active ones @@ -145,6 +146,55 @@ public async Task> Handle(LicenceListQuery que return new FileResponse(); } + public async Task> Handle(LicenceListSearch search, CancellationToken cancellationToken) + { + LicenceListResp response = new LicenceListResp(); + if (search.ServiceTypeCode == ServiceTypeCode.SecurityWorkerLicence) + { + if (string.IsNullOrWhiteSpace(search.LicenceNumber) && string.IsNullOrWhiteSpace(search.FirstName) && string.IsNullOrWhiteSpace(search.LastName)) + throw new ApiException(HttpStatusCode.BadRequest, "Not enough parameter"); + if ((!string.IsNullOrWhiteSpace(search.LicenceNumber) && !string.IsNullOrWhiteSpace(search.FirstName)) + || (!string.IsNullOrWhiteSpace(search.LicenceNumber) && !string.IsNullOrWhiteSpace(search.LastName))) + throw new ApiException(HttpStatusCode.BadRequest, "Cannot search name and licence number together."); + response = await _licenceRepository.QueryAsync( + new LicenceQry + { + LicenceNumber = search.LicenceNumber, + FirstName = search.FirstName, + LastName = search.LastName, + Type = ServiceTypeEnum.SecurityWorkerLicence, + IncludeInactive = true + }, cancellationToken); + } + + if (search.ServiceTypeCode == ServiceTypeCode.SecurityBusinessLicence) + { + if (string.IsNullOrWhiteSpace(search.LicenceNumber) && string.IsNullOrWhiteSpace(search.BizName)) + throw new ApiException(HttpStatusCode.BadRequest, "Not enough parameter"); + if (!string.IsNullOrWhiteSpace(search.LicenceNumber) && !string.IsNullOrWhiteSpace(search.BizName)) + throw new ApiException(HttpStatusCode.BadRequest, "Cannot search biz name and licence number together."); + if (!string.IsNullOrWhiteSpace(search.BizName) && search.BizName.Length < 3) + throw new ApiException(HttpStatusCode.BadRequest, "Business name must have at least 3 chars."); + + response = await _licenceRepository.QueryAsync( + new LicenceQry + { + LicenceNumber = search.LicenceNumber, + BizName = search.BizName, + IncludeInactive = true, + Type = ServiceTypeEnum.SecurityBusinessLicence, + }, cancellationToken); + } + + var result = response.Items.Where(r => r.LicenceStatusCode == LicenceStatusEnum.Active || r.LicenceStatusCode == LicenceStatusEnum.Expired || r.LicenceStatusCode == LicenceStatusEnum.Preview) + .GroupBy(r => r.LicenceNumber) + .Select(g => g.OrderByDescending(i => i.CreatedOn).FirstOrDefault()) + .ToList(); + //only return expired and active ones + return _mapper.Map>(result); + + } + private async Task GetSoleProprietorInfoAsync(LicenceResponse lic, LicenceResp licResp, CancellationToken cancellationToken) { if (licResp.ServiceTypeCode == ServiceTypeEnum.SecurityWorkerLicence && licResp.SoleProprietorOrgId != null) @@ -217,4 +267,5 @@ private async Task GetDogRestraintsDocumentsInfoAsync(LicenceResponse lic, Cance lic.RestraintsDocumentInfos = _mapper.Map>(docList.Items); } } + } diff --git a/src/Spd.Presentation.Licensing/Controllers/LicenceController.cs b/src/Spd.Presentation.Licensing/Controllers/LicenceController.cs index 6bcd61192..dd7857be9 100644 --- a/src/Spd.Presentation.Licensing/Controllers/LicenceController.cs +++ b/src/Spd.Presentation.Licensing/Controllers/LicenceController.cs @@ -182,5 +182,30 @@ public async Task GetLicence([FromRoute] Guid licenceId, Cancel { return await _mediator.Send(new LicenceByIdQuery(licenceId), ct); } + + /// + /// Get latest secure worker licence by licence number or firstname, lastname + /// Example: http://localhost:5114/api/licences/security-worker-licence?licenceNumber=E123 + /// http://localhost:5114/api/licences/security-worker-licence?firstName=XXX&lastName=yyy + /// + [Route("api/licences/security-worker-licence")] + [HttpGet] + [AllowAnonymous] + public async Task> SearchSecureWorkerLicence([FromQuery] string? licenceNumber, [FromQuery] string? firstName = null, [FromQuery] string? lastName = null) + { + return await _mediator.Send(new LicenceListSearch(licenceNumber?.Trim(), firstName?.Trim(), lastName?.Trim(), null, ServiceTypeCode.SecurityWorkerLicence)); + } + + /// + /// Get latest secure business licence by licence number or at least the first 3 letters of biz name (for either legal name or trade name) + /// Example: http://localhost:5114/api/licences/business-licence?licenceNumber=B123 + /// + [Route("api/licences/business-licence")] + [HttpGet] + [AllowAnonymous] + public async Task> SearchBizLicence([FromQuery] string? licenceNumber, [FromQuery] string? businessName = null) + { + return await _mediator.Send(new LicenceListSearch(licenceNumber, null, null, businessName, ServiceTypeCode.SecurityBusinessLicence)); + } } } \ No newline at end of file diff --git a/src/Spd.Resource.Repository/Licence/Contract.cs b/src/Spd.Resource.Repository/Licence/Contract.cs index 13b898408..93ae2dce6 100644 --- a/src/Spd.Resource.Repository/Licence/Contract.cs +++ b/src/Spd.Resource.Repository/Licence/Contract.cs @@ -19,6 +19,9 @@ public record LicenceQry public ServiceTypeEnum? Type { get; set; } public bool IncludeInactive { get; set; } public bool? IsExpired { get; set; } + public string? FirstName { get; set; } + public string? LastName { get; set; } + public string? BizName { get; set; } }; public record LicenceListResp { diff --git a/src/Spd.Resource.Repository/Licence/LicenceRepository.cs b/src/Spd.Resource.Repository/Licence/LicenceRepository.cs index f09b281fb..c319bcdb0 100644 --- a/src/Spd.Resource.Repository/Licence/LicenceRepository.cs +++ b/src/Spd.Resource.Repository/Licence/LicenceRepository.cs @@ -43,11 +43,6 @@ public LicenceRepository(IDynamicsContextFactory ctx, public async Task QueryAsync(LicenceQry qry, CancellationToken ct) { - if (qry.LicenceNumber == null && qry.AccountId == null && qry.ContactId == null && qry.LicenceId == null) - { - throw new ArgumentException("at least need 1 parameter to do licence query."); - } - IQueryable lics = _context.spd_licences .Expand(i => i.spd_spd_licence_spd_caselicencecategory_licenceid) .Expand(i => i.spd_LicenceHolder_contact) @@ -90,7 +85,14 @@ public async Task QueryAsync(LicenceQry qry, CancellationToken { lics = lics.Where(a => a.spd_LicenceHolder_contact.spd_accesscode == qry.AccessCode); } - + if (qry.LastName != null || qry.FirstName != null) + { + lics = lics.Where(a => a.spd_LicenceHolder_contact.firstname == qry.FirstName && a.spd_LicenceHolder_contact.lastname == qry.LastName); + } + if (qry.BizName != null) + { + lics = lics.Where(a => a.spd_LicenceHolder_account.name.StartsWith(qry.BizName) || a.spd_LicenceHolder_account.spd_organizationlegalname.StartsWith(qry.BizName)); + } return new LicenceListResp() { Items = _mapper.Map>(lics)