Skip to content

Commit

Permalink
refactor cm api (#1368)
Browse files Browse the repository at this point in the history
# Description

This PR includes the following proposed change(s):

- [refactor cm api](spdbt-3011: refactor controlling member api)
  • Loading branch information
peggy-quartech authored Sep 7, 2024
1 parent c29d428 commit 592cde7
Show file tree
Hide file tree
Showing 7 changed files with 242 additions and 44 deletions.
24 changes: 16 additions & 8 deletions src/Spd.Manager.Licence/BizMemberContract.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,30 @@ namespace Spd.Manager.Licence;
public interface IBizMemberManager
{
public Task<Members> Handle(GetBizMembersQuery query, CancellationToken ct);
public Task<BizMemberResponse> Handle(CreateBizEmployeeCommand cmd, CancellationToken ct);
public Task<BizMemberResponse> Handle(CreateBizSwlControllingMemberCommand cmd, CancellationToken ct);
public Task<BizMemberResponse> Handle(CreateBizNonSwlControllingMemberCommand cmd, CancellationToken ct);
public Task<BizMemberResponse> Handle(UpdateBizNonSwlControllingMemberCommand cmd, CancellationToken ct);
public Task<Unit> Handle(DeleteBizMemberCommand cmd, CancellationToken ct);
public Task<Unit> Handle(UpsertBizMembersCommand cmd, CancellationToken ct);
public Task<ControllingMemberInvitesCreateResponse> Handle(BizControllingMemberNewInviteCommand command, CancellationToken ct);
public Task<ControllingMemberAppInviteVerifyResponse> Handle(VerifyBizControllingMemberInviteCommand command, CancellationToken ct);
}

public record BizControllingMemberNewInviteCommand(Guid BizContactId, Guid UserId, string HostUrl) : IRequest<ControllingMemberInvitesCreateResponse>;
public record VerifyBizControllingMemberInviteCommand(string InviteEncryptedCode) : IRequest<ControllingMemberAppInviteVerifyResponse>;

public record GetBizMembersQuery(Guid BizId, Guid? AppId = null) : IRequest<Members>;

public record UpsertBizMembersCommand(
Guid BizId,
Guid? ApplicationId,
Members Members,
IEnumerable<LicAppFileInfo> LicAppFileInfos) : IRequest<Unit>; //deprecated
public record CreateBizEmployeeCommand(Guid BizId, SwlContactInfo Employee) : IRequest<BizMemberResponse>;
public record CreateBizSwlControllingMemberCommand(Guid BizId, SwlContactInfo SwlControllingMember) : IRequest<BizMemberResponse>;
public record CreateBizNonSwlControllingMemberCommand(Guid BizId, NonSwlContactInfo NonSwlControllingMember) : IRequest<BizMemberResponse>;
public record UpdateBizNonSwlControllingMemberCommand(Guid BizId, Guid BizContactId, NonSwlContactInfo NonSwlControllingMember) : IRequest<BizMemberResponse>;
public record DeleteBizMemberCommand(Guid BizId, Guid BizContactId) : IRequest<Unit>;
public record BizMemberResponse(Guid? bizContactId);
public record Members
{
public IEnumerable<SwlContactInfo> SwlControllingMembers { get; set; }
Expand All @@ -27,12 +41,6 @@ public record MembersRequest : Members
public IEnumerable<Guid> ControllingMemberDocumentKeyCodes { get; set; } = Array.Empty<Guid>();//the document is saved in cache.
}

public record UpsertBizMembersCommand(
Guid BizId,
Guid? ApplicationId,
Members Members,
IEnumerable<LicAppFileInfo> LicAppFileInfos) : IRequest<Unit>;

public record ControllingMemberInvitesCreateResponse(Guid BizContactId)
{
public bool CreateSuccess { get; set; }
Expand Down
43 changes: 42 additions & 1 deletion src/Spd.Manager.Licence/BizMemberManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,11 @@ internal class BizMemberManager :
IRequestHandler<UpsertBizMembersCommand, Unit>,
IRequestHandler<BizControllingMemberNewInviteCommand, ControllingMemberInvitesCreateResponse>,
IRequestHandler<VerifyBizControllingMemberInviteCommand, ControllingMemberAppInviteVerifyResponse>,
IRequestHandler<CreateBizEmployeeCommand, BizMemberResponse>,
IRequestHandler<CreateBizSwlControllingMemberCommand, BizMemberResponse>,
IRequestHandler<CreateBizNonSwlControllingMemberCommand, BizMemberResponse>,
IRequestHandler<UpdateBizNonSwlControllingMemberCommand, BizMemberResponse>,
IRequestHandler<DeleteBizMemberCommand, Unit>,
IBizMemberManager
{
private readonly IBizLicApplicationRepository _bizLicApplicationRepository;
Expand Down Expand Up @@ -106,7 +111,6 @@ public async Task<ControllingMemberInvitesCreateResponse> Handle(BizControllingM
throw new ApiException(HttpStatusCode.BadRequest, "Cannot send out invitation when there is no email address provided.");
if (contactResp.LatestControllingMemberCrcAppPortalStatusEnum != null)
throw new ApiException(HttpStatusCode.BadRequest, "This business contact already has a CRC application");
//todo : how can we check if the CRC approved but it has been expired.

var createCmd = _mapper.Map<ControllingMemberInviteCreateCmd>(contactResp);
createCmd.CreatedByUserId = cmd.UserId;
Expand Down Expand Up @@ -137,6 +141,43 @@ public async Task<Members> Handle(GetBizMembersQuery qry, CancellationToken ct)
return members;
}

public async Task<BizMemberResponse> Handle(CreateBizEmployeeCommand cmd, CancellationToken ct)
{
BizContact bizContact = _mapper.Map<BizContact>(cmd.Employee);
bizContact.BizContactRoleCode = BizContactRoleEnum.Employee;
bizContact.BizId = cmd.BizId;
Guid? bizContactId = await _bizContactRepository.ManageBizContactsAsync(new BizContactCreateCmd(bizContact), ct);
return new BizMemberResponse(bizContactId);
}
public async Task<BizMemberResponse> Handle(CreateBizSwlControllingMemberCommand cmd, CancellationToken ct)
{
BizContact bizContact = _mapper.Map<BizContact>(cmd.SwlControllingMember);
bizContact.BizContactRoleCode = BizContactRoleEnum.ControllingMember;
bizContact.BizId = cmd.BizId;
Guid? bizContactId = await _bizContactRepository.ManageBizContactsAsync(new BizContactCreateCmd(bizContact), ct);
return new BizMemberResponse(bizContactId);
}
public async Task<BizMemberResponse> Handle(CreateBizNonSwlControllingMemberCommand cmd, CancellationToken ct)
{
BizContact bizContact = _mapper.Map<BizContact>(cmd.NonSwlControllingMember);
bizContact.BizContactRoleCode = BizContactRoleEnum.ControllingMember;
bizContact.BizId = cmd.BizId;
Guid? bizContactId = await _bizContactRepository.ManageBizContactsAsync(new BizContactCreateCmd(bizContact), ct);
return new BizMemberResponse(bizContactId);
}
public async Task<Unit> Handle(DeleteBizMemberCommand cmd, CancellationToken ct)
{
await _bizContactRepository.ManageBizContactsAsync(new BizContactDeleteCmd(cmd.BizContactId), ct);
return default;
}
public async Task<BizMemberResponse> Handle(UpdateBizNonSwlControllingMemberCommand cmd, CancellationToken ct)
{
BizContact bizContact = _mapper.Map<BizContact>(cmd.NonSwlControllingMember);
bizContact.BizContactRoleCode = BizContactRoleEnum.ControllingMember;
bizContact.BizId = cmd.BizId;
Guid? bizContactId = await _bizContactRepository.ManageBizContactsAsync(new BizContactUpdateCmd(cmd.BizContactId, bizContact), ct);
return new BizMemberResponse(bizContactId);
}
public async Task<Unit> Handle(UpsertBizMembersCommand cmd, CancellationToken ct)
{
await UpdateMembersAsync(cmd.Members, cmd.BizId, ct);
Expand Down
4 changes: 2 additions & 2 deletions src/Spd.Manager.Licence/Mappings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -352,7 +352,8 @@ public Mappings()
CreateMap<BizContactResp, ControllingMemberInviteCreateCmd>()
.IncludeBase<BizContactResp, ControllingMemberInvite>()
.ForMember(d => d.HostUrl, opt => opt.Ignore());

CreateMap<SwlContactInfo, BizContact>();
CreateMap<NonSwlContactInfo, BizContact>();
CreateMap<ControllingMemberCrcApplicationResp, ControllingMemberCrcAppResponse>()
.ForMember(d => d.ResidentialAddress, opt => opt.MapFrom(s => s.ResidentialAddressData))
.ForPath(d => d.ResidentialAddress.AddressLine1, opt => opt.MapFrom(s => s.ResidentialAddressData.AddressLine1))
Expand Down Expand Up @@ -647,7 +648,6 @@ private static List<BranchAddr> GetBranchAddr(IEnumerable<BranchInfo> branchInfo
{LicenceDocumentTypeCode.CorporateRegistryDocument, DocumentTypeEnum.CorporateRegistryDocument }
}.ToImmutableDictionary();


private static readonly ImmutableDictionary<LicenceDocumentTypeCode, DocumentTypeEnum> LicenceDocumentType2Dictionary = new Dictionary<LicenceDocumentTypeCode, DocumentTypeEnum>()
{
{LicenceDocumentTypeCode.BcServicesCard, DocumentTypeEnum.AdditionalGovIdDocument},
Expand Down
82 changes: 79 additions & 3 deletions src/Spd.Presentation.Licensing/Controllers/BizMembersController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ public BizMembersController(IPrincipal currentUser,
/// <param name="applicationId"></param>
/// <param name="ct"></param>
/// <returns></returns>
[Route("api/business-licence-application/{bizId}/members")]
[Route("api/business/{bizId}/members")]
[HttpGet]
[Authorize(Policy = "OnlyBceid", Roles = "PrimaryBusinessManager,BusinessManager")]
public async Task<Members> GetMembers([FromRoute] Guid bizId, CancellationToken ct)
Expand All @@ -48,13 +48,13 @@ public async Task<Members> GetMembers([FromRoute] Guid bizId, CancellationToken
}

/// <summary>
/// Upsert Biz Application controlling members and employees, controlling members include swl and non-swl
/// Deprecated. Upsert Biz Application controlling members and employees, controlling members include swl and non-swl
/// </summary>
/// <param name="bizId"></param>
/// <param name="applicationId"></param>
/// <param name="ct"></param>
/// <returns></returns>
[Route("api/business-licence-application/{bizId}/members")]
[Route("api/business/{bizId}/members")]
[HttpPost]
[Authorize(Policy = "OnlyBceid", Roles = "PrimaryBusinessManager,BusinessManager")]
public async Task<ActionResult> UpsertMembers([FromRoute] Guid bizId, [FromBody] MembersRequest members, CancellationToken ct)
Expand All @@ -68,6 +68,82 @@ public async Task<ActionResult> UpsertMembers([FromRoute] Guid bizId, [FromBody]
return Ok();
}

/// <summary>
/// Create Biz employee
/// </summary>
/// <param name="bizId"></param>
/// <param name="employee"></param>
/// <param name="ct"></param>
/// <returns></returns>
[Route("api/business/{bizId}/employees")]
[HttpPost]
[Authorize(Policy = "OnlyBceid", Roles = "PrimaryBusinessManager,BusinessManager")]
public async Task<BizMemberResponse> CreateEmployee([FromRoute] Guid bizId, [FromBody] SwlContactInfo employee, CancellationToken ct)
{
return await _mediator.Send(new CreateBizEmployeeCommand(bizId, employee), ct);
}

/// <summary>
/// Create Biz swl controlling member
/// </summary>
/// <param name="bizId"></param>
/// <param name="controllingMember"></param>
/// <param name="ct"></param>
/// <returns></returns>
[Route("api/business/{bizId}/swl-controlling-members")]
[HttpPost]
[Authorize(Policy = "OnlyBceid", Roles = "PrimaryBusinessManager,BusinessManager")]
public async Task<BizMemberResponse> CreateSwlControllingMember([FromRoute] Guid bizId, [FromBody] SwlContactInfo controllingMember, CancellationToken ct)
{
return await _mediator.Send(new CreateBizSwlControllingMemberCommand(bizId, controllingMember), ct);
}

/// <summary>
/// Create Biz swl controlling member
/// </summary>
/// <param name="bizId"></param>
/// <param name="employee"></param>
/// <param name="ct"></param>
/// <returns></returns>
[Route("api/business/{bizId}/non-swl-controlling-members")]
[HttpPost]
[Authorize(Policy = "OnlyBceid", Roles = "PrimaryBusinessManager,BusinessManager")]
public async Task<BizMemberResponse> CreateNonSwlControllingMember([FromRoute] Guid bizId, [FromBody] NonSwlContactInfo controllingMember, CancellationToken ct)
{
return await _mediator.Send(new CreateBizNonSwlControllingMemberCommand(bizId, controllingMember), ct);
}

/// <summary>
/// Update Non swl biz controlling member
/// </summary>
/// <param name="bizId"></param>
/// <param name="bizContactId"></param>
/// <param name="ct"></param>
/// <returns></returns>
[Route("api/business/{bizId}/non-swl-controlling-members/{bizContactId}")]
[HttpPut]
[Authorize(Policy = "OnlyBceid", Roles = "PrimaryBusinessManager,BusinessManager")]
public async Task<BizMemberResponse> UpdateNonSwlControllingMember([FromRoute] Guid bizId, [FromRoute] Guid bizContactId, NonSwlContactInfo controllingMember, CancellationToken ct)
{
return await _mediator.Send(new UpdateBizNonSwlControllingMemberCommand(bizId, bizContactId, controllingMember), ct);
}

/// <summary>
/// Delete Biz swl controlling member
/// </summary>
/// <param name="bizId"></param>
/// <param name="bizContactId"></param>
/// <param name="ct"></param>
/// <returns></returns>
[Route("api/business/{bizId}/members/{bizContactId}")]
[HttpDelete]
[Authorize(Policy = "OnlyBceid", Roles = "PrimaryBusinessManager,BusinessManager")]
public async Task<ActionResult> DeleteBizMember([FromRoute] Guid bizId, [FromRoute] Guid bizContactId, CancellationToken ct)
{
await _mediator.Send(new DeleteBizMemberCommand(bizId, bizContactId), ct);
return Ok();
}

/// <summary>
/// Create controlling member crc invitation for this biz contact
/// </summary>
Expand Down
69 changes: 66 additions & 3 deletions src/Spd.Resource.Repository/BizContact/BizContactRepository.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using AutoMapper;
using MediatR;
using Microsoft.Dynamics.CRM;
using Microsoft.Extensions.Logging;
using Spd.Utilities.Dynamics;
Expand Down Expand Up @@ -52,7 +51,71 @@ public async Task<IEnumerable<BizContactResp>> QueryBizContactsAsync(BizContactQ
return _mapper.Map<IEnumerable<BizContactResp>>(bizContacts.ToList());
}

public async Task<Unit> ManageBizContactsAsync(BizContactUpsertCmd cmd, CancellationToken ct)
public async Task<Guid?> ManageBizContactsAsync(BizContactCmd cmd, CancellationToken ct)
{
return cmd switch
{
BizContactCreateCmd c => await CreateBizContactAsync(c, ct),
BizContactUpdateCmd c => await UpdateBizContactAsync(c, ct),
BizContactDeleteCmd c => await DeleteBizContactAsync(c, ct),
_ => throw new NotSupportedException($"{cmd.GetType().Name} is not supported")
};
}

private async Task<Guid?> CreateBizContactAsync(BizContactCreateCmd cmd, CancellationToken ct)
{
account? biz = await _context.GetOrgById(cmd.BizContact.BizId, ct);
spd_businesscontact bizContact = _mapper.Map<spd_businesscontact>(cmd.BizContact);
bizContact.spd_businesscontactid = Guid.NewGuid();
contact? c = null;
if (cmd.BizContact.ContactId != null)
{
c = await _context.GetContactById((Guid)cmd.BizContact.ContactId, ct);
if (c == null)
throw new ApiException(HttpStatusCode.BadRequest, $"invalid contact {cmd.BizContact.ContactId.Value}");
bizContact.spd_fullname = $"{c.lastname},{c.firstname}";
}
_context.AddTospd_businesscontacts(bizContact);
if (c != null)
_context.SetLink(bizContact, nameof(bizContact.spd_ContactId), c);
if (cmd.BizContact.LicenceId != null)
{
spd_licence? swlLic = _context.spd_licences.Where(l => l.spd_licenceid == cmd.BizContact.LicenceId && l.statecode == DynamicsConstants.StateCode_Active).FirstOrDefault();
Guid swlServiceTypeId = DynamicsContextLookupHelpers.ServiceTypeGuidDictionary[ServiceTypeEnum.SecurityWorkerLicence.ToString()];
//only swl can be linked to.
if (swlLic == null || swlLic._spd_licencetype_value != swlServiceTypeId)
throw new ApiException(System.Net.HttpStatusCode.BadRequest, $"invalid licence {cmd.BizContact.LicenceId}");
_context.SetLink(bizContact, nameof(bizContact.spd_SWLNumber), swlLic);
}
_context.SetLink(bizContact, nameof(bizContact.spd_OrganizationId), biz);
await _context.SaveChangesAsync(ct);
return bizContact.spd_businesscontactid;
}

private async Task<Guid?> DeleteBizContactAsync(BizContactDeleteCmd cmd, CancellationToken ct)
{
spd_businesscontact? bizContact = await _context.GetBizContactById(cmd.BizContactId, ct);
bizContact.statecode = DynamicsConstants.StateCode_Inactive;
_context.UpdateObject(bizContact);
await _context.SaveChangesAsync(ct);
return null;
}

private async Task<Guid?> UpdateBizContactAsync(BizContactUpdateCmd cmd, CancellationToken ct)
{
spd_businesscontact? bizContact = await _context.GetBizContactById(cmd.BizContactId, ct);
if (bizContact == null) throw new ApiException(HttpStatusCode.BadRequest, "Cannot find the member.");
if (bizContact.spd_role != (int)BizContactRoleOptionSet.ControllingMember)
throw new ApiException(HttpStatusCode.BadRequest, "Cannot update non-controlling member.");
if (bizContact._spd_swlnumber_value != null)
throw new ApiException(HttpStatusCode.BadRequest, "Cannot update controlling member with secure worker licence.");
_mapper.Map<BizContact, spd_businesscontact>(cmd.BizContact, bizContact);
_context.UpdateObject(bizContact);
await _context.SaveChangesAsync(ct);
return cmd.BizContactId;
}

private async Task<Guid?> UpsertBizContacts(BizContactUpsertCmd cmd, CancellationToken ct)
{
IQueryable<spd_businesscontact> bizContacts = _context.spd_businesscontacts
.Expand(b => b.spd_businesscontact_spd_application)
Expand Down Expand Up @@ -116,7 +179,7 @@ public async Task<Unit> ManageBizContactsAsync(BizContactUpsertCmd cmd, Cancella
}
}
await _context.SaveChangesAsync(ct);
return default;
return null;
}

}
Expand Down
Loading

0 comments on commit 592cde7

Please sign in to comment.