Skip to content
Merged

Dev #2236

Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
d6743ba
AB#32469 add metadata (email) for tenant / providers
AndreGAot Apr 7, 2026
35cf19f
Merge remote-tracking branch 'origin/dev' into feature/AB#32469-multi…
AndreGAot Apr 7, 2026
42d60be
AB#32384: Validate UnityApplicantID If Already Existing
aurelio-aot Apr 8, 2026
3dbd71f
AB#32469 - apply copilot suggestions
AndreGAot Apr 8, 2026
c09190d
Merge pull request #2234 from bcgov/feature/AB#32469-multi-applicant-…
AndreGAot Apr 8, 2026
ebe765c
feature/AB#30089-CHEFSFormName
JamesPasta Apr 8, 2026
547e70f
Merge pull request #2233 from bcgov/bugfix/AB#32384-Unique-ApplicantID
JamesPasta Apr 8, 2026
8283a5a
AB#32346 - Add Applicant Detail routing from ApplicationId
plavoie-BC Apr 8, 2026
2e84fb1
AB#32346 - Add default applicant naming
plavoie-BC Apr 8, 2026
4a3e07d
Merge branch 'dev' into feature/AB#32346-applicant-name
plavoie-BC Apr 8, 2026
4a6383e
AB#32346 - Code Quality Improvements
plavoie-BC Apr 8, 2026
51504bf
Merge branch 'feature/AB#32346-applicant-name' of https://github.com/…
plavoie-BC Apr 8, 2026
8b8d96d
AB#32346 - Add additional applicant name placeholders
plavoie-BC Apr 8, 2026
89c30cd
feature/AB#32485-Filters
JamesPasta Apr 8, 2026
0e42d7c
AB#32525: EF Migration Script to Backfill UnityApplicationId of ABPP …
aurelio-aot Apr 8, 2026
241f8fe
AB#31160 Changed the sorting for comments FROM creation date by defau…
DavidBrightBcGov Apr 8, 2026
530ab1c
Merge pull request #2238 from bcgov/bugfix/AB#31160-comment-order-bas…
DavidBrightBcGov Apr 8, 2026
2de32bb
feature/AB#32485-Filters
JamesPasta Apr 8, 2026
ecfe8b2
Merge pull request #2239 from bcgov/bugfix/AB#32525-Backfill-Empty-Un…
JamesPasta Apr 8, 2026
d71a676
Merge pull request #2235 from bcgov/feature/AB#32346-applicant-name
JamesPasta Apr 8, 2026
d8372d8
Merge pull request #2240 from bcgov/feature/AB#30089-CHEFS-FormNameSynch
JamesPasta Apr 8, 2026
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 @@ -2,6 +2,7 @@ $(function () {
const l = abp.localization.getResource('Payments');
const nullPlaceholder = '—';
const formatter = createNumberFormatter();
const guidPattern = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
let dt = $('#PaymentRequestListTable');
let dataTable;
let isApprove = false;
Expand Down Expand Up @@ -377,7 +378,29 @@ $(function () {
name: 'applicantName',
data: 'payeeName',
className: 'data-table-header',
index: columnIndex
index: columnIndex,
render: function (data, type, row) {
let applicantName = (typeof data !== 'string' || data.trim() === '') ? 'Applicant Name' : data;

if (type === 'sort' || type === 'filter') {
return applicantName;
}

const safeApplicantName = $.fn.dataTable.render.text().display(applicantName);

if (type === 'display' && abp.auth.isGranted('GrantApplicationManagement.Applicants.ViewList')) {
const applicantId = row?.correlationId;
const isGuid = applicantId && guidPattern.test(applicantId);

if (row?.correlationProvider === 'Application' && isGuid) {
return `<a href="/GrantApplicants/Details?ApplicationId=${encodeURIComponent(applicantId)}">${safeApplicantName}</a>`;
}

return safeApplicantName;
}

return applicantName;
},
};
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -303,10 +303,10 @@ $(function () {
{
text: 'Filter',
className: 'custom-table-btn flex-none btn btn-secondary',
id: 'btn-toggle-filter',
id: 'btn-supplier-toggle-filter',
action: function (e, dt, node, config) { },
attr: {
id: 'btn-toggle-filter',
id: 'btn-supplier-toggle-filter',
},
},
];
Expand Down Expand Up @@ -334,6 +334,9 @@ $(function () {
dynamicButtonContainerId: 'siteDynamicButtonContainerId',
});

initializeFilterRowPlugin(dataTable, 'btn-supplier-toggle-filter');


function getColumns() {
let columnIndex = 0;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
'use strict';

let DataTable = $.fn.dataTable;
let _filterRowInstanceCount = 0;

// Ensure DataTable is loaded
if (!DataTable) {
Expand All @@ -55,7 +56,7 @@

this.s = {
dt: new DataTable.Api(settings),
namespace: '.dtFilterRow',
namespace: '.dtFilterRow' + (++_filterRowInstanceCount),
filterData: {},
opts: $.extend({}, DataTable.FilterRow.defaults, opts)
};
Expand Down Expand Up @@ -260,7 +261,8 @@

$btn.on('shown.bs.popover' + this.s.namespace, () => {

const $popover = $('.popover.custom-popover');
const popoverId = $btn.attr('aria-describedby');
const $popover = popoverId ? $('#' + popoverId) : $('.popover.custom-popover');

$popover.find('#showFilter')
.off('click' + this.s.namespace)
Expand Down Expand Up @@ -348,7 +350,12 @@
}
});

if (Object.keys(this.s.filterData).length > 0) {
// Show filter row if filters are active
let externalSearchId = dt.init().externalSearchInputId;
let externalSearchVal = externalSearchId ? $(externalSearchId).val() : '';
let hasFilters = Object.keys(this.s.filterData).length > 0 || externalSearchVal !== '';

if (hasFilters) {
this.dom.filterRow.show();
}

Expand Down Expand Up @@ -390,24 +397,40 @@
this._updateButtonState();
},

/**
* Show the filter row
* @public
*/
show: function () {
this.dom.filterRow.show();
this.s.dt.trigger('filterRow-visibility', [true]);
return this;
},

/**
* Hide the filter row
* @public
*/
hide: function () {
this.dom.filterRow.hide();
this.s.dt.trigger('filterRow-visibility', [false]);
return this;
},

/**
* Toggle the filter row visibility
* @public
*/
toggle: function () {
this.dom.filterRow.toggle();
this.s.dt.trigger('filterRow-visibility', [this.dom.filterRow.is(':visible')]);
return this;
},

/**
* Destroy the filter row feature
* @private
*/
_destroy: function () {
let dt = this.s.dt;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
using System;
using System.Collections.Generic;

namespace Unity.GrantManager.Applicants
{
public class ApplicantTenantDto
{
public Guid TenantId { get; set; }
public string TenantName { get; set; } = string.Empty;
public Dictionary<string, string> Metadata { get; set; } = [];
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
namespace Unity.GrantManager.Applicants
{
/// <summary>
/// Well-known keys for the <see cref="ApplicantTenantDto.Metadata"/> dictionary.
/// Shared with external consumers (e.g. Applicant Portal plugins).
/// </summary>
public static class ApplicantTenantMetadataKeys
{
public const string DefaultFromAddress = "DefaultFromAddress";
}
}
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using Unity.GrantManager.Applicants;
using Unity.GrantManager.Applications;
using Unity.Notifications.Settings;
using Volo.Abp;
using Volo.Abp.Application.Services;
using Volo.Abp.Domain.Repositories;
using Volo.Abp.MultiTenancy;
using Volo.Abp.Settings;
using Volo.Abp.TenantManagement;

namespace Unity.GrantManager.ApplicantProfile
Expand All @@ -20,7 +22,8 @@ public class ApplicantProfileAppService(
ITenantRepository tenantRepository,
IRepository<ApplicantTenantMap, Guid> applicantTenantMapRepository,
IRepository<ApplicationFormSubmission, Guid> applicationFormSubmissionRepository,
IEnumerable<IApplicantProfileDataProvider> dataProviders)
IEnumerable<IApplicantProfileDataProvider> dataProviders,
ISettingProvider settingProvider)
: ApplicationService, IApplicantProfileAppService
{
private readonly Dictionary<string, IApplicantProfileDataProvider> _providersByKey
Expand Down Expand Up @@ -69,21 +72,41 @@ public async Task<List<ApplicantTenantDto>> GetApplicantTenantsAsync(ApplicantPr
// Extract the username part from the OIDC sub (part before '@')
var subUsername = SubjectNormalizer.Normalize(request.Subject);
if (subUsername is null) return [];
List<ApplicantTenantDto> mappings = [];

// Query the ApplicantTenantMaps table in the host database
using (currentTenant.Change(null))
{
var queryable = await applicantTenantMapRepository.GetQueryableAsync();
var mappings = await queryable
mappings = await queryable
.Where(m => m.OidcSubUsername == subUsername)
.Select(m => new ApplicantTenantDto
{
TenantId = m.TenantId,
TenantName = m.TenantName
})
.ToListAsync();
}

// Apply tenant specific metadata
foreach (var map in mappings)
{
await AddTenantMetadataAsync(map);
}

return mappings;
}

return mappings;
/// <summary>
/// Add on any relevant tenant specific metadata
/// </summary>
/// <param name="tenantMap">The applicant tenant DTO to enrich with tenant-specific metadata.</param>
private async Task AddTenantMetadataAsync(ApplicantTenantDto tenantMap)
{
using (currentTenant.Change(tenantMap.TenantId))
{
var defaultEmailAddress = await settingProvider.GetOrNullAsync(NotificationsSettings.Mailing.DefaultFromAddress);
tenantMap.Metadata[ApplicantTenantMetadataKeys.DefaultFromAddress] = defaultEmailAddress ?? "NoReply@gov.bc.ca";
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -357,19 +357,22 @@ public async Task<int> GetNextUnityApplicantIdAsync()

foreach (var id in orderedIds)
{
if (id == candidate)
{
candidate++;
}
else // Gap found: candidate is the first available ID.
{
break;
}
if (id < candidate) continue; // Skip duplicates already passed.
if (id == candidate) candidate++;
else break; // Gap found: candidate is the first available ID.
}

return candidate;
}

[RemoteService(true)]
public async Task<bool> IsUnityApplicantIdAvailableAsync(string unityApplicantId, Guid currentApplicantId)
{
if (string.IsNullOrEmpty(unityApplicantId)) return true;
var existing = await applicantRepository.GetByUnityApplicantIdAsync(unityApplicantId);
return existing == null || existing.Id == currentApplicantId;
}

[RemoteService(true)]
public async Task<Applicant?> GetExistingApplicantAsync(string? unityApplicantId)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ public interface IApplicantAppService : IApplicationService
Task RelateDefaultSupplierAsync(ApplicantAgentDto applicantAgentDto);
Task<Applicant> UpdateApplicantOrgMatchAsync(Applicant applicant);
Task<int> GetNextUnityApplicantIdAsync();
Task<bool> IsUnityApplicantIdAvailableAsync(string unityApplicantId, Guid currentApplicantId);
Task<List<Applicant>> GetApplicantsBySiteIdAsync(Guid siteId);
Task<JsonDocument> GetApplicantLookUpAutocompleteQueryAsync(string? applicantLookUpQuery);
Task<PagedResultDto<ApplicantListDto>> GetListAsync(ApplicantListRequestDto input);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ join user in await _personRepository.GetQueryableAsync() on applicationComment.C
where applicationComment.ApplicationId == ownerId
orderby applicationComment.PinDateTime.HasValue descending,
applicationComment.PinDateTime ascending,
applicationComment.CreationTime descending
(applicationComment.LastModificationTime ?? applicationComment.CreationTime) descending
select new CommentListItem
{
Comment = applicationComment.Comment,
Expand All @@ -138,7 +138,7 @@ join user in await _personRepository.GetQueryableAsync() on assessmentComment.Co
where assessmentComment.AssessmentId == ownerId
orderby assessmentComment.PinDateTime.HasValue descending,
assessmentComment.PinDateTime ascending,
assessmentComment.CreationTime descending
(assessmentComment.LastModificationTime ?? assessmentComment.CreationTime) descending
select new CommentListItem
{
Comment = assessmentComment.Comment,
Expand All @@ -158,19 +158,19 @@ join user in await _personRepository.GetQueryableAsync() on applicantComment.Com
where applicantComment.ApplicantId == ownerId
orderby applicantComment.PinDateTime.HasValue descending,
applicantComment.PinDateTime ascending,
applicantComment.CreationTime descending
select new CommentListItem
{
Comment = applicantComment.Comment,
CommenterId = applicantComment.CommenterId,
CommenterDisplayName = user.OidcDisplayName,
CommenterBadge = user.Badge,
CreationTime = applicantComment.CreationTime,
OwnerId = ownerId,
Id = applicantComment.Id,
LastModificationTime = applicantComment.LastModificationTime,
PinDateTime = applicantComment.PinDateTime,
};
(applicantComment.LastModificationTime ?? applicantComment.CreationTime) descending
select new CommentListItem
{
Comment = applicantComment.Comment,
CommenterId = applicantComment.CommenterId,
CommenterDisplayName = user.OidcDisplayName,
CommenterBadge = user.Badge,
CreationTime = applicantComment.CreationTime,
OwnerId = ownerId,
Id = applicantComment.Id,
LastModificationTime = applicantComment.LastModificationTime,
PinDateTime = applicantComment.PinDateTime,
};
return applicantCommentsQry.ToList();
default:
throw new ArgumentOutOfRangeException(nameof(type));
Expand Down
Loading
Loading