From cc9ead786c9d53113b56b32176b3594db136b3c4 Mon Sep 17 00:00:00 2001 From: aurelio-aot Date: Mon, 15 Jun 2026 19:37:36 -0700 Subject: [PATCH 01/20] AB#30134: Use ApproxNumberOfEmployees Instead Of OrganizationSize --- .../ProfileData/OrgInfoItemDto.cs | 4 + .../Applicants/ApplicantListDto.cs | 1 - .../GrantApplications/ApplicantSummaryDto.cs | 2 +- .../CreateUpdateApplicantInfoDto.cs | 4 +- .../GrantApplicationApplicant.cs | 2 +- .../GrantApplications/GrantApplicationDto.cs | 2 +- .../UpdateApplicantSummaryDto.cs | 2 +- .../DataProviders/OrgInfoDataProvider.cs | 5 +- .../Applicants/ApplicantAppService.cs | 1 - .../GrantApplicationAppService.cs | 200 +++++++++--------- .../GrantManagerApplicationMapperlyProfile.cs | 4 +- .../Handlers/OrganizationEditHandler.cs | 2 +- .../Messages/Commands/OrganizationEditData.cs | 7 + .../Localization/GrantManager/en.json | 1 + .../Applications/Applicant.cs | 3 + .../Applications/ApplicationListRecord.cs | 2 +- .../Repositories/ApplicantRepository.cs | 1 - .../Repositories/ApplicationRepository.cs | 4 +- .../Mapping/GrantManagerWebMapperlyProfile.cs | 4 +- .../Pages/Applicants/Index.js | 17 +- .../ApplicantSummaryViewModel.cs | 4 +- .../Components/ApplicantInfo/Default.cshtml | 12 +- .../Components/ApplicantInfo/Default.js | 6 +- .../ApplicantOrganizationInfoViewComponent.cs | 2 +- .../ApplicantOrganizationInfoViewModel.cs | 2 +- .../ApplicantOrganizationInfo/Default.cshtml | 2 +- .../ApplicantOrganizationInfo/Default.js | 2 +- .../ApplicantsActionBar/ListMerge.js | 4 +- .../Applicants/OrgInfoDataProviderTests.cs | 2 +- .../ApplicationListRecordAlignmentTests.cs | 4 +- .../OrganizationEditHandlerTests.cs | 2 +- .../applicant-profile-data-providers.md | 6 +- 32 files changed, 158 insertions(+), 158 deletions(-) diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/ApplicantProfile/ProfileData/OrgInfoItemDto.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/ApplicantProfile/ProfileData/OrgInfoItemDto.cs index 4de11bf387..7c9bb154b8 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/ApplicantProfile/ProfileData/OrgInfoItemDto.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/ApplicantProfile/ProfileData/OrgInfoItemDto.cs @@ -14,7 +14,11 @@ public class OrgInfoItemDto public string? NonRegOrgName { get; set; } public string? FiscalMonth { get; set; } public int? FiscalDay { get; set; } + // Kept for Grants Portal backward compatibility — the portal reads this JSON key. + // Value is sourced from Applicant.ApproxNumberOfEmployees, not Applicant.OrganizationSize. + // Portal developer can migrate to ApproxNumberOfEmployees once this field is confirmed stable. public string? OrganizationSize { get; set; } + public string? ApproxNumberOfEmployees { get; set; } public string? Sector { get; set; } public string? SubSector { get; set; } } diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/Applicants/ApplicantListDto.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/Applicants/ApplicantListDto.cs index 117abbfcdb..fcf4d4b6db 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/Applicants/ApplicantListDto.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/Applicants/ApplicantListDto.cs @@ -18,7 +18,6 @@ public class ApplicantListDto : AuditedEntityDto // Additional columns (initially hidden) public string? NonRegisteredBusinessName { get; set; } public string? NonRegOrgName { get; set; } - public string? OrganizationSize { get; set; } public string? Sector { get; set; } public string? SubSector { get; set; } public string? ApproxNumberOfEmployees { get; set; } diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/GrantApplications/ApplicantSummaryDto.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/GrantApplications/ApplicantSummaryDto.cs index c8d35e6141..332d0f7986 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/GrantApplications/ApplicantSummaryDto.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/GrantApplications/ApplicantSummaryDto.cs @@ -14,7 +14,7 @@ public class ApplicantSummaryDto public string? OrgStatus { get; set; } public string? BusinessNumber { get; set; } public string? OrganizationType { get; set; } - public string? OrganizationSize { get; set; } + public string? ApproxNumberOfEmployees { get; set; } public string? SectorSubSectorIndustryDesc { get; set; } public bool? RedStop { get; set; } public bool? IndigenousOrgInd { get; set; } diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/GrantApplications/CreateUpdateApplicantInfoDto.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/GrantApplications/CreateUpdateApplicantInfoDto.cs index cce17c3579..6c9fb44c49 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/GrantApplications/CreateUpdateApplicantInfoDto.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/GrantApplications/CreateUpdateApplicantInfoDto.cs @@ -13,7 +13,7 @@ public class CreateUpdateApplicantInfoDto : CustomDataFieldDto public string? OrgStatus { get; set; } public string? BusinessNumber { get; set; } public string? OrganizationType { get; set; } - public string? OrganizationSize { get; set; } + public string? ApproxNumberOfEmployees { get; set; } public string? Sector { get; set; } public string? SubSector { get; set; } @@ -67,7 +67,7 @@ public class UpsertApplicantInfoDto : CustomDataFieldDto public string? OrgNumber { get; set; } public string? OrgStatus { get; set; } public string? OrganizationType { get; set; } - public string? OrganizationSize { get; set; } + public string? ApproxNumberOfEmployees { get; set; } public string? Sector { get; set; } public string? SubSector { get; set; } diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/GrantApplications/GrantApplicationApplicant.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/GrantApplications/GrantApplicationApplicant.cs index b5f642253c..423b60e6aa 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/GrantApplications/GrantApplicationApplicant.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/GrantApplications/GrantApplicationApplicant.cs @@ -15,7 +15,7 @@ public class GrantApplicationApplicantDto : AuditedEntityDto public string OrgStatus { get; set; } = string.Empty; public string BusinessNumber { get; set; } = string.Empty; public string OrganizationType { get; set; } = string.Empty; - public string OrganizationSize { get; set; } = string.Empty; + public string ApproxNumberOfEmployees { get; set; } = string.Empty; public string SectorSubSectorIndustryDesc { get; set; } = string.Empty; public bool RedStop { get; set; } = false; public string IndigenousOrgInd { get; set; } = string.Empty; diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/GrantApplications/GrantApplicationDto.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/GrantApplications/GrantApplicationDto.cs index 1f703d5204..53fda330fa 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/GrantApplications/GrantApplicationDto.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/GrantApplications/GrantApplicationDto.cs @@ -68,7 +68,7 @@ public class GrantApplicationDto : AuditedEntityDto public GrantApplicationAssigneeDto? Owner { get; set; } = new(); public string? OrgStatus { get; set; } = string.Empty; public string? BusinessNumber { get; set; } = string.Empty; - public string? OrganizationSize { get; set; } = string.Empty; + public string? ApproxNumberOfEmployees { get; set; } = string.Empty; public string? OrgNumber { get; set; } = string.Empty; public string? SectorSubSectorIndustryDesc { get; set; } = string.Empty; public string? SigningAuthorityFullName { get; set; } diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/GrantApplications/UpdateApplicantSummaryDto.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/GrantApplications/UpdateApplicantSummaryDto.cs index 0571deb1a3..fcf960d18f 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/GrantApplications/UpdateApplicantSummaryDto.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/GrantApplications/UpdateApplicantSummaryDto.cs @@ -13,7 +13,7 @@ public class UpdateApplicantSummaryDto public string? OrgStatus { get; set; } public string? BusinessNumber { get; set; } public string? OrganizationType { get; set; } - public string? OrganizationSize { get; set; } + public string? ApproxNumberOfEmployees { get; set; } public string? SectorSubSectorIndustryDesc { get; set; } public bool? RedStop { get; set; } public bool? IndigenousOrgInd { get; set; } diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/ApplicantProfile/DataProviders/OrgInfoDataProvider.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/ApplicantProfile/DataProviders/OrgInfoDataProvider.cs index 8b02ea0817..287cf93a98 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/ApplicantProfile/DataProviders/OrgInfoDataProvider.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/ApplicantProfile/DataProviders/OrgInfoDataProvider.cs @@ -56,7 +56,7 @@ join applicant in applicantsQuery on submission.ApplicantId equals applicant.Id applicant.NonRegOrgName, applicant.FiscalMonth, applicant.FiscalDay, - applicant.OrganizationSize, + applicant.ApproxNumberOfEmployees, applicant.Sector, applicant.SubSector }) @@ -75,7 +75,8 @@ join applicant in applicantsQuery on submission.ApplicantId equals applicant.Id NonRegOrgName = r.NonRegOrgName, FiscalMonth = r.FiscalMonth, FiscalDay = r.FiscalDay, - OrganizationSize = r.OrganizationSize, + OrganizationSize = r.ApproxNumberOfEmployees, + ApproxNumberOfEmployees = r.ApproxNumberOfEmployees, Sector = r.Sector, SubSector = r.SubSector })); diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Applicants/ApplicantAppService.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Applicants/ApplicantAppService.cs index 273a8c5f06..78d6add5e8 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Applicants/ApplicantAppService.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Applicants/ApplicantAppService.cs @@ -816,7 +816,6 @@ public async Task> GetListAsync(ApplicantListRe RedStop = applicant.RedStop, NonRegisteredBusinessName = applicant.NonRegisteredBusinessName, NonRegOrgName = applicant.NonRegOrgName, - OrganizationSize = applicant.OrganizationSize, Sector = applicant.Sector, SubSector = applicant.SubSector, ApproxNumberOfEmployees = applicant.ApproxNumberOfEmployees, diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/GrantApplications/GrantApplicationAppService.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/GrantApplications/GrantApplicationAppService.cs index 01b0be6f94..b8d7ddca13 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/GrantApplications/GrantApplicationAppService.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/GrantApplications/GrantApplicationAppService.cs @@ -13,10 +13,10 @@ using System.Text.Json; using System.Threading.Tasks; using Unity.Flex.WorksheetInstances; -using Unity.Flex.Worksheets; -using Unity.AI.Models; -using Unity.AI.RateLimit; -using Unity.AI.Responses; +using Unity.Flex.Worksheets; +using Unity.AI.Models; +using Unity.AI.RateLimit; +using Unity.AI.Responses; using Unity.GrantManager.Applicants; using Unity.GrantManager.ApplicationForms; using Unity.GrantManager.Applications; @@ -46,21 +46,21 @@ namespace Unity.GrantManager.GrantApplications; [Dependency(ReplaceServices = true)] [ExposeServices(typeof(GrantApplicationAppService), typeof(IGrantApplicationAppService))] public class GrantApplicationAppService( - IApplicationManager applicationManager, - IApplicationRepository applicationRepository, - IApplicationChefsFileAttachmentRepository applicationChefsFileAttachmentRepository, - IApplicationStatusRepository applicationStatusRepository, + IApplicationManager applicationManager, + IApplicationRepository applicationRepository, + IApplicationChefsFileAttachmentRepository applicationChefsFileAttachmentRepository, + IApplicationStatusRepository applicationStatusRepository, IApplicationFormSubmissionRepository applicationFormSubmissionRepository, IApplicantRepository applicantRepository, IApplicationFormRepository applicationFormRepository, IApplicantAgentRepository applicantAgentRepository, IApplicantAddressRepository applicantAddressRepository, IApplicantSupplierAppService applicantSupplierService, - IPaymentRequestAppService paymentRequestService, - IApplicationAIGenerationQueue aiGenerationQueue, - IAIGenerationStatusAppService aiGenerationStatusAppService, - IAIRateLimiter aiRateLimiter, - IFeatureChecker featureChecker) + IPaymentRequestAppService paymentRequestService, + IApplicationAIGenerationQueue aiGenerationQueue, + IAIGenerationStatusAppService aiGenerationStatusAppService, + IAIRateLimiter aiRateLimiter, + IFeatureChecker featureChecker) : GrantManagerAppService, IGrantApplicationAppService #pragma warning restore S107 // Methods should not have too many parameters { @@ -181,7 +181,7 @@ public async Task> GetListAsync(GrantApplica OrgStatus = rec.ApplicantOrgStatus ?? string.Empty, BusinessNumber = rec.ApplicantBusinessNumber ?? string.Empty, OrganizationType = rec.ApplicantOrganizationType ?? string.Empty, - OrganizationSize = rec.ApplicantOrganizationSize ?? string.Empty, + ApproxNumberOfEmployees = rec.ApplicantApproxNumberOfEmployees ?? string.Empty, SectorSubSectorIndustryDesc = rec.ApplicantSectorSubSectorIndustryDesc ?? string.Empty, RedStop = rec.ApplicantRedStop ?? false, IndigenousOrgInd = rec.ApplicantIndigenousOrgInd ?? string.Empty, @@ -195,7 +195,7 @@ public async Task> GetListAsync(GrantApplica OrgStatus = rec.ApplicantOrgStatus, BusinessNumber = rec.ApplicantBusinessNumber, OrgNumber = rec.ApplicantOrgNumber, - OrganizationSize = rec.ApplicantOrganizationSize, + ApproxNumberOfEmployees = rec.ApplicantApproxNumberOfEmployees, SectorSubSectorIndustryDesc = rec.ApplicantSectorSubSectorIndustryDesc, Sector = rec.ApplicantSector, SubSector = rec.ApplicantSubSector, @@ -344,7 +344,7 @@ public async Task GetAsync(Guid id) { appDto.OrganizationName = application.Applicant.OrgName; appDto.OrgNumber = application.Applicant.OrgNumber; - appDto.OrganizationSize = application.Applicant.OrganizationSize; + appDto.ApproxNumberOfEmployees = application.Applicant.ApproxNumberOfEmployees; appDto.OrgStatus = application.Applicant.OrgStatus; appDto.BusinessNumber = application.Applicant.BusinessNumber; appDto.NonRegOrgName = application.Applicant.NonRegOrgName; @@ -829,7 +829,7 @@ public async Task UpdateMergedApplicantAsync(Guid applicationId, CreateUpdateApp applicant.OrgName = input.OrgName ?? ""; applicant.OrgNumber = input.OrgNumber ?? ""; applicant.OrgStatus = input.OrgStatus ?? ""; - applicant.OrganizationSize = input.OrganizationSize ?? ""; + applicant.ApproxNumberOfEmployees = input.ApproxNumberOfEmployees ?? ""; applicant.Sector = input.Sector ?? ""; applicant.SubSector = input.SubSector ?? ""; applicant.SectorSubSectorIndustryDesc = input.SectorSubSectorIndustryDesc ?? ""; @@ -1165,14 +1165,14 @@ await LocalEventBus.PublishAsync( return ObjectMapper.Map(application); } - public async Task QueueAIGenerationAsync(Guid applicationId, string? promptVersion = null) + public async Task QueueAIGenerationAsync(Guid applicationId, string? promptVersion = null) { await EnsureAIAnalysisEnabledAsync(); return await QueueApplicationAnalysisAsync(applicationId, promptVersion); } [Authorize(AIPermissions.Analysis.GenerateApplicationAnalysis)] - public async Task QueueApplicationAnalysisAsync(Guid applicationId, string? promptVersion = null) + public async Task QueueApplicationAnalysisAsync(Guid applicationId, string? promptVersion = null) { await EnsureAIAnalysisEnabledAsync(); await aiGenerationQueue.QueueApplicationAnalysisAsync(applicationId, CurrentTenant.Id, promptVersion); @@ -1182,28 +1182,28 @@ public async Task QueueApplicationAnalysisAsync(Guid appl AIGenerationRequestKeyHelper.ApplicationAnalysisOperationType, CurrentTenant.Id); - return await CreateGenerationStatusAsync( - request ?? throw new UserFriendlyException("Unable to queue AI analysis request.")); + return await CreateGenerationStatusAsync( + request ?? throw new UserFriendlyException("Unable to queue AI analysis request.")); } [Authorize(AIPermissions.Analysis.GenerateAttachmentSummaries)] - public async Task QueueAttachmentSummaryAsync(QueueAttachmentSummaryRequestDto input, string? promptVersion = null) - { - await EnsureAttachmentSummariesEnabledAsync(); - var attachmentIds = await ResolveAttachmentSummaryIdsAsync(input); - await aiGenerationQueue.QueueAttachmentSummaryAsync(input.ApplicationId, CurrentTenant.Id, promptVersion, attachmentIds); - - var request = await aiGenerationStatusAppService.GetLatestAsync( - input.ApplicationId, - AIGenerationRequestKeyHelper.AttachmentSummaryOperationType, - CurrentTenant.Id); - - return await CreateGenerationStatusAsync( - request ?? throw new UserFriendlyException("Unable to queue AI attachment summary request.")); + public async Task QueueAttachmentSummaryAsync(QueueAttachmentSummaryRequestDto input, string? promptVersion = null) + { + await EnsureAttachmentSummariesEnabledAsync(); + var attachmentIds = await ResolveAttachmentSummaryIdsAsync(input); + await aiGenerationQueue.QueueAttachmentSummaryAsync(input.ApplicationId, CurrentTenant.Id, promptVersion, attachmentIds); + + var request = await aiGenerationStatusAppService.GetLatestAsync( + input.ApplicationId, + AIGenerationRequestKeyHelper.AttachmentSummaryOperationType, + CurrentTenant.Id); + + return await CreateGenerationStatusAsync( + request ?? throw new UserFriendlyException("Unable to queue AI attachment summary request.")); } [Authorize(AIPermissions.Analysis.GenerateScoring)] - public async Task QueueApplicationScoringAsync(Guid applicationId, string? promptVersion = null) + public async Task QueueApplicationScoringAsync(Guid applicationId, string? promptVersion = null) { await EnsureScoringEnabledAsync(); await aiGenerationQueue.QueueApplicationScoringAsync(applicationId, CurrentTenant.Id, promptVersion); @@ -1213,21 +1213,21 @@ public async Task QueueApplicationScoringAsync(Guid appli AIGenerationRequestKeyHelper.ApplicationScoringOperationType, CurrentTenant.Id); - return await CreateGenerationStatusAsync( - request ?? throw new UserFriendlyException("Unable to queue AI scoring request.")); + return await CreateGenerationStatusAsync( + request ?? throw new UserFriendlyException("Unable to queue AI scoring request.")); } - public async Task GetAIGenerationStatusAsync(Guid applicationId, string operationType, string? promptVersion = null) + public async Task GetAIGenerationStatusAsync(Guid applicationId, string operationType, string? promptVersion = null) { - await EnsureAIGenerationStatusAccessAsync(operationType); - return await CreateGenerationStatusAsync( - await aiGenerationStatusAppService.GetLatestAsync(applicationId, operationType, CurrentTenant.Id)); + await EnsureAIGenerationStatusAccessAsync(operationType); + return await CreateGenerationStatusAsync( + await aiGenerationStatusAppService.GetLatestAsync(applicationId, operationType, CurrentTenant.Id)); } [Authorize(AIPermissions.Analysis.GenerateApplicationAnalysis)] [Authorize(AIPermissions.Analysis.GenerateAttachmentSummaries)] [Authorize(AIPermissions.Analysis.GenerateScoring)] - public async Task QueueAllAIStagesAsync(Guid applicationId, string? promptVersion = null) + public async Task QueueAllAIStagesAsync(Guid applicationId, string? promptVersion = null) { await EnsureAttachmentSummariesEnabledAsync(); await EnsureAIAnalysisEnabledAsync(); @@ -1239,20 +1239,20 @@ public async Task QueueAllAIStagesAsync(Guid applicationI AIGenerationRequestKeyHelper.PipelineOperationType, CurrentTenant.Id); - return await CreateGenerationStatusAsync( - request ?? throw new UserFriendlyException("Unable to queue AI generation request.")); - } - - private async Task CreateGenerationStatusAsync(AIGenerationRequestDto? request) - { - var state = await aiRateLimiter.GetStateAsync(); - return new AIGenerationStatusDto - { - GenerationRequest = request, - IsGenerating = state.IsGenerating, - RetryAfterSeconds = state.RetryAfterSeconds - }; - } + return await CreateGenerationStatusAsync( + request ?? throw new UserFriendlyException("Unable to queue AI generation request.")); + } + + private async Task CreateGenerationStatusAsync(AIGenerationRequestDto? request) + { + var state = await aiRateLimiter.GetStateAsync(); + return new AIGenerationStatusDto + { + GenerationRequest = request, + IsGenerating = state.IsGenerating, + RetryAfterSeconds = state.RetryAfterSeconds + }; + } private async Task EnsureAIGenerationStatusAccessAsync(string operationType) { @@ -1277,49 +1277,49 @@ private async Task EnsureAIGenerationStatusAccessAsync(string operationType) } } - private async Task EnsureAttachmentSummariesEnabledAsync() - { - if (!await featureChecker.IsEnabledAsync("Unity.AI.AttachmentSummaries")) - { - throw new UserFriendlyException("AI attachment summaries are not enabled."); - } - } - - private async Task> ResolveAttachmentSummaryIdsAsync(QueueAttachmentSummaryRequestDto input) - { - if (input == null) - { - throw new UserFriendlyException("Attachment summary request is required."); - } - - if (input.ApplicationId == Guid.Empty) - { - throw new UserFriendlyException("Application id is required."); - } - - var applicationAttachmentIds = (await applicationChefsFileAttachmentRepository.GetListAsync(a => a.ApplicationId == input.ApplicationId)) - .Select(a => a.Id) - .ToList(); - - if (applicationAttachmentIds.Count == 0) - { - throw new UserFriendlyException("No attachments were found to generate summaries."); - } - - if (input.AttachmentIds is not { Count: > 0 }) - { - return applicationAttachmentIds; - } - - var applicationAttachmentIdSet = applicationAttachmentIds.ToHashSet(); - var selectedAttachmentIds = input.AttachmentIds.Distinct().ToList(); - if (selectedAttachmentIds.Any(id => !applicationAttachmentIdSet.Contains(id))) - { - throw new UserFriendlyException("One or more selected attachments do not belong to the application."); - } - - return selectedAttachmentIds; - } + private async Task EnsureAttachmentSummariesEnabledAsync() + { + if (!await featureChecker.IsEnabledAsync("Unity.AI.AttachmentSummaries")) + { + throw new UserFriendlyException("AI attachment summaries are not enabled."); + } + } + + private async Task> ResolveAttachmentSummaryIdsAsync(QueueAttachmentSummaryRequestDto input) + { + if (input == null) + { + throw new UserFriendlyException("Attachment summary request is required."); + } + + if (input.ApplicationId == Guid.Empty) + { + throw new UserFriendlyException("Application id is required."); + } + + var applicationAttachmentIds = (await applicationChefsFileAttachmentRepository.GetListAsync(a => a.ApplicationId == input.ApplicationId)) + .Select(a => a.Id) + .ToList(); + + if (applicationAttachmentIds.Count == 0) + { + throw new UserFriendlyException("No attachments were found to generate summaries."); + } + + if (input.AttachmentIds is not { Count: > 0 }) + { + return applicationAttachmentIds; + } + + var applicationAttachmentIdSet = applicationAttachmentIds.ToHashSet(); + var selectedAttachmentIds = input.AttachmentIds.Distinct().ToList(); + if (selectedAttachmentIds.Any(id => !applicationAttachmentIdSet.Contains(id))) + { + throw new UserFriendlyException("One or more selected attachments do not belong to the application."); + } + + return selectedAttachmentIds; + } private async Task EnsureAIAnalysisEnabledAsync() { @@ -1480,4 +1480,4 @@ private static void UpdateFindingDismissedState(IEnumerable HandleAsync(PluginDataPayload payload) applicant.OrgStatus = innerData.Status; applicant.NonRegOrgName = innerData.NonRegOrgName; applicant.FiscalMonth = innerData.FiscalMonth; - applicant.OrganizationSize = innerData.OrganizationSize; + applicant.ApproxNumberOfEmployees = innerData.ApproxNumberOfEmployees ?? innerData.OrganizationSize; if (int.TryParse(innerData.FiscalDay, out var fiscalDay)) { diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/GrantsPortal/Messages/Commands/OrganizationEditData.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/GrantsPortal/Messages/Commands/OrganizationEditData.cs index e2d08dc007..48deb25541 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/GrantsPortal/Messages/Commands/OrganizationEditData.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/GrantsPortal/Messages/Commands/OrganizationEditData.cs @@ -25,6 +25,13 @@ public class OrganizationEditData [JsonProperty("fiscalDay")] public string? FiscalDay { get; set; } + // Kept for Grants Portal backward compatibility — portal sends "organizationSize" in the PUT payload. + // OrganizationEditHandler falls back to this value when ApproxNumberOfEmployees is not present. [JsonProperty("organizationSize")] public string? OrganizationSize { get; set; } + + // Preferred field — portal developer should migrate the PUT payload to send "approxNumberOfEmployees" + // instead of "organizationSize" after deployment. Handler uses this when present. + [JsonProperty("approxNumberOfEmployees")] + public string? ApproxNumberOfEmployees { get; set; } } diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Domain.Shared/Localization/GrantManager/en.json b/applications/Unity.GrantManager/src/Unity.GrantManager.Domain.Shared/Localization/GrantManager/en.json index 77d536ea19..3673e3b039 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Domain.Shared/Localization/GrantManager/en.json +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Domain.Shared/Localization/GrantManager/en.json @@ -425,6 +425,7 @@ "ApplicantInfoView:ApplicantInfo.OrgBookStatus": "Org book status ", "ApplicantInfoView:ApplicantInfo.OrganizationType": "Organization Type", "ApplicantInfoView:ApplicantInfo.OrganizationSize": "Organization Size", + "ApplicantInfoView:ApplicantInfo.ApproxNumberOfEmployees": "Organization Size (Approximate Number of Employees)", "ApplicantInfoView:ApplicantInfo.UnityApplicant": "Applicant Id", "ApplicantInfoView:ApplicantInfo.FiscalMonth": "Fiscal Year End Month", "ApplicantInfoView:ApplicantInfo.FiscalDay": "Fiscal Year End Day", diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Domain/Applications/Applicant.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Domain/Applications/Applicant.cs index feac9027ac..7e497cdc25 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Domain/Applications/Applicant.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Domain/Applications/Applicant.cs @@ -13,6 +13,9 @@ public class Applicant : AuditedAggregateRoot, IMultiTenant public string? OrgNumber { get; set; } public string? OrgStatus { get; set; } public string? OrganizationType { get; set; } + // Retained to protect the DB column from being dropped by EF Core migrations. + // No longer read or written by Unity — ApproxNumberOfEmployees is the canonical field. + // Do not remove until a DB migration explicitly drops or consolidates the column. public string? OrganizationSize { get; set; } public string? Sector { get; set; } public string? SubSector { get; set; } diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Domain/Applications/ApplicationListRecord.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Domain/Applications/ApplicationListRecord.cs index f086d1299e..999ad5fa13 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Domain/Applications/ApplicationListRecord.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Domain/Applications/ApplicationListRecord.cs @@ -76,7 +76,7 @@ public class ApplicationListRecord public string? ApplicantOrgNumber { get; init; } public string? ApplicantOrgStatus { get; init; } public string? ApplicantBusinessNumber { get; init; } - public string? ApplicantOrganizationSize { get; init; } + public string? ApplicantApproxNumberOfEmployees { get; init; } public string? ApplicantSectorSubSectorIndustryDesc { get; init; } public bool? ApplicantRedStop { get; init; } public string? ApplicantIndigenousOrgInd { get; init; } diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.EntityFrameworkCore/Repositories/ApplicantRepository.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.EntityFrameworkCore/Repositories/ApplicantRepository.cs index 00facf5f20..c0578606cd 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.EntityFrameworkCore/Repositories/ApplicantRepository.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.EntityFrameworkCore/Repositories/ApplicantRepository.cs @@ -113,7 +113,6 @@ public async Task GetApplicantAutocompleteQueryAsync(string? appli a.OrgNumber, a.NonRegOrgName, a.OrganizationType, - a.OrganizationSize, a.ApproxNumberOfEmployees, a.OrgStatus, a.BusinessNumber, diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.EntityFrameworkCore/Repositories/ApplicationRepository.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.EntityFrameworkCore/Repositories/ApplicationRepository.cs index b0b10699ec..15ec1b58b8 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.EntityFrameworkCore/Repositories/ApplicationRepository.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.EntityFrameworkCore/Repositories/ApplicationRepository.cs @@ -334,7 +334,7 @@ public async Task> GetApplicationListRecordsAsync( ApplicantOrgNumber = a.Applicant.OrgNumber, ApplicantOrgStatus = a.Applicant.OrgStatus, ApplicantBusinessNumber = a.Applicant.BusinessNumber, - ApplicantOrganizationSize = a.Applicant.OrganizationSize, + ApplicantApproxNumberOfEmployees = a.Applicant.ApproxNumberOfEmployees, ApplicantSectorSubSectorIndustryDesc = a.Applicant.SectorSubSectorIndustryDesc, ApplicantRedStop = a.Applicant.RedStop, ApplicantIndigenousOrgInd = a.Applicant.IndigenousOrgInd, @@ -518,7 +518,7 @@ public async Task> GetApplicationListRecordsAsync( ApplicantOrgNumber = a.ApplicantOrgNumber, ApplicantOrgStatus = a.ApplicantOrgStatus, ApplicantBusinessNumber = a.ApplicantBusinessNumber, - ApplicantOrganizationSize = a.ApplicantOrganizationSize, + ApplicantApproxNumberOfEmployees = a.ApplicantApproxNumberOfEmployees, ApplicantSectorSubSectorIndustryDesc = a.ApplicantSectorSubSectorIndustryDesc, ApplicantRedStop = a.ApplicantRedStop, ApplicantIndigenousOrgInd = a.ApplicantIndigenousOrgInd, diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Mapping/GrantManagerWebMapperlyProfile.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Mapping/GrantManagerWebMapperlyProfile.cs index 220e1026f7..ad9bd5b7ab 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Mapping/GrantManagerWebMapperlyProfile.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Mapping/GrantManagerWebMapperlyProfile.cs @@ -76,7 +76,7 @@ public partial class ApplicationToGrantApplicationDtoWebMapper : MapperBase - +
@@ -510,17 +510,17 @@ - @L["ApplicantInfoView:ApplicantInfo.OrganizationSize"].Value + @L["ApplicantInfoView:ApplicantInfo.ApproxNumberOfEmployees"].Value diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Shared/Components/ApplicantInfo/Default.js b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Shared/Components/ApplicantInfo/Default.js index 3051f16949..8cf4737d2c 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Shared/Components/ApplicantInfo/Default.js +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Shared/Components/ApplicantInfo/Default.js @@ -285,7 +285,7 @@ function getExistingApplicantData() { NonRegOrgName: getVal('ApplicantSummary_NonRegOrgName'), OrganizationType: getVal('ApplicantSummary_OrganizationType'), BusinessNumber: getVal('ApplicantSummary_BusinessNumber'), - OrganizationSize: getVal('ApplicantSummary_OrganizationSize'), + ApproxNumberOfEmployees: getVal('ApplicantSummary_ApproxNumberOfEmployees'), OrgStatus: getVal('ApplicantSummary_OrgStatus'), IndigenousOrgInd: $activeWidget.find('#ApplicantSummary_IndigenousOrgInd').is(':checked') ? 'Yes' : 'No', Sector: getVal('ApplicantSummary_Sector'), @@ -316,7 +316,7 @@ function createNewApplicantDataObject(selectedData) { NonRegOrgName: selectedData.NonRegOrgName || '', OrganizationType: selectedData.OrganizationType || '', BusinessNumber: selectedData.BusinessNumber || '', - OrganizationSize: selectedData.OrganizationSize || '', + ApproxNumberOfEmployees: selectedData.ApproxNumberOfEmployees || '', OrgStatus: selectedData.OrgStatus || '', IndigenousOrgInd: selectedData.IndigenousOrgInd || '', Sector: selectedData.Sector || '', @@ -528,7 +528,7 @@ function initializeApplicantLookup() { OrgNumber: item.OrgNumber, NonRegOrgName: item.NonRegOrgName, OrganizationType: item.OrganizationType, - OrganizationSize: item.OrganizationSize, + ApproxNumberOfEmployees: item.ApproxNumberOfEmployees, OrgStatus: item.OrgStatus, BusinessNumber: item.BusinessNumber, IndigenousOrgInd: item.IndigenousOrgInd, diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Shared/Components/ApplicantOrganizationInfo/ApplicantOrganizationInfoViewComponent.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Shared/Components/ApplicantOrganizationInfo/ApplicantOrganizationInfoViewComponent.cs index a193691a4c..991e48f85f 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Shared/Components/ApplicantOrganizationInfo/ApplicantOrganizationInfoViewComponent.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Shared/Components/ApplicantOrganizationInfo/ApplicantOrganizationInfoViewComponent.cs @@ -56,7 +56,7 @@ public async Task InvokeAsync(Guid applicantId) BusinessNumber = applicant.BusinessNumber ?? string.Empty, OrgStatus = applicant.OrgStatus ?? string.Empty, OrganizationType = applicant.OrganizationType ?? string.Empty, - OrganizationSize = applicant.OrganizationSize ?? string.Empty, + ApproxNumberOfEmployees = applicant.ApproxNumberOfEmployees ?? string.Empty, NonRegOrgName = applicant.NonRegOrgName ?? string.Empty, // Sector Information diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Shared/Components/ApplicantOrganizationInfo/ApplicantOrganizationInfoViewModel.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Shared/Components/ApplicantOrganizationInfo/ApplicantOrganizationInfoViewModel.cs index 3c40725ebf..236dff6da8 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Shared/Components/ApplicantOrganizationInfo/ApplicantOrganizationInfoViewModel.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Shared/Components/ApplicantOrganizationInfo/ApplicantOrganizationInfoViewModel.cs @@ -43,7 +43,7 @@ public class ApplicantOrganizationInfoViewModel public string OrganizationType { get; set; } = string.Empty; [Display(Name = "Organization Size (Approximate Number of Employees)")] - public string OrganizationSize { get; set; } = string.Empty; + public string ApproxNumberOfEmployees { get; set; } = string.Empty; [Display(Name = "Non-Registered Organization Name")] public string NonRegOrgName { get; set; } = string.Empty; diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Shared/Components/ApplicantOrganizationInfo/Default.cshtml b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Shared/Components/ApplicantOrganizationInfo/Default.cshtml index 58ee78f3b7..129f591e06 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Shared/Components/ApplicantOrganizationInfo/Default.cshtml +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Shared/Components/ApplicantOrganizationInfo/Default.cshtml @@ -143,7 +143,7 @@ - +
diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Shared/Components/ApplicantOrganizationInfo/Default.js b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Shared/Components/ApplicantOrganizationInfo/Default.js index ceed6c2aa1..fa15f3c53e 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Shared/Components/ApplicantOrganizationInfo/Default.js +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Shared/Components/ApplicantOrganizationInfo/Default.js @@ -14,7 +14,7 @@ 'BusinessNumber', 'OrgStatus', 'OrganizationType', - 'OrganizationSize', + 'ApproxNumberOfEmployees', 'NonRegOrgName', 'Sector', 'SubSector', diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Shared/Components/ApplicantsActionBar/ListMerge.js b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Shared/Components/ApplicantsActionBar/ListMerge.js index 32655619e9..f3e7dd116f 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Shared/Components/ApplicantsActionBar/ListMerge.js +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Shared/Components/ApplicantsActionBar/ListMerge.js @@ -14,7 +14,7 @@ { label: 'Registered Organization Number', key: 'orgNumber', radioName: 'merge_OrgNumber' }, { label: 'Non-Registered Organization Name', key: 'nonRegOrgName', radioName: 'merge_NonRegOrgName' }, { label: 'Organization Type', key: 'organizationType', radioName: 'merge_OrganizationType' }, - { label: 'Organization Size', key: 'organizationSize', radioName: 'merge_OrganizationSize' }, + { label: 'Organization Size (Approximate Number of Employees)', key: 'approxNumberOfEmployees', radioName: 'merge_ApproxNumberOfEmployees' }, { label: 'Org book status', key: 'orgStatus', radioName: 'merge_OrgStatus' }, { label: 'Indigenous', key: 'indigenousOrgInd', radioName: 'merge_IndigenousOrgInd' }, { label: 'Sector', key: 'sector', radioName: 'merge_Sector' }, @@ -153,7 +153,7 @@ orgNumber: merged['orgNumber'] ?? null, nonRegOrgName: merged['nonRegOrgName'] ?? null, organizationType: merged['organizationType'] ?? null, - organizationSize: merged['organizationSize'] ?? null, + approxNumberOfEmployees: merged['approxNumberOfEmployees'] ?? null, orgStatus: merged['orgStatus'] ?? null, indigenousOrgInd: indigenousOrgIndBool, sector: merged['sector'] ?? null, diff --git a/applications/Unity.GrantManager/test/Unity.GrantManager.Application.Tests/Applicants/OrgInfoDataProviderTests.cs b/applications/Unity.GrantManager/test/Unity.GrantManager.Application.Tests/Applicants/OrgInfoDataProviderTests.cs index fa7c5420e2..6df0cb0b67 100644 --- a/applications/Unity.GrantManager/test/Unity.GrantManager.Application.Tests/Applicants/OrgInfoDataProviderTests.cs +++ b/applications/Unity.GrantManager/test/Unity.GrantManager.Application.Tests/Applicants/OrgInfoDataProviderTests.cs @@ -138,7 +138,7 @@ public async Task GetDataAsync_ShouldMapAllApplicantFields() a.NonRegOrgName = "Acme Trading"; a.FiscalMonth = "April"; a.FiscalDay = 1; - a.OrganizationSize = "51-100"; + a.ApproxNumberOfEmployees = "51-100"; a.Sector = "Technology"; a.SubSector = "Software"; })]); diff --git a/applications/Unity.GrantManager/test/Unity.GrantManager.Application.Tests/GrantApplications/ApplicationListRecordAlignmentTests.cs b/applications/Unity.GrantManager/test/Unity.GrantManager.Application.Tests/GrantApplications/ApplicationListRecordAlignmentTests.cs index 6229d9ef08..c749f09b28 100644 --- a/applications/Unity.GrantManager/test/Unity.GrantManager.Application.Tests/GrantApplications/ApplicationListRecordAlignmentTests.cs +++ b/applications/Unity.GrantManager/test/Unity.GrantManager.Application.Tests/GrantApplications/ApplicationListRecordAlignmentTests.cs @@ -142,8 +142,8 @@ public async Task GetApplicationListRecordsAsync_ApplicantFields_Match_WithFullD $"ApplicantSubSector mismatch for Id={app.Id}"); rec.ApplicantOrganizationType.ShouldBe(applicant.OrganizationType, $"ApplicantOrganizationType mismatch for Id={app.Id}"); - rec.ApplicantOrganizationSize.ShouldBe(applicant.OrganizationSize, - $"ApplicantOrganizationSize mismatch for Id={app.Id}"); + rec.ApplicantApproxNumberOfEmployees.ShouldBe(applicant.ApproxNumberOfEmployees, + $"ApplicantApproxNumberOfEmployees mismatch for Id={app.Id}"); rec.ApplicantIndigenousOrgInd.ShouldBe(applicant.IndigenousOrgInd, $"ApplicantIndigenousOrgInd mismatch for Id={app.Id}"); rec.ApplicantRedStop.ShouldBe(applicant.RedStop, diff --git a/applications/Unity.GrantManager/test/Unity.GrantManager.Application.Tests/GrantsPortal/OrganizationEditHandlerTests.cs b/applications/Unity.GrantManager/test/Unity.GrantManager.Application.Tests/GrantsPortal/OrganizationEditHandlerTests.cs index f30098b8c4..81791f8809 100644 --- a/applications/Unity.GrantManager/test/Unity.GrantManager.Application.Tests/GrantsPortal/OrganizationEditHandlerTests.cs +++ b/applications/Unity.GrantManager/test/Unity.GrantManager.Application.Tests/GrantsPortal/OrganizationEditHandlerTests.cs @@ -103,7 +103,7 @@ public async Task HandleAsync_ShouldUpdateAllApplicantFields() updatedApplicant.NonRegOrgName.ShouldBe("Friendly Name"); updatedApplicant.FiscalMonth.ShouldBe("April"); updatedApplicant.FiscalDay.ShouldBe(15); - updatedApplicant.OrganizationSize.ShouldBe("Medium"); + updatedApplicant.ApproxNumberOfEmployees.ShouldBe("Medium"); } [Fact] diff --git a/documentation/applicant-portal/applicant-profile-data-providers.md b/documentation/applicant-portal/applicant-profile-data-providers.md index 6cc8d3db98..816d9be7c8 100644 --- a/documentation/applicant-portal/applicant-profile-data-providers.md +++ b/documentation/applicant-portal/applicant-profile-data-providers.md @@ -389,6 +389,7 @@ flowchart LR "fiscalMonth": "April", "fiscalDay": 1, "organizationSize": "51-100", + "approxNumberOfEmployees": "51-100", "sector": "Technology", "subSector": "Software" } @@ -410,13 +411,14 @@ flowchart LR | `NonRegOrgName` | `Applicant.NonRegOrgName` | `string?` | Non-registered organization name | | `FiscalMonth` | `Applicant.FiscalMonth` | `string?` | Fiscal year start month | | `FiscalDay` | `Applicant.FiscalDay` | `int?` | Fiscal year start day | -| `OrganizationSize` | `Applicant.OrganizationSize` | `string?` | Size category | +| `OrganizationSize` | `Applicant.ApproxNumberOfEmployees` | `string?` | Sourced from `ApproxNumberOfEmployees` for backward portal compatibility; `Applicant.OrganizationSize` column retained in DB pending migration but no longer read or displayed | +| `ApproxNumberOfEmployees` | `Applicant.ApproxNumberOfEmployees` | `string?` | Approximate number of employees (replaces OrganizationSize in UI) | | `Sector` | `Applicant.Sector` | `string?` | Industry sector | | `SubSector` | `Applicant.SubSector` | `string?` | Industry sub-sector | **Multiple Applicants**: It is possible for a single OIDC subject to be linked to multiple distinct `Applicant` records (via different `ApplicationFormSubmission` rows). The provider returns all of them. When the same applicant is linked by multiple submissions, each join result is returned — the UI handles presentation and any eventual deduplication is a process-level concern. -**Relationship to OrganizationEditHandler**: The `ORGANIZATION_EDIT_COMMAND` handler (see [RabbitMQ integration](./grants-portal-rabbitmq-integration.md)) updates a single `Applicant` entity by its ID. The `Id` field in the org info response corresponds to the `organizationId` expected by the edit command payload. +**Relationship to OrganizationEditHandler**: The `ORGANIZATION_EDIT_COMMAND` handler (see [RabbitMQ integration](./grants-portal-rabbitmq-integration.md)) updates a single `Applicant` entity by its ID. The `Id` field in the org info response corresponds to the `organizationId` expected by the edit command payload. The inbound JSON field `organizationSize` is kept for external API compatibility but is now stored in `Applicant.ApproxNumberOfEmployees`, not `Applicant.OrganizationSize`. --- From e053a0900a5b5ef3dc0c1e499c4ca43a81beb85a Mon Sep 17 00:00:00 2001 From: Patrick <135162612+plavoie-BC@users.noreply.github.com> Date: Wed, 17 Jun 2026 09:24:32 -0700 Subject: [PATCH 02/20] [AB#32708] Fix preview attachment menu item alignment --- .../Shared/Components/ChefsAttachments/ChefsAttachments.js | 4 ++-- .../Views/Shared/Components/_Shared/Attachments.js | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Shared/Components/ChefsAttachments/ChefsAttachments.js b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Shared/Components/ChefsAttachments/ChefsAttachments.js index 5ee00dd3df..ea5d197029 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Shared/Components/ChefsAttachments/ChefsAttachments.js +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Shared/Components/ChefsAttachments/ChefsAttachments.js @@ -452,13 +452,13 @@ function getChefsFileDownloadColumn() { '' + '' + '