+ var item = Model.ApplicationPaymentRequestForm[i];
+ var itemParentReference = !string.IsNullOrEmpty(item.ParentReferenceNo)
+ ? item.ParentReferenceNo
+ : item.SubmissionConfirmationCode;
+ string? itemGroupKey = item.IsPartOfParentChildGroup
+ ? itemParentReference
+ : null;
+
+ string? nextGroupKey = null;
+ if (i + 1 < Model.ApplicationPaymentRequestForm.Count)
+ {
+ var next = Model.ApplicationPaymentRequestForm[i + 1];
+ var nextParentReference = !string.IsNullOrEmpty(next.ParentReferenceNo)
+ ? next.ParentReferenceNo
+ : next.SubmissionConfirmationCode;
+ nextGroupKey = next.IsPartOfParentChildGroup
+ ? nextParentReference
+ : null;
+ }
+
+ if (itemGroupKey != null && itemGroupKey != currentGroupKey)
+ {
+ @:
+ groupOpen = true;
+ }
+
+
- @Model.ApplicationPaymentRequestForm[i].ApplicantName/@Model.ApplicationPaymentRequestForm[i].InvoiceNumber
- @if (!string.IsNullOrEmpty(Model.ApplicationPaymentRequestForm[i].ParentReferenceNo))
+ @item.ApplicantName/@item.InvoiceNumber
+ @if (!string.IsNullOrEmpty(item.ParentReferenceNo))
{
- (Parent Id: @Model.ApplicationPaymentRequestForm[i].ParentReferenceNo)
+ (Parent Id: @item.ParentReferenceNo)
}
-
+ data-parameter="@item.CorrelationId" />
@@ -93,42 +143,50 @@
+
-
+
-
+ disabled="@item.DisableFields"
+ onchange='checkMaxValueRequest("@item.CorrelationId",this, @item.RemainingAmount)' />
-
+
-
+
-
- Error @L["ApplicationPaymentRequest:Validations:RemainingAmountExceeded"] @Model.ApplicationPaymentRequestForm[i].RemainingAmount
+
+ Error @L["ApplicationPaymentRequest:Validations:RemainingAmountExceeded"] @item.RemainingAmount
-
- Error
-
-
- @for (var j = 0; j < Model.ApplicationPaymentRequestForm[i].ErrorList?.Count; j++)
+ @for (var j = 0; j < item.ErrorList?.Count; j++)
{
- Error @Model.ApplicationPaymentRequestForm[i].ErrorList[j]
+ Error @item.ErrorList[j]
}
+
+ if (groupOpen && nextGroupKey != itemGroupKey)
+ {
+ @:
+ @: Error
+ @:
+ @:
+ groupOpen = false;
+ }
+
+ currentGroupKey = itemGroupKey;
}
No Payments Selected
@@ -163,6 +221,8 @@
(function () {
if (window.jQuery) {
$('.unity-currency-input').maskMoney();
+ // Validate payment amounts on initial page load
+ validateAllPaymentAmounts();
}
})();
diff --git a/applications/Unity.GrantManager/modules/Unity.Payments/src/Unity.Payments.Web/Pages/PaymentRequests/CreatePaymentRequests.cshtml.cs b/applications/Unity.GrantManager/modules/Unity.Payments/src/Unity.Payments.Web/Pages/PaymentRequests/CreatePaymentRequests.cshtml.cs
index caf1aee4a..bd7f4fae7 100644
--- a/applications/Unity.GrantManager/modules/Unity.Payments/src/Unity.Payments.Web/Pages/PaymentRequests/CreatePaymentRequests.cshtml.cs
+++ b/applications/Unity.GrantManager/modules/Unity.Payments/src/Unity.Payments.Web/Pages/PaymentRequests/CreatePaymentRequests.cshtml.cs
@@ -214,9 +214,28 @@ private async Task GetRemainingAmountAllowedByApplicationAsync(GrantApp
{
decimal approvedAmmount = application.ApprovedAmount;
decimal totalFutureRequested = await paymentRequestAppService.GetTotalPaymentRequestAmountByCorrelationIdAsync(application.Id);
- if (approvedAmmount > totalFutureRequested)
+
+ // If this application has children, include their paid/pending amounts too
+ decimal childrenTotalPaidPending = 0;
+ var applicationLinks = await applicationLinksService.GetListByApplicationAsync(application.Id);
+ var childLinks = applicationLinks.Where(link => link.LinkType == ApplicationLinkType.Child && link.ApplicationId != application.Id).ToList();
+
+ if (childLinks.Count > 0)
+ {
+ // This is a parent application, sum up all children's paid/pending payments
+ foreach (var childLink in childLinks)
+ {
+ decimal childTotal = await paymentRequestAppService
+ .GetTotalPaymentRequestAmountByCorrelationIdAsync(childLink.ApplicationId);
+ childrenTotalPaidPending += childTotal;
+ }
+ }
+
+ // Calculate remaining: Approved - (Parent Paid/Pending + Children Paid/Pending)
+ decimal totalConsumed = totalFutureRequested + childrenTotalPaidPending;
+ if (approvedAmmount > totalConsumed)
{
- remainingAmount = approvedAmmount - totalFutureRequested;
+ remainingAmount = approvedAmmount - totalConsumed;
}
}
@@ -257,9 +276,8 @@ private async Task GetRemainingAmountAllowedByApplicationAsync(GrantApp
return (errors, parentReferenceNo); // No validation needed
}
- // Check if ParentFormId and ParentFormVersionId are set
- if (!applicationForm.ParentFormId.HasValue ||
- !applicationForm.ParentFormVersionId.HasValue)
+ // Check if ParentFormId is set
+ if (!applicationForm.ParentFormId.HasValue)
{
// Configuration issue - should not happen if validation works
return (errors, parentReferenceNo);
@@ -284,11 +302,10 @@ private async Task GetRemainingAmountAllowedByApplicationAsync(GrantApp
var parentApplication = await applicationService.GetAsync(parentLink.ApplicationId);
parentReferenceNo = parentApplication.ReferenceNo;
- // Validate both ParentFormId and ParentFormVersionId
+ // Validate ParentFormId matches
bool formIdMatches = parentFormDetails.ApplicationFormId == applicationForm.ParentFormId.Value;
- bool versionIdMatches = parentFormDetails.ApplicationFormVersionId == applicationForm.ParentFormVersionId.Value;
- if (!formIdMatches || !versionIdMatches)
+ if (!formIdMatches)
{
errors.Add("The selected parent form in Payment Configuration does not match the application's linked parent. Please verify and try again.");
return (errors, parentReferenceNo);
@@ -460,6 +477,7 @@ private async Task PopulateParentChildValidationData()
{
child.MaximumAllowedAmount = maximumPaymentAmount;
child.IsPartOfParentChildGroup = true;
+ child.ParentApprovedAmount = approvedAmount;
}
// Apply validation data to parent if in submission
@@ -467,6 +485,7 @@ private async Task PopulateParentChildValidationData()
{
parentInSubmission.MaximumAllowedAmount = maximumPaymentAmount;
parentInSubmission.IsPartOfParentChildGroup = true;
+ parentInSubmission.ParentApprovedAmount = approvedAmount;
}
}
}
diff --git a/applications/Unity.GrantManager/modules/Unity.Payments/src/Unity.Payments.Web/Pages/PaymentRequests/CreatePaymentRequestsModal.js b/applications/Unity.GrantManager/modules/Unity.Payments/src/Unity.Payments.Web/Pages/PaymentRequests/CreatePaymentRequestsModal.js
index c9a8f1315..647eff6ff 100644
--- a/applications/Unity.GrantManager/modules/Unity.Payments/src/Unity.Payments.Web/Pages/PaymentRequests/CreatePaymentRequestsModal.js
+++ b/applications/Unity.GrantManager/modules/Unity.Payments/src/Unity.Payments.Web/Pages/PaymentRequests/CreatePaymentRequestsModal.js
@@ -2,6 +2,7 @@
function removeApplicationPaymentRequest(applicationId) {
let $container = $('#' + applicationId);
+ let $parentGroup = $container.closest('.parent-child-group');
$container.remove();
$('#' + applicationId).remove();
@@ -19,6 +20,11 @@ function removeApplicationPaymentRequest(applicationId) {
$('#no-payment-msg').css('display', 'none');
}
+ // Clean up empty group wrappers
+ if ($parentGroup.length && $parentGroup.find('.single-payment').length === 0) {
+ $parentGroup.remove();
+ }
+
// Always recalculate the total after removal
calculateTotalAmount();
@@ -169,9 +175,15 @@ function validateParentChildAmounts(correlationId) {
let maximumAllowedInput = $(
`input[name="ApplicationPaymentRequestForm[${index}].MaximumAllowedAmount"]`
).val();
+ let parentApprovedAmount = $(
+ `input[name="ApplicationPaymentRequestForm[${index}].ParentApprovedAmount"]`
+ ).val();
let maximumAllowed = maximumAllowedInput
? parseFloat(maximumAllowedInput)
: 0;
+ let approvedAmount = parentApprovedAmount
+ ? parseFloat(parentApprovedAmount)
+ : 0;
// Determine if this is a parent or child
let isChild = parentRefNo && parentRefNo.trim() !== '';
@@ -179,7 +191,6 @@ function validateParentChildAmounts(correlationId) {
// Find all payments in this parent-child group
let groupTotal = 0;
- let groupMembers = [];
$('input[name*=".CorrelationId"]').each(function () {
let itemCorrelationId = $(this).val();
@@ -208,28 +219,31 @@ function validateParentChildAmounts(correlationId) {
);
let amount = parseFloat(amountInput.val().replace(/,/g, '')) || 0;
groupTotal += amount;
- groupMembers.push(itemCorrelationId);
}
});
// Validate: groupTotal <= maximumAllowed
let hasError = groupTotal > maximumAllowed;
- // Show/hide errors for ALL members of the group
- groupMembers.forEach(function (memberId) {
- let errorDiv = $(`#column_${memberId}_parent_child_error`);
- let errorMessage = $(`#parent_child_error_message_${memberId}`);
-
- if (hasError) {
- let message = `Parent-child total (${formatCurrency(
- groupTotal
- )}) exceeds maximum allowed by parent (${formatCurrency(
- maximumAllowed
- )})`;
- errorMessage.text(message);
- errorDiv.css('display', 'block');
- } else {
- errorDiv.css('display', 'none');
- }
- });
+ // Show/hide error once at the group level
+ if (groupKey == null) return;
+ let groupWrapper = $(`.parent-child-group[data-group-key="${CSS.escape(groupKey)}"]`);
+ let groupErrorDiv = groupWrapper.find('[data-role="group-error"]');
+ let groupErrorMessage = groupWrapper.find('[data-role="group-error-message"]');
+
+ if (hasError) {
+ let message = `The total payment amount (${formatCurrency(
+ groupTotal
+ )}) exceeds the remaining balance (${formatCurrency(
+ maximumAllowed
+ )}) of the approved amount (${formatCurrency(
+ approvedAmount
+ )}) for the application or its parent application.`;
+ groupErrorMessage.text(message);
+ groupErrorDiv.css('display', 'block');
+ groupWrapper.addClass('has-error');
+ } else {
+ groupErrorDiv.css('display', 'none');
+ groupWrapper.removeClass('has-error');
+ }
}
diff --git a/applications/Unity.GrantManager/modules/Unity.Payments/src/Unity.Payments.Web/Pages/PaymentRequests/PaymentsModel.cs b/applications/Unity.GrantManager/modules/Unity.Payments/src/Unity.Payments.Web/Pages/PaymentRequests/PaymentsModel.cs
index 3c951a240..30fcfd50a 100644
--- a/applications/Unity.GrantManager/modules/Unity.Payments/src/Unity.Payments.Web/Pages/PaymentRequests/PaymentsModel.cs
+++ b/applications/Unity.GrantManager/modules/Unity.Payments/src/Unity.Payments.Web/Pages/PaymentRequests/PaymentsModel.cs
@@ -37,6 +37,7 @@ public class PaymentsModel
public Guid? AccountCodingId { get; set; }
public string? ParentReferenceNo { get; set; }
public decimal? MaximumAllowedAmount { get; set; }
+ public decimal? ParentApprovedAmount { get; set; }
public bool IsPartOfParentChildGroup { get; set; }
}
}
diff --git a/applications/Unity.GrantManager/modules/Unity.Payments/test/Unity.Payments.Application.Tests/BatchPaymentRequests/PaymentRequestAppService_Tests.cs b/applications/Unity.GrantManager/modules/Unity.Payments/test/Unity.Payments.Application.Tests/BatchPaymentRequests/PaymentRequestAppService_Tests.cs
index 6fd509b3e..81188411e 100644
--- a/applications/Unity.GrantManager/modules/Unity.Payments/test/Unity.Payments.Application.Tests/BatchPaymentRequests/PaymentRequestAppService_Tests.cs
+++ b/applications/Unity.GrantManager/modules/Unity.Payments/test/Unity.Payments.Application.Tests/BatchPaymentRequests/PaymentRequestAppService_Tests.cs
@@ -1,5 +1,4 @@
-using Microsoft.Extensions.DependencyInjection;
-using Shouldly;
+using Shouldly;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
@@ -8,7 +7,6 @@
using Unity.Payments.Domain.Suppliers.ValueObjects;
using Unity.Payments.Enums;
using Volo.Abp.Uow;
-using Volo.Abp.Users;
using Xunit;
namespace Unity.Payments.PaymentRequests;
diff --git a/applications/Unity.GrantManager/modules/Unity.TenantManagement/src/Unity.TenantManagement.Application.Contracts/TenantCreateOrUpdateDtoBase.cs b/applications/Unity.GrantManager/modules/Unity.TenantManagement/src/Unity.TenantManagement.Application.Contracts/TenantCreateOrUpdateDtoBase.cs
index ed2f985a9..0b89d2ddf 100644
--- a/applications/Unity.GrantManager/modules/Unity.TenantManagement/src/Unity.TenantManagement.Application.Contracts/TenantCreateOrUpdateDtoBase.cs
+++ b/applications/Unity.GrantManager/modules/Unity.TenantManagement/src/Unity.TenantManagement.Application.Contracts/TenantCreateOrUpdateDtoBase.cs
@@ -12,6 +12,11 @@ public abstract class TenantCreateOrUpdateDtoBase : ExtensibleObject
[Display(Name = "TenantName")]
public string Name { get; set; }
+ public string Division { get; set; } = string.Empty;
+ public string Branch { get; set; } = string.Empty;
+ public string Description { get; set; } = string.Empty;
+ public string CasClientCode { get; set; } = string.Empty;
+
protected TenantCreateOrUpdateDtoBase() : base(false)
{
}
diff --git a/applications/Unity.GrantManager/modules/Unity.TenantManagement/src/Unity.TenantManagement.Application.Contracts/TenantDto.cs b/applications/Unity.GrantManager/modules/Unity.TenantManagement/src/Unity.TenantManagement.Application.Contracts/TenantDto.cs
index 8d55f02f5..b1aaf19b9 100644
--- a/applications/Unity.GrantManager/modules/Unity.TenantManagement/src/Unity.TenantManagement.Application.Contracts/TenantDto.cs
+++ b/applications/Unity.GrantManager/modules/Unity.TenantManagement/src/Unity.TenantManagement.Application.Contracts/TenantDto.cs
@@ -7,6 +7,9 @@ namespace Unity.TenantManagement;
public class TenantDto : ExtensibleEntityDto, IHasConcurrencyStamp
{
public string Name { get; set; }
-
+ public string Division { get; set; } = string.Empty;
+ public string Branch { get; set; } = string.Empty;
+ public string Description { get; set; } = string.Empty;
+ public string CasClientCode { get; set; } = string.Empty;
public string ConcurrencyStamp { get; set; }
}
diff --git a/applications/Unity.GrantManager/modules/Unity.TenantManagement/src/Unity.TenantManagement.Application.Contracts/UnityTenantManagementPermissionDefinitionProvider.cs b/applications/Unity.GrantManager/modules/Unity.TenantManagement/src/Unity.TenantManagement.Application.Contracts/UnityTenantManagementPermissionDefinitionProvider.cs
index 96c835e77..4d29dda83 100644
--- a/applications/Unity.GrantManager/modules/Unity.TenantManagement/src/Unity.TenantManagement.Application.Contracts/UnityTenantManagementPermissionDefinitionProvider.cs
+++ b/applications/Unity.GrantManager/modules/Unity.TenantManagement/src/Unity.TenantManagement.Application.Contracts/UnityTenantManagementPermissionDefinitionProvider.cs
@@ -1,6 +1,5 @@
using Volo.Abp.Authorization.Permissions;
using Volo.Abp.Localization;
-using Volo.Abp.MultiTenancy;
using Volo.Abp.TenantManagement.Localization;
namespace Unity.TenantManagement;
@@ -9,14 +8,14 @@ public class UnityTenantManagementPermissionDefinitionProvider : PermissionDefin
{
public override void Define(IPermissionDefinitionContext context)
{
- var tenantManagementGroup = context.AddGroup(TenantManagementPermissions.GroupName, L("Permission:TenantManagement"));
-
- var tenantsPermission = tenantManagementGroup.AddPermission(TenantManagementPermissions.Tenants.Default, L("Permission:TenantManagement"), multiTenancySide: MultiTenancySides.Host);
- tenantsPermission.AddChild(TenantManagementPermissions.Tenants.Create, L("Permission:Create"), multiTenancySide: MultiTenancySides.Host);
- tenantsPermission.AddChild(TenantManagementPermissions.Tenants.Update, L("Permission:Edit"), multiTenancySide: MultiTenancySides.Host);
- tenantsPermission.AddChild(TenantManagementPermissions.Tenants.Delete, L("Permission:Delete"), multiTenancySide: MultiTenancySides.Host);
- tenantsPermission.AddChild(TenantManagementPermissions.Tenants.ManageFeatures, L("Permission:ManageFeatures"), multiTenancySide: MultiTenancySides.Host);
- tenantsPermission.AddChild(TenantManagementPermissions.Tenants.ManageConnectionStrings, L("Permission:ManageConnectionStrings"), multiTenancySide: MultiTenancySides.Host);
+ // Don't redefine permissions that already exist in the base ABP TenantManagement module
+ // Only add your custom permissions here
+ var tenantManagementGroup = context.GetGroupOrNull(TenantManagementPermissions.GroupName);
+
+ if (tenantManagementGroup == null)
+ {
+ context.AddGroup(TenantManagementPermissions.GroupName, L("Permission:TenantManagement"));
+ }
}
private static LocalizableString L(string name)
diff --git a/applications/Unity.GrantManager/modules/Unity.TenantManagement/src/Unity.TenantManagement.Application/TenantAppService.cs b/applications/Unity.GrantManager/modules/Unity.TenantManagement/src/Unity.TenantManagement.Application/TenantAppService.cs
index 12248e6de..1b76241d8 100644
--- a/applications/Unity.GrantManager/modules/Unity.TenantManagement/src/Unity.TenantManagement.Application/TenantAppService.cs
+++ b/applications/Unity.GrantManager/modules/Unity.TenantManagement/src/Unity.TenantManagement.Application/TenantAppService.cs
@@ -5,49 +5,32 @@
using Unity.TenantManagement.Abstractions;
using Unity.TenantManagement.Application;
using Unity.TenantManagement.Application.Contracts;
+using Volo.Abp;
using Volo.Abp.Application.Dtos;
using Volo.Abp.Data;
using Volo.Abp.EventBus.Local;
using Volo.Abp.MultiTenancy;
-using Volo.Abp.ObjectExtending;
using Volo.Abp.TenantManagement;
using Volo.Abp.Uow;
+using Volo.Abp.DependencyInjection;
namespace Unity.TenantManagement;
[Authorize(TenantManagementPermissions.Tenants.Default)]
-public class TenantAppService : TenantManagementAppServiceBase, ITenantAppService
+[ExposeServices(typeof(ITenantAppService), typeof(TenantAppService))]
+public class TenantAppService(
+ ICurrentTenant currentTenant,
+ ITenantRepository tenantRepository,
+ ITenantManager tenantManager,
+ ILocalEventBus localEventBus,
+ IUnitOfWorkManager unitOfWorkManager,
+ ITenantConnectionStringBuilder tenantConnectionStringBuilder) : TenantManagementAppServiceBase, ITenantAppService
{
- protected IDataSeeder DataSeeder { get; }
- protected ITenantRepository TenantRepository { get; }
- protected ITenantManager TenantManager { get; }
-
- private readonly ILocalEventBus _localEventBus;
-
- private readonly IUnitOfWorkManager _unitOfWorkManager;
-
- private readonly ITenantConnectionStringBuilder _tenantConnectionStringBuilder;
-
- public TenantAppService(
- ITenantRepository tenantRepository,
- ITenantManager tenantManager,
- IDataSeeder dataSeeder,
- ILocalEventBus localEventBus,
- IUnitOfWorkManager unitOfWorkManager,
- ITenantConnectionStringBuilder tenantConnectionStringBuilder)
- {
- DataSeeder = dataSeeder;
- TenantRepository = tenantRepository;
- TenantManager = tenantManager;
- _localEventBus = localEventBus;
- _unitOfWorkManager = unitOfWorkManager;
- _tenantConnectionStringBuilder = tenantConnectionStringBuilder;
- }
public virtual async Task GetAsync(Guid id)
{
return ObjectMapper.Map(
- await TenantRepository.GetAsync(id)
+ await tenantRepository.GetAsync(id)
);
}
@@ -58,8 +41,8 @@ public virtual async Task> GetListAsync(GetTenantsInpu
input.Sorting = nameof(Tenant.Name);
}
- var count = await TenantRepository.GetCountAsync(input.Filter);
- var list = await TenantRepository.GetListAsync(
+ var count = await tenantRepository.GetCountAsync(input.Filter);
+ var list = await tenantRepository.GetListAsync(
input.Sorting,
input.MaxResultCount,
input.SkipCount,
@@ -77,25 +60,28 @@ public virtual async Task CreateAsync(TenantCreateDto input)
{
Tenant tenant = null;
- using (var uow = _unitOfWorkManager.Begin(true, false))
+ using (var uow = unitOfWorkManager.Begin(true, false))
{
- tenant = await TenantManager.CreateAsync(input.Name);
+ tenant = await tenantManager.CreateAsync(input.Name);
tenant.ConnectionStrings
.Add(new TenantConnectionString(tenant.Id,
UnityTenantManagementConsts.TenantConnectionStringName,
- _tenantConnectionStringBuilder.Build(tenant.Name)));
+ tenantConnectionStringBuilder.Build(tenant.Name)));
- // This does not seem to work as intended?
- input.MapExtraPropertiesTo(tenant);
+ // Set ExtraProperties from input
+ tenant.ExtraProperties["Division"] = input.Division ?? string.Empty;
+ tenant.ExtraProperties["Branch"] = input.Branch ?? string.Empty;
+ tenant.ExtraProperties["Description"] = input.Description ?? string.Empty;
+ tenant.ExtraProperties["CasClientCode"] = input.CasClientCode ?? string.Empty;
- await TenantRepository.InsertAsync(tenant);
+ await tenantRepository.InsertAsync(tenant);
await uow.SaveChangesAsync();
await uow.CompleteAsync();
}
- await _localEventBus.PublishAsync(
+ await localEventBus.PublishAsync(
new TenantCreatedEto
{
Id = tenant.Id,
@@ -113,14 +99,19 @@ await _localEventBus.PublishAsync(
[Authorize(TenantManagementPermissions.Tenants.Update)]
public virtual async Task UpdateAsync(Guid id, TenantUpdateDto input)
{
- var tenant = await TenantRepository.GetAsync(id);
+ var tenant = await tenantRepository.GetAsync(id);
- await TenantManager.ChangeNameAsync(tenant, input.Name);
+ await tenantManager.ChangeNameAsync(tenant, input.Name);
tenant.SetConcurrencyStampIfNotNull(input.ConcurrencyStamp);
- input.MapExtraPropertiesTo(tenant);
+
+ // Update ExtraProperties from input
+ tenant.ExtraProperties["Division"] = input.Division ?? string.Empty;
+ tenant.ExtraProperties["Branch"] = input.Branch ?? string.Empty;
+ tenant.ExtraProperties["Description"] = input.Description ?? string.Empty;
+ tenant.ExtraProperties["CasClientCode"] = input.CasClientCode ?? string.Empty;
- await TenantRepository.UpdateAsync(tenant);
+ await tenantRepository.UpdateAsync(tenant);
return ObjectMapper.Map(tenant);
}
@@ -128,41 +119,56 @@ public virtual async Task UpdateAsync(Guid id, TenantUpdateDto input)
[Authorize(TenantManagementPermissions.Tenants.Delete)]
public virtual async Task DeleteAsync(Guid id)
{
- var tenant = await TenantRepository.FindAsync(id);
+ var tenant = await tenantRepository.FindAsync(id);
if (tenant == null)
{
return;
}
- await TenantRepository.DeleteAsync(tenant);
+ await tenantRepository.DeleteAsync(tenant);
}
[Authorize(TenantManagementPermissions.Tenants.ManageConnectionStrings)]
public virtual async Task GetDefaultConnectionStringAsync(Guid id)
{
- var tenant = await TenantRepository.GetAsync(id);
+ var tenant = await tenantRepository.GetAsync(id);
return tenant?.FindDefaultConnectionString();
}
[Authorize(TenantManagementPermissions.Tenants.ManageConnectionStrings)]
public virtual async Task UpdateDefaultConnectionStringAsync(Guid id, string defaultConnectionString)
{
- var tenant = await TenantRepository.GetAsync(id);
+ var tenant = await tenantRepository.GetAsync(id);
tenant.SetDefaultConnectionString(defaultConnectionString);
- await TenantRepository.UpdateAsync(tenant);
+ await tenantRepository.UpdateAsync(tenant);
}
[Authorize(TenantManagementPermissions.Tenants.ManageConnectionStrings)]
public virtual async Task DeleteDefaultConnectionStringAsync(Guid id)
{
- var tenant = await TenantRepository.GetAsync(id);
+ var tenant = await tenantRepository.GetAsync(id);
tenant.RemoveDefaultConnectionString();
- await TenantRepository.UpdateAsync(tenant);
+ await tenantRepository.UpdateAsync(tenant);
+ }
+
+ [RemoteService(false)]
+ [AllowAnonymous]
+ public async Task GetCurrentTenantCasClientCodeAsync(Guid tenantId)
+ {
+ var tenant = tenantId != Guid.Empty ? await tenantRepository.GetAsync(tenantId) : null;
+ return tenant?.ExtraProperties.TryGetValue("CasClientCode", out var value) == true ? value?.ToString() : null;
+ }
+
+ public async Task GetCurrentTenantName()
+ {
+ var tenantId = currentTenant.GetId();
+ var tenant = tenantId != Guid.Empty ? await tenantRepository.GetAsync(tenantId) : null;
+ return tenant?.Name ?? string.Empty;
}
public async Task AssignManagerAsync(TenantAssignManagerDto managerAssignment)
{
- await _localEventBus.PublishAsync(
+ await localEventBus.PublishAsync(
new TenantAssignManagerEto
{
TenantId = managerAssignment.TenantId,
diff --git a/applications/Unity.GrantManager/modules/Unity.TenantManagement/src/Unity.TenantManagement.Application/Unity.TenantManagement.Application.csproj b/applications/Unity.GrantManager/modules/Unity.TenantManagement/src/Unity.TenantManagement.Application/Unity.TenantManagement.Application.csproj
index 10a6939fd..53430a334 100644
--- a/applications/Unity.GrantManager/modules/Unity.TenantManagement/src/Unity.TenantManagement.Application/Unity.TenantManagement.Application.csproj
+++ b/applications/Unity.GrantManager/modules/Unity.TenantManagement/src/Unity.TenantManagement.Application/Unity.TenantManagement.Application.csproj
@@ -16,6 +16,7 @@
+
diff --git a/applications/Unity.GrantManager/modules/Unity.TenantManagement/src/Unity.TenantManagement.Application/UnityTenantManagementApplicationModule.cs b/applications/Unity.GrantManager/modules/Unity.TenantManagement/src/Unity.TenantManagement.Application/UnityTenantManagementApplicationModule.cs
index d3695545e..7b1d7a961 100644
--- a/applications/Unity.GrantManager/modules/Unity.TenantManagement/src/Unity.TenantManagement.Application/UnityTenantManagementApplicationModule.cs
+++ b/applications/Unity.GrantManager/modules/Unity.TenantManagement/src/Unity.TenantManagement.Application/UnityTenantManagementApplicationModule.cs
@@ -1,22 +1,26 @@
using Microsoft.Extensions.DependencyInjection;
-using Volo.Abp.Application;
using Volo.Abp.AutoMapper;
using Volo.Abp.Modularity;
using Volo.Abp.TenantManagement;
-namespace Unity.TenantManagement;
-
-[DependsOn(typeof(AbpTenantManagementDomainModule))]
-[DependsOn(typeof(UnityTenantManagementApplicationContractsModule))]
-[DependsOn(typeof(AbpDddApplicationModule))]
-public class UnityTenantManagementApplicationModule : AbpModule
+namespace Unity.TenantManagement
{
- public override void ConfigureServices(ServiceConfigurationContext context)
+ [DependsOn(
+ typeof(AbpTenantManagementDomainModule),
+ typeof(UnityTenantManagementApplicationContractsModule),
+ typeof(AbpTenantManagementApplicationModule),
+ typeof(AbpAutoMapperModule)
+ )]
+ public class UnityTenantManagementApplicationModule : AbpModule
{
- context.Services.AddAutoMapperObjectMapper();
- Configure(options =>
+ public override void ConfigureServices(ServiceConfigurationContext context)
{
- options.AddProfile(validate: true);
- });
+ context.Services.AddAutoMapperObjectMapper();
+
+ Configure(options =>
+ {
+ options.AddMaps(validate: true);
+ });
+ }
}
}
diff --git a/applications/Unity.GrantManager/modules/Unity.TenantManagement/src/Unity.TenantManagement.Application/UnityTenantManagementAutoMapperProfile.cs b/applications/Unity.GrantManager/modules/Unity.TenantManagement/src/Unity.TenantManagement.Application/UnityTenantManagementAutoMapperProfile.cs
new file mode 100644
index 000000000..8c11a3282
--- /dev/null
+++ b/applications/Unity.GrantManager/modules/Unity.TenantManagement/src/Unity.TenantManagement.Application/UnityTenantManagementAutoMapperProfile.cs
@@ -0,0 +1,28 @@
+#nullable enable
+
+using AutoMapper;
+using Volo.Abp.TenantManagement;
+
+namespace Unity.TenantManagement
+{
+ public class UnityTenantManagementAutoMapperProfile : Profile
+ {
+ public UnityTenantManagementAutoMapperProfile()
+ {
+ CreateMap()
+ .ForMember(dest => dest.CasClientCode, opt => opt.MapFrom(src =>
+ GetExtraProperty(src, "CasClientCode")))
+ .ForMember(dest => dest.Division, opt => opt.MapFrom(src =>
+ GetExtraProperty(src, "Division")))
+ .ForMember(dest => dest.Branch, opt => opt.MapFrom(src =>
+ GetExtraProperty(src, "Branch")))
+ .ForMember(dest => dest.Description, opt => opt.MapFrom(src =>
+ GetExtraProperty(src, "Description")));
+ }
+
+ private static string? GetExtraProperty(Tenant tenant, string key)
+ {
+ return tenant.ExtraProperties.TryGetValue(key, out var value) ? value?.ToString() : null;
+ }
+ }
+}
\ No newline at end of file
diff --git a/applications/Unity.GrantManager/modules/Unity.TenantManagement/src/Unity.TenantManagement.Web/Pages/TenantManagement/Tenants/CreateModal.cshtml.cs b/applications/Unity.GrantManager/modules/Unity.TenantManagement/src/Unity.TenantManagement.Web/Pages/TenantManagement/Tenants/CreateModal.cshtml.cs
index 070751aa8..a00e4f525 100644
--- a/applications/Unity.GrantManager/modules/Unity.TenantManagement/src/Unity.TenantManagement.Web/Pages/TenantManagement/Tenants/CreateModal.cshtml.cs
+++ b/applications/Unity.GrantManager/modules/Unity.TenantManagement/src/Unity.TenantManagement.Web/Pages/TenantManagement/Tenants/CreateModal.cshtml.cs
@@ -54,6 +54,12 @@ public class TenantInfoModel : ExtensibleObject
[Required]
public string Directory { get; set; } = "IDIR";
+ public string Division { get; set; } = string.Empty;
+ public string Branch { get; set; } = string.Empty;
+ public string Description { get; set; } = string.Empty;
+ public string CasClientCode { get; set; } = string.Empty;
+
+
[Required]
public string UserIdentifier { get; set; } = string.Empty;
}
diff --git a/applications/Unity.GrantManager/modules/Unity.TenantManagement/src/Unity.TenantManagement.Web/Pages/TenantManagement/Tenants/EditModal.cshtml b/applications/Unity.GrantManager/modules/Unity.TenantManagement/src/Unity.TenantManagement.Web/Pages/TenantManagement/Tenants/EditModal.cshtml
index a24b474ed..37f061a45 100644
--- a/applications/Unity.GrantManager/modules/Unity.TenantManagement/src/Unity.TenantManagement.Web/Pages/TenantManagement/Tenants/EditModal.cshtml
+++ b/applications/Unity.GrantManager/modules/Unity.TenantManagement/src/Unity.TenantManagement.Web/Pages/TenantManagement/Tenants/EditModal.cshtml
@@ -20,6 +20,22 @@
+
+
+
+
+
+
+
+
+
@foreach (var propertyInfo in ObjectExtensionManager.Instance.GetProperties())
{
if (!propertyInfo.Name.EndsWith("_Text"))
diff --git a/applications/Unity.GrantManager/modules/Unity.TenantManagement/src/Unity.TenantManagement.Web/Pages/TenantManagement/Tenants/EditModal.cshtml.cs b/applications/Unity.GrantManager/modules/Unity.TenantManagement/src/Unity.TenantManagement.Web/Pages/TenantManagement/Tenants/EditModal.cshtml.cs
index afbcebb1b..703aadd6f 100644
--- a/applications/Unity.GrantManager/modules/Unity.TenantManagement/src/Unity.TenantManagement.Web/Pages/TenantManagement/Tenants/EditModal.cshtml.cs
+++ b/applications/Unity.GrantManager/modules/Unity.TenantManagement/src/Unity.TenantManagement.Web/Pages/TenantManagement/Tenants/EditModal.cshtml.cs
@@ -1,7 +1,9 @@
using System;
+using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
+using Unity.GrantManager.Integrations;
using Volo.Abp.Domain.Entities;
using Volo.Abp.ObjectExtending;
using Volo.Abp.TenantManagement;
@@ -9,24 +11,22 @@
namespace Unity.TenantManagement.Web.Pages.TenantManagement.Tenants;
-public class EditModalModel : TenantManagementPageModel
+public class EditModalModel(ITenantAppService tenantAppService, ICasClientCodeLookupService lookupService) : TenantManagementPageModel
{
[BindProperty]
public TenantInfoModel Tenant { get; set; }
- protected ITenantAppService TenantAppService { get; }
- public EditModalModel(ITenantAppService tenantAppService)
- {
- TenantAppService = tenantAppService;
- }
+ public List CasClientOptions { get; set; } = [];
public virtual async Task OnGetAsync(Guid id)
{
Tenant = ObjectMapper.Map(
- await TenantAppService.GetAsync(id)
+ await tenantAppService.GetAsync(id)
);
+ CasClientOptions = await lookupService.GetActiveOptionsAsync();
+
return Page();
}
@@ -35,7 +35,7 @@ public virtual async Task OnPostAsync()
ValidateModel();
var input = ObjectMapper.Map(Tenant);
- await TenantAppService.UpdateAsync(Tenant.Id, input);
+ await tenantAppService.UpdateAsync(Tenant.Id, input);
return NoContent();
}
@@ -49,6 +49,12 @@ public class TenantInfoModel : ExtensibleObject, IHasConcurrencyStamp
[DynamicStringLength(typeof(TenantConsts), nameof(TenantConsts.MaxNameLength))]
[Display(Name = "DisplayName:TenantName")]
public string Name { get; set; }
+ public string Division { get; set; } = string.Empty;
+ public string Branch { get; set; } = string.Empty;
+ public string Description { get; set; } = string.Empty;
+
+ [Display(Name = "CAS Client Code")]
+ public string CasClientCode { get; set; } = string.Empty;
[HiddenInput]
public string ConcurrencyStamp { get; set; }
diff --git a/applications/Unity.GrantManager/modules/Unity.TenantManagement/src/Unity.TenantManagement.Web/Pages/TenantManagement/Tenants/Index.cshtml b/applications/Unity.GrantManager/modules/Unity.TenantManagement/src/Unity.TenantManagement.Web/Pages/TenantManagement/Tenants/Index.cshtml
index 160e25a0c..079457d92 100644
--- a/applications/Unity.GrantManager/modules/Unity.TenantManagement/src/Unity.TenantManagement.Web/Pages/TenantManagement/Tenants/Index.cshtml
+++ b/applications/Unity.GrantManager/modules/Unity.TenantManagement/src/Unity.TenantManagement.Web/Pages/TenantManagement/Tenants/Index.cshtml
@@ -38,3 +38,6 @@
+
diff --git a/applications/Unity.GrantManager/modules/Unity.TenantManagement/src/Unity.TenantManagement.Web/Pages/TenantManagement/Tenants/Index.cshtml.cs b/applications/Unity.GrantManager/modules/Unity.TenantManagement/src/Unity.TenantManagement.Web/Pages/TenantManagement/Tenants/Index.cshtml.cs
index 99c4a7a3e..31c3fabee 100644
--- a/applications/Unity.GrantManager/modules/Unity.TenantManagement/src/Unity.TenantManagement.Web/Pages/TenantManagement/Tenants/Index.cshtml.cs
+++ b/applications/Unity.GrantManager/modules/Unity.TenantManagement/src/Unity.TenantManagement.Web/Pages/TenantManagement/Tenants/Index.cshtml.cs
@@ -1,13 +1,32 @@
+using System.Collections.Generic;
+using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
+using Unity.GrantManager.Integrations;
namespace Unity.TenantManagement.Web.Pages.TenantManagement.Tenants;
public class IndexModel : TenantManagementPageModel
{
- public virtual Task OnGetAsync()
+ protected ICasClientCodeLookupService CasClientCodeLookupService { get; }
+
+ public Dictionary CasClientCodeHash { get; set; } = new();
+
+ public IndexModel(ICasClientCodeLookupService casClientCodeLookupService)
{
- return Task.FromResult(Page());
+ CasClientCodeLookupService = casClientCodeLookupService;
+ }
+
+ public virtual async Task OnGetAsync()
+ {
+ // Create hash where client code is key and code + description is value
+ var casClientCodes = await CasClientCodeLookupService.GetActiveOptionsAsync();
+ CasClientCodeHash = casClientCodes.ToDictionary(
+ c => c.Code,
+ c => c.DisplayName
+ );
+
+ return Page();
}
public virtual Task OnPostAsync()
diff --git a/applications/Unity.GrantManager/modules/Unity.TenantManagement/src/Unity.TenantManagement.Web/Pages/TenantManagement/Tenants/Index.js b/applications/Unity.GrantManager/modules/Unity.TenantManagement/src/Unity.TenantManagement.Web/Pages/TenantManagement/Tenants/Index.js
index 06da58750..049537e2f 100644
--- a/applications/Unity.GrantManager/modules/Unity.TenantManagement/src/Unity.TenantManagement.Web/Pages/TenantManagement/Tenants/Index.js
+++ b/applications/Unity.GrantManager/modules/Unity.TenantManagement/src/Unity.TenantManagement.Web/Pages/TenantManagement/Tenants/Index.js
@@ -99,6 +99,30 @@
title: l("TenantName"),
data: 'name',
},
+ {
+ title: l("Division"),
+ data: 'division',
+ },
+ {
+ title: l("Branch"),
+ data: 'branch',
+ },
+ {
+ title: l("Description"),
+ data: 'description',
+ },
+ {
+ title: "CAS Client Code",
+ data: 'casClientCode',
+ render: function (data, type, row) {
+ if (type === 'display') {
+ const code = row.casClientCode || '';
+ const displayValue = globalThis.casClientCodeHash?.[code] || '';
+ return displayValue;
+ }
+ return data;
+ }
+ },
{
title: l("Id"),
data: 'id',
@@ -254,4 +278,30 @@
_createModal.open();
});
});
+
+ // Use event delegation to handle dynamically loaded elements
+ $(document).on('change', '.cas-client-select', function() {
+ const $select = $(this);
+ const selectedOption = $select.find('option:selected');
+
+ // Handle ministry field update
+ const ministryValue = selectedOption.data('ministry') || '';
+ const ministryTarget = $select.data('ministry-target');
+ if (ministryTarget) {
+ const $targetInput = $(ministryTarget);
+ if ($targetInput.length) {
+ $targetInput.val(ministryValue);
+ }
+ }
+
+ // Handle CAS client code update
+ const casClientCode = selectedOption.data('cas-client-code');
+ if (casClientCode) {
+ const $container = $select.closest('form, .modal-body');
+ const $hiddenField = $container.find('input[name="CasClientCode"]');
+ if ($hiddenField.length) {
+ $hiddenField.val(casClientCode);
+ }
+ }
+ });
})();
diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/Applicants/ApplicantProfileDto.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/Applicants/ApplicantProfileDto.cs
index 30e2c1335..9ec81114f 100644
--- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/Applicants/ApplicantProfileDto.cs
+++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/Applicants/ApplicantProfileDto.cs
@@ -1,12 +1,14 @@
using System;
+using Unity.GrantManager.Applicants.ProfileData;
namespace Unity.GrantManager.Applicants
{
public class ApplicantProfileDto
{
public Guid ProfileId { get; set; }
- public string Subject { get; set; } = string.Empty;
- public string Email { get; set; } = string.Empty;
- public string DisplayName { get; set; } = string.Empty;
+ public string Subject { get; set; } = string.Empty;
+ public string Key { get; set; } = string.Empty;
+ public Guid TenantId { get; set; }
+ public ApplicantProfileDataDto? Data { get; set; }
}
}
diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/Applicants/ApplicantProfileRequest.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/Applicants/ApplicantProfileRequest.cs
index 3e5e2b610..9f65d31cd 100644
--- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/Applicants/ApplicantProfileRequest.cs
+++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/Applicants/ApplicantProfileRequest.cs
@@ -4,12 +4,13 @@ namespace Unity.GrantManager.Applicants
{
public class ApplicantProfileRequest
{
- public Guid ProfileId { get; set; } = Guid.NewGuid();
- public string Subject { get; set; } = string.Empty;
+ public Guid ProfileId { get; set; } = Guid.Empty;
+ public string Subject { get; set; } = string.Empty;
}
- public class TenantedApplicantProfileRequest : ApplicantProfileRequest
+ public class ApplicantProfileInfoRequest : ApplicantProfileRequest
{
- public Guid TenantId { get; set; }
+ public Guid TenantId { get; set; } = Guid.Empty;
+ public string Key { get; set; } = string.Empty;
}
}
diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/Applicants/IApplicantProfileAppService.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/Applicants/IApplicantProfileAppService.cs
index bab1f950c..968cef47f 100644
--- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/Applicants/IApplicantProfileAppService.cs
+++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/Applicants/IApplicantProfileAppService.cs
@@ -5,7 +5,7 @@ namespace Unity.GrantManager.Applicants
{
public interface IApplicantProfileAppService
{
- Task GetApplicantProfileAsync(ApplicantProfileRequest request);
+ Task GetApplicantProfileAsync(ApplicantProfileInfoRequest request);
Task> GetApplicantTenantsAsync(ApplicantProfileRequest request);
Task<(int Created, int Updated)> ReconcileApplicantTenantMapsAsync();
}
diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/Applicants/ProfileData/ApplicantAddressInfoDto.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/Applicants/ProfileData/ApplicantAddressInfoDto.cs
new file mode 100644
index 000000000..fde1734a0
--- /dev/null
+++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/Applicants/ProfileData/ApplicantAddressInfoDto.cs
@@ -0,0 +1,7 @@
+namespace Unity.GrantManager.Applicants.ProfileData
+{
+ public class ApplicantAddressInfoDto : ApplicantProfileDataDto
+ {
+ public override string DataType => "ADDRESSINFO";
+ }
+}
diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/Applicants/ProfileData/ApplicantContactInfoDto.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/Applicants/ProfileData/ApplicantContactInfoDto.cs
new file mode 100644
index 000000000..74c15630b
--- /dev/null
+++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/Applicants/ProfileData/ApplicantContactInfoDto.cs
@@ -0,0 +1,7 @@
+namespace Unity.GrantManager.Applicants.ProfileData
+{
+ public class ApplicantContactInfoDto : ApplicantProfileDataDto
+ {
+ public override string DataType => "CONTACTINFO";
+ }
+}
diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/Applicants/ProfileData/ApplicantOrgInfoDto.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/Applicants/ProfileData/ApplicantOrgInfoDto.cs
new file mode 100644
index 000000000..c14ac0413
--- /dev/null
+++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/Applicants/ProfileData/ApplicantOrgInfoDto.cs
@@ -0,0 +1,7 @@
+namespace Unity.GrantManager.Applicants.ProfileData
+{
+ public class ApplicantOrgInfoDto : ApplicantProfileDataDto
+ {
+ public override string DataType => "ORGINFO";
+ }
+}
diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/Applicants/ProfileData/ApplicantPaymentInfoDto.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/Applicants/ProfileData/ApplicantPaymentInfoDto.cs
new file mode 100644
index 000000000..a6f7b77c3
--- /dev/null
+++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/Applicants/ProfileData/ApplicantPaymentInfoDto.cs
@@ -0,0 +1,7 @@
+namespace Unity.GrantManager.Applicants.ProfileData
+{
+ public class ApplicantPaymentInfoDto : ApplicantProfileDataDto
+ {
+ public override string DataType => "PAYMENTINFO";
+ }
+}
diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/Applicants/ProfileData/ApplicantProfileDataDto.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/Applicants/ProfileData/ApplicantProfileDataDto.cs
new file mode 100644
index 000000000..3c717b28b
--- /dev/null
+++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/Applicants/ProfileData/ApplicantProfileDataDto.cs
@@ -0,0 +1,7 @@
+namespace Unity.GrantManager.Applicants.ProfileData
+{
+ public class ApplicantProfileDataDto
+ {
+ public virtual string DataType { get; } = "";
+ }
+}
diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/Applicants/ProfileData/ApplicantSubmissionInfoDto.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/Applicants/ProfileData/ApplicantSubmissionInfoDto.cs
new file mode 100644
index 000000000..4c0a0ba60
--- /dev/null
+++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/Applicants/ProfileData/ApplicantSubmissionInfoDto.cs
@@ -0,0 +1,7 @@
+namespace Unity.GrantManager.Applicants.ProfileData
+{
+ public class ApplicantSubmissionInfoDto : ApplicantProfileDataDto
+ {
+ public override string DataType => "SUBMISSIONINFO";
+ }
+}
diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/ApplicationForms/FormPaymentConfiguration.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/ApplicationForms/FormPaymentConfiguration.cs
index f2d177262..7991d7d21 100644
--- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/ApplicationForms/FormPaymentConfiguration.cs
+++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/ApplicationForms/FormPaymentConfiguration.cs
@@ -13,7 +13,6 @@ public class FormPaymentConfigurationDto
public decimal? PaymentApprovalThreshold { get; set; }
public FormHierarchyType? FormHierarchy { get; set; }
public Guid? ParentFormId { get; set; }
- public Guid? ParentFormVersionId { get; set; }
public PaymentGroup? DefaultPaymentGroup { get; set; }
}
}
diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/ApplicationForms/ParentFormLookupDto.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/ApplicationForms/ParentFormLookupDto.cs
index e5d61d1de..8c61da69f 100644
--- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/ApplicationForms/ParentFormLookupDto.cs
+++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/ApplicationForms/ParentFormLookupDto.cs
@@ -20,8 +20,7 @@ public ParentFormLookupRequestDto()
public class ParentFormLookupDto
{
public Guid ApplicationFormId { get; set; }
- public Guid ApplicationFormVersionId { get; set; }
public string ApplicationFormName { get; set; } = string.Empty;
- public int? Version { get; set; }
+ public string? Category { 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 6114bd34c..0571deb1a 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
@@ -1,4 +1,6 @@
-namespace Unity.GrantManager.GrantApplications;
+using System;
+
+namespace Unity.GrantManager.GrantApplications;
public class UpdateApplicantSummaryDto
{
@@ -17,5 +19,6 @@ public class UpdateApplicantSummaryDto
public bool? IndigenousOrgInd { get; set; }
public string? UnityApplicantId { get; set; }
public string? FiscalDay { get; set; }
- public string? FiscalMonth { get; set; }
+ public string? FiscalMonth { get; set; }
+ public DateOnly? StartedOperatingDate { get; set; }
}
diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/Integrations/CasClientCodeLookupDto.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/Integrations/CasClientCodeLookupDto.cs
new file mode 100644
index 000000000..0b7d43e8d
--- /dev/null
+++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/Integrations/CasClientCodeLookupDto.cs
@@ -0,0 +1,9 @@
+namespace Unity.GrantManager.Integrations
+{
+ public class CasClientCodeOptionDto
+ {
+ public string Code { get; set; } = string.Empty;
+ public string DisplayName { get; set; } = string.Empty;
+ public string Ministry { get; set; } = string.Empty;
+ }
+}
\ No newline at end of file
diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/Integrations/ICasClientCodeAppService.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/Integrations/ICasClientCodeAppService.cs
new file mode 100644
index 000000000..a91484d8a
--- /dev/null
+++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/Integrations/ICasClientCodeAppService.cs
@@ -0,0 +1,12 @@
+using System.Collections.Generic;
+using System.Threading.Tasks;
+using Volo.Abp.Application.Services;
+
+namespace Unity.GrantManager.Integrations
+{
+ public interface ICasClientCodeLookupService : IApplicationService
+ {
+ Task> GetActiveOptionsAsync();
+ Task GetClientIdByCasClientCodeAsync(string casClientCode);
+ }
+}
\ No newline at end of file
diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Applicants/ApplicantProfile/AddressInfoDataProvider.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Applicants/ApplicantProfile/AddressInfoDataProvider.cs
new file mode 100644
index 000000000..693a28994
--- /dev/null
+++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Applicants/ApplicantProfile/AddressInfoDataProvider.cs
@@ -0,0 +1,17 @@
+using System.Threading.Tasks;
+using Unity.GrantManager.Applicants.ProfileData;
+using Volo.Abp.DependencyInjection;
+
+namespace Unity.GrantManager.Applicants.ApplicantProfile
+{
+ [ExposeServices(typeof(IApplicantProfileDataProvider))]
+ public class AddressInfoDataProvider : IApplicantProfileDataProvider, ITransientDependency
+ {
+ public string Key => ApplicantProfileKeys.AddressInfo;
+
+ public Task GetDataAsync(ApplicantProfileInfoRequest request)
+ {
+ return Task.FromResult(new ApplicantAddressInfoDto());
+ }
+ }
+}
diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Applicants/ApplicantProfile/ApplicantProfileKeys.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Applicants/ApplicantProfile/ApplicantProfileKeys.cs
new file mode 100644
index 000000000..4b232c453
--- /dev/null
+++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Applicants/ApplicantProfile/ApplicantProfileKeys.cs
@@ -0,0 +1,11 @@
+namespace Unity.GrantManager.Applicants.ApplicantProfile
+{
+ public static class ApplicantProfileKeys
+ {
+ public const string ContactInfo = "CONTACTINFO";
+ public const string OrgInfo = "ORGINFO";
+ public const string AddressInfo = "ADDRESSINFO";
+ public const string SubmissionInfo = "SUBMISSIONINFO";
+ public const string PaymentInfo = "PAYMENTINFO";
+ }
+}
diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Applicants/ApplicantProfile/ContactInfoDataProvider.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Applicants/ApplicantProfile/ContactInfoDataProvider.cs
new file mode 100644
index 000000000..71539ca65
--- /dev/null
+++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Applicants/ApplicantProfile/ContactInfoDataProvider.cs
@@ -0,0 +1,17 @@
+using System.Threading.Tasks;
+using Unity.GrantManager.Applicants.ProfileData;
+using Volo.Abp.DependencyInjection;
+
+namespace Unity.GrantManager.Applicants.ApplicantProfile
+{
+ [ExposeServices(typeof(IApplicantProfileDataProvider))]
+ public class ContactInfoDataProvider : IApplicantProfileDataProvider, ITransientDependency
+ {
+ public string Key => ApplicantProfileKeys.ContactInfo;
+
+ public Task GetDataAsync(ApplicantProfileInfoRequest request)
+ {
+ return Task.FromResult(new ApplicantContactInfoDto());
+ }
+ }
+}
diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Applicants/ApplicantProfile/IApplicantProfileDataProvider.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Applicants/ApplicantProfile/IApplicantProfileDataProvider.cs
new file mode 100644
index 000000000..6a1b6b691
--- /dev/null
+++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Applicants/ApplicantProfile/IApplicantProfileDataProvider.cs
@@ -0,0 +1,27 @@
+using System.Threading.Tasks;
+using Unity.GrantManager.Applicants.ProfileData;
+
+namespace Unity.GrantManager.Applicants.ApplicantProfile
+{
+ ///
+ /// Defines a contract for components that can provide applicant profile data
+ /// based on an .
+ ///
+ public interface IApplicantProfileDataProvider
+ {
+ ///
+ /// Gets the unique key that identifies this applicant profile data provider.
+ ///
+ string Key { get; }
+
+ ///
+ /// Asynchronously retrieves applicant profile data for the specified request.
+ ///
+ /// The request containing the information needed to resolve the applicant profile.
+ ///
+ /// A task that, when completed successfully, returns an
+ /// containing the resolved applicant profile data.
+ ///
+ Task GetDataAsync(ApplicantProfileInfoRequest request);
+ }
+}
diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Applicants/ApplicantProfile/OrgInfoDataProvider.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Applicants/ApplicantProfile/OrgInfoDataProvider.cs
new file mode 100644
index 000000000..6d7f3c7cc
--- /dev/null
+++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Applicants/ApplicantProfile/OrgInfoDataProvider.cs
@@ -0,0 +1,17 @@
+using System.Threading.Tasks;
+using Unity.GrantManager.Applicants.ProfileData;
+using Volo.Abp.DependencyInjection;
+
+namespace Unity.GrantManager.Applicants.ApplicantProfile
+{
+ [ExposeServices(typeof(IApplicantProfileDataProvider))]
+ public class OrgInfoDataProvider : IApplicantProfileDataProvider, ITransientDependency
+ {
+ public string Key => ApplicantProfileKeys.OrgInfo;
+
+ public Task GetDataAsync(ApplicantProfileInfoRequest request)
+ {
+ return Task.FromResult(new ApplicantOrgInfoDto());
+ }
+ }
+}
diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Applicants/ApplicantProfile/PaymentInfoDataProvider.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Applicants/ApplicantProfile/PaymentInfoDataProvider.cs
new file mode 100644
index 000000000..5684f158e
--- /dev/null
+++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Applicants/ApplicantProfile/PaymentInfoDataProvider.cs
@@ -0,0 +1,17 @@
+using System.Threading.Tasks;
+using Unity.GrantManager.Applicants.ProfileData;
+using Volo.Abp.DependencyInjection;
+
+namespace Unity.GrantManager.Applicants.ApplicantProfile
+{
+ [ExposeServices(typeof(IApplicantProfileDataProvider))]
+ public class PaymentInfoDataProvider : IApplicantProfileDataProvider, ITransientDependency
+ {
+ public string Key => ApplicantProfileKeys.PaymentInfo;
+
+ public Task GetDataAsync(ApplicantProfileInfoRequest request)
+ {
+ return Task.FromResult(new ApplicantPaymentInfoDto());
+ }
+ }
+}
diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Applicants/ApplicantProfile/SubmissionInfoDataProvider.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Applicants/ApplicantProfile/SubmissionInfoDataProvider.cs
new file mode 100644
index 000000000..7af7e641f
--- /dev/null
+++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Applicants/ApplicantProfile/SubmissionInfoDataProvider.cs
@@ -0,0 +1,17 @@
+using System.Threading.Tasks;
+using Unity.GrantManager.Applicants.ProfileData;
+using Volo.Abp.DependencyInjection;
+
+namespace Unity.GrantManager.Applicants.ApplicantProfile
+{
+ [ExposeServices(typeof(IApplicantProfileDataProvider))]
+ public class SubmissionInfoDataProvider : IApplicantProfileDataProvider, ITransientDependency
+ {
+ public string Key => ApplicantProfileKeys.SubmissionInfo;
+
+ public Task GetDataAsync(ApplicantProfileInfoRequest request)
+ {
+ return Task.FromResult(new ApplicantSubmissionInfoDto());
+ }
+ }
+}
diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Applicants/ApplicantProfileAppService.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Applicants/ApplicantProfileAppService.cs
index 7f7066a0f..057b27d90 100644
--- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Applicants/ApplicantProfileAppService.cs
+++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Applicants/ApplicantProfileAppService.cs
@@ -4,6 +4,7 @@
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
+using Unity.GrantManager.Applicants.ApplicantProfile;
using Unity.GrantManager.Applications;
using Volo.Abp;
using Volo.Abp.Application.Services;
@@ -18,9 +19,12 @@ public class ApplicantProfileAppService(
ICurrentTenant currentTenant,
ITenantRepository tenantRepository,
IRepository applicantTenantMapRepository,
- IRepository applicationFormSubmissionRepository)
+ IRepository applicationFormSubmissionRepository,
+ IEnumerable dataProviders)
: ApplicationService, IApplicantProfileAppService
{
+ private readonly Dictionary _providersByKey
+ = dataProviders.ToDictionary(p => p.Key, StringComparer.OrdinalIgnoreCase);
///
/// Retrieves the applicant's profile information based on the specified request.
@@ -28,15 +32,26 @@ public class ApplicantProfileAppService(
/// An object containing the criteria used to identify the applicant profile to retrieve. Must not be null.
/// A task that represents the asynchronous operation. The task result contains an with the applicant's profile data.
- public async Task GetApplicantProfileAsync(ApplicantProfileRequest request)
+ public async Task GetApplicantProfileAsync(ApplicantProfileInfoRequest request)
{
- return await Task.FromResult(new ApplicantProfileDto
+ var dto = new ApplicantProfileDto
{
ProfileId = request.ProfileId,
- Subject = request.Subject,
- Email = string.Empty,
- DisplayName = string.Empty
- });
+ Subject = request.Subject,
+ TenantId = request.TenantId,
+ Key = request.Key
+ };
+
+ if (_providersByKey.TryGetValue(request.Key, out var provider))
+ {
+ dto.Data = await provider.GetDataAsync(request);
+ }
+ else
+ {
+ Logger.LogWarning("Unknown applicant profile key provided");
+ }
+
+ return dto;
}
///
diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/ApplicationForms/ApplicationFormAppService.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/ApplicationForms/ApplicationFormAppService.cs
index a26a91a97..d95d45758 100644
--- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/ApplicationForms/ApplicationFormAppService.cs
+++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/ApplicationForms/ApplicationFormAppService.cs
@@ -206,11 +206,6 @@ public async Task SavePaymentConfiguration(FormPaymentConfigurationDto dto)
throw new BusinessException(GrantManagerDomainErrorCodes.ChildFormRequiresParentForm);
}
- if (!dto.ParentFormVersionId.HasValue)
- {
- throw new BusinessException(GrantManagerDomainErrorCodes.ChildFormRequiresParentFormVersion);
- }
-
if (dto.ParentFormId.Value == appForm.Id)
{
throw new BusinessException(GrantManagerDomainErrorCodes.ChildFormCannotReferenceSelf);
@@ -221,12 +216,6 @@ public async Task SavePaymentConfiguration(FormPaymentConfigurationDto dto)
{
throw new BusinessException(GrantManagerDomainErrorCodes.ChildFormRequiresParentForm);
}
-
- var parentFormVersion = await _applicationFormVersionRepository.FindAsync(dto.ParentFormVersionId.Value);
- if (parentFormVersion is null || parentFormVersion.ApplicationFormId != parentForm.Id)
- {
- throw new BusinessException(GrantManagerDomainErrorCodes.ParentFormVersionMismatch);
- }
}
}
@@ -236,7 +225,6 @@ public async Task SavePaymentConfiguration(FormPaymentConfigurationDto dto)
appForm.PaymentApprovalThreshold = dto.PaymentApprovalThreshold;
appForm.FormHierarchy = dto.FormHierarchy;
appForm.ParentFormId = dto.ParentFormId;
- appForm.ParentFormVersionId = dto.ParentFormVersionId;
var resolvedDefaultPaymentGroup = dto.DefaultPaymentGroup ?? PaymentGroup.EFT;
appForm.DefaultPaymentGroup = dto.Payable ? (int?)resolvedDefaultPaymentGroup : null;
await Repository.UpdateAsync(appForm);
@@ -252,43 +240,40 @@ public async Task> GetParentFormLookupAsync(
var normalizedFilter = string.IsNullOrWhiteSpace(input.Filter) ? null : input.Filter.Trim();
var formsQueryable = await Repository.GetQueryableAsync();
- var versionsQueryable = await _applicationFormVersionRepository.GetQueryableAsync();
-
- var query =
- from form in formsQueryable
- join version in versionsQueryable on form.Id equals version.ApplicationFormId
- where version.Published
- select new { form, version };
+ var query = formsQueryable.AsQueryable();
if (input.ExcludeFormId.HasValue)
{
- query = query.Where(x => x.form.Id != input.ExcludeFormId.Value);
+ query = query.Where(x => x.Id != input.ExcludeFormId.Value);
}
if (!string.IsNullOrWhiteSpace(normalizedFilter))
{
var loweredFilter = normalizedFilter.ToLowerInvariant();
+#pragma warning disable CA1862 // Use the 'StringComparison' method overloads to perform case-insensitive string comparisons
+ // Need to suppress this because EF Core does not support StringComparison
query = query.Where(x =>
- x.form.ApplicationFormName != null &&
- x.form.ApplicationFormName.ToLower().Contains(loweredFilter));
+ (x.ApplicationFormName != null &&
+ x.ApplicationFormName.ToLower().Contains(loweredFilter)) ||
+ (x.Category != null &&
+ x.Category.ToLower().Contains(loweredFilter)));
+#pragma warning restore CA1862 // Use the 'StringComparison' method overloads to perform case-insensitive string comparisons
}
var totalCount = await AsyncExecuter.CountAsync(query);
var items = await AsyncExecuter.ToListAsync(
query
- .OrderBy(x => x.form.ApplicationFormName)
- .ThenByDescending(x => x.version.Version)
+ .OrderBy(x => x.ApplicationFormName)
.Skip(skipCount)
.Take(maxResultCount)
);
var results = items.Select(x => new ParentFormLookupDto
{
- ApplicationFormId = x.form.Id,
- ApplicationFormVersionId = x.version.Id,
- ApplicationFormName = x.form.ApplicationFormName ?? string.Empty,
- Version = x.version.Version
+ ApplicationFormId = x.Id,
+ ApplicationFormName = x.ApplicationFormName ?? string.Empty,
+ Category = x.Category
}).ToList();
return new PagedResultDto(totalCount, results);
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 4a6ea1a6a..66ddcf371 100644
--- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/GrantApplications/GrantApplicationAppService.cs
+++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/GrantApplications/GrantApplicationAppService.cs
@@ -122,7 +122,6 @@ public async Task> GetListAsync(GrantApplica
return new PagedResultDto(totalCount, appDtos);
}
-
private static string MapSubstatusDisplayValue(string subStatus)
{
if (subStatus == null) { return string.Empty; }
diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/GrantManagerApplicationAutoMapperProfile.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/GrantManagerApplicationAutoMapperProfile.cs
index f5ecfac7f..fd3459abe 100644
--- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/GrantManagerApplicationAutoMapperProfile.cs
+++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/GrantManagerApplicationAutoMapperProfile.cs
@@ -124,6 +124,7 @@ public GrantManagerApplicationAutoMapperProfile()
CreateMap()
.ForMember(dest => dest.Postal, opt => opt.MapFrom(src => src.PostalCode))
.IgnoreNullAndDefaultValues();
+
}
private static bool? ConvertIndigenousOrgIndToBool(string indigenousOrgInd)
@@ -145,6 +146,7 @@ public GrantManagerApplicationAutoMapperProfile()
_ => null
};
}
+
}
// Extension methods for reusable mapping configurations
diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Integrations/CasClientCodeAppService.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Integrations/CasClientCodeAppService.cs
new file mode 100644
index 000000000..d1d72f89f
--- /dev/null
+++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Integrations/CasClientCodeAppService.cs
@@ -0,0 +1,46 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+using Unity.GrantManager.Applications;
+using Volo.Abp;
+using Volo.Abp.Application.Services;
+
+namespace Unity.GrantManager.Integrations
+{
+ [RemoteService(false)]
+ public class CasClientCodeLookupService(ICasClientCodeRepository repository) : ApplicationService, ICasClientCodeLookupService
+ {
+
+ public async Task> GetActiveOptionsAsync()
+ {
+ var codes = await repository.GetListAsync();
+
+ return [.. codes
+ .Where(c => c.IsActive)
+ .OrderBy(c => c.ClientCode)
+ .Select(c => new CasClientCodeOptionDto
+ {
+ Code = c.ClientCode,
+ DisplayName = $"{c.ClientCode} - {c.Description}",
+ Ministry = c.FinancialMinistry ?? string.Empty
+ })];
+ }
+
+ public async Task GetClientIdByCasClientCodeAsync(string casClientCode)
+ {
+ if (string.IsNullOrWhiteSpace(casClientCode))
+ {
+ return null;
+ }
+
+ var queryable = await repository.GetQueryableAsync();
+ var code = await AsyncExecuter.FirstOrDefaultAsync(
+ queryable.Where(x => x.ClientCode == casClientCode)
+ );
+
+ return code?.ClientId;
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Integrations/Endpoints/EndpointManagementAppService.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Integrations/Endpoints/EndpointManagementAppService.cs
index 21cb718ec..59f7fa3a8 100644
--- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Integrations/Endpoints/EndpointManagementAppService.cs
+++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Integrations/Endpoints/EndpointManagementAppService.cs
@@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
+using Microsoft.AspNetCore.Authorization;
using Microsoft.Extensions.Caching.Distributed;
using Volo.Abp;
using Volo.Abp.Application.Dtos;
@@ -64,6 +65,8 @@ private async Task RemoveFromKeySetAsync(string cacheKey, Guid? tenantId)
}
[UnitOfWork]
+ [RemoteService(false)]
+ [AllowAnonymous]
public async Task GetChefsApiBaseUrlAsync()
{
var url = await GetUrlByKeyNameInternalAsync(DynamicUrlKeyNames.INTAKE_API_BASE, tenantSpecific: false);
@@ -75,6 +78,8 @@ public async Task GetChefsApiBaseUrlAsync()
}
[UnitOfWork]
+ [RemoteService(false)]
+ [AllowAnonymous]
public async Task GetUgmUrlByKeyNameAsync(string keyName)
{
var url = await GetUrlByKeyNameInternalAsync(keyName, tenantSpecific: false);
diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.DbMigrator/appsettings.json b/applications/Unity.GrantManager/src/Unity.GrantManager.DbMigrator/appsettings.json
index 626191b07..452a5ac1d 100644
--- a/applications/Unity.GrantManager/src/Unity.GrantManager.DbMigrator/appsettings.json
+++ b/applications/Unity.GrantManager/src/Unity.GrantManager.DbMigrator/appsettings.json
@@ -1,7 +1,7 @@
{
"ConnectionStrings": {
- "Default": "Host=localhost;port=5432;Database=UnityGrantManager;Username=postgres;",
- "Tenant": "Host=localhost;port=5432;Database=UnityGrantTenant;Username=postgres;"
+ "Default": "Host=localhost;port=5432;Database=UnityGrantManager;Username=postgres",
+ "Tenant": "Host=localhost;port=5432;Database=UnityGrantTenant;Username=postgres"
},
"Redis": {
"Configuration": "127.0.0.1"
diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Domain.Shared/GrantManagerDomainErrorCodes.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Domain.Shared/GrantManagerDomainErrorCodes.cs
index e85a4e601..b06c20bc5 100644
--- a/applications/Unity.GrantManager/src/Unity.GrantManager.Domain.Shared/GrantManagerDomainErrorCodes.cs
+++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Domain.Shared/GrantManagerDomainErrorCodes.cs
@@ -20,7 +20,5 @@ public static class GrantManagerDomainErrorCodes
/* PAYMENT CONFIGURATION */
public const string PayableFormRequiresHierarchy = "GrantManager:PayableFormRequiresHierarchy";
public const string ChildFormRequiresParentForm = "GrantManager:ChildFormRequiresParentForm";
- public const string ChildFormRequiresParentFormVersion = "GrantManager:ChildFormRequiresParentFormVersion";
- public const string ParentFormVersionMismatch = "GrantManager:ParentFormVersionMismatch";
public const string ChildFormCannotReferenceSelf = "GrantManager:ChildFormCannotReferenceSelf";
}
diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Domain.Shared/Integrations/CasClientCode.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Domain.Shared/Integrations/CasClientCode.cs
new file mode 100644
index 000000000..c6ff0602f
--- /dev/null
+++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Domain.Shared/Integrations/CasClientCode.cs
@@ -0,0 +1,21 @@
+using System;
+using System.ComponentModel.DataAnnotations;
+using Volo.Abp.Domain.Entities.Auditing;
+
+namespace Unity.GrantManager.Integrations;
+
+public class CasClientCode : FullAuditedAggregateRoot
+{
+ [MaxLength(3)]
+ public string ClientCode { get; set; } = string.Empty;
+
+ public string Description { get; set; } = string.Empty;
+
+ [MaxLength(3)]
+ public string MinistryPrefix { get; set; } = string.Empty;
+
+ public string? FinancialMinistry { get; set; }
+ public string? ClientId { get; set; }
+ public bool IsActive { get; set; } = true;
+ public DateTimeOffset? LastUpdatedTime { 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 9efa6d229..667bc316f 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
@@ -246,8 +246,6 @@
"GrantManager:CantCreateAssessmentForFinalStateApplication": "Business Exception: You cannot create an assessment for an application in final state.",
"GrantManager:PayableFormRequiresHierarchy": "Please select a form hierarchy before saving a payable form.",
"GrantManager:ChildFormRequiresParentForm": "Please select a parent form when the form hierarchy is set to Child.",
- "GrantManager:ChildFormRequiresParentFormVersion": "Please select a parent form version when the form hierarchy is set to Child.",
- "GrantManager:ParentFormVersionMismatch": "The selected parent form version does not belong to the chosen parent form.",
"GrantManager:ChildFormCannotReferenceSelf": "A form cannot reference itself as the parent.",
"AssessmentResultsView:ApprovalTitle": "Approval",
diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Domain.Shared/Permissions/GrantApplicationPermissions.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Domain.Shared/Permissions/GrantApplicationPermissions.cs
index b3997090f..b46f5c310 100644
--- a/applications/Unity.GrantManager/src/Unity.GrantManager.Domain.Shared/Permissions/GrantApplicationPermissions.cs
+++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Domain.Shared/Permissions/GrantApplicationPermissions.cs
@@ -105,6 +105,22 @@ public static class ApplicantInfo
public const string DeleteAdditionalContact = Default + ".AdditionalContact" + Operation.Delete;
}
+ public static class Payments
+ {
+ public const string Default = GroupName + ".Payments";
+ public const string Create = Default + ".Create";
+ public const string Edit = Default + ".Edit";
+ public const string Delete = Default + ".Delete";
+
+ public static class PaymentRequests
+ {
+ public const string PaymentRequestDefault = Payments.Default + ".PaymentRequests";
+ public const string CreatePaymentRequest = Default + ".Create";
+ public const string EditPaymentRequest = Default + ".Edit";
+ public const string DeletePaymentRequest = Default + ".Delete";
+ }
+ }
+
public static string[] GetAll()
{
return ReflectionHelper.GetPublicConstantsRecursively(typeof(GrantApplicationPermissions));
diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Domain/Applications/ApplicationForm.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Domain/Applications/ApplicationForm.cs
index 62629517e..b60d8264f 100644
--- a/applications/Unity.GrantManager/src/Unity.GrantManager.Domain/Applications/ApplicationForm.cs
+++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Domain/Applications/ApplicationForm.cs
@@ -31,7 +31,6 @@ public class ApplicationForm : FullAuditedAggregateRoot, IMultiTenant
public int? DefaultPaymentGroup { get; set; }
public FormHierarchyType? FormHierarchy { get; set; }
public Guid? ParentFormId { get; set; }
- public Guid? ParentFormVersionId { get; set; }
public bool RenderFormIoToHtml { get; set; } = false;
public bool IsDirectApproval { get; set; } = false;
public string? Prefix { get; set; }
diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Domain/Applications/ICasClientCodeRepository.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Domain/Applications/ICasClientCodeRepository.cs
new file mode 100644
index 000000000..a152a7387
--- /dev/null
+++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Domain/Applications/ICasClientCodeRepository.cs
@@ -0,0 +1,9 @@
+using System;
+using Unity.GrantManager.Integrations;
+using Volo.Abp.Domain.Repositories;
+
+namespace Unity.GrantManager.Applications;
+
+public interface ICasClientCodeRepository : IRepository
+{
+}
diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Domain/Integrations/CasClientCodesDataSeeder.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Domain/Integrations/CasClientCodesDataSeeder.cs
new file mode 100644
index 000000000..26302b7ce
--- /dev/null
+++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Domain/Integrations/CasClientCodesDataSeeder.cs
@@ -0,0 +1,149 @@
+using System.Collections.Generic;
+using System.Threading.Tasks;
+using Unity.GrantManager.Applications;
+using Volo.Abp.Data;
+using Volo.Abp.DependencyInjection;
+using Volo.Abp.Domain.Repositories;
+
+namespace Unity.GrantManager.Integrations
+{
+ [Dependency(ReplaceServices = true)]
+ [ExposeServices(typeof(CasClientCodesDataSeeder), typeof(IDataSeedContributor))]
+ public class CasClientCodesDataSeeder(ICasClientCodeRepository CasClientCodeRepository) : IDataSeedContributor, ITransientDependency
+ {
+ public async Task SeedAsync(DataSeedContext context)
+ {
+ await SeedCasClientCodesAsync();
+ }
+
+ private async Task SeedCasClientCodesAsync()
+ {
+#pragma warning disable S1192 // Use 'new(...)
+ var clientCodes = new List
+ {
+ new() { ClientCode = "002", Description = "Legislative Assembly", FinancialMinistry = "", IsActive = true },
+ new() { ClientCode = "003", Description = "Auditor General", FinancialMinistry = "Office of the Auditor General ", IsActive = true },
+ new() { ClientCode = "004", Description = "Office of the Premier", FinancialMinistry = "Office of the Premier", IsActive = true },
+ new() { ClientCode = "005", Description = "Conflict of Interest Commissioner", FinancialMinistry = "", IsActive = true },
+ new() { ClientCode = "007", Description = "Ombudsperson", FinancialMinistry = "Office of the Ombudsperson", IsActive = true },
+ new() { ClientCode = "009", Description = "Info and Privacy Commissioner", FinancialMinistry = "Information and Privacy Commission", IsActive = true },
+ new() { ClientCode = "010", Description = "Public Safety and Solicitor General", FinancialMinistry = "Solicitor General", IsActive = true },
+ new() { ClientCode = "015", Description = "Elections BC", FinancialMinistry = "", IsActive = true },
+ new() { ClientCode = "019", Description = "Post-Secondary Education and Future Skills", FinancialMinistry = "Post Secondary Education and Future Skills", IsActive = true },
+ new() { ClientCode = "022", Description = "Finance", FinancialMinistry = "Finance", IsActive = true },
+ new() { ClientCode = "025", Description = "Police Complaint Commissioner", FinancialMinistry = "Police Complaint Commissioner Office", IsActive = true },
+ new() { ClientCode = "026", Description = "Health", FinancialMinistry = "Health", IsActive = true },
+ new() { ClientCode = "027", Description = "Mental Health and Addictions", FinancialMinistry = "Mental Health and Addictions", IsActive = true },
+ new() { ClientCode = "029", Description = "Vital Statistics CHIPS", FinancialMinistry = "", IsActive = true },
+ new() { ClientCode = "031", Description = "Social Development and Poverty Reduction", FinancialMinistry = "Social Development and Poverty Reduction", IsActive = true },
+ new() { ClientCode = "034", Description = "Transportation and Transit", FinancialMinistry = "Transportation and Transit", IsActive = true },
+ new() { ClientCode = "039", Description = "Children and Family Development", FinancialMinistry = "Children and Family Development", IsActive = true },
+ new() { ClientCode = "046", Description = "Liquor Distribution Branch", FinancialMinistry = "", IsActive = true },
+ new() { ClientCode = "048", Description = "Environment and Parks", FinancialMinistry = "Environment and Parks", IsActive = true },
+ new() { ClientCode = "050", Description = "Forests and Lands", FinancialMinistry = "Forests", IsActive = true },
+ new() { ClientCode = "055", Description = "British Columbia Utilities Commission", FinancialMinistry = "", IsActive = true },
+ new() { ClientCode = "057", Description = "Energy and Climate Solutions", FinancialMinistry = "Energy and Climate Solutions", IsActive = true },
+ new() { ClientCode = "058", Description = "Natural Gas Development", FinancialMinistry = "Energy and Climate Solutions", IsActive = true },
+ new() { ClientCode = "060", Description = "Municipal Affairs", FinancialMinistry = "Housing and Municipal Affairs", IsActive = true },
+ new() { ClientCode = "062", Description = "Education and Child Care", FinancialMinistry = "Education and Child Care", IsActive = true },
+ new() { ClientCode = "063", Description = "Management of Public Funds and Debt", FinancialMinistry = "Finance", IsActive = true },
+ new() { ClientCode = "067", Description = "Product Sales and Services BC", FinancialMinistry = "Citizens Services", IsActive = true },
+ new() { ClientCode = "068", Description = "Public Sector Employers Council", FinancialMinistry = "Finance", IsActive = true },
+ new() { ClientCode = "074", Description = "Government Agents", FinancialMinistry = "Citizens Services", IsActive = true },
+ new() { ClientCode = "079", Description = "Forest Practices Board", FinancialMinistry = "Forest Practices Board ", IsActive = true },
+ new() { ClientCode = "080", Description = "Env Appeal Board and Forest Appeals Commission", FinancialMinistry = "Attorney General", IsActive = true },
+ new() { ClientCode = "085", Description = "Tax Transfers", FinancialMinistry = "Finance", IsActive = true },
+ new() { ClientCode = "087", Description = "Contingencies", FinancialMinistry = "Finance", IsActive = true },
+ new() { ClientCode = "089", Description = "Provincial Treasury", FinancialMinistry = "Finance", IsActive = true },
+ new() { ClientCode = "090", Description = "Pymt Diversion Legal Encumbrance", FinancialMinistry = "Finance", IsActive = true },
+ new() { ClientCode = "099", Description = "BCGOV", FinancialMinistry = "", IsActive = true },
+ new() { ClientCode = "100", Description = "Public Service Agency", FinancialMinistry = "BC Public Service Agency", IsActive = true },
+ new() { ClientCode = "105", Description = "Attorney General", FinancialMinistry = "Attorney General", IsActive = true },
+ new() { ClientCode = "106", Description = "Merit Commissioner", FinancialMinistry = "Office of the Merit Commissioner", IsActive = true },
+ new() { ClientCode = "109", Description = "Representative for Children and Youth", FinancialMinistry = "Representative for Children and Youth", IsActive = true },
+ new() { ClientCode = "112", Description = "Citizens' Services", FinancialMinistry = "Citizens Services", IsActive = true },
+ new() { ClientCode = "113", Description = "Human Rights Commissioner", FinancialMinistry = "Office of the BC Human Rights Commission", IsActive = true },
+ new() { ClientCode = "114", Description = "Auditor General for Local Government", FinancialMinistry = "Housing and Municipal Affairs", IsActive = true },
+ new() { ClientCode = "115", Description = "Environmental Assessment Office", FinancialMinistry = "Environment and Parks", IsActive = true },
+ new() { ClientCode = "120", Description = "Indigenous Relations and Reconciliation", FinancialMinistry = "Indigenous Relations and Reconciliation", IsActive = true },
+ new() { ClientCode = "125", Description = "Jobs and Economic Growth", FinancialMinistry = "Jobs and Economic Growth", IsActive = true },
+ new() { ClientCode = "126", Description = "Tourism, Arts, Culture and Sport", FinancialMinistry = "Tourism Arts Culture and Sport", IsActive = true },
+ new() { ClientCode = "127", Description = "Labour", FinancialMinistry = "Labour", IsActive = true },
+ new() { ClientCode = "128", Description = "Forests", FinancialMinistry = "Forests", IsActive = true },
+ new() { ClientCode = "130", Description = "Agriculture and Food", FinancialMinistry = "Agriculture and Food", IsActive = true },
+ new() { ClientCode = "131", Description = "Housing", FinancialMinistry = "Housing and Municipal Affairs", IsActive = true },
+ new() { ClientCode = "133", Description = "Water, Land and Resource Stewardship", FinancialMinistry = "Water Land and Resource Stewardship", IsActive = true },
+ new() { ClientCode = "134", Description = "Emergency Management and Climate Readiness", FinancialMinistry = "Emergency Management and Climate Readiness", IsActive = true },
+ new() { ClientCode = "135", Description = "Mining and Critical Minerals", FinancialMinistry = "Mining and Critical Minerals", IsActive = true },
+ new() { ClientCode = "136", Description = "Infrastructure", FinancialMinistry = "Infrastructure", IsActive = true },
+ // Special accounts
+ new() { ClientCode = "300", Description = "BC Arts and Culture Endowment special account", FinancialMinistry = "Tourism Arts Culture and Sport", IsActive = true },
+ new() { ClientCode = "301", Description = "Park Enhancement Fund special account", FinancialMinistry = "Environment and Parks", IsActive = true },
+ new() { ClientCode = "302", Description = "Housing Endowment Fund special account", FinancialMinistry = "Housing and Municipal Affairs", IsActive = true },
+ new() { ClientCode = "303", Description = "Long Term Disability Fund special account", FinancialMinistry = "BC Public Service Agency", IsActive = true },
+ new() { ClientCode = "304", Description = "Housing Priority Initiatives special account", FinancialMinistry = "Finance", IsActive = true },
+ new() { ClientCode = "305", Description = "Provincial Home Acquisition Wind Up special account", FinancialMinistry = "Finance", IsActive = true },
+ new() { ClientCode = "307", Description = "Civil Forfeiture Account", FinancialMinistry = "Solicitor General", IsActive = true },
+ new() { ClientCode = "310", Description = "Production Insurance Account", FinancialMinistry = "Agriculture and Food", IsActive = true },
+ new() { ClientCode = "311", Description = "British Columbia Training and Education Savings Program", FinancialMinistry = "Education and Child Care", IsActive = true },
+ new() { ClientCode = "315", Description = "Innovative Clean Energy Fund special account", FinancialMinistry = "Energy and Climate Solutions", IsActive = true },
+ new() { ClientCode = "320", Description = "First Nations Clean Energy Business Fund special account", FinancialMinistry = "Indigenous Relations and Reconciliation", IsActive = true },
+ new() { ClientCode = "321", Description = "First Nations Equity Financing special account", FinancialMinistry = "", IsActive = true },
+ new() { ClientCode = "324", Description = "British Columbia Strategic Investments special account", FinancialMinistry = "Jobs and Economic Growth", IsActive = true },
+ // Consolidation accounts
+ new() { ClientCode = "400", Description = "Consolidation", FinancialMinistry = "", IsActive = true },
+ new() { ClientCode = "401", Description = "BC Prosperity Fund", FinancialMinistry = "", IsActive = true },
+ new() { ClientCode = "700", Description = "Finance-TBS Budget", FinancialMinistry = "Finance", IsActive = true },
+ // Other accounts with alpha-numeric codes
+ new() { ClientCode = "0AK", Description = "Public Guardian and Trustee Operating Account", FinancialMinistry = "Attorney General", IsActive = true },
+ new() { ClientCode = "0AT", Description = "BC Timber Sales Account", FinancialMinistry = "Forests", IsActive = true },
+ new() { ClientCode = "0BH", Description = "University Endowment Lands Administration Account", FinancialMinistry = "Housing and Municipal Affairs", IsActive = true },
+ new() { ClientCode = "0BM", Description = "Crown Land Small Business and Revenue", FinancialMinistry = "Finance", IsActive = true },
+ new() { ClientCode = "0BR", Description = "Corrections Work Program Account", FinancialMinistry = "Solicitor General", IsActive = true },
+ new() { ClientCode = "0ET", Description = "Teachers Act Special Account", FinancialMinistry = "Education and Child Care", IsActive = true },
+ new() { ClientCode = "0F3", Description = "Physical Fitness and Amateur Sports Fund", FinancialMinistry = "Tourism Arts Culture and Sport", IsActive = true },
+ new() { ClientCode = "0F9", Description = "First Citizens Fund", FinancialMinistry = "Indigenous Relations and Reconciliation", IsActive = true },
+ new() { ClientCode = "0FC", Description = "Criminal Asset Management Fund", FinancialMinistry = "Solicitor General", IsActive = true },
+ new() { ClientCode = "0FE", Description = "Forest Stand Management Fund", FinancialMinistry = "Forests", IsActive = true },
+ new() { ClientCode = "0FK", Description = "Insurance and Risk Management Account", FinancialMinistry = "Finance", IsActive = true },
+ new() { ClientCode = "0FS", Description = "Victim Surcharge Special Account", FinancialMinistry = "Solicitor General", IsActive = true },
+ new() { ClientCode = "0HL", Description = "Health Special Account", FinancialMinistry = "Health", IsActive = true },
+ new() { ClientCode = "0KR", Description = "Crown Land special account", FinancialMinistry = "Forests", IsActive = true },
+ new() { ClientCode = "0MH", Description = "Medical and Health Care Services", FinancialMinistry = "", IsActive = true },
+ new() { ClientCode = "0NF", Description = "Northern Development Fund", FinancialMinistry = "Jobs and Economic Growth", IsActive = true },
+ new() { ClientCode = "0SE", Description = "Sustainable Environment Fund", FinancialMinistry = "Environment and Parks", IsActive = true },
+ // Trust accounts
+ new() { ClientCode = "0T6", Description = "Trust-Public Safety and Solicitor General", FinancialMinistry = "Solicitor General", IsActive = true },
+ new() { ClientCode = "0TA", Description = "Trust-Agriculture and Food", FinancialMinistry = "Agriculture and Food", IsActive = true },
+ new() { ClientCode = "0TB", Description = "Trust-Attorney General", FinancialMinistry = "Attorney General", IsActive = true },
+ new() { ClientCode = "0TD", Description = "Trust-Education and Child Care", FinancialMinistry = "Education and Child Care", IsActive = true },
+ new() { ClientCode = "0TE", Description = "Energy and Climate Solutions", FinancialMinistry = "Energy and Climate Solutions", IsActive = true },
+ new() { ClientCode = "0TF", Description = "Environment and Parks", FinancialMinistry = "Environment and Parks", IsActive = true },
+ new() { ClientCode = "0TG", Description = "Trust-Finance", FinancialMinistry = "Finance", IsActive = true },
+ new() { ClientCode = "0TH", Description = "Trust-Forests", FinancialMinistry = "Forests", IsActive = true },
+ new() { ClientCode = "0TJ", Description = "Trust-Health", FinancialMinistry = "Health", IsActive = true },
+ new() { ClientCode = "0TK", Description = "Trust-Children and Family Dev", FinancialMinistry = "Children and Family Development", IsActive = true },
+ new() { ClientCode = "0TL", Description = "Trust-Small Business, Technology and Economic Development", FinancialMinistry = "Finance", IsActive = true },
+ new() { ClientCode = "0TM", Description = "Trust-Crown Lands", FinancialMinistry = "Forests", IsActive = true },
+ new() { ClientCode = "0TN", Description = "Trust-Crown Lands Minor Trusts", FinancialMinistry = "Forests", IsActive = true },
+ new() { ClientCode = "0TQ", Description = "Trust-Municipal Affairs", FinancialMinistry = "Housing and Municipal Affairs", IsActive = true },
+ new() { ClientCode = "0TR", Description = "Trust-Social Dev and Poverty Reduction", FinancialMinistry = "Social Development and Poverty Reduction", IsActive = true },
+ new() { ClientCode = "0TV", Description = "Trust-Natural Gas Development", FinancialMinistry = "Energy and Climate Solutions", IsActive = true },
+ new() { ClientCode = "0TW", Description = "Trust-Labour", FinancialMinistry = "Labour", IsActive = true },
+ new() { ClientCode = "0TX", Description = "Trust-Jobs and Economic Growth", FinancialMinistry = "Jobs and Economic Growth", IsActive = true },
+ new() { ClientCode = "0TZ", Description = "Trust-Post-Secondary Education and Future Skills", FinancialMinistry = "Post Secondary Education and Future Skills", IsActive = true },
+ new() { ClientCode = "0VB", Description = "Royal British Columbia Museum", FinancialMinistry = "", IsActive = true },
+ new() { ClientCode = "0VC", Description = "Vital Statistics", FinancialMinistry = "Health", IsActive = true }
+ };
+#pragma warning restore S1192 // Use 'new(...)'
+ foreach (var clientCode in clientCodes)
+ {
+ var existing = await CasClientCodeRepository.FirstOrDefaultAsync(s => s.ClientCode == clientCode.ClientCode);
+ if (existing == null)
+ {
+ await CasClientCodeRepository.InsertAsync(clientCode);
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.EntityFrameworkCore/EntityFrameworkCore/GrantManagerDbContext.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.EntityFrameworkCore/EntityFrameworkCore/GrantManagerDbContext.cs
index e0f7fcfa9..498c00a12 100644
--- a/applications/Unity.GrantManager/src/Unity.GrantManager.EntityFrameworkCore/EntityFrameworkCore/GrantManagerDbContext.cs
+++ b/applications/Unity.GrantManager/src/Unity.GrantManager.EntityFrameworkCore/EntityFrameworkCore/GrantManagerDbContext.cs
@@ -34,6 +34,7 @@ public class GrantManagerDbContext :
public DbSet ApplicantTenantMaps { get; set; }
public DbSet DynamicUrls { get; set; }
+ public DbSet CasClientCodes { get; set; }
public DbSet Sectors { get; set; }
public DbSet SubSectors { get; set; }
public DbSet EconomicRegion { get; set; }
@@ -94,6 +95,13 @@ protected override void OnModelCreating(ModelBuilder modelBuilder)
modelBuilder.AddQuartz(builder => builder.UsePostgreSql("qrtz_", null));
/* Configure your own tables/entities inside here */
+ modelBuilder.Entity(b =>
+ {
+ b.ToTable(GrantManagerConsts.DbTablePrefix + "CasClientCodes",
+ GrantManagerConsts.DbSchema);
+ b.ConfigureByConvention();
+ });
+
modelBuilder.Entity(b =>
{
b.ToTable(GrantManagerConsts.DbTablePrefix + "DynamicUrls",
diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.EntityFrameworkCore/EntityFrameworkCore/GrantTenantDbContext.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.EntityFrameworkCore/EntityFrameworkCore/GrantTenantDbContext.cs
index c463a6a4d..3e042440f 100644
--- a/applications/Unity.GrantManager/src/Unity.GrantManager.EntityFrameworkCore/EntityFrameworkCore/GrantTenantDbContext.cs
+++ b/applications/Unity.GrantManager/src/Unity.GrantManager.EntityFrameworkCore/EntityFrameworkCore/GrantTenantDbContext.cs
@@ -105,12 +105,6 @@ protected override void OnModelCreating(ModelBuilder modelBuilder)
.HasForeignKey(x => x.ParentFormId)
.IsRequired(false)
.OnDelete(DeleteBehavior.NoAction);
-
- b.HasOne()
- .WithMany()
- .HasForeignKey(x => x.ParentFormVersionId)
- .IsRequired(false)
- .OnDelete(DeleteBehavior.NoAction);
});
modelBuilder.Entity(b =>
diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.EntityFrameworkCore/Migrations/HostMigrations/20260128195715_CasClientCodes.Designer.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.EntityFrameworkCore/Migrations/HostMigrations/20260128195715_CasClientCodes.Designer.cs
new file mode 100644
index 000000000..0057f0421
--- /dev/null
+++ b/applications/Unity.GrantManager/src/Unity.GrantManager.EntityFrameworkCore/Migrations/HostMigrations/20260128195715_CasClientCodes.Designer.cs
@@ -0,0 +1,2567 @@
+//
+using System;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Infrastructure;
+using Microsoft.EntityFrameworkCore.Migrations;
+using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
+using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
+using Unity.GrantManager.EntityFrameworkCore;
+using Volo.Abp.EntityFrameworkCore;
+
+#nullable disable
+
+namespace Unity.GrantManager.Migrations.HostMigrations
+{
+ [DbContext(typeof(GrantManagerDbContext))]
+ [Migration("20260128195715_CasClientCodes")]
+ partial class CasClientCodes
+ {
+ ///
+ protected override void BuildTargetModel(ModelBuilder modelBuilder)
+ {
+#pragma warning disable 612, 618
+ modelBuilder
+ .HasAnnotation("_Abp_DatabaseProvider", EfCoreDatabaseProvider.PostgreSql)
+ .HasAnnotation("ProductVersion", "9.0.5")
+ .HasAnnotation("Relational:MaxIdentifierLength", 63);
+
+ NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
+
+ modelBuilder.Entity("AppAny.Quartz.EntityFrameworkCore.Migrations.QuartzBlobTrigger", b =>
+ {
+ b.Property("SchedulerName")
+ .HasColumnType("text")
+ .HasColumnName("sched_name");
+
+ b.Property("TriggerName")
+ .HasColumnType("text")
+ .HasColumnName("trigger_name");
+
+ b.Property("TriggerGroup")
+ .HasColumnType("text")
+ .HasColumnName("trigger_group");
+
+ b.Property("BlobData")
+ .HasColumnType("bytea")
+ .HasColumnName("blob_data");
+
+ b.HasKey("SchedulerName", "TriggerName", "TriggerGroup");
+
+ b.ToTable("qrtz_blob_triggers", (string)null);
+ });
+
+ modelBuilder.Entity("AppAny.Quartz.EntityFrameworkCore.Migrations.QuartzCalendar", b =>
+ {
+ b.Property("SchedulerName")
+ .HasColumnType("text")
+ .HasColumnName("sched_name");
+
+ b.Property("CalendarName")
+ .HasColumnType("text")
+ .HasColumnName("calendar_name");
+
+ b.Property("Calendar")
+ .IsRequired()
+ .HasColumnType("bytea")
+ .HasColumnName("calendar");
+
+ b.HasKey("SchedulerName", "CalendarName");
+
+ b.ToTable("qrtz_calendars", (string)null);
+ });
+
+ modelBuilder.Entity("AppAny.Quartz.EntityFrameworkCore.Migrations.QuartzCronTrigger", b =>
+ {
+ b.Property("SchedulerName")
+ .HasColumnType("text")
+ .HasColumnName("sched_name");
+
+ b.Property("TriggerName")
+ .HasColumnType("text")
+ .HasColumnName("trigger_name");
+
+ b.Property("TriggerGroup")
+ .HasColumnType("text")
+ .HasColumnName("trigger_group");
+
+ b.Property("CronExpression")
+ .IsRequired()
+ .HasColumnType("text")
+ .HasColumnName("cron_expression");
+
+ b.Property("TimeZoneId")
+ .HasColumnType("text")
+ .HasColumnName("time_zone_id");
+
+ b.HasKey("SchedulerName", "TriggerName", "TriggerGroup");
+
+ b.ToTable("qrtz_cron_triggers", (string)null);
+ });
+
+ modelBuilder.Entity("AppAny.Quartz.EntityFrameworkCore.Migrations.QuartzFiredTrigger", b =>
+ {
+ b.Property("SchedulerName")
+ .HasColumnType("text")
+ .HasColumnName("sched_name");
+
+ b.Property("EntryId")
+ .HasColumnType("text")
+ .HasColumnName("entry_id");
+
+ b.Property("FiredTime")
+ .HasColumnType("bigint")
+ .HasColumnName("fired_time");
+
+ b.Property("InstanceName")
+ .IsRequired()
+ .HasColumnType("text")
+ .HasColumnName("instance_name");
+
+ b.Property("IsNonConcurrent")
+ .HasColumnType("bool")
+ .HasColumnName("is_nonconcurrent");
+
+ b.Property("JobGroup")
+ .HasColumnType("text")
+ .HasColumnName("job_group");
+
+ b.Property("JobName")
+ .HasColumnType("text")
+ .HasColumnName("job_name");
+
+ b.Property("Priority")
+ .HasColumnType("integer")
+ .HasColumnName("priority");
+
+ b.Property("RequestsRecovery")
+ .HasColumnType("bool")
+ .HasColumnName("requests_recovery");
+
+ b.Property("ScheduledTime")
+ .HasColumnType("bigint")
+ .HasColumnName("sched_time");
+
+ b.Property("State")
+ .IsRequired()
+ .HasColumnType("text")
+ .HasColumnName("state");
+
+ b.Property("TriggerGroup")
+ .IsRequired()
+ .HasColumnType("text")
+ .HasColumnName("trigger_group");
+
+ b.Property("TriggerName")
+ .IsRequired()
+ .HasColumnType("text")
+ .HasColumnName("trigger_name");
+
+ b.HasKey("SchedulerName", "EntryId");
+
+ b.HasIndex("InstanceName")
+ .HasDatabaseName("idx_qrtz_ft_trig_inst_name");
+
+ b.HasIndex("JobGroup")
+ .HasDatabaseName("idx_qrtz_ft_job_group");
+
+ b.HasIndex("JobName")
+ .HasDatabaseName("idx_qrtz_ft_job_name");
+
+ b.HasIndex("RequestsRecovery")
+ .HasDatabaseName("idx_qrtz_ft_job_req_recovery");
+
+ b.HasIndex("TriggerGroup")
+ .HasDatabaseName("idx_qrtz_ft_trig_group");
+
+ b.HasIndex("TriggerName")
+ .HasDatabaseName("idx_qrtz_ft_trig_name");
+
+ b.HasIndex("SchedulerName", "TriggerName", "TriggerGroup")
+ .HasDatabaseName("idx_qrtz_ft_trig_nm_gp");
+
+ b.ToTable("qrtz_fired_triggers", (string)null);
+ });
+
+ modelBuilder.Entity("AppAny.Quartz.EntityFrameworkCore.Migrations.QuartzJobDetail", b =>
+ {
+ b.Property("SchedulerName")
+ .HasColumnType("text")
+ .HasColumnName("sched_name");
+
+ b.Property("JobName")
+ .HasColumnType("text")
+ .HasColumnName("job_name");
+
+ b.Property("JobGroup")
+ .HasColumnType("text")
+ .HasColumnName("job_group");
+
+ b.Property("Description")
+ .HasColumnType("text")
+ .HasColumnName("description");
+
+ b.Property("IsDurable")
+ .HasColumnType("bool")
+ .HasColumnName("is_durable");
+
+ b.Property("IsNonConcurrent")
+ .HasColumnType("bool")
+ .HasColumnName("is_nonconcurrent");
+
+ b.Property("IsUpdateData")
+ .HasColumnType("bool")
+ .HasColumnName("is_update_data");
+
+ b.Property("JobClassName")
+ .IsRequired()
+ .HasColumnType("text")
+ .HasColumnName("job_class_name");
+
+ b.Property("JobData")
+ .HasColumnType("bytea")
+ .HasColumnName("job_data");
+
+ b.Property("RequestsRecovery")
+ .HasColumnType("bool")
+ .HasColumnName("requests_recovery");
+
+ b.HasKey("SchedulerName", "JobName", "JobGroup");
+
+ b.HasIndex("RequestsRecovery")
+ .HasDatabaseName("idx_qrtz_j_req_recovery");
+
+ b.ToTable("qrtz_job_details", (string)null);
+ });
+
+ modelBuilder.Entity("AppAny.Quartz.EntityFrameworkCore.Migrations.QuartzLock", b =>
+ {
+ b.Property("SchedulerName")
+ .HasColumnType("text")
+ .HasColumnName("sched_name");
+
+ b.Property("LockName")
+ .HasColumnType("text")
+ .HasColumnName("lock_name");
+
+ b.HasKey("SchedulerName", "LockName");
+
+ b.ToTable("qrtz_locks", (string)null);
+ });
+
+ modelBuilder.Entity("AppAny.Quartz.EntityFrameworkCore.Migrations.QuartzPausedTriggerGroup", b =>
+ {
+ b.Property("SchedulerName")
+ .HasColumnType("text")
+ .HasColumnName("sched_name");
+
+ b.Property("TriggerGroup")
+ .HasColumnType("text")
+ .HasColumnName("trigger_group");
+
+ b.HasKey("SchedulerName", "TriggerGroup");
+
+ b.ToTable("qrtz_paused_trigger_grps", (string)null);
+ });
+
+ modelBuilder.Entity("AppAny.Quartz.EntityFrameworkCore.Migrations.QuartzSchedulerState", b =>
+ {
+ b.Property("SchedulerName")
+ .HasColumnType("text")
+ .HasColumnName("sched_name");
+
+ b.Property("InstanceName")
+ .HasColumnType("text")
+ .HasColumnName("instance_name");
+
+ b.Property("CheckInInterval")
+ .HasColumnType("bigint")
+ .HasColumnName("checkin_interval");
+
+ b.Property("LastCheckInTime")
+ .HasColumnType("bigint")
+ .HasColumnName("last_checkin_time");
+
+ b.HasKey("SchedulerName", "InstanceName");
+
+ b.ToTable("qrtz_scheduler_state", (string)null);
+ });
+
+ modelBuilder.Entity("AppAny.Quartz.EntityFrameworkCore.Migrations.QuartzSimplePropertyTrigger", b =>
+ {
+ b.Property("SchedulerName")
+ .HasColumnType("text")
+ .HasColumnName("sched_name");
+
+ b.Property("TriggerName")
+ .HasColumnType("text")
+ .HasColumnName("trigger_name");
+
+ b.Property("TriggerGroup")
+ .HasColumnType("text")
+ .HasColumnName("trigger_group");
+
+ b.Property("BooleanProperty1")
+ .HasColumnType("bool")
+ .HasColumnName("bool_prop_1");
+
+ b.Property("BooleanProperty2")
+ .HasColumnType("bool")
+ .HasColumnName("bool_prop_2");
+
+ b.Property("DecimalProperty1")
+ .HasColumnType("numeric")
+ .HasColumnName("dec_prop_1");
+
+ b.Property("DecimalProperty2")
+ .HasColumnType("numeric")
+ .HasColumnName("dec_prop_2");
+
+ b.Property("IntegerProperty1")
+ .HasColumnType("integer")
+ .HasColumnName("int_prop_1");
+
+ b.Property("IntegerProperty2")
+ .HasColumnType("integer")
+ .HasColumnName("int_prop_2");
+
+ b.Property("LongProperty1")
+ .HasColumnType("bigint")
+ .HasColumnName("long_prop_1");
+
+ b.Property("LongProperty2")
+ .HasColumnType("bigint")
+ .HasColumnName("long_prop_2");
+
+ b.Property("StringProperty1")
+ .HasColumnType("text")
+ .HasColumnName("str_prop_1");
+
+ b.Property("StringProperty2")
+ .HasColumnType("text")
+ .HasColumnName("str_prop_2");
+
+ b.Property("StringProperty3")
+ .HasColumnType("text")
+ .HasColumnName("str_prop_3");
+
+ b.Property("TimeZoneId")
+ .HasColumnType("text")
+ .HasColumnName("time_zone_id");
+
+ b.HasKey("SchedulerName", "TriggerName", "TriggerGroup");
+
+ b.ToTable("qrtz_simprop_triggers", (string)null);
+ });
+
+ modelBuilder.Entity("AppAny.Quartz.EntityFrameworkCore.Migrations.QuartzSimpleTrigger", b =>
+ {
+ b.Property("SchedulerName")
+ .HasColumnType("text")
+ .HasColumnName("sched_name");
+
+ b.Property("TriggerName")
+ .HasColumnType("text")
+ .HasColumnName("trigger_name");
+
+ b.Property("TriggerGroup")
+ .HasColumnType("text")
+ .HasColumnName("trigger_group");
+
+ b.Property("RepeatCount")
+ .HasColumnType("bigint")
+ .HasColumnName("repeat_count");
+
+ b.Property("RepeatInterval")
+ .HasColumnType("bigint")
+ .HasColumnName("repeat_interval");
+
+ b.Property("TimesTriggered")
+ .HasColumnType("bigint")
+ .HasColumnName("times_triggered");
+
+ b.HasKey("SchedulerName", "TriggerName", "TriggerGroup");
+
+ b.ToTable("qrtz_simple_triggers", (string)null);
+ });
+
+ modelBuilder.Entity("AppAny.Quartz.EntityFrameworkCore.Migrations.QuartzTrigger", b =>
+ {
+ b.Property("SchedulerName")
+ .HasColumnType("text")
+ .HasColumnName("sched_name");
+
+ b.Property("TriggerName")
+ .HasColumnType("text")
+ .HasColumnName("trigger_name");
+
+ b.Property("TriggerGroup")
+ .HasColumnType("text")
+ .HasColumnName("trigger_group");
+
+ b.Property("CalendarName")
+ .HasColumnType("text")
+ .HasColumnName("calendar_name");
+
+ b.Property("Description")
+ .HasColumnType("text")
+ .HasColumnName("description");
+
+ b.Property("EndTime")
+ .HasColumnType("bigint")
+ .HasColumnName("end_time");
+
+ b.Property("JobData")
+ .HasColumnType("bytea")
+ .HasColumnName("job_data");
+
+ b.Property("JobGroup")
+ .IsRequired()
+ .HasColumnType("text")
+ .HasColumnName("job_group");
+
+ b.Property("JobName")
+ .IsRequired()
+ .HasColumnType("text")
+ .HasColumnName("job_name");
+
+ b.Property("MisfireInstruction")
+ .HasColumnType("smallint")
+ .HasColumnName("misfire_instr");
+
+ b.Property("NextFireTime")
+ .HasColumnType("bigint")
+ .HasColumnName("next_fire_time");
+
+ b.Property("PreviousFireTime")
+ .HasColumnType("bigint")
+ .HasColumnName("prev_fire_time");
+
+ b.Property("Priority")
+ .HasColumnType("integer")
+ .HasColumnName("priority");
+
+ b.Property("StartTime")
+ .HasColumnType("bigint")
+ .HasColumnName("start_time");
+
+ b.Property("TriggerState")
+ .IsRequired()
+ .HasColumnType("text")
+ .HasColumnName("trigger_state");
+
+ b.Property("TriggerType")
+ .IsRequired()
+ .HasColumnType("text")
+ .HasColumnName("trigger_type");
+
+ b.HasKey("SchedulerName", "TriggerName", "TriggerGroup");
+
+ b.HasIndex("NextFireTime")
+ .HasDatabaseName("idx_qrtz_t_next_fire_time");
+
+ b.HasIndex("TriggerState")
+ .HasDatabaseName("idx_qrtz_t_state");
+
+ b.HasIndex("NextFireTime", "TriggerState")
+ .HasDatabaseName("idx_qrtz_t_nft_st");
+
+ b.HasIndex("SchedulerName", "JobName", "JobGroup");
+
+ b.ToTable("qrtz_triggers", (string)null);
+ });
+
+ modelBuilder.Entity("Unity.GrantManager.Integrations.DynamicUrl", b =>
+ {
+ b.Property("Id")
+ .HasColumnType("uuid");
+
+ b.Property("ConcurrencyStamp")
+ .IsConcurrencyToken()
+ .IsRequired()
+ .HasMaxLength(40)
+ .HasColumnType("character varying(40)")
+ .HasColumnName("ConcurrencyStamp");
+
+ b.Property("CreationTime")
+ .HasColumnType("timestamp without time zone")
+ .HasColumnName("CreationTime");
+
+ b.Property("CreatorId")
+ .HasColumnType("uuid")
+ .HasColumnName("CreatorId");
+
+ b.Property("DeleterId")
+ .HasColumnType("uuid")
+ .HasColumnName("DeleterId");
+
+ b.Property("DeletionTime")
+ .HasColumnType("timestamp without time zone")
+ .HasColumnName("DeletionTime");
+
+ b.Property("Description")
+ .IsRequired()
+ .HasMaxLength(256)
+ .HasColumnType("character varying(256)");
+
+ b.Property("IsDeleted")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("boolean")
+ .HasDefaultValue(false)
+ .HasColumnName("IsDeleted");
+
+ b.Property("KeyName")
+ .IsRequired()
+ .HasMaxLength(128)
+ .HasColumnType("character varying(128)");
+
+ b.Property("LastModificationTime")
+ .HasColumnType("timestamp without time zone")
+ .HasColumnName("LastModificationTime");
+
+ b.Property("LastModifierId")
+ .HasColumnType("uuid")
+ .HasColumnName("LastModifierId");
+
+ b.Property("TenantId")
+ .HasColumnType("uuid")
+ .HasColumnName("TenantId");
+
+ b.Property("Url")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.HasKey("Id");
+
+ b.ToTable("DynamicUrls", (string)null);
+ });
+
+ modelBuilder.Entity("Unity.GrantManager.Locality.Community", b =>
+ {
+ b.Property("Id")
+ .HasColumnType("uuid");
+
+ b.Property("ConcurrencyStamp")
+ .IsConcurrencyToken()
+ .IsRequired()
+ .HasMaxLength(40)
+ .HasColumnType("character varying(40)")
+ .HasColumnName("ConcurrencyStamp");
+
+ b.Property("CreationTime")
+ .HasColumnType("timestamp without time zone")
+ .HasColumnName("CreationTime");
+
+ b.Property("CreatorId")
+ .HasColumnType("uuid")
+ .HasColumnName("CreatorId");
+
+ b.Property("ExtraProperties")
+ .IsRequired()
+ .HasColumnType("text")
+ .HasColumnName("ExtraProperties");
+
+ b.Property("LastModificationTime")
+ .HasColumnType("timestamp without time zone")
+ .HasColumnName("LastModificationTime");
+
+ b.Property("LastModifierId")
+ .HasColumnType("uuid")
+ .HasColumnName("LastModifierId");
+
+ b.Property("Name")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.Property("RegionalDistrictCode")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.Property("Type")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.HasKey("Id");
+
+ b.ToTable("Communities", (string)null);
+ });
+
+ modelBuilder.Entity("Unity.GrantManager.Locality.EconomicRegion", b =>
+ {
+ b.Property("Id")
+ .HasColumnType("uuid");
+
+ b.Property("ConcurrencyStamp")
+ .IsConcurrencyToken()
+ .IsRequired()
+ .HasMaxLength(40)
+ .HasColumnType("character varying(40)")
+ .HasColumnName("ConcurrencyStamp");
+
+ b.Property("CreationTime")
+ .HasColumnType("timestamp without time zone")
+ .HasColumnName("CreationTime");
+
+ b.Property("CreatorId")
+ .HasColumnType("uuid")
+ .HasColumnName("CreatorId");
+
+ b.Property("EconomicRegionCode")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.Property("EconomicRegionName")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.Property("ExtraProperties")
+ .IsRequired()
+ .HasColumnType("text")
+ .HasColumnName("ExtraProperties");
+
+ b.Property("LastModificationTime")
+ .HasColumnType("timestamp without time zone")
+ .HasColumnName("LastModificationTime");
+
+ b.Property("LastModifierId")
+ .HasColumnType("uuid")
+ .HasColumnName("LastModifierId");
+
+ b.HasKey("Id");
+
+ b.ToTable("EconomicRegions", (string)null);
+ });
+
+ modelBuilder.Entity("Unity.GrantManager.Locality.ElectoralDistrict", b =>
+ {
+ b.Property("Id")
+ .HasColumnType("uuid");
+
+ b.Property("ConcurrencyStamp")
+ .IsConcurrencyToken()
+ .IsRequired()
+ .HasMaxLength(40)
+ .HasColumnType("character varying(40)")
+ .HasColumnName("ConcurrencyStamp");
+
+ b.Property("CreationTime")
+ .HasColumnType("timestamp without time zone")
+ .HasColumnName("CreationTime");
+
+ b.Property("CreatorId")
+ .HasColumnType("uuid")
+ .HasColumnName("CreatorId");
+
+ b.Property("ElectoralDistrictCode")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.Property("ElectoralDistrictName")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.Property("ExtraProperties")
+ .IsRequired()
+ .HasColumnType("text")
+ .HasColumnName("ExtraProperties");
+
+ b.Property("LastModificationTime")
+ .HasColumnType("timestamp without time zone")
+ .HasColumnName("LastModificationTime");
+
+ b.Property("LastModifierId")
+ .HasColumnType("uuid")
+ .HasColumnName("LastModifierId");
+
+ b.HasKey("Id");
+
+ b.ToTable("ElectoralDistricts", (string)null);
+ });
+
+ modelBuilder.Entity("Unity.GrantManager.Locality.RegionalDistrict", b =>
+ {
+ b.Property("Id")
+ .HasColumnType("uuid");
+
+ b.Property("ConcurrencyStamp")
+ .IsConcurrencyToken()
+ .IsRequired()
+ .HasMaxLength(40)
+ .HasColumnType("character varying(40)")
+ .HasColumnName("ConcurrencyStamp");
+
+ b.Property("CreationTime")
+ .HasColumnType("timestamp without time zone")
+ .HasColumnName("CreationTime");
+
+ b.Property("CreatorId")
+ .HasColumnType("uuid")
+ .HasColumnName("CreatorId");
+
+ b.Property("EconomicRegionCode")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.Property("ExtraProperties")
+ .IsRequired()
+ .HasColumnType("text")
+ .HasColumnName("ExtraProperties");
+
+ b.Property("LastModificationTime")
+ .HasColumnType("timestamp without time zone")
+ .HasColumnName("LastModificationTime");
+
+ b.Property("LastModifierId")
+ .HasColumnType("uuid")
+ .HasColumnName("LastModifierId");
+
+ b.Property("RegionalDistrictCode")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.Property("RegionalDistrictName")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.HasKey("Id");
+
+ b.ToTable("RegionalDistricts", (string)null);
+ });
+
+ modelBuilder.Entity("Unity.GrantManager.Locality.Sector", b =>
+ {
+ b.Property("Id")
+ .HasColumnType("uuid");
+
+ b.Property("ConcurrencyStamp")
+ .IsConcurrencyToken()
+ .IsRequired()
+ .HasMaxLength(40)
+ .HasColumnType("character varying(40)")
+ .HasColumnName("ConcurrencyStamp");
+
+ b.Property("CreationTime")
+ .HasColumnType("timestamp without time zone")
+ .HasColumnName("CreationTime");
+
+ b.Property("CreatorId")
+ .HasColumnType("uuid")
+ .HasColumnName("CreatorId");
+
+ b.Property("ExtraProperties")
+ .IsRequired()
+ .HasColumnType("text")
+ .HasColumnName("ExtraProperties");
+
+ b.Property("LastModificationTime")
+ .HasColumnType("timestamp without time zone")
+ .HasColumnName("LastModificationTime");
+
+ b.Property("LastModifierId")
+ .HasColumnType("uuid")
+ .HasColumnName("LastModifierId");
+
+ b.Property("SectorCode")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.Property("SectorName")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.HasKey("Id");
+
+ b.ToTable("Sectors", (string)null);
+ });
+
+ modelBuilder.Entity("Unity.GrantManager.Locality.SubSector", b =>
+ {
+ b.Property("Id")
+ .HasColumnType("uuid");
+
+ b.Property("ConcurrencyStamp")
+ .IsConcurrencyToken()
+ .IsRequired()
+ .HasMaxLength(40)
+ .HasColumnType("character varying(40)")
+ .HasColumnName("ConcurrencyStamp");
+
+ b.Property("CreationTime")
+ .HasColumnType("timestamp without time zone")
+ .HasColumnName("CreationTime");
+
+ b.Property("CreatorId")
+ .HasColumnType("uuid")
+ .HasColumnName("CreatorId");
+
+ b.Property("ExtraProperties")
+ .IsRequired()
+ .HasColumnType("text")
+ .HasColumnName("ExtraProperties");
+
+ b.Property("LastModificationTime")
+ .HasColumnType("timestamp without time zone")
+ .HasColumnName("LastModificationTime");
+
+ b.Property