diff --git a/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Application.Contracts/WorksheetInstances/IWorksheetInstanceAppService.cs b/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Application.Contracts/WorksheetInstances/IWorksheetInstanceAppService.cs index a7c0851eb..c19a67de9 100644 --- a/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Application.Contracts/WorksheetInstances/IWorksheetInstanceAppService.cs +++ b/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Application.Contracts/WorksheetInstances/IWorksheetInstanceAppService.cs @@ -6,7 +6,7 @@ namespace Unity.Flex.WorksheetInstances { public interface IWorksheetInstanceAppService : IApplicationService { - Task GetByCorrelationAnchorAsync(Guid correlationId, string correlationProvider, Guid? worksheetId, string uiAnchor); + Task GetByCorrelationAnchorAsync(Guid correlationId, string correlationProvider, Guid worksheetId, string uiAnchor); Task CreateAsync(CreateWorksheetInstanceDto dto); Task UpdateAsync(PersistWorksheetIntanceValuesDto dto); } diff --git a/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Application.Contracts/Worksheets/CustomDataFieldDto.cs b/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Application.Contracts/Worksheets/CustomDataFieldDto.cs index 9d018efe8..69b6e704f 100644 --- a/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Application.Contracts/Worksheets/CustomDataFieldDto.cs +++ b/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Application.Contracts/Worksheets/CustomDataFieldDto.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; namespace Unity.Flex.Worksheets { @@ -6,6 +7,7 @@ public class CustomDataFieldDto { public dynamic? CustomFields { get; set; } public Guid CorrelationId { get; set; } - public Guid WorksheetId { get; set; } + public Guid WorksheetId { get; set; } // Keep for backward compatibility + public List WorksheetIds { get; set; } = new List(); // NEW - multiple worksheets support } } diff --git a/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Application.Contracts/Worksheets/IWorksheetAppService.cs b/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Application.Contracts/Worksheets/IWorksheetAppService.cs index 35d89d837..e36f44c45 100644 --- a/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Application.Contracts/Worksheets/IWorksheetAppService.cs +++ b/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Application.Contracts/Worksheets/IWorksheetAppService.cs @@ -10,7 +10,7 @@ public interface IWorksheetAppService : IApplicationService Task GetAsync(Guid id); Task> GetListAsync(); Task> GetListByCorrelationAsync(Guid correlationId, string correlationProvider); - Task GetByCorrelationAnchorAsync(Guid correlationId, string correlationProvider, string uiAnchor); + Task> GetListByCorrelationAnchorAsync(Guid correlationId, string correlationProvider, string uiAnchor); Task CreateAsync(CreateWorksheetDto dto); Task CreateSectionAsync(Guid id, CreateSectionDto dto); Task EditAsync(Guid id, EditWorksheetDto dto); diff --git a/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Application/Domain/Services/WorksheetsManager.cs b/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Application/Domain/Services/WorksheetsManager.cs index a367feaa7..6dda9ec40 100644 --- a/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Application/Domain/Services/WorksheetsManager.cs +++ b/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Application/Domain/Services/WorksheetsManager.cs @@ -42,7 +42,12 @@ public async Task PersistWorksheetData(PersistWorksheetIntanceValuesEto eventDat Worksheet? worksheet; if (string.IsNullOrEmpty(eventData.FormDataName)) { - worksheet = await worksheetRepository.GetByCorrelationAnchorAsync(eventData.SheetCorrelationId, eventData.SheetCorrelationProvider, eventData.UiAnchor, true); + if (eventData.WorksheetId == Guid.Empty) + { + // WorksheetId is not set; cannot proceed. + return; + } + worksheet = await worksheetRepository.GetAsync(eventData.WorksheetId, true); } else { diff --git a/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Application/Domain/WorksheetInstances/IWorksheetInstanceRepository.cs b/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Application/Domain/WorksheetInstances/IWorksheetInstanceRepository.cs index 54d1767d5..b60d3f98c 100644 --- a/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Application/Domain/WorksheetInstances/IWorksheetInstanceRepository.cs +++ b/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Application/Domain/WorksheetInstances/IWorksheetInstanceRepository.cs @@ -8,7 +8,6 @@ namespace Unity.Flex.Domain.WorksheetInstances public interface IWorksheetInstanceRepository : IBasicRepository { Task GetByCorrelationAnchorWorksheetAsync(Guid correlationId, string correlationProvider, Guid worksheetId, string uiAnchor, bool includeDetails); - Task GetByCorrelationAnchorAsync(Guid correlationId, string correlationProvider, string uiAnchor, bool includeDetails); Task> GetByWorksheetCorrelationAsync(Guid worksheetId, string uiAnchor, Guid worksheetCorrelationId, string worksheetCorrelationProvider); Task GetWithValuesAsync(Guid worksheetInstanceId); Task ExistsAsync(Guid worksheetId, Guid instanceCorrelationId, string instanceCorrelationProvider, Guid sheetCorrelationId, string sheetCorrelationProvider, string? uiAnchor); diff --git a/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Application/Domain/Worksheets/IWorksheetRepository.cs b/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Application/Domain/Worksheets/IWorksheetRepository.cs index 31e39276c..992ba2942 100644 --- a/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Application/Domain/Worksheets/IWorksheetRepository.cs +++ b/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Application/Domain/Worksheets/IWorksheetRepository.cs @@ -9,7 +9,7 @@ public interface IWorksheetRepository : IBasicRepository { Task GetAsync(Guid id, bool includeDetails = true); Task> GetListAsync(bool includeDetails = false); - Task GetByCorrelationAnchorAsync(Guid correlationId, string correlationProvider, string uiAnchor, bool includeDetails = false); + Task> GetListByCorrelationAnchorAsync(Guid correlationId, string correlationProvider, string uiAnchor, bool includeDetails = false); Task GetByCorrelationByNameAsync(Guid correlationId, string correlationProvider, string name, bool includeDetails = false); Task GetByNameAsync(string name, bool includeDetails = false); Task GetBySectionAsync(Guid id, bool includeDetails = false); diff --git a/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Application/EntityFrameworkCore/Repositories/WorksheetInstanceRepository.cs b/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Application/EntityFrameworkCore/Repositories/WorksheetInstanceRepository.cs index e050aa414..ee92456a1 100644 --- a/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Application/EntityFrameworkCore/Repositories/WorksheetInstanceRepository.cs +++ b/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Application/EntityFrameworkCore/Repositories/WorksheetInstanceRepository.cs @@ -26,19 +26,6 @@ public class WorksheetInstanceRepository(IDbContextProvider dbCon && s.UiAnchor == uiAnchor); } - public async Task GetByCorrelationAnchorAsync(Guid correlationId, - string correlationProvider, - string uiAnchor, - bool includeDetails) - { - var dbSet = await GetDbSetAsync(); - - return await dbSet.IncludeDetails(includeDetails) - .FirstOrDefaultAsync(s => s.CorrelationId == correlationId - && s.CorrelationProvider == correlationProvider - && s.UiAnchor == uiAnchor); - } - public async Task> GetByWorksheetCorrelationAsync(Guid worksheetId, string uiAnchor, Guid worksheetCorrelationId, diff --git a/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Application/EntityFrameworkCore/Repositories/WorksheetRepository.cs b/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Application/EntityFrameworkCore/Repositories/WorksheetRepository.cs index a7fd6bcd0..1dcd9ddcc 100644 --- a/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Application/EntityFrameworkCore/Repositories/WorksheetRepository.cs +++ b/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Application/EntityFrameworkCore/Repositories/WorksheetRepository.cs @@ -11,13 +11,28 @@ namespace Unity.Flex.EntityFrameworkCore.Repositories { public class WorksheetRepository(IDbContextProvider dbContextProvider) : EfCoreRepository(dbContextProvider), IWorksheetRepository { - public async Task GetByCorrelationAnchorAsync(Guid correlationId, string correlationProvider, string uiAnchor, bool includeDetails = false) + public async Task> GetListByCorrelationAnchorAsync(Guid correlationId, string correlationProvider, string uiAnchor, bool includeDetails = false) { var dbSet = await GetDbSetAsync(); - return await dbSet - .IncludeDetails(includeDetails) - .FirstOrDefaultAsync(s => s.Links.Any(s => s.CorrelationId == correlationId && s.CorrelationProvider == correlationProvider && s.UiAnchor == uiAnchor)); + // First, get the worksheet IDs with their order from Links + var worksheetIdsWithOrder = await dbSet + .SelectMany(w => w.Links) + .Where(l => l.CorrelationId == correlationId && l.CorrelationProvider == correlationProvider && l.UiAnchor == uiAnchor) + .Select(l => new { l.WorksheetId, l.Order }) + .ToListAsync(); + + var worksheetIds = worksheetIdsWithOrder.Select(w => w.WorksheetId).ToList(); + + // Then get the full worksheets + var worksheets = await dbSet + .IncludeDetails(includeDetails) + .Where(w => worksheetIds.Contains(w.Id)) + .ToListAsync(); + + // Finally, order them in memory using the order we retrieved + var orderLookup = worksheetIdsWithOrder.ToDictionary(w => w.WorksheetId, w => w.Order ?? 0); + return worksheets.OrderBy(w => orderLookup[w.Id]).ToList(); } public async Task GetByCorrelationByNameAsync(Guid correlationId, string correlationProvider, string name, bool includeDetails = false) diff --git a/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Application/EntityFrameworkCore/WorksheetQueryableExtensions.cs b/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Application/EntityFrameworkCore/WorksheetQueryableExtensions.cs index b8f335456..788cb0ed3 100644 --- a/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Application/EntityFrameworkCore/WorksheetQueryableExtensions.cs +++ b/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Application/EntityFrameworkCore/WorksheetQueryableExtensions.cs @@ -12,7 +12,8 @@ public static IQueryable IncludeDetails(this IQueryable qu { return !include ? queryable : queryable .Include(s => s.Sections.OrderBy(s => s.Order)) - .ThenInclude(s => s.Fields.OrderBy(s => s.Order)); + .ThenInclude(s => s.Fields.OrderBy(s => s.Order)) + .Include(s => s.Links); } public static IQueryable IncludeDetails(this IQueryable queryable, bool include = true) diff --git a/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Application/Worksheets/WorksheetAppService.cs b/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Application/Worksheets/WorksheetAppService.cs index 2bb0e08ca..47114d2e2 100644 --- a/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Application/Worksheets/WorksheetAppService.cs +++ b/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Application/Worksheets/WorksheetAppService.cs @@ -33,13 +33,11 @@ public virtual async Task> GetListByCorrelationAsync(Guid cor return ObjectMapper.Map, List>(worksheets); } - public virtual async Task GetByCorrelationAnchorAsync(Guid correlationId, string correlationProvider, string uiAnchor) + public virtual async Task> GetListByCorrelationAnchorAsync(Guid correlationId, string correlationProvider, string uiAnchor) { - var worksheet = await worksheetRepository.GetByCorrelationAnchorAsync(correlationId, correlationProvider, uiAnchor, true); + var worksheets = await worksheetRepository.GetListByCorrelationAnchorAsync(correlationId, correlationProvider, uiAnchor, true); - if (worksheet == null) return null; - - return ObjectMapper.Map(worksheet); + return ObjectMapper.Map, List>(worksheets); } public virtual async Task CreateAsync(CreateWorksheetDto dto) diff --git a/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Application/Worksheets/WorksheetInstanceAppService.cs b/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Application/Worksheets/WorksheetInstanceAppService.cs index bdad72b10..da2c963a1 100644 --- a/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Application/Worksheets/WorksheetInstanceAppService.cs +++ b/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Application/Worksheets/WorksheetInstanceAppService.cs @@ -9,12 +9,9 @@ namespace Unity.Flex.WorksheetInstances [Authorize] public class WorksheetInstanceAppService(IWorksheetInstanceRepository worksheetInstanceRepository, WorksheetsManager worksheetsManager) : FlexAppService, IWorksheetInstanceAppService { - public virtual async Task GetByCorrelationAnchorAsync(Guid correlationId, string correlationProvider, Guid? worksheetId, string uiAnchor) + public virtual async Task GetByCorrelationAnchorAsync(Guid correlationId, string correlationProvider, Guid worksheetId, string uiAnchor) { - if (worksheetId == null) - return ObjectMapper.Map(await worksheetInstanceRepository.GetByCorrelationAnchorAsync(correlationId, correlationProvider, uiAnchor, true)); - else - return ObjectMapper.Map(await worksheetInstanceRepository.GetByCorrelationAnchorWorksheetAsync(correlationId, correlationProvider, worksheetId.Value, uiAnchor, true)); + return ObjectMapper.Map(await worksheetInstanceRepository.GetByCorrelationAnchorWorksheetAsync(correlationId, correlationProvider, worksheetId, uiAnchor, true)); } public virtual async Task CreateAsync(CreateWorksheetInstanceDto dto) diff --git a/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Application/Worksheets/WorksheetLinkAppService.cs b/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Application/Worksheets/WorksheetLinkAppService.cs index de20c6938..dadecaf92 100644 --- a/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Application/Worksheets/WorksheetLinkAppService.cs +++ b/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Application/Worksheets/WorksheetLinkAppService.cs @@ -50,13 +50,13 @@ private static async Task AddAndUnorphanLinksAsync(IWorksheetLinkRepository work List refreshedLinks) { // Add new - foreach (var (worksheetId, anchor, _) in dto.WorksheetAnchors) + foreach (var (worksheetId, anchor, order) in dto.WorksheetAnchors) { if (worksheetLinks.Find(s => s.CorrelationId == dto.CorrelationId && s.CorrelationProvider == dto.CorrelationProvider && s.WorksheetId == worksheetId) == null) { - var newLink = new WorksheetLink(Guid.NewGuid(), worksheetId, dto.CorrelationId, dto.CorrelationProvider, anchor); + var newLink = new WorksheetLink(Guid.NewGuid(), worksheetId, dto.CorrelationId, dto.CorrelationProvider, anchor, order); var worksheetInstances = await worksheetInstanceRepository .GetByWorksheetCorrelationAsync(worksheetId, ORPHANED, dto.CorrelationId, dto.CorrelationProvider); diff --git a/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Views/Shared/Components/BCAddressWidget/BCAddressWidget.cs b/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Views/Shared/Components/BCAddressWidget/BCAddressWidget.cs index 1b699cf49..e50d6e692 100644 --- a/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Views/Shared/Components/BCAddressWidget/BCAddressWidget.cs +++ b/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Views/Shared/Components/BCAddressWidget/BCAddressWidget.cs @@ -1,4 +1,5 @@ using Microsoft.AspNetCore.Mvc; +using System; using System.Threading.Tasks; using Unity.Flex.Web.Views.Shared.Components.WorksheetInstanceWidget.ViewModels; using Volo.Abp.AspNetCore.Mvc.UI.Widgets; @@ -16,12 +17,13 @@ namespace Unity.Flex.Web.Views.Shared.Components.BCAddressWidget AutoInitialize = true)] public class BCAddressWidget : AbpViewComponent { - public async Task InvokeAsync(WorksheetFieldViewModel? fieldModel, string modelName) + public async Task InvokeAsync(WorksheetFieldViewModel? fieldModel, string modelName, Guid? worksheetId = null) { return View(await Task.FromResult(new BCAddressViewModel() { Field = fieldModel, - Name = modelName + Name = modelName, + WorksheetId = worksheetId })); } } diff --git a/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Views/Shared/Components/BCAddressWidget/BCAddressWidgetController.cs b/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Views/Shared/Components/BCAddressWidget/BCAddressWidgetController.cs index 05bcf1394..7273e8686 100644 --- a/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Views/Shared/Components/BCAddressWidget/BCAddressWidgetController.cs +++ b/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Views/Shared/Components/BCAddressWidget/BCAddressWidgetController.cs @@ -1,5 +1,6 @@ using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Logging; +using System; using Unity.Flex.Web.Views.Shared.Components.WorksheetInstanceWidget.ViewModels; using Unity.Modules.Shared.Utils; using Volo.Abp.AspNetCore.Mvc; @@ -12,14 +13,14 @@ public class BCAddressWidgetController : AbpController { [HttpGet] [Route("Refresh")] - public IActionResult Refresh(WorksheetFieldViewModel? fieldModel, string modelName) + public IActionResult Refresh(WorksheetFieldViewModel? fieldModel, string modelName, Guid? worksheetId = null) { if (!ModelState.IsValid) { Logger.LogWarning("Invalid model state for Refresh: {ModelName}, {FieldModel}", modelName.SanitizeField(), fieldModel?.Id.ToString()); return ViewComponent(typeof(BCAddressWidget)); } - return ViewComponent(typeof(BCAddressWidget), new { fieldModel, modelName }); + return ViewComponent(typeof(BCAddressWidget), new { fieldModel, modelName, worksheetId }); } } } diff --git a/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Views/Shared/Components/CheckboxGroupWidget/CheckboxGroupWidget.cs b/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Views/Shared/Components/CheckboxGroupWidget/CheckboxGroupWidget.cs index 9545bad9a..7520b626e 100644 --- a/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Views/Shared/Components/CheckboxGroupWidget/CheckboxGroupWidget.cs +++ b/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Views/Shared/Components/CheckboxGroupWidget/CheckboxGroupWidget.cs @@ -1,4 +1,5 @@ using Microsoft.AspNetCore.Mvc; +using System; using System.Threading.Tasks; using Unity.Flex.Web.Views.Shared.Components.WorksheetInstanceWidget.ViewModels; using Volo.Abp.AspNetCore.Mvc.UI.Widgets; @@ -16,9 +17,9 @@ namespace Unity.Flex.Web.Views.Shared.Components.CheckboxGroupWidget AutoInitialize = true)] public class CheckboxGroupWidget : AbpViewComponent { - public async Task InvokeAsync(WorksheetFieldViewModel? fieldModel, string modelName) + public async Task InvokeAsync(WorksheetFieldViewModel? fieldModel, string modelName, Guid? worksheetId = null) { - return View(await Task.FromResult(new CheckboxGroupViewModel() { Field = fieldModel, Name = modelName })); + return View(await Task.FromResult(new CheckboxGroupViewModel() { Field = fieldModel, Name = modelName, WorksheetId = worksheetId })); } } diff --git a/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Views/Shared/Components/CheckboxGroupWidget/CheckboxGroupWidgetController.cs b/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Views/Shared/Components/CheckboxGroupWidget/CheckboxGroupWidgetController.cs index ea9bdd318..dd5c9f676 100644 --- a/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Views/Shared/Components/CheckboxGroupWidget/CheckboxGroupWidgetController.cs +++ b/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Views/Shared/Components/CheckboxGroupWidget/CheckboxGroupWidgetController.cs @@ -1,4 +1,5 @@ using Microsoft.AspNetCore.Mvc; +using System; using Unity.Flex.Web.Views.Shared.Components.WorksheetInstanceWidget.ViewModels; using Volo.Abp.AspNetCore.Mvc; @@ -10,12 +11,12 @@ public class CheckboxGroupWidgetController : AbpController { [HttpGet] [Route("Refresh")] - public IActionResult Refresh(WorksheetFieldViewModel? fieldModel, string modelName) + public IActionResult Refresh(WorksheetFieldViewModel? fieldModel, string modelName, Guid? worksheetId = null) { if (ModelState.IsValid) { - return ViewComponent(typeof(CheckboxGroupWidget), new { fieldModel, modelName }); + return ViewComponent(typeof(CheckboxGroupWidget), new { fieldModel, modelName, worksheetId }); } else diff --git a/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Views/Shared/Components/CheckboxGroupWidget/Default.cshtml b/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Views/Shared/Components/CheckboxGroupWidget/Default.cshtml index ac8cf6b0d..b29b275ac 100644 --- a/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Views/Shared/Components/CheckboxGroupWidget/Default.cshtml +++ b/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Views/Shared/Components/CheckboxGroupWidget/Default.cshtml @@ -7,29 +7,34 @@ @if (Model.Field != null) { +
@{ var checkedValues = Model.Field?.CurrentValue?.GetCheckedOptions() ?? []; foreach (var option in ((CheckboxGroupDefinition?)Model.Field?.Definition?.ConvertDefinition(Model.Field.Type))?.Options ?? []) - { + { + var optionId = Model.WorksheetId.HasValue + ? $"{Model.Field?.Name}.{Model.Name}.{Model.Field?.Id}.{option.Key}.{Model.WorksheetId}" + : $"{Model.Field?.Name}.{Model.Name}.{Model.Field?.Id}.{option.Key}"; +
@if (checkedValues.Contains(option.Key)) { } else { } - +
} } diff --git a/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Views/Shared/Components/CheckboxWidget/CheckboxWidget.cs b/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Views/Shared/Components/CheckboxWidget/CheckboxWidget.cs index 612fc4c0a..5fd729d58 100644 --- a/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Views/Shared/Components/CheckboxWidget/CheckboxWidget.cs +++ b/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Views/Shared/Components/CheckboxWidget/CheckboxWidget.cs @@ -1,4 +1,5 @@ using Microsoft.AspNetCore.Mvc; +using System; using System.Threading.Tasks; using Unity.Flex.Web.Views.Shared.Components.WorksheetInstanceWidget.ViewModels; using Volo.Abp.AspNetCore.Mvc.UI.Widgets; @@ -16,9 +17,9 @@ namespace Unity.Flex.Web.Views.Shared.Components.CheckboxWidget AutoInitialize = true)] public class CheckboxWidget : AbpViewComponent { - public async Task InvokeAsync(WorksheetFieldViewModel? fieldModel, string modelName) + public async Task InvokeAsync(WorksheetFieldViewModel? fieldModel, string modelName, Guid? worksheetId = null) { - return View(await Task.FromResult(new CheckboxViewModel() { Field = fieldModel, Name = modelName })); + return View(await Task.FromResult(new CheckboxViewModel() { Field = fieldModel, Name = modelName, WorksheetId = worksheetId })); } } diff --git a/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Views/Shared/Components/CheckboxWidget/CheckboxWidgetController.cs b/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Views/Shared/Components/CheckboxWidget/CheckboxWidgetController.cs index d6528399c..501aeea8f 100644 --- a/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Views/Shared/Components/CheckboxWidget/CheckboxWidgetController.cs +++ b/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Views/Shared/Components/CheckboxWidget/CheckboxWidgetController.cs @@ -1,5 +1,6 @@ using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Logging; +using System; using Unity.Flex.Web.Views.Shared.Components.WorksheetInstanceWidget.ViewModels; using Unity.Modules.Shared.Utils; using Volo.Abp.AspNetCore.Mvc; @@ -12,7 +13,7 @@ public class CheckboxWidgetController : AbpController { [HttpGet] [Route("Refresh")] - public IActionResult Refresh(WorksheetFieldViewModel? fieldModel, string modelName) + public IActionResult Refresh(WorksheetFieldViewModel? fieldModel, string modelName, Guid? worksheetId = null) { if (!ModelState.IsValid) { @@ -20,7 +21,7 @@ public IActionResult Refresh(WorksheetFieldViewModel? fieldModel, string modelNa return ViewComponent(typeof(CheckboxWidget)); } - return ViewComponent(typeof(CheckboxWidget), new { fieldModel, modelName }); + return ViewComponent(typeof(CheckboxWidget), new { fieldModel, modelName, worksheetId }); } } } diff --git a/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Views/Shared/Components/CheckboxWidget/Default.cshtml b/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Views/Shared/Components/CheckboxWidget/Default.cshtml index be8fa4388..fbc2b5f70 100644 --- a/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Views/Shared/Components/CheckboxWidget/Default.cshtml +++ b/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Views/Shared/Components/CheckboxWidget/Default.cshtml @@ -6,22 +6,27 @@ @if (Model.Field != null) { + + var fieldId = Model.WorksheetId.HasValue + ? $"{Model.Field?.Name}.{Model.Name}.{Model.Field?.Id}.{Model.WorksheetId}" + : $"{Model.Field?.Name}.{Model.Name}.{Model.Field?.Id}"; +
@if ((bool)(Model.Field?.CurrentValue?.ConvertInputValueOrNull(Model.Field.Type) ?? false)) { } else { } - +
} \ No newline at end of file diff --git a/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Views/Shared/Components/CurrencyWidget/CurrencyWidget.cs b/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Views/Shared/Components/CurrencyWidget/CurrencyWidget.cs index 769346ac8..ae0e5d685 100644 --- a/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Views/Shared/Components/CurrencyWidget/CurrencyWidget.cs +++ b/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Views/Shared/Components/CurrencyWidget/CurrencyWidget.cs @@ -1,4 +1,5 @@ using Microsoft.AspNetCore.Mvc; +using System; using System.Threading.Tasks; using Unity.Flex.Web.Views.Shared.Components.WorksheetInstanceWidget.ViewModels; using Volo.Abp.AspNetCore.Mvc.UI.Bundling; @@ -16,9 +17,9 @@ namespace Unity.Flex.Web.Views.Shared.Components.CurrencyWidget AutoInitialize = true)] public class CurrencyWidget : AbpViewComponent { - public async Task InvokeAsync(WorksheetFieldViewModel? fieldModel, string modelName) + public async Task InvokeAsync(WorksheetFieldViewModel? fieldModel, string modelName, Guid? worksheetId = null) { - return View(await Task.FromResult(new CurrencyViewModel() { Field = fieldModel, Name = modelName })); + return View(await Task.FromResult(new CurrencyViewModel() { Field = fieldModel, Name = modelName, WorksheetId = worksheetId })); } } diff --git a/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Views/Shared/Components/CurrencyWidget/CurrencyWidgetController.cs b/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Views/Shared/Components/CurrencyWidget/CurrencyWidgetController.cs index 9d177a070..7a62072f7 100644 --- a/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Views/Shared/Components/CurrencyWidget/CurrencyWidgetController.cs +++ b/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Views/Shared/Components/CurrencyWidget/CurrencyWidgetController.cs @@ -1,5 +1,6 @@ using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Logging; +using System; using Unity.Flex.Web.Views.Shared.Components.WorksheetInstanceWidget.ViewModels; using Volo.Abp.AspNetCore.Mvc; @@ -11,7 +12,7 @@ public class CurrencyWidgetController : AbpController { [HttpGet] [Route("Refresh")] - public IActionResult Refresh(WorksheetFieldViewModel? fieldModel, string modelName) + public IActionResult Refresh(WorksheetFieldViewModel? fieldModel, string modelName, Guid? worksheetId = null) { // Check if the model state is valid if (!ModelState.IsValid) @@ -21,7 +22,7 @@ public IActionResult Refresh(WorksheetFieldViewModel? fieldModel, string modelNa } // If the model state is valid, render the view component - return ViewComponent(typeof(CurrencyWidget), new { fieldModel, modelName }); + return ViewComponent(typeof(CurrencyWidget), new { fieldModel, modelName, worksheetId }); } } } diff --git a/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Views/Shared/Components/CurrencyWidget/Default.cshtml b/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Views/Shared/Components/CurrencyWidget/Default.cshtml index 06c53a5b0..6b84c9ef8 100644 --- a/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Views/Shared/Components/CurrencyWidget/Default.cshtml +++ b/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Views/Shared/Components/CurrencyWidget/Default.cshtml @@ -6,6 +6,11 @@ @if (Model.Field != null) { + + var fieldId = Model.WorksheetId.HasValue + ? $"{Model.Field.Name}.{Model.Name}.{Model.Field.Id}.{Model.WorksheetId}" + : $"{Model.Field.Name}.{Model.Name}.{Model.Field.Id}"; +
$ - +
} \ No newline at end of file diff --git a/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Views/Shared/Components/DateWidget/DateWidget.cs b/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Views/Shared/Components/DateWidget/DateWidget.cs index 8d1df78a3..09ab5165b 100644 --- a/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Views/Shared/Components/DateWidget/DateWidget.cs +++ b/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Views/Shared/Components/DateWidget/DateWidget.cs @@ -1,4 +1,5 @@ using Microsoft.AspNetCore.Mvc; +using System; using System.Threading.Tasks; using Unity.Flex.Web.Views.Shared.Components.WorksheetInstanceWidget.ViewModels; using Volo.Abp.AspNetCore.Mvc.UI.Widgets; @@ -16,9 +17,9 @@ namespace Unity.Flex.Web.Views.Shared.Components.DateWidget AutoInitialize = true)] public class DateWidget : AbpViewComponent { - public async Task InvokeAsync(WorksheetFieldViewModel? fieldModel, string modelName) + public async Task InvokeAsync(WorksheetFieldViewModel? fieldModel, string modelName, Guid? worksheetId = null) { - return View(await Task.FromResult(new DateViewModel() { Field = fieldModel, Name = modelName })); + return View(await Task.FromResult(new DateViewModel() { Field = fieldModel, Name = modelName, WorksheetId = worksheetId })); } } diff --git a/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Views/Shared/Components/DateWidget/DateWidgetController.cs b/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Views/Shared/Components/DateWidget/DateWidgetController.cs index 34452dde6..3d1e10eb9 100644 --- a/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Views/Shared/Components/DateWidget/DateWidgetController.cs +++ b/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Views/Shared/Components/DateWidget/DateWidgetController.cs @@ -1,5 +1,6 @@ using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Logging; +using System; using Unity.Flex.Web.Views.Shared.Components.WorksheetInstanceWidget.ViewModels; using Volo.Abp.AspNetCore.Mvc; @@ -11,7 +12,7 @@ public class DateWidgetController : AbpController { [HttpGet] [Route("Refresh")] - public IActionResult Refresh(WorksheetFieldViewModel? fieldModel, string modelName) + public IActionResult Refresh(WorksheetFieldViewModel? fieldModel, string modelName, Guid? worksheetId = null) { // Check if the model state is valid @@ -22,7 +23,7 @@ public IActionResult Refresh(WorksheetFieldViewModel? fieldModel, string modelNa } // If the model state is valid, render the view component - return ViewComponent(typeof(DateWidget), new { fieldModel, modelName }); + return ViewComponent(typeof(DateWidget), new { fieldModel, modelName, worksheetId }); } } } diff --git a/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Views/Shared/Components/DateWidget/Default.cshtml b/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Views/Shared/Components/DateWidget/Default.cshtml index b9e5b1e66..5006e52bb 100644 --- a/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Views/Shared/Components/DateWidget/Default.cshtml +++ b/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Views/Shared/Components/DateWidget/Default.cshtml @@ -6,14 +6,19 @@ @if (Model.Field != null) { + + var fieldId = Model.WorksheetId.HasValue + ? $"{Model.Field.Name}.{Model.Name}.{Model.Field.Id}.{Model.WorksheetId}" + : $"{Model.Field.Name}.{Model.Name}.{Model.Field.Id}"; +
} \ No newline at end of file diff --git a/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Views/Shared/Components/RadioWidget/Default.cshtml b/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Views/Shared/Components/RadioWidget/Default.cshtml index e7eb992bc..59d3a1cca 100644 --- a/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Views/Shared/Components/RadioWidget/Default.cshtml +++ b/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Views/Shared/Components/RadioWidget/Default.cshtml @@ -7,18 +7,26 @@ @if (Model.Field != null) { + + var fieldBaseName = Model.WorksheetId.HasValue + ? $"{Model.Field.Name}.{Model.Name}.{Model.Field.Id}.{Model.WorksheetId}" + : $"{Model.Field.Name}.{Model.Name}.{Model.Field.Id}"; +
@foreach (var option in ((RadioDefinition?)Model.Field?.Definition?.ConvertDefinition(Model.Field.Type))?.Options ?? []) { + + var optionId = $"{fieldBaseName}.{option.Value}"; +
@if (Model.Field != null) { @if ((Model.Field?.CurrentValue?.ConvertInputValueOrNull(Model.Field.Type))?.ToString() == option.Value) { @@ -26,12 +34,12 @@ else { } - + }
} diff --git a/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Views/Shared/Components/RadioWidget/RadioWidget.cs b/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Views/Shared/Components/RadioWidget/RadioWidget.cs index fe0a67370..f5bdace73 100644 --- a/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Views/Shared/Components/RadioWidget/RadioWidget.cs +++ b/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Views/Shared/Components/RadioWidget/RadioWidget.cs @@ -1,4 +1,5 @@ using Microsoft.AspNetCore.Mvc; +using System; using System.Threading.Tasks; using Unity.Flex.Web.Views.Shared.Components.WorksheetInstanceWidget.ViewModels; using Volo.Abp.AspNetCore.Mvc.UI.Widgets; @@ -16,9 +17,9 @@ namespace Unity.Flex.Web.Views.Shared.Components.RadioWidget AutoInitialize = true)] public class RadioWidget : AbpViewComponent { - public async Task InvokeAsync(WorksheetFieldViewModel? fieldModel, string modelName) + public async Task InvokeAsync(WorksheetFieldViewModel? fieldModel, string modelName, Guid? worksheetId = null) { - return View(await Task.FromResult(new RadioViewModel() { Field = fieldModel, Name = modelName })); + return View(await Task.FromResult(new RadioViewModel() { Field = fieldModel, Name = modelName, WorksheetId = worksheetId })); } } diff --git a/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Views/Shared/Components/RadioWidget/RadioWidgetController.cs b/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Views/Shared/Components/RadioWidget/RadioWidgetController.cs index da523dd55..01be1f58f 100644 --- a/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Views/Shared/Components/RadioWidget/RadioWidgetController.cs +++ b/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Views/Shared/Components/RadioWidget/RadioWidgetController.cs @@ -1,5 +1,6 @@ using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Logging; +using System; using Unity.Flex.Web.Views.Shared.Components.WorksheetInstanceWidget.ViewModels; using Volo.Abp.AspNetCore.Mvc; @@ -11,7 +12,7 @@ public class RadioWidgetController : AbpController { [HttpGet] [Route("Refresh")] - public IActionResult Refresh(WorksheetFieldViewModel? fieldModel, string modelName) + public IActionResult Refresh(WorksheetFieldViewModel? fieldModel, string modelName, Guid? worksheetId = null) { // Check if the model state is valid if (!ModelState.IsValid) @@ -21,7 +22,7 @@ public IActionResult Refresh(WorksheetFieldViewModel? fieldModel, string modelNa } // If the model state is valid, render the view component - return ViewComponent(typeof(RadioWidget), new { fieldModel, modelName }); + return ViewComponent(typeof(RadioWidget), new { fieldModel, modelName, worksheetId }); } } } diff --git a/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Views/Shared/Components/SelectListWidget/Default.cshtml b/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Views/Shared/Components/SelectListWidget/Default.cshtml index e3ae125b2..1c4a6512b 100644 --- a/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Views/Shared/Components/SelectListWidget/Default.cshtml +++ b/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Views/Shared/Components/SelectListWidget/Default.cshtml @@ -7,9 +7,14 @@ @if (Model.Field != null) { + + var fieldId = Model.WorksheetId.HasValue + ? $"{Model.Field.Name}.{Model.Name}.{Model.Field.Id}.{Model.WorksheetId}" + : $"{Model.Field.Name}.{Model.Name}.{Model.Field.Id}"; + + +
+
+
Add Member
+ + + +
+
+
+
Group Members
+
+ + + + + + + + + + + + + + +
First NameLast NameDisplay Name
No users selected
+
+
+ + + + + + + `; + + $('body').append(modalHtml); + const modal = new bootstrap.Modal(document.getElementById('createGroupModal')); + + // Initialize DataTable for selected users + let createGroupUsersTable = null; + + // Wait for modal to be fully shown before initializing DataTable + $('#createGroupModal').on('shown.bs.modal', function () { + createGroupUsersTable = $('#createGroupUsersTable').DataTable(abp.libs.datatables.normalizeConfiguration( + self.utils.getStandardDataTableConfig([]) + )); + + // Force columns to adjust + createGroupUsersTable.columns.adjust().draw(); + }); + + modal.show(); + + // Initialize user search with shared utility + self.utils.setupUserSearchDropdown( + 'createGroupUserSearch', + 'createGroupUserDropdown', + 'createAddUserBtn', + function(selectedUser) { + // Add to selected users if not already there + if (!selectedUsers.find(u => u.userId === selectedUser.userId)) { + const newUser = { + userId: selectedUser.userId, + userName: selectedUser.userName, + userEmail: selectedUser.userEmail, + firstName: selectedUser.firstName || '', + lastName: selectedUser.lastName || '', + isNew: true + }; + selectedUsers.push(newUser); + + // Update DataTable + if (createGroupUsersTable) { + createGroupUsersTable.row.add(newUser).draw(); + } + } + } + ); + + // Override the default displayFilteredUsers for create modal to exclude selected users + const originalDisplayFilteredUsers = self.utils.displayFilteredUsers.bind(self.utils); + self.utils.displayFilteredUsers = function(dropdownId, filteredUsers, excludeUserIds = []) { + if (dropdownId === 'createGroupUserDropdown') { + const selectedUserIds = selectedUsers.map(u => u.userId); + excludeUserIds = [...excludeUserIds, ...selectedUserIds]; + } + return originalDisplayFilteredUsers(dropdownId, filteredUsers, excludeUserIds); + }; + + // Handle removing user from selected list + $(document).on('click', '#createGroupUsersTable .remove-selected-user', function (e) { + e.preventDefault(); + const userId = $(this).data('user-id'); + const rowElement = $(this).closest('tr'); + + // Remove from array + const index = selectedUsers.findIndex(u => u.userId === userId); + if (index > -1) { + selectedUsers.splice(index, 1); + + // Remove from DataTable + if (createGroupUsersTable) { + createGroupUsersTable.row(rowElement).remove().draw(); + } + } + }); + + $('#saveNewGroup').on('click', function () { + const name = $('#groupName').val(); + const description = $('#groupDescription').val(); + + if (!name) { + abp.notify.error('Group name is required'); + return; + } + + const dto = { + name: name, + description: description, + type: 'Dynamic' + }; + + unity.notifications.emailGroups.emailGroups.create(dto).then(result => { + if (!(result?.id && selectedUsers?.length)) { + abp.notify.success('Email group created successfully'); + modal.hide(); + emailGroupsTable?.ajax.reload(); + return; + } + + const ops = selectedUsers.map(u => + unity.notifications.emailGroups.emailGroupUsers.insert({ userId: u.userId, groupId: result.id }) + ); + + Promise.all(ops).then(() => { + abp.notify.success(`Email group created with ${selectedUsers.length} users`); + modal.hide(); + emailGroupsTable?.ajax.reload(); + }); + }).catch(err => { + console.error('Failed to create email group:', err); + abp.notify.error('Failed to create email group'); + }); + }); + + $('#createGroupModal').on('hidden.bs.modal', function () { + // Restore original displayFilteredUsers function + self.utils.displayFilteredUsers = originalDisplayFilteredUsers; + + // Clean up DataTable + if (createGroupUsersTable) { + createGroupUsersTable.destroy(); + } + // Clean up event handlers + $(document).off('click', '#createGroupUserDropdown .dropdown-user-item'); + $(document).off('click', '#createGroupUsersTable .remove-selected-user'); + $(this).remove(); + }); + }, + + deleteGroup: function (groupId) { + abp.message.confirm( + 'Are you sure you want to delete this email group? This action cannot be undone.', + 'Delete Email Group', + function (isConfirmed) { + if (isConfirmed) { + unity.notifications.emailGroups.emailGroups.delete(groupId).then(function () { + abp.notify.success('Email group deleted successfully'); + if (emailGroupsTable) { + emailGroupsTable.ajax.reload(); + } + }).catch(function (error) { + console.error('Failed to delete email group:', error); + abp.notify.error('Failed to delete email group'); + }); + } + } + ); + }, + + showManageUsersModal: function (group) { + const self = this; + const isDynamic = group.type === 'dynamic' || group.type === 'Dynamic'; + + // Track changes locally + let pendingUserAdditions = []; + let pendingUserRemovals = []; + + const modalHtml = ` + + `; + + $('body').append(modalHtml); + const modal = new bootstrap.Modal(document.getElementById('manageUsersModal')); + modal.show(); + + // Initialize DataTable for group users + let groupUsersTable = null; + + // Function to add user to local state only + const addUserLocally = function (userInfo) { + // Check if user is already in the table + const existingUsers = groupUsersTable.rows().data().toArray(); + if (existingUsers.some(u => u.userId === userInfo.userId)) { + abp.notify.warn('User is already in the group'); + return; + } + + // Check if this user was previously removed (cancel out the removal) + const removalIndex = pendingUserRemovals.findIndex(u => u.userId === userInfo.userId); + if (removalIndex > -1) { + pendingUserRemovals.splice(removalIndex, 1); + } else if (!pendingUserAdditions.some(u => u.userId === userInfo.userId)) { + pendingUserAdditions.push(userInfo); + } + + // Add to DataTable for visual feedback + const newRow = { + id: 'temp_' + userInfo.userId, // Temporary ID for new users + userId: userInfo.userId, + groupId: group.id, + userName: userInfo.userName, + email: userInfo.userEmail || userInfo.email || '', + firstName: userInfo.firstName || '', + lastName: userInfo.lastName || '', + isNew: true // Flag to identify newly added users + }; + groupUsersTable.row.add(newRow).draw(); + }; + + // Function to remove user from local state only + const removeUserLocally = function (rowElement, rowData) { + const userId = rowData.userId; + + // Check if this is a newly added user (not yet saved) + const additionIndex = pendingUserAdditions.findIndex(u => u.userId === userId); + if (additionIndex > -1) { + // Remove from pending additions + pendingUserAdditions.splice(additionIndex, 1); + } else if (!pendingUserRemovals.some(u => u.userId === userId)) { + // Add to pending removals if not already there + pendingUserRemovals.push(rowData); + } + + // Remove from DataTable for visual feedback + groupUsersTable.row(rowElement).remove().draw(); + }; + + $('#manageUsersModal').one('shown.bs.modal', () => { + groupUsersTable = $('#groupUsersTable').DataTable( + abp.libs.datatables.normalizeConfiguration(self.utils.getStandardDataTableConfig([])) + ); + self.loadGroupUsersForTable(group.id, groupUsersTable); + }); + + // Initialize user search with shared utility and custom filtering for existing group users + self.utils.setupUserSearchDropdown( + 'userSearchInput', + 'userDropdownMenu', + 'manageAddUserBtn', + function(selectedUser) { + addUserLocally(selectedUser); + } + ); + + // Override the default displayFilteredUsers for manage modal to exclude current group users + const originalDisplayFilteredUsers = self.utils.displayFilteredUsers.bind(self.utils); + self.utils.displayFilteredUsers = function(dropdownId, filteredUsers, excludeUserIds = []) { + if (dropdownId === 'userDropdownMenu') { + // Get current group users from DataTable and exclude them + const currentUsers = groupUsersTable ? groupUsersTable.rows().data().toArray() : []; + const currentUserIds = currentUsers.map(u => u.userId); + excludeUserIds = [...excludeUserIds, ...currentUserIds]; + } + return originalDisplayFilteredUsers(dropdownId, filteredUsers, excludeUserIds); + }; + + // Also show dropdown on focus + $('#userSearchInput').on('focus', function () { + if ($(this).val().length > 0) { + $('#userDropdownMenu').addClass('show'); + $(this).attr('aria-expanded', 'true'); + } + }); + + // Handle remove user button click - removes locally only + $('#manageUsersModal').on('click', '.remove-user-btn, .remove-selected-user', function (e) { + e.preventDefault(); + e.stopPropagation(); + const rowElement = $(this).closest('tr'); + const rowData = groupUsersTable.row(rowElement).data(); + if (rowData) { + removeUserLocally(rowElement, rowData); + } + }); + + // Save all changes (group info and user changes) + $('#saveGroupChanges').on('click', function () { + const name = $('#editGroupName').val(); + const description = $('#editGroupDescription').val(); + + if (!name) { + abp.notify.error('Group name is required'); + return; + } + + // Disable save button to prevent double-clicking + $(this).prop('disabled', true).html('Saving...'); + + // Create array of promises for all operations + const promises = []; + + // Update group info if changed + const groupInfoChanged = (isDynamic && name !== group.name) || description !== (group.description || ''); + if (groupInfoChanged) { + const dto = { + id: group.id, + name: isDynamic ? name : group.name, + description: description, + type: group.type + }; + promises.push( + unity.notifications.emailGroups.emailGroups.update(dto) + .catch(error => { + console.error('Failed to update group:', error); + throw new Error('Failed to update group information'); + }) + ); + } + + // Process user removals + pendingUserRemovals.forEach(user => { + if (user.id && user.id !== 'temp_' + user.userId) { + promises.push( + unity.notifications.emailGroups.emailGroupUsers.deleteUser(user.id) + .catch(error => { + console.error(`Failed to remove user ${user.userName}:`, error); + throw new Error(`Failed to remove user ${user.userName}`); + }) + ); + } + }); + + // Process user additions + pendingUserAdditions.forEach(user => { + const dto = { + userId: user.userId, + groupId: group.id + }; + promises.push( + unity.notifications.emailGroups.emailGroupUsers.insert(dto) + .catch(error => { + console.error(`Failed to add user ${user.userName}:`, error); + throw new Error(`Failed to add user ${user.userName}`); + }) + ); + }); + + // Execute all promises + if (promises.length > 0) { + Promise.all(promises) + .then(() => { + abp.notify.success('All changes saved successfully'); + + // Reload the main table + if (emailGroupsTable) { + emailGroupsTable.ajax.reload(); + } + + // Close the modal + const modal = bootstrap.Modal.getInstance(document.getElementById('manageUsersModal')); + modal.hide(); + }) + .catch(error => { + abp.notify.error(error.message || 'Failed to save some changes'); + // Re-enable save button + $('#saveGroupChanges').prop('disabled', false).html('Save'); + }); + } else { + // No changes to save + abp.notify.info('No changes to save'); + $('#saveGroupChanges').prop('disabled', false).html('Save'); + } + }); + + // Handle modal close/cancel + $('#manageUsersModal').on('hidden.bs.modal', function () { + + // Restore original displayFilteredUsers function + self.utils.displayFilteredUsers = originalDisplayFilteredUsers; + + if (groupUsersTable) { + groupUsersTable.destroy(); + } + // Clean up event handlers + $(document).off('click', '#userDropdownMenu .dropdown-user-item'); + $(this).remove(); + }); + }, + + + loadAllUsers: function (callback) { + // Load all users for the dropdown + $.ajax({ + url: '/api/identity/users', + method: 'GET', + data: { + maxResultCount: 1000, + skipCount: 0 + }, + headers: { + 'RequestVerificationToken': abp.security.antiForgery.getToken() + }, + success: function (response) { + const users = response.items || response || []; + callback(users); + }, + error: function (xhr, status, error) { + console.error('Failed to load users:', error); + callback([]); + } + }); + }, + + + loadGroupUsersForTable: function (groupId, dataTable) { + + unity.notifications.emailGroups.emailGroupUsers.getEmailGroupUsersByGroupId(groupId).then(function (groupUsers) { + + if (!groupUsers || groupUsers.length === 0) { + dataTable.clear().draw(); + return; + } + + // Fetch user details for each group user + const userPromises = groupUsers.map(gu => + $.ajax({ + url: `/api/identity/users/${gu.userId}`, + method: 'GET' + }).then(function (user) { + return { + id: gu.id, + userId: gu.userId, + groupId: gu.groupId, + userName: user.userName || user.name, + email: user.email, + firstName: user.name ? user.name.split(' ')[0] : '', + lastName: user.surname || '' + }; + }).catch(function () { + return { + id: gu.id, + userId: gu.userId, + groupId: gu.groupId, + userName: 'Unknown User', + email: '', + firstName: '', + lastName: '' + }; + }) + ); + + Promise.all(userPromises).then(function (usersWithDetails) { + // Create unique list based on userId to prevent duplicates + const uniqueUsers = []; + const seenUserIds = new Set(); + + usersWithDetails.forEach(user => { + if (!seenUserIds.has(user.userId)) { + seenUserIds.add(user.userId); + uniqueUsers.push(user); + } + }); + + // Update DataTable with users + dataTable.clear(); + dataTable.rows.add(uniqueUsers); + dataTable.draw(); + }); + }).catch(function (error) { + console.error('Failed to load group users:', error); + abp.notify.error('Failed to load group users'); + }); + }, + +}; + +$(document).on('shown.bs.tab', '#nav-internal-email-group-tab', () => { + emailGroupsManager.init(); +}); \ No newline at end of file diff --git a/applications/Unity.GrantManager/modules/Unity.Payments/src/Unity.Payments.Application.Contracts/PaymentTags/IPaymentTagAppService.cs b/applications/Unity.GrantManager/modules/Unity.Payments/src/Unity.Payments.Application.Contracts/PaymentTags/IPaymentTagAppService.cs index 86f99e69b..ad0c7deb0 100644 --- a/applications/Unity.GrantManager/modules/Unity.Payments/src/Unity.Payments.Application.Contracts/PaymentTags/IPaymentTagAppService.cs +++ b/applications/Unity.GrantManager/modules/Unity.Payments/src/Unity.Payments.Application.Contracts/PaymentTags/IPaymentTagAppService.cs @@ -4,18 +4,15 @@ using Volo.Abp.Application.Dtos; using Volo.Abp.Application.Services; -namespace Unity.Payments.PaymentTags -{ - public interface IPaymentTagAppService : IApplicationService - { - Task> GetListAsync(); - Task> GetListWithPaymentRequestIdsAsync(List ids); - Task> AssignTagsAsync(AssignPaymentTagDto input); - Task GetPaymentTagsAsync(Guid id); +namespace Unity.Payments.PaymentTags; - Task> GetTagSummaryAsync(); - Task> RenameTagAsync(string originalTag, string replacementTag); - Task DeleteTagAsync(Guid id); - Task DeleteTagWithTagIdAsync(Guid tagId); - } +public interface IPaymentTagAppService : IApplicationService +{ + Task> GetListAsync(); + Task> GetListWithPaymentRequestIdsAsync(List ids); + Task> AssignTagsAsync(AssignPaymentTagDto input); + Task GetPaymentTagsAsync(Guid id); + Task> GetTagSummaryAsync(); + Task DeleteTagAsync(Guid id); + Task DeleteTagWithTagIdAsync(Guid tagId); } \ No newline at end of file diff --git a/applications/Unity.GrantManager/modules/Unity.Payments/src/Unity.Payments.Application/Domain/PaymentTags/PaymentTag.cs b/applications/Unity.GrantManager/modules/Unity.Payments/src/Unity.Payments.Application/Domain/PaymentTags/PaymentTag.cs index 87408b7cc..da6ffa368 100644 --- a/applications/Unity.GrantManager/modules/Unity.Payments/src/Unity.Payments.Application/Domain/PaymentTags/PaymentTag.cs +++ b/applications/Unity.GrantManager/modules/Unity.Payments/src/Unity.Payments.Application/Domain/PaymentTags/PaymentTag.cs @@ -9,8 +9,6 @@ public class PaymentTag : AuditedAggregateRoot, IMultiTenant { public Guid? TenantId { get; set; } public Guid PaymentRequestId { get; set; } - public string Text { get; set; } = string.Empty; - public Guid TagId { get; set; } public virtual Tag Tag diff --git a/applications/Unity.GrantManager/modules/Unity.Payments/src/Unity.Payments.Application/Events/RenameTagEto.cs b/applications/Unity.GrantManager/modules/Unity.Payments/src/Unity.Payments.Application/Events/RenameTagEto.cs deleted file mode 100644 index 0a14e85d6..000000000 --- a/applications/Unity.GrantManager/modules/Unity.Payments/src/Unity.Payments.Application/Events/RenameTagEto.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System; - -namespace Unity.Payments.Events; - -[Serializable] -public class RenameTagEto -{ - public required string originalTagName { get; set; } - public required string replacementTagName { get; set; } -} diff --git a/applications/Unity.GrantManager/modules/Unity.Payments/src/Unity.Payments.Application/Handlers/RenameTagHandler.cs b/applications/Unity.GrantManager/modules/Unity.Payments/src/Unity.Payments.Application/Handlers/RenameTagHandler.cs deleted file mode 100644 index 147a73e6b..000000000 --- a/applications/Unity.GrantManager/modules/Unity.Payments/src/Unity.Payments.Application/Handlers/RenameTagHandler.cs +++ /dev/null @@ -1,16 +0,0 @@ -using System.Threading.Tasks; -using Unity.Payments.Events; -using Unity.Payments.PaymentTags; -using Volo.Abp.DependencyInjection; -using Volo.Abp.EventBus; - -namespace Unity.Payments.Handlers; -public class RenameTagHandler(PaymentTagAppService paymentTagAppService) : - ILocalEventHandler, - ITransientDependency -{ - public async Task HandleEventAsync(RenameTagEto eventData) - { - await paymentTagAppService.RenameTagAsync(eventData.originalTagName, eventData.replacementTagName); - } -} diff --git a/applications/Unity.GrantManager/modules/Unity.Payments/src/Unity.Payments.Application/PaymentInfo/PaymentInfoAppService.cs b/applications/Unity.GrantManager/modules/Unity.Payments/src/Unity.Payments.Application/PaymentInfo/PaymentInfoAppService.cs index bf94bfc4f..89f28a80a 100644 --- a/applications/Unity.GrantManager/modules/Unity.Payments/src/Unity.Payments.Application/PaymentInfo/PaymentInfoAppService.cs +++ b/applications/Unity.GrantManager/modules/Unity.Payments/src/Unity.Payments.Application/PaymentInfo/PaymentInfoAppService.cs @@ -1,6 +1,9 @@ using Microsoft.AspNetCore.Authorization; using Microsoft.Extensions.Logging; using System; +using System.Collections.Generic; +using System.Linq; +using System.Text.Json; using System.Threading.Tasks; using Unity.Flex.WorksheetInstances; using Unity.Flex.Worksheets; @@ -17,11 +20,42 @@ public class PaymentInfoAppService(ILocalEventBus localEventBus) : PaymentsAppSe { public async Task UpdateAsync(Guid id, CreateUpdatePaymentInfoDto input) { - await PublishCustomFieldUpdatesAsync(id, FlexConsts.PaymentInfoUiAnchor, input); + // Handle custom fields for payment info + if (HasValue(input.CustomFields) && input.CorrelationId != Guid.Empty) + { + // Handle multiple worksheets + if (input.WorksheetIds?.Count > 0) + { + foreach (var worksheetId in input.WorksheetIds) + { + var worksheetCustomFields = ExtractCustomFieldsForWorksheet(input.CustomFields, worksheetId); + if (worksheetCustomFields.Count > 0) + { + var worksheetData = new CustomDataFieldDto + { + WorksheetId = worksheetId, + CustomFields = worksheetCustomFields, + CorrelationId = input.CorrelationId + }; + await PublishCustomFieldUpdatesAsync(id, FlexConsts.PaymentInfoUiAnchor, worksheetData); + } + } + } + // Fallback for single worksheet (backward compatibility) + else if (input.WorksheetId != Guid.Empty) + { + await PublishCustomFieldUpdatesAsync(id, FlexConsts.PaymentInfoUiAnchor, input); + } + } return new PaymentInfoDto(); } + private static bool HasValue(JsonElement element) + { + return element.ValueKind != JsonValueKind.Null && element.ValueKind != JsonValueKind.Undefined; + } + protected virtual async Task PublishCustomFieldUpdatesAsync(Guid applicationId, string uiAnchor, CustomDataFieldDto input) @@ -46,6 +80,24 @@ await localEventBus.PublishAsync(new PersistWorksheetIntanceValuesEto() Logger.LogError("Unable to resolve for version"); } } + } + + private static Dictionary ExtractCustomFieldsForWorksheet(dynamic customFields, Guid worksheetId) + { + var result = new Dictionary(); + var worksheetSuffix = $".{worksheetId}"; + + if (customFields is JsonElement jsonElement) + { + result = jsonElement.EnumerateObject() + .Where(property => property.Name.EndsWith(worksheetSuffix)) + .ToDictionary( + property => property.Name[..^worksheetSuffix.Length], + property => property.Value.ValueKind == JsonValueKind.String ? (object)property.Value.GetString()! : string.Empty + ); + } + + return result; } } } \ No newline at end of file diff --git a/applications/Unity.GrantManager/modules/Unity.Payments/src/Unity.Payments.Application/PaymentTags/PaymentTagAppService.cs b/applications/Unity.GrantManager/modules/Unity.Payments/src/Unity.Payments.Application/PaymentTags/PaymentTagAppService.cs index 50188c4ff..2c59147fb 100644 --- a/applications/Unity.GrantManager/modules/Unity.Payments/src/Unity.Payments.Application/PaymentTags/PaymentTagAppService.cs +++ b/applications/Unity.GrantManager/modules/Unity.Payments/src/Unity.Payments.Application/PaymentTags/PaymentTagAppService.cs @@ -107,53 +107,6 @@ public async Task> GetTagSummaryAsync() ); } - [Authorize(UnitySelector.SettingManagement.Tags.Update)] - public async Task> RenameTagAsync(string originalTag, string replacementTag) - { - Check.NotNullOrWhiteSpace(originalTag, nameof(originalTag)); - Check.NotNullOrWhiteSpace(replacementTag, nameof(replacementTag)); - - // Remove commas and trim whitespace from tags - originalTag = originalTag.Replace(",", string.Empty).Trim(); - replacementTag = replacementTag.Replace(",", string.Empty).Trim(); - - if (string.Equals(originalTag, replacementTag, StringComparison.InvariantCultureIgnoreCase)) - { - throw new BusinessException("Cannot update a tag to itself."); - } - - var paymentRequestTags = await _paymentTagRepository - .GetListAsync(e => e.Text.Contains(originalTag)); - - if (paymentRequestTags.Count == 0) - return []; - - var updatedTags = new List(paymentRequestTags.Count); - - foreach (var item in paymentRequestTags) - { - // Split and trim tags, use case-insensitive HashSet for matching - var tagSet = new HashSet( - item.Text.Split(',', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries), - StringComparer.InvariantCultureIgnoreCase); - - // Only replace if the original tag exists (case-insensitive) - if (tagSet.Remove(originalTag)) - { - tagSet.Add(replacementTag); // No effect if replacement already exists - item.Text = string.Join(',', tagSet.OrderBy(t => t, StringComparer.InvariantCultureIgnoreCase)); - updatedTags.Add(item); - } - } - - if (updatedTags.Count > 0) - { - await _paymentTagRepository.UpdateManyAsync(updatedTags, autoSave: true); - } - - return [.. updatedTags.Select(x => x.Id)]; - } - /// /// Deletes a tag from all application tags. Only whole-word tags are removed; substring matches are ignored. /// diff --git a/applications/Unity.GrantManager/modules/Unity.Payments/src/Unity.Payments.Web/Pages/PaymentApprovals/UpdatePaymentRequestStatus.cshtml.cs b/applications/Unity.GrantManager/modules/Unity.Payments/src/Unity.Payments.Web/Pages/PaymentApprovals/UpdatePaymentRequestStatus.cshtml.cs index fc55717f5..4df589584 100644 --- a/applications/Unity.GrantManager/modules/Unity.Payments/src/Unity.Payments.Web/Pages/PaymentApprovals/UpdatePaymentRequestStatus.cshtml.cs +++ b/applications/Unity.GrantManager/modules/Unity.Payments/src/Unity.Payments.Web/Pages/PaymentApprovals/UpdatePaymentRequestStatus.cshtml.cs @@ -194,11 +194,20 @@ private static PaymentRequestStatus GetNextStatus(PaymentRequestStatus status, P return PaymentRequestStatus.Submitted; } + if (status == PaymentRequestStatus.L3Pending && isApproval) + { + if (preventPayment) + { + return PaymentRequestStatus.FSB; + } + return PaymentRequestStatus.Submitted; + } + return status switch { PaymentRequestStatus.L1Pending => isApproval ? PaymentRequestStatus.L2Pending : PaymentRequestStatus.L1Declined, PaymentRequestStatus.L2Pending => PaymentRequestStatus.L2Declined, - PaymentRequestStatus.L3Pending => isApproval ? PaymentRequestStatus.Submitted : PaymentRequestStatus.L3Declined, + PaymentRequestStatus.L3Pending => PaymentRequestStatus.L3Declined, _ => request.ToStatus }; } 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 65fa8e4d4..ec8df337a 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 @@ -20,7 +20,9 @@ let formData = $("#paymentInfoForm").serializeArray(); let paymentInfoObj = {}; let formVersionId = $("#ApplicationFormVersionId").val(); - let worksheetId = $("#PaymentInfo_WorksheetId").val(); + // Check for worksheet scenario - multiple vs single + let multipleWorksheetsIds = $("#PaymentInfo_WorksheetIds").val(); + let singleWorksheetId = $("#PaymentInfo_WorksheetId").val(); $.each(formData, function (_, input) { if (typeof Flex === 'function' && Flex?.isCustomField(input)) { @@ -42,7 +44,15 @@ } paymentInfoObj['correlationId'] = formVersionId; - paymentInfoObj['worksheetId'] = worksheetId; + + // Set correct payload property based on worksheet scenario + if (multipleWorksheetsIds) { + // Multiple worksheets scenario - send as worksheetIds array + paymentInfoObj['worksheetIds'] = multipleWorksheetsIds.split(',').map(id => id.trim()); + } else if (singleWorksheetId) { + // Single worksheet scenario - send as worksheetId + paymentInfoObj['worksheetId'] = singleWorksheetId.trim(); + } updatePaymentInfo(applicationId, paymentInfoObj); }); diff --git a/applications/Unity.GrantManager/modules/Unity.Payments/src/Unity.Payments.Web/Views/Shared/Components/SupplierInfo/SupplierInfo.css b/applications/Unity.GrantManager/modules/Unity.Payments/src/Unity.Payments.Web/Views/Shared/Components/SupplierInfo/SupplierInfo.css index 5a198a248..0bedbd494 100644 --- a/applications/Unity.GrantManager/modules/Unity.Payments/src/Unity.Payments.Web/Views/Shared/Components/SupplierInfo/SupplierInfo.css +++ b/applications/Unity.GrantManager/modules/Unity.Payments/src/Unity.Payments.Web/Views/Shared/Components/SupplierInfo/SupplierInfo.css @@ -30,5 +30,5 @@ input[readonly] { background-color: var(--bc-colors-grey-hover) !important; opacity: var(--bs-btn-disabled-opacity); background-blend-mode: difference; - border: none !important; + border: var(--bs-border-width) solid var(--bs-border-color); } \ No newline at end of file diff --git a/applications/Unity.GrantManager/modules/Unity.Theme.UX2/src/Unity.Theme.UX2/wwwroot/themes/ux2/layout.css b/applications/Unity.GrantManager/modules/Unity.Theme.UX2/src/Unity.Theme.UX2/wwwroot/themes/ux2/layout.css index 3d7716128..ccb25972f 100644 --- a/applications/Unity.GrantManager/modules/Unity.Theme.UX2/src/Unity.Theme.UX2/wwwroot/themes/ux2/layout.css +++ b/applications/Unity.GrantManager/modules/Unity.Theme.UX2/src/Unity.Theme.UX2/wwwroot/themes/ux2/layout.css @@ -501,7 +501,7 @@ input.form-control-currency { background-color: var(--bc-colors-grey-hover) !important; opacity: var(--bs-btn-disabled-opacity); background-blend-mode: difference; - border: none !important; + border: var(--bs-border-width) solid var(--bs-border-color); } input.form-control-currency:disabled { @@ -510,7 +510,7 @@ input.form-control-currency { background-color: var(--bc-colors-grey-hover) !important; opacity: var(--bs-btn-disabled-opacity); background-blend-mode: difference; - border: var(--bs-border-width) solid var(--bs-border-color) !important; + border: var(--bs-border-width) solid var(--bs-border-color); } textarea.form-control:disabled { @@ -798,7 +798,7 @@ input.form-control.disabled:read-only, textarea.form-control.disabled:read-only, background-color: var(--bc-colors-grey-hover) !important; opacity: var(--bs-btn-disabled-opacity); background-blend-mode: difference; - border: none !important; + border: var(--bs-border-width) solid var(--bs-border-color); } diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/ApplicationForms/ApplicationFormDetailsDto.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/ApplicationForms/ApplicationFormDetailsDto.cs new file mode 100644 index 000000000..98089fdc1 --- /dev/null +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/ApplicationForms/ApplicationFormDetailsDto.cs @@ -0,0 +1,14 @@ +using System; + +namespace Unity.GrantManager.ApplicationForms; + +public class ApplicationFormDetailsDto +{ + public Guid ApplicationId { get; set; } + public Guid ApplicationFormId { get; set; } + public string ApplicationFormName { get; set; } = string.Empty; + public string ApplicationFormDescription { get; set; } = string.Empty; + public string ApplicationFormCategory { get; set; } = string.Empty; + public Guid ApplicationFormVersionId { get; set; } + public int ApplicationFormVersion { get; set; } +} diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/ApplicationForms/IApplicationFormAppService.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/ApplicationForms/IApplicationFormAppService.cs index 285357a88..b1242e3f0 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/ApplicationForms/IApplicationFormAppService.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/ApplicationForms/IApplicationFormAppService.cs @@ -20,5 +20,6 @@ public interface IApplicationFormAppService : ICrudAppService< Task PatchOtherConfig(Guid id, OtherConfigDto config); Task GetFormPaymentApprovalThresholdByApplicationIdAsync(Guid applicationId); Task GetFormPreventPaymentStatusByApplicationId(Guid applicationId); + Task GetFormDetailsByApplicationIdAsync(Guid applicationId); } } diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/GrantApplications/GrantApplicationDto.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/GrantApplications/GrantApplicationDto.cs index 6be96816b..cef1eaff1 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/GrantApplications/GrantApplicationDto.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/GrantApplications/GrantApplicationDto.cs @@ -5,6 +5,7 @@ namespace Unity.GrantManager.GrantApplications; +// NOTE: Removing properties from this class will impact Email Notification Templates public class GrantApplicationDto : AuditedEntityDto { public int RowCount { get; set; } = 0; diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/GrantApplications/IApplicationTagsService.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/GrantApplications/IApplicationTagsService.cs index bcc2aa109..6fa861baf 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/GrantApplications/IApplicationTagsService.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/GrantApplications/IApplicationTagsService.cs @@ -10,15 +10,9 @@ public interface IApplicationTagsService : IApplicationService { Task> GetListAsync(); Task> GetListWithApplicationIdsAsync(List ids); - Task> AssignTagsAsync(AssignApplicationTagsDto input); - Task> GetApplicationTagsAsync(Guid id); - Task> GetTagSummaryAsync(); - Task> RenameTagAsync(string originalTag, string replacementTag); - Task RenameTagGlobalAsync(string originalTag, string replacementTag); Task DeleteTagWithTagIdAsync(Guid id); Task DeleteTagAsync(Guid id); - } diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/Locality/IElectoralDistrictService.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/Locality/IElectoralDistrictService.cs index 57977121c..4ce380569 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/Locality/IElectoralDistrictService.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/Locality/IElectoralDistrictService.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.Threading.Tasks; using Volo.Abp.Application.Services; @@ -7,5 +8,6 @@ namespace Unity.GrantManager.Locality; public interface IElectoralDistrictService : IApplicationService { Task> GetListAsync(); + Task RetroFillElectoralDistricts(Guid tenantId); } 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 afb6b1cf3..a4d4cb7cd 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/ApplicationForms/ApplicationFormAppService.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/ApplicationForms/ApplicationFormAppService.cs @@ -34,13 +34,15 @@ public class ApplicationFormAppService : private readonly IApplicationFormVersionRepository _applicationFormVersionRepository; private readonly IGrantApplicationAppService _applicationService; private readonly IRepository _applicationFormRepository; + private readonly IApplicationFormSubmissionRepository _applicationFormSubmissionRepository; public ApplicationFormAppService(IRepository repository, IStringEncryptionService stringEncryptionService, IApplicationFormVersionAppService applicationFormVersionAppService, IApplicationFormVersionRepository applicationFormVersionRepository, IGrantApplicationAppService applicationService, - IFormsApiService formsApiService) + IFormsApiService formsApiService, + IApplicationFormSubmissionRepository applicationFormSubmissionRepository) : base(repository) { _stringEncryptionService = stringEncryptionService; @@ -49,6 +51,7 @@ public ApplicationFormAppService(IRepository repository, _applicationFormVersionRepository = applicationFormVersionRepository; _applicationFormRepository = repository; _applicationService = applicationService; + _applicationFormSubmissionRepository = applicationFormSubmissionRepository; } [Authorize(GrantManagerPermissions.ApplicationForms.Default)] @@ -189,4 +192,20 @@ public async Task SavePaymentConfiguration(FormPaymentConfigurationDto dto) ApplicationForm appForm = await _applicationFormRepository.GetAsync(formId); return appForm.PaymentApprovalThreshold; } + + public async Task GetFormDetailsByApplicationIdAsync(Guid applicationId) + { + var formDetails = await _applicationFormSubmissionRepository.GetFormDetailsByApplicationIdAsync(applicationId); + + return new ApplicationFormDetailsDto + { + ApplicationId = formDetails.ApplicationId, + ApplicationFormId = formDetails.ApplicationFormId, + ApplicationFormName = formDetails.ApplicationFormName, + ApplicationFormDescription = formDetails.ApplicationFormDescription, + ApplicationFormCategory = formDetails.ApplicationFormCategory, + ApplicationFormVersionId = formDetails.ApplicationFormVersionId, + ApplicationFormVersion = formDetails.ApplicationFormVersion + }; + } } diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Dashboard/DashboardAppService.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Dashboard/DashboardAppService.cs index ed12f9ca4..9ae027115 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Dashboard/DashboardAppService.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Dashboard/DashboardAppService.cs @@ -10,6 +10,7 @@ using Unity.GrantManager.Intakes; using Volo.Abp.Application.Services; using Volo.Abp.Domain.Repositories; +using Microsoft.AspNetCore.Mvc; namespace Unity.GrantManager.Dashboard; @@ -44,6 +45,7 @@ IIntakeRepository intakeRepository } [Authorize(GrantApplicationPermissions.Dashboard.EconomicRegionCount)] + [HttpPost] public virtual async Task> GetEconomicRegionCountAsync(DashboardParametersDto dashboardParams) { var parameters = PrepareParameters(dashboardParams); @@ -70,6 +72,7 @@ public virtual async Task> GetEconomicRegionCountAsyn } [Authorize(GrantApplicationPermissions.Dashboard.ApplicationStatusCount)] + [HttpPost] public virtual async Task> GetApplicationStatusCountAsync(DashboardParametersDto dashboardParams) { var parameters = PrepareParameters(dashboardParams); @@ -96,6 +99,7 @@ public virtual async Task> GetApplicationStatusCou } [Authorize(GrantApplicationPermissions.Dashboard.ApplicationTagsCount)] + [HttpPost] public virtual async Task> GetApplicationTagsCountAsync(DashboardParametersDto dashboardParams) { var parameters = PrepareParameters(dashboardParams); @@ -124,6 +128,7 @@ join tag in tagQueryable on baseQuery.Application.Id equals tag.ApplicationId } [Authorize(GrantApplicationPermissions.Dashboard.RequestedAmountPerSubsector)] + [HttpPost] public virtual async Task> GetRequestedAmountPerSubsectorAsync(DashboardParametersDto dashboardParams) { var parameters = PrepareParameters(dashboardParams); @@ -154,6 +159,7 @@ join applicant in await _applicantRepository.GetQueryableAsync() on baseQuery.Ap } [Authorize(GrantApplicationPermissions.Dashboard.ApplicationAssigneeCount)] + [HttpPost] public virtual async Task> GetApplicationAssigneeCountAsync(DashboardParametersDto dashboardParams) { var parameters = PrepareParameters(dashboardParams); @@ -186,6 +192,7 @@ where parameters.Assignees.Contains(baseQuery.AppAssignee.AssigneeId.ToString()) } [Authorize(GrantApplicationPermissions.Dashboard.RequestApprovedCount)] + [HttpPost] public virtual async Task> GetRequestApprovedCountAsync(DashboardParametersDto dashboardParams) { var parameters = PrepareParameters(dashboardParams); diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/GrantApplications/ApplicationApplicantAppService.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/GrantApplications/ApplicationApplicantAppService.cs index 2177a6bdf..d0a1d6403 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/GrantApplications/ApplicationApplicantAppService.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/GrantApplications/ApplicationApplicantAppService.cs @@ -1,30 +1,30 @@ -using Microsoft.AspNetCore.Authorization; -using Microsoft.Extensions.Logging; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text.Json; -using System.Threading.Tasks; -using Unity.Flex.WorksheetInstances; -using Unity.Flex.Worksheets; -using Unity.GrantManager.Applications; -using Unity.GrantManager.Flex; -using Unity.Modules.Shared; -using Unity.Modules.Shared.Correlation; -using Unity.Modules.Shared.Utils; -using Volo.Abp.Domain.Entities; -using Volo.Abp.Domain.Repositories; -using Volo.Abp.EventBus.Local; - -namespace Unity.GrantManager.GrantApplications; - -[Authorize] -public class ApplicationApplicantAppService( - IApplicantRepository applicantRepository, - IApplicationRepository applicationRepository, - IApplicantAgentRepository applicantAgentRepository, - IApplicantAddressRepository applicantAddressRepository, - ILocalEventBus localEventBus) : GrantManagerAppService, IApplicationApplicantAppService +using Microsoft.AspNetCore.Authorization; +using Microsoft.Extensions.Logging; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text.Json; +using System.Threading.Tasks; +using Unity.Flex.WorksheetInstances; +using Unity.Flex.Worksheets; +using Unity.GrantManager.Applications; +using Unity.GrantManager.Flex; +using Unity.Modules.Shared; +using Unity.Modules.Shared.Correlation; +using Unity.Modules.Shared.Utils; +using Volo.Abp.Domain.Entities; +using Volo.Abp.Domain.Repositories; +using Volo.Abp.EventBus.Local; + +namespace Unity.GrantManager.GrantApplications; + +[Authorize] +public class ApplicationApplicantAppService( + IApplicantRepository applicantRepository, + IApplicationRepository applicationRepository, + IApplicantAgentRepository applicantAgentRepository, + IApplicantAddressRepository applicantAddressRepository, + ILocalEventBus localEventBus) : GrantManagerAppService, IApplicationApplicantAppService { [Authorize(UnitySelector.Applicant.Default)] public async Task GetApplicantInfoTabAsync(Guid applicationId) @@ -38,10 +38,10 @@ public async Task GetApplicantInfoTabAsync(Guid applicationId) var applicantInfoDto = ObjectMapper.Map(application); applicantInfoDto.ApplicationId = application.Id; - applicantInfoDto.ApplicantId = application.ApplicantId; + applicantInfoDto.ApplicantId = application.ApplicantId; applicantInfoDto.ApplicationFormId = application.ApplicationFormId; - applicantInfoDto.ApplicationReferenceNo = application.ReferenceNo; + applicantInfoDto.ApplicationReferenceNo = application.ReferenceNo; applicantInfoDto.ApplicantName = application.Applicant?.ApplicantName ?? string.Empty; applicantInfoDto.ApplicationStatusCode = application.ApplicationStatus.StatusCode; @@ -93,53 +93,53 @@ public async Task GetApplicantInfoTabAsync(Guid applicationId) [Obsolete("Use GetApplicantInfoTabAsync instead.")] [Authorize] - public async Task GetByApplicationIdAsync(Guid applicationId) - { - var applicantInfo = await applicationRepository.WithBasicDetailsAsync(applicationId); - if (applicantInfo == null) return new ApplicationApplicantInfoDto(); - - return new ApplicationApplicantInfoDto() - { - ApplicantId = applicantInfo.Applicant.Id, - ApplicationFormId = applicantInfo.ApplicationFormId, - ApplicantName = applicantInfo.Applicant?.ApplicantName ?? string.Empty, - ApplicationReferenceNo = applicantInfo.ReferenceNo, - ApplicationStatus = applicantInfo.ApplicationStatus.InternalStatus, - ApplicationStatusCode = applicantInfo.ApplicationStatus.StatusCode, - - OrganizationName = applicantInfo.Applicant?.OrgName ?? string.Empty, - OrganizationSize = applicantInfo.Applicant?.OrganizationSize ?? string.Empty, - OrganizationType = applicantInfo.Applicant?.OrganizationType ?? string.Empty, - OrgNumber = applicantInfo.Applicant?.OrgNumber ?? string.Empty, - OrgStatus = applicantInfo.Applicant?.OrgStatus ?? string.Empty, - NonRegOrgName = applicantInfo.Applicant?.NonRegOrgName ?? string.Empty, - - Sector = applicantInfo.Applicant?.Sector ?? string.Empty, - SectorSubSectorIndustryDesc = applicantInfo.Applicant?.SectorSubSectorIndustryDesc ?? string.Empty, - SubSector = applicantInfo.Applicant?.SubSector ?? string.Empty, - RedStop = applicantInfo.Applicant?.RedStop ?? false, - IndigenousOrgInd = applicantInfo.Applicant?.IndigenousOrgInd ?? string.Empty, - UnityApplicantId = applicantInfo.Applicant?.UnityApplicantId ?? string.Empty, - FiscalDay = applicantInfo.Applicant?.FiscalDay.ToString() ?? string.Empty, - FiscalMonth = applicantInfo.Applicant?.FiscalMonth ?? string.Empty, - - SigningAuthorityBusinessPhone = applicantInfo.SigningAuthorityBusinessPhone ?? string.Empty, - SigningAuthorityCellPhone = applicantInfo.SigningAuthorityCellPhone ?? string.Empty, - SigningAuthorityEmail = applicantInfo.SigningAuthorityEmail ?? string.Empty, - SigningAuthorityFullName = applicantInfo.SigningAuthorityFullName ?? string.Empty, - SigningAuthorityTitle = applicantInfo.SigningAuthorityTitle ?? string.Empty, - - ContactFullName = applicantInfo.ApplicantAgent?.Name ?? string.Empty, - ContactTitle = applicantInfo.ApplicantAgent?.Title ?? string.Empty, - ContactEmail = applicantInfo.ApplicantAgent?.Email ?? string.Empty, - ContactBusinessPhone = applicantInfo.ApplicantAgent?.Phone ?? string.Empty, - ContactCellPhone = applicantInfo.ApplicantAgent?.Phone2 ?? string.Empty, - - ApplicantAddresses = ObjectMapper.Map, List>(applicantInfo.Applicant?.ApplicantAddresses?.ToList() ?? []), - ElectoralDistrict = applicantInfo.Applicant?.ElectoralDistrict ?? string.Empty - }; - } - + public async Task GetByApplicationIdAsync(Guid applicationId) + { + var applicantInfo = await applicationRepository.WithBasicDetailsAsync(applicationId); + if (applicantInfo == null) return new ApplicationApplicantInfoDto(); + + return new ApplicationApplicantInfoDto() + { + ApplicantId = applicantInfo.Applicant.Id, + ApplicationFormId = applicantInfo.ApplicationFormId, + ApplicantName = applicantInfo.Applicant?.ApplicantName ?? string.Empty, + ApplicationReferenceNo = applicantInfo.ReferenceNo, + ApplicationStatus = applicantInfo.ApplicationStatus.InternalStatus, + ApplicationStatusCode = applicantInfo.ApplicationStatus.StatusCode, + + OrganizationName = applicantInfo.Applicant?.OrgName ?? string.Empty, + OrganizationSize = applicantInfo.Applicant?.OrganizationSize ?? string.Empty, + OrganizationType = applicantInfo.Applicant?.OrganizationType ?? string.Empty, + OrgNumber = applicantInfo.Applicant?.OrgNumber ?? string.Empty, + OrgStatus = applicantInfo.Applicant?.OrgStatus ?? string.Empty, + NonRegOrgName = applicantInfo.Applicant?.NonRegOrgName ?? string.Empty, + + Sector = applicantInfo.Applicant?.Sector ?? string.Empty, + SectorSubSectorIndustryDesc = applicantInfo.Applicant?.SectorSubSectorIndustryDesc ?? string.Empty, + SubSector = applicantInfo.Applicant?.SubSector ?? string.Empty, + RedStop = applicantInfo.Applicant?.RedStop ?? false, + IndigenousOrgInd = applicantInfo.Applicant?.IndigenousOrgInd ?? string.Empty, + UnityApplicantId = applicantInfo.Applicant?.UnityApplicantId ?? string.Empty, + FiscalDay = applicantInfo.Applicant?.FiscalDay.ToString() ?? string.Empty, + FiscalMonth = applicantInfo.Applicant?.FiscalMonth ?? string.Empty, + + SigningAuthorityBusinessPhone = applicantInfo.SigningAuthorityBusinessPhone ?? string.Empty, + SigningAuthorityCellPhone = applicantInfo.SigningAuthorityCellPhone ?? string.Empty, + SigningAuthorityEmail = applicantInfo.SigningAuthorityEmail ?? string.Empty, + SigningAuthorityFullName = applicantInfo.SigningAuthorityFullName ?? string.Empty, + SigningAuthorityTitle = applicantInfo.SigningAuthorityTitle ?? string.Empty, + + ContactFullName = applicantInfo.ApplicantAgent?.Name ?? string.Empty, + ContactTitle = applicantInfo.ApplicantAgent?.Title ?? string.Empty, + ContactEmail = applicantInfo.ApplicantAgent?.Email ?? string.Empty, + ContactBusinessPhone = applicantInfo.ApplicantAgent?.Phone ?? string.Empty, + ContactCellPhone = applicantInfo.ApplicantAgent?.Phone2 ?? string.Empty, + + ApplicantAddresses = ObjectMapper.Map, List>(applicantInfo.Applicant?.ApplicantAddresses?.ToList() ?? []), + ElectoralDistrict = applicantInfo.Applicant?.ElectoralDistrict ?? string.Empty + }; + } + [Authorize(UnitySelector.Applicant.UpdatePolicy)] public async Task UpdatePartialApplicantInfoAsync(Guid applicationId, PartialUpdateDto input) { @@ -200,15 +200,42 @@ public async Task UpdatePartialApplicantInfoAsync(Guid appl } //-- APPLICANT INFO CUSTOM FIELDS - if (input.Data.CustomFields?.ValueKind != JsonValueKind.Null && input.Data.WorksheetId != Guid.Empty && input.Data.CorrelationId != Guid.Empty) + if (HasValue(input.Data.CustomFields) && input.Data.CorrelationId != Guid.Empty) { - await PublishCustomFieldUpdatesAsync(application.Id, FlexConsts.ApplicantInfoUiAnchor, input.Data); + // Handle multiple worksheets + if (input.Data.WorksheetIds?.Count > 0) + { + foreach (var worksheetId in input.Data.WorksheetIds) + { + var worksheetCustomFields = ExtractCustomFieldsForWorksheet(input.Data.CustomFields, worksheetId); + if (worksheetCustomFields.Count > 0) + { + var worksheetData = new CustomDataFieldDto + { + WorksheetId = worksheetId, + CustomFields = worksheetCustomFields, + CorrelationId = input.Data.CorrelationId + }; + await PublishCustomFieldUpdatesAsync(application.Id, FlexConsts.ApplicantInfoUiAnchor, worksheetData); + } + } + } + // Fallback for single worksheet (backward compatibility) + else if (input.Data.WorksheetId != Guid.Empty) + { + await PublishCustomFieldUpdatesAsync(application.Id, FlexConsts.ApplicantInfoUiAnchor, input.Data); + } } var updatedApplication = await applicationRepository.UpdateAsync(application); return ObjectMapper.Map(updatedApplication); } + private static bool HasValue(JsonElement? element) + { + return element?.ValueKind != JsonValueKind.Null && element?.ValueKind != JsonValueKind.Undefined; + } + /// /// Updates the Applicant Summary information for the given applicant while ignoring null values unless explicitly specified in modifiedFields. /// @@ -216,8 +243,8 @@ public async Task UpdatePartialApplicantInfoAsync(Guid appl /// /// /// - /// - [Authorize(UnitySelector.Applicant.Summary.Update)] + /// + [Authorize(UnitySelector.Applicant.Summary.Update)] protected internal async Task PartialUpdateApplicantSummaryInfoAsync(Guid applicantId, UpdateApplicantSummaryDto applicantSummary, List? modifiedFields = default) { var applicant = await applicantRepository.GetAsync(applicantId) ?? throw new EntityNotFoundException(); @@ -231,26 +258,26 @@ public async Task UpdatePartialApplicantInfoAsync(Guid appl /// /// /// - /// - private async Task InternalPartialUpdateApplicantSummaryInfoAsync(Applications.Applicant applicant, UpdateApplicantSummaryDto applicantSummary, List? modifiedFields = default) - { - ObjectMapper.Map(applicantSummary, applicant); - - var modifiedSummaryFields = modifiedFields? - .Where(f => f.StartsWith("ApplicantSummary.", StringComparison.Ordinal)) - .Select(f => f["ApplicantSummary.".Length..]).ToList() ?? []; - - if (modifiedSummaryFields != null && modifiedSummaryFields.Count > 0) // Ensure modifiedFields is not null - { - // Handle null values for changed fields - PropertyHelper.ApplyNullValuesFromDto( - applicantSummary, - applicant, - modifiedSummaryFields ?? []); // Provide a fallback for null - } - - return await applicantRepository.UpdateAsync(applicant); - } + /// + private async Task InternalPartialUpdateApplicantSummaryInfoAsync(Applications.Applicant applicant, UpdateApplicantSummaryDto applicantSummary, List? modifiedFields = default) + { + ObjectMapper.Map(applicantSummary, applicant); + + var modifiedSummaryFields = modifiedFields? + .Where(f => f.StartsWith("ApplicantSummary.", StringComparison.Ordinal)) + .Select(f => f["ApplicantSummary.".Length..]).ToList() ?? []; + + if (modifiedSummaryFields != null && modifiedSummaryFields.Count > 0) // Ensure modifiedFields is not null + { + // Handle null values for changed fields + PropertyHelper.ApplyNullValuesFromDto( + applicantSummary, + applicant, + modifiedSummaryFields ?? []); // Provide a fallback for null + } + + return await applicantRepository.UpdateAsync(applicant); + } /// /// Creates or updates the appicant agent (contact info) for the given applicant. Ignores null values unless explicitly specified in modifiedFields. @@ -258,14 +285,14 @@ public async Task UpdatePartialApplicantInfoAsync(Guid appl /// /// /// - [Authorize(UnitySelector.Applicant.Contact.Update)] - protected internal async Task CreateOrUpdateContactInfoAsync(Guid applicationId, Guid applicantId, ContactInfoDto contactInfo) + [Authorize(UnitySelector.Applicant.Contact.Update)] + protected internal async Task CreateOrUpdateContactInfoAsync(Guid applicationId, Guid applicantId, ContactInfoDto contactInfo) { - var applicantAgent = await applicantAgentRepository.FirstOrDefaultAsync(a => a.ApplicantId == applicantId && a.ApplicationId == applicationId) - ?? new ApplicantAgent - { - ApplicantId = applicantId, - ApplicationId = applicationId, + var applicantAgent = await applicantAgentRepository.FirstOrDefaultAsync(a => a.ApplicantId == applicantId && a.ApplicationId == applicationId) + ?? new ApplicantAgent + { + ApplicantId = applicantId, + ApplicationId = applicationId, }; ObjectMapper.Map(contactInfo, applicantAgent); @@ -292,12 +319,12 @@ protected internal async Task CreateOrUpdateApplicantAddress(Guid applicationId, { var applicantAddresses = await applicantAddressRepository.FindByApplicantIdAndApplicationIdAsync(applicantId, applicationId); - ApplicantAddress? dbAddress = applicantAddresses.FirstOrDefault(a => a.AddressType == updatedAddress.AddressType) - ?? new ApplicantAddress - { - ApplicantId = applicantId, - AddressType = updatedAddress.AddressType, - ApplicationId = applicationId, + ApplicantAddress? dbAddress = applicantAddresses.FirstOrDefault(a => a.AddressType == updatedAddress.AddressType) + ?? new ApplicantAddress + { + ApplicantId = applicantId, + AddressType = updatedAddress.AddressType, + ApplicationId = applicationId, }; ObjectMapper.Map(updatedAddress, dbAddress); @@ -310,8 +337,8 @@ protected internal async Task CreateOrUpdateApplicantAddress(Guid applicationId, { await applicantAddressRepository.UpdateAsync(dbAddress); } - } - + } + protected virtual async Task PublishCustomFieldUpdatesAsync(Guid applicationId, string uiAnchor, CustomDataFieldDto input) { if (await FeatureChecker.IsEnabledAsync("Unity.Flex")) @@ -334,8 +361,8 @@ await localEventBus.PublishAsync(new PersistWorksheetIntanceValuesEto() Logger.LogError("Unable to resolve for version"); } } - } - + } + public async Task GetSupplierNameMatchesCheck(Guid applicantId, string? supplierName) { if (string.IsNullOrWhiteSpace(supplierName)) @@ -357,7 +384,19 @@ public async Task GetSupplierNameMatchesCheck(Guid applicantId, string? su return true; } - return string.Equals(normalizedSupplierName, organizationName, StringComparison.OrdinalIgnoreCase) + return string.Equals(normalizedSupplierName, organizationName, StringComparison.OrdinalIgnoreCase) || string.Equals(normalizedSupplierName, nonRegisteredOrganizationName, StringComparison.OrdinalIgnoreCase); - } -} + } + + private static Dictionary ExtractCustomFieldsForWorksheet(JsonElement customFields, Guid worksheetId) + { + var worksheetSuffix = $".{worksheetId}"; + + return customFields.EnumerateObject() + .Where(property => property.Name.EndsWith(worksheetSuffix)) + .ToDictionary( + property => property.Name[..^worksheetSuffix.Length], + property => property.Value.ValueKind == JsonValueKind.String ? (object)property.Value.GetString()! : string.Empty + ); + } +} diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/GrantApplications/ApplicationTagsAppService.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/GrantApplications/ApplicationTagsAppService.cs index 2512b3684..f4b733877 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/GrantApplications/ApplicationTagsAppService.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/GrantApplications/ApplicationTagsAppService.cs @@ -114,85 +114,6 @@ public async Task> GetTagSummaryAsync() ); } - /// - /// Renames a tag across all application tags, replacing the original tag with the replacement tag. - /// Only whole-word tags are replaced; substring matches are ignored. - /// Throws a BusinessException if the original and replacement tags are the same. - /// - /// The tag to be replaced. - /// The new tag to use as a replacement. - /// A list of IDs for the ApplicationTags entities that were updated. - /// Thrown if the original and replacement tags are the same. - [Authorize(UnitySelector.SettingManagement.Tags.Update)] - public async Task> RenameTagAsync(string originalTag, string replacementTag) - { - Check.NotNullOrWhiteSpace(originalTag, nameof(originalTag)); - Check.NotNullOrWhiteSpace(replacementTag, nameof(replacementTag)); - - // Remove commas and trim whitespace from tags - originalTag = originalTag.Replace(",", string.Empty).Trim(); - replacementTag = replacementTag.Replace(",", string.Empty).Trim(); - - if (string.Equals(originalTag, replacementTag, StringComparison.InvariantCultureIgnoreCase)) - { - throw new BusinessException("Cannot update a tag to itself."); - } - - var applicationTags = await _applicationTagsRepository - .GetListAsync(e => e.Tag.Name.Contains(originalTag)); - - if (applicationTags.Count == 0) - return []; - - var updatedTags = new List(applicationTags.Count); - - foreach (var item in applicationTags) - { - // Split and trim tags, use case-insensitive HashSet for matching - var tagSet = new HashSet( - item.Tag.Name.Split(',', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries), - StringComparer.InvariantCultureIgnoreCase); - - // Only replace if the original tag exists (case-insensitive) - if (tagSet.Remove(originalTag)) - { - tagSet.Add(replacementTag); // No effect if replacement already exists - item.Tag.Name = string.Join(',', tagSet.OrderBy(t => t, StringComparer.InvariantCultureIgnoreCase)); - updatedTags.Add(item); - } - } - - if (updatedTags.Count > 0) - { - await _applicationTagsRepository.UpdateManyAsync(updatedTags, autoSave: true); - } - - return [.. updatedTags.Select(x => x.Id)]; - } - - /// - /// Deletes a tag from all applications and payment requests. - /// - /// String of tag to be deleted. - [Authorize(UnitySelector.SettingManagement.Tags.Update)] - public virtual async Task RenameTagGlobalAsync(string originalTag, string replacementTag) - { - Check.NotNullOrWhiteSpace(originalTag, nameof(originalTag)); - Check.NotNullOrWhiteSpace(replacementTag, nameof(replacementTag)); - - // NOTE: Unable to get the MIN of the MaxRenameLength for both Application and Payments. Must get on front-end by 2 API calls. - // May result in one EntityType tag renaming with the other failing in rare cases. - - await RenameTagAsync(originalTag, replacementTag); - await _localEventBus.PublishAsync( - new RenameTagEto - { - originalTagName = originalTag, - replacementTagName = replacementTag - } - ); - } - /// /// Deletes a tag from all application tags. Only whole-word tags are removed; substring matches are ignored. /// 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 20cd5a8a1..4690d58bf 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/GrantApplications/GrantApplicationAppService.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/GrantApplications/GrantApplicationAppService.cs @@ -10,6 +10,7 @@ using System.Collections.Generic; using System.Diagnostics; using System.Linq; +using System.Text.Json; using System.Threading.Tasks; using Unity.Flex.WorksheetInstances; using Unity.Flex.Worksheets; @@ -22,14 +23,12 @@ using Unity.GrantManager.Flex; using Unity.GrantManager.Identity; using Unity.GrantManager.Payments; -using Unity.GrantManager.Permissions; using Unity.GrantManager.Zones; using Unity.Modules.Shared; using Unity.Modules.Shared.Correlation; using Unity.Payments.Domain.PaymentRequests; using Unity.Payments.Enums; using Unity.Payments.PaymentRequests; -using Unity.Payments.Permissions; using Volo.Abp; using Volo.Abp.Application.Dtos; using Volo.Abp.Authorization; @@ -223,6 +222,7 @@ private static GrantApplicationAssigneeDto BuildApplicationOwner(Person? applica public async Task GetAsync(Guid id) { + // NOTE: Changes to this method can impact Email Notification Templates var application = await _applicationRepository.GetWithFullDetailsByIdAsync(id); if (application == null) return new GrantApplicationDto(); @@ -348,7 +348,33 @@ public async Task UpdateAssessmentResultsAsync(Guid id, Cre } } - await PublishCustomFieldUpdatesAsync(application.Id, FlexConsts.AssessmentInfoUiAnchor, input); + // Handle custom fields for assessment info + if (HasValue(input.CustomFields) && input.CorrelationId != Guid.Empty) + { + // Handle multiple worksheets + if (input.WorksheetIds?.Count > 0) + { + foreach (var worksheetId in input.WorksheetIds) + { + var worksheetCustomFields = ExtractCustomFieldsForWorksheet(input.CustomFields, worksheetId); + if (worksheetCustomFields.Count > 0) + { + var worksheetData = new CustomDataFieldDto + { + WorksheetId = worksheetId, + CustomFields = worksheetCustomFields, + CorrelationId = input.CorrelationId + }; + await PublishCustomFieldUpdatesAsync(application.Id, FlexConsts.AssessmentInfoUiAnchor, worksheetData); + } + } + } + // Fallback for single worksheet (backward compatibility) + else if (input.WorksheetId != Guid.Empty) + { + await PublishCustomFieldUpdatesAsync(application.Id, FlexConsts.AssessmentInfoUiAnchor, input); + } + } await _applicationRepository.UpdateAsync(application); @@ -462,7 +488,33 @@ public async Task UpdateProjectInfoAsync(Guid id, CreateUpd application.RegionalDistrict = input.RegionalDistrict; application.Place = input.Place; - await PublishCustomFieldUpdatesAsync(application.Id, FlexConsts.ProjectInfoUiAnchor, input); + // Handle custom fields for project info + if (HasValue(input.CustomFields) && input.CorrelationId != Guid.Empty) + { + // Handle multiple worksheets + if (input.WorksheetIds?.Count > 0) + { + foreach (var worksheetId in input.WorksheetIds) + { + var worksheetCustomFields = ExtractCustomFieldsForWorksheet(input.CustomFields, worksheetId); + if (worksheetCustomFields.Count > 0) + { + var worksheetData = new CustomDataFieldDto + { + WorksheetId = worksheetId, + CustomFields = worksheetCustomFields, + CorrelationId = input.CorrelationId + }; + await PublishCustomFieldUpdatesAsync(application.Id, FlexConsts.ProjectInfoUiAnchor, worksheetData); + } + } + } + // Fallback for single worksheet (backward compatibility) + else if (input.WorksheetId != Guid.Empty) + { + await PublishCustomFieldUpdatesAsync(application.Id, FlexConsts.ProjectInfoUiAnchor, input); + } + } await _applicationRepository.UpdateAsync(application); @@ -515,9 +567,31 @@ public async Task UpdatePartialProjectInfoAsync(Guid id, Pa application.UpdatePercentageTotalProjectBudget(); // Add custom worksheet data - if (input.Data.CustomFields is not null && input.Data.WorksheetId != Guid.Empty && input.Data.CorrelationId != Guid.Empty) + if (HasValue(input.Data.CustomFields) && input.Data.CorrelationId != Guid.Empty) { - await PublishCustomFieldUpdatesAsync(application.Id, FlexConsts.ProjectInfoUiAnchor, input.Data); + // Handle multiple worksheets + if (input.Data.WorksheetIds?.Count > 0) + { + foreach (var worksheetId in input.Data.WorksheetIds) + { + var worksheetCustomFields = ExtractCustomFieldsForWorksheet(input.Data.CustomFields, worksheetId); + if (worksheetCustomFields.Count > 0) + { + var worksheetData = new CustomDataFieldDto + { + WorksheetId = worksheetId, + CustomFields = worksheetCustomFields, + CorrelationId = input.Data.CorrelationId + }; + await PublishCustomFieldUpdatesAsync(application.Id, FlexConsts.ProjectInfoUiAnchor, worksheetData); + } + } + } + // Fallback for single worksheet (backward compatibility) + else if (input.Data.WorksheetId != Guid.Empty) + { + await PublishCustomFieldUpdatesAsync(application.Id, FlexConsts.ProjectInfoUiAnchor, input.Data); + } } await _applicationRepository.UpdateAsync(application); @@ -533,7 +607,33 @@ public async Task UpdateFundingAgreementInfoAsync(Guid id, application.ContractNumber = input.ContractNumber; application.ContractExecutionDate = input.ContractExecutionDate; - await PublishCustomFieldUpdatesAsync(application.Id, FlexConsts.FundingAgreementInfoUiAnchor, input); + // Handle custom fields for funding agreement info + if (HasValue(input.CustomFields) && input.CorrelationId != Guid.Empty) + { + // Handle multiple worksheets + if (input.WorksheetIds?.Count > 0) + { + foreach (var worksheetId in input.WorksheetIds) + { + var worksheetCustomFields = ExtractCustomFieldsForWorksheet(input.CustomFields, worksheetId); + if (worksheetCustomFields.Count > 0) + { + var worksheetData = new CustomDataFieldDto + { + WorksheetId = worksheetId, + CustomFields = worksheetCustomFields, + CorrelationId = input.CorrelationId + }; + await PublishCustomFieldUpdatesAsync(application.Id, FlexConsts.FundingAgreementInfoUiAnchor, worksheetData); + } + } + } + // Fallback for single worksheet (backward compatibility) + else if (input.WorksheetId != Guid.Empty) + { + await PublishCustomFieldUpdatesAsync(application.Id, FlexConsts.FundingAgreementInfoUiAnchor, input); + } + } await _applicationRepository.UpdateAsync(application); @@ -545,6 +645,11 @@ public async Task UpdateFundingAgreementInfoAsync(Guid id, } } + private static bool HasValue(JsonElement element) + { + return element.ValueKind != JsonValueKind.Null && element.ValueKind != JsonValueKind.Undefined; + } + /// /// Update the supplier number for the applicant associated with the application. /// @@ -1117,4 +1222,22 @@ public async Task> GetAllApplicationsAsync() return await query.ToListAsync(); } + + private static Dictionary ExtractCustomFieldsForWorksheet(dynamic customFields, Guid worksheetId) + { + var result = new Dictionary(); + var worksheetSuffix = $".{worksheetId}"; + + if (customFields is JsonElement jsonElement) + { + result = jsonElement.EnumerateObject() + .Where(property => property.Name.EndsWith(worksheetSuffix)) + .ToDictionary( + property => property.Name[..^worksheetSuffix.Length], + property => property.Value.ValueKind == JsonValueKind.String ? (object)property.Value.GetString()! : string.Empty + ); + } + + return result; + } } diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/History/HistoryAppService.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/History/HistoryAppService.cs index bde5340f9..514d82b85 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/History/HistoryAppService.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/History/HistoryAppService.cs @@ -2,92 +2,98 @@ using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; +using Volo.Abp; using Volo.Abp.Auditing; using Volo.Abp.AuditLogging; +using Volo.Abp.Data; using Volo.Abp.Domain.ChangeTracking; using Volo.Abp.Identity; -namespace Unity.GrantManager.History +namespace Unity.GrantManager.History; + +public class HistoryAppService( + IAuditLogRepository auditLogRepository, + IIdentityUserRepository identityUserRepository, + IDataFilter softDataFilter) : GrantManagerAppService, IHistoryAppService { - public class HistoryAppService(IAuditLogRepository auditLogRepository, IIdentityUserRepository identityUserRepository) : GrantManagerAppService, IHistoryAppService + [DisableEntityChangeTracking] + public async Task> GetHistoryList(string? entityId, + string filterPropertyName, + Dictionary? lookupDictionary) { - [DisableEntityChangeTracking] - public async Task> GetHistoryList(string? entityId, - string filterPropertyName, - Dictionary? lookupDictionary) - { - List historyList = []; - string? sorting = null; - int maxResultCount = 50; - int skipCount = 0; - DateTime? startTime = null; - DateTime? endTime = null; - bool includeDetails = true; - Guid? auditLogId = null; - EntityChangeType? changeType = null; - string? entityTypeFullName = null; - CancellationToken cancellationToken = default; + List historyList = []; + string? sorting = null; + int maxResultCount = 50; + int skipCount = 0; + DateTime? startTime = null; + DateTime? endTime = null; + bool includeDetails = true; + Guid? auditLogId = null; + EntityChangeType? changeType = null; + string? entityTypeFullName = null; + CancellationToken cancellationToken = default; - var entityChanges = await auditLogRepository.GetEntityChangeListAsync( - sorting, - maxResultCount, - skipCount, - auditLogId, - startTime, endTime, - changeType, - entityId, - entityTypeFullName, - includeDetails, - cancellationToken); + var entityChanges = await auditLogRepository.GetEntityChangeListAsync( + sorting, + maxResultCount, + skipCount, + auditLogId, + startTime, endTime, + changeType, + entityId, + entityTypeFullName, + includeDetails, + cancellationToken); - foreach (var entityChange in entityChanges) + foreach (var entityChange in entityChanges) + { + foreach (var propertyChange in entityChange.PropertyChanges) { - foreach (var propertyChange in entityChange.PropertyChanges) + if (propertyChange.PropertyName == filterPropertyName) { - if (propertyChange.PropertyName == filterPropertyName) + string origninalValue = CleanValue(propertyChange.OriginalValue); + string newValue = CleanValue(propertyChange.NewValue); + // Signal the kind of time so that tolocal knows how to convert it on the page + DateTime utcDateTime = DateTime.SpecifyKind(entityChange.ChangeTime, DateTimeKind.Utc); + HistoryDto historyDto = new() { - string origninalValue = CleanValue(propertyChange.OriginalValue); - string newValue = CleanValue(propertyChange.NewValue); - // Signal the kind of time so that tolocal knows how to convert it on the page - DateTime utcDateTime = DateTime.SpecifyKind(entityChange.ChangeTime, DateTimeKind.Utc); - HistoryDto historyDto = new() - { - OriginalValue = GetLookupValue(origninalValue, lookupDictionary), - NewValue = GetLookupValue(newValue, lookupDictionary), - ChangeTime = utcDateTime.ToLocalTime(), - UserName = await LookupUserName(entityChange.AuditLogId) - }; - historyList.Add(historyDto); - } + OriginalValue = GetLookupValue(origninalValue, lookupDictionary), + NewValue = GetLookupValue(newValue, lookupDictionary), + ChangeTime = utcDateTime.ToLocalTime(), + UserName = await LookupUserName(entityChange.AuditLogId) + }; + historyList.Add(historyDto); } } - return historyList; } + return historyList; + } - private static string CleanValue(string? value) - { - return value?.Replace("\"", "") ?? ""; - } + private static string CleanValue(string? value) + { + return value?.Replace("\"", "") ?? ""; + } - private static string GetLookupValue(string value, Dictionary? lookupDictionary) + private static string GetLookupValue(string value, Dictionary? lookupDictionary) + { + return lookupDictionary != null && lookupDictionary.TryGetValue(value, out var lookupValue) + ? lookupValue + : value; + } + + public async Task LookupUserName(Guid auditLogId) + { + var auditLog = await auditLogRepository.GetAsync(auditLogId); + if (auditLog?.UserId == null || auditLog.UserId == Guid.Empty) { - return lookupDictionary != null && lookupDictionary.TryGetValue(value, out var lookupValue) - ? lookupValue - : value; + return string.Empty; } - public async Task LookupUserName(Guid auditLogId) + var userId = auditLog.UserId.Value; + using (softDataFilter.Disable()) { - var auditLog = await auditLogRepository.GetAsync(auditLogId); - if (auditLog?.UserId == null || auditLog.UserId == Guid.Empty) - { - return string.Empty; - } - - var userId = auditLog.UserId.Value; - var user = await identityUserRepository.GetAsync(userId); - - return user != null ? $"{user.Name} {user.Surname}" : string.Empty; + var user = await identityUserRepository.FindAsync(userId); + return user != null ? $"{user.Name} {user.Surname}" : "(Full-Deleted User)"; } } } diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Intakes/Events/ApplicationProcessEvent.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Intakes/Events/ApplicationProcessEvent.cs index 4eff7732c..c5e218694 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Intakes/Events/ApplicationProcessEvent.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Intakes/Events/ApplicationProcessEvent.cs @@ -8,5 +8,8 @@ public class ApplicationProcessEvent public ApplicationFormVersion? FormVersion { get; internal set; } public ApplicationFormSubmission? ApplicationFormSubmission { get; internal set; } public dynamic? RawSubmission { get; internal set; } + + // As this expands, turn this into a flags enum for control over which event handlers to run + public bool OnlyLocationRetrofill { get; set; } } } diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Intakes/Handlers/DetermineElectoralDistrictHandler.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Intakes/Handlers/DetermineElectoralDistrictHandler.cs index 487a6bac1..392216c7a 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Intakes/Handlers/DetermineElectoralDistrictHandler.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Intakes/Handlers/DetermineElectoralDistrictHandler.cs @@ -28,6 +28,13 @@ public async Task HandleEventAsync(ApplicationProcessEvent eventData) return; } + if (!string.IsNullOrEmpty(eventData.Application.Applicant.ElectoralDistrict)) + { + logger.LogInformation("Electoral district already set to '{ExistingElectoralDistrict}' for application {ApplicationId}.", + eventData.Application.Applicant.ElectoralDistrict, eventData.Application.Id); + return; + } + if (eventData.FormVersion == null) { logger.LogWarning("Form version data is null in DetermineElectoralDistrictHandler."); @@ -50,7 +57,7 @@ public async Task HandleEventAsync(ApplicationProcessEvent eventData) if (applicantAddresses == null || applicantAddresses.Count == 0) { - logger.LogWarning("Applicant addresses are null or empty in DetermineElectoralDistrictHandler for application {ApplicationId}.", + logger.LogWarning("Applicant addresses are null or empty in DetermineElectoralDistrictHandler for application {ApplicationId}.", eventData.Application.Id); return; } @@ -81,6 +88,8 @@ public async Task HandleEventAsync(ApplicationProcessEvent eventData) if (electoralDistrict.Name != null) { eventData.Application.Applicant.SetElectoralDistrict(electoralDistrict.Name); + logger.LogInformation("Electoral district '{ElectoralDistrict}' determined for address: {Address}", + electoralDistrict.Name, address); } else { diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Intakes/Handlers/GenerateReportDataHandler.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Intakes/Handlers/GenerateReportDataHandler.cs index 189441218..406fac8f0 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Intakes/Handlers/GenerateReportDataHandler.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Intakes/Handlers/GenerateReportDataHandler.cs @@ -10,7 +10,7 @@ namespace Unity.GrantManager.Intakes.Handlers { public class GenerateReportDataHandler(IReportingDataGenerator reportingDataGenerator, - ILogger logger, + ILogger logger, IFeatureChecker featureChecker) : ILocalEventHandler, ITransientDependency { /// @@ -26,6 +26,12 @@ public async Task HandleEventAsync(ApplicationProcessEvent eventData) return; } + if (eventData.OnlyLocationRetrofill) + { + logger.LogInformation("Skip report data generator handler."); + return; + } + if (await featureChecker.IsEnabledAsync(FeatureConsts.Reporting)) { logger.LogInformation("Generating report data for application {ApplicationId}.", eventData.Application?.Id); diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Locality/BackgroundJobs/RetrofillElectoralDistrictsBackgroundJob.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Locality/BackgroundJobs/RetrofillElectoralDistrictsBackgroundJob.cs new file mode 100644 index 000000000..fb7c6dedf --- /dev/null +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Locality/BackgroundJobs/RetrofillElectoralDistrictsBackgroundJob.cs @@ -0,0 +1,103 @@ +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Logging; +using System; +using System.Linq; +using System.Threading.Tasks; +using Unity.GrantManager.Applications; +using Unity.GrantManager.Intakes.Events; +using Volo.Abp.BackgroundJobs; +using Volo.Abp.DependencyInjection; +using Volo.Abp.EventBus.Local; +using Volo.Abp.MultiTenancy; +using Volo.Abp.Uow; + +namespace Unity.GrantManager.Locality.BackgroundJobs +{ + public class RetrofillElectoralDistrictsBackgroundJob( + IApplicationRepository applicationRepository, + IApplicationFormSubmissionRepository applicationFormSubmissionRepository, + IApplicationFormVersionRepository applicationFormVersionRepository, + ILocalEventBus localEventBus, + ICurrentTenant currentTenant, + IUnitOfWorkManager unitOfWorkManager, + ILogger logger) : AsyncBackgroundJob, ITransientDependency + { + private const string LogPrefix = "[ElectoralRetroFill]"; + + public override async Task ExecuteAsync(RetrofillElectoralDistrictsBackgroundJobArgs args) + { + LogPrefixedInfo($"Executing electoral district retrofill for {args.TenantId}"); + + using (currentTenant.Change(args.TenantId)) + { + try + { + // Read all the applications for the tenant, get a list of their Id's + var applicationIds = (await applicationRepository + .GetListAsync()) + .Select(s => s.Id); + + // Foreach one we read again individually, and commit indivudally and log per record + foreach (var applicationId in applicationIds) + { + try + { + using var unitOfWork = unitOfWorkManager.Begin(true); + + LogPrefixedInfo($"Processing applicationId {applicationId}"); + + var application = await (await applicationRepository.GetQueryableAsync()) + .Include(s => s.Applicant) + .ThenInclude(s => s.ApplicantAddresses) + .Include(s => s.ApplicationForm) + .FirstOrDefaultAsync(s => s.Id == applicationId); + + var submission = await applicationFormSubmissionRepository.GetByApplicationAsync(applicationId); + var formVersionId = submission?.ApplicationFormVersionId; + + if (formVersionId == null) + { + LogPrefixedInfo($"No form version found for applicationId {applicationId}, skipping retrofill."); + continue; + } + + var formVersion = await applicationFormVersionRepository.GetAsync(formVersionId.Value); + + await localEventBus.PublishAsync(new ApplicationProcessEvent + { + Application = application, + FormVersion = formVersion, + ApplicationFormSubmission = null, + RawSubmission = null, + OnlyLocationRetrofill = true + }); + + await unitOfWork.CompleteAsync(); + + // To avoid any rate limiting issues with any external services, we add a small delay + await Task.Delay(500); + } + catch (Exception ex) + { + LogPrefixedError(ex, $"Error executing electoral district retrofill for applicationId: {applicationId}"); + } + } + } + catch (Exception ex) + { + LogPrefixedError(ex, $"Error executing electoral district retrofill for tenantId: {args.TenantId}"); + } + } + } + + private void LogPrefixedInfo(string message) + { + logger.LogInformation("{Prefix} {Message}", LogPrefix, message); + } + + private void LogPrefixedError(Exception ex, string message) + { + logger.LogError(ex, "{Prefix} {Message}", LogPrefix, message); + } + } +} diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Locality/BackgroundJobs/RetrofillElectoralDistrictsBackgroundJobArgs.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Locality/BackgroundJobs/RetrofillElectoralDistrictsBackgroundJobArgs.cs new file mode 100644 index 000000000..290af8743 --- /dev/null +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Locality/BackgroundJobs/RetrofillElectoralDistrictsBackgroundJobArgs.cs @@ -0,0 +1,9 @@ +using System; + +namespace Unity.GrantManager.Locality.BackgroundJobs +{ + public class RetrofillElectoralDistrictsBackgroundJobArgs + { + public Guid? TenantId { get; set; } + } +} diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Locality/ElectoralDistrictAppService.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Locality/ElectoralDistrictAppService.cs index 8da6f0802..b4ca4b29b 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Locality/ElectoralDistrictAppService.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Locality/ElectoralDistrictAppService.cs @@ -1,11 +1,14 @@ -using System; +using Microsoft.AspNetCore.Authorization; +using Microsoft.Extensions.Caching.Distributed; +using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; -using Microsoft.AspNetCore.Authorization; -using Microsoft.Extensions.Caching.Distributed; +using Unity.GrantManager.Locality.BackgroundJobs; using Unity.GrantManager.Settings; +using Unity.Modules.Shared.Permissions; using Volo.Abp.Application.Services; +using Volo.Abp.BackgroundJobs; using Volo.Abp.Caching; using Volo.Abp.DependencyInjection; using Volo.Abp.MultiTenancy; @@ -17,7 +20,8 @@ namespace Unity.GrantManager.Locality [Dependency(ReplaceServices = true)] [ExposeServices(typeof(ElectoralDistrictAppService), typeof(IElectoralDistrictService))] public class ElectoralDistrictAppService(IElectoralDistrictRepository electoralDistrictRepository, - IDistributedCache cache) : ApplicationService, IElectoralDistrictService + IDistributedCache cache, + IBackgroundJobManager backgroundJobManager) : ApplicationService, IElectoralDistrictService { public virtual async Task> GetListAsync() { @@ -32,6 +36,12 @@ public virtual async Task> GetListAsync() return electoralDistrictsCache?.ElectoralDistricts ?? []; } + + [Authorize(IdentityConsts.ITAdminPolicyName)] + public virtual async Task RetroFillElectoralDistricts(Guid tenantId) + { + await backgroundJobManager.EnqueueAsync(new RetrofillElectoralDistrictsBackgroundJobArgs() { TenantId = tenantId }); + } protected virtual async Task GetElectoralDistrictsAsync() { diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Tags/TagsAppService.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Tags/TagsAppService.cs index 6425567b5..b6dde60a4 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Tags/TagsAppService.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Tags/TagsAppService.cs @@ -133,18 +133,7 @@ public virtual async Task RenameTagGlobalAsync(Guid id, string originalTag, stri { Check.NotNullOrWhiteSpace(originalTag, nameof(originalTag)); Check.NotNullOrWhiteSpace(replacementTag, nameof(replacementTag)); - - // NOTE: Unable to get the MIN of the MaxRenameLength for both Application and Payments. Must get on front-end by 2 API calls. - // May result in one EntityType tag renaming with the other failing in rare cases. - await RenameTagAsync(id, originalTag, replacementTag); - await _localEventBus.PublishAsync( - new RenameTagEto - { - originalTagName = originalTag, - replacementTagName = replacementTag - } - ); } /// diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.DbMigrator/appsettings.json b/applications/Unity.GrantManager/src/Unity.GrantManager.DbMigrator/appsettings.json index cfb8e65c8..b62692978 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.DbMigrator/appsettings.json +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.DbMigrator/appsettings.json @@ -1,5 +1,5 @@ { - "ConnectionStrings": { + "ConnectionStrings": { "Default": "Host=localhost;port=5432;Database=UnityGrantManager;Username=postgres;Password=admin", "Tenant": "Host=localhost;port=5432;Database=UnityGrantTenant;Username=postgres;Password=admin" }, diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Domain/Applications/ApplicationFormDetails.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Domain/Applications/ApplicationFormDetails.cs new file mode 100644 index 000000000..6b0dcccd1 --- /dev/null +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Domain/Applications/ApplicationFormDetails.cs @@ -0,0 +1,15 @@ +using System; + +namespace Unity.GrantManager.Applications; + +[Serializable] +public class ApplicationFormDetails +{ + public Guid ApplicationId { get; set; } + public Guid ApplicationFormId { get; set; } + public string ApplicationFormName { get; set; } = string.Empty; + public string ApplicationFormDescription { get; set; } = string.Empty; + public string ApplicationFormCategory { get; set; } = string.Empty; + public Guid ApplicationFormVersionId { get; set; } + public int ApplicationFormVersion { get; set; } +} diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Domain/Applications/ApplicationTags.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Domain/Applications/ApplicationTags.cs index 52fd8c08e..5dc944d07 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Domain/Applications/ApplicationTags.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Domain/Applications/ApplicationTags.cs @@ -15,8 +15,6 @@ public virtual Application Application ?? throw new InvalidOperationException("Uninitialized property: " + nameof(Application)); } private Application? _application; - - public string Text { get; set; } = string.Empty; public Guid TagId { get; set; } public virtual Tag Tag diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Domain/Applications/IApplicationFormSubmissionRepository.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Domain/Applications/IApplicationFormSubmissionRepository.cs index b3dd17532..6dfc2f04e 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Domain/Applications/IApplicationFormSubmissionRepository.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Domain/Applications/IApplicationFormSubmissionRepository.cs @@ -7,4 +7,5 @@ namespace Unity.GrantManager.Applications; public interface IApplicationFormSubmissionRepository : IRepository { Task GetByApplicationAsync(Guid applicationId); + Task GetFormDetailsByApplicationIdAsync(Guid applicationId); } diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Domain/Intakes/Mapping/ChefsFormIOReplacement.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Domain/Intakes/Mapping/ChefsFormIOReplacement.cs index 6483f5b23..379b57915 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Domain/Intakes/Mapping/ChefsFormIOReplacement.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Domain/Intakes/Mapping/ChefsFormIOReplacement.cs @@ -15,91 +15,84 @@ public static void InitializeLogger(ILoggerFactory loggerFactory) { logger = loggerFactory.CreateLogger("ChefsFormIOReplacement"); } + private static readonly TimeSpan RegexTimeout = TimeSpan.FromMinutes(1); + + // Map of regex => replacement + private static readonly Dictionary SubPatterns = new() + { + // Advanced components + { new Regex(@"""type""\s*:\s*""orgbook""", RegexOptions.Compiled, RegexTimeout), "\"type\": \"select\"" }, + { new Regex(@"""type""\s*:\s*""simpleaddressadvanced""", RegexOptions.Compiled, RegexTimeout), "\"type\": \"address\"" }, + { new Regex(@"""type""\s*:\s*""simplebuttonadvanced""", RegexOptions.Compiled, RegexTimeout), "\"type\": \"button\"" }, + { new Regex(@"""type""\s*:\s*""simplecheckboxadvanced""", RegexOptions.Compiled, RegexTimeout), "\"type\": \"checkbox\"" }, + { new Regex(@"""type""\s*:\s*""simplecurrencyadvanced""", RegexOptions.Compiled, RegexTimeout), "\"type\": \"currency\"" }, + { new Regex(@"""type""\s*:\s*""simpledatetimeadvanced""", RegexOptions.Compiled, RegexTimeout), "\"type\": \"datetime\"" }, + { new Regex(@"""type""\s*:\s*""simpledayadvanced""", RegexOptions.Compiled, RegexTimeout), "\"type\": \"day\"" }, + { new Regex(@"""type""\s*:\s*""simpleemailadvanced""", RegexOptions.Compiled, RegexTimeout), "\"type\": \"email\"" }, + { new Regex(@"""type""\s*:\s*""simplenumberadvanced""", RegexOptions.Compiled, RegexTimeout), "\"type\": \"number\"" }, + { new Regex(@"""type""\s*:\s*""simplepasswordadvanced""", RegexOptions.Compiled, RegexTimeout), "\"type\": \"password\"" }, + { new Regex(@"""type""\s*:\s*""simplephonenumberadvanced""", RegexOptions.Compiled, RegexTimeout), "\"type\": \"phoneNumber\"" }, + { new Regex(@"""type""\s*:\s*""simpleradioadvanced""", RegexOptions.Compiled, RegexTimeout), "\"type\": \"radio\"" }, + { new Regex(@"""type""\s*:\s*""simpleselectadvanced""", RegexOptions.Compiled, RegexTimeout), "\"type\": \"select\"" }, + { new Regex(@"""type""\s*:\s*""simpleselectboxesadvanced""", RegexOptions.Compiled, RegexTimeout), "\"type\": \"selectboxes\"" }, + { new Regex(@"""type""\s*:\s*""simplesignatureadvanced""", RegexOptions.Compiled, RegexTimeout), "\"type\": \"signature\"" }, + { new Regex(@"""type""\s*:\s*""simplesurveyadvanced""", RegexOptions.Compiled, RegexTimeout), "\"type\": \"survey\"" }, + { new Regex(@"""type""\s*:\s*""simpletagsadvanced""", RegexOptions.Compiled, RegexTimeout), "\"type\": \"tags\"" }, + { new Regex(@"""type""\s*:\s*""simpletextareaadvanced""", RegexOptions.Compiled, RegexTimeout), "\"type\": \"textarea\"" }, + { new Regex(@"""type""\s*:\s*""simpletextfieldadvanced""", RegexOptions.Compiled, RegexTimeout), "\"type\": \"textfield\"" }, + { new Regex(@"""type""\s*:\s*""simpletimeadvanced""", RegexOptions.Compiled, RegexTimeout), "\"type\": \"time\"" }, + { new Regex(@"""type""\s*:\s*""simpleurladvanced""", RegexOptions.Compiled, RegexTimeout), "\"type\": \"url\"" }, + + // Regular components + { new Regex(@"""type""\s*:\s*""simplebcaddress""", RegexOptions.Compiled, RegexTimeout), "\"type\": \"address\"" }, + { new Regex(@"""type""\s*:\s*""bcaddress""", RegexOptions.Compiled, RegexTimeout), "\"type\": \"address\"" }, + { new Regex(@"""type""\s*:\s*""simplebtnreset""", RegexOptions.Compiled, RegexTimeout), "\"type\": \"button\"" }, + { new Regex(@"""type""\s*:\s*""simplebtnsubmit""", RegexOptions.Compiled, RegexTimeout), "\"type\": \"button\"" }, + { new Regex(@"""type""\s*:\s*""simplecheckboxes""", RegexOptions.Compiled, RegexTimeout), "\"type\": \"selectboxes\"" }, + { new Regex(@"""type""\s*:\s*""simplecheckbox""", RegexOptions.Compiled, RegexTimeout), "\"type\": \"checkbox\"" }, + { new Regex(@"""type""\s*:\s*""simplecols2""", RegexOptions.Compiled, RegexTimeout), "\"type\": \"columns\"" }, + { new Regex(@"""type""\s*:\s*""simplecols3""", RegexOptions.Compiled, RegexTimeout), "\"type\": \"columns\"" }, + { new Regex(@"""type""\s*:\s*""simplecols4""", RegexOptions.Compiled, RegexTimeout), "\"type\": \"columns\"" }, + { new Regex(@"""type""\s*:\s*""simplecontent""", RegexOptions.Compiled, RegexTimeout), "\"type\": \"content\"" }, + { new Regex(@"""type""\s*:\s*""simpledatetime""", RegexOptions.Compiled, RegexTimeout), "\"type\": \"datetime\"" }, + { new Regex(@"""type""\s*:\s*""simpleday""", RegexOptions.Compiled, RegexTimeout), "\"type\": \"day\"" }, + { new Regex(@"""type""\s*:\s*""simpleemail""", RegexOptions.Compiled, RegexTimeout), "\"type\": \"email\"" }, + { new Regex(@"""type""\s*:\s*""simplefile""", RegexOptions.Compiled, RegexTimeout), "\"type\": \"file\"" }, + { new Regex(@"""type""\s*:\s*""simpleheading""", RegexOptions.Compiled, RegexTimeout), "\"type\": \"header\"" }, + { new Regex(@"""type""\s*:\s*""simplefieldset""", RegexOptions.Compiled, RegexTimeout), "\"type\": \"fieldset\"" }, + { new Regex(@"""type""\s*:\s*""simplenumber""", RegexOptions.Compiled, RegexTimeout), "\"type\": \"number\"" }, + { new Regex(@"""type""\s*:\s*""simplepanel""", RegexOptions.Compiled, RegexTimeout), "\"type\": \"panel\"" }, + { new Regex(@"""type""\s*:\s*""simpleparagraph""", RegexOptions.Compiled, RegexTimeout), "\"type\": \"textarea\"" }, + { new Regex(@"""type""\s*:\s*""simplephonenumber""", RegexOptions.Compiled, RegexTimeout), "\"type\": \"phoneNumber\"" }, + { new Regex(@"""type""\s*:\s*""simpleradios""", RegexOptions.Compiled, RegexTimeout), "\"type\": \"radio\"" }, + { new Regex(@"""type""\s*:\s*""simpleselect""", RegexOptions.Compiled, RegexTimeout), "\"type\": \"select\"" }, + { new Regex(@"""type""\s*:\s*""simpletabs""", RegexOptions.Compiled, RegexTimeout), "\"type\": \"tabs\"" }, + { new Regex(@"""type""\s*:\s*""simpletextarea""", RegexOptions.Compiled, RegexTimeout), "\"type\": \"textarea\"" }, + { new Regex(@"""type""\s*:\s*""simpletextfield""", RegexOptions.Compiled, RegexTimeout), "\"type\": \"textfield\"" }, + { new Regex(@"""type""\s*:\s*""simpletime""", RegexOptions.Compiled, RegexTimeout), "\"type\": \"time\"" } + }; - private static int OneMinuteMilliseconds = 60000; public static string ReplaceAdvancedFormIoControls(dynamic formSubmission) { - string formSubmissionStr = formSubmission.ToString(); - if (!string.IsNullOrEmpty(formSubmissionStr)) - { - Dictionary subPatterns = new Dictionary - { - { @"\borgbook\b", "select" }, - { @"\bsimpleaddressadvanced\b", "address" }, - { @"\bsimplebuttonadvanced\b", "button" }, - { @"\bsimplecheckboxadvanced\b", "checkbox" }, - { @"\bsimplecurrencyadvanced\b", "currency" }, - { @"\bsimpledatetimeadvanced\b", "datetime" }, - { @"\bsimpledayadvanced\b", "day" }, - { @"\bsimpleemailadvanced\b", "email" }, - { @"\bsimplenumberadvanced\b", "number" }, - { @"\bsimplepasswordadvanced\b", "password" }, - { @"\bsimplephonenumberadvanced\b", "phoneNumber" }, - { @"\bsimpleradioadvanced\b", "radio" }, - { @"\bsimpleselectadvanced\b", "select" }, - { @"\bsimpleselectboxesadvanced\b", "selectboxes" }, - { @"\bsimplesignatureadvanced\b", "signature" }, - { @"\bsimplesurveyadvanced\b", "survey" }, - { @"\bsimpletagsadvanced\b", "tags" }, - { @"\bsimpletextareaadvanced\b", "textarea" }, - { @"\bsimpletextfieldadvanced\b", "textfield" }, - { @"\bsimpletimeadvanced\b", "time" }, - { @"\bsimpleurladvanced\b", "url" }, + string? formSubmissionStr = formSubmission?.ToString(); + if (string.IsNullOrEmpty(formSubmissionStr)) + return string.Empty; - // Regular components - { @"\bsimplebcaddress\b", "address" }, - { @"\bbcaddress\b", "address" }, - { @"\bsimplebtnreset\b", "button" }, - { @"\bsimplebtnsubmit\b", "button" }, - { @"\bsimplecheckboxes\b", "selectboxes" }, - { @"\bsimplecheckbox\b", "checkbox" }, - { @"\bsimplecols2\b", "columns" }, - { @"\bsimplecols3\b", "columns" }, - { @"\bsimplecols4\b", "columns" }, - { @"\bsimplecontent\b", "content" }, - { @"\bsimpledatetime\b", "datetime" }, - { @"\bsimpleday\b", "day" }, - { @"\bsimpleemail\b", "email" }, - { @"\bsimplefile\b", "file" }, - { @"\bsimpleheading\b", "header" }, - { @"\bsimplefieldset\b", "fieldset" }, - { @"\bsimplenumber\b", "number" }, - { @"\bsimplepanel", "panel" }, - { @"\bsimpleparagraph\b", "textarea" }, - { @"\bsimplephonenumber\b", "phoneNumber" }, - { @"\bsimpleradios\b", "radio" }, - { @"\bsimpleselect\b", "select" }, - { @"\bsimpletabs\b", "tabs" }, - { @"\bsimpletextarea\b", "textarea" }, - { @"\bsimpletextfield\b", "textfield" }, - { @"\bsimpletime\b", "time" } - }; - string replacedString = formSubmissionStr; + string replacedString = formSubmissionStr; - //find the replacement - foreach (var subPattern in subPatterns) + try + { + foreach (var kv in SubPatterns) { - string patternKey = subPattern.Key; - string replace = subPattern.Value; - // Allow one minute timeout - try - { - replacedString = Regex.Replace(replacedString, - patternKey, - replace, - RegexOptions.None, - TimeSpan.FromMilliseconds(OneMinuteMilliseconds)); - } - catch (RegexMatchTimeoutException ex) - { - string ExceptionMessage = ex.Message; - logger.LogWarning(ex, "ReplaceAdvancedFormIoControls RegEx Exception {ExceptionMessage}", ExceptionMessage); - } + replacedString = kv.Key.Replace(replacedString, kv.Value); } - - formSubmissionStr = replacedString; } - return formSubmissionStr; + catch (RegexMatchTimeoutException ex) + { + logger.LogWarning(ex, "ReplaceAdvancedFormIoControls RegEx Timeout: {Message}", ex.Message); + } + + return replacedString; } } } \ No newline at end of file diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.EntityFrameworkCore/Migrations/TenantMigrations/20250815155039_DropPaymentColumns.Designer.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.EntityFrameworkCore/Migrations/TenantMigrations/20250815155039_DropPaymentColumns.Designer.cs new file mode 100644 index 000000000..18992fd1e --- /dev/null +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.EntityFrameworkCore/Migrations/TenantMigrations/20250815155039_DropPaymentColumns.Designer.cs @@ -0,0 +1,4233 @@ +// +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.TenantMigrations +{ + [DbContext(typeof(GrantTenantDbContext))] + [Migration("20250815155039_DropPaymentColumns")] + partial class DropPaymentColumns + { + /// + 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("Unity.Flex.Domain.ScoresheetInstances.ScoresheetInstance", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CorrelationId") + .HasColumnType("uuid"); + + b.Property("CorrelationProvider") + .IsRequired() + .HasColumnType("text"); + + 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("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("ReportData") + .IsRequired() + .HasColumnType("jsonb"); + + b.Property("ScoresheetId") + .HasColumnType("uuid"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("Value") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("ScoresheetId"); + + b.ToTable("ScoresheetInstances", "Flex"); + }); + + modelBuilder.Entity("Unity.Flex.Domain.Scoresheets.Answer", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("CurrentValue") + .HasColumnType("jsonb"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("DeletionTime"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("QuestionId") + .HasColumnType("uuid"); + + b.Property("ScoresheetInstanceId") + .HasColumnType("uuid"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("Version") + .HasColumnType("bigint"); + + b.HasKey("Id"); + + b.HasIndex("QuestionId"); + + b.HasIndex("ScoresheetInstanceId"); + + b.ToTable("Answers", "Flex"); + }); + + modelBuilder.Entity("Unity.Flex.Domain.Scoresheets.Question", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("Definition") + .IsRequired() + .HasColumnType("jsonb"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("DeletionTime"); + + b.Property("Description") + .HasColumnType("text"); + + b.Property("Enabled") + .HasColumnType("boolean"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("Label") + .IsRequired() + .HasColumnType("text"); + + 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("Order") + .HasColumnType("bigint"); + + b.Property("SectionId") + .HasColumnType("uuid"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("Type") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("SectionId"); + + b.ToTable("Questions", "Flex"); + }); + + modelBuilder.Entity("Unity.Flex.Domain.Scoresheets.Scoresheet", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .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("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + 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("Order") + .HasColumnType("bigint"); + + b.Property("Published") + .HasColumnType("boolean"); + + b.Property("ReportColumns") + .IsRequired() + .HasColumnType("text"); + + b.Property("ReportKeys") + .IsRequired() + .HasColumnType("text"); + + b.Property("ReportViewName") + .IsRequired() + .HasColumnType("text"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("Title") + .IsRequired() + .HasColumnType("text"); + + b.Property("Version") + .HasColumnType("bigint"); + + b.HasKey("Id"); + + b.ToTable("Scoresheets", "Flex"); + }); + + modelBuilder.Entity("Unity.Flex.Domain.Scoresheets.ScoresheetSection", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + 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("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + 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("Order") + .HasColumnType("bigint"); + + b.Property("ScoresheetId") + .HasColumnType("uuid"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("ScoresheetId"); + + b.ToTable("ScoresheetSections", "Flex"); + }); + + modelBuilder.Entity("Unity.Flex.Domain.WorksheetInstances.CustomFieldValue", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("CurrentValue") + .IsRequired() + .HasColumnType("jsonb"); + + b.Property("CustomFieldId") + .HasColumnType("uuid"); + + 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("WorksheetInstanceId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("WorksheetInstanceId"); + + b.ToTable("CustomFieldValues", "Flex"); + }); + + modelBuilder.Entity("Unity.Flex.Domain.WorksheetInstances.WorksheetInstance", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CorrelationId") + .HasColumnType("uuid"); + + b.Property("CorrelationProvider") + .IsRequired() + .HasColumnType("text"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("CurrentValue") + .IsRequired() + .HasColumnType("jsonb"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("DeletionTime"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("ReportData") + .IsRequired() + .HasColumnType("jsonb"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("UiAnchor") + .IsRequired() + .HasColumnType("text"); + + b.Property("WorksheetCorrelationId") + .HasColumnType("uuid"); + + b.Property("WorksheetCorrelationProvider") + .IsRequired() + .HasColumnType("text"); + + b.Property("WorksheetId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.ToTable("WorksheetInstances", "Flex"); + }); + + modelBuilder.Entity("Unity.Flex.Domain.WorksheetLinks.WorksheetLink", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CorrelationId") + .HasColumnType("uuid"); + + b.Property("CorrelationProvider") + .IsRequired() + .HasColumnType("text"); + + 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("Order") + .HasColumnType("bigint"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("UiAnchor") + .IsRequired() + .HasColumnType("text"); + + b.Property("WorksheetId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("WorksheetId"); + + b.ToTable("WorksheetLinks", "Flex"); + }); + + modelBuilder.Entity("Unity.Flex.Domain.Worksheets.CustomField", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("Definition") + .IsRequired() + .HasColumnType("jsonb"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("DeletionTime"); + + b.Property("Enabled") + .HasColumnType("boolean"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("Key") + .IsRequired() + .HasColumnType("text"); + + b.Property("Label") + .IsRequired() + .HasColumnType("text"); + + 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("Order") + .HasColumnType("bigint"); + + b.Property("SectionId") + .HasColumnType("uuid"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("Type") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("SectionId"); + + b.ToTable("CustomFields", "Flex"); + }); + + modelBuilder.Entity("Unity.Flex.Domain.Worksheets.Worksheet", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .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("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + 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("Published") + .HasColumnType("boolean"); + + b.Property("ReportColumns") + .IsRequired() + .HasColumnType("text"); + + b.Property("ReportKeys") + .IsRequired() + .HasColumnType("text"); + + b.Property("ReportViewName") + .IsRequired() + .HasColumnType("text"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("Title") + .IsRequired() + .HasColumnType("text"); + + b.Property("Version") + .HasColumnType("bigint"); + + b.HasKey("Id"); + + b.ToTable("Worksheets", "Flex"); + }); + + modelBuilder.Entity("Unity.Flex.Domain.Worksheets.WorksheetSection", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + 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("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + 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("Order") + .HasColumnType("bigint"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("WorksheetId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("WorksheetId"); + + b.ToTable("WorksheetSections", "Flex"); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.Applicant", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ApplicantName") + .IsRequired() + .HasMaxLength(600) + .HasColumnType("character varying(600)"); + + b.Property("ApproxNumberOfEmployees") + .HasColumnType("text"); + + b.Property("BusinessNumber") + .HasColumnType("text"); + + 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("ElectoralDistrict") + .HasColumnType("text"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("FiscalDay") + .HasColumnType("integer"); + + b.Property("FiscalMonth") + .HasColumnType("text"); + + b.Property("IndigenousOrgInd") + .HasColumnType("text"); + + b.Property("IsDuplicated") + .HasColumnType("boolean"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("MatchPercentage") + .HasColumnType("numeric"); + + b.Property("NonRegOrgName") + .HasColumnType("text"); + + b.Property("NonRegisteredBusinessName") + .HasColumnType("text"); + + b.Property("OrgName") + .HasColumnType("text"); + + b.Property("OrgNumber") + .HasColumnType("text"); + + b.Property("OrgStatus") + .HasColumnType("text"); + + b.Property("OrganizationSize") + .HasColumnType("text"); + + b.Property("OrganizationType") + .HasColumnType("text"); + + b.Property("RedStop") + .HasColumnType("boolean"); + + b.Property("Sector") + .HasColumnType("text"); + + b.Property("SectorSubSectorIndustryDesc") + .HasColumnType("text"); + + b.Property("SiteId") + .HasColumnType("uuid"); + + b.Property("StartedOperatingDate") + .HasColumnType("date"); + + b.Property("Status") + .HasColumnType("text"); + + b.Property("SubSector") + .HasColumnType("text"); + + b.Property("SupplierId") + .HasColumnType("uuid"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("UnityApplicantId") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("ApplicantName"); + + b.ToTable("Applicants", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicantAddress", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("AddressType") + .HasColumnType("integer"); + + b.Property("ApplicantId") + .HasColumnType("uuid"); + + b.Property("ApplicationId") + .HasColumnType("uuid"); + + b.Property("City") + .HasColumnType("text"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("Country") + .HasColumnType("text"); + + 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("Postal") + .HasColumnType("text"); + + b.Property("Province") + .HasColumnType("text"); + + b.Property("Street") + .HasColumnType("text"); + + b.Property("Street2") + .HasColumnType("text"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("Unit") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("ApplicantId"); + + b.HasIndex("ApplicationId"); + + b.ToTable("ApplicantAddresses", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicantAgent", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ApplicantId") + .HasColumnType("uuid"); + + b.Property("ApplicationId") + .HasColumnType("uuid"); + + b.Property("BceidBusinessGuid") + .HasColumnType("uuid"); + + b.Property("BceidBusinessName") + .HasColumnType("text"); + + b.Property("BceidUserGuid") + .HasColumnType("uuid"); + + b.Property("BceidUserName") + .HasColumnType("text"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("ContactOrder") + .HasColumnType("integer"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("Email") + .HasColumnType("text"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IdentityEmail") + .HasColumnType("text"); + + b.Property("IdentityName") + .HasColumnType("text"); + + b.Property("IdentityProvider") + .HasColumnType("text"); + + b.Property("IsActive") + .HasColumnType("boolean"); + + b.Property("IsConfirmed") + .HasColumnType("boolean"); + + 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("OidcSubUser") + .HasColumnType("text"); + + b.Property("Phone") + .HasColumnType("text"); + + b.Property("Phone2") + .HasColumnType("text"); + + b.Property("Phone2Extension") + .HasColumnType("text"); + + b.Property("PhoneExtension") + .HasColumnType("text"); + + b.Property("RoleForApplicant") + .IsRequired() + .HasColumnType("text"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("Title") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("ApplicantId"); + + b.HasIndex("ApplicationId") + .IsUnique(); + + b.HasIndex("OidcSubUser"); + + b.ToTable("ApplicantAgents", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.Application", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("Acquisition") + .HasColumnType("text"); + + b.Property("ApplicantId") + .HasColumnType("uuid"); + + b.Property("ApplicationFormId") + .HasColumnType("uuid"); + + b.Property("ApplicationStatusId") + .HasColumnType("uuid"); + + b.Property("ApprovedAmount") + .HasColumnType("numeric"); + + b.Property("AssessmentResultDate") + .HasColumnType("timestamp without time zone"); + + b.Property("AssessmentResultStatus") + .HasColumnType("text"); + + b.Property("AssessmentStartDate") + .HasColumnType("timestamp without time zone"); + + b.Property("City") + .HasColumnType("text"); + + b.Property("Community") + .HasColumnType("text"); + + b.Property("CommunityPopulation") + .HasColumnType("integer"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("ContractExecutionDate") + .HasColumnType("timestamp without time zone"); + + b.Property("ContractNumber") + .HasColumnType("text"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DeclineRational") + .HasColumnType("text"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("DeletionTime"); + + b.Property("DueDate") + .HasColumnType("timestamp without time zone"); + + b.Property("DueDiligenceStatus") + .HasColumnType("text"); + + b.Property("EconomicRegion") + .HasColumnType("text"); + + b.Property("ElectoralDistrict") + .HasColumnType("text"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("FinalDecisionDate") + .HasColumnType("timestamp without time zone"); + + b.Property("Forestry") + .HasColumnType("text"); + + b.Property("ForestryFocus") + .HasColumnType("text"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("LikelihoodOfFunding") + .HasColumnType("text"); + + b.Property("Notes") + .HasColumnType("text"); + + b.Property("NotificationDate") + .HasColumnType("timestamp without time zone"); + + b.Property("OwnerId") + .HasColumnType("uuid"); + + b.Property("Payload") + .HasColumnType("jsonb"); + + b.Property("PercentageTotalProjectBudget") + .HasColumnType("double precision"); + + b.Property("Place") + .HasColumnType("text"); + + b.Property("ProjectEndDate") + .HasColumnType("timestamp without time zone"); + + b.Property("ProjectFundingTotal") + .HasColumnType("numeric"); + + b.Property("ProjectName") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.Property("ProjectStartDate") + .HasColumnType("timestamp without time zone"); + + b.Property("ProjectSummary") + .HasColumnType("text"); + + b.Property("ProposalDate") + .HasColumnType("timestamp without time zone"); + + b.Property("RecommendedAmount") + .HasColumnType("numeric"); + + b.Property("ReferenceNo") + .IsRequired() + .HasColumnType("text"); + + b.Property("RegionalDistrict") + .HasColumnType("text"); + + b.Property("RequestedAmount") + .HasColumnType("numeric"); + + b.Property("RiskRanking") + .HasColumnType("text"); + + b.Property("SigningAuthorityBusinessPhone") + .HasColumnType("text"); + + b.Property("SigningAuthorityCellPhone") + .HasColumnType("text"); + + b.Property("SigningAuthorityEmail") + .HasColumnType("text"); + + b.Property("SigningAuthorityFullName") + .HasColumnType("text"); + + b.Property("SigningAuthorityTitle") + .HasColumnType("text"); + + b.Property("SubStatus") + .HasColumnType("text"); + + b.Property("SubmissionDate") + .HasColumnType("timestamp without time zone"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("TotalProjectBudget") + .HasColumnType("numeric"); + + b.Property("TotalScore") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("ApplicantId"); + + b.HasIndex("ApplicationFormId"); + + b.HasIndex("ApplicationStatusId"); + + b.HasIndex("OwnerId"); + + b.ToTable("Applications", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicationAssignment", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ApplicationId") + .HasColumnType("uuid"); + + b.Property("AssigneeId") + .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("Duty") + .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("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("ApplicationId"); + + b.HasIndex("AssigneeId"); + + b.ToTable("ApplicationAssignments", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicationAttachment", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ApplicationId") + .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("DisplayName") + .HasMaxLength(1024) + .HasColumnType("character varying(1024)"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("FileName") + .HasColumnType("text"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("S3ObjectKey") + .IsRequired() + .HasColumnType("text"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("Time") + .HasColumnType("timestamp without time zone"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("ApplicationId"); + + b.ToTable("ApplicationAttachments", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicationChefsFileAttachment", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ApplicationId") + .HasColumnType("uuid"); + + b.Property("ChefsFileId") + .HasColumnType("text"); + + b.Property("ChefsSumbissionId") + .HasColumnType("text"); + + 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("DisplayName") + .HasMaxLength(1024) + .HasColumnType("character varying(1024)"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("FileName") + .HasColumnType("text"); + + 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.HasKey("Id"); + + b.HasIndex("ApplicationId"); + + b.ToTable("ApplicationChefsFileAttachments", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicationContact", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ApplicationId") + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("ContactEmail") + .HasColumnType("text"); + + b.Property("ContactFullName") + .IsRequired() + .HasColumnType("text"); + + b.Property("ContactMobilePhone") + .HasColumnType("text"); + + b.Property("ContactTitle") + .HasColumnType("text"); + + b.Property("ContactType") + .IsRequired() + .HasColumnType("text"); + + b.Property("ContactWorkPhone") + .HasColumnType("text"); + + 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("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("ApplicationId"); + + b.ToTable("ApplicationContact", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicationForm", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("AccountCodingId") + .HasColumnType("uuid"); + + b.Property("ApiKey") + .HasColumnType("text"); + + b.Property("ApplicationFormDescription") + .HasColumnType("text"); + + b.Property("ApplicationFormName") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.Property("AttemptedConnectionDate") + .HasColumnType("timestamp without time zone"); + + b.Property("AvailableChefsFields") + .HasColumnType("text"); + + b.Property("Category") + .HasColumnType("text"); + + b.Property("ChefsApplicationFormGuid") + .HasColumnType("text"); + + b.Property("ChefsCriteriaFormGuid") + .HasColumnType("text"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("ConnectionHttpStatus") + .HasColumnType("text"); + + 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("ElectoralDistrictAddressType") + .HasColumnType("integer"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IntakeId") + .HasColumnType("uuid"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("IsDirectApproval") + .HasColumnType("boolean"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("Payable") + .HasColumnType("boolean"); + + b.Property("PaymentApprovalThreshold") + .HasColumnType("numeric"); + + b.Property("PreventPayment") + .HasColumnType("boolean"); + + b.Property("RenderFormIoToHtml") + .HasColumnType("boolean"); + + b.Property("ScoresheetId") + .HasColumnType("uuid"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("Version") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("IntakeId"); + + b.ToTable("ApplicationForms", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicationFormSubmission", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ApplicantId") + .HasColumnType("uuid"); + + b.Property("ApplicationFormId") + .HasColumnType("uuid"); + + b.Property("ApplicationFormVersionId") + .HasColumnType("uuid"); + + b.Property("ApplicationId") + .HasColumnType("uuid"); + + b.Property("ChefsSubmissionGuid") + .IsRequired() + .HasColumnType("text"); + + 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("FormVersionId") + .HasColumnType("uuid"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("OidcSub") + .IsRequired() + .HasColumnType("text"); + + b.Property("RenderedHTML") + .HasColumnType("text"); + + b.Property("ReportData") + .IsRequired() + .HasColumnType("jsonb"); + + b.Property("Submission") + .IsRequired() + .HasColumnType("jsonb"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("ApplicantId"); + + b.HasIndex("ApplicationFormId"); + + b.ToTable("ApplicationFormSubmissions", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicationFormVersion", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ApplicationFormId") + .HasColumnType("uuid"); + + b.Property("AvailableChefsFields") + .HasColumnType("text"); + + b.Property("ChefsApplicationFormGuid") + .HasColumnType("text"); + + b.Property("ChefsFormVersionGuid") + .HasColumnType("text"); + + 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("FormSchema") + .HasColumnType("jsonb"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("Published") + .HasColumnType("boolean"); + + b.Property("ReportColumns") + .IsRequired() + .HasColumnType("text"); + + b.Property("ReportKeys") + .IsRequired() + .HasColumnType("text"); + + b.Property("ReportViewName") + .IsRequired() + .HasColumnType("text"); + + b.Property("SubmissionHeaderMapping") + .HasColumnType("text"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("Version") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("ApplicationFormId"); + + b.ToTable("ApplicationFormVersion", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicationLink", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ApplicationId") + .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("LinkedApplicationId") + .HasColumnType("uuid"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("ApplicationId"); + + b.ToTable("ApplicationLinks", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicationStatus", 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("ExternalStatus") + .IsRequired() + .HasColumnType("text"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("InternalStatus") + .IsRequired() + .HasColumnType("text"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("StatusCode") + .IsRequired() + .HasMaxLength(250) + .HasColumnType("character varying(250)"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("StatusCode") + .IsUnique(); + + b.ToTable("ApplicationStatuses", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicationTags", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ApplicationId") + .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("TagId") + .HasColumnType("uuid"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("Text") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("ApplicationId"); + + b.HasIndex("TagId"); + + b.ToTable("ApplicationTags", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.AssessmentAttachment", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("AssessmentId") + .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("DisplayName") + .HasMaxLength(1024) + .HasColumnType("character varying(1024)"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("FileName") + .HasColumnType("text"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("S3ObjectKey") + .IsRequired() + .HasColumnType("text"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("Time") + .HasColumnType("timestamp without time zone"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("AssessmentId"); + + b.ToTable("AssessmentAttachments", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Assessments.Assessment", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ApplicationId") + .HasColumnType("uuid"); + + b.Property("ApprovalRecommended") + .HasColumnType("boolean"); + + b.Property("AssessorId") + .HasColumnType("uuid"); + + b.Property("CleanGrowth") + .HasColumnType("integer"); + + 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("EconomicImpact") + .HasColumnType("integer"); + + b.Property("EndDate") + .HasColumnType("timestamp without time zone"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("FinancialAnalysis") + .HasColumnType("integer"); + + b.Property("InclusiveGrowth") + .HasColumnType("integer"); + + b.Property("IsComplete") + .HasColumnType("boolean"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("ApplicationId"); + + b.HasIndex("AssessorId"); + + b.ToTable("Assessments", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Comments.ApplicationComment", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ApplicationId") + .HasColumnType("uuid"); + + b.Property("Comment") + .IsRequired() + .HasColumnType("text"); + + b.Property("CommenterId") + .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("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("ApplicationId"); + + b.HasIndex("CommenterId"); + + b.ToTable("ApplicationComments", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Comments.AssessmentComment", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("AssessmentId") + .HasColumnType("uuid"); + + b.Property("Comment") + .IsRequired() + .HasColumnType("text"); + + b.Property("CommenterId") + .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("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("AssessmentId"); + + b.HasIndex("CommenterId"); + + b.ToTable("AssessmentComments", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.GlobalTag.Tag", 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("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.ToTable("Tags", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Identity.Person", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("Badge") + .IsRequired() + .HasColumnType("text"); + + 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("FullName") + .IsRequired() + .HasColumnType("text"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("OidcDisplayName") + .IsRequired() + .HasColumnType("text"); + + b.Property("OidcSub") + .IsRequired() + .HasColumnType("text"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("OidcSub"); + + b.ToTable("Persons", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Intakes.Intake", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("Budget") + .HasColumnType("double precision"); + + 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("EndDate") + .HasColumnType("timestamp without time zone"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IntakeName") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("StartDate") + .HasColumnType("timestamp without time zone"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.ToTable("Intakes", (string)null); + }); + + modelBuilder.Entity("Unity.Notifications.EmailGroups.EmailGroup", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .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("Description") + .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("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("Type") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("EmailGroups", "Notifications"); + }); + + modelBuilder.Entity("Unity.Notifications.EmailGroups.EmailGroupUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .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("GroupId") + .HasColumnType("uuid"); + + 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("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("GroupId"); + + b.ToTable("EmailGroupUsers", "Notifications"); + }); + + modelBuilder.Entity("Unity.Notifications.Emails.EmailLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ApplicantId") + .HasColumnType("uuid"); + + b.Property("ApplicationId") + .HasColumnType("uuid"); + + b.Property("AssessmentId") + .HasColumnType("uuid"); + + b.Property("BCC") + .IsRequired() + .HasColumnType("text"); + + b.Property("Body") + .IsRequired() + .HasColumnType("text"); + + b.Property("BodyType") + .IsRequired() + .HasColumnType("text"); + + b.Property("CC") + .IsRequired() + .HasColumnType("text"); + + b.Property("ChesMsgId") + .HasColumnType("uuid"); + + b.Property("ChesResponse") + .IsRequired() + .HasColumnType("text"); + + b.Property("ChesStatus") + .IsRequired() + .HasColumnType("text"); + + 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("FromAddress") + .IsRequired() + .HasColumnType("text"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("Priority") + .IsRequired() + .HasColumnType("text"); + + b.Property("RetryAttempts") + .HasColumnType("integer"); + + b.Property("SendOnDateTime") + .HasColumnType("timestamp without time zone"); + + b.Property("SentDateTime") + .HasColumnType("timestamp without time zone"); + + b.Property("Status") + .IsRequired() + .HasColumnType("text"); + + b.Property("Subject") + .IsRequired() + .HasColumnType("text"); + + b.Property("Tag") + .IsRequired() + .HasColumnType("text"); + + b.Property("TemplateName") + .IsRequired() + .HasColumnType("text"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("ToAddress") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("EmailLogs", "Notifications"); + }); + + modelBuilder.Entity("Unity.Notifications.Templates.EmailTemplate", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("BodyHTML") + .IsRequired() + .HasColumnType("text"); + + b.Property("BodyText") + .IsRequired() + .HasColumnType("text"); + + 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() + .HasColumnType("text"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + 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("SendFrom") + .IsRequired() + .HasColumnType("text"); + + b.Property("Subject") + .IsRequired() + .HasColumnType("text"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.ToTable("EmailTemplates", "Notifications"); + }); + + modelBuilder.Entity("Unity.Notifications.Templates.Subscriber", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .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("Email") + .IsRequired() + .HasColumnType("text"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("FirstName") + .IsRequired() + .HasColumnType("text"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("LastName") + .IsRequired() + .HasColumnType("text"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.ToTable("Subscribers", "Notifications"); + }); + + modelBuilder.Entity("Unity.Notifications.Templates.SubscriptionGroup", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .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("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.ToTable("SubscriptionGroups", "Notifications"); + }); + + modelBuilder.Entity("Unity.Notifications.Templates.SubscriptionGroupSubscription", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .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("GroupId") + .HasColumnType("uuid"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("SubscriberId") + .HasColumnType("uuid"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("GroupId"); + + b.HasIndex("SubscriberId"); + + b.ToTable("SubscriptionGroupSubscribers", "Notifications"); + }); + + modelBuilder.Entity("Unity.Notifications.Templates.TemplateVariable", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .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("MapTo") + .IsRequired() + .HasColumnType("text"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("Token") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("TemplateVariables", "Notifications"); + }); + + modelBuilder.Entity("Unity.Notifications.Templates.Trigger", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Active") + .HasColumnType("boolean"); + + 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("InternalName") + .IsRequired() + .HasColumnType("text"); + + 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("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.ToTable("Triggers", "Notifications"); + }); + + modelBuilder.Entity("Unity.Notifications.Templates.TriggerSubscription", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .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("SubscriptionGroupId") + .HasColumnType("uuid"); + + b.Property("TemplateId") + .HasColumnType("uuid"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("TriggerId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("SubscriptionGroupId"); + + b.HasIndex("TemplateId"); + + b.HasIndex("TriggerId"); + + b.ToTable("TriggerSubscriptions", "Notifications"); + }); + + modelBuilder.Entity("Unity.Payments.Domain.AccountCodings.AccountCoding", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .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("MinistryClient") + .IsRequired() + .HasColumnType("text"); + + b.Property("ProjectNumber") + .IsRequired() + .HasColumnType("text"); + + b.Property("Responsibility") + .IsRequired() + .HasColumnType("text"); + + b.Property("ServiceLine") + .IsRequired() + .HasColumnType("text"); + + b.Property("Stob") + .IsRequired() + .HasColumnType("text"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.ToTable("AccountCodings", "Payments"); + }); + + modelBuilder.Entity("Unity.Payments.Domain.PaymentConfigurations.PaymentConfiguration", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .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("DefaultAccountCodingId") + .HasColumnType("uuid"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("DeletionTime"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("PaymentIdPrefix") + .IsRequired() + .HasColumnType("text"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.ToTable("PaymentConfigurations", "Payments"); + }); + + modelBuilder.Entity("Unity.Payments.Domain.PaymentRequests.ExpenseApproval", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DecisionDate") + .HasColumnType("timestamp without time zone"); + + b.Property("DecisionUserId") + .HasColumnType("uuid"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("DeletionTime"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("PaymentRequestId") + .HasColumnType("uuid"); + + b.Property("Status") + .HasColumnType("integer"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("Type") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("PaymentRequestId"); + + b.ToTable("ExpenseApprovals", "Payments"); + }); + + modelBuilder.Entity("Unity.Payments.Domain.PaymentRequests.PaymentRequest", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("AccountCodingId") + .HasColumnType("uuid"); + + b.Property("Amount") + .HasColumnType("numeric"); + + b.Property("BatchName") + .IsRequired() + .HasColumnType("text"); + + b.Property("BatchNumber") + .HasColumnType("numeric"); + + b.Property("CasHttpStatusCode") + .HasColumnType("integer"); + + b.Property("CasResponse") + .HasColumnType("text"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("ContractNumber") + .IsRequired() + .HasColumnType("text"); + + b.Property("CorrelationId") + .HasColumnType("uuid"); + + b.Property("CorrelationProvider") + .IsRequired() + .HasColumnType("text"); + + 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") + .HasColumnType("text"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("InvoiceNumber") + .IsRequired() + .HasColumnType("text"); + + b.Property("InvoiceStatus") + .HasColumnType("text"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("IsRecon") + .HasColumnType("boolean"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("Note") + .HasColumnType("text"); + + b.Property("PayeeName") + .IsRequired() + .HasColumnType("text"); + + b.Property("PaymentDate") + .HasColumnType("text"); + + b.Property("PaymentNumber") + .HasColumnType("text"); + + b.Property("PaymentStatus") + .HasColumnType("text"); + + b.Property("ReferenceNumber") + .IsRequired() + .HasColumnType("text"); + + b.Property("RequesterName") + .IsRequired() + .HasColumnType("text"); + + b.Property("SiteId") + .HasColumnType("uuid"); + + b.Property("Status") + .HasColumnType("integer"); + + b.Property("SubmissionConfirmationCode") + .IsRequired() + .HasColumnType("text"); + + b.Property("SupplierName") + .HasColumnType("text"); + + b.Property("SupplierNumber") + .IsRequired() + .HasColumnType("text"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("AccountCodingId"); + + b.HasIndex("ReferenceNumber") + .IsUnique(); + + b.HasIndex("SiteId"); + + b.ToTable("PaymentRequests", "Payments"); + }); + + modelBuilder.Entity("Unity.Payments.Domain.PaymentTags.PaymentTag", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .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("PaymentRequestId") + .HasColumnType("uuid"); + + b.Property("TagId") + .HasColumnType("uuid"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("Text") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("PaymentRequestId"); + + b.HasIndex("TagId"); + + b.ToTable("PaymentTags", "Payments"); + }); + + modelBuilder.Entity("Unity.Payments.Domain.PaymentThresholds.PaymentThreshold", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .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") + .HasColumnType("text"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + 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("Threshold") + .HasColumnType("numeric"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.ToTable("PaymentThresholds", "Payments"); + }); + + modelBuilder.Entity("Unity.Payments.Domain.Suppliers.Site", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("AddressLine1") + .HasColumnType("text"); + + b.Property("AddressLine2") + .HasColumnType("text"); + + b.Property("AddressLine3") + .HasColumnType("text"); + + b.Property("BankAccount") + .HasColumnType("text"); + + b.Property("City") + .HasColumnType("text"); + + b.Property("Country") + .HasColumnType("text"); + + 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("EFTAdvicePref") + .HasColumnType("text"); + + b.Property("EmailAddress") + .HasColumnType("text"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("LastUpdatedInCas") + .HasColumnType("timestamp without time zone"); + + b.Property("MarkDeletedInUse") + .HasColumnType("boolean"); + + b.Property("Number") + .IsRequired() + .HasColumnType("text"); + + b.Property("PaymentGroup") + .HasColumnType("integer"); + + b.Property("PostalCode") + .HasColumnType("text"); + + b.Property("ProviderId") + .HasColumnType("text"); + + b.Property("Province") + .HasColumnType("text"); + + b.Property("SiteProtected") + .HasColumnType("text"); + + b.Property("Status") + .HasColumnType("text"); + + b.Property("SupplierId") + .HasColumnType("uuid"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("SupplierId"); + + b.ToTable("Sites", "Payments"); + }); + + modelBuilder.Entity("Unity.Payments.Domain.Suppliers.Supplier", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("BusinessNumber") + .HasColumnType("text"); + + b.Property("City") + .HasColumnType("text"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CorrelationId") + .HasColumnType("uuid"); + + b.Property("CorrelationProvider") + .IsRequired() + .HasColumnType("text"); + + 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("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("LastUpdatedInCAS") + .HasColumnType("timestamp without time zone"); + + b.Property("MailingAddress") + .HasColumnType("text"); + + b.Property("Name") + .HasColumnType("text"); + + b.Property("Number") + .HasColumnType("text"); + + b.Property("PostalCode") + .HasColumnType("text"); + + b.Property("ProviderId") + .HasColumnType("text"); + + b.Property("Province") + .HasColumnType("text"); + + b.Property("SIN") + .HasColumnType("text"); + + b.Property("StandardIndustryClassification") + .HasColumnType("text"); + + b.Property("Status") + .HasColumnType("text"); + + b.Property("Subcategory") + .HasColumnType("text"); + + b.Property("SupplierProtected") + .HasColumnType("text"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.ToTable("Suppliers", "Payments"); + }); + + modelBuilder.Entity("Unity.Flex.Domain.ScoresheetInstances.ScoresheetInstance", b => + { + b.HasOne("Unity.Flex.Domain.Scoresheets.Scoresheet", "Scoresheet") + .WithMany("Instances") + .HasForeignKey("ScoresheetId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Scoresheet"); + }); + + modelBuilder.Entity("Unity.Flex.Domain.Scoresheets.Answer", b => + { + b.HasOne("Unity.Flex.Domain.Scoresheets.Question", "Question") + .WithMany("Answers") + .HasForeignKey("QuestionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Unity.Flex.Domain.ScoresheetInstances.ScoresheetInstance", null) + .WithMany("Answers") + .HasForeignKey("ScoresheetInstanceId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Question"); + }); + + modelBuilder.Entity("Unity.Flex.Domain.Scoresheets.Question", b => + { + b.HasOne("Unity.Flex.Domain.Scoresheets.ScoresheetSection", "Section") + .WithMany("Fields") + .HasForeignKey("SectionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Section"); + }); + + modelBuilder.Entity("Unity.Flex.Domain.Scoresheets.ScoresheetSection", b => + { + b.HasOne("Unity.Flex.Domain.Scoresheets.Scoresheet", "Scoresheet") + .WithMany("Sections") + .HasForeignKey("ScoresheetId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Scoresheet"); + }); + + modelBuilder.Entity("Unity.Flex.Domain.WorksheetInstances.CustomFieldValue", b => + { + b.HasOne("Unity.Flex.Domain.WorksheetInstances.WorksheetInstance", null) + .WithMany("Values") + .HasForeignKey("WorksheetInstanceId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Unity.Flex.Domain.WorksheetLinks.WorksheetLink", b => + { + b.HasOne("Unity.Flex.Domain.Worksheets.Worksheet", "Worksheet") + .WithMany("Links") + .HasForeignKey("WorksheetId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Worksheet"); + }); + + modelBuilder.Entity("Unity.Flex.Domain.Worksheets.CustomField", b => + { + b.HasOne("Unity.Flex.Domain.Worksheets.WorksheetSection", "Section") + .WithMany("Fields") + .HasForeignKey("SectionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Section"); + }); + + modelBuilder.Entity("Unity.Flex.Domain.Worksheets.WorksheetSection", b => + { + b.HasOne("Unity.Flex.Domain.Worksheets.Worksheet", "Worksheet") + .WithMany("Sections") + .HasForeignKey("WorksheetId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Worksheet"); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicantAddress", b => + { + b.HasOne("Unity.GrantManager.Applications.Applicant", "Applicant") + .WithMany("ApplicantAddresses") + .HasForeignKey("ApplicantId") + .OnDelete(DeleteBehavior.NoAction) + .IsRequired(); + + b.HasOne("Unity.GrantManager.Applications.Application", "Application") + .WithMany("ApplicantAddresses") + .HasForeignKey("ApplicationId"); + + b.Navigation("Applicant"); + + b.Navigation("Application"); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicantAgent", b => + { + b.HasOne("Unity.GrantManager.Applications.Applicant", null) + .WithMany() + .HasForeignKey("ApplicantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Unity.GrantManager.Applications.Application", "Application") + .WithOne("ApplicantAgent") + .HasForeignKey("Unity.GrantManager.Applications.ApplicantAgent", "ApplicationId"); + + b.HasOne("Unity.GrantManager.Identity.Person", null) + .WithMany() + .HasForeignKey("OidcSubUser") + .HasPrincipalKey("OidcSub"); + + b.Navigation("Application"); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.Application", b => + { + b.HasOne("Unity.GrantManager.Applications.Applicant", "Applicant") + .WithMany() + .HasForeignKey("ApplicantId") + .OnDelete(DeleteBehavior.NoAction) + .IsRequired(); + + b.HasOne("Unity.GrantManager.Applications.ApplicationForm", "ApplicationForm") + .WithMany() + .HasForeignKey("ApplicationFormId") + .OnDelete(DeleteBehavior.NoAction) + .IsRequired(); + + b.HasOne("Unity.GrantManager.Applications.ApplicationStatus", "ApplicationStatus") + .WithMany("Applications") + .HasForeignKey("ApplicationStatusId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Unity.GrantManager.Identity.Person", "Owner") + .WithMany() + .HasForeignKey("OwnerId") + .OnDelete(DeleteBehavior.NoAction); + + b.Navigation("Applicant"); + + b.Navigation("ApplicationForm"); + + b.Navigation("ApplicationStatus"); + + b.Navigation("Owner"); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicationAssignment", b => + { + b.HasOne("Unity.GrantManager.Applications.Application", "Application") + .WithMany("ApplicationAssignments") + .HasForeignKey("ApplicationId") + .OnDelete(DeleteBehavior.NoAction) + .IsRequired(); + + b.HasOne("Unity.GrantManager.Identity.Person", "Assignee") + .WithMany() + .HasForeignKey("AssigneeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Application"); + + b.Navigation("Assignee"); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicationAttachment", b => + { + b.HasOne("Unity.GrantManager.Applications.Application", null) + .WithMany() + .HasForeignKey("ApplicationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicationChefsFileAttachment", b => + { + b.HasOne("Unity.GrantManager.Applications.Application", null) + .WithMany() + .HasForeignKey("ApplicationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicationContact", b => + { + b.HasOne("Unity.GrantManager.Applications.Application", null) + .WithMany() + .HasForeignKey("ApplicationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicationForm", b => + { + b.HasOne("Unity.GrantManager.Intakes.Intake", null) + .WithMany() + .HasForeignKey("IntakeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicationFormSubmission", b => + { + b.HasOne("Unity.GrantManager.Applications.Applicant", null) + .WithMany() + .HasForeignKey("ApplicantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Unity.GrantManager.Applications.ApplicationForm", null) + .WithMany() + .HasForeignKey("ApplicationFormId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicationFormVersion", b => + { + b.HasOne("Unity.GrantManager.Applications.ApplicationForm", null) + .WithMany() + .HasForeignKey("ApplicationFormId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicationLink", b => + { + b.HasOne("Unity.GrantManager.Applications.Application", null) + .WithMany() + .HasForeignKey("ApplicationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicationTags", b => + { + b.HasOne("Unity.GrantManager.Applications.Application", "Application") + .WithMany("ApplicationTags") + .HasForeignKey("ApplicationId") + .OnDelete(DeleteBehavior.NoAction) + .IsRequired(); + + b.HasOne("Unity.GrantManager.GlobalTag.Tag", "Tag") + .WithMany() + .HasForeignKey("TagId") + .OnDelete(DeleteBehavior.NoAction) + .IsRequired(); + + b.Navigation("Application"); + + b.Navigation("Tag"); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.AssessmentAttachment", b => + { + b.HasOne("Unity.GrantManager.Assessments.Assessment", null) + .WithMany() + .HasForeignKey("AssessmentId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Unity.GrantManager.Assessments.Assessment", b => + { + b.HasOne("Unity.GrantManager.Applications.Application", "Application") + .WithMany("Assessments") + .HasForeignKey("ApplicationId") + .OnDelete(DeleteBehavior.NoAction) + .IsRequired(); + + b.HasOne("Unity.GrantManager.Identity.Person", null) + .WithMany() + .HasForeignKey("AssessorId") + .OnDelete(DeleteBehavior.NoAction) + .IsRequired(); + + b.Navigation("Application"); + }); + + modelBuilder.Entity("Unity.GrantManager.Comments.ApplicationComment", b => + { + b.HasOne("Unity.GrantManager.Applications.Application", null) + .WithMany() + .HasForeignKey("ApplicationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Unity.GrantManager.Identity.Person", null) + .WithMany() + .HasForeignKey("CommenterId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Unity.GrantManager.Comments.AssessmentComment", b => + { + b.HasOne("Unity.GrantManager.Assessments.Assessment", null) + .WithMany() + .HasForeignKey("AssessmentId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Unity.GrantManager.Identity.Person", null) + .WithMany() + .HasForeignKey("CommenterId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Unity.Notifications.EmailGroups.EmailGroupUser", b => + { + b.HasOne("Unity.Notifications.EmailGroups.EmailGroup", null) + .WithMany() + .HasForeignKey("GroupId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Unity.Notifications.Templates.SubscriptionGroupSubscription", b => + { + b.HasOne("Unity.Notifications.Templates.SubscriptionGroup", "SubscriptionGroup") + .WithMany() + .HasForeignKey("GroupId"); + + b.HasOne("Unity.Notifications.Templates.Subscriber", "Subscriber") + .WithMany() + .HasForeignKey("SubscriberId"); + + b.Navigation("Subscriber"); + + b.Navigation("SubscriptionGroup"); + }); + + modelBuilder.Entity("Unity.Notifications.Templates.TriggerSubscription", b => + { + b.HasOne("Unity.Notifications.Templates.SubscriptionGroup", "SubscriptionGroup") + .WithMany() + .HasForeignKey("SubscriptionGroupId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Unity.Notifications.Templates.EmailTemplate", "EmailTemplate") + .WithMany() + .HasForeignKey("TemplateId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Unity.Notifications.Templates.Trigger", "Trigger") + .WithMany() + .HasForeignKey("TriggerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("EmailTemplate"); + + b.Navigation("SubscriptionGroup"); + + b.Navigation("Trigger"); + }); + + modelBuilder.Entity("Unity.Payments.Domain.PaymentRequests.ExpenseApproval", b => + { + b.HasOne("Unity.Payments.Domain.PaymentRequests.PaymentRequest", "PaymentRequest") + .WithMany("ExpenseApprovals") + .HasForeignKey("PaymentRequestId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("PaymentRequest"); + }); + + modelBuilder.Entity("Unity.Payments.Domain.PaymentRequests.PaymentRequest", b => + { + b.HasOne("Unity.Payments.Domain.AccountCodings.AccountCoding", "AccountCoding") + .WithMany() + .HasForeignKey("AccountCodingId") + .OnDelete(DeleteBehavior.NoAction); + + b.HasOne("Unity.Payments.Domain.Suppliers.Site", "Site") + .WithMany() + .HasForeignKey("SiteId") + .OnDelete(DeleteBehavior.NoAction) + .IsRequired(); + + b.Navigation("AccountCoding"); + + b.Navigation("Site"); + }); + + modelBuilder.Entity("Unity.Payments.Domain.PaymentTags.PaymentTag", b => + { + b.HasOne("Unity.Payments.Domain.PaymentRequests.PaymentRequest", null) + .WithMany("PaymentTags") + .HasForeignKey("PaymentRequestId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Unity.GrantManager.GlobalTag.Tag", "Tag") + .WithMany() + .HasForeignKey("TagId") + .OnDelete(DeleteBehavior.NoAction) + .IsRequired(); + + b.Navigation("Tag"); + }); + + modelBuilder.Entity("Unity.Payments.Domain.Suppliers.Site", b => + { + b.HasOne("Unity.Payments.Domain.Suppliers.Supplier", "Supplier") + .WithMany("Sites") + .HasForeignKey("SupplierId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Supplier"); + }); + + modelBuilder.Entity("Unity.Flex.Domain.ScoresheetInstances.ScoresheetInstance", b => + { + b.Navigation("Answers"); + }); + + modelBuilder.Entity("Unity.Flex.Domain.Scoresheets.Question", b => + { + b.Navigation("Answers"); + }); + + modelBuilder.Entity("Unity.Flex.Domain.Scoresheets.Scoresheet", b => + { + b.Navigation("Instances"); + + b.Navigation("Sections"); + }); + + modelBuilder.Entity("Unity.Flex.Domain.Scoresheets.ScoresheetSection", b => + { + b.Navigation("Fields"); + }); + + modelBuilder.Entity("Unity.Flex.Domain.WorksheetInstances.WorksheetInstance", b => + { + b.Navigation("Values"); + }); + + modelBuilder.Entity("Unity.Flex.Domain.Worksheets.Worksheet", b => + { + b.Navigation("Links"); + + b.Navigation("Sections"); + }); + + modelBuilder.Entity("Unity.Flex.Domain.Worksheets.WorksheetSection", b => + { + b.Navigation("Fields"); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.Applicant", b => + { + b.Navigation("ApplicantAddresses"); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.Application", b => + { + b.Navigation("ApplicantAddresses"); + + b.Navigation("ApplicantAgent"); + + b.Navigation("ApplicationAssignments"); + + b.Navigation("ApplicationTags"); + + b.Navigation("Assessments"); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicationStatus", b => + { + b.Navigation("Applications"); + }); + + modelBuilder.Entity("Unity.Payments.Domain.PaymentRequests.PaymentRequest", b => + { + b.Navigation("ExpenseApprovals"); + + b.Navigation("PaymentTags"); + }); + + modelBuilder.Entity("Unity.Payments.Domain.Suppliers.Supplier", b => + { + b.Navigation("Sites"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.EntityFrameworkCore/Migrations/TenantMigrations/20250815155039_DropPaymentColumns.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.EntityFrameworkCore/Migrations/TenantMigrations/20250815155039_DropPaymentColumns.cs new file mode 100644 index 000000000..bc7a3a065 --- /dev/null +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.EntityFrameworkCore/Migrations/TenantMigrations/20250815155039_DropPaymentColumns.cs @@ -0,0 +1,72 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Unity.GrantManager.Migrations.TenantMigrations +{ + /// + public partial class DropPaymentColumns : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.Sql(@" + DO $$ + BEGIN + IF EXISTS ( + SELECT 1 FROM information_schema.columns + WHERE table_schema = 'Payments' + AND table_name = 'PaymentConfigurations' + AND column_name = 'MinistryClient' + ) THEN + ALTER TABLE ""Payments"".""PaymentConfigurations"" DROP COLUMN ""MinistryClient""; + END IF; + + IF EXISTS ( + SELECT 1 FROM information_schema.columns + WHERE table_schema = 'Payments' + AND table_name = 'PaymentConfigurations' + AND column_name = 'Responsibility' + ) THEN + ALTER TABLE ""Payments"".""PaymentConfigurations"" DROP COLUMN ""Responsibility""; + END IF; + + IF EXISTS ( + SELECT 1 FROM information_schema.columns + WHERE table_schema = 'Payments' + AND table_name = 'PaymentConfigurations' + AND column_name = 'Stob' + ) THEN + ALTER TABLE ""Payments"".""PaymentConfigurations"" DROP COLUMN ""Stob""; + END IF; + + IF EXISTS ( + SELECT 1 FROM information_schema.columns + WHERE table_schema = 'Payments' + AND table_name = 'PaymentConfigurations' + AND column_name = 'ServiceLine' + ) THEN + ALTER TABLE ""Payments"".""PaymentConfigurations"" DROP COLUMN ""ServiceLine""; + END IF; + + IF EXISTS ( + SELECT 1 FROM information_schema.columns + WHERE table_schema = 'Payments' + AND table_name = 'PaymentConfigurations' + AND column_name = 'ProjectNumber' + ) THEN + ALTER TABLE ""Payments"".""PaymentConfigurations"" DROP COLUMN ""ProjectNumber""; + END IF; + END + $$ LANGUAGE plpgsql; + "); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + + } + } +} diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.EntityFrameworkCore/Migrations/TenantMigrations/20250819182438_AB29758_Remove_Legacy_Tags.Designer.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.EntityFrameworkCore/Migrations/TenantMigrations/20250819182438_AB29758_Remove_Legacy_Tags.Designer.cs new file mode 100644 index 000000000..cea28a574 --- /dev/null +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.EntityFrameworkCore/Migrations/TenantMigrations/20250819182438_AB29758_Remove_Legacy_Tags.Designer.cs @@ -0,0 +1,4225 @@ +// +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.TenantMigrations +{ + [DbContext(typeof(GrantTenantDbContext))] + [Migration("20250819182438_AB29758_Remove_Legacy_Tags")] + partial class AB29758_Remove_Legacy_Tags + { + /// + 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("Unity.Flex.Domain.ScoresheetInstances.ScoresheetInstance", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CorrelationId") + .HasColumnType("uuid"); + + b.Property("CorrelationProvider") + .IsRequired() + .HasColumnType("text"); + + 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("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("ReportData") + .IsRequired() + .HasColumnType("jsonb"); + + b.Property("ScoresheetId") + .HasColumnType("uuid"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("Value") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("ScoresheetId"); + + b.ToTable("ScoresheetInstances", "Flex"); + }); + + modelBuilder.Entity("Unity.Flex.Domain.Scoresheets.Answer", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("CurrentValue") + .HasColumnType("jsonb"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("DeletionTime"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("QuestionId") + .HasColumnType("uuid"); + + b.Property("ScoresheetInstanceId") + .HasColumnType("uuid"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("Version") + .HasColumnType("bigint"); + + b.HasKey("Id"); + + b.HasIndex("QuestionId"); + + b.HasIndex("ScoresheetInstanceId"); + + b.ToTable("Answers", "Flex"); + }); + + modelBuilder.Entity("Unity.Flex.Domain.Scoresheets.Question", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("Definition") + .IsRequired() + .HasColumnType("jsonb"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("DeletionTime"); + + b.Property("Description") + .HasColumnType("text"); + + b.Property("Enabled") + .HasColumnType("boolean"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("Label") + .IsRequired() + .HasColumnType("text"); + + 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("Order") + .HasColumnType("bigint"); + + b.Property("SectionId") + .HasColumnType("uuid"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("Type") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("SectionId"); + + b.ToTable("Questions", "Flex"); + }); + + modelBuilder.Entity("Unity.Flex.Domain.Scoresheets.Scoresheet", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .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("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + 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("Order") + .HasColumnType("bigint"); + + b.Property("Published") + .HasColumnType("boolean"); + + b.Property("ReportColumns") + .IsRequired() + .HasColumnType("text"); + + b.Property("ReportKeys") + .IsRequired() + .HasColumnType("text"); + + b.Property("ReportViewName") + .IsRequired() + .HasColumnType("text"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("Title") + .IsRequired() + .HasColumnType("text"); + + b.Property("Version") + .HasColumnType("bigint"); + + b.HasKey("Id"); + + b.ToTable("Scoresheets", "Flex"); + }); + + modelBuilder.Entity("Unity.Flex.Domain.Scoresheets.ScoresheetSection", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + 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("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + 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("Order") + .HasColumnType("bigint"); + + b.Property("ScoresheetId") + .HasColumnType("uuid"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("ScoresheetId"); + + b.ToTable("ScoresheetSections", "Flex"); + }); + + modelBuilder.Entity("Unity.Flex.Domain.WorksheetInstances.CustomFieldValue", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("CurrentValue") + .IsRequired() + .HasColumnType("jsonb"); + + b.Property("CustomFieldId") + .HasColumnType("uuid"); + + 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("WorksheetInstanceId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("WorksheetInstanceId"); + + b.ToTable("CustomFieldValues", "Flex"); + }); + + modelBuilder.Entity("Unity.Flex.Domain.WorksheetInstances.WorksheetInstance", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CorrelationId") + .HasColumnType("uuid"); + + b.Property("CorrelationProvider") + .IsRequired() + .HasColumnType("text"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("CurrentValue") + .IsRequired() + .HasColumnType("jsonb"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("DeletionTime"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("ReportData") + .IsRequired() + .HasColumnType("jsonb"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("UiAnchor") + .IsRequired() + .HasColumnType("text"); + + b.Property("WorksheetCorrelationId") + .HasColumnType("uuid"); + + b.Property("WorksheetCorrelationProvider") + .IsRequired() + .HasColumnType("text"); + + b.Property("WorksheetId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.ToTable("WorksheetInstances", "Flex"); + }); + + modelBuilder.Entity("Unity.Flex.Domain.WorksheetLinks.WorksheetLink", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CorrelationId") + .HasColumnType("uuid"); + + b.Property("CorrelationProvider") + .IsRequired() + .HasColumnType("text"); + + 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("Order") + .HasColumnType("bigint"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("UiAnchor") + .IsRequired() + .HasColumnType("text"); + + b.Property("WorksheetId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("WorksheetId"); + + b.ToTable("WorksheetLinks", "Flex"); + }); + + modelBuilder.Entity("Unity.Flex.Domain.Worksheets.CustomField", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("Definition") + .IsRequired() + .HasColumnType("jsonb"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("DeletionTime"); + + b.Property("Enabled") + .HasColumnType("boolean"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("Key") + .IsRequired() + .HasColumnType("text"); + + b.Property("Label") + .IsRequired() + .HasColumnType("text"); + + 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("Order") + .HasColumnType("bigint"); + + b.Property("SectionId") + .HasColumnType("uuid"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("Type") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("SectionId"); + + b.ToTable("CustomFields", "Flex"); + }); + + modelBuilder.Entity("Unity.Flex.Domain.Worksheets.Worksheet", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .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("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + 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("Published") + .HasColumnType("boolean"); + + b.Property("ReportColumns") + .IsRequired() + .HasColumnType("text"); + + b.Property("ReportKeys") + .IsRequired() + .HasColumnType("text"); + + b.Property("ReportViewName") + .IsRequired() + .HasColumnType("text"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("Title") + .IsRequired() + .HasColumnType("text"); + + b.Property("Version") + .HasColumnType("bigint"); + + b.HasKey("Id"); + + b.ToTable("Worksheets", "Flex"); + }); + + modelBuilder.Entity("Unity.Flex.Domain.Worksheets.WorksheetSection", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + 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("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + 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("Order") + .HasColumnType("bigint"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("WorksheetId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("WorksheetId"); + + b.ToTable("WorksheetSections", "Flex"); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.Applicant", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ApplicantName") + .IsRequired() + .HasMaxLength(600) + .HasColumnType("character varying(600)"); + + b.Property("ApproxNumberOfEmployees") + .HasColumnType("text"); + + b.Property("BusinessNumber") + .HasColumnType("text"); + + 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("ElectoralDistrict") + .HasColumnType("text"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("FiscalDay") + .HasColumnType("integer"); + + b.Property("FiscalMonth") + .HasColumnType("text"); + + b.Property("IndigenousOrgInd") + .HasColumnType("text"); + + b.Property("IsDuplicated") + .HasColumnType("boolean"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("MatchPercentage") + .HasColumnType("numeric"); + + b.Property("NonRegOrgName") + .HasColumnType("text"); + + b.Property("NonRegisteredBusinessName") + .HasColumnType("text"); + + b.Property("OrgName") + .HasColumnType("text"); + + b.Property("OrgNumber") + .HasColumnType("text"); + + b.Property("OrgStatus") + .HasColumnType("text"); + + b.Property("OrganizationSize") + .HasColumnType("text"); + + b.Property("OrganizationType") + .HasColumnType("text"); + + b.Property("RedStop") + .HasColumnType("boolean"); + + b.Property("Sector") + .HasColumnType("text"); + + b.Property("SectorSubSectorIndustryDesc") + .HasColumnType("text"); + + b.Property("SiteId") + .HasColumnType("uuid"); + + b.Property("StartedOperatingDate") + .HasColumnType("date"); + + b.Property("Status") + .HasColumnType("text"); + + b.Property("SubSector") + .HasColumnType("text"); + + b.Property("SupplierId") + .HasColumnType("uuid"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("UnityApplicantId") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("ApplicantName"); + + b.ToTable("Applicants", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicantAddress", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("AddressType") + .HasColumnType("integer"); + + b.Property("ApplicantId") + .HasColumnType("uuid"); + + b.Property("ApplicationId") + .HasColumnType("uuid"); + + b.Property("City") + .HasColumnType("text"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("Country") + .HasColumnType("text"); + + 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("Postal") + .HasColumnType("text"); + + b.Property("Province") + .HasColumnType("text"); + + b.Property("Street") + .HasColumnType("text"); + + b.Property("Street2") + .HasColumnType("text"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("Unit") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("ApplicantId"); + + b.HasIndex("ApplicationId"); + + b.ToTable("ApplicantAddresses", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicantAgent", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ApplicantId") + .HasColumnType("uuid"); + + b.Property("ApplicationId") + .HasColumnType("uuid"); + + b.Property("BceidBusinessGuid") + .HasColumnType("uuid"); + + b.Property("BceidBusinessName") + .HasColumnType("text"); + + b.Property("BceidUserGuid") + .HasColumnType("uuid"); + + b.Property("BceidUserName") + .HasColumnType("text"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("ContactOrder") + .HasColumnType("integer"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("Email") + .HasColumnType("text"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IdentityEmail") + .HasColumnType("text"); + + b.Property("IdentityName") + .HasColumnType("text"); + + b.Property("IdentityProvider") + .HasColumnType("text"); + + b.Property("IsActive") + .HasColumnType("boolean"); + + b.Property("IsConfirmed") + .HasColumnType("boolean"); + + 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("OidcSubUser") + .HasColumnType("text"); + + b.Property("Phone") + .HasColumnType("text"); + + b.Property("Phone2") + .HasColumnType("text"); + + b.Property("Phone2Extension") + .HasColumnType("text"); + + b.Property("PhoneExtension") + .HasColumnType("text"); + + b.Property("RoleForApplicant") + .IsRequired() + .HasColumnType("text"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("Title") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("ApplicantId"); + + b.HasIndex("ApplicationId") + .IsUnique(); + + b.HasIndex("OidcSubUser"); + + b.ToTable("ApplicantAgents", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.Application", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("Acquisition") + .HasColumnType("text"); + + b.Property("ApplicantId") + .HasColumnType("uuid"); + + b.Property("ApplicationFormId") + .HasColumnType("uuid"); + + b.Property("ApplicationStatusId") + .HasColumnType("uuid"); + + b.Property("ApprovedAmount") + .HasColumnType("numeric"); + + b.Property("AssessmentResultDate") + .HasColumnType("timestamp without time zone"); + + b.Property("AssessmentResultStatus") + .HasColumnType("text"); + + b.Property("AssessmentStartDate") + .HasColumnType("timestamp without time zone"); + + b.Property("City") + .HasColumnType("text"); + + b.Property("Community") + .HasColumnType("text"); + + b.Property("CommunityPopulation") + .HasColumnType("integer"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("ContractExecutionDate") + .HasColumnType("timestamp without time zone"); + + b.Property("ContractNumber") + .HasColumnType("text"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DeclineRational") + .HasColumnType("text"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("DeletionTime"); + + b.Property("DueDate") + .HasColumnType("timestamp without time zone"); + + b.Property("DueDiligenceStatus") + .HasColumnType("text"); + + b.Property("EconomicRegion") + .HasColumnType("text"); + + b.Property("ElectoralDistrict") + .HasColumnType("text"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("FinalDecisionDate") + .HasColumnType("timestamp without time zone"); + + b.Property("Forestry") + .HasColumnType("text"); + + b.Property("ForestryFocus") + .HasColumnType("text"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("LikelihoodOfFunding") + .HasColumnType("text"); + + b.Property("Notes") + .HasColumnType("text"); + + b.Property("NotificationDate") + .HasColumnType("timestamp without time zone"); + + b.Property("OwnerId") + .HasColumnType("uuid"); + + b.Property("Payload") + .HasColumnType("jsonb"); + + b.Property("PercentageTotalProjectBudget") + .HasColumnType("double precision"); + + b.Property("Place") + .HasColumnType("text"); + + b.Property("ProjectEndDate") + .HasColumnType("timestamp without time zone"); + + b.Property("ProjectFundingTotal") + .HasColumnType("numeric"); + + b.Property("ProjectName") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.Property("ProjectStartDate") + .HasColumnType("timestamp without time zone"); + + b.Property("ProjectSummary") + .HasColumnType("text"); + + b.Property("ProposalDate") + .HasColumnType("timestamp without time zone"); + + b.Property("RecommendedAmount") + .HasColumnType("numeric"); + + b.Property("ReferenceNo") + .IsRequired() + .HasColumnType("text"); + + b.Property("RegionalDistrict") + .HasColumnType("text"); + + b.Property("RequestedAmount") + .HasColumnType("numeric"); + + b.Property("RiskRanking") + .HasColumnType("text"); + + b.Property("SigningAuthorityBusinessPhone") + .HasColumnType("text"); + + b.Property("SigningAuthorityCellPhone") + .HasColumnType("text"); + + b.Property("SigningAuthorityEmail") + .HasColumnType("text"); + + b.Property("SigningAuthorityFullName") + .HasColumnType("text"); + + b.Property("SigningAuthorityTitle") + .HasColumnType("text"); + + b.Property("SubStatus") + .HasColumnType("text"); + + b.Property("SubmissionDate") + .HasColumnType("timestamp without time zone"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("TotalProjectBudget") + .HasColumnType("numeric"); + + b.Property("TotalScore") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("ApplicantId"); + + b.HasIndex("ApplicationFormId"); + + b.HasIndex("ApplicationStatusId"); + + b.HasIndex("OwnerId"); + + b.ToTable("Applications", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicationAssignment", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ApplicationId") + .HasColumnType("uuid"); + + b.Property("AssigneeId") + .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("Duty") + .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("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("ApplicationId"); + + b.HasIndex("AssigneeId"); + + b.ToTable("ApplicationAssignments", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicationAttachment", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ApplicationId") + .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("DisplayName") + .HasMaxLength(1024) + .HasColumnType("character varying(1024)"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("FileName") + .HasColumnType("text"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("S3ObjectKey") + .IsRequired() + .HasColumnType("text"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("Time") + .HasColumnType("timestamp without time zone"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("ApplicationId"); + + b.ToTable("ApplicationAttachments", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicationChefsFileAttachment", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ApplicationId") + .HasColumnType("uuid"); + + b.Property("ChefsFileId") + .HasColumnType("text"); + + b.Property("ChefsSumbissionId") + .HasColumnType("text"); + + 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("DisplayName") + .HasMaxLength(1024) + .HasColumnType("character varying(1024)"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("FileName") + .HasColumnType("text"); + + 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.HasKey("Id"); + + b.HasIndex("ApplicationId"); + + b.ToTable("ApplicationChefsFileAttachments", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicationContact", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ApplicationId") + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("ContactEmail") + .HasColumnType("text"); + + b.Property("ContactFullName") + .IsRequired() + .HasColumnType("text"); + + b.Property("ContactMobilePhone") + .HasColumnType("text"); + + b.Property("ContactTitle") + .HasColumnType("text"); + + b.Property("ContactType") + .IsRequired() + .HasColumnType("text"); + + b.Property("ContactWorkPhone") + .HasColumnType("text"); + + 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("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("ApplicationId"); + + b.ToTable("ApplicationContact", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicationForm", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("AccountCodingId") + .HasColumnType("uuid"); + + b.Property("ApiKey") + .HasColumnType("text"); + + b.Property("ApplicationFormDescription") + .HasColumnType("text"); + + b.Property("ApplicationFormName") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.Property("AttemptedConnectionDate") + .HasColumnType("timestamp without time zone"); + + b.Property("AvailableChefsFields") + .HasColumnType("text"); + + b.Property("Category") + .HasColumnType("text"); + + b.Property("ChefsApplicationFormGuid") + .HasColumnType("text"); + + b.Property("ChefsCriteriaFormGuid") + .HasColumnType("text"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("ConnectionHttpStatus") + .HasColumnType("text"); + + 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("ElectoralDistrictAddressType") + .HasColumnType("integer"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IntakeId") + .HasColumnType("uuid"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("IsDirectApproval") + .HasColumnType("boolean"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("Payable") + .HasColumnType("boolean"); + + b.Property("PaymentApprovalThreshold") + .HasColumnType("numeric"); + + b.Property("PreventPayment") + .HasColumnType("boolean"); + + b.Property("RenderFormIoToHtml") + .HasColumnType("boolean"); + + b.Property("ScoresheetId") + .HasColumnType("uuid"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("Version") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("IntakeId"); + + b.ToTable("ApplicationForms", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicationFormSubmission", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ApplicantId") + .HasColumnType("uuid"); + + b.Property("ApplicationFormId") + .HasColumnType("uuid"); + + b.Property("ApplicationFormVersionId") + .HasColumnType("uuid"); + + b.Property("ApplicationId") + .HasColumnType("uuid"); + + b.Property("ChefsSubmissionGuid") + .IsRequired() + .HasColumnType("text"); + + 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("FormVersionId") + .HasColumnType("uuid"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("OidcSub") + .IsRequired() + .HasColumnType("text"); + + b.Property("RenderedHTML") + .HasColumnType("text"); + + b.Property("ReportData") + .IsRequired() + .HasColumnType("jsonb"); + + b.Property("Submission") + .IsRequired() + .HasColumnType("jsonb"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("ApplicantId"); + + b.HasIndex("ApplicationFormId"); + + b.ToTable("ApplicationFormSubmissions", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicationFormVersion", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ApplicationFormId") + .HasColumnType("uuid"); + + b.Property("AvailableChefsFields") + .HasColumnType("text"); + + b.Property("ChefsApplicationFormGuid") + .HasColumnType("text"); + + b.Property("ChefsFormVersionGuid") + .HasColumnType("text"); + + 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("FormSchema") + .HasColumnType("jsonb"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("Published") + .HasColumnType("boolean"); + + b.Property("ReportColumns") + .IsRequired() + .HasColumnType("text"); + + b.Property("ReportKeys") + .IsRequired() + .HasColumnType("text"); + + b.Property("ReportViewName") + .IsRequired() + .HasColumnType("text"); + + b.Property("SubmissionHeaderMapping") + .HasColumnType("text"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("Version") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("ApplicationFormId"); + + b.ToTable("ApplicationFormVersion", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicationLink", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ApplicationId") + .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("LinkedApplicationId") + .HasColumnType("uuid"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("ApplicationId"); + + b.ToTable("ApplicationLinks", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicationStatus", 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("ExternalStatus") + .IsRequired() + .HasColumnType("text"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("InternalStatus") + .IsRequired() + .HasColumnType("text"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("StatusCode") + .IsRequired() + .HasMaxLength(250) + .HasColumnType("character varying(250)"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("StatusCode") + .IsUnique(); + + b.ToTable("ApplicationStatuses", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicationTags", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ApplicationId") + .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("TagId") + .HasColumnType("uuid"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("ApplicationId"); + + b.HasIndex("TagId"); + + b.ToTable("ApplicationTags", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.AssessmentAttachment", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("AssessmentId") + .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("DisplayName") + .HasMaxLength(1024) + .HasColumnType("character varying(1024)"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("FileName") + .HasColumnType("text"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("S3ObjectKey") + .IsRequired() + .HasColumnType("text"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("Time") + .HasColumnType("timestamp without time zone"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("AssessmentId"); + + b.ToTable("AssessmentAttachments", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Assessments.Assessment", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ApplicationId") + .HasColumnType("uuid"); + + b.Property("ApprovalRecommended") + .HasColumnType("boolean"); + + b.Property("AssessorId") + .HasColumnType("uuid"); + + b.Property("CleanGrowth") + .HasColumnType("integer"); + + 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("EconomicImpact") + .HasColumnType("integer"); + + b.Property("EndDate") + .HasColumnType("timestamp without time zone"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("FinancialAnalysis") + .HasColumnType("integer"); + + b.Property("InclusiveGrowth") + .HasColumnType("integer"); + + b.Property("IsComplete") + .HasColumnType("boolean"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("ApplicationId"); + + b.HasIndex("AssessorId"); + + b.ToTable("Assessments", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Comments.ApplicationComment", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ApplicationId") + .HasColumnType("uuid"); + + b.Property("Comment") + .IsRequired() + .HasColumnType("text"); + + b.Property("CommenterId") + .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("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("ApplicationId"); + + b.HasIndex("CommenterId"); + + b.ToTable("ApplicationComments", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Comments.AssessmentComment", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("AssessmentId") + .HasColumnType("uuid"); + + b.Property("Comment") + .IsRequired() + .HasColumnType("text"); + + b.Property("CommenterId") + .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("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("AssessmentId"); + + b.HasIndex("CommenterId"); + + b.ToTable("AssessmentComments", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.GlobalTag.Tag", 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("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.ToTable("Tags", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Identity.Person", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("Badge") + .IsRequired() + .HasColumnType("text"); + + 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("FullName") + .IsRequired() + .HasColumnType("text"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("OidcDisplayName") + .IsRequired() + .HasColumnType("text"); + + b.Property("OidcSub") + .IsRequired() + .HasColumnType("text"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("OidcSub"); + + b.ToTable("Persons", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Intakes.Intake", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("Budget") + .HasColumnType("double precision"); + + 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("EndDate") + .HasColumnType("timestamp without time zone"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IntakeName") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("StartDate") + .HasColumnType("timestamp without time zone"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.ToTable("Intakes", (string)null); + }); + + modelBuilder.Entity("Unity.Notifications.EmailGroups.EmailGroup", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .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("Description") + .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("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("Type") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("EmailGroups", "Notifications"); + }); + + modelBuilder.Entity("Unity.Notifications.EmailGroups.EmailGroupUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .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("GroupId") + .HasColumnType("uuid"); + + 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("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("GroupId"); + + b.ToTable("EmailGroupUsers", "Notifications"); + }); + + modelBuilder.Entity("Unity.Notifications.Emails.EmailLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ApplicantId") + .HasColumnType("uuid"); + + b.Property("ApplicationId") + .HasColumnType("uuid"); + + b.Property("AssessmentId") + .HasColumnType("uuid"); + + b.Property("BCC") + .IsRequired() + .HasColumnType("text"); + + b.Property("Body") + .IsRequired() + .HasColumnType("text"); + + b.Property("BodyType") + .IsRequired() + .HasColumnType("text"); + + b.Property("CC") + .IsRequired() + .HasColumnType("text"); + + b.Property("ChesMsgId") + .HasColumnType("uuid"); + + b.Property("ChesResponse") + .IsRequired() + .HasColumnType("text"); + + b.Property("ChesStatus") + .IsRequired() + .HasColumnType("text"); + + 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("FromAddress") + .IsRequired() + .HasColumnType("text"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("Priority") + .IsRequired() + .HasColumnType("text"); + + b.Property("RetryAttempts") + .HasColumnType("integer"); + + b.Property("SendOnDateTime") + .HasColumnType("timestamp without time zone"); + + b.Property("SentDateTime") + .HasColumnType("timestamp without time zone"); + + b.Property("Status") + .IsRequired() + .HasColumnType("text"); + + b.Property("Subject") + .IsRequired() + .HasColumnType("text"); + + b.Property("Tag") + .IsRequired() + .HasColumnType("text"); + + b.Property("TemplateName") + .IsRequired() + .HasColumnType("text"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("ToAddress") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("EmailLogs", "Notifications"); + }); + + modelBuilder.Entity("Unity.Notifications.Templates.EmailTemplate", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("BodyHTML") + .IsRequired() + .HasColumnType("text"); + + b.Property("BodyText") + .IsRequired() + .HasColumnType("text"); + + 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() + .HasColumnType("text"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + 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("SendFrom") + .IsRequired() + .HasColumnType("text"); + + b.Property("Subject") + .IsRequired() + .HasColumnType("text"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.ToTable("EmailTemplates", "Notifications"); + }); + + modelBuilder.Entity("Unity.Notifications.Templates.Subscriber", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .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("Email") + .IsRequired() + .HasColumnType("text"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("FirstName") + .IsRequired() + .HasColumnType("text"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("LastName") + .IsRequired() + .HasColumnType("text"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.ToTable("Subscribers", "Notifications"); + }); + + modelBuilder.Entity("Unity.Notifications.Templates.SubscriptionGroup", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .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("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.ToTable("SubscriptionGroups", "Notifications"); + }); + + modelBuilder.Entity("Unity.Notifications.Templates.SubscriptionGroupSubscription", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .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("GroupId") + .HasColumnType("uuid"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("SubscriberId") + .HasColumnType("uuid"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("GroupId"); + + b.HasIndex("SubscriberId"); + + b.ToTable("SubscriptionGroupSubscribers", "Notifications"); + }); + + modelBuilder.Entity("Unity.Notifications.Templates.TemplateVariable", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .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("MapTo") + .IsRequired() + .HasColumnType("text"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("Token") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("TemplateVariables", "Notifications"); + }); + + modelBuilder.Entity("Unity.Notifications.Templates.Trigger", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Active") + .HasColumnType("boolean"); + + 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("InternalName") + .IsRequired() + .HasColumnType("text"); + + 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("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.ToTable("Triggers", "Notifications"); + }); + + modelBuilder.Entity("Unity.Notifications.Templates.TriggerSubscription", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .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("SubscriptionGroupId") + .HasColumnType("uuid"); + + b.Property("TemplateId") + .HasColumnType("uuid"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("TriggerId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("SubscriptionGroupId"); + + b.HasIndex("TemplateId"); + + b.HasIndex("TriggerId"); + + b.ToTable("TriggerSubscriptions", "Notifications"); + }); + + modelBuilder.Entity("Unity.Payments.Domain.AccountCodings.AccountCoding", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .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("MinistryClient") + .IsRequired() + .HasColumnType("text"); + + b.Property("ProjectNumber") + .IsRequired() + .HasColumnType("text"); + + b.Property("Responsibility") + .IsRequired() + .HasColumnType("text"); + + b.Property("ServiceLine") + .IsRequired() + .HasColumnType("text"); + + b.Property("Stob") + .IsRequired() + .HasColumnType("text"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.ToTable("AccountCodings", "Payments"); + }); + + modelBuilder.Entity("Unity.Payments.Domain.PaymentConfigurations.PaymentConfiguration", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .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("DefaultAccountCodingId") + .HasColumnType("uuid"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("DeletionTime"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("PaymentIdPrefix") + .IsRequired() + .HasColumnType("text"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.ToTable("PaymentConfigurations", "Payments"); + }); + + modelBuilder.Entity("Unity.Payments.Domain.PaymentRequests.ExpenseApproval", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DecisionDate") + .HasColumnType("timestamp without time zone"); + + b.Property("DecisionUserId") + .HasColumnType("uuid"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("DeletionTime"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("PaymentRequestId") + .HasColumnType("uuid"); + + b.Property("Status") + .HasColumnType("integer"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("Type") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("PaymentRequestId"); + + b.ToTable("ExpenseApprovals", "Payments"); + }); + + modelBuilder.Entity("Unity.Payments.Domain.PaymentRequests.PaymentRequest", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("AccountCodingId") + .HasColumnType("uuid"); + + b.Property("Amount") + .HasColumnType("numeric"); + + b.Property("BatchName") + .IsRequired() + .HasColumnType("text"); + + b.Property("BatchNumber") + .HasColumnType("numeric"); + + b.Property("CasHttpStatusCode") + .HasColumnType("integer"); + + b.Property("CasResponse") + .HasColumnType("text"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("ContractNumber") + .IsRequired() + .HasColumnType("text"); + + b.Property("CorrelationId") + .HasColumnType("uuid"); + + b.Property("CorrelationProvider") + .IsRequired() + .HasColumnType("text"); + + 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") + .HasColumnType("text"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("InvoiceNumber") + .IsRequired() + .HasColumnType("text"); + + b.Property("InvoiceStatus") + .HasColumnType("text"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("IsRecon") + .HasColumnType("boolean"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("Note") + .HasColumnType("text"); + + b.Property("PayeeName") + .IsRequired() + .HasColumnType("text"); + + b.Property("PaymentDate") + .HasColumnType("text"); + + b.Property("PaymentNumber") + .HasColumnType("text"); + + b.Property("PaymentStatus") + .HasColumnType("text"); + + b.Property("ReferenceNumber") + .IsRequired() + .HasColumnType("text"); + + b.Property("RequesterName") + .IsRequired() + .HasColumnType("text"); + + b.Property("SiteId") + .HasColumnType("uuid"); + + b.Property("Status") + .HasColumnType("integer"); + + b.Property("SubmissionConfirmationCode") + .IsRequired() + .HasColumnType("text"); + + b.Property("SupplierName") + .HasColumnType("text"); + + b.Property("SupplierNumber") + .IsRequired() + .HasColumnType("text"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("AccountCodingId"); + + b.HasIndex("ReferenceNumber") + .IsUnique(); + + b.HasIndex("SiteId"); + + b.ToTable("PaymentRequests", "Payments"); + }); + + modelBuilder.Entity("Unity.Payments.Domain.PaymentTags.PaymentTag", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .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("PaymentRequestId") + .HasColumnType("uuid"); + + b.Property("TagId") + .HasColumnType("uuid"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("PaymentRequestId"); + + b.HasIndex("TagId"); + + b.ToTable("PaymentTags", "Payments"); + }); + + modelBuilder.Entity("Unity.Payments.Domain.PaymentThresholds.PaymentThreshold", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .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") + .HasColumnType("text"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + 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("Threshold") + .HasColumnType("numeric"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.ToTable("PaymentThresholds", "Payments"); + }); + + modelBuilder.Entity("Unity.Payments.Domain.Suppliers.Site", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("AddressLine1") + .HasColumnType("text"); + + b.Property("AddressLine2") + .HasColumnType("text"); + + b.Property("AddressLine3") + .HasColumnType("text"); + + b.Property("BankAccount") + .HasColumnType("text"); + + b.Property("City") + .HasColumnType("text"); + + b.Property("Country") + .HasColumnType("text"); + + 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("EFTAdvicePref") + .HasColumnType("text"); + + b.Property("EmailAddress") + .HasColumnType("text"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("LastUpdatedInCas") + .HasColumnType("timestamp without time zone"); + + b.Property("MarkDeletedInUse") + .HasColumnType("boolean"); + + b.Property("Number") + .IsRequired() + .HasColumnType("text"); + + b.Property("PaymentGroup") + .HasColumnType("integer"); + + b.Property("PostalCode") + .HasColumnType("text"); + + b.Property("ProviderId") + .HasColumnType("text"); + + b.Property("Province") + .HasColumnType("text"); + + b.Property("SiteProtected") + .HasColumnType("text"); + + b.Property("Status") + .HasColumnType("text"); + + b.Property("SupplierId") + .HasColumnType("uuid"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("SupplierId"); + + b.ToTable("Sites", "Payments"); + }); + + modelBuilder.Entity("Unity.Payments.Domain.Suppliers.Supplier", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("BusinessNumber") + .HasColumnType("text"); + + b.Property("City") + .HasColumnType("text"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CorrelationId") + .HasColumnType("uuid"); + + b.Property("CorrelationProvider") + .IsRequired() + .HasColumnType("text"); + + 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("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("LastUpdatedInCAS") + .HasColumnType("timestamp without time zone"); + + b.Property("MailingAddress") + .HasColumnType("text"); + + b.Property("Name") + .HasColumnType("text"); + + b.Property("Number") + .HasColumnType("text"); + + b.Property("PostalCode") + .HasColumnType("text"); + + b.Property("ProviderId") + .HasColumnType("text"); + + b.Property("Province") + .HasColumnType("text"); + + b.Property("SIN") + .HasColumnType("text"); + + b.Property("StandardIndustryClassification") + .HasColumnType("text"); + + b.Property("Status") + .HasColumnType("text"); + + b.Property("Subcategory") + .HasColumnType("text"); + + b.Property("SupplierProtected") + .HasColumnType("text"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.ToTable("Suppliers", "Payments"); + }); + + modelBuilder.Entity("Unity.Flex.Domain.ScoresheetInstances.ScoresheetInstance", b => + { + b.HasOne("Unity.Flex.Domain.Scoresheets.Scoresheet", "Scoresheet") + .WithMany("Instances") + .HasForeignKey("ScoresheetId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Scoresheet"); + }); + + modelBuilder.Entity("Unity.Flex.Domain.Scoresheets.Answer", b => + { + b.HasOne("Unity.Flex.Domain.Scoresheets.Question", "Question") + .WithMany("Answers") + .HasForeignKey("QuestionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Unity.Flex.Domain.ScoresheetInstances.ScoresheetInstance", null) + .WithMany("Answers") + .HasForeignKey("ScoresheetInstanceId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Question"); + }); + + modelBuilder.Entity("Unity.Flex.Domain.Scoresheets.Question", b => + { + b.HasOne("Unity.Flex.Domain.Scoresheets.ScoresheetSection", "Section") + .WithMany("Fields") + .HasForeignKey("SectionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Section"); + }); + + modelBuilder.Entity("Unity.Flex.Domain.Scoresheets.ScoresheetSection", b => + { + b.HasOne("Unity.Flex.Domain.Scoresheets.Scoresheet", "Scoresheet") + .WithMany("Sections") + .HasForeignKey("ScoresheetId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Scoresheet"); + }); + + modelBuilder.Entity("Unity.Flex.Domain.WorksheetInstances.CustomFieldValue", b => + { + b.HasOne("Unity.Flex.Domain.WorksheetInstances.WorksheetInstance", null) + .WithMany("Values") + .HasForeignKey("WorksheetInstanceId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Unity.Flex.Domain.WorksheetLinks.WorksheetLink", b => + { + b.HasOne("Unity.Flex.Domain.Worksheets.Worksheet", "Worksheet") + .WithMany("Links") + .HasForeignKey("WorksheetId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Worksheet"); + }); + + modelBuilder.Entity("Unity.Flex.Domain.Worksheets.CustomField", b => + { + b.HasOne("Unity.Flex.Domain.Worksheets.WorksheetSection", "Section") + .WithMany("Fields") + .HasForeignKey("SectionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Section"); + }); + + modelBuilder.Entity("Unity.Flex.Domain.Worksheets.WorksheetSection", b => + { + b.HasOne("Unity.Flex.Domain.Worksheets.Worksheet", "Worksheet") + .WithMany("Sections") + .HasForeignKey("WorksheetId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Worksheet"); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicantAddress", b => + { + b.HasOne("Unity.GrantManager.Applications.Applicant", "Applicant") + .WithMany("ApplicantAddresses") + .HasForeignKey("ApplicantId") + .OnDelete(DeleteBehavior.NoAction) + .IsRequired(); + + b.HasOne("Unity.GrantManager.Applications.Application", "Application") + .WithMany("ApplicantAddresses") + .HasForeignKey("ApplicationId"); + + b.Navigation("Applicant"); + + b.Navigation("Application"); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicantAgent", b => + { + b.HasOne("Unity.GrantManager.Applications.Applicant", null) + .WithMany() + .HasForeignKey("ApplicantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Unity.GrantManager.Applications.Application", "Application") + .WithOne("ApplicantAgent") + .HasForeignKey("Unity.GrantManager.Applications.ApplicantAgent", "ApplicationId"); + + b.HasOne("Unity.GrantManager.Identity.Person", null) + .WithMany() + .HasForeignKey("OidcSubUser") + .HasPrincipalKey("OidcSub"); + + b.Navigation("Application"); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.Application", b => + { + b.HasOne("Unity.GrantManager.Applications.Applicant", "Applicant") + .WithMany() + .HasForeignKey("ApplicantId") + .OnDelete(DeleteBehavior.NoAction) + .IsRequired(); + + b.HasOne("Unity.GrantManager.Applications.ApplicationForm", "ApplicationForm") + .WithMany() + .HasForeignKey("ApplicationFormId") + .OnDelete(DeleteBehavior.NoAction) + .IsRequired(); + + b.HasOne("Unity.GrantManager.Applications.ApplicationStatus", "ApplicationStatus") + .WithMany("Applications") + .HasForeignKey("ApplicationStatusId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Unity.GrantManager.Identity.Person", "Owner") + .WithMany() + .HasForeignKey("OwnerId") + .OnDelete(DeleteBehavior.NoAction); + + b.Navigation("Applicant"); + + b.Navigation("ApplicationForm"); + + b.Navigation("ApplicationStatus"); + + b.Navigation("Owner"); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicationAssignment", b => + { + b.HasOne("Unity.GrantManager.Applications.Application", "Application") + .WithMany("ApplicationAssignments") + .HasForeignKey("ApplicationId") + .OnDelete(DeleteBehavior.NoAction) + .IsRequired(); + + b.HasOne("Unity.GrantManager.Identity.Person", "Assignee") + .WithMany() + .HasForeignKey("AssigneeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Application"); + + b.Navigation("Assignee"); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicationAttachment", b => + { + b.HasOne("Unity.GrantManager.Applications.Application", null) + .WithMany() + .HasForeignKey("ApplicationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicationChefsFileAttachment", b => + { + b.HasOne("Unity.GrantManager.Applications.Application", null) + .WithMany() + .HasForeignKey("ApplicationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicationContact", b => + { + b.HasOne("Unity.GrantManager.Applications.Application", null) + .WithMany() + .HasForeignKey("ApplicationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicationForm", b => + { + b.HasOne("Unity.GrantManager.Intakes.Intake", null) + .WithMany() + .HasForeignKey("IntakeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicationFormSubmission", b => + { + b.HasOne("Unity.GrantManager.Applications.Applicant", null) + .WithMany() + .HasForeignKey("ApplicantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Unity.GrantManager.Applications.ApplicationForm", null) + .WithMany() + .HasForeignKey("ApplicationFormId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicationFormVersion", b => + { + b.HasOne("Unity.GrantManager.Applications.ApplicationForm", null) + .WithMany() + .HasForeignKey("ApplicationFormId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicationLink", b => + { + b.HasOne("Unity.GrantManager.Applications.Application", null) + .WithMany() + .HasForeignKey("ApplicationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicationTags", b => + { + b.HasOne("Unity.GrantManager.Applications.Application", "Application") + .WithMany("ApplicationTags") + .HasForeignKey("ApplicationId") + .OnDelete(DeleteBehavior.NoAction) + .IsRequired(); + + b.HasOne("Unity.GrantManager.GlobalTag.Tag", "Tag") + .WithMany() + .HasForeignKey("TagId") + .OnDelete(DeleteBehavior.NoAction) + .IsRequired(); + + b.Navigation("Application"); + + b.Navigation("Tag"); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.AssessmentAttachment", b => + { + b.HasOne("Unity.GrantManager.Assessments.Assessment", null) + .WithMany() + .HasForeignKey("AssessmentId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Unity.GrantManager.Assessments.Assessment", b => + { + b.HasOne("Unity.GrantManager.Applications.Application", "Application") + .WithMany("Assessments") + .HasForeignKey("ApplicationId") + .OnDelete(DeleteBehavior.NoAction) + .IsRequired(); + + b.HasOne("Unity.GrantManager.Identity.Person", null) + .WithMany() + .HasForeignKey("AssessorId") + .OnDelete(DeleteBehavior.NoAction) + .IsRequired(); + + b.Navigation("Application"); + }); + + modelBuilder.Entity("Unity.GrantManager.Comments.ApplicationComment", b => + { + b.HasOne("Unity.GrantManager.Applications.Application", null) + .WithMany() + .HasForeignKey("ApplicationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Unity.GrantManager.Identity.Person", null) + .WithMany() + .HasForeignKey("CommenterId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Unity.GrantManager.Comments.AssessmentComment", b => + { + b.HasOne("Unity.GrantManager.Assessments.Assessment", null) + .WithMany() + .HasForeignKey("AssessmentId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Unity.GrantManager.Identity.Person", null) + .WithMany() + .HasForeignKey("CommenterId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Unity.Notifications.EmailGroups.EmailGroupUser", b => + { + b.HasOne("Unity.Notifications.EmailGroups.EmailGroup", null) + .WithMany() + .HasForeignKey("GroupId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Unity.Notifications.Templates.SubscriptionGroupSubscription", b => + { + b.HasOne("Unity.Notifications.Templates.SubscriptionGroup", "SubscriptionGroup") + .WithMany() + .HasForeignKey("GroupId"); + + b.HasOne("Unity.Notifications.Templates.Subscriber", "Subscriber") + .WithMany() + .HasForeignKey("SubscriberId"); + + b.Navigation("Subscriber"); + + b.Navigation("SubscriptionGroup"); + }); + + modelBuilder.Entity("Unity.Notifications.Templates.TriggerSubscription", b => + { + b.HasOne("Unity.Notifications.Templates.SubscriptionGroup", "SubscriptionGroup") + .WithMany() + .HasForeignKey("SubscriptionGroupId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Unity.Notifications.Templates.EmailTemplate", "EmailTemplate") + .WithMany() + .HasForeignKey("TemplateId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Unity.Notifications.Templates.Trigger", "Trigger") + .WithMany() + .HasForeignKey("TriggerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("EmailTemplate"); + + b.Navigation("SubscriptionGroup"); + + b.Navigation("Trigger"); + }); + + modelBuilder.Entity("Unity.Payments.Domain.PaymentRequests.ExpenseApproval", b => + { + b.HasOne("Unity.Payments.Domain.PaymentRequests.PaymentRequest", "PaymentRequest") + .WithMany("ExpenseApprovals") + .HasForeignKey("PaymentRequestId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("PaymentRequest"); + }); + + modelBuilder.Entity("Unity.Payments.Domain.PaymentRequests.PaymentRequest", b => + { + b.HasOne("Unity.Payments.Domain.AccountCodings.AccountCoding", "AccountCoding") + .WithMany() + .HasForeignKey("AccountCodingId") + .OnDelete(DeleteBehavior.NoAction); + + b.HasOne("Unity.Payments.Domain.Suppliers.Site", "Site") + .WithMany() + .HasForeignKey("SiteId") + .OnDelete(DeleteBehavior.NoAction) + .IsRequired(); + + b.Navigation("AccountCoding"); + + b.Navigation("Site"); + }); + + modelBuilder.Entity("Unity.Payments.Domain.PaymentTags.PaymentTag", b => + { + b.HasOne("Unity.Payments.Domain.PaymentRequests.PaymentRequest", null) + .WithMany("PaymentTags") + .HasForeignKey("PaymentRequestId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Unity.GrantManager.GlobalTag.Tag", "Tag") + .WithMany() + .HasForeignKey("TagId") + .OnDelete(DeleteBehavior.NoAction) + .IsRequired(); + + b.Navigation("Tag"); + }); + + modelBuilder.Entity("Unity.Payments.Domain.Suppliers.Site", b => + { + b.HasOne("Unity.Payments.Domain.Suppliers.Supplier", "Supplier") + .WithMany("Sites") + .HasForeignKey("SupplierId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Supplier"); + }); + + modelBuilder.Entity("Unity.Flex.Domain.ScoresheetInstances.ScoresheetInstance", b => + { + b.Navigation("Answers"); + }); + + modelBuilder.Entity("Unity.Flex.Domain.Scoresheets.Question", b => + { + b.Navigation("Answers"); + }); + + modelBuilder.Entity("Unity.Flex.Domain.Scoresheets.Scoresheet", b => + { + b.Navigation("Instances"); + + b.Navigation("Sections"); + }); + + modelBuilder.Entity("Unity.Flex.Domain.Scoresheets.ScoresheetSection", b => + { + b.Navigation("Fields"); + }); + + modelBuilder.Entity("Unity.Flex.Domain.WorksheetInstances.WorksheetInstance", b => + { + b.Navigation("Values"); + }); + + modelBuilder.Entity("Unity.Flex.Domain.Worksheets.Worksheet", b => + { + b.Navigation("Links"); + + b.Navigation("Sections"); + }); + + modelBuilder.Entity("Unity.Flex.Domain.Worksheets.WorksheetSection", b => + { + b.Navigation("Fields"); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.Applicant", b => + { + b.Navigation("ApplicantAddresses"); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.Application", b => + { + b.Navigation("ApplicantAddresses"); + + b.Navigation("ApplicantAgent"); + + b.Navigation("ApplicationAssignments"); + + b.Navigation("ApplicationTags"); + + b.Navigation("Assessments"); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicationStatus", b => + { + b.Navigation("Applications"); + }); + + modelBuilder.Entity("Unity.Payments.Domain.PaymentRequests.PaymentRequest", b => + { + b.Navigation("ExpenseApprovals"); + + b.Navigation("PaymentTags"); + }); + + modelBuilder.Entity("Unity.Payments.Domain.Suppliers.Supplier", b => + { + b.Navigation("Sites"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.EntityFrameworkCore/Migrations/TenantMigrations/20250819182438_AB29758_Remove_Legacy_Tags.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.EntityFrameworkCore/Migrations/TenantMigrations/20250819182438_AB29758_Remove_Legacy_Tags.cs new file mode 100644 index 000000000..118606027 --- /dev/null +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.EntityFrameworkCore/Migrations/TenantMigrations/20250819182438_AB29758_Remove_Legacy_Tags.cs @@ -0,0 +1,43 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Unity.GrantManager.Migrations.TenantMigrations +{ + /// + public partial class AB29758_Remove_Legacy_Tags : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "Text", + schema: "Payments", + table: "PaymentTags"); + + migrationBuilder.DropColumn( + name: "Text", + table: "ApplicationTags"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "Text", + schema: "Payments", + table: "PaymentTags", + type: "text", + nullable: false, + defaultValue: ""); + + migrationBuilder.AddColumn( + name: "Text", + table: "ApplicationTags", + type: "text", + nullable: false, + defaultValue: ""); + } + } +} diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.EntityFrameworkCore/Migrations/TenantMigrations/GrantTenantDbContextModelSnapshot.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.EntityFrameworkCore/Migrations/TenantMigrations/GrantTenantDbContextModelSnapshot.cs index fe61ccb52..0f0cc39bc 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.EntityFrameworkCore/Migrations/TenantMigrations/GrantTenantDbContextModelSnapshot.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.EntityFrameworkCore/Migrations/TenantMigrations/GrantTenantDbContextModelSnapshot.cs @@ -1981,10 +1981,6 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasColumnType("uuid") .HasColumnName("TenantId"); - b.Property("Text") - .IsRequired() - .HasColumnType("text"); - b.HasKey("Id"); b.HasIndex("ApplicationId"); @@ -3103,6 +3099,10 @@ protected override void BuildModel(ModelBuilder modelBuilder) .IsRequired() .HasColumnType("text"); + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + b.HasKey("Id"); b.ToTable("AccountCodings", "Payments"); @@ -3426,10 +3426,6 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasColumnType("uuid") .HasColumnName("TenantId"); - b.Property("Text") - .IsRequired() - .HasColumnType("text"); - b.HasKey("Id"); b.HasIndex("PaymentRequestId"); diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.EntityFrameworkCore/Repositories/ApplicationFormSubmissionRepository.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.EntityFrameworkCore/Repositories/ApplicationFormSubmissionRepository.cs index e1873bd7e..34dcbe6ed 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.EntityFrameworkCore/Repositories/ApplicationFormSubmissionRepository.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.EntityFrameworkCore/Repositories/ApplicationFormSubmissionRepository.cs @@ -1,5 +1,6 @@ using Microsoft.EntityFrameworkCore; using System; +using System.Linq; using System.Threading.Tasks; using Unity.GrantManager.Applications; using Unity.GrantManager.EntityFrameworkCore; @@ -23,5 +24,37 @@ public async Task GetByApplicationAsync(Guid applicat return await dbContext.ApplicationFormSubmissions .FirstAsync(s => s.ApplicationId == applicationId); } + + public async Task GetFormDetailsByApplicationIdAsync(Guid applicationId) + { + var dbContext = await GetDbContextAsync(); + + // Join ApplicationFormSubmission with ApplicationForm and ApplicationFormVersion + // to get all required data in a single query + return await dbContext.ApplicationFormSubmissions + .Where(s => s.ApplicationId == applicationId) + .Join( + dbContext.ApplicationFormVersions, + submission => submission.ApplicationFormVersionId, + version => version.Id, + (submission, version) => new { submission, version } + ) + .Join( + dbContext.ApplicationForms, + formVersion => formVersion.version.ApplicationFormId, + form => form.Id, + (formVersion, form) => new ApplicationFormDetails + { + ApplicationId = applicationId, + ApplicationFormId = form.Id, + ApplicationFormName = form.ApplicationFormName ?? string.Empty, + ApplicationFormDescription = form.ApplicationFormDescription ?? string.Empty, + ApplicationFormCategory = form.Category ?? string.Empty, + ApplicationFormVersionId = formVersion.version.Id, + ApplicationFormVersion = formVersion.version.Version ?? 0 + } + ) + .FirstOrDefaultAsync() ?? new ApplicationFormDetails { ApplicationId = applicationId }; + } } } diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Identity/PolicyRegistrant.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Identity/PolicyRegistrant.cs index e712e4019..5da56c246 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Identity/PolicyRegistrant.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Identity/PolicyRegistrant.cs @@ -222,13 +222,6 @@ internal static void Register(ServiceConfigurationContext context) policy => policy.RequireClaim(PermissionConstant, UnitySelector.Project.Location.Update.Default)); authorizationBuilder.AddPolicy(UnitySelector.Project.Location.Update.UpdateFinalStateFields, policy => policy.RequireClaim(PermissionConstant, UnitySelector.Project.Location.Update.UpdateFinalStateFields)); - - // Project Info - Worksheet Policies - authorizationBuilder.AddPolicy(UnitySelector.Project.Worksheet.Default, - policy => policy.RequireClaim(PermissionConstant, UnitySelector.Project.Worksheet.Default)); // NOTE: Will be replaced when Worksheets normalized - - authorizationBuilder.AddPolicy(UnitySelector.Project.Worksheet.Update, - policy => policy.RequireClaim(PermissionConstant, UnitySelector.Project.Worksheet.Update)); // NOTE: Will be replaced when Worksheets normalized } } diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/ApplicationForms/Index.css b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/ApplicationForms/Index.css index ecc228497..f59a984fa 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/ApplicationForms/Index.css +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/ApplicationForms/Index.css @@ -27,7 +27,7 @@ background-color: var(--bc-colors-grey-hover) !important; opacity: var(--bs-btn-disabled-opacity); background-blend-mode: difference; - border: none !important; + border: var(--bs-border-width) solid var(--bs-border-color); } .search-action-bar { diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/ApplicationForms/LinkWorksheetsModal.cshtml b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/ApplicationForms/LinkWorksheetsModal.cshtml index a18486337..5728116f9 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/ApplicationForms/LinkWorksheetsModal.cshtml +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/ApplicationForms/LinkWorksheetsModal.cshtml @@ -12,11 +12,11 @@
- - - - - + + + + + @@ -37,58 +37,73 @@
Assessment Info:
-
- @if (Model.AssessmentInfoLink != null) +
+ @if (Model.AssessmentInfoLinks != null) { -
- - @Model.AssessmentInfoLink.Worksheet.Title (@Model.AssessmentInfoLink.Worksheet.Name) - -
+ @foreach (var assessmentInfo in Model.AssessmentInfoLinks.OrderBy(s => s.Order)) + { +
+ + @assessmentInfo.Worksheet.Title (@assessmentInfo.Worksheet.Name) + +
+ } }
Project Info:
-
- @if (Model.ProjectInfoLink != null) +
+ @if (Model.ProjectInfoLinks != null) { -
- - @Model.ProjectInfoLink.Worksheet.Title (@Model.ProjectInfoLink.Worksheet.Name) - -
+ @foreach (var projectInfo in Model.ProjectInfoLinks.OrderBy(s => s.Order)) + { +
+ + @projectInfo.Worksheet.Title (@projectInfo.Worksheet.Name) + +
+ } }
Applicant Info:
-
- @if (Model.ApplicantInfoLink != null) +
+ @if (Model.ApplicantInfoLinks != null) { -
- - @Model.ApplicantInfoLink.Worksheet.Title (@Model.ApplicantInfoLink.Worksheet.Name) - -
+ @foreach (var applicantInfo in Model.ApplicantInfoLinks.OrderBy(s => s.Order)) + { +
+ + @applicantInfo.Worksheet.Title (@applicantInfo.Worksheet.Name) + +
+ } }
Payment Info:
-
- @if (Model.PaymentInfoLink != null) +
+ @if (Model.PaymentInfoLinks != null) { -
- - @Model.PaymentInfoLink.Worksheet.Title (@Model.PaymentInfoLink.Worksheet.Name) - -
+ @foreach (var paymentInfo in Model.PaymentInfoLinks.OrderBy(s => s.Order)) + { +
+ + @paymentInfo.Worksheet.Title (@paymentInfo.Worksheet.Name) + +
+ } }
Funding Agreement:
-
- @if (Model.FundingAgreementInfoLink != null) +
+ @if (Model.FundingAgreementInfoLinks != null) { -
- - @Model.FundingAgreementInfoLink.Worksheet.Title (@Model.FundingAgreementInfoLink.Worksheet.Name) - -
+ @foreach (var fundingAgreementInfo in Model.FundingAgreementInfoLinks.OrderBy(s => s.Order)) + { +
+ + @fundingAgreementInfo.Worksheet.Title (@fundingAgreementInfo.Worksheet.Name) + +
+ } }
Additional Tabs:
diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/ApplicationForms/LinkWorksheetsModal.cshtml.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/ApplicationForms/LinkWorksheetsModal.cshtml.cs index e219e13ed..08dc3b478 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/ApplicationForms/LinkWorksheetsModal.cshtml.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/ApplicationForms/LinkWorksheetsModal.cshtml.cs @@ -22,19 +22,19 @@ public class LinkWorksheetModalModel(IWorksheetListAppService worksheetListAppSe public string? FormName { get; set; } [BindProperty] - public string? AssessmentInfoSlotId { get; set; } + public string? AssessmentInfoSlotIds { get; set; } [BindProperty] - public string? ProjectInfoSlotId { get; set; } + public string? ProjectInfoSlotIds { get; set; } [BindProperty] - public string? ApplicantInfoSlotId { get; set; } + public string? ApplicantInfoSlotIds { get; set; } [BindProperty] - public string? PaymentInfoSlotId { get; set; } + public string? PaymentInfoSlotIds { get; set; } [BindProperty] - public string? FundingAgreementInfoSlotId { get; set; } + public string? FundingAgreementInfoSlotIds { get; set; } [BindProperty] public string? CustomTabsSlotIds { get; set; } @@ -46,19 +46,19 @@ public class LinkWorksheetModalModel(IWorksheetListAppService worksheetListAppSe public List? PublishedWorksheets { get; set; } [BindProperty] - public WorksheetLinkDto? AssessmentInfoLink { get; set; } + public List? AssessmentInfoLinks { get; set; } [BindProperty] - public WorksheetLinkDto? ApplicantInfoLink { get; set; } + public List? ApplicantInfoLinks { get; set; } [BindProperty] - public WorksheetLinkDto? ProjectInfoLink { get; set; } + public List? ProjectInfoLinks { get; set; } [BindProperty] - public WorksheetLinkDto? PaymentInfoLink { get; set; } + public List? PaymentInfoLinks { get; set; } [BindProperty] - public WorksheetLinkDto? FundingAgreementInfoLink { get; set; } + public List? FundingAgreementInfoLinks { get; set; } [BindProperty] public List? CustomTabLinks { get; set; } @@ -75,49 +75,27 @@ public async Task OnGetAsync(Guid formVersionId, string formName) .Where(s => s.Published && !WorksheetLinks.Select(s => s.WorksheetId).Contains(s.Id)) .OrderBy(s => s.Title)]; - GetSlotIdAnchors(WorksheetLinks); - CustomTabLinks = WorksheetLinks.Where(s => s.UiAnchor == FlexConsts.CustomTab).ToList(); - CustomTabsSlotIds = string.Join(";", CustomTabLinks - .OrderBy(s => s.Order) - .Select(s => s.WorksheetId)); + (CustomTabLinks, CustomTabsSlotIds) = ProcessWorksheetLinks(WorksheetLinks, FlexConsts.CustomTab); + (AssessmentInfoLinks, AssessmentInfoSlotIds) = ProcessWorksheetLinks(WorksheetLinks, FlexConsts.AssessmentInfoUiAnchor); + (ProjectInfoLinks, ProjectInfoSlotIds) = ProcessWorksheetLinks(WorksheetLinks, FlexConsts.ProjectInfoUiAnchor); + (ApplicantInfoLinks, ApplicantInfoSlotIds) = ProcessWorksheetLinks(WorksheetLinks, FlexConsts.ApplicantInfoUiAnchor); + (PaymentInfoLinks, PaymentInfoSlotIds) = ProcessWorksheetLinks(WorksheetLinks, FlexConsts.PaymentInfoUiAnchor); + (FundingAgreementInfoLinks, FundingAgreementInfoSlotIds) = ProcessWorksheetLinks(WorksheetLinks, FlexConsts.FundingAgreementInfoUiAnchor); } - private void GetSlotIdAnchors(List worksheetLinks) - { - AssessmentInfoLink = worksheetLinks.Find(s => s.UiAnchor == FlexConsts.AssessmentInfoUiAnchor); - AssessmentInfoSlotId = AssessmentInfoLink?.WorksheetId.ToString(); - - ProjectInfoLink = worksheetLinks.Find(s => s.UiAnchor == FlexConsts.ProjectInfoUiAnchor); - ProjectInfoSlotId = ProjectInfoLink?.WorksheetId.ToString(); - - ApplicantInfoLink = worksheetLinks.Find(s => s.UiAnchor == FlexConsts.ApplicantInfoUiAnchor); - ApplicantInfoSlotId = ApplicantInfoLink?.WorksheetId.ToString(); - - PaymentInfoLink = worksheetLinks.Find(s => s.UiAnchor == FlexConsts.PaymentInfoUiAnchor); - PaymentInfoSlotId = PaymentInfoLink?.WorksheetId.ToString(); - - FundingAgreementInfoLink = worksheetLinks.Find(s => s.UiAnchor == FlexConsts.FundingAgreementInfoUiAnchor); - FundingAgreementInfoSlotId = FundingAgreementInfoLink?.WorksheetId.ToString(); - } public async Task OnPostAsync() { var tabLinks = new List<(Guid worksheetId, string anchor, uint order)>(); - AddSlotIdAnchors(tabLinks); - if (CustomTabsSlotIds != null && CustomTabsSlotIds != Guid.Empty.ToString()) - { - var customTabs = CustomTabsSlotIds.Split(';'); - uint order = 1; - - foreach (var customTabId in customTabs) //this comes in sequenced as we want for custom tabs - { - tabLinks.Add(new(Guid.Parse(customTabId), FlexConsts.CustomTab, order)); - order++; - } - } + ProcessSlotIds(CustomTabsSlotIds, FlexConsts.CustomTab, tabLinks); + ProcessSlotIds(AssessmentInfoSlotIds, FlexConsts.AssessmentInfoUiAnchor, tabLinks); + ProcessSlotIds(ProjectInfoSlotIds, FlexConsts.ProjectInfoUiAnchor, tabLinks); + ProcessSlotIds(ApplicantInfoSlotIds, FlexConsts.ApplicantInfoUiAnchor, tabLinks); + ProcessSlotIds(PaymentInfoSlotIds, FlexConsts.PaymentInfoUiAnchor, tabLinks); + ProcessSlotIds(FundingAgreementInfoSlotIds, FlexConsts.FundingAgreementInfoUiAnchor, tabLinks); var formVersion = await applicationFormVersionAppService.GetByChefsFormVersionId(ChefsFormVersionId); _ = await worksheetLinkAppService @@ -131,32 +109,24 @@ public async Task OnPostAsync() return new OkObjectResult(new { ChefsFormVersionId }); } - private void AddSlotIdAnchors(List<(Guid worksheetId, string anchor, uint order)> tabLinks) + private static (List links, string slotIds) ProcessWorksheetLinks(List worksheetLinks, string uiAnchor) { - // We leave the order for the predefined tabs as 0 as they slot into a fixed position - if (AssessmentInfoSlotId != null && AssessmentInfoSlotId != Guid.Empty.ToString()) - { - tabLinks.Add(new(Guid.Parse(AssessmentInfoSlotId), FlexConsts.AssessmentInfoUiAnchor, 0)); - } - - if (ProjectInfoSlotId != null && ProjectInfoSlotId != Guid.Empty.ToString()) - { - tabLinks.Add(new(Guid.Parse(ProjectInfoSlotId), FlexConsts.ProjectInfoUiAnchor, 0)); - } - - if (ApplicantInfoSlotId != null && ApplicantInfoSlotId != Guid.Empty.ToString()) - { - tabLinks.Add(new(Guid.Parse(ApplicantInfoSlotId), FlexConsts.ApplicantInfoUiAnchor, 0)); - } - - if (PaymentInfoSlotId != null && PaymentInfoSlotId != Guid.Empty.ToString()) - { - tabLinks.Add(new(Guid.Parse(PaymentInfoSlotId), FlexConsts.PaymentInfoUiAnchor, 0)); - } + var links = worksheetLinks.Where(s => s.UiAnchor == uiAnchor).ToList(); + var slotIds = string.Join(";", links.OrderBy(s => s.Order).Select(s => s.WorksheetId)); + return (links, slotIds); + } - if (FundingAgreementInfoSlotId != null && FundingAgreementInfoSlotId != Guid.Empty.ToString()) + private static void ProcessSlotIds(string? slotIds, string uiAnchor, List<(Guid worksheetId, string anchor, uint order)> tabLinks) + { + if (!string.IsNullOrWhiteSpace(slotIds) && slotIds != Guid.Empty.ToString()) { - tabLinks.Add(new(Guid.Parse(FundingAgreementInfoSlotId), FlexConsts.FundingAgreementInfoUiAnchor, 0)); + var tabs = slotIds.Split(';'); + uint order = 1; + foreach (var tabId in tabs) + { + tabLinks.Add(new(Guid.Parse(tabId), uiAnchor, order)); + order++; + } } } } diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/ApplicationForms/LinkWorksheetsModal.css b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/ApplicationForms/LinkWorksheetsModal.css index d4a3e9b5d..d86586c63 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/ApplicationForms/LinkWorksheetsModal.css +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/ApplicationForms/LinkWorksheetsModal.css @@ -26,6 +26,9 @@ flex: 0.5; padding: 5px; border-radius: 5px; + height: 100%; + max-height: 400px; + overflow-y: auto; } .single-slot { @@ -38,7 +41,7 @@ } .multi-slot { - height: 100px; + min-height: 100px; overflow-y: scroll; width: 98%; border: 1px solid gray; diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/ApplicationForms/LinkWorksheetsModal.js b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/ApplicationForms/LinkWorksheetsModal.js index 2eb2b395d..ccbb2d841 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/ApplicationForms/LinkWorksheetsModal.js +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/ApplicationForms/LinkWorksheetsModal.js @@ -2,12 +2,22 @@ let lastDroppedLocation = {}; let lastDragFromLocation = {}; let customTabIds = []; + let assessmentInfoIds = []; + let projectInfoIds = []; + let applicantInfoIds = []; + let paymentInfoIds = []; + let fundingAgreementInfoIds = []; PubSub.subscribe( 'refresh_configure_worksheets', () => { lastDroppedLocation = {}; customTabIds = []; + assessmentInfoIds = []; + projectInfoIds = []; + applicantInfoIds = []; + paymentInfoIds = []; + fundingAgreementInfoIds = []; } ); @@ -54,6 +64,36 @@ if (dragOver.classList.contains('multi-target') && event.target.classList.contains('custom-tabs-list')) { dropToCustomTabs(event, null, 'published-form'); + return; + } + + if (dragOver.classList.contains('multi-target') + && event.target.classList.contains('assessment-info-list')) { + dropToAssessmentInfo(event, null, 'published-form'); + return; + } + + if (dragOver.classList.contains('multi-target') + && event.target.classList.contains('project-info-list')) { + dropToProjectInfo(event, null, 'published-form'); + return; + } + + if (dragOver.classList.contains('multi-target') + && event.target.classList.contains('applicant-info-list')) { + dropToApplicantInfo(event, null, 'published-form'); + return; + } + + if (dragOver.classList.contains('multi-target') + && event.target.classList.contains('payment-info-list')) { + dropToPaymentInfo(event, null, 'published-form'); + return; + } + + if (dragOver.classList.contains('multi-target') + && event.target.classList.contains('funding-agreement-info-list')) { + dropToFundingAgreementInfo(event, null, 'published-form'); } }); @@ -70,76 +110,88 @@ if (draggedEl.classList + "" != "undefined") { draggedEl.classList.remove('dragging'); - clearSlotId(); - updateSlotId(draggedEl); storeCustomTabsIdChange(); + storeAssessmentInfoIdChange(); + storeProjectInfoIdChange(); + storeApplicantInfoIdChange(); + storePaymentInfoIdChange(); + storeFundingAgreementInfoIdChange(); } } - function clearSlotId() { - switch (lastDragFromLocation?.dataset?.target) { - case 'assessmentInfo': - $('#AssessmentInfoSlotId').val(null); - break; - case 'projectInfo': - $('#ProjectInfoSlotId').val(null); - break; - case 'applicantInfo': - $('#ApplicantInfoSlotId').val(null); - break; - case 'paymentInfo': - $('#PaymentInfoSlotId').val(null); - break; - case 'fundingAgreementInfo': - $('#FundingAgreementInfoSlotId').val(null); - break; - } - } - - function updateSlotId(draggedEl) { - switch (lastDroppedLocation?.dataset?.target) { - case 'assessmentInfo': - $('#AssessmentInfoSlotId').val(draggedEl.dataset.worksheetId); - break; - case 'projectInfo': - $('#ProjectInfoSlotId').val(draggedEl.dataset.worksheetId); - break; - case 'applicantInfo': - $('#ApplicantInfoSlotId').val(draggedEl.dataset.worksheetId); - break; - case 'paymentInfo': - $('#PaymentInfoSlotId').val(draggedEl.dataset.worksheetId); - break; - case 'fundingAgreementInfo': - $('#FundingAgreementInfoSlotId').val(draggedEl.dataset.worksheetId); - break; - } + function getMultiTargetIds(cssSelector) { + let ids = []; + let items = Array.from($(cssSelector).children()); + items.forEach((item) => { + ids.push(item.dataset.worksheetId); + }); + return ids; } - - function dropToCustomTabs(event, addClass, removeClass) { + function dropToMultiTarget(event, addClass, removeClass, storeFunction) { event.preventDefault(); - let dragOver = event.target; let beingDragged = document.querySelector('.dragging'); - - // handle reordering in the ui - updateDraggedClasses(beingDragged, addClass, removeClass); dragOver.appendChild(beingDragged); lastDroppedLocation = dragOver; - storeCustomTabsIdChange(); + storeFunction(); + } + + function dropToCustomTabs(event, addClass, removeClass) { + dropToMultiTarget(event, addClass, removeClass, storeCustomTabsIdChange); + } + + function dropToAssessmentInfo(event, addClass, removeClass) { + dropToMultiTarget(event, addClass, removeClass, storeAssessmentInfoIdChange); } function storeCustomTabsIdChange() { - customTabIds= []; - let items = Array.from($('.custom-tabs-list').children()); - items.forEach((item) => { - customTabIds.push(item.dataset.worksheetId); - }); + customTabIds = getMultiTargetIds('.custom-tabs-list'); $('#CustomTabsSlotIds').val(customTabIds.join(';')); } + function dropToProjectInfo(event, addClass, removeClass) { + dropToMultiTarget(event, addClass, removeClass, storeProjectInfoIdChange); + } + + function storeAssessmentInfoIdChange() { + assessmentInfoIds = getMultiTargetIds('.assessment-info-list'); + $('#AssessmentInfoSlotIds').val(assessmentInfoIds.join(';')); + } + + function dropToApplicantInfo(event, addClass, removeClass) { + dropToMultiTarget(event, addClass, removeClass, storeApplicantInfoIdChange); + } + + function storeProjectInfoIdChange() { + projectInfoIds = getMultiTargetIds('.project-info-list'); + $('#ProjectInfoSlotIds').val(projectInfoIds.join(';')); + } + + function dropToPaymentInfo(event, addClass, removeClass) { + dropToMultiTarget(event, addClass, removeClass, storePaymentInfoIdChange); + } + + function storeApplicantInfoIdChange() { + applicantInfoIds = getMultiTargetIds('.applicant-info-list'); + $('#ApplicantInfoSlotIds').val(applicantInfoIds.join(';')); + } + + function dropToFundingAgreementInfo(event, addClass, removeClass) { + dropToMultiTarget(event, addClass, removeClass, storeFundingAgreementInfoIdChange); + } + + function storePaymentInfoIdChange() { + paymentInfoIds = getMultiTargetIds('.payment-info-list'); + $('#PaymentInfoSlotIds').val(paymentInfoIds.join(';')); + } + + function storeFundingAgreementInfoIdChange() { + fundingAgreementInfoIds = getMultiTargetIds('.funding-agreement-info-list'); + $('#FundingAgreementInfoSlotIds').val(fundingAgreementInfoIds.join(';')); + } + function dropToAvailableWorksheets(event, addClass, removeClass) { dropToSingleTarget(event, addClass, removeClass); sortAvailableWorksheets(); diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/ApplicationForms/TokenModal.css b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/ApplicationForms/TokenModal.css index baaa20114..fecb7fb67 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/ApplicationForms/TokenModal.css +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/ApplicationForms/TokenModal.css @@ -4,7 +4,7 @@ background-color: var(--bc-colors-grey-hover) !important; opacity: var(--bs-btn-disabled-opacity); background-blend-mode: difference; - border: none !important; + border: var(--bs-border-width) solid var(--bs-border-color); } .app-forms-token-wrapper { diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/Dashboard/Index.cshtml.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/Dashboard/Index.cshtml.cs index 9155568cd..d3a725aca 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/Dashboard/Index.cshtml.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/Dashboard/Index.cshtml.cs @@ -1,5 +1,5 @@ +using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; -using Microsoft.AspNetCore.Mvc.RazorPages; using Microsoft.AspNetCore.Mvc.Rendering; using Microsoft.EntityFrameworkCore; using System; @@ -12,166 +12,167 @@ using Unity.GrantManager.GrantApplications; using Unity.GrantManager.Identity; using Unity.GrantManager.Intakes; +using Unity.GrantManager.Permissions; using Volo.Abp.Domain.Repositories; -namespace Unity.GrantManager.Web.Pages.Dashboard +namespace Unity.GrantManager.Web.Pages.Dashboard; + +[Authorize(GrantApplicationPermissions.Dashboard.Default)] +public class IndexModel : GrantManagerPageModel { - public class IndexModel : PageModel + private readonly IIntakeRepository _intakeRepository; + private readonly IApplicationFormRepository _applicationFormRepository; + private readonly IApplicationStatusRepository _applicationStatusRepository; + private readonly IApplicationTagsRepository _applicationTagsRepository; + private readonly IApplicationAssignmentRepository _applicationAssignmentRepository; + private readonly IPersonRepository _personRepository; + + public List IntakeOptionsList { get; set; } = []; + public List CategoryOptionsList { get; set; } = []; + public List StatusOptionsList { get; set; } = []; + public List SubStatusActionList { get; set; } = []; + public List TagsOptionsList { get; set; } = []; + public List AssigneesOptionList { get; set; } = []; + + [BindProperty] + [Display(Name = "")] + public Guid[] IntakeIds { get; set; } = []; + [BindProperty] + [Display(Name = "")] + public string[]? CategoryNames { get; set; } + [BindProperty] + [Display(Name = "")] + public string[]? Statuses { get; set; } + [BindProperty] + [Display(Name = "")] + public string[]? SubStatuses { get; set; } + + [BindProperty] + [Display(Name = "")] + public DateTime? SubmissionDateFrom { get; set; } + [BindProperty] + [Display(Name = "")] + public DateTime? SubmissionDateTo { get; set; } + [BindProperty] + [Display(Name = "")] + public string[]? Tags { get; set; } + [BindProperty] + [Display(Name = "")] + public string[]? Assignees { get; set; } + + public List DashboardIntakes { get; set; } = []; + + public IndexModel(IIntakeRepository intakeRepository, + IApplicationFormRepository applicationFormRepository, + IApplicationStatusRepository applicationStatusRepository, + IApplicationTagsRepository applicationTagsRepository, + IApplicationAssignmentRepository applicationAssignmentRepository, + IPersonRepository personRepository) { - private readonly IIntakeRepository _intakeRepository; - private readonly IApplicationFormRepository _applicationFormRepository; - private readonly IApplicationStatusRepository _applicationStatusRepository; - private readonly IApplicationTagsRepository _applicationTagsRepository; - private readonly IApplicationAssignmentRepository _applicationAssignmentRepository; - private readonly IPersonRepository _personRepository; - - public List IntakeOptionsList { get; set; } = []; - public List CategoryOptionsList { get; set; } = []; - public List StatusOptionsList { get; set; } = []; - public List SubStatusActionList { get; set; } = []; - public List TagsOptionsList { get; set; } = []; - public List AssigneesOptionList { get; set; } = []; - - [BindProperty] - [Display(Name = "")] - public Guid[] IntakeIds { get; set; } = []; - [BindProperty] - [Display(Name = "")] - public string[]? CategoryNames { get; set; } - [BindProperty] - [Display(Name = "")] - public string[]? Statuses { get; set; } - [BindProperty] - [Display(Name = "")] - public string[]? SubStatuses { get; set; } - - [BindProperty] - [Display(Name = "")] - public DateTime? SubmissionDateFrom { get; set; } - [BindProperty] - [Display(Name = "")] - public DateTime? SubmissionDateTo { get; set; } - [BindProperty] - [Display(Name = "")] - public string[]? Tags { get; set; } - [BindProperty] - [Display(Name = "")] - public string[]? Assignees { get; set; } - - public List DashboardIntakes { get; set; } = []; - - public IndexModel(IIntakeRepository intakeRepository, - IApplicationFormRepository applicationFormRepository, - IApplicationStatusRepository applicationStatusRepository, - IApplicationTagsRepository applicationTagsRepository, - IApplicationAssignmentRepository applicationAssignmentRepository, - IPersonRepository personRepository) - { - _intakeRepository = intakeRepository; - _applicationFormRepository = applicationFormRepository; - _applicationStatusRepository = applicationStatusRepository; - _applicationTagsRepository = applicationTagsRepository; - _applicationAssignmentRepository = applicationAssignmentRepository; - _personRepository = personRepository; - } + _intakeRepository = intakeRepository; + _applicationFormRepository = applicationFormRepository; + _applicationStatusRepository = applicationStatusRepository; + _applicationTagsRepository = applicationTagsRepository; + _applicationAssignmentRepository = applicationAssignmentRepository; + _personRepository = personRepository; + } - public async Task OnGetAsync() + public async Task OnGetAsync() + { + using (_intakeRepository.DisableTracking()) + using (_applicationFormRepository.DisableTracking()) { - using (_intakeRepository.DisableTracking()) - using (_applicationFormRepository.DisableTracking()) + var intakesQ = from intakesq in await _intakeRepository.GetQueryableAsync() + join formsq in await _applicationFormRepository.GetQueryableAsync() on intakesq.Id equals formsq.IntakeId + select new IntakeQ + { + IntakeId = intakesq.Id, + IntakeCreationTime = intakesq.CreationTime, + IntakeName = intakesq.IntakeName, + Category = formsq.Category ?? DashboardConsts.EmptyValue + }; + + var intakeR = await intakesQ.ToListAsync(); + if (intakeR.Count == 0) return; + + IntakeOptionsList = intakeR.DistinctBy(s => s.IntakeId).Select(intake => new SelectListItem { Value = intake.IntakeId.ToString(), Text = intake.IntakeName }).ToList(); + var latestIntakeId = intakeR.OrderByDescending(intake => intake.IntakeCreationTime).FirstOrDefault()?.IntakeId; + IntakeIds = [latestIntakeId ?? Guid.Empty]; + + foreach (var intake in intakeR) { - var intakesQ = from intakesq in await _intakeRepository.GetQueryableAsync() - join formsq in await _applicationFormRepository.GetQueryableAsync() on intakesq.Id equals formsq.IntakeId - select new IntakeQ - { - IntakeId = intakesq.Id, - IntakeCreationTime = intakesq.CreationTime, - IntakeName = intakesq.IntakeName, - Category = formsq.Category ?? DashboardConsts.EmptyValue - }; - - var intakeR = await intakesQ.ToListAsync(); - if (intakeR.Count == 0) return; - - IntakeOptionsList = intakeR.DistinctBy(s => s.IntakeId).Select(intake => new SelectListItem { Value = intake.IntakeId.ToString(), Text = intake.IntakeName }).ToList(); - var latestIntakeId = intakeR.OrderByDescending(intake => intake.IntakeCreationTime).FirstOrDefault()?.IntakeId; - IntakeIds = [latestIntakeId ?? Guid.Empty]; - - foreach (var intake in intakeR) - { - List categoryList = [.. intakeR.Where(s => !string.IsNullOrWhiteSpace(s.Category) && s.IntakeId == intake.IntakeId) - .Select(s => s.Category) - .Distinct() - .OrderBy(c => c)]; - - DashboardIntakes.Add(new() - { - IntakeId = intake.IntakeId, - IntakeName = intake.IntakeName, - Categories = categoryList - }); - - if (intake.IntakeId == latestIntakeId) - { - CategoryOptionsList = categoryList.Select(category => new SelectListItem { Value = category, Text = category }).ToList(); - CategoryNames = [.. categoryList]; - } - } + List categoryList = [.. intakeR.Where(s => !string.IsNullOrWhiteSpace(s.Category) && s.IntakeId == intake.IntakeId) + .Select(s => s.Category) + .Distinct() + .OrderBy(c => c)]; - var statuses = await _applicationStatusRepository.GetListAsync(); - StatusOptionsList = statuses.Select(s => new SelectListItem { Value = s.StatusCode.ToString(), Text = s.InternalStatus }).ToList(); - Statuses = statuses.Select(s => s.StatusCode.ToString()).ToArray(); - SubStatusActionList = AssessmentResultsOptionsList.SubStatusActionList.Select(s => new SelectListItem { Value = s.Key, Text = s.Value }).ToList(); - SubStatusActionList.Add(new SelectListItem { Value = DashboardConsts.EmptyValue, Text = DashboardConsts.EmptyValue }); //for applications with no Sub-Status - SubStatuses = SubStatusActionList.Select(s => s.Value).ToArray(); + DashboardIntakes.Add(new() + { + IntakeId = intake.IntakeId, + IntakeName = intake.IntakeName, + Categories = categoryList + }); - await GetTagsFilter(); - await GetUsersFilter(); + if (intake.IntakeId == latestIntakeId) + { + CategoryOptionsList = categoryList.Select(category => new SelectListItem { Value = category, Text = category }).ToList(); + CategoryNames = [.. categoryList]; + } } - } - private async Task GetUsersFilter() - { - var userAssignments = await _applicationAssignmentRepository.GetQueryableAsync(); - var users = await _personRepository.GetQueryableAsync(); + var statuses = await _applicationStatusRepository.GetListAsync(); + StatusOptionsList = statuses.Select(s => new SelectListItem { Value = s.StatusCode.ToString(), Text = s.InternalStatus }).ToList(); + Statuses = statuses.Select(s => s.StatusCode.ToString()).ToArray(); + SubStatusActionList = AssessmentResultsOptionsList.SubStatusActionList.Select(s => new SelectListItem { Value = s.Key, Text = s.Value }).ToList(); + SubStatusActionList.Add(new SelectListItem { Value = DashboardConsts.EmptyValue, Text = DashboardConsts.EmptyValue }); //for applications with no Sub-Status + SubStatuses = SubStatusActionList.Select(s => s.Value).ToArray(); - var assignees = from userAssignment in userAssignments - join user in users on userAssignment.AssigneeId equals user.Id - select new { user.Id, user.FullName }; + await GetTagsFilter(); + await GetUsersFilter(); + } + } - var distinctOrderedUsers = assignees.Distinct().OrderBy(s => s.FullName); + private async Task GetUsersFilter() + { + var userAssignments = await _applicationAssignmentRepository.GetQueryableAsync(); + var users = await _personRepository.GetQueryableAsync(); - AssigneesOptionList = await distinctOrderedUsers.Select(user => new SelectListItem - { - Value = user.Id.ToString(), - Text = !string.IsNullOrEmpty(user.FullName) ? user.FullName : DashboardConsts.EmptyValue, - }).ToListAsync(); + var assignees = from userAssignment in userAssignments + join user in users on userAssignment.AssigneeId equals user.Id + select new { user.Id, user.FullName }; - AssigneesOptionList.Add(new SelectListItem { Value = string.Empty, Text = DashboardConsts.EmptyValue }); - Assignees = AssigneesOptionList.Select(s => s.Value).Distinct().ToArray(); - } + var distinctOrderedUsers = assignees.Distinct().OrderBy(s => s.FullName); - private async Task GetTagsFilter() + AssigneesOptionList = await distinctOrderedUsers.Select(user => new SelectListItem { - var tagResult = await _applicationTagsRepository.GetListAsync(true); - var tags = tagResult.SelectMany(tag => tag.Tag.Name.Split(',').Select(t => t.Trim())).Distinct(); + Value = user.Id.ToString(), + Text = !string.IsNullOrEmpty(user.FullName) ? user.FullName : DashboardConsts.EmptyValue, + }).ToListAsync(); - TagsOptionsList = tags.Select(tag => new SelectListItem - { - Value = tag, - Text = !string.IsNullOrEmpty(tag) ? tag : DashboardConsts.EmptyValue - }).ToList(); + AssigneesOptionList.Add(new SelectListItem { Value = string.Empty, Text = DashboardConsts.EmptyValue }); + Assignees = AssigneesOptionList.Select(s => s.Value).Distinct().ToArray(); + } - TagsOptionsList.Add(new SelectListItem { Value = string.Empty, Text = DashboardConsts.EmptyValue }); - Tags = TagsOptionsList.Select(tag => tag.Value).Distinct().ToArray(); - } + private async Task GetTagsFilter() + { + var tagResult = await _applicationTagsRepository.GetListAsync(true); + var tags = tagResult.SelectMany(tag => tag.Tag.Name.Split(',').Select(t => t.Trim())).Distinct(); - private sealed class IntakeQ + TagsOptionsList = tags.Select(tag => new SelectListItem { - public Guid IntakeId { get; internal set; } - public string? Category { get; internal set; } = null; - public DateTime IntakeCreationTime { get; internal set; } - public string IntakeName { get; internal set; } = string.Empty; - } + Value = tag, + Text = !string.IsNullOrEmpty(tag) ? tag : DashboardConsts.EmptyValue + }).ToList(); + + TagsOptionsList.Add(new SelectListItem { Value = string.Empty, Text = DashboardConsts.EmptyValue }); + Tags = TagsOptionsList.Select(tag => tag.Value).Distinct().ToArray(); + } + + private sealed class IntakeQ + { + public Guid IntakeId { get; internal set; } + public string? Category { get; internal set; } = null; + public DateTime IntakeCreationTime { get; internal set; } + public string IntakeName { get; internal set; } = string.Empty; } } diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Settings/TagManagement/TagManagement.js b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Settings/TagManagement/TagManagement.js index 8bfda579d..0b95a47da 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Settings/TagManagement/TagManagement.js +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Settings/TagManagement/TagManagement.js @@ -251,7 +251,7 @@ $(function () { function handleDeleteTag(id,tagText) { console.log("handleDeleteTag") - abp.message.confirm(`Are you sure you want to delete the "${tagText}" tag?`, "Delete Tag?") + abp.message.confirm(`Are you sure you want to delete this tag? Deleting it will remove the tag from all assigned records.`, "Delete Tag?") .then(function (confirmed) { if (confirmed) { try { diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Shared/Components/ApplicantInfo/Default.js b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Shared/Components/ApplicantInfo/Default.js index 7c6925a33..60444af53 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Shared/Components/ApplicantInfo/Default.js +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Shared/Components/ApplicantInfo/Default.js @@ -24,25 +24,25 @@ this.setupEventHandlers(); registerElectoralDistrictControls(this.zoneForm.form); registerApplicantInfoSummaryDropdowns(this.zoneForm.form); - }, - refresh: function () { - const currentFilters = this.getFilters(); - widgetManager.refresh($wrapper, currentFilters); - }, - setupEventHandlers: function () { - const self = this; + }, + refresh: function () { + const currentFilters = this.getFilters(); + widgetManager.refresh($wrapper, currentFilters); + }, + setupEventHandlers: function () { + const self = this; PubSub.subscribe( 'applicant_info_merged', () => { self.refresh(); } - ); + ); // Save button handler - self.zoneForm.saveButton.on('click', function () { - let applicationId = document.getElementById('ApplicantInfo_ApplicationId').value; - let applicantInfoSubmission = self.getPartialUpdate(); + self.zoneForm.saveButton.on('click', function () { + let applicationId = document.getElementById('ApplicantInfo_ApplicationId').value; + let applicantInfoSubmission = self.getPartialUpdate(); try { unity.grantManager.grantApplications.applicationApplicant .updatePartialApplicantInfo(applicationId, applicantInfoSubmission) @@ -59,18 +59,29 @@ } catch (error) { abp.notify.error('An unexpected error occurred.'); console.log(error); - } - }); - }, - getPartialUpdate: function () { - let submissionPayload = this.serializeWidget(); + } + }); + }, + getPartialUpdate: function () { + let submissionPayload = this.serializeWidget(); const customIncludes = new Set(); if (typeof Flex === 'function' && Object.keys(submissionPayload.CustomFields || {}).length > 0) { // Add Worksheet Metadata and filter conditions submissionPayload.CorrelationId = $("#ApplicantInfo_ApplicationFormVersionId").val(); - submissionPayload.WorksheetId = $("#ApplicantInfo_WorksheetId").val(); + // Check for worksheet scenario - multiple vs single + let multipleWorksheetsIds = $("#ApplicantInfo_WorksheetIds").val(); + let singleWorksheetId = $("#ApplicantInfo_WorksheetId").val(); + + // Set correct payload property based on worksheet scenario + if (multipleWorksheetsIds) { + // Multiple worksheets scenario - send as WorksheetIds array + submissionPayload.WorksheetIds = multipleWorksheetsIds.split(',').map(id => id.trim()); + } else if (singleWorksheetId) { + // Single worksheet scenario - send as WorksheetId + submissionPayload.WorksheetId = singleWorksheetId.trim(); + } // Normalize checkboxes to string for custom worksheets $(`#Unity_GrantManager_ApplicationManagement_Applicant_Worksheet input:checkbox`).each(function () { @@ -79,8 +90,14 @@ customIncludes .add('CustomFields') - .add('CorrelationId') - .add('WorksheetId'); + .add('CorrelationId'); + + // Add appropriate worksheet ID field based on scenario + if(multipleWorksheetsIds) { + customIncludes.add('WorksheetIds'); + } else if(singleWorksheetId) { + customIncludes.add('WorksheetId'); + } } customIncludes.add('ApplicantId'); @@ -97,8 +114,8 @@ data: unflattenObject(modifiedFieldData) }; - return partialSubmissionPayload; - }, + return partialSubmissionPayload; + }, serializeWidget: function () { let formData = this.zoneForm.serializeZoneArray(); let submissionPayload = {}; @@ -109,11 +126,11 @@ }); return submissionPayload; - }, - processFormField: function (submissionPayload, input) { + }, + processFormField: function (submissionPayload, input) { const fieldName = input.name; - const inputElement = $(`[name="${fieldName}"]`); - + const inputElement = $(`[name="${fieldName}"]`); + // Handle checkboxes explicitly if (inputElement.length && inputElement.attr('type') === 'checkbox') { // Only process the actual checkbox, not the hidden field @@ -123,34 +140,34 @@ if (typeof Flex === 'function' && Flex?.isCustomField(input)) { Flex.includeCustomFieldObj(submissionPayload, input); } else { - submissionPayload[fieldName] = checkbox.is(':checked'); + submissionPayload[fieldName] = checkbox.is(':checked'); } return; } - } - + } + // Existing logic for custom fields if (typeof Flex === 'function' && Flex?.isCustomField(input)) { Flex.includeCustomFieldObj(submissionPayload, input); return; } - let fieldValue = input.value; - + let fieldValue = input.value; + if (inputElement.hasClass('unity-currency-input') || inputElement.hasClass('numeric-mask')) { fieldValue = fieldValue.replace(/,/g, ''); - } + } if (fieldName.startsWith('ApplicantInfo.')) { const propertyName = fieldName.split('.')[1]; submissionPayload[propertyName] = fieldValue; } else { submissionPayload[fieldName] = fieldValue; - } - } - } + } + } + } - return widgetApi; + return widgetApi; } $(function () { @@ -365,18 +382,18 @@ $(function () { }); }); -$(document).on('click', '#btnClearOrgbook', function (e) { - e.preventDefault(); - const $f = $('#ApplicantInfoForm'); - - if ($f.find('#ApplicantSummary_OrgName').val()) $('#saveApplicantInfoBtn').prop('disabled', false); - - $f.find('#ApplicantSummary_OrgName').val('').trigger('change'); - $f.find('#ApplicantSummary_OrgNumber').val('').trigger('change'); - $f.find('#ApplicantSummary_OrgStatus').val('').trigger('change'); - $f.find('#ApplicantSummary_OrganizationType').val('').trigger('change'); - - $('#orgBookSelect').val(null).trigger('change'); +$(document).on('click', '#btnClearOrgbook', function (e) { + e.preventDefault(); + const $f = $('#ApplicantInfoForm'); + + if ($f.find('#ApplicantSummary_OrgName').val()) $('#saveApplicantInfoBtn').prop('disabled', false); + + $f.find('#ApplicantSummary_OrgName').val('').trigger('change'); + $f.find('#ApplicantSummary_OrgNumber').val('').trigger('change'); + $f.find('#ApplicantSummary_OrgStatus').val('').trigger('change'); + $f.find('#ApplicantSummary_OrganizationType').val('').trigger('change'); + + $('#orgBookSelect').val(null).trigger('change'); }); // Move to zone-extensions @@ -458,7 +475,7 @@ function registerApplicantInfoSummaryDropdowns($container) { $container.find('#ApplicantSummary_OrgStatus').val(org_status).trigger('change'); $container.find('#ApplicantSummary_OrganizationType').val(entity_type.value).trigger('change'); }); - }); + }); } function getAttributeObjectByType(type, attributes) { @@ -544,25 +561,25 @@ async function handleApplicantMerge(applicationId, principalApplicantId, nonPrin await setApplicantDuplicatedStatus(principalApplicantId, nonPrincipalApplicantId); - if (principalApplicantId === newData.ApplicantId) { - await updatePrincipalApplicant(applicationId, principalApplicantId); + if (principalApplicantId === newData.ApplicantId) { + await updatePrincipalApplicant(applicationId, principalApplicantId); } await updateMergedApplicant(applicationId, ApplicantInfoObj); } -function updateMergedApplicant(applicationId, appInfoObj) { - return unity.grantManager.grantApplications.grantApplication - .updateMergedApplicant(applicationId, appInfoObj) - .done(function () { - abp.notify.success( - 'The Applicant info has been updated.' - ); - $('#saveApplicantInfoBtn').prop('disabled', true); - PubSub.publish("refresh_detail_panel_summary"); - PubSub.publish('applicant_info_updated', appInfoObj); - PubSub.publish('applicant_info_merged'); - }); +function updateMergedApplicant(applicationId, appInfoObj) { + return unity.grantManager.grantApplications.grantApplication + .updateMergedApplicant(applicationId, appInfoObj) + .done(function () { + abp.notify.success( + 'The Applicant info has been updated.' + ); + $('#saveApplicantInfoBtn').prop('disabled', true); + PubSub.publish("refresh_detail_panel_summary"); + PubSub.publish('applicant_info_updated', appInfoObj); + PubSub.publish('applicant_info_merged'); + }); } async function generateUnityApplicantIdBtn() { @@ -597,10 +614,10 @@ async function checkUnityApplicantIdExist(unityAppId, appId, appInfoObj) { function enableApplicantInfoSaveBtn(inputText) { if (!$("#ApplicantInfoForm").valid() - || !abp.auth.isGranted('Unity.GrantManager.ApplicationManagement.Applicant') // Note: Will replace after worksheet permissions added - || !abp.auth.isGranted('Unity.GrantManager.ApplicationManagement.Applicant.Summary.Update') - || !abp.auth.isGranted('Unity.GrantManager.ApplicationManagement.Applicant.Authority.Update') - || !abp.auth.isGranted('Unity.GrantManager.ApplicationManagement.Applicant.Location.Update') + || !abp.auth.isGranted('Unity.GrantManager.ApplicationManagement.Applicant') // Note: Will replace after worksheet permissions added + || !abp.auth.isGranted('Unity.GrantManager.ApplicationManagement.Applicant.Summary.Update') + || !abp.auth.isGranted('Unity.GrantManager.ApplicationManagement.Applicant.Authority.Update') + || !abp.auth.isGranted('Unity.GrantManager.ApplicationManagement.Applicant.Location.Update') || !abp.auth.isGranted('Unity.GrantManager.ApplicationManagement.Applicant.Contact.Update') || formHasInvalidCurrencyCustomFields("ApplicantInfoForm")) { $('#saveApplicantInfoBtn').prop('disabled', true); @@ -634,20 +651,20 @@ function setApplicantDuplicatedStatus(principalApplicantId, nonPrincipalApplican }); } -function updatePrincipalApplicant(applicationId, principalApplicantId) { - return $.ajax({ - url: '/api/app/applicant/applicant-id', - type: 'PUT', - contentType: 'application/json', - data: JSON.stringify({ - applicationId: applicationId, - applicantId: principalApplicantId - }) - }) - .done(function () { - abp.notify.success('Principal Applicant updated successfully.'); - }) - .fail(function (xhr, status) { - abp.notify.error('Failed to update Principal Applicant.'); - }); +function updatePrincipalApplicant(applicationId, principalApplicantId) { + return $.ajax({ + url: '/api/app/applicant/applicant-id', + type: 'PUT', + contentType: 'application/json', + data: JSON.stringify({ + applicationId: applicationId, + applicantId: principalApplicantId + }) + }) + .done(function () { + abp.notify.success('Principal Applicant updated successfully.'); + }) + .fail(function (xhr, status) { + abp.notify.error('Failed to update Principal Applicant.'); + }); } diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Shared/Components/ApplicationBreadcrumbWidget/ApplicationBreadcrumbWidget.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Shared/Components/ApplicationBreadcrumbWidget/ApplicationBreadcrumbWidget.cs index 4e065bf15..ee16d0432 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Shared/Components/ApplicationBreadcrumbWidget/ApplicationBreadcrumbWidget.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Shared/Components/ApplicationBreadcrumbWidget/ApplicationBreadcrumbWidget.cs @@ -18,26 +18,44 @@ namespace Unity.GrantManager.Web.Views.Shared.Components.ApplicationBreadcrumbWi public class ApplicationBreadcrumbWidgetViewComponent : AbpViewComponent { private readonly IApplicationApplicantAppService _applicationApplicantAppService; - private readonly IApplicationFormVersionAppService _formVersionAppService; + private readonly IApplicationFormAppService _applicationFormAppService; - public ApplicationBreadcrumbWidgetViewComponent(IApplicationApplicantAppService applicationApplicantAppService, IApplicationFormVersionAppService formVersionAppService) + public ApplicationBreadcrumbWidgetViewComponent( + IApplicationApplicantAppService applicationApplicantAppService, + IApplicationFormAppService applicationFormAppService) { _applicationApplicantAppService = applicationApplicantAppService; - _formVersionAppService = formVersionAppService; + _applicationFormAppService = applicationFormAppService; } public async Task InvokeAsync(Guid applicationId) { var applicationApplicant = await _applicationApplicantAppService.GetByApplicationIdAsync(applicationId); - int formVersion = await _formVersionAppService.GetFormVersionByApplicationIdAsync(applicationId); - return View(new ApplicationBreadcrumbWidgetViewModel() - { + var formDetails = await _applicationFormAppService.GetFormDetailsByApplicationIdAsync(applicationId); + + return View(new ApplicationBreadcrumbWidgetViewModel() + { ApplicantName = applicationApplicant.ApplicantName, ApplicationStatus = applicationApplicant.ApplicationStatus, ReferenceNo = applicationApplicant.ApplicationReferenceNo, - ApplicationFormVersion = formVersion + ApplicationFormId = formDetails.ApplicationFormId, + ApplicationFormName = formDetails.ApplicationFormName, + ApplicationFormCategory = formDetails.ApplicationFormCategory, + ApplicationFormVersionId = formDetails.ApplicationFormVersionId, + ApplicationFormVersion = formDetails.ApplicationFormVersion, + SubmissionFormDescription = CreateSubmissionFormDescription(formDetails) }); } + + private static string CreateSubmissionFormDescription(ApplicationFormDetailsDto formDetails) + { + if (!string.IsNullOrWhiteSpace(formDetails.ApplicationFormCategory)) + { + return $"({formDetails.ApplicationFormCategory} V{formDetails.ApplicationFormVersion})"; + } + + return $"(Form V{formDetails.ApplicationFormVersion})"; + } } public class ApplicationBreadcrumbWidgetStyleBundleContributor : BundleContributor diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Shared/Components/ApplicationBreadcrumbWidget/ApplicationBreadcrumbWidgetViewModel.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Shared/Components/ApplicationBreadcrumbWidget/ApplicationBreadcrumbWidgetViewModel.cs index 4c31b3236..4ad298762 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Shared/Components/ApplicationBreadcrumbWidget/ApplicationBreadcrumbWidgetViewModel.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Shared/Components/ApplicationBreadcrumbWidget/ApplicationBreadcrumbWidgetViewModel.cs @@ -1,10 +1,18 @@ -namespace Unity.GrantManager.Web.Views.Shared.Components.ApplicationBreadcrumbWidget +using System; + +namespace Unity.GrantManager.Web.Views.Shared.Components.ApplicationBreadcrumbWidget { public class ApplicationBreadcrumbWidgetViewModel { public string ReferenceNo { get; set; } = string.Empty; public string ApplicantName { get; set; } = string.Empty; public string ApplicationStatus { get; set; } = string.Empty; + + public Guid ApplicationFormId { get; set; } = Guid.Empty; + public string ApplicationFormName { get; set; } = string.Empty; + public string ApplicationFormCategory { get; set; } = string.Empty; + public Guid ApplicationFormVersionId { get; set; } = Guid.Empty; public int ApplicationFormVersion { get; set; } = 0; + public string SubmissionFormDescription { get; set; } = string.Empty; } } diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Shared/Components/ApplicationBreadcrumbWidget/Default.cshtml b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Shared/Components/ApplicationBreadcrumbWidget/Default.cshtml index 371640448..bd60256de 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Shared/Components/ApplicationBreadcrumbWidget/Default.cshtml +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Shared/Components/ApplicationBreadcrumbWidget/Default.cshtml @@ -7,7 +7,7 @@
@Model.ReferenceNo
@Model.ApplicantName
-
@(string.Format("(Form Version: {0})", Model.ApplicationFormVersion))
+
@Model.SubmissionFormDescription
@Model.ApplicationStatus
diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Shared/Components/AssessmentResults/Default.js b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Shared/Components/AssessmentResults/Default.js index b1583978a..11a8042d6 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Shared/Components/AssessmentResults/Default.js +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Shared/Components/AssessmentResults/Default.js @@ -6,7 +6,9 @@ let combinedData = formData.concat(assessmentResultsCustomForm); let assessmentResultObj = {}; let formVersionId = $("#ApplicationFormVersionId").val(); - let worksheetId = $("#AssessmentInfo_WorksheetId").val(); + // Check for worksheet scenario - multiple vs single + let multipleWorksheetsIds = $("#AssessmentInfo_WorksheetIds").val(); + let singleWorksheetId = $("#AssessmentInfo_WorksheetId").val(); $.each(combinedData, function (_, input) { if (typeof Flex === 'function' && Flex?.isCustomField(input)) { @@ -48,7 +50,16 @@ try { assessmentResultObj['correlationId'] = formVersionId; - assessmentResultObj['worksheetId'] = worksheetId; + + // Set correct payload property based on worksheet scenario + if (multipleWorksheetsIds) { + // Multiple worksheets scenario - send as WorksheetIds array + assessmentResultObj['worksheetIds'] = multipleWorksheetsIds.split(',').map(id => id.trim()); + } else if (singleWorksheetId) { + // Single worksheet scenario - send as WorksheetId + assessmentResultObj['worksheetId'] = singleWorksheetId.trim(); + } + if(assessmentResultObj['ApprovedAmount'] == '') { assessmentResultObj['ApprovedAmount'] = null; } diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Shared/Components/FundingAgreementInfo/Default.js b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Shared/Components/FundingAgreementInfo/Default.js index 9c3a8d81c..285a05f60 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Shared/Components/FundingAgreementInfo/Default.js +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Shared/Components/FundingAgreementInfo/Default.js @@ -4,7 +4,9 @@ let formVersionId = $("#FundingAgreementInfoView_FormVersionId").val(); let formData = $("#fundingAgreementInfoForm").serializeArray(); let fundingAgreementInfoObj = {}; - let worksheetId = $("#FundingAgreementInfo_WorksheetId").val(); + // Check for worksheet scenario - multiple vs single + let multipleWorksheetsIds = $("#FundingAgreementInfo_WorksheetIds").val(); + let singleWorksheetId = $("#FundingAgreementInfo_WorksheetId").val(); $.each(formData, function (_, input) { if (typeof Flex === 'function' && Flex?.isCustomField(input)) { @@ -25,7 +27,15 @@ } fundingAgreementInfoObj['correlationId'] = formVersionId; - fundingAgreementInfoObj['worksheetId'] = worksheetId; + + // Set correct payload property based on worksheet scenario + if (multipleWorksheetsIds) { + // Multiple worksheets scenario - send as worksheetIds array + fundingAgreementInfoObj['worksheetIds'] = multipleWorksheetsIds.split(',').map(id => id.trim()); + } else if (singleWorksheetId) { + // Single worksheet scenario - send as worksheetId + fundingAgreementInfoObj['worksheetId'] = singleWorksheetId.trim(); + } updateFundingAgreementInfo(applicationId, fundingAgreementInfoObj); }); diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Shared/Components/ProjectInfo/Default.js b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Shared/Components/ProjectInfo/Default.js index 036bde603..f2101f7c8 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Shared/Components/ProjectInfo/Default.js +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Shared/Components/ProjectInfo/Default.js @@ -41,7 +41,18 @@ abp.widgets.ProjectInfo = function ($wrapper) { if (typeof Flex === 'function' && Object.keys(projectInfoObj.CustomFields || {}).length > 0) { // Add Worksheet Metadata and filter conditions projectInfoObj.CorrelationId = $("#ProjectInfo_ApplicationFormVersionId").val(); - projectInfoObj.WorksheetId = $("#ProjectInfo_WorksheetId").val(); + // Check for worksheet scenario - multiple vs single + let multipleWorksheetsIds = $("#ProjectInfo_WorksheetIds").val(); + let singleWorksheetId = $("#ProjectInfo_WorksheetId").val(); + + // Set correct payload property based on worksheet scenario + if (multipleWorksheetsIds) { + // Multiple worksheets scenario - send as WorksheetIds array + projectInfoObj.WorksheetIds = multipleWorksheetsIds.split(',').map(id => id.trim()); + } else if (singleWorksheetId) { + // Single worksheet scenario - send as WorksheetId + projectInfoObj.WorksheetId = singleWorksheetId.trim(); + } // Normalize checkboxes to string for custom worksheets $(`#Unity_GrantManager_ApplicationManagement_Project_Worksheet input:checkbox`).each(function () { @@ -50,8 +61,14 @@ abp.widgets.ProjectInfo = function ($wrapper) { customIncludes .add('CustomFields') - .add('CorrelationId') - .add('WorksheetId'); + .add('CorrelationId'); + + // Add appropriate worksheet ID field based on scenario + if (multipleWorksheetsIds) { + customIncludes.add('WorksheetIds'); + } else if (singleWorksheetId) { + customIncludes.add('WorksheetId'); + } } // Create filtered object in one functional operation diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Shared/Components/SummaryWidget/Default.css b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Shared/Components/SummaryWidget/Default.css index 92cd3386d..d96a3fce6 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Shared/Components/SummaryWidget/Default.css +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Shared/Components/SummaryWidget/Default.css @@ -22,9 +22,9 @@ background-color: var(--bc-colors-grey-hover) !important; opacity: var(--bs-btn-disabled-opacity); background-blend-mode: difference; - border: none !important; + border: var(--bs-border-width) solid var(--bs-border-color); padding: 0.4rem; - border-radius: 2px; + border-radius: var(--bc-layout-margin-small) !important; min-height: 2rem; } @@ -56,4 +56,4 @@ .currency-display { text-align: right; -} \ No newline at end of file +} diff --git a/database/crunchy-postgres/templates/data-restore-configmap.yaml b/database/crunchy-postgres/templates/data-restore-configmap.yaml index d60ad8ea6..7c268931d 100644 --- a/database/crunchy-postgres/templates/data-restore-configmap.yaml +++ b/database/crunchy-postgres/templates/data-restore-configmap.yaml @@ -21,9 +21,9 @@ data: repo{{ .Values.dataRestore.repo.name | replace "repo" "" }}-type=s3 repo{{ .Values.dataRestore.repo.name | replace "repo" "" }}-s3-bucket={{ .Values.dataRestore.repo.bucket }} repo{{ .Values.dataRestore.repo.name | replace "repo" "" }}-s3-endpoint={{ .Values.dataRestore.repo.endpoint }} - repo{{ .Values.dataRestore.repo.name | replace "repo" "" }}-s3-region={{ .Values.dataRestore.repo.s3.region | default "not-used" }} + repo{{ .Values.dataRestore.repo.name | replace "repo" "" }}-s3-region={{ .Values.dataRestore.repo.region | default "not-used" }} repo{{ .Values.dataRestore.repo.name | replace "repo" "" }}-path={{ .Values.dataRestore.repo.path }} - repo{{ .Values.dataRestore.repo.name | replace "repo" "" }}-s3-uri-style={{ .Values.dataRestore.repo.s3.uriStyle | default "path" }} + repo{{ .Values.dataRestore.repo.name | replace "repo" "" }}-s3-uri-style={{ .Values.dataRestore.repo.uriStyle | default "path" }} log-level-console=info log-level-file=debug