Skip to content

Commit cadc611

Browse files
authored
Merge pull request #1436 from bcgov/dev
Dev
2 parents b6a8cd2 + 1f6c391 commit cadc611

43 files changed

Lines changed: 1783 additions & 926 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

applications/Unity.GrantManager/modules/Unity.SharedKernel/Constants/UnitySelector.cs

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@ public static partial class UnitySelector
1414

1515
public static partial class Applicant
1616
{
17-
public const string Default = "Unity.GrantManager.ApplicationManagement.Applicant";
17+
public const string Default = "Unity.GrantManager.ApplicationManagement.Applicant";
18+
public const string UpdatePolicy = "Unity.GrantManager.ApplicationManagement.Applicant.UpdatePolicy"; // Custom Policy
1819
public static partial class Authority
1920
{
2021
public const string Default = "Unity.GrantManager.ApplicationManagement.Applicant.Authority";
@@ -29,6 +30,13 @@ public static partial class Contact
2930
public const string Update = "Unity.GrantManager.ApplicationManagement.Applicant.Contact.Update";
3031
public const string Delete = "Unity.GrantManager.ApplicationManagement.Applicant.Contact.Delete";
3132
}
33+
public static partial class AdditionalContact
34+
{
35+
public const string Default = "Unity.GrantManager.ApplicationManagement.Applicant.AdditionalContact";
36+
public const string Create = "Unity.GrantManager.ApplicationManagement.Applicant.AdditionalContact.Create";
37+
public const string Update = "Unity.GrantManager.ApplicationManagement.Applicant.AdditionalContact.Update";
38+
public const string Delete = "Unity.GrantManager.ApplicationManagement.Applicant.AdditionalContact.Delete";
39+
}
3240
public static partial class Location
3341
{
3442
public const string Default = "Unity.GrantManager.ApplicationManagement.Applicant.Location";
@@ -156,6 +164,7 @@ public static partial class History
156164
{
157165
public const string Default = "Unity.GrantManager.ApplicationManagement.History";
158166
}
167+
159168
public static partial class Notification
160169
{
161170
public const string Default = "Unity.GrantManager.ApplicationManagement.Notification";
@@ -170,8 +179,10 @@ public static partial class Draft
170179
public const string Update = "Unity.GrantManager.ApplicationManagement.Notification.Draft.Update";
171180
}
172181
}
182+
173183
public static partial class Payment
174184
{
185+
// NOTE: Review Payment namespace for permissions
175186
public const string Default = "Unity.GrantManager.ApplicationManagement.Payment";
176187
public static partial class Summary
177188
{
@@ -183,10 +194,10 @@ public static partial class Summary
183194

184195
public static partial class Supplier
185196
{
186-
public const string Default = "Unity.GrantManager.ApplicationManagement.Applicant.Supplier";
187-
public const string Create = "Unity.GrantManager.ApplicationManagement.Applicant.Supplier.Create";
188-
public const string Update = "Unity.GrantManager.ApplicationManagement.Applicant.Supplier.Update";
189-
public const string Delete = "Unity.GrantManager.ApplicationManagement.Applicant.Supplier.Delete";
197+
public const string Default = "Unity.GrantManager.ApplicationManagement.Payment.Supplier";
198+
public const string Create = "Unity.GrantManager.ApplicationManagement.Payment.Supplier.Create";
199+
public const string Update = "Unity.GrantManager.ApplicationManagement.Payment.Supplier.Update";
200+
public const string Delete = "Unity.GrantManager.ApplicationManagement.Payment.Supplier.Delete";
190201
}
191202

192203
public static partial class PaymentList
@@ -197,6 +208,7 @@ public static partial class PaymentList
197208
public const string Delete = "Unity.GrantManager.ApplicationManagement.Payment.PaymentList.Delete";
198209
}
199210
}
211+
200212
public static partial class Project
201213
{
202214
public const string Default = "Unity.GrantManager.ApplicationManagement.Project";
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Reflection;
5+
6+
namespace Unity.Modules.Shared.Utils;
7+
8+
public static class PropertyHelper
9+
{
10+
/// <summary>
11+
/// Applies null values from a DTO to a target entity for specified modified fields.
12+
/// Handles special cases for value types by either creating default instances or setting to null.
13+
/// </summary>
14+
/// <typeparam name="TDto">The source DTO type</typeparam>
15+
/// <typeparam name="TEntity">The target entity type</typeparam>
16+
/// <param name="sourceDto">The source DTO instance containing potential null values</param>
17+
/// <param name="targetEntity">The target entity to update</param>
18+
/// <param name="modifiedFields">Collection of field names that were modified</param>
19+
public static void ApplyNullValuesFromDto<TDto, TEntity>(
20+
TDto sourceDto,
21+
TEntity targetEntity,
22+
IEnumerable<string> modifiedFields)
23+
where TDto : class
24+
where TEntity : class
25+
{
26+
var dtoProperties = typeof(TDto).GetProperties();
27+
var entityProperties = typeof(TEntity).GetProperties().ToDictionary(p => p.Name, p => p);
28+
29+
foreach (var fieldName in modifiedFields)
30+
{
31+
if (dtoProperties.FirstOrDefault(p =>
32+
string.Equals(p.Name, fieldName, StringComparison.OrdinalIgnoreCase)) is { } dtoProperty)
33+
{
34+
var value = dtoProperty.GetValue(sourceDto);
35+
if (value == null && entityProperties.TryGetValue(dtoProperty.Name, out var entityProperty) && entityProperty.CanWrite)
36+
{
37+
entityProperty.SetValue(targetEntity, entityProperty.PropertyType.IsValueType
38+
&& Nullable.GetUnderlyingType(entityProperty.PropertyType) == null
39+
? Activator.CreateInstance(entityProperty.PropertyType)
40+
: null);
41+
}
42+
}
43+
}
44+
}
45+
}

applications/Unity.GrantManager/modules/Unity.Theme.UX2/src/Unity.Theme.UX2/wwwroot/themes/ux2/zone-extensions.js

Lines changed: 124 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,29 @@
33
return;
44
}
55

6+
/**
7+
* Unflatten dot separated JSON objects into nested objects
8+
*/
9+
$.fn.unflattenObject = function(flatObj) {
10+
const result = {};
11+
for (const flatKey in flatObj) {
12+
const value = flatObj[flatKey];
13+
if (!flatKey) continue;
14+
const keys = flatKey.split('.');
15+
let cur = result;
16+
for (let i = 0; i < keys.length; i++) {
17+
const k = keys[i];
18+
if (i === keys.length - 1) {
19+
cur[k] = value;
20+
} else {
21+
cur[k] = cur[k] || {};
22+
cur = cur[k];
23+
}
24+
}
25+
}
26+
return result;
27+
}
28+
629
/**
730
* @public
831
* Handles zone fieldset serialization with DTO nesting
@@ -16,7 +39,6 @@
1639
// OPTIONS NOTE: Zones to include
1740
// OPTIONS NOTE: Properties to include
1841

19-
2042
// Initialize result object
2143
const resultObject = {};
2244
// Collection phase: Gather all field data in a single pass
@@ -41,8 +63,16 @@
4163

4264
data.push({ name: this.name, value: value });
4365
});
44-
}
66+
} else {
67+
// Add only disabled fields marked with data-zone-include="true"
68+
$form.find(':disabled[name][data-zone-include="true"]').each(function () {
69+
const value = $(this).is(":checkbox") ?
70+
$(this).is(':checked') :
71+
$(this).val();
4572

73+
data.push({ name: this.name, value: value });
74+
});
75+
}
4676

4777
// Convert field names to camelCase if required
4878
if (camelCase) {
@@ -137,7 +167,7 @@ class UnityChangeTrackingForm {
137167
constructor($form, options = {}) {
138168

139169
this.options = {
140-
modifiedClass: 'unity-modified-field-marker',
170+
modifiedClass: options.modifiedClass || 'unity-modified-field-marker',
141171
saveButtonSelector: options.saveButtonSelector || '#saveButton',
142172
...options
143173
};
@@ -173,6 +203,9 @@ class UnityChangeTrackingForm {
173203
if ($el.prop('checked')) {
174204
this.originalValues[name] = $el.val();
175205
}
206+
} else if ($el.attr('data-zone-include') === 'true') {
207+
// Store whether this field should be included even when disabled
208+
this.originalValues[name] = $el.val();
176209
} else {
177210
this.originalValues[name] = $el.val();
178211
}
@@ -202,12 +235,15 @@ class UnityChangeTrackingForm {
202235
} else {
203236
return; // Skip radio buttons that aren't checked
204237
}
238+
} else if ($element.attr('data-zone-include') === 'true') {
239+
// Store whether this field should be included even when disabled
240+
currentValue = $element.val();
205241
} else {
206242
currentValue = $element.val();
207243
}
208244

209245
const originalValue = this.originalValues[name];
210-
246+
211247
if (currentValue !== originalValue) {
212248
this.markAsModified($element, name);
213249
} else {
@@ -313,6 +349,14 @@ class UnityZoneForm extends UnityChangeTrackingForm {
313349
this.addSubmitHandler();
314350
}
315351

352+
// NOTE Get Zone Status
353+
// NOTE Get field by name or id
354+
// NOTE Get field value by name or id
355+
356+
isValid() {
357+
return this.form.valid();
358+
}
359+
316360
initializeNumericFields() {
317361
$('.numeric-mask').maskMoney({ precision: 0 });
318362
$('.percentage-mask').maskMoney();
@@ -334,10 +378,86 @@ class UnityZoneForm extends UnityChangeTrackingForm {
334378
$('.unity-currency-input').maskMoney();
335379
}
336380

381+
/**
382+
* Extracts the last two segments from a string separated by underscores,
383+
* and returns them joined by an underscore (e.g., "Unity_GrantManager_ApplicationManagement_Applicant_Summary" => "Applicant_Summary").
384+
* If the input does not have at least two segments, returns the original string.
385+
* @private
386+
* @param {string} input
387+
* @returns {string}
388+
*/
389+
#extractZoneSuffix(input) {
390+
if (typeof input !== 'string') return input;
391+
const parts = input.split('_');
392+
if (parts.length < 2) return input;
393+
return parts.slice(-2).join('_');
394+
}
395+
337396
addSubmitHandler() {
338397
this.form.on('submit', (e) => {
339398
e.preventDefault();
399+
// Include submission handler callback
340400
this.resetTracking();
341401
});
342402
}
403+
404+
reportZones(viewExpanded = false) {
405+
let tableData = [];
406+
const self = this; // Store reference to the class instance
407+
408+
this.form.find('fieldset').each(function () {
409+
const fieldName = $(this).attr('name');
410+
411+
$(this).find(':input').each(function () {
412+
const $el = $(this);
413+
const name = this.name || '(no name)';
414+
415+
// Get current value based on input type
416+
let currentValue;
417+
if ($el.is(':checkbox')) {
418+
currentValue = $el.prop('checked');
419+
} else if ($el.is(':radio')) {
420+
if ($el.prop('checked')) {
421+
currentValue = $el.val();
422+
} else {
423+
currentValue = '(unchecked radio)';
424+
}
425+
} else {
426+
currentValue = $el.val() || '(no value)';
427+
}
428+
429+
// Get original value if it exists
430+
const originalValue = name !== '(no name)' && self.originalValues.hasOwnProperty(name) ?
431+
self.originalValues[name] : '(not tracked)';
432+
433+
const isModified = self.modifiedFields.has(name);
434+
435+
let tableOutput = {
436+
'fieldsetName': self.#extractZoneSuffix(fieldName),
437+
'id': this.id
438+
}
439+
440+
if (viewExpanded) {
441+
let expandedProperties = {
442+
'name': name,
443+
'tag': this.tagName.toLowerCase(),
444+
'type': this.type
445+
};
446+
447+
tableOutput = { ...tableOutput, ...expandedProperties };
448+
}
449+
450+
let changeProperties = {
451+
'originalValue': originalValue,
452+
'currentValue': currentValue,
453+
'modified': isModified
454+
};
455+
tableOutput = { ...tableOutput, ...changeProperties };
456+
457+
tableData.push(tableOutput);
458+
});
459+
});
460+
461+
console.table(tableData);
462+
}
343463
}

applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/Emails/CreateEmailDto.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ public class CreateEmailDto
1515
[MaxLength(1023)] // Max for CHES
1616
public string EmailSubject { get; set; } = string.Empty;
1717

18-
[MaxLength(40000)]
18+
1919
[Required]
2020
public string EmailBody { get; set; } = string.Empty;
2121
public Guid ApplicationId { get; set; }
Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
using System;
22
using Volo.Abp.Application.Dtos;
3+
using Volo.Abp.Auditing;
34

45
namespace Unity.GrantManager.GrantApplications;
56

67
[Serializable]
7-
public class ApplicantAddressDto : EntityDto<Guid>
8+
public class ApplicantAddressDto : EntityDto<Guid>, IHasCreationTime, IHasModificationTime
89
{
910
public Guid ApplicantId { get; set; }
1011
public string Street { get; set; } = string.Empty;
@@ -13,6 +14,8 @@ public class ApplicantAddressDto : EntityDto<Guid>
1314
public string? City { get; set; }
1415
public string? Province { get; set; }
1516
public string? Postal { get; set; }
17+
public AddressType AddressType { get; set; }
18+
1619
public DateTime CreationTime { get; set; }
17-
public AddressType AddressType { get; set; }
20+
public DateTime? LastModificationTime { get; set; }
1821
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using Unity.Flex.Worksheets;
4+
5+
namespace Unity.GrantManager.GrantApplications;
6+
7+
public class ApplicantInfoDto : CustomDataFieldDto
8+
{
9+
public Guid ApplicationId { get; set; }
10+
public Guid ApplicantId { get; set; }
11+
public Guid ApplicationFormId { get; set; }
12+
13+
public string ApplicationReferenceNo { get; set; } = string.Empty;
14+
public string ApplicantName { get; set; } = string.Empty;
15+
public GrantApplicationState ApplicationStatusCode { get; set; }
16+
public string? ElectoralDistrict { get; set; }
17+
18+
public ApplicantSummaryDto? ApplicantSummary { get; set; }
19+
public List<ApplicantAddressDto>? ApplicantAddresses { get; set; }
20+
public SigningAuthorityDto? SigningAuthority { get; set; }
21+
public ContactInfoDto? ContactInfo { get; set; }
22+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
using System;
2+
3+
namespace Unity.GrantManager.GrantApplications;
4+
5+
public class ApplicantSummaryDto
6+
{
7+
public Guid ApplicantId { get; set; }
8+
public string? ApplicantName { get; set; }
9+
public string? Sector { get; set; }
10+
public string? SubSector { get; set; }
11+
public string? OrgNumber { get; set; }
12+
public string? OrgName { get; set; }
13+
public string? NonRegOrgName { get; set; }
14+
public string? OrgStatus { get; set; }
15+
public string? OrganizationType { get; set; }
16+
public string? OrganizationSize { get; set; }
17+
public string? SectorSubSectorIndustryDesc { get; set; }
18+
public bool? RedStop { get; set; }
19+
public bool? IndigenousOrgInd { get; set; }
20+
public string? UnityApplicantId { get; set; }
21+
public string? FiscalDay { get; set; }
22+
public string? FiscalMonth { get; set; }
23+
public string? ElectoralDistrict { get; set; }
24+
}

0 commit comments

Comments
 (0)