diff --git a/.github/workflows/docker-build-dev.yml b/.github/workflows/docker-build-dev.yml index c62ad497f..70596aa88 100644 --- a/.github/workflows/docker-build-dev.yml +++ b/.github/workflows/docker-build-dev.yml @@ -1,4 +1,6 @@ name: Dev - Build & Push docker images +permissions: + contents: read on: push: @@ -87,6 +89,8 @@ jobs: needs: [Setup,Branch] runs-on: ubuntu-latest environment: dev + permissions: + actions: write steps: - name: Checkout repository uses: actions/checkout@v4 diff --git a/.github/workflows/docker-build-main.yml b/.github/workflows/docker-build-main.yml index e87dcb553..f583143dc 100644 --- a/.github/workflows/docker-build-main.yml +++ b/.github/workflows/docker-build-main.yml @@ -1,4 +1,6 @@ name: Main - Build & Push docker images +permissions: + contents: read on: push: @@ -36,7 +38,7 @@ env: UGM_RELEASE_PREFIX: Unity_Grant_Manager_v UGM_RELEASE_MESSAGE: "Production deployment" -jobs: +jobs: Setup: runs-on: ubuntu-latest environment: main @@ -87,6 +89,8 @@ jobs: needs: [Setup,Branch] runs-on: ubuntu-latest environment: main + permissions: + contents: write steps: - name: Checkout repository uses: actions/checkout@v4 @@ -138,6 +142,8 @@ jobs: needs: [Setup,Branch,GenerateTag] runs-on: ubuntu-latest environment: main + permissions: + actions: write steps: - name: Checkout repository uses: actions/checkout@v4 diff --git a/.github/workflows/docker-build-test.yml b/.github/workflows/docker-build-test.yml index e596ec4dc..c061a34c6 100644 --- a/.github/workflows/docker-build-test.yml +++ b/.github/workflows/docker-build-test.yml @@ -1,4 +1,6 @@ name: Test - Build & Push docker images +permissions: + contents: read on: push: @@ -110,6 +112,8 @@ jobs: TAGVERSION: ${{steps.tag_selector.outputs.TAGVERSION}} PushVariables: needs: [Setup,Branch,GenerateTag] + permissions: + actions: write runs-on: ubuntu-latest environment: test steps: diff --git a/.github/workflows/manual-trigger.yml b/.github/workflows/manual-trigger.yml index 664b693c5..31415a568 100644 --- a/.github/workflows/manual-trigger.yml +++ b/.github/workflows/manual-trigger.yml @@ -1,6 +1,8 @@ # This is a basic workflow that is manually triggered name: Workflow - Run manual trigger +permissions: + contents: read # Controls when the action will run. Workflow runs when manually triggered on: @@ -82,6 +84,8 @@ jobs: needs: [Setup,Branch] runs-on: ubuntu-latest environment: ${{ inputs.name }} + permissions: + actions: write steps: - name: Checkout repository uses: actions/checkout@v4 diff --git a/.github/workflows/pr-check-dev-branch.yml b/.github/workflows/pr-check-dev-branch.yml index 9de01e89c..1f90bf25d 100644 --- a/.github/workflows/pr-check-dev-branch.yml +++ b/.github/workflows/pr-check-dev-branch.yml @@ -1,4 +1,6 @@ name: Dev - Branch Protection +permissions: + contents: read on: pull_request: diff --git a/.github/workflows/pr-check-main-branch.yml b/.github/workflows/pr-check-main-branch.yml index 9456f3f65..536793d73 100644 --- a/.github/workflows/pr-check-main-branch.yml +++ b/.github/workflows/pr-check-main-branch.yml @@ -1,4 +1,6 @@ name: Main - Branch Protection +permissions: + contents: read on: pull_request: diff --git a/.github/workflows/pr-check-test-branch.yml b/.github/workflows/pr-check-test-branch.yml index cad2784dc..236607db9 100644 --- a/.github/workflows/pr-check-test-branch.yml +++ b/.github/workflows/pr-check-test-branch.yml @@ -1,4 +1,6 @@ name: Test - Branch Protection +permissions: + contents: read on: pull_request: diff --git a/README.md b/README.md index b44735c63..4425d1952 100644 --- a/README.md +++ b/README.md @@ -1,23 +1,26 @@ # Unity Portal + [![Lifecycle:Stable](https://img.shields.io/badge/Lifecycle-Stable-97ca00)](https://github.com/bcgov/repomountie/blob/master/doc/lifecycle-badges.m) The project is in a reliable state and major changes are unlikely to happen. ## Directory Structure - .github - GitHub Actions - applications/ - Application Root - ├── Unity.ApplicantPortal/ - Applicant Information solution - ├── Unity.AutoUI/ - Automated User Interface testing - ├── Unity.GrantManager/ - Grant manager and adjudication solution - ├── Unity.RabbitMQ/ - Messaging and streaming broker configuration - ├── Unity.Tools/ - DevOps tools - database/ - Database configuration files - documentation/ - Solution documentation and assets - openshift/ - OpenShift deployment files - COMPLIANCE.yaml - BCGov PIA/STRA compliance status - CONTRIBUTING.md - How to contribute - LICENSE - License - SECURITY.md - Security Policy and Reporting + .github/ - GitHub Actions and workflows + applications/ - Application root containing all major components + ├── Unity.AutoUI/ - Automated end-to-end UI testing (Cypress) + ├── Unity.GrantManager/ - Grant management and adjudication solution + └── Unity.Tools/ - Supporting tools and services + ├── Unity.Metabase/ - Reserved for Metabase integration + ├── Unity.NginxData/ - Nginx HTTP server and reference files + ├── Unity.RabbitMQ/ - RabbitMQ message broker configuration + └── Unity.RedisSentinel/- Redis Sentinel high-availability setup + database/ - Database configuration and scripts + documentation/ - Solution documentation and assets + openshift/ - OpenShift deployment files and configs + COMPLIANCE.yaml - BCGov PIA/STRA compliance status + CONTRIBUTING.md - How to contribute + LICENSE - License + SECURITY.md - Security Policy and Reporting ## Documentation diff --git a/SECURITY.md b/SECURITY.md index 888a18c28..564e48f7f 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -3,7 +3,7 @@ This document outlines security procedures for the Economy Sector Grant Management Solution application project. - [Supported Versions](#supported-versions) -- [Reporting a Security Bug](#reporting-a-bug) +- [Reporting a Security Bug](#reporting-a-security-bug) - [Disclosure Policy](#disclosure-policy) - [Comments on this Policy](#comments-on-this-policy) @@ -17,7 +17,7 @@ This document outlines security procedures for the Economy Sector Grant Manageme ## Reporting a Security Bug -The `Unity` team and community take all security bugs seriously. Reporting security issues can be helpful to the team this can be done by sending an email to +The `Unity` team and community take all security bugs seriously. Reporting security issues can be helpful to the team. This can be done by sending an email to ## Disclosure Policy @@ -29,4 +29,4 @@ When the `Unity` team receives a bug report, they will assign it to a primary ha ## Comments on this Policy -If you have suggestions on how this process could be improved please send an email to \ No newline at end of file +If you have suggestions on how this process could be improved please send an email to diff --git a/applications/README.md b/applications/README.md index b08482651..d0aef0e30 100644 --- a/applications/README.md +++ b/applications/README.md @@ -1,7 +1,7 @@ -# Unity Solution +# Unity Application Solution -- [Unity.ApplicantPortal](Unity.ApplicantPortal/README.md) -- [Unity.AutoUI](Unity.AutoUI/README.md) -- [Unity.GrantManager](Unity.GrantManager/README.md) -- [Unity.RabbitMQ](Unity.RabbitMQ/README.md) -- [Unity.Tools](Unity.Tools/README.md) \ No newline at end of file +This directory contains all major application components for the Unity platform: + +- [Unity.AutoUI](Unity.AutoUI/README.md): Cypress-based end-to-end testing project for the Unity Grant Manager application. +- [Unity.GrantManager](Unity.GrantManager/README.md): Main grant management application, including backend and web components. +- [Unity.Tools](Unity.Tools/README.md): Collection of supporting tools and services for the Unity platform. diff --git a/applications/Unity.ApplicantPortal/README.md b/applications/Unity.ApplicantPortal/README.md deleted file mode 100644 index 6d64992e7..000000000 --- a/applications/Unity.ApplicantPortal/README.md +++ /dev/null @@ -1,2 +0,0 @@ -# Unity Applicant Portal -Removed until picked up again with updated NuGet packages and when CHEFS has figured out how to do MultiTenancy diff --git a/applications/Unity.ApplicantPortal/Unity.ApplicantPortal.sln b/applications/Unity.ApplicantPortal/Unity.ApplicantPortal.sln deleted file mode 100644 index 9e56b7a71..000000000 --- a/applications/Unity.ApplicantPortal/Unity.ApplicantPortal.sln +++ /dev/null @@ -1,41 +0,0 @@ -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 17 -VisualStudioVersion = 17.8.34309.116 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Unity.ApplicantPortal.Web", "Unity.ApplicantPortal.Web\Unity.ApplicantPortal.Web.csproj", "{9EBED5DE-596F-4A33-B5E8-AB64201CF1D0}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Unity.ApplicantPortal.Web.Tests", "Unity.ApplicantPortal.Web.Tests\Unity.ApplicantPortal.Web.Tests.csproj", "{5207412E-86F8-40E9-82AC-55E70C8ED561}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Unity.ApplicantPortal.Data", "Unity.ApplicantPortal.Data\Unity.ApplicantPortal.Data.csproj", "{6E56D97A-D4B3-44CB-85CD-8270913E6EEA}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{2EAEEE3A-8D30-43FE-959E-0E95A4DF01DE}" - ProjectSection(SolutionItems) = preProject - .editorconfig = .editorconfig - EndProjectSection -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Release|Any CPU = Release|Any CPU - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {9EBED5DE-596F-4A33-B5E8-AB64201CF1D0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {9EBED5DE-596F-4A33-B5E8-AB64201CF1D0}.Debug|Any CPU.Build.0 = Debug|Any CPU - {9EBED5DE-596F-4A33-B5E8-AB64201CF1D0}.Release|Any CPU.ActiveCfg = Release|Any CPU - {9EBED5DE-596F-4A33-B5E8-AB64201CF1D0}.Release|Any CPU.Build.0 = Release|Any CPU - {5207412E-86F8-40E9-82AC-55E70C8ED561}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {5207412E-86F8-40E9-82AC-55E70C8ED561}.Debug|Any CPU.Build.0 = Debug|Any CPU - {5207412E-86F8-40E9-82AC-55E70C8ED561}.Release|Any CPU.ActiveCfg = Release|Any CPU - {5207412E-86F8-40E9-82AC-55E70C8ED561}.Release|Any CPU.Build.0 = Release|Any CPU - {6E56D97A-D4B3-44CB-85CD-8270913E6EEA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {6E56D97A-D4B3-44CB-85CD-8270913E6EEA}.Debug|Any CPU.Build.0 = Debug|Any CPU - {6E56D97A-D4B3-44CB-85CD-8270913E6EEA}.Release|Any CPU.ActiveCfg = Release|Any CPU - {6E56D97A-D4B3-44CB-85CD-8270913E6EEA}.Release|Any CPU.Build.0 = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {A6BD9E02-0080-4512-ACA9-0F380B5FC305} - EndGlobalSection -EndGlobal diff --git a/applications/Unity.AutoUI/README.md b/applications/Unity.AutoUI/README.md index 2625371c9..2479786ea 100644 --- a/applications/Unity.AutoUI/README.md +++ b/applications/Unity.AutoUI/README.md @@ -2,6 +2,16 @@ This project uses a Cypress folder structure to automate end-to-end testing for the Unity Grant Manager application. The Cypress testing framework executes automated tests to ensure the quality and reliability of the web application using continuous integration. +## Subfolders and Files + +- `cypress/`: Cypress configuration and test files. +- `cypress.config.ts`: Cypress configuration in TypeScript. +- `cypress.pipeline.env.json`: CI/CD environment overrides. +- `package.json`, `package-lock.json`: Project dependencies and metadata. +- `tsconfig.json`: TypeScript configuration. + +See the README for setup and usage instructions. + ## Getting Started To get started with this Cypress project, follow these steps: diff --git a/applications/Unity.AutoUI/cypress/e2e/chefsdata.cy.ts b/applications/Unity.AutoUI/cypress/e2e/chefsdata.cy.ts index 3ffd75071..48432f83d 100644 --- a/applications/Unity.AutoUI/cypress/e2e/chefsdata.cy.ts +++ b/applications/Unity.AutoUI/cypress/e2e/chefsdata.cy.ts @@ -1,14 +1,19 @@ +/// describe('Unity Login and check data from CHEFS', () => { + it('Verify Login', () => { cy.login() }) // 19.) Verify that the info panel populates with mapped data it('Verify the UI is populated with valid data from CHEFS', () => { + cy.getSubmissionDetail('confirmationID').then(id => {cy.log(`Confirmation ID: ${id}`);}); + cy.get('#search').should('exist').clear(); // Ensure the field exists and clear its contents cy.get('#search').click() // click the search field cy.getSubmissionDetail('confirmationID').then(id => cy.get('#search').type(id)); // Fetch the confirmation ID and type it into the search field cy.getSubmissionDetail('confirmationID').then(id => cy.contains('tr', id).find('.checkbox-select').click()); // Fetch the confirmation ID, find its row, and click the checkbox + cy.get('#applicationLink').should('exist').click() // open the info panel // 19.) Verify that the info panel populates with mapped data // Category: AutoUI @@ -153,17 +158,15 @@ describe('Unity Login and check data from CHEFS', () => { }) // 25 Verify that the Payment Info tab populates with mapped data cy.get('#nav-payment-info-tab').should('exist').click() // open the Payment Info tab - // Requested Amount: 89000.00 - cy.get('#RequestedAmount').should('have.value', '89000.00') + // Requested Amount: 89,000.00 + cy.get('#RequestedAmount').should('have.value', '89,000.00') // 26.) Verify that the Submission tab populates with all form data cy.get('#nav-summery-tab').should('exist').click() // open the Submission tab - cy.getSubmissionDetail('formObjectID').then(formId => { // Fetch formObjectID - let headers = ['1. INTRODUCTION','2. ELIGIBILITY','3. APPLICANT INFORMATION','4. PROJECT INFORMATION','5. PROJECT TIMELINES','6. PROJECT BUDGET','7. ATTESTATION']; // Define headers - headers.forEach((header, index) => { // Iterate over headers - cy.get(`#${formId} > div:nth-child(${index + 1}) > div.card-header.bg-default > h4`) // Select header element - .should('contain', header) // Assert header text - .click(); // Click header to expand/collapse - }); + const headers = ['1. INTRODUCTION', '2. ELIGIBILITY', '3. APPLICANT INFORMATION','4. PROJECT INFORMATION', '5. PROJECT TIMELINES', '6. PROJECT BUDGET', '7. ATTESTATION']; + headers.forEach(header => { + cy.contains('h4', header) + .should('exist') + .click(); }); }) it('Verify Logout', () => { diff --git a/applications/Unity.AutoUI/cypress/e2e/lists.cy.ts b/applications/Unity.AutoUI/cypress/e2e/lists.cy.ts index e3777f552..5bb645d36 100644 --- a/applications/Unity.AutoUI/cypress/e2e/lists.cy.ts +++ b/applications/Unity.AutoUI/cypress/e2e/lists.cy.ts @@ -1,10 +1,11 @@ describe('Grant Manager Login and List Navigation', () => { + it('Verify Login', () => { cy.login() }) // 12.) Ensure all of the lists are populated. it('Verify Applications, Roles, Users, Intakes, Forms, Dashboard lists are populated', () => { - // 12.) Verify Default Grant Program tenant is selected. + // Verify Default Grant Program tenant is selected. cy.get('.unity-user-initials').should('exist').click() cy.get('#user-dropdown .btn-dropdown span').should('contain', 'Default Grants Program') // 13.) Applications diff --git a/applications/Unity.AutoUI/cypress/e2e/login.cy.ts b/applications/Unity.AutoUI/cypress/e2e/login.cy.ts index f410431dd..8dc67c30f 100644 --- a/applications/Unity.AutoUI/cypress/e2e/login.cy.ts +++ b/applications/Unity.AutoUI/cypress/e2e/login.cy.ts @@ -1,4 +1,5 @@ describe('Grant Manager Login and Logout', () => { + it('Verify Default Grant Program tenant is selected.', () => { cy.login() cy.get('.unity-user-initials').should('exist').click() diff --git a/applications/Unity.AutoUI/cypress/e2e/navigation.cy.ts b/applications/Unity.AutoUI/cypress/e2e/navigation.cy.ts index ec55a29b0..bb41f556c 100644 --- a/applications/Unity.AutoUI/cypress/e2e/navigation.cy.ts +++ b/applications/Unity.AutoUI/cypress/e2e/navigation.cy.ts @@ -1,4 +1,5 @@ describe('Grant Manager Login and Top Navigation', () => { + it('Verify Login', () => { cy.login() }) diff --git a/applications/Unity.AutoUI/cypress/fixtures/submissions.json b/applications/Unity.AutoUI/cypress/fixtures/submissions.json index c91c1fd9b..d84fb5785 100644 --- a/applications/Unity.AutoUI/cypress/fixtures/submissions.json +++ b/applications/Unity.AutoUI/cypress/fixtures/submissions.json @@ -13,7 +13,7 @@ { "unityEnv": "TEST", "confirmationID": "68090C5E", - "formObjectID": "efkdeiq" + "formObjectID": "evigmss" }, { "unityEnv": "UAT", diff --git a/applications/Unity.AutoUI/cypress/support/commands.ts b/applications/Unity.AutoUI/cypress/support/commands.ts index 24ffbce82..b302bf72e 100644 --- a/applications/Unity.AutoUI/cypress/support/commands.ts +++ b/applications/Unity.AutoUI/cypress/support/commands.ts @@ -75,21 +75,22 @@ Cypress.Commands.add('getMetabaseDetail', (key: string) => { }); Cypress.Commands.add('metabaseLogin', () => { - cy.getMetabaseDetail('baseURL').then(baseURL => {cy.visit(baseURL); // Visit the URL fetched from metabase.json - cy.get('#root > div > div > main > div > div.emotion-iq817s.euvero02 > div > div.emotion-1spv9yy > div > form > div:nth-child(1) > div.emotion-17sifsc.edcfyzd6 > input[name="username"]') - .should('exist') - .click(); - cy.get('#root > div > div > main > div > div.emotion-iq817s.euvero02 > div > div.emotion-1spv9yy > div > form > div:nth-child(1) > div.emotion-17sifsc.edcfyzd6 > input[name="username"]') - .type('iDontHave@ValidEmail.com'); // the test account doesn't have an email address - cy.get('#root > div > div > main > div > div.emotion-iq817s.euvero02 > div > div.emotion-1spv9yy > div > form > div:nth-child(2) > div.emotion-17sifsc.edcfyzd6 > input[name="password"]') + cy.getMetabaseDetail('baseURL').then((baseURL) => { + cy.visit(baseURL); + + // Target the username field using its `name` attribute + cy.get('input[name="username"]') .should('exist') - .click(); - cy.get('#root > div > div > main > div > div.emotion-iq817s.euvero02 > div > div.emotion-1spv9yy > div > form > div:nth-child(2) > div.emotion-17sifsc.edcfyzd6 > input[name="password"]') + .click() + .type('iDontHave@ValidEmail.com'); // Placeholder email address + + // Target the password field using its `name` attribute + cy.get('input[name="password"]') .should('exist') - .type('pointless'); // there's no point adding a valid password yet because the test account doesn't have an email address - //.type(Cypress.env('test1password')) + .click() + .type('pointless'); // Placeholder password }); - }); +}); interface chefsDetail { unityEnv: string; diff --git a/applications/Unity.GrantManager/README.md b/applications/Unity.GrantManager/README.md index 22cec284b..5518ac38b 100644 --- a/applications/Unity.GrantManager/README.md +++ b/applications/Unity.GrantManager/README.md @@ -1,5 +1,13 @@ # Unity Grant Manager Application +This is the main grant management application for the Unity platform. It includes backend services, web components, and database management. + +## Subfolders + +- `modules/`: Application modules. +- `src/`: Source code for the application. +- `test/`: Test projects and files. + ## Getting Started 1. With .NET Core installed, run `dotnet tool install -g Volo.Abp.Cli` @@ -26,4 +34,4 @@ - [ABP Platform Roadmap](https://docs.abp.io/en/abp/latest/Road-Map) - [ABP Platform Module Packages](https://abp.io/packages) -- [EF Core Database Migrations](https://docs.abp.io/en/abp/latest/Entity-Framework-Core-Migrations) +- [EF Core Database Migrations](https://docs.abp.io/en/abp/latest/Entity-Framework-Core-Migrations) diff --git a/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Application.Contracts/Scoresheets/QuestionDto.cs b/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Application.Contracts/Scoresheets/QuestionDto.cs index affa91464..3708cad7c 100644 --- a/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Application.Contracts/Scoresheets/QuestionDto.cs +++ b/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Application.Contracts/Scoresheets/QuestionDto.cs @@ -12,7 +12,6 @@ public class QuestionDto : ExtensibleEntityDto public virtual string Name { get; set; } = string.Empty; public virtual string Label { get; set; } = string.Empty; public virtual string? Description { get; set; } - public virtual bool Enabled { get; private set; } public virtual QuestionType Type { get; set; } public virtual uint Order { get; set; } diff --git a/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/FlexWebModule.cs b/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/FlexWebModule.cs index e89257b32..2b8ccff96 100644 --- a/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/FlexWebModule.cs +++ b/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/FlexWebModule.cs @@ -1,12 +1,10 @@ using Microsoft.AspNetCore.Mvc.RazorPages; using Microsoft.Extensions.DependencyInjection; using Unity.Flex.Localization; -using Unity.Flex.Web.Menus; using Volo.Abp.AspNetCore.Mvc.Localization; using Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared; using Volo.Abp.AutoMapper; using Volo.Abp.Modularity; -using Volo.Abp.UI.Navigation; using Volo.Abp.VirtualFileSystem; namespace Unity.Flex.Web; @@ -33,7 +31,7 @@ public override void PreConfigureServices(ServiceConfigurationContext context) public override void ConfigureServices(ServiceConfigurationContext context) { - + Configure(options => { diff --git a/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Pages/Components/DataGrid/DataGridReadService.cs b/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Pages/Components/DataGrid/DataGridReadService.cs index 07e3ed7cf..a08a9e245 100644 --- a/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Pages/Components/DataGrid/DataGridReadService.cs +++ b/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Pages/Components/DataGrid/DataGridReadService.cs @@ -2,7 +2,6 @@ using System.Collections.Generic; using System.Text.Json; using System.Threading.Tasks; -using Unity.Flex.Web.Views.Shared.Components.DataGridWidget; using Unity.Flex.Web.Views.Shared.Components.WorksheetInstanceWidget.ViewModels; using Unity.Flex.WorksheetInstances; using Unity.Flex.Worksheets; diff --git a/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Pages/Components/DataGrid/DataGridWriteService.cs b/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Pages/Components/DataGrid/DataGridWriteService.cs index e244649d7..6a1440df9 100644 --- a/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Pages/Components/DataGrid/DataGridWriteService.cs +++ b/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Pages/Components/DataGrid/DataGridWriteService.cs @@ -4,7 +4,6 @@ using System.Linq; using System.Text.Json; using System.Threading.Tasks; -using Unity.Flex.Web.Views.Shared.Components.DataGridWidget; using Unity.Flex.WorksheetInstances; using Unity.Flex.Worksheets; using Unity.Flex.Worksheets.Definitions; diff --git a/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Unity.Flex.Web.csproj b/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Unity.Flex.Web.csproj index 62a83d1be..ebac4ee98 100644 --- a/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Unity.Flex.Web.csproj +++ b/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Unity.Flex.Web.csproj @@ -1,171 +1,63 @@  - - - - net9.0 - enable - true - Library - Unity.Flex.Web - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Always - - - Always - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - true - PreserveNewest - - - - - - - all - runtime; build; native; contentfiles; analyzers - - + + + + net9.0 + enable + true + Library + Unity.Flex.Web + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + true + PreserveNewest + + + + + + + all + runtime; build; native; contentfiles; analyzers + + diff --git a/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Views/Shared/Components/BCAddressWidget/Default.css b/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Views/Shared/Components/BCAddressWidget/Default.css index 5f282702b..19a76f130 100644 --- a/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Views/Shared/Components/BCAddressWidget/Default.css +++ b/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Views/Shared/Components/BCAddressWidget/Default.css @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Views/Shared/Components/CurrencyDefinitionWidget/Default.css b/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Views/Shared/Components/CurrencyDefinitionWidget/Default.css index 5f282702b..19a76f130 100644 --- a/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Views/Shared/Components/CurrencyDefinitionWidget/Default.css +++ b/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Views/Shared/Components/CurrencyDefinitionWidget/Default.css @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Views/Shared/Components/CurrencyWidget/Default.css b/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Views/Shared/Components/CurrencyWidget/Default.css index 5f282702b..19a76f130 100644 --- a/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Views/Shared/Components/CurrencyWidget/Default.css +++ b/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Views/Shared/Components/CurrencyWidget/Default.css @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Views/Shared/Components/CustomFieldDefinitionWidget/Default.cshtml b/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Views/Shared/Components/CustomFieldDefinitionWidget/Default.cshtml index 9317675fe..c8d596a93 100644 --- a/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Views/Shared/Components/CustomFieldDefinitionWidget/Default.cshtml +++ b/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Views/Shared/Components/CustomFieldDefinitionWidget/Default.cshtml @@ -1,5 +1,4 @@ -@using Unity.Flex.Web.Views.Shared.Components; -@using Unity.Flex.Web.Views.Shared.Components.CheckboxGroupDefinitionWidget +@using Unity.Flex.Web.Views.Shared.Components.CheckboxGroupDefinitionWidget @using Unity.Flex.Web.Views.Shared.Components.CurrencyDefinitionWidget @using Unity.Flex.Web.Views.Shared.Components.CustomFieldDefinitionWidget; @using Unity.Flex.Web.Views.Shared.Components.DataGridDefinitionWidget diff --git a/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Views/Shared/Components/CustomFieldDefinitionWidget/Default.css b/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Views/Shared/Components/CustomFieldDefinitionWidget/Default.css index 5f282702b..19a76f130 100644 --- a/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Views/Shared/Components/CustomFieldDefinitionWidget/Default.css +++ b/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Views/Shared/Components/CustomFieldDefinitionWidget/Default.css @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Views/Shared/Components/CustomTabWidget/Default.css b/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Views/Shared/Components/CustomTabWidget/Default.css index 5f282702b..19a76f130 100644 --- a/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Views/Shared/Components/CustomTabWidget/Default.css +++ b/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Views/Shared/Components/CustomTabWidget/Default.css @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Views/Shared/Components/DateWidget/Default.css b/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Views/Shared/Components/DateWidget/Default.css index 5f282702b..19a76f130 100644 --- a/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Views/Shared/Components/DateWidget/Default.css +++ b/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Views/Shared/Components/DateWidget/Default.css @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Views/Shared/Components/NumericDefinitionWidget/Default.cshtml b/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Views/Shared/Components/NumericDefinitionWidget/Default.cshtml index 0ce1381b2..45171d84d 100644 --- a/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Views/Shared/Components/NumericDefinitionWidget/Default.cshtml +++ b/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Views/Shared/Components/NumericDefinitionWidget/Default.cshtml @@ -1,6 +1,4 @@ -@using Unity.Flex.Web.Views.Shared.Components; -@using Unity.Flex.Web.Views.Shared.Components.NumericDefinitionWidget; -@using Unity.Flex.Worksheets.Definitions; +@using Unity.Flex.Web.Views.Shared.Components.NumericDefinitionWidget; @model NumericDefinitionViewModel; diff --git a/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Views/Shared/Components/NumericDefinitionWidget/Default.css b/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Views/Shared/Components/NumericDefinitionWidget/Default.css index 5f282702b..19a76f130 100644 --- a/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Views/Shared/Components/NumericDefinitionWidget/Default.css +++ b/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Views/Shared/Components/NumericDefinitionWidget/Default.css @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Views/Shared/Components/QuestionSelectListWidget/Default.cshtml b/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Views/Shared/Components/QuestionSelectListWidget/Default.cshtml index aa077f19d..7c477202f 100644 --- a/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Views/Shared/Components/QuestionSelectListWidget/Default.cshtml +++ b/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Views/Shared/Components/QuestionSelectListWidget/Default.cshtml @@ -1,5 +1,4 @@ -@using Unity.Flex.Web.Views.Shared.Components; -@using Unity.Flex.Web.Views.Shared.Components.QuestionSelectListWidget; +@using Unity.Flex.Web.Views.Shared.Components.QuestionSelectListWidget; @using Unity.Flex.Worksheets.Definitions; @using Unity.Flex; @using Unity.Flex.Scoresheets.Enums; diff --git a/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Views/Shared/Components/QuestionYesNoDefinitionWidget/Default.css b/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Views/Shared/Components/QuestionYesNoDefinitionWidget/Default.css index 5f282702b..19a76f130 100644 --- a/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Views/Shared/Components/QuestionYesNoDefinitionWidget/Default.css +++ b/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Views/Shared/Components/QuestionYesNoDefinitionWidget/Default.css @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Views/Shared/Components/RadioDefinitionWidget/Default.cshtml b/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Views/Shared/Components/RadioDefinitionWidget/Default.cshtml index c9b57e630..1f5295287 100644 --- a/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Views/Shared/Components/RadioDefinitionWidget/Default.cshtml +++ b/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Views/Shared/Components/RadioDefinitionWidget/Default.cshtml @@ -1,6 +1,4 @@ -@using Unity.Flex.Web.Views.Shared.Components; -@using Unity.Flex.Web.Views.Shared.Components.RadioDefinitionWidget; -@using Unity.Flex.Worksheets.Definitions; +@using Unity.Flex.Web.Views.Shared.Components.RadioDefinitionWidget; @model RadioDefinitionViewModel diff --git a/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Views/Shared/Components/SelectListWidget/Default.css b/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Views/Shared/Components/SelectListWidget/Default.css index 5f282702b..19a76f130 100644 --- a/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Views/Shared/Components/SelectListWidget/Default.css +++ b/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Views/Shared/Components/SelectListWidget/Default.css @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Views/Shared/Components/TextDefinitionWidget/Default.cshtml b/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Views/Shared/Components/TextDefinitionWidget/Default.cshtml index 363c9738e..75f9c994b 100644 --- a/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Views/Shared/Components/TextDefinitionWidget/Default.cshtml +++ b/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Views/Shared/Components/TextDefinitionWidget/Default.cshtml @@ -1,6 +1,4 @@ -@using Unity.Flex.Web.Views.Shared.Components; -@using Unity.Flex.Web.Views.Shared.Components.TextDefinitionWidget; -@using Unity.Flex.Worksheets.Definitions; +@using Unity.Flex.Web.Views.Shared.Components.TextDefinitionWidget; @model TextDefinitionViewModel; diff --git a/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Views/Shared/Components/TextDefinitionWidget/Default.css b/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Views/Shared/Components/TextDefinitionWidget/Default.css index 5f282702b..19a76f130 100644 --- a/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Views/Shared/Components/TextDefinitionWidget/Default.css +++ b/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Views/Shared/Components/TextDefinitionWidget/Default.css @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Views/Shared/Components/WorksheetInstanceWidget/Default.cshtml b/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Views/Shared/Components/WorksheetInstanceWidget/Default.cshtml index 2f14d17df..9078c5ed9 100644 --- a/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Views/Shared/Components/WorksheetInstanceWidget/Default.cshtml +++ b/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Views/Shared/Components/WorksheetInstanceWidget/Default.cshtml @@ -4,7 +4,6 @@ @using Unity.Flex.Web.Views.Shared.Components.TextAreaWidget @using Unity.Flex.Web.Views.Shared.Components.WorksheetInstanceWidget.ViewModels; @using Unity.Flex.Worksheets; -@using Unity.Flex.Web.Views.Shared.Components; @using Unity.Flex.Web.Views.Shared.Components.CheckboxWidget; @using Unity.Flex.Web.Views.Shared.Components.YesNoWidget; @using Unity.Flex.Web.Views.Shared.Components.CurrencyWidget; diff --git a/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Views/Shared/Components/YesNoWidget/Default.css b/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Views/Shared/Components/YesNoWidget/Default.css index 5f282702b..19a76f130 100644 --- a/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Views/Shared/Components/YesNoWidget/Default.css +++ b/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Views/Shared/Components/YesNoWidget/Default.css @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/applications/Unity.GrantManager/modules/Unity.Identity.Web/src/Pages/Identity/Roles/CreateModal.cshtml b/applications/Unity.GrantManager/modules/Unity.Identity.Web/src/Pages/Identity/Roles/CreateModal.cshtml index 8cd601e76..eef21fdfd 100644 --- a/applications/Unity.GrantManager/modules/Unity.Identity.Web/src/Pages/Identity/Roles/CreateModal.cshtml +++ b/applications/Unity.GrantManager/modules/Unity.Identity.Web/src/Pages/Identity/Roles/CreateModal.cshtml @@ -1,14 +1,15 @@ @page @using Microsoft.AspNetCore.Mvc.Localization @using Microsoft.Extensions.Localization -@using Microsoft.Extensions.Logging +@using Unity.Identity.Web.Pages.Identity.Roles @using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Modal +@using Volo.Abp.Data @using Volo.Abp.Identity.Localization -@using Unity.Identity.Web.Pages.Identity.Roles @using Volo.Abp.Localization @using Volo.Abp.ObjectExtending -@using Volo.Abp.Data + @model CreateModalModel + @inject IHtmlLocalizer L @inject IStringLocalizerFactory StringLocalizerFactory @{ diff --git a/applications/Unity.GrantManager/modules/Unity.Identity.Web/src/Pages/Identity/Roles/EditModal.cshtml b/applications/Unity.GrantManager/modules/Unity.Identity.Web/src/Pages/Identity/Roles/EditModal.cshtml index a596d6f26..4ecd338f1 100644 --- a/applications/Unity.GrantManager/modules/Unity.Identity.Web/src/Pages/Identity/Roles/EditModal.cshtml +++ b/applications/Unity.GrantManager/modules/Unity.Identity.Web/src/Pages/Identity/Roles/EditModal.cshtml @@ -1,13 +1,15 @@ @page @using Microsoft.AspNetCore.Mvc.Localization @using Microsoft.Extensions.Localization +@using Unity.Identity.Web.Pages.Identity.Roles @using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Modal +@using Volo.Abp.Data @using Volo.Abp.Identity.Localization -@using Unity.Identity.Web.Pages.Identity.Roles @using Volo.Abp.Localization @using Volo.Abp.ObjectExtending -@using Volo.Abp.Data + @model EditModalModel + @inject IHtmlLocalizer L @inject IStringLocalizerFactory StringLocalizerFactory @{ diff --git a/applications/Unity.GrantManager/modules/Unity.Identity.Web/src/Pages/Identity/Roles/Index.cshtml b/applications/Unity.GrantManager/modules/Unity.Identity.Web/src/Pages/Identity/Roles/Index.cshtml index 40928c600..51e0555b4 100644 --- a/applications/Unity.GrantManager/modules/Unity.Identity.Web/src/Pages/Identity/Roles/Index.cshtml +++ b/applications/Unity.GrantManager/modules/Unity.Identity.Web/src/Pages/Identity/Roles/Index.cshtml @@ -1,13 +1,13 @@ @page @using Microsoft.AspNetCore.Authorization @using Microsoft.AspNetCore.Mvc.Localization -@using Volo.Abp.AspNetCore.Mvc.UI.Layout -@using Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Pages.Shared.Components.AbpPageToolbar -@using Volo.Abp.Identity -@using Volo.Abp.Identity.Localization @using Unity.Identity.Web.Navigation @using Unity.Identity.Web.Pages.Identity.Roles +@using Volo.Abp.AspNetCore.Mvc.UI.Layout +@using Volo.Abp.Identity.Localization + @model IndexModel + @inject IHtmlLocalizer L @inject IAuthorizationService Authorization @inject IPageLayout PageLayout diff --git a/applications/Unity.GrantManager/modules/Unity.Identity.Web/src/Pages/Identity/Roles/PermissionRoleMatrix.cshtml b/applications/Unity.GrantManager/modules/Unity.Identity.Web/src/Pages/Identity/Roles/PermissionRoleMatrix.cshtml new file mode 100644 index 000000000..9b86a080f --- /dev/null +++ b/applications/Unity.GrantManager/modules/Unity.Identity.Web/src/Pages/Identity/Roles/PermissionRoleMatrix.cshtml @@ -0,0 +1,164 @@ +@page + +@using Microsoft.Extensions.Localization +@using Unity.GrantManager.Localization +@using Volo.Abp.AspNetCore.Mvc.UI.Layout +@using Volo.Abp.MultiTenancy + +@model Unity.GrantManager.Web.Pages.Identity.Roles.PermissionRoleMatrixModel + +@inject ICurrentTenant CurrentTenant +@inject IPageLayout PageLayout +@inject IStringLocalizer L + +@tagHelperPrefix th: + +@{ + PageLayout.Content.Title = "Permission-Role Matrix"; + ViewBag.PageTitle = "Permission-Role Matrix"; + int rowCount = 1; + int maxDepth = Model.PermissionRoleMatrix.Max(item => item.Depth); + int headerLevel = maxDepth + 1; + + var roleHeaders = Model.PermissionRoleMatrix.FirstOrDefault()?.RolePermissions.Keys ?? Enumerable.Empty(); + var filteredPermissions = Model.ShowNotDefined + ? Model.PermissionRoleMatrix.Where(p => !p.IsDefined) + : Model.PermissionRoleMatrix.Where(p => p.IsDefined); +} + +@section scripts { + + +} + +@section styles { + +} + +
+
+
+

Permission-Role Matrix - @CurrentTenant.Name

+
+
+ +
+ +
+
+ +
+
+
+
+
+

Loading permission matrix...

+
+ + @if (!Model.IsExpanded) + { + + + + + + + + @foreach (var role in roleHeaders) + { + + } + + + + @foreach (var permission in filteredPermissions) + { + + + @{ + rowCount++; + } + + + + + @foreach (var hasPermission in permission.RolePermissions.Values) + { + + } + + } + + } + else + { + + + + + + + + @foreach (var role in roleHeaders) + { + + } + + + @for (int groupLevel = 1; groupLevel < headerLevel + 1; groupLevel++) + { + + } + + + + @foreach (var permission in filteredPermissions) + { + + + @{ + rowCount++; + } + + + @for (int i = 0; i < permission.Depth; i++) + { + + } + + + + @for (int j = permission.Depth; j < maxDepth; j++) + { + + } + + + + @foreach (var hasPermission in permission.RolePermissions.Values) + { + + } + + } + + } +
#LPermission GroupPermissionDescription@role
@rowCount.ToString("D2")@permission.Depth.ToString("D1")@permission.GroupName@permission.PermissionName@(L[permission.PermissionDisplayName].Value)@(hasPermission ? "TRUE" : string.Empty)
#LPermission GroupPermissionDescription@role
Level @groupLevel
+ @rowCount.ToString("D2") + @permission.Depth.ToString("D1")@permission.GroupName@permission.PermissionName@permission.PermissionDisplayName@(hasPermission ? "TRUE" : string.Empty)
+
+
diff --git a/applications/Unity.GrantManager/modules/Unity.Identity.Web/src/Pages/Identity/Roles/PermissionRoleMatrix.cshtml.cs b/applications/Unity.GrantManager/modules/Unity.Identity.Web/src/Pages/Identity/Roles/PermissionRoleMatrix.cshtml.cs new file mode 100644 index 000000000..6a7ed8a91 --- /dev/null +++ b/applications/Unity.GrantManager/modules/Unity.Identity.Web/src/Pages/Identity/Roles/PermissionRoleMatrix.cshtml.cs @@ -0,0 +1,48 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Unity.GrantManager.Repositories; +using Volo.Abp.AspNetCore.Mvc.UI.RazorPages; +using Volo.Abp.Authorization.Permissions; +using Volo.Abp.Localization; + +namespace Unity.GrantManager.Web.Pages.Identity.Roles; + +public class PermissionRoleMatrixModel(IPermissionRoleMatrixRepository repository, IPermissionDefinitionManager permissionDefinitionManager) : AbpPageModel +{ + public bool IsExpanded { get; private set; } + public bool ShowNotDefined { get; private set; } = false; + public required IList PermissionRoleMatrix { get; set; } + + public async Task OnGetAsync() + { + // Check if the query parameter "Render" is set to "Expanded" + IsExpanded = Request.Query["Render"].ToString().Equals("Expanded", StringComparison.OrdinalIgnoreCase); + ShowNotDefined = Request.Query["Show"].ToString().Equals("NotDefined", StringComparison.OrdinalIgnoreCase); + + PermissionRoleMatrix = await repository.GetPermissionRoleMatrixAsync(); + + var definedPermissionSet = await permissionDefinitionManager.GetPermissionsAsync(); + var definedPermissionNames = new HashSet(definedPermissionSet.Select(x => x.Name)); + + foreach (var item in PermissionRoleMatrix) + { + item.IsDefined = definedPermissionNames.Contains(item.PermissionName); + + var displayName = item.PermissionDisplayName; + if (displayName.Length > 2 && displayName.StartsWith("L:")) + { + var parts = displayName.AsSpan(2).ToString().Split(','); + if (parts.Length == 2) + { + var resourceName = parts[0]; + var name = parts[1]; + var localizable = new LocalizableString(name, resourceName); + var localized = await localizable.LocalizeAsync(StringLocalizerFactory); + item.PermissionDisplayName = localized?.Value ?? displayName; + } + } + } + } +} \ No newline at end of file diff --git a/applications/Unity.GrantManager/modules/Unity.Identity.Web/src/Pages/Identity/Roles/PermissionRoleMatrix.js b/applications/Unity.GrantManager/modules/Unity.Identity.Web/src/Pages/Identity/Roles/PermissionRoleMatrix.js new file mode 100644 index 000000000..8ad60b312 --- /dev/null +++ b/applications/Unity.GrantManager/modules/Unity.Identity.Web/src/Pages/Identity/Roles/PermissionRoleMatrix.js @@ -0,0 +1,147 @@ +$(document).ready(function () { + const urlParams = new URLSearchParams(window.location.search); + const isExpanded = urlParams.get('Render') === 'Expanded'; + const exportTitle = `${abp.currentTenant.name}_${(new Date()).toISOString().slice(0, 10)}_Permission-Role Matrix`; + + const userRoles = abp.currentUser.roles; + const userPolicies = abp.auth.grantedPolicies; + + let _permissionsModal = new abp.ModalManager( + abp.appPath + 'AbpPermissionManagement/PermissionManagementModal' + ); + _permissionsModal.onClose(function () { + // Refresh the page to show updated permissions + window.location.reload(); + }); + + const roleColumnIndexes = []; + $('#permissionTable th[data-role-header]').each(function (index) { + roleColumnIndexes.push($(this).index()); + }); + + const columnDefs = [ + { + targets: 0, + orderable: true, + className: 'notexport' + } + ]; + + if (roleColumnIndexes.length > 0) { + columnDefs.push({ + targets: roleColumnIndexes, + orderable: false + }); + } + + $.fn.dataTable.Buttons.defaults.dom.button.className = 'btn flex-none'; + let localTable = $('#permissionTable').DataTable({ + paging: false, + searching: true, + ordering: true, + fixedHeader: { + header: true, + footer: false, + headerOffset: 0 + }, + scrollX: true, + scrollCollapse: true, + dom: 'Blfrtip', + columnDefs: columnDefs, + buttons: [ + { + text: isExpanded + ? ' View Simple' + : ' View Expanded', + className: 'btn-light rounded-1', + action: function (e, dt, button, config) { + window.location = isExpanded + ? '/Identity/Roles/PermissionRoleMatrix' + : '/Identity/Roles/PermissionRoleMatrix?Render=Expanded'; + } + }, + { + extend: 'copy', + text: 'Copy', + title: exportTitle, + className: 'custom-table-btn flex-none btn btn-secondary', + exportOptions: { + columns: ':visible:not(.notexport)' + } + }, + { + extend: 'csv', + text: 'Export', + title: exportTitle, + className: 'custom-table-btn flex-none btn btn-secondary', + exportOptions: { + columns: ':visible:not(.notexport)' + } + } + ], + createdRow: function (row, data, dataIndex) { + $('td', row).each(function () { + let cellText = $(this).text().trim(); + + // Check if the cell text matches a key in userPolicies + if (userPolicies[cellText]) { + $(this).addClass('text-decoration-underline'); + } + + if (cellText === "TRUE") { + $(this).addClass('bg-success text-dark bg-opacity-25 fw-bold border border-success dt-center'); + } + }); + }, + initComplete: function () { + const table = this.api(); + + // Required for DataTable 1.x - Disable sorting for role name columns after table initialization + // Explicitly disable ordering for role columns using the API + $('th[data-role-header]').removeClass('sorting').addClass('sorting_disabled'); + + const headers = table.columns().header().toArray().map(header => $(header).text().trim()); + + // Highlight columns where the header matches a user role + headers.forEach((header, index) => { + if (userRoles.includes(header.toLowerCase())) { + $(table.column(index).header()).addClass('text-decoration-underline'); + table.column(index).nodes().to$().filter(function () { + return !$(this).text().trim(); + }).addClass('bg-light'); + } + }); + } + }); + + localTable.buttons().container().prependTo('#dynamicButtonContainerId'); + $("#search").on('input', function () { + localTable.search($(this).val()).draw(); + }); + + // Hide spinner and show table after initialization + $('.loading-spinner').hide(); + $('#permissionTable').show(); + + // Add click handlers to role column headers using data-role-header attribute + $(document).on('click', 'th[data-role-header]', function () { + const roleName = $(this).attr('data-role-header'); + _permissionsModal.open({ + providerName: 'R', + providerKey: roleName, + providerKeyDisplayName: roleName + }); + }); + + // Add styles to all headers, including dynamically created ones + $(document).on('mouseover', 'th[data-role-header]', function () { + $(this).css('cursor', 'pointer'); + if (!$(this).attr('title')) { + $(this).attr('title', 'Click to manage permissions for this role'); + } + }); + + init(localTable); + // Workaround - required until Datatables.net 2.x + $('th[data-role-header]').removeClass('sorting').addClass('sorting_disabled'); +}); diff --git a/applications/Unity.GrantManager/modules/Unity.Identity.Web/src/Pages/Identity/Roles/index.js b/applications/Unity.GrantManager/modules/Unity.Identity.Web/src/Pages/Identity/Roles/index.js index 43693f803..74f5376cf 100644 --- a/applications/Unity.GrantManager/modules/Unity.Identity.Web/src/Pages/Identity/Roles/index.js +++ b/applications/Unity.GrantManager/modules/Unity.Identity.Web/src/Pages/Identity/Roles/index.js @@ -120,6 +120,13 @@ $(function () { $.fn.dataTable.Buttons.defaults.dom.button.className = 'btn flex-none'; let actionButtons = [ + { + text: 'View Role Matrix', + className: 'btn-light rounded-1', + action: function (e, dt, button, config) { + window.location = '/Identity/Roles/PermissionRoleMatrix' + } + }, { text: ' ' + l('NewRole') + '', titleAttr: l('NewRole'), diff --git a/applications/Unity.GrantManager/modules/Unity.Identity.Web/src/Pages/Identity/Users/EditModal.cshtml b/applications/Unity.GrantManager/modules/Unity.Identity.Web/src/Pages/Identity/Users/EditModal.cshtml index 6dc992012..f5a488198 100644 --- a/applications/Unity.GrantManager/modules/Unity.Identity.Web/src/Pages/Identity/Users/EditModal.cshtml +++ b/applications/Unity.GrantManager/modules/Unity.Identity.Web/src/Pages/Identity/Users/EditModal.cshtml @@ -1,14 +1,15 @@ @page @using Microsoft.AspNetCore.Mvc.Localization @using Microsoft.Extensions.Localization +@using Unity.Identity.Web.Pages.Identity.Users @using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Modal +@using Volo.Abp.Data @using Volo.Abp.Identity.Localization -@using Unity.Identity.Web.Pages.Identity.Users @using Volo.Abp.Localization @using Volo.Abp.ObjectExtending -@using Volo.Abp.Data -@using Volo.Abp.Identity + @model EditModalModel + @inject IHtmlLocalizer L @inject IStringLocalizerFactory StringLocalizerFactory @{ diff --git a/applications/Unity.GrantManager/modules/Unity.Identity.Web/src/Pages/Identity/Users/ImportModal.cshtml b/applications/Unity.GrantManager/modules/Unity.Identity.Web/src/Pages/Identity/Users/ImportModal.cshtml index 92356b2d6..f257daa8e 100644 --- a/applications/Unity.GrantManager/modules/Unity.Identity.Web/src/Pages/Identity/Users/ImportModal.cshtml +++ b/applications/Unity.GrantManager/modules/Unity.Identity.Web/src/Pages/Identity/Users/ImportModal.cshtml @@ -2,17 +2,13 @@ @using Microsoft.AspNetCore.Mvc.Localization @using Microsoft.Extensions.Localization @using Unity.GrantManager.Localization; -@using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Modal -@using Volo.Abp.Identity.Localization @using Unity.Identity.Web.Pages.Identity.Users -@using Volo.Abp.Localization -@using Volo.Abp.ObjectExtending -@using Volo.Abp.Data -@using Volo.Abp.Identity +@using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Modal + @model ImportModalModel + @inject IHtmlLocalizer L @inject IStringLocalizerFactory StringLocalizerFactory - @{ Layout = null; } diff --git a/applications/Unity.GrantManager/modules/Unity.Identity.Web/src/Pages/Identity/Users/Index.cshtml b/applications/Unity.GrantManager/modules/Unity.Identity.Web/src/Pages/Identity/Users/Index.cshtml index c92827008..37a9c8a2e 100644 --- a/applications/Unity.GrantManager/modules/Unity.Identity.Web/src/Pages/Identity/Users/Index.cshtml +++ b/applications/Unity.GrantManager/modules/Unity.Identity.Web/src/Pages/Identity/Users/Index.cshtml @@ -1,14 +1,13 @@ @page @using Microsoft.AspNetCore.Authorization @using Microsoft.AspNetCore.Mvc.Localization -@using Unity.GrantManager.Localization; -@using Volo.Abp.AspNetCore.Mvc.UI.Layout -@using Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Pages.Shared.Components.AbpPageToolbar -@using Volo.Abp.Identity -@using Volo.Abp.Identity.Localization +@using Unity.GrantManager.Localization @using Unity.Identity.Web.Navigation @using Unity.Identity.Web.Pages.Identity.Users +@using Volo.Abp.AspNetCore.Mvc.UI.Layout + @model IndexModel + @inject IHtmlLocalizer L @inject IAuthorizationService Authorization @inject IPageLayout PageLayout diff --git a/applications/Unity.GrantManager/modules/Unity.Identity.Web/src/Unity.Identity.Web.csproj b/applications/Unity.GrantManager/modules/Unity.Identity.Web/src/Unity.Identity.Web.csproj index 43ff153d8..176c34cfd 100644 --- a/applications/Unity.GrantManager/modules/Unity.Identity.Web/src/Unity.Identity.Web.csproj +++ b/applications/Unity.GrantManager/modules/Unity.Identity.Web/src/Unity.Identity.Web.csproj @@ -45,6 +45,7 @@ + diff --git a/applications/Unity.GrantManager/modules/Unity.Identity.Web/src/UnitydentityWebModule.cs b/applications/Unity.GrantManager/modules/Unity.Identity.Web/src/UnitydentityWebModule.cs index d457c4711..50d8dc7e1 100644 --- a/applications/Unity.GrantManager/modules/Unity.Identity.Web/src/UnitydentityWebModule.cs +++ b/applications/Unity.GrantManager/modules/Unity.Identity.Web/src/UnitydentityWebModule.cs @@ -69,6 +69,8 @@ public override void ConfigureServices(ServiceConfigurationContext context) options.Conventions.AuthorizePage("/Identity/Roles/Index", IdentityPermissions.Roles.Default); options.Conventions.AuthorizePage("/Identity/Roles/CreateModal", IdentityPermissions.Roles.Create); options.Conventions.AuthorizePage("/Identity/Roles/EditModal", IdentityPermissions.Roles.Update); + + options.Conventions.AuthorizePage("/Identity/Roles/PermissionRoleMatrix", IdentityPermissions.Roles.Default); }); Configure(options => diff --git a/applications/Unity.GrantManager/modules/Unity.Notifications/src/Unity.Notifications.Domain/NotificationsDataSeedContributor.cs b/applications/Unity.GrantManager/modules/Unity.Notifications/src/Unity.Notifications.Domain/NotificationsDataSeedContributor.cs index 7d885b285..165ae2e8d 100644 --- a/applications/Unity.GrantManager/modules/Unity.Notifications/src/Unity.Notifications.Domain/NotificationsDataSeedContributor.cs +++ b/applications/Unity.GrantManager/modules/Unity.Notifications/src/Unity.Notifications.Domain/NotificationsDataSeedContributor.cs @@ -41,7 +41,8 @@ public async Task SeedAsync(DataSeedContext context) new EmailTempateVariableDto { Name = "Project Name", Token = "project_name", MapTo = "projectName" }, new EmailTempateVariableDto { Name = "Project Summary", Token = "project_summary", MapTo = "projectSummary" }, new EmailTempateVariableDto { Name = "Signing Authority Full Name", Token = "signing_authority_full_name", MapTo = "signingAuthorityFullName" }, - new EmailTempateVariableDto { Name = "Signing Authority Title", Token = "signing_authority_title", MapTo = "signingAuthorityTitle" } + new EmailTempateVariableDto { Name = "Signing Authority Title", Token = "signing_authority_title", MapTo = "signingAuthorityTitle" }, + new EmailTempateVariableDto { Name = "Applicant ID", Token = "applicant_id", MapTo = "applicant.unityApplicantId" } }; foreach (var template in emailTemplateVariableDtos) @@ -54,6 +55,11 @@ await _templateVariablesRepository.InsertAsync( autoSave: true ); } + else if (existingVariable.Token == "category" && existingVariable.MapTo == "category") + { + existingVariable.MapTo = "applicationForm.category"; + await _templateVariablesRepository.UpdateAsync(existingVariable, autoSave: true); + } } } } diff --git a/applications/Unity.GrantManager/modules/Unity.Notifications/src/Unity.Notifications.Web/Views/Settings/NotificationsSettingGroup/Default.cshtml b/applications/Unity.GrantManager/modules/Unity.Notifications/src/Unity.Notifications.Web/Views/Settings/NotificationsSettingGroup/Default.cshtml index 0586b5b85..e088a067d 100644 --- a/applications/Unity.GrantManager/modules/Unity.Notifications/src/Unity.Notifications.Web/Views/Settings/NotificationsSettingGroup/Default.cshtml +++ b/applications/Unity.GrantManager/modules/Unity.Notifications/src/Unity.Notifications.Web/Views/Settings/NotificationsSettingGroup/Default.cshtml @@ -5,12 +5,15 @@
+
+

Notifications

+
+ - + + } } -} + \ No newline at end of file diff --git a/applications/Unity.GrantManager/modules/Unity.Theme.UX2/src/Unity.Theme.UX2/wwwroot/themes/ux2/fluentui-icons.css b/applications/Unity.GrantManager/modules/Unity.Theme.UX2/src/Unity.Theme.UX2/wwwroot/themes/ux2/fluentui-icons.css index 488da210d..89cc56360 100644 --- a/applications/Unity.GrantManager/modules/Unity.Theme.UX2/src/Unity.Theme.UX2/wwwroot/themes/ux2/fluentui-icons.css +++ b/applications/Unity.GrantManager/modules/Unity.Theme.UX2/src/Unity.Theme.UX2/wwwroot/themes/ux2/fluentui-icons.css @@ -108,6 +108,11 @@ content: '\E89F'; } +/*GID144 : U+E740*/ +.fl-fullscreen:before { + content: '\E740'; +} + /*GID144 : U+E871*/ .fl-back-to-window:before { content: '\E73F'; @@ -241,10 +246,6 @@ content: '\EA4A'; } -.fl-history:before { - content: '\E81C'; -} - .fl-comments:before { content: '\E15F'; } diff --git a/applications/Unity.GrantManager/modules/Unity.Theme.UX2/src/Unity.Theme.UX2/wwwroot/themes/ux2/fonts.css b/applications/Unity.GrantManager/modules/Unity.Theme.UX2/src/Unity.Theme.UX2/wwwroot/themes/ux2/fonts.css index 9ca64701d..06c45030c 100644 --- a/applications/Unity.GrantManager/modules/Unity.Theme.UX2/src/Unity.Theme.UX2/wwwroot/themes/ux2/fonts.css +++ b/applications/Unity.GrantManager/modules/Unity.Theme.UX2/src/Unity.Theme.UX2/wwwroot/themes/ux2/fonts.css @@ -1,42 +1,42 @@  @font-face { font-family: 'BCSans'; - src: url('fonts/BCSans/BCSans-Regular.ttf') format('truetype'), url('fonts/BCSans/BCSans-Regular.woff') format('woff'), url('fonts/BCSans/BCSans-Regular.woff2') format('woff2'), url('fonts/BCSans/BCSans-Regular.otf') format('opentype'); + src: url('fonts/BCSans/BCSans-Regular.woff2') format('woff2'), url('fonts/BCSans/BCSans-Regular.woff') format('woff'); font-weight: 300 600; font-style: normal; } @font-face { font-family: 'BCSans'; - src: url('fonts/BCSans/BCSans-Bold.ttf') format('truetype'), url('fonts/BCSans/BCSans-Bold.woff') format('woff'), url('fonts/BCSans/BCSans-Bold.woff2') format('woff2'), url('fonts/BCSans/BCSans-Bold.otf') format('opentype'); + src: url('fonts/BCSans/BCSans-Bold.woff2') format('woff2'), url('fonts/BCSans/BCSans-Bold.woff') format('woff'); font-weight: 700 900; font-style: normal; } @font-face { font-family: 'BCSans'; - src: url('fonts/BCSans/BCSans-Light.ttf') format('truetype'), url('fonts/BCSans/BCSans-Light.woff') format('woff'), url('fonts/BCSans/BCSans-Light.woff2') format('woff2'), url('fonts/BCSans/BCSans-Light.otf') format('opentype'); + src: url('fonts/BCSans/BCSans-Light.woff2') format('woff2'), url('fonts/BCSans/BCSans-Light.woff') format('woff'); font-weight: 100 200; font-style: normal; } @font-face { font-family: 'BCSans'; - src: url('fonts/BCSans/BCSans-Italic.ttf') format('truetype'), url('fonts/BCSans/BCSans-Italic.woff') format('woff'), url('fonts/BCSans/BCSans-Italic.woff2') format('woff2'), url('fonts/BCSans/BCSans-Italic.otf') format('opentype'); + src: url('fonts/BCSans/BCSans-Italic.woff2') format('woff2'), url('fonts/BCSans/BCSans-Italic.woff') format('woff'); font-weight: 400 600; font-style: italic; } @font-face { font-family: 'BCSans'; - src: url('fonts/BCSans/BCSans-BoldItalic.ttf') format('truetype'), url('fonts/BCSans/BCSans-BoldItalic.woff') format('woff'), url('fonts/BCSans/BCSans-BoldItalic.woff2') format('woff2'), url('fonts/BCSans/BCSans-BoldItalic.otf') format('opentype'); + src: url('fonts/BCSans/BCSans-BoldItalic.woff2') format('woff2'), url('fonts/BCSans/BCSans-BoldItalic.woff') format('woff'); font-weight: 700 bold; font-style: italic; } @font-face { font-family: 'BCSans'; - src: url('fonts/BCSans/BCSans-LightItalic.ttf') format('truetype'), url('fonts/BCSans/BCSans-LightItalic.woff') format('woff'), url('fonts/BCSans/BCSans-LightItalic.woff2') format('woff2'), url('fonts/BCSans/BCSans-LightItalic.otf') format('opentype'); + src: url('fonts/BCSans/BCSans-LightItalic.woff2') format('woff2'), url('fonts/BCSans/BCSans-LightItalic.woff') format('woff'); font-weight: 100 300; font-style: italic; } diff --git a/applications/Unity.GrantManager/modules/Unity.Theme.UX2/src/Unity.Theme.UX2/wwwroot/themes/ux2/fonts/BCSans/BCSans-Bold.otf b/applications/Unity.GrantManager/modules/Unity.Theme.UX2/src/Unity.Theme.UX2/wwwroot/themes/ux2/fonts/BCSans/BCSans-Bold.otf deleted file mode 100644 index 28a2e7cf4..000000000 Binary files a/applications/Unity.GrantManager/modules/Unity.Theme.UX2/src/Unity.Theme.UX2/wwwroot/themes/ux2/fonts/BCSans/BCSans-Bold.otf and /dev/null differ diff --git a/applications/Unity.GrantManager/modules/Unity.Theme.UX2/src/Unity.Theme.UX2/wwwroot/themes/ux2/fonts/BCSans/BCSans-Bold.ttf b/applications/Unity.GrantManager/modules/Unity.Theme.UX2/src/Unity.Theme.UX2/wwwroot/themes/ux2/fonts/BCSans/BCSans-Bold.ttf deleted file mode 100644 index ee38cb984..000000000 Binary files a/applications/Unity.GrantManager/modules/Unity.Theme.UX2/src/Unity.Theme.UX2/wwwroot/themes/ux2/fonts/BCSans/BCSans-Bold.ttf and /dev/null differ diff --git a/applications/Unity.GrantManager/modules/Unity.Theme.UX2/src/Unity.Theme.UX2/wwwroot/themes/ux2/fonts/BCSans/BCSans-BoldItalic.otf b/applications/Unity.GrantManager/modules/Unity.Theme.UX2/src/Unity.Theme.UX2/wwwroot/themes/ux2/fonts/BCSans/BCSans-BoldItalic.otf deleted file mode 100644 index ccd07b0e2..000000000 Binary files a/applications/Unity.GrantManager/modules/Unity.Theme.UX2/src/Unity.Theme.UX2/wwwroot/themes/ux2/fonts/BCSans/BCSans-BoldItalic.otf and /dev/null differ diff --git a/applications/Unity.GrantManager/modules/Unity.Theme.UX2/src/Unity.Theme.UX2/wwwroot/themes/ux2/fonts/BCSans/BCSans-BoldItalic.ttf b/applications/Unity.GrantManager/modules/Unity.Theme.UX2/src/Unity.Theme.UX2/wwwroot/themes/ux2/fonts/BCSans/BCSans-BoldItalic.ttf deleted file mode 100644 index 342d919d2..000000000 Binary files a/applications/Unity.GrantManager/modules/Unity.Theme.UX2/src/Unity.Theme.UX2/wwwroot/themes/ux2/fonts/BCSans/BCSans-BoldItalic.ttf and /dev/null differ diff --git a/applications/Unity.GrantManager/modules/Unity.Theme.UX2/src/Unity.Theme.UX2/wwwroot/themes/ux2/fonts/BCSans/BCSans-Italic.otf b/applications/Unity.GrantManager/modules/Unity.Theme.UX2/src/Unity.Theme.UX2/wwwroot/themes/ux2/fonts/BCSans/BCSans-Italic.otf deleted file mode 100644 index 19982adfa..000000000 Binary files a/applications/Unity.GrantManager/modules/Unity.Theme.UX2/src/Unity.Theme.UX2/wwwroot/themes/ux2/fonts/BCSans/BCSans-Italic.otf and /dev/null differ diff --git a/applications/Unity.GrantManager/modules/Unity.Theme.UX2/src/Unity.Theme.UX2/wwwroot/themes/ux2/fonts/BCSans/BCSans-Italic.ttf b/applications/Unity.GrantManager/modules/Unity.Theme.UX2/src/Unity.Theme.UX2/wwwroot/themes/ux2/fonts/BCSans/BCSans-Italic.ttf deleted file mode 100644 index 82aff09db..000000000 Binary files a/applications/Unity.GrantManager/modules/Unity.Theme.UX2/src/Unity.Theme.UX2/wwwroot/themes/ux2/fonts/BCSans/BCSans-Italic.ttf and /dev/null differ diff --git a/applications/Unity.GrantManager/modules/Unity.Theme.UX2/src/Unity.Theme.UX2/wwwroot/themes/ux2/fonts/BCSans/BCSans-Light.otf b/applications/Unity.GrantManager/modules/Unity.Theme.UX2/src/Unity.Theme.UX2/wwwroot/themes/ux2/fonts/BCSans/BCSans-Light.otf deleted file mode 100644 index 9e1774bae..000000000 Binary files a/applications/Unity.GrantManager/modules/Unity.Theme.UX2/src/Unity.Theme.UX2/wwwroot/themes/ux2/fonts/BCSans/BCSans-Light.otf and /dev/null differ diff --git a/applications/Unity.GrantManager/modules/Unity.Theme.UX2/src/Unity.Theme.UX2/wwwroot/themes/ux2/fonts/BCSans/BCSans-Light.ttf b/applications/Unity.GrantManager/modules/Unity.Theme.UX2/src/Unity.Theme.UX2/wwwroot/themes/ux2/fonts/BCSans/BCSans-Light.ttf deleted file mode 100644 index b7a00e8e3..000000000 Binary files a/applications/Unity.GrantManager/modules/Unity.Theme.UX2/src/Unity.Theme.UX2/wwwroot/themes/ux2/fonts/BCSans/BCSans-Light.ttf and /dev/null differ diff --git a/applications/Unity.GrantManager/modules/Unity.Theme.UX2/src/Unity.Theme.UX2/wwwroot/themes/ux2/fonts/BCSans/BCSans-LightItalic.otf b/applications/Unity.GrantManager/modules/Unity.Theme.UX2/src/Unity.Theme.UX2/wwwroot/themes/ux2/fonts/BCSans/BCSans-LightItalic.otf deleted file mode 100644 index 770c25700..000000000 Binary files a/applications/Unity.GrantManager/modules/Unity.Theme.UX2/src/Unity.Theme.UX2/wwwroot/themes/ux2/fonts/BCSans/BCSans-LightItalic.otf and /dev/null differ diff --git a/applications/Unity.GrantManager/modules/Unity.Theme.UX2/src/Unity.Theme.UX2/wwwroot/themes/ux2/fonts/BCSans/BCSans-LightItalic.ttf b/applications/Unity.GrantManager/modules/Unity.Theme.UX2/src/Unity.Theme.UX2/wwwroot/themes/ux2/fonts/BCSans/BCSans-LightItalic.ttf deleted file mode 100644 index 491c3820e..000000000 Binary files a/applications/Unity.GrantManager/modules/Unity.Theme.UX2/src/Unity.Theme.UX2/wwwroot/themes/ux2/fonts/BCSans/BCSans-LightItalic.ttf and /dev/null differ diff --git a/applications/Unity.GrantManager/modules/Unity.Theme.UX2/src/Unity.Theme.UX2/wwwroot/themes/ux2/fonts/BCSans/BCSans-Regular.otf b/applications/Unity.GrantManager/modules/Unity.Theme.UX2/src/Unity.Theme.UX2/wwwroot/themes/ux2/fonts/BCSans/BCSans-Regular.otf deleted file mode 100644 index bea110185..000000000 Binary files a/applications/Unity.GrantManager/modules/Unity.Theme.UX2/src/Unity.Theme.UX2/wwwroot/themes/ux2/fonts/BCSans/BCSans-Regular.otf and /dev/null differ diff --git a/applications/Unity.GrantManager/modules/Unity.Theme.UX2/src/Unity.Theme.UX2/wwwroot/themes/ux2/fonts/BCSans/BCSans-Regular.ttf b/applications/Unity.GrantManager/modules/Unity.Theme.UX2/src/Unity.Theme.UX2/wwwroot/themes/ux2/fonts/BCSans/BCSans-Regular.ttf deleted file mode 100644 index 3c0a838de..000000000 Binary files a/applications/Unity.GrantManager/modules/Unity.Theme.UX2/src/Unity.Theme.UX2/wwwroot/themes/ux2/fonts/BCSans/BCSans-Regular.ttf and /dev/null differ 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 89ac6303c..3dbd816a3 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 @@ -1,6 +1,5 @@ /** Layout/Component based styles */ - html, body { height: 100%; width: 100%; @@ -167,13 +166,18 @@ body { font-size: var(--bc-font-size-sm); } - .dataTables_wrapper table th:first-child { - border-top-left-radius: 10px; - } +.dataTables_wrapper table th:first-child { + border-top-left-radius: 10px; +} - .dataTables_wrapper table th:last-child { - border-top-right-radius: 10px; - } +.dataTables_wrapper table th:last-child { + border-top-right-radius: 10px; +} + +.dataTables_wrapper table thead tr:not(:first-child) th:first-child, +.dataTables_wrapper table thead tr:not(:first-child) th:last-child { + border-radius: inherit; +} .dataTables_wrapper thead tr.filters th { border-top-left-radius: 0; @@ -439,7 +443,7 @@ div.dataTables_wrapper div.dataTables_length label { } .nav-item > a { - padding: 1.2rem; + padding: 10px 20px; width: 100%; height: 100%; display: flex; diff --git a/applications/Unity.GrantManager/modules/Unity.Theme.UX2/src/Unity.Theme.UX2/wwwroot/themes/ux2/table-utils.js b/applications/Unity.GrantManager/modules/Unity.Theme.UX2/src/Unity.Theme.UX2/wwwroot/themes/ux2/table-utils.js index 161782893..6cd30bf62 100644 --- a/applications/Unity.GrantManager/modules/Unity.Theme.UX2/src/Unity.Theme.UX2/wwwroot/themes/ux2/table-utils.js +++ b/applications/Unity.GrantManager/modules/Unity.Theme.UX2/src/Unity.Theme.UX2/wwwroot/themes/ux2/table-utils.js @@ -133,27 +133,70 @@ function initializeDataTable(options) { ...(Array.isArray(listColumnDefs) && listColumnDefs.length > 0 ? listColumnDefs : []) ], processing: true, - stateSaveParams: function (settings, data) { - let searchValue = $(settings.oInit.externalSearchInputId).val(); - data.search.search = searchValue; - - let hasFilter = data.columns.some(value => value.search.search !== '') || searchValue !== ''; - $('#btn-toggle-filter').text(hasFilter ? FilterDesc.With_Filter : FilterDesc.Default); + stateSaveParams: function (settings, data) { + let searchValue = $(settings.oInit.externalSearchInputId).val(); + data.search.search = searchValue; + + // Assign unique keys to columns based on their original index + data.columns.forEach((col, idx) => { + let aoCol = settings.aoColumns[idx]; + let originalIdx = typeof aoCol._ColReorder_iOrigCol !== "undefined" ? aoCol._ColReorder_iOrigCol : idx; + let originalCol = settings.aoColumns.find(col => col.index === originalIdx); + data.columns[originalIdx].uniqueKey = originalCol.name; + }); + + let hasFilter = data.columns.some(value => value.search.search !== '') || searchValue !== ''; + $('#btn-toggle-filter').text(hasFilter ? FilterDesc.With_Filter : FilterDesc.Default); }, - stateLoadParams: function (settings, data) { - $(settings.oInit.externalSearchInputId).val(data.search.search); - - data.columns.forEach((column, index) => { - if(settings.aoColumns[index] +"" != "undefined") { - const title = settings.aoColumns[index].sTitle; - const value = column.search.search; - filterData[title] = value; - } - }); + stateLoadParams: function (settings, data) { + $(settings.oInit.externalSearchInputId).val(data.search.search); + let stateCorrupted = false; + const tableId = settings.sTableId || settings.nTable.id; + + data.columns.forEach((column, index) => { + if (settings.aoColumns[index] + "" != "undefined") { + const title = settings.aoColumns[index].sTitle; + const name = settings.aoColumns[index].name; + const dataObj = data.columns.find(col => col.uniqueKey === name); + if (typeof dataObj === "undefined") { + localStorage.removeItem(`DataTables_${tableId}_${window.location.pathname}`); + cleanInvalidStateRestore(tableId); + stateCorrupted = true; + } else { + const value = dataObj?.search?.search ?? ''; + filterData[title] = value; + } + } + }); + + if (stateCorrupted) { + window.location.reload(); + return false; + } } }) ); + function cleanInvalidStateRestore(tableId) { + Object.keys(localStorage) + .filter(key => key.includes('DataTables_stateRestore') && key.includes(`${tableId}`)) + .forEach(key => { + try { + const value = localStorage.getItem(key); + if (!value) return; + const obj = JSON.parse(value); + if (Array.isArray(obj.columns)) { + const hasMissingUniqueKey = obj.columns.some(col => !('uniqueKey' in col)); + if (hasMissingUniqueKey) { + localStorage.removeItem(key); + } + } + } catch (e) { + console.warn(`Could not process DataTables state for key: ${key}`, e); + } + }); + } + // Add custom manage columns button that remains sorted alphabetically if (!disableColumnSelect) { iDt.button().add(updatedActionButtons.length + 1, { @@ -403,8 +446,7 @@ function getColumnToggleButtonsSorted(displayListColumns, dataTable) { node.removeClass('dt-button-active'); } }, - className: 'dt-button dropdown-item buttons-columnVisibility' + isColumnVisToggled(a.title, dataTable), - extend: 'columnToggle', + className: 'dt-button dropdown-item buttons-columnVisibility' + isColumnVisToggled(a.title, dataTable), columns: a.index })); return res; diff --git a/applications/Unity.GrantManager/modules/Unity.Theme.UX2/src/Unity.Theme.UX2/wwwroot/themes/ux2/unity-styles.css b/applications/Unity.GrantManager/modules/Unity.Theme.UX2/src/Unity.Theme.UX2/wwwroot/themes/ux2/unity-styles.css index 231db0896..d6b55df92 100644 --- a/applications/Unity.GrantManager/modules/Unity.Theme.UX2/src/Unity.Theme.UX2/wwwroot/themes/ux2/unity-styles.css +++ b/applications/Unity.GrantManager/modules/Unity.Theme.UX2/src/Unity.Theme.UX2/wwwroot/themes/ux2/unity-styles.css @@ -51,6 +51,13 @@ margin: auto; } +.unity-navbar-nav { + display: flex; + padding-left: 0; + margin-bottom: 0; + list-style: none; +} + .unity-navbar .unity-container-fluid { display: flex; } @@ -342,7 +349,6 @@ thead input { } .abp-widget-wrapper { - /* position: sticky; */ top: 0; z-index: 2; } @@ -525,6 +531,7 @@ div.dt-buttons div.dropdown-menu { .dataTables_filter { margin-bottom: .5rem; + display: none; } .custom-table-btn { @@ -567,10 +574,6 @@ div.dt-buttons div.dropdown-menu { margin-left: 5px; } -.dataTables_filter { - display: none; -} - ul.pagination { justify-content: center !important; margin-top: -20px !important; @@ -768,6 +771,10 @@ div.dataTables_wrapper div.dataTables_filter { font-size: 14px !important; } +.unt-icon-m { + font-size: 16px !important; +} + .unt-accordion { --bs-accordion-active-bg: #5595D9; } diff --git a/applications/Unity.GrantManager/modules/Unity.Theme.UX2/src/Unity.Theme.UX2/wwwroot/themes/ux2/zone-extensions.js b/applications/Unity.GrantManager/modules/Unity.Theme.UX2/src/Unity.Theme.UX2/wwwroot/themes/ux2/zone-extensions.js new file mode 100644 index 000000000..1003da21f --- /dev/null +++ b/applications/Unity.GrantManager/modules/Unity.Theme.UX2/src/Unity.Theme.UX2/wwwroot/themes/ux2/zone-extensions.js @@ -0,0 +1,463 @@ +(function ($) { + if (!$) { + return; + } + + /** + * Unflatten dot separated JSON objects into nested objects + */ + $.fn.unflattenObject = function(flatObj) { + const result = {}; + for (const flatKey in flatObj) { + const value = flatObj[flatKey]; + if (!flatKey) continue; + const keys = flatKey.split('.'); + let cur = result; + for (let i = 0; i < keys.length; i++) { + const k = keys[i]; + if (i === keys.length - 1) { + cur[k] = value; + } else { + cur[k] = cur[k] || {}; + cur = cur[k]; + } + } + } + return result; + } + + /** + * @public + * Handles zone fieldset serialization with DTO nesting + * @param {any} includeDisabled + * @param {any} camelCase + * @returns + */ + $.fn.serializeZoneFieldsets = function (camelCase = true, includeDisabledFields = false, nested = false) { + let $form = $(this); + // OPTIONS NOTE: Zones to exclude + // OPTIONS NOTE: Zones to include + // OPTIONS NOTE: Properties to include + + // Initialize result object + const resultObject = {}; + // Collection phase: Gather all field data in a single pass + const data = []; + + // 1. Get standard form fields + Array.prototype.push.apply(data, $form.serializeArray()); + + // 2. Add unchecked checkboxes (serializeArray ignores them) + $form.find("input[type=checkbox]").each(function () { + if (!$(this).is(':checked')) { + data.push({ name: this.name, value: this.checked }); + } + }); + + // 3. Add disabled fields (also ignored by serializeArray) + if (includeDisabledFields) { + $form.find(':disabled[name]').each(function () { + const value = $(this).is(":checkbox") ? + $(this).is(':checked') : + $(this).val(); + + data.push({ name: this.name, value: value }); + }); + } else { + // Add only disabled fields marked with data-zone-include="true" + $form.find(':disabled[name][data-zone-include="true"]').each(function () { + const value = $(this).is(":checkbox") ? + $(this).is(':checked') : + $(this).val(); + + data.push({ name: this.name, value: value }); + }); + } + + // Convert field names to camelCase if required + if (camelCase) { + data.forEach(item => item.name = toCamelCaseInternal(item.name)); + } + + if (nested) { + // Transformation phase: Convert flat data to nested object structure + data.forEach(field => { + const nameParts = field.name.split('.'); + let current = resultObject; + + // Navigate through the object hierarchy + for (let i = 0; i < nameParts.length - 1; i++) { + const part = nameParts[i]; + if (!current[part]) { + current[part] = {}; + } + current = current[part]; + } + + // Set the final property value + const lastPart = nameParts[nameParts.length - 1]; + if (!current[lastPart] || Object.keys(current[lastPart]).length === 0) { + current[lastPart] = field.value; + } + }); + + return resultObject; + } else { + return data; + } + }; + + /** + * Converts a string to camelCase + * @param {string} str + * @returns + */ + let toCamelCaseInternal = function (str) { + let regexs = [ + /(^[A-Z])/, // first char of string + /((\.)[A-Z])/ // first char after a dot (.) + ]; + + regexs.forEach( + function (regex) { + let infLoopAvoider = 0; + + while (regex.test(str)) { + str = str + .replace(regex, function ($1) { return $1.toLowerCase(); }); + + if (infLoopAvoider++ > 1000) { + break; + } + } + } + ); + + return str; + } + + /** + * @public + * Report fields and feildsets for the initialized component + */ + $.fn.reportZones = function () { + let $form = $(this); + let tableData = []; + + $form.find('fieldset').each(function () { + const fieldName = $(this).attr('name'); + + $(this).find(':input').each(function () { + tableData.push({ + 'fieldsetName': fieldName, + 'id': this.id, + 'name': this.name || '(no name)', + 'type': this.type, + 'tag': this.tagName.toLowerCase(), + 'value': this.value || '(no value)' + }); + }); + }); + + console.table(tableData); + } +})(jQuery); + +class UnityChangeTrackingForm { + constructor($form, options = {}) { + + this.options = { + modifiedClass: options.modifiedClass || 'unity-modified-field-marker', + saveButtonSelector: options.saveButtonSelector || '#saveButton', + ...options + }; + + + // Expect options.form to be a jQuery object representing the form element + if (!$form || !($form instanceof $) || !$form.is('form')) { + throw new Error('UnityChangeTrackingForm requires a jQuery form object in options.form'); + } + + this.form = $form; + this.modifiedFields = new Set(); + this.originalValues = {}; + this.saveButton = $(this.options.saveButtonSelector); + } + + init() { + this.captureInitialValues(); + this.addChangeHandler(); + this.saveButton.prop('disabled', true); + } + + captureInitialValues() { + this.form.find('input, select, textarea').each((_, element) => { + const $el = $(element); + const name = $el.attr('name'); + + if (name) { + // Handle different input types + if ($el.is(':checkbox')) { + this.originalValues[name] = $el.prop('checked'); + } else if ($el.is(':radio')) { + if ($el.prop('checked')) { + this.originalValues[name] = $el.val(); + } + } else if ($el.attr('data-zone-include') === 'true') { + // Store whether this field should be included even when disabled + this.originalValues[name] = $el.val(); + } else { + this.originalValues[name] = $el.val(); + } + } + }); + } + + addChangeHandler() { + this.form.find('input, select, textarea').on('change', (e) => { + const $el = $(e.target); + const name = $el.attr('name'); + + if (name) { + this.checkFieldModified($el, name); + } + }); + } + + checkFieldModified($element, name) { + let currentValue; + + if ($element.is(':checkbox')) { + currentValue = $element.prop('checked'); + } else if ($element.is(':radio')) { + if ($element.prop('checked')) { + currentValue = $element.val(); + } else { + return; // Skip radio buttons that aren't checked + } + } else if ($element.attr('data-zone-include') === 'true') { + // Store whether this field should be included even when disabled + currentValue = $element.val(); + } else { + currentValue = $element.val(); + } + + const originalValue = this.originalValues[name]; + + if (currentValue !== originalValue) { + this.markAsModified($element, name); + } else { + this.markAsUnmodified($element, name); + } + + this.updateSaveButtonState(); + } + + markAsModified($element, name) { + this.modifiedFields.add(name); + $element.addClass(this.options.modifiedClass); + $element.attr('data-field-modified', 'true'); + } + + markAsUnmodified($element, name) { + this.modifiedFields.delete(name); + $element.removeClass(this.options.modifiedClass); + } + + updateSaveButtonState() { + this.saveButton.prop('disabled', this.modifiedFields.size === 0); + } + + /** + * Reset tracking without changing values + */ + resetTracking() { + this.modifiedFields.clear(); + this.form.find('input, select, textarea').each((_, element) => { + const $el = $(element); + $el.removeClass(this.options.modifiedClass); + $el.removeAttr('data-field-modified'); + }); + this.saveButton.prop('disabled', true); + this.captureInitialValues(); + } + + /** + * Reset form to original values and clear tracking + */ + resetForm() { + // Reset each field to its original value + this.form.find('input, select, textarea').each((_, element) => { + const $el = $(element); + const name = $el.attr('name'); + + if (name && this.originalValues.hasOwnProperty(name)) { + // Handle different input types + if ($el.is(':checkbox')) { + $el.prop('checked', this.originalValues[name]); + } else if ($el.is(':radio')) { + if ($el.val() === this.originalValues[name]) { + $el.prop('checked', true); + } + } else { + $el.val(this.originalValues[name]); + + // Re-apply any special formatting (like currency masks) + if ($el.hasClass('unity-currency-input') || + $el.hasClass('numeric-mask') || + $el.hasClass('percentage-mask')) { + $el.maskMoney('mask', this.originalValues[name]); + } + } + + // Remove modification styling + $el.removeClass(this.options.modifiedClass); + $el.removeAttr('data-field-modified'); + } + }); + + // Clear tracking + this.modifiedFields.clear(); + this.saveButton.prop('disabled', true); + + // Trigger change events for any dependent calculations + this.form.find('.numeric-mask, .unity-currency-input').trigger('change'); + } + + serializeZoneObject(camelCase = true, includeDisabledFields = false) { + return this.form.serializeZoneFieldsets(camelCase, includeDisabledFields); + } + + serializeZoneArray(camelCase = false, includeDisabledFields = false, nested = false) { + return this.form.serializeZoneFieldsets(camelCase, includeDisabledFields, nested); + } +} + +class UnityZoneForm extends UnityChangeTrackingForm { + constructor($form, options = {}) { + super($form, options); + this.options = { + ...this.options, + ...options + }; + } + + init() { + super.init(); + this.form.on('reset', () => this.resetTracking()); + this.initializeNumericFields(); + this.addSubmitHandler(); + } + + // NOTE Get Zone Status + // NOTE Get field by name or id + // NOTE Get field value by name or id + + isValid() { + return this.form.valid(); + } + + initializeNumericFields() { + $('.numeric-mask').maskMoney({ precision: 0 }); + $('.percentage-mask').maskMoney(); + + $('.numeric-mask').each(function () { + $(this).maskMoney('mask', this.value); + }); + + $('.percentage-mask').each(function () { + $(this).maskMoney('mask', this.value); + }); + + $('.remove-leading-zeros').on('input', function () { + let inputValue = $(this).val(); + let newValue = inputValue.replace(/^0+(?!$)/, ''); + $(this).val(newValue); + }); + + $('.unity-currency-input').maskMoney(); + } + + /** + * Extracts the last two segments from a string separated by underscores, + * and returns them joined by an underscore (e.g., "Unity_GrantManager_ApplicationManagement_Applicant_Summary" => "Applicant_Summary"). + * If the input does not have at least two segments, returns the original string. + * @private + * @param {string} input + * @returns {string} + */ + #extractZoneSuffix(input) { + if (typeof input !== 'string') return input; + const parts = input.split('_'); + if (parts.length < 2) return input; + return parts.slice(-2).join('_'); + } + + addSubmitHandler() { + this.form.on('submit', (e) => { + e.preventDefault(); + // Include submission handler callback + this.resetTracking(); + }); + } + + reportZones(viewExpanded = false) { + let tableData = []; + const self = this; // Store reference to the class instance + + this.form.find('fieldset').each(function () { + const fieldName = $(this).attr('name'); + + $(this).find(':input').each(function () { + const $el = $(this); + const name = this.name || '(no name)'; + + // Get current value based on input type + let currentValue; + if ($el.is(':checkbox')) { + currentValue = $el.prop('checked'); + } else if ($el.is(':radio')) { + if ($el.prop('checked')) { + currentValue = $el.val(); + } else { + currentValue = '(unchecked radio)'; + } + } else { + currentValue = $el.val() || '(no value)'; + } + + // Get original value if it exists + const originalValue = name !== '(no name)' && self.originalValues.hasOwnProperty(name) ? + self.originalValues[name] : '(not tracked)'; + + const isModified = self.modifiedFields.has(name); + + let tableOutput = { + 'fieldsetName': self.#extractZoneSuffix(fieldName), + 'id': this.id + } + + if (viewExpanded) { + let expandedProperties = { + 'name': name, + 'tag': this.tagName.toLowerCase(), + 'type': this.type + }; + + tableOutput = { ...tableOutput, ...expandedProperties }; + } + + let changeProperties = { + 'originalValue': originalValue, + 'currentValue': currentValue, + 'modified': isModified + }; + tableOutput = { ...tableOutput, ...changeProperties }; + + tableData.push(tableOutput); + }); + }); + + console.table(tableData); + } +} \ No newline at end of file diff --git a/applications/Unity.GrantManager/ocUnityDbConnect.ps1 b/applications/Unity.GrantManager/ocUnityDbConnect.ps1 new file mode 100644 index 000000000..a575ec6c4 --- /dev/null +++ b/applications/Unity.GrantManager/ocUnityDbConnect.ps1 @@ -0,0 +1,128 @@ +# Prompt the user to optionally login to OpenShift +Write-Host "Do you want to log in to OpenShift now? (y/n)" -ForegroundColor Green +$loginResponse = Read-Host +if ($loginResponse -match '^(y|yes)$') { + try { + oc login --web --server=https://api.silver.devops.gov.bc.ca:6443 + } + catch { + Write-Host "Login failed. Please check your connection and credentials." -ForegroundColor Red + exit 1 + } +} + +# Prompt user for environment selection +$validEnvironments = @("dev", "test", "prod") +do { + Write-Host "Enter environment (dev, test, prod)" -ForegroundColor Green + $environment = Read-Host +} while (-not ($validEnvironments -contains $environment)) + + +# Define cluster mappings +$clusterMappings = @{ + 'dev' = @('dev', 'dev2') + 'test' = @('test', 'uat') + 'prod' = @('prod') +} + +if ($environment -eq 'prod') { + $cluster = 'prod' +} else { + $validClusters = $clusterMappings[$environment] + do { + Write-Host "Please select between $($validClusters -join ' and ')" -ForegroundColor Green + $cluster = Read-Host "Enter cluster ($($validClusters -join ', '))" + } while (-not ($validClusters -contains $cluster)) +} + + +# Configuration parameters (dynamically updated based on environment) +$NameSpace = "d18498-$environment" # OpenShift project namespace +$ClusterName = "$cluster-crunchy-postgres" +$LocalPort = 5436 +$RemotePort = 5432 +$ListenInterface = "localhost" +$RetrySeconds = 3 + +# Check if oc is installed +if (-not (Get-Command oc -ErrorAction SilentlyContinue)) { + Write-Host "The OpenShift CLI (oc) is not installed or not available in PATH." -ForegroundColor Red + exit 1 +} + +# Set the OpenShift project namespace +Write-Host "Setting OpenShift project to $NameSpace..." -ForegroundColor Cyan +try { + oc project $NameSpace +} +catch { + Write-Host "Error setting project: $_" -ForegroundColor Red + Write-Host "Please ensure you're logged in to OpenShift before running this script." -ForegroundColor Yellow + exit 1 +} + +# Function to get the current primary pod using selectors +function Get-PrimaryPod { + $selector = "postgres-operator.crunchydata.com/cluster=$ClusterName,postgres-operator.crunchydata.com/role=master" + try { + $primaryPod = oc get pod -o name --selector=$selector + if ([string]::IsNullOrEmpty($primaryPod)) { + Write-Host "No primary pod found with selector: $selector" -ForegroundColor Yellow + return $null + } + return ($primaryPod -replace "^pod/", "").Trim() + } + catch { + Write-Host "Error getting primary pod: $_" -ForegroundColor Red + return $null + } +} + +# Function to check if still logged in +function Test-OCLogin { + try { + $null = oc project $NameSpace 2>&1 + return $true + } + catch { + Write-Host "OpenShift login has expired or cannot access namespace '$NameSpace'. Please run the script again to re-authenticate." -ForegroundColor Red + return $false + } +} + +# Main connection loop +while ($true) { + Write-Host "" + $datetime = Get-Date -Format "yyyy-MM-dd HH:mm:ss K" + Write-Host $datetime -ForegroundColor Cyan + + # Get the current primary pod + $primaryPod = Get-PrimaryPod + + if ($primaryPod) { + Write-Host "Connecting to primary pod: $primaryPod" -ForegroundColor Green + + # Forward the port + try { + oc port-forward --address $ListenInterface $primaryPod "${LocalPort}:${RemotePort}" + } + catch { + Write-Host "Error occurred during port forwarding: $_" -ForegroundColor Red + } + } + else { + Write-Host "Unable to find primary PostgreSQL pod. Retrying in $RetrySeconds seconds..." -ForegroundColor Yellow + } + + # Pause before retry + Start-Sleep -Seconds $RetrySeconds + + # Check login status + if (-not (Test-OCLogin)) { + break + } +} + +Write-Host "Press any key to exit..." -ForegroundColor Yellow +$null = $Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown") \ No newline at end of file diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/ApplicationForms/ApplicationFormDto.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/ApplicationForms/ApplicationFormDto.cs index 850e528a1..6a1176c74 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/ApplicationForms/ApplicationFormDto.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/ApplicationForms/ApplicationFormDto.cs @@ -1,4 +1,5 @@ using System; +using Unity.GrantManager.GrantApplications; using Volo.Abp.Application.Dtos; namespace Unity.GrantManager.ApplicationForms @@ -24,5 +25,6 @@ public class ApplicationFormDto : EntityDto public Guid? ScoresheetId { get; set; } public Guid? TenantId { get; set; } public bool IsDirectApproval { get; set; } + public AddressType? ElectoralDistrictAddressType { 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 32c9fbbf6..e7db0c975 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 @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Threading.Tasks; using Unity.GrantManager.Forms; +using Unity.GrantManager.GrantApplications; using Volo.Abp.Application.Dtos; using Volo.Abp.Application.Services; @@ -13,8 +14,9 @@ public interface IApplicationFormAppService : ICrudAppService< PagedAndSortedResultRequestDto, CreateUpdateApplicationFormDto> { + Task GetElectoralDistrictAddressTypeAsync(Guid id); Task> GetVersionsAsync(Guid id); Task> GetPublishedVersionsAsync(Guid id); - Task UpdateOtherConfig(Guid id, OtherConfigDto config); + Task PatchOtherConfig(Guid id, OtherConfigDto config); } } diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/ApplicationForms/IApplicationFormSycnronizationService.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/ApplicationForms/IApplicationFormSycnronizationService.cs index b65438de9..767c9fb7a 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/ApplicationForms/IApplicationFormSycnronizationService.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/ApplicationForms/IApplicationFormSycnronizationService.cs @@ -1,22 +1,22 @@ -using System; -using System.Collections.Generic; -using System.Threading.Tasks; -using Unity.GrantManager.Forms; -using Volo.Abp.Application.Dtos; -using Volo.Abp.Application.Services; - -namespace Unity.GrantManager.ApplicationForms -{ - public interface IApplicationFormSycnronizationService : ICrudAppService< - ApplicationFormDto, - Guid, - PagedAndSortedResultRequestDto, - CreateUpdateApplicationFormDto> - { - Task> GetConnectedApplicationFormsAsync(); - Task> GetMissingSubmissions(int numberOfDaysToCheck); - Task> GetChefsSubmissions(ApplicationFormDto applicationFormDto, int numberOfDaysToCheck); +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using Unity.GrantManager.Forms; +using Volo.Abp.Application.Dtos; +using Volo.Abp.Application.Services; + +namespace Unity.GrantManager.ApplicationForms +{ + public interface IApplicationFormSycnronizationService : ICrudAppService< + ApplicationFormDto, + Guid, + PagedAndSortedResultRequestDto, + CreateUpdateApplicationFormDto> + { + Task> GetConnectedApplicationFormsAsync(); + Task<(HashSet MissingSubmissions, string MissingSubmissionsReport)> GetMissingSubmissions(int numberOfDaysToCheck); + Task> GetChefsSubmissions(ApplicationFormDto applicationFormDto, int numberOfDaysToCheck); HashSet GetSubmissionsByForm(Guid applicationFormId); - - } -} + + } +} diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/ApplicationForms/OtherConfigDto.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/ApplicationForms/OtherConfigDto.cs index 81632c106..311779cb2 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/ApplicationForms/OtherConfigDto.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/ApplicationForms/OtherConfigDto.cs @@ -1,7 +1,10 @@ -namespace Unity.GrantManager.Forms +using Unity.GrantManager.GrantApplications; + +namespace Unity.GrantManager.ApplicationForms { public class OtherConfigDto { public bool IsDirectApproval { get; set; } + public AddressType? ElectoralDistrictAddressType { get; set; } } } diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/Emails/CreateEmailDto.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/Emails/CreateEmailDto.cs index 61949c518..f6ddffba4 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/Emails/CreateEmailDto.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/Emails/CreateEmailDto.cs @@ -15,7 +15,7 @@ public class CreateEmailDto [MaxLength(1023)] // Max for CHES public string EmailSubject { get; set; } = string.Empty; - [MaxLength(40000)] + [Required] public string EmailBody { get; set; } = string.Empty; public Guid ApplicationId { get; set; } diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/GrantApplications/ApplicantAddressDto.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/GrantApplications/ApplicantAddressDto.cs index 429f6689d..ff96dd506 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/GrantApplications/ApplicantAddressDto.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/GrantApplications/ApplicantAddressDto.cs @@ -1,10 +1,11 @@ using System; using Volo.Abp.Application.Dtos; +using Volo.Abp.Auditing; namespace Unity.GrantManager.GrantApplications; [Serializable] -public class ApplicantAddressDto : EntityDto +public class ApplicantAddressDto : EntityDto, IHasCreationTime, IHasModificationTime { public Guid ApplicantId { get; set; } public string Street { get; set; } = string.Empty; @@ -13,6 +14,8 @@ public class ApplicantAddressDto : EntityDto public string? City { get; set; } public string? Province { get; set; } public string? Postal { get; set; } + public AddressType AddressType { get; set; } + public DateTime CreationTime { get; set; } - public AddressType AddressType { get; set; } + public DateTime? LastModificationTime { get; set; } } \ No newline at end of file diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/GrantApplications/ApplicantInfoDto.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/GrantApplications/ApplicantInfoDto.cs new file mode 100644 index 000000000..1d861bcf2 --- /dev/null +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/GrantApplications/ApplicantInfoDto.cs @@ -0,0 +1,22 @@ +using System; +using System.Collections.Generic; +using Unity.Flex.Worksheets; + +namespace Unity.GrantManager.GrantApplications; + +public class ApplicantInfoDto : CustomDataFieldDto +{ + public Guid ApplicationId { get; set; } + public Guid ApplicantId { get; set; } + public Guid ApplicationFormId { get; set; } + + public string ApplicationReferenceNo { get; set; } = string.Empty; + public string ApplicantName { get; set; } = string.Empty; + public GrantApplicationState ApplicationStatusCode { get; set; } + public string? ElectoralDistrict { get; set; } + + public ApplicantSummaryDto? ApplicantSummary { get; set; } + public List? ApplicantAddresses { get; set; } + public SigningAuthorityDto? SigningAuthority { get; set; } + public ContactInfoDto? ContactInfo { get; set; } +} diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/GrantApplications/ApplicantSummaryDto.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/GrantApplications/ApplicantSummaryDto.cs new file mode 100644 index 000000000..885df95bf --- /dev/null +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/GrantApplications/ApplicantSummaryDto.cs @@ -0,0 +1,24 @@ +using System; + +namespace Unity.GrantManager.GrantApplications; + +public class ApplicantSummaryDto +{ + public Guid ApplicantId { get; set; } + public string? ApplicantName { get; set; } + public string? Sector { get; set; } + public string? SubSector { get; set; } + public string? OrgNumber { get; set; } + public string? OrgName { get; set; } + public string? NonRegOrgName { get; set; } + public string? OrgStatus { get; set; } + public string? OrganizationType { get; set; } + public string? OrganizationSize { get; set; } + public string? SectorSubSectorIndustryDesc { get; set; } + public bool? RedStop { get; set; } + public bool? IndigenousOrgInd { get; set; } + public string? UnityApplicantId { get; set; } + public string? FiscalDay { get; set; } + public string? FiscalMonth { get; set; } + public string? ElectoralDistrict { get; set; } +} diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/GrantApplications/ApplicationApplicantInfoDto.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/GrantApplications/ApplicationApplicantInfoDto.cs index 1a4a38937..4e29860b0 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/GrantApplications/ApplicationApplicantInfoDto.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/GrantApplications/ApplicationApplicantInfoDto.cs @@ -1,28 +1,27 @@ using System; using System.Collections.Generic; -namespace Unity.GrantManager.GrantApplications +namespace Unity.GrantManager.GrantApplications; + +[Serializable] +public class ApplicationApplicantInfoDto : GrantApplicationApplicantDto { - [Serializable] - public class ApplicationApplicantInfoDto : GrantApplicationApplicantDto - { - public Guid ApplicantId { get; set; } - public string ContactFullName { get; set; } = string.Empty; - public string ContactTitle { get; set; } = string.Empty; - public string ContactEmail { get; set; } = string.Empty; - public string ContactBusinessPhone { get; set; } = string.Empty; - public string ContactCellPhone { get; set; } = string.Empty; - public string OrganizationName { get; set; } = string.Empty; - public string SigningAuthorityFullName { get; set; } = string.Empty; - public string SigningAuthorityTitle { get; set; } = string.Empty; - public string SigningAuthorityEmail { get; set; } = string.Empty; - public string SigningAuthorityBusinessPhone { get; set; } = string.Empty; - public string SigningAuthorityCellPhone { get; set; } = string.Empty; - public string ApplicationReferenceNo { get; set; } = string.Empty; - public string ApplicationStatus { get; set; } = string.Empty; - public GrantApplicationState ApplicationStatusCode { get; set; } - public List ApplicantAddresses { get; set; } = new List(); - public Guid ApplicationFormId { get; set; } - public string NonRegOrgName { get; set; } = string.Empty; - } + public Guid ApplicantId { get; set; } + public string ContactFullName { get; set; } = string.Empty; + public string ContactTitle { get; set; } = string.Empty; + public string ContactEmail { get; set; } = string.Empty; + public string ContactBusinessPhone { get; set; } = string.Empty; + public string ContactCellPhone { get; set; } = string.Empty; + public string OrganizationName { get; set; } = string.Empty; + public string SigningAuthorityFullName { get; set; } = string.Empty; + public string SigningAuthorityTitle { get; set; } = string.Empty; + public string SigningAuthorityEmail { get; set; } = string.Empty; + public string SigningAuthorityBusinessPhone { get; set; } = string.Empty; + public string SigningAuthorityCellPhone { get; set; } = string.Empty; + public string ApplicationReferenceNo { get; set; } = string.Empty; + public string ApplicationStatus { get; set; } = string.Empty; + public GrantApplicationState ApplicationStatusCode { get; set; } + public List ApplicantAddresses { get; set; } = []; + public Guid ApplicationFormId { get; set; } + public string NonRegOrgName { get; set; } = string.Empty; } diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/GrantApplications/BulkApprovalDto.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/GrantApplications/BulkApprovalDto.cs index 5e08208af..cd248c606 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/GrantApplications/BulkApprovalDto.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/GrantApplications/BulkApprovalDto.cs @@ -25,5 +25,7 @@ public BulkApprovalDto() public string ApplicantName { get; set; } public string FormName { get; set; } public string ApplicationStatus { get; set; } + public bool? IsDirectApproval { get; set; } + public decimal RecommendedAmount { get; set; } } } diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/GrantApplications/ContactInfoDto.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/GrantApplications/ContactInfoDto.cs new file mode 100644 index 000000000..f0a1c0209 --- /dev/null +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/GrantApplications/ContactInfoDto.cs @@ -0,0 +1,15 @@ +using System; + +namespace Unity.GrantManager.GrantApplications; + +public class ContactInfoDto +{ + public Guid? ApplicantAgentId { get; set; } + public Guid? ApplicationId { get; set; } + + public string? Name { get; set; } + public string? Title { get; set; } + public string? Email { get; set; } + public string? Phone { get; set; } + public string? Phone2 { get; set; } +} diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/GrantApplications/CreateUpdateApplicantInfoDto.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/GrantApplications/CreateUpdateApplicantInfoDto.cs index cf46c49a4..92c317d68 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/GrantApplications/CreateUpdateApplicantInfoDto.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/GrantApplications/CreateUpdateApplicantInfoDto.cs @@ -1,18 +1,21 @@ using System; +using System.Collections.Generic; using Unity.Flex.Worksheets; namespace Unity.GrantManager.GrantApplications { public class CreateUpdateApplicantInfoDto : CustomDataFieldDto { + public Guid? ApplicationId { get; set; } + public Guid ApplicantId { get; set; } public string? OrgName { get; set; } public string? OrgNumber { get; set; } public string? OrgStatus { get; set; } - public string? OrganizationType { get; set; } + public string? OrganizationType { get; set; } public string? OrganizationSize { get; set; } public string? Sector { get; set; } - public string? SubSector { get; set; } + public string? SubSector { get; set; } public string? SectorSubSectorIndustryDesc { get; set; } = string.Empty; public bool? RedStop { get; set; } public string? IndigenousOrgInd { get; set; } @@ -29,8 +32,6 @@ public class CreateUpdateApplicantInfoDto : CustomDataFieldDto public string? SigningAuthorityEmail { get; set; } public string? SigningAuthorityBusinessPhone { get; set; } public string? SigningAuthorityCellPhone { get; set; } - public string? SupplierNumber { get; set; } - public string? OriginalSupplierNumber { get; set; } public string? PhysicalAddressStreet { get; set; } public string? PhysicalAddressStreet2 { get; set; } public string? PhysicalAddressUnit { get; set; } @@ -45,7 +46,61 @@ public class CreateUpdateApplicantInfoDto : CustomDataFieldDto public string? MailingAddressProvince { get; set; } public string? MailingAddressPostalCode { get; set; } - public Guid ApplicantId { get; set; } public string? NonRegOrgName { get; set; } + public string? ElectoralDistrict { get; set; } + public string? ApplicantName { get; set; } + } + + public class UpsertApplicantInfoDto : CustomDataFieldDto + { + public string ApplicationReferenceNo { get; set; } = string.Empty; + public string ApplicantName { get; set; } = string.Empty; + public GrantApplicationState ApplicationStatusCode { get; set; } + + public ApplicantSummaryDto? ApplicantSummary { get; set; } + public List? ApplicantAddresses { get; set; } + public SigningAuthorityDto? SigningAuthority { get; set; } + public ContactInfoDto? ContactInfo { get; set; } + + public string? OrgName { get; set; } + public string? OrgNumber { get; set; } + public string? OrgStatus { get; set; } + public string? OrganizationType { get; set; } + public string? OrganizationSize { get; set; } + + public string? Sector { get; set; } + public string? SubSector { get; set; } + public string? SectorSubSectorIndustryDesc { get; set; } = string.Empty; + public bool? RedStop { get; set; } + public string? IndigenousOrgInd { get; set; } + public string? UnityApplicantId { get; set; } + public int? FiscalDay { get; set; } + public string? FiscalMonth { get; set; } + public string? ContactFullName { get; set; } + public string? ContactTitle { get; set; } + public string? ContactEmail { get; set; } + public string? ContactBusinessPhone { get; set; } + public string? ContactCellPhone { get; set; } + public string? SigningAuthorityFullName { get; set; } + public string? SigningAuthorityTitle { get; set; } + public string? SigningAuthorityEmail { get; set; } + public string? SigningAuthorityBusinessPhone { get; set; } + public string? SigningAuthorityCellPhone { get; set; } + public string? PhysicalAddressStreet { get; set; } + public string? PhysicalAddressStreet2 { get; set; } + public string? PhysicalAddressUnit { get; set; } + public string? PhysicalAddressCity { get; set; } + public string? PhysicalAddressProvince { get; set; } + public string? PhysicalAddressPostalCode { get; set; } + + public string? MailingAddressStreet { get; set; } + public string? MailingAddressStreet2 { get; set; } + public string? MailingAddressUnit { get; set; } + public string? MailingAddressCity { get; set; } + public string? MailingAddressProvince { get; set; } + public string? MailingAddressPostalCode { get; set; } + + public string? NonRegOrgName { get; set; } + public string? ElectoralDistrict { get; set; } } } diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/GrantApplications/CreateUpdateProjectInfoDto.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/GrantApplications/CreateUpdateProjectInfoDto.cs index 3e87c8475..be38844d1 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/GrantApplications/CreateUpdateProjectInfoDto.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/GrantApplications/CreateUpdateProjectInfoDto.cs @@ -1,39 +1,38 @@ using System; using Unity.Flex.Worksheets; -namespace Unity.GrantManager.GrantApplications +namespace Unity.GrantManager.GrantApplications; + +public class CreateUpdateProjectInfoDto : CustomDataFieldDto { - public class CreateUpdateProjectInfoDto : CustomDataFieldDto - { - public Guid? ApplicationId { get; set; } - public string? ProjectSummary { get; set; } - public string? ProjectName { get; set; } - public decimal? RequestedAmount { get; set; } - public decimal? TotalProjectBudget { get; set; } - public DateTime? ProjectStartDate { get; set; } - public DateTime? ProjectEndDate { get; set; } - public double? PercentageTotalProjectBudget { get; set; } - public decimal? ProjectFundingTotal { get; set; } - public string? Community { get; set; } - public int? CommunityPopulation { get; set; } - public string? Acquisition { get; set; } - public string? Forestry { get; set; } - public string? ForestryFocus { get; set; } - public string? Sector { get; set; } - public string? SubSector { get; set; } - public string? ElectoralDistrict { get; set; } - public string? EconomicRegion { get; set; } - public string? RegionalDistrict { get; set; } - public string? ContactFullName { get; set; } - public string? ContactTitle { get; set;} - public string? ContactEmail { get; set;} - public string? ContactBusinessPhone { get; set;} - public string? ContactCellPhone { get; set;} - public string? SigningAuthorityFullName { get; set; } - public string? SigningAuthorityTitle { get; set; } - public string? SigningAuthorityEmail { get; set; } - public string? SigningAuthorityBusinessPhone { get; set; } - public string? SigningAuthorityCellPhone { get; set; } - public string? Place { get; set; } - } + public Guid? ApplicationId { get; set; } + public string? ProjectSummary { get; set; } + public string? ProjectName { get; set; } + public decimal? RequestedAmount { get; set; } + public decimal? TotalProjectBudget { get; set; } + public DateTime? ProjectStartDate { get; set; } + public DateTime? ProjectEndDate { get; set; } + public double? PercentageTotalProjectBudget { get; set; } + public decimal? ProjectFundingTotal { get; set; } + public string? Community { get; set; } + public int? CommunityPopulation { get; set; } + public string? Acquisition { get; set; } + public string? Forestry { get; set; } + public string? ForestryFocus { get; set; } + public string? Sector { get; set; } + public string? SubSector { get; set; } + public string? ElectoralDistrict { get; set; } + public string? EconomicRegion { get; set; } + public string? RegionalDistrict { get; set; } + public string? ContactFullName { get; set; } + public string? ContactTitle { get; set; } + public string? ContactEmail { get; set; } + public string? ContactBusinessPhone { get; set; } + public string? ContactCellPhone { get; set; } + public string? SigningAuthorityFullName { get; set; } + public string? SigningAuthorityTitle { get; set; } + public string? SigningAuthorityEmail { get; set; } + public string? SigningAuthorityBusinessPhone { get; set; } + public string? SigningAuthorityCellPhone { get; set; } + public string? Place { get; set; } } diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/GrantApplications/GrantApplicationApplicant.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/GrantApplications/GrantApplicationApplicant.cs index 849a3e336..67409f497 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/GrantApplications/GrantApplicationApplicant.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/GrantApplications/GrantApplicationApplicant.cs @@ -21,4 +21,5 @@ public class GrantApplicationApplicantDto : AuditedEntityDto public string UnityApplicantId { get; set; } = string.Empty; public string FiscalDay { get; set; } = string.Empty; public string FiscalMonth { get; set; } = string.Empty; + public string? ElectoralDistrict { get; set; } } diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/GrantApplications/IApplicationApplicantAppService.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/GrantApplications/IApplicationApplicantAppService.cs index aabd77357..04b603ea8 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/GrantApplications/IApplicationApplicantAppService.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/GrantApplications/IApplicationApplicantAppService.cs @@ -1,5 +1,6 @@ using System; using System.Threading.Tasks; +using Unity.Modules.Shared; using Volo.Abp.Application.Services; namespace Unity.GrantManager.GrantApplications @@ -7,5 +8,7 @@ namespace Unity.GrantManager.GrantApplications public interface IApplicationApplicantAppService : IApplicationService { Task GetByApplicationIdAsync(Guid applicationId); + Task GetApplicantInfoTabAsync(Guid applicationId); + Task UpdatePartialApplicantInfoAsync(Guid applicationId, PartialUpdateDto input); } } 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 aba2c029e..ab7b02653 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 @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Threading.Tasks; +using Volo.Abp.Application.Dtos; using Volo.Abp.Application.Services; namespace Unity.GrantManager.GrantApplications; @@ -14,4 +15,10 @@ public interface IApplicationTagsService : IApplicationService Task GetApplicationTagsAsync(Guid id); + Task> GetTagSummaryAsync(); + Task GetMaxRenameLengthAsync(string originalTag); + Task> RenameTagAsync(string originalTag, string replacementTag); + Task RenameTagGlobalAsync(string originalTag, string replacementTag); + Task DeleteTagAsync(string deleteTag); + Task DeleteTagGlobalAsync(string deleteTag); } diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/GrantApplications/IGrantApplicationAppService.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/GrantApplications/IGrantApplicationAppService.cs index bff3976b9..bc22b37da 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/GrantApplications/IGrantApplicationAppService.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/GrantApplications/IGrantApplicationAppService.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Threading.Tasks; using Unity.GrantManager.Comments; +using Unity.Modules.Shared; using Volo.Abp.Application.Dtos; namespace Unity.GrantManager.GrantApplications @@ -12,8 +13,10 @@ public interface IGrantApplicationAppService : ICommentsService Task> GetActions(Guid applicationId, bool includeInternal = false); Task GetSummaryAsync(Guid applicationId); Task UpdateProjectInfoAsync(Guid id, CreateUpdateProjectInfoDto input); + Task UpdatePartialProjectInfoAsync(Guid id, PartialUpdateDto input); Task UpdateProjectApplicantInfoAsync(Guid id, CreateUpdateApplicantInfoDto input); Task UpdateAssessmentResultsAsync(Guid id, CreateUpdateAssessmentResultsDto input); + Task UpdateSupplierNumberAsync(Guid applicationId, string supplierNumber); Task> GetAllApplicationsAsync(); Task> GetApplicationDetailsListAsync(List applicationIds); Task GetAsync(Guid id); diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/GrantApplications/PaymentInfoDto.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/GrantApplications/PaymentInfoDto.cs index 4783ffaa3..22b61f0c2 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/GrantApplications/PaymentInfoDto.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/GrantApplications/PaymentInfoDto.cs @@ -1,4 +1,3 @@ - namespace Unity.GrantManager.GrantApplications; public class PaymentInfoDto diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/GrantApplications/SigningAuthorityDto.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/GrantApplications/SigningAuthorityDto.cs new file mode 100644 index 000000000..56ce79819 --- /dev/null +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/GrantApplications/SigningAuthorityDto.cs @@ -0,0 +1,10 @@ +namespace Unity.GrantManager.GrantApplications; + +public class SigningAuthorityDto +{ + public string? SigningAuthorityFullName { get; set; } + public string? SigningAuthorityTitle { get; set; } + public string? SigningAuthorityEmail { get; set; } + public string? SigningAuthorityBusinessPhone { get; set; } + public string? SigningAuthorityCellPhone { get; set; } +} diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/GrantApplications/TagSummaryCountDto.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/GrantApplications/TagSummaryCountDto.cs new file mode 100644 index 000000000..8507c88c4 --- /dev/null +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/GrantApplications/TagSummaryCountDto.cs @@ -0,0 +1,6 @@ +namespace Unity.GrantManager.GrantApplications; +public class TagSummaryCountDto +{ + public required string Text { get; set; } + public required int Count { get; set; } +} diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/GrantApplications/UpdateApplicantAddressDto.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/GrantApplications/UpdateApplicantAddressDto.cs new file mode 100644 index 000000000..ad283d6fa --- /dev/null +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/GrantApplications/UpdateApplicantAddressDto.cs @@ -0,0 +1,16 @@ +using System; + +namespace Unity.GrantManager.GrantApplications; + +public class UpdateApplicantAddressDto +{ + public Guid ApplicantId { get; set; } + public AddressType AddressType { get; set; } + + public string? Street { get; set; } + public string? Street2 { get; set; } + public string? Unit { get; set; } + public string? City { get; set; } + public string? Province { get; set; } + public string? PostalCode { get; set; } +} diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/GrantApplications/UpdateApplicantInfoDto.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/GrantApplications/UpdateApplicantInfoDto.cs new file mode 100644 index 000000000..a4a626d1e --- /dev/null +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/GrantApplications/UpdateApplicantInfoDto.cs @@ -0,0 +1,19 @@ +using System; +using Unity.Flex.Worksheets; + +namespace Unity.GrantManager.GrantApplications; + +public class UpdateApplicantInfoDto : CustomDataFieldDto +{ + public Guid ApplicationId { get; set; } + public Guid ApplicantId { get; set; } + public Guid ApplicationFormId { get; set; } + + public string? ElectoralDistrict { get; set; } + + public UpdateApplicantSummaryDto? ApplicantSummary { get; set; } + public UpdateApplicantAddressDto? PhysicalAddress { get; set; } + public UpdateApplicantAddressDto? MailingAddress { get; set; } + public SigningAuthorityDto? SigningAuthority { get; set; } + public ContactInfoDto? ContactInfo { get; set; } +} diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/GrantApplications/UpdateApplicantSummaryDto.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/GrantApplications/UpdateApplicantSummaryDto.cs new file mode 100644 index 000000000..cbe79cc0d --- /dev/null +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/GrantApplications/UpdateApplicantSummaryDto.cs @@ -0,0 +1,21 @@ +namespace Unity.GrantManager.GrantApplications; + +public class UpdateApplicantSummaryDto +{ + public string? ApplicantName { get; set; } + public string? Sector { get; set; } + public string? SubSector { get; set; } + public string? OrgNumber { get; set; } + public string? OrgName { get; set; } + public string? NonRegOrgName { get; set; } + public string? OrgStatus { get; set; } + public string? OrganizationType { get; set; } + public string? OrganizationSize { get; set; } + public string? SectorSubSectorIndustryDesc { get; set; } + public bool? RedStop { get; set; } + public bool? IndigenousOrgInd { get; set; } + public string? UnityApplicantId { get; set; } + public string? FiscalDay { get; set; } + public string? FiscalMonth { get; set; } + public string? ElectoralDistrict { get; set; } +} diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/GrantApplications/UpdateProjectInfoDto.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/GrantApplications/UpdateProjectInfoDto.cs new file mode 100644 index 000000000..7fe2b2373 --- /dev/null +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/GrantApplications/UpdateProjectInfoDto.cs @@ -0,0 +1,41 @@ +using System; +using System.Text.Json.Serialization; +using Unity.Flex.Worksheets; + +namespace Unity.GrantManager.GrantApplications; + +public class UpdateProjectInfoDto : CustomDataFieldDto +{ + public Guid? ApplicationId { get; set; } + public string? ProjectSummary { get; set; } + public string? ProjectName { get; set; } + public decimal? RequestedAmount { get; set; } + public decimal? TotalProjectBudget { get; set; } + public DateTime? ProjectStartDate { get; set; } + public DateTime? ProjectEndDate { get; set; } + + [JsonIgnore] // Calculated Property + public double? PercentageTotalProjectBudget { get; set; } + public decimal? ProjectFundingTotal { get; set; } + public string? Community { get; set; } + public int? CommunityPopulation { get; set; } + public string? Acquisition { get; set; } + public string? Forestry { get; set; } + public string? ForestryFocus { get; set; } + public string? Sector { get; set; } + public string? SubSector { get; set; } + public string? ElectoralDistrict { get; set; } + public string? EconomicRegion { get; set; } + public string? RegionalDistrict { get; set; } + public string? ContactFullName { get; set; } + public string? ContactTitle { get; set; } + public string? ContactEmail { get; set; } + public string? ContactBusinessPhone { get; set; } + public string? ContactCellPhone { get; set; } + public string? SigningAuthorityFullName { get; set; } + public string? SigningAuthorityTitle { get; set; } + public string? SigningAuthorityEmail { get; set; } + public string? SigningAuthorityBusinessPhone { get; set; } + public string? SigningAuthorityCellPhone { get; set; } + public string? Place { get; set; } +} diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/Intakes/FormSubmissionSummaryDto.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/Intakes/FormSubmissionSummaryDto.cs index 7b553192f..b441a4e6d 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/Intakes/FormSubmissionSummaryDto.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/Intakes/FormSubmissionSummaryDto.cs @@ -53,4 +53,19 @@ public class FormSubmissionSummaryDto [JsonPropertyName("submissionDate")] public DateTime? SubmissionDate { get; set; } + + [JsonPropertyName("name")] + public string name { get; set; } = string.Empty; + + [JsonPropertyName("tenant")] + public string tenant { get; set; } = string.Empty; + + [JsonPropertyName("form")] + public string form { get; set; } = string.Empty; + + [JsonPropertyName("category")] + public string category { get; set; } = string.Empty; + + [JsonPropertyName("inUnity")] + public bool inUnity { get; set; } = false; } diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/Intakes/ISubmissionAppService.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/Intakes/ISubmissionAppService.cs index f2590f4c6..8962ab097 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/Intakes/ISubmissionAppService.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/Intakes/ISubmissionAppService.cs @@ -17,7 +17,7 @@ public interface ISubmissionAppService : IApplicationService /// ID of the form /// A list of form fields to search on. Refer to the related `versions/{formVersionId}/fields` endpoint for a list of valid values to query for. The list should be comma separated. /// List<FormSubmissionSummary> - Task> GetSubmissionsList(Guid? formId); + Task> GetSubmissionsList(bool allSubmissions); /// /// Get a form submission diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/Permissions/GrantApplications/GrantApplicationPermissionDefinitionProvider.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/Permissions/GrantApplications/GrantApplicationPermissionDefinitionProvider.cs index ceb051364..41852b750 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/Permissions/GrantApplications/GrantApplicationPermissionDefinitionProvider.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/Permissions/GrantApplications/GrantApplicationPermissionDefinitionProvider.cs @@ -45,6 +45,7 @@ public override void Define(IPermissionDefinitionContext context) // Applicant var applicatPermissions = grantApplicationPermissionsGroup.AddPermission(GrantApplicationPermissions.Applicants.Default, L("Permission:GrantApplicationManagement.Applicants.Default")); applicatPermissions.AddChild(GrantApplicationPermissions.Applicants.Edit, L("Permission:GrantApplicationManagement.Applicants.Edit")); + applicatPermissions.AddChild(GrantApplicationPermissions.Applicants.AssignApplicant, L("Permission:GrantApplicationManagement.Applicants.AssignApplicant")); // Assignment var assignmentPermissions = grantApplicationPermissionsGroup.AddPermission(GrantApplicationPermissions.Assignments.Default, L("Permission:GrantApplicationManagement.Assignments.Default")); @@ -58,6 +59,7 @@ public override void Define(IPermissionDefinitionContext context) // Approval var approvalPermissions = grantApplicationPermissionsGroup.AddPermission(GrantApplicationPermissions.Approvals.Default, L("Permission:GrantApplicationManagement.Approvals.Default")); approvalPermissions.AddChild(GrantApplicationPermissions.Approvals.Complete, L("Permission:GrantApplicationManagement.Approvals.Complete")); + approvalPermissions.AddChild(GrantApplicationPermissions.Approvals.DeferAfterApproval, L("Permission:GrantApplicationManagement.Approvals.DeferAfterApproval")); approvalPermissions.AddChild(GrantApplicationPermissions.Approvals.BulkApplicationApproval, L("Permission:GrantApplicationManagement.Approvals.BulkApplicationApproval")); // Comments @@ -67,19 +69,21 @@ public override void Define(IPermissionDefinitionContext context) //-- REVIEW & ASSESSMENT PERMISSIONS grantApplicationPermissionsGroup.AddApplication_ReviewAndAssessment_Permissions(); - // Applicant Info - var applicantInfoPermissions = grantApplicationPermissionsGroup.AddPermission(GrantApplicationPermissions.ApplicantInfo.Default, L($"Permission:{GrantApplicationPermissions.ApplicantInfo.Default}")); - applicantInfoPermissions.AddChild(GrantApplicationPermissions.ApplicantInfo.Update, L($"Permission:{GrantApplicationPermissions.ApplicantInfo.Update}")); + //-- APPLICANT INFO PERMISSIONS + grantApplicationPermissionsGroup.AddApplication_ApplicantInfo_Permissions(); // Project Info - var projectInfoPermissions = grantApplicationPermissionsGroup.AddPermission(GrantApplicationPermissions.ProjectInfo.Default, L("Permission:GrantApplicationManagement.ProjectInfo")); - var updateProjectInfoPermissions = projectInfoPermissions.AddChild(GrantApplicationPermissions.ProjectInfo.Update, L("Permission:GrantApplicationManagement.ProjectInfo.Update")); - updateProjectInfoPermissions.AddChild(GrantApplicationPermissions.ProjectInfo.UpdateFinalStateFields, L("Permission:GrantApplicationManagement.ProjectInfo.Update.UpdateFinalStateFields")); + grantApplicationPermissionsGroup.AddApplication_ProjectInfo_Permissions(); var settingManagement = context.GetGroup(SettingManagementPermissions.GroupName); settingManagement.AddPermission(UnitySettingManagementPermissions.UserInterface, L("Permission:UnitySettingManagementPermissions.UserInterface")); settingManagement.AddPermission(UnitySettingManagementPermissions.BackgroundJobSettings, L("Permission:UnitySettingManagementPermissions.BackgroundJobs")); + // Settings - Tag Management + var tagManagement = settingManagement.AddPermission(UnitySelector.SettingManagement.Tags.Default, L(UnitySelector.SettingManagement.Tags.Default)); + tagManagement.AddChild(UnitySelector.SettingManagement.Tags.Update, L(UnitySelector.SettingManagement.Tags.Update)); + tagManagement.AddChild(UnitySelector.SettingManagement.Tags.Delete, L(UnitySelector.SettingManagement.Tags.Delete)); + var emailingPermission = context.GetPermissionOrNull(SettingManagementPermissions.Emailing); if (emailingPermission != null) { @@ -123,25 +127,49 @@ public static void AddApplication_ReviewAndAssessment_Permissions(this Permissio var upx_Review_AssessmentResults_UpdateFinalStateFields = upx_Review_AssessmentResults_Update.AddUnityChild(UnitySelector.Review.AssessmentResults.Update.UpdateFinalStateFields); var upx_Review_AssessmentReviewList = upx_Review.AddUnityChild(UnitySelector.Review.AssessmentReviewList.Default); - var upx_Review_AssessmentReviewList_Create = upx_Review_AssessmentReviewList.AddUnityChild(UnitySelector.Review.AssessmentReviewList.Create); - - // Assessment Review Transitions are implied update functions but not in the update hierarchy at this time - // var upx_Review_AssessmentReviewList_Update = upx_Review_AssessmentReviewList.AddUnityChild(UnitySelector.Review.AssessmentReviewList.Update.Default); + var upx_Review_AssessmentReviewList_Create = upx_Review_AssessmentReviewList.AddUnityChild(UnitySelector.Review.AssessmentReviewList.Create); + var upx_Review_AssessmentReviewList_SendBack = upx_Review_AssessmentReviewList.AddUnityChild(UnitySelector.Review.AssessmentReviewList.Update.SendBack); var upx_Review_AssessmentReviewList_Complete = upx_Review_AssessmentReviewList.AddUnityChild(UnitySelector.Review.AssessmentReviewList.Update.Complete); + #endregion + } - //var upx_Review_Worksheet = upx_Review.AddUnityChild(UnitySelector.Review.Worksheet.Default); - //var upx_Review_Worksheet_Update = upx_Review_Worksheet.AddUnityChild(UnitySelector.Review.Worksheet.Update); + public static void AddApplication_ProjectInfo_Permissions(this PermissionGroupDefinition grantApplicationPermissionsGroup) + { + #region PROJECT INFO GRANULAR PERMISSIONS + var upx_Project = grantApplicationPermissionsGroup.AddPermission(UnitySelector.Project.Default, L(UnitySelector.Project.Default)); + + var upx_Project_Summary = upx_Project.AddUnityChild(UnitySelector.Project.Summary.Default); + var upx_Project_Summary_Update = upx_Project_Summary.AddUnityChild(UnitySelector.Project.Summary.Update.Default); + var upx_Project_Summary_UpdateFinalStateFields = upx_Project_Summary_Update.AddUnityChild(UnitySelector.Project.Summary.Update.UpdateFinalStateFields); + + var upx_Project_Location = upx_Project.AddUnityChild(UnitySelector.Project.Location.Default); + var upx_Project_Location_Update = upx_Project_Location.AddUnityChild(UnitySelector.Project.Location.Update.Default); + var upx_Project_Location_UpdateFinalStateFields = upx_Project_Location_Update.AddUnityChild(UnitySelector.Project.Location.Update.UpdateFinalStateFields); #endregion + } - // Available Permission Hooks - // var upx_Review_Approval_Create = upx_Review_Approval.AddUnityChild(UnitySelector.Review.Approval.Create); - // var upx_Review_Approval_Delete = upx_Review_Approval.AddUnityChild(UnitySelector.Review.Approval.Delete); - // var upx_Review_AssessmentResults_Create = upx_Review_AssessmentResults.AddUnityChild(UnitySelector.Review.AssessmentResults.Create); - // var upx_Review_AssessmentResults_Delete = upx_Review_AssessmentResults.AddUnityChild(UnitySelector.Review.AssessmentResults.Delete); - // var upx_Review_AssessmentReviewList_Delete = upx_Review_AssessmentReviewList.AddUnityChild(UnitySelector.Review.AssessmentReviewList.Delete); - // var upx_Review_Worksheet_Create = upx_Review_Worksheet.AddUnityChild(UnitySelector.Review.Worksheet.Create); - // var upx_Review_Worksheet_Delete = upx_Review_Worksheet.AddUnityChild(UnitySelector.Review.Worksheet.Delete); + public static void AddApplication_ApplicantInfo_Permissions(this PermissionGroupDefinition grantApplicationPermissionsGroup) + { + #region APPLICANT INFO GRANULAR PERMISSIONS + var upx_Applicant = grantApplicationPermissionsGroup.AddPermission(UnitySelector.Applicant.Default, L(UnitySelector.Applicant.Default)); + + var upx_Applicant_Summary = upx_Applicant.AddUnityChild(UnitySelector.Applicant.Summary.Default); + var upx_Applicant_Summary_Update = upx_Applicant_Summary.AddUnityChild(UnitySelector.Applicant.Summary.Update); + + var upx_Applicant_Contact = upx_Applicant.AddUnityChild(UnitySelector.Applicant.Contact.Default); + var upx_Applicant_Contact_Update = upx_Applicant_Contact.AddUnityChild(UnitySelector.Applicant.Contact.Update); + + var upx_Applicant_Authority = upx_Applicant.AddUnityChild(UnitySelector.Applicant.Authority.Default); + var upx_Applicant_Authority_Update = upx_Applicant_Authority.AddUnityChild(UnitySelector.Applicant.Authority.Update); + + var upx_Applicant_Location = upx_Applicant.AddUnityChild(UnitySelector.Applicant.Location.Default); + var upx_Applicant_Location_Update = upx_Applicant_Location.AddUnityChild(UnitySelector.Applicant.Location.Update); + + var upx_Applicant_AdditionalContact = upx_Applicant.AddUnityChild(UnitySelector.Applicant.AdditionalContact.Default); + var upx_Applicant_AdditionalContact_Create = upx_Applicant_AdditionalContact.AddUnityChild(UnitySelector.Applicant.AdditionalContact.Create); + var upx_Applicant_AdditionalContact_Update = upx_Applicant_AdditionalContact.AddUnityChild(UnitySelector.Applicant.AdditionalContact.Update); + #endregion } public static PermissionDefinition AddUnityChild(this PermissionDefinition parent, string name) diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Applicants/ApplicantAppService.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Applicants/ApplicantAppService.cs index 56c537b6a..e038b3a66 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Applicants/ApplicantAppService.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Applicants/ApplicantAppService.cs @@ -1,22 +1,23 @@ -using System.Threading.Tasks; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Abstractions; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using System.Text.Json; using Unity.GrantManager.Applications; -using Volo.Abp.DependencyInjection; +using Unity.GrantManager.GrantApplications; using Unity.GrantManager.Intakes; -using System; using Unity.GrantManager.Intakes.Mapping; -using Unity.GrantManager.GrantApplications; -using Unity.Payments.Events; -using Volo.Abp; -using System.Collections.Generic; using Unity.GrantManager.Integration.Orgbook; -using Newtonsoft.Json.Linq; -using System.Linq; using Unity.Modules.Shared.Utils; -using Microsoft.Extensions.Logging; +using Unity.Payments.Domain.Suppliers; +using Unity.Payments.Events; using Unity.Payments.Integrations.Cas; -using Microsoft.Extensions.Logging.Abstractions; using Unity.Payments.Suppliers; -using Unity.Payments.Domain.Suppliers; +using Volo.Abp; +using Volo.Abp.DependencyInjection; namespace Unity.GrantManager.Applicants; @@ -28,7 +29,8 @@ public class ApplicantAppService(IApplicantRepository applicantRepository, ISiteAppService siteAppService, IApplicantAddressRepository addressRepository, IOrgBookService orgBookService, - IApplicantAgentRepository applicantAgentRepository) : GrantManagerAppService, IApplicantAppService + IApplicantAgentRepository applicantAgentRepository, + IApplicationRepository applicationRepository) : GrantManagerAppService, IApplicantAppService { protected new ILogger Logger => LazyServiceProvider.LazyGetService(provider => LoggerFactory?.CreateLogger(GetType().FullName!) ?? NullLogger.Instance); @@ -43,6 +45,7 @@ public async Task CreateOrRetrieveApplicantAsync(IntakeMapping intake applicant = await CreateNewApplicantAsync(intakeMap); } else { applicant.ApplicantName = MappingUtil.ResolveAndTruncateField(600, string.Empty, intakeMap.ApplicantName) ?? applicant.ApplicantName; + applicant.ElectoralDistrict = intakeMap.ElectoralDistrict ?? applicant.ElectoralDistrict; applicant.NonRegisteredBusinessName = intakeMap.NonRegisteredBusinessName ?? applicant.NonRegisteredBusinessName; applicant.OrgName = intakeMap.OrgName ?? applicant.OrgName; applicant.OrgNumber = intakeMap.OrgNumber ?? applicant.OrgNumber; @@ -163,16 +166,46 @@ public async Task MatchApplicantOrgNamesAsync() [RemoteService(true)] public async Task GetNextUnityApplicantIdAsync() { - List applicants = await applicantRepository.GetApplicantsWithUnityApplicantIdAsync(); - // Convert UnityApplicantId to int, filter only valid numbers - var unityIds = applicants - .Where(a => int.TryParse(a.UnityApplicantId, out _)) // Ensure it's numeric - .Select(a => int.Parse(a.UnityApplicantId!)) + // Finds the first available Unity Applicant ID, starting from 100000. + var applicantQuery = await applicantRepository.GetQueryableAsync(); + + var relevantUnityIds = await applicantQuery + .Where(a => a.UnityApplicantId != null) + .Select(a => new { UnityApplicantId = a.UnityApplicantId, ParsedId = (int?)null }) + .ToListAsync(); + + var updatedRelevantUnityIds = relevantUnityIds + .Select(item => + { + if (int.TryParse(item.UnityApplicantId, out var parsedId) && parsedId >= 100000) + { + return new { UnityApplicantId = item.UnityApplicantId ?? string.Empty, ParsedId = (int?)parsedId }; + } + return new { UnityApplicantId = item.UnityApplicantId ?? string.Empty, ParsedId = item.ParsedId }; + }) + .ToList(); + + var orderedIds = updatedRelevantUnityIds + .Where(a => a.ParsedId.HasValue) + .Select(a => a.ParsedId!.Value) // Use the null-forgiving operator (!) to assert that ParsedId is not null + .OrderBy(id => id) .ToList(); - int nextId = unityIds.Count > 0 ? unityIds.Max() + 1 : 000001; + int candidate = 100000; // Starting ID for availability search. + + foreach (var id in orderedIds) + { + if (id == candidate) + { + candidate++; + } + else // Gap found: candidate is the first available ID. + { + break; + } + } - return nextId; + return candidate; } [RemoteService(true)] @@ -188,40 +221,37 @@ public async Task UpdateApplicantOrgMatchAsync(Applicant applicant) { string? orgbookLookup = string.IsNullOrEmpty(applicant.OrgNumber) ? applicant.ApplicantName : applicant.OrgNumber; if (string.IsNullOrEmpty(orgbookLookup)) return applicant; - - JObject? result = await orgBookService.GetOrgBookQueryAsync(orgbookLookup); - var orgData = result?.SelectToken("results")?.Children().FirstOrDefault(); - if (orgData == null) return applicant; - + // Use the built-in System.Text.Json API + using JsonDocument result = await orgBookService.GetOrgBookAutocompleteQueryAsync(orgbookLookup); + if (!result.RootElement.TryGetProperty("results", out JsonElement results) || + results.GetArrayLength() == 0) + return applicant; + JsonElement orgData = results[0]; await UpdateApplicantOrgNumberAsync(applicant, orgData); - await UpdateApplicantNamesAsync(applicant, orgData.SelectToken("names")?.Children()); + await UpdateApplicantNamesAsync(applicant, orgData.GetProperty("names").EnumerateArray()); } catch (Exception ex) { Logger.LogInformation(ex, "UpdateApplicantOrgMatchAsync: Exception: {ExceptionMessage}", ex.Message); } - return applicant; } - private async Task UpdateApplicantOrgNumberAsync(Applicant applicant, JToken orgData) + private async Task UpdateApplicantOrgNumberAsync(Applicant applicant, JsonElement orgData) { - var orgNumber = orgData.SelectToken("source_id"); - if (applicant.OrgNumber == null && orgNumber != null) + if (orgData.TryGetProperty("source_id", out JsonElement orgNumberElement) && applicant.OrgNumber == null) { - applicant.OrgNumber = orgNumber.ToString(); + applicant.OrgNumber = orgNumberElement.GetString(); await applicantRepository.UpdateAsync(applicant); } } - private async Task UpdateApplicantNamesAsync(Applicant applicant, IEnumerable? namesChildren) + private async Task UpdateApplicantNamesAsync(Applicant applicant, IEnumerable namesChildren) { - if (namesChildren == null) return; - foreach (var name in namesChildren) { - string nameType = name.SelectToken("type")?.ToString() ?? string.Empty; - string nameText = name.SelectToken("text")?.ToString() ?? string.Empty; + string nameType = name.TryGetProperty("type", out JsonElement typeEl) ? typeEl.GetString() ?? string.Empty : string.Empty; + string nameText = name.TryGetProperty("text", out JsonElement textEl) ? textEl.GetString() ?? string.Empty : string.Empty; if (nameType == "entity_name") { @@ -248,6 +278,7 @@ private async Task CreateNewApplicantAsync(IntakeMapping intakeMap) var applicant = new Applicant { ApplicantName = MappingUtil.ResolveAndTruncateField(600, string.Empty, intakeMap.ApplicantName), + ElectoralDistrict = intakeMap.ElectoralDistrict, NonRegisteredBusinessName = intakeMap.NonRegisteredBusinessName, OrgName = intakeMap.OrgName, OrgNumber = intakeMap.OrgNumber, @@ -310,5 +341,120 @@ public async Task> GetApplicantsBySiteIdAsync(Guid siteId) List applicants = await applicantRepository.GetApplicantsBySiteIdAsync(siteId); return applicants; } + [RemoteService(true)] + public async Task GetApplicantLookUpAutocompleteQueryAsync(string? applicantLookUpQuery) + { + JsonDocument result = await applicantRepository.GetApplicantAutocompleteQueryAsync(applicantLookUpQuery); + return result; + } + [RemoteService(true)] + public async Task UpdateApplicantIdAsync(UpdateApplicantIdDto dto) + { + // Validate input + if (dto == null) + { + Logger.LogWarning("UpdateApplicantIdAsync called with null dto."); + return; + } + + //Update Application + var application = await applicationRepository.GetAsync(dto.ApplicationId); + if (application == null) + { + Logger.LogWarning("Application not found for ApplicationId: {ApplicationId}", dto.ApplicationId); + return; + } + + var oldApplicantId = application.ApplicantId; + if (oldApplicantId == dto.ApplicantId) + { + Logger.LogInformation("ApplicantId is already set to the requested value. No update required."); + return; + } + + application.ApplicantId = dto.ApplicantId; + await applicationRepository.UpdateAsync(application); + + //Update ApplicationFormSubmissions + await UpdateApplicationFormSubmissionsAsync(dto.ApplicationId, dto.ApplicantId); + + //Update ApplicantAgent records + await UpdateApplicantAgentRecordsAsync(oldApplicantId, dto.ApplicantId, dto.ApplicationId); + } + + [RemoteService(true)] + public async Task SetDuplicatedAsync(SetApplicantDuplicateDto dto) + { + // Set principal as not duplicated + var principal = await applicantRepository.GetAsync(dto.PrincipalApplicantId); + if (principal != null && principal.IsDuplicated != false) + { + principal.IsDuplicated = false; + await applicantRepository.UpdateAsync(principal); + } + + // Set non-principal as duplicated + var nonPrincipal = await applicantRepository.GetAsync(dto.NonPrincipalApplicantId); + if (nonPrincipal != null && nonPrincipal.IsDuplicated != true) + { + nonPrincipal.IsDuplicated = true; + await applicantRepository.UpdateAsync(nonPrincipal); + } + } + + private async Task UpdateApplicationFormSubmissionsAsync(Guid applicationId, Guid newApplicantId) + { + try + { + var formSubmissionRepository = LazyServiceProvider.LazyGetRequiredService(); + var formSubmissions = await (await formSubmissionRepository.GetQueryableAsync()) + .Where(s => s.ApplicationId == applicationId) + .ToListAsync(); + + foreach (var submission in formSubmissions) + { + submission.ApplicantId = newApplicantId; + await formSubmissionRepository.UpdateAsync(submission); + } + } + catch (Exception ex) + { + Logger.LogError(ex, "Error updating ApplicationFormSubmissions for ApplicationId: {ApplicationId}", applicationId); + throw new UserFriendlyException("An error occurred while updating application form submissions."); + } + } + + private async Task UpdateApplicantAgentRecordsAsync(Guid oldApplicantId, Guid newApplicantId, Guid applicationId) + { + try + { + var agentQueryable = await applicantAgentRepository.GetQueryableAsync(); + + // Detach old agent from application + var oldAgent = await agentQueryable + .FirstOrDefaultAsync(a => a.ApplicantId == oldApplicantId && a.ApplicationId == applicationId); + + if (oldAgent != null) + { + oldAgent.ApplicationId = null; + await applicantAgentRepository.UpdateAsync(oldAgent); + } + + // Attach new agent to application + var newAgent = await agentQueryable + .FirstOrDefaultAsync(a => a.ApplicantId == newApplicantId); + + if (newAgent != null) + { + newAgent.ApplicationId = applicationId; + await applicantAgentRepository.UpdateAsync(newAgent); + } + } + catch (Exception ex) + { + Logger.LogError(ex, "Error updating ApplicantAgent records for ApplicationId: {ApplicationId}", applicationId); + throw new UserFriendlyException("An error occurred while updating applicant agent records."); + } + } } \ No newline at end of file diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Applicants/ApplicantSupplierAppService.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Applicants/ApplicantSupplierAppService.cs index 3cbcdd0fb..358d2f400 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Applicants/ApplicantSupplierAppService.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Applicants/ApplicantSupplierAppService.cs @@ -1,72 +1,96 @@ -using System.Threading.Tasks; -using Unity.GrantManager.Applications; -using Volo.Abp.DependencyInjection; -using System; -using Unity.Payments.Suppliers; -using Unity.Modules.Shared.Correlation; -using System.Collections.Generic; -using Unity.Payments.Domain.Suppliers; -using Microsoft.AspNetCore.Mvc; -using Unity.Payments.Integrations.Cas; - -namespace Unity.GrantManager.Applicants; - - -[Dependency(ReplaceServices = true)] -[ExposeServices(typeof(ApplicantSupplierAppService), typeof(IApplicantSupplierAppService))] -public class ApplicantSupplierAppService(ISiteRepository siteRepository, - IApplicantRepository applicantRepository, - ISupplierService supplierService, - ISupplierAppService supplierAppService) : GrantManagerAppService, IApplicantSupplierAppService -{ - - public async Task> GetSitesBySupplierIdAsync(Guid supplierId) - { - return await siteRepository.GetBySupplierAsync(supplierId); - } - - public async Task GetSupplierByNumber(string supplierNumber) - { - return await supplierService.GetCasSupplierInformationAsync(supplierNumber); - } - - public async Task GetSupplierByBusinessNumber(string bn9) - { - return await supplierService.GetCasSupplierInformationByBn9Async(bn9); - } - - [HttpPut("api/app/applicant/{applicantId}/bn9/{bn9}")] - public async Task UpdateAplicantSupplierByBn9Async(Guid applicantId, string bn9) - { - return await supplierService.UpdateApplicantSupplierInfoByBn9(bn9, applicantId); - } - - [HttpPost("api/app/applicant/{applicantId}/site/{siteId}")] - public async Task DefaultApplicantSite(Guid applicantId, Guid siteId) - { - Applicant applicant = await applicantRepository.GetAsync(applicantId); - applicant.SiteId = siteId; - await applicantRepository.UpdateAsync(applicant); - } - - public async Task GetSupplierByApplicantIdAsync(Guid applicantId) - { - - Applicant applicant = await applicantRepository.GetAsync(applicantId); - - //If SupplierId is available, use it to get the supplier - if (applicant.SupplierId.HasValue) - { - Guid supplierId = applicant.SupplierId.Value; - return await supplierAppService.GetAsync(supplierId); - } - - // If no SupplierId, fetch the supplier using the correlation - return await supplierAppService.GetByCorrelationAsync(new GetSupplierByCorrelationDto() - { - CorrelationId = applicantId, - CorrelationProvider = CorrelationConsts.Applicant, - IncludeDetails = true - }); - } +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using Unity.GrantManager.Applications; +using Unity.GrantManager.Payments; +using Unity.Modules.Shared.Correlation; +using Unity.Payments.Domain.Suppliers; +using Unity.Payments.Integrations.Cas; +using Unity.Payments.Permissions; +using Unity.Payments.Suppliers; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Domain.Repositories; + +namespace Unity.GrantManager.Applicants; + + +[Dependency(ReplaceServices = true)] +[ExposeServices(typeof(ApplicantSupplierAppService), typeof(IApplicantSupplierAppService))] +public class ApplicantSupplierAppService(ISiteRepository siteRepository, + IApplicantRepository applicantRepository, + ISupplierService supplierService, + ISupplierAppService supplierAppService) : GrantManagerAppService, IApplicantSupplierAppService +{ + + public async Task> GetSitesBySupplierIdAsync(Guid supplierId) + { + return await siteRepository.GetBySupplierAsync(supplierId); + } + + public async Task GetSupplierByNumber(string supplierNumber) + { + return await supplierService.GetCasSupplierInformationAsync(supplierNumber); + } + + public async Task GetSupplierByBusinessNumber(string bn9) + { + return await supplierService.GetCasSupplierInformationByBn9Async(bn9); + } + + /// + /// Update the supplier number for the applicant regardless of application. + /// + [Authorize(PaymentsPermissions.Payments.EditSupplierInfo)] + public async Task UpdateApplicantSupplierNumberAsync(Guid applicantId, string supplierNumber) + { + if (await FeatureChecker.IsEnabledAsync(PaymentConsts.UnityPaymentsFeature) && !string.IsNullOrEmpty(supplierNumber)) + { + await applicantRepository.EnsureExistsAsync(applicantId); + var supplier = await GetSupplierByApplicantIdAsync(applicantId); + + if (supplier != null && string.Compare(supplierNumber, supplier?.Number, true) == 0) + { + return; // No change in supplier number, so no action needed + } + + await supplierService.UpdateApplicantSupplierInfo(supplierNumber, applicantId); + } + } + + [HttpPut("api/app/applicant/{applicantId}/bn9/{bn9}")] + public async Task UpdateAplicantSupplierByBn9Async(Guid applicantId, string bn9) + { + return await supplierService.UpdateApplicantSupplierInfoByBn9(bn9, applicantId); + } + + [HttpPost("api/app/applicant/{applicantId}/site/{siteId}")] + public async Task DefaultApplicantSite(Guid applicantId, Guid siteId) + { + Applicant applicant = await applicantRepository.GetAsync(applicantId); + applicant.SiteId = siteId; + await applicantRepository.UpdateAsync(applicant); + } + + public async Task GetSupplierByApplicantIdAsync(Guid applicantId) + { + + Applicant applicant = await applicantRepository.GetAsync(applicantId); + + //If SupplierId is available, use it to get the supplier + if (applicant.SupplierId.HasValue) + { + Guid supplierId = applicant.SupplierId.Value; + return await supplierAppService.GetAsync(supplierId); + } + + // If no SupplierId, fetch the supplier using the correlation + return await supplierAppService.GetByCorrelationAsync(new GetSupplierByCorrelationDto() + { + CorrelationId = applicantId, + CorrelationProvider = CorrelationConsts.Applicant, + IncludeDetails = true + }); + } } \ No newline at end of file diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Applicants/IApplicantAppService.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Applicants/IApplicantAppService.cs index 49b917ead..416bb7c50 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Applicants/IApplicantAppService.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Applicants/IApplicantAppService.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Text.Json; using System.Threading.Tasks; using Unity.GrantManager.Applications; using Unity.GrantManager.Intakes; @@ -17,4 +18,5 @@ public interface IApplicantAppService : IApplicationService Task UpdateApplicantOrgMatchAsync(Applicant applicant); Task GetNextUnityApplicantIdAsync(); Task> GetApplicantsBySiteIdAsync(Guid siteId); + Task GetApplicantLookUpAutocompleteQueryAsync(string? applicantLookUpQuery); } diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Applicants/IApplicantSupplierAppService.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Applicants/IApplicantSupplierAppService.cs index e34936e85..0fa9f816e 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Applicants/IApplicantSupplierAppService.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Applicants/IApplicantSupplierAppService.cs @@ -1,16 +1,17 @@ -using System; -using System.Collections.Generic; -using System.Threading.Tasks; -using Unity.Payments.Domain.Suppliers; -using Unity.Payments.Suppliers; -using Volo.Abp.Application.Services; - -namespace Unity.GrantManager.Applicants; - -public interface IApplicantSupplierAppService : IApplicationService -{ - Task GetSupplierByNumber(string supplierNumber); - Task GetSupplierByApplicantIdAsync(Guid applicantId); - Task> GetSitesBySupplierIdAsync(Guid supplierId); - Task UpdateAplicantSupplierByBn9Async(Guid applicantId, string bn9); -} +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using Unity.Payments.Domain.Suppliers; +using Unity.Payments.Suppliers; +using Volo.Abp.Application.Services; + +namespace Unity.GrantManager.Applicants; + +public interface IApplicantSupplierAppService : IApplicationService +{ + Task GetSupplierByNumber(string supplierNumber); + Task GetSupplierByApplicantIdAsync(Guid applicantId); + Task> GetSitesBySupplierIdAsync(Guid supplierId); + Task UpdateApplicantSupplierNumberAsync(Guid applicantId, string supplierNumber); + Task UpdateAplicantSupplierByBn9Async(Guid applicantId, string bn9); +} diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Applicants/SetApplicantDuplicateDto.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Applicants/SetApplicantDuplicateDto.cs new file mode 100644 index 000000000..48a5d0105 --- /dev/null +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Applicants/SetApplicantDuplicateDto.cs @@ -0,0 +1,10 @@ +using System; + +namespace Unity.GrantManager.Applicants +{ + public class SetApplicantDuplicateDto + { + public Guid PrincipalApplicantId { get; set; } + public Guid NonPrincipalApplicantId { get; set; } + } +} diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Applicants/UpdateApplicantIdDto.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Applicants/UpdateApplicantIdDto.cs new file mode 100644 index 000000000..81df66fd4 --- /dev/null +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Applicants/UpdateApplicantIdDto.cs @@ -0,0 +1,10 @@ +using System; + +namespace Unity.GrantManager.Applicants +{ + public class UpdateApplicantIdDto + { + public Guid ApplicationId { get; set; } + public Guid ApplicantId { get; set; } + } +} 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 bffa9a3d1..edcfb9c80 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/ApplicationForms/ApplicationFormAppService.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/ApplicationForms/ApplicationFormAppService.cs @@ -6,6 +6,7 @@ using System.Threading.Tasks; using Unity.GrantManager.Applications; using Unity.GrantManager.Forms; +using Unity.GrantManager.GrantApplications; using Unity.GrantManager.Integration.Chefs; using Unity.GrantManager.Permissions; using Volo.Abp; @@ -14,128 +15,144 @@ using Volo.Abp.Domain.Repositories; using Volo.Abp.Security.Encryption; -namespace Unity.GrantManager.ApplicationForms +namespace Unity.GrantManager.ApplicationForms; + +[Authorize] +public class ApplicationFormAppService : +CrudAppService< + ApplicationForm, + ApplicationFormDto, + Guid, + PagedAndSortedResultRequestDto, + CreateUpdateApplicationFormDto>, + IApplicationFormAppService { - [Authorize(GrantManagerPermissions.ApplicationForms.Default)] - public class ApplicationFormAppService : - CrudAppService< - ApplicationForm, - ApplicationFormDto, - Guid, - PagedAndSortedResultRequestDto, - CreateUpdateApplicationFormDto>, - IApplicationFormAppService + private readonly IStringEncryptionService _stringEncryptionService; + private readonly IFormsApiService _formsApiService; + private readonly IApplicationFormVersionAppService _applicationFormVersionAppService; + private readonly IApplicationFormVersionRepository _applicationFormVersionRepository; + private readonly IRepository _applicationFormRepository; + public ApplicationFormAppService(IRepository repository, + IStringEncryptionService stringEncryptionService, + IApplicationFormVersionAppService applicationFormVersionAppService, + IApplicationFormVersionRepository applicationFormVersionRepository, + IFormsApiService formsApiService) + : base(repository) { - private readonly IStringEncryptionService _stringEncryptionService; - private readonly IFormsApiService _formsApiService; - private readonly IApplicationFormVersionAppService _applicationFormVersionAppService; - private readonly IApplicationFormVersionRepository _applicationFormVersionRepository; - private readonly IRepository _applicationFormRepository; - public ApplicationFormAppService(IRepository repository, - IStringEncryptionService stringEncryptionService, - IApplicationFormVersionAppService applicationFormVersionAppService, - IApplicationFormVersionRepository applicationFormVersionRepository, - IFormsApiService formsApiService) - : base(repository) - { - _stringEncryptionService = stringEncryptionService; - _applicationFormVersionAppService = applicationFormVersionAppService; - _formsApiService = formsApiService; - _applicationFormVersionRepository = applicationFormVersionRepository; - _applicationFormRepository = repository; - } + _stringEncryptionService = stringEncryptionService; + _applicationFormVersionAppService = applicationFormVersionAppService; + _formsApiService = formsApiService; + _applicationFormVersionRepository = applicationFormVersionRepository; + _applicationFormRepository = repository; + } - public override async Task CreateAsync(CreateUpdateApplicationFormDto input) - { - input.ApiKey = _stringEncryptionService.Encrypt(input.ApiKey); - ApplicationFormDto applicationFormDto = await base.CreateAsync(input); - return await InitializeFormVersion(applicationFormDto.Id, input); - } + [Authorize(GrantManagerPermissions.ApplicationForms.Default)] + public override async Task CreateAsync(CreateUpdateApplicationFormDto input) + { + input.ApiKey = _stringEncryptionService.Encrypt(input.ApiKey); + ApplicationFormDto applicationFormDto = await base.CreateAsync(input); + return await InitializeFormVersion(applicationFormDto.Id, input); + } - public override async Task UpdateAsync(Guid id, CreateUpdateApplicationFormDto input) - { - var existingForm = await Repository.GetAsync(id); - input.ApiKey = _stringEncryptionService.Encrypt(input.ApiKey); + [Authorize(GrantManagerPermissions.ApplicationForms.Default)] + public override async Task UpdateAsync(Guid id, CreateUpdateApplicationFormDto input) + { + var existingForm = await Repository.GetAsync(id); + input.ApiKey = _stringEncryptionService.Encrypt(input.ApiKey); - bool hasFormGuidChanged = existingForm.ChefsApplicationFormGuid != input.ChefsApplicationFormGuid; - bool hasFormApiKeyChanged = existingForm.ApiKey != input.ApiKey; + bool hasFormGuidChanged = existingForm.ChefsApplicationFormGuid != input.ChefsApplicationFormGuid; + bool hasFormApiKeyChanged = existingForm.ApiKey != input.ApiKey; - // Only initialize form version if changes are made to form connection details - if (hasFormGuidChanged || hasFormApiKeyChanged) - { - return await InitializeFormVersion(id, input); - } - else - { - return await base.UpdateAsync(id, input); - } + // Only initialize form version if changes are made to form connection details + if (hasFormGuidChanged || hasFormApiKeyChanged) + { + return await InitializeFormVersion(id, input); + } + else + { + return await base.UpdateAsync(id, input); } + } - private async Task InitializeFormVersion(Guid id, CreateUpdateApplicationFormDto input) + [Authorize(GrantManagerPermissions.ApplicationForms.Default)] + private async Task InitializeFormVersion(Guid id, CreateUpdateApplicationFormDto input) + { + var applicationFormDto = new ApplicationFormDto(); + try { - var applicationFormDto = new ApplicationFormDto(); - try + if (input.ChefsApplicationFormGuid != null && input.ApiKey != null) { - if (input.ChefsApplicationFormGuid != null && input.ApiKey != null) + dynamic form = await _formsApiService.GetForm(Guid.Parse(input.ChefsApplicationFormGuid), input.ChefsApplicationFormGuid.ToString(), input.ApiKey); + if (form != null) { - dynamic form = await _formsApiService.GetForm(Guid.Parse(input.ChefsApplicationFormGuid), input.ChefsApplicationFormGuid.ToString(), input.ApiKey); - if (form != null) + JObject formObject = JObject.Parse(form.ToString()); + var formName = formObject.SelectToken("name"); + if (formName != null) { - JObject formObject = JObject.Parse(form.ToString()); - var formName = formObject.SelectToken("name"); - if (formName != null) - { - input.ApplicationFormName = formName.ToString(); - applicationFormDto = await base.UpdateAsync(id, input); - } - bool initializePublishedOnly = false; - await _applicationFormVersionAppService.InitializePublishedFormVersion(form, id, initializePublishedOnly); + input.ApplicationFormName = formName.ToString(); + applicationFormDto = await base.UpdateAsync(id, input); } + bool initializePublishedOnly = false; + await _applicationFormVersionAppService.InitializePublishedFormVersion(form, id, initializePublishedOnly); } - return applicationFormDto; - } - catch (Exception ex) - { - throw new UserFriendlyException("Exception: " + ex.Message + "\n\r Please check the CHEFS Form ID and CHEFS Form API Key"); } - + return applicationFormDto; } - - public override async Task GetAsync(Guid id) + catch (Exception ex) { - var dto = await base.GetAsync(id); - dto.ApiKey = _stringEncryptionService.Decrypt(dto.ApiKey); - dto.ApiToken = _stringEncryptionService.Decrypt(dto.ApiToken); - return dto; + throw new UserFriendlyException("Exception: " + ex.Message + "\n\r Please check the CHEFS Form ID and CHEFS Form API Key"); } - public async Task> GetPublishedVersionsAsync(Guid id) - { - IQueryable queryableFormVersions = _applicationFormVersionRepository.GetQueryableAsync().Result; - var formVersions = queryableFormVersions.Where(c => c.ApplicationFormId.Equals(id) && c.Published.Equals(true)).ToList(); - return await Task.FromResult>(ObjectMapper.Map, List>(formVersions.OrderByDescending(s => s.Version).ToList())); - } + } - public async Task> GetVersionsAsync(Guid id) - { - IQueryable queryableFormVersions = _applicationFormVersionRepository.GetQueryableAsync().Result; - var formVersions = queryableFormVersions.Where(c => c.ApplicationFormId.Equals(id)).ToList(); - return await Task.FromResult>(ObjectMapper.Map, List>(formVersions.OrderByDescending(s => s.Version).ToList())); - } + [Authorize(GrantManagerPermissions.ApplicationForms.Default)] + public override async Task GetAsync(Guid id) + { + var dto = await base.GetAsync(id); + dto.ApiKey = _stringEncryptionService.Decrypt(dto.ApiKey); + dto.ApiToken = _stringEncryptionService.Decrypt(dto.ApiToken); + return dto; + } - public async Task SaveApplicationFormScoresheet(FormScoresheetDto dto) - { - var appForm = await _applicationFormRepository.GetAsync(dto.ApplicationFormId); - appForm.ScoresheetId = dto.ScoresheetId; - await _applicationFormRepository.UpdateAsync(appForm); - } + [Authorize] + public async Task GetElectoralDistrictAddressTypeAsync(Guid id) + { + var applicationFormDto = await base.GetAsync(id); + return applicationFormDto?.ElectoralDistrictAddressType ?? ApplicationForm.GetDefaultElectoralDistrictAddressType(); + } - public async Task UpdateOtherConfig(Guid id, OtherConfigDto config) - { - var appForm = await _applicationFormRepository.GetAsync(id); - appForm.IsDirectApproval = config.IsDirectApproval; - await _applicationFormRepository.UpdateAsync(appForm); - return ObjectMapper.Map(appForm); - } + [Authorize(GrantManagerPermissions.ApplicationForms.Default)] + public async Task> GetPublishedVersionsAsync(Guid id) + { + IQueryable queryableFormVersions = _applicationFormVersionRepository.GetQueryableAsync().Result; + var formVersions = queryableFormVersions.Where(c => c.ApplicationFormId.Equals(id) && c.Published.Equals(true)).ToList(); + return await Task.FromResult>(ObjectMapper.Map, List>(formVersions.OrderByDescending(s => s.Version).ToList())); + } + + [Authorize(GrantManagerPermissions.ApplicationForms.Default)] + public async Task> GetVersionsAsync(Guid id) + { + IQueryable queryableFormVersions = _applicationFormVersionRepository.GetQueryableAsync().Result; + var formVersions = queryableFormVersions.Where(c => c.ApplicationFormId.Equals(id)).ToList(); + return await Task.FromResult>(ObjectMapper.Map, List>(formVersions.OrderByDescending(s => s.Version).ToList())); } + + [Authorize(GrantManagerPermissions.ApplicationForms.Default)] + public async Task SaveApplicationFormScoresheet(FormScoresheetDto dto) + { + var appForm = await _applicationFormRepository.GetAsync(dto.ApplicationFormId); + appForm.ScoresheetId = dto.ScoresheetId; + await _applicationFormRepository.UpdateAsync(appForm); + } + + [Authorize(GrantManagerPermissions.ApplicationForms.Default)] + public async Task PatchOtherConfig(Guid id, OtherConfigDto config) + { + var form = await _applicationFormRepository.GetAsync(id); + + form.IsDirectApproval = config.IsDirectApproval; + form.ElectoralDistrictAddressType = config.ElectoralDistrictAddressType; + + await _applicationFormRepository.UpdateAsync(form); + } } diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/ApplicationForms/ApplicationFormSycnronizationService.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/ApplicationForms/ApplicationFormSycnronizationService.cs index f0265e1f6..af5911b1d 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/ApplicationForms/ApplicationFormSycnronizationService.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/ApplicationForms/ApplicationFormSycnronizationService.cs @@ -171,9 +171,11 @@ private async Task ProcessSubmission(ApplicationFormDto applicationFormDto, JObj AddFact("Synchronizing Data - Form Version: ", $"{version} Unity Application ID: {result}"); } - public async Task> GetMissingSubmissions(int numberOfDaysToCheck) + public async Task<(HashSet MissingSubmissions, string MissingSubmissionsReport)> GetMissingSubmissions(int numberOfDaysToCheck) { _facts = new List(); + var missingSubmissionsReportBuilder = new System.Text.StringBuilder(); + int missingSubmissionsCounter = 1; HashSet missingSubmissions = new HashSet(); // Get all forms with api keys @@ -200,6 +202,13 @@ public async Task> GetMissingSubmissions(int numberOfDaysToCheck AddFact("------------------------------------", "----------------------------------------"); AddFact("Application Form Name: ", applicationFormDto.ApplicationFormName ?? string.Empty); AddFact("Missing Submissions Count: ", missingSubmissions.Count.ToString()); + + foreach (string submissionId in missingSubmissions) + { + missingSubmissionsReportBuilder.AppendLine($"{missingSubmissionsCounter}-{applicationFormDto.ApplicationFormName}-{submissionId}
"); + missingSubmissionsCounter++; + } + await SynchronizeFormSubmissions(missingSubmissions, applicationFormDto); } } @@ -222,13 +231,16 @@ public async Task> GetMissingSubmissions(int numberOfDaysToCheck AddFact("Total Missing Submissions Count: ", missingSubmissionsCount.ToString()); } - string tenantName = await GetTenantNameAsync() ?? ""; - string? envInfo = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT"); - string activityTitle = "Review Missed Chefs Submissions " + tenantName; - string activitySubtitle = "Environment: " + envInfo; - string teamsChannel = _configuration["Notifications:TeamsNotificationsWebhook"] ?? ""; - await TeamsNotificationService.PostToTeamsAsync(teamsChannel, activityTitle, activitySubtitle, _facts); - return missingSubmissions ?? new HashSet(); + if (missingSubmissions.Count > 0) + { + string tenantName = await GetTenantNameAsync() ?? ""; + string? envInfo = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT"); + string activityTitle = "Review Missed Chefs Submissions " + tenantName; + string activitySubtitle = "Environment: " + envInfo; + string teamsChannel = _configuration["Notifications:TeamsNotificationsWebhook"] ?? ""; + await TeamsNotificationService.PostToTeamsAsync(teamsChannel, activityTitle, activitySubtitle, _facts); + } + return (missingSubmissions ?? new HashSet(), missingSubmissionsReportBuilder.ToString()); } private async Task GetTenantNameAsync() diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/ApplicationForms/ApplicationFormVersionAppService.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/ApplicationForms/ApplicationFormVersionAppService.cs index 71db731c3..de58359ed 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/ApplicationForms/ApplicationFormVersionAppService.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/ApplicationForms/ApplicationFormVersionAppService.cs @@ -270,28 +270,45 @@ private async Task UpdateApplicationFormVersionFields(ApplicationFormVersion app public async Task GetFormVersionByApplicationIdAsync(Guid applicationId) { var formSubmission = await _formSubmissionRepository.GetByApplicationAsync(applicationId); + if (formSubmission.FormVersionId == null) { - try - { - var submissionJson = JObject.Parse(formSubmission.Submission); - var tokenFormVersionId = submissionJson?.SelectToken("submission.formVersionId")?.ToString(); - if (tokenFormVersionId == null) return 0; - - var formVersionId = Guid.Parse(tokenFormVersionId); - formSubmission.FormVersionId = formVersionId; - await _formSubmissionRepository.UpdateAsync(formSubmission); - return await GetVersion(formVersionId); - } - catch - { - return 0; - } + return await HandleEmptyFormVersionIdAsync(formSubmission); } return await GetVersion(formSubmission.FormVersionId ?? Guid.Empty); } + /// + /// Handles the case where the form version ID is empty or null in the form submission. + /// This method is for backward compatibility with legacy submissions that may not have the form version ID set. + /// This method should be reviewed later as it can be removed once all submissions have been migrated to include the form version ID. + /// + /// + /// + private async Task HandleEmptyFormVersionIdAsync(ApplicationFormSubmission formSubmission) + { + try + { + var submissionJson = JObject.Parse(formSubmission.Submission); + var legacyTokenFormVersionId = submissionJson?.SelectToken("submission.formVersionId")?.ToString(); + var newTokenFormVersionId = submissionJson?.SelectToken("formVersionId")?.ToString(); + + var formVersionIdString = legacyTokenFormVersionId ?? newTokenFormVersionId; + if (formVersionIdString == null) + return 0; + + var formVersionId = Guid.Parse(formVersionIdString); + formSubmission.FormVersionId = formVersionId; + await _formSubmissionRepository.UpdateAsync(formSubmission); + return await GetVersion(formVersionId); + } + catch + { + return 0; + } + } + public async Task DeleteWorkSheetMappingByFormName(string formName, Guid formVersionId) { var applicationFormVersion = await _formVersionRepository.GetAsync(formVersionId); diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Attachments/S3BlobProvider.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Attachments/S3BlobProvider.cs index d140d6db3..ca02d5919 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Attachments/S3BlobProvider.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Attachments/S3BlobProvider.cs @@ -51,8 +51,10 @@ public S3BlobProvider(IHttpContextAccessor httpContextAccessor, IApplicationAtta public override async Task DeleteAsync(BlobProviderDeleteArgs args) { string s3ObjectKey = args.BlobName; - var attachmentType = _httpContextAccessor.HttpContext.Request.Form["AttachmentType"]; - var attachmentTypeId = _httpContextAccessor.HttpContext.Request.Form["AttachmentTypeId"]; + var httpContext = _httpContextAccessor.HttpContext ?? throw new InvalidOperationException("No active HttpContext."); + var form = httpContext.Request?.Form ?? throw new InvalidOperationException("No form data in the current request."); + string attachmentType = form.TryGetValue("AttachmentType", out var typeValue) ? typeValue.ToString() : string.Empty; + string attachmentTypeId = form.TryGetValue("AttachmentTypeId", out var idValue) ? idValue.ToString() : string.Empty; var config = args.Configuration.GetS3BlobProviderConfiguration(); var deleteObjectRequest = new DeleteObjectRequest @@ -142,7 +144,8 @@ private static string GetMimeType(string fileName) public override async Task SaveAsync(BlobProviderSaveArgs args) { - var queryParams = _httpContextAccessor.HttpContext.Request.Query; + var httpContext = _httpContextAccessor.HttpContext ?? throw new InvalidOperationException("No active HttpContext."); + var queryParams = httpContext.Request?.Query ?? throw new InvalidOperationException("No query parameters in the current request."); var routeData = _httpContextAccessor.HttpContext.GetRouteData(); var assessmentId = routeData.Values["assessmentId"]; diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Events/ApplicationChangedHandler.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Events/ApplicationChangedHandler.cs index 28e5d8c9b..56ae9a2a1 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Events/ApplicationChangedHandler.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Events/ApplicationChangedHandler.cs @@ -1,5 +1,4 @@ using System.Threading.Tasks; -using Microsoft.Extensions.Configuration; using Unity.GrantManager.Applications; using Unity.GrantManager.GrantApplications; using Unity.Notifications.Emails; @@ -19,17 +18,14 @@ internal class ApplicationChangedHandler : ILocalEventHandler GetApplicantInfoTabAsync(Guid applicationId) + { + var application = await applicationRepository.WithBasicDetailsAsync(applicationId); + if (application == null || !await AuthorizationService.IsGrantedAsync(UnitySelector.Applicant.Default)) + { + return new ApplicantInfoDto(); + } + + var applicantInfoDto = ObjectMapper.Map(application); + + applicantInfoDto.ApplicationId = application.Id; + applicantInfoDto.ApplicantId = application.ApplicantId; + applicantInfoDto.ApplicationFormId = application.ApplicationFormId; + + applicantInfoDto.ApplicationReferenceNo = application.ReferenceNo; + applicantInfoDto.ApplicantName = application.Applicant?.ApplicantName ?? string.Empty; + + applicantInfoDto.ApplicationStatusCode = application.ApplicationStatus.StatusCode; + applicantInfoDto.ElectoralDistrict = application.Applicant?.ElectoralDistrict ?? string.Empty; + + //-- APPLICANT INFO SUMMARY + if (application.Applicant != null && await AuthorizationService.IsGrantedAsync(UnitySelector.Applicant.Summary.Default)) + { + applicantInfoDto.ApplicantSummary = ObjectMapper.Map(application.Applicant); + applicantInfoDto.ApplicantSummary.FiscalDay = application.Applicant?.FiscalDay.ToString() ?? string.Empty; + } + else + { + applicantInfoDto.ApplicantSummary = new ApplicantSummaryDto(); + } + + //-- APPLICANT INFO CONTACT + if (application?.ApplicantAgent != null && await AuthorizationService.IsGrantedAsync(UnitySelector.Applicant.Contact.Default)) + { + applicantInfoDto.ContactInfo = ObjectMapper.Map(application.ApplicantAgent); + } + else + { + applicantInfoDto.ContactInfo = new ContactInfoDto(); + } + + //-- SIGNING AUTHORITY + if (application != null && await AuthorizationService.IsGrantedAsync(UnitySelector.Applicant.Authority.Default)) + { + applicantInfoDto.SigningAuthority = ObjectMapper.Map(application); + } + else + { + applicantInfoDto.SigningAuthority = new SigningAuthorityDto(); + } + + //-- APPLICANT INFO ADDRESS + if (await AuthorizationService.IsGrantedAsync(UnitySelector.Applicant.Location.Default)) + { + applicantInfoDto.ApplicantAddresses = ObjectMapper.Map, List>(application?.Applicant?.ApplicantAddresses?.ToList() ?? []); + } + else + { + applicantInfoDto.ApplicantAddresses = []; + } + + return applicantInfoDto; + } + + [Obsolete("Use GetApplicantInfoTabAsync instead.")] + [Authorize] + public async Task GetByApplicationIdAsync(Guid applicationId) { - private readonly IApplicationRepository _applicationRepository; + var applicantInfo = await applicationRepository.WithBasicDetailsAsync(applicationId); + if (applicantInfo == null) return new ApplicationApplicantInfoDto(); - public ApplicationApplicantAppService(IApplicationRepository applicationRepository) + return new ApplicationApplicantInfoDto() { - _applicationRepository = applicationRepository; - } + ApplicantId = applicantInfo.Applicant.Id, + ApplicationFormId = applicantInfo.ApplicationFormId, + ApplicantName = applicantInfo.Applicant?.ApplicantName ?? string.Empty, + ApplicationReferenceNo = applicantInfo.ReferenceNo, + ApplicationStatus = applicantInfo.ApplicationStatus.InternalStatus, + ApplicationStatusCode = applicantInfo.ApplicationStatus.StatusCode, - public async Task GetByApplicationIdAsync(Guid applicationId) - { - var applicantInfo = await _applicationRepository.WithBasicDetailsAsync(applicationId); - if (applicantInfo == null) return new ApplicationApplicantInfoDto(); + 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, - 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, + 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, - 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, + 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, - 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, + 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, - 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, + ApplicantAddresses = ObjectMapper.Map, List>(applicantInfo.Applicant?.ApplicantAddresses?.ToList() ?? []), + ElectoralDistrict = applicantInfo.Applicant?.ElectoralDistrict ?? 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, + [Authorize(UnitySelector.Applicant.UpdatePolicy)] + public async Task UpdatePartialApplicantInfoAsync(Guid applicationId, PartialUpdateDto input) + { + var application = await applicationRepository.GetAsync(applicationId) ?? throw new EntityNotFoundException(); + + if (input == null || input.Data == null) + { + throw new ArgumentNullException(nameof(input), "Input data cannot be null."); + } + + // Only update the fields we need to update based on the modified + ObjectMapper.Map(input.Data, application); + + //-- APPLICANT INFO - SUMMARY + if (input.Data.ApplicantSummary != null + && await AuthorizationService.IsGrantedAsync(UnitySelector.Applicant.Summary.Update)) + { + await InternalPartialUpdateApplicantSummaryInfoAsync(application.Applicant, input.Data.ApplicantSummary, input.ModifiedFields); + } + + //-- APPLICANT INFO - CONTACT (APPLICANT AGENT) + if (input.Data.ContactInfo != null + && await AuthorizationService.IsGrantedAsync(UnitySelector.Applicant.Contact.Update)) + { + await CreateOrUpdateContactInfoAsync(application.ApplicantId, input.Data.ContactInfo); + } + + //-- APPLICANT INFO - SIGNING AUTHORITY (APPLICATION) + if (input.Data.SigningAuthority != null + && await AuthorizationService.IsGrantedAsync(UnitySelector.Applicant.Authority.Update)) + { + // Move to applicaiton service + ObjectMapper.Map(input.Data.SigningAuthority, application); + } + + //-- APPLICANT INFO - ADDRESS + if (input.Data.PhysicalAddress != null + && await AuthorizationService.IsGrantedAsync(UnitySelector.Applicant.Location.Update)) + { + input.Data.PhysicalAddress.AddressType = AddressType.PhysicalAddress; + await CreateOrUpdateApplicantAddress(application.ApplicantId, input.Data.PhysicalAddress); + } + + if (input.Data.MailingAddress != null + && await AuthorizationService.IsGrantedAsync(UnitySelector.Applicant.Location.Update)) + { + input.Data.MailingAddress.AddressType = AddressType.MailingAddress; + await CreateOrUpdateApplicantAddress(application.ApplicantId, input.Data.MailingAddress); + } + + //-- APPLICANT INFO CUSTOM FIELDS + if (input.Data.CustomFields?.ValueKind != JsonValueKind.Null && input.Data.WorksheetId != Guid.Empty && input.Data.CorrelationId != Guid.Empty) + { + await PublishCustomFieldUpdatesAsync(application.Id, FlexConsts.ApplicantInfoUiAnchor, input.Data); + } + + var updatedApplication = await applicationRepository.UpdateAsync(application); + return ObjectMapper.Map(updatedApplication); + } + + /// + /// Updates the Applicant Summary information for the given applicant while ignoring null values unless explicitly specified in modifiedFields. + /// + /// + /// + /// + /// + /// + [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(); + return await InternalPartialUpdateApplicantSummaryInfoAsync(applicant, applicantSummary, modifiedFields); + } + + /// + /// Updates the Applicant Summary information for the given applicant while ignoring null values unless explicitly specified in modifiedFields. + /// + /// + /// + /// + /// + /// + 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() ?? []; - ApplicantAddresses = ObjectMapper.Map, List>(applicantInfo.Applicant?.ApplicantAddresses?.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. + /// + /// + /// + /// + [Authorize(UnitySelector.Applicant.Contact.Update)] + protected internal async Task CreateOrUpdateContactInfoAsync(Guid applicantId, ContactInfoDto contactInfo) + { + var applicantAgent = await applicantAgentRepository.FirstOrDefaultAsync(a => a.ApplicantId == applicantId) + ?? new ApplicantAgent + { + ApplicantId = applicantId, + ApplicationId = contactInfo.ApplicationId, + }; + + ObjectMapper.Map(contactInfo, applicantAgent); + + if (applicantAgent.Id == Guid.Empty) + { + return await applicantAgentRepository.InsertAsync(applicantAgent); + } + else + { + return await applicantAgentRepository.UpdateAsync(applicantAgent); + } + } + + /// + /// Creates or updates the applicant addresses for the given applicant. Ignores null values unless explicitly specified in modifiedFields. + /// + /// + /// + /// + /// + [Authorize(UnitySelector.Applicant.Location.Update)] + protected internal async Task CreateOrUpdateApplicantAddress(Guid applicantId, UpdateApplicantAddressDto updatedAddress) + { + var applicantAddresses = await applicantAddressRepository.FindByApplicantIdAsync(applicantId); + + ApplicantAddress? dbAddress = applicantAddresses.FirstOrDefault(a => a.AddressType == updatedAddress.AddressType) + ?? new ApplicantAddress + { + ApplicantId = applicantId, + AddressType = updatedAddress.AddressType, + }; + + ObjectMapper.Map(updatedAddress, dbAddress); + + if (dbAddress.Id == Guid.Empty) + { + await applicantAddressRepository.InsertAsync(dbAddress); + } + else + { + await applicantAddressRepository.UpdateAsync(dbAddress); + } + } + + protected virtual async Task PublishCustomFieldUpdatesAsync(Guid applicationId, string uiAnchor, CustomDataFieldDto input) + { + if (await FeatureChecker.IsEnabledAsync("Unity.Flex")) + { + if (input.CorrelationId != Guid.Empty) + { + await localEventBus.PublishAsync(new PersistWorksheetIntanceValuesEto() + { + InstanceCorrelationId = applicationId, + InstanceCorrelationProvider = CorrelationConsts.Application, + SheetCorrelationId = input.CorrelationId, + SheetCorrelationProvider = CorrelationConsts.FormVersion, + UiAnchor = uiAnchor, + CustomFields = input.CustomFields, + WorksheetId = input.WorksheetId + }); + } + else + { + Logger.LogError("Unable to resolve for version"); + } + } } } 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 629b4c79c..e398922bf 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/GrantApplications/ApplicationTagsAppService.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/GrantApplications/ApplicationTagsAppService.cs @@ -4,9 +4,14 @@ using System.Linq; using System.Threading.Tasks; using Unity.GrantManager.Applications; +using Unity.Modules.Shared; +using Unity.Payments.Events; +using Volo.Abp; +using Volo.Abp.Application.Dtos; using Volo.Abp.Application.Services; using Volo.Abp.DependencyInjection; using Volo.Abp.Domain.Repositories; +using Volo.Abp.EventBus.Local; namespace Unity.GrantManager.GrantApplications; @@ -16,9 +21,12 @@ namespace Unity.GrantManager.GrantApplications; public class ApplicationTagsAppService : ApplicationService, IApplicationTagsService { private readonly IApplicationTagsRepository _applicationTagsRepository; - public ApplicationTagsAppService(IApplicationTagsRepository repository) + private readonly ILocalEventBus _localEventBus; + + public ApplicationTagsAppService(IApplicationTagsRepository repository, ILocalEventBus localEventBus) { _applicationTagsRepository = repository; + _localEventBus = localEventBus; } public async Task> GetListAsync() @@ -48,6 +56,10 @@ public async Task CreateorUpdateTagsAsync(Guid id, Applicati { var applicationTag = await _applicationTagsRepository.FirstOrDefaultAsync(e => e.ApplicationId == id); + // Sanitize input tag text string + var tagInput = input.Text.Split(',', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries).ToHashSet(); + input.Text = string.Join(',', tagInput.OrderBy(t => t, StringComparer.InvariantCultureIgnoreCase)); + if (applicationTag == null) { var newTag = await _applicationTagsRepository.InsertAsync(new ApplicationTags @@ -66,4 +78,179 @@ public async Task CreateorUpdateTagsAsync(Guid id, Applicati return ObjectMapper.Map(applicationTag); } } + + [Authorize(UnitySelector.SettingManagement.Tags.Default)] + public async Task> GetTagSummaryAsync() + { + var tagSummary = ObjectMapper.Map, List>( + await _applicationTagsRepository.GetTagSummary()); + + return new PagedResultDto( + tagSummary.Count, + tagSummary + ); + } + + /// + /// For a given Tag, finds the maximum length available for renaming. + /// + /// The tag to be replaced. + /// The maximum length available for renaming + [Authorize(UnitySelector.SettingManagement.Tags.Update)] + public async Task GetMaxRenameLengthAsync(string originalTag) + { + Check.NotNullOrWhiteSpace(originalTag, nameof(originalTag)); + return await _applicationTagsRepository.GetMaxRenameLengthAsync(originalTag); + } + + /// + /// 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.Text.Contains(originalTag)); + + if (applicationTags.Count == 0) + return []; + + int maxRemainingLength = await GetMaxRenameLengthAsync(originalTag); + if (replacementTag.Length > maxRemainingLength) + { + throw new ArgumentOutOfRangeException( + nameof(replacementTag), + $"String length exceeds maximum allowed length of {maxRemainingLength}. Actual length: {replacementTag.Length}" + ); + } + + 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.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 _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. + /// + /// String of tag to be deleted. + [Authorize(UnitySelector.SettingManagement.Tags.Delete)] + public async Task DeleteTagAsync(string deleteTag) + { + Check.NotNullOrWhiteSpace(deleteTag, nameof(deleteTag)); + + // Remove commas from the originalTag and replacementTag + deleteTag = deleteTag.Replace(",", string.Empty).Trim(); + + var applicationTags = await _applicationTagsRepository + .GetListAsync(e => e.Text.Contains(deleteTag)); + + var updatedTags = new List(); + var deletedTags = new List(); + + foreach (var item in applicationTags) + { + var tagSet = new HashSet( + item.Text.Split(',', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries), + StringComparer.InvariantCultureIgnoreCase); + + // Only replace whole word tags - skip substring matches + if (tagSet.Remove(deleteTag)) + { + if (tagSet.Count > 0) + { + item.Text = string.Join(',', tagSet.OrderBy(t => t, StringComparer.InvariantCultureIgnoreCase)); + updatedTags.Add(item); + } + else + { + deletedTags.Add(item); + } + } + } + + if (deletedTags.Count > 0) + { + await _applicationTagsRepository.DeleteManyAsync(deletedTags, autoSave: true); + } + + if (updatedTags.Count > 0) + { + await _applicationTagsRepository.UpdateManyAsync(updatedTags, autoSave: true); + } + } + + /// + /// Deletes a tag from all applications and payment requests. + /// + /// String of tag to be deleted. + [Authorize(UnitySelector.SettingManagement.Tags.Delete)] + public virtual async Task DeleteTagGlobalAsync(string deleteTag) + { + Check.NotNullOrWhiteSpace(deleteTag, nameof(deleteTag)); + + await DeleteTagAsync(deleteTag); + await _localEventBus.PublishAsync(new DeleteTagEto { TagName = deleteTag }); + } } \ No newline at end of file diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/GrantApplications/BulkApprovalsAppService.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/GrantApplications/BulkApprovalsAppService.cs index 86dcece18..8153e606f 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/GrantApplications/BulkApprovalsAppService.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/GrantApplications/BulkApprovalsAppService.cs @@ -42,9 +42,10 @@ public async Task BulkApproveApplications(List> ValidateBulkApplications(Application[] foreach (var application in applications) { - List<(bool, string)> validationMessages = await RunValidations(application); - - applicationsForApproval.Add(new BulkApprovalDto() - { - ApplicationId = application.Id, - ApprovedAmount = application.ApprovedAmount, - RequestedAmount = application.RequestedAmount, - FinalDecisionDate = application.FinalDecisionDate, - ReferenceNo = application.ReferenceNo, - ValidationMessages = validationMessages.Select(s => s.Item2).ToList(), - ApplicantName = application.Applicant.ApplicantName ?? string.Empty, - ApplicationStatus = application.ApplicationStatus.InternalStatus, - FormName = application.ApplicationForm?.ApplicationFormName ?? string.Empty, - IsValid = !validationMessages.Exists(s => s.Item1) - }); + applicationsForApproval + .Add(MapBulkApproval(application, await RunValidations(application))); } return applicationsForApproval; } + + /// + /// Map the application to a BulkApprovalDto with validation messages + /// + /// + /// + /// + private static BulkApprovalDto MapBulkApproval(Application application, List<(bool, string)> validationMessages) + { + return new BulkApprovalDto() + { + ApplicationId = application.Id, + ApprovedAmount = application.ApprovedAmount, + RequestedAmount = application.RequestedAmount, + FinalDecisionDate = application.FinalDecisionDate, + ReferenceNo = application.ReferenceNo, + ValidationMessages = validationMessages.Select(s => s.Item2).ToList(), + ApplicantName = application.Applicant.ApplicantName ?? string.Empty, + ApplicationStatus = application.ApplicationStatus.InternalStatus, + FormName = application.ApplicationForm?.ApplicationFormName ?? string.Empty, + IsValid = !validationMessages.Exists(s => s.Item1), + IsDirectApproval = application.ApplicationForm?.IsDirectApproval, + RecommendedAmount = application.RecommendedAmount + }; + } + /// /// Run the validations for the application /// @@ -139,6 +153,29 @@ private async Task> ValidateBulkApplications(Application[] if (!authorized) validationMessages.Add(new(true, "INVALID_PERMISSIONS")); + // If this application belongs to a direct approval form, we default to RequestedAmount if the ApprovedAmount is 0.00 + if (application.ApplicationForm?.IsDirectApproval == true) + { + application.ApprovedAmount = application.ApprovedAmount == 0m ? application.RequestedAmount : application.ApprovedAmount; + } + else + { + // If this application does not belong to a direct approval form, ensure that RecommendedAmount is not 0.00. + if (application.RecommendedAmount == 0m) + { + validationMessages.Add(new(false, "INVALID_RECOMMENDED_AMOUNT")); + } + + // If ApprovedAmount is 0.00, we default it to RecommendedAmount + application.ApprovedAmount = application.ApprovedAmount == 0m ? application.RecommendedAmount : application.ApprovedAmount; + } + + // If approved amount is still 0.00 after default sets then it is an error + if (application.ApprovedAmount == 0m) + { + validationMessages.Add(new(false, "INVALID_APPROVED_AMOUNT")); + } + return validationMessages; } @@ -154,8 +191,15 @@ private static bool MeetsWorkflowRequirement(Application application, GrantAppli { return false; } - if(application.ApplicationForm.IsDirectApproval) + + // Specific ruleset for the Is Direct Approval flow + if (application.ApplicationForm.IsDirectApproval) { + if (application.ApplicationStatus.StatusCode == GrantApplicationState.GRANT_APPROVED) + { + return false; + } + return true; } 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 05985bb13..e7388a434 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/GrantApplications/GrantApplicationAppService.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/GrantApplications/GrantApplicationAppService.cs @@ -13,6 +13,7 @@ using System.Threading.Tasks; using Unity.Flex.WorksheetInstances; using Unity.Flex.Worksheets; +using Unity.GrantManager.Applicants; using Unity.GrantManager.ApplicationForms; using Unity.GrantManager.Applications; using Unity.GrantManager.Comments; @@ -27,10 +28,11 @@ using Unity.Modules.Shared.Correlation; using Unity.Payments.Domain.PaymentRequests; using Unity.Payments.Enums; -using Unity.Payments.Integrations.Cas; using Unity.Payments.PaymentRequests; +using Unity.Payments.Permissions; using Volo.Abp; using Volo.Abp.Application.Dtos; +using Volo.Abp.Authorization; using Volo.Abp.DependencyInjection; using Volo.Abp.Domain.Entities; using Volo.Abp.Domain.Repositories; @@ -56,7 +58,7 @@ public class GrantApplicationAppService : GrantManagerAppService, IGrantApplicat private readonly IApplicantAgentRepository _applicantAgentRepository; private readonly IApplicantAddressRepository _applicantAddressRepository; private readonly ILocalEventBus _localEventBus; - private readonly ISupplierService _iSupplierService; + private readonly IApplicantSupplierAppService _applicantSupplierService; private readonly IPaymentRequestAppService _paymentRequestService; private readonly IPaymentRequestRepository _paymentRequestsRepository; private readonly IZoneChecker _zoneChecker; @@ -74,7 +76,7 @@ public GrantApplicationAppService( IApplicantAgentRepository applicantAgentRepository, IApplicantAddressRepository applicantAddressRepository, ILocalEventBus localEventBus, - ISupplierService iSupplierService, + IApplicantSupplierAppService applicantSupplierService, IPaymentRequestAppService paymentRequestService, IPaymentRequestRepository paymentRequestsRepository, IZoneChecker zoneChecker) @@ -90,7 +92,7 @@ public GrantApplicationAppService( _personRepository = personRepository; _applicantAgentRepository = applicantAgentRepository; _applicantAddressRepository = applicantAddressRepository; - _iSupplierService = iSupplierService; + _applicantSupplierService = applicantSupplierService; _localEventBus = localEventBus; _paymentRequestService = paymentRequestService; _paymentRequestsRepository = paymentRequestsRepository; @@ -103,9 +105,16 @@ public async Task> GetListAsync(PagedAndSort // Pre-fetch payment requests for all applications in a single query to reduce database calls var applicationIds = groupedResult.SelectMany(g => g).Select(a => a.Id).ToList(); - var paymentRequests = await _paymentRequestService.GetListByApplicationIdsAsync(applicationIds); + bool paymentsFeatureEnabled = await FeatureChecker.IsEnabledAsync(PaymentConsts.UnityPaymentsFeature); + List paymentRequests = new List(); + if (paymentsFeatureEnabled) + { + paymentRequests = await _paymentRequestService.GetListByApplicationIdsAsync(applicationIds); + } + + // Map applications to DTOs var appDtos = groupedResult.Select(grouping => { @@ -130,7 +139,8 @@ public async Task> GetListAsync(PagedAndSort appDto.ContactCellPhone = firstApplication.ApplicantAgent?.Phone2; //Payment request info if the feature is enabled - if (paymentsFeatureEnabled) + + if (paymentsFeatureEnabled && paymentRequests != null && paymentRequests is { Count: > 0 }) { var paymentInfo = new PaymentInfoDto { @@ -233,7 +243,7 @@ public async Task GetAsync(Guid id) appDto.Sector = application.Applicant.Sector; appDto.OrganizationType = application.Applicant.OrganizationType; appDto.SubSector = application.Applicant.SubSector; - appDto.SectorSubSectorIndustryDesc = application.Applicant.SectorSubSectorIndustryDesc; + appDto.SectorSubSectorIndustryDesc = application.Applicant.SectorSubSectorIndustryDesc; } return appDto; @@ -300,7 +310,7 @@ public async Task UpdateAssessmentResultsAsync(Guid id, Cre await SanitizeApprovalZoneInputs(input, application); await SanitizeAssessmentResultsZoneInputs(input, application); - application.ValidateAndChangeDueDate(input.DueDate); + application.ValidateAndSetDueDate(input.DueDate); application.UpdateAlwaysChangeableFields(input.Notes, input.SubStatus, input.LikelihoodOfFunding, input.TotalProjectBudget, input.NotificationDate, input.RiskRanking); if (application.IsInFinalDecisionState()) @@ -319,7 +329,7 @@ public async Task UpdateAssessmentResultsAsync(Guid id, Cre { if (await CurrentUserCanUpdateAssessmentFieldsAsync()) { - application.ValidateAndChangeFinalDecisionDate(input.FinalDecisionDate); + application.ValidateAndSetFinalDecisionDate(input.FinalDecisionDate); application.UpdateApprovalFieldsRequiringPostEditPermission(input.ApprovedAmount); application.UpdateAssessmentResultFieldsRequiringPostEditPermission(input.RequestedAmount, input.TotalScore); application.UpdateFieldsOnlyForPreFinalDecision(input.DueDiligenceStatus, @@ -362,33 +372,33 @@ private async Task SanitizeApprovalZoneInputs(CreateUpdateAssessmentResultsDto i private async Task SanitizeAssessmentResultsZoneInputs(CreateUpdateAssessmentResultsDto input, Application application) { // Approval Zone Fields - Disabled Inputs - input.RequestedAmount ??= application.RequestedAmount; - input.TotalProjectBudget ??= application.TotalProjectBudget; - input.RecommendedAmount ??= application.RecommendedAmount; - input.TotalScore ??= application.TotalScore; + input.RequestedAmount ??= application.RequestedAmount; + input.TotalProjectBudget ??= application.TotalProjectBudget; + input.RecommendedAmount ??= application.RecommendedAmount; + input.TotalScore ??= application.TotalScore; // Sanitize if zone is disabled if (!await _zoneChecker.IsEnabledAsync(UnitySelector.Review.AssessmentResults.Default, application.ApplicationFormId)) { - input.LikelihoodOfFunding ??= application.LikelihoodOfFunding; - input.RiskRanking ??= application.RiskRanking; - input.DueDiligenceStatus ??= application.DueDiligenceStatus; - input.AssessmentResultStatus ??= application.AssessmentResultStatus; - input.DeclineRational ??= application.DeclineRational; - - input.NotificationDate ??= application.NotificationDate; - input.DueDate ??= application.DueDate; + input.LikelihoodOfFunding ??= application.LikelihoodOfFunding; + input.RiskRanking ??= application.RiskRanking; + input.DueDiligenceStatus ??= application.DueDiligenceStatus; + input.AssessmentResultStatus ??= application.AssessmentResultStatus; + input.DeclineRational ??= application.DeclineRational; + + input.NotificationDate ??= application.NotificationDate; + input.DueDate ??= application.DueDate; } else { // Sanitize if zone is enabled but fields are disabled if (application.IsInFinalDecisionState()) { - input.LikelihoodOfFunding ??= application.LikelihoodOfFunding; - input.RiskRanking ??= application.RiskRanking; - input.DueDiligenceStatus ??= application.DueDiligenceStatus; + input.LikelihoodOfFunding ??= application.LikelihoodOfFunding; + input.RiskRanking ??= application.RiskRanking; + input.DueDiligenceStatus ??= application.DueDiligenceStatus; input.AssessmentResultStatus ??= application.AssessmentResultStatus; - input.DeclineRational ??= application.DeclineRational; + input.DeclineRational ??= application.DeclineRational; } } } @@ -398,11 +408,28 @@ private async Task CurrentUserCanUpdateAssessmentFieldsAsync() return await AuthorizationService.IsGrantedAsync(UnitySelector.Review.AssessmentResults.Update.Default); } - [Authorize(GrantApplicationPermissions.ProjectInfo.Update)] + [Authorize(UnitySelector.Project.UpdatePolicy)] public async Task UpdateProjectInfoAsync(Guid id, CreateUpdateProjectInfoDto input) { + // Check if the user has the required permissions to update Project Info for either fieldset zone + var hasSummaryPermission = await AuthorizationService.IsGrantedAsync(UnitySelector.Project.Summary.Update.Default); + var hasLocationPermission = await AuthorizationService.IsGrantedAsync(UnitySelector.Project.Location.Update.Default); + + if (!hasSummaryPermission || !hasLocationPermission) + { + throw new AbpAuthorizationException("The user doesn't have the required permissions to update Project Info."); + } + var application = await _applicationRepository.GetAsync(id); + var hasSummaryZone = await _zoneChecker.IsEnabledAsync(UnitySelector.Project.Summary.Default, application.ApplicationFormId); + var hasLocationZone = await _zoneChecker.IsEnabledAsync(UnitySelector.Project.Location.Default, application.ApplicationFormId); + + if (!hasSummaryZone || !hasLocationZone) + { + throw new BusinessException("The Project Info zones are not enabled for this application form."); + } + SanitizeProjectInfoDisabledInputs(input, application); var percentageTotalProjectBudget = (input.TotalProjectBudget == 0 || input.TotalProjectBudget == null) ? 0 : decimal.Multiply(decimal.Divide(input.RequestedAmount ?? 0, input.TotalProjectBudget ?? 0), 100).To(); @@ -438,6 +465,56 @@ public async Task UpdateProjectInfoAsync(Guid id, CreateUpd throw new EntityNotFoundException(); } } + private static void SanitizeProjectInfoDisabledInputs(CreateUpdateProjectInfoDto input, Application application) + { + // Cater for disabled fields that are not serialized with post - fall back to the previous value, these should be 0 from the API call + input.TotalProjectBudget ??= application.TotalProjectBudget; + input.RequestedAmount ??= application.RequestedAmount; + input.ProjectFundingTotal ??= application.ProjectFundingTotal; + } + + [Authorize(UnitySelector.Project.UpdatePolicy)] + public async Task UpdatePartialProjectInfoAsync(Guid id, PartialUpdateDto input) + { + // Only update the fields we need to update based on the modified fields + // This is required to handle controls like the date picker that do not send null values for unchanged fields + var application = await _applicationRepository.GetAsync(id) ?? throw new EntityNotFoundException($"Application with ID {id} not found."); + ObjectMapper.Map(input.Data, application); + + // Explicitly handle properties that are null but listed in ModifiedFields + var dtoProperties = typeof(UpdateProjectInfoDto).GetProperties(); + var appProperties = typeof(Application).GetProperties().ToDictionary(p => p.Name, p => p); + + foreach (var fieldName in input.ModifiedFields) + { + if (dtoProperties.FirstOrDefault(p => + string.Equals(p.Name, fieldName, StringComparison.OrdinalIgnoreCase)) is { } dtoProperty) + { + var value = dtoProperty.GetValue(input.Data); + if (value == null && appProperties.TryGetValue(dtoProperty.Name, out var appProperty) && appProperty.CanWrite) + { + appProperty.SetValue(application, appProperty.PropertyType.IsValueType + && Nullable.GetUnderlyingType(appProperty.PropertyType) == null + ? Activator.CreateInstance(appProperty.PropertyType) + : null); + } + } + } + + // Calculate the percentage of the total project budget based on + // the requested amount and total project budget. Percentage total has to be + // updated whenever RequestedAmount or TotalProjectBudget changes + application.UpdatePercentageTotalProjectBudget(); + + // Add custom worksheet data + if (input.Data.CustomFields is not null && input.Data.WorksheetId != Guid.Empty && input.Data.CorrelationId != Guid.Empty) + { + await PublishCustomFieldUpdatesAsync(application.Id, FlexConsts.ProjectInfoUiAnchor, input.Data); + } + + await _applicationRepository.UpdateAsync(application); + return ObjectMapper.Map(application); + } public async Task UpdateFundingAgreementInfoAsync(Guid id, CreateUpdateFundingAgreementInfoDto input) { @@ -460,104 +537,129 @@ public async Task UpdateFundingAgreementInfoAsync(Guid id, } } - private static void SanitizeProjectInfoDisabledInputs(CreateUpdateProjectInfoDto input, Application application) - { - // Cater for disabled fields that are not serialized with post - fall back to the previous value, these should be 0 from the API call - input.TotalProjectBudget ??= application.TotalProjectBudget; - input.RequestedAmount ??= application.RequestedAmount; - input.ProjectFundingTotal ??= application.ProjectFundingTotal; + /// + /// Update the supplier number for the applicant associated with the application. + /// + [Authorize(PaymentsPermissions.Payments.EditSupplierInfo)] + public async Task UpdateSupplierNumberAsync(Guid applicationId, string supplierNumber) + { + // Could be moved to payments module but dependency on ApplicationId + // Integrate with payments module to update / insert supplier + var application = await _applicationRepository.GetAsync(applicationId); + if (await FeatureChecker.IsEnabledAsync(PaymentConsts.UnityPaymentsFeature) && application != null && !string.IsNullOrEmpty(supplierNumber)) + { + var pendingPayments = await _paymentRequestsRepository.GetPaymentPendingListByCorrelationIdAsync(applicationId); + if (pendingPayments != null && pendingPayments.Count > 0) + { + throw new UserFriendlyException("There are outstanding payment requests with the current Supplier. Please decline or approve the outstanding payments before changing the Supplier Number"); + } + + await _applicantSupplierService.UpdateApplicantSupplierNumberAsync(application.ApplicantId, supplierNumber); + } } - [Authorize(GrantApplicationPermissions.ApplicantInfo.Update)] + protected internal async Task CreateOrUpdateApplicantAgentAsync(Application application, ContactInfoDto? input) + { + if (input == null + || !await AuthorizationService.IsGrantedAnyAsync(UnitySelector.Applicant.Contact.Create, UnitySelector.Applicant.Contact.Update)) + { + return null; + } + + var applicantAgent = await _applicantAgentRepository + .FirstOrDefaultAsync(a => a.ApplicantId == application.ApplicantId) + ?? new ApplicantAgent + { + ApplicantId = application.ApplicantId, + ApplicationId = application.Id + }; + + applicantAgent.Name = input?.Name ?? string.Empty; + applicantAgent.Phone = input?.Phone ?? string.Empty; + applicantAgent.Phone2 = input?.Phone2 ?? string.Empty; + applicantAgent.Email = input?.Email ?? string.Empty; + applicantAgent.Title = input?.Title ?? string.Empty; + + if (applicantAgent.Id == Guid.Empty) + { + return await _applicantAgentRepository.InsertAsync(applicantAgent); + } + + return await _applicantAgentRepository.UpdateAsync(applicantAgent); + } + + [Obsolete("Use ApplicationApplicantAppService.UpdatePartialApplicantInfoAsync instead.")] + [Authorize(UnitySelector.Applicant.UpdatePolicy)] public async Task UpdateProjectApplicantInfoAsync(Guid id, CreateUpdateApplicantInfoDto input) { var application = await _applicationRepository.GetAsync(id); - - if (application != null) + + var applicant = await _applicantRepository + .FirstOrDefaultAsync(a => a.Id == application.ApplicantId) ?? throw new EntityNotFoundException(); + + applicant.OrganizationType = input.OrganizationType ?? ""; + applicant.OrgName = input.OrgName ?? ""; + applicant.OrgNumber = input.OrgNumber ?? ""; + applicant.OrgStatus = input.OrgStatus ?? ""; + applicant.OrganizationSize = input.OrganizationSize ?? ""; + applicant.Sector = input.Sector ?? ""; + applicant.SubSector = input.SubSector ?? ""; + applicant.SectorSubSectorIndustryDesc = input.SectorSubSectorIndustryDesc ?? ""; + applicant.IndigenousOrgInd = input.IndigenousOrgInd ?? ""; + applicant.UnityApplicantId = input.UnityApplicantId ?? ""; + applicant.FiscalDay = input.FiscalDay; + applicant.FiscalMonth = input.FiscalMonth ?? ""; + applicant.NonRegOrgName = input.NonRegOrgName ?? ""; + applicant.ElectoralDistrict = input.ElectoralDistrict ?? ""; + applicant.ApplicantName = input.ApplicantName ?? ""; + + _ = await _applicantRepository.UpdateAsync(applicant); + + var applicantAgent = await _applicantAgentRepository.FirstOrDefaultAsync(agent => agent.ApplicantId == application.ApplicantId); + if (applicantAgent == null) { - var applicant = await _applicantRepository.FirstOrDefaultAsync(a => a.Id == application.ApplicantId) ?? throw new EntityNotFoundException(); - // This applicant should never be null! - - applicant.OrganizationType = input.OrganizationType ?? ""; - applicant.OrgName = input.OrgName ?? ""; - applicant.OrgNumber = input.OrgNumber ?? ""; - applicant.OrgStatus = input.OrgStatus ?? ""; - applicant.OrganizationSize = input.OrganizationSize ?? ""; - applicant.Sector = input.Sector ?? ""; - applicant.SubSector = input.SubSector ?? ""; - applicant.SectorSubSectorIndustryDesc = input.SectorSubSectorIndustryDesc ?? ""; - applicant.IndigenousOrgInd = input.IndigenousOrgInd ?? ""; - applicant.UnityApplicantId = input.UnityApplicantId ?? ""; - applicant.FiscalDay = input.FiscalDay; - applicant.FiscalMonth = input.FiscalMonth ?? ""; - applicant.NonRegOrgName = input.NonRegOrgName ?? ""; - - _ = await _applicantRepository.UpdateAsync(applicant); - - // Integrate with payments module to update / insert supplier - // Check that the original supplier number has changed - if (await FeatureChecker.IsEnabledAsync(PaymentConsts.UnityPaymentsFeature) - && !string.IsNullOrEmpty(input.SupplierNumber) - && input.OriginalSupplierNumber != input.SupplierNumber) - { - var pendingPayments = await _paymentRequestsRepository.GetPaymentPendingListByCorrelationIdAsync(id); - if (pendingPayments != null && pendingPayments.Count > 0) - { - throw new UserFriendlyException("There are outstanding payment requests with the current Supplier. Please decline or approve the outstanding payments before changing the Supplier Number"); - } - await _iSupplierService.UpdateApplicantSupplierInfo(input.SupplierNumber, application.ApplicantId); - } - - var applicantAgent = await _applicantAgentRepository.FirstOrDefaultAsync(agent => agent.ApplicantId == application.ApplicantId); - if (applicantAgent == null) + applicantAgent = await _applicantAgentRepository.InsertAsync(new ApplicantAgent { - applicantAgent = await _applicantAgentRepository.InsertAsync(new ApplicantAgent - { - ApplicantId = application.ApplicantId, - ApplicationId = application.Id, - Name = input.ContactFullName ?? "", - Phone = input.ContactBusinessPhone ?? "", - Phone2 = input.ContactCellPhone ?? "", - Email = input.ContactEmail ?? "", - Title = input.ContactTitle ?? "" - }); - } - else - { - applicantAgent.Name = input.ContactFullName ?? ""; - applicantAgent.Phone = input.ContactBusinessPhone ?? ""; - applicantAgent.Phone2 = input.ContactCellPhone ?? ""; - applicantAgent.Email = input.ContactEmail ?? ""; - applicantAgent.Title = input.ContactTitle ?? ""; - applicantAgent = await _applicantAgentRepository.UpdateAsync(applicantAgent); - } + ApplicantId = application.ApplicantId, + ApplicationId = application.Id, + Name = input.ContactFullName ?? "", + Phone = input.ContactBusinessPhone ?? "", + Phone2 = input.ContactCellPhone ?? "", + Email = input.ContactEmail ?? "", + Title = input.ContactTitle ?? "" + }); + } + else + { + applicantAgent.Name = input.ContactFullName ?? ""; + applicantAgent.Phone = input.ContactBusinessPhone ?? ""; + applicantAgent.Phone2 = input.ContactCellPhone ?? ""; + applicantAgent.Email = input.ContactEmail ?? ""; + applicantAgent.Title = input.ContactTitle ?? ""; + applicantAgent = await _applicantAgentRepository.UpdateAsync(applicantAgent); + } - await UpdateApplicantAddresses(input); + await UpdateApplicantAddresses(input); - application.SigningAuthorityFullName = input.SigningAuthorityFullName ?? ""; - application.SigningAuthorityTitle = input.SigningAuthorityTitle ?? ""; - application.SigningAuthorityEmail = input.SigningAuthorityEmail ?? ""; - application.SigningAuthorityBusinessPhone = input.SigningAuthorityBusinessPhone ?? ""; - application.SigningAuthorityCellPhone = input.SigningAuthorityCellPhone ?? ""; + application.SigningAuthorityFullName = input.SigningAuthorityFullName ?? ""; + application.SigningAuthorityTitle = input.SigningAuthorityTitle ?? ""; + application.SigningAuthorityEmail = input.SigningAuthorityEmail ?? ""; + application.SigningAuthorityBusinessPhone = input.SigningAuthorityBusinessPhone ?? ""; + application.SigningAuthorityCellPhone = input.SigningAuthorityCellPhone ?? ""; - await PublishCustomFieldUpdatesAsync(application.Id, FlexConsts.ApplicantInfoUiAnchor, input); + await PublishCustomFieldUpdatesAsync(application.Id, FlexConsts.ApplicantInfoUiAnchor, input); - await _applicationRepository.UpdateAsync(application); + await _applicationRepository.UpdateAsync(application); - var appDto = ObjectMapper.Map(application); + var appDto = ObjectMapper.Map(application); - appDto.ContactFullName = applicantAgent.Name; - appDto.ContactEmail = applicantAgent.Email; - appDto.ContactTitle = applicantAgent.Title; - appDto.ContactBusinessPhone = applicantAgent.Phone; - appDto.ContactCellPhone = applicantAgent.Phone2; + appDto.ContactFullName = applicantAgent.Name; + appDto.ContactEmail = applicantAgent.Email; + appDto.ContactTitle = applicantAgent.Title; + appDto.ContactBusinessPhone = applicantAgent.Phone; + appDto.ContactCellPhone = applicantAgent.Phone2; - return appDto; - } - else - { - throw new EntityNotFoundException(); - } + return appDto; } protected virtual async Task PublishCustomFieldUpdatesAsync(Guid applicationId, @@ -970,5 +1072,5 @@ public async Task> GetAllApplicationsAsync() }; return await query.ToListAsync(); - } + } } diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/GrantManagerApplicationAutoMapperProfile.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/GrantManagerApplicationAutoMapperProfile.cs index 9d67e624b..c97bfde6d 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/GrantManagerApplicationAutoMapperProfile.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/GrantManagerApplicationAutoMapperProfile.cs @@ -1,4 +1,5 @@ using AutoMapper; +using System; using Unity.GrantManager.ApplicationForms; using Unity.GrantManager.Applications; using Unity.GrantManager.Assessments; @@ -48,6 +49,7 @@ public GrantManagerApplicationAutoMapperProfile() CreateMap(); CreateMap(); CreateMap(); + CreateMap(); CreateMap(); CreateMap(); CreateMap(); @@ -74,6 +76,87 @@ public GrantManagerApplicationAutoMapperProfile() CreateMap().ReverseMap(); CreateMap().ReverseMap(); CreateMap().ReverseMap(); + + CreateMap(); + + //-- PROJECT INFO + CreateMap() + .IgnoreNullAndDefaultValues(); + + //-- APPLICANT INFO - OUTBOUND MAPS + CreateMap(); + CreateMap(); + CreateMap() + .ForMember(dest => dest.IndigenousOrgInd, + opt => opt.MapFrom(src => + src.IndigenousOrgInd == "Yes" ? true : + src.IndigenousOrgInd == "No" ? false : (bool?)null)); + CreateMap(); + CreateMap(); + + //-- APPLICANT INFO - INBOUND MAPS + CreateMap() + .IgnoreNullAndDefaultValues(); + CreateMap() + .IgnoreNullAndDefaultValues(); + CreateMap() + .IgnoreNullAndDefaultValues(); + CreateMap() + .ForMember(dest => dest.IndigenousOrgInd, + opt => opt.MapFrom(src => + src.IndigenousOrgInd == true ? "Yes" : + src.IndigenousOrgInd == false ? "No" : null)) + .IgnoreNullAndDefaultValues(); + CreateMap() + .IgnoreNullAndDefaultValues(); + CreateMap() + .ForMember(dest => dest.Postal, opt => opt.MapFrom(src => src.PostalCode)) + .IgnoreNullAndDefaultValues(); } } +// Extension methods for reusable mapping configurations +public static class MappingExtensions +{ + /// + /// Configures the mapping to ignore null and default values for all members. + /// Useful for patch/update scenarios where only non-default values should be mapped. + /// + /// The source type. + /// The destination type. + /// The mapping expression. + /// The updated mapping expression. + public static IMappingExpression IgnoreNullAndDefaultValues( + this IMappingExpression expression) + { + expression.ForAllMembers(opts => + { + opts.AllowNull(); // Ignore Null Values for Lists and Collections + opts.Condition((src, dest, srcMember) => + srcMember != null && !IsValueDefault(srcMember)); // Ignore Null and Default Values for Properties + }); + + return expression; + } + + /// + /// Determines whether the provided value is the default value for its type. + /// + /// The value to check. + /// + /// true if the value is null or the default for its type; otherwise, false. + /// + public static bool IsValueDefault(object value) + { + if (value == null) + return true; + + Type type = value.GetType(); + // For reference types, null is the only default + if (!type.IsValueType) + return false; + + // For value types, compare with default instance + return value.Equals(Activator.CreateInstance(type)); + } +} diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/GrantManagerApplicationModule.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/GrantManagerApplicationModule.cs index 7692b4bfd..20808103a 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/GrantManagerApplicationModule.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/GrantManagerApplicationModule.cs @@ -27,20 +27,17 @@ using Unity.Payments.Integrations.Cas; using Unity.Flex; using Unity.Payments; -using Volo.Abp.Caching; using Volo.Abp.Quartz; using System; using Quartz; -using Microsoft.Extensions.Caching.StackExchangeRedis; using Unity.Modules.Shared.MessageBrokers.RabbitMQ; using Volo.Abp.BackgroundJobs; using Unity.Reporting; using Volo.Abp.DistributedLocking; -using Medallion.Threading.Redis; +using Unity.GrantManager.Zones; +using Unity.GrantManager.Infrastructure; using Medallion.Threading; -using StackExchange.Redis; using Unity.GrantManager.Locks; -using Unity.GrantManager.Zones; namespace Unity.GrantManager; @@ -141,8 +138,16 @@ public override void ConfigureServices(ServiceConfigurationContext context) context.Services.Configure(configuration.GetSection(key: "Notifications")); ConfigureBackgroundServices(configuration); - ConfigureDistributedCache(context, configuration); - ConfigureDistributedLocking(context, configuration); + + if (Convert.ToBoolean(configuration["Redis:IsEnabled"])) + { + RedisInfrastructureManager.ConfigureRedis(context.Services, configuration); + } + else + { + // We need this because adding the AbpDistributedLockingModule requires a provider + context.Services.AddSingleton(); + } context.Services.ConfigureRabbitMQ(); context.Services.AddScoped(); @@ -198,20 +203,6 @@ public override void ConfigureServices(ServiceConfigurationContext context) LimitedResultRequestDto.MaxMaxResultCount = int.MaxValue; } - private static void ConfigureDistributedLocking(ServiceConfigurationContext context, IConfiguration configuration) - { - if (!Convert.ToBoolean(configuration["Redis:IsEnabled"])) - { - context.Services.AddSingleton(); - return; - } - - var redisConnectionString = $"{configuration["Redis:Host"]}:{configuration["Redis:Port"]},password={configuration["Redis:Password"]}"; - var redisConnection = ConnectionMultiplexer.Connect(redisConnectionString); - - context.Services.AddSingleton(new RedisDistributedSynchronizationProvider(redisConnection.GetDatabase())); - } - private void ConfigureBackgroundServices(IConfiguration configuration) { if (!Convert.ToBoolean(configuration["BackgroundJobs:IsJobExecutionEnabled"])) return; @@ -235,26 +226,4 @@ private void ConfigureBackgroundServices(IConfiguration configuration) options.Quartz.IsAutoRegisterEnabled = configuration.GetValue("BackgroundJobs:Quartz:IsAutoRegisterEnabled"); }); } - - private void ConfigureDistributedCache(ServiceConfigurationContext context, IConfiguration configuration) - { - if (!Convert.ToBoolean(configuration["Redis:IsEnabled"])) return; - - context.Services.AddStackExchangeRedisCache(options => - { - options.InstanceName = configuration["Redis:InstanceName"]; - options.Configuration = $"{configuration["Redis:Host"]}:{configuration["Redis:Port"]},password={configuration["Redis:Password"]}"; - }); - - Configure(options => - { - options.InstanceName = configuration["Redis:InstanceName"]; - options.Configuration = $"{configuration["Redis:Host"]}:{configuration["Redis:Port"]},password={configuration["Redis:Password"]}"; - }); - - Configure(options => - { - options.KeyPrefix = configuration["Redis:KeyPrefix"] ?? "unity"; - }); - } } \ No newline at end of file diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Infrastructure/RedisInfrastructureManager.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Infrastructure/RedisInfrastructureManager.cs new file mode 100644 index 000000000..74b9f772a --- /dev/null +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Infrastructure/RedisInfrastructureManager.cs @@ -0,0 +1,111 @@ +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using StackExchange.Redis; +using Volo.Abp.Caching; +using System; +using Medallion.Threading.Redis; +using Medallion.Threading; +using System.Threading.Tasks; + +namespace Unity.GrantManager.Infrastructure +{ + internal static class RedisInfrastructureManager + { + private const string RedisInstanceNameKey = "Redis:InstanceName"; + private const string RedisPasswordKey = "Redis:Password"; + private const string RedisHostKey = "Redis:Host"; + private const string RedisPortKey = "Redis:Port"; + private const string RedisDefaultDatabaseKey = "Redis:DatabaseId"; + private const string RedisConfigurationKey = "Redis:Configuration"; + private const string RedisSentinelMasterNameKey = "Redis:SentinelMasterName"; + private const string RedisUseSentinel = "Redis:UseSentinel"; + private const string RedisKeyPrefix = "Redis:KeyPrefix"; + + internal static void ConfigureRedis(IServiceCollection services, IConfiguration configuration) + { + var useSentinel = Convert.ToBoolean(configuration[RedisUseSentinel]); + + // Helper to build ConfigurationOptions for Sentinel + ConfigurationOptions BuildSentinelOptions() + { + var sentinelMasterName = configuration[RedisSentinelMasterNameKey]; + var endpointConfiguration = configuration[RedisConfigurationKey]?.Split(',', StringSplitOptions.RemoveEmptyEntries); + var password = configuration[RedisPasswordKey]; + var defaultDatabase = configuration.GetValue(RedisDefaultDatabaseKey, 0); + + var options = new ConfigurationOptions + { + ServiceName = sentinelMasterName, + Password = password, + AbortOnConnectFail = false, + AllowAdmin = true, + DefaultVersion = new Version(7, 0, 0), + DefaultDatabase = defaultDatabase, + }; + + if (endpointConfiguration != null) + { + foreach (var endpoint in endpointConfiguration) + { + options.EndPoints.Add(endpoint.Trim()); + } + } + + return options; + } + + // Helper to build standard connection string + string BuildConnectionString() => + $"{configuration[RedisHostKey]}:{configuration[RedisPortKey]},password={configuration[RedisPasswordKey]},abortConnect=false"; + + // Lazy multiplexer registration + services.AddSingleton(sp => + { + if (useSentinel) + { + var options = BuildSentinelOptions(); + return ConnectionMultiplexer.Connect(options); + } + else + { + var connStr = BuildConnectionString(); + return ConnectionMultiplexer.Connect(connStr); + } + }); + + // Configure the cache + services.AddStackExchangeRedisCache(options => + { + if (useSentinel) + { + var sentinelOptions = BuildSentinelOptions(); + options.ConfigurationOptions = sentinelOptions; + options.ConnectionMultiplexerFactory = () => + { + // Use the same multiplexer as registered in DI + var provider = services.BuildServiceProvider(); + var muxer = provider.GetRequiredService(); + return Task.FromResult(muxer); + }; + } + else + { + options.InstanceName = configuration[RedisInstanceNameKey]; + options.Configuration = BuildConnectionString(); + } + }); + + services.Configure(options => + { + options.KeyPrefix = configuration[RedisKeyPrefix] ?? "unity"; + }); + + // Distributed lock provider + services.AddSingleton(sp => + { + var multiplexer = sp.GetRequiredService(); + return new RedisDistributedSynchronizationProvider(multiplexer.GetDatabase()); + }); + } + } +} diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Intakes/BackgroundWorkers/IntakeSyncWorker.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Intakes/BackgroundWorkers/IntakeSyncWorker.cs index 8a771abf6..bbd104010 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Intakes/BackgroundWorkers/IntakeSyncWorker.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Intakes/BackgroundWorkers/IntakeSyncWorker.cs @@ -4,6 +4,7 @@ using Unity.GrantManager.ApplicationForms; using Unity.GrantManager.Settings; using Unity.Modules.Shared.Utils; +using Unity.Notifications.EmailNotifications; using Volo.Abp.BackgroundWorkers.Quartz; using Volo.Abp.MultiTenancy; using Volo.Abp.SettingManagement; @@ -18,15 +19,18 @@ public class IntakeSyncWorker : QuartzBackgroundWorkerBase private readonly ITenantRepository _tenantRepository; private readonly IApplicationFormSycnronizationService _applicationFormSynchronizationService; private readonly string _numberOfDaysToCheck; + private readonly IEmailNotificationService _emailNotificationService; public IntakeSyncWorker(ICurrentTenant currentTenant, ITenantRepository tenantRepository, ISettingManager settingManager, - IApplicationFormSycnronizationService applicationFormSynchronizationService) + IApplicationFormSycnronizationService applicationFormSynchronizationService, + IEmailNotificationService emailNotificationService) { _currentTenant = currentTenant; _tenantRepository = tenantRepository; _applicationFormSynchronizationService = applicationFormSynchronizationService; + _emailNotificationService = emailNotificationService; string intakeResyncExpression = SettingDefinitions.GetSettingsValue(settingManager, SettingsConstants.BackgroundJobs.IntakeResync_Expression); _numberOfDaysToCheck = SettingDefinitions.GetSettingsValue(settingManager, SettingsConstants.BackgroundJobs.IntakeResync_NumDaysToCheck); @@ -55,14 +59,46 @@ public override async Task Execute(IJobExecutionContext context) return; } + bool sendEmail = false; + var emailBodyBuilder = new System.Text.StringBuilder(); + emailBodyBuilder.AppendLine("Hello,

This email is to inform you about recent CHEFS submissions that failed to be imported into Unity Production."); + foreach (var tenant in tenants) { using (_currentTenant.Change(tenant.Id, tenant.Name)) { - await _applicationFormSynchronizationService.GetMissingSubmissions(numberDaysBack); + var (missingSubmissions, submissionReport) = await _applicationFormSynchronizationService.GetMissingSubmissions(numberDaysBack); + if (missingSubmissions?.Count > 0) + { + emailBodyBuilder.AppendLine($"

Tenant: {tenant.Name}
{submissionReport}"); + sendEmail = true; + } } } + emailBodyBuilder.AppendLine("
Bests"); + string emailBody = emailBodyBuilder.ToString(); + + if (sendEmail) { + string htmlBody = $@" + + +

{emailBody}

+
+

*Note - Please do not reply to this email as it is an automated notification.

+ + "; + + await _emailNotificationService.SendEmailNotification( + "grantmanagementsupport@gov.bc.ca", + htmlBody, + "Unity Failed Submissions Notification", + "NoReply@gov.bc.ca", "html", + ""); + + Logger.LogInformation("Missing Submissions Email Sent..."); + } + Logger.LogInformation("IntakeSyncWorker Executed..."); await Task.CompletedTask; } 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 new file mode 100644 index 000000000..4eff7732c --- /dev/null +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Intakes/Events/ApplicationProcessEvent.cs @@ -0,0 +1,12 @@ +using Unity.GrantManager.Applications; + +namespace Unity.GrantManager.Intakes.Events +{ + public class ApplicationProcessEvent + { + public Application? Application { get; set; } + public ApplicationFormVersion? FormVersion { get; internal set; } + public ApplicationFormSubmission? ApplicationFormSubmission { get; internal set; } + public dynamic? RawSubmission { get; internal 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 new file mode 100644 index 000000000..118fa2ad3 --- /dev/null +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Intakes/Handlers/DetermineElectoralDistrictHandler.cs @@ -0,0 +1,89 @@ +using Microsoft.Extensions.Logging; +using System; +using System.Linq; +using System.Threading.Tasks; +using Unity.GrantManager.Intakes.Events; +using Unity.GrantManager.Integration.Geocoder; +using Volo.Abp.DependencyInjection; +using Volo.Abp.EventBus; + +namespace Unity.GrantManager.Intakes.Handlers +{ + public class DetermineElectoralDistrictHandler(IGeocoderApiService geocoderApiService, + ILogger logger) + : ILocalEventHandler, ITransientDependency + { + /// + /// Determines the Electoral Distrct based on the Address. + /// + /// + /// + public async Task HandleEventAsync(ApplicationProcessEvent eventData) + { + try + { + if (eventData.Application == null) + { + logger.LogWarning("Application data is null in DetermineElectoralDistrictHandler."); + return; + } + + if (eventData.FormVersion == null) + { + logger.LogWarning("Application data is null in DetermineElectoralDistrictHandler."); + return; + } + + // Check if the electoral district is already mapped for the form submission, if so then no work to be done + if (eventData.FormVersion.HasSubmissionHeaderMapping("ApplicantElectoralDistrict")) + return; + + var electoralDistrictAddressType = eventData.Application.ApplicationForm.ElectoralDistrictAddressType; + var applicantAddresses = eventData.Application.Applicant.ApplicantAddresses; + + if (applicantAddresses == null || applicantAddresses.Count == 0) + { + logger.LogWarning("Application data is null in DetermineElectoralDistrictHandler."); + return; + } + + // Find the related address type + var matchedAddressType = applicantAddresses + .FirstOrDefault(a => a.AddressType == electoralDistrictAddressType); + + if (matchedAddressType == null) + { + logger.LogWarning("No address of type {AddressType} found for application {ApplicationId}.", + electoralDistrictAddressType, eventData.Application.Id); + return; + } + + // Extract from geo services + var address = matchedAddressType.GetFullAddress(); + var geoAddressDetails = await geocoderApiService.GetAddressDetailsAsync(address); + + if (geoAddressDetails == null || geoAddressDetails.Coordinates == null) + { + logger.LogWarning("No coordinates found for address: {Address}", address); + return; + } + + var electoralDistrict = await geocoderApiService.GetElectoralDistrictAsync(geoAddressDetails.Coordinates); + + if (electoralDistrict.Name != null) + { + eventData.Application.Applicant.SetElectoralDistrict(electoralDistrict.Name); + } + else + { + logger.LogWarning("Electoral district could not be determined for address: {Address}", address); + } + } + catch (Exception ex) + { + logger.LogError(ex, "An error occurred while determining the electoral district."); + // Swallow the exception to ensure best effort and prevent propagation + } + } + } +} 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 new file mode 100644 index 000000000..189441218 --- /dev/null +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Intakes/Handlers/GenerateReportDataHandler.cs @@ -0,0 +1,49 @@ +using Microsoft.Extensions.Logging; +using System.Threading.Tasks; +using Unity.GrantManager.Intakes.Events; +using Unity.Modules.Shared.Features; +using Volo.Abp.DependencyInjection; +using Volo.Abp.EventBus; +using Volo.Abp.Features; +using Unity.GrantManager.Reporting.DataGenerators; + +namespace Unity.GrantManager.Intakes.Handlers +{ + public class GenerateReportDataHandler(IReportingDataGenerator reportingDataGenerator, + ILogger logger, + IFeatureChecker featureChecker) : ILocalEventHandler, ITransientDependency + { + /// + /// Generate Reporting for the submission + /// + /// + /// + public async Task HandleEventAsync(ApplicationProcessEvent eventData) + { + if (eventData == null) + { + logger.LogWarning("Event data is null in GenerateReportDataHandler."); + return; + } + + if (await featureChecker.IsEnabledAsync(FeatureConsts.Reporting)) + { + logger.LogInformation("Generating report data for application {ApplicationId}.", eventData.Application?.Id); + + if (eventData.ApplicationFormSubmission == null) + { + logger.LogWarning("ApplicationFormSubmission is null in GenerateReportDataHandler."); + return; + } + + if (await featureChecker.IsEnabledAsync(FeatureConsts.Reporting)) + { + eventData.ApplicationFormSubmission.ReportData = reportingDataGenerator + .Generate(eventData.RawSubmission, + eventData.FormVersion?.ReportKeys, + eventData.ApplicationFormSubmission.Id) ?? "{}"; + } + } + } + } +} diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Intakes/IntakeFormSubmissionManager.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Intakes/IntakeFormSubmissionManager.cs index df5819a7e..09f2e6d06 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Intakes/IntakeFormSubmissionManager.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Intakes/IntakeFormSubmissionManager.cs @@ -1,5 +1,4 @@ using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Logging.Abstractions; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using System; @@ -8,16 +7,17 @@ using Unity.GrantManager.Applicants; using Unity.GrantManager.Applications; using Unity.GrantManager.GrantApplications; +using Unity.GrantManager.Intakes.Events; using Unity.GrantManager.Intakes.Mapping; -using Unity.GrantManager.Reporting.DataGenerators; -using Unity.Modules.Shared.Features; +using Volo.Abp; using Volo.Abp.Domain.Repositories; using Volo.Abp.Domain.Services; -using Volo.Abp.Features; +using Volo.Abp.EventBus.Local; using Volo.Abp.Uow; namespace Unity.GrantManager.Intakes { + [RemoteService(IsEnabled = false)] public class IntakeFormSubmissionManager(IUnitOfWorkManager _unitOfWorkManager, IApplicantAppService applicantService, IApplicationRepository _applicationRepository, @@ -26,11 +26,8 @@ public class IntakeFormSubmissionManager(IUnitOfWorkManager _unitOfWorkManager, IIntakeFormSubmissionMapper _intakeFormSubmissionMapper, IApplicationFormVersionRepository _applicationFormVersionRepository, CustomFieldsIntakeSubmissionMapper _customFieldsIntakeSubmissionMapper, - IReportingDataGenerator _reportingDataGenerator, - IFeatureChecker featureChecker) : DomainService, IIntakeFormSubmissionManager + ILocalEventBus localEventBus) : DomainService, IIntakeFormSubmissionManager { - protected ILogger logger => LazyServiceProvider.LazyGetService(provider => LoggerFactory?.CreateLogger(GetType().FullName!) ?? NullLogger.Instance); - public async Task GetApplicationFormVersionMapping(string chefsFormVersionId) { var applicationFormVersion = (await _applicationFormVersionRepository @@ -70,23 +67,29 @@ public async Task ProcessFormSubmissionAsync(ApplicationForm applicationFo ApplicationFormId = applicationForm.Id, ChefsSubmissionGuid = intakeMap.SubmissionId ?? $"{Guid.Empty}", ApplicationId = application.Id, - Submission = dataNode?.ToString() ?? string.Empty + Submission = dataNode?.ToString() ?? string.Empty }; _ = await _applicationFormSubmissionRepository.InsertAsync(newSubmission); ApplicationFormVersion? localFormVersion = await _applicationFormVersionRepository.GetByChefsFormVersionAsync(Guid.Parse(formVersionId)); + await _customFieldsIntakeSubmissionMapper.MapAndPersistCustomFields(application.Id, localFormVersion?.Id ?? Guid.Empty, formSubmission, formVersionSubmissionHeaderMapping); - if (await featureChecker.IsEnabledAsync(FeatureConsts.Reporting)) - { - newSubmission.ReportData = _reportingDataGenerator.Generate(formSubmission, localFormVersion?.ReportKeys, newSubmission.Id); - } - newSubmission.ApplicationFormVersionId = localFormVersion?.Id; + newSubmission.FormVersionId = string.IsNullOrWhiteSpace(localFormVersion?.ChefsFormVersionGuid) ? null : Guid.Parse(localFormVersion.ChefsFormVersionGuid); + + // Extend any further processing of the application here through local event bus and handlers + await localEventBus.PublishAsync(new ApplicationProcessEvent + { + Application = application, + FormVersion = localFormVersion, + ApplicationFormSubmission = newSubmission, + RawSubmission = formSubmission + }); await uow.SaveChangesAsync(); @@ -104,7 +107,7 @@ private async Task CreateNewApplicationAsync(IntakeMapping intakeMa ProjectName = MappingUtil.ResolveAndTruncateField(255, string.Empty, intakeMap.ProjectName), ApplicantId = applicant.Id, ApplicationFormId = applicationForm.Id, - ApplicationStatusId = submittedStatus.Id, + ApplicationStatusId = submittedStatus.Id, ReferenceNo = intakeMap.ConfirmationId ?? string.Empty, Acquisition = intakeMap.Acquisition, Forestry = intakeMap.Forestry, @@ -130,23 +133,27 @@ private async Task CreateNewApplicationAsync(IntakeMapping intakeMa ProjectSummary = intakeMap.ProjectSummary, } ); - ApplicantAgentDto applicantAgentDto = new ApplicantAgentDto + + ApplicantAgentDto applicantAgentDto = new() { Applicant = applicant, Application = application, IntakeMap = intakeMap }; - + await applicantService.CreateApplicantAgentAsync(applicantAgentDto); - try { + try + { await applicantService.RelateDefaultSupplierAsync(applicantAgentDto); - } catch (Exception ex) { + } + catch (Exception ex) + { // This was failing with SSL Certificate errors, so we're catching the exception and logging it string MessageException = ex.Message; - logger.LogError(ex, "Error Relating Default Supplier {MessageException}", MessageException); + Logger.LogError(ex, "Error Relating Default Supplier {MessageException}", MessageException); } - + return application; } diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Intakes/IntakeSubmissionAppService.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Intakes/IntakeSubmissionAppService.cs index fe242daf1..a19e4db14 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Intakes/IntakeSubmissionAppService.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Intakes/IntakeSubmissionAppService.cs @@ -119,7 +119,7 @@ private async Task SendTeamsNotification(string factName, string factValue) string activityTitle = "Chefs Submission Event Validation Error"; string activitySubtitle = "Environment: " + envInfo; string teamsChannel = _configuration["Notifications:TeamsNotificationsWebhook"] ?? ""; - TeamsNotificationService teamsNotificationService = new TeamsNotificationService(); + TeamsNotificationService teamsNotificationService = new(); teamsNotificationService.AddFact(factName, factValue); await teamsNotificationService.PostFactsToTeamsAsync(teamsChannel, activityTitle, activitySubtitle); } diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Intakes/SubmissionAppService.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Intakes/SubmissionAppService.cs index 407b998dd..aa77546fd 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Intakes/SubmissionAppService.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Intakes/SubmissionAppService.cs @@ -9,48 +9,28 @@ using System.Threading.Tasks; using Unity.GrantManager.Applications; using Unity.GrantManager.Attachments; +using Unity.GrantManager.GrantApplications; using Volo.Abp.Application.Dtos; using Volo.Abp.Domain.Repositories; using Volo.Abp.Security.Encryption; +using Volo.Abp.TenantManagement; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Abstractions; namespace Unity.GrantManager.Intakes; [Authorize] -public class SubmissionAppService : GrantManagerAppService, ISubmissionAppService -{ - private readonly IApplicationFormSubmissionRepository _applicationFormSubmissionRepository; - private readonly IRepository _applicationFormRepository; - private readonly RestClient _intakeClient; - private readonly IStringEncryptionService _stringEncryptionService; - private static List SummaryFieldsFilter - { - // NOTE: This will be replaced by a customizable filter. - get - { - return new List(new string[] { - "projectTitle", - "projectLocation", - "contactName", - "organizationLegalName", - "eligibleCost", - "totalRequest" - }); - } - } - - public SubmissionAppService( +public class SubmissionAppService( IApplicationFormSubmissionRepository applicationFormSubmissionRepository, IRepository applicationFormRepository, RestClient restClient, - IStringEncryptionService stringEncryptionService - ) - { - _applicationFormSubmissionRepository = applicationFormSubmissionRepository; - _applicationFormRepository = applicationFormRepository; - _intakeClient = restClient; - _stringEncryptionService = stringEncryptionService; - } + IStringEncryptionService stringEncryptionService, + IApplicationRepository applicationRepository, + ITenantRepository tenantRepository + ) : GrantManagerAppService, ISubmissionAppService +{ + protected ILogger logger => LazyServiceProvider.LazyGetService(provider => LoggerFactory?.CreateLogger(GetType().FullName!) ?? NullLogger.Instance); public async Task GetSubmission(Guid? formSubmissionId) { @@ -116,10 +96,10 @@ public async Task GetChefsFileAttachment(Guid? formSubmissionId, Guid? var request = new RestRequest($"/files/{chefsFileAttachmentId}", Method.Get) { - Authenticator = new HttpBasicAuthenticator(applicationForm.ChefsApplicationFormGuid!, _stringEncryptionService.Decrypt(applicationForm.ApiKey!) ?? string.Empty) + Authenticator = new HttpBasicAuthenticator(applicationForm.ChefsApplicationFormGuid!, stringEncryptionService.Decrypt(applicationForm.ApiKey!) ?? string.Empty) }; - var response = await _intakeClient.GetAsync(request); + var response = await restClient.GetAsync(request); if (((int)response.StatusCode) != 200) @@ -137,8 +117,8 @@ public async Task GetChefsFileAttachment(Guid? formSubmissionId, Guid? if (formSubmissionId != null) { - var query = from applicationSubmission in await _applicationFormSubmissionRepository.GetQueryableAsync() - join applicationForm in await _applicationFormRepository.GetQueryableAsync() on applicationSubmission.ApplicationFormId equals applicationForm.Id + var query = from applicationSubmission in await applicationFormSubmissionRepository.GetQueryableAsync() + join applicationForm in await applicationFormRepository.GetQueryableAsync() on applicationSubmission.ApplicationFormId equals applicationForm.Id where applicationSubmission.ChefsSubmissionGuid == formSubmissionId.ToString() select applicationForm; applicationFormData = await AsyncExecuter.FirstOrDefaultAsync(query); @@ -152,7 +132,7 @@ join applicationForm in await _applicationFormRepository.GetQueryableAsync() on if (formSubmissionId != null) { - var query = from applicationFormSubmission in await _applicationFormSubmissionRepository.GetQueryableAsync() + var query = from applicationFormSubmission in await applicationFormSubmissionRepository.GetQueryableAsync() where applicationFormSubmission.ChefsSubmissionGuid == formSubmissionId.ToString() select applicationFormSubmission; applicationFormSubmissionData = await AsyncExecuter.FirstOrDefaultAsync(query); @@ -160,46 +140,89 @@ join applicationForm in await _applicationFormRepository.GetQueryableAsync() on return applicationFormSubmissionData; } - public async Task> GetSubmissionsList(Guid? formId) + public async Task> GetSubmissionsList(bool allSubmissions) { - if (formId == null) - { - throw new ApiException(400, "Missing required parameter 'formId' when calling ListFormSubmissions"); - } - - var request = new RestRequest($"/forms/{formId}/submissions", Method.Get) - .AddParameter("fields", SummaryFieldsFilter.JoinAsString(",")); - - var response = await _intakeClient.GetAsync(request); - - if (((int)response.StatusCode) >= 400) - { - throw new ApiException((int)response.StatusCode, "Error calling ListFormSubmissions: " + response.Content, response.ErrorMessage ?? $"{response.StatusCode}"); - } - else if (((int)response.StatusCode) == 0) - { - throw new ApiException((int)response.StatusCode, "Error calling ListFormSubmissions: " + response.ErrorMessage, response.ErrorMessage ?? $"{response.StatusCode}"); - } - - var submissionOptions = new JsonSerializerOptions - { - WriteIndented = true, - PropertyNameCaseInsensitive = true, - ReadCommentHandling = JsonCommentHandling.Skip, - DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull - }; - - List? jsonResponse = JsonSerializer.Deserialize>(response.Content ?? string.Empty, submissionOptions); - - if (null == jsonResponse) - { - return new PagedResultDto(0, new List()); - } - else - { - // Remove all deleted and draft submissions - jsonResponse.RemoveAll(r => r.Deleted || r.FormSubmissionStatusCode != "SUBMITTED"); - return new PagedResultDto(jsonResponse.Count, jsonResponse); - } + List chefsSubmissions = new List(); + + var tenants = await tenantRepository.GetListAsync(); + foreach (var tenant in tenants) + { + using (CurrentTenant.Change(tenant.Id)) + { + var groupedResult = await applicationRepository.WithFullDetailsGroupedAsync(0, int.MaxValue); + var appDtos = new List(); + var rowCounter = 0; + + List checkedForms = new List(); + + foreach (var grouping in groupedResult) + { + var appDto = ObjectMapper.Map(grouping.First()); + appDto.RowCount = rowCounter; + appDtos.Add(appDto); + rowCounter++; + + // Chef's API call to get submissions + if (!checkedForms.Contains(appDto.ApplicationForm.ChefsApplicationFormGuid ?? string.Empty)) + { + + var id = appDto.ApplicationForm.ChefsApplicationFormGuid; + var apiKey = stringEncryptionService.Decrypt(appDto.ApplicationForm.ApiKey! ?? string.Empty); + var request = new RestRequest($"/forms/{id}/submissions", Method.Get) + .AddParameter("fields", "applicantAgent.name"); + request.Authenticator = new HttpBasicAuthenticator(id ?? "ID", apiKey ?? "no api key given"); + + RestResponse? response = null; + try + { + response = await restClient.GetAsync(request); + var submissionOptions = new JsonSerializerOptions + { + WriteIndented = true, + PropertyNameCaseInsensitive = true, + ReadCommentHandling = JsonCommentHandling.Skip, + DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull + }; + + var submissions = JsonSerializer.Deserialize>(response.Content ?? string.Empty, submissionOptions); + if (submissions != null) + { + foreach (var submission in submissions) + { + submission.tenant = tenant.Name; + submission.form = appDto.ApplicationForm.ApplicationFormName ?? string.Empty; + submission.category = appDto.ApplicationForm.Category ?? string.Empty; + } + chefsSubmissions.AddRange(submissions); + } + } + catch (Exception ex) + { + var ExceptionMessage = ex.Message; + logger.LogError(ex, "GetSubmissionsList Exception: {ExceptionMessage}", ExceptionMessage); + } + + checkedForms.Add(id ?? string.Empty); + } + } + + // Set inUnity property for each submission based on whether it exists in appDtos + foreach (var submission in chefsSubmissions) + { + submission.inUnity = appDtos.Any(appDto => submission.ConfirmationId.ToString() == appDto.ReferenceNo); + } + + + // Remove chef's submissions if Unity has an application with the same reference number + if (!allSubmissions) + { + chefsSubmissions.RemoveAll(r => appDtos.Any(appDto => r.ConfirmationId.ToString() == appDto.ReferenceNo)); + } + } + } + + // Remove all deleted submissions + chefsSubmissions.RemoveAll(r => r.Deleted); + return new PagedResultDto(chefsSubmissions.Count, chefsSubmissions); } } \ No newline at end of file diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Integrations/Geocoder/GeocoderApiService.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Integrations/Geocoder/GeocoderApiService.cs index 5352da0eb..4c3d6c3a4 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Integrations/Geocoder/GeocoderApiService.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Integrations/Geocoder/GeocoderApiService.cs @@ -1,44 +1,35 @@ -using Microsoft.Extensions.Configuration; +using Microsoft.AspNetCore.Authorization; +using Microsoft.Extensions.Configuration; using Newtonsoft.Json; using RestSharp; using System.Threading.Tasks; using Unity.GrantManager.Integration.Geocoder; using Unity.GrantManager.Integrations.Exceptions; using Unity.GrantManager.Integrations.Http; -using Volo.Abp; using Volo.Abp.Application.Services; -using Volo.Abp.DependencyInjection; namespace Unity.GrantManager.Integrations.Geocoder { - [IntegrationService] - [ExposeServices(typeof(GeocoderApiService), typeof(IGeocoderApiService))] - public class GeocoderApiService : ApplicationService, IGeocoderApiService + //[IntegrationService] + //[ExposeServices(typeof(GeocoderApiService), typeof(IGeocoderApiService))] + [AllowAnonymous] + public class GeocoderApiService(IResilientHttpRequest resilientRestClient, IConfiguration configuration) : ApplicationService, IGeocoderApiService { - private readonly IResilientHttpRequest _resilientRestClient; - private readonly IConfiguration _configuration; - - public GeocoderApiService(IResilientHttpRequest resilientRestClient, IConfiguration configuration) - { - _resilientRestClient = resilientRestClient; - _configuration = configuration; - } - public async Task GetAddressDetailsAsync(string address) { - var resource = $"{_configuration["Geocoder:LocationDetails:BaseUri"]}/addresses.json?outputSRS=3005&addressString={address}"; + var resource = $"{configuration["Geocoder:LocationDetails:BaseUri"]}/addresses.json?outputSRS=3005&addressString={address}"; return ResultMapper.MapToLocation(await GetGeoCodeDataSegmentAsync(resource)); } public async Task GetElectoralDistrictAsync(LocationCoordinates locationCoordinates) { - var resource = $"{_configuration["Geocoder:BaseUri"]}" + - $"{_configuration["Geocoder:ElectoralDistrict:feature"]}" + + var resource = $"{configuration["Geocoder:BaseUri"]}" + + $"{configuration["Geocoder:ElectoralDistrict:feature"]}" + $"&srsname=EPSG:4326" + - $"&propertyName={_configuration["Geocoder:ElectoralDistrict:property"]}" + + $"&propertyName={configuration["Geocoder:ElectoralDistrict:property"]}" + $"&outputFormat=application/json" + - $"&cql_filter=INTERSECTS({_configuration["Geocoder:ElectoralDistrict:querytype"]}" + + $"&cql_filter=INTERSECTS({configuration["Geocoder:ElectoralDistrict:querytype"]}" + $",POINT(" + locationCoordinates.Latitude.ToString() + " " + locationCoordinates.Longitude.ToString() + "))"; return ResultMapper.MapToElectoralDistrict(await GetGeoCodeDataSegmentAsync(resource)); @@ -46,12 +37,12 @@ public async Task GetElectoralDistrictAsync(LocationCoordi public async Task GetEconomicRegionAsync(LocationCoordinates locationCoordinates) { - var resource = $"{_configuration["Geocoder:BaseUri"]}" + - $"{_configuration["Geocoder:EconomicRegion:feature"]}" + + var resource = $"{configuration["Geocoder:BaseUri"]}" + + $"{configuration["Geocoder:EconomicRegion:feature"]}" + $"&srsname=EPSG:4326" + - $"&propertyName={_configuration["Geocoder:EconomicRegion:property"]}" + + $"&propertyName={configuration["Geocoder:EconomicRegion:property"]}" + $"&outputFormat=application%2Fjson" + - $"&cql_filter=INTERSECTS({_configuration["Geocoder:EconomicRegion:querytype"]}" + + $"&cql_filter=INTERSECTS({configuration["Geocoder:EconomicRegion:querytype"]}" + $",POINT(" + locationCoordinates.Latitude.ToString() + " " + locationCoordinates.Longitude.ToString() + "))"; return ResultMapper.MapToEconomicRegion(await GetGeoCodeDataSegmentAsync(resource)); @@ -59,12 +50,12 @@ public async Task GetEconomicRegionAsync(LocationCoordinates public async Task GetRegionalDistrictAsync(LocationCoordinates locationCoordinates) { - var resource = $"{_configuration["Geocoder:BaseUri"]}" + - $"{_configuration["Geocoder:RegionalDistrict:feature"]}" + + var resource = $"{configuration["Geocoder:BaseUri"]}" + + $"{configuration["Geocoder:RegionalDistrict:feature"]}" + $"&srsname=EPSG:4326" + - $"&propertyName={_configuration["Geocoder:RegionalDistrict:property"]}" + + $"&propertyName={configuration["Geocoder:RegionalDistrict:property"]}" + $"&outputFormat=application/json" + - $"&cql_filter=INTERSECTS({_configuration["Geocoder:RegionalDistrict:querytype"]}" + + $"&cql_filter=INTERSECTS({configuration["Geocoder:RegionalDistrict:querytype"]}" + $",POINT(" + locationCoordinates.Latitude.ToString() + " " + locationCoordinates.Longitude.ToString() + "))"; return ResultMapper.MapToRegionalDistrict(await GetGeoCodeDataSegmentAsync(resource)); @@ -72,7 +63,7 @@ public async Task GetRegionalDistrictAsync(LocationCoordina private async Task GetGeoCodeDataSegmentAsync(string resource) { - var response = await _resilientRestClient.HttpAsync(Method.Get, resource); + var response = await resilientRestClient.HttpAsync(Method.Get, resource); if (response != null && response.Content != null 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 2eafb09a1..8da6f0802 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Locality/ElectoralDistrictAppService.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Locality/ElectoralDistrictAppService.cs @@ -22,7 +22,7 @@ public class ElectoralDistrictAppService(IElectoralDistrictRepository electoralD public virtual async Task> GetListAsync() { var electoralDistrictsCache = await cache.GetOrAddAsync( - SettingsConstants.EconomicRegionsCacheKey, + SettingsConstants.ElectoralDistrictsCacheKey, GetElectoralDistrictsAsync, () => new DistributedCacheEntryOptions { diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Domain.Shared/GrantApplications/AddressType.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Domain.Shared/GrantApplications/AddressType.cs index e140b5d28..cd1e957d9 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Domain.Shared/GrantApplications/AddressType.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Domain.Shared/GrantApplications/AddressType.cs @@ -1,9 +1,11 @@ -namespace Unity.GrantManager.GrantApplications +using System.Text.Json.Serialization; + +namespace Unity.GrantManager.GrantApplications; + +[JsonConverter(typeof(JsonStringEnumConverter))] +public enum AddressType { - public enum AddressType - { - PhysicalAddress = 1, - MailingAddress = 2, - BusinessAddress = 3 - } + PhysicalAddress = 1, + MailingAddress = 2, + BusinessAddress = 3 } \ No newline at end of file diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Domain.Shared/Localization/GrantManager/en.json b/applications/Unity.GrantManager/src/Unity.GrantManager.Domain.Shared/Localization/GrantManager/en.json index 1a3a9ed2d..415b3f886 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Domain.Shared/Localization/GrantManager/en.json +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Domain.Shared/Localization/GrantManager/en.json @@ -125,6 +125,7 @@ "Permission:GrantApplicationManagement.Applications.Default": "Applications", "Permission:GrantApplicationManagement.Applicants.Default": "Applicants", "Permission:GrantApplicationManagement.Applicants.Edit": "Edit Applicant", + "Permission:GrantApplicationManagement.Applicants.AssignApplicant": "Assign Applicant to an Application", "Permission:GrantApplicationManagement.Assignments.Default": "Assignment", "Permission:GrantApplicationManagement.Assignments.AssignInitial": "Initial Assignment", "Permission:GrantApplicationManagement.Reviews.Default": "Reviews", @@ -135,6 +136,7 @@ "Permission:GrantApplicationManagement.Assessments.Complete": "Complete Assessment", "Permission:GrantApplicationManagement.Approvals.Default": "Approvals", "Permission:GrantApplicationManagement.Approvals.Complete": "Complete Approval", + "Permission:GrantApplicationManagement.Approvals.DeferAfterApproval": "Defer After Approval", "Permission:GrantApplicationManagement.Comments.Default": "Comments", "Permission:GrantApplicationManagement.Comments.Add": "Add Application Comment", "Permission:GrantApplicationManagement.Organizations.Default": "Organizations", @@ -159,6 +161,9 @@ "ApplicationForms:Payable": "Payable", "ApplicationForms:RenderFormIoToHtml": "Render FormIO to HTML", "ApplicationForms:ConfigureWorksheets": "Configure Worksheets", + "ApplicationForms.Configuration.Notes:BypassAssessmentWorkflow": "Enabling this feature will bypass the Assessment workflow when you approve submissions associated with this form.", + "ApplicationForms.Configuration.Notes:SelectedApplicantElectoralAddress": "The selected address type will determine which submitted applicant address is used to extract the electoral district.", + "ApplicationForms.Configuration.Warnings:ApplicantElectoralAddressTypeChange": "Changing the address type will only affect new submissions. Existing applications will retain the electoral district extracted from their original address type.", "Intakes": "Intakes", @@ -183,11 +188,13 @@ "Unity.GrantManager.ApplicationManagement.Review.Results.Update": "Edit Application Assessment Results", "Unity.GrantManager.ApplicationManagement.Review.ReviewList": "Assessment List", - "Unity.GrantManager.ApplicationManagement.Project": "Project", + "Unity.GrantManager.ApplicationManagement.Project": "Project Info", "Unity.GrantManager.ApplicationManagement.Project.Summary": "Project Summary", "Unity.GrantManager.ApplicationManagement.Project.Summary.Update": "Edit Project Summary", + "Unity.GrantManager.ApplicationManagement.Project.Summary.Update.UpdateFinalStateFields": "Edit Project Summary after approval", "Unity.GrantManager.ApplicationManagement.Project.Location": "Project Location", "Unity.GrantManager.ApplicationManagement.Project.Location.Update": "Edit Project Location", + "Unity.GrantManager.ApplicationManagement.Project.Location.Update.UpdateFinalStateFields": "Edit Project Location after approval", "Unity.GrantManager.ApplicationManagement.Applicant": "Applicant Info", "Unity.GrantManager.ApplicationManagement.Applicant.Summary": "Applicant Info", @@ -198,6 +205,9 @@ "Unity.GrantManager.ApplicationManagement.Applicant.Authority.Update": "Edit Signing Authority", "Unity.GrantManager.ApplicationManagement.Applicant.Location": "Address", "Unity.GrantManager.ApplicationManagement.Applicant.Location.Update": "Edit Address", + "Unity.GrantManager.ApplicationManagement.Applicant.AdditionalContact": "Additional Contact(s)", + "Unity.GrantManager.ApplicationManagement.Applicant.AdditionalContact.Create": "Add Additional Contact(s)", + "Unity.GrantManager.ApplicationManagement.Applicant.AdditionalContact.Update": "Edit Additional Contact(s)", "Unity.GrantManager.ApplicationManagement.Funding": "Funding", "Unity.GrantManager.ApplicationManagement.Funding.Agreement": "Funding Agreement", @@ -206,12 +216,19 @@ "Unity.GrantManager.ApplicationManagement.Payment": "Payment", "Unity.GrantManager.ApplicationManagement.Payment.Summary": "Payment Summary", "Unity.GrantManager.ApplicationManagement.Payment.Summary.Update": "Edit Payment Summary", + "Unity.GrantManager.ApplicationManagement.Payment.Supplier": "Supplier Info", + "Unity.GrantManager.ApplicationManagement.Payment.Supplier.Update": "Edit Supplier Info", "Unity.GrantManager.ApplicationManagement.Payment.PaymentList": "Payment List", "Permission:GrantApplicationManagement.ProjectInfo": "Project Info", "Permission:GrantApplicationManagement.ProjectInfo.Update": "Project Info Update", "Permission:GrantApplicationManagement.ProjectInfo.Update.UpdateFinalStateFields": "Edit Project Info Fields After Approval", + "Unity.GrantManager.SettingManagement.Tags": "Manage Tags", + "Unity.GrantManager.SettingManagement.Tags.Create": "Create Tag", + "Unity.GrantManager.SettingManagement.Tags.Update": "Edit Tag", + "Unity.GrantManager.SettingManagement.Tags.Delete": "Delete Tag", + "GrantManager:AssessmentUserAssignmentAlreadyExists": "Business Exception: You cannot create two assessments on an application for the same user.", "GrantManager:CantCreateAssessmentForFinalStateApplication": "Business Exception: You cannot create an assessment for an application in final state.", @@ -321,7 +338,7 @@ "Summary:Assessment.Batch": "Batch #", "Summary:ApplicationTags": "Application Tags", - "ProjectInfoView:ProjectInfoTitle": "Project Summary", + "Unity.GrantManager.ApplicationManagement.Project.Summary:DisplayName": "Project Summary", "ProjectInfoView:ProjectInfo.ProjectName": "Project Name", "ProjectInfoView:ProjectInfo.ProjectSummary": "Project Summary", "ProjectInfoView:ProjectInfo.ProjectStartDate": "Project Start Date", @@ -334,7 +351,7 @@ "ProjectInfoView:ProjectInfo.SubSector": "Sub Sector", "ProjectInfoView:ProjectInfo.Community": "Community", "ProjectInfoView:ProjectInfo.EconomicRegion": "Economic Region", - "ProjectInfoView:ProjectInfo.ElectoralDistrict": "Electoral District", + "ProjectInfoView:ProjectInfo.ElectoralDistrict": "Project Electoral District", "ProjectInfoView:ProjectInfo.CommunityPopulation": "Community Population", "ProjectInfoView:ProjectInfo.Place": "Place", "ProjectInfoView:ProjectInfo.Acquisition": "Acquisition", @@ -342,7 +359,8 @@ "ProjectInfoView:ProjectInfo.ForestryFocus": "Forestry Focus", "ProjectInfoView:ProjectInfo.CensusSubdivision": "Census Subdivision", "ProjectInfoView:ProjectInfo.RegionalDistrict": "Regional District", - "ProjectInfoView:ProjectInfoLocation": "Project Location", + + "Unity.GrantManager.ApplicationManagement.Project.Location:DisplayName": "Project Location", "ProjectInfoView:ProjectInfoContactInfo": "Contact Info", "ProjectInfoView:ProjectInfo.ContactFullName": "Contact Full Name", "ProjectInfoView:ProjectInfo.ContactTitle": "Contact Title", @@ -350,9 +368,6 @@ "ProjectInfoView:ProjectInfo.ContactBusinessPhone": "Contact Business Phone", "ProjectInfoView:ProjectInfo.ContactCellPhone": "Contact Cell Phone", - "Permission:GrantApplicationManagement.ApplicantInfo": "Applicant Info", - "Permission:GrantApplicationManagement.ApplicantInfo.Update": "Applicant Info Update", - "ApplicantInfoView:ApplicantInfoContactInfo": "Contact Info", "ApplicantInfoView:SigningAuthorityTitle": "Signing Authority", "ApplicantInfoView:PhysicalAddress": "Physical Address", @@ -391,6 +406,16 @@ "ApplicantInfoView:ApplicantInfo.NonRegOrgName": "Non-Registered Organization Name", "ApplicantInfoView:ApplicantInfo.OrgBookSearchPlaceholder": "Start typing to search for your registered organization name", "ApplicantInfoView:ApplicantInfo.OrgBookSearch": "Search in BC Registries", + "ApplicantInfoView:ElectoralDistrict": "Electoral District", + "ApplicantInfoView:ApplicantElectoralDistrict": "Applicant Electoral District", + "ApplicantInfoView:Notes.ElectoralDistrict": "The electoral district is identified based on the {0}", + "ApplicantInfoView:ApplicantInfo.ApplicantLookUp": "Applicant Look up", + "ApplicantInfoView:ApplicantInfo.ApplicantLookUpPlaceholder": "Start typing applicant name or number to search for applicant...", + "ApplicantInfoView:ApplicantInfo.PrincipalRecord": "Principal Record", + "ApplicantInfoView:ApplicantInfo.Principal": "Use as a Principal", + "ApplicantInfoView:ApplicantInfo.ApplicantName": "Applicant Name", + + "FundingAgreementInfoView:FundingAgreementInfoTitle": "Funding Agreement", "FundingAgreementInfoView:FundingAgreementInfoContract": "Contract", @@ -423,6 +448,7 @@ "ApplicationBatchApprovalRequest:InvalidStatus": "The assessment for the selected item is not in the Assessment Completed state", "ApplicationBatchApprovalRequest:InvalidPermissions": "Invalid permissions", "ApplicationBatchApprovalRequest:InvalidApprovedAmount": "Invalid Approved Amount, it must be greater than 0.00", - "ApplicationBatchApprovalRequest:MaxCountExceeded": "You have exceeded the maximum number of items for bulk approval. Please reduce the number to {0} or fewer" + "ApplicationBatchApprovalRequest:MaxCountExceeded": "You have exceeded the maximum number of items for bulk approval. Please reduce the number to {0} or fewer", + "ApplicationBatchApprovalRequest:InvalidRecommendedAmount": "Invalid Recommended Amount, it must be greater than 0.00" } } diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Domain.Shared/Permissions/GrantApplicationPermissions.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Domain.Shared/Permissions/GrantApplicationPermissions.cs index 9144c6ee6..9bbf55137 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Domain.Shared/Permissions/GrantApplicationPermissions.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Domain.Shared/Permissions/GrantApplicationPermissions.cs @@ -36,6 +36,7 @@ public static class Applicants { public const string Default = GroupName + ".Applicants"; public const string Edit = Default + Operation.Update; + public const string AssignApplicant = Default + ".AssignApplicant"; } public static class Assignments @@ -56,6 +57,7 @@ public static class Approvals public const string Default = GroupName + ".Approvals"; public const string Complete = Default + ".Complete"; public const string BulkApplicationApproval = Default + ".BulkApplicationApproval"; + public const string DeferAfterApproval = Default + ".DeferAfterApproval"; } public static class Comments @@ -82,13 +84,6 @@ public static class ApplicantInfo public const string DeleteAdditionalContact = Default + ".AdditionalContact" + Operation.Delete; } - public static class ProjectInfo - { - public const string Default = GroupName + ".ProjectInfo"; - public const string Update = Default + Operation.Update; - public const string UpdateFinalStateFields = Update + ".UpdateFinalStateFields"; - } - public static string[] GetAll() { return ReflectionHelper.GetPublicConstantsRecursively(typeof(GrantApplicationPermissions)); diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Domain/Applications/Applicant.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Domain/Applications/Applicant.cs index cd4beb5a6..981ef90a5 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Domain/Applications/Applicant.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Domain/Applications/Applicant.cs @@ -32,4 +32,14 @@ public class Applicant : AuditedAggregateRoot, IMultiTenant public virtual Collection? ApplicantAddresses { get; set; } public decimal? MatchPercentage { get; set; } public string? NonRegOrgName { get; set; } + public bool? IsDuplicated { get; set; } + + // This is the Applicant's Electoral District, not the Project Level Electoral District. + public string? ElectoralDistrict { get; set; } + + public Applicant SetElectoralDistrict(string? electoralDistrict) + { + ElectoralDistrict = electoralDistrict; + return this; + } } diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Domain/Applications/ApplicantAddress.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Domain/Applications/ApplicantAddress.cs index 7a79d3379..4040b0ee8 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Domain/Applications/ApplicantAddress.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Domain/Applications/ApplicantAddress.cs @@ -1,4 +1,5 @@ using System; +using System.Linq; using System.Text.Json.Serialization; using Unity.GrantManager.GrantApplications; using Volo.Abp.Domain.Entities.Auditing; @@ -28,4 +29,27 @@ public virtual Applicant Applicant public string? Unit { get; set; } = string.Empty; public AddressType AddressType { get; set; } = AddressType.PhysicalAddress; public Guid? TenantId { get; set; } + + /// + /// Returns the address as a single comma-separated string, ordered by relevance. + /// + public string GetFullAddress() + { + var parts = new[] + { + Street, + Street2, + Unit, + City, + Province, + Postal, + Country + }; + + var address = string.Join(", ", parts + .Where(p => !string.IsNullOrWhiteSpace(p)) + .Select(p => p!.Trim())); + + return address; + } } diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Domain/Applications/Application.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Domain/Applications/Application.cs index 58bc8069c..c83cf9326 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Domain/Applications/Application.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Domain/Applications/Application.cs @@ -109,7 +109,9 @@ public virtual ApplicationStatus ApplicationStatus public string? ForestryFocus { get; set; } + // This is the Project Level Electoral District, not the Applicant's Electoral District. public string? ElectoralDistrict { get; set; } + public string? Place { get; set; } public string? RegionalDistrict { get; set; } @@ -143,6 +145,9 @@ public void UpdateAlwaysChangeableFields(string? notes, string? subStatus, strin TotalProjectBudget = totalProjectBudget ?? 0; NotificationDate = notificationDate; RiskRanking = riskRanking; + + // Recalculate percentage when TotalProjectBudget changes + UpdatePercentageTotalProjectBudget(); } public void UpdateApprovalFieldsRequiringPostEditPermission(decimal? approvedAmount) @@ -154,6 +159,9 @@ public void UpdateAssessmentResultFieldsRequiringPostEditPermission(decimal? req { RequestedAmount = requestedAmount ?? 0; TotalScore = totalScore ?? 0; + + // Recalculate percentage when RequestedAmount changes + UpdatePercentageTotalProjectBudget(); } public void UpdateAssessmentResultStatus(string? assessmentResultStatus) @@ -168,12 +176,17 @@ public void UpdateAssessmentResultStatus(string? assessmentResultStatus) public void UpdateFieldsOnlyForPreFinalDecision(string? dueDiligenceStatus, decimal? recommendedAmount, string? declineRational) { - DueDiligenceStatus = dueDiligenceStatus; + DueDiligenceStatus = dueDiligenceStatus; RecommendedAmount = recommendedAmount ?? 0; DeclineRational = declineRational; } - public void ValidateAndChangeDueDate(DateTime? dueDate) + /// + /// Validates and sets the DueDate property. + /// + /// + /// + public void ValidateAndSetDueDate(DateTime? dueDate) { if ((DueDate != dueDate) && dueDate != null && dueDate.Value < DateTime.Now.AddDays(-1)) { @@ -185,7 +198,12 @@ public void ValidateAndChangeDueDate(DateTime? dueDate) } } - public void ValidateAndChangeFinalDecisionDate(DateTime? finalDecisionDate) + /// + /// Validates and sets the FinalDecisionDate property. + /// + /// + /// + public void ValidateAndSetFinalDecisionDate(DateTime? finalDecisionDate) { if ((FinalDecisionDate != finalDecisionDate) && finalDecisionDate != null && finalDecisionDate.Value > DateTime.Now) { @@ -197,11 +215,56 @@ public void ValidateAndChangeFinalDecisionDate(DateTime? finalDecisionDate) } } - public void ValidateMinAndChangeApprovedAmount(decimal approvedAmount) + /// + /// Validates and sets the ApprovedAmount property. + /// + /// + /// + public void ValidateAndSetApprovedAmount(decimal approvedAmount) { if ((ApprovedAmount != approvedAmount) && approvedAmount <= 0m) { throw new BusinessException("Approved amount cannot be 0."); } + else + { + ApprovedAmount = approvedAmount; + } + } + + /// + /// Validates the recommended amount for direct approval. + /// + /// + /// + /// + public void ValidateDirectApprovalRecommendedAmount(decimal recommendedAmount, bool? isDirectApproval) + { + if (isDirectApproval != true && (RecommendedAmount != recommendedAmount) && recommendedAmount <= 0m) + { + throw new BusinessException("Recommended amount cannot be 0."); + } + } + + /// + /// Calculates and updates the PercentageTotalProjectBudget property based on + /// RequestedAmount and TotalProjectBudget values. + /// This method should be called whenever either of those properties change. + /// + public void UpdatePercentageTotalProjectBudget() + { + PercentageTotalProjectBudget + = (this.TotalProjectBudget == 0) + ? 0 : decimal.Multiply(decimal.Divide(this.RequestedAmount, this.TotalProjectBudget), 100).To(); + } + + /// + /// Sets the Electoral District for the application. + /// + /// + public void SetElectoralDistrict(string electoralDistrict) + { + ElectoralDistrict = electoralDistrict; } } + diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Domain/Applications/ApplicationForm.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Domain/Applications/ApplicationForm.cs index 0dcddae68..b16d577b4 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Domain/Applications/ApplicationForm.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Domain/Applications/ApplicationForm.cs @@ -1,5 +1,7 @@ using System; +using System.Collections.Generic; using System.ComponentModel.DataAnnotations; +using Unity.GrantManager.GrantApplications; using Volo.Abp.Domain.Entities.Auditing; using Volo.Abp.MultiTenancy; @@ -19,10 +21,34 @@ public class ApplicationForm : FullAuditedAggregateRoot, IMultiTenant public string? Category { get; set; } public string? ConnectionHttpStatus { get; set; } public DateTime? AttemptedConnectionDate { get; set; } - public bool Payable { get; set; } - public Guid? ScoresheetId { get; set; } + public bool Payable { get; set; } + public Guid? ScoresheetId { get; set; } public Guid? TenantId { get; set; } public bool RenderFormIoToHtml { get; set; } = false; public bool IsDirectApproval { get; set; } = false; - + public AddressType? ElectoralDistrictAddressType { get; set; } = AddressType.PhysicalAddress; + + public static List<(AddressType AddressType, string DisplayName)> GetAvailableElectoralDistrictAddressTypes() + { + return [ + new (AddressType.PhysicalAddress, "Physical Address"), + new (AddressType.MailingAddress, "Mailing Address") + ]; + } + + public ApplicationForm SetElectoralDistrictAddressType(AddressType addressType) + { + if (!Enum.IsDefined(typeof(AddressType), addressType)) + { + throw new ArgumentOutOfRangeException(nameof(addressType), "Invalid address type provided."); + } + ElectoralDistrictAddressType = addressType; + + return this; + } + + public static AddressType GetDefaultElectoralDistrictAddressType() + { + return AddressType.PhysicalAddress; + } } diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Domain/Applications/ApplicationFormVersion.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Domain/Applications/ApplicationFormVersion.cs index 6b3378a97..e9cfb1467 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Domain/Applications/ApplicationFormVersion.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Domain/Applications/ApplicationFormVersion.cs @@ -1,5 +1,7 @@ using System; +using System.Collections.Generic; using System.ComponentModel.DataAnnotations.Schema; +using System.Text.Json; using Volo.Abp.Domain.Entities.Auditing; using Volo.Abp.MultiTenancy; @@ -20,4 +22,27 @@ public class ApplicationFormVersion : AuditedAggregateRoot, IMultiTenant public string ReportViewName { get; set; } = string.Empty; [Column(TypeName = "jsonb")] public string? FormSchema { get; set; } = string.Empty; + + /// + /// Checks if the submission header mapping contains a specific field. + /// + /// + /// + /// + public bool HasSubmissionHeaderMapping(string field) + { + if (string.IsNullOrWhiteSpace(SubmissionHeaderMapping)) + return false; + + try + { + var mapping = JsonSerializer.Deserialize>(SubmissionHeaderMapping); + return mapping != null && mapping.ContainsKey(field); + } + catch (JsonException) + { + // Optionally log or handle malformed JSON + return false; + } + } } diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Domain/Applications/ApplicationManager.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Domain/Applications/ApplicationManager.cs index c8740c0b9..3ceddf836 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Domain/Applications/ApplicationManager.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Domain/Applications/ApplicationManager.cs @@ -5,8 +5,10 @@ using System.Threading.Tasks; using Unity.GrantManager.GrantApplications; using Unity.GrantManager.Identity; +using Unity.GrantManager.Permissions; using Unity.GrantManager.Workflow; using Volo.Abp; +using Volo.Abp.Authorization.Permissions; using Volo.Abp.Domain.Services; using Volo.Abp.Uow; @@ -18,22 +20,25 @@ public class ApplicationManager : DomainService, IApplicationManager private readonly IApplicationAssignmentRepository _applicationAssignmentRepository; private readonly IUnitOfWorkManager _unitOfWorkManager; private readonly IPersonRepository _personRepository; + private readonly IPermissionChecker _permissionChecker; public ApplicationManager( IApplicationRepository applicationRepository, IApplicationStatusRepository applicationStatus, IApplicationAssignmentRepository applicationAssignmentRepository, IUnitOfWorkManager unitOfWorkManager, - IPersonRepository personRepository) + IPersonRepository personRepository, + IPermissionChecker permissionChecker) { _applicationRepository = applicationRepository; _applicationStatusRepository = applicationStatus; _applicationAssignmentRepository = applicationAssignmentRepository; _unitOfWorkManager = unitOfWorkManager; _personRepository = personRepository; + _permissionChecker = permissionChecker; } - public static void ConfigureWorkflow(StateMachine stateMachine, bool isDirectApproval = false) + public void ConfigureWorkflow(StateMachine stateMachine, bool isDirectApproval = false) { // TODO: ENSURE APPLICATION STATE MACHINE MATCHES WORKFLOW IN AB#8375 stateMachine.Configure(GrantApplicationState.OPEN) @@ -126,13 +131,19 @@ public static void ConfigureWorkflow(StateMachine HasPermission(GrantApplicationPermissions.Approvals.DeferAfterApproval)); + + stateMachine.Configure(GrantApplicationState.GRANT_NOT_APPROVED) .Permit(GrantApplicationAction.Close, GrantApplicationState.CLOSED) .PermitIf(GrantApplicationAction.Approve, GrantApplicationState.GRANT_APPROVED, () => isDirectApproval); } + private bool HasPermission(string permission) + { + return _permissionChecker.IsGrantedAsync(permission).Result; + } public async Task> GetActions(Guid applicationId) { @@ -367,4 +378,6 @@ await _applicationAssignmentRepository.InsertAsync(new ApplicationAssignment() } await uow.SaveChangesAsync(); } + + } diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Domain/Applications/IApplicantRepository.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Domain/Applications/IApplicantRepository.cs index 12f725b89..e3ac80259 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Domain/Applications/IApplicantRepository.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Domain/Applications/IApplicantRepository.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Text.Json; using System.Threading.Tasks; using Volo.Abp.Domain.Repositories; @@ -12,4 +13,5 @@ public interface IApplicantRepository : IRepository Task GetByUnityApplicantNameAsync(string unityApplicantName); Task> GetApplicantsWithUnityApplicantIdAsync(); Task> GetApplicantsBySiteIdAsync(Guid siteId); + Task GetApplicantAutocompleteQueryAsync(string? applicantLookUpQuery); } diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Domain/Applications/IApplicationTagsRepository.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Domain/Applications/IApplicationTagsRepository.cs index f2756ace7..74eb5ebf3 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Domain/Applications/IApplicationTagsRepository.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Domain/Applications/IApplicationTagsRepository.cs @@ -1,8 +1,12 @@ using System; +using System.Collections.Generic; +using System.Threading.Tasks; using Volo.Abp.Domain.Repositories; namespace Unity.GrantManager.Applications; public interface IApplicationTagsRepository : IRepository { + Task> GetTagSummary(); + Task GetMaxRenameLengthAsync(string originalTag); } diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Domain/Applications/TagSummaryCount.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Domain/Applications/TagSummaryCount.cs new file mode 100644 index 000000000..66e88c481 --- /dev/null +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Domain/Applications/TagSummaryCount.cs @@ -0,0 +1,6 @@ +namespace Unity.GrantManager.Applications; +public class TagSummaryCount(string name, int count) +{ + public string Text { get; set; } = name; + public int Count { get; set; } = count; +} diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Domain/Intakes/ApplicantResult.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Domain/Intakes/ApplicantResult.cs index 32a55d26a..b60bea8eb 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Domain/Intakes/ApplicantResult.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Domain/Intakes/ApplicantResult.cs @@ -1,6 +1,4 @@ -using System.Text.Json.Serialization; - -namespace Unity.GrantManager.Intakes +namespace Unity.GrantManager.Intakes { public class ApplicantResult { diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Domain/Intakes/Mapping/IntakeMapping.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Domain/Intakes/Mapping/IntakeMapping.cs index dd131639d..52cadba16 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Domain/Intakes/Mapping/IntakeMapping.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Domain/Intakes/Mapping/IntakeMapping.cs @@ -21,6 +21,11 @@ public class IntakeMapping [Browsable(true)] public string? ApplicantName { get; set; } + [DisplayName("Applicant Electoral District")] + [MapFieldType("String")] + [Browsable(true)] + public string? ApplicantElectoralDistrict { get; set; } + [DisplayName("Approximate Number Of Employees")] [MapFieldType("Number")] [Browsable(true)] @@ -71,7 +76,7 @@ public class IntakeMapping [Browsable(true)] public string? EconomicRegion { get; set; } - [DisplayName("Electoral District")] + [DisplayName("Project Electoral District")] [MapFieldType("String")] [Browsable(true)] public string? ElectoralDistrict { get; set; } diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Domain/Permissions/PermissionGrantsDataSeeder.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Domain/Permissions/PermissionGrantsDataSeeder.cs index fc951a312..d7af16c3f 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Domain/Permissions/PermissionGrantsDataSeeder.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Domain/Permissions/PermissionGrantsDataSeeder.cs @@ -31,20 +31,38 @@ public PermissionGrantsDataSeeder(IPermissionDataSeeder permissionDataSeeder) UnitySelector.Review.AssessmentReviewList.Default, UnitySelector.Review.AssessmentReviewList.Create, UnitySelector.Review.AssessmentReviewList.Update.SendBack, - UnitySelector.Review.AssessmentReviewList.Update.Complete, - - UnitySelector.Review.Worksheet.Default, - UnitySelector.Review.Worksheet.Update, + UnitySelector.Review.AssessmentReviewList.Update.Complete ]; public readonly List ApplicantInfo_CommonPermissions = [ - GrantApplicationPermissions.ApplicantInfo.Default, - GrantApplicationPermissions.ApplicantInfo.Update, + UnitySelector.Applicant.Default, + UnitySelector.Applicant.Summary.Default, + UnitySelector.Applicant.Summary.Update, + UnitySelector.Applicant.Contact.Default, + UnitySelector.Applicant.Contact.Update, + UnitySelector.Applicant.Authority.Default, + UnitySelector.Applicant.Authority.Update, + UnitySelector.Applicant.Location.Default, + UnitySelector.Applicant.Location.Update, + UnitySelector.Applicant.AdditionalContact.Default, + UnitySelector.Applicant.AdditionalContact.Create, + UnitySelector.Applicant.AdditionalContact.Update, + ]; public readonly List ProjectInfo_CommonPermissions = [ - GrantApplicationPermissions.ProjectInfo.Default, - GrantApplicationPermissions.ProjectInfo.Update, + UnitySelector.Project.Default, + UnitySelector.Project.Summary.Default, + UnitySelector.Project.Summary.Update.Default, + UnitySelector.Project.Location.Default, + UnitySelector.Project.Location.Update.Default, + ]; + + public readonly List PaymentInfo_CommonPermissions = [ + UnitySelector.Payment.Summary.Default, + UnitySelector.Payment.Supplier.Default, + UnitySelector.Payment.Supplier.Update, + UnitySelector.Payment.PaymentList.Default ]; public readonly List Notifications_CommonPermissions = [ @@ -136,18 +154,27 @@ await _permissionDataSeeder.SeedAsync(RolePermissionValueProvider.ProviderName, GrantManagerPermissions.Default, GrantApplicationPermissions.Applications.Default, GrantApplicationPermissions.Assignments.AssignInitial, + GrantApplicationPermissions.Applicants.AssignApplicant, GrantApplicationPermissions.Reviews.StartInitial, GrantApplicationPermissions.Reviews.CompleteInitial, GrantApplicationPermissions.Comments.Add, GrantManagerPermissions.Organizations.Default, GrantManagerPermissions.Organizations.ManageProfiles, GrantApplicationPermissions.Approvals.BulkApplicationApproval, + GrantApplicationPermissions.Approvals.DeferAfterApproval, + UnitySelector.SettingManagement.Tags.Default, + UnitySelector.SettingManagement.Tags.Update, + UnitySelector.SettingManagement.Tags.Delete, .. ReviewAndAssessment_CommonPermissions, .. ApplicantInfo_CommonPermissions, .. ProjectInfo_CommonPermissions, .. Notifications_CommonPermissions, - .. Dashboard_CommonPermissions + .. Dashboard_CommonPermissions, + + // Role Specific Permissions + UnitySelector.Project.Summary.Update.UpdateFinalStateFields, + UnitySelector.Project.Location.Update.UpdateFinalStateFields, ], context.TenantId); // - Approver @@ -156,6 +183,7 @@ await _permissionDataSeeder.SeedAsync(RolePermissionValueProvider.ProviderName, GrantManagerPermissions.Default, GrantApplicationPermissions.Applications.Default, GrantApplicationPermissions.Approvals.Complete, + GrantApplicationPermissions.Approvals.DeferAfterApproval, GrantApplicationPermissions.Comments.Add, .. ReviewAndAssessment_CommonPermissions, @@ -183,7 +211,10 @@ await _permissionDataSeeder.SeedAsync(RolePermissionValueProvider.ProviderName, NotificationsPermissions.Settings, .. Dashboard_CommonPermissions, - UnitySettingManagementPermissions.BackgroundJobSettings + UnitySettingManagementPermissions.BackgroundJobSettings, + UnitySelector.SettingManagement.Tags.Default, + UnitySelector.SettingManagement.Tags.Update, + UnitySelector.SettingManagement.Tags.Delete ], context.TenantId); @@ -248,8 +279,16 @@ await _permissionDataSeeder.SeedAsync(RolePermissionValueProvider.ProviderName, UnitySelector.Review.AssessmentReviewList.Update.Complete, UnitySelector.Review.Worksheet.Default, - GrantApplicationPermissions.ApplicantInfo.Default, - GrantApplicationPermissions.ProjectInfo.Default, + UnitySelector.Applicant.Default, + UnitySelector.Applicant.Summary.Default, + UnitySelector.Applicant.Contact.Default, + UnitySelector.Applicant.Authority.Default, + UnitySelector.Applicant.Location.Default, + UnitySelector.Applicant.AdditionalContact.Default, + + UnitySelector.Project.Default, + UnitySelector.Project.Summary.Default, + UnitySelector.Project.Location.Default, NotificationsPermissions.Email.Default, ], context.TenantId); diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Domain/Settings/GrantManagerSettingDefinitionProvider.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Domain/Settings/GrantManagerSettingDefinitionProvider.cs index 0d2d77254..3338d5858 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Domain/Settings/GrantManagerSettingDefinitionProvider.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Domain/Settings/GrantManagerSettingDefinitionProvider.cs @@ -57,7 +57,7 @@ private static void AddBackgroundJobSettingDefinition(ISettingDefinitionContext { var backGroundSchedules = new Dictionary { - { SettingsConstants.BackgroundJobs.IntakeResync_NumDaysToCheck, "-2" }, + { SettingsConstants.BackgroundJobs.IntakeResync_NumDaysToCheck, "-4" }, // 23 = 11 pm So 23 + 8 UTC = 7 also at 19 = 11 am { SettingsConstants.BackgroundJobs.IntakeResync_Expression, "0 0 7,19 1/1 * ? *" }, // 24 = 12 am So 24 + 8 UTC = 8 diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Domain/Settings/GrantManagerSettings.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Domain/Settings/GrantManagerSettings.cs index 21234d098..8c78fafc1 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Domain/Settings/GrantManagerSettings.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Domain/Settings/GrantManagerSettings.cs @@ -2,6 +2,5 @@ public static class GrantManagerSettings { - //Add your own setting names here. Example: - //public const string MySetting1 = Prefix + ".MySetting1"; + //Add your own setting names here. } diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Domain/Zones/DefaultZoneDefinition.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Domain/Zones/DefaultZoneDefinition.cs index f08afd6ce..dea377698 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Domain/Zones/DefaultZoneDefinition.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Domain/Zones/DefaultZoneDefinition.cs @@ -1,5 +1,4 @@ -using Unity.GrantManager.Settings; -using Unity.Modules.Shared; +using Unity.Modules.Shared; namespace Unity.GrantManager.Zones; public static class DefaultZoneDefinition @@ -49,12 +48,11 @@ public static class DefaultZoneDefinition Name = UnitySelector.Project.Location.Default, ViewComponentType = "ProjectLocationViewComponent", IsEnabled = true, - IsConfigurationDisabled = true, SortOrder = 2 }, ] - }, - new ZoneTabDefinition { + }, + new ZoneTabDefinition { Name = UnitySelector.Applicant.Default, IsEnabled = true, SortOrder = 3, @@ -70,23 +68,25 @@ public static class DefaultZoneDefinition Name = UnitySelector.Applicant.Contact.Default, ViewComponentType = "ApplicantContactInfoViewComponent", IsEnabled = true, - IsConfigurationDisabled = true, SortOrder = 2 }, new ZoneDefinition { Name = UnitySelector.Applicant.Authority.Default, ViewComponentType = "ApplicantSigningAuthorityViewComponent", IsEnabled = true, - IsConfigurationDisabled = true, SortOrder = 3 }, new ZoneDefinition { Name = UnitySelector.Applicant.Location.Default, ViewComponentType = "ApplicantPhysicalAddressViewComponent", IsEnabled = true, - IsConfigurationDisabled = true, SortOrder = 4 }, + new ZoneDefinition { + Name = UnitySelector.Applicant.AdditionalContact.Default, + IsEnabled = true, + SortOrder = 5 + }, ] }, new ZoneTabDefinition { @@ -113,14 +113,22 @@ public static class DefaultZoneDefinition Name = UnitySelector.Payment.Summary.Default, ViewComponentType = "PaymentInfoViewComponent", IsEnabled = true, + IsConfigurationDisabled = true, SortOrder = 1 }, - new ZoneDefinition { + new ZoneDefinition { + Name = UnitySelector.Payment.Supplier.Default, + ViewComponentType = "SupplierInfoViewComponent", + IsEnabled = true, + IsConfigurationDisabled = true, + SortOrder = 2 + }, + new ZoneDefinition { Name = UnitySelector.Payment.PaymentList.Default, ViewComponentType = "PaymentListViewComponent", IsEnabled = true, IsConfigurationDisabled = true, - SortOrder = 2 + SortOrder = 3 } ] } diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.EntityFrameworkCore/Migrations/TenantMigrations/20250528224549_FixSnapshot.Designer.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.EntityFrameworkCore/Migrations/TenantMigrations/20250528224549_FixSnapshot.Designer.cs new file mode 100644 index 000000000..cd63c2e01 --- /dev/null +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.EntityFrameworkCore/Migrations/TenantMigrations/20250528224549_FixSnapshot.Designer.cs @@ -0,0 +1,3889 @@ +// +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("20250528224549_FixSnapshot")] + partial class FixSnapshot + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("_Abp_DatabaseProvider", EfCoreDatabaseProvider.PostgreSql) + .HasAnnotation("ProductVersion", "8.0.8") + .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("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("FiscalDay") + .HasColumnType("integer"); + + b.Property("FiscalMonth") + .HasColumnType("text"); + + b.Property("IndigenousOrgInd") + .HasColumnType("text"); + + 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") + .IsRequired() + .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.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("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("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("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("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("Text") + .IsRequired() + .HasMaxLength(250) + .HasColumnType("character varying(250)"); + + b.HasKey("Id"); + + b.HasIndex("ApplicationId"); + + 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.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.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.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("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("MinistryClient") + .HasColumnType("text"); + + b.Property("PaymentIdPrefix") + .IsRequired() + .HasColumnType("text"); + + b.Property("PaymentThreshold") + .HasColumnType("numeric"); + + b.Property("ProjectNumber") + .HasColumnType("text"); + + b.Property("Responsibility") + .HasColumnType("text"); + + b.Property("ServiceLine") + .HasColumnType("text"); + + b.Property("Stob") + .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("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("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("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("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("Text") + .IsRequired() + .HasMaxLength(250) + .HasColumnType("character varying(250)"); + + b.HasKey("Id"); + + b.HasIndex("PaymentRequestId"); + + b.ToTable("PaymentTags", "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.Navigation("Applicant"); + }); + + 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.Navigation("Application"); + }); + + 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.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.Suppliers.Site", "Site") + .WithMany() + .HasForeignKey("SiteId") + .OnDelete(DeleteBehavior.NoAction) + .IsRequired(); + + 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(); + }); + + 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("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/20250528224549_FixSnapshot.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.EntityFrameworkCore/Migrations/TenantMigrations/20250528224549_FixSnapshot.cs new file mode 100644 index 000000000..b352f0e3d --- /dev/null +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.EntityFrameworkCore/Migrations/TenantMigrations/20250528224549_FixSnapshot.cs @@ -0,0 +1,20 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Unity.GrantManager.Migrations.TenantMigrations +{ + /// + public partial class FixSnapshot : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + } + } +} diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.EntityFrameworkCore/Migrations/TenantMigrations/20250528224843_AddAddressTypeToElectoralDistrict.Designer.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.EntityFrameworkCore/Migrations/TenantMigrations/20250528224843_AddAddressTypeToElectoralDistrict.Designer.cs new file mode 100644 index 000000000..f34b901a5 --- /dev/null +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.EntityFrameworkCore/Migrations/TenantMigrations/20250528224843_AddAddressTypeToElectoralDistrict.Designer.cs @@ -0,0 +1,3892 @@ +// +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("20250528224843_AddAddressTypeToElectoralDistrict")] + partial class AddAddressTypeToElectoralDistrict + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("_Abp_DatabaseProvider", EfCoreDatabaseProvider.PostgreSql) + .HasAnnotation("ProductVersion", "8.0.8") + .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("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("FiscalDay") + .HasColumnType("integer"); + + b.Property("FiscalMonth") + .HasColumnType("text"); + + b.Property("IndigenousOrgInd") + .HasColumnType("text"); + + 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") + .IsRequired() + .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.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("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("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("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("Text") + .IsRequired() + .HasMaxLength(250) + .HasColumnType("character varying(250)"); + + b.HasKey("Id"); + + b.HasIndex("ApplicationId"); + + 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.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.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.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("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("MinistryClient") + .HasColumnType("text"); + + b.Property("PaymentIdPrefix") + .IsRequired() + .HasColumnType("text"); + + b.Property("PaymentThreshold") + .HasColumnType("numeric"); + + b.Property("ProjectNumber") + .HasColumnType("text"); + + b.Property("Responsibility") + .HasColumnType("text"); + + b.Property("ServiceLine") + .HasColumnType("text"); + + b.Property("Stob") + .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("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("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("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("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("Text") + .IsRequired() + .HasMaxLength(250) + .HasColumnType("character varying(250)"); + + b.HasKey("Id"); + + b.HasIndex("PaymentRequestId"); + + b.ToTable("PaymentTags", "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.Navigation("Applicant"); + }); + + 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.Navigation("Application"); + }); + + 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.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.Suppliers.Site", "Site") + .WithMany() + .HasForeignKey("SiteId") + .OnDelete(DeleteBehavior.NoAction) + .IsRequired(); + + 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(); + }); + + 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("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/20250528224843_AddAddressTypeToElectoralDistrict.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.EntityFrameworkCore/Migrations/TenantMigrations/20250528224843_AddAddressTypeToElectoralDistrict.cs new file mode 100644 index 000000000..ac710b86a --- /dev/null +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.EntityFrameworkCore/Migrations/TenantMigrations/20250528224843_AddAddressTypeToElectoralDistrict.cs @@ -0,0 +1,28 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Unity.GrantManager.Migrations.TenantMigrations +{ + /// + public partial class AddAddressTypeToElectoralDistrict : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "ElectoralDistrictAddressType", + table: "ApplicationForms", + type: "integer", + nullable: true); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "ElectoralDistrictAddressType", + table: "ApplicationForms"); + } + } +} diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.EntityFrameworkCore/Migrations/TenantMigrations/20250610215934_AddApplicantElectoralDistrict.Designer.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.EntityFrameworkCore/Migrations/TenantMigrations/20250610215934_AddApplicantElectoralDistrict.Designer.cs new file mode 100644 index 000000000..4d48264c1 --- /dev/null +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.EntityFrameworkCore/Migrations/TenantMigrations/20250610215934_AddApplicantElectoralDistrict.Designer.cs @@ -0,0 +1,3895 @@ +// +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("20250610215934_AddApplicantElectoralDistrict")] + partial class AddApplicantElectoralDistrict + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("_Abp_DatabaseProvider", EfCoreDatabaseProvider.PostgreSql) + .HasAnnotation("ProductVersion", "8.0.8") + .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("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") + .IsRequired() + .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.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("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("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("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("Text") + .IsRequired() + .HasMaxLength(250) + .HasColumnType("character varying(250)"); + + b.HasKey("Id"); + + b.HasIndex("ApplicationId"); + + 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.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.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.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("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("MinistryClient") + .HasColumnType("text"); + + b.Property("PaymentIdPrefix") + .IsRequired() + .HasColumnType("text"); + + b.Property("PaymentThreshold") + .HasColumnType("numeric"); + + b.Property("ProjectNumber") + .HasColumnType("text"); + + b.Property("Responsibility") + .HasColumnType("text"); + + b.Property("ServiceLine") + .HasColumnType("text"); + + b.Property("Stob") + .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("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("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("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("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("Text") + .IsRequired() + .HasMaxLength(250) + .HasColumnType("character varying(250)"); + + b.HasKey("Id"); + + b.HasIndex("PaymentRequestId"); + + b.ToTable("PaymentTags", "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.Navigation("Applicant"); + }); + + 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.Navigation("Application"); + }); + + 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.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.Suppliers.Site", "Site") + .WithMany() + .HasForeignKey("SiteId") + .OnDelete(DeleteBehavior.NoAction) + .IsRequired(); + + 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(); + }); + + 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("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/20250610215934_AddApplicantElectoralDistrict.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.EntityFrameworkCore/Migrations/TenantMigrations/20250610215934_AddApplicantElectoralDistrict.cs new file mode 100644 index 000000000..0974fa9d2 --- /dev/null +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.EntityFrameworkCore/Migrations/TenantMigrations/20250610215934_AddApplicantElectoralDistrict.cs @@ -0,0 +1,28 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Unity.GrantManager.Migrations.TenantMigrations +{ + /// + public partial class AddApplicantElectoralDistrict : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "ElectoralDistrict", + table: "Applicants", + type: "text", + nullable: true); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "ElectoralDistrict", + table: "Applicants"); + } + } +} diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.EntityFrameworkCore/Migrations/TenantMigrations/20250611184011_AddIsDuplicatedToApplicants.Designer.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.EntityFrameworkCore/Migrations/TenantMigrations/20250611184011_AddIsDuplicatedToApplicants.Designer.cs new file mode 100644 index 000000000..8b0529899 --- /dev/null +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.EntityFrameworkCore/Migrations/TenantMigrations/20250611184011_AddIsDuplicatedToApplicants.Designer.cs @@ -0,0 +1,3892 @@ +// +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("20250611184011_AddIsDuplicatedToApplicants")] + partial class AddIsDuplicatedToApplicants + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("_Abp_DatabaseProvider", EfCoreDatabaseProvider.PostgreSql) + .HasAnnotation("ProductVersion", "8.0.8") + .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("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("FiscalDay") + .HasColumnType("integer"); + + b.Property("FiscalMonth") + .HasColumnType("text"); + + b.Property("IndigenousOrgInd") + .HasColumnType("text"); + + 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") + .IsRequired() + .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.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("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("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("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("Text") + .IsRequired() + .HasMaxLength(250) + .HasColumnType("character varying(250)"); + + b.HasKey("Id"); + + b.HasIndex("ApplicationId"); + + 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.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.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.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("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("MinistryClient") + .HasColumnType("text"); + + b.Property("PaymentIdPrefix") + .IsRequired() + .HasColumnType("text"); + + b.Property("PaymentThreshold") + .HasColumnType("numeric"); + + b.Property("ProjectNumber") + .HasColumnType("text"); + + b.Property("Responsibility") + .HasColumnType("text"); + + b.Property("ServiceLine") + .HasColumnType("text"); + + b.Property("Stob") + .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("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("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("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("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("Text") + .IsRequired() + .HasMaxLength(250) + .HasColumnType("character varying(250)"); + + b.HasKey("Id"); + + b.HasIndex("PaymentRequestId"); + + b.ToTable("PaymentTags", "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.Navigation("Applicant"); + }); + + 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.Navigation("Application"); + }); + + 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.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.Suppliers.Site", "Site") + .WithMany() + .HasForeignKey("SiteId") + .OnDelete(DeleteBehavior.NoAction) + .IsRequired(); + + 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(); + }); + + 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("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/20250611184011_AddIsDuplicatedToApplicants.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.EntityFrameworkCore/Migrations/TenantMigrations/20250611184011_AddIsDuplicatedToApplicants.cs new file mode 100644 index 000000000..2cb51f8ab --- /dev/null +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.EntityFrameworkCore/Migrations/TenantMigrations/20250611184011_AddIsDuplicatedToApplicants.cs @@ -0,0 +1,29 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Unity.GrantManager.Migrations.TenantMigrations +{ + /// + public partial class AddIsDuplicatedToApplicants : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "IsDuplicated", + table: "Applicants", + type: "boolean", + nullable: false, + defaultValue: false); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "IsDuplicated", + table: "Applicants"); + } + } +} diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.EntityFrameworkCore/Migrations/TenantMigrations/20250618172856_SetIsDuplicatedColumnNullable.Designer.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.EntityFrameworkCore/Migrations/TenantMigrations/20250618172856_SetIsDuplicatedColumnNullable.Designer.cs new file mode 100644 index 000000000..dd4d59038 --- /dev/null +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.EntityFrameworkCore/Migrations/TenantMigrations/20250618172856_SetIsDuplicatedColumnNullable.Designer.cs @@ -0,0 +1,3898 @@ +// +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("20250618172856_SetIsDuplicatedColumnNullable")] + partial class SetIsDuplicatedColumnNullable + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("_Abp_DatabaseProvider", EfCoreDatabaseProvider.PostgreSql) + .HasAnnotation("ProductVersion", "8.0.8") + .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") + .IsRequired() + .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.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("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("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("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("Text") + .IsRequired() + .HasMaxLength(250) + .HasColumnType("character varying(250)"); + + b.HasKey("Id"); + + b.HasIndex("ApplicationId"); + + 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.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.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.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("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("MinistryClient") + .HasColumnType("text"); + + b.Property("PaymentIdPrefix") + .IsRequired() + .HasColumnType("text"); + + b.Property("PaymentThreshold") + .HasColumnType("numeric"); + + b.Property("ProjectNumber") + .HasColumnType("text"); + + b.Property("Responsibility") + .HasColumnType("text"); + + b.Property("ServiceLine") + .HasColumnType("text"); + + b.Property("Stob") + .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("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("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("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("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("Text") + .IsRequired() + .HasMaxLength(250) + .HasColumnType("character varying(250)"); + + b.HasKey("Id"); + + b.HasIndex("PaymentRequestId"); + + b.ToTable("PaymentTags", "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.Navigation("Applicant"); + }); + + 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.Navigation("Application"); + }); + + 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.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.Suppliers.Site", "Site") + .WithMany() + .HasForeignKey("SiteId") + .OnDelete(DeleteBehavior.NoAction) + .IsRequired(); + + 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(); + }); + + 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("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/20250618172856_SetIsDuplicatedColumnNullable.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.EntityFrameworkCore/Migrations/TenantMigrations/20250618172856_SetIsDuplicatedColumnNullable.cs new file mode 100644 index 000000000..c0611f06a --- /dev/null +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.EntityFrameworkCore/Migrations/TenantMigrations/20250618172856_SetIsDuplicatedColumnNullable.cs @@ -0,0 +1,35 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Unity.GrantManager.Migrations.TenantMigrations +{ + /// + public partial class SetIsDuplicatedColumnNullable : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AlterColumn( + name: "IsDuplicated", + table: "Applicants", + type: "boolean", + nullable: true, + oldClrType: typeof(bool), + oldType: "boolean"); + } + + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.AlterColumn( + name: "IsDuplicated", + table: "Applicants", + type: "boolean", + nullable: false, + oldClrType: typeof(bool), + oldType: "boolean"); + } + } +} 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 3e7df5b7f..36a7df928 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 @@ -816,6 +816,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasColumnType("uuid") .HasColumnName("CreatorId"); + b.Property("ElectoralDistrict") + .HasColumnType("text"); + b.Property("ExtraProperties") .IsRequired() .HasColumnType("text") @@ -830,6 +833,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("IndigenousOrgInd") .HasColumnType("text"); + b.Property("IsDuplicated") + .HasColumnType("boolean"); + b.Property("LastModificationTime") .HasColumnType("timestamp without time zone") .HasColumnName("LastModificationTime"); @@ -1600,6 +1606,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasColumnType("timestamp without time zone") .HasColumnName("DeletionTime"); + b.Property("ElectoralDistrictAddressType") + .HasColumnType("integer"); + b.Property("ExtraProperties") .IsRequired() .HasColumnType("text") @@ -1765,6 +1774,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasColumnType("text") .HasColumnName("ExtraProperties"); + b.Property("FormSchema") + .HasColumnType("jsonb"); + b.Property("LastModificationTime") .HasColumnType("timestamp without time zone") .HasColumnName("LastModificationTime"); @@ -3192,7 +3204,8 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("Text") .IsRequired() - .HasColumnType("text"); + .HasMaxLength(250) + .HasColumnType("character varying(250)"); b.HasKey("Id"); diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.EntityFrameworkCore/Repositories/ApplicantRepository.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.EntityFrameworkCore/Repositories/ApplicantRepository.cs index 074c525e9..ba597ae87 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.EntityFrameworkCore/Repositories/ApplicantRepository.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.EntityFrameworkCore/Repositories/ApplicantRepository.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Text.Json; using System.Threading.Tasks; using Microsoft.EntityFrameworkCore; using Unity.GrantManager.Applications; @@ -61,5 +62,51 @@ public async Task> GetApplicantsBySiteIdAsync(Guid siteId) .Where(x => x.SiteId == siteId) .ToListAsync(); } + + public async Task GetApplicantAutocompleteQueryAsync(string? applicantLookUpQuery) + { + if (string.IsNullOrWhiteSpace(applicantLookUpQuery)) + { + // Return an empty JSON array if the query is null or only whitespace + return JsonDocument.Parse("[]"); + } + + var dbContext = await GetDbContextAsync(); + var searchQuery = applicantLookUpQuery.ToLower(); + + var applicants = await dbContext.Applicants + .AsNoTracking() + .ToListAsync(); + + var filteredApplicants = applicants + .Where(a => + (!string.IsNullOrEmpty(a.ApplicantName) && a.ApplicantName.Contains(searchQuery, StringComparison.OrdinalIgnoreCase)) || + (!string.IsNullOrEmpty(a.UnityApplicantId) && a.UnityApplicantId.Contains(searchQuery, StringComparison.OrdinalIgnoreCase)) + ) + .Select(a => new + { + a.Id, + a.ApplicantName, + a.OrgName, + a.OrgNumber, + a.NonRegOrgName, + a.OrganizationType, + a.OrganizationSize, + a.ApproxNumberOfEmployees, + a.OrgStatus, + a.IndigenousOrgInd, + a.Sector, + a.SubSector, + a.SectorSubSectorIndustryDesc, + a.FiscalDay, + a.FiscalMonth, + a.UnityApplicantId + }) + .Take(10) + .ToList(); + + var json = JsonSerializer.Serialize(filteredApplicants); + return JsonDocument.Parse(json); + } } } diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.EntityFrameworkCore/Repositories/ApplicationRepository.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.EntityFrameworkCore/Repositories/ApplicationRepository.cs index d6d66e542..2c50b4ba3 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.EntityFrameworkCore/Repositories/ApplicationRepository.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.EntityFrameworkCore/Repositories/ApplicationRepository.cs @@ -60,7 +60,7 @@ private async Task> BuildBaseQueryAsync() .AsQueryable(); } - private IQueryable ApplySorting(IQueryable query, string? sorting) + private static IQueryable ApplySorting(IQueryable query, string? sorting) { if (string.IsNullOrEmpty(sorting)) { @@ -84,7 +84,7 @@ private IQueryable ApplySorting(IQueryable query, stri return query; } - private string? MapSortingField(string field) + private static string? MapSortingField(string field) { if (field.StartsWith("status ", StringComparison.OrdinalIgnoreCase) || field.Equals("status", StringComparison.OrdinalIgnoreCase)) { diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.EntityFrameworkCore/Repositories/ApplicationTagsRepository.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.EntityFrameworkCore/Repositories/ApplicationTagsRepository.cs index 18c5a1f95..b2a6b6869 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.EntityFrameworkCore/Repositories/ApplicationTagsRepository.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.EntityFrameworkCore/Repositories/ApplicationTagsRepository.cs @@ -1,21 +1,67 @@ -using System; +using Microsoft.EntityFrameworkCore; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; using Unity.GrantManager.Applications; using Unity.GrantManager.EntityFrameworkCore; using Volo.Abp.DependencyInjection; using Volo.Abp.Domain.Repositories.EntityFrameworkCore; using Volo.Abp.EntityFrameworkCore; -namespace Unity.GrantManager.Repositories -{ - [Dependency(ReplaceServices = true)] - [ExposeServices(typeof(IApplicationTagsRepository))] +namespace Unity.GrantManager.Repositories; + +[Dependency(ReplaceServices = true)] +[ExposeServices(typeof(IApplicationTagsRepository))] #pragma warning disable CS8613 // Nullability of reference types in return type doesn't match implicitly implemented member. - // This pattern is an implementation ontop of ABP framework, will not change this - public class ApplicationTagsRepository : EfCoreRepository, IApplicationTagsRepository +// This pattern is an implementation ontop of ABP framework, will not change this +public class ApplicationTagsRepository(IDbContextProvider dbContextProvider) + : EfCoreRepository(dbContextProvider), IApplicationTagsRepository #pragma warning restore CS8613 // Nullability of reference types in return type doesn't match implicitly implemented member. +{ + public virtual async Task> GetTagSummary() { - public ApplicationTagsRepository(IDbContextProvider dbContextProvider) : base(dbContextProvider) + var dbSet = await GetDbSetAsync(); + var results = dbSet + .AsNoTracking() + .AsEnumerable() // Forces client-side evaluation + .SelectMany(tag => tag.Text.Split(',', StringSplitOptions.RemoveEmptyEntries) + .Select(t => t.Trim())) + .GroupBy(tag => tag) + .Select(group => new TagSummaryCount( + group.Key, + group.Count() + )).ToList(); + + return results; + } + + /// + /// For a given Tag, finds the maximum length available for renaming. + /// + /// The tag to be replaced. + /// The maximum length available for renaming + public virtual async Task GetMaxRenameLengthAsync(string originalTag) + { + var dbContext = await GetDbContextAsync(); + var entityType = dbContext.Model.FindEntityType(typeof(ApplicationTags)); + var property = entityType?.FindProperty(nameof(ApplicationTags.Text)); + + int maxColumnLength = property?.GetMaxLength() ?? 0; + + var dbSet = await GetDbSetAsync(); + int? maxTagSetLength = await dbSet + .AsNoTracking() + .Where(t => t.Text.Contains(originalTag)) + .Select(t => t.Text.Length) + .OrderByDescending(len => len) + .FirstOrDefaultAsync(); + + if (maxTagSetLength == null || maxTagSetLength == 0) { + return maxColumnLength; } + + return maxColumnLength + originalTag.Length - maxTagSetLength.Value; } } diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.EntityFrameworkCore/Repositories/PermissionRoleMatrixRepository.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.EntityFrameworkCore/Repositories/PermissionRoleMatrixRepository.cs new file mode 100644 index 000000000..ff5113620 --- /dev/null +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.EntityFrameworkCore/Repositories/PermissionRoleMatrixRepository.cs @@ -0,0 +1,87 @@ +using Microsoft.EntityFrameworkCore; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Unity.GrantManager.EntityFrameworkCore; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Domain.Repositories.EntityFrameworkCore; +using Volo.Abp.EntityFrameworkCore; +using Volo.Abp.Identity; +using Volo.Abp.MultiTenancy; +using Volo.Abp.PermissionManagement; + +namespace Unity.GrantManager.Repositories; + +[Dependency(ReplaceServices = true)] +[ExposeServices(typeof(IPermissionRoleMatrixRepository))] +public class PermissionRoleMatrixRepository(IDbContextProvider dbContextProvider) : EfCoreRepository(dbContextProvider), IPermissionRoleMatrixRepository +{ + public async Task> GetPermissionRoleMatrixAsync() + { + var dbContext = await GetDbContextAsync(); + + // Query permissionGrants and roles + var permissions = await dbContext.Set() + .Where(p => p.IsEnabled && p.MultiTenancySide != MultiTenancySides.Host) + .ToListAsync(); + + var permissionGrants = await dbContext.Set() + .ToListAsync(); + + var roles = await dbContext.Set() + .OrderBy(r => r.Name) + .ToListAsync(); + + var matrix = permissions + .Select(permission => new PermissionRoleMatrixDto + { + GroupName = permission.GroupName, + PermissionName = permission.Name, + PermissionDisplayName = permission.DisplayName, + Depth = CalculatePermissionDepth(permission.Name, permissions), + RolePermissions = roles.ToDictionary( + role => role.Name, + role => permissionGrants.Any(pg => + pg.Name == permission.Name && + pg.ProviderName == "R" && + pg.TenantId == CurrentTenant.Id && + pg.ProviderKey.Equals(role.Name, StringComparison.CurrentCultureIgnoreCase)) + ) + }) + .OrderBy(p => p.GroupName) + .ThenBy(p => p.PermissionName) + .ToList(); + + return matrix; + } + + private static int CalculatePermissionDepth(string permissionName, List permissions) + { + var parentPermission = permissions.FirstOrDefault(p => p.Name == permissionName)?.ParentName; + + if (string.IsNullOrEmpty(parentPermission)) + { + // If there is no parent, this is a top-level permission (depth = 0) + return 0; + } + + // Recursively calculate the depth of the parent permission + return 1 + CalculatePermissionDepth(parentPermission, permissions); + } +} + +public interface IPermissionRoleMatrixRepository +{ + Task> GetPermissionRoleMatrixAsync(); +} + +public class PermissionRoleMatrixDto +{ + public required string GroupName { get; set; } + public required string PermissionName { get; set; } + public required string PermissionDisplayName { get; set; } + public int Depth { get; set; } + public required Dictionary RolePermissions { get; set; } + public bool IsDefined { get; set; } = false; +} \ No newline at end of file diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.HttpApi/Controllers/AttachmentController.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.HttpApi/Controllers/AttachmentController.cs index bc35d1f80..57eccb8b6 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.HttpApi/Controllers/AttachmentController.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.HttpApi/Controllers/AttachmentController.cs @@ -298,7 +298,7 @@ private List GetInvalidFileTypes(IList files) return DisallowedFileTypes.Contains(FileType.ToLower()); })) { - ErrorList.Add(new ValidationResult("Invalid file type for " + source.FileName, new[] { "FileName" })); + ErrorList.Add(new ValidationResult("Invalid file type for " + source.FileName, [nameof(source.FileName)])); } return ErrorList; } diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/GrantManagerWebModule.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/GrantManagerWebModule.cs index d9bbfa9ca..d23c2f83e 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/GrantManagerWebModule.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/GrantManagerWebModule.cs @@ -76,6 +76,7 @@ using Unity.Notifications.Web.Views.Settings; using Unity.Notifications.Web.Bundling; using Unity.Reporting.Web; +using Unity.GrantManager.Web.Views.Settings; namespace Unity.GrantManager.Web; @@ -124,6 +125,10 @@ public override void PreConfigureServices(ServiceConfigurationContext context) }); } + private static readonly string[] _liveHealthCheckTags = ["live"]; + private static readonly string[] _readyHealthCheckTags = ["ready"]; + private static readonly string[] _startupHealthCheckTags = ["startup"]; + public override void ConfigureServices(ServiceConfigurationContext context) { var hostingEnvironment = context.Services.GetHostingEnvironment(); @@ -199,16 +204,17 @@ public override void ConfigureServices(ServiceConfigurationContext context) Configure(options => { options.Contributors.Add(new BackgroundJobsPageContributor()); + options.Contributors.Add(new TagManagementPageContributor()); }); context.Services.AddHealthChecks() - .AddCheck("live", tags: new[] { "live" }); + .AddCheck("live", tags: _liveHealthCheckTags); context.Services.AddHealthChecks() - .AddCheck("ready", tags: new[] { "ready" }); + .AddCheck("ready", tags: _readyHealthCheckTags); context.Services.AddHealthChecks() - .AddCheck("startup", tags: new[] { "startup" }); + .AddCheck("startup", tags: _startupHealthCheckTags); Configure(options => { @@ -218,30 +224,28 @@ public override void ConfigureServices(ServiceConfigurationContext context) private static void ConfigureDataProtection(ServiceConfigurationContext context, IConfiguration configuration) { + /* The rest of the Redis Configuration happens in the application layer */ if (!Convert.ToBoolean(configuration["DataProtection:IsEnabled"])) return; if (!Convert.ToBoolean(configuration["Redis:IsEnabled"])) return; - var configurationOptions = new ConfigurationOptions + // Configure Data Protection + if (Convert.ToBoolean(configuration["DataProtection:IsEnabled"]) && Convert.ToBoolean(configuration["Redis:IsEnabled"])) { - EndPoints = { $"{configuration["Redis:Host"]}:{configuration["Redis:Port"]}" }, - Password = configuration["Redis:Password"], - ClientName = configuration["Redis:InstanceName"] - }; - - IDataProtectionBuilder dataProtectionBuilder = context - .Services - .AddDataProtection() - .SetApplicationName("UnityGrantManagerWeb"); - - var redis = ConnectionMultiplexer - .Connect(configurationOptions); - - dataProtectionBuilder.PersistKeysToStackExchangeRedis(redis, "Unity-DataKeys"); + context.Services.AddDataProtection() + .SetApplicationName("UnityGrantManagerWeb") + .PersistKeysToStackExchangeRedis( + () => + { + var multiplexer = context.Services.GetRequiredService(); + return multiplexer.GetDatabase(); + }, + "Unity-DataKeys"); - context.Services.AddSession(options => - { - options.IdleTimeout = TimeSpan.FromHours(8); - }); + context.Services.AddSession(options => + { + options.IdleTimeout = TimeSpan.FromHours(8); + }); + } } private static void ConfigureUtils(ServiceConfigurationContext context) @@ -381,7 +385,7 @@ private void ConfigureUrls(IConfiguration configuration) } private void ConfigureBundles() - { + { Configure(options => { options @@ -396,7 +400,7 @@ private void ConfigureBundles() NotificationsBundles.Styles.Notifications, bundle => { - bundle.AddContributors(typeof(NotificationsStyleBundleContributor)); + bundle.AddContributors(typeof(NotificationsStyleBundleContributor)); }); }); } @@ -602,7 +606,9 @@ public override void OnApplicationInitialization(ApplicationInitializationContex options.SupportedUICultures = supportedCultures; }); - if (Convert.ToBoolean(configuration["DataProtection:IsEnabled"])) + // If both Redis and Data Protection are enabled then we can enable this session middleware + if (Convert.ToBoolean(configuration["Redis:IsEnabled"]) + && Convert.ToBoolean(configuration["DataProtection:IsEnabled"])) { app.UseSession(); } 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 38ef25bdb..33eb40802 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Identity/PolicyRegistrant.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Identity/PolicyRegistrant.cs @@ -60,6 +60,8 @@ internal static void Register(ServiceConfigurationContext context) policy => policy.RequireClaim(PermissionConstant, GrantApplicationPermissions.Applicants.Default)); authorizationBuilder.AddPolicy(GrantApplicationPermissions.Applicants.Edit, policy => policy.RequireClaim(PermissionConstant, GrantApplicationPermissions.Applicants.Edit)); + authorizationBuilder.AddPolicy(GrantApplicationPermissions.Applicants.AssignApplicant, + policy => policy.RequireClaim(PermissionConstant, GrantApplicationPermissions.Applicants.AssignApplicant)); authorizationBuilder.AddPolicy(GrantApplicationPermissions.Assignments.Default, policy => policy.RequireClaim(PermissionConstant, GrantApplicationPermissions.Assignments.Default)); authorizationBuilder.AddPolicy(GrantApplicationPermissions.Assignments.AssignInitial, @@ -79,6 +81,7 @@ internal static void Register(ServiceConfigurationContext context) authorizationBuilder.AddPolicy(GrantApplicationPermissions.Comments.Add, policy => policy.RequireClaim(PermissionConstant, GrantApplicationPermissions.Comments.Add)); + // R&A Policies authorizationBuilder.AddPolicy(UnitySelector.Review.Default, policy => policy.RequireClaim(PermissionConstant, UnitySelector.Review.Default)); @@ -108,6 +111,55 @@ internal static void Register(ServiceConfigurationContext context) authorizationBuilder.AddPolicy(UnitySelector.Review.AssessmentReviewList.Update.Complete, policy => policy.RequireClaim(PermissionConstant, UnitySelector.Review.AssessmentReviewList.Update.Complete)); + //-- APPLICANT INFO + authorizationBuilder.AddPolicy(UnitySelector.Applicant.Default, + policy => policy.RequireClaim(PermissionConstant, UnitySelector.Applicant.Default)); + authorizationBuilder.AddPolicy(UnitySelector.Applicant.Authority.Default, + policy => policy.RequireClaim(PermissionConstant, UnitySelector.Applicant.Authority.Default)); + authorizationBuilder.AddPolicy(UnitySelector.Applicant.Authority.Update, + policy => policy.RequireClaim(PermissionConstant, UnitySelector.Applicant.Authority.Update)); + authorizationBuilder.AddPolicy(UnitySelector.Applicant.Contact.Default, + policy => policy.RequireClaim(PermissionConstant, UnitySelector.Applicant.Contact.Default)); + authorizationBuilder.AddPolicy(UnitySelector.Applicant.Contact.Update, + policy => policy.RequireClaim(PermissionConstant, UnitySelector.Applicant.Contact.Update)); + authorizationBuilder.AddPolicy(UnitySelector.Applicant.Location.Default, + policy => policy.RequireClaim(PermissionConstant, UnitySelector.Applicant.Location.Default)); + authorizationBuilder.AddPolicy(UnitySelector.Applicant.Location.Update, + policy => policy.RequireClaim(PermissionConstant, UnitySelector.Applicant.Location.Update)); + authorizationBuilder.AddPolicy(UnitySelector.Applicant.Summary.Default, + policy => policy.RequireClaim(PermissionConstant, UnitySelector.Applicant.Summary.Default)); + authorizationBuilder.AddPolicy(UnitySelector.Applicant.Summary.Update, + policy => policy.RequireClaim(PermissionConstant, UnitySelector.Applicant.Summary.Update)); + authorizationBuilder.AddPolicy(UnitySelector.Applicant.AdditionalContact.Default, + policy => policy.RequireClaim(PermissionConstant, UnitySelector.Applicant.AdditionalContact.Default)); + authorizationBuilder.AddPolicy(UnitySelector.Applicant.AdditionalContact.Create, + policy => policy.RequireClaim(PermissionConstant, UnitySelector.Applicant.AdditionalContact.Create)); + authorizationBuilder.AddPolicy(UnitySelector.Applicant.AdditionalContact.Update, + policy => policy.RequireClaim(PermissionConstant, UnitySelector.Applicant.AdditionalContact.Update)); + + // Applicant Info Logical OR policy + authorizationBuilder.AddPolicy(UnitySelector.Applicant.UpdatePolicy, + policy => policy.RequireAssertion(context => + context.User.HasClaim(PermissionConstant, UnitySelector.Applicant.Summary.Update) || + context.User.HasClaim(PermissionConstant, UnitySelector.Applicant.Contact.Update) || + context.User.HasClaim(PermissionConstant, UnitySelector.Applicant.Authority.Update) || + context.User.HasClaim(PermissionConstant, UnitySelector.Applicant.Location.Update) || + context.User.HasClaim(PermissionConstant, UnitySelector.Applicant.AdditionalContact.Update) || + + // NOTE: This will be replaced when Worksheets are normalized with UnitySelector.Applicant.Worksheet.Update + context.User.HasClaim(PermissionConstant, UnitySelector.Applicant.Default) + )); + + //-- PAYMENT INFO + authorizationBuilder.AddPolicy(UnitySelector.Payment.Supplier.Default, + policy => policy.RequireClaim(PermissionConstant, UnitySelector.Payment.Summary.Default)); + authorizationBuilder.AddPolicy(UnitySelector.Payment.Supplier.Default, + policy => policy.RequireClaim(PermissionConstant, UnitySelector.Payment.Supplier.Default)); + authorizationBuilder.AddPolicy(UnitySelector.Payment.Supplier.Update, + policy => policy.RequireClaim(PermissionConstant, UnitySelector.Payment.Supplier.Update)); + authorizationBuilder.AddPolicy(UnitySelector.Payment.Supplier.Default, + policy => policy.RequireClaim(PermissionConstant, UnitySelector.Payment.PaymentList.Default)); + // Tenancy Policies authorizationBuilder.AddPolicy(TenantManagementPermissions.Tenants.Default, policy => policy.RequireClaim(PermissionConstant, TenantManagementPermissions.Tenants.Default)); @@ -122,12 +174,57 @@ internal static void Register(ServiceConfigurationContext context) authorizationBuilder.AddPolicy(TenantManagementPermissions.Tenants.ManageConnectionStrings, policy => policy.RequireClaim(PermissionConstant, TenantManagementPermissions.Tenants.ManageConnectionStrings)); + // Setting Management - Tag Management + authorizationBuilder.AddPolicy(UnitySelector.SettingManagement.Tags.Default, + policy => policy.RequireClaim(PermissionConstant, UnitySelector.SettingManagement.Tags.Default)); + authorizationBuilder.AddPolicy(UnitySelector.SettingManagement.Tags.Update, + policy => policy.RequireClaim(PermissionConstant, UnitySelector.SettingManagement.Tags.Update)); + authorizationBuilder.AddPolicy(UnitySelector.SettingManagement.Tags.Delete, + policy => policy.RequireClaim(PermissionConstant, UnitySelector.SettingManagement.Tags.Delete)); + // IT Administrator Policies authorizationBuilder.AddPolicy(IdentityConsts.ITAdminPolicyName, policy => policy.RequireAssertion(context => context.User.IsInRole(IdentityConsts.ITAdminRoleName) || context.User.HasClaim(c => c.Type == PermissionConstant && c.Value == IdentityConsts.ITAdminPermissionName) )); + + // Project Info Policies + authorizationBuilder.AddPolicy(UnitySelector.Project.Default, + policy => policy.RequireClaim(PermissionConstant, UnitySelector.Project.Default)); + + // Project Info Logical OR policy + authorizationBuilder.AddPolicy(UnitySelector.Project.UpdatePolicy, + policy => policy.RequireAssertion(context => + context.User.HasClaim(PermissionConstant, UnitySelector.Project.Location.Update.Default) || + context.User.HasClaim(PermissionConstant, UnitySelector.Project.Summary.Update.Default) || + + // NOTE: This will be replaced when Worksheets are normalized with UnitySelector.Project.Worksheet.Update + context.User.HasClaim(PermissionConstant, UnitySelector.Project.Default) + )); + + // Project Info - Summary Policies + authorizationBuilder.AddPolicy(UnitySelector.Project.Summary.Default, + policy => policy.RequireClaim(PermissionConstant, UnitySelector.Project.Summary.Default)); + authorizationBuilder.AddPolicy(UnitySelector.Project.Summary.Update.Default, + policy => policy.RequireClaim(PermissionConstant, UnitySelector.Project.Summary.Update.Default)); + authorizationBuilder.AddPolicy(UnitySelector.Project.Summary.Update.UpdateFinalStateFields, + policy => policy.RequireClaim(PermissionConstant, UnitySelector.Project.Summary.Update.UpdateFinalStateFields)); + + // Project Info - Location Policies + authorizationBuilder.AddPolicy(UnitySelector.Project.Location.Default, + policy => policy.RequireClaim(PermissionConstant, UnitySelector.Project.Location.Default)); + authorizationBuilder.AddPolicy(UnitySelector.Project.Location.Update.Default, + 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/Identity/UnityClaimsResolver.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Identity/UnityClaimsResolver.cs index 7610a58a7..59b026859 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Identity/UnityClaimsResolver.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Identity/UnityClaimsResolver.cs @@ -1,24 +1,21 @@ -using System; +namespace Unity.GrantManager.Web.Identity; -namespace Unity.GrantManager.Web.Identity +public static class UnityClaimsResolver { - public static class UnityClaimsResolver + /// + /// Provide the claim type and the identity provider and resolver for this combination + /// + /// + /// + /// + /// + internal static string ResolveFor(string claimType, string? idp) { - /// - /// Provide the claim type and the identity provider and resolver for this combination - /// - /// - /// - /// - /// - internal static string ResolveFor(string claimType, string? idp) + if ((idp == "idir" || idp == "azureidir") && claimType == UnityClaimsTypes.PreferredUsername) { - if ((idp == "idir" || idp == "azureidir") && claimType == UnityClaimsTypes.PreferredUsername) - { - return UnityClaimsTypes.IDirUsername; - } - - return claimType; + return UnityClaimsTypes.IDirUsername; } + + return claimType; } } diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Mapping/GrantApplicationsMapper.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Mapping/GrantApplicationsMapper.cs index 6be0c5f24..de831593f 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Mapping/GrantApplicationsMapper.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Mapping/GrantApplicationsMapper.cs @@ -2,19 +2,25 @@ using Unity.GrantManager.Applications; using Unity.GrantManager.GrantApplications; using Unity.GrantManager.Web.Pages.ApplicationContact; +using Unity.GrantManager.Web.Views.Shared.Components.ApplicantInfo; using Unity.GrantManager.Web.Views.Shared.Components.SummaryWidget; -namespace Unity.GrantManager.Web.Mapping +namespace Unity.GrantManager.Web.Mapping; + +public class GrantApplicationsMapper : Profile { - public class GrantApplicationsMapper : Profile + public GrantApplicationsMapper() { - public GrantApplicationsMapper() - { - CreateMap(); - CreateMap(). - ForMember(dest => dest.SubmissionDate, opt => opt.MapFrom(s => s.SubmissionDate==null ? "" : s.SubmissionDate.Value.ToShortDateString())); - CreateMap(); - CreateMap(); - } + CreateMap(); + CreateMap(). + ForMember(dest => dest.SubmissionDate, opt => opt.MapFrom(s => s.SubmissionDate == null ? "" : s.SubmissionDate.Value.ToShortDateString())); + CreateMap(); + CreateMap(); + + CreateMap(); + CreateMap(); + CreateMap(); + CreateMap() + .ForMember(dest => dest.PostalCode, opt => opt.MapFrom(src => src.Postal)); } } diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/Account/AccessDenied.cshtml b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/Account/AccessDenied.cshtml index a8b263402..dc991bea7 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/Account/AccessDenied.cshtml +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/Account/AccessDenied.cshtml @@ -1,14 +1,11 @@ @page @model Unity.GrantManager.Web.Pages.Account.AccessDeniedModel -@using Microsoft.AspNetCore.Mvc.Localization -@*@using Volo.Abp.Account.Localization -@inject IHtmlLocalizer L*@

Access Denied To This Page

-

Access Denied To This Page

+

Access Denied To This Page

diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/ApplicationContact/CreateContactModal.cshtml b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/ApplicationContact/CreateContactModal.cshtml index a9b508202..8cea1745a 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/ApplicationContact/CreateContactModal.cshtml +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/ApplicationContact/CreateContactModal.cshtml @@ -1,9 +1,7 @@ @page -@using Unity.GrantManager.Localization @using Microsoft.Extensions.Localization -@using Volo.Abp.AspNetCore.Mvc.UI.Layout; -@using Unity.GrantManager.Web.Pages.GrantApplications; -@using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Modal; +@using Unity.GrantManager.Localization +@using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Modal @model Unity.GrantManager.Web.Pages.ApplicationContact.CreateContactModal diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/ApplicationContact/EditContactModal.cshtml b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/ApplicationContact/EditContactModal.cshtml index 6b747ae99..437084740 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/ApplicationContact/EditContactModal.cshtml +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/ApplicationContact/EditContactModal.cshtml @@ -1,9 +1,7 @@ @page -@using Unity.GrantManager.Localization @using Microsoft.Extensions.Localization -@using Volo.Abp.AspNetCore.Mvc.UI.Layout; -@using Unity.GrantManager.Web.Pages.GrantApplications; -@using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Modal; +@using Unity.GrantManager.Localization +@using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Modal @model Unity.GrantManager.Web.Pages.ApplicationContact.EditContactModal diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/ApplicationForms/Mapping.cshtml b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/ApplicationForms/Mapping.cshtml index 84f73d989..d7e8a5a21 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/ApplicationForms/Mapping.cshtml +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/ApplicationForms/Mapping.cshtml @@ -1,17 +1,13 @@ @page @using Unity.GrantManager.ApplicationForms -@using Unity.GrantManager.Localization; @using Volo.Abp.AspNetCore.Mvc.UI.Layout; @using Unity.GrantManager.Web.Pages.ApplicationForms; -@using Microsoft.Extensions.Localization; -@using Microsoft.AspNetCore.Authorization; @using Unity.GrantManager.Permissions; @using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Modal; @using Volo.Abp.Authorization.Permissions; +@using Unity.GrantManager.Web.Views.Shared.Components.ApplicationFormConfigWidget; @model MappingModel -@inject IAuthorizationService AuthorizationService -@inject IStringLocalizer L @inject IPageLayout PageLayout @inject IPermissionChecker PermissionChecker @{ @@ -197,26 +193,13 @@ - + - + - + @await Component.InvokeAsync(typeof(ApplicationFormConfigWidget), new { configType = "Other", applicationForm = Model?.ApplicationFormDto })
diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/ApplicationForms/Mapping.cshtml.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/ApplicationForms/Mapping.cshtml.cs index 09f81f9d7..54f447565 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/ApplicationForms/Mapping.cshtml.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/ApplicationForms/Mapping.cshtml.cs @@ -113,7 +113,7 @@ public async Task OnGetAsync() IntakeProperties = JsonSerializer.Serialize(await GenerateMappingFieldsAsync()); } - + private async Task> GenerateMappingFieldsAsync() { IntakeMapping intakeMapping = new(); diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/ApplicationForms/Mapping.js b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/ApplicationForms/Mapping.js index 8db1d3361..d6058b68b 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/ApplicationForms/Mapping.js +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/ApplicationForms/Mapping.js @@ -67,12 +67,12 @@ selectVersionList: $('#applicationFormVersion'), editMappingModal: $('#editMappingModal'), linkWorksheets: $('#btn-link-worksheets'), - uiConfigurationTab: $('#nav-ui-configuration') + uiConfigurationTab: $('#nav-ui-configuration') }; init(); - worksheetsModal.onResult(function (_, response) { + worksheetsModal.onResult(function (_, response) { navigateToVersion(response.responseText.chefsFormVersionId); }); @@ -103,11 +103,11 @@ UIElements.btnClose.on('click', handleCancelMapping); UIElements.inputSearchBar.on('keyup', handleSeearchBar); UIElements.selectVersionList.on('change', handleSelectVersion); - UIElements.linkWorksheets.on('click', handleLinkWorksheets); + UIElements.linkWorksheets.on('click', handleLinkWorksheets); } function handleLinkWorksheets() { - worksheetsModal.open({ formVersionId: $('#chefsFormVersionId').val(), formName: $('#formName').val(), size: 'Large' }); + worksheetsModal.open({ formVersionId: $('#chefsFormVersionId').val(), formName: $('#formName').val(), size: 'Large' }); } function initializeUIConfiguration() { @@ -372,7 +372,8 @@ } function initializeIntakeMap(availableChefsFields) { - try { + try { + let intakeFields = JSON.parse(intakeFieldsString); for (let intakeField of intakeFields) { @@ -389,13 +390,19 @@ let keys = Object.keys(availableChefsFields); dataTable.clear(); + + let rowsToAdd = []; for (let key of keys) { let jsonObj = JSON.parse(availableChefsFields[key]); - if (allowableTypes.includes(jsonObj.type.trim())) { - dataTable.row.add([stripHtml(jsonObj.label), key, jsonObj.type, key]).draw(); + rowsToAdd.push([stripHtml(jsonObj.label), key, jsonObj.type, key]); } } + + if (rowsToAdd.length > 0) { + dataTable.rows.add(rowsToAdd); + } + dataTable.draw(); } catch (err) { console.info('Mapping error: ' + err); @@ -617,33 +624,5 @@ for (let i = 0; i < depth; i++) { prettyJson.push(TAB); } - } - - $("#directApproval").on('change', function (e) { - - let config = { - "isDirectApproval": this.checked - } - $.ajax( - { - url: `/api/app/application-form/${applicationFormId}/other-config`, - data: JSON.stringify(config), - contentType: "application/json", - type: "PUT", - success: function (data) { - - abp.notify.success( - data.responseText, - 'Settings Saved Successfully' - ); - }, - error: function (data) { - abp.notify.error( - data.responseText, - 'Settings Not Saved Successful' - ); - } - } - ); - }) + } }); diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/ApplicationLinks/ApplicationLinks.js b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/ApplicationLinks/ApplicationLinks.js index 5e9754d84..af1153ecd 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/ApplicationLinks/ApplicationLinks.js +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/ApplicationLinks/ApplicationLinks.js @@ -91,11 +91,6 @@ $(function () { // Make sure input string have no error with the plugin LinksInput.prototype.anyErrors = function (string) { - // if (this.options.max != null && this.arr.length >= this.options.max) { - // console.log('max links limit reached'); - // return true; - // } - if (!this.options.duplicate && this.arr.indexOf(string) != -1) { console.log('duplicate found " ' + string + ' " ') return true; diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/BulkApprovals/ApproveApplicationsModal.cshtml b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/BulkApprovals/ApproveApplicationsModal.cshtml index eb8d4fd59..b9ae4e4e8 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/BulkApprovals/ApproveApplicationsModal.cshtml +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/BulkApprovals/ApproveApplicationsModal.cshtml @@ -21,7 +21,7 @@ {
- +
@Model.BulkApplicationApprovals[i].ReferenceNo
@Model.BulkApplicationApprovals[i].ApplicantName
@@ -29,7 +29,16 @@
@Model.BulkApplicationApprovals[i].ApplicationStatus
- + + +
+ +
- + - + + + + - + @for (var j = 0; j < Model.BulkApplicationApprovals[i].Notes?.Count; j++) diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/BulkApprovals/ApproveApplicationsModal.cshtml.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/BulkApprovals/ApproveApplicationsModal.cshtml.cs index e0be96b5a..8bb15f7d1 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/BulkApprovals/ApproveApplicationsModal.cshtml.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/BulkApprovals/ApproveApplicationsModal.cshtml.cs @@ -1,12 +1,11 @@ using Microsoft.AspNetCore.Mvc; -using Microsoft.Extensions.Localization; using Microsoft.Extensions.Logging; using Newtonsoft.Json; using System; using System.Collections.Generic; -using System.ComponentModel; using System.Threading.Tasks; using Unity.GrantManager.GrantApplications; +using Unity.GrantManager.Web.Pages.BulkApprovals.ViewModels; using Unity.Modules.Shared.Utils; using Volo.Abp.AspNetCore.Mvc.UI.RazorPages; @@ -16,7 +15,7 @@ public class ApproveApplicationsModalModel(IBulkApprovalsAppService bulkApproval BrowserUtils browserUtils) : AbpPageModel { [BindProperty] - public List? BulkApplicationApprovals { get; set; } + public List? BulkApplicationApprovals { get; set; } [TempData] public int ApplicationsCount { get; set; } @@ -57,20 +56,22 @@ public async Task OnGetAsync(string applicationIds) foreach (var application in applications) { - var bulkApproval = new BulkApplicationApproval + var bulkApproval = new BulkApplicationApprovalViewModel { ApplicationId = application.ApplicationId, ReferenceNo = application.ReferenceNo, ApplicantName = application.ApplicantName, DecisionDate = application.FinalDecisionDate ?? DateTime.UtcNow.AddMinutes(-offsetMinutes), RequestedAmount = application.RequestedAmount, - ApprovedAmount = application.ApprovedAmount == 0m ? application.RequestedAmount : application.ApprovedAmount, + RecommendedAmount = application.RecommendedAmount, + ApprovedAmount = application.ApprovedAmount, ApplicationStatus = application.ApplicationStatus, FormName = application.FormName, IsValid = application.IsValid, - Notes = SetNotesForApplication(application) + IsDirectApproval = application.IsDirectApproval }; + SetNotes(application, bulkApproval); BulkApplicationApprovals.Add(bulkApproval); } @@ -78,25 +79,27 @@ public async Task OnGetAsync(string applicationIds) ApplicationsCount = applications.Count; } - private List SetNotesForApplication(BulkApprovalDto application) + private void SetNotes(BulkApprovalDto application, BulkApplicationApprovalViewModel bulkApproval) { - var notes = new List - { - new("DECISION_DATE_DEFAULTED", false, L.GetString("ApplicationBatchApprovalRequest:DecisionDateDefaulted"), false), - new("APPROVED_AMOUNT_DEFAULTED", false, L.GetString("ApplicationBatchApprovalRequest:ApprovedAmountDefaulted"), false), - new("INVALID_STATUS", false, L.GetString("ApplicationBatchApprovalRequest:InvalidStatus"), true), - new("INVALID_PERMISSIONS", false, L.GetString("ApplicationBatchApprovalRequest:InvalidPermissions"), true), - new("INVALID_APPROVED_AMOUNT", false, L.GetString("ApplicationBatchApprovalRequest:InvalidApprovedAmount"), true) - }; + /* + * 0 - Decision Date Defaulted + * 1 - Approved Amount Defaulted + * 2 - Invalid Status + * 3 - Invalid Permissions + * 4 - Invalid Approved Amount + * 5 - Invalid Recommended Amount + */ + + List notes = ApprovalNoteViewModel.CreateNotesList(localizer: L); if (application.FinalDecisionDate == null) { - notes[0] = new ApprovalNote(notes[0].Key, true, notes[0].Description, notes[0].IsError); + notes[0] = new ApprovalNoteViewModel(notes[0].Key, true, notes[0].Description, notes[0].IsError); } - if (application.ApprovedAmount == 0m) + if (bulkApproval.ApprovedAmount == 0m) // this will be defaulted either way if is 0 { - notes[0] = new ApprovalNote(notes[1].Key, true, notes[1].Description, notes[1].IsError); + notes[1] = new ApprovalNoteViewModel(notes[1].Key, true, notes[1].Description, notes[1].IsError); } foreach (var validation in application.ValidationMessages) @@ -104,11 +107,11 @@ private List SetNotesForApplication(BulkApprovalDto application) var index = notes.FindIndex(note => note.Key == validation); if (index != -1) { - notes[index] = new ApprovalNote(validation, true, notes[index].Description, notes[index].IsError); + notes[index] = new ApprovalNoteViewModel(validation, true, notes[index].Description, notes[index].IsError); } } - return notes; + bulkApproval.Notes = notes; } public async Task OnPostAsync() @@ -136,6 +139,7 @@ public async Task OnPostAsync() private List MapBulkApprovalRequests() { var bulkApprovals = new List(); + foreach (var application in BulkApplicationApprovals ?? []) { bulkApprovals.Add(new BulkApprovalDto() @@ -143,6 +147,8 @@ private List MapBulkApprovalRequests() ApplicantName = application.ApplicantName ?? string.Empty, ApplicationId = application.ApplicationId, ApprovedAmount = application.ApprovedAmount, + RecommendedAmount = application.RecommendedAmount, + IsDirectApproval = application.IsDirectApproval, FinalDecisionDate = application.DecisionDate, ReferenceNo = application.ReferenceNo, RequestedAmount = application.RequestedAmount, @@ -163,45 +169,4 @@ private bool ValidCount(Guid[] applicationGuids) // Soft check in the UI for max approvals in one batch, this is subject to be tweaked later after performance testing return applicationGuids.Length <= MaxBatchCount; } - - public class BulkApplicationApproval - { - public BulkApplicationApproval() - { - Notes = []; - } - - public Guid ApplicationId { get; set; } - public string ReferenceNo { get; set; } = string.Empty; - public string? ApplicantName { get; set; } = string.Empty; - public string FormName { get; set; } = string.Empty; - public string ApplicationStatus { get; set; } = string.Empty; - - [DisplayName("Requested Amount")] - public decimal RequestedAmount { get; set; } = 0m; - - [DisplayName("Approved Amount")] - public decimal ApprovedAmount { get; set; } = 0m; - - [DisplayName("Decision Date")] - public DateTime DecisionDate { get; set; } - public bool IsValid { get; set; } - public List Notes { get; set; } - } - - public class ApprovalNote - { - public ApprovalNote(string key, bool active, string description, bool isError) - { - Key = key; - Active = active; - Description = description; - IsError = isError; - } - - public string Key { get; set; } - public bool Active { get; set; } - public string Description { get; set; } - public bool IsError { get; set; } - } } diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/BulkApprovals/ApproveApplicationsModal.css b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/BulkApprovals/ApproveApplicationsModal.css index 6c0d55f71..4f41ee12a 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/BulkApprovals/ApproveApplicationsModal.css +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/BulkApprovals/ApproveApplicationsModal.css @@ -112,4 +112,8 @@ .batch-approval-summary { text-align: center; +} + +.batch-direct-approval-indicator { + padding-left: 1rem; } \ No newline at end of file diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/BulkApprovals/ViewModels/ApprovalNoteViewModel.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/BulkApprovals/ViewModels/ApprovalNoteViewModel.cs new file mode 100644 index 000000000..1ab475991 --- /dev/null +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/BulkApprovals/ViewModels/ApprovalNoteViewModel.cs @@ -0,0 +1,34 @@ +using Microsoft.Extensions.Localization; +using System.Collections.Generic; + +namespace Unity.GrantManager.Web.Pages.BulkApprovals.ViewModels +{ + public class ApprovalNoteViewModel + { + public ApprovalNoteViewModel(string key, bool active, string description, bool isError) + { + Key = key; + Active = active; + Description = description; + IsError = isError; + } + + public string Key { get; set; } + public bool Active { get; set; } + public string Description { get; set; } + public bool IsError { get; set; } + + public static List CreateNotesList(IStringLocalizer localizer) + { + return + [ + new("DECISION_DATE_DEFAULTED", false, localizer.GetString("ApplicationBatchApprovalRequest:DecisionDateDefaulted"), false), + new("APPROVED_AMOUNT_DEFAULTED", false, localizer.GetString("ApplicationBatchApprovalRequest:ApprovedAmountDefaulted"), false), + new("INVALID_STATUS", false, localizer.GetString("ApplicationBatchApprovalRequest:InvalidStatus"), true), + new("INVALID_PERMISSIONS", false, localizer.GetString("ApplicationBatchApprovalRequest:InvalidPermissions"), true), + new("INVALID_APPROVED_AMOUNT", false, localizer.GetString("ApplicationBatchApprovalRequest:InvalidApprovedAmount"), true), + new("INVALID_RECOMMENDED_AMOUNT", false, localizer.GetString("ApplicationBatchApprovalRequest:InvalidRecommendedAmount"), true) + ]; + } + } +} diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/BulkApprovals/ViewModels/BulkApplicationApproval.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/BulkApprovals/ViewModels/BulkApplicationApproval.cs new file mode 100644 index 000000000..3a6618e8f --- /dev/null +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/BulkApprovals/ViewModels/BulkApplicationApproval.cs @@ -0,0 +1,35 @@ +using System.Collections.Generic; +using System.ComponentModel; +using System; + +namespace Unity.GrantManager.Web.Pages.BulkApprovals.ViewModels +{ + public class BulkApplicationApprovalViewModel + { + public BulkApplicationApprovalViewModel() + { + Notes = []; + } + + public Guid ApplicationId { get; set; } + public string ReferenceNo { get; set; } = string.Empty; + public string? ApplicantName { get; set; } = string.Empty; + public string FormName { get; set; } = string.Empty; + public string ApplicationStatus { get; set; } = string.Empty; + + [DisplayName("Requested Amount")] + public decimal RequestedAmount { get; set; } = 0m; + + [DisplayName("Approved Amount")] + public decimal ApprovedAmount { get; set; } = 0m; + + [DisplayName("Decision Date")] + public DateTime DecisionDate { get; set; } + public bool IsValid { get; set; } + public List Notes { get; set; } + public bool? IsDirectApproval { get; internal set; } + + [DisplayName("Recommended Amount")] + public decimal RecommendedAmount { get; internal set; } + } +} diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/Dashboard/Index.cshtml b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/Dashboard/Index.cshtml index 728faa437..be2f3c00a 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/Dashboard/Index.cshtml +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/Dashboard/Index.cshtml @@ -14,6 +14,7 @@ + }
diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/GrantApplications/Details.cshtml b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/GrantApplications/Details.cshtml index c7d15a33c..3f8837388 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/GrantApplications/Details.cshtml +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/GrantApplications/Details.cshtml @@ -1,23 +1,15 @@ @page "{@Model.ApplicationFormSubmissionId?}" @* #pragma warning disable S1128 *@ +@using Microsoft.Extensions.Localization @using Unity.Flex.Web.Views.Shared.Components.WorksheetInstanceWidget @using Unity.GrantManager.Flex @using Unity.GrantManager.Localization -@using Unity.GrantManager.Settings -@using Unity.GrantManager.Web.Views.Shared.Components.CommentsWidget; -@using Unity.GrantManager.Web.Views.Shared.Components.HistoryWidget; +@using Unity.GrantManager.Web.Pages.GrantApplications @using Unity.GrantManager.Web.Views.Shared.Components.CustomTabWidget -@using Unity.GrantManager.Web.Views.Shared.Components.DetailsActionBar; -@using Unity.GrantManager.Web.Views.Shared.Components.ReviewList; -@using Unity.GrantManager.Web.Views.Shared.Components.UserInfoWidget; -@using Unity.GrantManager.Web.Views.Shared.Components.AssessmentResults; -@using Unity.GrantManager.Web.Views.Shared.Components.AssessmentScoresWidget; -@using Unity.GrantManager.Web.Views.Shared.Components.ProjectInfo; +@using Unity.GrantManager.Web.Views.Shared.Components.DetailsActionBar @using Unity.Modules.Shared @using Unity.Modules.Shared.Correlation @using Volo.Abp.AspNetCore.Mvc.UI.Layout -@using Unity.GrantManager.Web.Pages.GrantApplications -@using Microsoft.Extensions.Localization @using Volo.Abp.Authorization.Permissions @using Volo.Abp.Features @using Volo.Abp.MultiTenancy @@ -46,8 +38,8 @@ @section scripts { - - + + } @@ -86,12 +78,20 @@ return initials; } - public bool IsZoneVisible(string zoneName) => Model.ZoneStateSet.Contains(zoneName); - - public string ZoneCssClass(string zoneName) => IsZoneVisible(zoneName) ? string.Empty : "d-none"; + public async Task IsZoneVisible(string zoneName) => Model.ZoneStateSet.Contains(zoneName) && await PermissionChecker.IsGrantedAsync(zoneName); + public bool IsZoneEnabled(string zoneName) => Model.ZoneStateSet.Contains(zoneName); + public string ZoneCssClass(string zoneName) => IsZoneEnabled(zoneName) ? string.Empty : "d-none"; } +
- unity-application-loading +
+ unity-application-loading +
+
+
+ Loading... +
+
@@ -121,7 +121,7 @@ @*-------- Submission Section END ---------*@ @*-------- Review & Assessment Section ---------*@ - @if (IsZoneVisible(UnitySelector.Review.Default)) + @if (await IsZoneVisible(UnitySelector.Review.Default)) {
@@ -173,10 +173,10 @@ @*-------- Review & Assessment Section END ---------*@ @*-------- Project Info Section ---------*@ - @if (IsZoneVisible(UnitySelector.Project.Default)) + @if (await IsZoneVisible(UnitySelector.Project.Default)) { -
+
@await Component.InvokeAsync("ProjectInfo", new { applicationId = Model.ApplicationId, applicationFormVersionId = Model.ApplicationFormVersionId })
@@ -184,10 +184,10 @@ @*-------- Project Info Section END ---------*@ @*-------- Applicant Info Section ---------*@ - @if (IsZoneVisible(UnitySelector.Applicant.Default)) + @if (await IsZoneVisible(UnitySelector.Applicant.Default)) { -
+
@await Component.InvokeAsync("ApplicantInfo", new { applicationId = Model.ApplicationId, applicationFormVersionId = Model.ApplicationFormVersionId })
@@ -196,7 +196,7 @@ @*-------- Applicant Info Section END ---------*@ @*-------- Funding Agreement Info Section ---------*@ - @if (IsZoneVisible(UnitySelector.Funding.Default)) + @if (IsZoneEnabled(UnitySelector.Funding.Default)) {
@@ -207,11 +207,10 @@ @*-------- Funding Agreement Section END ---------*@ @*-------- Payments Section ---------*@ - @if (await FeatureChecker.IsEnabledAsync("Unity.Payments") - && IsZoneVisible(UnitySelector.Payment.Default)) + @if (await FeatureChecker.IsEnabledAsync("Unity.Payments") && IsZoneEnabled(UnitySelector.Payment.Default)) { -
+
@await Component.InvokeAsync("PaymentInfo", new { applicationId = Model.ApplicationId, applicationFormVersionId = Model.ApplicationFormVersionId })
diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/GrantApplications/Details.cshtml.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/GrantApplications/Details.cshtml.cs index d2e1e6541..71915a418 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/GrantApplications/Details.cshtml.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/GrantApplications/Details.cshtml.cs @@ -2,23 +2,22 @@ using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.Rendering; +using Microsoft.Extensions.Configuration; using System; using System.Collections.Generic; +using System.Linq; using System.Threading.Tasks; -using Unity.GrantManager.GrantApplications; -using Volo.Abp.AspNetCore.Mvc.UI.RazorPages; -using Volo.Abp.Users; -using Microsoft.Extensions.Configuration; +using Unity.Flex.WorksheetLinks; using Unity.Flex.Worksheets; +using Unity.GrantManager.ApplicationForms; using Unity.GrantManager.Applications; -using Unity.Modules.Shared.Correlation; -using Volo.Abp.Features; -using System.Linq; using Unity.GrantManager.Flex; -using Unity.Flex.WorksheetLinks; -using Newtonsoft.Json.Linq; -using Unity.GrantManager.ApplicationForms; +using Unity.GrantManager.GrantApplications; using Unity.GrantManager.Zones; +using Unity.Modules.Shared.Correlation; +using Volo.Abp.AspNetCore.Mvc.UI.RazorPages; +using Volo.Abp.Features; +using Volo.Abp.Users; namespace Unity.GrantManager.Web.Pages.GrantApplications { @@ -113,7 +112,7 @@ public async Task OnGetAsync() { ApplicationFormSubmission applicationFormSubmission = await _grantApplicationAppService.GetFormSubmissionByApplicationId(ApplicationId); ZoneStateSet = await _zoneManagementAppService.GetZoneStateSetAsync(applicationFormSubmission.ApplicationFormId); - + if (await _featureChecker.IsEnabledAsync("Unity.Flex")) { // Need to look at finding another way to extract / store this info on intake diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/GrantApplications/Details.css b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/GrantApplications/Details.css index 5a901ba72..1a0a3bd7e 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/GrantApplications/Details.css +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/GrantApplications/Details.css @@ -1,15 +1,4 @@ -@media (min-width: 1400px) { - .container-xxl, - .container-xl, - .container-lg, - .container-md, - .container-sm, - .container { - max-width: 1600px; - } -} - -.application-details-container { +.application-details-container { width: 100%; } @@ -23,7 +12,7 @@ .card-header:not(.card-body .card-header)::before { content: ' '; - display: inline-block; + display: block; border-bottom: 1px solid #313132; border-right: 1px solid #313132; height: 10px; @@ -35,7 +24,7 @@ .card-header:not(.card-body .card-header).custom-active::before { content: ' '; - display: inline-block; + display: block; border-bottom: 1px solid #313132; border-right: 1px solid #313132; height: 10px; @@ -54,9 +43,8 @@ font-weight: bold !important; } - /* Target elements with class names starting with 'same-class' */ -[class^="formio-component-nextTab"] { +[class^='formio-component-nextTab'] { /* Apply your common CSS styles here */ display: none; /* Add more common styles as needed */ @@ -82,11 +70,9 @@ border-right: 1px solid #dddddd; } - - .add-review-btn { background: #003366; - color: #FFFFFF; + color: #ffffff; border: 0px; border-radius: 3px; font-weight: 400; @@ -147,7 +133,7 @@ gap: 8px; display: flex; background: #003366; - color: #FFFFFF; + color: #ffffff; border: 0px; border-radius: 3px; font-weight: 400; @@ -156,11 +142,9 @@ margin-top: 1rem; } - - .recom-select { background: #003366; - color: #FFFFFF; + color: #ffffff; border: 0px; border-radius: 3px; font-weight: 400; @@ -168,7 +152,7 @@ } .recom-select:hover { - background: #FFFFFF; + background: #ffffff; color: #333; } @@ -219,7 +203,6 @@ textarea::placeholder { color: #b9b9b9 !important; } - #widget { position: relative; } @@ -228,7 +211,7 @@ textarea::placeholder { position: absolute; top: 0; right: 0; - background-color: #FFFFFF; + background-color: #ffffff; box-shadow: 1px 1px 1px rgba(0, 0, 0, 0.1); } @@ -251,14 +234,13 @@ select.selected { background-color: #fff !important; } - .review-list-heading { margin-left: 0.5rem; margin-top: 0.3rem; } .mb-2.card.border { - border-bottom: 1px solid rgba(214, 214, 214, 1) + border-bottom: 1px solid rgba(214, 214, 214, 1); } .card-header.bg-default { @@ -305,7 +287,6 @@ select.selected { overflow-y: scroll; overflow-x: hidden; height: calc(100vh - 300px); - /* position: relative; */ z-index: 1; } @@ -354,7 +335,6 @@ div#formio button { display: none; } - form label.error { color: #dc3545 !important; font-size: 0.8em; @@ -404,14 +384,8 @@ form label.error { .fade-in-load { opacity: 0; transition: opacity 0.15s ease-in-out; - /* Adjust the duration and easing as needed */ } .fade-in-load.visible { opacity: 1; } - -#main-loading { - display: flex; - justify-content: center; -} \ No newline at end of file diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/GrantApplications/Details.js b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/GrantApplications/Details.js index c1924ad9e..1ef50c38d 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/GrantApplications/Details.js +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/GrantApplications/Details.js @@ -70,7 +70,7 @@ $(function () { let submissionJson = JSON.parse(submissionDataString); let formSchema; let submissionData; - + // Check if the submission data is pure data or the entire form if (submissionJson.version !== undefined && submissionJson.submission !== undefined) { // The submission data is in the form of a version and submission object @@ -336,75 +336,94 @@ $(function () { }); $('#printPdf').click(function () { - let submissionId = getSubmissionId(); - - // Fetch submission data - fetchSubmissionData(submissionId) - .done(function (result) { - openDataInNewTab(result, submissionId); - }) - .fail(function (error) { - console.error('Error fetching submission data:', error); - }); - }); + let submissionId = document.getElementById('ChefsSubmissionId').value; + let submissionDataString = document.getElementById('ApplicationFormSubmissionData').value; + let formSchemaString = document.getElementById('ApplicationFormSchema').value; + let submissionJson = JSON.parse(submissionDataString); + let formSchema; + let submissionData; + + // Initialize data with correct structure + let data = { + version: { + schema: null + }, + submission: { + submission: null + } + }; - // Get submission ID from the input field - function getSubmissionId() { - return document.getElementById('ChefsSubmissionId').value; - } + // Determine how to extract form schema and submission + if (submissionJson.version !== undefined && submissionJson.submission !== undefined) { + formSchema = submissionJson.version.schema; + submissionData = submissionJson.submission.submission; + } else if (formSchemaString !== undefined && formSchemaString !== "") { + formSchema = JSON.parse(formSchemaString); + submissionData = submissionJson.submission; + } - // Fetch the submission data - function fetchSubmissionData(submissionId) { - return unity.grantManager.intakes.submission.getSubmission(submissionId); - } + data.version.schema = formSchema; + data.submission.submission = submissionData; - // Handle the submission result - function openDataInNewTab(data, submissionId) { + // Open a new tab let newTab = window.open('', '_blank'); - let newDiv = $('
'); - // Set the ID for the new div - newDiv.attr('id', 'new-rendering'); + // Wait for the new tab's document to be available + const doc = newTab.document; - // Add some content to the new div if needed - newDiv.html('Content for the new div'); + // Set title + doc.title = "Print"; - // Store the outer HTML of the new div in divToStore - let divToStore = newDiv.prop('outerHTML'); + // HEAD + const head = doc.head; - newTab.document.write('Print'); - newTab.document.write(''); - newTab.document.write(''); - newTab.document.write(''); - newTab.document.write(''); - newTab.document.write(''); + const jqueryScript = doc.createElement('script'); + jqueryScript.src = '/libs/jquery/jquery.js'; - let newHiddenInput = $(''); - // Set attributes for the hidden input - newHiddenInput.attr({ - 'type': 'hidden', - 'name': 'ApplicationFormSubmissionId', - 'value': submissionId - }); + const formioScript = doc.createElement('script'); + formioScript.src = '/libs/formiojs/formio.form.min.js'; - let inputToStore = newHiddenInput.prop('outerHTML'); - newTab.document.write(inputToStore); - newTab.document.write(divToStore); - newTab.document.write(''); - newTab.onload = function () { - let script = newTab.document.createElement('script'); - script.src = '/Pages/GrantApplications/loadPrint.js'; - script.onload = function () { - newTab.executeOperations(data); + const bootstrapCSS = doc.createElement('link'); + bootstrapCSS.rel = 'stylesheet'; + bootstrapCSS.href = '/libs/bootstrap-4/dist/css/bootstrap.min.css'; - }; + const formioCSS = doc.createElement('link'); + formioCSS.rel = 'stylesheet'; + formioCSS.href = '/libs/formiojs/formio.form.css'; - newTab.document.head.appendChild(script); + head.appendChild(jqueryScript); + head.appendChild(formioScript); + head.appendChild(bootstrapCSS); + head.appendChild(formioCSS); + + // BODY + const body = doc.body; + + // Hidden input + const hiddenInput = doc.createElement('input'); + hiddenInput.type = 'hidden'; + hiddenInput.name = 'ApplicationFormSubmissionId'; + hiddenInput.value = submissionId; + body.appendChild(hiddenInput); + + // Placeholder div + const formContainer = doc.createElement('div'); + formContainer.id = 'new-rendering'; + formContainer.textContent = 'Loading form...'; + body.appendChild(formContainer); + // Load your custom script after Form.io is ready + formioScript.onload = () => { + const customScript = doc.createElement('script'); + customScript.src = '/Pages/GrantApplications/loadPrint.js'; + customScript.onload = function () { + // Call your global executeOperations function + newTab.executeOperations(data); + }; + head.appendChild(customScript); }; + }); - newTab.document.close(); - } function openScoreSheetDataInNewTab(assessmentScoresheet) { let newTab = window.open('', '_blank'); @@ -477,12 +496,12 @@ $(function () { } } }; - + const assessmentResultObserver = new MutationObserver(widgetCallback); - if (assessmentResultTargetNode) { + if (assessmentResultTargetNode) { assessmentResultObserver.observe(assessmentResultTargetNode, widgetConfig); - } + } PubSub.subscribe( 'application_status_changed', diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/GrantApplications/Index.cshtml b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/GrantApplications/Index.cshtml index 7c3c10651..2f79a046e 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/GrantApplications/Index.cshtml +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/GrantApplications/Index.cshtml @@ -1,39 +1,28 @@ -@page "{formId:guid?}" +@page + @using Unity.GrantManager.Localization @using Volo.Abp.AspNetCore.Mvc.UI.Layout @using Unity.GrantManager.Web.Pages.GrantApplications @using Microsoft.Extensions.Localization + @model IndexModel + @inject IStringLocalizer L @inject IPageLayout PageLayout @{ PageLayout.Content.MenuItemName = "GrantManager.GrantApplications"; PageLayout.Content.Title = L["Applications"].Value; - ViewBag.UserName = "Test User"; ViewBag.PageTitle = "Applications"; } + @section scripts { - @if (Model.FormId == null) - { - - - - } - else - { - - } + + } @section styles { - + }
@@ -42,5 +31,3 @@
- - diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/GrantApplications/Index.cshtml.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/GrantApplications/Index.cshtml.cs index 563fd0b5c..89b9ab843 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/GrantApplications/Index.cshtml.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/GrantApplications/Index.cshtml.cs @@ -6,50 +6,54 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; +using Unity.Modules.Shared.Permissions; using Volo.Abp.Identity; using Volo.Abp.Identity.Integration; -namespace Unity.GrantManager.Web.Pages.GrantApplications +namespace Unity.GrantManager.Web.Pages.GrantApplications; + +[Authorize] +public class IndexModel : GrantManagerPageModel { - [Authorize] - public class IndexModel : GrantManagerPageModel - { - [BindProperty] - public Guid AssigneeId { get; set; } - public List AssigneeList { get; set; } = new(); + [BindProperty] + public Guid AssigneeId { get; set; } + public List AssigneeList { get; set; } = []; - [BindProperty(SupportsGet = true)] - public Guid? FormId { get; set; } + public IReadOnlyList Users { get; set; } = []; - public IReadOnlyList Users { get; set; } = new List(); + private readonly IIdentityUserIntegrationService _identityUserLookupAppService; - private readonly IIdentityUserIntegrationService _identityUserLookupAppService; + public IndexModel(IIdentityUserIntegrationService identityUserLookupAppService) + { + _identityUserLookupAppService = identityUserLookupAppService ?? throw new ArgumentNullException(nameof(identityUserLookupAppService)); + } - public IndexModel(IIdentityUserIntegrationService identityUserLookupAppService) + public async Task OnGetAsync() + { + try { - _identityUserLookupAppService = identityUserLookupAppService ?? throw new ArgumentNullException(nameof(identityUserLookupAppService)); - } - public async Task OnGetAsync() - { - try + if (User.IsInRole(IdentityConsts.ITAdminRoleName)) { - var users = (await _identityUserLookupAppService.SearchAsync(new UserLookupSearchInputDto())).Items; - AssigneeList ??= new List(); - foreach (var user in users.OrderBy(s => s.UserName)) - { - AssigneeList.Add(new() - { - Value = user.Id.ToString(), - Text = $"{user.Name} {user.Surname}", - }); - } + Response.Redirect("/TenantManagement/Tenants"); + return; } - catch (Exception ex) + + var users = (await _identityUserLookupAppService.SearchAsync(new UserLookupSearchInputDto())).Items; + AssigneeList ??= new List(); + foreach (var user in users.OrderBy(s => s.UserName)) { - Logger.LogError(ex, message: "Error loading users select list"); + AssigneeList.Add(new() + { + Value = user.Id.ToString(), + Text = $"{user.Name} {user.Surname}", + }); } } + catch (Exception ex) + { + Logger.LogError(ex, message: "Error loading users select list"); + } } } \ No newline at end of file diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/GrantApplications/Index.js b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/GrantApplications/Index.js index 8b7792d34..0cc15ab4d 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/GrantApplications/Index.js +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/GrantApplications/Index.js @@ -7,21 +7,19 @@ const listColumns = getColumns(); const defaultVisibleColumns = ['select', 'applicantName', - 'referenceNo', 'category', + 'referenceNo', 'submissionDate', - 'projectName', - 'subsector', - 'totalProjectBudget', - 'assignees', 'status', + 'subStatusDisplayValue', + 'community', 'requestedAmount', 'approvedAmount', - 'economicRegion', - 'regionalDistrict', - 'community', - 'orgNumber', - 'orgBookStatus']; + 'projectName', + 'applicantId', + 'applicationTag', + 'assignees' + ] //For stateRestore label in modal let languageSetValues = { @@ -69,6 +67,44 @@ }, buttons: [ { extend: 'createState', text: 'Save As View' }, + { + text: "Reset to Default View", + action: function (e, dt, node, config) + { + dt.columns().visible(false); + + // List of all columns not including default columns + const allColumnNames = dt.settings()[0].aoColumns.map(col => col.name).filter(colName => !defaultVisibleColumns.includes(colName)); + const orderedIndexes = []; + + // Set the visible columns, and collect id's for the reorder + defaultVisibleColumns.forEach((colName) => { + const colIdx = dt.column(`${colName}:name`).index(); + if (colIdx !== undefined && colIdx !== -1) { + dt.column(colIdx).visible(true); + orderedIndexes.push(colIdx); + } + }); + + // Column reorder only works if all columns included in new order, so get the rest of the columns + allColumnNames.forEach((colName) => { + const colIdx = dt.column(`${colName}:name`).index(); + if (colIdx !== undefined && colIdx !== -1) { + orderedIndexes.push(colIdx); + } + }) + dt.colReorder.order(orderedIndexes); + + dt.order([4, 'asc']).search('').draw(); + + // Close the dropdown + dt.buttons('.grp-savedStates') + .container() + .find('.dt-button-collection') + .hide(); + $('div.dt-button-background').trigger('click'); + } + }, { extend: 'removeAllStates', text: 'Delete All Views' }, { extend: 'spacer', @@ -82,10 +118,20 @@ return { recordsTotal: result.totalCount, recordsFiltered: result.totalCount, - data: result.items + data: formatItems(result.items) }; }; + let formatItems = function (items) { + const newData = items.map((item, index) => { + return { + ...item, + rowCount: index + }; + }); + return newData; + } + dataTable = initializeDataTable({ dt, defaultVisibleColumns, @@ -179,6 +225,7 @@ getTotalProjectBudgetPercentageColumn(), getTotalPaidAmountColumn(), getElectoralDistrictColumn(), + getApplicantElectoralDistrictColumn(), getForestryOrNonForestryColumn(), getForestryFocusColumn(), getAcquisitionColumn(), @@ -523,7 +570,7 @@ function getElectoralDistrictColumn() { return { - title: 'Electoral District', + title: 'Project Electoral District', name: 'electoralDistrict', data: 'electoralDistrict', className: 'data-table-header', @@ -779,7 +826,7 @@ data: 'organizationType', className: 'data-table-header', render: function (data) { - return data ?? ''; + return getFullType(data) ?? ''; }, index: 39 } @@ -1083,6 +1130,60 @@ } } + function getApplicantElectoralDistrictColumn() { + return { + title: 'Applicant Electoral District', + name: 'applicantElectoralDistrict', + data: 'applicant.electoralDistrict', + className: 'data-table-header', + render: function (data) { + return data ?? ''; + }, + index: 63 + } + } + + function getFullType(code) { + const companyTypes = [ + { code: "BC", name: "BC Company" }, + { code: "CP", name: "Cooperative" }, + { code: "GP", name: "General Partnership" }, + { code: "S", name: "Society" }, + { code: "SP", name: "Sole Proprietorship" }, + { code: "A", name: "Extraprovincial Company" }, + { code: "B", name: "Extraprovincial" }, + { code: "BEN", name: "Benefit Company" }, + { code: "C", name: "Continuation In" }, + { code: "CC", name: "BC Community Contribution Company" }, + { code: "CS", name: "Continued In Society" }, + { code: "CUL", name: "Continuation In as a BC ULC" }, + { code: "EPR", name: "Extraprovincial Registration" }, + { code: "FI", name: "Financial Institution" }, + { code: "FOR", name: "Foreign Registration" }, + { code: "LIB", name: "Public Library Association" }, + { code: "LIC", name: "Licensed (Extra-Pro)" }, + { code: "LL", name: "Limited Liability Partnership" }, + { code: "LLC", name: "Limited Liability Company" }, + { code: "LP", name: "Limited Partnership" }, + { code: "MF", name: "Miscellaneous Firm" }, + { code: "PA", name: "Private Act" }, + { code: "PAR", name: "Parish" }, + { code: "QA", name: "CO 1860" }, + { code: "QB", name: "CO 1862" }, + { code: "QC", name: "CO 1878" }, + { code: "QD", name: "CO 1890" }, + { code: "QE", name: "CO 1897" }, + { code: "REG", name: "Registraton (Extra-pro)" }, + { code: "ULC", name: "BC Unlimited Liability Company" }, + { code: "XCP", name: "Extraprovincial Cooperative" }, + { code: "XL", name: "Extrapro Limited Liability Partnership" }, + { code: "XP", name: "Extraprovincial Limited Partnership" }, + { code: "XS", name: "Extraprovincial Society" } + ]; + const match = companyTypes.find(entry => entry.code === code); + return match ? match.name : "Unknown"; + } + window.addEventListener('resize', () => { }); diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/GrantApplications/Intake.js b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/GrantApplications/Intake.js deleted file mode 100644 index f626105ef..000000000 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/GrantApplications/Intake.js +++ /dev/null @@ -1,105 +0,0 @@ -$(function () { - const formatter = new Intl.NumberFormat('en-CA', { - style: 'currency', - currency: 'CAD', - minimumFractionDigits: 2, - maximumFractionDigits: 2 - }); - - const l = abp.localization.getResource('GrantManager'); - - const placeholderText = function () { - return "PLACEHOLDER"; - } - - let inputAction = function (requestData, dataTableSettings) { - return document.getElementById('PassFormIdToJavaScript').value; - } - - $('#GrantApplicationsTable').DataTable( - abp.libs.datatables.normalizeConfiguration({ - serverSide: true, - paging: true, - order: [[1, "asc"]], - searching: false, - scrollX: true, - ajax: - abp.libs.datatables.createAjax( - unity.grantManager.intakes.submission.getSubmissionsList, inputAction), - columnDefs: [ - { - title: l('ProjectName'), - data: "projectTitle" - }, - { - title: l('ReferenceNo'), - data: "confirmationId", - render: function (data) { - return '' + data + ''; - } - }, - { - title: l('EligibleAmount'), - data: "totalRequestToMjf", - render: function (data) { - return formatter.format(data) - } - }, - { - title: l('RequestedAmount'), - data: "eligibleCost", - render: function (data) { - return formatter.format(data) - } - }, - { - title: l('Assignee'), - data: "assignees", - render: placeholderText - //render: function (data) { - // return (!data || data.length === 0) ? null : data.length > 1 ? l('Multiple') : data[0].username; - //} - }, - { - title: l('Probability'), - data: "probability", - render: placeholderText - }, - { - title: l('GrantApplicationStatus'), - data: "status", - render: placeholderText - //render: (data) => l('Enum:GrantApplicationStatus.' + data) - }, - { - title: l('ProposalDate'), - data: "proposalDate", - render: placeholderText - }, - { - title: l('ProposalDate'), - data: "proposalDate", - render: placeholderText - //render: function (data) { - // return luxon - // .DateTime - // .fromISO(data, { - // locale: abp.localization.currentCulture.name - // }).toLocaleString(); - //} - }, - { - title: l('SubmissionDate'), - data: "createdAt", - render: function (data) { - return luxon - .DateTime - .fromISO(data, { - locale: abp.localization.currentCulture.name - }).toLocaleString(); - } - }, - ] - }) - ); -}); diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/GrantApplications/ScoresheetPrint.css b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/GrantApplications/ScoresheetPrint.css index 3e7218020..b2cd89f79 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/GrantApplications/ScoresheetPrint.css +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/GrantApplications/ScoresheetPrint.css @@ -18,12 +18,10 @@ button { display: none; } - .user-role-full { margin-left: 20px; } - .form-control:disabled, .form-control[readonly] { background-color: #ffffff; @@ -40,22 +38,10 @@ button { overflow-anchor: none; } -&:hover { - z-index: 2; -} - -&:focus { - z-index: 3; - outline: 0; - -} - - .accordion-header { margin-bottom: 0; } - #assessment-scoresheet #section-button::after { -webkit-filter: grayscale(1) invert(0); filter: grayscale(1) invert(0); @@ -69,4 +55,4 @@ button { #assessment-scoresheet .preview-btn:not(.collapsed) { background-color: #007bff; color: #ffffff; -} \ No newline at end of file +} diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/GrantPrograms/Index.cshtml b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/GrantPrograms/Index.cshtml index 9f858a354..71b133178 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/GrantPrograms/Index.cshtml +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/GrantPrograms/Index.cshtml @@ -1,11 +1,13 @@ @page +@using Microsoft.Extensions.Localization @using Unity.GrantManager.Localization @using Volo.Abp.AspNetCore.Mvc.UI.Layout -@using Unity.GrantManager.Web.Pages.Intakes -@using Microsoft.Extensions.Localization + @model Unity.GrantManager.Web.Pages.GrantPrograms.IndexModel + @inject IStringLocalizer L @inject IPageLayout PageLayout + @{ PageLayout.Content.MenuItemName = "GrantManager.GrantPrograms"; PageLayout.Content.Title = L["GrantPrograms"].Value; diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/SettingManagement/TagManagement/RenameTagModal.cshtml b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/SettingManagement/TagManagement/RenameTagModal.cshtml new file mode 100644 index 000000000..99b743841 --- /dev/null +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/SettingManagement/TagManagement/RenameTagModal.cshtml @@ -0,0 +1,29 @@ +@page +@using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form +@using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Modal + +@model Unity.GrantManager.Web.Pages.SettingManagement.TagManagement.RenameTagModal +@{ + Layout = null; +} + +@if (Model.ViewModel == null) +{ + throw new InvalidOperationException("ViewModel cannot be null."); +} + + +
+ + + + + + + + + + + +
+ diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/SettingManagement/TagManagement/RenameTagModal.cshtml.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/SettingManagement/TagManagement/RenameTagModal.cshtml.cs new file mode 100644 index 000000000..f4208b99f --- /dev/null +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/SettingManagement/TagManagement/RenameTagModal.cshtml.cs @@ -0,0 +1,64 @@ +using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.Logging; +using System; +using System.ComponentModel; +using System.ComponentModel.DataAnnotations; +using System.Threading.Tasks; +using Unity.GrantManager.GrantApplications; +using Volo.Abp.AspNetCore.Mvc.UI.RazorPages; +using Volo.Abp.Validation; + +namespace Unity.GrantManager.Web.Pages.SettingManagement.TagManagement; + +public class RenameTagModal(IApplicationTagsService applicationTagService) : AbpPageModel +{ + [HiddenInput] + [BindProperty(SupportsGet = true)] + public string SelectedTagText { get; set; } = string.Empty; + + [BindProperty] + public RenameTagViewModel? ViewModel { get; set; } + + public void OnGet() + { + ViewModel = new RenameTagViewModel + { + OriginalTag = SelectedTagText, + ReplacementTag = SelectedTagText + }; + } + + public class RenameTagViewModel + { + [Required] + [HiddenInput] + public required string OriginalTag { get; set; } + + [DisplayName("New Tag Name")] + [Required(ErrorMessage = "Replacement tag is required")] + [RegularExpression(@"^[^\s,]+$", ErrorMessage = "Tag cannot contain spaces or commas.")] + [MaxLength(250)] + public required string ReplacementTag { get; set; } + } + + public async Task OnPostAsync() + { + if (ViewModel == null) return NoContent(); + + if (ViewModel.OriginalTag == ViewModel.ReplacementTag) + { + throw new AbpValidationException("New tag cannot be the same as the original tag."); + } + + try + { + await applicationTagService.RenameTagGlobalAsync(ViewModel.OriginalTag, ViewModel.ReplacementTag); + } + catch (Exception ex) + { + Logger.LogError(ex, message: "Error updating application tags"); + } + + return NoContent(); + } +} diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/TagHelpers/Zone/UnityZoneTagHelper.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/TagHelpers/Zone/UnityZoneTagHelper.cs index f2e5751c8..98bed4987 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/TagHelpers/Zone/UnityZoneTagHelper.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/TagHelpers/Zone/UnityZoneTagHelper.cs @@ -25,5 +25,8 @@ public class UnityZoneTagHelper(UnityZoneTagHelperService tagHelperService) public Guid FormId { get; set; } = Guid.Empty; [HtmlAttributeName("check-if")] - public bool Condition { get; set; } = true; + public bool? ReadCondition { get; set; } + + [HtmlAttributeName("editable-if")] + public bool? UpdateCondition { get; set; } } \ No newline at end of file diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/TagHelpers/Zone/UnityZoneTagHelperService.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/TagHelpers/Zone/UnityZoneTagHelperService.cs index 0357d7e39..65421b9c1 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/TagHelpers/Zone/UnityZoneTagHelperService.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/TagHelpers/Zone/UnityZoneTagHelperService.cs @@ -21,12 +21,15 @@ public class UnityZoneTagHelperService : AbpTagHelperService protected IStringLocalizer L { get; } - private bool _featureState = true; - private bool _zoneState = true; - private bool _readRermissionState = true; - private bool _updateRermissionState = true; + private bool _featureState = true; + private bool _zoneState = true; + private bool _readPermissionState = true; + private bool _readCondition = true; + private bool _updatePermissionState = true; + private bool _updateCondition = true; - private bool _allRequirementsSatisfied => _featureState && _zoneState && _readRermissionState; + private bool _readRequirementsSatisfied => _readCondition && _featureState && _zoneState && _readPermissionState; + private bool _updateRequirementsSatisfied => _readRequirementsSatisfied && _updatePermissionState && _updateCondition; public UnityZoneTagHelperService( IFeatureChecker featureChecker, @@ -48,7 +51,7 @@ public override async Task ProcessAsync(TagHelperContext context, TagHelperOutpu await CheckRequirementsAsync(); - if (!TagHelper.Condition || !_allRequirementsSatisfied) + if (!_readRequirementsSatisfied) { output.SuppressOutput(); await CheckRequirementsAsync(); @@ -56,6 +59,13 @@ public override async Task ProcessAsync(TagHelperContext context, TagHelperOutpu return; } + ConfigureOutputTag(output); + AppendDebugHeader(output); + await output.GetChildContentAsync(); + } + + private void ConfigureOutputTag(TagHelperOutput output) + { if (output.TagName == "zone") { output.TagName = "div"; @@ -68,7 +78,7 @@ public override async Task ProcessAsync(TagHelperContext context, TagHelperOutpu output.Attributes.Add("name", TagHelper.ElementId); // Toggle fieldset enabled/disabled on edit permission - if (!_updateRermissionState) + if (!_updateRequirementsSatisfied) { output.Attributes.Add("disabled", "disabled"); } @@ -78,9 +88,42 @@ public override async Task ProcessAsync(TagHelperContext context, TagHelperOutpu output.TagMode = TagMode.StartTagAndEndTag; output.Attributes.AddClass("unity-zone"); + } - AppendDebugHeader(output); - await output.GetChildContentAsync(); + protected async Task CheckRequirementsAsync() + { + _featureState = await CheckFeatureRequirementAsync(); + _readPermissionState = await CheckPermissionRequirementAsync(TagHelper.PermissionRequirement); + _zoneState = await CheckZoneRequirementAsync(); + _updatePermissionState = await CheckPermissionRequirementAsync(TagHelper.UpdatePermissionRequirement); + + // Check if the conditions are explicitly set + _readCondition = TagHelper.ReadCondition ?? true; + _updateCondition = TagHelper.UpdateCondition ?? true; + } + + private async Task CheckFeatureRequirementAsync() + { + if (string.IsNullOrWhiteSpace(TagHelper.FeatureRequirement)) + return true; + + return await FeatureChecker.IsEnabledAsync(TagHelper.FeatureRequirement); + } + + private async Task CheckPermissionRequirementAsync(string? permissionName) + { + if (string.IsNullOrWhiteSpace(permissionName)) + return true; + + return await PermissionChecker.IsGrantedAsync(permissionName); + } + + private async Task CheckZoneRequirementAsync() + { + if (string.IsNullOrWhiteSpace(TagHelper.ZoneRequirement) || TagHelper.FormId == Guid.Empty) + return true; + + return await ZoneChecker.IsEnabledAsync(TagHelper.ZoneRequirement, TagHelper.FormId); } protected virtual void AddFieldsetLegend(TagHelperOutput output) @@ -112,52 +155,113 @@ protected virtual void AppendDebugHeader(TagHelperOutput output) debugAlert.AddCssClass("alert shadow-sm alert-info zone-debugger-alert font-monospace m-2 d-none"); debugAlert.Attributes.Add("role", "alert"); - var debugMessage = $@" -
-
Zone Element ID
{TagHelper.ElementId}
-
Form ID
- {TagHelper.FormId} -
-
FeatureRequirement
{StatusBadge(_featureState)}{TagHelper.FeatureRequirement ?? "N/A"}{(TagHelper.Id == TagHelper.FeatureRequirement ? " (Inherited)" : string.Empty)}
-
ZoneRequirement
{StatusBadge(_zoneState)}{TagHelper.ZoneRequirement ?? "N/A"}{(TagHelper.Id == TagHelper.ZoneRequirement ? " (Inherited)" : string.Empty)}
-
ReadPermissionRequirement
{StatusBadge(_readRermissionState)}{TagHelper.PermissionRequirement ?? "N/A"}{(TagHelper.Id == TagHelper.PermissionRequirement ? " (Inherited)" : string.Empty)}
-
-
UpdatePermissionRequirement
{StatusBadge(_updateRermissionState)}{TagHelper.UpdatePermissionRequirement ?? "N/A"}
-
"; - - debugAlert.InnerHtml.SetHtmlContent(debugMessage); + var content = new HtmlContentBuilder(); + var dl = new TagBuilder("dl"); + dl.AddCssClass("row"); + + // Basic information + AddDefinitionItem(dl, "Zone Element ID", TagHelper.ElementId); + AddFormIdWithLink(dl); + + // Feature and Zone requirements + AddRequirementItem(dl, + "FeatureRequirement", + string.IsNullOrEmpty(TagHelper.FeatureRequirement) ? null : _featureState, + TagHelper.FeatureRequirement, + TagHelper.Id); + AddRequirementItem(dl, "ZoneRequirement", _zoneState, + TagHelper.ZoneRequirement, TagHelper.Id); + + AddSeparator(dl); + + // Permission requirements + AddRequirementItem(dl, "ReadPermissionRequirement", _readPermissionState, + TagHelper.PermissionRequirement, TagHelper.Id); + AddDefinitionItem(dl, "ReadCondition", NotApplicableStatusBadge(TagHelper.ReadCondition)); + + AddSeparator(dl); + + // Update requirements + AddRequirementItem(dl, "UpdatePermissionRequirement", _updatePermissionState, + TagHelper.UpdatePermissionRequirement, null); + AddDefinitionItem(dl, "UpdateCondition", NotApplicableStatusBadge(TagHelper.UpdateCondition)); + + content.AppendHtml(dl); + debugAlert.InnerHtml.AppendHtml(content); output.PreElement.AppendHtml(debugAlert); } - private static string StatusBadge(bool condition) - => (condition ? "PASS " : "FAIL "); + private void AddFormIdWithLink(TagBuilder dl) + { + var formLink = new TagBuilder("a"); + formLink.Attributes.Add("href", $"/ApplicationForms/Mapping?ApplicationId={TagHelper.FormId}"); + formLink.Attributes.Add("target", "_blank"); + formLink.Attributes.Add("rel", "noopener noreferrer"); + formLink.InnerHtml.AppendHtml($"{TagHelper.FormId}"); + formLink.InnerHtml.AppendHtml(""); + AddDefinitionItem(dl, "Form ID", formLink); + } - protected async Task CheckRequirementsAsync() + private static void AddRequirementItem(TagBuilder dl, string label, bool? state, string? requirement, string? inheritFrom) { - if (!string.IsNullOrWhiteSpace(TagHelper.FeatureRequirement) - && !await FeatureChecker.IsEnabledAsync(TagHelper.FeatureRequirement)) - { - _featureState = false; - } + var content = new HtmlContentBuilder(); + content.AppendHtml(NotApplicableStatusBadge(state)); + content.Append(requirement ?? "N/A"); - if (!string.IsNullOrWhiteSpace(TagHelper.PermissionRequirement) - && !await PermissionChecker.IsGrantedAsync(TagHelper.PermissionRequirement)) + // Add inheritance notice if applicable + if (inheritFrom != null && inheritFrom == requirement) { - _readRermissionState = false; + content.Append(" (Inherited)"); } - // Skip zone checks if FormId is null - if (TagHelper.FormId != Guid.Empty - && !string.IsNullOrWhiteSpace(TagHelper.ZoneRequirement) - && !await ZoneChecker.IsEnabledAsync(TagHelper.ZoneRequirement, TagHelper.FormId)) - { - _zoneState = false; - } + AddDefinitionItem(dl, label, content); + } - if (!string.IsNullOrWhiteSpace(TagHelper.UpdatePermissionRequirement) - && !await PermissionChecker.IsGrantedAsync(TagHelper.UpdatePermissionRequirement)) - { - _updateRermissionState = false; - } + private static void AddSeparator(TagBuilder container) + { + container.InnerHtml.AppendHtml("
"); + } + + private static void AddDefinitionItem(TagBuilder dl, string term, IHtmlContent content) + { + var dt = new TagBuilder("dt"); + dt.AddCssClass("col-sm-3"); + dt.InnerHtml.Append(term); + + var dd = new TagBuilder("dd"); + dd.AddCssClass("col-sm-9"); + dd.InnerHtml.AppendHtml(content); + + dl.InnerHtml.AppendHtml(dt); + dl.InnerHtml.AppendHtml(dd); + } + + private static void AddDefinitionItem(TagBuilder dl, string term, string content) + { + AddDefinitionItem(dl, term, new HtmlString(content)); + } + + private static HtmlContentBuilder NotApplicableStatusBadge(bool? condition) + => condition == null + ? CreateBadge("NONE", "text-bg-light") + : StatusBadge(condition); + + private static HtmlContentBuilder StatusBadge(bool? condition) + => condition == true + ? CreateBadge("PASS", "text-bg-primary") + : CreateBadge("FAIL", "text-bg-secondary"); + + private static HtmlContentBuilder CreateBadge(string text, string styleClass) + { + var badge = new TagBuilder("span"); + badge.AddCssClass("badge"); + badge.AddCssClass(styleClass); + badge.InnerHtml.Append(text); + + var content = new HtmlContentBuilder(); + content.AppendHtml(badge); + content.Append(" "); // Add space after badge + + return content; } } \ No newline at end of file diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Unity.GrantManager.Web.csproj b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Unity.GrantManager.Web.csproj index 7c93ee059..4457487b9 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Unity.GrantManager.Web.csproj +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Unity.GrantManager.Web.csproj @@ -40,6 +40,12 @@ Always + + Always + + + Always + Always diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Settings/BackgroundJobsPageContributor.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Settings/BackgroundJobsPageContributor.cs index f5d6acbd5..187d2d191 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Settings/BackgroundJobsPageContributor.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Settings/BackgroundJobsPageContributor.cs @@ -20,7 +20,8 @@ public override Task ConfigureAsync(SettingPageCreationContext context) new SettingPageGroup( "GrantManager.BackgroundJobs", "Background Jobs", - typeof(BackgroundJobsViewComponent) + typeof(BackgroundJobsViewComponent), + order: 1 ) ); diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Settings/BackgroundJobsSettingGroup/Default.js b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Settings/BackgroundJobsSettingGroup/Default.js new file mode 100644 index 000000000..436c3baea --- /dev/null +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Settings/BackgroundJobsSettingGroup/Default.js @@ -0,0 +1 @@ +abp.log.debug('BackgroundJobs initialized!'); \ No newline at end of file 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 new file mode 100644 index 000000000..9697cb08b --- /dev/null +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Settings/TagManagement/TagManagement.js @@ -0,0 +1,265 @@ +const TagTypes = {}; +let userCanUpdate = abp.auth.isGranted('Unity.GrantManager.SettingManagement.Tags.Update'); +let userCanDelete = abp.auth.isGranted('Unity.GrantManager.SettingManagement.Tags.Delete'); + +function defineTagSummaryColumnDefs() { + // Define columns - start with fixed columns + const columnDefs = [ + { + title: "Tags", + name: 'text', + data: 'text' + } + ]; + + // Add a column for each tag type + Object.values(TagTypes).forEach(tagType => { + columnDefs.push({ + title: `${tagType.name} Count`, + name: `${tagType.name.toLowerCase()}Count`, + data: `tagTypeCounts.${tagType.name}`, + defaultContent: 0, + render: function (data) { + return data || 0; + } + }); + }); + + columnDefs.push({ + title: "Count", + name: 'totalCount', + data: 'totalCount' + }); + + // Add the actions column + columnDefs.push({ + title: "Actions", + name: 'actions', + data: 'text', + orderable: false, + render: function (data, type, row) { + let $buttonWrapper = $('
').addClass('d-flex flex-nowrap gap-1'); + + let $editButton = $('
diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Shared/Components/ApplicantInfo/ApplicantAddressViewModel.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Shared/Components/ApplicantInfo/ApplicantAddressViewModel.cs new file mode 100644 index 000000000..0071a4dd5 --- /dev/null +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Shared/Components/ApplicantInfo/ApplicantAddressViewModel.cs @@ -0,0 +1,33 @@ +using System; +using System.ComponentModel.DataAnnotations; +using Unity.GrantManager.GrantApplications; + +namespace Unity.GrantManager.Web.Views.Shared.Components.ApplicantInfo; + +public class ApplicantAddressViewModel +{ + public Guid ApplicantAddressId { get; set; } + public Guid ApplicantId { get; set; } + + [Display(Name = "ApplicantInfoView:ApplicantInfo.AddressType")] + public AddressType AddressType { get; set; } + + [Display(Name = "ApplicantInfoView:ApplicantInfo.Street")] + public string Street { get; set; } = string.Empty; + + [Display(Name = "ApplicantInfoView:ApplicantInfo.Street2")] + public string Street2 { get; set; } = string.Empty; + + [Display(Name = "ApplicantInfoView:ApplicantInfo.Unit")] + public string? Unit { get; set; } + + [Display(Name = "ApplicantInfoView:ApplicantInfo.City")] + public string? City { get; set; } + + [Display(Name = "ApplicantInfoView:ApplicantInfo.Province")] + public string? Province { get; set; } + + [Display(Name = "ApplicantInfoView:ApplicantInfo.PostalCode")] + public string? PostalCode { get; set; } +} + diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Shared/Components/ApplicantInfo/ApplicantInfoController.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Shared/Components/ApplicantInfo/ApplicantInfoController.cs index 6ec4b937c..9f0896ba6 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Shared/Components/ApplicantInfo/ApplicantInfoController.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Shared/Components/ApplicantInfo/ApplicantInfoController.cs @@ -2,25 +2,23 @@ using Microsoft.AspNetCore.Mvc; using Volo.Abp.AspNetCore.Mvc; using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Logging.Abstractions; -namespace Unity.GrantManager.Web.Views.Shared.Components.ProjectInfo +namespace Unity.GrantManager.Web.Views.Shared.Components.ApplicantInfo { [ApiExplorerSettings(IgnoreApi = true)] [Route("GrantApplications/Widget/ApplicantInfo")] - public class ApplicantInfoController: AbpController - { - protected ILogger logger => LazyServiceProvider.LazyGetService(provider => LoggerFactory?.CreateLogger(GetType().FullName!) ?? NullLogger.Instance); - + public class ApplicantInfoController : AbpController + { [HttpGet] [Route("Refresh")] public IActionResult ApplicantInfo(Guid applicationId, Guid applicationFormVersionId) { - if (!ModelState.IsValid) - { - logger.LogWarning("Invalid model state for ApplicantInfoController: Refresh"); - return ViewComponent("ApplicantInfo"); - } + if (!ModelState.IsValid) + { + Logger.LogWarning("Invalid model state for ApplicantInfoController: Refresh"); + + return ViewComponent("ApplicantInfo"); + } return ViewComponent("ApplicantInfo", new { applicationId, applicationFormVersionId }); } } diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Shared/Components/ApplicantInfo/ApplicantInfoViewComponent.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Shared/Components/ApplicantInfo/ApplicantInfoViewComponent.cs index 79a75a6db..1ff68758d 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Shared/Components/ApplicantInfo/ApplicantInfoViewComponent.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Shared/Components/ApplicantInfo/ApplicantInfoViewComponent.cs @@ -1,148 +1,141 @@ using Microsoft.AspNetCore.Mvc; -using Volo.Abp.AspNetCore.Mvc.UI.Widgets; -using Volo.Abp.AspNetCore.Mvc; -using System.Threading.Tasks; +using Microsoft.AspNetCore.Mvc.Rendering; using System; -using Unity.GrantManager.GrantApplications; -using System.Linq; -using Volo.Abp.AspNetCore.Mvc.UI.Bundling; using System.Collections.Generic; -using Microsoft.AspNetCore.Mvc.Rendering; +using System.Linq; +using System.Threading.Tasks; +using Unity.GrantManager.ApplicationForms; +using Unity.GrantManager.GrantApplications; using Unity.GrantManager.Locality; +using Volo.Abp.AspNetCore.Mvc; +using Volo.Abp.AspNetCore.Mvc.UI.Bundling; +using Volo.Abp.AspNetCore.Mvc.UI.Widgets; + +namespace Unity.GrantManager.Web.Views.Shared.Components.ApplicantInfo; -namespace Unity.GrantManager.Web.Views.Shared.Components.ApplicantInfo -{ - [Widget( - RefreshUrl = "Widget/ApplicantInfo/Refresh", - ScriptTypes = [typeof(ApplicantInfoScriptBundleContributor)], - StyleTypes = [typeof(ApplicantInfoStyleBundleContributor)], - AutoInitialize = true)] - public class ApplicantInfoViewComponent : AbpViewComponent +[Widget( + RefreshUrl = "Widget/ApplicantInfo/Refresh", + ScriptTypes = [typeof(ApplicantInfoScriptBundleContributor)], + StyleTypes = [typeof(ApplicantInfoStyleBundleContributor)], + AutoInitialize = true)] +public class ApplicantInfoViewComponent( + IApplicationApplicantAppService applicationAppicantService, + ISectorService applicationSectorAppService, + IElectoralDistrictService applicationElectoralDistrictAppService, + IApplicationFormAppService applicationFormAppService) : AbpViewComponent +{ + public async Task InvokeAsync(Guid applicationId, Guid applicationFormVersionId) { - private readonly IApplicationApplicantAppService _applicationAppicantService; - private readonly ISectorService _applicationSectorAppService; + var applicantInfoDto = await applicationAppicantService.GetApplicantInfoTabAsync(applicationId); + var electoralDistrictAddressType = await applicationFormAppService.GetElectoralDistrictAddressTypeAsync(applicantInfoDto.ApplicationFormId); - public ApplicantInfoViewComponent( - IApplicationApplicantAppService applicationAppicantService, - ISectorService applicationSectorAppService) - { - _applicationAppicantService = applicationAppicantService; - _applicationSectorAppService = applicationSectorAppService; + if (applicantInfoDto == null) + { + throw new InvalidOperationException("Applicant information could not be retrieved."); } - public async Task InvokeAsync(Guid applicationId, Guid applicationFormVersionId) - { - var applicantInfoDto = await _applicationAppicantService.GetByApplicationIdAsync(applicationId); - List Sectors = [.. (await _applicationSectorAppService.GetListAsync())]; + ApplicantInfoViewModel viewModel = new() + { + ApplicationId = applicationId, + ApplicationFormId = applicantInfoDto.ApplicationFormId, + ApplicationFormVersionId = applicationFormVersionId, + ApplicantId = applicantInfoDto.ApplicantId, + ApplicantSummary = ObjectMapper.Map(applicantInfoDto.ApplicantSummary ?? new ApplicantSummaryDto()), + ContactInfo = ObjectMapper.Map(applicantInfoDto.ContactInfo ?? new ContactInfoDto()), + SigningAuthority = ObjectMapper.Map(applicantInfoDto.SigningAuthority ?? new SigningAuthorityDto()), + ApplicantElectoralAddressType = electoralDistrictAddressType, + }; + + viewModel.ApplicantSummary.ApplicantId = applicantInfoDto.ApplicantId; + + await PopulateSectorsAndSubSectorsAsync(viewModel); + await PopulateElectoralDistrictsAsync(viewModel); + + // MAPADDRESSES + if (applicantInfoDto.ApplicantAddresses?.Count > 0) + { + // Map physical address + var physicalAddress = FindMostRecentAddress(applicantInfoDto.ApplicantAddresses, AddressType.PhysicalAddress); + if (physicalAddress is not null) + { + viewModel.PhysicalAddress = ObjectMapper.Map(physicalAddress); + } - ApplicantInfoViewModel model = new() - { - ApplicationId = applicationId, - ApplicationFormId = applicantInfoDto.ApplicationFormId, - ApplicationFormVersionId = applicationFormVersionId, - ApplicationSectors = Sectors, - ApplicantId = applicantInfoDto.ApplicantId - }; + // Map mailing address + var mailingAddress = FindMostRecentAddress(applicantInfoDto.ApplicantAddresses, AddressType.MailingAddress); + if (mailingAddress is not null) + { + viewModel.MailingAddress = ObjectMapper.Map(mailingAddress); + } + } - model.ApplicationSectorsList.AddRange(Sectors.Select(Sector => - new SelectListItem { Value = Sector.SectorName, Text = Sector.SectorName })); + return View(viewModel); + } + + private static ApplicantAddressDto? FindMostRecentAddress(List applicantAddresses, AddressType addressType) + { + return applicantAddresses + .Where(address => address.AddressType == addressType) + .OrderByDescending(address => + address.CreationTime < address.LastModificationTime.GetValueOrDefault(DateTime.MinValue) + ? address.CreationTime + : address.LastModificationTime.GetValueOrDefault(DateTime.MinValue)) + .FirstOrDefault(); + } + private async Task PopulateElectoralDistrictsAsync(ApplicantInfoViewModel model) + { + List electoralDistricts = [.. (await applicationElectoralDistrictAppService.GetListAsync())]; - if (Sectors.Count > 0) + model.ElectoralDistrictList.AddRange(electoralDistricts.Select(electoralDistrict => + new SelectListItem { - List SubSectors = []; - - SectorDto? applicationSector = Sectors.Find(x => x.SectorName == applicantInfoDto.Sector); - SubSectors = applicationSector?.SubSectors ?? SubSectors; + Value = electoralDistrict.ElectoralDistrictName, + Text = electoralDistrict.ElectoralDistrictName + })); + } - model.ApplicationSubSectorsList.AddRange(SubSectors.Select(SubSector => - new SelectListItem { Value = SubSector.SubSectorName, Text = SubSector.SubSectorName })); - } + private async Task PopulateSectorsAndSubSectorsAsync(ApplicantInfoViewModel model) + { + List sectors = [.. (await applicationSectorAppService.GetListAsync())]; + model.ApplicationSectors = sectors; - model.ApplicantInfo = new() + model.ApplicationSectorsList.AddRange(sectors.Select(sector => + new SelectListItem { - Sector = applicantInfoDto.Sector, - SubSector = applicantInfoDto.SubSector, - ContactFullName = applicantInfoDto.ContactFullName, - ContactTitle = applicantInfoDto.ContactTitle, - ContactEmail = applicantInfoDto.ContactEmail, - ContactBusinessPhone = applicantInfoDto.ContactBusinessPhone, - ContactCellPhone = applicantInfoDto.ContactCellPhone, - OrgName = applicantInfoDto.OrganizationName, - OrgNumber = applicantInfoDto.OrgNumber, - OrgStatus = applicantInfoDto.OrgStatus, - OrganizationType = applicantInfoDto.OrganizationType, - SigningAuthorityFullName = applicantInfoDto.SigningAuthorityFullName, - SigningAuthorityTitle = applicantInfoDto.SigningAuthorityTitle, - SigningAuthorityEmail = applicantInfoDto.SigningAuthorityEmail, - SigningAuthorityBusinessPhone = applicantInfoDto.SigningAuthorityBusinessPhone, - SigningAuthorityCellPhone = applicantInfoDto.SigningAuthorityCellPhone, - OrganizationSize = applicantInfoDto.OrganizationSize, - SectorSubSectorIndustryDesc = applicantInfoDto.SectorSubSectorIndustryDesc, - RedStop = applicantInfoDto.RedStop, - IndigenousOrgInd = applicantInfoDto.IndigenousOrgInd, - UnityApplicantId = applicantInfoDto.UnityApplicantId, - FiscalDay = applicantInfoDto.FiscalDay, - FiscalMonth = applicantInfoDto.FiscalMonth, - NonRegOrgName = applicantInfoDto.NonRegOrgName - }; - - if (applicantInfoDto.ApplicantAddresses.Count != 0) - { - ApplicantAddressDto? physicalAddress = applicantInfoDto.ApplicantAddresses - .Where(address => address.AddressType == AddressType.PhysicalAddress) - .OrderByDescending(address => address.CreationTime) - .FirstOrDefault(); - - if (physicalAddress != null) - { - model.ApplicantInfo.PhysicalAddressStreet = physicalAddress.Street; - model.ApplicantInfo.PhysicalAddressStreet2 = physicalAddress.Street2; - model.ApplicantInfo.PhysicalAddressUnit = physicalAddress.Unit; - model.ApplicantInfo.PhysicalAddressCity = physicalAddress.City; - model.ApplicantInfo.PhysicalAddressProvince = physicalAddress.Province; - model.ApplicantInfo.PhysicalAddressPostalCode = physicalAddress.Postal; - } - - ApplicantAddressDto? mailingAddress = applicantInfoDto.ApplicantAddresses - .Where(address => address.AddressType == AddressType.MailingAddress) - .OrderByDescending(address => address.CreationTime) - .FirstOrDefault(); - - if (mailingAddress != null) - { - model.ApplicantInfo.MailingAddressStreet = mailingAddress.Street; - model.ApplicantInfo.MailingAddressStreet2 = mailingAddress.Street2; - model.ApplicantInfo.MailingAddressUnit = mailingAddress.Unit; - model.ApplicantInfo.MailingAddressCity = mailingAddress.City; - model.ApplicantInfo.MailingAddressProvince = mailingAddress.Province; - model.ApplicantInfo.MailingAddressPostalCode = mailingAddress.Postal; - } - } + Value = sector.SectorName, + Text = sector.SectorName + })); - return View(model); + if (sectors.Count > 0 && model.ApplicantSummary != null) + { + List SubSectors = []; + + SectorDto? applicationSector = sectors.Find(x => x.SectorName == model.ApplicantSummary.Sector); + SubSectors = applicationSector?.SubSectors ?? SubSectors; + + model.ApplicationSubSectorsList.AddRange(SubSectors.Select(SubSector => + new SelectListItem { Value = SubSector.SubSectorName, Text = SubSector.SubSectorName })); } } +} - public class ApplicantInfoStyleBundleContributor : BundleContributor +public class ApplicantInfoStyleBundleContributor : BundleContributor +{ + public override void ConfigureBundle(BundleConfigurationContext context) { - public override void ConfigureBundle(BundleConfigurationContext context) - { - context.Files - .AddIfNotContains("/Views/Shared/Components/ApplicantInfo/Default.css"); - } + context.Files + .AddIfNotContains("/Views/Shared/Components/ApplicantInfo/Default.css"); } +} - public class ApplicantInfoScriptBundleContributor : BundleContributor +public class ApplicantInfoScriptBundleContributor : BundleContributor +{ + public override void ConfigureBundle(BundleConfigurationContext context) { - public override void ConfigureBundle(BundleConfigurationContext context) - { - context.Files - .AddIfNotContains("/Views/Shared/Components/ApplicantInfo/Default.js"); - context.Files - .AddIfNotContains("/libs/jquery-maskmoney/dist/jquery.maskMoney.min.js"); - } + context.Files + .AddIfNotContains("/Views/Shared/Components/ApplicantInfo/Default.js"); } } diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Shared/Components/ApplicantInfo/ApplicantInfoViewModel.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Shared/Components/ApplicantInfo/ApplicantInfoViewModel.cs index 54cfbd358..0625d3548 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Shared/Components/ApplicantInfo/ApplicantInfoViewModel.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Shared/Components/ApplicantInfo/ApplicantInfoViewModel.cs @@ -1,193 +1,75 @@ -using System.ComponentModel.DataAnnotations; -using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form; -using Microsoft.AspNetCore.Mvc.RazorPages; -using Microsoft.AspNetCore.Mvc.Rendering; -using System.Collections.Generic; +using Microsoft.AspNetCore.Mvc.Rendering; using System; -using Unity.GrantManager.GrantApplications; +using System.Collections.Generic; using System.Collections.Immutable; -using Unity.GrantManager.Locality; -using System.Linq; +using System.ComponentModel.DataAnnotations; using System.Globalization; +using System.Linq; +using Unity.GrantManager.GrantApplications; +using Unity.GrantManager.Locality; +using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form; -namespace Unity.GrantManager.Web.Views.Shared.Components.ApplicantInfo +namespace Unity.GrantManager.Web.Views.Shared.Components.ApplicantInfo; + +public class ApplicantInfoViewModel { - public class ApplicantInfoViewModel : PageModel + public List OrganizationTypeList { get; set; } = FormatOptionsList(ProjectInfoOptionsList.OrganizationTypeList); + public List OrgBookStatusList { get; set; } = FormatOptionsList(ProjectInfoOptionsList.OrgBookStatusList); + public List ApplicationSectorsList { get; set; } = []; + public List ApplicationSubSectorsList { get; set; } = []; + public List IndigenousList { get; set; } = FormatOptionsList(ApplicantInfoOptionsList.IndigenousList); + public List FiscalDayList { get; set; } = [.. FormatOptionsList(ApplicantInfoOptionsList.FiscalDayList).OrderBy(x => int.Parse(x.Text))]; + public List FiscalMonthList { get; set; } = [.. FormatOptionsList(ApplicantInfoOptionsList.FiscalMonthList).OrderBy(x => DateTime.ParseExact(x.Text, "MMMM", CultureInfo.InvariantCulture).Month)]; + public List ElectoralDistrictList { get; set; } = []; + + public Guid ApplicationId { get; set; } + public Guid ApplicantId { get; set; } + public Guid ApplicationFormId { get; set; } + public Guid ApplicationFormVersionId { get; set; } + [Display(Name = "ApplicantInfoView:ApplicantElectoralDistrict")] + [SelectItems(nameof(ElectoralDistrictList))] + public string? ElectoralDistrict { get; set; } + + public List ApplicationSectors { get; set; } = []; + + // Core Model + public ApplicantSummaryViewModel ApplicantSummary { get; set; } = new ApplicantSummaryViewModel(); + public SigningAuthorityViewModel SigningAuthority { get; set; } = new SigningAuthorityViewModel(); + public ContactInfoViewModel ContactInfo { get; set; } = new ContactInfoViewModel(); + public ApplicantAddressViewModel PhysicalAddress { get; set; } = new ApplicantAddressViewModel(); + public ApplicantAddressViewModel MailingAddress { get; set; } = new ApplicantAddressViewModel(); + + public AddressType ApplicantElectoralAddressType { get; set; } = AddressType.PhysicalAddress; + public string ApplicantElectoralAddressTypeDisplay { - public static ImmutableDictionary DropdownList => - ImmutableDictionary.CreateRange(new[] - { - new KeyValuePair("VALUE1", "Value 1"), - new KeyValuePair("VALUE2", "Value 2"), - }); - - public List OrganizationTypeList { get; set; } = FormatOptionsList(ProjectInfoOptionsList.OrganizationTypeList); - public List OrgBookStatusList { get; set; } = FormatOptionsList(ProjectInfoOptionsList.OrgBookStatusList); - public List ApplicationSectorsList { get; set; } = new List(); - public List ApplicationSubSectorsList { get; set; } = new List(); - public List IndigenousList { get; set; } = FormatOptionsList(ApplicantInfoOptionsList.IndigenousList); - public List FiscalDayList { get; set; } = FormatOptionsList(ApplicantInfoOptionsList.FiscalDayList).OrderBy(x => int.Parse(x.Text)).ToList(); - public List FiscalMonthList { get; set; } = FormatOptionsList(ApplicantInfoOptionsList.FiscalMonthList).OrderBy(x => DateTime.ParseExact(x.Text, "MMMM", CultureInfo.InvariantCulture).Month).ToList(); - - public Guid ApplicationId { get; set; } - public Guid ApplicantId { get; set; } - public Guid ApplicationFormId { get; set; } - public Guid ApplicationFormVersionId { get; set; } - - public List ApplicationSectors { get; set; } = new List(); - public bool IsFinalDecisionMade { get; set; } - public ApplicantInfoViewModelModel ApplicantInfo { get; set; } = new(); - - - public class ApplicantInfoViewModelModel + get { + return ApplicantElectoralAddressType switch + { + AddressType.PhysicalAddress => "Physical Address", + AddressType.MailingAddress => "Mailing Address", + AddressType.BusinessAddress => "Business Address", + _ => "Address" + }; + } + } - [Display(Name = "ApplicantInfoView:ApplicantInfo.OrgName")] - public string? OrgName { get; set; } - - [Display(Name = "ApplicantInfoView:ApplicantInfo.OrgNumber")] - public string? OrgNumber { get; set; } - - [Display(Name = "ApplicantInfoView:ApplicantInfo.OrgBookStatus")] - [SelectItems(nameof(OrgBookStatusList))] - public string? OrgStatus { get; set; } - - [Display(Name = "ApplicantInfoView:ApplicantInfo.OrganizationType")] - [SelectItems(nameof(OrganizationTypeList))] - public string? OrganizationType { get; set; } - - [Display(Name = "ApplicantInfoView:ApplicantInfo.OrganizationSize")] - public string? OrganizationSize { get; set; } - - [Display(Name = "ApplicantInfoView:ApplicantInfo.UnityApplicant")] - public string? UnityApplicantId { get; set; } - - [Display(Name = "ApplicantInfoView:ApplicantInfo.FiscalMonth")] - [SelectItems(nameof(FiscalMonthList))] - public string? FiscalMonth { get; set; } - [Display(Name = "ApplicantInfoView:ApplicantInfo.FiscalDay")] - [SelectItems(nameof(FiscalDayList))] - public string? FiscalDay { get; set; } - - - [Display(Name = "ApplicantInfoView:ApplicantInfo.Sector")] - [SelectItems(nameof(ApplicationSectorsList))] - public string? Sector { get; set; } - - [Display(Name = "ApplicantInfoView:ApplicantInfo.SubSector")] - [SelectItems(nameof(ApplicationSubSectorsList))] - public string? SubSector { get; set; } - - public bool RedStop { get; set; } - - [Display(Name = "ApplicantInfoView:ApplicantInfo.IndigenousOrgInd")] - public string? IndigenousOrgInd { get; set; } - - [Display(Name = "ApplicantInfoView:ApplicantInfo.ContactFullName")] - [MaxLength(600, ErrorMessage = "Must be a maximum of 6 characters")] - public string? ContactFullName { get; set; } - - [Display(Name = "ApplicantInfoView:ApplicantInfo.ContactTitle")] - public string? ContactTitle { get; set; } - - [Display(Name = "ApplicantInfoView:ApplicantInfo.ContactEmail")] - [DataType(DataType.EmailAddress, ErrorMessage = "Provided email is not valid")] - public string? ContactEmail { get; set; } - - [Display(Name = "ApplicantInfoView:ApplicantInfo.ContactBusinessPhone")] - [DataType(DataType.PhoneNumber, ErrorMessage = "Invalid Phone Number")] - [RegularExpression(@"^(\+\s?)?((? FormatOptionsList(ImmutableDictionary optionsList) + public static List FormatOptionsList(ImmutableDictionary optionsList) + { + List optionsFormattedList = []; + foreach (KeyValuePair entry in optionsList) { - List optionsFormattedList = new(); - foreach (KeyValuePair entry in optionsList) - { - optionsFormattedList.Add(new SelectListItem { Value = entry.Key, Text = entry.Value }); - } - return optionsFormattedList; + optionsFormattedList.Add(new SelectListItem { Value = entry.Key, Text = entry.Value }); } + return optionsFormattedList; } } - diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Shared/Components/ApplicantInfo/ApplicantSummaryViewModel.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Shared/Components/ApplicantInfo/ApplicantSummaryViewModel.cs new file mode 100644 index 000000000..5740a523b --- /dev/null +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Shared/Components/ApplicantInfo/ApplicantSummaryViewModel.cs @@ -0,0 +1,62 @@ +using Microsoft.AspNetCore.Mvc; +using System; +using System.ComponentModel.DataAnnotations; +using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form; + +namespace Unity.GrantManager.Web.Views.Shared.Components.ApplicantInfo; + +public class ApplicantSummaryViewModel +{ + [HiddenInput] + public Guid ApplicantId { get; set; } + + [Display(Name = "ApplicantInfoView:ApplicantInfo.OrgName")] + public string? OrgName { get; set; } + + [Display(Name = "ApplicantInfoView:ApplicantInfo.OrgNumber")] + public string? OrgNumber { get; set; } + + [Display(Name = "ApplicantInfoView:ApplicantInfo.OrgBookStatus")] + [SelectItems(nameof(ApplicantInfoViewModel.OrgBookStatusList))] + public string? OrgStatus { get; set; } + + [Display(Name = "ApplicantInfoView:ApplicantInfo.OrganizationType")] + [SelectItems(nameof(ApplicantInfoViewModel.OrganizationTypeList))] + public string? OrganizationType { get; set; } + + + [Display(Name = "ApplicantInfoView:ApplicantInfo.NonRegOrgName")] + public string? NonRegOrgName { get; set; } + + [Display(Name = "ApplicantInfoView:ApplicantInfo.OrganizationSize")] + public string? OrganizationSize { get; set; } + + [Display(Name = "ApplicantInfoView:ApplicantInfo.IndigenousOrgInd")] + public bool IndigenousOrgInd { get; set; } = false; + + [Display(Name = "ApplicantInfoView:ApplicantInfo.UnityApplicant")] + public string? UnityApplicantId { get; set; } + + [Display(Name = "ApplicantInfoView:ApplicantInfo.FiscalMonth")] + [SelectItems(nameof(ApplicantInfoViewModel.FiscalMonthList))] + public string? FiscalMonth { get; set; } + [Display(Name = "ApplicantInfoView:ApplicantInfo.FiscalDay")] + [SelectItems(nameof(ApplicantInfoViewModel.FiscalDayList))] + public string? FiscalDay { get; set; } + + + [Display(Name = "ApplicantInfoView:ApplicantInfo.Sector")] + [SelectItems(nameof(ApplicantInfoViewModel.ApplicationSectorsList))] + public string? Sector { get; set; } + + [Display(Name = "ApplicantInfoView:ApplicantInfo.SubSector")] + [SelectItems(nameof(ApplicantInfoViewModel.ApplicationSubSectorsList))] + public string? SubSector { get; set; } + + [Display(Name = "ApplicantInfoView:ApplicantInfo.SectorSubSectorIndustryDesc")] + [TextArea(Rows = 2)] + public string? SectorSubSectorIndustryDesc { get; set; } + + public bool RedStop { get; set; } +} + diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Shared/Components/ApplicantInfo/ContactInfoViewModel.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Shared/Components/ApplicantInfo/ContactInfoViewModel.cs new file mode 100644 index 000000000..df8995d07 --- /dev/null +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Shared/Components/ApplicantInfo/ContactInfoViewModel.cs @@ -0,0 +1,31 @@ +using System; +using System.ComponentModel.DataAnnotations; + +namespace Unity.GrantManager.Web.Views.Shared.Components.ApplicantInfo; + +public class ContactInfoViewModel +{ + public Guid? ApplicantAgentId { get; set; } + + [Display(Name = "ApplicantInfoView:ApplicantInfo.ContactFullName")] + [MaxLength(600, ErrorMessage = "Must be a maximum of 600 characters")] + public string? Name { get; set; } + + [Display(Name = "ApplicantInfoView:ApplicantInfo.ContactTitle")] + public string? Title { get; set; } + + [Display(Name = "ApplicantInfoView:ApplicantInfo.ContactEmail")] + [DataType(DataType.EmailAddress, ErrorMessage = "Provided email is not valid")] + public string? Email { get; set; } + + [Display(Name = "ApplicantInfoView:ApplicantInfo.ContactBusinessPhone")] + [DataType(DataType.PhoneNumber, ErrorMessage = "Invalid Phone Number")] + [RegularExpression(@"^(\+\s?)?((? + + + + - - - - -
-
@L["ApplicantInfoView:ApplicantInfo.ApplicantInfoTitle"].Value
-
+
- +
-
+ -
- @L["ApplicantInfoView:ApplicantInfo.ApplicantInfoTitle"].Value + + @* Zone Section : Applicant Info Summary *@ + + + + - + - - - + - + - + - + - + - - + + - + - +
-
- - - - - +
+
+ + + + + +
- +
- +
- + - +
- + - +
-
- - +
+
- + -
+ - @if (await FeatureChecker.IsEnabledAsync(PaymentConsts.UnityPaymentsFeature)) - { -
- @await Component.InvokeAsync("SupplierInfo", new { applicantId = Model.ApplicantId }) -
- } -
- @L["ApplicantInfoView:ApplicantInfoContactInfo"].Value + @* Zone Section : Contact Info *@ + - - -
-
@L["ApplicantInfoView:ApplicantInfoContactInfo"].Value
-
-
-
- + - + - + - + - +
-
+ -
- @L["ApplicantInfoView:SigningAuthorityTitle"].Value + @* Zone Section : Signing Authority *@ + -
+ -
- @L["ApplicantInfoView:PhysicalAddress"].Value + @* Zone Section : Address *@ +
- +
@@ -258,34 +241,28 @@
- + - + - + - + - + - + - + - +
@@ -293,69 +270,393 @@
- + - + - + - + - + - + - +
-
- @if (await FeatureChecker.IsEnabledAsync("Unity.Flex")) - { + + + +
+
@L["ApplicantInfoView:ElectoralDistrict"].Value
+ +
+
+
+ + + + + + + + + + + + +
NOTE: @L["ApplicantInfoView:Notes.ElectoralDistrict", Model.ApplicantElectoralAddressTypeDisplay].Value
+
+ + + @* Zone Section : Worksheet *@ + @await Component.InvokeAsync(typeof(WorksheetInstanceWidget), - new - { - instanceCorrelationId = Model.ApplicationId, - instanceCorrelationProvider = CorrelationConsts.Application, - sheetCorrelationId = Model.ApplicationFormVersionId, - sheetCorrelationProvider = CorrelationConsts.FormVersion, - uiAnchor = FlexConsts.ApplicantInfoUiAnchor - }) - } + new + { + instanceCorrelationId = Model.ApplicationId, + instanceCorrelationProvider = CorrelationConsts.Application, + sheetCorrelationId = Model.ApplicationFormVersionId, + sheetCorrelationProvider = CorrelationConsts.FormVersion, + uiAnchor = FlexConsts.ApplicantInfoUiAnchor + }) +
- -
@L["Summary:ContactsTitle"].Value
-
- @await Component.InvokeAsync("ApplicationContactsWidget", new { applicationId = Model.ApplicationId, isReadOnly = !IsViewEditable }) -
- @if (IsViewEditable) - { -
- +@* Zone Section : AdditionalContact *@ + + +
@L["Summary:ContactsTitle"].Value
+
+ @await Component.InvokeAsync("ApplicationContactsWidget", new { applicationId = Model.ApplicationId, isReadOnly = !IsAdditionalContactEditable })
- } -
- + +
+ + + \ No newline at end of file diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Shared/Components/ApplicantInfo/Default.css b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Shared/Components/ApplicantInfo/Default.css index 60e54e061..ea2742a9c 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Shared/Components/ApplicantInfo/Default.css +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Shared/Components/ApplicantInfo/Default.css @@ -49,11 +49,30 @@ .unt-input-group-append { position: absolute; right: 0; - margin: 32px 10px 0px 0px; + margin: 28px 2px 0px 0px; } .unt-input-group-append .unt-btn-outline-primary { padding: 6px; min-height: 25px; border-radius: 2em; +} + +.unt-btn-link { + margin:0px; +} + +.aligned-select-btn { + padding-top: 1.7rem !important; +} + + .aligned-select-btn button { + border-radius: 2em; + } + +.select-disabled { + background-color: #e9ecef; + pointer-events: none; + color: #6c757d; + opacity: 1; } \ No newline at end of file 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 b85510dca..d581ba82d 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 @@ -1,109 +1,423 @@ -$(function () { - $('.numeric-mask').maskMoney({ precision: 0 }); - $('.numeric-mask').each(function () { - $(this).maskMoney('mask', this.value); - }); +abp.widgets.ApplicantInfo = function ($wrapper) { + let widgetManager = $wrapper.data('abp-widget-manager'); + + let widgetApi = { + getFilters: function () { + return { + applicationId: $wrapper.find('#ApplicantInfo_ApplicationId').val(), + applicationFormVersionId: $wrapper.find("#ApplicantInfo_ApplicationFormVersionId").val() + }; + }, + init: function (filters) { + let $widgetForm = $wrapper.find('form'); + + // Create a new form instance and store it on the widget API + this.zoneForm = new UnityZoneForm($widgetForm, { + saveButtonSelector: '#saveApplicantInfoBtn' + }); - const $unityAppId = $('#applicantInfoUnityApplicantId'); - let previousUnityAppId = $unityAppId.val(); + console.log("Applicant Info Initialized"); + + this.zoneForm.init(); + + // Set up additional event handlers here + this.setupEventHandlers(); + registerElectoralDistrictControls(this.zoneForm.form); + registerApplicantInfoSummaryDropdowns(this.zoneForm.form); + }, + refresh: function () { + widgetManager.refresh($wrapper); + }, + 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(); + try { + unity.grantManager.grantApplications.applicationApplicant + .updatePartialApplicantInfo(applicationId, applicantInfoSubmission) + .done(function () { + abp.notify.success('The Applicant Info has been updated.'); + self.zoneForm.resetTracking(); + PubSub.publish("refresh_detail_panel_summary"); + PubSub.publish('applicant_info_updated', applicantInfoSubmission); + }) + .fail(function (error) { + abp.notify.error('Failed to update Applicant Info.'); + console.log(error); + }); + } catch (error) { + abp.notify.error('An unexpected error occurred.'); + console.log(error); + } + }); + }, + 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(); + + // Normalize checkboxes to string for custom worksheets + $(`#Unity_GrantManager_ApplicationManagement_Applicant_Worksheet input:checkbox`).each(function () { + submissionPayload.CustomFields[this.name] = (this.checked).toString(); + }); + + customIncludes + .add('CustomFields') + .add('CorrelationId') + .add('WorksheetId'); + } - $unityAppId.on('input', function () { - const currentUnityAppId = $(this).val().trim(); - $('#saveApplicantInfoBtn').prop('disabled', currentUnityAppId === previousUnityAppId); - }); + customIncludes.add('ApplicantId'); + + let modifiedFieldData = Object.fromEntries( + Object.entries(submissionPayload).filter(([key, _]) => { + // Check if it's a modified widget field + return this.zoneForm.modifiedFields.has(key) || customIncludes.has(key) || key.startsWith('custom_'); + }) + ); - $('body').on('click', '#saveApplicantInfoBtn', function () { - let applicationId = document.getElementById('ApplicantInfoViewApplicationId').value; - let formData = $("#ApplicantInfoForm").serializeArray(); - let ApplicantInfoObj = {}; - let formVersionId = $("#ApplicationFormVersionId").val(); - let worksheetId = $("#ApplicantInfo_WorksheetId").val(); + let partialSubmissionPayload = { + modifiedFields: Array.from(this.zoneForm.modifiedFields), + data: unflattenObject(modifiedFieldData) + }; - $.each(formData, function (_, input) { + return partialSubmissionPayload; + }, + serializeWidget: function () { + let formData = this.zoneForm.serializeZoneArray(); + let submissionPayload = {}; + + // Process all form fields + $.each(formData, (_, input) => { + this.processFormField(submissionPayload, input); + }); + + return submissionPayload; + }, + processFormField: function (submissionPayload, input) { + const fieldName = input.name; + const inputElement = $(`[name="${fieldName}"]`); + + // Handle checkboxes explicitly + if (inputElement.length && inputElement.attr('type') === 'checkbox') { + // Only process the actual checkbox, not the hidden field + // If multiple elements with the same name, pick the checkbox + const checkbox = inputElement.filter('[type="checkbox"]'); + if (checkbox.length) { + if (typeof Flex === 'function' && Flex?.isCustomField(input)) { + Flex.includeCustomFieldObj(submissionPayload, input); + } else { + submissionPayload[fieldName] = checkbox.is(':checked'); + } + return; + } + } + + // Existing logic for custom fields if (typeof Flex === 'function' && Flex?.isCustomField(input)) { - Flex.includeCustomFieldObj(ApplicantInfoObj, input); + Flex.includeCustomFieldObj(submissionPayload, input); + return; + } + + 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; +} + +$(function () { + // Initialize widget through ABP's widget system instead of global object + abp.zones = abp.zones || {}; + abp.zones.applicantInfo = $('[data-widget-name="ApplicantInfo"]') + .data('abp-widget-api') || null; + + $('#applicantLookupSelect').select2({ + ajax: { + url: '/api/app/applicant/applicant-look-up-autocomplete-query', + dataType: 'json', + delay: 250, + data: function (params) { + return { applicantLookUpQuery: params.term }; + }, + processResults: function (data) { + return { + results: data.map(function (item) { + const res = { + id: item.Id, + text: `${item.UnityApplicantId?.trim() ? item.UnityApplicantId : 'None'} / ${item.ApplicantName}`, + ApplicantName: item.ApplicantName, + OrgName: item.OrgName, + OrgNumber: item.OrgNumber, + NonRegOrgName: item.NonRegOrgName, + OrganizationType: item.OrganizationType, + OrganizationSize: item.OrganizationSize, + OrgStatus: item.OrgStatus, + IndigenousOrgInd: item.IndigenousOrgInd, + Sector: item.Sector, + SubSector: item.SubSector, + SectorSubSectorIndustryDesc: item.SectorSubSectorIndustryDesc, + FiscalDay: item.FiscalDay, + FiscalMonth: item.FiscalMonth, + UnityApplicantId: item.UnityApplicantId + }; + return res + }) + }; } - else { - // This will not work if the culture is different and uses a different decimal separator - ApplicantInfoObj[input.name.split(".")[1]] = input.value; + }, + minimumInputLength: 3, + placeholder: 'Start typing applicant name or number to search for applicant...' + }); - if (ApplicantInfoObj[input.name.split(".")[1]] == '') { - ApplicantInfoObj[input.name.split(".")[1]] = null; + $('#applicantLookupSelect').on('select2:select', function (e) { + $('#mergeApplicantsMergeBtn').prop('disabled', false); + let selectedData = e.params.data; + + // Gather existing values from the form + let getVal = id => $(`#${id}`).val() || ''; + let existing = { + ApplicantId: getVal('ApplicantId'), + UnityApplicantId: getVal('ApplicantSummary_UnityApplicantId'), + ApplicantName: $('.application-details-breadcrumb .applicant-name').text(), + OrgName: getVal('ApplicantSummary_OrgName'), + OrgNumber: getVal('ApplicantSummary_OrgNumber'), + NonRegOrgName: getVal('ApplicantSummary_NonRegOrgName'), + OrganizationType: getVal('ApplicantSummary_OrganizationType'), + OrganizationSize: getVal('ApplicantSummary_OrganizationSize'), + OrgStatus: getVal('ApplicantSummary_OrgStatus'), + IndigenousOrgInd: $('#indigenousOrgInd').is(':checked') ? 'Yes' : 'No', + Sector: getVal('ApplicantSummary_Sector'), + SubSector: getVal('ApplicantSummary_SubSector'), + SectorSubSectorIndustryDesc: getVal('ApplicantSummary_SectorSubSectorIndustryDesc'), + FiscalDay: getVal('ApplicantSummary_FiscalDay'), + FiscalMonth: getVal('ApplicantSummary_FiscalMonth') + }; + + let newData = { + ApplicantId: selectedData.id || '', + UnityApplicantId: selectedData.UnityApplicantId || '', + ApplicantName: selectedData.ApplicantName || '', + OrgName: selectedData.OrgName || '', + OrgNumber: selectedData.OrgNumber || '', + NonRegOrgName: selectedData.NonRegOrgName || '', + OrganizationType: selectedData.OrganizationType || '', + OrganizationSize: selectedData.OrganizationSize || '', + OrgStatus: selectedData.OrgStatus || '', + IndigenousOrgInd: selectedData.IndigenousOrgInd || '', + Sector: selectedData.Sector || '', + SubSector: selectedData.SubSector || '', + SectorSubSectorIndustryDesc: selectedData.SectorSubSectorIndustryDesc || '', + FiscalDay: selectedData.FiscalDay || '', + FiscalMonth: selectedData.FiscalMonth || '' + }; + + $('#existing_ApplicantNameHeader').text(existing.ApplicantName); + $('#new_ApplicantNameHeader').text(newData.ApplicantName); + + // Fill modal fields + for (const key in existing) { + $(`#existing_${key}`).text(existing[key]); + $(`#new_${key}`).text(newData[key]); + $(`input[name="merge_${key}"][value="existing"]`).prop('checked', true); + } + + // Show step 1, hide step 2 + $('#mergeApplicantsStep1').show(); + $('#mergeApplicantsStep2').hide(); + + // Remove previous handlers + $('#mergeApplicantsNextBtn').off('click'); + $('#mergeApplicantsBackBtn').off('click'); + $('#mergeApplicantsMergeBtn').off('click'); + $('#mergeDuplicateApplicantsModal').off('hidden.bs.modal'); + + // Next button: go to confirmation + $('#mergeApplicantsNextBtn').on('click', function () { + $('#mergeApplicantsStep1').hide(); + $('#mergeApplicantsStep2').show(); + }); + + // Back button: return to comparison + $('#mergeApplicantsBackBtn').on('click', function () { + $('#mergeApplicantsStep2').hide(); + $('#mergeApplicantsStep1').show(); + }); + + // Merge button: apply selected values to form + $('#mergeApplicantsMergeBtn').on('click', async function () { + $('#mergeApplicantsMergeBtn').prop('disabled', true); + $('#mergeApplicantsSpinner').show(); + + let selectedPrincipal = $('input[name="merge_ApplicantId"]:checked').val(); + let principalApplicantId = selectedPrincipal === 'existing' ? existing.ApplicantId : newData.ApplicantId; + let nonPrincipalApplicantId = selectedPrincipal === 'existing' ? newData.ApplicantId : existing.ApplicantId; + let applicationId = $('#ApplicantInfoViewApplicationId').val(); + + // Merge and update applicant info + let mergedApplicantInfo = {}; + if (principalApplicantId) { + mergedApplicantInfo = getMergedApplicantInfo(existing, newData); + mergedApplicantInfo.ApplicantId = principalApplicantId; + + let formData = $("#ApplicantInfoForm").serializeArray(); + let ApplicantInfoObj = {}; + let formVersionId = $("#ApplicationFormVersionId").val(); + let worksheetId = $("#WorksheetId").val(); + + $.each(formData, function (_, input) { + if (typeof Flex === 'function' && Flex?.isCustomField(input)) { + Flex.includeCustomFieldObj(ApplicantInfoObj, input); + } + else { + ApplicantInfoObj[input.name] = input.value; + + if (ApplicantInfoObj[input.name] == '') { + ApplicantInfoObj[input.name] = null; + } + } + }); + + $(`#ApplicantInfoForm input:checkbox`).each(function () { + ApplicantInfoObj[this.name] = (this.checked).toString(); + }); + if (typeof Flex === 'function') { + Flex?.setCustomFields(ApplicantInfoObj); } - if (input.name == 'ApplicantId' || input.name == 'SupplierNumber' || input.name == 'OriginalSupplierNumber') { - ApplicantInfoObj[input.name] = input.value; + Object.assign(ApplicantInfoObj, mergedApplicantInfo); + Object.keys(ApplicantInfoObj).forEach(key => { + if (ApplicantInfoObj[key] === "") { + ApplicantInfoObj[key] = null; + } + }); + + const orgName = $('#ApplicantSummary_OrgName').val(); + ApplicantInfoObj['ApplicantSummary.OrgName'] = orgName; + const orgNumber = $('#ApplicantSummary_OrgNumber').val(); + ApplicantInfoObj['ApplicantSummary.OrgNumber'] = orgNumber; + const orgStatus = $('#ApplicantSummary_OrgStatus').val(); + ApplicantInfoObj['ApplicantSummary.OrgStatus'] = orgStatus; + const organizationType = $('#ApplicantSummary_OrganizationType').val(); + ApplicantInfoObj['OrganizationType'] = organizationType; + + const indigenousOrgInd = $('#indigenousOrgInd').is(":checked"); + ApplicantInfoObj['IndigenousOrgInd'] = indigenousOrgInd ? "Yes" : "No"; + ApplicantInfoObj['correlationId'] = formVersionId; + ApplicantInfoObj['worksheetId'] = worksheetId; + ApplicantInfoObj.ApplicantId = principalApplicantId; + + try { + await handleApplicantMerge(applicationId, principalApplicantId, nonPrincipalApplicantId, newData, ApplicantInfoObj); + } catch (err) { + console.error(err); } } + + // Triggers a refresh of the ApplicantInfo widget on merge + PubSub.publish('applicant_info_merged'); + + $('#mergeApplicantsSpinner').hide(); + $('#mergeDuplicateApplicantsModal').modal('hide'); }); - // Update checkboxes which are serialized if unchecked - $(`#ApplicantInfoForm input:checkbox`).each(function () { - ApplicantInfoObj[this.name] = (this.checked).toString(); + // On modal close, clear the ApplicantLookUp field + $('#mergeDuplicateApplicantsModal').on('hidden.bs.modal', function () { + $('#applicantLookupSelect').val(null).trigger('change'); }); - // Make sure all the custom fields are set in the custom fields object - if (typeof Flex === 'function') { - Flex?.setCustomFields(ApplicantInfoObj); - } + // Show the modal + $('#mergeDuplicateApplicantsModal').modal('show'); - try { - if (ApplicantInfoObj["SupplierNumber"] + "" != "undefined" - && ApplicantInfoObj["SupplierNumber"] + "" != "" - && ApplicantInfoObj["SupplierNumber"] + "" != ApplicantInfoObj["OriginalSupplierNumber"] + "") { - $('.cas-spinner').show(); - } + }); - const orgName = $('#ApplicantInfo_OrgName').val(); - ApplicantInfoObj['orgName'] = orgName; - const orgNumber = $('#ApplicantInfo_OrgNumber').val(); - ApplicantInfoObj['orgNumber'] = orgNumber; - const orgStatus = $('#orgBookStatusDropdown').val(); - ApplicantInfoObj['orgStatus'] = orgStatus; - const organizationType = $('#orgTypeDropdown').val(); - ApplicantInfoObj['organizationType'] = organizationType; - const indigenousOrgInd = $('#indigenousOrgInd').is(":checked"); - if (indigenousOrgInd) { - ApplicantInfoObj['IndigenousOrgInd'] = "Yes"; - } - else { - ApplicantInfoObj['IndigenousOrgInd'] = "No"; - } - + $('#selectAllExistingBtn').on('click', function () { + $('#mergeApplicantsStep1 input[type="radio"][value="existing"]').each(function () { + $(this).prop('checked', true); + }); + }); - ApplicantInfoObj['correlationId'] = formVersionId; - ApplicantInfoObj['worksheetId'] = worksheetId; + $('#selectAllNewBtn').on('click', function () { + $('#mergeApplicantsStep1 input[type="radio"][value="new"]').each(function () { + $(this).prop('checked', true); + }); + }); +}); - let currentUnityAppId = ApplicantInfoObj['UnityApplicantId']; - if (currentUnityAppId !== null) { - if (previousUnityAppId !== currentUnityAppId) { - checkUnityApplicantIdExist(currentUnityAppId, applicationId, ApplicantInfoObj); - } else { - updateApplicantInfo(applicationId, ApplicantInfoObj); - } +// Move to zone-extensions +function unflattenObject(flatObj) { + const result = {}; + for (const flatKey in flatObj) { + const value = flatObj[flatKey]; + if (!flatKey) continue; + const keys = flatKey.split('.'); + let cur = result; + for (let i = 0; i < keys.length; i++) { + const k = keys[i]; + if (i === keys.length - 1) { + cur[k] = value; } else { - updateApplicantInfo(applicationId, ApplicantInfoObj); + cur[k] = cur[k] || {}; + cur = cur[k]; } - - previousUnityAppId = currentUnityAppId; - $('#saveApplicantInfoBtn').prop('disabled', true); - PubSub.publish("applicant_info_updated", ApplicantInfoObj); - } - catch (error) { - $('.cas-spinner').hide(); - console.log(error); - $('#saveApplicantInfoBtn').prop('disabled', false); + } + return result; +} + +function registerElectoralDistrictControls($container) { + $container.find('[data-bs-toggle="tooltip"]').tooltip(); + setElectoralDistrictLockState(true); + + const $electoralType = $('#ApplicantElectoralAddressType'); + + // Delegate change event for both address groups + $container.on('change', '.physical-address-fields-group input, .mailing-address-fields-group input', function () { + const type = $electoralType.val(); + if ( + ((type === "PhysicalAddress" && $(this).closest('.physical-address-fields-group').length) || + (type === "MailingAddress" && $(this).closest('.mailing-address-fields-group').length)) && + !electoralDistrictLocked + ) { + refreshApplicantElectoralDistrict(); } }); +} - $('#orgSectorDropdown').change(function () { +function registerApplicantInfoSummaryDropdowns($container) { + $container.find('#ApplicantSummary_Sector').on('change', function () { const selectedValue = $(this).val(); let sectorList = JSON.parse($('#orgApplicationSectorList').text()); - let childDropdown = $('#orgSubSectorDropdown'); + let childDropdown = $('#ApplicantSummary_SubSector'); childDropdown.empty(); let subSectors = sectorList.find(sector => (sector.sectorName === selectedValue))?.subSectors; @@ -111,6 +425,7 @@ value: '', text: 'Please choose...' })); + $.each(subSectors, function (index, item) { childDropdown.append($('
diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Shared/Components/EmailsWidget/Default.js b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Shared/Components/EmailsWidget/Default.js index 8d4f6decc..3813c69d0 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Shared/Components/EmailsWidget/Default.js +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Shared/Components/EmailsWidget/Default.js @@ -454,18 +454,25 @@ } function processString(token,inputString) { let lookupArray = ['category', 'status', 'decline_rationale']; + let datesArray = ['submission_date', 'approval_date', 'project_start_date', 'project_end_date'] if(typeof inputString !== 'string') { return inputString; } - - let date = new Date(inputString); - if (!isNaN(date.getTime())) { - - return luxon.DateTime.fromISO(inputString, { - locale: abp.localization.currentCulture.name, - }).toUTC().toLocaleString() - } else { + + if (datesArray.includes(token)) { + let date = new Date(inputString); + if (!isNaN(date.getTime())) { + + return luxon.DateTime.fromISO(inputString, { + locale: abp.localization.currentCulture.name, + }).toUTC().toLocaleString() + } + else { + return ''; + } + } + else { if (lookupArray.includes(token)) { inputString = inputString.replace(/_/g, ' '); diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Shared/Components/EmailsWidget/EmailsWidgetViewModel.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Shared/Components/EmailsWidget/EmailsWidgetViewModel.cs index 8522d3ff2..e73fc6578 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Shared/Components/EmailsWidget/EmailsWidgetViewModel.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Shared/Components/EmailsWidget/EmailsWidgetViewModel.cs @@ -30,7 +30,6 @@ public class EmailsWidgetViewModel [TextArea(Rows = 4)] [Placeholder("Body of email")] [DisplayName("Email Body")] - [MaxLength(40000)] [Required] public string EmailBody { get; set; } = string.Empty; public Guid OwnerId { get; set; } diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Shared/Components/HistoryWidget/Default.cshtml b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Shared/Components/HistoryWidget/Default.cshtml index f14f64967..73dd8d406 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Shared/Components/HistoryWidget/Default.cshtml +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Shared/Components/HistoryWidget/Default.cshtml @@ -1,9 +1,11 @@ -@model HistoryWidgetViewModel @using Unity.GrantManager.History -@using Unity.GrantManager.Web.Views.Shared.Components.HistoryWidget; +@using Unity.GrantManager.Web.Views.Shared.Components.HistoryWidget @using Microsoft.AspNetCore.Mvc.Localization -@using Unity.GrantManager.Localization; +@using Unity.GrantManager.Localization @using Microsoft.Extensions.Localization + +@model HistoryWidgetViewModel + @inject IHtmlLocalizer L @inject IStringLocalizerFactory StringLocalizerFactory @{ @@ -26,10 +28,10 @@
} - @foreach (HistoryDto historyDto in Model.ApplicationStatusHistoryList) + @foreach (HistoryDto historyDto in Model.ApplicationStatusHistoryList ?? Enumerable.Empty()) { - string fromString = ""; - if (!historyDto.OriginalValue.IsNullOrEmpty()) + string fromString = string.Empty; + if (!string.IsNullOrEmpty(historyDto?.OriginalValue)) { fromString = "from"; } @@ -38,17 +40,17 @@
- @historyDto.UserName + @historyDto?.UserName
- Status changed @fromString @historyDto.OriginalValue + Status changed @fromString @historyDto?.OriginalValue to - @historyDto.NewValue + @historyDto?.NewValue
-
@historyDto.ChangeTime.ToString("yyyy-MM-dd h:mm tt")
+
@historyDto?.ChangeTime.ToString("yyyy-MM-dd h:mm tt")
} diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Shared/Components/ProjectInfo/Default.cshtml b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Shared/Components/ProjectInfo/Default.cshtml index 1bf6a96ed..97e3c4a00 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Shared/Components/ProjectInfo/Default.cshtml +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Shared/Components/ProjectInfo/Default.cshtml @@ -1,24 +1,24 @@ @using Microsoft.AspNetCore.Authorization; +@using Microsoft.Extensions.Localization @using Unity.Flex.Web.Views.Shared.Components.WorksheetInstanceWidget @using Unity.GrantManager.Flex @using Unity.GrantManager.Localization -@using Microsoft.Extensions.Localization -@using Unity.GrantManager.Permissions; -@using Unity.GrantManager.Web.Views.Shared.Components.ProjectInfo; +@using Unity.GrantManager.Web.Views.Shared.Components.ProjectInfo +@using Unity.Modules.Shared @using Unity.Modules.Shared.Correlation @using Volo.Abp.Features +@model ProjectInfoViewModel + @inject IAuthorizationService AuthorizationService @inject IStringLocalizer L @inject IFeatureChecker FeatureChecker - -@model ProjectInfoViewModel @{ Layout = null; } - - + + @@ -26,136 +26,139 @@ - -
-
@L["ProjectInfoView:ProjectInfoTitle"].Value
-
- + -
- -
- @L["ProjectInfoView:ProjectInfoTitle"].Value - - - - - - - - - - - - - - - - - - - -
- $ - -
-
- -
- $ - -
-
- - - - - +
+ + @* Zone Section : ProjectInfo.Summary *@ + + + + + + + + + + + + + + + + + + + + +
+ $ + +
+
+ +
+ $ + +
+
+ + + + + +
+ + +
+ $ + +
+
+ +
+ + + + + + + + + + + + + + + + + +
- - -
- $ - -
-
- -
- - - - - - - - - - - - - - - - - +
+ + @* Zone Section : ProjectInfo.Location *@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - -
-
@L["ProjectInfoView:ProjectInfoLocation"].Value
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @if (await FeatureChecker.IsEnabledAsync("Unity.Flex")) - { + @* Zone Section : ProjectInfo.Worksheet *@ + @await Component.InvokeAsync(typeof(WorksheetInstanceWidget), new { @@ -163,18 +166,8 @@ instanceCorrelationProvider = CorrelationConsts.Application, sheetCorrelationId = Model.ApplicationFormVersionId, sheetCorrelationProvider = CorrelationConsts.FormVersion, - uiAnchor = FlexConsts.ProjectInfoUiAnchor + uiAnchor = FlexConsts.ProjectInfoUiAnchor }) - } - + - - - 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 85ec888b2..036bde603 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 @@ -1,204 +1,282 @@ -$(function () { - $('.numeric-mask').maskMoney({ precision: 0 }); - $('.percentage-mask').maskMoney(); - $('.numeric-mask').each(function () { - $(this).maskMoney('mask', this.value); - }); - $('.percentage-mask').each(function () { - $(this).maskMoney('mask', this.value); - }); - $('body').on('click', '#saveProjectInfoBtn', function () { - let applicationId = document.getElementById('ProjectInfoViewApplicationId').value; - let formData = $("#projectInfoForm").serializeArray(); - let projectInfoObj = {}; - let formVersionId = $("#ApplicationFormVersionId").val(); - let worksheetId = $("#ProjectInfo_WorksheetId").val(); - - $.each(formData, function (_, input) { - if (typeof Flex === 'function' && Flex?.isCustomField(input)) { - Flex.includeCustomFieldObj(projectInfoObj, input); - } - else if ((input.name == "ProjectInfo.ProjectName") || (input.name == "ProjectInfo.ProjectSummary") || (input.name == "ProjectInfo.Community")) { - projectInfoObj[input.name.split(".")[1]] = input.value; - } else { - buildFormData(projectInfoObj, input) - } - }); +// Called on widget initialization +abp.widgets.ProjectInfo = function ($wrapper) { + let widgetApi = { + getFilters: function () { + return { + applicationId: $wrapper.find('#ProjectInfo_ApplicationId').val(), + applicationFormVersionId: $wrapper.find("#ProjectInfo_ApplicationFormVersionId").val() + }; + }, + init: function (filters) { + let $widgetForm = $wrapper.find('form'); - // Update checkboxes which are serialized if unchecked - $(`#projectInfoForm input:checkbox`).each(function () { - projectInfoObj[this.name] = (this.checked).toString(); - }); + // Create a new form instance and store it on the widget API + this.zoneForm = new UnityZoneForm($widgetForm, { + saveButtonSelector: '#saveProjectInfoBtn', + modifiedClass: 'bg-info-subtle' + }); - // Make sure all the custom fields are set in the custom fields object - if (typeof Flex === 'function') { - Flex?.setCustomFields(projectInfoObj); - } + this.zoneForm.init(); - projectInfoObj['correlationId'] = formVersionId; - projectInfoObj['worksheetId'] = worksheetId; - updateProjectInfo(applicationId, projectInfoObj); - }); + // Set up additional event handlers here + this.setupEventHandlers(); + }, + setupEventHandlers: function() { + const self = this; - function buildFormData(projectInfoObj, input) { + // Save button handler + self.zoneForm.saveButton.on('click', function () { + let applicationId = document.getElementById('ProjectInfo_ApplicationId').value; + let formData = self.zoneForm.serializeZoneArray(); + + let projectInfoObj = {}; + + // Process all form fields + $.each(formData, function (_, input) { + self.processFormField(projectInfoObj, input); + }); - let inputElement = $('[name="' + input.name + '"]'); - // This will not work if the culture is different and uses a different decimal separator - if (inputElement.hasClass('unity-currency-input') || inputElement.hasClass('numeric-mask')) { - projectInfoObj[input.name.split(".")[1]] = input.value.replace(/,/g, ''); - } - else { - projectInfoObj[input.name.split(".")[1]] = input.value; - } - if (isNumberField(input)) { - if (projectInfoObj[input.name.split(".")[1]] == '') { - projectInfoObj[input.name.split(".")[1]] = 0; - } else if (projectInfoObj[input.name.split(".")[1]] > getMaxNumberField(input)) { - projectInfoObj[input.name.split(".")[1]] = getMaxNumberField(input); - } - } - else if (projectInfoObj[input.name.split(".")[1]] == '') { - projectInfoObj[input.name.split(".")[1]] = null; - } - } + const customIncludes = new Set(); - function updateProjectInfo(applicationId, projectInfoObj) { - try { - unity.grantManager.grantApplications.grantApplication - .updateProjectInfo(applicationId, projectInfoObj) - .done(function () { - abp.notify.success( - 'The project info has been updated.' - ); - $('#saveProjectInfoBtn').prop('disabled', true); - PubSub.publish('project_info_saved', projectInfoObj); - PubSub.publish('refresh_detail_panel_summary'); - }); - } - catch (error) { - console.log(error); - $('#saveProjectInfoBtn').prop('disabled', false); - } - } + 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(); - function getMaxNumberField(input) { - const maxCurrency = 10000000000000000000000000000; - const maxScore = 2147483647; - if (isCurrencyField(input)) - return maxCurrency; - else - return maxScore; - } + // Normalize checkboxes to string for custom worksheets + $(`#Unity_GrantManager_ApplicationManagement_Project_Worksheet input:checkbox`).each(function () { + projectInfoObj.CustomFields[this.name] = (this.checked).toString(); + }); - function isNumberField(input) { - return isCurrencyField(input) || isPercentageField(input); - } + customIncludes + .add('CustomFields') + .add('CorrelationId') + .add('WorksheetId'); + } + + // Create filtered object in one functional operation + let modifiedFieldData = Object.fromEntries( + Object.entries(projectInfoObj).filter(([key, _]) => { + // Check if it's a directly included widget field + if (customIncludes.has(key)) return true; + + // Check if it's a modified widget field + return self.zoneForm.modifiedFields.has(`ProjectInfo.${key}`); + }) + ); - function isCurrencyField(input) { - const currencyFields = ['ProjectInfo.RequestedAmount', - 'ProjectInfo.TotalProjectBudget', - 'ProjectInfo.ProjectFundingTotal']; - return currencyFields.includes(input.name); - } + let projectInfoSubmission = { + modifiedFields: Array.from(self.zoneForm.modifiedFields).map(field => { + const parts = field.split('.'); + return parts.length > 1 ? parts.slice(1).join('.') : field; + }), + data: modifiedFieldData + }; + + try { + unity.grantManager.grantApplications.grantApplication + .updatePartialProjectInfo(applicationId, projectInfoSubmission) + .done(function () { + abp.notify.success('The project info has been updated.'); + self.zoneForm.resetTracking(); + PubSub.publish('project_info_saved', projectInfoObj); + PubSub.publish('refresh_detail_panel_summary'); + }); + } + catch (error) { + console.log(error); + self.zoneForm.resetTracking(); + } + }); - function isPercentageField(input) { - return input.name == 'ProjectInfo.PercentageTotalProjectBudget'; - } + // Date picker initialization + $('#startDate').on('apply.daterangepicker', function (event, picker) { + console.log(event, picker); + }); - $('#startDate').on('apply.daterangepicker', function (event, picker) { - console.log(event, picker); - }); + // Location dropdowns handling + $('#economicRegions').change(function () { + const selectedValue = $(this).val(); + let allEconomicRegions = JSON.parse($('#allEconomicRegionList').text()); + let allRegionalDistricts = JSON.parse($('#allRegionalDistrictList').text()); + let selectedEconomicRegion = allEconomicRegions.find(d => d.economicRegionName == selectedValue); + let childDropdown = self.initializeDroplist('#regionalDistricts'); + + if (selectedValue) { + let regionalDistricts = allRegionalDistricts.filter(d => + d.economicRegionCode == selectedEconomicRegion.economicRegionCode); + $.each(regionalDistricts, function (index, item) { + childDropdown.append($('