Skip to content
Merged

Dev #1540

Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
62561e6
bugfix/AB#29581 Fix css due to upgrade
samsaravillo Jul 25, 2025
f6a6140
AB#29492: Add ApplicationId in ApplicantAddresses
aurelio-aot Jul 23, 2025
3babf75
AB#29492: Fix EF DB Snapshot
aurelio-aot Jul 23, 2025
9d8c6fc
AB#29492: Add ApplicationId in ApplicationAddress table
aurelio-aot Jul 23, 2025
8a0a88d
AB#29492: database script to populate applicationID in addresses
aurelio-aot Jul 24, 2025
2868659
AB#29492: ApplicantAddress is now related to Application
aurelio-aot Jul 24, 2025
ee4c538
AB#29492: Fix Indigenous indicator bug
aurelio-aot Jul 24, 2025
c231323
AB#29492:Electoral District is not included in the merging choices
aurelio-aot Jul 24, 2025
7219a6e
AB#29492: Fix bug on wrong values to be merged
aurelio-aot Jul 24, 2025
14967a2
AB#29492: Applicant Lookup: Merge Duplicate Applicants
aurelio-aot Jul 26, 2025
461701e
AB#29492: Add message about preserving contact info and address
aurelio-aot Jul 26, 2025
552a5de
AB#29492: Fix sonarqube issues
aurelio-aot Jul 26, 2025
78db0c8
AB#29596 - Remove legacy Supplier Info Permission
plavoie-BC Jul 28, 2025
0af2d31
AB#29596 - Add Payment Configuration UI Fieldset for Edit Permissions
plavoie-BC Jul 28, 2025
c23563a
Merge branch 'dev' into bugfix/AB#29581-CSS-issue
plavoie-BC Jul 28, 2025
028c918
Merge pull request #1536 from bcgov/bugfix/AB#29581-CSS-issue
plavoie-BC Jul 28, 2025
2537487
Merge remote-tracking branch 'origin/dev' into bugfix/AB#29596-paymen…
plavoie-BC Jul 28, 2025
cd12371
Merge pull request #1538 from bcgov/features/AB#29492-Merge-Duplicate…
JamesPasta Jul 29, 2025
f9751dc
Merge pull request #1539 from bcgov/bugfix/AB#29596-payment-ui-config…
JamesPasta Jul 29, 2025
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
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ public override void Define(IPermissionDefinitionContext context)

//-- PAYMENT INFO PERMISSIONS
grantApplicationPermissionsGroup.Add_PaymentInfo_Permissions();
paymentsPermissions.AddChild(PaymentsPermissions.Payments.EditSupplierInfo, L("Permission:Payments.EditSupplierInfo"));
paymentsPermissions.AddChild(PaymentsPermissions.Payments.EditFormPaymentConfiguration, L("Permission:Payments.EditFormPaymentConfiguration"));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -476,7 +476,15 @@ input.form-control, textarea.form-control, .form-select {
text-overflow: ellipsis;
}

input.form-control:hover, textarea.form-control:hover, .form-select:hover {
input.form-control-currency {
font-size: var(--bc-font-size);
color: var(--bc-colors-grey-text-500);
border: 2px solid var(--bc-colors-blue-primary);
text-overflow: ellipsis;
padding-right: 0.75em;
}

input.form-control:hover, textarea.form-control:hover, .form-select:hover, input.form-control-currency:hover {
box-shadow: 0px 2px 4px 0px rgba(0, 0, 0, 0.18);
}

Expand All @@ -487,7 +495,7 @@ input.form-control, textarea.form-control, .form-select {
font-weight: 700;
}

input.form-control:disabled, textarea.form-control:disabled, .form-select:disabled {
input.form-control:disabled, textarea.form-control:disabled, .form-select:disabled, input.form-control-currency:disabled {
color: var(--bc-colors-grey-text-200);
pointer-events: none;
background-color: var(--bc-colors-grey-hover) !important;
Expand All @@ -496,6 +504,15 @@ input.form-control, textarea.form-control, .form-select {
border: none !important;
}

input.form-control-currency:disabled {
color: var(--bc-colors-grey-text-200);
pointer-events: none;
background-color: var(--bc-colors-grey-hover) !important;
opacity: var(--bs-btn-disabled-opacity);
background-blend-mode: difference;
border: var(--bs-border-width) solid var(--bs-border-color) !important;
}

textarea.form-control:disabled {
pointer-events: auto;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@
--bc-layout-margin-large: 24px;
}


.unity-app-container {
background: var(--bc-colors-white-background);
height: 100%; /* confirm this */
Expand Down Expand Up @@ -619,6 +618,16 @@ div.dataTables_filter > label > input {
.checkbox-select:checked {
outline: 1px solid var(--bc-colors-blue-primary);
outline-style: auto;
accent-color: var(--bc-colors-blue-primary) !important;
}

input[type="radio"] {
accent-color: var(--bc-colors-blue-primary) !important;
}

.nav-pills .nav-link.active, .nav-pills .show > .nav-link {
color: var(--bs-nav-pills-link-active-color) !important;
background-color: var(--bs-nav-pills-link-active-bg) !important;
}

div.dataTables_wrapper div.dataTables_filter {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ public class ApplicantAppService(IApplicantRepository applicantRepository,
protected new ILogger Logger => LazyServiceProvider.LazyGetService<ILogger>(provider => LoggerFactory?.CreateLogger(GetType().FullName!) ?? NullLogger.Instance);

[RemoteService(false)]
public async Task<Applicant> CreateOrRetrieveApplicantAsync(IntakeMapping intakeMap)
public async Task<Applicant> CreateOrRetrieveApplicantAsync(IntakeMapping intakeMap, Guid applicationId)
{
ArgumentNullException.ThrowIfNull(intakeMap);

Expand All @@ -60,7 +60,7 @@ public async Task<Applicant> CreateOrRetrieveApplicantAsync(IntakeMapping intake
applicant.FiscalMonth = intakeMap.FiscalMonth ?? applicant.FiscalMonth;
}

await CreateApplicantAddressesAsync(intakeMap, applicant);
await CreateApplicantAddressesAsync(intakeMap, applicant, applicationId);
return applicant;
}

Expand Down Expand Up @@ -301,7 +301,7 @@ private async Task<Applicant> CreateNewApplicantAsync(IntakeMapping intakeMap)
return await applicantRepository.InsertAsync(applicant);
}

private async Task CreateApplicantAddressesAsync(IntakeMapping intakeMap, Applicant applicant)
private async Task CreateApplicantAddressesAsync(IntakeMapping intakeMap, Applicant applicant, Guid applicationId)
{
ArgumentNullException.ThrowIfNull(intakeMap);

Expand All @@ -318,7 +318,8 @@ await addressRepository.InsertAsync(new ApplicantAddress
Street = intakeMap.PhysicalStreet,
Street2 = intakeMap.PhysicalStreet2,
Unit = intakeMap.PhysicalUnit,
AddressType = AddressType.PhysicalAddress
AddressType = AddressType.PhysicalAddress,
ApplicationId = applicationId
});
}

Expand All @@ -335,7 +336,8 @@ await addressRepository.InsertAsync(new ApplicantAddress
Street = intakeMap.MailingStreet,
Street2 = intakeMap.MailingStreet2,
Unit = intakeMap.MailingUnit,
AddressType = AddressType.MailingAddress
AddressType = AddressType.MailingAddress,
ApplicationId = applicationId
});
}
}
Expand Down Expand Up @@ -385,8 +387,38 @@ public async Task UpdateApplicantIdAsync(UpdateApplicantIdDto dto)

//Update ApplicantAgent records
await UpdateApplicantAgentRecordsAsync(oldApplicantId, dto.ApplicantId, dto.ApplicationId);

//Update ApplicantAddresses records
await UpdateApplicantAddressRecords(oldApplicantId, dto.ApplicantId, dto.ApplicationId);
}

private async Task UpdateApplicantAddressRecords(Guid oldApplicantId, Guid newApplicantId, Guid applicationId)
{
try
{
List<ApplicantAddress> applicantAddresses = await addressRepository.FindByApplicantIdAndApplicationIdAsync(oldApplicantId, applicationId);
await UpdateAddress(applicantAddresses, AddressType.MailingAddress, newApplicantId, applicationId);
await UpdateAddress(applicantAddresses, AddressType.PhysicalAddress, newApplicantId, applicationId);
}
catch (Exception ex)
{
Logger.LogError(ex, "Error updating ApplicantAddress records for ApplicationId: {ApplicationId}", applicationId);
throw new UserFriendlyException("An error occurred while updating applicant address records.");
}
}

private async Task UpdateAddress(List<ApplicantAddress> applicantAddresses, AddressType applicantAddressType, Guid newApplicantId, Guid applicationId)
{
ApplicantAddress? dbAddress = applicantAddresses.Find(address => address.AddressType == applicantAddressType && address.ApplicationId == applicationId);

if (dbAddress != null)
{
dbAddress.ApplicantId = newApplicantId;
await addressRepository.UpdateAsync(dbAddress);
}
}


[RemoteService(true)]
public async Task SetDuplicatedAsync(SetApplicantDuplicateDto dto)
{
Expand Down Expand Up @@ -435,24 +467,13 @@ private async Task UpdateApplicantAgentRecordsAsync(Guid oldApplicantId, Guid ne
{
var agentQueryable = await applicantAgentRepository.GetQueryableAsync();

// Detach old agent from application
var oldAgent = await agentQueryable
var agent = await agentQueryable
.FirstOrDefaultAsync(a => a.ApplicantId == oldApplicantId && a.ApplicationId == applicationId);

if (oldAgent != null)
{
oldAgent.ApplicationId = null;
await applicantAgentRepository.UpdateAsync(oldAgent);
}

// Attach new agent to application
var newAgent = await agentQueryable
.FirstOrDefaultAsync(a => a.ApplicantId == newApplicantId);

if (newAgent != null)
if (agent != null)
{
newAgent.ApplicationId = applicationId;
await applicantAgentRepository.UpdateAsync(newAgent);
agent.ApplicantId = newApplicantId;
await applicantAgentRepository.UpdateAsync(agent);
}
}
catch (Exception ex)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ namespace Unity.GrantManager.Applicants;

public interface IApplicantAppService : IApplicationService
{
Task<Applicant> CreateOrRetrieveApplicantAsync(IntakeMapping intakeMap);
Task<Applicant> CreateOrRetrieveApplicantAsync(IntakeMapping intakeMap, Guid applicationId);
Task<ApplicantAgent> CreateApplicantAgentAsync(ApplicantAgentDto applicantAgentDto);
Task<Applicant> RelateSupplierToApplicant(ApplicantSupplierEto applicantSupplierEto);
Task RelateDefaultSupplierAsync(ApplicantAgentDto applicantAgentDto);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
using Unity.GrantManager.GrantApplications;
using Unity.GrantManager.Integration.Chefs;
using Unity.GrantManager.Permissions;
using Unity.Payments.Permissions;
using Volo.Abp;
using Volo.Abp.Application.Dtos;
using Volo.Abp.Application.Services;
Expand Down Expand Up @@ -160,6 +161,7 @@ public async Task PatchOtherConfig(Guid id, OtherConfigDto config)
await _applicationFormRepository.UpdateAsync(form);
}

[Authorize(PaymentsPermissions.Payments.EditFormPaymentConfiguration)]
public async Task SavePaymentConfiguration(FormPaymentConfigurationDto dto)
{
ApplicationForm appForm = await _applicationFormRepository.GetAsync(dto.ApplicationFormId);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -180,14 +180,14 @@ public async Task<GrantApplicationDto> UpdatePartialApplicantInfoAsync(Guid appl
&& await AuthorizationService.IsGrantedAsync(UnitySelector.Applicant.Location.Update))
{
input.Data.PhysicalAddress.AddressType = AddressType.PhysicalAddress;
await CreateOrUpdateApplicantAddress(application.ApplicantId, input.Data.PhysicalAddress);
await CreateOrUpdateApplicantAddress(applicationId, application.ApplicantId, input.Data.PhysicalAddress);
}

if (input.Data.MailingAddress != null
&& await AuthorizationService.IsGrantedAsync(UnitySelector.Applicant.Location.Update))
{
input.Data.MailingAddress.AddressType = AddressType.MailingAddress;
await CreateOrUpdateApplicantAddress(application.ApplicantId, input.Data.MailingAddress);
await CreateOrUpdateApplicantAddress(applicationId, application.ApplicantId, input.Data.MailingAddress);
}

//-- APPLICANT INFO CUSTOM FIELDS
Expand Down Expand Up @@ -279,15 +279,16 @@ public async Task<GrantApplicationDto> UpdatePartialApplicantInfoAsync(Guid appl
/// <param name="modifiedFields"></param>
/// <returns></returns>
[Authorize(UnitySelector.Applicant.Location.Update)]
protected internal async Task CreateOrUpdateApplicantAddress(Guid applicantId, UpdateApplicantAddressDto updatedAddress)
protected internal async Task CreateOrUpdateApplicantAddress(Guid applicationId, Guid applicantId, UpdateApplicantAddressDto updatedAddress)
{
var applicantAddresses = await applicantAddressRepository.FindByApplicantIdAsync(applicantId);
var applicantAddresses = await applicantAddressRepository.FindByApplicantIdAndApplicationIdAsync(applicantId, applicationId);

ApplicantAddress? dbAddress = applicantAddresses.FirstOrDefault(a => a.AddressType == updatedAddress.AddressType)
?? new ApplicantAddress
{
ApplicantId = applicantId,
AddressType = updatedAddress.AddressType,
ApplicationId = applicationId,
};

ObjectMapper.Map<UpdateApplicantAddressDto, ApplicantAddress>(updatedAddress, dbAddress);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -646,7 +646,7 @@ public async Task<GrantApplicationDto> UpdateProjectApplicantInfoAsync(Guid id,
applicantAgent = await _applicantAgentRepository.UpdateAsync(applicantAgent);
}

await UpdateApplicantAddresses(input);
await UpdateApplicantAddresses(application.Id, input);

application.SigningAuthorityFullName = input.SigningAuthorityFullName ?? "";
application.SigningAuthorityTitle = input.SigningAuthorityTitle ?? "";
Expand All @@ -669,6 +669,32 @@ public async Task<GrantApplicationDto> UpdateProjectApplicantInfoAsync(Guid id,
return appDto;
}

[Authorize(UnitySelector.Applicant.UpdatePolicy)]
public async Task UpdateMergedApplicantAsync(Guid applicationId, CreateUpdateApplicantInfoDto input)
{
var application = await _applicationRepository.GetAsync(applicationId);

var applicant = await _applicantRepository
.FirstOrDefaultAsync(a => a.Id == application.ApplicantId) ?? throw new EntityNotFoundException();

applicant.OrganizationType = input.OrganizationType ?? "";
applicant.OrgName = input.OrgName ?? "";
applicant.OrgNumber = input.OrgNumber ?? "";
applicant.OrgStatus = input.OrgStatus ?? "";
applicant.OrganizationSize = input.OrganizationSize ?? "";
applicant.Sector = input.Sector ?? "";
applicant.SubSector = input.SubSector ?? "";
applicant.SectorSubSectorIndustryDesc = input.SectorSubSectorIndustryDesc ?? "";
applicant.IndigenousOrgInd = input.IndigenousOrgInd ?? "";
applicant.UnityApplicantId = input.UnityApplicantId ?? "";
applicant.FiscalDay = input.FiscalDay;
applicant.FiscalMonth = input.FiscalMonth ?? "";
applicant.NonRegOrgName = input.NonRegOrgName ?? "";
applicant.ApplicantName = input.ApplicantName ?? "";

_ = await _applicantRepository.UpdateAsync(applicant);
}

protected virtual async Task PublishCustomFieldUpdatesAsync(Guid applicationId,
string uiAnchor,
CustomDataFieldDto input)
Expand All @@ -695,19 +721,19 @@ await _localEventBus.PublishAsync(new PersistWorksheetIntanceValuesEto()
}
}

protected virtual async Task UpdateApplicantAddresses(CreateUpdateApplicantInfoDto input)
protected virtual async Task UpdateApplicantAddresses(Guid applicationId, CreateUpdateApplicantInfoDto input)
{
List<ApplicantAddress> applicantAddresses = await _applicantAddressRepository.FindByApplicantIdAsync(input.ApplicantId);
List<ApplicantAddress> applicantAddresses = await _applicantAddressRepository.FindByApplicantIdAndApplicationIdAsync(input.ApplicantId, applicationId);
if (applicantAddresses != null)
{
await UpsertAddress(input, applicantAddresses, AddressType.MailingAddress, input.ApplicantId);
await UpsertAddress(input, applicantAddresses, AddressType.PhysicalAddress, input.ApplicantId);
await UpsertAddress(input, applicantAddresses, AddressType.MailingAddress, input.ApplicantId, applicationId);
await UpsertAddress(input, applicantAddresses, AddressType.PhysicalAddress, input.ApplicantId, applicationId);
}
}

protected virtual async Task UpsertAddress(CreateUpdateApplicantInfoDto input, List<ApplicantAddress> applicantAddresses, AddressType applicantAddressType, Guid applicantId)
protected virtual async Task UpsertAddress(CreateUpdateApplicantInfoDto input, List<ApplicantAddress> applicantAddresses, AddressType applicantAddressType, Guid applicantId, Guid applicationId)
{
ApplicantAddress? dbAddress = applicantAddresses.Find(address => address.AddressType == applicantAddressType);
ApplicantAddress? dbAddress = applicantAddresses.Find(address => address.AddressType == applicantAddressType && address.ApplicationId == applicationId);

if (dbAddress != null)
{
Expand All @@ -716,7 +742,7 @@ protected virtual async Task UpsertAddress(CreateUpdateApplicantInfoDto input, L
}
else
{
var newAddress = new ApplicantAddress() { AddressType = applicantAddressType, ApplicantId = applicantId };
var newAddress = new ApplicantAddress() { AddressType = applicantAddressType, ApplicantId = applicantId, ApplicationId = applicationId };
MapApplicantAddress(input, applicantAddressType, newAddress);
await _applicantAddressRepository.InsertAsync(newAddress);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,14 +98,12 @@ await localEventBus.PublishAsync(new ApplicationProcessEvent

private async Task<Application> CreateNewApplicationAsync(IntakeMapping intakeMap,
ApplicationForm applicationForm)
{
var applicant = await applicantService.CreateOrRetrieveApplicantAsync(intakeMap);
{
var submittedStatus = await _applicationStatusRepository.FirstAsync(s => s.StatusCode.Equals(GrantApplicationState.SUBMITTED));
var application = await _applicationRepository.InsertAsync(
new Application
{
ProjectName = MappingUtil.ResolveAndTruncateField(255, string.Empty, intakeMap.ProjectName),
ApplicantId = applicant.Id,
ProjectName = MappingUtil.ResolveAndTruncateField(255, string.Empty, intakeMap.ProjectName),
ApplicationFormId = applicationForm.Id,
ApplicationStatusId = submittedStatus.Id,
ReferenceNo = intakeMap.ConfirmationId ?? string.Empty,
Expand Down Expand Up @@ -134,6 +132,13 @@ private async Task<Application> CreateNewApplicationAsync(IntakeMapping intakeMa
}
);

var applicant = await applicantService.CreateOrRetrieveApplicantAsync(intakeMap, application.Id);
if (applicant != null)
{
application.ApplicantId = applicant.Id;
application = await _applicationRepository.UpdateAsync(application);
}

ApplicantAgentDto applicantAgentDto = new()
{
Applicant = applicant,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ namespace Unity.GrantManager.Applications;
public class ApplicantAddress : AuditedAggregateRoot<Guid>, IMultiTenant
{
public Guid? ApplicantId { get; set; }

[JsonIgnore]
public virtual Applicant Applicant
{
Expand All @@ -20,6 +20,17 @@ public virtual Applicant Applicant
}
private Applicant? _applicant;

public Guid? ApplicationId { get; set; }

[JsonIgnore]
public virtual Application Application
{
set => _application = value;
get => _application
?? throw new InvalidOperationException("Uninitialized property: " + nameof(Application));
}
private Application? _application;

public string? City { get; set; } = string.Empty;
public string? Country { get; set; } = string.Empty;
public string? Province { get; set; } = string.Empty;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@ public virtual ApplicationStatus ApplicationStatus
public string? ContractNumber { get; set; }
public DateTime? ContractExecutionDate { get; set; }
public string? RiskRanking { get; set; }
public virtual Collection<ApplicantAddress>? ApplicantAddresses { get; set; }

public bool IsInFinalDecisionState()
{
Expand Down
Loading