+ 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 d54ee06cf..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
@@ -160,7 +160,7 @@ public async Task OnGetAsync(string cacheKey)
bool missingFields = false;
List errorList = [];
- if (supplier == null || site == null || supplier.Number == null)
+ if (supplier == null || site == null || string.IsNullOrWhiteSpace(supplier.Number))
{
missingFields = true;
}
@@ -178,7 +178,7 @@ public async Task OnGetAsync(string cacheKey)
if (missingFields)
{
- errorList.Add("Some payment information is missing for this applicant, please make sure Supplier info is provided and default site is selected.");
+ errorList.Add("Some payment information is missing for this applicant. Please make sure supplier information is provided and default site is selected.");
}
if (application.StatusCode != GrantApplicationState.GRANT_APPROVED)
@@ -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)
{
- remainingAmount = approvedAmmount - totalFutureRequested;
+ // 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 - 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);
@@ -308,6 +325,12 @@ public async Task OnPostAsync()
throw new UserFriendlyException(string.Join(" ", validationErrors));
}
+ if (ApplicationPaymentRequestForm.Exists(payment => string.IsNullOrWhiteSpace(payment.SupplierNumber)))
+ {
+ throw new UserFriendlyException(
+ "Cannot submit payment request: Supplier number is missing for one or more applications.");
+ }
+
var payments = MapPaymentRequests();
await paymentRequestAppService.CreateAsync(payments);
@@ -454,6 +477,7 @@ private async Task PopulateParentChildValidationData()
{
child.MaximumAllowedAmount = maximumPaymentAmount;
child.IsPartOfParentChildGroup = true;
+ child.ParentApprovedAmount = approvedAmount;
}
// Apply validation data to parent if in submission
@@ -461,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/Index.js b/applications/Unity.GrantManager/modules/Unity.Payments/src/Unity.Payments.Web/Pages/PaymentRequests/Index.js
index 2fd4a5f98..5b7aff6ba 100644
--- a/applications/Unity.GrantManager/modules/Unity.Payments/src/Unity.Payments.Web/Pages/PaymentRequests/Index.js
+++ b/applications/Unity.GrantManager/modules/Unity.Payments/src/Unity.Payments.Web/Pages/PaymentRequests/Index.js
@@ -151,7 +151,10 @@ $(function () {
defaultVisibleColumns,
listColumns,
maxRowsPerPage: 10,
- defaultSortColumn: 13,
+ defaultSortColumn: {
+ name: 'requestedOn',
+ dir: 'desc'
+ },
dataEndpoint: unity.payments.paymentRequests.paymentRequest.getList,
data: {},
responseCallback,
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/src/Unity.Payments.Web/Unity.Payments.Web.csproj b/applications/Unity.GrantManager/modules/Unity.Payments/src/Unity.Payments.Web/Unity.Payments.Web.csproj
index dfa8df5b4..5b30a7e69 100644
--- a/applications/Unity.GrantManager/modules/Unity.Payments/src/Unity.Payments.Web/Unity.Payments.Web.csproj
+++ b/applications/Unity.GrantManager/modules/Unity.Payments/src/Unity.Payments.Web/Unity.Payments.Web.csproj
@@ -12,6 +12,7 @@
+
diff --git a/applications/Unity.GrantManager/modules/Unity.Payments/src/Unity.Payments.Web/Views/Shared/Components/PaymentInfo/Default.js b/applications/Unity.GrantManager/modules/Unity.Payments/src/Unity.Payments.Web/Views/Shared/Components/PaymentInfo/Default.js
index 3cceaffd6..56cd6f0cb 100644
--- a/applications/Unity.GrantManager/modules/Unity.Payments/src/Unity.Payments.Web/Views/Shared/Components/PaymentInfo/Default.js
+++ b/applications/Unity.GrantManager/modules/Unity.Payments/src/Unity.Payments.Web/Views/Shared/Components/PaymentInfo/Default.js
@@ -198,7 +198,10 @@
defaultVisibleColumns,
listColumns,
maxRowsPerPage: 10,
- defaultSortColumn: 3,
+ defaultSortColumn: {
+ name: 'requestedOn',
+ dir: 'desc'
+ },
dataEndpoint:
unity.payments.paymentRequests.paymentRequest
.getListByApplicationId,
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 162fa4f7d..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;
@@ -70,10 +68,10 @@ public async Task CreateAsync_CreatesPaymentRequest()
Description = "",
PayeeName= "",
SiteId= siteId,
- SupplierNumber = "",
+ SupplierNumber = "SUP-TEST",
}
];
- // Act
+ // Act
var insertedPaymentRequest = await _paymentRequestAppService
.CreateAsync(paymentRequests);
@@ -97,7 +95,7 @@ public async Task GetListAsync_ReturnsPaymentsList()
Amount = 100,
PayeeName = "Test",
ContractNumber = "0000000000",
- SupplierNumber = "",
+ SupplierNumber = "SUP-TEST",
SiteId = addedSupplier.Sites[0].Id,
CorrelationId = Guid.NewGuid(),
CorrelationProvider = "",
diff --git a/applications/Unity.GrantManager/modules/Unity.Payments/test/Unity.Payments.Application.Tests/Unity.Payments.Application.Tests.csproj b/applications/Unity.GrantManager/modules/Unity.Payments/test/Unity.Payments.Application.Tests/Unity.Payments.Application.Tests.csproj
index bae71a56e..71873b876 100644
--- a/applications/Unity.GrantManager/modules/Unity.Payments/test/Unity.Payments.Application.Tests/Unity.Payments.Application.Tests.csproj
+++ b/applications/Unity.GrantManager/modules/Unity.Payments/test/Unity.Payments.Application.Tests/Unity.Payments.Application.Tests.csproj
@@ -13,6 +13,7 @@
+
diff --git a/applications/Unity.GrantManager/modules/Unity.Payments/test/Unity.Payments.TestBase/Unity.Payments.TestBase.csproj b/applications/Unity.GrantManager/modules/Unity.Payments/test/Unity.Payments.TestBase/Unity.Payments.TestBase.csproj
index ddf7960b9..ff5f727d5 100644
--- a/applications/Unity.GrantManager/modules/Unity.Payments/test/Unity.Payments.TestBase/Unity.Payments.TestBase.csproj
+++ b/applications/Unity.GrantManager/modules/Unity.Payments/test/Unity.Payments.TestBase/Unity.Payments.TestBase.csproj
@@ -9,6 +9,7 @@
+
diff --git a/applications/Unity.GrantManager/modules/Unity.Reporting/src/Unity.Reporting.Application/Unity.Reporting.Application.csproj b/applications/Unity.GrantManager/modules/Unity.Reporting/src/Unity.Reporting.Application/Unity.Reporting.Application.csproj
index a1857d920..4d171a861 100644
--- a/applications/Unity.GrantManager/modules/Unity.Reporting/src/Unity.Reporting.Application/Unity.Reporting.Application.csproj
+++ b/applications/Unity.GrantManager/modules/Unity.Reporting/src/Unity.Reporting.Application/Unity.Reporting.Application.csproj
@@ -9,6 +9,7 @@
+
diff --git a/applications/Unity.GrantManager/modules/Unity.Reporting/test/Unity.Reporting.Application.Tests/Unity.Reporting.Application.Tests.csproj b/applications/Unity.GrantManager/modules/Unity.Reporting/test/Unity.Reporting.Application.Tests/Unity.Reporting.Application.Tests.csproj
index 7d02e2456..ca6484286 100644
--- a/applications/Unity.GrantManager/modules/Unity.Reporting/test/Unity.Reporting.Application.Tests/Unity.Reporting.Application.Tests.csproj
+++ b/applications/Unity.GrantManager/modules/Unity.Reporting/test/Unity.Reporting.Application.Tests/Unity.Reporting.Application.Tests.csproj
@@ -11,6 +11,7 @@
+
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/modules/Unity.TenantManagement/test/Unity.TenantManagement.Application.Tests/Unity.TenantManagement.Application.Tests.csproj b/applications/Unity.GrantManager/modules/Unity.TenantManagement/test/Unity.TenantManagement.Application.Tests/Unity.TenantManagement.Application.Tests.csproj
index 22c98939d..fd22d2f4f 100644
--- a/applications/Unity.GrantManager/modules/Unity.TenantManagement/test/Unity.TenantManagement.Application.Tests/Unity.TenantManagement.Application.Tests.csproj
+++ b/applications/Unity.GrantManager/modules/Unity.TenantManagement/test/Unity.TenantManagement.Application.Tests/Unity.TenantManagement.Application.Tests.csproj
@@ -18,6 +18,7 @@
+
diff --git a/applications/Unity.GrantManager/modules/Unity.TenantManagement/test/Unity.TenantManagement.EntityFrameworkCore.Tests/Unity.TenantManagement.EntityFrameworkCore.Tests.csproj b/applications/Unity.GrantManager/modules/Unity.TenantManagement/test/Unity.TenantManagement.EntityFrameworkCore.Tests/Unity.TenantManagement.EntityFrameworkCore.Tests.csproj
index 949df6382..511db9ce2 100644
--- a/applications/Unity.GrantManager/modules/Unity.TenantManagement/test/Unity.TenantManagement.EntityFrameworkCore.Tests/Unity.TenantManagement.EntityFrameworkCore.Tests.csproj
+++ b/applications/Unity.GrantManager/modules/Unity.TenantManagement/test/Unity.TenantManagement.EntityFrameworkCore.Tests/Unity.TenantManagement.EntityFrameworkCore.Tests.csproj
@@ -13,6 +13,7 @@
+
diff --git a/applications/Unity.GrantManager/modules/Unity.TenantManagement/test/Unity.TenantManagement.TestBase/Unity.TenantManagement.TestBase.csproj b/applications/Unity.GrantManager/modules/Unity.TenantManagement/test/Unity.TenantManagement.TestBase/Unity.TenantManagement.TestBase.csproj
index 30c4af10d..d0efac359 100644
--- a/applications/Unity.GrantManager/modules/Unity.TenantManagement/test/Unity.TenantManagement.TestBase/Unity.TenantManagement.TestBase.csproj
+++ b/applications/Unity.GrantManager/modules/Unity.TenantManagement/test/Unity.TenantManagement.TestBase/Unity.TenantManagement.TestBase.csproj
@@ -12,6 +12,7 @@
+
diff --git a/applications/Unity.GrantManager/modules/Unity.Theme.UX2/src/Unity.Theme.UX2/Unity.AspNetCore.Mvc.UI.Theme.UX2.csproj b/applications/Unity.GrantManager/modules/Unity.Theme.UX2/src/Unity.Theme.UX2/Unity.AspNetCore.Mvc.UI.Theme.UX2.csproj
index af8be1dee..92019f78c 100644
--- a/applications/Unity.GrantManager/modules/Unity.Theme.UX2/src/Unity.Theme.UX2/Unity.AspNetCore.Mvc.UI.Theme.UX2.csproj
+++ b/applications/Unity.GrantManager/modules/Unity.Theme.UX2/src/Unity.Theme.UX2/Unity.AspNetCore.Mvc.UI.Theme.UX2.csproj
@@ -26,7 +26,7 @@
-
+
diff --git a/applications/Unity.GrantManager/modules/Unity.Theme.UX2/src/Unity.Theme.UX2/wwwroot/themes/ux2/plugins/filterRow.js b/applications/Unity.GrantManager/modules/Unity.Theme.UX2/src/Unity.Theme.UX2/wwwroot/themes/ux2/plugins/filterRow.js
index 353c9cd08..781616ad2 100644
--- a/applications/Unity.GrantManager/modules/Unity.Theme.UX2/src/Unity.Theme.UX2/wwwroot/themes/ux2/plugins/filterRow.js
+++ b/applications/Unity.GrantManager/modules/Unity.Theme.UX2/src/Unity.Theme.UX2/wwwroot/themes/ux2/plugins/filterRow.js
@@ -380,7 +380,9 @@
*/
clearFilters: function () {
let dt = this.s.dt;
- let externalSearchId = dt.init().externalSearchInputId;
+ let dtInit = dt.init();
+ let externalSearchId = dtInit.externalSearchInputId;
+ let initialSortOrder = (dtInit && dtInit.order) ? dtInit.order : [];
// Clear external search
if (externalSearchId) {
@@ -391,10 +393,10 @@
$('.custom-filter-input').val('');
// Clear DataTable searches
- dt.search('').columns().search('').draw();
+ dt.search('').columns().search('');
// Clear order
- dt.order([]).draw();
+ dt.order(initialSortOrder);
// Reload data
dt.ajax.reload();
diff --git a/applications/Unity.GrantManager/modules/Unity.Theme.UX2/src/Unity.Theme.UX2/wwwroot/themes/ux2/table-utils.js b/applications/Unity.GrantManager/modules/Unity.Theme.UX2/src/Unity.Theme.UX2/wwwroot/themes/ux2/table-utils.js
index d0fa628e3..0d3372b1b 100644
--- a/applications/Unity.GrantManager/modules/Unity.Theme.UX2/src/Unity.Theme.UX2/wwwroot/themes/ux2/table-utils.js
+++ b/applications/Unity.GrantManager/modules/Unity.Theme.UX2/src/Unity.Theme.UX2/wwwroot/themes/ux2/table-utils.js
@@ -171,7 +171,7 @@ if ($.fn.dataTable !== undefined && $.fn.dataTable.Api) {
* @param {jQuery} options.dt - jQuery element to initialize as DataTable
* @param {Array} [options.defaultVisibleColumns=[]] - Column names visible by default
* @param {Array